Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ The Helios FHIR Server supports multiple storage backend configurations. Choose
| **PostgreSQL** | Built-in full-text search (tsvector/tsquery) | Production OLTP deployments |
| **PostgreSQL + Elasticsearch** | Elasticsearch-powered search with PostgreSQL CRUD | Production deployments needing RDBMS + robust search |
| **S3** | Object storage for CRUD, versioning, history, and bulk operations (no search) | Archival, bulk analytics, cost-effective storage |
| **S3 + Elasticsearch** | Elasticsearch-powered search with S3 object storage as canonical source | Object-storage-first deployments needing robust FHIR search |

### Running the Server

Expand Down Expand Up @@ -202,13 +203,23 @@ HFS_S3_BUCKET=my-fhir-bucket \
AWS_PROFILE=your-aws-profile \
AWS_REGION=us-east-1 \
./hfs

# S3 + Elasticsearch (S3 is canonical, Elasticsearch handles all search)
HFS_STORAGE_BACKEND=s3-elasticsearch \
HFS_ELASTICSEARCH_NODES=http://localhost:9200 \
HFS_S3_TENANCY_MODE=prefix-per-tenant \
HFS_S3_BUCKET=hfs \
HFS_S3_ENDPOINT_URL=http://localhost:9000 \
HFS_S3_ALLOW_HTTP=true \
HFS_S3_FORCE_PATH_STYLE=true \
./hfs
```

### Environment Variables

| Variable | Default | Description |
|---|---|---|
| `HFS_STORAGE_BACKEND` | `sqlite` | Backend mode: `sqlite`, `sqlite-elasticsearch`, `postgres`, `postgres-elasticsearch`, or `s3` |
| `HFS_STORAGE_BACKEND` | `sqlite` | Backend mode: `sqlite`, `sqlite-elasticsearch`, `postgres`, `postgres-elasticsearch`, `s3`, or `s3-elasticsearch` |
| `HFS_SERVER_PORT` | `8080` | Server port |
| `HFS_SERVER_HOST` | `127.0.0.1` | Host to bind |
| `HFS_DATABASE_URL` | `fhir.db` | Database URL (SQLite path or PostgreSQL connection string) |
Expand All @@ -219,8 +230,19 @@ AWS_REGION=us-east-1 \
| `HFS_ELASTICSEARCH_USERNAME` | *(none)* | ES basic auth username |
| `HFS_ELASTICSEARCH_PASSWORD` | *(none)* | ES basic auth password |
| `HFS_S3_BUCKET` | `hfs` | S3 bucket name (prefix-per-tenant mode) |
| `HFS_S3_TENANCY_MODE` | `prefix-per-tenant` | S3 tenant isolation mode (`prefix-per-tenant` or `bucket-per-tenant`) |
| `HFS_S3_TENANT_BUCKET_MAP` | *(none)* | Per-tenant bucket mapping (`tenant=bucket,tenant2=bucket2`) for bucket-per-tenant mode |
| `HFS_S3_DEFAULT_SYSTEM_BUCKET` | *(none)* | Optional fallback bucket for non-tenant/system artifacts |
| `HFS_S3_REGION` | *(AWS provider chain)* | AWS region override |
| `HFS_S3_PREFIX` | *(none)* | Optional global key prefix inside bucket(s) |
| `HFS_S3_ENDPOINT_URL` | *(none)* | Custom S3 endpoint (for MinIO/local S3-compatible storage) |
| `HFS_S3_FORCE_PATH_STYLE` | `false` | Use path-style addressing (`http://host/bucket/key`) |
| `HFS_S3_ALLOW_HTTP` | `false` | Allow plain HTTP endpoints for local/dev environments |
| `HFS_S3_VALIDATE_BUCKETS` | `true` | Validate bucket access on startup |
| `HFS_S3_ES_REINDEX_ON_STARTUP` | `false` | Rebuild Elasticsearch index from S3 current objects at startup (`s3-elasticsearch` mode) |
| `HFS_S3_ES_REINDEX_BATCH_SIZE` | `500` | Batch size for startup S3->ES reindex |
| `HFS_S3_ES_REINDEX_CLEAR_EXISTING` | `false` | Clear tenant/type ES indices before reindex replay |
| `HFS_S3_ES_REINDEX_RESOURCE_TYPES` | *(none)* | Optional comma-separated resource type filter for reindex |

