merge: coverage debt paid — 51/51, and the root really did hide a service

R-C2-01 and R-C2-02 were the last two uncovered requirements (49/51). Now
100% with 0 gaps, via an offline L0 check (49 assertions) that compares two
repository facts: every home-zone hostname the repo routes over HTTP must be
linked from the apex dashboard, and every link the dashboard offers must
resolve to something the repo actually serves at L7 or L4.

'A service the root hid' was still a live defect: crafty.${BASE_DOMAIN} was
served and reconciled while nothing on the root linked to it. Committed RED
first so the history shows the check catching it, then fixed.

Also fixes a regex that could never have worked: ci/touched-requirements.sh
matched R-[A-Z]+-[0-9]+, where [A-Z]+ eats the C of R-C2-01 and then demands
a dash where the 2 is — so a manifest declaring either ID attributed nothing.
Every other consumer already used [A-Z0-9]+.

16 mutations proven caught. R-TLS-02's drafted amendment is recovered into
DECISIONS-LOG: revocation is not implementable with cert-manager, and the
choice between amending the requirement and a reviewed DOCUMENTED_GAPS entry
is the owner's.

# Conflicts:
#	DECISIONS-LOG.md
This commit is contained in:
jakman85 committed 2026-09-13 16:34:54 -05:00
commit 088ff13d15
8 files changed
+921 -4

No files matched your search

+81
View File
@@ -3163,3 +3163,84 @@ scaffold containing 8 `TODO` echoes and asserts none of the behaviours it names
bound, default-deny, egress class, DNS/TLS, metrics, update policy). This is a concrete instance of
the fail-open the `feat/coverage-debt-paydown` and `fix/touched-requirements-fail-closed` branches are
about: a stage that reports green while verifying nothing.
## R-TLS-02 — the "revoked" clause still needs the OWNER's decision (recovered 2026-09-13)
**This is a decision only the repo owner/architect can make. It has now been escalated twice and
lost twice, which is why it is written into this log rather than into another branch's commit
message.** The analysis was first drafted on `feat/coverage-debt-paydown` (`b37defe`, 2026-09-07),
a branch whose tree is ~107 commits behind main and which must never be merged; the drafted
amendment lived only in that branch's copy of this file, so it disappeared from view the moment the
branch went stale. Recovered here, re-checked against today's main, and restated unchanged in
substance.
**R-TLS-02, verbatim (spec `docs/00-vision-and-scope.md`):** *"Certificates MUST be automatically
**issued, renewed, and revoked** without manual steps."*
Three verbs. Two hold; the third does not, and cannot with the stack ADR-0006 selects:
- **Issued — satisfied.** Both ClusterIssuers are declarative (ACME DNS-01, Cloudflare token
referenced by name from SOPS), the wildcard Certificate plus its apex SAN make onboarding
certificate-free, and the active issuer is chosen per environment by `${ACME_CLUSTER_ISSUER}`.
- **Renewed — satisfied, and unhobbled.** cert-manager renews at ~2/3 of lifetime with no operator
action; nothing in the repo sets a `duration`/`renewBefore` that would defeat it, and
`CertificateExpiringSoon` / `CertificateExpiryImminent` / `CertificateNotReady` fire if renewal
silently stops.
- **Revoked — NOT implemented, and not implementable here.** cert-manager has no automatic ACME
revocation: no revoke-on-delete, no `Certificate` field that requests revocation, no controller
that calls ACME `revokeCert`. Deleting a `Certificate` stops renewal; it does not revoke, and the
issued certificate stays valid at the CA until it expires. Neither ADR-0006 nor `docs/08`
specifies a mechanism — `docs/08`'s own "Renewal & revocation" section describes replacement
issuance, which is rotation.
**`enableCertificateOwnerRef` is NOT the remedy, and is still not set.** That cert-manager
controller flag makes a `Certificate` own its `Secret`, so deleting the Certificate
garbage-collects the key material. That is *cleanup*, not revocation. It does remove one real
manual step (today a deleted Certificate leaves an orphaned TLS Secret and private key to be
deleted by hand), so it is defensible on its own merits — but it is a GLOBAL controller flag, and
any future rename or prune that deletes and recreates a `Certificate` would take the Gateway's
`wildcard-home-tls` Secret with it, dropping TLS on every service until reissuance, against Let's
Encrypt rate limits, on two clusters. It deserves its own risk assessment, not a side effect of a
coverage or test task.
**WHAT HAS CHANGED SINCE THE FIRST ESCALATION.** R-TLS-02 is no longer a COVERAGE gap — main
carries `l0-static/tls-lifecycle-automated` and `l2-behavioral/cert-lifecycle-automated`, and the
coverage report counts it covered. The honesty was kept where it matters: the L0 check's own verdict
line ends *"R-TLS-02 'without manual steps' clause only — issued/renewed/revoked are RUNTIME verbs
(see l2-behavioral/cert-lifecycle-automated; 'revoked' is NOT proven at any layer)"*. But the
decision is now also LOAD-BEARING on the gate in a second way: the L2 test deletes a Certificate and
requires its Secret to disappear, and on failure prints *"set enableCertificateOwnerRef: true in
platform/cert-manager values (owner decision — WS-TEST does not weaken the assertion instead)"*. So
that test is written to FAIL on any live cluster run until the owner decides. Nobody should weaken
it to make a run green; that is the decision below, arriving as a red test instead of as a question.
**THE TWO OPTIONS, in the drafted preference order. The spec repo is READ-ONLY to every agent
(R-TEST-06), so neither has been applied — this is a request for a human decision.**
1. **PREFERRED — amend R-TLS-02 to the property that is achievable and actually protective**, and
move revocation to an explicitly manual, documented break-glass procedure:
> **R-TLS-02** — Certificates MUST be automatically **issued and renewed** without manual steps,
> and decommissioning a service MUST NOT leave its key material behind. Certificate
> **revocation** is an exceptional, operator-initiated action (suspected key compromise); it is
> NOT automated, and MUST have a documented procedure. Rationale: the ACME / Let's Encrypt model
> relies on SHORT certificate lifetimes plus automated rotation rather than on revocation — Let's
> Encrypt retired OCSP in 2025 and cert-manager implements no automatic revocation — so an
> "auto-revoked" requirement cannot be met by the stack ADR-0006 selects, and could only be met
> by bespoke revocation automation the threat model does not justify.
Under this wording R-TLS-02 becomes fully testable: issuance and renewal are already asserted
statically, and "no key material left behind" is exactly what `enableCertificateOwnerRef`
implements — which makes that flag a *consequence of the requirement*, decided on its own risk
assessment, rather than a fudge to turn a gate green.
2. **Keep R-TLS-02 as written and accept it as permanently partially satisfied**, with a reviewed
`DOCUMENTED_GAPS` entry in `conformance/run.sh` naming the revocation clause, the reason (no ACME
revocation exists in cert-manager) and the removal condition (cert-manager ships revocation, or
the requirement is amended). Cheaper, and records a requirement the system does not meet.
**Until the owner picks one, the state is: R-TLS-02 counted as covered, its third clause
unimplemented and labelled as such in the test's own output, and the L2 withdrawal assertion
standing as a deliberate red.** Writing a test tagged R-TLS-02 that silently verifies only issuance
and renewal would report the requirement as met while a third of its normative text is
unimplemented — which is the one thing this harness exists to prevent. The choice is the
architect's, not an agent's.