Technical manual
cdr.pdhc is the canonical clinical data repository for the PDHC platform.
It receives normalised observations from gateway.pdhc (and later 2gate.pdhc),
stores them in a three-layer architecture (raw → standard → canonical), and
automatically delivers concept-mapped data to the Cambio CDR sandbox.
Ports: 9046 (Flask), 9047 (PostgreSQL), 9048–9049 reserved.
ingest_rawfhir_resources — FHIR R5 Observation resourcesopenehr_compositions — openEHR Compositionshealth_observations — numeric health metrics (weight, BP, SpO2, etc.)activities — activity-type observations (steps, exercise, etc.)The transformer uses a LOINC-to-archetype mapping table (11 seed entries):
| LOINC | Metric | openEHR Archetype | Unit |
|---|---|---|---|
| 29463-7 | body_weight_kg | openEHR-EHR-OBSERVATION.body_weight.v2 | kg |
| 85354-9 | blood_pressure_systolic | openEHR-EHR-OBSERVATION.blood_pressure.v2 | mmHg |
| 8867-4 | heart_rate_bpm | openEHR-EHR-OBSERVATION.pulse.v2 | /min |
| 8310-5 | body_temperature_c | openEHR-EHR-OBSERVATION.body_temperature.v2 | Cel |
| 2708-6 | spo2_percent | openEHR-EHR-OBSERVATION.pulse_oximetry.v1 | % |
| 8302-2 | body_height_cm | openEHR-EHR-OBSERVATION.height.v2 | cm |
| 9279-1 | respiratory_rate | openEHR-EHR-OBSERVATION.respiration.v2 | /min |
| 39156-5 | bmi | openEHR-EHR-OBSERVATION.body_mass_index.v2 | kg/m2 |
| 2339-0 | blood_glucose_mmol | openEHR-EHR-OBSERVATION.laboratory_test_result.v1 | mmol/L |
| 8280-0 | waist_circumference_cm | openEHR-EHR-OBSERVATION.waist_circumference.v2 | cm |
| 93832-4 | sleep_hours | openEHR-EHR-OBSERVATION.sleep.v0 | h |
Unknown LOINC codes fall back to the generic laboratory_test_result.v1 archetype.
The 8-step ingest pipeline processes each incoming observation:
Two headers required:
- X-Service-Key: shared secret per source service
- X-Source-Service: service identifier (gateway.pdhc or 2gate.pdhc)
AUTH_MODE=sso enables SSO; AUTH_MODE=off uses dev SU userOnly observations with a concept_guid referencing the plan.pdhc.se concept store
are eligible for Cambio delivery. Data without concept mappings is stored locally only.
Single observation ingest. Returns 202 (accepted) or 200 (duplicate).
Batch ingest (max 100). Accepts {"items": [...]} or bare array.
FHIR CapabilityStatement.
Search FHIR resources. Optional: limit, offset.
Read single FHIR resource.
Search openEHR compositions.
Query canonical tables (health_observations, activities).
Delivery counts by status (pending, delivered, failed, skipped).
Patient mapping + delivery history.
Reset all failed deliveries to pending.
cd /usr/local/www/cdr.pdhc
bash start.sh
cd /usr/local/www/cdr.pdhc
bash safe_restart.sh
| Variable | Purpose |
|---|---|
| DATABASE_URL | PostgreSQL connection string |
| AUTH_MODE | off (dev) or sso (production) |
| SSO_BASE_URL | SSO service URL |
| SSO_CLIENT_ID / SSO_CLIENT_SECRET | SSO client credentials |
| GATEWAY_PDHC_SERVICE_KEY | Shared secret for gateway.pdhc |
| CAMBIO_DELIVERY_ENABLED | true to activate delivery worker |
| CAMBIO_CLIENT_ID / CAMBIO_CLIENT_SECRET | Cambio OAuth2 credentials |
| CAMBIO_BASE_URL | Cambio sandbox base URL |
| CAMBIO_TOKEN_URL | Cambio IdP token endpoint |
13 tables across PostgreSQL:
| Table | Layer | Description |
|---|---|---|
| ingest_raw | Raw | Immutable payload store |
| fhir_resources | Standard | FHIR R5 Observations |
| openehr_compositions | Standard | openEHR Compositions |
| health_observations | Canonical | Numeric health metrics |
| activities | Canonical | Activity observations |
| clinical_context | Provenance | Careplan/transaction links |
| dedupe_registry | Infra | SHA-256 dedup hashes |
| loinc_archetype_map | Infra | LOINC ↔ archetype mappings |
| service_keys | Auth | Gateway service keys |
| users | Auth | SSO-synced users |
| audit_log | Governance | Event audit trail |
| cambio_patient_map | Cambio | PDHC ↔ Cambio patient IDs |
| cambio_delivery_log | Cambio | Delivery tracking with retry |