Policy & enforcement¶
Implemented
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:
operationIdis 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
ErrorResponseschema (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¶
- Governance model — the precedence stack the policy sits in
- Multi-agent orchestration — how agents consume the policy
- CI gates (Developers section) — gate-by-gate reference
- Sanitize-first (Security section) — one rule's detailed enforcement
- Source:
agent_policy.yaml,Agent_Enforcement.md,reviewguard_policy_draft.yaml,CI_Enforcement_Checklist.md