For detailed backend setup instructions (building from source, Docker commands, and search offloading architecture), see the [persistence crate documentation](crates/persistence/README.md#building--running-storage-backends).

Expand Down Expand Up @@ -432,4 +454,3 @@ The Helios FHIR Server is licensed under the [MIT License](LICENSE).
---

HL7® and FHIR® are registered trademarks of Health Level Seven International.

Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@
<label value="requirement-2"/>
<conformance value="SHALL"/>
<requirement value="Operations based on the codeSystem resource SHALL have the same result whether or not the relationships are represented explicitly as properties or implicitly using the CodeSystem resource hierarchy"/>
<category>
<system value="http://example.org/requirement-categories"/>
<code value="processing"/>
</category>
<source>
<display value="Jose Costa Teixeira"/>
</source>
Expand Down
92 changes: 46 additions & 46 deletions crates/fhir/tests/data/xml/R6/account.profile.xml

Large diffs are not rendered by default.

150 changes: 75 additions & 75 deletions crates/fhir/tests/data/xml/R6/activitydefinition.profile.xml

Large diffs are not rendered by default.

56 changes: 28 additions & 28 deletions crates/fhir/tests/data/xml/R6/actordefinition.profile.xml

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions crates/fhir/tests/data/xml/R6/address.profile.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
<a href="types.html#Element" title="Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.">id</a>,
<a href="types.html#Element" title="May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.">extension</a>
</td>
</tr>
</tr>

<tr style="border: 0px #F0F0F0 solid; padding:0px; vertical-align: top; background-color: #F7F7F7">
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: #F7F7F7; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px; white-space: nowrap; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAACCAYAAACg/LjIAAAALUlEQVR4Xu3IoREAIAwEwfT6/ddA0GBAxO3NrLlKUj9263wAAAAvrgEAADClAVWFQIBRHMicAAAAAElFTkSuQmCC)" class="hierarchy">
Expand All @@ -71,7 +71,7 @@
<a href="terminologies.html#required" title="To be conformant, the concept in this element SHALL be from the specified value set.">Required</a>)
<br/>
</td>
</tr>
</tr>

<tr style="border: 0px #F0F0F0 solid; padding:0px; vertical-align: top; background-color: white">
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: white; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px; white-space: nowrap; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAACCAYAAACg/LjIAAAALUlEQVR4Xu3IoREAIAwEwfT6/ddA0GBAxO3NrLlKUj9263wAAAAvrgEAADClAVWFQIBRHMicAAAAAElFTkSuQmCC)" class="hierarchy">
Expand All @@ -93,7 +93,7 @@
<a href="terminologies.html#required" title="To be conformant, the concept in this element SHALL be from the specified value set.">Required</a>)
<br/>
</td>
</tr>
</tr>

<tr style="border: 0px #F0F0F0 solid; padding:0px; vertical-align: top; background-color: #F7F7F7">
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: #F7F7F7; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px; white-space: nowrap; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAACCAYAAACg/LjIAAAALUlEQVR4Xu3IoREAIAwEwfT6/ddA0GBAxO3NrLlKUj9263wAAAAvrgEAADClAVWFQIBRHMicAAAAAElFTkSuQmCC)" class="hierarchy">
Expand All @@ -112,7 +112,7 @@
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: #F7F7F7; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px" class="hierarchy">Text representation of the address
<br/>
</td>
</tr>
</tr>

<tr style="border: 0px #F0F0F0 solid; padding:0px; vertical-align: top; background-color: white">
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: white; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px; white-space: nowrap; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAACCAYAAACg/LjIAAAALUlEQVR4Xu3IoREAIAwEwfT6/ddA0GBAxO3NrLlKUj9263wAAAAvrgEAADClAVWFQIBRHMicAAAAAElFTkSuQmCC)" class="hierarchy">
Expand All @@ -132,7 +132,7 @@
<br/>This repeating element order: The order in which lines should appear in an address label
<br/>
</td>
</tr>
</tr>

