Skip to content

feat: add project identification to request tracking#53

Open
zenprocess wants to merge 1 commit intosnipeship:mainfrom
zenprocess:feat/project-tracking
Open

feat: add project identification to request tracking#53
zenprocess wants to merge 1 commit intosnipeship:mainfrom
zenprocess:feat/project-tracking

Conversation

@zenprocess
Copy link
Copy Markdown

Summary

  • Extracts project name from Claude API requests to tag each proxied request with its originating project
  • Uses a 3-tier extraction strategy: x-project header > system prompt path pattern > system prompt heading
  • Adds project column to requests table with migration guard and performance index
  • Fully backward-compatible — project defaults to null for existing requests

Motivation

When ccflare proxies traffic from multiple Claude Code projects across multiple machines, there's no way to tell which project generated which request. This makes per-project analytics, cost tracking, and session correlation impossible.

Changes

File Change
packages/types/src/api.ts Add project to RequestMeta
packages/types/src/request.ts Add project to RequestRow, Request, RequestResponse + mappers
packages/proxy/src/post-processor.worker.ts Add extractProjectFromRequest(), wire through handleStart/handleEnd
packages/database/src/repositories/request.repository.ts Add project to RequestData, saveMeta(), save()
packages/database/src/database-operations.ts Thread project param through facade methods
packages/database/src/migrations.ts ALTER TABLE ADD COLUMN project TEXT
packages/database/src/performance-indexes.ts Add idx_requests_project_timestamp

Test plan

  • Build passes: bun run build
  • Start server, make a Claude API call from a project with CLAUDE.md
  • Verify project column populated: sqlite3 ccflare.db "SELECT id, project FROM requests LIMIT 5"
  • Verify x-project header override: curl -H "x-project: test" ...
  • Verify null project for requests without system prompt

🤖 Generated with Claude Code

Extract project name from Claude API requests using:
1. x-project header (explicit override)
2. Path patterns in system prompt (/Users/.../Desktop/{Project}/)
3. First markdown heading in system prompt

Adds `project` column to requests table with migration guard,
performance index, and pass-through to all domain types and
API responses. Backward-compatible — project defaults to null.

Files: types (api.ts, request.ts), database (migrations, repository,
operations, indexes), proxy (post-processor.worker.ts)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@zenprocess
Copy link
Copy Markdown
Author

zenprocess commented Apr 6, 2026

Context: Why project tracking matters

This PR was born from a real production need — we run ccflare as shared infrastructure proxying Claude API traffic across multiple accounts, machines, and projects. Without project tagging, analytics showed aggregate token usage but couldn't answer basic questions like:

  • "Which project is burning the most cache tokens?"
  • "Is the rate limiting happening because of project A dispatch or project B?"
  • "What's the cost per project per day?"

The bigger picture: ccflare + Afterburn

Project tracking unlocks a powerful integration with Afterburn — a tool that mines Claude Code session history to find recurring friction patterns, successful approaches, and skill gaps.

The pipeline:

ccflare (proxies all Claude API traffic, tags by project)
    │
    └─→ Afterburn (hourly scheduled workflow)
            ├─ Fetches ccflare's request history grouped by project
            ├─ Reconstructs conversation sessions from request/response bodies
            ├─ Runs friction/patterns/gaps analysis passes
            └─ Publishes findings to a dashboard

What this enables that neither tool can do alone:

  • Cross-machine pattern detection — the same correction happening on multiple machines = systemic issue, not a one-off
  • Cost-of-friction quantification — ccflare has token counts per request, afterburn knows which requests were retries. Multiply = dollar cost of each recurring mistake
  • Per-project skill evolution — afterburn's CCAR loop benchmarks skills against historical correction rates, now segmented by project

ccflare's project column is the join key that makes all of this work. Without it, the afterburn pipeline can only analyze sessions from one machine at a time (via local JSONL files). With it, ccflare becomes the single aggregation point for cross-machine Claude intelligence.

Happy to share more details if useful for the project roadmap.

@tombii
Copy link
Copy Markdown

tombii commented Apr 6, 2026

Hi @zenprocess,
Might I shamelessly suggest my fork: https://github.com/tombii/better-ccflare
It supports API keys so that each project can get its own API key. Metrics are displayed per API key and the API key used is also visible per request.
Best regards,
Tom

zenprocess pushed a commit to zenprocess/ccflare that referenced this pull request Apr 6, 2026
* feat: add dashboard authentication for API key protection [skip-version]

Implements secure dashboard authentication when API keys are configured:
- Store/retrieve API keys from localStorage
- Authentication dialog prompts for API key on first access
- Automatic inclusion of API key in all dashboard API requests
- Validates API key before accepting it

Fixes snipeship#53

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: dashboard authentication now properly includes API key headers [skip-version]

Fixed critical issues preventing dashboard from working with API keys:

- Auth service now exempts static assets (.js, .css, .svg, etc.) from authentication
- API client properly overrides request() method to inject x-api-key header
- ApiKeysTab now uses api client instead of direct fetch() calls
- Added comprehensive tests for static asset exemption

This resolves the 401 errors on dashboard API requests and allows full
dashboard functionality when API keys are configured.

Closes snipeship#53

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: Dashboard authentication with API keys (fix snipeship#53) [skip-version]

- Exempt dashboard routes from server-side auth (only API endpoints require auth)
- Add global 401 error handler via custom event system
- Auto-trigger auth dialog when closing generated key dialog
- Disable queries while key dialog is open to prevent premature 401s
- Show auth dialog on any page, not just root
- Clean up debug logging

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* security: Add CSP headers and improve error type checking [skip-version]

- Add Content Security Policy headers for dashboard HTML
- Add security headers (X-Frame-Options, X-Content-Type-Options, etc.)
- Replace duck-typed error checks with instanceof HttpError
- Ensure consistent error handling across codebase

CSP protects against:
- XSS attacks (restricts script sources)
- Data exfiltration (connect-src 'self' only)
- Clickjacking (frame-ancestors 'none')
- MIME type confusion (X-Content-Type-Options: nosniff)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* security: Fix authentication bypass and harden CSP [skip-version]

Critical fixes:
- Fix authentication bypass: Only render content when isAuthenticated=true
- Remove 'unsafe-inline' from script-src in CSP (only external scripts allowed)
- Keep 'unsafe-inline' for style-src (required for CSS-in-JS/Tailwind)

Previous logic allowed unauthenticated access if auth dialog was closed.
New logic: Content only renders when explicitly authenticated.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* security: Use sessionStorage instead of localStorage for API keys [skip-version]

- Replace localStorage with sessionStorage for API key storage
- sessionStorage is cleared when tab closes (reduces exposure window)
- Still survives page reloads within same tab (good UX)
- Combined with strict CSP headers for XSS protection

Benefits:
- API key not persisted after browser/tab close
- Reduced risk window compared to localStorage
- No code changes needed in components (same API)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants