Decision Types
Every audit event records a decision — the outcome of evaluating the request against your policies.
Decision types
| Decision | Meaning |
|---|---|
| Allow | Request passed all policy checks and was forwarded to the upstream |
| Deny | Request was blocked by a policy or budget rule; the caller received an error. An outbound network call blocked by the network egress filtering proxy — either the always-on SSRF floor or an egress policy — also records a Deny, distinguished from MCP/LLM denials by a request type of egress in the audit API |
| Audit | Request was allowed but flagged — typically by an audit-mode rule or anomaly detection |
| Warn | Request was allowed with a warning appended to the response |
Ask (warn-ask) | Request was paused and the user was asked to confirm inline; on confirmation the request proceeds and the event is recorded (appears as warn_confirm in the audit API). Produced by enforcement-mode: Ask (validationActions: [Warn] + proxy.nirmata.io/require-confirmation: "true", or the annotation value Ask/warn-ask). |
Approve (warn-approve, shown as Pending) | Request is waiting for human approval in the Approvals queue (appears as require_approval in the audit API). Produced by enforcement-mode: Approve/warn-approve. |
The proxy.nirmata.io/enforcement-mode annotation is case-insensitive and accepts either the short user-facing names (Deny, Approve, Ask, Warn, Audit) or their longer-form values (deny, warn-approve, warn-ask, warn, audit).
Policies written with the legacy annotation values enforcement-mode: require-approval or enforcement-mode: warn-confirm are still accepted and behave identically to Approve (warn-approve) and Ask (warn-ask) respectively — no action needed for existing policies.
Quiet confidence
The Security Posture dashboard and the weekly admin digest surface Quiet confidence — the percentage of call dispositions resolved with zero human involvement.
Decisions are split into three sets:
| Set | Decisions |
|---|---|
| Quiet (no human involved) | Allow, Mutated, Cache Hit, Audit, Allowed by Exception |
| Human-involved | Deny, Warn Approve (require_approval), Warn Ask (warn_confirm). Egress denials are included via Deny — they record a Deny with request type egress, not a separate decision |
| Excluded from both | Exception lifecycle rows — exception_requested, exception_granted, exception_partial_approval, exception_denied, exception_revoked, exception_expired |
Quiet confidence is quiet ÷ (quiet + human-involved), computed over the period window selected on the Security Posture dashboard. Exception-lifecycle rows are workflow bookkeeping, not call dispositions, so they never appear in the denominator — this makes the metric deliberately narrower than total call volume.
Synthetic policy names
Every audit event has a Policy field naming the rule that produced the decision. Most values are the name of a CEL policy you (or the built-in library) authored. A few reserved names come from proxy-level checks that aren't backed by an editable policy:
| Policy name | Decision | Fires when |
|---|---|---|
unverified-identity | Deny | identity.requireVerifiedIdentity is enabled and the request's identity was not cryptographically or credential-verified |
mcp-ssrf-guard | Deny | The always-on SSRF floor blocked an MCP tool call whose URL argument resolved to a private, loopback, or internal address |
egress-warn-fallback | Deny | networkFilter.warnFallback: deny is set and an outbound HTTP(S) call matched no egress policy that gave a definitive allow or deny |
Access Binding decisionMode values map onto these same decisions — Allow, Audit, and Warn behave exactly as above; RequireApproval produces Held; Deny blocks the request (invalid_grant at token issuance, or denied at the tool call).