Skip to main content

Terminology Service — Security Model

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · 13 security-compliance-tenancy · 02 DDD

1. Authentication

Route prefixMechanismNotes
GET /v1/terminology/*Keycloak JWT (Authorization: Bearer)All clinical service consumers; patient-facing via portal BFF
POST/PUT/DELETE /v1/terminology/concepts*JWT + role guard (platform:admin or tenant:admin)Concept CRUD requires elevated role
GET /fhir/R4/*JWT (same Keycloak realm)FHIR operation surface; proxied from interop-service
GET/POST /internal/terminology/*Optional X-Terminology-Internal-Token header OR network mesh trustService-to-service calls from within the cluster

Anonymous access is never permitted on any route (FR-TERM-010).


2. Authorization — RBAC Matrix

RoleAllowed operations
platform:adminCreate/update/deactivate global concepts; trigger imports; manage all value sets and concept maps
tenant:adminCreate/update/deactivate tenant-scoped concepts only; cannot touch global concepts
clinical:* (any clinical role)Read-only: search, lookup, validate, expand, CDS queries
service:internal (machine token)Internal routes: all read operations + import (if enabled)

3. Tenant Isolation

Terminology-service uses a dual-layer isolation model:

  1. PostgreSQL RLS policy: concepts table has RLS enabled. The policy concepts_tenant_isolation ensures a query with app.tenant_id = 'TENANT_A' can only see global concepts (tenant_id IS NULL) and concepts scoped to TENANT_A. Cross-tenant concept visibility is impossible at the database layer.

  2. Application-layer scope: All query handlers extract tenantId from the JWT tid claim and pass it to the repository. The internal route enforces tenantId = NULL (global only) when no JWT is present.


4. Data Classification

DataClassificationNotes
Global terminology conceptsPublic reference data (no PHI)SNOMED, LOINC, RxNorm, ICD-10 codes are publicly known
Tenant-scoped custom conceptsOrganizational reference dataMay contain internal facility coding; not PHI
Drug interactions / contraindicationsLicensed clinical knowledgeNot PHI; licensed data — never committed to repo
Query logs (what was searched/looked up)Operational dataNo PHI; service does not log the clinical context of the calling service

Terminology-service never handles or stores PHI. Concept codes are identifiers; clinical context (which patient has which condition) is never stored here.


5. Licensed Data Handling

Licensed terminology content (LOINC CSV, SNOMED RF2, RxNorm RRF) must never be committed to the source repository. The ETL pipeline loads licensed data into the PostgreSQL database at deployment time from a secured, access-controlled object storage bucket.

SystemLicenseRepository policy
LOINCFree (Regenstrief)No raw CSV in repo
SNOMED CTSNOMED NRC/affiliate licenseNo RF2 files in repo
RxNormNLM public domainNo RRF files in repo
Drug interaction dataCommercial license (Multum/DrugBank)No interaction data in repo
ICD-10-CMHHS / MoPH adaptationNo raw coding data in repo

6. Import Endpoint Security

POST /internal/terminology/import is:

  • Disabled in production by default (IMPORT_ENABLED=false).
  • Accessible only via the internal network route (not exposed through Kong).
  • Callable only by authenticated platform operators with platform:admin role.
  • Guarded by the optional X-Terminology-Internal-Token header when INTERNAL_TOKEN env var is set.

7. Audit Events

EventTriggerDestination
concept.createdAdmin creates a conceptNATS → audit-service
concept.deactivatedAdmin deactivates a conceptNATS → audit-service
dataset.updatedBulk import completesNATS → audit-service
Auth failureInvalid JWT or insufficient roleOpenTelemetry → security dashboard

Query operations (search, lookup, validate, expand, CDS) do not produce audit events — they are high-volume read-only operations. The calling clinical service is responsible for auditing its clinical decisions.


8. GDPR Participation

Terminology-service is out of scope for GDPR from a data subject perspective. It holds no personal data. No data subject rights (access, erasure, portability) apply to this service's data.