Skip to main content

Decision Types

Reference

Every audit event records a decision — the outcome of evaluating the request against your policies.

Decision types

DecisionMeaning
AllowRequest passed all policy checks and was forwarded to the upstream
DenyRequest 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
AuditRequest was allowed but flagged — typically by an audit-mode rule or anomaly detection
WarnRequest 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).

note

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:

SetDecisions
Quiet (no human involved)Allow, Mutated, Cache Hit, Audit, Allowed by Exception
Human-involvedDeny, 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 bothException 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 nameDecisionFires when
unverified-identityDenyidentity.requireVerifiedIdentity is enabled and the request's identity was not cryptographically or credential-verified
mcp-ssrf-guardDenyThe always-on SSRF floor blocked an MCP tool call whose URL argument resolved to a private, loopback, or internal address
egress-warn-fallbackDenynetworkFilter.warnFallback: deny is set and an outbound HTTP(S) call matched no egress policy that gave a definitive allow or deny
note

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).

See also