v9.9.0 — per-user audit attribution unified + session-override hardening
[9.9.0] - 2026-07-11 (per-user audit attribution unified + session-override forgery hardening)
Security + correctness. v9.9.0 unifies per-user audit attribution across all four governance planes behind an opt-in trust gate (AXONFLOW_TRUST_IDENTITY_HEADERS, default off), and closes a forged-identity session-override hijack — a deny→allow flip in which one governed user could apply another user's active session override — across the request-plane governance and workflow endpoints. No database migration. Behavior change: the planes that previously honored client-asserted identity headers unconditionally now ignore them unless the gate is on — set AXONFLOW_TRUST_IDENTITY_HEADERS=true on the agent (after confirming your identity source is trusted) to retain per-user attribution.
Fixed
- Per-user audit attribution unified across all four governance planes, behind a trust gate. (Community) The client-asserted
X-User-Email/X-Session-Id/X-User-IDheaders were honored on only two of the four governance planes — MCP check-input and MCP-servertools/callread them unconditionally, while/api/v1/decideand MCP check-output ignored them entirely. The split had two consequences: PEPs that front many principals behind one org:license credential (the Claude Desktop proxy calls only decide + check-output) silently lost per-user attribution — every action attributed to the fleet service identity — and on the two planes that did read the headers, ANY governed caller could forge another principal's audit identity, including hijacking another user's active ADR-044 session override (a deny→allow flip keyed on the unvalidated header). All four planes now resolve the headers through one shared trust gate,AXONFLOW_TRUST_IDENTITY_HEADERS(default off; only the exact stringtrueopts in — the same contract as the 9.8.0 gateway adapters): with the gate on, the headers attributeaudit_logs.user_email/session_idon every plane, and per-user features (ADR-044 session overrides, user-scoped dynamic policies) key on that trusted identity — a forged header can never influence a verdict, authz decision, policy selection, or tenant/org resolution; with the gate off, the headers are ignored everywhere and attribution falls back to the validated identity, with a once-per-process detection warning when a request carries identity headers so an operator never silently loses attribution. Additionally, no platform-synthesized SHARED identity — themcp-client:<client-id>pseudo-identity, the<client-id>@axonflow.local/unknown@axonflow.localservice fallbacks, the internal-service and community-SaaS evaluator identities, or the communitylocal-devidentity when asserted outside community mode — can create, be offered, or apply an ADR-044 session override on any plane; a shared identity's override would flip a deny for every caller on the client. And every orchestrator ingress that keys an ADR-044 override apply — override-create, the WCP step-gate, the MAP confirm-mode plan-execute and plan-resume, and both workflow checkpoint-resume paths (which re-evaluate a step under the checkpoint's stored actor identity) — now requires the Agent gateway's HMAC proxy token, so a caller reaching the orchestrator directly cannot forge the override identity (Community mode is exempt, matching the existing audit-tool-call enforcement). The MAP execute path additionally derives the checkpoint's actor email from the trust-gatedX-User-Emailheader rather than the request body, closing a channel the header gate does not cover. Complementing that, the Agent proxy now trust-gates the per-user identity headers (X-User-Email/X-User-ID/X-Session-Id) on every proxied route rather than a per-prefix allowlist: with the gate off (default) a forged per-user identity is stripped before it can reach any orchestrator route, and the auth-derived tenant/org headers and the proxy-auth token are never touched. Advertised as theidentity_header_attributioncapability. Upgrade note: deployments relying on plugin-supplied identity headers must setAXONFLOW_TRUST_IDENTITY_HEADERS=trueon the agent after confirming their identity source is trusted (MDM-managed plugin fleet, desktop proxy, gateway jwtAuth) — until then, per-user attribution, the session-summary/Claude-Code dashboards' per-session drill-down (session_idstays NULL on new rows), and per-user session overrides all fall back to the client-scoped identity. The previous always-trust behavior was a forgery exposure and is deliberately not preserved.
Full notes: https://docs.getaxonflow.com/docs/releases/v9-9-0