Registry stack documentation: machine-readable Markdown.
Index of all pages: https://docs.registrystack.org/llms.txt
Full corpus: https://docs.registrystack.org/llms-full.txt

# Configure a FHIR R4 integration

> Use product-neutral script calls and the bounded FHIR R4 search-set helper in a Registry Stack project.

import ProjectStarterSequence from '../../../components/ProjectStarterSequence.astro';

Use this guide when a reviewed source exposes a bounded FHIR R4 search journey that needs more
than one HTTP request. You will keep source authority in configuration, use ordinary Rhai for
project-specific decisions, and delegate FHIR search-set parsing to the versioned protocol helper.

{/* Evidence: crates/registryctl/tests/fixtures/project-authoring/fhir-r4-coverage-active/ and
    crates/registryctl/tests/project_authoring.rs. */}

## When to use this

Use `script` when one consultation must follow a bounded relationship or same-origin pagination
link. A maintained journey can:

1. search `Patient` with reviewed selector parameters;
2. follow at most the declared number of same-origin pages;
3. search `Coverage` using the selected Patient id; and
4. fetch a related `Organization` through a reviewed path rule.

This is not a generic FHIR proxy. The script cannot select another origin, credential, HTTP
method, unreviewed path, or output field. Transactions, subscriptions, GraphQL, writes, and
unbounded pagination remain outside the contract.

## Before you start

You need:

- a Registry Stack project and reviewed FHIR R4 endpoint;
- exact Patient selectors and bounded relationship rules;
- an `adapter.rhai` file; and
- synthetic request-aware fixtures for match, no match, and ambiguity.

## Try the bundled FHIR starter

The starter demonstrates the complete offline sequence before you adapt its endpoint, selectors,
relationships, and synthetic observations.

<ProjectStarterSequence starter="fhir-r4" />

## Declare typed inputs and source authority

The source product and version are optional interoperability evidence. They never select the
executor or make Rhai available.

```yaml
version: 1
id: coverage-active
revision: 1

source:
  product: fhir-server
  versions: { unverified: [r4-api] }
  auth: { type: none }
  allow:
    - { method: GET, path: /fhir/Patient }
    - { method: GET, path: /fhir/Coverage }
    - { method: GET, path: /fhir/Organization/* }

input:
  birthdate:
    role: selector
    type: string
    format: date
    minLength: 10
    maxLength: 10
  family: { role: selector, type: string, maxLength: 80 }
  given: { role: selector, type: string, maxLength: 80 }

capability:
  script: { file: adapter.rhai }

outputs:
  coverage_status: { type: string, maxLength: 32 }
  insurer_name: { type: string, maxLength: 160 }

limits:
  calls: 5
  source_bytes: 2MiB
  deadline: 15s
```

An exact rule admits only that path. `*` admits one bounded path segment. A terminal `/**` is
available when a reviewed API genuinely needs a bounded suffix. Query names and values remain
script-selected but are independently bounded and canonicalized by the host.

## Parse search-set Bundles in Rhai

Call the source through the host API, then pass the response to the FHIR helper:

```rhai
let response = source.get("/fhir/Patient", #{
    query: #{
        _count: 2,
        birthdate: ctx.input.birthdate,
        family: ctx.input.family,
        given: ctx.input.given
    }
});
if response.status != 200 {
    return result.fail(failure.source_rejected);
}
let page = protocol.fhir.parse_searchset(response, "Patient");
```

`protocol.fhir.parse_searchset` requires a FHIR R4 `Bundle` whose type is `searchset`. It returns
bounded `matches`, `included`, `outcomes`, and an optional `next` link. It rejects malformed
structure, wrong match resource types, and conflicting next links before the script can use them.

An absolute `next` link can be passed to `source.get` only when it has the configured source
origin and its path matches an allow rule. Fragments, user information, another port, another
scheme, and another host fail before dispatch.

The project script owns profile-specific choices such as identifier systems, Patient matching,
Coverage relationships, and the final minimized output map. Keep those decisions visible in the
script instead of adding product-specific Rust branches.

## Bind the private source

The environment supplies the deployment origin and secrets without repeating the auth type:

```yaml
integrations:
  coverage:
    source:
      origin: https://fhir.internal.invalid
      timeout: 10s
      concurrency: 4
      rate: { per_minute: 120, burst: 10 }
```

Add private CIDRs, a private CA, mTLS, or a credential binding only when the deployment needs
them. These settings cannot widen the stable method and path authority.

## Add request-aware fixtures

Each semantic fixture describes the exact canonical request and its synthetic response. Large
FHIR bodies belong under `fixtures/bodies/` and are referenced with `file`. Cover a positive
match, no match, ambiguity, and meaningful project-specific variations. The harness derives
platform-generic malformed, oversized, timeout, authorization-before-source, and minimization
checks.

## Verify the journey

```sh
registryctl test --project-dir <project>
registryctl check \
  --project-dir <project> \
  --environment <environment> \
  --explain
```

Confirm the request trace contains only reviewed methods and paths, safe header names, bounded
query shape, and the expected call order. Fixture success proves the compiled contract and local
decoder behavior. It does not prove interoperability, legal suitability, or deployment source
semantics.

## Troubleshooting

| Symptom | Cause | Fix |
| --- | --- | --- |
| `source.get` rejects a target | The path or absolute link is outside the reviewed source authority. | Correct the script or add the narrow reviewed allow rule. |
| The FHIR helper rejects a Bundle | The response is not one valid R4 search-set shape. | Correct the synthetic body or review the real source contract. |
| The result is ambiguous | More than one subject or relation matched within the bounded journey. | Strengthen reviewed selectors or correct the source data. |
| A later page is not fetched | The call limit, path rule, same-origin check, or deadline closed the request. | Use the smallest honest bounds demonstrated by fixtures. |

## Next

- Return to [Author an HTTP Registry Stack project](../author-registry-project/) to review and
  build the project.
- Use [Configure API-key source authentication](../configure-project-api-key-authentication/) if
  the FHIR endpoint requires a fixed API key.