AxonFlow v9.11.0 — streaming prompt-DLP, seam-capability obligations & fleet-identity fixes
[9.11.0] - 2026-07-17 (streaming prompt-DLP, seam-capability obligations & Path B fleet-identity fixes)
Makes inline prompt-DLP work on streaming LLM chat, moves the "what happens when a seam can't redact" decision from the enforcement point back into the platform behind an org-configurable posture, closes a class of governance-signal gaps where a matched PII policy could return a bare allow, and fixes the SSO/SCIM org-key and role-seeding defects that blocked fleet OIDC (Path B). Migrations core/144–core/147 (existence-guarded, with down migrations). Three deliberate behavior changes — see Changed.
Added
- Streaming-safe ext_proc request redaction for SSE completions (Enterprise). (Enterprise) The
axonflow-gateway-adaptersext_proc seam now validates gateway body modes per direction instead of OR-ing them:requestBodyMode: buffered+responseBodyMode: noneis accepted under a new adapter-side opt-in,AXONFLOW_EXTPROC_RESPONSE_GOVERNANCE=off(defaultbufferedkeeps today's fully-governed contract; any other value refuses to boot). On such a leg the prompt is still decided and engine-redacted in full before the provider sees it — deny blocks pre-stream,AXONFLOW_FAIL_MODEand the body-size bound unchanged — while the completion streams back as SSE with no adapter latency. The response body is not scanned on an opted-innoneleg; the posture is logged at startup and once per stream. This is the seam for inline prompt-DLP on streaming LLM chat, which previously required disabling body inspection entirely. - Seam-capability–aware obligations +
obligation_fallbackposture (Enterprise). (Enterprise)POST /api/v1/decidenow emits only the obligations the calling seam can fulfill: a PEP advertises its seam viaDecideRequest.fulfillment_capabilities(vocabularyrequest_body_redaction,request_header_mutation; a capability-aware seam always advertises ≥1). A request-body redaction suppressed on a non-body-capable seam (e.g. Envoy ext_authz, headers-only) applies the org's newobligation_fallbackdetection-posture category —log(default: allow, no obligation, canonical audit row records the suppressed redaction + detected categories) orblock(deny) — resolved server-side from the org, never from the request. Absent/empty capabilities = legacy caller, byte-identical pre-9.11.0 behavior (all SDKs unaffected). The gateway adapter's localallow → 403conversion is deleted; a never-fires fail-closed backstop remains for platform-version skew. Advertised as capabilityseam_capability_decisioning. Portal: Settings → Governance → Detection Posture; migrationcore/144. - Per-org fleet system roles seeded + non-fleet SCIM role mappings rejected (Enterprise). (Enterprise) Every organization now has the six fleet system roles (
admin,owner,policy_admin,developer,member,viewer) via an org-creation trigger + one-time backfill (core/146), soGET /api/v1/scim/rolesreturns a mappable set and Path B group→role mapping works on every org. Mapping a SCIM group to a non-fleet role name is rejected with400instead of silently dropping members to least privilege. caller_namereplaces the misnamedtool_typeon the tool-call audit surface (Community). (Community) Theaudit_tool_callMCP tool and the orchestratorToolCallAuditEntrygain acaller_namefield identifying which client/integration made the call (e.g.claude_code,codex,cursor,openclaw).tool_type— which every real caller used to identify itself, never to classify a tool — is soft-deprecated: still accepted as a legacy input fallback, but no longer authoritative. The value is resolved centrally in the orchestrator through the chaincaller_name→ legacytool_type→ an"unknown"terminal default; an unidentified caller is no longer attributed to the specific clientclaude_code. New audit rows writepolicy_details.caller_nameand no longer writepolicy_details.tool_type. SIEM impact: consumers keying onpolicy_details.tool_typefor tool-call attribution must move topolicy_details.caller_name; unattributed calls now readcaller_name = "unknown"rather thantool_type = "claude_code". Historical rows are not backfilled, and the WCP/HITL plane still writes a genuinetool_typecall-kind (function/mcp/api), which is unaffected. In the portal audit detail (Enterprise), a new-style row surfaces its client under a Client row while a WCPtool_typestays under Tool type — the two render as independent rows.- Response-plane two-field tool identity on check-output (Community). (Community)
MCPCheckOutputRequestgains atoolfield (mirroring the check-inputserver/toolsplit added in 9.10.0), threaded into the response-plane capability-scoping identity so it staysserver.toolonce the langgraph de-concatenation SDKs — which send bareserverplus atoolkey the platform previously ignored — ship. Without it those SDKs degrade response-plane scoping toserver, re-running execution-class detectors on document-classified tool output and regressing the documentation false-positive hardening for LangGraph users. - Client support for
caller_name(dual-send). The Claude Code, Cursor, Codex, and OpenClaw plugins addcaller_nameto theiraudit_tool_callpayloads, dual-sent alongside the legacytool_typefor the deprecation window. Attribution is exact on a 9.11.0+ platform (wherecaller_namewins) and unchanged on any pre-9.11.0 platform (where the legacytool_typestill attributes the row), so the plugin minors can ship independently of a customer's platform upgrade without an attribution regression;tool_typeis dropped in a later plugin release once the platform floor includes this change. Ships as Claude Code 1.11.0, Cursor 1.7.0, Codex 1.7.0, OpenClaw 2.8.0;/healthrecommendations advertise these plus the 9.0.0 SDK majors (go/python/typescript/java — langgraph de-concatenation; rust unchanged at 0.8.1; min floors unchanged).
Changed
- Behavior change — ext_proc
responseBodyMode: nonenow requires the adapter opt-in (Enterprise). (Enterprise) Earlier adapters accepted anoneresponse advertisement silently (the response plane simply never ran), so a gateway-config edit alone could switch response governance off. Anoneleg is now rejected fail-closed unless the adapter runs withAXONFLOW_EXTPROC_RESPONSE_GOVERNANCE=off— deployments already runningresponseBodyMode: nonemust set the variable when upgrading the adapter. Partial modes (bufferedPartial,streamed,fullDuplexStreamed) remain rejected in both directions and both postures. - Behavior change —
pii-indonesiais now evaluated on the proxy and OpenAI-compatible planes (Community). (Community) Those planes hand-listed their PII categories and omittedpii-indonesia; all request planes now converge on one canonical PII category set. Under the defaultredactposture a matched KTP/NIK is now redacted on those planes (previously forwarded untouched); under ablockposture those planes now deny KTP/NIK traffic they previously forwarded — the largest-impact change in this release; review your Indonesian-PII posture before upgrading. Underwarn/logthese planes gain evaluation + telemetry parity only (no new redactions). Relatedly,warn/logPII postures no longer silently redact — they emit an advisory reason and leave content unmodified. - Behavior change — headers-only seams default to
log, not deny, on an unmaskable redaction (Enterprise). (Enterprise) Where the gateway adapter previously converted an allow-with-redaction into a local 403 on a headers-only seam, the platform now applies the org'sobligation_fallbackposture, defaultlog(allow + audited suppressed-redaction). Setobligation_fallback = blockto restore deny-on-unmaskable. - Advertised plugin recommendations updated to the published v9.10.0-train versions — claude-code 1.10.0, cursor 1.6.0, codex 1.6.0, openclaw 2.7.0 (claude-desktop stays 0.3.1); min floors unchanged.
Fixed
- Matched PII policy can no longer yield a bare allow (Community). (Community)
/api/v1/decidereturnedallowwith no obligation and no reason whileevaluated_policiesnamed a matched, block-configured Indonesian KTP policy: the obligation bridge classified PII with a duplicate agent-local category switch that omittedpii-indonesiaand derived redaction from category rather than the resolved action. The duplicate predicate is deleted (converged on the shared prefix predicate), the verdict mapping is action-aware (redact⇒ obligation,warn/log/other ⇒ advisory reason,block⇒ deny), and a registry cross-check + class guard pin that a matchedpii-*policy always produces a governance signal. Code-only. - In-VPC Path B / OIDC: SSO configuration org key decoupled from tenant id (Enterprise). (Enterprise) The portal wrote a deployment-collapsed tenant sentinel into
sso_configurations.org_id(the RLS isolation key), so org-scoped readers missed the row and the fleet OIDC verifier rejected every in-VPC Path B token fail-closed.org_idnow always carries the real org; migrationcore/145repairs sentinel rows in place. - SCIM
role_assignments.org_idkeyed on the real org, not the portal tenant id (Enterprise). (Enterprise) The SCIM plane wroterole_assignments.org_idfrom the session tenant while the fleet role resolver reads by authenticated org — where the two diverge, Path B developers silently resolved to least privilege. Writes now key on the real org across both the session and bearer/IdP-sync paths (the bearer tenant→org lookup runs on the BYPASSRLS admin pool and fails closed on resolution errors),SyncUserRolesvalidates mapped roles under the org, and migrationcore/147repairs historically mis-keyed rows (skipped rows are reported for operator re-sync). - Migration
enterprise/117made idempotent + migration-wait hardened (Community). (Community) FiveCREATE POLICY+ twoCREATE TRIGGERstatements had no drop-guards, so a container recreate mid-migration left objects created but the migration unrecorded — bricking every subsequent boot; the SDK-smoke workflow also polled/health, which the agent serves before migrations complete. Both layers fixed.
Full release notes: https://docs.getaxonflow.com/docs/releases/v9-11-0
Upgrade guidance: see the Upgrading section of the release notes. AxonFlow is source-available under BSL 1.1.