Skip to main content

Terminology Service — Application Logic

Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · 03 platform-services · 02 DDD


1. Commands

CommandHandlerSource FRNotes
CreateConceptConceptCommandHandlerFR-TERM-008Platform admin (global) or tenant admin (tenant-scoped)
UpdateConceptConceptCommandHandlerFR-TERM-008Updates display or definition only; code/system immutable
DeactivateConceptConceptCommandHandlerFR-TERM-008One-way; publishes TerminologyConcept.Deactivated
ImportConceptBatchImportCommandHandlerFR-TERM-009Admin CSV import; may be disabled via env flag; publishes TerminologyDataset.Updated

2. Queries

QueryHandlerSource FRCacheNotes
SearchConceptsConceptQueryHandlerFR-TERM-001No (dynamic)Full-text search; active concepts only; respects tenantId scope
LookupConceptConceptQueryHandlerFR-TERM-002Redis 1hExact system+code lookup
ValidateConceptConceptQueryHandlerFR-TERM-003Redis 1hReturns {valid: boolean, active: boolean}
ExpandValueSetValueSetQueryHandlerFR-TERM-004Redis 5minReturns active concepts for a ValueSet URL
GetDrugClassesDrugClassQueryHandlerFR-TERM-005Redis 1hReturns class(es) for an RxNorm code
CheckDrugInteractionsDrugInteractionQueryHandlerFR-TERM-006No (dynamic)Returns pairwise interactions for supplied RxNorm codes
CheckDuplicateTherapyDrugInteractionQueryHandlerFR-TERM-011No (dynamic)Returns drug pairs sharing a drug class
CheckContraindicationsDrugInteractionQueryHandlerFR-TERM-012No (dynamic)Returns drug-condition contraindication matches
TranslateConceptConceptMapQueryHandlerTERM-ENH-EPIC-01Redis 1hMaps code from source to target system via ConceptMap

3. Ports (Hexagonal Architecture)

PortDirectionAdapter
IConceptRepositoryOutDrizzle ORM → PostgreSQL
IDrugInteractionRepositoryOutDrizzle ORM → PostgreSQL
IDrugClassRepositoryOutDrizzle ORM → PostgreSQL
IDrugContraindicationRepositoryOutDrizzle ORM → PostgreSQL
IValueSetRepositoryOutDrizzle ORM → PostgreSQL
IConceptCacheOutRedis (ioredis)
IEventPublisherOutNATS JetStream via @ghasi/nats-client
IImportFileReaderOutMinIO or local filesystem (CSV)

4. Sequence: Concept Lookup (with Cache)


5. Sequence: Drug Interaction Check


6. Sequence: ValueSet Expansion


7. Sequence: Bulk Concept Import


8. Business Rules (applied in application layer)

RuleEnforcement point
Only active concepts returned by public queriesConceptQueryHandler — appends AND active = true to all read queries
Global concepts visible to all tenants; tenant concepts visible only to ownerConceptQueryHandlerWHERE tenant_id IS NULL OR tenant_id = :tenantId
Code and system are immutable after creationUpdateConcept command rejects changes to code/system fields
Deactivation is one-wayDeactivateConcept command checks active = true before proceeding
Only platform admin may manage global conceptsConceptCommandHandler — checks hasRole('platform:admin') when tenantId = null
Drug interactions checked symmetricallyQuery builds both (A,B) and (B,A) pairs before DB lookup
Duplicate therapy: two drugs sharing at least one classNameDrugInteractionQueryHandler — joins drug_classes on rxnormCode IN (codes) and groups by className
Import endpoint disabled if TERMINOLOGY_CONCEPT_IMPORT_ENABLED=falseImportCommandHandler — returns 403 at guard level when flag is off