<tr style="border: 0px #F0F0F0 solid; padding:0px; vertical-align: top; background-color: #F7F7F7">
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: #F7F7F7; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px; white-space: nowrap; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAACCAYAAACg/LjIAAAALUlEQVR4Xu3IoREAIAwEwfT6/ddA0GBAxO3NrLlKUj9263wAAAAvrgEAADClAVWFQIBRHMicAAAAAElFTkSuQmCC)" class="hierarchy">
Expand All @@ -151,7 +151,7 @@
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: #F7F7F7; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px" class="hierarchy">Name of city, town etc.
<br/>
</td>
</tr>
</tr>

<tr style="border: 0px #F0F0F0 solid; padding:0px; vertical-align: top; background-color: white">
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: white; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px; white-space: nowrap; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAACCAYAAACg/LjIAAAALUlEQVR4Xu3IoREAIAwEwfT6/ddA0GBAxO3NrLlKUj9263wAAAAvrgEAADClAVWFQIBRHMicAAAAAElFTkSuQmCC)" class="hierarchy">
Expand All @@ -170,7 +170,7 @@
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: white; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px" class="hierarchy">District name (aka county)
<br/>
</td>
</tr>
</tr>

<tr style="border: 0px #F0F0F0 solid; padding:0px; vertical-align: top; background-color: #F7F7F7">
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: #F7F7F7; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px; white-space: nowrap; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAACCAYAAACg/LjIAAAALUlEQVR4Xu3IoREAIAwEwfT6/ddA0GBAxO3NrLlKUj9263wAAAAvrgEAADClAVWFQIBRHMicAAAAAElFTkSuQmCC)" class="hierarchy">
Expand All @@ -189,7 +189,7 @@
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: #F7F7F7; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px" class="hierarchy">Sub-unit of country (abbreviations ok)
<br/>
</td>
</tr>
</tr>

<tr style="border: 0px #F0F0F0 solid; padding:0px; vertical-align: top; background-color: white">
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: white; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px; white-space: nowrap; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAACCAYAAACg/LjIAAAALUlEQVR4Xu3IoREAIAwEwfT6/ddA0GBAxO3NrLlKUj9263wAAAAvrgEAADClAVWFQIBRHMicAAAAAElFTkSuQmCC)" class="hierarchy">
Expand All @@ -208,7 +208,7 @@
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: white; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px" class="hierarchy">Postal code for area
<br/>
</td>
</tr>
</tr>

<tr style="border: 0px #F0F0F0 solid; padding:0px; vertical-align: top; background-color: #F7F7F7">
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: #F7F7F7; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px; white-space: nowrap; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAACCAYAAACg/LjIAAAALUlEQVR4Xu3IoREAIAwEwfT6/ddA0GBAxO3NrLlKUj9263wAAAAvrgEAADClAVWFQIBRHMicAAAAAElFTkSuQmCC)" class="hierarchy">
Expand All @@ -227,7 +227,7 @@
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: #F7F7F7; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px" class="hierarchy">Country (e.g. may be ISO 3166 2 or 3 letter code)
<br/>
</td>
</tr>
</tr>

<tr style="border: 0px #F0F0F0 solid; padding:0px; vertical-align: top; background-color: white">
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: white; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px; white-space: nowrap; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAACCAYAAACg/LjIAAAAJUlEQVR4Xu3IIQEAAAgDsHd9/w4EQIOamFnaBgAA4MMKAACAKwNp30CqZFfFmwAAAABJRU5ErkJggg==)" class="hierarchy">
Expand All @@ -246,7 +246,7 @@
<td style="vertical-align: top; text-align : var(--ig-left,left); background-color: white; border: 0px #F0F0F0 solid; padding:0px 4px 0px 4px" class="hierarchy">Time period when address was/is in use
<br/>
</td>
</tr>
</tr>

<tr>
<td colspan="5" class="hierarchy">
Expand All @@ -270,7 +270,7 @@
<name value="Address"/>
<status value="active"/>
<experimental value="false"/>
<date value="2025-11-27T16:48:47+00:00"/>
<date value="2025-12-17T09:50:17+00:00"/>
<publisher value="HL7 International / FHIR Infrastructure"/>
<contact>
<telecom>
Expand Down
Loading
Loading