# Locate a FHIR reference without changing its identity

Original LockedIn Labs instruction · 50-minute healthcare integration lab · reviewed 28 October 2026.

An Observation names `Patient/42`. A Bundle contains two Patient resources with
ID 42 under different server bases. Which one did it reference? Taking the first
matching ID changes the answer when entry order changes. You will reproduce that
shortcut, then compare full URLs, resource revisions, UUID references, contained
resources and logical identifiers.

FHIR means Fast Healthcare Interoperability Resources. This workshop uses a
narrow FHIR R4 collection-Bundle subset and invented Patient/Observation records.
It locates data already in those fixtures. It uses Python 3.11+ and the standard
library, with no network, database, credentials or real health records. Locating
a resource does not verify a person's identity, establish permission or support
a clinical, coverage or payment decision.

## 1. Distinguish the identities in one reference

| Term | Meaning in this exercise | Shortcut to avoid |
| --- | --- | --- |
| Resource type and id | Patient with local logical ID 42 | Treating 42 as globally unique |
| Server base | The FHIR service context preceding Patient/42 | Dropping it because both records have the same ID |
| Bundle entry fullUrl | Identity used to locate a resource in this Bundle | Assuming array position or display text supplies identity |
| Resource meta.versionId | An opaque revision of this resource instance | Sorting version labels as numbers or substituting a vocabulary version |
| Reference.identifier | A logical/business identifier with its own system and value | Treating its value as a FHIR resource id |
| Contained reference | `#p1` inside its owning resource's context | Resolving it to an unrelated top-level resource with id p1 |

A resource id, business identifier and real-world person are different concepts.
The standard describes references; an enterprise agreement supplies the permitted
source, business context and any identity-matching or lookup process. This lab
does not implement an identity service or a full FHIR profile validator.

## 2. Follow the source context before choosing a target

The relative-reference fixture has these three entries:

| Identity | Resource | Teaching label |
| --- | --- | --- |
| https://synthetic-a.example/fhir/Observation/obs-1 | Observation with subject Patient/42 | The referring record |
| https://synthetic-b.example/fhir/Patient/42 | Patient id 42 | SYNTHETIC-B |
| https://synthetic-a.example/fhir/Patient/42 | Patient id 42 | SYNTHETIC-A |

The Observation's REST-shaped full URL supplies the relative service base for
this collection. The target locator is therefore the synthetic-a Patient URL.
The broken matcher keeps only 42 and initially picks SYNTHETIC-B. Its program
returns JSON successfully while locating the wrong fixture record.

A fullUrl can instead be a UUID URN, such as `urn:uuid:11111111-1111-4111-8111-111111111111`.
It is matched as a Bundle identity; its final characters are not a resource id.
An owner with a UUID URN does not supply this lab's relative HTTP service base.
The fixture has no separate transaction/request base from which to infer one.

Six authored visual frames explain the actual Python observations. The browser
does not run a source adapter. The written ledger below preserves the same
reasoning without requiring the diagram.

## 3. Run nine bounded reference cases

Download [the FHIR reference runner](/templates/fde-fhir-references.py). Predict
the target or unresolved reason before each comparison:

```sh
python3 --version
python3 fde-fhir-references.py > references-original.json
python3 fde-fhir-references.py --case relative-two-bases --reverse-entries > references-reversed.json
python3 fde-fhir-references.py --case version-specific > references-versioned.json
```

The report retains each original Bundle, owner fullUrl, guarded trace and broken
ID-only target. `entry_index` locates an observed target in that particular
report; it is an evidence path, not its identity. Reversing entries changes that
path without changing the guarded target. No URL is fetched or turned into an
external request.

### The written ledger

| Case | Guarded observation | Why the ID-only shortcut is insufficient |
| --- | --- | --- |
| `relative-two-bases` | Locate SYNTHETIC-A by the owner's base and fullUrl | Both servers use Patient id 42; first match initially picks B |
| `urn` | Locate the exact UUID fullUrl already in the Bundle | The resource id is 42, not the UUID string |
| `version-specific` | Match the versionless fullUrl and exact meta.versionId v2 | Stripping history and taking the first id initially picks v1 |
| `versionless-versions` | Withhold: `ambiguous_bundle_identity` | This fixture contains multiple versions and defines no latest-version choice |
| `contained` | Locate #p1 only in the owner’s contained list | A top-level Patient/p1 is a different candidate |
| `logical-only` | Withhold: `identifier_lookup_required` | A chart identifier's value 42 does not become resource id 42 |
| `urn-owner-relative` | Withhold: `relative_base_unavailable` | A plausible Patient/42 elsewhere cannot supply the missing source base |
| `missing` | Report `not_in_bundle`, with no target | Missing from this fixture does not mean absent from an authoritative server |
| `duplicate-identity` | Withhold: `ambiguous_bundle_identity` | Two conflicting entries claim the same fullUrl and requested revision |

