agent-passport-system 3.0.0 → 3.2.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 (168) hide show
  1. package/README.md +7 -4
  2. package/dist/src/adapters/governance-hook.d.ts.map +1 -1
  3. package/dist/src/adapters/ibac-cedar.d.ts.map +1 -1
  4. package/dist/src/adapters/ibac-cedar.js +22 -4
  5. package/dist/src/adapters/ibac-cedar.js.map +1 -1
  6. package/dist/src/adapters/langchain.d.ts +1 -1
  7. package/dist/src/adapters/langchain.d.ts.map +1 -1
  8. package/dist/src/adapters/mcp.d.ts.map +1 -1
  9. package/dist/src/adapters/oauth-id-jag/index.js.map +1 -1
  10. package/dist/src/adapters/oauth-id-jag/types.d.ts.map +1 -1
  11. package/dist/src/adapters/oauth-id-jag/types.js.map +1 -1
  12. package/dist/src/adapters/oauth-rfc8693/types.d.ts +7 -7
  13. package/dist/src/adapters/oauth-rfc8693/types.d.ts.map +1 -1
  14. package/dist/src/adapters/remote-signer/handle-signer.d.ts.map +1 -1
  15. package/dist/src/adapters/remote-signer/local-signer.d.ts.map +1 -1
  16. package/dist/src/adapters/remote-signer/types.d.ts.map +1 -1
  17. package/dist/src/cli/index.js +12 -5
  18. package/dist/src/cli/index.js.map +1 -1
  19. package/dist/src/core/anchor-state.js.map +1 -1
  20. package/dist/src/core/aps-txt.js.map +1 -1
  21. package/dist/src/core/attestation.js.map +1 -1
  22. package/dist/src/core/canonical-jcs.js.map +1 -1
  23. package/dist/src/core/commerce.d.ts +1 -1
  24. package/dist/src/core/commerce.d.ts.map +1 -1
  25. package/dist/src/core/context.d.ts.map +1 -1
  26. package/dist/src/core/cross-chain.js.map +1 -1
  27. package/dist/src/core/data-enforcement.d.ts.map +1 -1
  28. package/dist/src/core/data-gateway.d.ts.map +1 -1
  29. package/dist/src/core/data-lifecycle.js.map +1 -1
  30. package/dist/src/core/data-source-attribution.js.map +1 -1
  31. package/dist/src/core/did-interop.d.ts.map +1 -1
  32. package/dist/src/core/did-interop.js +63 -0
  33. package/dist/src/core/did-interop.js.map +1 -1
  34. package/dist/src/core/execution-attestation.js.map +1 -1
  35. package/dist/src/core/gateway.d.ts.map +1 -1
  36. package/dist/src/core/governance.js.map +1 -1
  37. package/dist/src/core/obligations.js.map +1 -1
  38. package/dist/src/core/passport.js.map +1 -1
  39. package/dist/src/core/policy.d.ts.map +1 -1
  40. package/dist/src/core/principal.js.map +1 -1
  41. package/dist/src/core/reputation-authority.js.map +1 -1
  42. package/dist/src/core/time.js.map +1 -1
  43. package/dist/src/core/values.js.map +1 -1
  44. package/dist/src/crypto/key-storage.d.ts.map +1 -1
  45. package/dist/src/crypto/keys.js +1 -1
  46. package/dist/src/crypto/keys.js.map +1 -1
  47. package/dist/src/decisionReceipt.d.ts +3 -3
  48. package/dist/src/errors/identity-composition-error.d.ts.map +1 -1
  49. package/dist/src/errors/identity-composition-error.js.map +1 -1
  50. package/dist/src/interop/qntm-bridge.d.ts.map +1 -1
  51. package/dist/src/interop/qntm-bridge.js +36 -4
  52. package/dist/src/interop/qntm-bridge.js.map +1 -1
  53. package/dist/src/storage/volatile-backend.d.ts.map +1 -1
  54. package/dist/src/v2/accountability/__tests__/bundle.test.js.map +1 -1
  55. package/dist/src/v2/accountability/__tests__/contestability.test.js.map +1 -1
  56. package/dist/src/v2/accountability/__tests__/custody.test.js.map +1 -1
  57. package/dist/src/v2/accountability/__tests__/fixtures.test.js.map +1 -1
  58. package/dist/src/v2/assurance/descriptor.js.map +1 -1
  59. package/dist/src/v2/attribution-primitive/canonical.js.map +1 -1
  60. package/dist/src/v2/attribution-primitive/merkle.js.map +1 -1
  61. package/dist/src/v2/attribution-primitive/residual.js.map +1 -1
  62. package/dist/src/v2/attribution-weights/compute-axis.js.map +1 -1
  63. package/dist/src/v2/audience-binding/types.d.ts +1 -1
  64. package/dist/src/v2/bridge.js.map +1 -1
  65. package/dist/src/v2/claim-evidence-types.d.ts +5 -5
  66. package/dist/src/v2/claim-evidence-types.d.ts.map +1 -1
  67. package/dist/src/v2/composition-check/types.d.ts +2 -2
  68. package/dist/src/v2/context-provenance/__tests__/cross-lang-parity.test.js.map +1 -1
  69. package/dist/src/v2/context-provenance/vectors/generate-vectors.js.map +1 -1
  70. package/dist/src/v2/cross_issuer_attestation/__tests__/cross_issuer_attestation.test.js.map +1 -1
  71. package/dist/src/v2/delegation-v2.js.map +1 -1
  72. package/dist/src/v2/feasibility/__tests__/feasibility.test.js.map +1 -1
  73. package/dist/src/v2/feasibility/compiler.js.map +1 -1
  74. package/dist/src/v2/hash-pointer/profile.js.map +1 -1
  75. package/dist/src/v2/hash-pointer/types.d.ts +1 -1
  76. package/dist/src/v2/human-escalation.js.map +1 -1
  77. package/dist/src/v2/instruction-provenance/canonicalize.d.ts.map +1 -1
  78. package/dist/src/v2/instruction-provenance/canonicalize.js.map +1 -1
  79. package/dist/src/v2/instruction-provenance/envelope.d.ts.map +1 -1
  80. package/dist/src/v2/instruction-provenance/envelope.js.map +1 -1
  81. package/dist/src/v2/key-resolution/resolver.d.ts.map +1 -1
  82. package/dist/src/v2/key-resolution/resolver.js.map +1 -1
  83. package/dist/src/v2/memory_provenance/__tests__/memory_provenance.test.js.map +1 -1
  84. package/dist/src/v2/mutual-auth/certificate.js.map +1 -1
  85. package/dist/src/v2/offline-verifier/middleware.js.map +1 -1
  86. package/dist/src/v2/offline-verifier/verify.js.map +1 -1
  87. package/dist/src/v2/outcome-v2.js.map +1 -1
  88. package/dist/src/v2/payment-rails/acp/index.js.map +1 -1
  89. package/dist/src/v2/payment-rails/acp/types.d.ts +1 -1
  90. package/dist/src/v2/payment-rails/ap2/fixtures/_generate.js.map +1 -1
  91. package/dist/src/v2/payment-rails/ap2/index.js.map +1 -1
  92. package/dist/src/v2/payment-rails/conformance/binding-harness.js.map +1 -1
  93. package/dist/src/v2/payment-rails/conformance/fixtures/_generate.js.map +1 -1
  94. package/dist/src/v2/payment-rails/conformance/harness.js.map +1 -1
  95. package/dist/src/v2/payment-rails/cycles/evidence-resolution.js.map +1 -1
  96. package/dist/src/v2/payment-rails/cycles/index.js.map +1 -1
  97. package/dist/src/v2/payment-rails/cycles/types.d.ts +5 -5
  98. package/dist/src/v2/payment-rails/fixtures/_generate.js.map +1 -1
  99. package/dist/src/v2/payment-rails/hooks.js.map +1 -1
  100. package/dist/src/v2/payment-rails/mpp/index.js.map +1 -1
  101. package/dist/src/v2/payment-rails/mpp/types.d.ts +1 -1
  102. package/dist/src/v2/payment-rails/nano.d.ts.map +1 -1
  103. package/dist/src/v2/payment-rails/scope-resolution.js.map +1 -1
  104. package/dist/src/v2/payment-rails/stripe-issuing/fixtures/_generate-cross-rail.js.map +1 -1
  105. package/dist/src/v2/payment-rails/stripe-issuing/fixtures/_generate.js.map +1 -1
  106. package/dist/src/v2/payment-rails/stripe-issuing/primitives.js.map +1 -1
  107. package/dist/src/v2/payment-rails/x402/fixtures/_generate.js.map +1 -1
  108. package/dist/src/v2/payment-rails/x402/index.d.ts.map +1 -1
  109. package/dist/src/v2/policy-bundle/bundle.js.map +1 -1
  110. package/dist/src/v2/provisional-statement/promote.js.map +1 -1
  111. package/dist/src/v2/read_fidelity_receipt/__tests__/read_fidelity_receipt.test.d.ts +2 -0
  112. package/dist/src/v2/read_fidelity_receipt/__tests__/read_fidelity_receipt.test.d.ts.map +1 -0
  113. package/dist/src/v2/read_fidelity_receipt/__tests__/read_fidelity_receipt.test.js +392 -0
  114. package/dist/src/v2/read_fidelity_receipt/__tests__/read_fidelity_receipt.test.js.map +1 -0
  115. package/dist/src/v2/read_fidelity_receipt/index.d.ts +4 -0
  116. package/dist/src/v2/read_fidelity_receipt/index.d.ts.map +1 -0
  117. package/dist/src/v2/read_fidelity_receipt/index.js +16 -0
  118. package/dist/src/v2/read_fidelity_receipt/index.js.map +1 -0
  119. package/dist/src/v2/read_fidelity_receipt/receipt.d.ts +45 -0
  120. package/dist/src/v2/read_fidelity_receipt/receipt.d.ts.map +1 -0
  121. package/dist/src/v2/read_fidelity_receipt/receipt.js +283 -0
  122. package/dist/src/v2/read_fidelity_receipt/receipt.js.map +1 -0
  123. package/dist/src/v2/read_fidelity_receipt/sampler.d.ts +35 -0
  124. package/dist/src/v2/read_fidelity_receipt/sampler.d.ts.map +1 -0
  125. package/dist/src/v2/read_fidelity_receipt/sampler.js +110 -0
  126. package/dist/src/v2/read_fidelity_receipt/sampler.js.map +1 -0
  127. package/dist/src/v2/read_fidelity_receipt/types.d.ts +139 -0
  128. package/dist/src/v2/read_fidelity_receipt/types.d.ts.map +1 -0
  129. package/dist/src/v2/read_fidelity_receipt/types.js +17 -0
  130. package/dist/src/v2/read_fidelity_receipt/types.js.map +1 -0
  131. package/dist/src/v2/read_fidelity_receipt/vectors/generate.d.ts +2 -0
  132. package/dist/src/v2/read_fidelity_receipt/vectors/generate.d.ts.map +1 -0
  133. package/dist/src/v2/read_fidelity_receipt/vectors/generate.js +261 -0
  134. package/dist/src/v2/read_fidelity_receipt/vectors/generate.js.map +1 -0
  135. package/dist/src/v2/regulated-action/types.d.ts +7 -7
  136. package/dist/src/v2/regulated-action/types.d.ts.map +1 -1
  137. package/dist/src/v2/scope-registry/registry.js.map +1 -1
  138. package/dist/src/v2/semantic-scoping.js.map +1 -1
  139. package/dist/src/v2/transport/rfc9421/profile.d.ts +1 -1
  140. package/dist/src/v2/transport/rfc9421/profile.d.ts.map +1 -1
  141. package/dist/src/v2/transport/rfc9421/signature-base.js.map +1 -1
  142. package/dist/src/v2/trust-policy/types.d.ts +1 -1
  143. package/dist/src/v2/trust-policy/well-known.d.ts +2 -2
  144. package/dist/src/v2/verifier-hardening/index.d.ts.map +1 -1
  145. package/dist/src/v2/word_handles/__tests__/word_handles.test.d.ts +2 -0
  146. package/dist/src/v2/word_handles/__tests__/word_handles.test.d.ts.map +1 -0
  147. package/dist/src/v2/word_handles/__tests__/word_handles.test.js +312 -0
  148. package/dist/src/v2/word_handles/__tests__/word_handles.test.js.map +1 -0
  149. package/dist/src/v2/word_handles/codec.d.ts +54 -0
  150. package/dist/src/v2/word_handles/codec.d.ts.map +1 -0
  151. package/dist/src/v2/word_handles/codec.js +334 -0
  152. package/dist/src/v2/word_handles/codec.js.map +1 -0
  153. package/dist/src/v2/word_handles/index.d.ts +4 -0
  154. package/dist/src/v2/word_handles/index.d.ts.map +1 -0
  155. package/dist/src/v2/word_handles/index.js +13 -0
  156. package/dist/src/v2/word_handles/index.js.map +1 -0
  157. package/dist/src/v2/word_handles/lexicon.d.ts +7 -0
  158. package/dist/src/v2/word_handles/lexicon.d.ts.map +1 -0
  159. package/dist/src/v2/word_handles/lexicon.js +276 -0
  160. package/dist/src/v2/word_handles/lexicon.js.map +1 -0
  161. package/dist/src/v2/word_handles/types.d.ts +58 -0
  162. package/dist/src/v2/word_handles/types.d.ts.map +1 -0
  163. package/dist/src/v2/word_handles/types.js +13 -0
  164. package/dist/src/v2/word_handles/types.js.map +1 -0
  165. package/dist/src/verification/verify.d.ts.map +1 -1
  166. package/dist/src/verification/verify.js +6 -1
  167. package/dist/src/verification/verify.js.map +1 -1
  168. package/package.json +11 -12
