Per-Org Detection Posture
Concept page. This explains how one deployment can enforce different detection actions for different teams. For the detectors themselves, see PII Detection; for how each decision is recorded, see Audit Logging.
Available on platform v8.7.0+.
A single AxonFlow deployment often serves more than one team, and those teams do not always want the same enforcement behavior. A customer-facing chat assistant usually wants PII redacted so the conversation keeps flowing; a nightly batch export usually wants the same PII to block the job outright. Before v8.7.0 the detection action was a single deployment-wide setting (PII_ACTION and the related SQLi / dangerous-operation levers), resolved once at boot — so those two teams could not coexist on one platform.
Detection posture makes the enforcement action per-organization and per-category. Each org can override the deployment-global action for a specific detection category; anything it does not override inherits the deployment default.
The model
The effective action for a given (org, category) is resolved as:
effective action = per-org override ELSE deployment-global default
- The deployment-global default is the platform-wide setting (
PII_ACTIONfor PII; the equivalent levers for the other categories). It is the baseline every org starts from. - A per-org override replaces that baseline for one category, for one organization. Set none and the org is byte-for-byte identical to today's behavior.
Overrides are stored per organization with row-level security, so one org can never read or set another org's posture.
Categories you can set
| Category | What it governs |
|---|---|
pii | PII detection / redaction (the PII_ACTION lever) |
sqli | SQL-injection detection on request statements |
dangerous_query | Dangerous database operations (e.g. DROP TABLE) |
dangerous_command | Dangerous shell / command patterns |
obligation_fallback | Not a detector. What to do when a policy decided a request body must be redacted but the calling enforcement point structurally cannot mask it (e.g. an Envoy ext_authz leg, which is headers-only). Accepts block or log only — default log. Requires platform ≥ 9.11.0. See Decision Mode → Seam capabilities. |
Actions you can set
| Action | Behavior |
|---|---|
block | Hard-deny the request (or response) when the category matches. |
redact | Mask the matched value and continue. |
warn | Detect and record, but do not modify content. |
log | Detect and record only (lowest-friction). |
Not every action is meaningful for every category. obligation_fallback accepts only block and log: redact is precisely what the seam in question cannot do, and warn has no enforcement distinct from log on that axis. The API rejects the other two for that category and names the ones it accepts.
There is no "governance off" action — a category is always at least detected and recorded. To run a category permissively, set it to warn or log; you cannot disable detection through posture.
Where posture is enforced
A team's posture has to hold on every path a request can take, not just the one someone happened to test. v8.7.0 wires the per-org override into all three enforcement planes:
| Plane | What it covers |
|---|---|
| Agent request/response | The MCP check-input / check-output paths, the Gateway pre-check, POST /api/v1/decide, the proxy, the policy-test surface, and the OpenAI-compatible endpoint. |
| Orchestrator response redaction | The proxy / gateway / MAP LLM-response redaction plane, which runs in a separate binary from the agent and previously always used the deployment-global action. |
| Customer-portal write path | The authenticated surface platform teams use to set posture (below). |
Because the agent and the orchestrator are separate processes, an override is applied independently on each. On the hot path neither process makes a per-request database call — each holds a short-TTL per-org cache and fails safe to the deployment-global action if a posture lookup ever errors, so a transient database issue can never silently drop enforcement to a weaker action.
Setting posture from the portal
Enterprise. The customer portal exposes a Detection Posture page under Settings → Governance (/settings/detection-posture). For each category you can pick an action or leave it on Default (inherit the deployment-global baseline).
The write path is authenticated and gated by the sso:configure permission — the same gate as SCIM token management — so only a user who can already configure identity for the org can change its enforcement posture. The organization is taken from the authenticated session, never from a request header or body, so a spoofed X-Tenant-ID can't steer the write to another org.
Posture changes propagate to the enforcement planes within the cache TTL (a short, bounded staleness window — seconds, not minutes). The TTL is deployment-tunable via AXONFLOW_DETECTION_OVERRIDE_TTL_SECONDS (default 60s).
The API surface
| Method | Endpoint | Purpose |
|---|---|---|
GET | /api/v1/detection-posture | List the org's current per-category overrides. |
PUT | /api/v1/detection-posture/{category} | Set the action for one category. |
DELETE | /api/v1/detection-posture/{category} | Clear the override (revert the category to the deployment default). |
All three require an authenticated session with sso:configure. A request without the permission returns 403; an unauthenticated request returns 401.
The API accepts only the supported categories and actions documented above. Invalid categories return 400 with INVALID_CATEGORY; invalid actions return 400 with INVALID_ACTION. There is no off action. Deleting an override is the way to return a category to the deployment-global default.
Each set or delete attempt is recorded as an admin audit event:
DETECTION_POSTURE_SETDETECTION_POSTURE_DELETE
Audit details include the category and, for set operations, the new action. The audit path records both success and failure outcomes and does not include secrets.
A concrete example
A deployment runs PII_ACTION=redact globally — a sensible default that keeps interactive products usable. One org, nightly-exports, runs a batch pipeline where any PII in the output is a compliance incident, not something to mask:
- A platform owner for
nightly-exportsopens Settings → Governance → Detection Posture. - They set PII to Block.
- The override is written for
(nightly-exports, pii). - Within the cache TTL, every plane — agent request/response, orchestrator LLM-response redaction — enforces block for that org's PII, while every other org continues to redact.
No deployment restart, no global config change, no impact on any other tenant.
Community vs Enterprise
| Capability | Community | Enterprise |
|---|---|---|
Deployment-global detection action (PII_ACTION, SQLi, dangerous-op levers) | ✅ | ✅ |
| Per-org / per-category posture enforcement (agent + orchestrator planes) | ✅ | ✅ |
Portal write path to set posture (/settings/detection-posture, sso:configure) | ✅ |
The enforcement planes are part of the platform binaries, so per-org posture is honored in both editions. The authenticated portal surface for setting posture is part of the Enterprise customer portal; a Community deployment can seed overrides directly.
See also
- PII Detection — what each detector matches, and the context-gating that prevents false positives
- Audit Logging — how an enforcement action is recorded
- SCIM 2.0 Provisioning — the
sso:configurepermission and group-to-role mapping - Decision Mode architecture — the PDP/PEP request and response planes posture applies to
Rollout Checklist
Use this page as one layer of the broader governance rollout:
- decide where the rule belongs with Policy Hierarchy
- test the request path with Runtime Request Paths
- connect review workflows to HITL Approval Gates when a block should become a human decision
- compare Community vs Evaluation vs Enterprise when simulation, evidence export, SSO, SCIM, or portal operations become requirements
