Commit graph

3 commits

Author SHA1 Message Date
Garm
5a2c484430 refactor(telemetry): centralize stack slug validation + cardinality cap
Addresses review feedback on PR #194: prior code validated X-Headroom-Stack
slugs differently at each ingress — the Prometheus counter capped length but
the env-var path and beacon didn't. Under a misconfigured or malicious client
sending arbitrary X-Headroom-Stack values, requests_by_stack could grow
unbounded in memory, in the Prometheus scrape, and in the JSONB telemetry
payload.

- New normalize_stack(raw) in headroom/telemetry/context.py: strips, lowercases,
  enforces ^[a-z][a-z0-9_]{0,63}$. Single chokepoint.
- detect_stack now routes HEADROOM_STACK and stats dominant-slug through it;
  invalid env values fall through to the agent-type path or default "proxy".
- PrometheusMetrics.record_stack routes through normalize_stack and rejects
  new slugs once the dict hits MAX_DISTINCT_STACKS (32); existing slugs still
  increment so valid callers aren't starved.
- 10 new unit tests covering normalize_stack charset/length/empty cases, the
  cardinality cap, and invalid-env fallback paths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 18:42:41 +02:00
Garm
4a8d9812cf fix(ci): resolve mypy no-any-return and ruff formatting
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 18:42:41 +02:00
Garm
d4cd49af95 feat(telemetry): add headroom_stack and install_mode identity fields
Adds two orthogonal identity fields to the anonymous telemetry beacon so we
can segment usage by integration surface and deployment shape:

- headroom_stack: how Headroom is invoked (proxy, wrap_claude, wrap_codex,
  adapter_ts_openai, adapter_ts_anthropic, etc.). Resolved from HEADROOM_STACK
  env, HEADROOM_AGENT_TYPE fallback, or aggregated request-header counts.
- install_mode: how the proxy is deployed (wrapped / persistent / on_demand).
  Detected from HEADROOM_AGENT_TYPE plus DeploymentManifest lookup.

TS SDK adapters now tag every request with X-Headroom-Stack; a FastAPI
middleware buckets the counts and surfaces them via /stats so the beacon can
report requests_by_stack for mixed-integration sessions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 17:12:38 +02:00