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
encryptionabsorbsfips-cryptographyandtls-transitvulnerability-deltawrites down whatosv-verdictalready 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-closedproject-settingscoversprotected-branchesandleast-privilege-tokens, which had no enforcement at allstandards/releasegained thecheck.shit 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_settingcould not fail.jq -eexits nonzero on a literalfalse, so a boolean that was legitimatelyfalseSKIPped with a misleading reason instead of failing. No standard had ever called it.check-with-deviations.shsilently 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 greenPIPELINE_REPO=<catalog> just validate-binding: 31 controls, 22 standards, all four invariants pass, 3 deferred, 0 danglingcheck-with-deviations.sh: 22 standards passed, 0 failed- deviations:
compliance/deviations.yamlis back to the single structural self-exemption