Repository navigation
effects: read a paged FHIR or REST record list whole, or not at all - #1538
Conversation
The FHIR verifier read only the first page of a search, so a record on page two read as absent. It now follows the Bundle's next links on the same origin and checks total. The REST verifier follows the next page's URL at records_next_path when it is set (relative links resolve against the page). A next page on another origin, a failed page, more than 50 pages, or a total above what was read makes the read unreadable, never a confirmation or a refutation from the first pages. Unset, records_next_path drops out of the config so existing digests hold. FHIR/REST pagination also proposed by @yunusarda-sudo in #1511 (superseded by this change). Co-authored-by: yunusarda-sudo <yunusarda-sudo@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
abrichr
left a comment
There was a problem hiding this comment.
Coordinator safety review (AI-assisted). Approved, with small fixes. Same-origin next links, the page cap, failed pages and the co-author trailer all check out.
- FHIR total check: make it
total != len(out), not one-sided. - REST total: add an optional
records_total_path, or document that REST paging trusts the chain. - Redirects: use
allow_redirects=False, or re-check the origin, so custom auth headers can't follow a redirect to another host. - OpenEMR REST next links: document the case where they name the configured site address, with a test and a distinct error ("next link origin X != base_url Y").
- CAPABILITIES row: add the PR number.
Review of #1538: - FHIR: a total other than the number of matches read (included resources don't count) is unreadable, not only a total above it. - REST: records_total_path checks the record count against a total in the first page; without it a REST read trusts the page chain (documented). - A requests session doesn't follow redirects, so the configured auth headers never reach another host, and a response that landed on another origin is unreadable. - Each unreadable read says why (verdict reason, detail.read_problem), such as "next link origin X != base_url Y". OpenEMR builds REST next links from its site address; EFFECT_KIT.md says to set base_url to it, with a test. - The CAPABILITIES row names this PR. Co-authored-by: yunusarda-sudo <yunusarda-sudo@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
AI re-review (coordinator). All five items fixed. (1) FHIR checks |
# Conflicts: # llms-full.txt
The FHIR record check read only the first page of a search, so a record on page two read as absent. This PR takes the pagination engine fix out of #1520 on its own.
Change
runtime/effects/fhir.py): follows the Bundle'snextlinks on the same origin and checkstotal.runtime/effects/rest.py): follows the next page's URL atrecords_next_path(a dotted path in the body, such aslinks.next) when it is set. A relative link resolves against the page it came from.totaldiffers from the number of matches read (included resources don't count);records_total_path(REST), the first page's total differs from the records read, or is missing;requestssession doesn't follow redirects, so the configured auth headers never reach another host.detail.read_problem, for examplenext link origin https://localhost:9300 != base_url http://localhost:9520.base_urlto the site address.deployment.py):records_next_pathandrecords_total_pathoneffects:. When they are unset they drop out of the serialized config and the verifier identity, so existing digests hold. Without it, one REST response is the whole read, as before.This changes when VERIFIED is issued: on a server that pages, a record past page one now confirms instead of reading as absent, and a partial read is INDETERMINATE.
Credit
FHIR/REST pagination also proposed by @yunusarda-sudo in #1511 (superseded by this PR). The commit carries their
Co-authored-bytrailer.Tests
tests/test_effect_paging.pyruns the FHIR and REST verifiers against local servers:nextlink is the whole read.nextlink to another origin, a failed later page, atotalabove the read, or an endless chain is unreadable.records_next_path.records_next_paththroughEffectsConfigandbuild_effect_verifier; an unset value doesn't change the serialized config.records_total_pathequal, above, below and missing; a 302 that never reaches the other host (REST with an API key header, and FHIR); the reason in the verdict.Run:
test_effect_paging,test_effect_fhir,test_rest_verifier_transport,test_smart_backend_auth,test_effect_kit_config,test_effect_collateral_change_hashes,test_effect_verifier_transport,test_effect_verifier,test_cli_deploymentandtest_effect_fault_matrix. 159 passed, 1 skipped.Not run against live OpenEMR FHIR; that needs the shared fixture slot (
test_effect_fhir_live_openemr.py).🤖 Generated with Claude Code