fhirsmith 0.18.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/ACCESSIBILITY.md +119 -0
  2. package/CHANGELOG.md +149 -0
  3. package/CONFIGURATION.md +305 -0
  4. package/LICENSE +29 -0
  5. package/README.md +29 -122
  6. package/cluster.js +1220 -0
  7. package/cluster.md +707 -0
  8. package/config-template.json +77 -8
  9. package/extension-tracker/extension-tracker-template.html +5 -8
  10. package/extension-tracker/extension-tracker.js +0 -2
  11. package/folder/folder.js +7 -6
  12. package/ips/analysis.js +560 -0
  13. package/ips/ips-template.html +5 -8
  14. package/ips/ips.js +132 -59
  15. package/ips/nationality.js +120 -0
  16. package/ips/pipeline.js +74 -21
  17. package/ips/presenter.js +1 -1
  18. package/ips/readme.md +132 -25
  19. package/ips/render.js +466 -77
  20. package/ips/store.js +79 -22
  21. package/ips/structure.js +247 -0
  22. package/ips/terminology.js +1 -1
  23. package/library/body-limit.js +22 -0
  24. package/library/cache-generation.js +15 -0
  25. package/library/cgroup-memory.js +133 -1
  26. package/library/cluster-counts.js +121 -0
  27. package/library/cluster-events.js +153 -0
  28. package/library/cluster-metrics.js +193 -0
  29. package/library/cluster-status.js +468 -0
  30. package/library/config-reader.js +96 -0
  31. package/library/daily-report.js +100 -2
  32. package/library/html-server.js +27 -1
  33. package/library/i18nsupport.js +23 -1
  34. package/library/keep-alive.js +18 -0
  35. package/library/languages.js +17 -3
  36. package/library/logger.js +31 -0
  37. package/library/memory-guard.js +428 -0
  38. package/library/native-memory.js +52 -0
  39. package/library/npm-audit.js +51 -25
  40. package/library/openapi-doc.js +7 -5
  41. package/library/package-manager.js +8 -0
  42. package/library/role.js +197 -0
  43. package/library/server-credentials.js +169 -0
  44. package/library/sqlite-utilities.js +59 -0
  45. package/library/ssrf-guard.js +100 -0
  46. package/library/static-response-stats.js +16 -0
  47. package/library/version-utilities.js +50 -0
  48. package/library/worker-count.js +192 -0
  49. package/nginx.md +30 -11
  50. package/npmprojector/indexer.js +18 -10
  51. package/package.json +11 -8
  52. package/packages/feed-check-page.js +117 -0
  53. package/packages/feed-check.js +279 -0
  54. package/packages/npm-check.js +57 -3
  55. package/packages/npm-signing.js +219 -0
  56. package/packages/openapi.yaml +207 -1
  57. package/packages/package-crawler.js +322 -41
  58. package/packages/packages-template.html +6 -8
  59. package/packages/packages.js +604 -57
  60. package/packages/readme.md +113 -1
  61. package/publisher/publisher-template.html +2 -5
  62. package/publisher/publisher.js +121 -110
  63. package/publisher/readme.md +75 -0
  64. package/registry/crawler.js +84 -108
  65. package/registry/documentation/configuration.md +34 -0
  66. package/registry/registry-template.html +5 -8
  67. package/registry/registry.js +5 -4
  68. package/root-bare-template.html +7 -4
  69. package/root-template.html +5 -8
  70. package/server.js +398 -198
  71. package/shl/shl.js +38 -37
  72. package/static/a11y/a11y-check.js +832 -0
  73. package/static/a11y/axe.min.js +12 -0
  74. package/static/assets/css/bootstrap-fhir.css +15 -15
  75. package/static/assets/images/flags/au.svg +18 -0
  76. package/static/assets/images/flags/unknown.svg +11 -0
  77. package/static/assets/images/flags/us.svg +63 -0
  78. package/static/assets/images/icon_audit.png +0 -0
  79. package/static/assets/images/icon_clinical.png +0 -0
  80. package/static/assets/images/icon_document.png +0 -0
  81. package/static/assets/images/icon_external.png +0 -0
  82. package/static/assets/images/icon_medication.png +0 -0
  83. package/static/assets/images/icon_organization.png +0 -0
  84. package/static/assets/images/icon_other.png +0 -0
  85. package/static/assets/images/icon_person.png +0 -0
  86. package/static/assets/images/icon_section.png +0 -0
  87. package/stats-db.js +45 -0
  88. package/stats.js +197 -10
  89. package/testing/testing-template.html +5 -8
  90. package/token/nginx_passport_setup.md +1 -1
  91. package/token/security_guide.md +1 -1
  92. package/token/token-template.html +2 -5
  93. package/token/token.js +40 -36
  94. package/translations/Messages.properties +19 -0
  95. package/tx/README.md +154 -4
  96. package/tx/closure/closure-store.js +126 -3
  97. package/tx/cm/cm-database.js +69 -57
  98. package/tx/cm/cm-package.js +29 -1
  99. package/tx/cs/cs-api.js +284 -19
  100. package/tx/cs/cs-api.md +41 -4
  101. package/tx/cs/cs-areacode.js +1 -1
  102. package/tx/cs/cs-country.js +17 -5
  103. package/tx/cs/cs-cpt.js +33 -16
  104. package/tx/cs/cs-cs.js +148 -14
  105. package/tx/cs/cs-currency.js +1 -1
  106. package/tx/cs/cs-icd11.js +21 -13
  107. package/tx/cs/cs-icf.js +22 -3
  108. package/tx/cs/cs-lang.js +2 -2
  109. package/tx/cs/cs-loinc.js +185 -66
  110. package/tx/cs/cs-mimetypes.js +12 -2
  111. package/tx/cs/cs-ndc.js +40 -25
  112. package/tx/cs/cs-omop.js +54 -29
  113. package/tx/cs/cs-rxnorm.js +300 -196
  114. package/tx/cs/cs-snomed.js +608 -64
  115. package/tx/cs/cs-ucum.js +14 -4
  116. package/tx/cs/cs-unii.js +18 -14
  117. package/tx/cs/cs-virtual.js +210 -0
  118. package/tx/ecosystem-resolver.js +413 -0
  119. package/tx/html/cluster-dash-metrics.liquid +26 -0
  120. package/tx/html/cluster-home-metrics.liquid +31 -0
  121. package/tx/html/cluster-metrics-script.liquid +251 -0
  122. package/tx/html/codesystem-operations.liquid +3 -3
  123. package/tx/html/ecl-panel.liquid +1 -1
  124. package/tx/html/external-metrics.liquid +17 -0
  125. package/tx/html/operations-form.liquid +17 -17
  126. package/tx/html/search-form.liquid +11 -11
  127. package/tx/html/status-line.liquid +58 -0
  128. package/tx/html/status-panel.liquid +140 -0
  129. package/tx/html/status-tasks.liquid +25 -0
  130. package/tx/html/tx-template.html +2 -5
  131. package/tx/importers/atc-to-fhir.js +17 -16
  132. package/tx/importers/export-icd11-codesystem.js +3 -2
  133. package/tx/importers/import-icd11.js +4 -3
  134. package/tx/importers/import-loinc.module.js +118 -56
  135. package/tx/importers/import-ndc.module.js +56 -44
  136. package/tx/importers/import-rxnorm.module.js +118 -79
  137. package/tx/importers/import-sct.module.js +57 -58
  138. package/tx/importers/import-unii.module.js +37 -36
  139. package/tx/importers/subset-loinc.module.js +49 -48
  140. package/tx/importers/subset-rxnorm.module.js +29 -28
  141. package/tx/importers/terminal.js +18 -0
  142. package/tx/importers/tx-import-base.js +13 -12
  143. package/tx/importers/tx-import-settings.js +5 -4
  144. package/tx/importers/tx-import.js +53 -52
  145. package/tx/library/canonical-resource.js +49 -0
  146. package/tx/library/codesystem.js +94 -5
  147. package/tx/library/designations.js +45 -2
  148. package/tx/library/extensions.js +13 -7
  149. package/tx/library/implicit-valuesets.js +66 -0
  150. package/tx/library/renderer.js +77 -21
  151. package/tx/library/sqlite-utilities.js +2 -0
  152. package/tx/library/ucum-parsers.js +11 -1
  153. package/tx/library/wait-for-cache.js +43 -0
  154. package/tx/library.js +321 -22
  155. package/tx/openapi-operations.js +6 -4
  156. package/tx/operation-context.js +460 -99
  157. package/tx/params.js +25 -0
  158. package/tx/problems.js +3 -5
  159. package/tx/provider.js +278 -42
  160. package/tx/resource-cache-sqlite.js +1050 -0
  161. package/tx/sct/ecl.js +47 -6
  162. package/tx/sct/editions.js +39 -0
  163. package/tx/sct/expressions.js +10 -1
  164. package/tx/sct/load-config.js +107 -0
  165. package/tx/sct/mmap.js +109 -0
  166. package/tx/sct/structures.js +166 -13
  167. package/tx/sct/text-index.js +5 -1
  168. package/tx/syndication/syndication-feed.js +2 -2
  169. package/tx/tx-html.js +44 -8
  170. package/tx/tx.fhir.org.yml +8 -8
  171. package/tx/tx.js +282 -80
  172. package/tx/usage-tracker.js +39 -11
  173. package/tx/vs/vs-api.js +19 -0
  174. package/tx/vs/vs-database.js +386 -62
  175. package/tx/vs/vs-package.js +27 -4
  176. package/tx/vs/vs-vsac.js +648 -100
  177. package/tx/workers/batch-validate.js +37 -10
  178. package/tx/workers/batch.js +6 -1
  179. package/tx/workers/cache-control.js +15 -4
  180. package/tx/workers/closure.js +156 -13
  181. package/tx/workers/compare.js +8 -5
  182. package/tx/workers/expand.js +1173 -289
  183. package/tx/workers/metadata.js +35 -0
  184. package/tx/workers/search.js +53 -1
  185. package/tx/workers/supplement-filters.js +145 -0
  186. package/tx/workers/translate.js +169 -4
  187. package/tx/workers/validate.js +223 -119
  188. package/tx/workers/worker.js +123 -31
  189. package/tx/xversion/xv-valueset.js +7 -4
  190. package/utilities/submit-test-report.js +3 -1
  191. package/utilities/tx-stress-test.js +482 -0
  192. package/vcl/readme.md +37 -0
  193. package/vcl/vcl-parser.js +15 -0
  194. package/xig/readme.md +52 -0
  195. package/xig/xig-template.html +5 -8
  196. package/xig/xig.js +238 -422
  197. package/changelog-template.md +0 -22
  198. package/registry/test-runner.js +0 -237
  199. package/release.sh +0 -80
  200. package/test-scripts/repro-re2-wasm-leak.js +0 -34
  201. package/tsconfig.eslint.json +0 -9
  202. package/tx/html/dash-metrics.liquid +0 -147
  203. package/tx/html/home-metrics.liquid +0 -225
