@cosyte/fhir 0.0.10 → 0.1.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.
package/dist/index.d.ts CHANGED
@@ -359,6 +359,28 @@ interface FhirComplex {
359
359
  * read from JSON. See {@link isDroppedText}.
360
360
  */
361
361
  readonly droppedText?: true;
362
+ /**
363
+ * Set when the XML document's **root** element resolved to a vocabulary that is neither FHIR's nor
364
+ * none at all: `<Observation xmlns="urn:vendor">` or `<v:Observation xmlns:v="urn:vendor">`. The
365
+ * reader already reports that position ({@link ../xml/issues.js ISSUE_CODES.UNEXPECTED_XML_CONTENT}),
366
+ * but a report lives in the issue list and the issue list is not carried on the model, so a writer
367
+ * handed the model alone could not tell a vendor-rooted resource from one authored in FHIR.
368
+ *
369
+ * **A marker that the root named another vocabulary, NOT the vocabulary.** It is a literal `true`:
370
+ * the namespace URI is document content and is deliberately not kept, so nothing here can be
371
+ * echoed into a diagnostic and no walker gains a position. What it buys is that
372
+ * {@link ../xml/write.js serializeResourceXml} refuses rather than emitting a FHIR-namespaced
373
+ * document whose re-read carries an empty issue list.
374
+ *
375
+ * **Set at a document root and nowhere else.** An element that merely inherits a foreign namespace
376
+ * from its parent is flagged where the document leaves the vocabulary and is not marked here, and
377
+ * a root whose prefix resolves to **nothing** is not marked either: that root reads under its
378
+ * verbatim tag, and its XML write is refused at the tag sites on a code of its own rather than
379
+ * through this marker. A root declaring no
380
+ * namespace at all is read as FHIR, unflagged and unmarked. Absent on every conformant document
381
+ * and on every document read from JSON. See {@link isForeignRoot}.
382
+ */
383
+ readonly foreignRoot?: true;
362
384
  }
363
385
  /**
364
386
  * A repeating element: an ordered list of item nodes. A primitive list preserves value-absent slots
@@ -531,6 +553,35 @@ declare function isDroppedText(node: FhirNode): boolean;
531
553
  * ```
532
554
  */
533
555
  declare function isUndefinedNull(node: FhirNode): boolean;
556
+ /**
557
+ * Whether the XML document's **root** element resolved to a vocabulary other than FHIR's: a vendor
558
+ * namespace reached by a default declaration or by a bound prefix.
559
+ *
560
+ * The reader models such a root as the FHIR resource its local name spells and reports the position,
561
+ * because it is schema-free and lenient and the local name is the only thing it has to go on. That
562
+ * report is a warning in the issue list and the model carries no issue list, so before this marker
563
+ * existed a caller could write the model back to XML and get a document in the FHIR namespace whose
564
+ * re-read said nothing at all: one round trip and a vendor document was indistinguishable from FHIR.
565
+ * {@link ../xml/write.js serializeResourceXml} refuses a marked model rather than emit that.
566
+ *
567
+ * **The namespace itself is NOT kept**, which is the difference between this and recovering the
568
+ * vocabulary. The document's own namespace URI is content, and a marker cannot leak content.
569
+ *
570
+ * `false` for a root that declares no namespace (read as FHIR on purpose), for a root whose prefix
571
+ * resolves to nothing (modeled under its verbatim tag, and refused by the XML writer at its tag
572
+ * sites rather than through this marker), for
573
+ * foreign content below a root, for every document read from JSON, and for every conformant document.
574
+ *
575
+ * @param node - Any model node.
576
+ * @returns `true` when this node is a root the XML reader read out of another vocabulary.
577
+ * @example
578
+ * ```ts
579
+ * import { isForeignRoot, parseResourceXml } from "@cosyte/fhir";
580
+ * const { resource } = parseResourceXml('<Observation xmlns="urn:vendor"><id value="o1"/></Observation>');
581
+ * isForeignRoot(resource); // true
582
+ * ```
583
+ */
584
+ declare function isForeignRoot(node: FhirNode): boolean;
534
585
  /** Optional `id` / `extension` metadata for {@link primitive}. */
