Trust
6 min read
Policy governance
StateAnchor enforces API contract policy through the gate engine. This page explains who can change that policy, how changes are governed, and why there is no administrative backdoor that can silently weaken the gate.
Who controls gate policy
Gate policy is controlled by the stateanchor.yamlfile in your repository. Policy is code — it is reviewed in pull requests, approved by teammates, and committed to version control like any other configuration change. There is no separate “admin panel” for policy settings.
This means every policy change has:
- A commit SHA (who changed it and when)
- A pull request (who reviewed it)
- A diff (exactly what changed)
- A gate evaluation (StateAnchor evaluates the policy change itself through the pipeline)
How to change gate thresholds
The gate engine has one configurable threshold: warn_count_threshold. This controls how many WARN-lane findings are allowed before the gate blocks. The default is 1 — meaning a single WARN finding blocks the push.
# stateanchor.yaml -- gate policy section gate: warn_count_threshold: 3 # allow up to 3 WARN findings before blocking predictive_horizon: 5 # project drift velocity 5 commits ahead predictive_threshold: 60 # PREDICTIVE_WARN fires if projected score > 60
To change the threshold:
- Edit
stateanchor.yamlin a branch. - Open a pull request. The change is visible in the diff.
- Get it reviewed. Your team sees exactly what the policy change means.
- Merge. The next push uses the new threshold.
Setting warn_count_threshold: 0makes WARN findings advisory only — they are reported but never block. This is useful during initial onboarding when existing API drift produces many WARN findings.
What cannot be changed
Some aspects of the gate engine are fixed by design and cannot be overridden by configuration:
| Fixed behavior | Why |
|---|---|
| ERR lane always blocks | Endpoint removal, field removal, type changes, and auth changes are universally breaking. No threshold makes them safe. |
| INFO lane never blocks | Additive changes (new endpoints, optional fields) are safe by definition. Blocking them would create false positives. |
| Lane classification per change type | The mapping of change types to lanes is fixed. endpoint_removed is always ERR, endpoint_added is always INFO. You cannot reclassify a change type. |
| Fail-open on system error | If the StateAnchor service is unreachable, pushes pass through. StateAnchor never becomes a hard dependency that blocks your entire deploy pipeline. |
Exception governance
When a breaking change is intentional, you create a drift exceptionthat suppresses the specific finding. Exceptions are not blanket overrides — they are scoped, time-limited, and auditable.
Every exception requires four fields:
| Field | Required | Purpose |
|---|---|---|
endpoint | Yes | The specific endpoint the exception covers (e.g. DELETE /users/{id}). |
kind | Yes | The change type being suppressed (e.g. endpoint_removed, field_removed). |
approver | Yes | The email of the person who approved the breaking change. This is recorded in the audit trail. |
reason | Yes | A human-readable explanation of why the exception exists. |
expires_at | Yes | Expiration date. Maximum TTL is 90 days. When the exception expires, the finding reactivates. |
Exception behavior:
- An exception suppresses exactly one finding (one endpoint + one change kind). It does not suppress the entire gate.
- Every push still runs a full gate evaluation. New findings from other endpoints are not suppressed.
- Expired exceptions have no effect. The finding reactivates on the next push after expiration.
- Exception creation and expiration are recorded in the sync run audit trail.
Audit trail
Every gate decision is recorded in the sync_runs table with:
- gate_action —
proceedorblock - gate_reason — human-readable explanation of the decision
- gate_policy_snapshot — the exact policy configuration used for the decision
- spec_diff_json — every finding, classified by lane, with active/suppressed split
- breaking_score — raw and effective breaking scores
- commit_sha — the exact commit that triggered the evaluation
- scope_id — the user identity (Clerk user ID) that owns the project
This record is immutable. The sync_runs table has database triggers that prevent deletion and prevent modification of gate decision fields after they are written. You cannot retroactively change a gate decision.
No admin backdoor
There is no dashboard setting, API flag, environment variable, or hidden parameter that silently weakens the gate. Every mechanism that affects gate behavior is documented on this page:
warn_count_thresholdinstateanchor.yaml— visible in the repo, reviewable in PRs.- Drift exceptions — scoped, time-limited, require named approver, recorded in audit trail.
outage-policyin the GitHub Action — controls behavior during StateAnchor outages only.
If you need to understand why a gate decision was made, the spec_diff_json andgate_policy_snapshot fields on the sync run contain the complete input data. The decision is reproducible: given the same IR diff and the same policy, the gate engine always produces the same decision.
Design principle: if someone can weaken the gate without a code-reviewed commit, the gate is not trustworthy. StateAnchor eliminates this class of risk by treating policy as code.
Governance for teams
For teams with multiple developers, the governance model is straightforward:
- Policy changes require a PR to
stateanchor.yaml. Use GitHub's branch protection rules to require approvals. - Exception creation requires specifying an approver. The approver field is recorded but not verified against GitHub permissions — it is a social contract backed by audit visibility.
- Threshold decisions are team decisions. A senior engineer raising
warn_count_thresholdfrom 0 to 3 (to start blocking on three or more warnings per sync) is a policy choice that should be discussed, not a setting someone flips in a dashboard.
The combination of repo-based policy, scoped exceptions with TTLs, immutable audit records, and no admin backdoor means that every gate decision is explainable, every policy change is reviewable, and no single person can silently compromise the contract enforcement.