Invalidate the composed index when a registration changes (REUSE-WP-0020-T09)
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
ci / validate-registry (push) Successful in 1m18s
Build and Publish Container Image / build-and-push (push) Successful in 23s

Enabling a federation source left /v1/federated serving its cached compose and
reporting stale: false while doing it, so a repo could be correctly registered
and silently invisible for as long as its cached index survived. That is how
evidence-binder stayed missing after re-enabling until a manual
POST /v1/federated/compose was issued.

Registration writes now mark the composed index stale, and a plain GET
recomposes when the flag is set. Clearing it there is not a silent clear: that
pass really did refetch. A PATCH touching only a description does not
invalidate anything.

This changes a contract documented in specs/FederationHubAPI.md, so the
staleness section is rewritten rather than left to drift, including the two
triggers that now set the flag.

The first two tests written for this were worthless -- they passed with the fix
removed, because a newly registered repo has no cache entry and gets fetched
regardless. The real failure needs a populated cache holding stale content
inside its 24h TTL. test_re_enabled_source_refetches_a_stale_cache models that
and fails on pre-fix code; verified by reverting the mark_stale calls.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-08-21 13:51:58 +02:00
parent d1de320743
commit 6cbc862371
5 changed files with 235 additions and 26 deletions

View file

@ -371,7 +371,7 @@ derived from `STALE_DAYS`. Full suite: 179 passed.
```task
id: REUSE-WP-0020-T09
status: todo
status: done
priority: medium
```
@ -393,8 +393,30 @@ Fix: have the write paths on `/v1/repos` (create, and update where `enabled`,
`GET /v1/federated` recomposes — or at minimum report `stale: true` so a caller
can tell the served view no longer matches the registrations behind it.
Add a hub test: register or enable a source, then `GET /v1/federated` without
`refresh`, and assert the new source's capabilities are present.
**Done 2026-08-21.** `POST /v1/repos`, `DELETE /v1/repos/{repo}`, and a
`PATCH` touching `COMPOSITION_FIELDS` (`enabled`, `url`, `index`, `required`,
`domain`) now call `mark_stale()`; a plain `GET /v1/federated` recomposes when
the flag is set and clears it. A cosmetic `PATCH` (description only) leaves the
cache alone. `specs/FederationHubAPI.md` updated — this changes a documented
contract, so the spec's staleness section was rewritten rather than left to
drift.
Three tests added. **The first two I wrote were worthless** and it is worth
recording why: they passed with the fix removed. A *newly* registered repo has
no cache entry, so a plain `GET` fetches it regardless — that was never the
bug. The real failure needs a **populated cache holding the old content**:
evidence-binder's cached index was the broken pre-repair copy, still inside the
24h `cache_ttl_seconds`, so the plain `GET` kept serving zero rows from it.
`test_re_enabled_source_refetches_a_stale_cache` reproduces exactly that —
cache the broken index, disable, republish repaired content, re-enable, plain
`GET` — and fails with an assertion error on pre-T09 code.
Verified by mutation: reverting the three `mark_stale()` calls makes both
behavioural tests fail. 184 tests pass on the fix.
**Not yet deployed.** Production still has the bug; it needs an image build of
this commit and a `make reuse-deploy`.
---