Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help


id: TEDY.02 template: tool-feature module: tedy state: Proposed traces-from: [] # TODO: link terminology-editor user stories source-refs:

  • reference-editor/app/src/app/resources/value-set
  • reference-editor/app/src/app/resources/_lib/value-set/model/value-set.ts
  • reference-editor/app/src/app/resources/_lib/value-set/model/value-set-version.ts
  • reference-editor/app/src/app/resources/_lib/value-set/model/value-set-version-rule.ts
  • reference-editor/app/src/app/resources/_lib/value-set/model/value-set-version-rule-set.ts
  • reference-editor/app/src/app/resources/_lib/value-set/model/value-set-version-concept.ts
  • reference-editor/app/src/app/resources/_lib/value-set/services/value-set-lib.service.ts # GET /ts/value-sets*
  • reference-editor/app/src/app/resources/value-set/services/value-set.service.ts # write /ts/value-sets*
  • reference-editor/app/src/app/fhir/_lib/value-set/services/fhir-value-set-lib.service.ts # /fhir/ValueSet*
  • terminology-server (/ts/value-sets, /ts/value-set-versions, /fhir/ValueSet, /file-importer/value-set) author: TEDY bootstrap created: 2026-08-08 updated: 2026-08-08

TEDY.02 – Value Set (Common Spec)

Description

Common specification for Value Set management in TEDY — browse, view, and author FHIR ValueSets over terminology-server (/ts/value-sets). Unlike a Code System (which owns its concepts), a Value Set selects concepts from one or more code systems (or other value sets) through compose rules; those rules are expanded into the concrete member list (and materialized as a snapshot). This root spec owns the shared vocabulary, data model, compose/expansion model, FHIR mapping, privileges, the full API surface, and navigation so the child (screen) specs don’t duplicate them.

terminology-server owns persistence + the FHIR + expansion engine; TEDY is the React client. Derived via spec-authoring.md (Step-1 dev-tx.example scan, Step-2 reference-editor + terminology-server reconcile). The complete REST surface below was read from reference-editor’s value-set services and confirmed live on dev-tx.example (guest yupi).

Child specs:

Glossary Terms

Term (canonical)Meaning
Value SetA FHIR ValueSet — a curated selection of concepts drawn from code systems / other value sets.
VersionA ValueSetVersion with a publication status (draft/active/retired) + release date; carries the rule set.
Rule setValueSetVersion.ruleSet — the container of compose rules for that version (lockedDate, inactive, rules[]).
Compose ruleValueSetVersionRule — one include/exclude entry referencing a code system (or another value set), optionally narrowed by explicit concepts, filters, and properties.
FilterValueSetRuleFilter{property, operator, value} on a rule (e.g. is-a, descendent-of); operators per FHIR filter-operator.
ExpansionThe concrete member list produced by evaluating the rule set (POST /ts/value-sets/expand).
SnapshotValueSetSnapshot — a stored, materialized expansion for a version (conceptsTotal, expansion[]).
Member (concept)ValueSetVersionConcept — an expanded member: concept (code + system) + display + additionalDesignations + orderNumber + active.
DesignationA member’s localized display; display is the chosen one, additionalDesignations the rest.
PublisherValueSet.publisher — resolved via the publisher value set when a code, else free text.

Business Feature Sitemap

flowchart LR
    US["(TODO) US: manage value sets"] --> ROOT[TEDY.02]
    ROOT --> LST[TEDY.02.1 List]
    ROOT --> CRT[TEDY.02.2 Add]
    ROOT --> VIEW[TEDY.02.3 View]
    LST -->|Add value set| CRT
    LST -->|row / ID| VIEW
    CRT -->|save| VIEW
    VIEW --> RULES[Rules / compose]
    VIEW --> EXP[Concepts / expansion]
    RULES -->|expand| EXP

Data Model

Shared model for list / create / view. terminology-server owns the tables; TEDY consumes the JSON envelopes.

Entity / Resourcethe reference platform APIFHIRNotes
ValueSet/ts/value-setsValueSetlist + detail; lastVersion / versions decorated
ValueSetVersion/ts/value-sets/{id}/versionsValueSet.versionstatus ∈ draft/active/retired; carries ruleSet
ValueSetVersionRuleSet(embedded in version)ValueSet.compose{id, lockedDate, inactive, rules[]}
ValueSetVersionRule(embedded in ruleSet)ValueSet.compose.include/excludetype = include/exclude
ValueSetRuleFilter(embedded in rule)ValueSet.compose.*.filter{property, operator, value}
ValueSetVersionConceptexpand result / snapshotValueSet.compose.*.concept / expansion.containsexpanded member
ValueSetSnapshotversion.snapshotValueSet.expansionmaterialized {conceptsTotal, expansion[]}
List envelopen/an/a{ data: [...], meta: { total, offset } }

