headroom/docs/content/docs
chopratejas 2e874c5e3e fix: A5 — strip x-headroom-* from upstream-bound headers (P5-49)
Eliminate P5-49: every Python forwarder and the Rust transparent proxy
now drop internal `x-headroom-*` request headers (`x-headroom-bypass`,
`x-headroom-mode`, `x-headroom-user-id`, `x-headroom-stack`,
`x-headroom-base-url`) before the upstream call. Stops fingerprinting
of the proxy by subscription-revocation enforcers and prevents leakage
of internal user-id / stack / base-url internals to whichever vendor
terminates the request.

Python:
- `_strip_internal_headers(headers)` in `headroom/proxy/helpers.py`
  returns a NEW dict with `x-headroom-*` keys removed (case-insensitive
  prefix match, no regex). Pure function. Operator opt-in
  `HEADROOM_STRIP_INTERNAL_HEADERS=disabled` keeps internal headers in
  the upstream-bound dict for diagnostic shadow tracing — explicit, not
  a fallback.
- Strip applied at every handler entry capture in `anthropic.py`,
  `openai.py`, `batch.py`, `gemini.py` (chat completions, responses,
  WebSocket handshake, Copilot passthrough, batch passthroughs, Gemini
  generate / stream / countTokens / cloudcode-assist, Anthropic
  passthrough + batch results). Inbound reads of x-headroom (bypass
  gating, memory user-id) migrated to `request.headers.get(...)` so
  they continue working off the original dict.
- `log_outbound_headers` emits `event=outbound_headers forwarder=...
  stripped_count=N request_id=...` per call. Never logs header values.

Rust (crates/headroom-proxy):
- `strip_internal_headers(&mut HeaderMap)` and `is_internal_header`
  helpers in `src/headers.rs`. `build_forward_request_headers` accepts
  a `strip_internal: bool` so the same path serves HTTP and WebSocket.
- `Config::strip_internal_headers: StripInternalHeaders` driven by CLI
  flag `--strip-internal-headers` and env var
  `HEADROOM_PROXY_STRIP_INTERNAL_HEADERS` (default `enabled`).
- `proxy.rs` and `websocket.rs` call `build_forward_request_headers`
  with the resolved policy; structured `tracing::info!` /
  `tracing::warn!` line per request describes the strip decision.

Tests: 24 Python (`tests/test_header_isolation.py`) + 4 Rust
integration (`crates/headroom-proxy/tests/integration_headers.rs`) +
4 Rust unit tests in `headers.rs`. Covers every named header
(`bypass`, `mode`, `user-id`, `stack`, `base-url`), case-insensitive
prefix matching, legitimate-headers passthrough, the `disabled`
operator-opt-in mode, and that the inbound bypass-gating read path
is unaffected by the strip.

Acceptance: targeted `pytest -x` suite green (87 tests across
test_header_isolation, test_proxy_byte_faithful_forwarding,
test_proxy_anthropic_cache_stability, test_proxy_system_prompt_immutable,
test_proxy_openai_cache_stability, test_proxy_pipeline_lifecycle).
`cargo test -p headroom-proxy` green (23 tests across all integrations
plus 7 lib unit tests). `cargo clippy -p headroom-proxy -- -D warnings`
clean. `cargo fmt --all -- --check` clean. `cargo test --workspace`
green (~900 tests total).

Per realignment build constraints: configurable (env + CLI), no
hardcodes, no regex (pure `.lower().starts_with()` match), no silent
fallbacks (`disabled` is loud operator opt-in), structured logs
(`event=outbound_headers`).

Remaining `x-headroom-` references in `headroom/proxy/handlers/` are
inbound-read sites only: `request.headers.get("x-headroom-bypass")` /
`x-headroom-mode` for behavior gating, `request.headers.get
("x-headroom-user-id")` for memory user-id resolution, and `ws_headers
.get(...)` on the WebSocket inbound path. Response-side `X-Headroom-*`
injection (e.g. `x-headroom-tokens-saved`) is unrelated to upstream
forwarding and untouched.
2026-05-02 09:35:27 -07:00
..
agno.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
anthropic-sdk.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
api-reference.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
architecture.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
benchmarks.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
cache-optimization.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
ccr.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
code-compression.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
community-savings.mdx tokens saved grid 2026-04-12 13:42:20 +06:00
configuration.mdx fix: A5 — strip x-headroom-* from upstream-bound headers (P5-49) 2026-05-02 09:35:27 -07:00
context-management.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
docker-install.mdx docs: port Docker-native, filesystem-contract, and persistent-installs pages to Fumadocs 2026-04-20 23:05:15 -07:00
errors.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
failure-learning.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
filesystem-contract.mdx docs: port Docker-native, filesystem-contract, and persistent-installs pages to Fumadocs 2026-04-20 23:05:15 -07:00
how-compression-works.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
image-compression.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
index.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
installation.mdx docs: port Docker-native, filesystem-contract, and persistent-installs pages to Fumadocs 2026-04-20 23:05:15 -07:00
langchain.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
limitations.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
litellm.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
mcp.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
memory.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
meta.json docs: port Docker-native, filesystem-contract, and persistent-installs pages to Fumadocs 2026-04-20 23:05:15 -07:00
metrics.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
openai-sdk.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
persistent-installs.mdx docs: port Docker-native, filesystem-contract, and persistent-installs pages to Fumadocs 2026-04-20 23:05:15 -07:00
proxy.mdx feat: add Pi/Codex and Cloud Code Assist compatibility routes 2026-04-17 17:45:08 +00:00
quickstart.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
releases.mdx ci: publish Python distributions to GitHub releases 2026-04-20 23:32:31 -05:00
shared-context.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
simulation.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
smart-crusher.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
strands.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
text-and-logs.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
troubleshooting.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00
vercel-ai-sdk.mdx new docs UI + ts doc coverage 2026-04-12 13:15:58 +06:00