@@ -0,0 +1,312 @@
1
+ // Copyright 2024-2026 Tymofii Pidlisnyi. Apache-2.0 license. See LICENSE.
2
+ // ══════════════════════════════════════════════════════════════════
3
+ // word_handles codec (v2): tests
4
+ // ══════════════════════════════════════════════════════════════════
5
+ // Deterministic throughout: every derived digest, substituted
6
+ // position, replacement word, and transposition site comes from
7
+ // sha256 over a fixed label plus a counter. No wall clock, no
8
+ // randomness.
9
+ // ══════════════════════════════════════════════════════════════════
10
+ import { describe, it } from 'node:test';
11
+ import assert from 'node:assert/strict';
12
+ import { createHash } from 'node:crypto';
13
+ import { readFileSync } from 'node:fs';
14
+ import { encode, decode, encodeProfile, decodeProfile, minUniquePrefixBits, PROFILES, LEXICON_PROFILE, LEXICON_ID, LEXICON_NAME, WORDS, canonicalWordlistText, } from '../index.js';
15
+ function sha256Hex(s) {
16
+ return createHash('sha256').update(s, 'utf8').digest('hex');
17
+ }
18
+ /** First 4 bytes of sha256(label) as a big-endian uint32 seed. */
19
+ function seedUint32(label) {
20
+ return createHash('sha256').update(label, 'utf8').digest().readUInt32BE(0);
21
+ }
22
+ const WORD_TO_INDEX = (() => {
23
+ const m = new Map();
24
+ for (let i = 0; i < WORDS.length; i++)
25
+ m.set(WORDS[i], i);
26
+ return m;
27
+ })();
28
+ /** Expected prefixHex: first ceil(prefixBits/8) bytes, pad bits zeroed. */
29
+ function expectedPrefixHex(digestHex, prefixBits) {
30
+ const byteLen = Math.ceil(prefixBits / 8);
31
+ const bytes = Buffer.from(digestHex.slice(0, byteLen * 2), 'hex');
32
+ const rem = prefixBits % 8;
33
+ if (rem !== 0) {
34
+ bytes[byteLen - 1] &= (0xff << (8 - rem)) & 0xff;
35
+ }
36
+ return bytes.toString('hex');
37
+ }
38
+ const PROFILE_NAMES = [
39
+ 'compact',
40
+ 'default',
41
+ 'high_assurance',
42
+ ];
43
+ describe('lexicon integrity', () => {
44
+ it('has exactly 2048 words', () => {
45
+ assert.equal(WORDS.length, 2048);
46
+ });
47
+ it('is strictly sorted ascending (implies unique words)', () => {
48
+ for (let i = 1; i < WORDS.length; i++) {
49
+ assert.ok(WORDS[i - 1] < WORDS[i], `words not strictly sorted at index ${i}: ${WORDS[i - 1]} vs ${WORDS[i]}`);
50
+ }
51
+ });
52
+ it('has unique 4-character prefixes', () => {
53
+ const prefixes = new Set(WORDS.map((w) => w.slice(0, 4)));
54
+ assert.equal(prefixes.size, WORDS.length);
55
+ });
56
+ it('canonical wordlist text hashes to LEXICON_ID', () => {
57
+ assert.equal(LEXICON_NAME, 'aps-handle-en-v1');
58
+ const hex = createHash('sha256')
59
+ .update(canonicalWordlistText(), 'utf8')
60
+ .digest('hex');
61
+ assert.equal(`sha256:${hex}`, LEXICON_ID);
62
+ });
63
+ it('has zero overlap with the bip39_english.txt disjointness input', () => {
64
+ // lexicon-source/bip39_english.txt is a pinned DISJOINTNESS input to
65
+ // the lexicon generator; no lexicon word may appear in it.
66
+ const raw = readFileSync(new URL('../lexicon-source/bip39_english.txt', import.meta.url), 'utf8');
67
+ const banned = new Set(raw
68
+ .split('\n')
69
+ .map((w) => w.trim())
70
+ .filter((w) => w.length > 0));
71
+ assert.equal(banned.size, 2048);
72
+ const overlap = WORDS.filter((w) => banned.has(w));
73
+ assert.deepEqual(overlap, []);
74
+ });
75
+ });
76
+ describe('round-trip across all three profiles', () => {
77
+ it('round-trips 200 derived digests per profile', () => {
78
+ for (let t = 0; t < 200; t++) {
79
+ const digest = sha256Hex(`wh-roundtrip:${t}`);
80
+ for (const name of PROFILE_NAMES) {
81
+ const p = PROFILES[name];
82
+ const words = encodeProfile(digest, name);
83
+ assert.equal(words.length, p.dataWords + p.checksumWords);
84
+ const res = decodeProfile(words, name);
85
+ assert.equal(res.checksumOk, true);
86
+ assert.equal(res.prefixBits, p.prefixBits);
87
+ assert.equal(res.prefixHex, expectedPrefixHex(digest, p.prefixBits));
88
+ assert.equal(res.failedWordIndex, null);
89
+ assert.deepEqual(res.outOfLexicon, []);
90
+ }
91
+ }
92
+ });
93
+ it('accepts a sha256: prefix and raw bytes as equivalent inputs', () => {
94
+ const digest = sha256Hex('wh-input-forms:0');
95
+ const fromHex = encode(digest);
96
+ const fromPrefixed = encode(`sha256:${digest}`);
97
+ const fromBytes = encode(new Uint8Array(Buffer.from(digest, 'hex')));
98
+ assert.deepEqual(fromPrefixed, fromHex);
99
+ assert.deepEqual(fromBytes, fromHex);
100
+ });
101
+ it('exposes the profile table and lexicon profile id', () => {
102
+ assert.equal(LEXICON_PROFILE, 'single-list-v1');
103
+ assert.deepEqual(PROFILES.compact, {
104
+ name: 'compact',
105
+ dataWords: 4,
106
+ checksumWords: 1,
107
+ prefixBits: 44,
108
+ });
109
+ assert.deepEqual(PROFILES.default, {
110
+ name: 'default',
111
+ dataWords: 6,
112
+ checksumWords: 1,
113
+ prefixBits: 66,
114
+ });
115
+ assert.deepEqual(PROFILES.high_assurance, {
116
+ name: 'high_assurance',
117
+ dataWords: 8,
118
+ checksumWords: 2,
119
+ prefixBits: 88,
120
+ });
121
+ });
122
+ });
123
+ describe('substitution detection (default profile, 600 trials)', () => {
124
+ it('detects >= 597 of 600 single data word substitutions', () => {
125
+ const dataWords = PROFILES.default.dataWords;
126
+ let detected = 0;
127
+ for (let t = 0; t < 600; t++) {
128
+ const digest = sha256Hex(`wh-substitute:${t}`);
129
+ const words = encode(digest);
130
+ const pos = seedUint32(`wh-substitute-pos:${t}`) % dataWords;
131
+ const origIdx = WORD_TO_INDEX.get(words[pos]);
132
+ const delta = 1 + (seedUint32(`wh-substitute-word:${t}`) % (WORDS.length - 1));
133
+ const mutated = words.slice();
134
+ mutated[pos] = WORDS[(origIdx + delta) % WORDS.length];
135
+ const res = decode(mutated);
136
+ if (!res.checksumOk)
137
+ detected++;
138
+ if (res.failedWordIndex !== null) {
139
+ assert.equal(res.failedWordIndex, pos, `trial ${t}: localized ${res.failedWordIndex}, substituted ${pos}`);
140
+ }
141
+ }
142
+ assert.ok(detected >= 597, `detected ${detected} of 600, expected >= 597`);
143
+ });
144
+ });
145
+ describe('transposition detection (default profile, 300 trials)', () => {
146
+ it('detects >= 297 of 300 adjacent differing data word swaps', () => {
147
+ const dataWords = PROFILES.default.dataWords;
148
+ let detected = 0;
149
+ for (let t = 0; t < 300; t++) {
150
+ const digest = sha256Hex(`wh-transpose:${t}`);
151
+ const words = encode(digest);
152
+ const start = seedUint32(`wh-transpose-pos:${t}`) % (dataWords - 1);
153
+ let pair = -1;
154
+ for (let k = 0; k < dataWords - 1; k++) {
155
+ const i = (start + k) % (dataWords - 1);
156
+ if (words[i] !== words[i + 1]) {
157
+ pair = i;
158
+ break;
159
+ }
160
+ }
161
+ assert.ok(pair >= 0, `trial ${t}: no adjacent differing data words`);
162
+ const mutated = words.slice();
163
+ const tmp = mutated[pair];
164
+ mutated[pair] = mutated[pair + 1];
165
+ mutated[pair + 1] = tmp;
166
+ const res = decode(mutated);
167
+ if (!res.checksumOk)
168
+ detected++;
169
+ }
170
+ assert.ok(detected >= 297, `detected ${detected} of 300, expected >= 297`);
171
+ });
172
+ });
173
+ describe('high_assurance profile (2 checksum words)', () => {
174
+ it('round-trips and reports both checksum words through decode', () => {
175
+ const digest = sha256Hex('wh-high-assurance:0');
176
+ const words = encodeProfile(digest, 'high_assurance');
177
+ assert.equal(words.length, 10);
178
+ const res = decode(words, 2);
179
+ assert.equal(res.checksumOk, true);
180
+ assert.equal(res.prefixBits, 88);
181
+ assert.equal(res.prefixHex, expectedPrefixHex(digest, 88));
182
+ });
183
+ it('detects data word substitutions and localizes them precisely', () => {
184
+ const dataWords = PROFILES.high_assurance.dataWords;
185
+ let localized = 0;
186
+ for (let t = 0; t < 40; t++) {
187
+ const digest = sha256Hex(`wh-ha-substitute:${t}`);
188
+ const words = encodeProfile(digest, 'high_assurance');
189
+ const pos = seedUint32(`wh-ha-substitute-pos:${t}`) % dataWords;
190
+ const origIdx = WORD_TO_INDEX.get(words[pos]);
191
+ const delta = 1 + (seedUint32(`wh-ha-substitute-word:${t}`) % (WORDS.length - 1));
192
+ const mutated = words.slice();
193
+ mutated[pos] = WORDS[(origIdx + delta) % WORDS.length];
194
+ const res = decodeProfile(mutated, 'high_assurance');
195
+ assert.equal(res.checksumOk, false, `trial ${t}: substitution not detected`);
196
+ if (res.failedWordIndex !== null) {
197
+ assert.equal(res.failedWordIndex, pos);
198
+ localized++;
199
+ }
200
+ }
201
+ // With two checksum words a wrong position is coincidentally fixable
202
+ // with probability about 2047 * 2^-22, so localization is almost
203
+ // always unique.
204
+ assert.ok(localized >= 35, `localized ${localized} of 40, expected >= 35`);
205
+ });
206
+ });
207
+ describe('out-of-lexicon words', () => {
208
+ it('reports indices and suppresses decoding', () => {
209
+ const digest = sha256Hex('wh-out-of-lexicon:0');
210
+ const words = encode(digest);
211
+ const mutated = words.slice();
212
+ mutated[2] = 'notaword';
213
+ mutated[4] = 'Abacus'; // case-sensitive: 'abacus' is in the lexicon, this is not
214
+ const res = decode(mutated);
215
+ assert.deepEqual(res.outOfLexicon, [2, 4]);
216
+ assert.equal(res.prefixHex, null);
217
+ assert.equal(res.prefixBits, null);
218
+ assert.equal(res.checksumOk, false);
219
+ assert.equal(res.failedWordIndex, null);
220
+ });
221
+ it('does not trim whitespace (exact code-unit equality)', () => {
222
+ const digest = sha256Hex('wh-out-of-lexicon:1');
223
+ const words = encode(digest);
224
+ const mutated = words.slice();
225
+ mutated[0] = `${mutated[0]} `;
226
+ const res = decode(mutated);
227
+ assert.deepEqual(res.outOfLexicon, [0]);
228
+ assert.equal(res.checksumOk, false);
229
+ });
230
+ });
231
+ describe('prefixHex padding semantics', () => {
232
+ it('66-bit decode returns 18 hex chars with pad bits zero and prefixBits 66', () => {
233
+ const allOnes = 'ff'.repeat(32);
234
+ const res = decode(encode(allOnes, 66, 1));
235
+ assert.equal(res.prefixBits, 66);
236
+ assert.equal(res.prefixHex?.length, 18);
237
+ // 66 data bits into 9 bytes: the final byte keeps its top 2 bits and
238
+ // pads the low 6 with zeros, so an all-ones input ends in "c0".
239
+ assert.equal(res.prefixHex, 'ffffffffffffffffc0');
240
+ });
241
+ it('44-bit and 88-bit cases pad to the byte boundary', () => {
242
+ const allOnes = 'ff'.repeat(32);
243
+ const compact = decode(encode(allOnes, 44, 1));
244
+ assert.equal(compact.prefixBits, 44);
245
+ assert.equal(compact.prefixHex, 'fffffffffff0');
246
+ const high = decode(encode(allOnes, 88, 2), 2);
247
+ assert.equal(high.prefixBits, 88);
248
+ assert.equal(high.prefixHex, 'ff'.repeat(11));
249
+ });
250
+ });
251
+ describe('minUniquePrefixBits', () => {
252
+ it('returns 44 when 44-bit prefixes are already pairwise distinct', () => {
253
+ const digests = [0, 1, 2, 3].map((i) => sha256Hex(`wh-unique:${i}`));
254
+ assert.equal(minUniquePrefixBits(digests), 44);
255
+ });
256
+ it('moves to the next multiple of 11 that separates shared 44-bit prefixes', () => {
257
+ // Shared first 48 bits (12 hex chars), differing at bit 48: 44-bit
258
+ // prefixes collide, 55-bit prefixes differ.
259
+ const shared = '0123456789ab';
260
+ const digests = [`${shared}0${'0'.repeat(19)}`, `${shared}f${'0'.repeat(19)}`];
261
+ assert.equal(minUniquePrefixBits(digests), 55);
262
+ // Shared first 56 bits (14 hex chars), differing at bit 56: 55-bit
263
+ // prefixes collide too, 66-bit prefixes differ.
264
+ const shared56 = '0123456789abcd';
265
+ const digests56 = [`${shared56}0${'0'.repeat(17)}`, `${shared56}f${'0'.repeat(17)}`];
266
+ assert.equal(minUniquePrefixBits(digests56), 66);
267
+ });
268
+ it('rounds startBits up to a multiple of 11', () => {
269
+ const digests = [0, 1].map((i) => sha256Hex(`wh-startbits:${i}`));
270
+ assert.equal(minUniquePrefixBits(digests, 50), 55);
271
+ });
272
+ it('strips sha256: prefixes and returns 44 for a single digest', () => {
273
+ const digest = sha256Hex('wh-single:0');
274
+ assert.equal(minUniquePrefixBits([`sha256:${digest}`]), 44);
275
+ });
276
+ it('throws on duplicates and on empty input', () => {
277
+ const digest = sha256Hex('wh-duplicate:0');
278
+ assert.throws(() => minUniquePrefixBits([`sha256:${digest}`, digest]), /duplicate digests/);
279
+ assert.throws(() => minUniquePrefixBits([]), /at least one digest/);
280
+ });
281
+ });
282
+ describe('encode and decode validation errors', () => {
283
+ const digest = sha256Hex('wh-validate:0');
284
+ it('rejects prefixBits that is not a positive multiple of 11', () => {
285
+ assert.throws(() => encode(digest, 12), /positive multiple of 11/);
286
+ assert.throws(() => encode(digest, 0), /positive multiple of 11/);
287
+ assert.throws(() => encode(digest, -11), /positive multiple of 11/);
288
+ assert.throws(() => encode(digest, 11.5), /positive multiple of 11/);
289
+ });
290
+ it('rejects input shorter than prefixBits bits', () => {
291
+ assert.throws(() => encode('abcd', 66), /supplies 16 bits/);
292
+ assert.throws(() => encode(new Uint8Array(8), 88, 2), /supplies 64 bits/);
293
+ });
294
+ it('rejects checksumWords outside {1, 2}', () => {
295
+ assert.throws(() => encode(digest, 66, 0), /checksumWords must be 1 or 2/);
296
+ assert.throws(() => encode(digest, 66, 3), /checksumWords must be 1 or 2/);
297
+ assert.throws(() => encode(digest, 66, 1.5), /checksumWords must be 1 or 2/);
298
+ assert.throws(() => decode(encode(digest), 3), /checksumWords must be 1 or 2/);
299
+ });
300
+ it('rejects non-hex string input', () => {
301
+ assert.throws(() => encode('xyz'), /non-hex characters/);
302
+ });
303
+ it('rejects word counts that leave no data words', () => {
304
+ assert.throws(() => decode([WORDS[0]], 1), /leaves no data words/);
305
+ assert.throws(() => decode([WORDS[0], WORDS[1]], 2), /leaves no data words/);
306
+ });
307
+ it('rejects profile word count mismatches', () => {
308
+ const words = encodeProfile(digest, 'default');
309
+ assert.throws(() => decodeProfile(words.slice(0, 5), 'default'), /expects 7 words, got 5/);
310
+ });
311
+ });
312
+ //# sourceMappingURL=word_handles.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"word_handles.test.js","sourceRoot":"","sources":["../../../../../src/v2/word_handles/__tests__/word_handles.test.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,qEAAqE;AACrE,iCAAiC;AACjC,qEAAqE;AACrE,8DAA8D;AAC9D,gEAAgE;AAChE,8DAA8D;AAC9D,cAAc;AACd,qEAAqE;AAErE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,MAAM,MAAM,oBAAoB,CAAA;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEtC,OAAO,EACL,MAAM,EACN,MAAM,EACN,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,QAAQ,EACR,eAAe,EACf,UAAU,EACV,YAAY,EACZ,KAAK,EACL,qBAAqB,GACtB,MAAM,aAAa,CAAA;AAIpB,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC7D,CAAC;AAED,kEAAkE;AAClE,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;AAC5E,CAAC;AAED,MAAM,aAAa,GAAgC,CAAC,GAAG,EAAE;IACvD,MAAM,CAAC,GAAG,IAAI,GAAG,EAAkB,CAAA;IACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACzD,OAAO,CAAC,CAAA;AACV,CAAC,CAAC,EAAE,CAAA;AAEJ,2EAA2E;AAC3E,SAAS,iBAAiB,CAAC,SAAiB,EAAE,UAAkB;IAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAA;IACzC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IACjE,MAAM,GAAG,GAAG,UAAU,GAAG,CAAC,CAAA;IAC1B,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;QACd,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,CAAA;IAClD,CAAC;IACD,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAC9B,CAAC;AAED,MAAM,aAAa,GAAqC;IACtD,SAAS;IACT,SAAS;IACT,gBAAgB;CACjB,CAAA;AAED,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IAClC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,CAAC,EAAE,CACP,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,EACvB,sCAAsC,CAAC,KAAK,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,CAC1E,CAAA;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QACzD,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAC3C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAA;QAC9C,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC;aAC7B,MAAM,CAAC,qBAAqB,EAAE,EAAE,MAAM,CAAC;aACvC,MAAM,CAAC,KAAK,CAAC,CAAA;QAChB,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,EAAE,EAAE,UAAU,CAAC,CAAA;IAC3C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,qEAAqE;QACrE,2DAA2D;QAC3D,MAAM,GAAG,GAAG,YAAY,CACtB,IAAI,GAAG,CAAC,qCAAqC,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAC/D,MAAM,CACP,CAAA;QACD,MAAM,MAAM,GAAG,IAAI,GAAG,CACpB,GAAG;aACA,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAC/B,CAAA;QACD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QAClD,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;IAC/B,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACpD,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,SAAS,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAA;YAC7C,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;gBACjC,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;gBACxB,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;gBACzC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,aAAa,CAAC,CAAA;gBACzD,MAAM,GAAG,GAAG,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;gBACtC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;gBAClC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC,CAAA;gBAC1C,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,iBAAiB,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;gBACpE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,CAAA;gBACvC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,EAAE,EAAE,CAAC,CAAA;YACxC,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,MAAM,GAAG,SAAS,CAAC,kBAAkB,CAAC,CAAA;QAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;QAC9B,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,MAAM,EAAE,CAAC,CAAA;QAC/C,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;QACpE,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;QACvC,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IACtC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAA;QAC/C,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE;YACjC,IAAI,EAAE,SAAS;YACf,SAAS,EAAE,CAAC;YACZ,aAAa,EAAE,CAAC;YAChB,UAAU,EAAE,EAAE;SACf,CAAC,CAAA;QACF,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE;YACjC,IAAI,EAAE,SAAS;YACf,SAAS,EAAE,CAAC;YACZ,aAAa,EAAE,CAAC;YAChB,UAAU,EAAE,EAAE;SACf,CAAC,CAAA;QACF,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE;YACxC,IAAI,EAAE,gBAAgB;YACtB,SAAS,EAAE,CAAC;YACZ,aAAa,EAAE,CAAC;YAChB,UAAU,EAAE,EAAE;SACf,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,sDAAsD,EAAE,GAAG,EAAE;IACpE,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAA;QAC5C,IAAI,QAAQ,GAAG,CAAC,CAAA;QAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,SAAS,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAA;YAC9C,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;YAC5B,MAAM,GAAG,GAAG,UAAU,CAAC,qBAAqB,CAAC,EAAE,CAAC,GAAG,SAAS,CAAA;YAC5D,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAW,CAAA;YACvD,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,sBAAsB,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;YAC9E,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,CAAA;YAC7B,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;YACtD,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,CAAA;YAC3B,IAAI,CAAC,GAAG,CAAC,UAAU;gBAAE,QAAQ,EAAE,CAAA;YAC/B,IAAI,GAAG,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;gBACjC,MAAM,CAAC,KAAK,CACV,GAAG,CAAC,eAAe,EACnB,GAAG,EACH,SAAS,CAAC,eAAe,GAAG,CAAC,eAAe,iBAAiB,GAAG,EAAE,CACnE,CAAA;YACH,CAAC;QACH,CAAC;QACD,MAAM,CAAC,EAAE,CAAC,QAAQ,IAAI,GAAG,EAAE,YAAY,QAAQ,0BAA0B,CAAC,CAAA;IAC5E,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,uDAAuD,EAAE,GAAG,EAAE;IACrE,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAA;QAC5C,IAAI,QAAQ,GAAG,CAAC,CAAA;QAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,SAAS,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAA;YAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;YAC5B,MAAM,KAAK,GAAG,UAAU,CAAC,oBAAoB,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,CAAA;YACnE,IAAI,IAAI,GAAG,CAAC,CAAC,CAAA;YACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBACvC,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,CAAA;gBACvC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;oBAC9B,IAAI,GAAG,CAAC,CAAA;oBACR,MAAK;gBACP,CAAC;YACH,CAAC;YACD,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,SAAS,CAAC,oCAAoC,CAAC,CAAA;YACpE,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,CAAA;YAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;YACzB,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAA;YACjC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,CAAA;YACvB,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,CAAA;YAC3B,IAAI,CAAC,GAAG,CAAC,UAAU;gBAAE,QAAQ,EAAE,CAAA;QACjC,CAAC;QACD,MAAM,CAAC,EAAE,CAAC,QAAQ,IAAI,GAAG,EAAE,YAAY,QAAQ,0BAA0B,CAAC,CAAA;IAC5E,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,2CAA2C,EAAE,GAAG,EAAE;IACzD,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,MAAM,GAAG,SAAS,CAAC,qBAAqB,CAAC,CAAA;QAC/C,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;QACrD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;QAC9B,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;QAC5B,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;QAClC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;QAChC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,iBAAiB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAA;IAC5D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,SAAS,GAAG,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAA;QACnD,IAAI,SAAS,GAAG,CAAC,CAAA;QACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,SAAS,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAA;YACjD,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;YACrD,MAAM,GAAG,GAAG,UAAU,CAAC,wBAAwB,CAAC,EAAE,CAAC,GAAG,SAAS,CAAA;YAC/D,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAW,CAAA;YACvD,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,yBAAyB,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;YACjF,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,CAAA;YAC7B,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;YACtD,MAAM,GAAG,GAAG,aAAa,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAA;YACpD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,EAAE,SAAS,CAAC,6BAA6B,CAAC,CAAA;YAC5E,IAAI,GAAG,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;gBACjC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,EAAE,GAAG,CAAC,CAAA;gBACtC,SAAS,EAAE,CAAA;YACb,CAAC;QACH,CAAC;QACD,qEAAqE;QACrE,iEAAiE;QACjE,iBAAiB;QACjB,MAAM,CAAC,EAAE,CAAC,SAAS,IAAI,EAAE,EAAE,aAAa,SAAS,wBAAwB,CAAC,CAAA;IAC5E,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,MAAM,GAAG,SAAS,CAAC,qBAAqB,CAAC,CAAA;QAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;QAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,CAAA;QAC7B,OAAO,CAAC,CAAC,CAAC,GAAG,UAAU,CAAA;QACvB,OAAO,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAA,CAAC,0DAA0D;QAChF,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,CAAA;QAC3B,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QAC1C,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;QACjC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;QAClC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAA;QACnC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,MAAM,GAAG,SAAS,CAAC,qBAAqB,CAAC,CAAA;QAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;QAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,CAAA;QAC7B,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAA;QAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,CAAA;QAC3B,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QACvC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAA;IACrC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAA;QAC1C,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;QAChC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC,CAAA;QACvC,qEAAqE;QACrE,gEAAgE;QAChE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAC/B,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAA;QAC9C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;QACpC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,cAAc,CAAC,CAAA;QAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QAC9C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;QACjC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;IAC/C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAA;QACpE,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wEAAwE,EAAE,GAAG,EAAE;QAChF,mEAAmE;QACnE,4CAA4C;QAC5C,MAAM,MAAM,GAAG,cAAc,CAAA;QAC7B,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;QAC9E,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;QAC9C,mEAAmE;QACnE,gDAAgD;QAChD,MAAM,QAAQ,GAAG,gBAAgB,CAAA;QACjC,MAAM,SAAS,GAAG,CAAC,GAAG,QAAQ,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,QAAQ,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;QACpF,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAA;QACjE,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,CAAC,CAAA;QACvC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,UAAU,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAC7D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,MAAM,GAAG,SAAS,CAAC,gBAAgB,CAAC,CAAA;QAC1C,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CAAC,mBAAmB,CAAC,CAAC,UAAU,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC,EACvD,mBAAmB,CACpB,CAAA;QACD,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC,EAAE,qBAAqB,CAAC,CAAA;IACrE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;IACnD,MAAM,MAAM,GAAG,SAAS,CAAC,eAAe,CAAC,CAAA;IAEzC,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,yBAAyB,CAAC,CAAA;QAClE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,yBAAyB,CAAC,CAAA;QACjE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,yBAAyB,CAAC,CAAA;QACnE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,yBAAyB,CAAC,CAAA;IACtE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,kBAAkB,CAAC,CAAA;QAC3D,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,8BAA8B,CAAC,CAAA;QAC1E,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,8BAA8B,CAAC,CAAA;QAC1E,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,8BAA8B,CAAC,CAAA;QAC5E,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,8BAA8B,CAAC,CAAA;IAChF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,oBAAoB,CAAC,CAAA;IAC1D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAA;QAClE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAA;IAC9E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QAC9C,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,SAAS,CAAC,EACjD,wBAAwB,CACzB,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,54 @@
1
+ import type { DecodeResult, WordHandleProfile, WordHandleProfileName } from './types.js';
2
+ /** Identifier of the lexicon layout profile used by this codec. */
3
+ export declare const LEXICON_PROFILE = "single-list-v1";
4
+ /**
5
+ * Built-in word handle profiles. Word count = dataWords + checksumWords;
6
+ * prefixBits = 11 * dataWords.
7
+ *
8
+ * compact: 4+1 (44 bits). Set-scoped display ONLY; render-time
9
+ * uniqueness plus lengthening is mandatory
10
+ * (minUniquePrefixBits is the tool).
11
+ * default: 6+1 (66 bits). Minimum for any cross-set reference.
12
+ * high_assurance: 8+2 (88 bits). Archival and adversarial contexts.
13
+ */
14
+ export declare const PROFILES: Readonly<Record<WordHandleProfileName, WordHandleProfile>>;
15
+ /**
16
+ * Encode the first `prefixBits` bits of `input` as a word_digest_handle:
17
+ * prefixBits/11 data words followed by `checksumWords` checksum words.
18
+ *
19
+ * `input` is raw bytes or a hex string; a leading "sha256:" prefix on
20
+ * hex input is stripped. Throws when prefixBits is not a positive
21
+ * multiple of 11, when the input supplies fewer than prefixBits bits,
22
+ * or when checksumWords is not 1 or 2.
23
+ */
24
+ export declare function encode(input: Uint8Array | string, prefixBits?: number, checksumWords?: number): string[];
25
+ /** Encode with a named profile (prefixBits and checksumWords from the table). */
26
+ export declare function encodeProfile(input: Uint8Array | string, profile: WordHandleProfileName): string[];
27
+ /**
28
+ * Decode a word_digest_handle. Never throws on unknown words (reported
29
+ * via `outOfLexicon`); throws when checksumWords is not 1 or 2 or when
30
+ * the word count leaves no data words.
31
+ *
32
+ * `prefixHex` is the full packed prefix, 2*ceil(prefixBits/8) lowercase
33
+ * hex characters with trailing pad bits zero; `prefixBits` is returned
34
+ * so consumers compare BIT-scoped, never by raw string beyond
35
+ * prefixBits. Localization (`failedWordIndex`) is best effort and only
36
+ * attempted when the checksum fails and every word is in the lexicon.
37
+ * See DecodeResult for the exact rules.
38
+ */
39
+ export declare function decode(words: readonly string[], checksumWords?: number): DecodeResult;
40
+ /**
41
+ * Decode with a named profile. Throws when the word count does not
42
+ * match the profile shape (dataWords + checksumWords).
43
+ */
44
+ export declare function decodeProfile(words: readonly string[], profile: WordHandleProfileName): DecodeResult;
45
+ /**
46
+ * Smallest multiple of 11 that is >= startBits such that the leading
47
+ * prefixes of all digests are pairwise BIT-distinct at that length.
48
+ *
49
+ * Hex inputs may carry "sha256:" prefixes (stripped) and are compared
50
+ * case-insensitively. Throws on empty input or duplicate full digests
51
+ * (no prefix length can separate identical digests).
52
+ */
53
+ export declare function minUniquePrefixBits(digestsHex: readonly string[], startBits?: number): number;
54
+ //# sourceMappingURL=codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../../../../src/v2/word_handles/codec.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAKxF,mEAAmE;AACnE,eAAO,MAAM,eAAe,mBAAmB,CAAA;AAE/C;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,qBAAqB,EAAE,iBAAiB,CAAC,CAI/E,CAAA;AAyGD;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CACpB,KAAK,EAAE,UAAU,GAAG,MAAM,EAC1B,UAAU,SAAK,EACf,aAAa,SAAI,GAChB,MAAM,EAAE,CAuBV;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAC3B,KAAK,EAAE,UAAU,GAAG,MAAM,EAC1B,OAAO,EAAE,qBAAqB,GAC7B,MAAM,EAAE,CAMV;AAyBD;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,aAAa,SAAI,GAAG,YAAY,CAsEhF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,OAAO,EAAE,qBAAqB,GAC7B,YAAY,CAYd;AAsBD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,SAAS,SAAK,GAAG,MAAM,CAuBzF"}