535
586
  interface PrimitiveMeta {
536
587
  readonly id?: string;
@@ -1423,25 +1474,40 @@ declare function serializeResource(node: FhirComplex): string;
1423
1474
  * {@link assertSerializable} runs in both writers, because a dropped-character-data marker has no
1424
1475
  * conformant encoding in either format. {@link breaksTag} governs the XML writer only, because the
1425
1476
  * harm is a name reaching a tag position, and JSON escapes a member name so no name reaches this
1426
- * refusal there. {@link refuseUnserializableDivMarkup} is raised by the XML writer for the same
1427
- * reason, at its one raw-markup site: JSON carries the string as a string.
1428
- * {@link assertXmlSerializable}, {@link assertXmlArrayWrapper} and {@link assertXmlResourceType} are
1477
+ * refusal there. {@link carriesUndeclarablePrefix} is XML-only for the same reason: a colon is a
1478
+ * namespace prefix only in an XML name, and JSON spells the member name as a string.
1479
+ * {@link refuseUnserializableDivMarkup} and {@link refuseUnboundDivPrefixes} are raised by the XML
1480
+ * writer for the same reason, at its one raw-markup site: JSON carries the string as a string.
1481
+ * {@link isXmlName} and {@link carriesNonXmlCharacter} are XML-only too: they are the XML 1.0 `Name`
1482
+ * and `Char` productions, asked of what the XML writer emits as a tag name, an attribute value or a
1483
+ * spliced `div` string, and JSON spells every one of those as a string.
1484
+ * {@link assertXmlSerializable}, {@link assertXmlArrayWrapper}, {@link assertXmlValueChoiceWrapper}
1485
+ * and {@link assertXmlResourceType} are
1429
1486
  * XML-only for the mirror-image reason: the shapes they refuse are ones the JSON writer writes, and
1430
- * XML has no channel to write them into. {@link assertNoShadowedProperty} runs in **both** for the
1431
- * first reason again: a
1487
+ * XML has no channel to write them into. {@link assertXmlForeignRoot} is XML-only for a reason of its
1488
+ * own and the difference is worth reading rather than assuming: a namespace is an XML construct, so
1489
+ * it is the XML writer that has a vocabulary to get wrong, and `serializeResource` emits that model
1490
+ * exactly as it always did. **That is not a claim the JSON channel keeps the flag** -- it does not,
1491
+ * and that half is declared open rather than closed by this one.
1492
+ * {@link assertNoShadowedProperty} runs in **both** for the first reason again: a
1432
1493
  * member a repeated property name shadowed falls outside both walks, which visit `properties` only,
1433
1494
  * and neither format has a spelling that re-reads as the ambiguity the model holds. No refusal here
1434
1495
  * recognises anything new or invents a value. **It is NOT true that none of them changes a document
1435
- * that reads clean** -- `breaksTag` and {@link assertXmlResourceType} each name a document of their
1436
- * own that reads with zero issues and is refused anyway; that clause was carried here as a universal
1437
- * and is cut rather than reworded.
1496
+ * that reads clean** -- `breaksTag`, {@link assertXmlResourceType} and
1497
+ * {@link carriesUndeclarablePrefix} each name a document of their own that reads with zero issues and
1498
+ * is refused anyway, and so do {@link refuseUnboundDivPrefixes}, {@link isXmlName} and
1499
+ * {@link carriesNonXmlCharacter}; that clause was carried here as a universal and is cut rather than
1500
+ * reworded.
1438
1501
  *
1439
1502
  * **This module is a list of the refusals it implements, NOT a closed account of what a writer can
1440
1503
  * author.** Two of the predicates deliberately live somewhere else rather than being copied here,
1441
1504
  * because a copy would be free to disagree with the thing it copies: `emitsOneDivElement` sits in
1442
- * `../xml/write.js` next to the code that emits the markup, and the cardinality window
1505
+ * `../xml/write.js` next to the code that emits the markup (and `bindsEveryPrefix`, the question that
1506
+ * branch asks of the same parse next, sits beside it for the same reason), and the cardinality window
1443
1507
  * {@link assertXmlArrayWrapper} refuses on is the safety layer's own walk in `../safety/status.js`,
1444
- * the same walk that reports it to a caller.
1508
+ * the same walk that reports it to a caller. {@link assertXmlValueChoiceWrapper} follows that rule
1509
+ * at the one position the safety layer's walk does not reach: its window is the value layer's own,
1510
+ * in `../quantity/value.js`, the same call the validator and the value readout report from.
1445
1511
  *
1446
1512
  * The rest of this comment is the first refusal.
1447
1513
  *
@@ -1528,6 +1594,21 @@ declare const SERIALIZE_ERROR_CODES: {
1528
1594
  * See {@link assertXmlArrayWrapper} for the exact predicate and for what it deliberately leaves.
1529
1595
  */
1530
1596
  readonly UNSERIALIZABLE_ARRAY_WRAPPER: "UNSERIALIZABLE_ARRAY_WRAPPER";
1597
+ /**
1598
+ * The model carries, at a location this library already reports as an array-wrapped
1599
+ * `Observation.value[x]` choice, a wrapper FHIR XML has no repetition to spell back: one holding
1600
+ * fewer than two items. **XML only**: `serializeResource` writes the list back and the re-read
1601
+ * reports the same location, so that route stays open.
1602
+ *
1603
+ * The same harm as {@link SERIALIZE_ERROR_CODES.UNSERIALIZABLE_ARRAY_WRAPPER}, at the position
1604
+ * where the number is a DOSE: `{"resourceType":"Observation","status":"final","valueQuantity":
1605
+ * [{"value":5,"system":"http://unitsofmeasure.org","code":"mg"}]}` reads with the encoding
1606
+ * reported and no magnitude handed out, and used to come back from XML as an unambiguous 5 mg
1607
+ * nothing had complained about.
1608
+ *
1609
+ * See {@link assertXmlValueChoiceWrapper} for the window and for what it deliberately leaves.
1610
+ */
1611
+ readonly UNSERIALIZABLE_CHOICE_WRAPPER: "UNSERIALIZABLE_CHOICE_WRAPPER";
1531
1612
  /**
1532
1613
  * The model carries, at one or more object elements, a member a repeated property name shadowed
1533
1614
  * ({@link ../model/node.js} `duplicates`). **Both writers**, unlike the four refusals above it:
@@ -1548,6 +1629,151 @@ declare const SERIALIZE_ERROR_CODES: {
1548
1629
  * See {@link assertXmlResourceType} for the window and for what it deliberately leaves.
1549
1630
  */
1550
1631
  readonly UNSERIALIZABLE_RESOURCE_TYPE: "UNSERIALIZABLE_RESOURCE_TYPE";
1632
+ /**
1633
+ * The model carries, at one or more elements, a root the XML reader read out of a vocabulary that
1634
+ * resolved to something other than FHIR's. **XML only**: `serializeResource` spells a member name
1635
+ * and never a namespace, so it emits the model exactly as it did before this refusal existed and
1636
+ * that route stays open -- which is a statement about that writer's output, **not** a claim that
1637
+ * the JSON channel keeps the flag. It does not, and that half is declared open.
1638
+ *
1639
+ * FHIR XML puts the resource in the FHIR namespace, and the writer has no vendor binding to write
1640
+ * instead, so it emitted a document in the FHIR namespace with no trace of the one the sender
1641
+ * wrote. That output re-reads with an **empty** issue list, so the one warning that said the
1642
+ * document came from another vocabulary is gone after a single trip and the vendor document is
1643
+ * indistinguishable from FHIR.
1644
+ *
1645
+ * See {@link assertXmlForeignRoot} for the window, the two routes weighed, and what it costs.
1646
+ */
1647
+ readonly UNSERIALIZABLE_FOREIGN_ROOT: "UNSERIALIZABLE_FOREIGN_ROOT";
1648
+ /**
1649
+ * The model holds, at one or more tag positions, a name carrying a colon. XML reads the colon as
1650
+ * a namespace prefix, and the model carries no namespace binding for the writer to declare one
1651
+ * with, so the document would not be namespace-well-formed. **XML only**: `serializeResource`
1652
+ * spells a member name as a JSON string, so this refusal never reaches it and that route stays
1653
+ * open.
1654
+ *
1655
+ * Written anyway, the output named a prefix nothing declared, which a conformant XML parser
1656
+ * rejects, and a prefix rebound between siblings (`<p:x xmlns:p="urn:a"/>` beside
1657
+ * `<p:x xmlns:p="urn:b"/>`) lost its `MIXED_XML_SPELLING` report across one write and one re-read.
1658
+ * **Not {@link SERIALIZE_ERROR_CODES.UNSERIALIZABLE_ELEMENT_NAME}**, whose line is whether this
1659
+ * library's own round trip survives a name: a colon-bearing name survives that round trip, so the
1660
+ * two are different questions and keep different codes. A name that trips both keeps that one.
1661
+ *
1662
+ * See {@link carriesUndeclarablePrefix} for the exact predicate, its one exemption, and what it
1663
+ * leaves.
1664
+ */
1665
+ readonly UNSERIALIZABLE_PREFIXED_NAME: "UNSERIALIZABLE_PREFIXED_NAME";
1666
+ /**
1667
+ * The model holds, at one or more `div` locations, a string the XML writer would splice in as raw
1668
+ * markup that spells the one `div` element the property names, and whose markup names a namespace
1669
+ * prefix, on an element or on an attribute, that no declaration inside the string binds. **XML
1670
+ * only**: `serializeResource` carries the string as a string, so this refusal never reaches it and
1671
+ * that route stays open.
1672
+ *
1673
+ * Written anyway, `<v:div>x</v:div>` put a prefix nothing declared into the output, which a
1674
+ * conformant XML parser rejects, and this library's own re-read of that output turned the narrative
1675
+ * into a property named `v:div`: the narrative gone after one write and one read, with no
1676
+ * diagnostic at either end. **Not {@link SERIALIZE_ERROR_CODES.UNSERIALIZABLE_PREFIXED_NAME}**,
1677
+ * whose published meaning is a name at a tag position, and **not
1678
+ * {@link SERIALIZE_ERROR_CODES.UNSERIALIZABLE_DIV_MARKUP}**, whose question is which elements the
1679
+ * string contributes: a string that fails that question keeps that code whatever prefix it names.
1680
+ *
1681
+ * See `bindsEveryPrefix` in `../xml/write.js` for the exact predicate and what it leaves.
1682
+ *
1683
+ * @example
1684
+ * ```ts
1685
+ * import {
1686
+ * FhirSerializeError,
1687
+ * SERIALIZE_ERROR_CODES,
1688
+ * parseResource,
1689
+ * serializeResourceXml,
1690
+ * } from "@cosyte/fhir";
1691
+ * const { resource } = parseResource(
1692
+ * '{"resourceType":"Patient","text":{"status":"generated","div":"<v:div>x</v:div>"}}',
1693
+ * );
1694
+ * try {
1695
+ * serializeResourceXml(resource);
1696
+ * } catch (err) {
1697
+ * if (err instanceof FhirSerializeError && err.code === SERIALIZE_ERROR_CODES.UNSERIALIZABLE_DIV_PREFIX) {
1698
+ * err.locations; // ["Patient.text.div"]
1699
+ * }
1700
+ * }
1701
+ * ```
1702
+ */
1703
+ readonly UNSERIALIZABLE_DIV_PREFIX: "UNSERIALIZABLE_DIV_PREFIX";
1704
+ /**
1705
+ * The model holds, at one or more tag positions, a name that is not an XML 1.0 `Name` (production
1706
+ * [5]): `a&b`, `1abc`, `-x`, a name carrying U+0000 or an unpaired surrogate. A conforming XML
1707
+ * processor must reject such a document as a fatal error. **XML only**: `serializeResource` spells
1708
+ * a member name as a JSON string, so this refusal never reaches it and that route stays open.
1709
+ *
1710
+ * Written anyway, `<a&b value="v"/>` was a document this library's own reader read back unchanged
1711
+ * and a third-party parser rejected, which is why the tag-breaking refusal, whose line is this
1712
+ * library's own round trip, never reached it. **Not
1713
+ * {@link SERIALIZE_ERROR_CODES.UNSERIALIZABLE_ELEMENT_NAME}** and **not
1714
+ * {@link SERIALIZE_ERROR_CODES.UNSERIALIZABLE_PREFIXED_NAME}**: a name that breaks the tag, or
1715
+ * carries a colon, keeps the code it drew before this one existed, whether or not it is a `Name`.
1716
+ * A name carrying a character outside `Char` is not a `Name`, so it draws this code rather than
1717
+ * {@link SERIALIZE_ERROR_CODES.UNSERIALIZABLE_XML_CHARACTER}.
1718
+ *
1719
+ * See {@link isXmlName} for the exact predicate and what it leaves.
1720
+ *
1721
+ * @example
1722
+ * ```ts
1723
+ * import {
1724
+ * FhirSerializeError,
1725
+ * SERIALIZE_ERROR_CODES,
1726
+ * parseResource,
1727
+ * serializeResourceXml,
1728
+ * } from "@cosyte/fhir";
1729
+ * const { resource } = parseResource('{"resourceType":"Patient","1abc":"v"}');
1730
+ * try {
1731
+ * serializeResourceXml(resource);
1732
+ * } catch (err) {
1733
+ * if (err instanceof FhirSerializeError && err.code === SERIALIZE_ERROR_CODES.UNSERIALIZABLE_XML_NAME) {
1734
+ * err.locations; // ["Patient.<withheld>"]
1735
+ * }
1736
+ * }
1737
+ * ```
1738
+ */
1739
+ readonly UNSERIALIZABLE_XML_NAME: "UNSERIALIZABLE_XML_NAME";
1740
+ /**
1741
+ * The model holds, at one or more locations, a value the XML writer would emit as an attribute
1742
+ * value (a primitive's `value`, an `id` written as an attribute, an `Extension.url`), or a `div`
1743
+ * string it would splice in, carrying a code point outside XML 1.0 `Char` (production [2]): U+0000
1744
+ * to U+0008, U+000B, U+000C, U+000E to U+001F, an unpaired surrogate, U+FFFE or U+FFFF. In a `div`
1745
+ * string that includes a numeric character reference denoting one (`&#0;`), which the Legal
1746
+ * Character constraint makes as fatal as the raw character; each reference is judged on its own, so
1747
+ * `&#xD83D;&#xDE00;` is two unpaired surrogates, not one character. **XML only**: `serializeResource`
1748
+ * writes these values as JSON strings, so this refusal never reaches it and that route stays open.
1749
+ *
1750
+ * Written anyway, a U+0000 went into the output raw and a conforming processor rejected the
1751
+ * document. **Refused, never repaired**: a reference to a non-`Char` is itself a fatal error, and
1752
+ * replacing or dropping the character would change a value the sender wrote, so the model is left
1753
+ * exactly as it was and no string is returned. Raised after every other refusal, the name code
1754
+ * included.
1755
+ *
1756
+ * See {@link carriesNonXmlCharacter} for the exact predicate.
1757
+ *
1758
+ * @example
1759
+ * ```ts
1760
+ * import {
1761
+ * FhirSerializeError,
1762
+ * SERIALIZE_ERROR_CODES,
1763
+ * parseResource,
1764
+ * serializeResourceXml,
1765
+ * } from "@cosyte/fhir";
1766
+ * const { resource } = parseResource('{"resourceType":"Patient","gender":"a\\u0000"}');
1767
+ * try {
1768
+ * serializeResourceXml(resource);
1769
+ * } catch (err) {
1770
+ * if (err instanceof FhirSerializeError && err.code === SERIALIZE_ERROR_CODES.UNSERIALIZABLE_XML_CHARACTER) {
1771
+ * err.locations; // ["Patient.gender"]
1772
+ * }
1773
+ * }
1774
+ * ```
1775
+ */
1776
+ readonly UNSERIALIZABLE_XML_CHARACTER: "UNSERIALIZABLE_XML_CHARACTER";
1551
1777
  };
1552
1778
  /** Discriminant union of every {@link SERIALIZE_ERROR_CODES} value. */
1553
1779
  type SerializeErrorCode = (typeof SERIALIZE_ERROR_CODES)[keyof typeof SERIALIZE_ERROR_CODES];
@@ -1920,6 +2146,18 @@ declare function buildBindingRegistry(extra?: readonly TerminologyBinding[]): Bi
1920
2146
  * With **no** service configured at all, the validator behaves as if every membership question
1921
2147
  * returned `"unknown"`: it never emits a false "not a member" error (fail-safe).
1922
2148
  *
2149
+ * **A membership answer may declare the code-system release it was made against.** A `not-in` for an
2150
+ * RxNorm code is an answer against one monthly RxNorm drop, not a timeless fact, so
2151
+ * {@link CodeValidationResult} carries an optional `systemVersion`: the release the service consulted
2152
+ * when it decided. The declaration is the **caller's own assertion** and the library verifies nothing
2153
+ * about it, it does not fetch, parse, compare or normalise the string, and it bundles no code-system
2154
+ * content against which it could. The declaration is **optional and additive**: a service that
2155
+ * declares nothing is a conformant service, and the absent case is a first-class part of this
2156
+ * contract rather than an omission, a finding derived from an undeclared answer is marked as having
2157
+ * an undeclared release rather than left silent (see {@link ../validate/issues.js}
2158
+ * `CodeSystemVersionRecord`), because a silence reads as "current" and that is exactly the
2159
+ * implication a stale answer must not carry.
2160
+ *
1923
2161
  * The library ships **no implementation**, wiring a real one is a consumer/`pathways` concern. This
1924
2162
  * module defines only the contract.
1925
2163
  *
@@ -1952,6 +2190,30 @@ type CodeMembership =
1952
2190
  interface CodeValidationResult {
1953
2191
  /** Whether the code is in the value set, not in it, or undecidable. */
1954
2192
  readonly membership: CodeMembership;
2193
+ /**
2194
+ * **Optional.** The code-system release this answer was made against, exactly as the service
2195
+ * names it: an RxNorm monthly drop (`"2026-08-04"`), a SNOMED CT edition
2196
+ * (`"http://snomed.info/sct/731000124108/version/20260301"`), a LOINC release (`"2.78"`). It is
2197
+ * carried onto the finding the validator emits (`CODE_NOT_IN_VALUESET`) and reaches the
2198
+ * `OperationOutcome`, so a consumer reconciling a validation report months later can tell which
2199
+ * release the answer was made against without asking the service again.
2200
+ *
2201
+ * **The library verifies nothing about it.** This is the service's own assertion, preserved
2202
+ * **exactly**: never trimmed, case-folded, parsed, truncated or substituted. The library vendors
2203
+ * no code-system content, so it has nothing to check the string against and does not pretend to.
2204
+ *
2205
+ * **Declaring nothing is conformant, and is recorded rather than assumed.** Omit it (or, from
2206
+ * untyped JavaScript, hand over a value that is not a non-blank string) and the finding is marked
2207
+ * as having an **undeclared** release. No default, "latest" or "current" release is ever
2208
+ * substituted, and the answer is otherwise unchanged: this field never affects `membership`,
2209
+ * severity, or whether a finding is emitted at all.
2210
+ *
2211
+ * It is a code-**system** release, not a value-set version, and it must never be read from the
2212
+ * instance being validated: a resource's own `Coding.version` is document content, and echoing it
2213
+ * onto a finding would publish instance data through the one surface this library keeps
2214
+ * value-free.
2215
+ */
2216
+ readonly systemVersion?: string;
1955
2217
  }
1956
2218
  /**
1957
2219
  * A pluggable terminology service, the one seam through which value-set **content** enters the
@@ -1959,7 +2221,10 @@ interface CodeValidationResult {
1959
2221
  *
1960
2222
  * An implementation MUST be **fail-safe**: when it cannot answer, it returns
1961
2223
  * `{ membership: "unknown" }` rather than throwing or guessing. It MUST be value-free, it receives
1962
- * only identities ({@link CodeValidationRequest}), never a resource or a patient value.
2224
+ * only identities ({@link CodeValidationRequest}), never a resource or a patient value. It MAY
2225
+ * declare the code-system release an answer was made against
2226
+ * ({@link CodeValidationResult.systemVersion}); declaring nothing is conformant and is recorded as
2227
+ * undeclared rather than read as "current".
1963
2228
  *
1964
2229
  * @example
1965
2230
  * ```ts
@@ -1972,6 +2237,15 @@ interface CodeValidationResult {
1972
2237
  * return { membership: ["red", "green", "blue"].includes(code) ? "in" : "not-in" };
1973
2238
  * },
1974
2239
  * };
2240
+ *
2241
+ * // The same service, declaring the release each answer was made against.
2242
+ * const dated: TerminologyService = {
2243
+ * validateCode({ valueSet, code }) {
2244
+ * if (valueSet !== "http://example.org/vs/colors") return { membership: "unknown" };
2245
+ * const membership = ["red", "green", "blue"].includes(code) ? "in" : "not-in";
2246
+ * return { membership, systemVersion: "2026-08-04" };
2247
+ * },
2248
+ * };
1975
2249
  * ```
1976
2250
  */
1977
2251
  interface TerminologyService {
@@ -1995,13 +2269,23 @@ interface TerminologyService {
1995
2269
  *
1996
2270
  * **What ships built-in here is a named, deliberately short list:** the base `Resource` /
1997
2271
  * `DomainResource` elements (which are the same on every resource), plus one element table per
1998
- * modeled resource type. The types modeled today are exactly **`Patient`** and **`Observation`**,
1999
- * and that enumeration is the whole set, there is no third. Every other resource type is
2272
+ * modeled resource type. Read the enumeration off {@link BUILTIN_SCHEMAS} and never off a sentence
2273
+ * here: it is `Patient` plus the resource types this library treats as safety-critical, and a
2274
+ * written-down list in prose is the thing that goes stale. Every other resource type is
2000
2275
  * "not modeled yet" and degrades safely (see {@link ./validate.js}) rather than emitting false
2001
2276
  * errors, which is why the set grows one fully-verified table at a time: a table missing a row R4
2002
2277
  * defines turns a conformant document into an unknown-element finding, so a half-entered type would
2003
2278
  * be worse than no entry at all. Cardinalities are cited from the R4 4.0.1 base definitions
2004
- * (resource.html, domainresource.html, patient.html, observation.html).
2279
+ * (resource.html, domainresource.html, patient.html, observation.html, allergyintolerance.html,
2280
+ * condition.html, diagnosticreport.html, immunization.html, medicationrequest.html,
2281
+ * medicationstatement.html).
2282
+ *
2283
+ * **Only a `required`-strength binding on a `code`-typed element is carried here**, because that is
2284
+ * the only one this layer can decide from an enumeration alone. A `required` binding on a
2285
+ * `CodeableConcept` (`Condition.clinicalStatus` and `AllergyIntolerance.verificationStatus` among
2286
+ * them) is a membership question about a `Coding` inside a complex datatype, which belongs to the
2287
+ * terminology layer; the element is carried with its cardinality and datatype and its binding is
2288
+ * left alone. Weaker strengths (`extensible`, `preferred`, `example`) are that layer's too.
2005
2289
  *
2006
2290
  * @packageDocumentation
2007
2291
  */
@@ -2127,6 +2411,14 @@ declare function resolveElement(elements: Readonly<Record<string, ElementSchema>
2127
2411
  * {@link diagnosticFor} table, there is no code path that interpolates an instance value into a
2128
2412
  * message. This is the redaction chokepoint.
2129
2413
  *
2414
+ * Two identities ride **beside** that text rather than through it, and neither is instance data: the
2415
+ * invariant {@link ValidationIssue.constraint} key (a published FHIR identifier such as `"ait-1"`)
2416
+ * and the {@link ValidationIssue.codeSystemVersion} record (the code-system release a
2417
+ * caller-supplied terminology service declared its answer was made against, plus the explicit
2418
+ * marker for an answer that declared none). Both are assertions made outside the document: adding
2419
+ * one to `DIAGNOSTIC_OF`, or interpolating either into a diagnostic string, would breach the
2420
+ * chokepoint, so neither ever does.
2421
+ *
2130
2422
  * @packageDocumentation
2131
2423
  */
2132
2424
  /**
@@ -2218,6 +2510,30 @@ declare const VALIDATION_CODES: {
2218
2510
  * and the safety layer reads through it; this reports that the encoding was ambiguous.
2219
2511
  */
2220
2512
  readonly ARRAY_WRAPPED_SCALAR: "ARRAY_WRAPPED_SCALAR";
2513
+ /**
2514
+ * Safety, an `Observation.value[x]` choice element arrived wrapped in a JSON array. The same
2515
+ * non-conformant encoding {@link VALIDATION_CODES.ARRAY_WRAPPED_SCALAR} reports (json.html
2516
+ * §2.6.2.2 reserves the array for a repeating element), at the one position whose cardinality is
2517
+ * decided by a choice rather than by a per-resource element table, so it needs a code of its own
2518
+ * rather than a wider window on that one. An `error`.
2519
+ *
2520
+ * **Why the value readout needs its own channel.** `readObservationValue` fails safe on this
2521
+ * shape, it reports the variant that is present and no `quantity`, so no wrong number is handed
2522
+ * out, but "the variant is present and the magnitude is absent" reads identically to an
2523
+ * `Observation` whose `valueQuantity` carried no `value`. A dose the sender wrote is then
2524
+ * indistinguishable from one it did not, and this is the record that the position held content
2525
+ * nothing here would read.
2526
+ *
2527
+ * **The window is `Observation.value[x]` and `Observation.component.value[x]`, at every
2528
+ * Observation resource root the model holds**, which is the window the value readout itself reads
2529
+ * (`../quantity/value.js`). Both are `0..1` in R4 (observation.html), so this needs no
2530
+ * per-resource cardinality table and cannot fire on a conformant document. It is deliberately not
2531
+ * every R4 `0..1` element: that is the per-resource model this library does not have.
2532
+ *
2533
+ * Value-free, the location of the choice variant, never the magnitude, unit or code inside the
2534
+ * wrapper.
2535
+ */
2536
+ readonly ARRAY_WRAPPED_CHOICE: "ARRAY_WRAPPED_CHOICE";
2221
2537
  /**
2222
2538
  * Safety, the document wrote a JSON array **inside another array**. FHIR JSON uses an array for a
2223
2539
  * repeating element and for nothing else (json.html §2.6.2.2), so a list of lists has no meaning at
@@ -2285,17 +2601,26 @@ declare const VALIDATION_CODES: {
2285
2601
  */
2286
2602
  readonly RETRACTED_RESOURCE: "RETRACTED_RESOURCE";
2287
2603
  /**
2288
- * Safety, a named resource invariant failed (`ait-1`/`ait-2`, `con-3`/`con-4`/`con-5`,
2289
- * `obs-6`/`obs-7`). The specific constraint key travels in {@link ValidationIssue.constraint}, and
2290
- * the severity mirrors the constraint's own (`error`, except the best-practice `con-3` → `warning`).
2604
+ * Invariant, a resource constraint failed. Three sources raise it, each with or without the
2605
+ * others: the safety layer's named invariants (`ait-1`/`ait-2`, `con-3`/`con-4`/`con-5`,
2606
+ * `obs-6`/`obs-7`); the base-constraint layer, which evaluates the other error-severity
2607
+ * constraints R4 declares on the eight modeled types and their `DomainResource` / `Element` /
2608
+ * `Extension` base (`pat-1`, `obs-3`, `con-1`, `con-2`, `imm-1`, `dom-2` to `dom-5`, `ele-1`,
2609
+ * `ext-1`) with no profile supplied; and a supplied profile's own `constraint`s. The specific
2610
+ * constraint key travels in {@link ValidationIssue.constraint}, and the severity mirrors the
2611
+ * constraint's own (`error`, except a `warning` constraint such as the best-practice `con-3`).
2291
2612
  */
2292
2613
  readonly INVARIANT_VIOLATED: "INVARIANT_VIOLATED";
2293
2614
  /**
2294
- * Invariant, a profile `constraint`'s FHIRPath `expression` is **outside the bounded
2615
+ * Invariant, a `constraint`'s FHIRPath `expression`, from a supplied profile or from the R4 base
2616
+ * constraints the base-constraint layer evaluates, is **outside the bounded
2295
2617
  * engine's subset** and could not be evaluated. Always `information` (`informational`):
2296
2618
  * the constraint is reported **unchecked, never assumed to pass** (fail-safe), the
2297
2619
  * library does not claim conformance to an invariant it could not test. The constraint `key` travels
2298
2620
  * in {@link ValidationIssue.constraint}. Value-free (the location + key, never an instance value).
2621
+ * A profile's verbatim copy of an R4 base constraint that the base-constraint layer decided at the
2622
+ * same occurrence is not reported this way, because that constraint was evaluated: R4's `dom-3`
2623
+ * on a resource with nothing contained draws nothing, with or without a profile.
2299
2624
  */
2300
2625
  readonly INVARIANT_UNCHECKED: "INVARIANT_UNCHECKED";
2301
2626
  /**
@@ -2341,6 +2666,11 @@ declare const VALIDATION_CODES: {
2341
2666
  * never an error). Emitted **only** when a service definitively answers `not-in`; with no service,
2342
2667
  * or an `unknown` answer, the library degrades to the content-free system checks and never
2343
2668
  * false-errors (fail-safe). Value-free, the coding location, never the code itself.
2669
+ *
2670
+ * The **only** finding that carries a {@link ValidationIssue.codeSystemVersion} record, because it
2671
+ * is the only one a terminology service produces: the release the service declared its answer was
2672
+ * made against, or the explicit mark that it declared none. Severity, emission and the fail-safe
2673
+ * degrade are all independent of it.
2344
2674
  */
2345
2675
  readonly CODE_NOT_IN_VALUESET: "CODE_NOT_IN_VALUESET";
2346
2676
  /**
@@ -2417,6 +2747,60 @@ declare const VALIDATION_CODES: {
2417
2747
  };
2418
2748
  /** Discriminant union of every {@link VALIDATION_CODES} value. */
2419
2749
  type ValidationCode = (typeof VALIDATION_CODES)[keyof typeof VALIDATION_CODES];
2750
+ /**
2751
+ * The canonical identity of the library's own code system for the **code-system release record**
2752
+ * carried by a membership finding. It names the two-concept vocabulary in
2753
+ * {@link CODE_SYSTEM_VERSION_RECORD_CODES} and nothing else, and it reaches an `OperationOutcome` as
2754
+ * `issue.details.coding[0].system`.
2755
+ *
2756
+ * It is **this library's** canonical, not a third-party terminology identity: the known-systems
2757
+ * registry ({@link ../terminology/systems.js}) stays a frozen set of verified external URIs and
2758
+ * gains nothing here. Renaming this is a breaking change.
2759
+ */
2760
+ declare const CODE_SYSTEM_VERSION_RECORD_SYSTEM = "https://cosyte.com/fhir/CodeSystem/code-system-version-record";
2761
+ /**
2762
+ * The two-concept vocabulary that says **whether** a membership answer declared the code-system
2763
+ * release it was made against. Frozen via `as const`; the set is snapshotted (see
2764
+ * `test/validation-codes.test.ts`) because it is a public wire identity.
2765
+ *
2766
+ * The concept is deliberately separate from the release string itself: the marker rides on
2767
+ * `issue.details.coding[0].code` and the declared release rides on `issue.details.text`, so no
2768
+ * release a service could declare (`"undeclared"` included) can ever be mistaken for the marker.
2769
+ */
2770
+ declare const CODE_SYSTEM_VERSION_RECORD_CODES: {
2771
+ /** The service declared a release; the string it declared travels beside this marker. */
2772
+ readonly DECLARED: "declared";
2773
+ /**
2774
+ * The service was consulted, answered definitively, and declared **no** release. It is an
2775
+ * applicable, unanswered question, **not** "current" and not "not applicable": the marker is
2776
+ * emitted precisely so the silence cannot be read as currency.
2777
+ */
2778
+ readonly UNDECLARED: "undeclared";
2779
+ };
2780
+ /** One of the {@link CODE_SYSTEM_VERSION_RECORD_CODES}. */
2781
+ type CodeSystemVersionRecordCode = (typeof CODE_SYSTEM_VERSION_RECORD_CODES)[keyof typeof CODE_SYSTEM_VERSION_RECORD_CODES];
2782
+ /**
2783
+ * Which code-system release a membership answer was made against, as recorded on the finding.
2784
+ *
2785
+ * Three states, all distinguishable, which is the whole point of the type:
2786
+ *
2787
+ * - the field is **absent** from a {@link ValidationIssue}: no terminology service was consulted to
2788
+ * produce that finding, so there is no release to record (every content-free system check, every
2789
+ * non-terminology finding);
2790
+ * - `{ declared: true, version }`: the service named the release, and `version` is its string
2791
+ * **exactly** as declared, never normalised, trimmed, truncated or substituted;
2792
+ * - `{ declared: false }`: the service answered but named no release. The answer stands; its
2793
+ * currency is **unknown and said so**, rather than left to a reader to fill in with "current".
2794
+ *
2795
+ * The release is always the caller's own assertion. It is never read from the instance: a resource's
2796
+ * own `Coding.version` is document content and never reaches a finding.
2797
+ */
2798
+ type CodeSystemVersionRecord = {
2799
+ readonly declared: true;
2800
+ readonly version: string;
2801
+ } | {
2802
+ readonly declared: false;
2803
+ };
2420
2804
  /**
2421
2805
  * A single value-free validation finding.
2422
2806
  *
@@ -2446,6 +2830,19 @@ interface ValidationIssue {
2446
2830
  * every non-invariant finding. It reaches the `OperationOutcome` as `issue.details.text`.
2447
2831
  */
2448
2832
  readonly constraint?: string;
2833
+ /**
2834
+ * Which code-system release the terminology service's answer was made against, when a service was
2835
+ * consulted to produce this finding (today, `CODE_NOT_IN_VALUESET` and only it). `undefined` for
2836
+ * every finding no service produced, including the content-free `CODE_SYSTEM_UNKNOWN` /
2837
+ * `CODE_SYSTEM_UNEXPECTED` checks, which consult nothing.
2838
+ *
2839
+ * A declared release is the **caller's own assertion**, a public code-system release identifier on
2840
+ * the same footing as the constraint key an invariant finding surfaces, never an instance value,
2841
+ * so it is safe to surface. It reaches the `OperationOutcome` as `issue.details`
2842
+ * ({@link ./operation-outcome.js}), and the `diagnostics` string stays derived from the finding
2843
+ * code alone.
2844
+ */
2845
+ readonly codeSystemVersion?: CodeSystemVersionRecord;
2449
2846
  }
2450
2847
  /**
2451
2848
  * The value-free diagnostic line for a code, the only text that reaches an `OperationOutcome`.
@@ -2467,13 +2864,16 @@ declare function diagnosticFor(code: ValidationCode): string;
2467
2864
  * @param severity - The R4 severity to record (mode-dependent for some codes).
2468
2865
  * @param expression - The FHIRPath location of the finding, never a value.
2469
2866
  * @param constraint - The spec constraint key, for an invariant finding only (e.g. `"ait-1"`).
2867
+ * @param codeSystemVersion - The code-system release record, for a finding a terminology service
2868
+ * produced only. Omit it for every finding no service was consulted for; passing
2869
+ * `{ declared: false }` is the distinct claim that a service answered and named no release.
2470
2870
  * @example
2471
2871
  * ```ts
2472
2872
  * import { validationIssue } from "@cosyte/fhir";
2473
2873
  * const issue = validationIssue("CODE_INVALID", "error", "Patient.gender");
2474
2874
  * ```
2475
2875
  */
2476
- declare function validationIssue(code: ValidationCode, severity: ValidationSeverity, expression: string, constraint?: string): ValidationIssue;
2876
+ declare function validationIssue(code: ValidationCode, severity: ValidationSeverity, expression: string, constraint?: string, codeSystemVersion?: CodeSystemVersionRecord): ValidationIssue;
2477
2877
 
2478
2878
  /**
2479
2879
  * The layered structural / cardinality / value-domain validator (validation layers 1–3).
@@ -2503,6 +2903,19 @@ declare function validationIssue(code: ValidationCode, severity: ValidationSever
2503
2903
  * the resource types {@link ./schema.js} enumerates; other resource types validate only when the
2504
2904
  * caller supplies a schema.
2505
2905
  *
2906
+ * **Invariants run with or without a profile.** {@link validateResource} runs the layers above and
2907
+ * then the others in turn: the safety layer ({@link ./safety.js}), whose seven named invariants
2908
+ * fire for every AllergyIntolerance, Condition and Observation; the base-constraint layer
2909
+ * ({@link ./base-invariants.js}), which evaluates every other error-severity constraint R4 declares
2910
+ * on the eight modeled types (AllergyIntolerance, Condition, DiagnosticReport, Immunization,
2911
+ * MedicationRequest, MedicationStatement, Observation, Patient) and on their `DomainResource`,
2912
+ * `Element` and `Extension` base, `pat-1`, `ext-1` and `ele-1` among them, with no profile supplied;
2913
+ * and, for each supplied profile whose `type` matches, that profile's own `constraint`s
2914
+ * ({@link ../profiles/invariants.js}). A violation both a profile and the base-constraint layer
2915
+ * find at one occurrence is reported once, and a base constraint the base-constraint layer decides
2916
+ * at an occurrence is never also reported unevaluated there because a profile's verbatim copy of
2917
+ * it lies outside the subset. A resource type outside the eight draws no base-constraint finding.
2918
+ *
2506
2919
  * @packageDocumentation
2507
2920
  */
2508
2921
 
@@ -2573,7 +2986,13 @@ declare function validateResource(resource: FhirComplex, options?: ValidateOptio
2573
2986
  * gap rather than a path that resolves against the instance, so the outcome is spec-clean as a
2574
2987
  * resource while that one element is deliberately not resolvable; and
2575
2988
  * - `diagnostics`, a value-free line derived **only** from the validation code (the redaction
2576
- * chokepoint in {@link ./issues.js}). No instance value ever reaches this resource.
2989
+ * chokepoint in {@link ./issues.js}). No instance value ever reaches this resource; in particular
2990
+ * neither identity below is interpolated into it; and
2991
+ * - `details`, present only when the finding carries an identity asserted **outside** the document:
2992
+ * an invariant's constraint key (`details.text`), or a membership finding's code-system release
2993
+ * record (`details.coding` marks whether the caller's terminology service declared a release, and
2994
+ * a declared one rides verbatim in `details.text`). A resource's own `Coding.version` is never
2995
+ * read and never appears here.
2577
2996
  *
2578
2997
  * An `OperationOutcome.issue` is `1..*`, it must carry at least one issue. When validation found
2579
2998
  * nothing, {@link toOperationOutcome} emits a single `information` / `informational` "all clear"
@@ -2773,13 +3192,15 @@ declare function collectSafetyIssues(resource: FhirComplex, rt: string): Validat
2773
3192
  *
2774
3193
  * `modifierExtension` already fails closed on its own channel ({@link ./status.js}
2775
3194
  * `unhandledModifierExtensions`) and is deliberately NOT reported here, so one modifier extension
2776
- * still yields one report. The other four land on the channel this module feeds.
3195
+ * still yields one report. The other four land on the channel this module feeds, and so do three
3196
+ * more R4 flags on the resource types this library reads a safety verdict from: a Patient's
3197
+ * `deceased[x]` and `link`, and an Immunization's `isSubpotent`.
2777
3198
  *
2778
3199
  * ## The recognition predicate, and why it is by KEY NAME
2779
3200
  *
2780
3201
  * An occurrence is decided by key name and by literal `resourceType` equality alone: no element
2781
- * table, no StructureDefinition, no datatype model, no sibling-key shape. Four rules and nothing
2782
- * else is an occurrence:
3202
+ * table, no StructureDefinition, no datatype model, no sibling-key shape. These rules and nothing
3203
+ * else make an occurrence:
2783
3204
  *
2784
3205
  * - `comparator`: ANY object node the walk reaches that carries a member named `comparator` or
2785
3206
  * `_comparator`, whatever element name it sits under, whatever the enclosing `resourceType` is,
@@ -2789,7 +3210,26 @@ declare function collectSafetyIssues(resource: FhirComplex, rt: string): Validat
2789
3210
  * `resourceType` is the exact string `Patient`, top-level or contained or a Bundle entry, and
2790
3211
  * nowhere else;
2791
3212
  * - `use`: a member named `use` or `_use` on any entry of the `identifier` array on the ROOT object
2792
- * of a resource whose `resourceType` is the exact string `Practitioner`, and nowhere else.
3213
+ * of a resource whose `resourceType` is the exact string `Practitioner`, and nowhere else. On the
3214
+ * eight types this library models, `use` is surfaced as a code rather than reported (see below);
3215
+ * - `deceased`: a member whose name, less a leading `_`, begins `deceased`, on the ROOT object of a
3216
+ * `Patient`, and nowhere else. The element is the R4 choice `deceased[x]`, so the stem is the key:
3217
+ * `deceasedBoolean` and `deceasedDateTime` are the two members R4 defines, and a member it does not
3218
+ * define (`deceasedString`, a bare `deceased`) is reported rather than passed over, because a
3219
+ * choice suffix nobody expected is still the sender saying something about a death. The report
3220
+ * is located at the member as written, so a caller can tell the two R4 members apart;
3221
+ * - `link`: a member named `link` or `_link` on the ROOT object of a `Patient`, and nowhere else,
3222
+ * reported ONCE at `link` however many entries it holds. No entry is read: `link.type` is what
3223
+ * says whether this record was replaced by another, and reading it would be interpreting the
3224
+ * modifier rather than reporting it;
3225
+ * - `isSubpotent`: a member named `isSubpotent` or `_isSubpotent` on the ROOT object of an
3226
+ * `Immunization`, and nowhere else.
3227
+ *
3228
+ * The three gated on a Patient or an Immunization report at ANY value, `false` included, exactly as
3229
+ * `active` does. `{"deceasedBoolean":false}` is a Patient the sender says is alive, and deciding
3230
+ * that from the value would be reading a modifier to decide whether to report it, which opens a
3231
+ * readable-versus-unreadable fork this channel does not have. A caller that has read the element
3232
+ * handles the report; one that has not is refused.
2793
3233
  *
2794
3234
  * The first two OVER-REPORT by construction, and that is the trade taken rather than an oversight.
2795
3235
  * `{"resourceType":"Foo","x":{"comparator":"anything"}}` is an occurrence, so a non-FHIR payload
@@ -2809,8 +3249,67 @@ declare function collectSafetyIssues(resource: FhirComplex, rt: string): Validat
2809
3249
  * ## What a report may carry, and what a LOCATION may carry
2810
3250
  *
2811
3251
  * The element name and the location, and nothing taken from the document: no measurement value, no
2812
- * unit, no code, no `implicitRules` URI, no name, no identifier, no free text. The element name is
2813
- * safe by construction, being one of four literal keys this module spells.
3252
+ * unit, no code, no `implicitRules` URI, no name, no identifier, no date, no linked record, no free
3253
+ * text. The element name is safe by construction, being one of the literal keys this module spells
3254
+ * ({@link ModifierElementName}).
3255
+ *
3256
+ * ## `MedicationRequest.intent`, which is SURFACED rather than reported
3257
+ *
3258
+ * R4 flags `intent` a modifier too, and it is mandatory (`1..1`), so reporting it on presence would
3259
+ * refuse every MedicationRequest there is. It is surfaced instead, the way `status` is: at every
3260
+ * `MedicationRequest` root, the code paired with the location of that root's `intent`
3261
+ * ({@link IntentReport}). Only the eight codes the R4 value set defines can be surfaced
3262
+ * ({@link MedicationRequestIntent}), matched exactly and case-sensitively, so this channel never
3263
+ * echoes a string the document wrote. Anything else present at `intent` (a string outside the
3264
+ * eight, a case or whitespace variant of one, a JSON `null`, a value of another JSON type, the `_`
3265
+ * form with no value, an array wrapper, a name written twice) is not a code this library may read:
3266
+ * nothing is surfaced for that root, its location is reported as unreadable, and that lowers the
3267
+ * verdict. Nothing is case-folded, trimmed or mapped to a nearby code. An ABSENT `intent` surfaces
3268
+ * nothing and refuses nothing, because a missing mandatory element is the validator's verdict.
3269
+ *
3270
+ * No meaning is read out of the code: whether a `proposal` is an order is the caller's question.
3271
+ *
3272
+ * ## `use` on Identifier, HumanName, Address and ContactPoint, which is SURFACED rather than reported
3273
+ *
3274
+ * R4 flags `use` a modifier on all four datatypes, so that an old or temporary identifier, name,
3275
+ * address or contact point is not mistaken for a current one, and binds each `0..1` `use` to its
3276
+ * own value set at required strength. It is optional and written on most real records, so reporting
3277
+ * it on presence would refuse nearly every Patient; and refusing on WHICH code was written would be
3278
+ * interpreting the modifier. It is surfaced instead, the way `intent` is ({@link DatatypeUseReport}):
3279
+ * the code paired with the location of the `use` element, one pair per covered position.
3280
+ *
3281
+ * A covered position is an object entry (an array entry or a lone object) at one of these, below a
3282
+ * resource root of one of the eight types in {@link USE_ROOT_TYPES} and not below a nested resource
3283
+ * root of any type:
3284
+ *
3285
+ * - every member named `identifier` or `groupIdentifier`, at any depth, read as an Identifier. R4
3286
+ * types every element of the eight types with those names as Identifier, and `Reference.identifier`
3287
+ * is one too, so a Reference's identifier and an Identifier's `assigner.identifier` are covered;
3288
+ * - on a `Patient` root: `name` (HumanName), `telecom` (ContactPoint) and `address` (Address), and
3289
+ * the same three on each `contact` entry. R4 types no other Patient element as one of the four.
3290
+ *
3291
+ * Readability is decided against the value set of the position's OWN datatype, so `temp` reads on
3292
+ * all four and `maiden` on a HumanName only. The code is surfaced only when the document wrote
3293
+ * exactly one `use` member holding one JSON string equal to a code of that set; anything else
3294
+ * written there (a case or whitespace variant, the empty string, a code from a sibling set, a JSON
3295
+ * `null`, a value of another JSON type, the `_use` form with no value, an array wrapper, the name
3296
+ * written twice) surfaces nothing and its location is reported as unreadable, which lowers the
3297
+ * verdict. Nothing is case-folded, trimmed or mapped to a nearby code, and no meaning is read out of
3298
+ * a code: nothing here says an `old` entry is not current, and nothing is filtered or reordered. A
3299
+ * position carrying neither `use` nor `_use` draws nothing.
3300
+ *
3301
+ * **A `Practitioner` root is outside this read, and that is the rule rather than a gap.**
3302
+ * `Practitioner.identifier.use` keeps its own rule above, reported on presence, and a root naming
3303
+ * `Practitioner` among its types surfaces and locates nothing here, so a Practitioner identifier is
3304
+ * never on both channels. Every position belongs to its NEAREST enclosing resource root, so a
3305
+ * Practitioner contained in a Patient is governed by the Practitioner rule alone.
3306
+ *
3307
+ * **Declared limits.** `use` on these datatypes carried as an extension VALUE (`valueIdentifier`,
3308
+ * `valueHumanName`, `valueAddress`, `valueContactPoint`) is not read, because the member is not
3309
+ * named `identifier`; and a nested resource root whose type is not one of the eight (a contained
3310
+ * `Organization`'s `identifier` or `telecom`) is not read, because the position table is known only
3311
+ * for the eight and a key-name guess inside an unmodeled resource could surface a same-named element
3312
+ * that is not one of these datatypes.
2814
3313
  *
2815
3314
  * The location is the one place document text can reach a report, and it is bounded twice:
2816
3315
  *
@@ -2832,16 +3331,26 @@ declare function collectSafetyIssues(resource: FhirComplex, rt: string): Validat
2832
3331
  */
2833
3332
 
2834
3333
  /**
2835
- * The modifier elements this channel reports, by their R4 element names.
3334
+ * The modifier elements this channel reports, by their R4 element names. `deceased` names the R4
3335
+ * choice element `deceased[x]`; the report's location carries the member as the document wrote it.
2836
3336
  *
2837
3337
  * `modifierExtension` is deliberately absent: it keeps its own fail-closed channel, so a modifier
2838
- * extension yields one report and not two.
3338
+ * extension yields one report and not two. `MedicationRequest.intent` is absent too: it is
3339
+ * surfaced as a code on its own field rather than reported on presence ({@link IntentReport}).
3340
+ *
3341
+ * @example
3342
+ * ```ts
3343
+ * import { parseResource, readSafety, type ModifierElementName } from "@cosyte/fhir";
3344
+ * const { resource } = parseResource('{"resourceType":"Patient","deceasedBoolean":true}');
3345
+ * const names: ModifierElementName[] = readSafety(resource).modifierElements.map((r) => r.element);
3346
+ * names; // ["deceased"]
3347
+ * ```
2839
3348
  */
2840
- type ModifierElementName = "comparator" | "implicitRules" | "active" | "use";
3349
+ type ModifierElementName = "comparator" | "implicitRules" | "active" | "use" | "deceased" | "link" | "isSubpotent";
2841
3350
  /**
2842
3351
  * One reported modifier element: which element, and where.
2843
3352
  *
2844
- * Value-free by contract. `element` is one of four literal keys this library spells, never a name
3353
+ * Value-free by contract. `element` is one of the literal keys this library spells, never a name
2845
3354
  * read off the document, and `location` is bounded segment by segment with its root restricted to
2846
3355
  * {@link MODIFIER_ELEMENT_ROOT_TYPES}.
2847
3356
  */
@@ -2851,6 +3360,75 @@ interface ModifierElementReport {
2851
3360
  /** The FHIRPath location it is present at, bounded (never a document value). */
2852
3361
  readonly location: string;
2853
3362
  }
3363
+ /**
3364
+ * A `MedicationRequest.intent` code this library surfaces: exactly the eight concepts of the R4
3365
+ * 4.0.1 value set the element binds to at required strength, and nothing else.
3366
+ *
3367
+ * @example
3368
+ * ```ts
3369
+ * import { parseResource, readSafety, type MedicationRequestIntent } from "@cosyte/fhir";
3370
+ * const { resource } = parseResource('{"resourceType":"MedicationRequest","intent":"proposal"}');
3371
+ * const codes: MedicationRequestIntent[] = readSafety(resource).intents.map((i) => i.code);
3372
+ * codes; // ["proposal"]
3373
+ * ```
3374
+ */
3375
+ type MedicationRequestIntent = "proposal" | "plan" | "order" | "original-order" | "reflex-order" | "filler-order" | "instance-order" | "option";
3376
+ /**
3377
+ * One surfaced `MedicationRequest.intent`: the code exactly as the document wrote it, and the
3378
+ * location of the `intent` element it was read from, one per `MedicationRequest` root.
3379
+ *
3380
+ * The code is one of the eight {@link MedicationRequestIntent} values, matched exactly, so this
3381
+ * carries no text the library did not spell itself. The location follows the same bound and the
3382
+ * same root rule as {@link ModifierElementReport}'s.
3383
+ */
3384
+ interface IntentReport {
3385
+ /** The intent code, exactly as written. */
3386
+ readonly code: MedicationRequestIntent;
3387
+ /** The FHIRPath location of the `intent` element it was read from, bounded. */
3388
+ readonly location: string;
3389
+ }
3390
+ /**
3391
+ * A `use` code this library surfaces on an Identifier, a HumanName, an Address or a ContactPoint:
3392
+ * the union of the four R4 4.0.1 value sets those elements bind to at required strength, and
3393
+ * nothing else. Which of them a given position may carry is decided by that position's own
3394
+ * datatype (IdentifierUse `usual` `official` `temp` `secondary` `old`; NameUse `usual` `official`
3395
+ * `temp` `nickname` `anonymous` `old` `maiden`; AddressUse `home` `work` `temp` `old` `billing`;
3396
+ * ContactPointUse `home` `work` `temp` `old` `mobile`).
3397
+ *
3398
+ * @example
3399
+ * ```ts
3400
+ * import { parseResource, readSafety, type DatatypeUseCode } from "@cosyte/fhir";
3401
+ * const { resource } = parseResource('{"resourceType":"Patient","name":[{"use":"old"}]}');
3402
+ * const codes: DatatypeUseCode[] = readSafety(resource).datatypeUses.map((u) => u.code);
3403
+ * codes; // ["old"]
3404
+ * ```
3405
+ */
3406
+ type DatatypeUseCode = "usual" | "official" | "temp" | "secondary" | "old" | "nickname" | "anonymous" | "maiden" | "home" | "work" | "billing" | "mobile";
3407
+ /**
3408
+ * One surfaced `use` on an Identifier, a HumanName, an Address or a ContactPoint: the code exactly
3409
+ * as the document wrote it, and the location of the `use` element it was read from, one per covered
3410
+ * position.
3411
+ *
3412
+ * The code is one of the {@link DatatypeUseCode} values of that position's own value set, matched
3413
+ * exactly, so this carries no text the library did not spell itself. The location follows the same
3414
+ * bound and the same root rule as {@link ModifierElementReport}'s.
3415
+ *
3416
+ * @example
3417
+ * ```ts
3418
+ * import { parseResource, readSafety, type DatatypeUseReport } from "@cosyte/fhir";
3419
+ * const { resource } = parseResource(
3420
+ * '{"resourceType":"Patient","identifier":[{"use":"old","value":"S1"}]}',
3421
+ * );
3422
+ * const uses: readonly DatatypeUseReport[] = readSafety(resource).datatypeUses;
3423
+ * uses; // [{ code: "old", location: "Patient.identifier[0].use" }]
3424
+ * ```
3425
+ */
3426
+ interface DatatypeUseReport {
3427
+ /** The `use` code, exactly as written. */
3428
+ readonly code: DatatypeUseCode;
3429
+ /** The FHIRPath location of the `use` element it was read from, bounded. */
3430
+ readonly location: string;
3431
+ }
2854
3432
  /**
2855
3433
  * The resource type names that may root a modifier-element location, which is every resource type
2856
3434
  * name THIS LIBRARY spells in its own source, and no other.
@@ -2859,12 +3437,16 @@ interface ModifierElementReport {
2859
3437
  * with different memberships and the choice decides what a location reads:
2860
3438
  *
2861
3439
  * - the seven `SAFETY_RESOURCE_TYPES` ({@link ./codes.js}), the types whose type-scoped safety
2862
- * elements this library surfaces;
2863
- * - `Patient`, the one type the validator carries a built-in element table for, and one of the two
3440
+ * elements this library surfaces, `Immunization` and `MedicationRequest` among them;
3441
+ * - `Patient`, the one type the validator carries a built-in element table for, and one of the
2864
3442
  * types this module's own predicate gates on;
2865
- * - `Practitioner`, the other type this module's predicate gates on;
3443
+ * - `Practitioner`, another type this module's predicate gates on;
2866
3444
  * - `Bundle`, which the validator branches on by name when it checks entries.
2867
3445
  *
3446
+ * The surfaced `MedicationRequest.intent` locations ({@link IntentReport}) and the unreadable ones
3447
+ * are rooted by the same rule, since they are read by this module at the same window, and so are the
3448
+ * surfaced and the unreadable `use` locations on the four datatypes ({@link DatatypeUseReport}).
3449
+ *
2868
3450
  * The set is the union, and it is derived from source constants only. **It is never derived from
2869
3451
  * the input**: a type name is a member because this package wrote it down, not because a document
2870
3452
  * looked plausible. That is the whole property, and a "shaped like a resource type" test would
@@ -3139,11 +3721,13 @@ type NegationKind =
3139
3721
  * reasons given there.
3140
3722
  *
3141
3723
  * **Two groups of fields, and the difference is which question they answer.** The location channels
3142
- * (`unhandledModifierExtensions`, `shadowedProperties`, `arrayWrappedScalars`, `nestedArrays`,
3143
- * `droppedText`, `unreadableBooleans`, `nearMissNegationCodes`, `unreadableNegationCodes`,
3144
- * `absenceMarkers`, `unreadableAbsenceMarkers`, `conflictingAbsenceMarkers`) and the
3145
- * `safeToSummarize` derived from them (from all but `absenceMarkers`, which discloses rather than
3146
- * refuses) are **document-wide**: they carry FHIRPath locations, so a nested finding has an address to name, and
3724
+ * (`unhandledModifierExtensions`, `modifierElements`, `intents`, `datatypeUses`,
3725
+ * `shadowedProperties`, `arrayWrappedScalars`, `nestedArrays`, `droppedText`, `unreadableBooleans`,
3726
+ * `nearMissNegationCodes`, `unreadableNegationCodes`, `unreadableIntents`,
3727
+ * `unreadableDatatypeUses`, `absenceMarkers`, `unreadableAbsenceMarkers`,
3728
+ * `conflictingAbsenceMarkers`) and the `safeToSummarize` derived from them (from all but
3729
+ * `absenceMarkers`, `intents` and `datatypeUses`, which disclose rather than refuse) are
3730
+ * **document-wide**: they carry FHIRPath locations, so a nested finding has an address to name, and
3147
3731
  * `assertSafeToSummarize` refuses over a `Bundle`'s entries. The **single-valued** fields
3148
3732
  * (`resourceType` / `status` / `clinicalStatus` / `verificationStatus` / `doNotPerform` / `retracted`
3149
3733
  * / `noKnownAllergy`) answer about **the resource handed in** and nothing nested inside it, because
@@ -3240,9 +3824,20 @@ interface SafetyReadout {
3240
3824
  * element and where it is. R4 flags several ordinary base elements `Is Modifier: true` because
3241
3825
  * they change how the value beside them must be read, and this is the channel that surfaces them:
3242
3826
  * `comparator` wherever the walk reaches a node carrying it, `implicitRules` likewise,
3243
- * `Patient.active`, and `use` on a `Practitioner`'s `identifier` entries. Every one of them
3244
- * lowers {@link safeToSummarize}, because a bounded quantity summarized as a point value is a
3245
- * wrong clinical number delivered under a clean verdict.
3827
+ * `Patient.active`, `Patient.deceased[x]` (element `deceased`, located at the member as written,
3828
+ * `deceasedBoolean` or `deceasedDateTime`), `Patient.link` (once, at `link`, however many entries),
3829
+ * `Immunization.isSubpotent`, and `use` on a `Practitioner`'s `identifier` entries. Every one of
3830
+ * them lowers {@link safeToSummarize} **on presence, at any value**: a bounded quantity summarized
3831
+ * as a point value is a wrong clinical number delivered under a clean verdict, a deceased patient
3832
+ * or a record replaced by another is not the live record a summary would present, and a
3833
+ * subpotent dose does not protect the way the record would otherwise say. `deceasedBoolean: false`
3834
+ * and `isSubpotent: false` report too, as `active: true` does, because deciding from the value
3835
+ * would be interpreting the modifier; an unreadable value (a `null`, a wrong JSON type, the `_`
3836
+ * form alone, an array wrapper, a name written twice, a `deceased` member R4 does not define) is
3837
+ * reported the same way and never read.
3838
+ *
3839
+ * `MedicationRequest.intent` is not here: it is mandatory, so it is surfaced on {@link intents}
3840
+ * instead.
3246
3841
  *
3247
3842
  * **Distinct from {@link unhandledModifierExtensions}, and the two never double-report.** A
3248
3843
  * modifier EXTENSION stays on that channel and draws nothing here, so one modifier extension is
@@ -3257,6 +3852,55 @@ interface SafetyReadout {
3257
3852
  * did.
3258
3853
  */
3259
3854
  readonly modifierElements: readonly ModifierElementReport[];
3855
+ /**
3856
+ * `MedicationRequest.intent`, surfaced at **every `MedicationRequest` root** the document carries
3857
+ * (the resource handed in, a `contained` one, a `Bundle.entry`): the code exactly as written,
3858
+ * paired with the location of that root's `intent`, one pair per root, in walk order.
3859
+ *
3860
+ * R4 flags `intent` a modifier (a `proposal` is not an `order`) and makes it mandatory, so it is
3861
+ * surfaced the way `status` is rather than refused on presence, and a readable one **does not
3862
+ * lower {@link safeToSummarize}**. Only the eight codes of the R4 value set can appear here,
3863
+ * matched exactly and case-sensitively, so this field carries no text the library did not spell.
3864
+ * An `intent` that is present and not one of them is on {@link unreadableIntents} instead, and its
3865
+ * root surfaces nothing here. A root with no `intent` at all surfaces nothing and refuses nothing:
3866
+ * a missing mandatory element is the validator's verdict, not this readout's.
3867
+ *
3868
+ * No meaning is read from the code: nothing here says whether a request is in force.
3869
+ */
3870
+ readonly intents: readonly IntentReport[];
3871
+ /**
3872
+ * `use` on an Identifier, a HumanName, an Address or a ContactPoint, surfaced at **every covered
3873
+ * position** the document carries: the code exactly as written, paired with the location of that
3874
+ * `use` element, one pair per position, in walk order.
3875
+ *
3876
+ * The covered positions sit below a resource root of one of the eight types this library's safety
3877
+ * layer models (`AllergyIntolerance`, `Condition`, `DiagnosticReport`, `Immunization`,
3878
+ * `MedicationRequest`, `MedicationStatement`, `Observation`, `Patient`), whether that root is the
3879
+ * resource handed in, a `contained` one or a `Bundle.entry`: every member named `identifier` or
3880
+ * `groupIdentifier` at any depth (a Reference's identifier included), and on a `Patient` its
3881
+ * `name`, `telecom` and `address` and the same three on each `contact` entry. A position belongs to
3882
+ * its nearest enclosing resource root, and a root of any other type reads nothing here.
3883
+ *
3884
+ * R4 flags `use` a modifier on all four datatypes, so that an `old` or `temp` entry is not taken
3885
+ * for a current one. It is optional and written on most records, so it is surfaced rather than
3886
+ * refused on presence, and a readable one **does not lower {@link safeToSummarize}**. Only a code
3887
+ * of the value set of the position's OWN datatype is surfaced, matched exactly, so `temp` reads on
3888
+ * all four and `maiden` on a HumanName only, and this field carries no text the library did not
3889
+ * spell. A `use` that is present and not one of those codes is on {@link unreadableDatatypeUses}
3890
+ * instead. A position with no `use` surfaces nothing.
3891
+ *
3892
+ * **Surfaced, never interpreted.** Nothing here maps `old` or `temp` to "not current", and nothing
3893
+ * is filtered, reordered or picked as the current entry: which entry to show is the caller's
3894
+ * decision. `Practitioner.identifier.use` is not here: it keeps its presence rule on
3895
+ * {@link modifierElements}. **Declared limits:** a datatype carried as an extension value
3896
+ * (`valueIdentifier`, `valueHumanName`, `valueAddress`, `valueContactPoint`) is not read, nor is a
3897
+ * position inside a nested resource root whose type is not one of the eight (a contained
3898
+ * `Organization`'s `identifier` or `telecom`); and an ended `period` on an entry is a separate
3899
+ * element this does not read.
3900
+ *
3901
+ * Located by the same bound and the same root rule as {@link modifierElements}.
3902
+ */
3903
+ readonly datatypeUses: readonly DatatypeUseReport[];
3260
3904
  /**
3261
3905
  * FHIRPath locations where the document wrote a property name more than once, so the element has
3262
3906
  * several values and no rule says which one the sender meant (fail-closed). Empty on every
@@ -3421,6 +4065,39 @@ interface SafetyReadout {
3421
4065
  * that is wholly a `CodeableConcept`.
3422
4066
  */
3423
4067
  readonly unreadableNegationCodes: readonly string[];
4068
+ /**
4069
+ * FHIRPath locations of a `MedicationRequest.intent` this library could not read as one of the
4070
+ * eight R4 codes, at any `MedicationRequest` root: a string outside them (including a case or
4071
+ * surrounding-whitespace variant of one, and the empty string), a JSON `null`, a value of another
4072
+ * JSON type, the `_` form with no value, an array wrapper, or the name written twice.
4073
+ *
4074
+ * `intent` is a modifier bound to its value set at required strength, so a value outside it says
4075
+ * something this library cannot establish, and **nothing is case-folded, trimmed or mapped to a
4076
+ * nearby code**: the root surfaces no code on {@link intents}, its location is here, and the
4077
+ * resource is not {@link safeToSummarize}. Value-free: the text that failed is carried nowhere.
4078
+ *
4079
+ * Located by the same bound and the same root rule as {@link modifierElements}. Empty for every
4080
+ * conformant document.
4081
+ */
4082
+ readonly unreadableIntents: readonly string[];
4083
+ /**
4084
+ * FHIRPath locations of a `use` on an Identifier, a HumanName, an Address or a ContactPoint, at a
4085
+ * covered position ({@link datatypeUses}), that this library could not read as a code of that
4086
+ * position's own R4 value set: a string outside it (a case or surrounding-whitespace variant of a
4087
+ * code, the empty string, or a code from a sibling set, such as `maiden` on an Identifier), a JSON
4088
+ * `null`, a value of another JSON type, the `_use` form with no value, an array wrapper, or the
4089
+ * name written twice.
4090
+ *
4091
+ * Each `use` is a modifier bound to its value set at required strength, so a value outside it says
4092
+ * something this library cannot establish, and **nothing is case-folded, trimmed or mapped to a
4093
+ * nearby code**: the position surfaces no code on {@link datatypeUses}, its location is here, and
4094
+ * the resource is not {@link safeToSummarize}. Value-free: the text that failed is carried
4095
+ * nowhere.
4096
+ *
4097
+ * Located by the same bound and the same root rule as {@link modifierElements}. Empty for every
4098
+ * conformant document.
4099
+ */
4100
+ readonly unreadableDatatypeUses: readonly string[];
3424
4101
  /**
3425
4102
  * Every element the document declares an absence for, with the reason the sender spelled and the
3426
4103
  * FHIRPath location of the element it sits on. This is the read that separates "we asked and
@@ -3492,7 +4169,9 @@ interface SafetyReadout {
3492
4169
  * character data on an element was dropped, a boolean-valued safety element carries a written
3493
4170
  * value this layer cannot read, a `code`-valued negation element carries a value that spells a
3494
4171
  * negation code bar its case or its surrounding whitespace, such an element holds content at a
3495
- * position no `code` read can reach, an element declares an absence in a reason this library
4172
+ * position no `code` read can reach, a `MedicationRequest.intent` is not one of the eight R4
4173
+ * codes, a `use` on an Identifier, a HumanName, an Address or a ContactPoint is not a code of its
4174
+ * datatype's R4 value set, an element declares an absence in a reason this library
3496
4175
  * cannot read, or an element declares an absence and carries a value. Each is a case where a
3497
4176
  * summary would have to assert something this library cannot establish (for the negation pair,
3498
4177
  * that no negation was asserted; for the absence pair, which of two contradictory answers the
@@ -3501,7 +4180,10 @@ interface SafetyReadout {
3501
4180
  * **A readable, non-conflicting absence marker does NOT move this**, and that exception is the
3502
4181
  * point of the channel rather than a hole in the rule: the declaration is read, carried and
3503
4182
  * addressable, so nothing about the document is unestablished. See
3504
- * {@link SafetyReadout.absenceMarkers}.
4183
+ * {@link SafetyReadout.absenceMarkers}. **Nor does a readable `intent`**, which is surfaced on
4184
+ * {@link SafetyReadout.intents} for the caller to read, **nor a readable `use`** on the four
4185
+ * datatypes, which is surfaced on {@link SafetyReadout.datatypeUses}: `old` and `temp` included,
4186
+ * because refusing on WHICH code was written would be interpreting the modifier.
3505
4187
  */
3506
4188
  readonly safeToSummarize: boolean;
3507
4189
  }
@@ -3976,11 +4658,13 @@ declare function readSafety(resource: FhirComplex): SafetyReadout;
3976
4658
  * was dropped, a boolean-valued safety element carries a written value outside the datatype's
3977
4659
  * lexical space, a `code`-valued negation element carries a value that spells a negation code bar
3978
4660
  * its case or its surrounding whitespace, such an element holds content at a position no `code`
3979
- * read can reach, an element declares an absence in a reason this library cannot read, or an element
4661
+ * read can reach, a `MedicationRequest.intent` is not one of the eight R4 codes, a `use` on an
4662
+ * Identifier, a HumanName, an Address or a ContactPoint is not a code of its datatype's R4 value
4663
+ * set, an element declares an absence in a reason this library cannot read, or an element
3980
4664
  * declares an absence and carries a value. Every way the safe move is to **refuse**, value-free,
3981
4665
  * carrying only the locations. A **readable, non-conflicting** absence marker is not on that list
3982
4666
  * and never refuses: it is a declaration the caller can now read, so summarizing over it asserts
3983
- * nothing this library cannot establish.
4667
+ * nothing this library cannot establish. Neither does a readable `use`, which is surfaced.
3984
4668
  *
3985
4669
  * @example
3986
4670
  * ```ts
@@ -4009,9 +4693,11 @@ declare class FhirSafetyError extends Error {
4009
4693
  * array inside an array, dropped XML element text, a boolean-valued safety element holding a written
4010
4694
  * value outside the datatype's lexical space, or a `code`-valued negation element holding a value
4011
4695
  * that spells a negation code bar its case or its surrounding whitespace, or content at a position
4012
- * no `code` read can reach, or an element declaring an absence in a reason this library cannot read,
4696
+ * no `code` read can reach, or a `MedicationRequest.intent` that is not one of the eight R4 codes,
4697
+ * or a `use` on an Identifier, a HumanName, an Address or a ContactPoint that is not a code of its
4698
+ * datatype's R4 value set, or an element declaring an absence in a reason this library cannot read,
4013
4699
  * or an element declaring an absence beside a value of its own. A readable, non-conflicting declared
4014
- * absence throws nothing. This is the executable
4700
+ * absence throws nothing, and neither does a readable `intent` or `use`. This is the executable
4015
4701
  * form of "carries status
4016
4702
  * **or refuses**": a summary helper calls it first, and never silently drops a modifier it cannot
4017
4703
  * honor, nor summarizes an element whose value the document left ambiguous or whose content the codec
@@ -4422,6 +5108,24 @@ interface ObservationValue {
4422
5108
  readonly quantity: Quantity | undefined;
4423
5109
  /** Additional `value[x]` variants also present (a structural ambiguity); empty in a clean resource. */
4424
5110
  readonly ambiguous: readonly ObservationValueType[];
5111
+ /**
5112
+ * The published {@link ../validate/issues.js} `ValidationCode` for the ENCODING the present
5113
+ * variant arrived in, when FHIR JSON gives that shape no meaning at a `0..1` choice, and
5114
+ * `undefined` otherwise, which is every conformant document.
5115
+ *
5116
+ * The one value it takes today is `ARRAY_WRAPPED_CHOICE`: the variant arrived wrapped in a JSON
5117
+ * array, which json.html §2.6.2.2 reserves for a repeating element. **This is the channel that
5118
+ * distinguishes "the sender wrote a value here and nothing read it" from "the sender wrote no
5119
+ * value here"**, which `quantity: undefined` alone cannot: a `valueQuantity` of `[{"value":5,
5120
+ * "code":"mg"}]` and one of `{}` both read as a present `Quantity` with no magnitude, and one of
5121
+ * them is a 5 mg dose. It is the same code `validateResource` raises at the same location, so a
5122
+ * caller switching on this and a caller reading the issue list see one vocabulary.
5123
+ *
5124
+ * **It says nothing about the value's CONTENT.** A variant that arrived the way FHIR JSON spells
5125
+ * it and holds a shape the variant cannot carry is not this channel's business; nothing here is
5126
+ * a general "the value was unreadable" report.
5127
+ */
5128
+ readonly encodingIssue: ValidationCode | undefined;
4425
5129
  }
4426
5130
  /**
4427
5131
  * Read the present `value[x]` variant off an Observation (or a `component`), typed by what is actually
@@ -4562,6 +5266,12 @@ declare function readMedicationDoses(resource: FhirComplex, rt: string | undefin
4562
5266
  * is **not** a Quantity is `VALUE_TYPE_UNEXPECTED` (`warning`).
4563
5267
  * 3. **Dose units.** `MedicationRequest`/`MedicationStatement` dose quantities are UCUM-shape-checked
4564
5268
  * the same way (a wrong dose unit is a prescribing hazard).
5269
+ * 4. **The `value[x]` ENCODING, not its value.** A choice variant wrapped in a JSON array is
5270
+ * `ARRAY_WRAPPED_CHOICE` (`error`). The three checks above read the value and cannot see this:
5271
+ * a wrapper reads identically to an element the sender left out, so a 5 mg dose inside one is
5272
+ * indistinguishable from no dose at all. Scoped to `Observation.value[x]` and
5273
+ * `Observation.component.value[x]`, `0..1` in R4, so it needs no per-resource cardinality table
5274
+ * and cannot fire on a conformant document. Nothing is read out of the wrapper.
4565
5275
  *
4566
5276
  * **Never a false error.** The vital-signs check fires only when the element declares the vital-signs
4567
5277
  * category (or the vital-signs profile) **and** its own LOINC code is in the closed required-unit
@@ -4678,6 +5388,14 @@ declare function isKnownSystem(system: string): boolean;
4678
5388
  * `information` at most and a wrong system draws nothing, rebinding an example code can never fail
4679
5389
  * validation.
4680
5390
  *
5391
+ * **The membership finding records which code-system release the answer was made against.** A
5392
+ * service may declare one per answer ({@link ../terminology/service.js}
5393
+ * `CodeValidationResult.systemVersion`); it is carried verbatim onto the finding, and an answer that
5394
+ * declares none is marked **undeclared** rather than left silent, so a `not-in` never reads as a
5395
+ * timeless fact when it is really an answer against one release. The record is the caller's
5396
+ * assertion and nothing else: **the resource's own `Coding.version` is never read**, by this layer
5397
+ * or any other, because it is document content and a finding is not a place to put document content.
5398
+ *
4681
5399
  * Every finding is **value-free**: a code / severity / FHIRPath location, never a code value or a
4682
5400
  * resource value. The value-set identity is used only to call the service, never emitted.
4683
5401
  *
@@ -5021,6 +5739,16 @@ declare function collectProfileVersionIssues(resource: FhirComplex, profiles: re
5021
5739
  * US Core `us-core-*`, vendor invariants). Its agreement with the reference validator on the named
5022
5740
  * safety expressions is proven directly against {@link ../fhirpath/index.js evaluateInvariant}.
5023
5741
  *
5742
+ * **What {@link collectInvariantIssues} returns does not depend on the base-constraint layer.**
5743
+ * Called directly it reports every constraint the profile carries, the R4 base ones (`pat-1`,
5744
+ * `ext-1`, `ele-1`, `dom-2` and the rest) included. Under `validateResource` the base-constraint
5745
+ * layer ({@link ../validate/base-invariants.js}) evaluates those base constraints on the eight
5746
+ * modeled types whether or not a profile is supplied, and a finding this layer makes at the same
5747
+ * occurrence, for the same key and code, is reported once rather than twice. Where that layer
5748
+ * decided a base constraint at an occurrence and this layer could not evaluate the profile's
5749
+ * verbatim copy of it there (`dom-3`, whose expression lies outside the subset, over a resource
5750
+ * with no `contained` entry), the decision stands and no `INVARIANT_UNCHECKED` is added for it.
5751
+ *
5024
5752
  * @packageDocumentation
5025
5753
  */
5026
5754
 
@@ -5443,14 +6171,17 @@ declare function parseFhirPath(expression: string): Expr;
5443
6171
  * `last`, `distinct`, `hasValue`, `children`, `extension`, `intersect`;
5444
6172
  * - **logic**, `and` / `or` / `xor` / `implies` with FHIRPath three-valued (empty-propagating) truth;
5445
6173
  * - **comparison / membership / union**, `=`, `!=`, `<`, `>`, `<=`, `>=`, `in`, `contains`, `|`;
5446
- * - **type tests** on the System primitive types (`is` / `as` / `ofType` for `Boolean` / `String` /
5447
- * `Integer` / `Decimal`).
6174
+ * - **type tests** (`is` / `as` / `ofType`) on the System primitive types `Boolean` / `String` /
6175
+ * `Integer` / `Decimal`, and on a FHIR type wherever the instance itself establishes the item's
6176
+ * type ({@link ./types.js}: a choice variant of the resource, the resource root, or the node's
6177
+ * kind), in operator and function form;
6178
+ * - **`matches(regex)`** over a pattern in a portable subset ({@link ./matches.js}).
5448
6179
  *
5449
6180
  * A **type-qualified path head** (`Patient.name`) resolves only where the focus is a resource root
5450
6181
  * whose `resourceType` the qualifier names, which is the one place a generic model can check it; see
5451
- * {@link resolveTypeQualifier}. Everything else, arithmetic, string functions, `descendants()`,
5452
- * `resolve()`, FHIR-type `is`/`as` (a generic model carries no datatype name), and a type qualifier
5453
- * that cannot be checked, raises {@link ./errors.js UnsupportedFhirPathError}.
6182
+ * {@link resolveTypeQualifier}. Everything else, arithmetic, other string functions,
6183
+ * `descendants()`, `resolve()`, a FHIR-type test the instance does not establish the answer to, and
6184
+ * a type qualifier that cannot be checked, raises {@link ./errors.js UnsupportedFhirPathError}.
5454
6185
  * That is the whole safety contract: the engine **never guesses**. Refusing is not the only way not
5455
6186
  * to guess, and it is the expensive one, because a refusal makes a constraint *unchecked* and takes
5456
6187
  * a diagnostic away: an ordering comparison the generic model cannot decide (see {@link compare})
@@ -5458,9 +6189,11 @@ declare function parseFhirPath(expression: string): Expr;
5458
6189
  * coerces exactly as `false` does and so leaves every finding where it was.
5459
6190
  * `where`/`select`/`all`
5460
6191
  * evaluate their criteria *lazily per item*, so an unsupported sub-term inside a filter over an empty
5461
- * collection (e.g. `contained.where(descendants()…)` on a resource with no `contained`) never fires,
5462
- * exactly the common case that lets base constraints like `dom-3` pass without implementing their full
5463
- * machinery.
6192
+ * collection (e.g. `contained.where(descendants()…)` on a resource with no `contained`) never fires.
6193
+ * R4's own `dom-3` still does not parse here as written (it calls `as()` in function form and ends
6194
+ * in `trace()`), so the base-constraint layer ({@link ../validate/base-invariants.js}) decides it by
6195
+ * that same reading, an empty `contained` selection making the whole filter empty, and reports it
6196
+ * unchecked whenever something is contained.
5464
6197
  *
5465
6198
  * A constraint is **satisfied** iff {@link convertToBoolean} of the result is `true`, matching the
5466
6199
  * reference validator's coercion (empty → false, a single non-boolean item → true), so an unmet or
@@ -5741,12 +6474,25 @@ declare class FhirXmlError extends Error {
5741
6474
  * separated, exactly as before. Reading is otherwise lenient (Postel's Law): nothing here is
5742
6475
  * rejected. **Lenient does not mean lossless, and the two halves differ.** An element in an
5743
6476
  * unexpected namespace is modeled and flagged; non-whitespace character data written directly on a
5744
- * FHIR element is **dropped** and flagged, because a FHIR element carries its value in `value=`
5745
- * (§2.6.1) and there is no slot on the model for text. Wherever `hasStrayText` observes such text
5746
- * the node is also **marked** ({@link ../model/node.js} `isDroppedText`), which is what the safety
5747
- * layer reads: the flag says the position was odd, the marker says content is missing from it, and
5748
- * only the second can stop an affirmative verdict being computed over an element the document did
5749
- * fill in. **`hasStrayText` is the scope of both, and it is narrower than "any character data":** it
6477
+ * FHIR element is **flagged wherever it appears**, because a FHIR element carries its value in
6478
+ * `value=` (§2.6.1) and an element holding nothing but text has none of the three things §2.6.1 says
6479
+ * an element SHALL have. Wherever `hasStrayText` observes such text the node is also **marked**
6480
+ * ({@link ../model/node.js} `isDroppedText`), which is what the safety layer reads: the flag says
6481
+ * the position was odd, the marker says the format puts no content there, and only the second can
6482
+ * stop an affirmative verdict being computed over an element the document did fill in.
6483
+ *
6484
+ * **Whether that text is also READ is decided by the position, and one position reads it.** On a
6485
+ * primitive element carrying no `value` attribute the character data is the value the sender wrote
6486
+ * in the wrong place, so it is read as the element's lexical value ({@link elementTextValue}) as
6487
+ * well as flagged and marked. Everywhere else it is genuinely dropped: a complex element has no
6488
+ * value slot to read it into, and the resource-valued unwrap models the wrapped resource and nothing
6489
+ * beside it. Reading it repairs no document and displaces no value that arrived properly - the
6490
+ * encoding stays non-conformant, stays reported at its own position, stays marked, and both writers
6491
+ * keep refusing the model - so the tolerance can only add a retraction, a negation or a dose that
6492
+ * would otherwise have read as an element the sender left out.
6493
+ *
6494
+ * **`hasStrayText` is the scope of the flag and the marker, and it is narrower than "any character
6495
+ * data":** it
5750
6496
  * tests JS `String.trim()`, whose whitespace set is wider than XML's S production and is not one
5751
6497
  * Unicode category: it spans U+00A0 and the Zs block, U+2028 (Zl) and U+2029 (Zp), U+FEFF (Cf), and
5752
6498
  * VT/FF. Character data made only of those is dropped with neither a flag nor a marker. That gap is
@@ -5783,11 +6529,14 @@ declare function parseResourceXml(input: string | XmlElement): ReadResult;
5783
6529
  /**
5784
6530
  * The XML write path: the {@link FhirNode} model → compact FHIR XML text (xml.html).
5785
6531
  *
5786
- * **The output is NOT unconditionally spec-clean, and this line used to say it was.** A property name
5787
- * carrying a prefix is written with no declaration to bind it and a name that is not a conformant XML
5788
- * name at all is written verbatim, so `<v:x value="1"/>`, `<a&b/>` and `<1abc/>` are all emitted; a
5789
- * conformant third-party parser rejects each. The exceptions are enumerated on
5790
- * {@link serializeResourceXml}, with the refusals, and this header deliberately keeps no second copy.
6532
+ * **The output is NOT unconditionally spec-clean, and this line used to say it was.** A tag name the
6533
+ * writer writes that is not an XML 1.0 `Name` (`a&b`, `1abc`) is refused rather than written, and so
6534
+ * is an attribute value or a spliced `div` string carrying a code point outside `Char`. A name
6535
+ * carrying a colon is refused too, and so is a narrative `div` string whose own markup names a prefix
6536
+ * nothing inside it binds. That is not every way a strict processor can reject the output: an element
6537
+ * or attribute name inside a `div` string is checked for `Char` and never for `Name`, and the `div`
6538
+ * branch carries three more counterexamples. They are enumerated on {@link serializeResourceXml},
6539
+ * with the refusals, and this header deliberately keeps no second copy.
5791
6540
  *
5792
6541
  * The writer is the conservative half of Postel's Law, and for a model read from a conformant
5793
6542
  * document it emits canonical FHIR XML, the exact inverse of {@link ./read.js}:
@@ -5808,7 +6557,9 @@ declare function parseResourceXml(input: string | XmlElement): ReadResult;
5808
6557
  * A decimal value is emitted from its exact lexical text and never routes
5809
6558
  * through a JavaScript `number`. Narrative `<div>` XHTML is written back as the opaque string the
5810
6559
  * model carries, verbatim. Its XHTML is not validated, but the string is checked at that branch for
5811
- * the one property splicing it in depends on ({@link emitsOneDivElement}).
6560
+ * the two properties splicing it in depends on: that it spells the one `div` element the property
6561
+ * names ({@link emitsOneDivElement}), and that every prefix its markup names is bound inside it
6562
+ * ({@link bindsEveryPrefix}).
5812
6563
  *
5813
6564
  * @packageDocumentation
5814
6565
  */
@@ -5822,32 +6573,47 @@ declare function parseResourceXml(input: string | XmlElement): ReadResult;
5822
6573
  *
5823
6574
  * ## What this output is NOT guaranteed to be, stated rather than implied
5824
6575
  *
5825
- * "Spec-clean" is a claim about the FHIR structure, not about namespace well-formedness, and the
5826
- * gap is real for a model that carries content FHIR cannot spell. A property name carrying a
5827
- * **prefix** is written verbatim with no declaration to bind it (`<v:x value="1"/>`), because the
5828
- * binding was never modeled; a name that is not a conformant XML name at all is written verbatim
5829
- * too (`<a&b/>`, `<1abc/>`). Both re-read through {@link parseResourceXml} exactly as written, and
5830
- * both are rejected by a conformant third-party parser. They are not refused precisely because this
5831
- * library's own round trip does survive them, and refusing would withdraw that from models it reads
5832
- * as valid. What IS refused is the subset where nothing survives; see the `@throws` below.
6576
+ * "Spec-clean" is a claim about the FHIR structure, and the XML 1.0 grammar for a name and a
6577
+ * character is now held at every site this writer writes one: a tag name that is not a `Name`
6578
+ * (`<a&b/>`, `<1abc/>`) is refused rather than written, although it re-reads through
6579
+ * {@link parseResourceXml} exactly as written, because a conforming third-party processor must
6580
+ * reject it; and a code point outside `Char` in an attribute value or a spliced `div` string is
6581
+ * refused, raw or as a reference (see the `@throws` below). A name carrying a **colon** is refused
6582
+ * on a code of its own, because the model carries no binding to declare. **What is still written,
6583
+ * each a declared residual rather than an oversight**:
6584
+ *
6585
+ * - a `Name` that is not namespace-well-formed after `xml:` (`<xml:1abc/>`), since only the colon
6586
+ * question reads the `xml:` prefix and it exempts that prefix;
6587
+ * - an element or attribute name inside a `div` string that is not a `Name` (`<p>` spelled `<1p>`):
6588
+ * the string is asked the `Char` question, never the `Name` question, which is asked at tag
6589
+ * positions only;
6590
+ * - the three `div` counterexamples below, none of them a name or a character matter.
6591
+ *
6592
+ * The reader is unchanged and still reads `<1abc>` and `<a&b>` back, and `validateResource` still
6593
+ * returns `valid: true` for a `string` carrying U+0000; both are separate surfaces.
5833
6594
  *
5834
6595
  * ## The `div` branch, which writes markup rather than a name
5835
6596
  *
5836
6597
  * A `div` property is written back as its own raw string, so what that string spells is markup in
5837
6598
  * the output. `emitsOneDivElement` is checked at that branch before the string is spliced in, and
5838
6599
  * the string is written only when it parses as exactly one element whose local name is `div`; a
5839
- * string that fails raises `UNSERIALIZABLE_DIV_MARKUP` below. The shape that check exists for is
6600
+ * string that fails raises `UNSERIALIZABLE_DIV_MARKUP` below. A string that passes is written only
6601
+ * when every prefix its markup names is bound by a declaration inside it (`bindsEveryPrefix`); one
6602
+ * that is not raises `UNSERIALIZABLE_DIV_PREFIX` below. A string that passes both is written only
6603
+ * when it carries no code point outside XML 1.0 `Char`, neither raw nor denoted by a numeric
6604
+ * character reference its parse decoded, each reference judged on its own; one that does raises
6605
+ * `UNSERIALIZABLE_XML_CHARACTER` below, and a reference inside a comment, which is never decoded, is
6606
+ * not one. The shape the first
6607
+ * check exists for is
5840
6608
  * `<div xmlns="…xhtml">ok</div></text><code><coding>…716186003…</coding></code><text>` on an
5841
6609
  * `AllergyIntolerance`: it used to be spliced in whole, and the emitted document re-read with
5842
6610
  * `noKnownAllergy: true` and a `no-known-allergy` negation over a record that had asserted nothing,
5843
6611
  * with no diagnostic at either end and `readSafety` affirming it.
5844
6612
  *
5845
- * **What passing that check does and does not settle, by example rather than by rule.** A string it
5846
- * accepts contributes one element, and that element is the `div`; it is not a claim that the round
5847
- * trip is lossless or that the output is well-formed from there. `<v:div>x</v:div>` carrying no
5848
- * binding for `v` is accepted, and the emitted document re-reads it as a property named `v:div`
5849
- * rather than as the narrative, which is the same unbound-prefix residual the paragraph above
5850
- * declares for names. A comment beside the root (`<!--c--><div …/>`) is accepted and does not
6613
+ * **What passing the three checks does and does not settle, by example rather than by rule.** A
6614
+ * string they accept contributes one element, that element is the `div`, every prefix its markup
6615
+ * names is bound inside it, and every character it spells or denotes is a `Char`; it is not a claim
6616
+ * that the round trip is lossless or that the output is well-formed from there. A comment beside the root (`<!--c--><div …/>`) is accepted and does not
5851
6617
  * survive the re-read. `emitsOneDivElement` carries three more counterexamples, each `PRE-EXISTING`
5852
6618
  * and each asserted rather than argued: a depth bound this check spends from a different starting
5853
6619
  * depth than the re-read, an inserted namespace declaration, and an XML declaration a conformant
@@ -5923,6 +6689,103 @@ declare function parseResourceXml(input: string | XmlElement): ReadResult;
5923
6689
  * case. `serializeResource` emits a non-string `resourceType` through its
5924
6690
  * ordinary path, so this refusal does not reach it. See `assertXmlResourceType` for the window,
5925
6691
  * which reaches every depth, and for the bound that holds only at the root.
6692
+ * @throws {FhirSerializeError} With `UNSERIALIZABLE_FOREIGN_ROOT` if the model holds a resource whose
6693
+ * root the XML reader read out of a vocabulary that resolved to something other than FHIR's, by a
6694
+ * default declaration or by a bound prefix. FHIR XML puts the resource in the FHIR namespace and
6695
+ * this writer has no vendor binding to write instead, so
6696
+ * `<v:Observation xmlns:v="urn:vendor"><v:status value="entered-in-error"/>…</v:Observation>` came
6697
+ * back as `<Observation xmlns="http://hl7.org/fhir">…</Observation>` whose re-read carried an
6698
+ * **empty** issue list: the one warning saying the document came from elsewhere was gone after a
6699
+ * single trip. **Unlike most of the refusals above it this one withdraws a round trip from a
6700
+ * document that reads `valid: true`**, because the root flag is a warning; the cost is bounded to
6701
+ * this class. A root declaring no namespace at all is untouched, and one carrying a prefix bound to
6702
+ * nothing is outside it too, refused on `UNSERIALIZABLE_PREFIXED_NAME` below rather than on this
6703
+ * code. `serializeResource` emits the model exactly as it always did, so this refusal does not
6704
+ * reach it -- a statement about that writer's output, not a claim that the JSON channel keeps the
6705
+ * flag. See `assertXmlForeignRoot` for the window and for the route not taken.
6706
+ * @throws {FhirSerializeError} With `UNSERIALIZABLE_CHOICE_WRAPPER` if the model carries an array
6707
+ * wrapper around an `Observation.value[x]` choice, at a location this library already reports as
6708
+ * `ARRAY_WRAPPED_CHOICE`, that XML has no repeated element to spell back: one holding fewer than
6709
+ * two items. `{"resourceType":"Observation","status":"final","valueQuantity":[{"value":5,
6710
+ * "system":"http://unitsofmeasure.org","code":"mg"}]}` reads with the encoding reported and no
6711
+ * magnitude handed out, and used to come back as `<valueQuantity><value value="5"/>…` re-reading
6712
+ * as an unambiguous 5 mg under an empty issue list: a **dose** a format change made confident. **A
6713
+ * wrapper of two or more items is left alone rather than refused**, because it writes as repeated
6714
+ * elements that re-read as a list and the location is reported again. Scoped to `value[x]` and
6715
+ * `component.value[x]`, `0..1` in R4, at every Observation resource root; the window is the value
6716
+ * layer's own rather than a second cardinality table. {@link serializeResource} writes the wrapper
6717
+ * back, so this refusal does not reach it. See `assertXmlValueChoiceWrapper`.
6718
+ * @throws {FhirSerializeError} With `UNSERIALIZABLE_PREFIXED_NAME` if any tag position holds a name
6719
+ * carrying a colon, other than `xml:` followed by a local part with no colon in it. XML reads the
6720
+ * colon as a namespace prefix and the model carries no binding for this writer to declare one
6721
+ * with, so it used to write the prefix bound to nothing: `<v:x value="1"/>`, `<:x/>`, `<a:b:c/>`,
6722
+ * `<xmlns:x/>`, and a root read as `<v:Observation>` written back as
6723
+ * `<v:Observation xmlns="http://hl7.org/fhir">`. A conformant parser rejects all of them, and a
6724
+ * prefix rebound between siblings lost its `MIXED_XML_SPELLING` report across one write and one
6725
+ * re-read. **It withdraws an XML write from models that read `valid: true`**, the cost the
6726
+ * foreign-root refusal above already pays: a property named `p:x` reads with zero issues. Checked
6727
+ * at every tag position, at every depth, including a resource composed into a `contained` or a
6728
+ * `Bundle.entry.resource` after it was read. Raised after every refusal above, so a model carrying
6729
+ * one of these names beside anything above keeps the code it already reported, and a name that
6730
+ * both carries a colon and breaks the tag stays `UNSERIALIZABLE_ELEMENT_NAME`. **Not covered**: a
6731
+ * name with no colon that is not an XML 1.0 `Name`, which is refused on
6732
+ * `UNSERIALIZABLE_XML_NAME` below, not on this code; and the local part after `xml:`, which is
6733
+ * not checked for namespace well-formedness, so `<xml:1abc/>` is still written. A `div` string
6734
+ * whose own markup carries an unbound prefix is written by the `div` branch rather than at a tag
6735
+ * position, so this refusal does not reach it either; that branch refuses it on
6736
+ * `UNSERIALIZABLE_DIV_PREFIX`, below. {@link serializeResource} spells a member name as a JSON
6737
+ * string, so this refusal does not reach it and that route stays open.
6738
+ * @throws {FhirSerializeError} With `UNSERIALIZABLE_DIV_PREFIX` if a `div` property carries a string
6739
+ * that passes the `UNSERIALIZABLE_DIV_MARKUP` check above and whose markup names, on an element or
6740
+ * on an attribute, a namespace prefix no declaration inside the string binds (`xml` is bound by
6741
+ * definition, and an `xmlns` or `xmlns:p` attribute is a declaration, not a prefixed name). The
6742
+ * branch splices the string in verbatim, so it used to write `<v:div>x</v:div>` into a document a
6743
+ * conformant parser rejects, and this library's re-read of that document turned the narrative into
6744
+ * a property named `v:div`, with no diagnostic at either end. An unbound prefix on an inner element
6745
+ * or an attribute (`<div xmlns="…xhtml"><v:p>x</v:p></div>`) is refused as well: the line is
6746
+ * namespace-well-formedness, the one the colon refusal above draws at the tag sites. **It withdraws
6747
+ * an XML write from models that read `valid: true`**, and for an inner prefix from a model this
6748
+ * library itself round-tripped, the cost that refusal already pays. A prefix a conformant document
6749
+ * bound on an ANCESTOR of the `div` is not refused, because the reader writes that declaration into
6750
+ * the string it hands back. Checked at the `div` branch at every depth, including a resource
6751
+ * composed into a `contained` or a `Bundle.entry.resource` after it was read, and raised after
6752
+ * every refusal above, so a model that also trips any of them keeps the code it already reported.
6753
+ * The message and the locations carry neither the string nor its prefix. {@link serializeResource}
6754
+ * carries the string as a string, so this refusal does not reach it and that route stays open.
6755
+ * @throws {FhirSerializeError} With `UNSERIALIZABLE_XML_NAME` if any tag position holds a name that
6756
+ * is not an XML 1.0 `Name` (production [5]) and that neither breaks the tag nor carries a colon:
6757
+ * `a&b`, `1abc`, `-x`, `.x`, `a"b`, a name beginning U+00B7, a name carrying U+0000 or an unpaired
6758
+ * surrogate. Each used to be written verbatim, and this library's own reader read each back
6759
+ * unchanged, which is why the tag-breaking line above never reached it; a conforming processor must
6760
+ * reject every one. Checked at every tag position at every depth: a property name, a name inside
6761
+ * `contained`, `Bundle.entry.resource` or an extension, a resource-valued element's wrapper, and a
6762
+ * `resourceType` that names a root or a nested resource's tag, the last reported at the location of
6763
+ * the element wrapping it. Every position once, in walk order; a refused name's own segment renders
6764
+ * `WITHHELD`, and neither the message nor a location carries the name. **Refused, never repaired**:
6765
+ * XML has no escape for a name. **It withdraws an XML write from models that read `valid: true`**,
6766
+ * the cost the colon refusal above already pays: a JSON property named `1abc` reads with zero
6767
+ * issues. Raised after every refusal above, so a model that trips any of them keeps the code it
6768
+ * already reported. {@link serializeResource} spells a member name as a JSON string, so this
6769
+ * refusal does not reach it and that route stays open.
6770
+ * @throws {FhirSerializeError} With `UNSERIALIZABLE_XML_CHARACTER` if a value this writer emits as an
6771
+ * attribute value (a primitive's `value`, an `id` written as an attribute, an `Extension.url`) or
6772
+ * a `div` string that passes both `div` checks above carries a code point outside XML 1.0 `Char`
6773
+ * (production [2]): U+0000 to U+0008, U+000B, U+000C, U+000E to U+001F, an unpaired surrogate,
6774
+ * U+FFFE or U+FFFF. In a `div` string a numeric character reference denoting one (`&#0;`,
6775
+ * `&#x1F;`) counts as the raw character does, because the Legal Character constraint makes it as
6776
+ * fatal; each reference is judged on its own, so two references to the halves of a surrogate pair
6777
+ * (`&#xD83D;&#xDE00;`) are refused although they decode to one `Char`, while `&#x1F600;` is
6778
+ * written. A reference inside a comment is never decoded and does not count. A U+0000 used to be
6779
+ * written raw into its `value` attribute. **Refused, never repaired**: the character is not written raw,
6780
+ * as a reference or replaced, and neither it nor its value is dropped, so the model is left as it
6781
+ * was. The location is the value's (`Patient.gender`, `Patient.gender.id`,
6782
+ * `Patient.extension[0].url`, `Patient.text.div`), every one once, in walk order; neither the
6783
+ * message nor a location carries the value or the character. The discouraged code points `Char`
6784
+ * still admits (U+007F to U+009F, U+FDD0 to U+FDEF) are written. Raised last of all, after
6785
+ * `UNSERIALIZABLE_XML_NAME`, so a model that trips any refusal above keeps the code it already
6786
+ * reported and a model carrying both a name that is not a `Name` and a character that is not a
6787
+ * `Char` draws the name code. {@link serializeResource} writes these values as JSON strings, so
6788
+ * this refusal does not reach it and that route stays open.
5926
6789
  * @example
5927
6790
  * ```ts
5928
6791
  * import { parseResource, serializeResourceXml } from "@cosyte/fhir";
@@ -6458,4 +7321,4 @@ declare function collectBundleIssues(resource: FhirComplex): ValidationIssue[];
6458
7321
  */
6459
7322
  declare const VERSION: string;
6460
7323
 
6461
- export { ABSENCE_CODES, ALLERGY_CLINICAL_SYSTEM, ALLERGY_SUBSTANCE_VALUESET, ALLERGY_VERIFICATION_SYSTEM, type AbsenceCode, type AbsenceMarker, BINDING_STRENGTHS, BUNDLE_TYPES, type BaseResolver, type BindingRegistry, type BindingStrength, type BundleEntry, type BundleIndex, type BundleReadout, type BundleType, CONDITION_CATEGORY_SYSTEM, CONDITION_CLINICAL_SYSTEM, CONDITION_VERIFICATION_SYSTEM, CPT_SYSTEM, CVX_SYSTEM, type CodeMembership, type CodeValidationRequest, type CodeValidationResult, type Coded, type ContainedIndex, DATA_ABSENT_REASON_URL, DISCRIMINATOR_TYPES, type Derivation, type Discriminator$1 as Discriminator, type DiscriminatorType, ENTERED_IN_ERROR, type ElementBinding, type ElementConstraint, type ElementDefinition, type ElementSchema, type ElementType, type EntryProcessing, type Expr, FATAL_CODES, FHIR_XML_NAMESPACE, type FatalCode, FhirCodecError, type FhirComplex, FhirDecimal, FhirInteger64, type FhirIssue, type FhirList, type FhirNode, type FhirPrimitive, FhirProfileError, type FhirProperty, FhirSafetyError, FhirSerializeError, FhirXmlError, type FpColl, type FpItem, ICD10CM_SYSTEM, ICD9CM_SYSTEM, ISSUE_CODES, ISSUE_SEVERITIES, ISSUE_TYPES, InvalidProfileError, type InvariantOptions, type InvariantResult, type IssueCode, type IssueSeverity, type IssueType, KNOWN_MODIFIER_EXTENSION_URLS, KNOWN_SYSTEMS, LOINC_SYSTEM, type LocatedDoseQuantity, MAX_REFERENCE_DEPTH, MEDICATION_VALUESET, MODIFIER_ELEMENT_ROOT_TYPES, type ModifierElementName, type ModifierElementReport, NDC_SYSTEM, NDJSON_ERROR_CODES, NOT_DONE, NOT_TAKEN, NO_KNOWN_ALLERGY, type NdjsonError, type NdjsonErrorCode, type NdjsonOptions, type NdjsonRecord, type NegationKind, type NestedArrayChannel, type NestedArrayContent, OBSERVATION_CATEGORY_SYSTEM, OBSERVATION_VALUE_TYPES, type ObservationReferenceRange, type ObservationValue, type ObservationValueType, PATIENT_IDENTIFIER_STARTER, PRIMITIVE_TYPES, type ParsedReference, type PrimitiveMeta, type PrimitiveType, type PrimitiveValue, type ProfileConstraintSpec, type ProfileElementSpec, type ProfileOptions, type ProfileSpec, type Quantity, REFUTED, RXNORM_SYSTEM, type RawArray, type RawBool, type RawJson, type RawMember, type RawNull, type RawNumber, type RawObject, type RawString, type ReadResult, type ReferenceKind, type ReferenceResolution, type RequiredBinding, type ResourceSchema, SAFETY_RESOURCE_TYPES, SERIALIZE_ERROR_CODES, SNOMED_SCT, STARTER_PROFILES, STARTER_PROFILE_BASE_URL, type SafetyReadout, type SchemaRegistry, type SerializeErrorCode, type SliceConstraint, type SliceDefinition, type SliceMatchResult, type Slicing, type SlicingRules, type StructureDefinition, TERMINOLOGY_BINDINGS, type TerminologyBinding, type TerminologyOptions, type TerminologyService, type Token, type TokenType, type TypedValue, UCUM_SYSTEM, UNBOUNDED, type UcumShapeVerdict, UnsupportedFhirPathError, VALIDATION_CODES, VERSION, VITAL_SIGNS_CATEGORY, VITAL_SIGNS_PROFILE, VITAL_SIGN_OBSERVATION_STARTER, VITAL_SIGN_UNITS, type ValidateOptions, type ValidationCode, type ValidationIssue, type ValidationMode, type ValidationResult, type ValidationSeverity, WITHHELD, XHTML_NAMESPACE, XML_FATAL_CODES, type XmlAttribute, type XmlElement, type XmlFatalCode, type XmlNode, type XmlText, absenceMarkers, arrayWrappedScalars, assertSafeToSummarize, baseSchema, buildBindingRegistry, buildBundleIndex, buildRegistry, codeOf, codingsOf, collectBundleIssues, collectInvariantIssues, collectProfileIssues, collectProfileVersionIssues, collectQuantityIssues, collectSafetyIssues, collectTerminologyIssues, complex, conflictingAbsenceMarkers, containedIndex, convertToBoolean, decimal, decimalPrecisionAtRisk, defineProfile, diagnosticFor, droppedText, duplicateProperty, entryProcessing, evaluateInvariant, generateSnapshot, getAllProperties, getProperty, hasCodeAnySystem, hasCoding, hasContainedCycle, integer64, isAbsenceCode, isAtomicBundle, isChoice, isComplex, isDroppedText, isKnownSystem, isList, isNestedArray, isPrimitive, isPrimitiveType, isRetracted, isUndefinedNull, list, loadStructureDefinition, locateDoseQuantities, matchSlices, matchesFixed, matchesPattern, misplacedPrimitiveExtension, mixedXmlSpelling, modifierElements, nearMissNegationCodes, nestedArray, nestedArrayContent, nestedArrays, nodesEquivalent, parseFhirPath, parseNdjsonLine, parseReference, parseResource, parseResourceXml, pathExists, primitive, readBundle, readInterpretations, readMedicationDoses, readObservationValue, readQuantity, readRawJson, readRawXml, readReferenceRanges, readSafety, requiredVitalSignUnits, resolveElement, resolvePath, resolveReference, resolveSlices, resourceType, serializeResource, serializeResourceXml, shadowedProperties, snapshotElements, starterProfile, streamNdjson, toOperationOutcome, tokenize, undefinedJsonNull, unexpectedXmlContent, unhandledModifierExtensions, unknownProperty, unreadableAbsenceMarkers, unreadableBooleans, unreadableNegationCodes, validatePrimitiveValue, validateResource, validateUcumShape, validationIssue, wouldLosePrecisionAsDouble };
7324
+ export { ABSENCE_CODES, ALLERGY_CLINICAL_SYSTEM, ALLERGY_SUBSTANCE_VALUESET, ALLERGY_VERIFICATION_SYSTEM, type AbsenceCode, type AbsenceMarker, BINDING_STRENGTHS, BUNDLE_TYPES, type BaseResolver, type BindingRegistry, type BindingStrength, type BundleEntry, type BundleIndex, type BundleReadout, type BundleType, CODE_SYSTEM_VERSION_RECORD_CODES, CODE_SYSTEM_VERSION_RECORD_SYSTEM, CONDITION_CATEGORY_SYSTEM, CONDITION_CLINICAL_SYSTEM, CONDITION_VERIFICATION_SYSTEM, CPT_SYSTEM, CVX_SYSTEM, type CodeMembership, type CodeSystemVersionRecord, type CodeSystemVersionRecordCode, type CodeValidationRequest, type CodeValidationResult, type Coded, type ContainedIndex, DATA_ABSENT_REASON_URL, DISCRIMINATOR_TYPES, type DatatypeUseCode, type DatatypeUseReport, type Derivation, type Discriminator$1 as Discriminator, type DiscriminatorType, ENTERED_IN_ERROR, type ElementBinding, type ElementConstraint, type ElementDefinition, type ElementSchema, type ElementType, type EntryProcessing, type Expr, FATAL_CODES, FHIR_XML_NAMESPACE, type FatalCode, FhirCodecError, type FhirComplex, FhirDecimal, FhirInteger64, type FhirIssue, type FhirList, type FhirNode, type FhirPrimitive, FhirProfileError, type FhirProperty, FhirSafetyError, FhirSerializeError, FhirXmlError, type FpColl, type FpItem, ICD10CM_SYSTEM, ICD9CM_SYSTEM, ISSUE_CODES, ISSUE_SEVERITIES, ISSUE_TYPES, type IntentReport, InvalidProfileError, type InvariantOptions, type InvariantResult, type IssueCode, type IssueSeverity, type IssueType, KNOWN_MODIFIER_EXTENSION_URLS, KNOWN_SYSTEMS, LOINC_SYSTEM, type LocatedDoseQuantity, MAX_REFERENCE_DEPTH, MEDICATION_VALUESET, MODIFIER_ELEMENT_ROOT_TYPES, type MedicationRequestIntent, type ModifierElementName, type ModifierElementReport, NDC_SYSTEM, NDJSON_ERROR_CODES, NOT_DONE, NOT_TAKEN, NO_KNOWN_ALLERGY, type NdjsonError, type NdjsonErrorCode, type NdjsonOptions, type NdjsonRecord, type NegationKind, type NestedArrayChannel, type NestedArrayContent, OBSERVATION_CATEGORY_SYSTEM, OBSERVATION_VALUE_TYPES, type ObservationReferenceRange, type ObservationValue, type ObservationValueType, PATIENT_IDENTIFIER_STARTER, PRIMITIVE_TYPES, type ParsedReference, type PrimitiveMeta, type PrimitiveType, type PrimitiveValue, type ProfileConstraintSpec, type ProfileElementSpec, type ProfileOptions, type ProfileSpec, type Quantity, REFUTED, RXNORM_SYSTEM, type RawArray, type RawBool, type RawJson, type RawMember, type RawNull, type RawNumber, type RawObject, type RawString, type ReadResult, type ReferenceKind, type ReferenceResolution, type RequiredBinding, type ResourceSchema, SAFETY_RESOURCE_TYPES, SERIALIZE_ERROR_CODES, SNOMED_SCT, STARTER_PROFILES, STARTER_PROFILE_BASE_URL, type SafetyReadout, type SchemaRegistry, type SerializeErrorCode, type SliceConstraint, type SliceDefinition, type SliceMatchResult, type Slicing, type SlicingRules, type StructureDefinition, TERMINOLOGY_BINDINGS, type TerminologyBinding, type TerminologyOptions, type TerminologyService, type Token, type TokenType, type TypedValue, UCUM_SYSTEM, UNBOUNDED, type UcumShapeVerdict, UnsupportedFhirPathError, VALIDATION_CODES, VERSION, VITAL_SIGNS_CATEGORY, VITAL_SIGNS_PROFILE, VITAL_SIGN_OBSERVATION_STARTER, VITAL_SIGN_UNITS, type ValidateOptions, type ValidationCode, type ValidationIssue, type ValidationMode, type ValidationResult, type ValidationSeverity, WITHHELD, XHTML_NAMESPACE, XML_FATAL_CODES, type XmlAttribute, type XmlElement, type XmlFatalCode, type XmlNode, type XmlText, absenceMarkers, arrayWrappedScalars, assertSafeToSummarize, baseSchema, buildBindingRegistry, buildBundleIndex, buildRegistry, codeOf, codingsOf, collectBundleIssues, collectInvariantIssues, collectProfileIssues, collectProfileVersionIssues, collectQuantityIssues, collectSafetyIssues, collectTerminologyIssues, complex, conflictingAbsenceMarkers, containedIndex, convertToBoolean, decimal, decimalPrecisionAtRisk, defineProfile, diagnosticFor, droppedText, duplicateProperty, entryProcessing, evaluateInvariant, generateSnapshot, getAllProperties, getProperty, hasCodeAnySystem, hasCoding, hasContainedCycle, integer64, isAbsenceCode, isAtomicBundle, isChoice, isComplex, isDroppedText, isForeignRoot, isKnownSystem, isList, isNestedArray, isPrimitive, isPrimitiveType, isRetracted, isUndefinedNull, list, loadStructureDefinition, locateDoseQuantities, matchSlices, matchesFixed, matchesPattern, misplacedPrimitiveExtension, mixedXmlSpelling, modifierElements, nearMissNegationCodes, nestedArray, nestedArrayContent, nestedArrays, nodesEquivalent, parseFhirPath, parseNdjsonLine, parseReference, parseResource, parseResourceXml, pathExists, primitive, readBundle, readInterpretations, readMedicationDoses, readObservationValue, readQuantity, readRawJson, readRawXml, readReferenceRanges, readSafety, requiredVitalSignUnits, resolveElement, resolvePath, resolveReference, resolveSlices, resourceType, serializeResource, serializeResourceXml, shadowedProperties, snapshotElements, starterProfile, streamNdjson, toOperationOutcome, tokenize, undefinedJsonNull, unexpectedXmlContent, unhandledModifierExtensions, unknownProperty, unreadableAbsenceMarkers, unreadableBooleans, unreadableNegationCodes, validatePrimitiveValue, validateResource, validateUcumShape, validationIssue, wouldLosePrecisionAsDouble };