Skip to main content

Policy Governance

Production policy changes never go straight to live. Adjudon's Policy Engine enforces a multi-stakeholder workflow that mirrors the role-separation auditors expect under EU AI Act Art. 14, BaFin MaRisk AT 4.3.1, and DORA Art. 8(4).

The 3-role separation

Every promotion to live (or to a canary % above 0) requires three distinct humans on Governance and Enterprise tiers:

RoleWhat they doGate
AuthorDrafts the policy, runs dry-runs, attaches regression testsSubmits the approval request
ReviewerInspects the proposed change against business intent + risk registerApproves or rejects
EnforcerConfirms operational readiness and authorizes the production cutoverPromotes to live

Backend enforcement: policyApprovalService rejects the action with one of two error codes — AUTHOR_REVIEWER_SAME_PERSON (when submittedBy === reviewedBy) or AUTHOR_ENFORCER_SAME_PERSON (when submittedBy === enforcedBy). Both return HTTP 403.

Workflow states

draft
↓ submit
pending_review
↓ reviewer-approve ↓ reviewer-reject
pending_enforce rejected
↓ enforcer-promote ↓ enforcer-reject
approved (live) rejected

The author can also withdraw a request before either reviewer or enforcer acts.

Break-glass

When the situation requires immediate enforcement and a normal approval flow is not feasible, an admin or owner can invoke break-glass on a pending request. The action:

  1. Bypasses the 3-role separation (single human authorizes the cutover).
  2. Requires a typed-confirm phrase (BREAK GLASS) plus a justification of at least 50 characters (enforced by policyApprovalService.breakGlassPromote with error code BREAK_GLASS_JUSTIFICATION_REQUIRED).
  3. Records viaBreakGlass: true, breakGlassJustification: <text>, the actor's identity, and the timestamp on the immutable hash chain.
  4. Surfaces the action in the Auditor View with a critical-severity badge.
  5. Is gated by requireRole('owner', 'admin') — never available to viewer or auditor.

Audit reviewers (PwC, BaFin examiners, EU notified bodies) can filter the auditor view to viaBreakGlass: true to inspect every break-glass override and its accompanying justification.

Canary deployment

Each policy version may be promoted to a fractional rollout instead of going straight to 100%. The canary cohort is selected deterministically by SHA-256 bucketing (shouldRouteToCanary({ traceId, policyId, canaryPercentage })). Once BOTH the canary AND the production-baseline cohort have each accumulated ≥30 samples in the current window, the SPRT decision banner (Wald 1947 sequential probability ratio test) makes one of three calls (below the threshold the decision is inconclusive):

DecisionMeaningAction
acceptCanary fire-rate is statistically equivalent to production within tolerancePromote to 100%
rejectCanary fire-rate is statistically worse than productionAuto-revert recommended
continueInsufficient evidenceWait for more samples

The dashboard's <CanaryPercentageSlider> component refreshes the SPRT result every 30 seconds. Operators can adjust the rollout % at any time; the decision gets recomputed against the new sample window.

The auditor role

The auditor role is read-only by design. An auditor can:

  • View every live policy and its history (GET /api/policies/audit/auditor-view)
  • Inspect recent transcripts (last 50 policy fires) including break-glass flags
  • Inspect recent approvals (last 20) including state transitions, reviewer/enforcer identities, and timestamps
  • Inspect recent effectiveness snapshots (precision/recall/F1/FPR)
  • Pull the immutable PolicyVersion chain count

An auditor cannot:

  • Create, edit, approve, reject, or delete policies
  • Initiate break-glass
  • Change canary rollout percentages
  • Generate or download the insurance attestation feed
  • Modify SSO, billing, or any organization-level setting

This separation ensures that an external auditor on-site can verify enforcement without holding any production-changing capability.

Customer-controlled audit-trail export

For court-admissible evidence (per eIDAS Art. 41(2) + §371a Abs. 3 ZPO), the customer-portable bundle export wraps the relevant transcripts, the policy version chain, and the qualified electronic timestamp. Download via Policy Engine → Export bundle. The bundle is dual-signed with Sigstore Cosign (transparency log) and D-Trust QTSP (qualified electronic signature). See Policy Portability for the full schema.