Skip to content

feat(seal): warn when the pinned anchor has been superseded - #321

Open
LKSNDRTMLKV wants to merge 8 commits into
mainfrom
feat/anchor-freshness
Open

LKSNDRTMLKV wants to merge 8 commits into
mainfrom
feat/anchor-freshness

Conversation

@LKSNDRTMLKV

Copy link
Copy Markdown
Member

Closes the anchor-refresh half of #295. Stacked on #316; retarget as that merges.

just check is green (1135/1135).

The gap

The trust anchor is pinned from an Official Journal notice rather than chained to a certificate authority, because the LOTL's signing certificates chain to no commercial root — there is nothing to walk up to. The Commission republishes that notice.

So a pin nobody refreshes eventually meets a LOTL signed by a certificate it does not name, and fails closed as NotAnchored — on a date nobody has in a calendar, looking like an outage rather than a lapsed pin.

LotlAnchor::notice_uri already carried a doc comment saying to compare it against the LOTL's first SchemeInformationURI entry. Nothing did. The affordance existed; the check did not.

What it adds

AnchorFreshness on VerifiedLotlCurrent, Superseded { lotl_names }, or Unknown — reported and logged.

A signal, never a verdict. A superseded pin keeps verifying until the certificates actually rotate, and that window is the only chance to refresh without an outage. Folding this into LotlRejected would refuse documents that verify perfectly and turn the early warning into the thing it exists to prevent. a_superseded_pin_does_not_refuse_a_document_that_verifies pins exactly that.

Unknown is not Current. A document naming no notice cannot be checked, and reporting it as up to date is how a staleness signal goes quiet at the moment it matters — the same fail-closed direction the capacity and placing-date questions take elsewhere in this workspace.

Logged as well as returned, because the caller that most needs to act on it is an operator reading logs, not the code holding the VerifiedLotl.

The assumption, asserted rather than trusted

The check reads the first SchemeInformationURI entry. That is load-bearing, so it is pinned against the real document: the LOTL lists 31 entries, and the notice is first, ahead of five pivots, the 2019 notice, the pivot explanation, and twenty-three per-language legal notices.

If that ordering ever changed, the check would compare against a pivot URL and report Superseded forever — noisy rather than silent, which is the right way round, but still wrong. the_notice_is_the_first_entry_the_document_lists fails instead.

Confirmed to bite

With the comparison neutered to always return Current, three of the five tests fail — the three asserting non-Current outcomes. The two positive controls correctly still pass, which is what a positive control is for.

Also from #295, and not here

SealChecks::QualifiedValidation remains unreachable, deliberately. A verified list says who is qualified; it does not say a particular seal validates. That is separate work and this does not pretend to close it.

What this does not solve

The refresh itself is still manual. This says the pin is stale; it does not fetch the new notice, re-read six digests out of it, or update the constant — all of which involve reading an Official Journal page, which is a human step by design. What changes is that the warning arrives while there is still time, instead of as a failed verification on an unscheduled day.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-ready Opt this PR into a CodeRabbit review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant