feat(config): session correlation header injection configuration#197
feat(config): session correlation header injection configuration#197
Conversation
c24a0fd to
c08f291
Compare
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.
c08f291 to
3ea7428
Compare
| --session-id-inject-target "domain=mydeployment.coder.com path=/api/v2/aibridge/*" \ | ||
| --allow "domain=mydeployment.coder.com" -- python train.py |
There was a problem hiding this comment.
Would it make sense to set automatically --session-id-inject-target with whatever domain is set via --allow?
| Flag: "", // No CLI flag, YAML only. | ||
| Description: "Inject targets from config file (YAML only).", | ||
| Value: &cliConfig.InjectSessionIDTargets, | ||
| YAML: "session_id_inject_targets", |
There was a problem hiding this comment.
Couldn't this be merged with the CLI session-id-inject-target? Is this a common pattern in coder to have separate CLI vs YAML options?
| userInfo := GetUserInfo() | ||
|
|
||
| // Build session correlation config from CLI and YAML sources. | ||
| sc, err := buildSessionCorrelation(cfg, os.Environ()) |
There was a problem hiding this comment.
nit: os.Environ() is hardcoded here, making NewAppConfigFromCliConfig untestable for the CODER_AGENT_URL fallback path 🤔 Maybe we can pass environ []string as a parameter and use os.Environ() from the caller?
| // Build session correlation config from CLI and YAML sources. | ||
| sc, err := buildSessionCorrelation(cfg, os.Environ()) | ||
| if err != nil { | ||
| return AppConfig{}, fmt.Errorf("session correlation config: %w", err) |
There was a problem hiding this comment.
nit: This should hint at the fix, e.g. "...set --session-id-inject-target or ensure CODER_AGENT_URL is set".
| ) | ||
| } | ||
| switch key { | ||
| case "domain": |
There was a problem hiding this comment.
There is an edge case here, imagine --session-id-inject-target "domain=staging.coder.com domain=prod.coder.com", domain will be overwritten. Probably worth checking for duplicates and adding a test case for this
| } | ||
|
|
||
| return &InjectTarget{ | ||
| Domain: u.Hostname(), |
There was a problem hiding this comment.
IIUC inject target basically defines which outbound HTTP requests should receive the session correlation headers, but we are stripping the port here. What happens if coder runs on a non-standard port?
| } | ||
|
|
||
| // Apply defaults for header names. | ||
| sessionIDHeader := cfg.SessionIDHeaderName.Value() |
There was a problem hiding this comment.
Do we want to make the headers configurable? This means a user could set existing headers for the correlation, like the "Authorization" header, for instance. Also, since this is for correlation with Coder, I assume we would also need to set this on Coder side. So it makes sense to have an agreement on both parts for the same header value, right?
| } | ||
| } | ||
|
|
||
| func TestBuildSessionCorrelation_AgentURLFallback(t *testing.T) { |
There was a problem hiding this comment.
I think we are missing a test for merging CLI and YAML configs.
PR Map
RFC: Bridge ↔ Boundaries Correlation
Add YAML and CLI configuration surface for session correlation header injection per FR 2 of the RFC.
Depends on #196.
Changes
config/session_correlation.go: New file. DefinesSessionCorrelationConfig,InjectTarget,ParseInjectTarget,ValidateSessionCorrelation, default header name constants (X-Coder-Agent-Firewall-Session-Id,X-Coder-Agent-Firewall-Sequence-Number), andDefaultInjectTargetFromEnv— a helper that derives a default inject target fromCODER_AGENT_URLwhen no explicit targets are configured.config/session_correlation_test.go: New file. Table-driven tests forParseInjectTarget,ValidateSessionCorrelation, the end-to-endNewAppConfigFromCliConfigsession correlation path,DefaultInjectTargetFromEnv, and thebuildSessionCorrelationCODER_AGENT_URLfallback path.config/config.go: Wire session correlation fields intoCliConfig(five new fields for serpent bindings) andAppConfig(newSessionCorrelationfield). AddbuildSessionCorrelationhelper that merges YAML+CLI inject targets, falls back to a target derived fromCODER_AGENT_URLwhen none are configured and session correlation is enabled, applies header name defaults, and validates the result. The helper acceptsenviron []stringexplicitly so callers and tests can supply a controlled environment.cli/cli.go: Register five new serpent options and add usage examples including a zero-config workspace example.New CLI flags
--enable-session-correlationBOUNDARY_SESSION_CORRELATION_ENABLEDsession_correlation_enabledfalseCODER_AGENT_URL(set automatically in Coder workspaces)--session-id-inject-targetBOUNDARY_SESSION_ID_INJECT_TARGETdomain=<host> [path=<glob>]session_id_inject_targets--session-id-header-nameBOUNDARY_SESSION_ID_HEADER_NAMEsession_id_header_nameX-Coder-Agent-Firewall-Session-Id--sequence-number-header-nameBOUNDARY_SEQUENCE_NUMBER_HEADER_NAMEsequence_number_header_nameX-Coder-Agent-Firewall-Sequence-NumberConfig validation ensures that when correlation is enabled at least one inject target is present (either explicit or auto-derived from
CODER_AGENT_URL), and header names are non-empty. Parsing validates thedomain=... path=...key-value format and rejects unknown keys.This commit adds config and validation only; runtime injection is wired in a follow-up PR.
Note
This PR was authored by Coder Agents.