@real-life/trust-protocol 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.
Files changed (58) hide show
  1. package/README.md +99 -0
  2. package/dist/core.d.ts +32 -0
  3. package/dist/core.d.ts.map +1 -0
  4. package/dist/core.js +312 -0
  5. package/dist/core.js.map +1 -0
  6. package/dist/crypto.d.ts +32 -0
  7. package/dist/crypto.d.ts.map +1 -0
  8. package/dist/crypto.js +114 -0
  9. package/dist/crypto.js.map +1 -0
  10. package/dist/delivery.d.ts +51 -0
  11. package/dist/delivery.d.ts.map +1 -0
  12. package/dist/delivery.js +170 -0
  13. package/dist/delivery.js.map +1 -0
  14. package/dist/encounter.d.ts +63 -0
  15. package/dist/encounter.d.ts.map +1 -0
  16. package/dist/encounter.js +56 -0
  17. package/dist/encounter.js.map +1 -0
  18. package/dist/identity.d.ts +25 -0
  19. package/dist/identity.d.ts.map +1 -0
  20. package/dist/identity.js +87 -0
  21. package/dist/identity.js.map +1 -0
  22. package/dist/index.d.ts +6 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +29 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/probe/continuity.d.ts +99 -0
  27. package/dist/probe/continuity.d.ts.map +1 -0
  28. package/dist/probe/continuity.js +303 -0
  29. package/dist/probe/continuity.js.map +1 -0
  30. package/dist/probe/deps.d.ts +61 -0
  31. package/dist/probe/deps.d.ts.map +1 -0
  32. package/dist/probe/deps.js +54 -0
  33. package/dist/probe/deps.js.map +1 -0
  34. package/dist/probe/introduce.d.ts +70 -0
  35. package/dist/probe/introduce.d.ts.map +1 -0
  36. package/dist/probe/introduce.js +295 -0
  37. package/dist/probe/introduce.js.map +1 -0
  38. package/dist/probe/membership.d.ts +90 -0
  39. package/dist/probe/membership.d.ts.map +1 -0
  40. package/dist/probe/membership.js +450 -0
  41. package/dist/probe/membership.js.map +1 -0
  42. package/dist/probe/trust.d.ts +116 -0
  43. package/dist/probe/trust.d.ts.map +1 -0
  44. package/dist/probe/trust.js +345 -0
  45. package/dist/probe/trust.js.map +1 -0
  46. package/dist/probe.d.ts +8 -0
  47. package/dist/probe.d.ts.map +1 -0
  48. package/dist/probe.js +41 -0
  49. package/dist/probe.js.map +1 -0
  50. package/dist/schemas.d.ts +2 -0
  51. package/dist/schemas.d.ts.map +1 -0
  52. package/dist/schemas.js +51 -0
  53. package/dist/schemas.js.map +1 -0
  54. package/dist/unicode15.d.ts +8 -0
  55. package/dist/unicode15.d.ts.map +1 -0
  56. package/dist/unicode15.js +55 -0
  57. package/dist/unicode15.js.map +1 -0
  58. package/package.json +55 -0
package/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # @real-life/trust-protocol
2
+
3
+ **The Real Life Trust Protocol (RLTP), as running code.** Trust rooted in
4
+ encounters between people: two humans meet, recognize each other, and record
5
+ that recognition as verifiable credentials. Cryptography proves freshness and
6
+ authorship; only a human can witness a human.
7
+
8
+ This package is the **executable form of the specification** — it lives beside
9
+ the schemas and the test vectors it must reproduce byte-for-byte. Published by
10
+ the [Real Life Organisation](https://real-life.org) under CC BY 4.0.
11
+
12
+ - Specification, schemas and vectors: <https://rltp.real-life.org>
13
+ - Zero dependencies. WebCrypto only (Ed25519, X25519, HKDF, AES-256-GCM).
14
+ - Works in browsers, Node ≥ 20, Deno, Bun. No DOM, no storage, no network:
15
+ the library computes and verifies, the host decides where bytes live.
16
+
17
+ ## Install
18
+
19
+ ```sh
20
+ npm i @real-life/trust-protocol
21
+ ```
22
+
23
+ ## The modules mirror the specification
24
+
25
+ Each module answers to one document, so a reader of the spec knows where to
26
+ look in the code:
27
+
28
+ | Module | Specification | What it carries |
29
+ |---|---|---|
30
+ | `core` | across all layers | The canonical form: JCS serialization, multibase encodings, digest equality over *decoded* bytes, whole-second timestamps, calendar validity — and the JSON-Schema subset validator the conformance runner uses. |
31
+ | `crypto` | — (primitives) | Hashes, HKDF, key pairs, did:key and multikey renderings, ECDH, and the eddsa-jcs-2022 Data Integrity proof every layer signs with. Answers *how*, never *what*. |
32
+ | `identity` | Identity Layer | One root seed, every context derived — community anchor, pair anchor per relationship, member anchor per group. Contexts never link without their holder's deliberate act. |
33
+ | `encounter` | Encounter Layer | The ceremony under fresh-always pair anchors: challenges, contact cards, the enactment binding both sides compute independently, encounter credentials. |
34
+ | `delivery` | Delivery Contract | The sealed envelope, and the receive chain in its declared order — size bound *before* decryption, envelope form, decryption, parse and digest over the canonical form, completed-effect cache. |
35
+
36
+ Everything is re-exported from the package root; the table is a map, not an
37
+ import instruction.
38
+
39
+ ```ts
40
+ import { labeledContext, signCard, seal, sameDigest } from '@real-life/trust-protocol'
41
+ ```
42
+
43
+ ## Two entry points
44
+
45
+ ```ts
46
+ import { … } from '@real-life/trust-protocol' // wire-normative core
47
+ import { introduce, trust, continuity, membership }
48
+ from '@real-life/trust-protocol/probe' // draft — will change
49
+ ```
50
+
51
+ The **`/probe` subpath is deliberate.** Its modules exercise the converged
52
+ *semantics* of their layers, but their transport shapes carry `@probe` and
53
+ are **not wire-normative**: mediated introductions over a rendezvous drop,
54
+ the explicit trust act with the blinded star, §6a continuity (chains
55
+ instead of duplicates), and group membership (founding, VIC invite,
56
+ admission, vouching). Experiment with them; do not treat their wire forms
57
+ as an interoperability target. A subpath import is a decision someone has
58
+ to make — nothing behind it can be reached by accident.
59
+
60
+ **The redelivery contract of probe receivers:** a receiver's inbound
61
+ effect is complete the moment it returns `handled: true` without `error` —
62
+ that delivery is cached and answers `duplicate-known` forever after.
63
+ Outbound work a receiver triggers (star refreshes, continuity mappings)
64
+ is built per recipient and never discards partial results; what failed is
65
+ named in `outboundError` / `outbound.failures`, and **redelivering the
66
+ inbound document is not the retry path** — re-invoking the producing call
67
+ (e.g. `trust.starRefreshAll`) is, and it is the host application's job.
68
+
69
+ ## Versions
70
+
71
+ This package uses its own semver; the specification uses castings. Each
72
+ release states, per module, whose **wire forms** it implements — and what
73
+ it deliberately does not:
74
+
75
+ | Module (0.1.x) | Casting | Implemented | Not in this package |
76
+ |---|---|---|---|
77
+ | `identity` | Identity 0.50 | context derivation under the closed label registry (§6.1, unchanged since 0.13) with the ordered persona pipeline (§6.2, Unicode 15.0 pinned) | recovery derivation (§5.3), service identities (§7), carrier relationship (§7a), the label register and its state |
78
+ | `encounter` | Encounter 0.29 — wire `0.25` (`rltp-card/0.25`, `encounter-scan@0.25`) | challenges, both card profiles, the enactment binding, encounter credentials | the ceremony state machine, acceptance rules, ack deadlines |
79
+ | `delivery` | Delivery 0.64 | the sealed envelope (§5) and the generic receive stages 1–4 | the type-specific stages, residual bookkeeping, transport adapters |
80
+ | `core`, `crypto` | cross-layer | canonical form, digest equality, timestamps, validator; primitives + `eddsa-jcs-2022` proof | — |
81
+ | `/probe` | Network Visibility · Membership Tasks + Access | introductions, trust act + blinded star, §6a continuity, group membership — semantics of the running castings, transport shapes `@probe` | any wire-form stability whatsoever |
82
+
83
+ Persona-name validation is **pinned to Unicode 15.0** as Identity §6.2
84
+ requires: the repertoire ships with the package (`unicode15.ts`, ~5 kB of
85
+ ranges) and no platform Unicode data is consulted — the same name derives
86
+ the same anchor on every runtime, whatever ICU it carries.
87
+
88
+ ## The contract: the vectors
89
+
90
+ A version that does not reproduce `vectors/` byte-for-byte is not a valid
91
+ version — the conformance runner checks every cryptographic claim, and every
92
+ negative case must fail at its declared stage. If you implement RLTP in
93
+ another language, those same vectors are how you check yourself; you do not
94
+ need this package to do it.
95
+
96
+ ## License
97
+
98
+ [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) — specification and
99
+ reference implementation alike.
package/dist/core.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ export type Json = string | number | boolean | null | Json[] | {
2
+ [k: string]: Json;
3
+ };
4
+ /** RFC 8785 subset for the ASCII I-JSON forms this stack ships. */
5
+ export declare const jcs: (o: unknown) => string;
6
+ export declare const B58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
7
+ export declare function base58(bytes: Uint8Array): string;
8
+ export declare function fromBase58(s: string): Uint8Array | null;
9
+ export declare const b64uOf: (bytes: Uint8Array) => string;
10
+ export declare const fromB64u: (s: string) => Uint8Array;
11
+ export declare const toU: (v: unknown) => string | null;
12
+ export declare const sameDigest: (a: unknown, b: unknown) => boolean;
13
+ /** Whole-second ISO rendering — the timestamp form every artifact carries. */
14
+ export declare const iso: (ms: number) => string;
15
+ export declare const tsec: (v: string | number) => number;
16
+ export declare const calOK: (t: unknown) => boolean;
17
+ export type Schema = boolean | {
18
+ [k: string]: any;
19
+ };
20
+ export type SchemaMap = Record<string, Schema>;
21
+ export interface Validator {
22
+ validate: (data: unknown, schema: Schema, root: Schema, path?: string) => string[];
23
+ resolveRef: (ref: string, root: Schema) => {
24
+ node: Schema;
25
+ root: Schema;
26
+ };
27
+ SCHEMAS: SchemaMap;
28
+ BYID: SchemaMap;
29
+ }
30
+ /** Builds a validator bound to one schema map ({ filename → parsed schema }). */
31
+ export declare function makeValidator(SCHEMAS: SchemaMap): Validator;
32
+ //# sourceMappingURL=core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,IAAI,EAAE,GAAG;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAA;AAEpF,mEAAmE;AACnE,eAAO,MAAM,GAAG,GAAI,GAAG,OAAO,KAAG,MA0ChC,CAAA;AAGD,eAAO,MAAM,GAAG,+DAA+D,CAAA;AAC/E,wBAAgB,MAAM,CAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAOjD;AACD,wBAAgB,UAAU,CAAE,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAWxD;AACD,eAAO,MAAM,MAAM,GAAI,OAAO,UAAU,KAAG,MAO1C,CAAA;AACD,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,KAAG,UAMpC,CAAA;AAMD,eAAO,MAAM,GAAG,GAAI,GAAG,OAAO,KAAG,MAAM,GAAG,IAgBzC,CAAA;AACD,eAAO,MAAM,UAAU,GAAI,GAAG,OAAO,EAAE,GAAG,OAAO,KAAG,OAAqE,CAAA;AAEzH,8EAA8E;AAC9E,eAAO,MAAM,GAAG,GAAI,IAAI,MAAM,KAAG,MAA8D,CAAA;AAI/F,eAAO,MAAM,IAAI,GAAI,GAAG,MAAM,GAAG,MAAM,KAAG,MAA+E,CAAA;AAGzH,eAAO,MAAM,KAAK,GAAI,GAAG,OAAO,KAAG,OAKlC,CAAA;AAKD,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CAAA;AACnD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAC9C,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,MAAM,EAAE,CAAA;IAClF,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IACzE,OAAO,EAAE,SAAS,CAAA;IAClB,IAAI,EAAE,SAAS,CAAA;CAChB;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAE,OAAO,EAAE,SAAS,GAAG,SAAS,CAiF5D"}
package/dist/core.js ADDED
@@ -0,0 +1,312 @@
1
+ // core — the form layer: the canonical rules every RLTP artifact obeys.
2
+ //
3
+ // One implementation of the canonical form (JCS subset, multibase
4
+ // encodings, digest equality over DECODED bytes, timestamp
5
+ // normalization) and the JSON-Schema subset validator. The conformance
6
+ // runner, the reference engine and every simulator delegate here.
7
+ //
8
+ // Predicates exist ONCE — that is the point. Weakening a rule here fails
9
+ // the conformance runner's self-tests rather than silently changing what
10
+ // some user interface accepts.
11
+ //
12
+ // Dependency-free and environment-free: no node:*, no DOM, no WebCrypto.
13
+ // Everything here is synchronous and pure.
14
+ /** RFC 8785 subset for the ASCII I-JSON forms this stack ships. */
15
+ export const jcs = (o) => {
16
+ if (o === undefined)
17
+ throw new Error('jcs: undefined is not serializable');
18
+ // RFC 8785 operates on Unicode strings — a lone surrogate is not one,
19
+ // and a conformant implementation MUST error rather than canonicalize
20
+ // it (review 3, B-1: divergent digests between implementations)
21
+ if (typeof o === 'string' && !o.isWellFormed())
22
+ throw new Error('jcs: lone surrogate');
23
+ if (typeof o === 'number' && !Number.isFinite(o))
24
+ throw new Error('jcs: non-finite number');
25
+ if (Array.isArray(o)) {
26
+ // a sparse array is not a JSON value: map() skips holes and join()
27
+ // erases them, so [empty] and [] would COLLIDE on one digest
28
+ // (review 4, B-3) — reject instead of silently canonicalizing
29
+ for (let i = 0; i < o.length; i++)
30
+ if (!(i in o))
31
+ throw new Error('jcs: sparse array');
32
+ // non-index own properties (arr.x = 1) and symbol keys would be
33
+ // silently DROPPED and collide with the bare array (review 6, B-2)
34
+ if (Object.getOwnPropertyNames(o).length !== o.length + 1 /* 'length' itself */ || Object.getOwnPropertySymbols(o).length > 0)
35
+ throw new Error('jcs: array with extra own properties');
36
+ return '[' + o.map(jcs).join(',') + ']';
37
+ }
38
+ if (o && typeof o === 'object') {
39
+ // only PLAIN objects are JSON values: a Date, Map or class instance
40
+ // would serialize by its enumerable keys alone and collide with {}
41
+ // (review 5, B-3) — reject at the edge of the digest domain
42
+ const proto = Object.getPrototypeOf(o);
43
+ if (proto !== null && proto !== Object.prototype)
44
+ throw new Error('jcs: not a plain JSON object');
45
+ // symbol-keyed own properties would be silently dropped — the object
46
+ // would collide with its symbol-free twin (review 6, B-2)
47
+ if (Object.getOwnPropertySymbols(o).length > 0)
48
+ throw new Error('jcs: object with symbol keys');
49
+ // non-enumerable own properties are invisible to Object.keys and
50
+ // would collide with the bare twin (review 7, B-4)
51
+ if (Object.getOwnPropertyNames(o).length !== Object.keys(o).length)
52
+ throw new Error('jcs: object with non-enumerable own properties');
53
+ const rec = o;
54
+ return '{' + Object.keys(rec).sort().map((k) => {
55
+ if (rec[k] === undefined)
56
+ throw new Error('jcs: undefined property ' + k);
57
+ if (!k.isWellFormed())
58
+ throw new Error('jcs: lone surrogate in key');
59
+ return JSON.stringify(k) + ':' + jcs(rec[k]);
60
+ }).join(',') + '}';
61
+ }
62
+ const s = JSON.stringify(o);
63
+ // M-4 (review 1): symbols and functions stringify to undefined — the
64
+ // invariant "jcs returns a string" is enforced at the API edge, not
65
+ // silently violated downstream in a digest.
66
+ if (typeof s !== 'string')
67
+ throw new Error('jcs: value is not JSON-representable');
68
+ return s;
69
+ };
70
+ // ── multibase encodings ─────────────────────────────────────────────────
71
+ export const B58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
72
+ export function base58(bytes) {
73
+ let n = 0n;
74
+ for (const b of bytes)
75
+ n = n * 256n + BigInt(b);
76
+ let out = '';
77
+ while (n > 0n) {
78
+ out = B58[Number(n % 58n)] + out;
79
+ n /= 58n;
80
+ }
81
+ for (const b of bytes) {
82
+ if (b === 0)
83
+ out = '1' + out;
84
+ else
85
+ break;
86
+ }
87
+ return out;
88
+ }
89
+ export function fromBase58(s) {
90
+ let n = 0n;
91
+ for (const c of s) {
92
+ const i = B58.indexOf(c);
93
+ if (i < 0)
94
+ return null;
95
+ n = n * 58n + BigInt(i);
96
+ }
97
+ const out = [];
98
+ while (n > 0n) {
99
+ out.unshift(Number(n % 256n));
100
+ n /= 256n;
101
+ }
102
+ for (const c of s) {
103
+ if (c === '1')
104
+ out.unshift(0);
105
+ else
106
+ break;
107
+ }
108
+ return new Uint8Array(out);
109
+ }
110
+ export const b64uOf = (bytes) => {
111
+ let s = '';
112
+ for (const b of bytes)
113
+ s += String.fromCharCode(b);
114
+ const btoaFn = typeof btoa === 'function'
115
+ ? btoa
116
+ : (x) => globalThis.Buffer.from(x, 'binary').toString('base64');
117
+ return btoaFn(s).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
118
+ };
119
+ export const fromB64u = (s) => {
120
+ const atobFn = typeof atob === 'function'
121
+ ? atob
122
+ : (x) => globalThis.Buffer.from(x, 'base64').toString('binary');
123
+ const bin = atobFn(s.replace(/-/g, '+').replace(/_/g, '/'));
124
+ return Uint8Array.from(bin, (c) => c.charCodeAt(0));
125
+ };
126
+ // ── digest equality over decoded multihash bytes (Encounter 2.3) ────────
127
+ // toU: strict multibase bridge — prefix, sha2-256 multihash header and
128
+ // length, AND canonical-form round-trip; returns the canonical u rendering
129
+ // or null. A u input is checked for header/length too.
130
+ export const toU = (v) => {
131
+ if (typeof v !== 'string' || v.length < 2)
132
+ return null;
133
+ let bytes;
134
+ if (v[0] === 'u') {
135
+ try {
136
+ bytes = fromB64u(v.slice(1));
137
+ }
138
+ catch {
139
+ return null;
140
+ }
141
+ // canonical base64url only — padding or non-zero trailing bits make a
142
+ // DIFFERENT string decode to the same bytes, and equality is decided
143
+ // over bytes; without this check 16 spellings of one digest verify
144
+ // (B-1, review 1; the shipped reject vectors demand exactly this).
145
+ if (bytes && 'u' + b64uOf(bytes) !== v)
146
+ return null;
147
+ }
148
+ else if (v[0] === 'z') {
149
+ bytes = fromBase58(v.slice(1));
150
+ if (bytes && 'z' + base58(bytes) !== v)
151
+ return null; // canonical base58btc only
152
+ }
153
+ else
154
+ return null;
155
+ if (!bytes || bytes.length !== 34 || bytes[0] !== 0x12 || bytes[1] !== 0x20)
156
+ return null;
157
+ return 'u' + b64uOf(bytes);
158
+ };
159
+ export const sameDigest = (a, b) => { const na = toU(a); return na !== null && na === toU(b); };
160
+ /** Whole-second ISO rendering — the timestamp form every artifact carries. */
161
+ export const iso = (ms) => new Date(ms).toISOString().replace(/\.\d{3}Z$/, 'Z');
162
+ // ── timestamps (Encounter 2.3) ──────────────────────────────────────────
163
+ // tsec: whole-second truncation of EVERY comparison operand (incl. now).
164
+ export const tsec = (v) => Math.floor((typeof v === 'number' ? v : Date.parse(v)) / 1000) * 1000;
165
+ // calOK: calendar-valid round-trip AND the ≤3-fractional-digit cap —
166
+ // Date.parse silently normalizes impossible dates, so demand the round-trip.
167
+ export const calOK = (t) => {
168
+ if (typeof t !== 'string')
169
+ return false;
170
+ if (!/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]{1,3})?Z$/.test(t))
171
+ return false;
172
+ const d = new Date(t);
173
+ return !Number.isNaN(d.getTime()) && d.toISOString().slice(0, 19) === t.slice(0, 19);
174
+ };
175
+ /** Builds a validator bound to one schema map ({ filename → parsed schema }). */
176
+ export function makeValidator(SCHEMAS) {
177
+ const BYID = {};
178
+ for (const s of Object.values(SCHEMAS))
179
+ if (typeof s === 'object' && s.$id)
180
+ BYID[s.$id] = s;
181
+ const walk = (node, parts) => { let n = node; for (const p of parts)
182
+ n = n[p]; return n; };
183
+ const resolveRef = (ref, root) => {
184
+ if (ref.startsWith('#'))
185
+ return { node: walk(root, ref.slice(2).split('/')), root };
186
+ const [base, frag] = ref.split('#');
187
+ const target = SCHEMAS[base] || BYID[base];
188
+ if (!target)
189
+ throw new Error('unresolvable $ref ' + ref);
190
+ if (!frag)
191
+ return { node: target, root: target };
192
+ return { node: walk(target, frag.slice(1).split('/')), root: target };
193
+ };
194
+ function validate(data, schema, root, path = '$') {
195
+ const errs = [];
196
+ const E = (m) => errs.push(`${path}: ${m}`);
197
+ if (schema === false) {
198
+ E('schema false');
199
+ return errs;
200
+ }
201
+ if (schema === true || schema == null)
202
+ return errs;
203
+ if (schema.$ref) {
204
+ const { node, root: r } = resolveRef(schema.$ref, root);
205
+ return validate(data, node, r, path);
206
+ }
207
+ const anyData = data;
208
+ if (schema.const !== undefined && jcs(data) !== jcs(schema.const))
209
+ E('const mismatch');
210
+ if (schema.enum && !schema.enum.some((v) => jcs(v) === jcs(data)))
211
+ E('enum mismatch');
212
+ if (schema.type) {
213
+ const t = Array.isArray(data) ? 'array' : data === null ? 'null' : typeof data;
214
+ const want = [].concat(schema.type);
215
+ const okT = want.some((w) => w === t || (w === 'integer' && t === 'number' && Number.isInteger(data)));
216
+ if (!okT) {
217
+ E(`type ${t} != ${schema.type}`);
218
+ return errs;
219
+ }
220
+ }
221
+ if (typeof data === 'string') {
222
+ if (schema.pattern && !new RegExp(schema.pattern).test(data))
223
+ E('pattern');
224
+ // JSON Schema misst Stringlänge in CODEPUNKTEN, nicht UTF-16-
225
+ // Einheiten (Review 4, M-2: 101 Emoji sind 101 Zeichen, nicht 202)
226
+ const cpLen = (schema.minLength != null || schema.maxLength != null) ? [...data].length : 0;
227
+ if (schema.minLength != null && cpLen < schema.minLength)
228
+ E('minLength');
229
+ if (schema.maxLength != null && cpLen > schema.maxLength)
230
+ E('maxLength');
231
+ }
232
+ if (Array.isArray(data)) {
233
+ if (schema.minItems != null && data.length < schema.minItems)
234
+ E('minItems');
235
+ if (schema.maxItems != null && data.length > schema.maxItems)
236
+ E('maxItems');
237
+ if (schema.uniqueItems && new Set(data.map(jcs)).size !== data.length)
238
+ E('uniqueItems');
239
+ if (schema.prefixItems) {
240
+ schema.prefixItems.forEach((ps, i) => { if (i < data.length)
241
+ errs.push(...validate(data[i], ps, root, `${path}[${i}]`)); });
242
+ if (schema.items === false && data.length > schema.prefixItems.length)
243
+ E('items false beyond prefixItems');
244
+ }
245
+ else if (schema.items !== undefined && schema.items !== true) {
246
+ data.forEach((d, i) => errs.push(...validate(d, schema.items, root, `${path}[${i}]`)));
247
+ }
248
+ if (schema.contains && !data.some((d) => validate(d, schema.contains, root, path).length === 0))
249
+ E('contains unmatched');
250
+ }
251
+ if (data && typeof data === 'object' && !Array.isArray(data)) {
252
+ const keys = Object.keys(anyData);
253
+ if (schema.minProperties != null && keys.length < schema.minProperties)
254
+ E('minProperties');
255
+ if (schema.maxProperties != null && keys.length > schema.maxProperties)
256
+ E('maxProperties');
257
+ for (const r of schema.required || [])
258
+ if (!Object.hasOwn(anyData, r))
259
+ E(`missing required ${r}`);
260
+ for (const [k, deps] of Object.entries(schema.dependentRequired || {})) {
261
+ if (Object.hasOwn(anyData, k))
262
+ for (const d of deps)
263
+ if (!Object.hasOwn(anyData, d))
264
+ E(`dependentRequired ${k}→${d}`);
265
+ }
266
+ if (schema.propertyNames)
267
+ for (const k of keys)
268
+ errs.push(...validate(k, schema.propertyNames, root, `${path}.<name:${k}>`));
269
+ for (const k of keys) {
270
+ if (schema.properties && Object.hasOwn(schema.properties, k))
271
+ errs.push(...validate(anyData[k], schema.properties[k], root, `${path}.${k}`));
272
+ else if (schema.additionalProperties === false)
273
+ E(`additionalProperty ${k}`);
274
+ else if (schema.additionalProperties && typeof schema.additionalProperties === 'object')
275
+ errs.push(...validate(anyData[k], schema.additionalProperties, root, `${path}.${k}`));
276
+ }
277
+ }
278
+ if (typeof data === 'number') {
279
+ if (schema.minimum != null && data < schema.minimum)
280
+ E('minimum');
281
+ if (schema.maximum != null && data > schema.maximum)
282
+ E('maximum');
283
+ if (schema.exclusiveMinimum != null && data <= schema.exclusiveMinimum)
284
+ E('exclusiveMinimum');
285
+ if (schema.exclusiveMaximum != null && data >= schema.exclusiveMaximum)
286
+ E('exclusiveMaximum');
287
+ if (schema.multipleOf != null && (data / schema.multipleOf) % 1 !== 0)
288
+ E('multipleOf');
289
+ }
290
+ if (schema.anyOf && !schema.anyOf.some((s2) => validate(data, s2, root, path).length === 0))
291
+ E('anyOf unmatched');
292
+ if (schema.oneOf) {
293
+ const n = schema.oneOf.filter((s2) => validate(data, s2, root, path).length === 0).length;
294
+ if (n !== 1)
295
+ E(`oneOf matched ${n}`);
296
+ }
297
+ if (schema.not !== undefined && validate(data, schema.not, root, path).length === 0)
298
+ E('not matched');
299
+ if (schema.if !== undefined) {
300
+ const hit = validate(data, schema.if, root, path).length === 0;
301
+ if (hit && schema.then !== undefined)
302
+ errs.push(...validate(data, schema.then, root, path));
303
+ if (!hit && schema.else !== undefined)
304
+ errs.push(...validate(data, schema.else, root, path));
305
+ }
306
+ for (const sub of (schema.allOf || []))
307
+ errs.push(...validate(data, sub, root, path));
308
+ return errs;
309
+ }
310
+ return { validate, resolveRef, SCHEMAS, BYID };
311
+ }
312
+ //# sourceMappingURL=core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,EAAE;AACF,kEAAkE;AAClE,2DAA2D;AAC3D,uEAAuE;AACvE,kEAAkE;AAClE,EAAE;AACF,yEAAyE;AACzE,yEAAyE;AACzE,+BAA+B;AAC/B,EAAE;AACF,yEAAyE;AACzE,2CAA2C;AAK3C,mEAAmE;AACnE,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAU,EAAU,EAAE;IACxC,IAAI,CAAC,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;IAC1E,sEAAsE;IACtE,sEAAsE;IACtE,gEAAgE;IAChE,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAE,CAA4C,CAAC,YAAY,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;IAClI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAA;IAC3F,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACrB,mEAAmE;QACnE,6DAA6D;QAC7D,8DAA8D;QAC9D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;YAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAA;QACtF,gEAAgE;QAChE,mEAAmE;QACnE,IAAI,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,qBAAqB,IAAI,MAAM,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;QACtL,OAAO,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAA;IACzC,CAAC;IACD,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC/B,oEAAoE;QACpE,mEAAmE;QACnE,4DAA4D;QAC5D,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAA;QACtC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,MAAM,CAAC,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;QACjG,qEAAqE;QACrE,0DAA0D;QAC1D,IAAI,MAAM,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;QAC/F,iEAAiE;QACjE,mDAAmD;QACnD,IAAI,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAA;QACrI,MAAM,GAAG,GAAG,CAA4B,CAAA;QACxC,OAAO,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAC7C,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,CAAC,CAAC,CAAA;YACzE,IAAI,CAAE,CAA4C,CAAC,YAAY,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAA;YAChH,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QAC9C,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAA;IACpB,CAAC;IACD,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;IAC3B,qEAAqE;IACrE,oEAAoE;IACpE,4CAA4C;IAC5C,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;IAClF,OAAO,CAAC,CAAA;AACV,CAAC,CAAA;AAED,2EAA2E;AAC3E,MAAM,CAAC,MAAM,GAAG,GAAG,4DAA4D,CAAA;AAC/E,MAAM,UAAU,MAAM,CAAE,KAAiB;IACvC,IAAI,CAAC,GAAG,EAAE,CAAA;IACV,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;IAC/C,IAAI,GAAG,GAAG,EAAE,CAAA;IACZ,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;QAAC,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;QAAC,CAAC,IAAI,GAAG,CAAA;IAAC,CAAC;IAC7D,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QAAC,IAAI,CAAC,KAAK,CAAC;YAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;;YAAM,MAAK;IAAC,CAAC;IACnE,OAAO,GAAG,CAAA;AACZ,CAAC;AACD,MAAM,UAAU,UAAU,CAAE,CAAS;IACnC,IAAI,CAAC,GAAG,EAAE,CAAA;IACV,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAClB,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QACxB,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAA;QACtB,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;IACzB,CAAC;IACD,MAAM,GAAG,GAAa,EAAE,CAAA;IACxB,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;QAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QAAC,CAAC,IAAI,IAAI,CAAA;IAAC,CAAC;IAC3D,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAAC,IAAI,CAAC,KAAK,GAAG;YAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;;YAAM,MAAK;IAAC,CAAC;IAChE,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAA;AAC5B,CAAC;AACD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,KAAiB,EAAU,EAAE;IAClD,IAAI,CAAC,GAAG,EAAE,CAAA;IACV,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;IAClD,MAAM,MAAM,GAA0B,OAAO,IAAI,KAAK,UAAU;QAC9D,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,UAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAC1E,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;AAC7E,CAAC,CAAA;AACD,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAc,EAAE;IAChD,MAAM,MAAM,GAA0B,OAAO,IAAI,KAAK,UAAU;QAC9D,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAE,UAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAC1E,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAA;IAC3D,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;AACrD,CAAC,CAAA;AAED,2EAA2E;AAC3E,uEAAuE;AACvE,2EAA2E;AAC3E,uDAAuD;AACvD,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAU,EAAiB,EAAE;IAC/C,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IACtD,IAAI,KAAwB,CAAA;IAC5B,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC;YAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,IAAI,CAAA;QAAC,CAAC;QAC1D,sEAAsE;QACtE,qEAAqE;QACrE,mEAAmE;QACnE,mEAAmE;QACnE,IAAI,KAAK,IAAI,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAA;IACrD,CAAC;SAAM,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;QACxB,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;QAC9B,IAAI,KAAK,IAAI,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAA,CAAC,2BAA2B;IACjF,CAAC;;QAAM,OAAO,IAAI,CAAA;IAClB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IACxF,OAAO,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;AAC5B,CAAC,CAAA;AACD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAU,EAAE,CAAU,EAAW,EAAE,GAAG,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,IAAI,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAA,CAAC,CAAC,CAAA;AAEzH,8EAA8E;AAC9E,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,EAAU,EAAU,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;AAE/F,2EAA2E;AAC3E,yEAAyE;AACzE,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAkB,EAAU,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAA;AACzH,qEAAqE;AACrE,6EAA6E;AAC7E,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAU,EAAW,EAAE;IAC3C,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IACvC,IAAI,CAAC,yEAAyE,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAA;IACpG,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAA;IACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AACtF,CAAC,CAAA;AAcD,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAE,OAAkB;IAC/C,MAAM,IAAI,GAAc,EAAE,CAAA;IAC1B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;QAAE,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG;YAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC3F,MAAM,IAAI,GAAG,CAAC,IAAS,EAAE,KAAe,EAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA,CAAC,CAAC,CAAA;IAC7G,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,IAAY,EAAE,EAAE;QAC/C,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAA;QACnF,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACnC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAK,CAAC,IAAI,IAAI,CAAC,IAAK,CAAC,CAAA;QAC5C,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,GAAG,GAAG,CAAC,CAAA;QACxD,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;QAChD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;IACvE,CAAC,CAAA;IACD,SAAS,QAAQ,CAAE,IAAa,EAAE,MAAc,EAAE,IAAY,EAAE,IAAI,GAAG,GAAG;QACxE,MAAM,IAAI,GAAa,EAAE,CAAA;QACzB,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,CAAC,EAAE,CAAC,CAAA;QACnD,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YAAC,CAAC,CAAC,cAAc,CAAC,CAAC;YAAC,OAAO,IAAI,CAAA;QAAC,CAAC;QACxD,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,IAAI,IAAI;YAAE,OAAO,IAAI,CAAA;QAClD,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAAC,OAAO,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;QAAC,CAAC;QAClH,MAAM,OAAO,GAAG,IAAW,CAAA;QAC3B,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;YAAE,CAAC,CAAC,gBAAgB,CAAC,CAAA;QACtF,IAAI,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC;YAAE,CAAC,CAAC,eAAe,CAAC,CAAA;QAC9F,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAChB,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,IAAI,CAAA;YAC9E,MAAM,IAAI,GAAc,EAAe,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YAC3D,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACtG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBAAC,OAAO,IAAI,CAAA;YAAC,CAAC;QAC7D,CAAC;QACD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,IAAI,MAAM,CAAC,OAAO,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,CAAC,CAAC,SAAS,CAAC,CAAA;YAC1E,8DAA8D;YAC9D,mEAAmE;YACnE,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,IAAI,IAAI,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;YAC3F,IAAI,MAAM,CAAC,SAAS,IAAI,IAAI,IAAI,KAAK,GAAG,MAAM,CAAC,SAAS;gBAAE,CAAC,CAAC,WAAW,CAAC,CAAA;YACxE,IAAI,MAAM,CAAC,SAAS,IAAI,IAAI,IAAI,KAAK,GAAG,MAAM,CAAC,SAAS;gBAAE,CAAC,CAAC,WAAW,CAAC,CAAA;QAC1E,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ;gBAAE,CAAC,CAAC,UAAU,CAAC,CAAA;YAC3E,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ;gBAAE,CAAC,CAAC,UAAU,CAAC,CAAA;YAC3E,IAAI,MAAM,CAAC,WAAW,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM;gBAAE,CAAC,CAAC,aAAa,CAAC,CAAA;YACvF,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;gBACvB,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM;oBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA,CAAC,CAAC,CAAC,CAAA;gBAC1I,IAAI,MAAM,CAAC,KAAK,KAAK,KAAK,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM;oBAAE,CAAC,CAAC,gCAAgC,CAAC,CAAA;YAC5G,CAAC;iBAAM,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;gBAC/D,IAAI,CAAC,OAAO,CAAC,CAAC,CAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YACzG,CAAC;YACD,IAAI,MAAM,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;gBAAE,CAAC,CAAC,oBAAoB,CAAC,CAAA;QACnI,CAAC;QACD,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACjC,IAAI,MAAM,CAAC,aAAa,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,aAAa;gBAAE,CAAC,CAAC,eAAe,CAAC,CAAA;YAC1F,IAAI,MAAM,CAAC,aAAa,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,aAAa;gBAAE,CAAC,CAAC,eAAe,CAAC,CAAA;YAC1F,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,IAAI,EAAE;gBAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;oBAAE,CAAC,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAA;YACjG,KAAK,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,iBAAiB,IAAI,EAA8B,CAAC,EAAE,CAAC;gBACnG,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;oBAAE,KAAK,MAAM,CAAC,IAAI,IAAgB;wBAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;4BAAE,CAAC,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YACnI,CAAC;YACD,IAAI,MAAM,CAAC,aAAa;gBAAE,KAAK,MAAM,CAAC,IAAI,IAAI;oBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,aAAa,EAAE,IAAI,EAAE,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,CAAA;YAC5H,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;gBACrB,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;oBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;qBACvI,IAAI,MAAM,CAAC,oBAAoB,KAAK,KAAK;oBAAE,CAAC,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAA;qBACvE,IAAI,MAAM,CAAC,oBAAoB,IAAI,OAAO,MAAM,CAAC,oBAAoB,KAAK,QAAQ;oBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,oBAAoB,EAAE,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;YAChL,CAAC;QACH,CAAC;QACD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,IAAI,MAAM,CAAC,OAAO,IAAI,IAAI,IAAI,IAAI,GAAG,MAAM,CAAC,OAAO;gBAAE,CAAC,CAAC,SAAS,CAAC,CAAA;YACjE,IAAI,MAAM,CAAC,OAAO,IAAI,IAAI,IAAI,IAAI,GAAG,MAAM,CAAC,OAAO;gBAAE,CAAC,CAAC,SAAS,CAAC,CAAA;YACjE,IAAI,MAAM,CAAC,gBAAgB,IAAI,IAAI,IAAI,IAAI,IAAI,MAAM,CAAC,gBAAgB;gBAAE,CAAC,CAAC,kBAAkB,CAAC,CAAA;YAC7F,IAAI,MAAM,CAAC,gBAAgB,IAAI,IAAI,IAAI,IAAI,IAAI,MAAM,CAAC,gBAAgB;gBAAE,CAAC,CAAC,kBAAkB,CAAC,CAAA;YAC7F,IAAI,MAAM,CAAC,UAAU,IAAI,IAAI,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,CAAC,CAAC,YAAY,CAAC,CAAA;QACxF,CAAC;QACD,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;YAAE,CAAC,CAAC,iBAAiB,CAAC,CAAA;QACzH,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAAC,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAU,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;YAAC,IAAI,CAAC,KAAK,CAAC;gBAAE,CAAC,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAA;QAAC,CAAC;QAC7J,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,CAAC,CAAC,aAAa,CAAC,CAAA;QACrG,IAAI,MAAM,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAA;YAC9D,IAAI,GAAG,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;gBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;YAC3F,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;gBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;QAC9F,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAa;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;QACjG,OAAO,IAAI,CAAA;IACb,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AAChD,CAAC","sourcesContent":["// core — the form layer: the canonical rules every RLTP artifact obeys.\n//\n// One implementation of the canonical form (JCS subset, multibase\n// encodings, digest equality over DECODED bytes, timestamp\n// normalization) and the JSON-Schema subset validator. The conformance\n// runner, the reference engine and every simulator delegate here.\n//\n// Predicates exist ONCE — that is the point. Weakening a rule here fails\n// the conformance runner's self-tests rather than silently changing what\n// some user interface accepts.\n//\n// Dependency-free and environment-free: no node:*, no DOM, no WebCrypto.\n// Everything here is synchronous and pure.\n\n// ── JCS (RFC 8785 subset for the ASCII I-JSON forms this stack ships) ──\nexport type Json = string | number | boolean | null | Json[] | { [k: string]: Json }\n\n/** RFC 8785 subset for the ASCII I-JSON forms this stack ships. */\nexport const jcs = (o: unknown): string => {\n if (o === undefined) throw new Error('jcs: undefined is not serializable')\n // RFC 8785 operates on Unicode strings — a lone surrogate is not one,\n // and a conformant implementation MUST error rather than canonicalize\n // it (review 3, B-1: divergent digests between implementations)\n if (typeof o === 'string' && !(o as unknown as { isWellFormed(): boolean }).isWellFormed()) throw new Error('jcs: lone surrogate')\n if (typeof o === 'number' && !Number.isFinite(o)) throw new Error('jcs: non-finite number')\n if (Array.isArray(o)) {\n // a sparse array is not a JSON value: map() skips holes and join()\n // erases them, so [empty] and [] would COLLIDE on one digest\n // (review 4, B-3) — reject instead of silently canonicalizing\n for (let i = 0; i < o.length; i++) if (!(i in o)) throw new Error('jcs: sparse array')\n // non-index own properties (arr.x = 1) and symbol keys would be\n // silently DROPPED and collide with the bare array (review 6, B-2)\n if (Object.getOwnPropertyNames(o).length !== o.length + 1 /* 'length' itself */ || Object.getOwnPropertySymbols(o).length > 0) throw new Error('jcs: array with extra own properties')\n return '[' + o.map(jcs).join(',') + ']'\n }\n if (o && typeof o === 'object') {\n // only PLAIN objects are JSON values: a Date, Map or class instance\n // would serialize by its enumerable keys alone and collide with {}\n // (review 5, B-3) — reject at the edge of the digest domain\n const proto = Object.getPrototypeOf(o)\n if (proto !== null && proto !== Object.prototype) throw new Error('jcs: not a plain JSON object')\n // symbol-keyed own properties would be silently dropped — the object\n // would collide with its symbol-free twin (review 6, B-2)\n if (Object.getOwnPropertySymbols(o).length > 0) throw new Error('jcs: object with symbol keys')\n // non-enumerable own properties are invisible to Object.keys and\n // would collide with the bare twin (review 7, B-4)\n if (Object.getOwnPropertyNames(o).length !== Object.keys(o).length) throw new Error('jcs: object with non-enumerable own properties')\n const rec = o as Record<string, unknown>\n return '{' + Object.keys(rec).sort().map((k) => {\n if (rec[k] === undefined) throw new Error('jcs: undefined property ' + k)\n if (!(k as unknown as { isWellFormed(): boolean }).isWellFormed()) throw new Error('jcs: lone surrogate in key')\n return JSON.stringify(k) + ':' + jcs(rec[k])\n }).join(',') + '}'\n }\n const s = JSON.stringify(o)\n // M-4 (review 1): symbols and functions stringify to undefined — the\n // invariant \"jcs returns a string\" is enforced at the API edge, not\n // silently violated downstream in a digest.\n if (typeof s !== 'string') throw new Error('jcs: value is not JSON-representable')\n return s\n}\n\n// ── multibase encodings ─────────────────────────────────────────────────\nexport const B58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'\nexport function base58 (bytes: Uint8Array): string {\n let n = 0n\n for (const b of bytes) n = n * 256n + BigInt(b)\n let out = ''\n while (n > 0n) { out = B58[Number(n % 58n)] + out; n /= 58n }\n for (const b of bytes) { if (b === 0) out = '1' + out; else break }\n return out\n}\nexport function fromBase58 (s: string): Uint8Array | null {\n let n = 0n\n for (const c of s) {\n const i = B58.indexOf(c)\n if (i < 0) return null\n n = n * 58n + BigInt(i)\n }\n const out: number[] = []\n while (n > 0n) { out.unshift(Number(n % 256n)); n /= 256n }\n for (const c of s) { if (c === '1') out.unshift(0); else break }\n return new Uint8Array(out)\n}\nexport const b64uOf = (bytes: Uint8Array): string => {\n let s = ''\n for (const b of bytes) s += String.fromCharCode(b)\n const btoaFn: (x: string) => string = typeof btoa === 'function'\n ? btoa\n : (x) => (globalThis as any).Buffer.from(x, 'binary').toString('base64')\n return btoaFn(s).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\nexport const fromB64u = (s: string): Uint8Array => {\n const atobFn: (x: string) => string = typeof atob === 'function'\n ? atob\n : (x) => (globalThis as any).Buffer.from(x, 'base64').toString('binary')\n const bin = atobFn(s.replace(/-/g, '+').replace(/_/g, '/'))\n return Uint8Array.from(bin, (c) => c.charCodeAt(0))\n}\n\n// ── digest equality over decoded multihash bytes (Encounter 2.3) ────────\n// toU: strict multibase bridge — prefix, sha2-256 multihash header and\n// length, AND canonical-form round-trip; returns the canonical u rendering\n// or null. A u input is checked for header/length too.\nexport const toU = (v: unknown): string | null => {\n if (typeof v !== 'string' || v.length < 2) return null\n let bytes: Uint8Array | null\n if (v[0] === 'u') {\n try { bytes = fromB64u(v.slice(1)) } catch { return null }\n // canonical base64url only — padding or non-zero trailing bits make a\n // DIFFERENT string decode to the same bytes, and equality is decided\n // over bytes; without this check 16 spellings of one digest verify\n // (B-1, review 1; the shipped reject vectors demand exactly this).\n if (bytes && 'u' + b64uOf(bytes) !== v) return null\n } else if (v[0] === 'z') {\n bytes = fromBase58(v.slice(1))\n if (bytes && 'z' + base58(bytes) !== v) return null // canonical base58btc only\n } else return null\n if (!bytes || bytes.length !== 34 || bytes[0] !== 0x12 || bytes[1] !== 0x20) return null\n return 'u' + b64uOf(bytes)\n}\nexport const sameDigest = (a: unknown, b: unknown): boolean => { const na = toU(a); return na !== null && na === toU(b) }\n\n/** Whole-second ISO rendering — the timestamp form every artifact carries. */\nexport const iso = (ms: number): string => new Date(ms).toISOString().replace(/\\.\\d{3}Z$/, 'Z')\n\n// ── timestamps (Encounter 2.3) ──────────────────────────────────────────\n// tsec: whole-second truncation of EVERY comparison operand (incl. now).\nexport const tsec = (v: string | number): number => Math.floor((typeof v === 'number' ? v : Date.parse(v)) / 1000) * 1000\n// calOK: calendar-valid round-trip AND the ≤3-fractional-digit cap —\n// Date.parse silently normalizes impossible dates, so demand the round-trip.\nexport const calOK = (t: unknown): boolean => {\n if (typeof t !== 'string') return false\n if (!/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{1,3})?Z$/.test(t)) return false\n const d = new Date(t)\n return !Number.isNaN(d.getTime()) && d.toISOString().slice(0, 19) === t.slice(0, 19)\n}\n\n// ── THE JSON-Schema subset validator (exactly the keywords we ship) ─────\n// makeValidator(schemaMap): schemaMap is { filename → parsed schema }.\n// Returns { validate, resolveRef, SCHEMAS, BYID } bound to that map.\nexport type Schema = boolean | { [k: string]: any }\nexport type SchemaMap = Record<string, Schema>\nexport interface Validator {\n validate: (data: unknown, schema: Schema, root: Schema, path?: string) => string[]\n resolveRef: (ref: string, root: Schema) => { node: Schema, root: Schema }\n SCHEMAS: SchemaMap\n BYID: SchemaMap\n}\n\n/** Builds a validator bound to one schema map ({ filename → parsed schema }). */\nexport function makeValidator (SCHEMAS: SchemaMap): Validator {\n const BYID: SchemaMap = {}\n for (const s of Object.values(SCHEMAS)) if (typeof s === 'object' && s.$id) BYID[s.$id] = s\n const walk = (node: any, parts: string[]): any => { let n = node; for (const p of parts) n = n[p]; return n }\n const resolveRef = (ref: string, root: Schema) => {\n if (ref.startsWith('#')) return { node: walk(root, ref.slice(2).split('/')), root }\n const [base, frag] = ref.split('#')\n const target = SCHEMAS[base!] || BYID[base!]\n if (!target) throw new Error('unresolvable $ref ' + ref)\n if (!frag) return { node: target, root: target }\n return { node: walk(target, frag.slice(1).split('/')), root: target }\n }\n function validate (data: unknown, schema: Schema, root: Schema, path = '$'): string[] {\n const errs: string[] = []\n const E = (m: string) => errs.push(`${path}: ${m}`)\n if (schema === false) { E('schema false'); return errs }\n if (schema === true || schema == null) return errs\n if (schema.$ref) { const { node, root: r } = resolveRef(schema.$ref, root); return validate(data, node, r, path) }\n const anyData = data as any\n if (schema.const !== undefined && jcs(data) !== jcs(schema.const)) E('const mismatch')\n if (schema.enum && !schema.enum.some((v: unknown) => jcs(v) === jcs(data))) E('enum mismatch')\n if (schema.type) {\n const t = Array.isArray(data) ? 'array' : data === null ? 'null' : typeof data\n const want: string[] = ([] as string[]).concat(schema.type)\n const okT = want.some((w) => w === t || (w === 'integer' && t === 'number' && Number.isInteger(data)))\n if (!okT) { E(`type ${t} != ${schema.type}`); return errs }\n }\n if (typeof data === 'string') {\n if (schema.pattern && !new RegExp(schema.pattern).test(data)) E('pattern')\n // JSON Schema misst Stringlänge in CODEPUNKTEN, nicht UTF-16-\n // Einheiten (Review 4, M-2: 101 Emoji sind 101 Zeichen, nicht 202)\n const cpLen = (schema.minLength != null || schema.maxLength != null) ? [...data].length : 0\n if (schema.minLength != null && cpLen < schema.minLength) E('minLength')\n if (schema.maxLength != null && cpLen > schema.maxLength) E('maxLength')\n }\n if (Array.isArray(data)) {\n if (schema.minItems != null && data.length < schema.minItems) E('minItems')\n if (schema.maxItems != null && data.length > schema.maxItems) E('maxItems')\n if (schema.uniqueItems && new Set(data.map(jcs)).size !== data.length) E('uniqueItems')\n if (schema.prefixItems) {\n schema.prefixItems.forEach((ps: Schema, i: number) => { if (i < data.length) errs.push(...validate(data[i], ps, root, `${path}[${i}]`)) })\n if (schema.items === false && data.length > schema.prefixItems.length) E('items false beyond prefixItems')\n } else if (schema.items !== undefined && schema.items !== true) {\n data.forEach((d: unknown, i: number) => errs.push(...validate(d, schema.items, root, `${path}[${i}]`)))\n }\n if (schema.contains && !data.some((d: unknown) => validate(d, schema.contains, root, path).length === 0)) E('contains unmatched')\n }\n if (data && typeof data === 'object' && !Array.isArray(data)) {\n const keys = Object.keys(anyData)\n if (schema.minProperties != null && keys.length < schema.minProperties) E('minProperties')\n if (schema.maxProperties != null && keys.length > schema.maxProperties) E('maxProperties')\n for (const r of schema.required || []) if (!Object.hasOwn(anyData, r)) E(`missing required ${r}`)\n for (const [k, deps] of Object.entries(schema.dependentRequired || {} as Record<string, string[]>)) {\n if (Object.hasOwn(anyData, k)) for (const d of deps as string[]) if (!Object.hasOwn(anyData, d)) E(`dependentRequired ${k}→${d}`)\n }\n if (schema.propertyNames) for (const k of keys) errs.push(...validate(k, schema.propertyNames, root, `${path}.<name:${k}>`))\n for (const k of keys) {\n if (schema.properties && Object.hasOwn(schema.properties, k)) errs.push(...validate(anyData[k], schema.properties[k], root, `${path}.${k}`))\n else if (schema.additionalProperties === false) E(`additionalProperty ${k}`)\n else if (schema.additionalProperties && typeof schema.additionalProperties === 'object') errs.push(...validate(anyData[k], schema.additionalProperties, root, `${path}.${k}`))\n }\n }\n if (typeof data === 'number') {\n if (schema.minimum != null && data < schema.minimum) E('minimum')\n if (schema.maximum != null && data > schema.maximum) E('maximum')\n if (schema.exclusiveMinimum != null && data <= schema.exclusiveMinimum) E('exclusiveMinimum')\n if (schema.exclusiveMaximum != null && data >= schema.exclusiveMaximum) E('exclusiveMaximum')\n if (schema.multipleOf != null && (data / schema.multipleOf) % 1 !== 0) E('multipleOf')\n }\n if (schema.anyOf && !schema.anyOf.some((s2: Schema) => validate(data, s2, root, path).length === 0)) E('anyOf unmatched')\n if (schema.oneOf) { const n = schema.oneOf.filter((s2: Schema) => validate(data, s2, root, path).length === 0).length; if (n !== 1) E(`oneOf matched ${n}`) }\n if (schema.not !== undefined && validate(data, schema.not, root, path).length === 0) E('not matched')\n if (schema.if !== undefined) {\n const hit = validate(data, schema.if, root, path).length === 0\n if (hit && schema.then !== undefined) errs.push(...validate(data, schema.then, root, path))\n if (!hit && schema.else !== undefined) errs.push(...validate(data, schema.else, root, path))\n }\n for (const sub of (schema.allOf || []) as Schema[]) errs.push(...validate(data, sub, root, path))\n return errs\n }\n return { validate, resolveRef, SCHEMAS, BYID }\n}\n"]}
@@ -0,0 +1,32 @@
1
+ import { base58, fromBase58, b64uOf, fromB64u } from './core.js';
2
+ export { b64uOf, fromB64u, base58, fromBase58 };
3
+ export declare const cat: (...bs: Uint8Array[]) => Uint8Array;
4
+ export declare const rand: (n: number) => Uint8Array;
5
+ export declare const sha: (bytes: Uint8Array) => Promise<Uint8Array>;
6
+ export declare const hkdf: (ikm: Uint8Array, info: string, len?: number) => Promise<Uint8Array>;
7
+ export declare const digestBytes: (bytes: Uint8Array) => Promise<string>;
8
+ export declare const digestDoc: (obj: unknown) => Promise<string>;
9
+ /** A key pair as this library carries it: the private CryptoKey plus the raw public bytes. */
10
+ export interface KeyPair {
11
+ priv: CryptoKey;
12
+ pubRaw: Uint8Array;
13
+ }
14
+ export declare function edFromSeed(seed: Uint8Array): Promise<KeyPair>;
15
+ export declare function xFromSeed(seed: Uint8Array): Promise<KeyPair>;
16
+ export declare const anchorOfEd: (pubRaw: Uint8Array) => string;
17
+ export declare const mkOfX: (pubRaw: Uint8Array) => string;
18
+ export declare const edRawOfAnchor: (did: unknown) => Uint8Array | null;
19
+ export declare const xRawOfMk: (mk: unknown) => Uint8Array | null;
20
+ export declare const ecdh: (xPriv: CryptoKey, theirPubRaw: Uint8Array) => Promise<Uint8Array>;
21
+ /** What a signer must offer: its anchor and its Ed25519 key. A full identity Context satisfies this. */
22
+ export interface Signer {
23
+ anchor: string;
24
+ ed: {
25
+ priv: CryptoKey;
26
+ };
27
+ }
28
+ export declare function diSign<T extends Record<string, any>>(ctx: Signer, doc: T, created: string): Promise<T & {
29
+ proof: Record<string, any>;
30
+ }>;
31
+ export declare function diVerify(doc: any, expectedAnchor?: string): Promise<boolean>;
32
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAcA,OAAO,EAAO,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAS,MAAM,WAAW,CAAA;AAC5E,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAA;AAM/C,eAAO,MAAM,GAAG,GAAI,GAAG,IAAI,UAAU,EAAE,KAAG,UAIzC,CAAA;AACD,eAAO,MAAM,IAAI,GAAI,GAAG,MAAM,KAAG,UAAkE,CAAA;AAGnG,eAAO,MAAM,GAAG,GAAU,OAAO,UAAU,KAAG,OAAO,CAAC,UAAU,CAAqD,CAAA;AACrH,eAAO,MAAM,IAAI,GAAU,KAAK,UAAU,EAAE,MAAM,MAAM,EAAE,YAAQ,KAAG,OAAO,CAAC,UAAU,CAGtF,CAAA;AAED,eAAO,MAAM,WAAW,GAAU,OAAO,UAAU,KAAG,OAAO,CAAC,MAAM,CAAuE,CAAA;AAE3I,eAAO,MAAM,SAAS,GAAU,KAAK,OAAO,KAAG,OAAO,CAAC,MAAM,CAAqC,CAAA;AAMlG,8FAA8F;AAC9F,MAAM,WAAW,OAAO;IAAG,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE;AAEhE,wBAAsB,UAAU,CAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAGpE;AACD,wBAAsB,SAAS,CAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAGnE;AACD,eAAO,MAAM,UAAU,GAAI,QAAQ,UAAU,KAAG,MAA0E,CAAA;AAC1H,eAAO,MAAM,KAAK,GAAI,QAAQ,UAAU,KAAG,MAAkE,CAAA;AAC7G,eAAO,MAAM,aAAa,GAAI,KAAK,OAAO,KAAG,UAAU,GAAG,IAIzD,CAAA;AACD,eAAO,MAAM,QAAQ,GAAI,IAAI,OAAO,KAAG,UAAU,GAAG,IAInD,CAAA;AACD,eAAO,MAAM,IAAI,GAAU,OAAO,SAAS,EAAE,aAAa,UAAU,KAAG,OAAO,CAAC,UAAU,CAGxF,CAAA;AAMD,wGAAwG;AACxG,MAAM,WAAW,MAAM;IAAG,MAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE;QAAE,IAAI,EAAE,SAAS,CAAA;KAAE,CAAA;CAAE;AAEnE,wBAAsB,MAAM,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAG,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAAE,CAAC,CAM9I;AACD,wBAAsB,QAAQ,CAAE,GAAG,EAAE,GAAG,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAyBnF"}