Skip to main content

AxonFlow v9.9.0 Release Notes

v9.9.0 is a minor release centered on identity attribution and a related security hardening. Per-user audit attribution — the user_email and session_id recorded on every governed action — is now unified across all four governance planes (/api/v1/decide, MCP check-input, MCP check-output, and the MCP-server tools/call path) behind a single opt-in trust gate, and a forged-identity session-override hijack is closed across the request-plane governance and workflow endpoints.

There are no database migrations. This release does carry a deliberate behavior change: the planes that previously honored client-asserted identity headers unconditionally now ignore them unless you opt in — see Upgrading. No SDK or plugin releases ride this train; the compatibility matrix advertised on /health is unchanged from v9.8.0.

Fixed

Per-user audit attribution unified across all four planes, behind a trust gate (Community)

The client-asserted X-User-Email / X-Session-Id / X-User-ID headers were honored on only two of the four governance planes — MCP check-input and MCP-server tools/call read them unconditionally, while /api/v1/decide and MCP check-output ignored them entirely. That split had two consequences: a policy-enforcement point that fronts many principals behind one org:license credential (for example the Claude Desktop governance proxy, which calls only decide + check-output) silently lost per-user attribution — every action landed on the fleet service identity; and on the two planes that did read the headers, any governed caller could assert another principal's identity in the audit trail.

v9.9.0 routes all four planes through one shared trust gate, AXONFLOW_TRUST_IDENTITY_HEADERS (default off; only the exact string true opts in — the same contract as the v9.8.0 gateway adapters):

  • Gate on — the headers attribute audit_logs.user_email / session_id on every plane, and per-user features (session overrides, user-scoped dynamic policies) key on that trusted identity. A trusted header can set the audit identity but can never influence a verdict, an authorization decision, policy selection, or tenant/org resolution — attribution only.
  • Gate off (default) — the identity headers are ignored on every plane 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.

No platform-synthesized shared identity (the client-scoped fallback identities, internal-service identities, or the local-dev identity when asserted outside community mode) can create or apply a per-user session override — a shared identity's override would otherwise affect every caller on the client.

Forged-identity session-override hijack closed (Community)

Because two planes trusted the identity header unconditionally, a governed caller could assert a colleague's identity and cause that colleague's active session override to be applied to the caller's own blocked request — flipping a denied action to allowed. v9.9.0 closes this at every layer: the per-user identity that keys an override is honored only from a trusted source (behind the gate), the agent proxy strips forgeable per-user identity headers on every proxied route when the gate is off (the auth-derived tenant/org headers and the internal proxy-auth token are never touched), and every orchestrator ingress that can apply a session override — override create, the workflow step-gate, plan-execute and plan-resume, and the workflow checkpoint-resume paths — now requires the agent gateway's signed proxy token, so a caller reaching the orchestrator directly cannot forge the override identity (Community-mode deployments are exempt, matching existing internal-service enforcement).

Upgrading

v9.9.0 is a drop-in upgrade from v9.8.x — no migrations, no configuration changes required.

# Community
docker compose pull && docker compose up -d

# Enterprise
docker compose -f docker-compose.yml -f docker-compose.enterprise.yml pull
docker compose -f docker-compose.yml -f docker-compose.enterprise.yml up -d

Behavior change — per-user attribution now requires an explicit opt-in. If your deployment relies on plugin- or proxy-supplied identity headers for per-user audit attribution (or for per-user session overrides / user-scoped dynamic policies), set AXONFLOW_TRUST_IDENTITY_HEADERS=true on the agent after upgrading. Until you do, those features fall back to the client-scoped identity and new rows record no per-session session_id. The previous always-trust behavior was a forgery exposure and is deliberately not preserved.

How much to worry about the trust boundary. For a small team or individual deployment, enabling the gate is fine out of the box — the "a colleague forges my identity header" concern is largely theoretical when you trust everyone who can reach the agent. At fleet scale, where an insider forging another principal's identity is a real risk, source the identity from a place the end user cannot edit — MDM/JumpCloud-managed plugin settings, or a gateway that sets it from a validated JWT. That is a scale-dependent hardening, not a prerequisite for turning the gate on.

The flag is exposed as a parameter in the CloudFormation templates and the install bundle (AXONFLOW_TRUST_IDENTITY_HEADERS, default false); it must remain false on any public multi-tenant deployment.