Skip to content

feat(analytics): add auth status gate for metrics sync - #488

Open
8nevil8 wants to merge 2 commits into
mainfrom
feat/analytics-auth-gate
Open

feat(analytics): add auth status gate for metrics sync#488
8nevil8 wants to merge 2 commits into
mainfrom
feat/analytics-auth-gate

Conversation

@8nevil8

@8nevil8 8nevil8 commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

Expired CodeMie SSO cookies caused the metrics endpoint (fronted by Keycloak) to answer POSTs with HTTP 200 + HTML login page instead of 401. Analytics auth failures were completely silent — sessions vanished from the metrics dashboard while local JSONL deltas looked healthy. This adds a three-layer auth status gate so broken analytics auth is detected and surfaced immediately.

Changes

  • src/utils/analytics-auth-status.ts (new): file-based marker recording metrics-endpoint credential rejections (~/.codemie/analytics-auth-status.json); best-effort, never throws
  • metrics-api-client.ts: classify HTTP 401/403 and non-JSON HTML responses (Keycloak login page) as auth failures; write marker on rejection, clear on successful send
  • sso.auth.ts: clear the marker on successful codemie profile login
  • hook.ts: generic UserPromptSubmit gate (all agents via unified codemie hook) — blocks the prompt with codemie profile login instructions when analytics auth is missing or was server-rejected; active only when analytics sync is configured
  • AgentCLI.ts: launch-time analytics auth check for non-SSO providers when analytics is enabled (codeMieUrl set); reuses SSO validateAuth (stored creds + live API test) with interactive re-auth prompt; non-fatal on decline; clears stale marker on success

Impact

Before: expired analytics credentials → silent metrics loss for days (observed 08-12 → 08-14 locally; data recovered only after manual re-login + session resumes).
After: launch-time warning with re-auth prompt; hard block at prompt level with exact re-login command if still unresolved; marker cleared automatically by login or any successful send.

Testing

  • Tests added/updated
  • Manual testing done (typecheck, ESLint zero-warning, build, lint-staged + related vitest via pre-commit)

Checklist

  • Code follows project standards
  • CI is green (npm run ci)
  • No merge conflicts with main

Expired CodeMie SSO cookies made the metrics endpoint answer with HTTP 200
Keycloak login HTML instead of 401, so analytics auth failures were silent
and sessions disappeared from metrics.

- Add analytics-auth-status marker util (records credential rejections)
- MetricsApiClient: flag 401/403 and HTML login-page responses as auth
  failures, write the marker, clear it on successful send
- SSO login flow clears the marker on successful authentication
- Unified hook: generic UserPromptSubmit gate blocks the prompt with
  re-login instructions when analytics auth is missing or rejected
  (all agents, only when analytics sync is configured)
- AgentCLI: launch-time analytics auth check for non-SSO providers when
  analytics is enabled, with interactive re-auth prompt (non-fatal)
@8nevil8

8nevil8 commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator Author

Automated review — critical findings

Focused on architecture, patterns, correctness, DRY, YAGNI. Minor issues intentionally omitted.

1. ssoSetupSteps.validateAuth(config) — live network call on every agent launch

src/agents/core/AgentCLI.ts:295–310

Any slow response or unreachable CodeMie backend hangs agent startup with no visible timeout guard. Every anthropic-subscription / moonshot-subscription user takes the hit on every launch.

Fix direction: Skip the live API call here; rely solely on the marker written by MetricsApiClient (already present), or gate on the marker first and only call validateAuth when the marker already exists.

2. Programmatic mode re-throws all gate errors, not just intentional blocks

src/cli/commands/hook.ts:550–570

In programmatic mode (config defined), the outer catch unconditionally re-throws all gate errors. A transient filesystem error reading the credential store or the auth-status file surfaces to the VSCode host as a blocking error, violating the gate's own "auxiliary, must never break the prompt flow" contract.

Fix direction: Distinguish intentional blocks (isAuthBlock flag or sentinel error subclass) from unexpected exceptions; only re-throw intentional blocks in programmatic mode.

3. Gate blocks on missing credentials before any server rejection

src/cli/commands/hook.ts:523–543

The gate blocks when hasValidAuth = false AND authStatus = null — i.e. it blocks on missing credentials even when no server-side rejection has ever been recorded. A fresh install with CODEMIE_URL + CODEMIE_SYNC_API_URL in the environment but no prior login gets hard-blocked at every prompt before the first metrics send attempt. This contradicts the gate's stated contract ("blocks when auth is known broken").

Fix direction: Restrict the credential-absence block to cases where a marker exists, or only run the credential check when authStatus is already set; let the first send attempt write the marker if credentials are absent.

Any add/remove/rename/rewrite of X-CodeMie-* attribution headers, the
Responses API `user` body field, JWT sub/email overrides, or their
derivation source is now called out as a strictly secured operation
that requires security-review sign-off before merge.

- security-practices.md: promote request header integrity to a Core
  Security Principle; add a top-priority "CRITICAL: Project & User
  Attribution Headers" section covering the in-scope surface (every
  X-CodeMie-* header injected by header-injection.plugin.ts plus the
  Responses `user` field and JWT claim overrides), five hard rules,
  Bad/Good examples, and a reviewer sub-checklist; extend the Common
  Security Pitfalls table and the Development checklist.
- git-workflow.md: lead the Code Review Checklist with a highlighted
  CRITICAL callout for attribution-header changes and require the
  security-review sign-off; add a canonical-injector check pointing at
  header-injection.plugin.ts.
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