Shared ValueSet fields

FieldTypeCard.Rule
idstring1..1identity; renamed only via change-id
uristring0..1canonical URL; unique
namestring0..1machine name
titleLocalizedName0..1multilingual display
description / purposeLocalizedName0..1
publisherstring0..1code from publisher VS or free text
narrativestring0..1HTML narrative (FHIR text)
experimentalboolean0..1
sourceReferencestring0..1
otherTitle{name, preferred}[]0..*aliases
topic{text, tags[]}0..1
useContext{type, value}[]0..*
identifiersIdentifier[]0..*
contactsContactDetail[]0..*name + telecoms
configurationAttributesany[]0..*
copyright{holder, jurisdiction, statement}0..1
permissions{admin, editor, viewer, endorser}0..1
settings{reviewRequired, approvalRequired}0..1
versions / lastVersionValueSetVersion[]0..*version + status + releaseDate + ruleSet + snapshot

ValueSetVersion fields

FieldTypeRule
idnumberversion key (with version) for PUT vs POST
versionstringsemver-ish; unique per value set
statuscodedraft / active / retired (lifecycle endpoints)
releaseDate / expirationDatedate (YYYY-MM-DD)
preferredLanguagestring
supportedLanguagesstring[]
descriptionLocalizedName
algorithmstringversion algorithm (e.g. semver)
ruleSetValueSetVersionRuleSetthe compose rules
snapshotValueSetSnapshotstored expansion (conceptsTotal, expansion[])
identifiersIdentifier[]

Compose model (ValueSet-specific)

ValueSetVersion.ruleSet          # ValueSetVersionRuleSet {id, lockedDate, inactive}
  └── rules[]                    # ValueSetVersionRule
        ├── type                 # 'include' | 'exclude'
        ├── codeSystem           # source code system id  (rule targets a CS…)
        ├── codeSystemVersion    # CodeSystemVersionReference {id, version}
        ├── valueSet             # …or another value set…
        ├── valueSetVersion      # ValueSetVersionReference
        ├── concepts[]           # explicit ValueSetVersionConcept members
        ├── filters[]            # ValueSetRuleFilter {property, operator, value}
        └── properties[]         # property codes to carry into members

ValueSetVersionConcept (a member): { id, concept: CodeSystemConcept, display: Designation, additionalDesignations: Designation[], orderNumber, active }.

Used value sets (resolved via @helex/tx)

FieldValueSetCanonical URLBinding
publisherpublisherhttps://tx.example/fhir/ValueSet/publisherextensible
version statuspublication-statushttp://hl7.org/fhir/ValueSet/publication-statusrequired
supported/preferred languagelanguageshttp://hl7.org/fhir/ValueSet/languagesrequired (the reference platform has no all-languages)
rule filter operatorfilter-operatorhttp://hl7.org/fhir/ValueSet/filter-operatorrequired

FHIR Mapping (Common)

Internal fieldFHIR R5 pathMapping
idValueSet.iddirect
uriValueSet.urldirect
nameValueSet.namedirect
titleValueSet.titletransform (LocalizedName → language-resolved)
publisherValueSet.publisherdirect
purposeValueSet.purposetransform
narrativeValueSet.textdirect (HTML)
version ruleSet.rules[type=include]ValueSet.compose.include[]transform
version ruleSet.rules[type=exclude]ValueSet.compose.exclude[]transform
rule filters[]compose.*.filter[]{property, op, value}
version snapshot.expansion[]ValueSet.expansion.contains[]transform

Common Rules

  • A value set’s members are derived by expanding the version’s ruleSet; never stored on the ValueSet root. Read the members via expansion (POST /ts/value-sets/expand) or the version snapshot.
  • Snapshot vs live: prefer the stored snapshot.expansion when present (fast); fall back to a live expand for drafts / previews. Rule editing previews use expand-rule (a single unsaved rule).
  • Version lifecycle mirrors Code System: draft → active → retire, via dedicated endpoints (empty body, 204); editing an active version’s metadata is frozen server-side (the reference platform rule).
  • Publisher / status / language / filter-operator selects use TxConceptSelect(url=…) (dev proxies /api/tx/$expand → the reference platform FHIR).
  • Concept/member display resolves from display (a Designation) → language match → the member code.

Shared Privileges

ActionPrivilege
View / browseauthenticated (dev: guest via the reference platform yupi)
Create / edit / delete / versions / rulesValueSet.write (the reference platform {id}.ValueSet.write)

Common API Surface

Base /ts/value-sets unless noted. All TEDY calls go through @helex/tedy’s txApi (/txapi → dev-tx.example /api).

ValueSet CRUD