package/ips/readme.md CHANGED
@@ -100,14 +100,42 @@ documentation section with the endpoint's URL, the CapabilityStatement link and
100
100
  the requests it answers - and `/ips/{code}/Bundle/{id}` shows the document.
101
101
  The document page's header names the patient, the document's date, when and how it was
102
102
  received and its size, with links to the FHIR JSON and to download it (`?download=1`, sent
103
- as an attachment named `ips-{code}-{id}.json`). Below it, each processing step is shown
104
- with where it is (tick: done, cross: failed, gear: running, moon: waiting - the step's note,
105
- or for managers the reason it failed, on hover), and managers get "Process again" and
106
- "Delete" buttons. The views of a document are tabs, chosen with `?view=`: `narrative` (the
107
- default - the Composition's narrative followed by each section's, with the section titles),
108
- `translation` (what the translate step did with each concept, below), `generated` (the
109
- narrative this server generates, below), `validation` (below), `terminology`, `ai` (the AI assessment, below) and `json`
110
- (pretty-printed, monospaced).
103
+ as an attachment named `ips-{code}-{id}.json`). Below it, the processing pipeline is shown
104
+ as one connected line: Received, then each step in the order it runs, coloured by where it
105
+ is (tick: done, cross: failed, gear: running, moon: waiting - the step's note, or for
106
+ managers the reason it failed, on hover); each step links to the view that shows its work.
107
+ Managers get "Process again" and "Delete" buttons. The views of a document are tabs, chosen
108
+ with `?view=`: `narrative` (the default; a switch, `&narrative=generated`, chooses between
109
+ the narrative as provided - the Composition's narrative followed by each section's, with
110
+ the section titles - and the narrative this server generates, below), `structure` (the
111
+ document's logical structure, below), `analysis` (what the analysis step found, below), `translation` (what
112
+ the translate step did with each concept, below), `terminology`, `validation` (below),
113
+ `national` (below), `profiles` (the clinical profile checks), `ai` (the AI assessment,
114
+ below) and `source` (the JSON, pretty-printed, monospaced). The old view names `generated`
115
+ and `json` still work. The actions (Edit, the Share buttons, and for managers Process again
116
+ and Delete) are on a line of their own below the pipeline.
117
+ `structure` shows the document as a tree table, in the style of the FHIR specification's
118
+ structure tables: columns Path, Type, Id and Details, with the tree drawn in the Path column
119
+ (each node expands and collapses; Expand all and Collapse all buttons; without scripts
120
+ every row shows). It starts at the Composition: first what the Composition refers to other
121
+ than its sections (subject, author, custodian, attesters, ...), then the sections, nested,
122
+ each with what it refers to (its entries, author, focus). Each reference's path is where it
123
+ is (`entry[0]`, `attester[0].party`), and the reference as given is on hover over the Id;
124
+ each resource expands into the references it makes, and so on (sections start open,
125
+ resources closed). A reference resolves as in a Bundle - by fullUrl, absolute or relative
126
+ to the referring entry's - and `#id` is a resource contained in the referring resource (or
127
+ in the resource that contains it). One that doesn't resolve is shown as external (not in
128
+ document). A resource is expanded once, at the shallowest place it is referred to (so one
129
+ the Composition refers to directly expands there, not inside the subject that also refers to
130
+ it); everywhere else it is shown again, greyed, saying where it is expanded, but doesn't
131
+ expand a second time. Details says what the resource is - a name (a person's, an organization's),
132
+ else its code (`code`, the medication - following `medicationReference` -, `vaccineCode`,
133
+ `type`...), with an Observation's value - and when: the first of the clinical dates (onset,
134
+ occurrence, performed, effective, ...), falling back to the record's own (`recorded`,
135
+ `issued`, `date`, `meta.lastUpdated`). Icons, from `static/assets/images`: the document,
136
+ sections, people (Patient, Practitioner, PractitionerRole, RelatedPerson), organizations,
137
+ medications (Medication and the Medication* resources), other clinical resources, Provenance
138
+ and AuditEvent, references outside the document, and anything else.
111
139
  `terminology` lists every CodeableConcept in the document (`ips/terminology.js`): the
