Skip to content

feat(proxy): inject session ID and sequence number headers on matching requests#198

Draft
SasSwart wants to merge 2 commits intosasswart/feat-config-session-correlation-header-injectionfrom
sasswart/feat-proxy-inject-session-headers
Draft

feat(proxy): inject session ID and sequence number headers on matching requests#198
SasSwart wants to merge 2 commits intosasswart/feat-config-session-correlation-header-injectionfrom
sasswart/feat-proxy-inject-session-headers

Conversation

@SasSwart
Copy link
Copy Markdown
Contributor

@SasSwart SasSwart commented Apr 30, 2026

PR Map

  1. feat(audit): session ID generation, sequence counter, and BoundaryLog wiring #196
  2. feat(config): session correlation header injection configuration #197
  3. 👉🏼 feat(proxy): inject session ID and sequence number headers on matching requests #198

RFC: Bridge ↔ Boundaries Correlation

When session correlation is enabled and the outgoing request matches a configured inject target, set X-Coder-Agent-Firewall-Session-Id and X-Coder-Agent-Firewall-Sequence-Number headers on the forwarded request. Any values the jailed client may have set are overwritten so the upstream always sees boundary's authoritative session ID and sequence number.

Depends on #197.

Changes

  • audit/request.go: Add SequenceNumber *uint64 field to Request. When non-nil, the auditor uses this pre-allocated value instead of generating its own, so the audit log and the injected HTTP header carry the same sequence number.
  • audit/socket_auditor.go: Use req.SequenceNumber when present, falling back to s.seq.Next() for backward compatibility.
  • proxy/proxy.go:
    • Add SessionCorrelation, SessionID, SequenceCounter to Config and Server.
    • New shouldInjectHeaders(host, path) method: matches request host (case-insensitive, port-stripped) and optional path glob against configured InjectTargets.
    • processHTTPRequest pre-allocates a sequence number from the shared counter and passes it to both AuditRequest and forwardRequest.
    • forwardRequest stamps both headers on matching requests after copying client headers (overwriting any client-supplied values).
  • proxy/proxy_framework_test.go: Add WithSessionCorrelation, WithSessionID, WithSequenceCounter test options; wire them into the proxy Config.
  • proxy/proxy_session_correlation_test.go: New test file with six tests:
    • TestSessionCorrelation_MatchedDomain: headers injected on matching domain.
    • TestSessionCorrelation_UnmatchedDomain: headers absent on non-matching domain.
    • TestSessionCorrelation_Disabled: headers absent when correlation is disabled.
    • TestSessionCorrelation_OverwritesClientValue: proxy overwrites spoofed client headers.
    • TestSessionCorrelation_PathMatching: headers injected only when path glob matches.
    • TestSessionCorrelation_SequenceNumberIncrements: sequence numbers increment across requests.
Implementation notes
  • The sequence number is allocated once in processHTTPRequest via the shared SequenceCounter, then threaded through to both the auditor and the header injection site. This guarantees the audit event and the HTTP header always agree on the sequence number for a given request.
  • shouldInjectHeaders strips the port from the host before comparison and uses path.Match for glob matching, consistent with the RFC's path=/api/v2/aibridge/* syntax.
  • The SequenceCounter reference on the proxy is optional (*audit.SequenceCounter). When nil (e.g. in existing tests that don't care about session correlation), no sequence number is allocated and the auditor falls back to its internal counter.

Note

This PR was authored by Coder Agents.

Add YAML and CLI configuration surface for session correlation header
injection per the Bridge/Boundaries Correlation RFC (FR 2).

New configuration options:

- --enable-session-correlation / session_correlation_enabled: top-level
  toggle to disable injection entirely for deployments without AI Bridge
  in front.
- --inject-session-id-on / session_id_inject_targets (YAML): repeatable
  list of inject targets in "domain=<host> [path=<glob>]" format.
- --session-id-header-name / session_id_header_name: configurable header
  name (default X-Coder-Agent-Firewall-Session-Id).
- --sequence-number-header-name / sequence_number_header_name:
  configurable header name (default X-Coder-Agent-Firewall-Sequence-Number).

Config validation ensures that when correlation is enabled at least one
inject target is present and header names are non-empty. Parsing
validates the domain=... path=... key-value format and rejects unknown
keys.

This commit adds config and validation only; runtime injection is wired
in a follow-up PR.
…g requests

When session correlation is enabled and the outgoing request matches a
configured inject target, set X-Coder-Agent-Firewall-Session-Id and
X-Coder-Agent-Firewall-Sequence-Number headers on the forwarded request.
Any values the jailed client may have set are overwritten so the upstream
always sees boundary's authoritative session ID and sequence number.

The sequence number is pre-allocated before the audit event so both the
audit log and the injected header carry the same value. audit.Request
gains a SequenceNumber pointer field; when non-nil the socket auditor
uses it instead of calling its own counter.

New proxy.Config fields: SessionCorrelation, SessionID, SequenceCounter.
New Server method: shouldInjectHeaders (domain + optional path glob
matching).

Tests cover matched domain, unmatched domain, disabled injection,
client-supplied header overwrite, path glob matching, and sequence
number incrementing.
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.

1 participant