feat(compliance): bind every control to a standard, a check, and a component

A principle should exist in four places bound by one id: a row in compliance/unified.yaml that carries every framework obligation asking for it, a SKILL.md that explains it to a human, a check.sh that decides it against a repo, and a catalog component that enforces it in CI. Neither repo should own a principle the other has not heard of.

None of that was checked. This binds it and adds the check.

invariant before after
every control names a standard: that exists 0 of 30 31 of 31
every standard has a check.sh 18 of 19 22 of 22
every enforced_by: catalog: resolves to a real template 2 dangling 0
every catalog component is cited by a control, or recorded exempt 9 of 22 21 of 21
every framework key cited resolves to compliance/registry.yaml unchecked 11 frameworks, 4 sectors

scripts/validate-binding.py asserts all four inside just validate. Invariants 3 and 4 need the sibling catalog, and they SKIP rather than pass when it is absent, so a missing checkout cannot read as conformance. Reference CI clones the catalog and exercises them for real.

fips-cryptography becomes encryption

Naming a control after one of its citations inverts it. FIPS is not a sibling standard, it is one of six frameworks asking for the same engineering decision. The row keeps all six citations (nist_800_53_r5 SC-13, nist_800_171_r2 3.13.11, cmmc_l2 SC.L2-3.13.11, ssdf_v1_1 PW.6.1, fips_140_3 core requirement, hipaa 164.312(a)(2)(iv)). A seventh framework becomes a citation on the row, never a new standard.

The check asserts the mechanism: a FIPS build target exists and is exercised. It deliberately does not assert certification, because the Go FIPS 140-3 module is CMVP In-Review and upstream certification is not ours to gate on. The prose carries the certification status and status: blocked stays authoritative until a CMVP number exists. A check that passed on "ships a FIPS variant" would be a green check over an unmet claim.

Standards authored

  • encryption absorbs fips-cryptography and tls-transit
  • vulnerability-delta writes down what osv-verdict already enforced on every consumer with nothing explaining it: a change is judged on the vulnerabilities it introduces, not the absolute count in the repository, so the gate stays actionable and fail-closed
  • project-settings covers protected-branches and least-privilege-tokens, which had no enforcement at all
  • standards/release gained the check.sh it never had

Components that are conveniences (site-check, paper, container-scan-summary, container-manifest, vale) are recorded exempt with a reason. Three that do carry a principle (automerge-gate, registry-cleanup, clone-upstream) are recorded as deferred with the condition that clears them, so the residual is zero rather than unexplained and the check stays green rather than red by design.

Two never-exercised primitives, both broken

  • check_gitlab_setting could not fail. jq -e exits nonzero on a literal false, so a boolean that was legitimately false SKIPped with a misleading reason instead of failing. No standard had ever called it.
  • check-with-deviations.sh silently ignored any quoted assertion value. The awk extraction did not strip quotes. This branch's entries were the first to use that field.

allow_force_push is not exposed on projects/:id and is documented as a known gap rather than asserted against an absent key.

Verified

  • just validate: all gates green
  • PIPELINE_REPO=<catalog> just validate-binding: 31 controls, 22 standards, all four invariants pass, 3 deferred, 0 dangling
  • check-with-deviations.sh: 22 standards passed, 0 failed
  • deviations: compliance/deviations.yaml is back to the single structural self-exemption

Merge request reports

Loading