# b10 EHI Export Format Specification (`ndjson-v1`)
**Status:** Active (Phase 4 Certification Hardening)
**Format Version:** `ndjson-v1`
**Specification Revision:** `2026.06.24-r4`
**Applies To:** ONC 170.315(b)(10) single-patient and population EHI export packages
**Canonical Contract Companion:** `docs/b10-ehi-export-manifest-contract.md`
---
## Table of Contents
1. [Layperson Summary](#layperson-summary)
2. [Purpose and Audience](#purpose-and-audience)
3. [Normative Language](#normative-language)
4. [Authoritative ZIP Layout](#authoritative-zip-layout)
5. [Manifest Schema (`manifest.json`)](#manifest-schema-manifestjson)
6. [NDJSON Rules (FHIR R4)](#ndjson-rules-fhir-r4)
7. [Resource Types Included](#resource-types-included)
8. [Data Dictionary and Field Definitions](#data-dictionary-and-field-definitions)
9. [Supplemental File Handling](#supplemental-file-handling)
10. [Checksums and Documentation URL Verification](#checksums-and-documentation-url-verification)
11. [Third-Party Parsing Procedure](#third-party-parsing-procedure)
12. [Worked Examples](#worked-examples)
13. [Supported Export Types](#supported-export-types)
14. [Generation Instructions](#generation-instructions)
15. [Authorized Roles and Scopes](#authorized-roles-and-scopes)
16. [No-Charge Statement](#no-charge-statement)
17. [Terms of Use](#terms-of-use)
18. [Physical Media Statement](#physical-media-statement)
19. [Relied-Upon Software](#relied-upon-software)
20. [Public Documentation URL](#public-documentation-url)
21. [Versioning and Change Control](#versioning-and-change-control)
22. [Conformance Checklist](#conformance-checklist)
23. [Troubleshooting](#troubleshooting)
---
## Layperson Summary
This document is the external parsing guide for Scribe Mutual EHI exports.
If a certifier or outside developer has only a ZIP file and this document, they should be able to:
- understand where every file must be located,
- validate whether the package is tampered or malformed,
- parse clinical NDJSON safely,
- and detect mismatches between manifest metadata and actual package contents.
In plain terms: the ZIP is a shipment, `manifest.json` is the packing list, `checksums.sha256` is tamper detection, and `clinical.ndjson` files are the machine-readable patient records.
---
## Purpose and Audience
This specification is for:
- independent validators,
- integration teams consuming exports,
- and certification auditors validating ONC 170.315(b)(10) behavior.
This document defines package format only. It does not define API authentication, permissions, or job scheduling internals.
---
## Normative Language
The words below are normative:
- **MUST**: mandatory for conformance
- **MUST NOT**: prohibited
- **SHOULD**: recommended unless a documented reason exists
- **MAY**: optional
---
## Authoritative ZIP Layout
Every export MUST be a ZIP archive with ZIP-relative paths only.
### Always Required Package-Level Files
```text
manifest.json
export-format-url.txt
checksums.sha256
```
### Required Clinical Payload Pattern
```text
patients/{patientId}/clinical.ndjson
```
### Optional Supplemental Payload Patterns
```text
patients/{patientId}/documents/{filename}
patients/{patientId}/media/{filename}
interoperability/{patientId}/{filename}.hl7
```
Layout constraints:
- Paths MUST NOT be absolute.
- Paths MUST NOT contain `..` path traversal segments.
- Population exports MAY contain zero patients (empty valid population package), one patient, or many patients.
- Single-patient exports MUST contain exactly one patient clinical path.
---
## Manifest Schema (`manifest.json`)
`manifest.json` MUST be valid JSON and MUST conform to the schema below.
### Top-Level Fields
| Field | Type | Required | Allowed Values / Rules | Meaning |
|---|---|---|---|---|
| `jobId` | string | yes | ULID | Export job identifier |
| `exportType` | string | yes | `single-patient` or `population` | Package export scope |
| `formatVersion` | string | yes | `ndjson-v1` | Package format contract version |
| `documentationUrl` | string | yes | Absolute URL in non-dev | Public parser specification URL |
| `createdAt` | string | yes | ISO 8601 timestamp | Package creation time |
| `requestedBy` | string | yes | non-empty | Requesting user/service identifier |
| `patientCount` | integer | yes | `>= 0` | Number of distinct exported patients |
| `fileCount` | integer | yes | must equal total ZIP file entries (`>= 3`; can be exactly `3` for empty population) | Total ZIP file entries |
| `files` | array | yes | one item per ZIP file | Inventory of package contents |
### `files[]` Entry Fields
| Field | Type | Required | Allowed Values / Rules | Meaning |
|---|---|---|---|---|
| `path` | string | yes | ZIP-relative; no `..` | File path inside ZIP |
| `category` | string | yes | `clinical-ndjson`, `document-binary`, `media-binary`, `interoperability-raw`, `manifest`, `checksum`, `format-url` | File classification |
| `patientId` | string or null | yes | patient logical ID or `null` for package-level files | Subject ownership |
| `mediaType` | string | yes | MIME type | Content type |
| `sha256` | string or null | yes | 64-char lowercase hex or `null` for generated contract files | Integrity digest |
| `sizeBytes` | integer or null | yes | `>= 0` or `null` for generated contract files | File size |
| `recordCount` | integer or null | yes | NDJSON line count for NDJSON files; `null` for non-NDJSON | NDJSON record quantity |
| `sourceSubsystem` | string | yes | source domain label | Origin of data |
Contract note:
- `manifest.json` and `checksums.sha256` entries may use `sha256: null` and `sizeBytes: null` in the inventory to avoid recursive checksum/self-size dependency.
- For all non-generated payload files, `sha256` and `sizeBytes` MUST be populated.
---
## NDJSON Rules (FHIR R4)
For every `patients/{patientId}/clinical.ndjson`:
- Content MUST be UTF-8.
- Each non-empty line MUST be a standalone JSON object.
- Each JSON object MUST contain `resourceType`.
- Payload MUST represent FHIR R4 resources (one resource per line).
- File SHOULD end with a trailing newline.
- Parsed line count MUST equal `manifest.files[].recordCount` for that path.
Consumers MUST NOT assume array wrappers. This is line-delimited JSON, not a JSON list document.
---
## Resource Types Included
The canonical FHIR resource types included by contract are:
- `Patient`
- `Encounter`
- `Condition`
- `Observation`
- `MedicationRequest`
- `AllergyIntolerance`
- `Procedure`
- `Immunization`
- `DiagnosticReport`
- `DocumentReference`
- `CareTeam`
- `Consent`
- `EpisodeOfCare`
- `List`
- `Media`
- `Provenance`
- `Communication`
- `Appointment`
Source of truth for the implementation list:
- `SM_backend/src/services/ehi/drsExportContract.js` (`CANONICAL_RESOURCES`)
Supplemental payload classes that may appear as file artifacts (not additional NDJSON resource types):
- clinical notes raw text
- CCDA XML
- Direct message attachments
- raw HL7 messages
---
## Data Dictionary and Field Definitions
This section describes the available data elements, field names, and how each field should be interpreted by a receiving system or end user.
For the complete field-level reference, see the companion [EHI Export Data Dictionary](b10-ehi-export-data-dictionary.md). The summary below covers the key elements for each resource type.
### Terminology and Coding Systems
Coded clinical data elements use nationally recognized terminology systems identified by the `system` field within FHIR `coding` arrays:
| System URI | Name | Used For |
|------------|------|----------|
| `http://snomed.info/sct` | SNOMED CT | Conditions, procedures, clinical findings |
| `http://loinc.org` | LOINC | Observations, lab results, vital signs, document types |
| `http://www.nlm.nih.gov/research/umls/rxnorm` | RxNorm | Medications (drug names, ingredients, strengths) |
| `http://hl7.org/fhir/sid/cvx` | CVX | Vaccine codes |
| `http://hl7.org/fhir/sid/icd-10-cm` | ICD-10-CM | Diagnosis codes |
| `http://hl7.org/fhir/sid/icd-10-pcs` | ICD-10-PCS | Procedure codes |
| `http://www.ama-assn.org/go/cpt` | CPT | Procedure codes |
| `http://terminology.hl7.org/CodeSystem/condition-clinical` | Condition Clinical Status | active, inactive, resolved, remission |
| `http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical` | Allergy Clinical Status | active, inactive, resolved |
| `http://terminology.hl7.org/CodeSystem/observation-category` | Observation Category | vital-signs, laboratory, social-history |
Coded fields use the FHIR `CodeableConcept` structure: `coding[].system` identifies the terminology, `coding[].code` is the machine-readable code, `coding[].display` is the human-readable label, and `text` is a free-text summary.
### Resource Field Summaries
#### Patient (Demographics)
Core demographic and administrative information. Key fields: `name` (given/family), `birthDate`, `gender`, `address`, `telecom` (phone/email), `identifier` (MRN and external IDs), `maritalStatus`, `communication` (languages), `contact` (emergency contacts), `generalPractitioner`, `managingOrganization`. US Core extensions may include race, ethnicity, and birth sex.
#### Encounter (Clinical Visits)
Records of patient-provider interactions. Key fields: `status` (planned/in-progress/finished/cancelled), `class` (AMB=ambulatory, IMP=inpatient, VR=virtual), `type` (visit type coded with SNOMED CT), `period` (start/end timestamps), `participant` (involved providers), `reasonCode` (visit reason), `diagnosis` (encounter diagnoses with references to Condition resources).
#### Condition (Problems / Diagnoses)
Clinical conditions on the patient's problem list. Key fields: `clinicalStatus` (active/inactive/resolved/remission), `verificationStatus` (confirmed/unconfirmed/refuted), `code` (diagnosis coded in SNOMED CT or ICD-10-CM), `onsetDateTime` (when it started), `recordedDate` (when entered in the system).
#### Observation (Vitals / Lab Results)
Clinical measurements and findings. Key fields: `status` (final/preliminary/amended), `category` (vital-signs/laboratory/social-history), `code` (what was measured, coded in LOINC), `effectiveDateTime` (when measured), `valueQuantity` (numeric result with unit in UCUM), `valueCodeableConcept` (coded result), `valueString` (text result), `interpretation` (normal/high/low/abnormal flags), `referenceRange` (normal ranges), `component` (sub-measurements like systolic/diastolic for blood pressure).
#### MedicationRequest (Prescriptions)
Medication orders and prescriptions. Key fields: `status` (active/completed/cancelled/stopped), `intent` (order), `medicationCodeableConcept` (drug name coded in RxNorm), `authoredOn` (prescription date), `requester` (prescribing provider), `dosageInstruction` (dosing text, timing, route), `dispenseRequest` (refill count, quantity).
#### AllergyIntolerance (Allergies)
Recorded allergies and intolerances. Key fields: `clinicalStatus` (active/inactive/resolved), `verificationStatus` (confirmed/unconfirmed), `type` (allergy vs intolerance), `category` (food/medication/environment), `criticality` (low/high), `code` (substance coded in RxNorm or SNOMED CT), `reaction` (manifestation symptoms and severity).
#### Procedure (Procedures)
Clinical procedures performed. Key fields: `status` (completed/in-progress/not-done), `code` (procedure coded in SNOMED CT, CPT, or ICD-10-PCS), `performedDateTime` (when performed), `performer` (who performed it), `bodySite` (anatomical location), `reasonCode` (indication).
#### Immunization (Vaccines)
Vaccine administration records. Key fields: `status` (completed/not-done), `vaccineCode` (vaccine product coded in CVX), `occurrenceDateTime` (administration date), `primarySource` (true=administered here, false=patient-reported), `lotNumber`, `site`, `route`.
#### DiagnosticReport (Reports)
Diagnostic test results and interpretations. Key fields: `status` (final/preliminary/amended), `category` (LAB/RAD/PATH), `code` (report type coded in LOINC), `effectiveDateTime` (specimen collection or exam time), `result` (references to individual Observation resources), `conclusion` (narrative interpretation), `presentedForm` (rendered report document).
#### DocumentReference (Documents)
Pointers to clinical documents. Key fields: `status` (current/superseded), `type` (document type coded in LOINC), `date` (creation date), `author` (who created it), `content` (attachment with `contentType` MIME type and `url` or embedded `data`), `context` (related encounter). Supplemental files in the `documents/` folder are described by DocumentReference resources in the NDJSON.
#### CareTeam (Care Coordination)
Healthcare team composition. Key fields: `status` (active/inactive), `participant` (team members with `role` and `member` reference to Practitioner/Organization), `managingOrganization`.
#### Consent (Consent / Advance Directives)
Patient consent records. Key fields: `status` (active/rejected/inactive), `scope` (adr=advance directive, patient-privacy, treatment), `dateTime` (when consent was given), `sourceReference` (reference to source DocumentReference), `provision` (consent constraints with permit/deny rules).
#### EpisodeOfCare (Care Episodes)
Managed care periods. Key fields: `status` (active/finished/cancelled), `type` (care episode type), `diagnosis` (related conditions), `period` (time span), `careManager` (responsible provider).
#### List (Clinical Lists)
Curated clinical item collections (problem lists, medication lists). Key fields: `status` (current/retired), `mode` (working/snapshot), `code` (list type), `entry` (items with references to clinical resources).
#### Media (Clinical Media)
Clinical images and recordings. Key fields: `status` (completed), `type` (classification), `content` (attachment with MIME type and data/URL), `createdDateTime`.
#### Provenance (Audit Trail)
Resource origin and modification history. Key fields: `target` (resources this record describes), `recorded` (timestamp), `agent` (who/what made the change).
#### Communication (Messages / Notifications)
Clinical messages and patient notifications. Key fields: `status` (completed), `category` (message type), `sent` (timestamp), `payload` (message content as `contentString`). Sources include patient portal notifications, Direct secure messages, and care coordination communications.
#### Appointment (Scheduling)
Calendar appointments. Key fields: `status` (booked/fulfilled/cancelled/noshow), `start`/`end` (UTC timestamps), `description` (appointment title/reason), `participant` (patient and provider references with acceptance status).
### Data Provenance Tagging
Resources synthesized from legacy data stores (rather than stored natively as FHIR) carry a provenance tag in `meta.tag`:
```json
{ "system": "urn:scribe-mutual:ehi:source", "code": "patient_conditions" }
```
The `code` value identifies the source data store. Resources **without** this tag were stored natively as FHIR R4 and are exported as-is. Synthesized resources contain faithfully mapped clinical content but may have fewer populated fields. See the [Data Dictionary](b10-ehi-export-data-dictionary.md) for the complete field mapping table.
### Supplemental File Interpretation
| File Type | Location Pattern | Format | Why Included |
|-----------|-----------------|--------|--------------|
| Clinical notes | `patients/{id}/documents/note-*.txt` | UTF-8 plain text | Finalized clinician-authored note content (accepted/signed/finalized status only) |
| C-CDA documents | `patients/{id}/documents/ccda-*.xml` | HL7 C-CDA R2.1 XML | Complete clinical documents in native C-CDA format; parseable with any C-CDA reader |
| Direct attachments | `patients/{id}/documents/direct-*.{ext}` | Varies (per `mediaType` in manifest) | Attachments from Direct secure health messaging exchanges |
| Raw HL7 messages | `interoperability/{id}/*.hl7` | HL7 v2.x pipe-delimited text | Complete interoperability record; included because HL7→FHIR conversion is confirmed lossy (drops NTE, OBR, NK1, IN1, AL1, DG1, GT1, Z-segments, and many PID/PV1/OBX fields) |
---
## Supplemental File Handling
Supplemental files are optional and appear only when available for the patient.
### Documents
- Path: `patients/{patientId}/documents/{filename}`
- Typical media types: `application/pdf`, `text/plain`, `application/xml`, `application/octet-stream`
### Media
- Path: `patients/{patientId}/media/{filename}`
- Includes non-document binary payloads allowed by scope policy
### Raw HL7
- Path: `interoperability/{patientId}/{filename}.hl7`
- Preserved as interoperability artifacts for downstream reconciliation or traceability
All supplemental files MUST:
- appear in `manifest.files[]`,
- carry checksum rows in `checksums.sha256`,
- and follow the same ZIP path safety constraints.
---
## Checksums and Documentation URL Verification
### `checksums.sha256`
Each line MUST use this exact pattern (double-space separator):
```text
{sha256_hex} {relative/path/to/file}
```
Verification procedure:
1. Parse each line into expected hash and path.
2. Recompute SHA-256 for each ZIP entry except `checksums.sha256`.
3. Compare actual digest to expected digest.
4. Any mismatch is non-conformant.
### `export-format-url.txt` and `manifest.documentationUrl`
- `export-format-url.txt` MUST contain exactly one URL line.
- URL line MUST equal `manifest.documentationUrl`.
- In non-dev environments, `documentationUrl` MUST be absolute HTTPS and externally reachable.
- Implementations MAY expose multiple no-auth route aliases, but all aliases MUST serve byte-equivalent documentation content.
---
## Third-Party Parsing Procedure
A third-party parser SHOULD execute this exact order:
1. Open ZIP; enumerate file entries.
2. Assert required package-level files exist.
3. Parse `manifest.json`; validate required fields and types.
4. Validate `manifest.formatVersion === "ndjson-v1"`.
5. Parse `checksums.sha256`; verify digest format and path mapping.
6. Verify checksums for all non-checksum files.
7. Validate path safety (no absolute paths, no traversal).
8. Parse each `clinical.ndjson` line; assert JSON parse success and `resourceType` presence.
9. Reconcile counts:
- ZIP file count vs `manifest.fileCount`
- distinct patient clinical paths vs `manifest.patientCount`
- NDJSON line counts vs per-file `recordCount`
10. Validate URL parity:
- `export-format-url.txt` equals `manifest.documentationUrl`
11. Optionally fetch `documentationUrl` to confirm third-party discoverability.
Any failed check means the package is non-conformant.
---
## Worked Examples
### Example A: Minimal Valid Single-Patient Package
```text
manifest.json
export-format-url.txt
checksums.sha256
patients/patient-123/clinical.ndjson
```
### Example B: Multi-Patient Package With Supplemental Data
```text
manifest.json
export-format-url.txt
checksums.sha256
patients/patient-1/clinical.ndjson
patients/patient-1/documents/discharge-summary.pdf
patients/patient-2/clinical.ndjson
patients/patient-2/media/image-1.jpg
interoperability/patient-2/admission.hl7
```
Example multi-patient manifest facts:
- `exportType = "population"`
- `patientCount = 2`
- `fileCount = 8`
- `files[]` has one row per ZIP path above with matching `category`, `recordCount`, and checksums metadata.
### Example Invalid Pattern A: Manifest/File Drift
- `manifest.fileCount=8`, actual ZIP file entries=7
Result: non-conformant (inventory mismatch).
### Example Invalid Pattern B: NDJSON Missing `resourceType`
- a parsed NDJSON line object has no `resourceType`
Result: non-conformant (FHIR line invariant violation).
### Example Invalid Pattern C: URL Drift
- `manifest.documentationUrl` differs from `export-format-url.txt`
Result: non-conformant (documentation pointer mismatch).
### Example Invalid Pattern D: Generated-File Metadata Drift
- `manifest.files[]` entry for `category = manifest` has non-null `sha256` while `checksums.sha256` entry has nullability rules violated
Result: non-conformant (contract nullability mismatch for generated inventory rows).
---
## Supported Export Types
This product supports two certified EHI export types as required by ONC 170.315(b)(10):
| Export Type | Manifest `exportType` | Description |
|-------------|----------------------|-------------|
| **Single-patient** | `single-patient` | Exports all EHI for one identified patient. May complete synchronously or asynchronously depending on data volume. |
| **Population** | `population` | Exports all EHI for all patients in the system. Always processed asynchronously. An empty population (zero patients) produces a valid package with `patientCount: 0`. |
Both export types produce a ZIP archive in the `ndjson-v1` format described in this specification.
---
## Generation Instructions
### Single-Patient Export
**Endpoint:** `POST /api/v2/ehi-exports/patients/{patientId}`
**Authentication:** Bearer token with `ehi:export:single` scope (or admin role)
**Request:**
```
POST /api/v2/ehi-exports/patients/patient-123
Authorization: Bearer <token>
Content-Type: application/json
{
"ttlHours": 72,
"documentationUrl": "https://app.scribemutual.com/ehi-export-format/ndjson-v1"
}
```
**Synchronous response** (HTTP 200): The response body is the ZIP file with `Content-Type: application/zip`.
**Asynchronous response** (HTTP 202): When the export exceeds the sync timeout, the server returns a job reference:
```json
{
"jobId": "01HXYZ...",
"status": "accepted",
"mode": "async",
"statusUrl": "/api/v2/ehi-exports/jobs/01HXYZ..."
}
```
**Polling:** `GET /api/v2/ehi-exports/jobs/{jobId}` returns current job status. When `status` is `completed`, the response includes a download URL.
**Download:** `GET /api/v2/ehi-exports/jobs/{jobId}/download` returns the ZIP file.
### Patient-Population Export
**Endpoint:** `POST /api/v2/ehi-exports/population`
**Authentication:** Bearer token with `ehi:export:population` scope (or admin role)
**Request:**
```
POST /api/v2/ehi-exports/population
Authorization: Bearer <token>
Content-Type: application/json
{
"ttlHours": 168,
"documentationUrl": "https://app.scribemutual.com/ehi-export-format/ndjson-v1"
}
```
**Response** (HTTP 202): Population exports are always asynchronous:
```json
{
"jobId": "01HXYZ...",
"status": "accepted",
"mode": "async",
"statusUrl": "/api/v2/ehi-exports/jobs/01HXYZ..."
}
```
**Polling and download:** Same as single-patient (see above).
### Job Management
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/v2/ehi-exports/jobs/{jobId}` | GET | Check job status, progress, and download availability |
| `/api/v2/ehi-exports/jobs/{jobId}/download` | GET | Download completed export ZIP |
| `/api/v2/ehi-exports/jobs/{jobId}/cancel` | POST | Cancel a running or queued job |
---
## Authorized Roles and Scopes
EHI export access is controlled by scope-based authorization. The following scopes govern export capabilities:
| Scope | Grants |
|-------|--------|
| `ehi:export:single` | Trigger single-patient EHI export for patients the user has access to |
| `ehi:export:population` | Trigger patient-population EHI export (all patients in the system) |
| `ehi:export:admin` | Full export access including job management for any user's jobs |
**Access rules:**
- Users with the **admin** role have implicit access to all export operations.
- **Healthcare professionals** (HCP) with the `ehi:export:single` scope can export data for patients assigned to them.
- **Population export** requires elevated privileges (`ehi:export:population` or admin role) and is typically restricted to system administrators or designated data officers.
- **Patient portal users** are explicitly denied access to the b(10) EHI export pathway. Patient self-service export is out of scope for this certification criterion.
- **Job access** is restricted to the job owner or admin users. A user cannot view, download, or cancel another user's export jobs unless they hold admin privileges.
---
## No-Charge Statement
The certified ONC 170.315(b)(10) EHI export functionality is provided at **no additional charge** to users of the Scribe Mutual platform. There are no fees, surcharges, or per-export costs associated with generating, downloading, or using single-patient or patient-population EHI exports.
This applies to both the export functionality itself and access to this public format documentation.
---
## Terms of Use
1. **Intended use.** The EHI export is intended to facilitate patient access to their health information and to support healthcare provider transitions between health IT systems, consistent with the purposes described in ONC 170.315(b)(10).
2. **Data accuracy.** Exported data reflects the electronic health information stored in the Scribe Mutual system at the time of export. The developer makes no warranty regarding the clinical accuracy or completeness of data entered by healthcare providers or imported from external systems.
3. **Recipient responsibility.** Recipients of EHI export packages are responsible for handling the data in compliance with applicable federal and state privacy laws, including HIPAA.
4. **No redistribution warranty.** This export format specification is provided for interoperability purposes. Redistribution of exported patient data must comply with all applicable privacy and security regulations.
5. **Format stability.** The `ndjson-v1` format version will remain stable for the duration of its certification lifecycle. Format changes will be published under a new version identifier.
6. **Support.** Technical questions about the export format may be directed to the Scribe Mutual development team. The publicly accessible documentation at the canonical URL is the authoritative reference.
---
## Physical Media Statement
No physical media (CD, DVD, USB drive, or printed materials) is used for the certified ONC 170.315(b)(10) EHI export. All exports are provided as electronic ZIP archives accessible via authenticated API download.
If a requesting party requires delivery on physical media due to special circumstances, such arrangements must be made separately and are outside the scope of the certified export capability.
---
## Relied-Upon Software
The certified EHI export does not rely on any third-party EHI export service. All export logic (scope resolution, data assembly, NDJSON serialization, ZIP packaging, manifest generation, checksum computation, and validation) is implemented within the Scribe Mutual product.
The following infrastructure components are used at runtime:
| Component | Role | Required? |
|-----------|------|-----------|
| Node.js | Application runtime | Yes |
| Express | HTTP server | Yes |
| PostgreSQL | Database (FHIR resource storage) | Yes |
| Knex | Database query builder | Yes |
| archiver | ZIP archive creation | Yes |
| AWS S3 | Export package storage (production) | Optional (local storage fallback) |
| AWS KMS | Encryption key management | Optional (local key fallback) |
For a complete inventory with version numbers and build/test-only components, see [`docs/drummond-self-testing/b10-relied-upon-software-and-third-party-inventory.md`](drummond-self-testing/b10-relied-upon-software-and-third-party-inventory.md).
---
## Public Documentation URL
This specification is served at two equivalent public URLs, both accessible without authentication:
| URL | Purpose |
|-----|---------|
| `https://app.scribemutual.com/ehi-export-format/ndjson-v1` | Canonical public documentation URL |
| `https://app.scribemutual.com/public/ehi-export-format/ndjson-v1` | Public alias (identical content) |
Both routes:
- Return HTTP 200 with `Content-Type: text/html`
- Require no authentication, cookies, or session
- Include a `X-Documentation-Url` response header with the canonical URL
- Serve the complete format specification rendered as HTML
The canonical URL is embedded in every export package via:
- `manifest.json` → `documentationUrl` field
- `export-format-url.txt` → single-line URL content
---
## Versioning and Change Control
### Format Version
- `formatVersion` is currently fixed at `ndjson-v1`.
- Any new format MUST use a new version label (for example `ndjson-v2`) and retain backward parse guidance.
### Specification Revision
- This document revision: `2026.04.29-r3`.
- Revision updates MAY clarify parsing guidance but MUST NOT silently change format behavior for the same `formatVersion`.
### Change Log
- `2026.06.24-r4`: Added comprehensive Data Dictionary and Field Definitions section (Section 8) with per-resource-type field summaries, terminology/coding system reference table, data provenance tagging explanation, supplemental file interpretation guide, and link to companion data dictionary document. Addresses Drummond reviewer feedback on data element detail and field interpretation guidance.
- `2026.04.29-r3`: Added Drummond checklist section (4) compliance: Supported Export Types, Generation Instructions, Authorized Roles and Scopes, No-Charge Statement, Terms of Use, Physical Media Statement, Relied-Upon Software summary, and Public Documentation URL sections.
- `2026.04.26-r2`: Added full manifest schema tables, explicit canonical resource-type list, worked multi-patient example, and formal versioning/change-control section for certification closeout.
---
## Conformance Checklist
A package is conformant only when all checks pass:
- required files are present,
- manifest schema and inventory validate,
- checksums validate for package contents,
- NDJSON lines parse and include `resourceType`,
- patient/file/record counts reconcile,
- documentation URL fields match,
- path safety rules hold.
Layperson summary: a third party can trust and parse the package if file layout, metadata, checksums, and NDJSON structure all agree.
---
## Troubleshooting
### Symptom: checksum mismatch
- Rebuild package and regenerate checksums after all payload files are finalized.
- Confirm the ZIP was not modified post-generation.
### Symptom: NDJSON parse failure
- Ensure one JSON object per line.
- Ensure UTF-8 encoding and no multiline object formatting.
### Symptom: patient counts do not reconcile
- Verify each exported patient has exactly one `clinical.ndjson` path.
- Confirm `manifest.patientCount` matches distinct patient clinical paths.
### Symptom: parser cannot reproduce expected output
- Run the validator script against the package first.
- If ambiguity remains, treat this as spec debt and update this document before release.