112
140
  Composition's own, then each section's entries in the IPS section order (Patient Story,
113
141
  Problems, Allergies, Medications, ... Results; sections not in that list after, in document
@@ -157,10 +185,10 @@ takes submitted documents in turn, marks each `processing`, runs the pipeline's
157
185
  it (`ips/pipeline.js`), and marks it `processed` with the steps' notes, or `error` with the
158
186
  message of the step that failed. Each step's own state (`waiting`, `running`, `done` or
159
187
  `failed`, with its note or error) is kept in its result row as it goes, which is what the
160
- document page's step line shows; processing again clears every step's result first. The pipeline, in order, will be: **translate** CodeableConcepts
188
+ document page's step line shows; processing again clears every step's result first. The pipeline, in order, will be: determine the document's **nationality**; **analyse** each resource; **translate** CodeableConcepts
161
189
  to the international terminologies; generate the **narrative**; **validate** the document; validate it against the
162
190
  **national profiles**; measure its quality with PIQI; check it against the **clinical profiles**; **assess** it with AI. Translation, the narrative,
163
- validation, the national profiles, the **terminology check**, the clinical profiles check and the AI assessment exist so far (PIQI does not). A step keeps what it finds in one of two places: as a result stored against the
191
+ validation, the analysis, the national profiles, the **terminology check**, the clinical profiles check and the AI assessment exist so far (PIQI does not). A step keeps what it finds in one of two places: as a result stored against the
164
192
  document in `document_results` (one row per step - the validation outcome), or in the
165
193
  **analysed copy** - a second copy of the document (`documents.analysed_json`) that the steps
166
194
  adorn with extensions, so that the master document is never changed. The analysed copy is
@@ -168,16 +196,85 @@ rebuilt from the master on every run, so a document can always be processed agai
168
196
  Anything left `processing` when the server stopped is queued again at startup. Managers can
169
197
  queue a document again from its page, though not while it is being processed.
170
198
 
199
+ ### Nationality
200
+
201
+ The first step (`ips/nationality.js`) works out which nation the document is from, as far as the document says -
202
+ few national IGs give a way to tell, so this is a short list of signs, to grow as more are found:
203
+
204
+ - **US**: the Bundle claims the US Patient Summary profile (`http://hl7.org/fhir/us/pcs/StructureDefinition/Bundle-us-pcs`),
205
+ or a US Core extension (`http://hl7.org/fhir/us/core/StructureDefinition/...`) is used anywhere in the document;
206
+ - **AU**: the Bundle claims the AU Patient Summary profile (`http://hl7.org.au/fhir/ps/StructureDefinition/au-ps-bundle`).
207
+
208
+ The nation is its ISO 3166 two-letter code, or unknown when nothing points to a nation, or the signs point to more
209
+ than one. It is kept as the step's result (with the reasons) and in `documents.nationality`, for the list: the
210
+ project page has a Nation column (the code, or `??`), the document page shows the nation's flag to the left of the
211
+ banner (a black and white globe when it isn't known, or there is no flag for it yet -
212
+ `static/assets/images/flags/{code}.svg`), and the first bullet on the Composition in the analysis view says what was
213
+ decided, and why.
214
+
215
+ ### Analysis
216
+
217
+ The first step (`ips/analysis.js`), over the document as submitted. It walks the same tree
218
+ as the structure view (`ips/structure.js`) and, for each resource there (once, where it is
219
+ first met; contained resources too) and for the Composition section by section (the
220
+ Composition itself without its sections), keeps a list of findings, by the node's key
221
+ (`e{n}` for entry n, `e{n}#id` for a contained resource, `s:{path}` for a section):
222
+
223
+ - every extension, at any depth (a primitive's extensions are at the primitive's path; an
224
+ extension's own parts are not listed), with its definition when the module can find one
225
+ - the validator is asked (fhir-validator-wrapper's `lookupCanonical()`, the service's
226
+ `/canonical`, which answers from the validator's context; with `autoLoadPackages`, on by
227
+ default, the validator finds, downloads and loads the package that defines an extension it
228
+ doesn't have, as it does while validating), and the answers are cached - or a note that it
229
+ couldn't be found;
230
+ modifier extensions likewise, in maroon; `textLink` extensions are left out;
231
+ - `implicitRules`, in maroon;
232
+ - in navy: `active` = false; a status of `entered-in-error` (and a Condition's or
233
+ AllergyIntolerance's `verificationStatus` of entered-in-error); a status of `unknown`; or no
234
+ status where the resource requires one (`lifecycleStatus` for a Goal);
235
+ - in dark green: a `subject` (or `patient`) that isn't the document's - not the same
236
+ resource in the document, nor the same reference, nor the same identifier - and any `focus`;
237
+ - dates in the future, where one isn't expected. Only elements the (R4) type model says are
238
+ dates (date, dateTime, instant) are looked at - so not an identifier or a note that looks
239
+ like a date - and not inside extensions. Some dates are about the future by their nature and
240
+ are never mentioned: the end of a period (a name's, address's or identifier's validity, a
241
+ prescription's), expiry dates, due dates, and schedules (Timing). Some resources may have
242
+ future dates: Appointment, AppointmentResponse, ImmunizationRecommendation, Schedule and
243
+ Slot always; requests and plans (ServiceRequest, MedicationRequest, DeviceRequest,
244
+ NutritionOrder, CommunicationRequest, SupplyRequest, VisionPrescription, CarePlan, Task, and
245
+ a Goal by its lifecycleStatus) until they are over (completed, revoked, cancelled,
246
+ entered-in-error, stopped, failed or rejected); and events still to come - a Procedure in
247
+ preparation, a planned Encounter, an intended MedicationStatement or DeviceUseStatement. A
248
+ date with no time zone is in the future only if it is everywhere;
249
+ - a Patient's `link`s; a Composition whose status isn't `final`;
250
+ - for a section: its `emptyReason`, and an author other than that of what contains it (the
251
+ Composition, or the containing section - which may have inherited its own);
252
+ - whether there is narrative.
253
+
254
+ With nothing but the narrative to say, a resource is "All OK". The `analysis` view shows the
255
+ structure as a flat table - each node's row as in the structure view but with its full path
256
+ (`Composition.section[0].entry[0].resolve().subject`) - with a row under each that lists the
257
+ findings; a resource already shown is "Analysed above", and a reference to a resource not
258
+ in the document has no rows at all.
259
+
171
260
  ### Translation
172
261
 
173
- The first step. Every CodeableConcept the terminology view lists is checked as the
262
+ The second step. Every CodeableConcept the terminology view lists is checked as the
174
263
  terminology check (below) checks it; one that fails - no coding in the element's value set,
175
264
  or, for an element with no value set of its own, no international coding - is sent to the
176
265
  terminology server to translate: `ConceptMap/$translate` with `sourceCodeableConcept` (the
177
266
  concept as submitted) and `targetScope` (the element's value set, or the fallback), the
178
- value set and what it draws on as `tx-resource`. The server chooses the concept maps. Every
267
+ value set and what it draws on as `tx-resource`. A SNOMED CT coding with no version is sent as a code of
268
+ the edition of the document's nation: when the [nationality](#nationality) step found one, and a national profile
269
+ for that nation names a SNOMED CT edition, the coding goes with `version` = `http://snomed.info/sct/{edition}`
270
+ (the document is not changed, and the translation view says which edition was used). Which edition a code is
271
+ from decides which maps apply - a national edition's own concepts translate to the International Edition. The
272
+ terminology check does not do this: it takes the codes as they are, so a SNOMED CT code with no version passes if
273
+ it is fine as it is, and one whose version names another edition does not. The server chooses the concept maps. Every
179
274
  match that comes back (whatever its relationship) is added to the concept in the analysed
180
- copy as a Coding, unless the concept already has that system and code, with an extension
275
+ copy as a Coding, unless the concept already has that coding - the same system and code, and the same version
276
+ when both give one (SNOMED CT versions compared by edition: the same code in the International Edition is a
277
+ different coding from the one in a national edition, and is what the translation is for) - with an extension
181
278
  saying where it came from:
182
279
  `http://healthintersections.com.au/fhirsmith/StructureDefinition/ips-translation`, with
183
280
  `server` (the terminology server, as configured), `conceptMap` (the match's `originMap`, when
@@ -240,15 +337,16 @@ does (`fhir-validator-wrapper`: the validator CLI jar in the data folder's `bin`
240
337
  run as a service on its own `port`, with `txServer` - tx.fhir.org, by default - and the IPS
241
338
  package loaded). `jar` names a validator jar of its own instead - a validator built locally from
242
339
  org.hl7.fhir.core, say: absolute, or relative to the data folder (`bin/local/validator_cli.jar`) - which
243
- is used as it is, never downloaded or updated. Keep such a jar out of `bin/validator_cli.jar`: the
244
- wrapper takes that jar's version from the `.version` file it wrote when it downloaded the release
245
- there, so a different jar in its place is started as if it were that release (and is replaced by
246
- the next one). It starts in the background when the module does, and the queue waits for
340
+ is used as it is, never downloaded or updated (the wrapper reads its version from the jar, so it
341
+ is only given the options it knows). Keep such a jar out of `bin/validator_cli.jar`: the wrapper
342
+ keeps that one up to date, so a different jar in its place is replaced by the next release. `autoLoadPackages` (default true) starts the validator with `-autoLoadPackages`, so
343
+ the analysis step's extension lookups can load the package that defines an extension (validator
344
+ 7.0.5 and `fhir-validator-wrapper` 1.7.0 or later; older ones just don't look further). It starts in the background when the module does, and the queue waits for
247
345
  it. Each document - its analysed copy, so the translations are seen (the validator will
248
346
  remark on the translation extension until it is given its definition) - is validated against the IPS Bundle profile
249
347
  (`http://hl7.org/fhir/uv/ips/StructureDefinition/Bundle-uv-ips`; set `profiles` to validate
250
- against something else) with the validator's IPS code checks on (`checkIpsCodes`), and the
251
- OperationOutcome is stored with the document and shown on
348
+ against something else) - validator 7.0.4 dropped its IPS code checks, so `checkIpsCodes` is no longer
349
+ sent (the validator refuses it) - and the OperationOutcome is stored with the document and shown on
252
350
  its `validation` view: the counts, each issue's severity, code, location and message, and
253
351
  the raw OperationOutcome. Without a configured, running validator the step fails, and the
254
352
  document's status is `error`.
@@ -258,7 +356,10 @@ document's status is `error`.
258
356
  The national step runs after validation. It validates the document (the analysed copy, as validation does) against each
259
357
  [national profile](#national-profiles) in turn: the national IG's package is loaded into the validator (once - a package
260
358
  that has loaded, or has failed to, is remembered until the national profiles are changed), then the document is
261
- validated against the IG's profile on Bundle, with the same `checkIpsCodes` setting. For each profile the result keeps
359
+ validated against the IG's profile on Bundle. The national profiles' packages are also loaded when the validator
360
+ starts (and when the national profiles are changed), before any document is processed, so that the analysis step -
361
+ which runs first - finds the extensions they define; an extension that couldn't be found is looked up again once a
362
+ package has loaded. For each profile the result keeps
262
363
  the OperationOutcome, its counts, and whether the document passed - it passes when the validator reports no errors (or
263
364
  fatal issues). A profile whose package can't be loaded, or that the validator can't validate against, is kept with the
264
365
  reason and counts as not checked; it doesn't stop the pipeline. With no national profiles there is nothing to do, and no
@@ -437,9 +538,9 @@ As FHIR: `GET /ips/StructureDefinition` is a searchset of them all, and `GET /ip
437
538
 
438
539
  ## National profiles
439
540
 
440
- A national profile is the profile a national implementation guide defines for an IPS document. Each has four parts:
441
- the jurisdiction it is for, the IG's package id (e.g. `hl7.fhir.au.ips`), the package version, and the canonical URL
442
- of the IG's profile on Bundle. National profiles are shared across all projects (`/ips/national-profiles`). Everyone can see them; only the
541
+ A national profile is the profile a national implementation guide defines for an IPS document. Each has five parts:
542
+ the jurisdiction it is for, the IG's package id (e.g. `hl7.fhir.au.ips`), the package version, the canonical URL
543
+ of the IG's profile on Bundle, and - optionally, since not every IG uses SNOMED CT - the SNOMED CT edition the IG takes for granted. National profiles are shared across all projects (`/ips/national-profiles`). Everyone can see them; only the
443
544
  administrator adds, edits and deletes them. There is at most one for a package id and version. Every document is
444
545
  validated against each of them by the [national profiles step](#national-profile-validation).
445
546
 
@@ -450,7 +551,12 @@ lists the terminology module holds (`tx/cs/cs-country.js`, `tx/cs/cs-areacode.js
450
551
  (`XK`, `XX`, `ZZ`...) and countries' M49 numeric codes aren't accepted. National profiles made before the jurisdiction was asked
451
552
  for show it as not given, until they are saved with one. The package id must be a FHIR package id (lower case letters, digits, `-` and `_`, in two or more parts separated by
452
553
  dots), the version a package version (`1.0.0`, `1.1.0-ballot`), and the profile an http or https URL. `GET
453
- /ips/national-profiles` with `Accept: application/json` returns them as `[{jurisdiction, packageId, version, url}]`.
554
+ /ips/national-profiles` with `Accept: application/json` returns them as `[{jurisdiction, packageId, version, url, snomedEdition}]`
555
+ (`snomedEdition` only when there is one).
556
+
557
+ The SNOMED CT edition is chosen from a list - the editions in `SNOMED_LINKABLE_EDITIONS` (`tx/sct/editions.js`, the
558
+ editions snomed.info can link to), by name - and kept as the edition's module id (`900000000000207008` for the
559
+ International Edition, `32506021000036107` for the Australian), the id in its edition URI `http://snomed.info/sct/{id}`.
454
560
 
455
561
  ## FHIRPath functions
456
562
 
@@ -498,6 +604,7 @@ shared this way. The QR codes are made with `qrcode-generator`, error correction
498
604
  ### Validation view
499
605
 
500
606
  The view shows everything by default; its "Show" selector (`?level=warning` or
501
- `?level=error`) hides the lesser issues - the summary line still counts them all.
607
+ `?level=error`) hides the lesser issues - the summary line still counts them all. A national profile's
608
+ validation (the `national` view, one profile) shows errors only by default (`?level=information` for everything).
502
609
  `fhir-validator-wrapper` 1.5.0 or later is needed: earlier versions sent the profiles in a
503
610
  form the validator service refuses.