Skip to content

fix(common): read every page of a dataset's versions and send no principal - #30

Merged
jm-rivera merged 2 commits into
devfrom
fix/versions-client-pages
Oct 23, 2026
Merged

jm-rivera merged 2 commits into
devfrom
fix/versions-client-pages

Conversation

@jm-rivera

Copy link
Copy Markdown
Contributor

LiveApisClient.list_versions in packages/common/src/common/live_apis.py follows next_cursor until the complete page, returns () when the first page refuses spec_not_found, raises any later refusal, refuses a page outside the contract as response_invalid, and stops at a repeated cursor or past VERSIONS_MAX_PAGES. It sends no principal. This matches apis, which serves GET /api/datasets/{spec_id}/versions with no principal, pages it with next_cursor and complete (100 versions a page by default), and refuses an id no dataset has with 404 spec_not_found (DevelopmentFinanceObservatory/apis#68). The earlier call read one page with the datasets principal, so against that server mint recovery and recipe replay would see only the newest 100 versions and an unknown id would raise.

The recipe backfill's preflight (services/harness/src/harness/recipe_backfill.py) proves the URL and the datasets principal before it walks frames by reading the recipe of a derived pair no frame has, which apis answers recipe_not_found only after it accepts the principal. The versions route takes no principal, so a versions read cannot prove it. packages/common/tests/fixtures/dfo_apis_live_refresh_wire_pairs.json is copied from the apis recording of the new route.

Merge this after the apis branch deploys to dev. Against today's dev every call fails, because the route refuses a call with no principal and its answer carries no complete.

Testing: just check at 7b9a5b2 passed lint, the type check and 11,186 tests, with 22 skipped and 5 xfailed.

…cipal

apis now serves `GET /api/datasets/{spec_id}/versions` with no principal, pages it with `next_cursor` and `complete` (100 versions a page by default), and refuses an id no dataset has with 404 `spec_not_found`. `LiveApisClient.list_versions` read one page with the datasets principal, so mint recovery and recipe replay saw only the newest 100 versions and an unknown id raised. It now follows `next_cursor` until the complete page, returns `()` on `spec_not_found`, refuses a page outside the contract (`response_invalid`), and stops at a repeated cursor or past `VERSIONS_MAX_PAGES`.

The recipe backfill's preflight read versions to prove the URL and the datasets principal, and the versions route no longer reads the principal. It now reads the recipe of a derived pair no frame has, which apis answers `recipe_not_found` only after it accepts the principal. The recorded apis wire pairs are copied from the apis recording of the new route.
A dataset that goes away between two page reads raised nothing and returned no versions, dropping the pages already read. `list_versions` now maps `spec_not_found` to `()` only on its first request and raises it on a later page.
@jm-rivera
jm-rivera marked this pull request as ready for review October 23, 2026 10:28
@jm-rivera
jm-rivera merged commit 2a49595 into dev Oct 23, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant