@bsv/dpp-profiles 0.3.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/LICENSE +58 -0
  2. package/README.md +64 -0
  3. package/dist/applicability.d.ts +96 -0
  4. package/dist/applicability.d.ts.map +1 -0
  5. package/dist/applicability.js +181 -0
  6. package/dist/applicability.js.map +1 -0
  7. package/dist/combinations.d.ts +30 -0
  8. package/dist/combinations.d.ts.map +1 -0
  9. package/dist/combinations.js +103 -0
  10. package/dist/combinations.js.map +1 -0
  11. package/dist/evidence-shapes.d.ts +198 -0
  12. package/dist/evidence-shapes.d.ts.map +1 -0
  13. package/dist/evidence-shapes.js +123 -0
  14. package/dist/evidence-shapes.js.map +1 -0
  15. package/dist/gs1-epc-binary.d.ts +81 -0
  16. package/dist/gs1-epc-binary.d.ts.map +1 -0
  17. package/dist/gs1-epc-binary.js +252 -0
  18. package/dist/gs1-epc-binary.js.map +1 -0
  19. package/dist/gs1-resolution.d.ts +392 -0
  20. package/dist/gs1-resolution.d.ts.map +1 -0
  21. package/dist/gs1-resolution.js +696 -0
  22. package/dist/gs1-resolution.js.map +1 -0
  23. package/dist/identifiers.d.ts +57 -0
  24. package/dist/identifiers.d.ts.map +1 -0
  25. package/dist/identifiers.js +117 -0
  26. package/dist/identifiers.js.map +1 -0
  27. package/dist/index.d.ts +235 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +124 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/manifest-v2.d.ts +87 -0
  32. package/dist/manifest-v2.d.ts.map +1 -0
  33. package/dist/manifest-v2.js +31 -0
  34. package/dist/manifest-v2.js.map +1 -0
  35. package/dist/mapping.d.ts +84 -0
  36. package/dist/mapping.d.ts.map +1 -0
  37. package/dist/mapping.js +88 -0
  38. package/dist/mapping.js.map +1 -0
  39. package/dist/projections.d.ts +233 -0
  40. package/dist/projections.d.ts.map +1 -0
  41. package/dist/projections.js +466 -0
  42. package/dist/projections.js.map +1 -0
  43. package/frozen.json +42 -0
  44. package/generated/consumer/battery-v2.json +2248 -0
  45. package/generated/consumer/battery-v3.json +4354 -0
  46. package/generated/consumer/general-v1.json +9 -0
  47. package/generated/consumer/general-v2.json +714 -0
  48. package/generated/consumer/textile-v1.json +101 -0
  49. package/generated/consumer/textile-v2.json +1033 -0
  50. package/generated/consumer/textile-v3.json +2011 -0
  51. package/generated/index.json +86 -0
  52. package/generated/mapping/battery@2.md +116 -0
  53. package/generated/mapping/battery@3.md +130 -0
  54. package/generated/mapping/general@2.md +50 -0
  55. package/generated/mapping/textile@2.md +61 -0
  56. package/generated/mapping/textile@3.md +73 -0
  57. package/generated/payload-schema/battery@2.public.schema.json +609 -0
  58. package/generated/payload-schema/battery@2.restricted.schema.json +377 -0
  59. package/generated/payload-schema/battery@3.public.schema.json +1364 -0
  60. package/generated/payload-schema/battery@3.restricted.schema.json +1097 -0
  61. package/generated/payload-schema/general@1.public.schema.json +37 -0
  62. package/generated/payload-schema/general@1.restricted.schema.json +9 -0
  63. package/generated/payload-schema/general@2.public.schema.json +352 -0
  64. package/generated/payload-schema/general@2.restricted.schema.json +52 -0
  65. package/generated/payload-schema/textile@1.public.schema.json +82 -0
  66. package/generated/payload-schema/textile@1.restricted.schema.json +22 -0
  67. package/generated/payload-schema/textile@2.public.schema.json +464 -0
  68. package/generated/payload-schema/textile@2.restricted.schema.json +78 -0
  69. package/generated/payload-schema/textile@3.public.schema.json +1299 -0
  70. package/generated/payload-schema/textile@3.restricted.schema.json +78 -0
  71. package/manifests/battery@2.json +4047 -0
  72. package/manifests/battery@3.json +6164 -0
  73. package/manifests/exchange/untp-0.7.0-jose@1.json +191 -0
  74. package/manifests/exchange/vc-di-ecdsa-rdfc-2019@1.json +74 -0
  75. package/manifests/exchange/vsc-draft-compat@0.1.0.json +64 -0
  76. package/manifests/general@1.json +148 -0
  77. package/manifests/general@2.json +1266 -0
  78. package/manifests/interoperability/epcis-json@1.json +69 -0
  79. package/manifests/interoperability/epcis-vsc@1.json +64 -0
  80. package/manifests/interoperability/gs1-digital-link@1.json +71 -0
  81. package/manifests/operator/federated-operators@1.json +54 -0
  82. package/manifests/operator/single-operator@1.json +52 -0
  83. package/manifests/textile@1.json +383 -0
  84. package/manifests/textile@2.json +1682 -0
  85. package/manifests/textile@3.json +2763 -0
  86. package/package.json +59 -0
  87. package/schemas/exchange-profile.schema.json +134 -0
  88. package/schemas/gs1/NOTICE.md +11 -0
  89. package/schemas/gs1/resolver-description-file-schema-1.2.0.json +124 -0
  90. package/schemas/gs1/resolver-linkset-context-1.2.1.jsonld +39 -0
  91. package/schemas/gs1/resolver-linkset-schema-1.2.1.json +96 -0
  92. package/schemas/interoperability-profile.schema.json +347 -0
  93. package/schemas/operator-profile.schema.json +108 -0
  94. package/schemas/product-identity.schema.json +45 -0
  95. package/schemas/profile-manifest-v2.schema.json +1087 -0
  96. package/schemas/profile-manifest.schema.json +291 -0
package/LICENSE ADDED
@@ -0,0 +1,58 @@
1
+ Open BSV License Version 6 – granted by BSV Association, Alpenstrasse 15, 6300
2
+ Zug, Switzerland (CHE-427.008.338) ("Licensor"), to you as a user (henceforth
3
+ "You", "User" or "Licensee").
4
+
5
+ For the purposes of this license, the definitions below have the following
6
+ meanings:
7
+
8
+ "Bitcoin Protocol" means the protocol implementation, cryptographic rules,
9
+ network protocols, and consensus mechanisms in the Bitcoin White Paper as
10
+ described here https://protocol.bsvblockchain.org.
11
+
12
+ "Bitcoin White Paper" means the paper entitled 'Bitcoin: A Peer-to-Peer
13
+ Electronic Cash System' published by 'Satoshi Nakamoto' in October 2008.
14
+
15
+ "BSV Blockchain" means:
16
+
17
+ (a) the Bitcoin blockchain containing block height #556767 with the hash
18
+ "000000000000000001d956714215d96ffc00e0afda4cd0a96c96f8d802b1662b" and
19
+ that contains the longest honest persistent chain of blocks which has been
20
+ produced in a manner which is consistent with the rules set forth in the
21
+ Network Access Rules; and
22
+ (b) the test blockchains that contain the longest honest persistent chains of
23
+ blocks which has been produced in a manner which is consistent with the
24
+ rules set forth in the Network Access Rules.
25
+
26
+ "Network Access Rules" or "Rules" means the set of rules regulating the
27
+ relationship between BSV Association and the nodes on BSV based on the Bitcoin
28
+ Protocol rules and those set out in the Bitcoin White Paper, and available here
29
+ https://bsvblockchain.org/network-access-rules.
30
+
31
+ "Software" means the software the subject of this license, including any/all
32
+ intellectual property rights therein and associated documentation files.
33
+
34
+ BSV Association grants permission, free of charge and on a non-exclusive basis
35
+ to any person obtaining a copy of the Software to deal in the Software, including
36
+ without limitation the rights to use, copy, modify, merge, publish, distribute,
37
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the
38
+ Software is furnished to do so, subject to and conditioned upon the following
39
+ conditions:
40
+
41
+ 1 - The text "© BSV Association", and this license shall be included in all
42
+ copies or substantial portions of the Software.
43
+
44
+ 2 - The Software, and any software that is derived from the Software or parts
45
+ thereof, may only be used exclusively on the BSV Blockchain.
46
+
47
+ For the avoidance of doubt, this license is granted subject to and conditioned
48
+ upon your compliance with these terms only and is limited to uses on the BSV
49
+ Blockchain. Any exercise of rights not compliant with these terms including
50
+ use not for the BSV Blockchain is deemed outside the scope of the license.
51
+
52
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES REGARDING ENTITLEMENT,
54
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
55
+ EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS THEREOF BE LIABLE FOR ANY CLAIM,
56
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
57
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
58
+ DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # @bsv/dpp-profiles
2
+
3
+ **Experimental prerelease:** For implementation and interoperability testing. APIs may change significantly before a stable release. Pin exact package versions and retain your lockfile. This package is not declared production-ready. Package versions are separate from the specification, wire-format and frozen profile versions they implement.
4
+
5
+ ## Install
6
+
7
+ This is a pre-1.0 candidate. After publication, install the selected version from npm:
8
+
9
+ ```sh
10
+ npm install --save-exact @bsv/dpp-profiles@0.3.0-beta.1
11
+ ```
12
+
13
+ The runtime requires Node >=22 and ECMAScript modules. The JSON data exports can be read in other runtimes. No repository checkout or package build is needed after installation.
14
+
15
+ The canonical industry data profiles of the DPP standard, as `spec/profiles.md` defines them: immutable manifests, the artefacts generated from them, the digests they are frozen at, and the GS1 identifier helpers a writer uses to mint an identifier it can stand behind. Data first: the manifests, schemas and generated documents are plain files any language reads, and the one runtime dependency of the code beside them is the RFC 8785 canonicaliser (`canonicalize`) the projection digest uses. The code reads its data files through the Node file system, so the root entry point is a Node module; a browser or another language reads the data files directly through the `./manifests/*`, `./schemas/*`, `./generated/*` and `./frozen.json` entry points.
16
+
17
+ ## What is in it
18
+
19
+ | Path | What it is |
20
+ |---|---|
21
+ | `manifests/<id>@<version>.json` | The canonical definition of one profile: every field with its pointer, semantic URI, value type, unit or code list, resolved constraints, cardinality, granularity, provenance, access tier, obligation, legal basis and applicability; the stamps, event mappings, access tiers, sources and identity model. Immutable once published. |
22
+ | `schemas/profile-manifest.schema.json` | The JSON Schema (2020-12) every manifest validates against. |
23
+ | `schemas/product-identity.schema.json` | The model, batch and item identity document a passport may relate. |
24
+ | `generated/payload-schema/<profile>.public.schema.json` | The JSON Schema for the public payload carried on chain, generated from the manifest. |
25
+ | `generated/payload-schema/<profile>.restricted.schema.json` | The same for the off-chain restricted tiers. |
26
+ | `generated/consumer/<id>-v<version>.json` | The legacy consumer document the registry serves and the application publishes, generated from the manifest. |
27
+ | `generated/mapping/<profile>.md` | The row-level field mapping inventory of each current profile, generated from the manifest; `needs review` where no generator can decide. |
28
+ | `generated/index.json` | Every file with its digest. |
29
+ | `frozen.json` | The digests every published manifest and generated file is held to. |
30
+ | `src/identifiers.ts` | GS1 check digit, GTIN-14 spelling, the demonstration prefix 952 and the Digital Link path parser and builder. |
31
+ | `src/combinations.ts` | `checkSelection`: supported combinations of baseline, industry, exchange and operator profiles pass, and contradictory selections are refused by name (a write under a superseded version, a claim on a proposed profile, a single operator with peers, a federation of one). |
32
+ | `src/mapping.ts` | `mapNativeOperation`: the conditional lifecycle mapping of `spec/rules.md` §2, one of four outcomes with a loss list on every outcome that is not lossless. |
33
+ | `src/gs1-resolution.ts`, `src/gs1-epc-binary.ts` | The `gs1-digital-link@1` discovery profile (`spec/gs1-discovery.md`): the full grammar for primary key 01 with its qualifiers and data attributes, key-tuple equivalence across hosts, EPC-binary decompression for SGTIN-96 and SGTIN-198, resolution records, the linkset hierarchy and selection, and the resolver description file; `schemas/gs1/` carries the pinned GS1 resolver schemas. |
34
+ | `manifests/interoperability/*.json`, `schemas/interoperability-profile.schema.json` | The interoperability profiles: discovery (`gs1-digital-link@1`), source exchange (`epcis-json@1`) and mapping (`epcis-vsc@1`), each recording its standards, pinned artefacts, formats, limits and what it cannot map. |
35
+ | `src/evidence-shapes.ts`, `src/applicability.ts`, `src/projections.ts` | The shared evidence, measurement, certification, document and language shapes of `contracts/profile-evidence.schema.json`, the declarative applicability evaluator of manifest version 2 (`schemas/profile-manifest-v2.schema.json`) whose `unresolved` outcome is never a pass, and `projectPassport`, the pure deterministic `passport-projection@1` of `spec/passport-projections.md` over versioned model, batch and item sources, digested under RFC 8785. |
36
+
37
+ Five profiles are published: `battery@2`, `textile@2` and `general@2` (current) and `textile@1` and `general@1` (superseded, and served for as long as any state declares them). They were inventoried from the application's attribute registries in full, including the fields captured over life or derived rather than at registration, and frozen. `battery@3` and `textile@3` are draft successors under manifest version 2: opt-in by explicit version, carrying a requirement status per field and a migration outcome per field, and leaving every byte of the two current versions unchanged until a reviewed cutover.
38
+
39
+ ## Working on it
40
+
41
+ ```
42
+ npm run build # tsc, then the generator: regenerates generated/ and refuses drift from frozen.json
43
+ npm run generate # the generator alone
44
+ npm run refreeze # writes the current digests into the manifests and frozen.json; review that diff
45
+ npm test # schema validity, uniqueness, freezing, deterministic generation, payload validation, identifiers, lifecycle mapping
46
+ ```
47
+
48
+ A frozen profile changes only by publishing a new version. A corrected mandatory field, a changed meaning or an incompatible validation rule is a new version; a state decodes under the version it declares and is never reinterpreted under a newer one. `--refreeze` exists for a reviewed change to the generator's output for an existing version, and the diff it produces is the review.
49
+
50
+ ## Using it
51
+
52
+ ```ts
53
+ import { readManifest, fieldsFor, missingRequired, parseGs1DigitalLink, parseGs1DigitalLinkUri, decompressGs1DigitalLink, projectPassport } from '@bsv/dpp-profiles'
54
+
55
+ const battery = readManifest('battery@2')
56
+ const { applies, needsReview } = fieldsFor(battery, 'ev')
57
+ const gaps = missingRequired(battery, payload, 'ev') // gaps.missing blocks; gaps.needsReview is shown, never assumed
58
+ const link = parseGs1DigitalLink(passportId) // link.checkDigitValid, link.demonstration, never allocation authority
59
+ const request = parseGs1DigitalLinkUri(uri) // key 01 with 22, 10 and 21, data attributes, linkType; never an exception
60
+ const plain = decompressGs1DigitalLink(compressed) // eh and ex forms carrying SGTIN-96 or SGTIN-198; other schemes refused by name
61
+ const { projection } = projectPassport(input) // one digest for one set of pinned sources, policy, cutoff and disclosure
62
+ ```
63
+
64
+ A consumer validates a public payload against the generated schema with a validator that asserts formats and refuses an unknown dialect, and reads `needs-review` as a list to show a person, never as satisfied and never as universally required. Syntax and a correct check digit never prove that GS1 allocated a number to the brand a record describes.
@@ -0,0 +1,96 @@
1
+ /**
2
+ * The declarative applicability evaluator (`spec/profiles.md` §3,
3
+ * `spec/passport-projections.md` §6). A rule is data, never an expression:
4
+ * category membership, jurisdiction, an effective interval, a numeric
5
+ * threshold on a payload value, `all` and `any` over those, `needs-review`
6
+ * for what only a person can decide, and `unresolved` for what the primary
7
+ * source could not establish. Three outcomes and never a fourth: a field
8
+ * applies, does not apply, or is unresolved. Unresolved is not satisfied and
9
+ * is not a failure either; it is shown, and it never becomes a pass.
10
+ */
11
+ import type { ApplicabilityRule, ProfileManifest } from './index.js';
12
+ import { type AnyProfileField, type AnyProfileManifest, type ApplicabilityRuleV2 } from './manifest-v2.js';
13
+ export type ApplicabilityOutcome = 'applies' | 'not-applicable' | 'unresolved';
14
+ export interface ApplicabilityContext {
15
+ /** The product category, as the manifest's `applicability.categoryKey` payload value names it. */
16
+ category?: string;
17
+ /** The jurisdiction the passport is evaluated for, for example `EU`. */
18
+ jurisdiction?: string;
19
+ /** The date or instant the evaluation is made at, for `effective` rules. */
20
+ asOf?: string;
21
+ /** Payload values a `threshold` rule may read, as numbers or as `{ value, unit }`. */
22
+ values?: Record<string, unknown>;
23
+ /**
24
+ * The field keys the record declares inapplicable under `inapplicableFields`
25
+ * (`spec/profiles.md` §3): a declaration by the declaring party, with a
26
+ * reason, that a conditional data point does not apply to this record. It
27
+ * turns an unresolved field into not-applicable with the reason `declared`;
28
+ * it never makes a required, enacted, unconditionally applicable field
29
+ * optional, because a declaration is not a value.
30
+ */
31
+ declaredNotApplicable?: string[];
32
+ }
33
+ export interface ApplicabilityResult {
34
+ outcome: ApplicabilityOutcome;
35
+ reasons: string[];
36
+ }
37
+ export declare function evaluateApplicability(rule: ApplicabilityRule | ApplicabilityRuleV2, ctx?: ApplicabilityContext): ApplicabilityResult;
38
+ /** The key under which a record declares fields inapplicable, and the shape of each declaration. */
39
+ export declare const INAPPLICABLE_FIELDS_KEY = "inapplicableFields";
40
+ export interface InapplicabilityDeclaration {
41
+ field: string;
42
+ reason: string;
43
+ declaredBy?: string;
44
+ }
45
+ /** The declarations a payload carries under `inapplicableFields`, as field keys; malformed entries are ignored, never read as a declaration. */
46
+ export declare function declaredInapplicable(payload: Record<string, unknown> | undefined): string[];
47
+ /**
48
+ * A field's applicability under a context: a declaration under
49
+ * `inapplicableFields` answers not-applicable with the reason `declared`
50
+ * only where the rule would otherwise be unresolved or conditional, so a
51
+ * declaration cannot switch off a field that applies unconditionally; the
52
+ * rule answers otherwise.
53
+ */
54
+ export declare function evaluateFieldApplicability(field: Pick<AnyProfileField, 'key' | 'applicability'>, ctx?: ApplicabilityContext): ApplicabilityResult;
55
+ export interface FieldsForResult<F extends AnyProfileField> {
56
+ applies: F[];
57
+ notApplicable: F[];
58
+ unresolved: Array<{
59
+ field: F;
60
+ reasons: string[];
61
+ }>;
62
+ }
63
+ /**
64
+ * The fields of a version 1 or version 2 manifest under a context: what
65
+ * applies, what does not, and what is unresolved with its reasons. The
66
+ * version 1 `fieldsFor` remains the reader for version 1 manifests with a
67
+ * bare category; this one takes the whole context.
68
+ */
69
+ export declare function fieldsForV2<M extends AnyProfileManifest>(manifest: M, ctx?: ApplicabilityContext): FieldsForResult<M['fields'][number]>;
70
+ export interface MissingRequiredV2Result<F extends AnyProfileField> {
71
+ /** Required, applicable, captured at registration, and absent: this blocks. */
72
+ missing: F[];
73
+ /** Required and absent, but whether it applies is unresolved: shown, never blocking, never satisfied. */
74
+ unresolved: Array<{
75
+ field: F;
76
+ reasons: string[];
77
+ }>;
78
+ /** Required in the profile's own terms but whose requirement status defers it: anticipated, not to be displayed, or under review. Never counted as missing. */
79
+ deferred: Array<{
80
+ field: F;
81
+ status: string;
82
+ }>;
83
+ }
84
+ /**
85
+ * Which required fields a payload lacks under a context, on three separate
86
+ * lists. A field whose applicability is unresolved is never missing and never
87
+ * satisfied; a field whose requirement status is anticipated, not to be
88
+ * displayed or under review is deferred and never blocks, so an adopter can
89
+ * keep incomplete draft data without a false failure or a false pass. A
90
+ * field the payload declares inapplicable under `inapplicableFields` is
91
+ * not-applicable where it would otherwise be unresolved.
92
+ */
93
+ export declare function missingRequiredV2<M extends AnyProfileManifest>(manifest: M, payload: Record<string, unknown>, ctx?: ApplicabilityContext): MissingRequiredV2Result<M['fields'][number]>;
94
+ /** The category value a payload names for a manifest, read at the manifest's declared category key. */
95
+ export declare function categoryOf(manifest: Pick<ProfileManifest, 'applicability'>, payload: Record<string, unknown> | undefined): string | undefined;
96
+ //# sourceMappingURL=applicability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applicability.d.ts","sourceRoot":"","sources":["../src/applicability.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,181 @@
1
+ import { isFieldV2 } from './manifest-v2.js';
2
+ const applies = (reasons = []) => ({ outcome: 'applies', reasons });
3
+ const notApplicable = (reason) => ({ outcome: 'not-applicable', reasons: [reason] });
4
+ const unresolved = (reason) => ({ outcome: 'unresolved', reasons: [reason] });
5
+ /** The calendar day of a date or instant, as `YYYY-MM-DD`, for a lexicographic comparison that needs no clock. */
6
+ function dayOf(value) {
7
+ const day = value.slice(0, 10);
8
+ return /^\d{4}-\d{2}-\d{2}$/.test(day) ? day : /^\d{4}-\d{2}$/.test(value) ? `${value}-01` : /^\d{4}$/.test(value) ? `${value}-01-01` : undefined;
9
+ }
10
+ function thresholdValue(raw, unit) {
11
+ if (raw == null)
12
+ return { reason: 'not supplied' };
13
+ if (typeof raw === 'number')
14
+ return Number.isFinite(raw) ? { value: raw } : { reason: 'not a finite number' };
15
+ if (typeof raw === 'object' && !Array.isArray(raw)) {
16
+ const record = raw;
17
+ if (typeof record.value !== 'number' || !Number.isFinite(record.value))
18
+ return { reason: 'carries no finite numeric value' };
19
+ if (unit != null && record.unit !== unit)
20
+ return { reason: `is in ${String(record.unit)}, not the rule's ${unit}` };
21
+ return { value: record.value };
22
+ }
23
+ return { reason: 'is not numeric' };
24
+ }
25
+ export function evaluateApplicability(rule, ctx = {}) {
26
+ switch (rule.rule) {
27
+ case 'always':
28
+ return applies();
29
+ case 'category-in': {
30
+ const categories = rule.categories ?? [];
31
+ if (ctx.category == null)
32
+ return applies(['no category supplied; a category-in rule is read as applying, as fieldsFor reads it']);
33
+ return categories.includes(ctx.category) ? applies() : notApplicable(`category ${ctx.category} is not one of ${categories.join(', ')}`);
34
+ }
35
+ case 'needs-review': {
36
+ const categories = rule.categories;
37
+ if (categories != null && ctx.category != null && !categories.includes(ctx.category))
38
+ return notApplicable(`category ${ctx.category} is outside the categories the review concerns`);
39
+ return unresolved(`needs review: ${rule.condition ?? 'the condition is not stated'}`);
40
+ }
41
+ case 'all': {
42
+ const results = rule.rules.map((r) => evaluateApplicability(r, ctx));
43
+ const no = results.filter((r) => r.outcome === 'not-applicable');
44
+ if (no.length > 0)
45
+ return { outcome: 'not-applicable', reasons: no.flatMap((r) => r.reasons) };
46
+ const open = results.filter((r) => r.outcome === 'unresolved');
47
+ if (open.length > 0)
48
+ return { outcome: 'unresolved', reasons: open.flatMap((r) => r.reasons) };
49
+ return applies(results.flatMap((r) => r.reasons));
50
+ }
51
+ case 'any': {
52
+ const results = rule.rules.map((r) => evaluateApplicability(r, ctx));
53
+ const yes = results.find((r) => r.outcome === 'applies');
54
+ if (yes != null)
55
+ return applies(yes.reasons);
56
+ const open = results.filter((r) => r.outcome === 'unresolved');
57
+ if (open.length > 0)
58
+ return { outcome: 'unresolved', reasons: open.flatMap((r) => r.reasons) };
59
+ return { outcome: 'not-applicable', reasons: results.flatMap((r) => r.reasons) };
60
+ }
61
+ case 'jurisdiction-in':
62
+ if (ctx.jurisdiction == null)
63
+ return unresolved('no jurisdiction supplied');
64
+ return rule.jurisdictions.includes(ctx.jurisdiction) ? applies() : notApplicable(`jurisdiction ${ctx.jurisdiction} is not one of ${rule.jurisdictions.join(', ')}`);
65
+ case 'effective': {
66
+ if (ctx.asOf == null)
67
+ return unresolved('no evaluation date supplied for an effective-date rule');
68
+ const day = dayOf(ctx.asOf);
69
+ if (day == null)
70
+ return unresolved(`the evaluation date ${ctx.asOf} is not a date`);
71
+ if (rule.from != null && day < rule.from)
72
+ return notApplicable(`not effective until ${rule.from}`);
73
+ if (rule.until != null && day > rule.until)
74
+ return notApplicable(`no longer effective after ${rule.until}`);
75
+ return applies();
76
+ }
77
+ case 'threshold': {
78
+ const read = thresholdValue(ctx.values?.[rule.field], rule.unit);
79
+ if ('reason' in read)
80
+ return unresolved(`${rule.field} ${read.reason}, so the threshold cannot be decided`);
81
+ const v = read.value;
82
+ const holds = rule.operator === 'gt' ? v > rule.value : rule.operator === 'gte' ? v >= rule.value : rule.operator === 'lt' ? v < rule.value : rule.operator === 'lte' ? v <= rule.value : v === rule.value;
83
+ return holds ? applies() : notApplicable(`${rule.field} ${v}${rule.unit == null ? '' : ` ${rule.unit}`} is not ${rule.operator} ${rule.value}`);
84
+ }
85
+ case 'unresolved':
86
+ return unresolved(`${rule.reason}${rule.source == null ? '' : ` (${rule.source})`}`);
87
+ default:
88
+ return unresolved(`rule ${String(rule.rule)} is not one this evaluator implements`);
89
+ }
90
+ }
91
+ /** The key under which a record declares fields inapplicable, and the shape of each declaration. */
92
+ export const INAPPLICABLE_FIELDS_KEY = 'inapplicableFields';
93
+ /** The declarations a payload carries under `inapplicableFields`, as field keys; malformed entries are ignored, never read as a declaration. */
94
+ export function declaredInapplicable(payload) {
95
+ const raw = payload?.[INAPPLICABLE_FIELDS_KEY];
96
+ if (!Array.isArray(raw))
97
+ return [];
98
+ return raw.filter((d) => d != null && typeof d === 'object' && typeof d.field === 'string' && typeof d.reason === 'string' && d.reason.trim() !== '').map((d) => d.field);
99
+ }
100
+ /**
101
+ * A field's applicability under a context: a declaration under
102
+ * `inapplicableFields` answers not-applicable with the reason `declared`
103
+ * only where the rule would otherwise be unresolved or conditional, so a
104
+ * declaration cannot switch off a field that applies unconditionally; the
105
+ * rule answers otherwise.
106
+ */
107
+ export function evaluateFieldApplicability(field, ctx = {}) {
108
+ const result = evaluateApplicability(field.applicability, ctx);
109
+ if (result.outcome !== 'unresolved' || !(ctx.declaredNotApplicable ?? []).includes(field.key))
110
+ return result;
111
+ return { outcome: 'not-applicable', reasons: ['declared: the record declares the field inapplicable under inapplicableFields'] };
112
+ }
113
+ /**
114
+ * The fields of a version 1 or version 2 manifest under a context: what
115
+ * applies, what does not, and what is unresolved with its reasons. The
116
+ * version 1 `fieldsFor` remains the reader for version 1 manifests with a
117
+ * bare category; this one takes the whole context.
118
+ */
119
+ export function fieldsForV2(manifest, ctx = {}) {
120
+ const result = { applies: [], notApplicable: [], unresolved: [] };
121
+ for (const field of manifest.fields) {
122
+ const r = evaluateFieldApplicability(field, ctx);
123
+ if (r.outcome === 'applies')
124
+ result.applies.push(field);
125
+ else if (r.outcome === 'not-applicable')
126
+ result.notApplicable.push(field);
127
+ else
128
+ result.unresolved.push({ field, reasons: r.reasons });
129
+ }
130
+ return result;
131
+ }
132
+ const CAPTURED_AT_REGISTRATION = ['form', 'brand', 'platform'];
133
+ function present(payload, key) {
134
+ const value = payload[key];
135
+ if (value === undefined || value === null || value === '')
136
+ return false;
137
+ if (Array.isArray(value) && value.length === 0)
138
+ return false;
139
+ return true;
140
+ }
141
+ /**
142
+ * Which required fields a payload lacks under a context, on three separate
143
+ * lists. A field whose applicability is unresolved is never missing and never
144
+ * satisfied; a field whose requirement status is anticipated, not to be
145
+ * displayed or under review is deferred and never blocks, so an adopter can
146
+ * keep incomplete draft data without a false failure or a false pass. A
147
+ * field the payload declares inapplicable under `inapplicableFields` is
148
+ * not-applicable where it would otherwise be unresolved.
149
+ */
150
+ export function missingRequiredV2(manifest, payload, ctx = {}) {
151
+ const result = { missing: [], unresolved: [], deferred: [] };
152
+ // The payload's own declarations, unless the caller supplied the list.
153
+ const effective = ctx.declaredNotApplicable == null ? { ...ctx, declaredNotApplicable: declaredInapplicable(payload) } : ctx;
154
+ for (const field of manifest.fields) {
155
+ if (field.obligation !== 'required' || present(payload, field.key))
156
+ continue;
157
+ if (isFieldV2(field) && ['anticipated', 'not-to-be-displayed', 'needs-review'].includes(field.requirement.status)) {
158
+ result.deferred.push({ field, status: field.requirement.status });
159
+ continue;
160
+ }
161
+ const r = evaluateFieldApplicability(field, effective);
162
+ if (r.outcome === 'not-applicable')
163
+ continue;
164
+ if (r.outcome === 'unresolved') {
165
+ result.unresolved.push({ field, reasons: r.reasons });
166
+ continue;
167
+ }
168
+ if (CAPTURED_AT_REGISTRATION.includes(field.provenance.capture))
169
+ result.missing.push(field);
170
+ }
171
+ return result;
172
+ }
173
+ /** The category value a payload names for a manifest, read at the manifest's declared category key. */
174
+ export function categoryOf(manifest, payload) {
175
+ const key = manifest.applicability.categoryKey;
176
+ if (key == null || payload == null)
177
+ return undefined;
178
+ const value = payload[key];
179
+ return typeof value === 'string' ? value : undefined;
180
+ }
181
+ //# sourceMappingURL=applicability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applicability.js","sourceRoot":"","sources":["../src/applicability.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ export declare const BASELINE_ID = "native-baseline@1";
2
+ /** The second recommended baseline: record version 2 with the managed-custody profile (conformance/baseline-native-2.json). */
3
+ export declare const BASELINE_ID_2 = "native-baseline@2";
4
+ export declare const BASELINE_IDS: readonly ["native-baseline@1", "native-baseline@2"];
5
+ export type SelectionPurpose = 'read' | 'write' | 'claim';
6
+ export interface DeploymentDeclaration {
7
+ operators?: number;
8
+ discovery?: 'none' | 'ship-slap' | 'static-peers';
9
+ gasp?: boolean;
10
+ }
11
+ export interface ProfileSelection {
12
+ baseline: string;
13
+ industry?: string;
14
+ exchange?: string[];
15
+ operator?: string;
16
+ deployment?: DeploymentDeclaration;
17
+ /** read: verify what exists; write: issue new states or claims; claim: state conformance to the selected profiles. */
18
+ purpose: SelectionPurpose;
19
+ }
20
+ export type SelectionConflictCode = 'baseline-unknown' | 'industry-unknown' | 'industry-superseded' | 'industry-draft' | 'exchange-unknown' | 'exchange-duplicate' | 'exchange-proposed' | 'exchange-artefacts-unpinned' | 'operator-unknown' | 'operator-proposed' | 'operator-single-with-federation-options' | 'operator-federation-needs-two' | 'operator-federation-without-discovery';
21
+ export interface SelectionResult {
22
+ ok: boolean;
23
+ conflicts: Array<{
24
+ code: SelectionConflictCode;
25
+ detail: string;
26
+ }>;
27
+ notes: string[];
28
+ }
29
+ export declare function checkSelection(selection: ProfileSelection): SelectionResult;
30
+ //# sourceMappingURL=combinations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"combinations.d.ts","sourceRoot":"","sources":["../src/combinations.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,WAAW,sBAAsB,CAAA;AAC9C,+HAA+H;AAC/H,eAAO,MAAM,aAAa,sBAAsB,CAAA;AAChD,eAAO,MAAM,YAAY,qDAAwC,CAAA;AAEjE,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAA;AAEzD,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,cAAc,CAAA;IACjD,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,qBAAqB,CAAA;IAClC,sHAAsH;IACtH,OAAO,EAAE,gBAAgB,CAAA;CAC1B;AAED,MAAM,MAAM,qBAAqB,GAC7B,kBAAkB,GAClB,kBAAkB,GAClB,qBAAqB,GACrB,gBAAgB,GAChB,kBAAkB,GAClB,oBAAoB,GACpB,mBAAmB,GACnB,6BAA6B,GAC7B,kBAAkB,GAClB,mBAAmB,GACnB,yCAAyC,GACzC,+BAA+B,GAC/B,uCAAuC,CAAA;AAE3C,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAA;IACX,SAAS,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,qBAAqB,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACjE,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,gBAAgB,GAAG,eAAe,CAoE3E"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Profile combinations (`spec/conformance.md` §4, `spec/profiles.md`): an
3
+ * industry profile says what a passport carries, an exchange profile how a
4
+ * credential travels beside it, an operator profile how an index is run. They
5
+ * are selected together, and some selections contradict themselves: a new
6
+ * state under a superseded version, a conformance claim on a proposed profile
7
+ * whose artefacts were never pinned, a single operator declaring peers, a
8
+ * federation of one. `checkSelection` names every contradiction rather than
9
+ * choosing for the caller, and passes with notes when the selection is only
10
+ * unusual.
11
+ */
12
+ import { EXCHANGE_PROFILE_IDS, OPERATOR_PROFILE_IDS, PROFILE_IDS, readExchangeProfile, readOperatorProfile } from './index.js';
13
+ import { isManifestV2, readManifestAny } from './manifest-v2.js';
14
+ export const BASELINE_ID = 'native-baseline@1';
15
+ /** The second recommended baseline: record version 2 with the managed-custody profile (conformance/baseline-native-2.json). */
16
+ export const BASELINE_ID_2 = 'native-baseline@2';
17
+ export const BASELINE_IDS = [BASELINE_ID, BASELINE_ID_2];
18
+ export function checkSelection(selection) {
19
+ const conflicts = [];
20
+ const notes = [];
21
+ const conflict = (code, detail) => { conflicts.push({ code, detail }); };
22
+ if (!BASELINE_IDS.includes(selection.baseline))
23
+ conflict('baseline-unknown', `${selection.baseline} is not a baseline this catalogue knows; the baselines are ${BASELINE_IDS.join(' and ')}`);
24
+ if (selection.industry != null) {
25
+ if (!PROFILE_IDS.includes(selection.industry)) {
26
+ conflict('industry-unknown', `${selection.industry} is not an industry profile in this catalogue`);
27
+ }
28
+ else {
29
+ const manifest = readManifestAny(selection.industry);
30
+ if (manifest.status === 'superseded') {
31
+ if (selection.purpose === 'read')
32
+ notes.push(`${manifest.profile} is superseded by ${manifest.supersededBy}; states that declare it decode under it and are never reinterpreted`);
33
+ else
34
+ conflict('industry-superseded', `${manifest.profile} is superseded by ${manifest.supersededBy}; a new state or claim is issued under the current version`);
35
+ }
36
+ else if (manifest.status === 'draft') {
37
+ // A draft successor is opt-in: a deployment may read and write under
38
+ // it by explicit version, and is told so; a conformance claim rests on
39
+ // the current version until the reviewed cutover marks it superseded.
40
+ const of = isManifestV2(manifest) && manifest.succession != null ? manifest.succession.of : 'the current version';
41
+ if (selection.purpose === 'claim')
42
+ conflict('industry-draft', `${manifest.profile} is a draft successor to ${of}; a conformance claim rests on the current version`);
43
+ else
44
+ notes.push(`${manifest.profile} is a draft: opt-in successor to ${of}, not yet the current version; a conformance claim rests on the current version`);
45
+ }
46
+ }
47
+ }
48
+ const seen = new Set();
49
+ for (const id of selection.exchange ?? []) {
50
+ if (seen.has(id)) {
51
+ conflict('exchange-duplicate', `${id} is selected twice`);
52
+ continue;
53
+ }
54
+ seen.add(id);
55
+ if (!EXCHANGE_PROFILE_IDS.includes(id)) {
56
+ conflict('exchange-unknown', `${id} is not an exchange profile in this catalogue`);
57
+ continue;
58
+ }
59
+ const profile = readExchangeProfile(id);
60
+ const unpinned = (profile.artefacts ?? []).filter((a) => a.retrieval === 'not-retrieved').map((a) => a.id);
61
+ if (selection.purpose === 'claim') {
62
+ if (profile.status !== 'current') {
63
+ conflict('exchange-proposed', `${id} is ${profile.status}; no conformance claim rests on a profile that is not current`);
64
+ if (unpinned.length > 0)
65
+ conflict('exchange-artefacts-unpinned', `${id} has artefacts not retrieved and pinned: ${unpinned.join(', ')}`);
66
+ }
67
+ else if (unpinned.length > 0) {
68
+ // A current profile with an upstream artefact nobody could retrieve
69
+ // (the ledger's unassessed rows) supports the implemented-subset claim
70
+ // and never the full one; the ledger's claim gate is where that split
71
+ // is enforced, and the note points at it.
72
+ notes.push(`${id}: the claim covers the implemented subset; artefacts not retrieved (${unpinned.join(', ')}) keep the full-conformance claim blocked in the ledger`);
73
+ }
74
+ }
75
+ else if (profile.status !== 'current' || unpinned.length > 0) {
76
+ notes.push(`${id} is ${profile.status}${unpinned.length > 0 ? ` with unpinned artefacts (${unpinned.join(', ')})` : ''}; usable for a pilot, not for a claim`);
77
+ }
78
+ }
79
+ if (selection.operator != null) {
80
+ if (!OPERATOR_PROFILE_IDS.includes(selection.operator)) {
81
+ conflict('operator-unknown', `${selection.operator} is not an operator profile in this catalogue`);
82
+ }
83
+ else {
84
+ const profile = readOperatorProfile(selection.operator);
85
+ const d = selection.deployment ?? {};
86
+ if (selection.operator === 'single-operator@1') {
87
+ if ((d.operators ?? 1) > 1 || d.gasp === true || (d.discovery != null && d.discovery !== 'none')) {
88
+ conflict('operator-single-with-federation-options', 'single-operator@1 declares one administration with discovery and synchronisation off; peers, GASP or advertisement belong to federated-operators@1');
89
+ }
90
+ }
91
+ else {
92
+ if ((d.operators ?? 1) < 2)
93
+ conflict('operator-federation-needs-two', 'federated-operators@1 needs at least two independently administered operators; one operator is single-operator@1');
94
+ if (d.discovery == null || d.discovery === 'none')
95
+ conflict('operator-federation-without-discovery', 'federated-operators@1 needs SHIP and SLAP or a declared static-peer profile so operators find each other; discovery none is single-operator@1');
96
+ if (selection.purpose === 'claim' && profile.status !== 'current')
97
+ conflict('operator-proposed', `${selection.operator} is ${profile.status}; the independently administered exercise has not been run, so no claim rests on it`);
98
+ }
99
+ }
100
+ }
101
+ return { ok: conflicts.length === 0, conflicts, notes };
102
+ }
103
+ //# sourceMappingURL=combinations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"combinations.js","sourceRoot":"","sources":["../src/combinations.ts"],"names":[],"mappings":"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"}