MethodPathPrivDescription
GET/ts/value-setsreadlist — params below
GET/ts/value-sets/{id}?decorate={bool}readload one (decorate embeds versions + ruleSet + snapshot)
POST/ts/value-sets/transactionwritecreate/update — body ValueSetTransactionRequest {valueSet, version?, identifiers?}
POST/ts/value-sets/{id}/change-idwriterename id — body {id: newId}
DELETE/ts/value-sets/{id}writedelete value set
GET/ts/value-sets/{id}/provenances?version=readprovenance history

List params (ValueSetSearchParams): id, ids, idContains, uri, uriContains, name, nameContains, description, descriptionContains, text, textContains, versionId, versionVersion, versionStatus, versionSource, decorated, lastVersionDecorated, lang, codeSystem, conceptCode, spaceId, packageId, packageVersionId, + limit/offset/sort.

Versions + lifecycle

MethodPathPrivDescription
GET/ts/value-sets/{id}/versionsreadversion list
GET/ts/value-sets/{id}/versions/{version}readload one version (with ruleSet + snapshot)
GET/ts/value-set-versions/{id}readload a version by numeric id
POST/ts/value-sets/{id}/versionswritecreate version (body ValueSetVersion)
PUT/ts/value-sets/{id}/versions/{version}writeupdate version
POST/ts/value-sets/{id}/versions/{version}/draftwrite→ draft (empty body, 204)
POST/ts/value-sets/{id}/versions/{version}/activatewrite→ active
POST/ts/value-sets/{id}/versions/{version}/retirewrite→ retired
POST/ts/value-sets/{id}/versions/{version}/duplicatewriteduplicate — body {valueSet, version}
DELETE/ts/value-sets/{id}/versions/{version}writedelete version

Compose rules / rule-sets

MethodPathPrivDescription
POST/ts/value-sets/{id}/versions/{v}/ruleswriteadd a compose rule (ValueSetVersionRule)
PUT/ts/value-sets/{id}/versions/{v}/rules/{ruleId}writeupdate a rule
DELETE/ts/value-sets/{id}/versions/{v}/rules/{ruleId}writedelete a rule
PUT/ts/value-sets/{id}/versions/{v}/rule-sets/{ruleSetId}writeupdate the rule set (e.g. inactive)

Expansion

MethodPathPrivDescription
POST/ts/value-sets/expandreadexpand a saved version — body {valueSet, valueSetVersion}ValueSetVersionConcept[]
POST/ts/value-sets/expand-asyncreadasync expand → JobLogResponse (poll)
POST/ts/value-sets/expand-rulereadpreview one unsaved rule — body {valueSet, valueSetVersion, inactiveConcepts?, rule}ValueSetVersionConcept[]
GET/ts/value-sets/{id}/versions/{v}/expansion-export?format={csv|xlsx|…}readstart expansion export (→ processId)
GET/ts/value-sets/expansion-export-{format}/result/{processId}readdownload export result

FHIR façade (read/validate/sync)

MethodPathDescription
GET/fhir/ValueSet/{id}[|{version}]read FHIR ValueSet
GET/fhir/ValueSetFHIR search
GET/fhir/ValueSet/{id}/$expandexpand by id
GET/fhir/ValueSet/$expand?url=…expand by canonical (used by @helex/tx selects)
GET/fhir/ValueSet/$validate-codevalidate a code against the VS
POST/fhir/ValueSet/$syncsync (body Parameters)

Import

MethodPathDescription
POST/file-importer/value-set/processfile import (multipart) → JobLogResponse

Sitemap / Navigation

  • /tedy/value-sets — list (TEDY.02.1)
  • /tedy/value-sets/new — create (TEDY.02.2)
  • /tedy/value-sets/{id} — view shell (TEDY.02.3): Summary · Metadata · Concepts (expansion) · Rules
  • /tedy/value-sets/{id}/versions/new · /versions/{version}/edit — version form
  • /tedy/value-sets/{id}/compare — version compare (placeholder, shared pattern)

(Standalone Router basename="/tedy"; menu routes are basename-relative.)

Non-functional Requirements

RequirementTarget
List load< 2s; server-side pagination (20/page); lastVersionDecorated only
Expansion (snapshot)< 2s; prefer stored snapshot; live expand only for drafts/preview
Rule preview (expand-rule)responsive; debounce edits
Search debounce~400ms

Business Tests

  1. List / view / create operate over /ts/value-sets* with the shared envelope.
  2. A version’s members come from expanding its ruleSet (or its snapshot), never from the root.
  3. Version lifecycle (draft/activate/retire) + rule add/edit/delete require ValueSet.write; read is open on the guest dev server.
  4. Publisher/status/language/filter-operator render via their value sets.

Traces

  • traces-from: TODO user stories
  • children: TEDY.02.1, TEDY.02.2, TEDY.02.3
  • sibling family: TEDY.01 Code System (shares the shell, version form, summary widgets)