Compare the original and reversed relative-reference reports. The broken target
changes from SYNTHETIC-B to SYNTHETIC-A. The guarded resource remains SYNTHETIC-A;
only its entry index changes. An accidentally correct first match under one order
is not a stable receiving contract.

## 4. Keep version and lookup gaps unresolved

The version-specific literal is `Patient/42/_history/v2`. The entry fullUrl stays
versionless, and the resource carries meta.versionId v2. The runner removes the
history suffix only to locate that fullUrl, then checks the requested revision.
It does not discard the version requirement. FHIR fullUrl itself is not a
version-specific URL.

A versionless reference with two candidate versions is refused by this exercise's
conservative policy. Revision strings are opaque. Choosing the lexically largest
label or last network arrival is not an implemented latest-version agreement.
A duplicated fullUrl plus revision remains ambiguous even if one candidate looks
more useful to the application.

For a logical-only reference, HL7 permits context-dependent identifier resolution.
This lab deliberately requires a separately agreed lookup and returns
identifier_lookup_required. It does not claim logical references are invalid
FHIR, or that FHIR prohibits inspecting identifiers within a Bundle. The fixture
has no authoritative business-identifier mapping or permitted source lookup.

The resolver supports only the stated collection, Patient-subject and literal
forms. Unsupported forms remain unresolved. A refusal is not a general FHIR
validation verdict. The same applies to not_in_bundle: any actual source read
would need a trusted allowlist, authorization, profile/freshness policy, response
bounds and receiving ownership. Never follow arbitrary supplied URLs just to
make the unresolved state disappear.

## 5. Receive the reference contract as a healthcare pod

Use integration builder, source/terminology steward and receiving engineer roles.
Combine roles explicitly for small groups; label solo work self-review. Each
person keeps their own predictions, evidence and help received. The receiver
chooses entry reversal or a requested revision and asks the builder to locate
its target and unresolved boundary without taking over their navigation.

| Role | Receiving responsibility |
| --- | --- |
| Integration builder | Preserve the referring resource, literal form, base/fullUrl, requested revision and exact observed evidence path |
| Source/identity steward | Establish permitted server and business-identifier context; define ambiguity and lookup policies |
| Receiving engineer | Reproduce one stable target and one withheld case, then return the specific missing evidence and next owner |
| Security/platform owner | Verify actual source authentication, URL restrictions, workspace permissions, limits and freshness before deployment |

```text
My role / exact command and report:
Prediction before resolving the reference:
Referring fullUrl / original Reference field:
Derived locator / requested resource revision:
Observed entry path or contained path / exact target:
One changed condition / prediction before that run:
New observation kept separately:
Receiving action actually attempted / assistance:
Unresolved lookup or authority / next accountable role and bounded action:
```

The result state is located_in_fixture, not patient_verified or ready_for_care.
Do not use real patient records in this exercise. Completing it does not establish
independent review, qualification, client placement or authority to access a
health system. Carry the identity evidence into the existing versioned-handoff
contract rather than treating a located record as a supported eligibility fact.

## 6. Defend the boundary in an interview

Why is Patient/42 insufficient without context? When can a UUID reference be
located locally? Why must a requested history revision survive URL matching?
Why does a contained id have a different scope? What evidence is still needed
for a business-identifier lookup? Explain using particular fixture rows.

Primary FHIR R4 sources checked 28 October 2026:

- [HL7 resource identity and business identifiers](https://hl7.org/fhir/R4/resource.html#identifiers).
- [HL7 resource references and logical identifier context](https://hl7.org/fhir/R4/references.html).
- [HL7 Bundle identity, contained distinction and reference resolution](https://hl7.org/fhir/R4/bundle.html#references).

The resolver policy, counterexamples and role exercise are original LockedIn
Labs instruction. Continue to [the versioned healthcare handoff](/training/guides/healthcare-handoff)
and its protected [Academy lesson](/app/academy?course=healthcare-operations&lesson=versioned-handoff&view=focus)
with existing training access.
