Skip to content

Policy & enforcement

Implemented

Source: doc/governance/agent_policy.yaml · doc/governance/Agent_Enforcement.md · doc/governance/reviewguard_policy_draft.yaml · doc/governance/reviewguard_adoption_plan.md · doc/governance/CI_Enforcement_Checklist.md · doc/governance/openapi.spectral.yaml · doc/governance/production_enforcement_policy.yaml

How the machine-readable policy layer is structured, what it covers, and how it gets enforced at three different boundaries — agent execution, PR review, and CI.

Three boundaries of enforcement

flowchart LR
    classDef agent fill:#fff8e1,stroke:#f57f17
    classDef pr fill:#e3f2fd,stroke:#1565c0
    classDef ci fill:#d1e7dd,stroke:#0a3622

    B1[Boundary 1<br/>Agent execution]:::agent
    B1 --> AGP[agent_policy.yaml<br/>CF / SEC / REL / DATA / OBS rules]
    B1 --> AGE[Agent_Enforcement.md<br/>contract-first, security, data integrity,<br/>testing + verification, no symptom-only fixes]

    B2[Boundary 2<br/>PR review]:::pr
    B2 --> RG[reviewguard_policy_draft.yaml<br/>title format, required reviewers,<br/>breaking-change labels]
    B2 --> RGA[reviewguard_adoption_plan.md<br/>rollout, exception handling]

    B3[Boundary 3<br/>CI pipeline]:::ci
    B3 --> CIC[CI_Enforcement_Checklist.md<br/>scripts/ci/*.sh gates]
    B3 --> SP[openapi.spectral.yaml<br/>OpenAPI lint]
    B3 --> PE[production_enforcement_policy.yaml<br/>deploy-time gate]

    B1 -.violation caught early.-> B2
    B2 -.violation caught at PR.-> B3
    B3 -.violation blocks merge.-> R[Rejected]

agent_policy.yaml — the machine baseline

The file is the highest-priority policy artifact. Coding agents must read it before generating any code.

mindmap
  root((agent_policy.yaml))
    contract_first
      CF-001 API changes require OpenAPI update before implementation
      CF-002 No UI feature may bypass API contract
    security
      SEC-001 No secrets in code or repo-tracked config
      SEC-002 All privileged endpoints enforce server-side authorization
      SEC-003 All external inputs validated with explicit schema
    reliability
      REL-001 Mutation endpoints support idempotency keys
      REL-002 Async workflows use durable queue + retry + DLQ
    data_integrity
      DATA-001 Balances are derived from immutable ledger entries
      DATA-002 No direct mutable balance writes
      DATA-003 No hardcoded runtime business-policy constants
    observability
      OBS-001 All request paths emit structured logs + correlation IDs
      OBS-002 (and more)

The format is YAML so the agent + CI gates can both parse it:

version: 1
policy:
  contract_first:
    required: true
    rules:
      - id: CF-001
        statement: "API changes require OpenAPI update before implementation."
      - id: CF-002
        statement: "No UI feature may bypass API contract."
  security:
    required: true
    rules:
      - id: SEC-001
        statement: "No secrets in code or repo-tracked config."
      - id: SEC-002
        statement: "All privileged endpoints enforce server-side authorization."
      - id: SEC-003
        statement: "All external inputs validated with explicit schema."
  reliability:
    required: true
    rules:
      - id: REL-001
        statement: "Mutation endpoints support idempotency keys."
      - id: REL-002
        statement: "Async workflows use durable queue + retry + DLQ."
  data_integrity:
    required: true
    rules:
      - id: DATA-001
        statement: "Balances are derived from immutable ledger entries."
      - id: DATA-002
        statement: "No direct mutable balance writes as source of truth."
      - id: DATA-003
        statement: "No hardcoded runtime business-policy constants; policy values must resolve from config/DB with audited updates."
  # ... observability, etc.

Every rule has a stable id so violations can be referenced precisely.

Agent_Enforcement.md — the non-negotiables

A prose companion that expands the YAML rules into agent-readable language. Excerpt:

mindmap
  root((Agent non-negotiables))
    Contract-First
      MUST read OpenAPI/AsyncAPI before code
      MUST NOT create UI-only logic without API contract
      MUST update specs first for any API change
    Security
      No hardcoded secrets, tokens, passwords, keys
      No insecure auth shortcuts
      All privileged operations require authz + audit
      Input validation on every boundary
      No direct control-plane SSH in MVP
      Provisioning state changes via Temporal only
    Data Integrity
      Monetary operations are immutable ledger entries
      Mutation endpoints support idempotency keys
      Async side effects use queue/outbox patterns
    Code Generation
      Typed clients/SDK from OpenAPI only
      Stable operationIds + versioned API docs
      Preserve backward compatibility unless version bump
    Testing & Verification
      Generate/update unit + integration tests for changed behavior
      Match acceptance matrix in Testing_Standards

→ Source: Agent_Enforcement.md

reviewguard — the PR-level gate

reviewguard_policy_draft.yaml is read by the PR review system. It enforces:

flowchart TB
    PR[PR opened] --> RG[reviewguard]
    RG --> C1{Title format<br/>matches convention?}
    C1 -- no --> X[Reject]
    C1 -- yes --> C2{Required reviewers<br/>per touched domain?}
    C2 -- no --> X
    C2 -- yes --> C3{Breaking-change<br/>labels accurate?}
    C3 -- no --> X
    C3 -- yes --> C4{Files touched<br/>match lane scope?}
    C4 -- no --> X
    C4 -- yes --> C5{Special path?<br/>agent_policy.yaml or<br/>governance dir}
    C5 -- yes --> SPC[Auto-block until<br/>explicit owner approval]
    C5 -- no --> OK[Pass]

    classDef block fill:#f8d7da,stroke:#42101e
    classDef ok fill:#d1e7dd,stroke:#0a3622
    class X,SPC block
    class OK ok

Special protections:

File / path reviewguard rule
governance/agent_policy.yaml Auto-block; explicit security + architecture owner approval
governance/reviewguard_*.yaml Same — meta-policy is even more protected
architecture/adrs/* Architecture owner required
db_schema_v1.sql DBA + architecture owners required
release/platform-control direct push Forbidden; must use promote script

→ Source: reviewguard_adoption_plan.md

CI enforcement checklist

Every PR runs through a fixed sequence of gates in scripts/ci/*.sh:

flowchart TB
    PR[PR opened] --> CI[CI pipeline]
    CI --> G1[bootstrap_ci_toolchain.sh]
    G1 --> G2[contracts_validate.sh<br/>Spectral lint + structural validation]
    G2 --> G3[contracts_breaking_change.sh<br/>Diff against main]
    G3 --> G4[backend_build_and_tests.sh<br/>go build + unit + integration]
    G4 --> G5[audit_mandatory_guard.sh<br/>Privileged mutations write audit_logs]
    G5 --> G6[audit_presence_guard.sh<br/>Integration tests assert audit rows]
    G6 --> G7[canonical_error_guard.sh<br/>All errors use catalog codes]
    G7 --> G8[observability_trace_gate.sh<br/>Tracing wired on every router]
    G8 --> G9[agent_queue_validate.sh<br/>Queue schema + invariants]
    G9 --> G10[agent_queue_git_consistency.sh<br/>Queue ↔ git state agree]
    G10 --> G11[frontend_build_and_tests.sh]
    G11 --> G12[frontend_e2e*.sh<br/>Playwright]
    G12 --> G13[contracts_schemathesis_report.sh<br/>Property-based contract tests]
    G13 --> OK[All gates green]

    classDef gate fill:#fff3e0,stroke:#e65100
    classDef ok fill:#d1e7dd,stroke:#0a3622
    class G1,G2,G3,G4,G5,G6,G7,G8,G9,G10,G11,G12,G13 gate
    class OK ok

Each gate maps to specific rules in agent_policy.yaml and prose standards. The map:

Gate Enforces
contracts_validate.sh CF-001, spectral lint
contracts_breaking_change.sh Contract_Versioning_Policy.md
audit_mandatory_guard.sh SEC-002, audit on privileged mutations
audit_presence_guard.sh Integration tests assert audit row presence
canonical_error_guard.sh Error_Code_Catalog.md, no off-catalog codes
observability_trace_gate.sh OBS-001, tracing + correlation IDs
agent_queue_validate.sh Task Authoring Standard
agent_queue_git_consistency.sh Queue ↔ git consistency
frontend_e2e*.sh E2E selector contract

Spectral lint (OpenAPI)

openapi.spectral.yaml enforces API design rules at the spec level. Examples:

  • operationId is camelCase per pattern <domain>_<resource><Verb>
  • Every operation has tags, summary, description
  • Path parameters are kebab-case
  • Every response has a JSON schema
  • Error responses use ErrorResponse schema (matches catalog)
  • No undocumented enums

These rules apply at PR time and block on violation.

Production enforcement policy

production_enforcement_policy.yaml is the deploy-time gate. It enforces:

mindmap
  root((Production gates))
    Security
      mTLS internal active
      WAF in front
      Secret scanning clean
    Data
      Migration rollback tested
      Backup drill < 30 days old
    Observability
      SLO dashboards live
      Alert routes wired to on-call
    Release process
      release/platform-control via promote script only
      All required CI gates green
      Approval recorded by platform + security owners

This is consumed by the platform-control promotion script and by deploy automation. Production deploys cannot bypass it.

Pipeline blueprint

Pipeline_Blueprint.md and CI_Pipeline_Implementation.md document the orchestration shape that connects all these gates:

flowchart TB
    LOC[Local make targets]
    CI[GitLab CI / GitHub Actions]
    SCR[scripts/ci/*.sh]

    LOC --> SCR
    CI --> SCR
    SCR --> POL[agent_policy.yaml]
    SCR --> RG[reviewguard]
    SCR --> SP[spectral]
    SCR --> PE[production_enforcement]
    SCR --> GATES[Each gate emits<br/>pass/fail + evidence]

    note[CI portability rule:<br/>Logic lives in scripts.<br/>CI workflow YAML is wrapper only.<br/>Switching hosts means rewriting wrappers,<br/>not gate logic.]

→ Source: Pipeline_Blueprint.md, CI_Pipeline_Implementation.md

Where to look next