Skip to content

fix(rest): execute search-style GET bundle entries as searches - #481

Open
angela-helios wants to merge 1 commit into
mainfrom
fix/478-bundle-get-search
Open

fix(rest): execute search-style GET bundle entries as searches#481
angela-helios wants to merge 1 commit into
mainfrom
fix/478-bundle-get-search

Conversation

@angela-helios

Copy link
Copy Markdown
Contributor

Closes #478

The bug

Bundle GET entries were unconditionally parsed as Type/id reads. GET Patient?name=Nguyen became a read of resource type Patient?name=Nguyen — a 404 in batch bundles, and a 400 rejecting the whole bundle in transactions — even though the spec's processing rules allow any read or search URL in a GET entry (this is what blocked the #476 screenshot bundle and got the bug filed).

The fix

  • parse_request_url strips the query string before extracting type/id, so scope checks and reads see the real resource type.
  • A GET entry addressing a type (Patient?name=x, or bare Patient) now runs through the same search pipeline as the HTTP endpoint (execute_search_bundle, factored out of the search handler): terminology expansion, _list/chain resolution, _include, paging clamps. The resulting searchset Bundle is embedded as the entry's resource with 200 OK. Instance reads (Patient/123) are untouched.
  • Transactions: the spec orders GETs after all writes, and a search cannot run inside the storage transaction, so search entries execute against the just-committed state — which also makes them see the bundle's own writes (tested: POST a patient + GET Patient?family=Tran in one transaction finds it). Their queries are validated up front, so a malformed search still rejects the whole bundle before anything executes; a post-commit execution failure surfaces as that entry's own error outcome rather than a misleading whole-bundle failure for writes that did commit. GET-by-id keeps running inside the storage transaction as before.

Tests

New search_entries conformance tests: batch search entry returns a searchset, bare-type GET is a search, batch mixing read + search entries, transaction search seeing the bundle's own writes, transaction GET-by-id unchanged. Full helios-rest suite green (33 test binaries, incl. batch_conformance 44, search_integration 101, rest_conformance 84); clippy clean.

Bundle GET entries were unconditionally parsed as Type/id reads, so a
search entry like 'Patient?name=x' became a read of resource type
'Patient?name=x' -- a 404 in batch bundles and a 400 rejecting the whole
bundle in transactions -- even though the spec allows any read OR search
URL in a GET entry.

The URL parser now strips the query string before extracting type/id,
and a GET entry addressing a type ('Patient?name=x', or bare 'Patient')
runs through the same search pipeline as the HTTP search endpoint
(terminology expansion, list/chain resolution, includes), embedding the
searchset Bundle as the entry resource. Instance reads ('Patient/123')
are untouched.

In transactions the spec orders GETs after all writes, and a search
cannot run inside the storage transaction, so search entries execute
against the just-committed state -- which also makes them see the
bundle's own writes. Their queries are validated up front so a
malformed search still rejects the whole bundle before anything
executes; a post-commit execution failure surfaces as that entry's own
error outcome rather than a misleading whole-bundle failure for writes
that did commit.

Closes #478
@codecov

codecov Bot commented Aug 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.82609% with 14 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/rest/src/handlers/batch.rs 89.13% 10 Missing ⚠️
crates/rest/src/handlers/search.rs 82.60% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

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.

batch/transaction: search-style GET entries are mis-parsed as instance reads

2 participants