keri-ts 0.7.0 → 0.9.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 (172) hide show
  1. package/README.md +10 -0
  2. package/esm/cesr/src/primitives/counter.js +64 -9
  3. package/esm/cesr/src/primitives/mapper.js +48 -41
  4. package/esm/cesr/src/serder/native.js +62 -29
  5. package/esm/cesr/src/serder/serder.js +35 -46
  6. package/esm/cesr/src/serder/serdery.js +7 -43
  7. package/esm/cesr/src/version.js +2 -2
  8. package/esm/keri/src/acdc/index.js +1 -0
  9. package/esm/keri/src/acdc/messaging.js +491 -0
  10. package/esm/keri/src/app/agent-runtime.js +46 -3
  11. package/esm/keri/src/app/cesr-http.js +13 -5
  12. package/esm/keri/src/app/cli/delegate.js +106 -10
  13. package/esm/keri/src/app/cli/did.js +182 -0
  14. package/esm/keri/src/app/cli/ends.js +40 -0
  15. package/esm/keri/src/app/cli/index.js +6 -0
  16. package/esm/keri/src/app/cli/ipex.js +786 -0
  17. package/esm/keri/src/app/cli/multisig.js +1089 -0
  18. package/esm/keri/src/app/cli/saidify.js +51 -0
  19. package/esm/keri/src/app/cli/vc.js +696 -0
  20. package/esm/keri/src/app/cli/verifier.js +104 -0
  21. package/esm/keri/src/app/delegating.js +26 -11
  22. package/esm/keri/src/app/endpoint-roleing.js +140 -0
  23. package/esm/keri/src/app/exchanging.js +44 -15
  24. package/esm/keri/src/app/forwarding.js +132 -58
  25. package/esm/keri/src/app/grouping.js +382 -0
  26. package/esm/keri/src/app/habbing.js +189 -36
  27. package/esm/keri/src/app/ipex-credentialing.js +245 -0
  28. package/esm/keri/src/app/ipexing.js +212 -0
  29. package/esm/keri/src/app/oobiery.js +62 -11
  30. package/esm/keri/src/app/parsering.js +58 -7
  31. package/esm/keri/src/app/reactor.js +30 -3
  32. package/esm/keri/src/app/schema-resolving.js +28 -0
  33. package/esm/keri/src/app/verifier-agent.js +408 -0
  34. package/esm/keri/src/app/verifying.js +358 -0
  35. package/esm/keri/src/app/version.js +2 -2
  36. package/esm/keri/src/app/witnessing.js +82 -49
  37. package/esm/keri/src/core/attachment-countering.js +105 -0
  38. package/esm/keri/src/core/mailbox-topics.js +2 -0
  39. package/esm/keri/src/core/protocol-exchanging.js +21 -15
  40. package/esm/keri/src/core/protocol-serialization.js +109 -86
  41. package/esm/keri/src/core/protocol-vdr-eventing.js +288 -0
  42. package/esm/keri/src/core/scheming.js +162 -0
  43. package/esm/keri/src/db/basing.js +34 -47
  44. package/esm/keri/src/db/index.js +1 -0
  45. package/esm/keri/src/db/reger.js +472 -0
  46. package/esm/keri/src/db/subing.js +32 -19
  47. package/esm/keri/src/db/verifier-cueing.js +125 -0
  48. package/esm/keri/src/did/index.js +7 -0
  49. package/esm/keri/src/did/keri/resolving.js +26 -0
  50. package/esm/keri/src/did/webs/artifacts.js +86 -0
  51. package/esm/keri/src/did/webs/designated-aliases-public-schema.js +156 -0
  52. package/esm/keri/src/did/webs/designated-aliases.js +235 -0
  53. package/esm/keri/src/did/webs/dids.js +186 -0
  54. package/esm/keri/src/did/webs/documenting.js +190 -0
  55. package/esm/keri/src/did/webs/resolving.js +115 -0
  56. package/esm/keri/src/library/index.js +1 -0
  57. package/esm/keri/src/runtime/index.js +13 -0
  58. package/esm/keri/src/vdr/credentialing.js +557 -0
  59. package/esm/keri/src/vdr/eventing.js +931 -0
  60. package/package.json +3 -2
  61. package/types/cesr/src/primitives/counter.d.ts +8 -0
  62. package/types/cesr/src/primitives/counter.d.ts.map +1 -1
  63. package/types/cesr/src/primitives/mapper.d.ts.map +1 -1
  64. package/types/cesr/src/serder/native.d.ts +9 -0
  65. package/types/cesr/src/serder/native.d.ts.map +1 -1
  66. package/types/cesr/src/serder/serder.d.ts.map +1 -1
  67. package/types/cesr/src/serder/serdery.d.ts.map +1 -1
  68. package/types/cesr/src/version.d.ts +2 -2
  69. package/types/keri/src/acdc/index.d.ts +2 -0
  70. package/types/keri/src/acdc/index.d.ts.map +1 -0
  71. package/types/keri/src/acdc/messaging.d.ts +104 -0
  72. package/types/keri/src/acdc/messaging.d.ts.map +1 -0
  73. package/types/keri/src/app/agent-runtime.d.ts +3 -1
  74. package/types/keri/src/app/agent-runtime.d.ts.map +1 -1
  75. package/types/keri/src/app/cesr-http.d.ts +2 -1
  76. package/types/keri/src/app/cesr-http.d.ts.map +1 -1
  77. package/types/keri/src/app/cli/delegate.d.ts.map +1 -1
  78. package/types/keri/src/app/cli/did.d.ts +10 -0
  79. package/types/keri/src/app/cli/did.d.ts.map +1 -0
  80. package/types/keri/src/app/cli/ends.d.ts.map +1 -1
  81. package/types/keri/src/app/cli/index.d.ts +6 -0
  82. package/types/keri/src/app/cli/index.d.ts.map +1 -1
  83. package/types/keri/src/app/cli/ipex.d.ts +20 -0
  84. package/types/keri/src/app/cli/ipex.d.ts.map +1 -0
  85. package/types/keri/src/app/cli/multisig.d.ts +12 -0
  86. package/types/keri/src/app/cli/multisig.d.ts.map +1 -0
  87. package/types/keri/src/app/cli/saidify.d.ts +4 -0
  88. package/types/keri/src/app/cli/saidify.d.ts.map +1 -0
  89. package/types/keri/src/app/cli/vc.d.ts +20 -0
  90. package/types/keri/src/app/cli/vc.d.ts.map +1 -0
  91. package/types/keri/src/app/cli/verifier.d.ts +3 -0
  92. package/types/keri/src/app/cli/verifier.d.ts.map +1 -0
  93. package/types/keri/src/app/delegating.d.ts +1 -0
  94. package/types/keri/src/app/delegating.d.ts.map +1 -1
  95. package/types/keri/src/app/endpoint-roleing.d.ts +46 -0
  96. package/types/keri/src/app/endpoint-roleing.d.ts.map +1 -0
  97. package/types/keri/src/app/exchanging.d.ts +7 -0
  98. package/types/keri/src/app/exchanging.d.ts.map +1 -1
  99. package/types/keri/src/app/forwarding.d.ts +7 -1
  100. package/types/keri/src/app/forwarding.d.ts.map +1 -1
  101. package/types/keri/src/app/grouping.d.ts +111 -0
  102. package/types/keri/src/app/grouping.d.ts.map +1 -0
  103. package/types/keri/src/app/habbing.d.ts +51 -4
  104. package/types/keri/src/app/habbing.d.ts.map +1 -1
  105. package/types/keri/src/app/ipex-credentialing.d.ts +88 -0
  106. package/types/keri/src/app/ipex-credentialing.d.ts.map +1 -0
  107. package/types/keri/src/app/ipexing.d.ts +84 -0
  108. package/types/keri/src/app/ipexing.d.ts.map +1 -0
  109. package/types/keri/src/app/oobiery.d.ts +3 -0
  110. package/types/keri/src/app/oobiery.d.ts.map +1 -1
  111. package/types/keri/src/app/parsering.d.ts +45 -3
  112. package/types/keri/src/app/parsering.d.ts.map +1 -1
  113. package/types/keri/src/app/protocol-host-policy.d.ts +8 -0
  114. package/types/keri/src/app/protocol-host-policy.d.ts.map +1 -1
  115. package/types/keri/src/app/reactor.d.ts +31 -1
  116. package/types/keri/src/app/reactor.d.ts.map +1 -1
  117. package/types/keri/src/app/schema-resolving.d.ts +31 -0
  118. package/types/keri/src/app/schema-resolving.d.ts.map +1 -0
  119. package/types/keri/src/app/verifier-agent.d.ts +82 -0
  120. package/types/keri/src/app/verifier-agent.d.ts.map +1 -0
  121. package/types/keri/src/app/verifying.d.ts +111 -0
  122. package/types/keri/src/app/verifying.d.ts.map +1 -0
  123. package/types/keri/src/app/version.d.ts +2 -2
  124. package/types/keri/src/app/witnessing.d.ts.map +1 -1
  125. package/types/keri/src/core/attachment-countering.d.ts +39 -0
  126. package/types/keri/src/core/attachment-countering.d.ts.map +1 -0
  127. package/types/keri/src/core/cues.d.ts +28 -3
  128. package/types/keri/src/core/cues.d.ts.map +1 -1
  129. package/types/keri/src/core/mailbox-topics.d.ts +2 -0
  130. package/types/keri/src/core/mailbox-topics.d.ts.map +1 -1
  131. package/types/keri/src/core/protocol-exchanging.d.ts +2 -1
  132. package/types/keri/src/core/protocol-exchanging.d.ts.map +1 -1
  133. package/types/keri/src/core/protocol-serialization.d.ts +38 -4
  134. package/types/keri/src/core/protocol-serialization.d.ts.map +1 -1
  135. package/types/keri/src/core/protocol-vdr-eventing.d.ts +69 -0
  136. package/types/keri/src/core/protocol-vdr-eventing.d.ts.map +1 -0
  137. package/types/keri/src/core/scheming.d.ts +38 -0
  138. package/types/keri/src/core/scheming.d.ts.map +1 -0
  139. package/types/keri/src/db/basing.d.ts +2 -2
  140. package/types/keri/src/db/basing.d.ts.map +1 -1
  141. package/types/keri/src/db/index.d.ts +1 -0
  142. package/types/keri/src/db/index.d.ts.map +1 -1
  143. package/types/keri/src/db/reger.d.ts +91 -0
  144. package/types/keri/src/db/reger.d.ts.map +1 -0
  145. package/types/keri/src/db/subing.d.ts +18 -3
  146. package/types/keri/src/db/subing.d.ts.map +1 -1
  147. package/types/keri/src/db/verifier-cueing.d.ts +46 -0
  148. package/types/keri/src/db/verifier-cueing.d.ts.map +1 -0
  149. package/types/keri/src/did/index.d.ts +8 -0
  150. package/types/keri/src/did/index.d.ts.map +1 -0
  151. package/types/keri/src/did/keri/resolving.d.ts +19 -0
  152. package/types/keri/src/did/keri/resolving.d.ts.map +1 -0
  153. package/types/keri/src/did/webs/artifacts.d.ts +19 -0
  154. package/types/keri/src/did/webs/artifacts.d.ts.map +1 -0
  155. package/types/keri/src/did/webs/designated-aliases-public-schema.d.ts +147 -0
  156. package/types/keri/src/did/webs/designated-aliases-public-schema.d.ts.map +1 -0
  157. package/types/keri/src/did/webs/designated-aliases.d.ts +46 -0
  158. package/types/keri/src/did/webs/designated-aliases.d.ts.map +1 -0
  159. package/types/keri/src/did/webs/dids.d.ts +65 -0
  160. package/types/keri/src/did/webs/dids.d.ts.map +1 -0
  161. package/types/keri/src/did/webs/documenting.d.ts +29 -0
  162. package/types/keri/src/did/webs/documenting.d.ts.map +1 -0
  163. package/types/keri/src/did/webs/resolving.d.ts +22 -0
  164. package/types/keri/src/did/webs/resolving.d.ts.map +1 -0
  165. package/types/keri/src/library/index.d.ts +1 -0
  166. package/types/keri/src/library/index.d.ts.map +1 -1
  167. package/types/keri/src/runtime/index.d.ts +13 -0
  168. package/types/keri/src/runtime/index.d.ts.map +1 -1
  169. package/types/keri/src/vdr/credentialing.d.ts +169 -0
  170. package/types/keri/src/vdr/credentialing.d.ts.map +1 -0
  171. package/types/keri/src/vdr/eventing.d.ts +157 -0
  172. package/types/keri/src/vdr/eventing.d.ts.map +1 -0
package/README.md CHANGED
@@ -18,6 +18,16 @@ npm install keri-ts
18
18
  Only those three entrypoints are supported public surfaces. Runnable CLI/server
19
19
  ownership lives in the separate `tufa` package.
20
20
 
21
+ ## Maintainer Docs
22
+
23
+ - `docs/ARCHITECTURE_MAP.md`: package and module ownership map
24
+ - `docs/design-docs/keri/ACDC_TEL_IPEX_VERIFIER_MAINTAINER_GUIDE.md`:
25
+ credential stack ownership and failure modes
26
+ - `docs/design-docs/keri/DELEGATION_MULTISIG_ENDPOINT_ROLES_MAINTAINER_GUIDE.md`:
27
+ delegation, group coordination, and endpoint-role mental model
28
+ - `docs/design-docs/keri/ATTACHMENT_COUNTER_GVRSN_MAINTAINER_GUIDE.md`:
29
+ attachment counter versioning and replay boundaries
30
+
21
31
  ## License
22
32
 
23
33
  Licensed under the Apache License, Version 2.0 (`Apache-2.0`). See the top-level
@@ -1,5 +1,6 @@
1
- import { b, b64ToInt, codeB2ToB64, codeB64ToB2, intToB64, nabSextets, sceil } from "../core/bytes.js";
1
+ import { b, b64ToInt, codeB2ToB64, codeB64ToB2, concatBytes, intToB64, nabSextets, sceil } from "../core/bytes.js";
2
2
  import { DeserializeError, ShortageError, UnknownCodeError } from "../core/errors.js";
3
+ import { CtrDexV2 } from "../tables/counter-codex.js";
3
4
  import { resolveCounterCodeNameTable, resolveCounterSizeTable } from "../tables/counter-version-registry.js";
4
5
  import { COUNTER_HARDS } from "../tables/counter.tables.generated.js";
5
6
  const COUNTER_BARDS = new Map([...COUNTER_HARDS.entries()].map(([code, hs]) => [
@@ -126,6 +127,38 @@ function encodeCounterFromFields(code, count, version) {
126
127
  version,
127
128
  };
128
129
  }
130
+ function semanticNameForCode(code, version) {
131
+ const nameTable = resolveCounterCodeNameTable(version);
132
+ return nameTable[code] ?? null;
133
+ }
134
+ function codeForSemanticName(name, version) {
135
+ const nameTable = resolveCounterCodeNameTable(version);
136
+ for (const [code, candidate] of Object.entries(nameTable)) {
137
+ if (candidate === name) {
138
+ return code;
139
+ }
140
+ }
141
+ return null;
142
+ }
143
+ function promoteCounterCodeForCount(code, count, version) {
144
+ const sizeTable = resolveCounterSizeTable(version);
145
+ const sizage = sizeTable.get(code);
146
+ if (!sizage) {
147
+ throw new UnknownCodeError(`Unsupported counter code for version: ${code}`);
148
+ }
149
+ if (count <= (64 ** sizage.ss) - 1) {
150
+ return code;
151
+ }
152
+ const name = semanticNameForCode(code, version);
153
+ if (!name || name.startsWith("Big")) {
154
+ throw new DeserializeError(`Invalid count=${count} for code=${code}`);
155
+ }
156
+ const bigCode = codeForSemanticName(`Big${name}`, version);
157
+ if (!bigCode) {
158
+ throw new DeserializeError(`Counter code=${code} has no Big${name} form.`);
159
+ }
160
+ return bigCode;
161
+ }
129
162
  /** Normalize the supported constructor variants into one shared counter payload. */
130
163
  function parseCounterInit(init) {
131
164
  const version = init.version ?? { major: 2, minor: 0 };
@@ -152,6 +185,34 @@ function parseCounterInit(init) {
152
185
  * payload groups and carry versioned code-name semantics.
153
186
  */
154
187
  export class Counter {
188
+ static makeGVC(version) {
189
+ return new Counter({
190
+ code: CtrDexV2.KERIACDCGenusVersion,
191
+ countB64: `${intToB64(version.major, 1)}${intToB64(version.minor, 2)}`,
192
+ version,
193
+ }).qb64b;
194
+ }
195
+ static enclose({ qb64 = undefined, qb2 = undefined, code = "AttachmentGroup", version = { major: 2, minor: 0 }, } = {}) {
196
+ const actualQb64 = typeof qb64 === "string" ? b(qb64) : qb64;
197
+ if (actualQb64 !== undefined && actualQb64 !== null) {
198
+ if (actualQb64.length % 4 !== 0) {
199
+ throw new DeserializeError(`Bad enclosed qb64 length=${actualQb64.length}`);
200
+ }
201
+ const count = actualQb64.length / 4;
202
+ const counterCode = promoteCounterCodeForCount(codeForSemanticName(code, version) ?? code, count, version);
203
+ return concatBytes(new Counter({ code: counterCode, count, version }).qb64b, actualQb64);
204
+ }
205
+ if (qb2 !== undefined && qb2 !== null) {
206
+ if (qb2.length % 3 !== 0) {
207
+ throw new DeserializeError(`Bad enclosed qb2 length=${qb2.length}`);
208
+ }
209
+ const count = qb2.length / 3;
210
+ const counterCode = promoteCounterCodeForCount(codeForSemanticName(code, version) ?? code, count, version);
211
+ return concatBytes(new Counter({ code: counterCode, count, version }).qb2, qb2);
212
+ }
213
+ const counterCode = promoteCounterCodeForCount(codeForSemanticName(code, version) ?? code, 0, version);
214
+ return new Counter({ code: counterCode, count: 0, version }).qb64b;
215
+ }
155
216
  constructor(init) {
156
217
  Object.defineProperty(this, "_code", {
157
218
  enumerable: true,
@@ -195,11 +256,7 @@ export class Counter {
195
256
  writable: true,
196
257
  value: void 0
197
258
  });
198
- const data = init instanceof Counter
199
- ? init.toCounterData()
200
- : isCounterData(init)
201
- ? init
202
- : parseCounterInit(init);
259
+ const data = init instanceof Counter ? init.toCounterData() : isCounterData(init) ? init : parseCounterInit(init);
203
260
  this._code = data.code;
204
261
  this._count = data.count;
205
262
  this._fullSize = data.fullSize;
@@ -287,7 +344,5 @@ export function parseCounterFromBinary(input, version) {
287
344
  }
288
345
  /** Parse counter using domain hint (`txt` or `bny`) and versioned codex tables. */
289
346
  export function parseCounter(input, version, cold) {
290
- return cold === "bny"
291
- ? parseCounterFromBinary(input, version)
292
- : parseCounterFromText(input, version);
347
+ return cold === "bny" ? parseCounterFromBinary(input, version) : parseCounterFromText(input, version);
293
348
  }
@@ -149,9 +149,7 @@ export function interpretMapperBodySyntax(syntax) {
149
149
  label: pendingLabel,
150
150
  primitive: entry.primitive,
151
151
  isCounter: entry.isCounter,
152
- children: entry.children
153
- ? interpretMapperBodySyntax(entry.children)
154
- : undefined,
152
+ children: entry.children ? interpretMapperBodySyntax(entry.children) : undefined,
155
153
  });
156
154
  pendingLabel = null;
157
155
  }
@@ -215,19 +213,13 @@ function encodeTag(text) {
215
213
  if (!code) {
216
214
  throw new SerializeError(`Unsupported mapper tag length=${text.length}`);
217
215
  }
218
- const pad = code === LabelDex.Tag1 || code === LabelDex.Tag5 || code === LabelDex.Tag9
219
- ? "_"
220
- : "";
216
+ const pad = code === LabelDex.Tag1 || code === LabelDex.Tag5 || code === LabelDex.Tag9 ? "_" : "";
221
217
  return `${code}${pad}${text}`;
222
218
  }
223
219
  /** Encode base64-safe text through the compact StrB64/Bexter families. */
224
220
  function encodeBext(text) {
225
221
  const rem = text.length % 4;
226
- const code = rem === 0
227
- ? LabelDex.StrB64_L0
228
- : rem === 1
229
- ? LabelDex.StrB64_L1
230
- : LabelDex.StrB64_L2;
222
+ const code = rem === 0 ? LabelDex.StrB64_L0 : rem === 1 ? LabelDex.StrB64_L1 : LabelDex.StrB64_L2;
231
223
  const raw = Bexter.rawify(text);
232
224
  return new Bexter({ code, raw }).qb64;
233
225
  }
@@ -235,13 +227,16 @@ function encodeBext(text) {
235
227
  function encodeBytes(text) {
236
228
  const raw = b(text);
237
229
  const rem = raw.length % 3;
238
- const code = rem === 0
239
- ? LabelDex.Bytes_L0
240
- : rem === 1
241
- ? LabelDex.Bytes_L1
242
- : LabelDex.Bytes_L2;
230
+ const code = rem === 0 ? LabelDex.Bytes_L0 : rem === 1 ? LabelDex.Bytes_L1 : LabelDex.Bytes_L2;
243
231
  return new Texter({ code, raw }).qb64;
244
232
  }
233
+ function encodeShortLabel(text) {
234
+ const raw = b(text);
235
+ return new Matter({
236
+ code: raw.length === 1 ? LabelDex.Label1 : LabelDex.Label2,
237
+ raw,
238
+ }).qb64;
239
+ }
245
240
  /**
246
241
  * Choose the narrowest native text encoding that can round-trip `text`.
247
242
  *
@@ -260,6 +255,26 @@ function encodeText(text) {
260
255
  }
261
256
  return encodeBytes(text);
262
257
  }
258
+ /** Encode scalar string values with KERIpy's tag-or-bytes native map policy. */
259
+ function encodeValueText(text) {
260
+ if (text.length === 0) {
261
+ return LabelDex.Empty;
262
+ }
263
+ if (/^[A-Za-z0-9_-]+$/.test(text)) {
264
+ if (text.length <= 11) {
265
+ return encodeTag(text);
266
+ }
267
+ const wadSize = (4 - (text.length % 4)) % 4;
268
+ if (text[0] !== "A" || (wadSize !== 0 && wadSize !== 1)) {
269
+ return encodeBext(text);
270
+ }
271
+ return encodeBytes(text);
272
+ }
273
+ if (text.length === 1 || text.length === 2) {
274
+ return encodeShortLabel(text);
275
+ }
276
+ return encodeBytes(text);
277
+ }
263
278
  function serializeValue(value, strict) {
264
279
  // This is the recursive mapper exhale ladder. Ordering matters because a
265
280
  // string might be either already-qualified CESR text or ordinary text that
@@ -280,42 +295,36 @@ function serializeValue(value, strict) {
280
295
  return new Decimer({ dns: value.toString() }).qb64;
281
296
  }
282
297
  if (typeof value === "string") {
283
- try {
284
- const primitive = parseMatter(b(value), "txt");
285
- if (primitive.qb64.length === value.length) {
286
- const escape = ESCAPE_CODES.has(primitive.code)
287
- ? new Matter({ code: MtrDex.Escape, raw: new Uint8Array() }).qb64
288
- : "";
289
- return `${escape}${primitive.qb64}`;
298
+ if (/^[A-Za-z0-9_-]+$/.test(value)) {
299
+ try {
300
+ const primitive = parseMatter(b(value), "txt");
301
+ if (primitive.qb64.length === value.length) {
302
+ const escape = ESCAPE_CODES.has(primitive.code)
303
+ ? new Matter({ code: MtrDex.Escape, raw: new Uint8Array() }).qb64
304
+ : "";
305
+ return `${escape}${primitive.qb64}`;
306
+ }
307
+ }
308
+ catch {
309
+ // fall through to text encoding
290
310
  }
291
311
  }
292
- catch {
293
- // fall through to text encoding
294
- }
295
- return encodeText(value);
312
+ return encodeValueText(value);
296
313
  }
297
314
  if (value instanceof Uint8Array) {
298
315
  return new Texter({
299
- code: value.length % 3 === 0
300
- ? LabelDex.Bytes_L0
301
- : value.length % 3 === 1
302
- ? LabelDex.Bytes_L1
303
- : LabelDex.Bytes_L2,
316
+ code: value.length % 3 === 0 ? LabelDex.Bytes_L0 : value.length % 3 === 1 ? LabelDex.Bytes_L1 : LabelDex.Bytes_L2,
304
317
  raw: value,
305
318
  }).qb64;
306
319
  }
307
320
  if (Array.isArray(value)) {
308
321
  const payload = value.map((entry) => serializeValue(entry, strict)).join("");
309
- const code = payload.length / 4 < 64 ** 2
310
- ? CtrDexV2.GenericListGroup
311
- : CtrDexV2.BigGenericListGroup;
322
+ const code = payload.length / 4 < 64 ** 2 ? CtrDexV2.GenericListGroup : CtrDexV2.BigGenericListGroup;
312
323
  return `${new Counter({ code, count: payload.length / 4 }).qb64}${payload}`;
313
324
  }
314
325
  if (value && typeof value === "object") {
315
326
  const payload = Object.entries(value).map(([label, entry]) => `${strict ? encodeText(label) : encodeText(label)}${serializeValue(entry, strict)}`).join("");
316
- const code = payload.length / 4 < 64 ** 2
317
- ? CtrDexV2.GenericMapGroup
318
- : CtrDexV2.BigGenericMapGroup;
327
+ const code = payload.length / 4 < 64 ** 2 ? CtrDexV2.GenericMapGroup : CtrDexV2.BigGenericMapGroup;
319
328
  return `${new Counter({ code, count: payload.length / 4 }).qb64}${payload}`;
320
329
  }
321
330
  throw new SerializeError(`Nonserializable mapper value=${String(value)}`);
@@ -687,9 +696,7 @@ export class Mapper {
687
696
  : serializeValue(value, strict);
688
697
  return `${encodeText(label)}${rendered}`;
689
698
  }).join("");
690
- const code = payload.length / 4 < 64 ** 2
691
- ? CtrDexV2.GenericMapGroup
692
- : CtrDexV2.BigGenericMapGroup;
699
+ const code = payload.length / 4 < 64 ** 2 ? CtrDexV2.GenericMapGroup : CtrDexV2.BigGenericMapGroup;
693
700
  return b(`${new Counter({ code, count: payload.length / 4 }).qb64}${payload}`);
694
701
  }
695
702
  static serializeNonNativeMap(mad, kind) {
@@ -1,6 +1,7 @@
1
1
  import { b, codeB2ToB64, intToB64, t } from "../core/bytes.js";
2
- import { DeserializeError, SerializeError } from "../core/errors.js";
2
+ import { DeserializeError, SerializeError, ShortageError, UnknownCodeError } from "../core/errors.js";
3
3
  import { Ilks } from "../core/vocabulary.js";
4
+ import { sniff } from "../parser/cold-start.js";
4
5
  import { parseAttachmentDispatch } from "../parser/group-dispatch.js";
5
6
  import { Aggor, isAggorListCode, isAggorMapCode, parseAggor } from "../primitives/aggor.js";
6
7
  import { Bexter } from "../primitives/bexter.js";
@@ -116,36 +117,78 @@ export function canonicalizeCesrNativeRaw(raw, version) {
116
117
  }
117
118
  return b(codeB2ToB64(raw, nativeQb64Size(raw, version)));
118
119
  }
120
+ /**
121
+ * Reap one CESR-native body group and derive the smellage metadata that
122
+ * non-native bodies expose through `smell()`.
123
+ */
124
+ export function reapCesrNativeBody(input, version = Vrsn_2_0) {
125
+ const cold = sniff(input);
126
+ if (cold !== "txt" && cold !== "bny") {
127
+ return null;
128
+ }
129
+ let counter;
130
+ try {
131
+ counter = parseCounter(input, version, cold);
132
+ }
133
+ catch (error) {
134
+ if (error instanceof ShortageError) {
135
+ throw error;
136
+ }
137
+ if (error instanceof UnknownCodeError || error instanceof DeserializeError) {
138
+ return null;
139
+ }
140
+ throw error;
141
+ }
142
+ if (counter.code !== CtrDexV2.FixBodyGroup
143
+ && counter.code !== CtrDexV2.BigFixBodyGroup
144
+ && counter.code !== CtrDexV2.MapBodyGroup
145
+ && counter.code !== CtrDexV2.BigMapBodyGroup) {
146
+ return null;
147
+ }
148
+ const consumed = cold === "txt" ? counter.fullSize + counter.count * 4 : counter.fullSizeB2 + counter.count * 3;
149
+ if (input.length < consumed) {
150
+ throw new ShortageError(consumed, input.length);
151
+ }
152
+ const raw = canonicalizeCesrNativeRaw(input.slice(0, consumed), version);
153
+ const textCounter = parseCounter(raw, version, "txt");
154
+ let offset = textCounter.fullSize;
155
+ if (textCounter.code === CtrDexV2.MapBodyGroup
156
+ || textCounter.code === CtrDexV2.BigMapBodyGroup) {
157
+ offset += parseLabeler(raw.slice(offset), "txt").fullSize;
158
+ }
159
+ const verser = parseVerser(raw.slice(offset), "txt");
160
+ return {
161
+ raw,
162
+ smellage: {
163
+ proto: verser.proto,
164
+ pvrsn: verser.pvrsn,
165
+ gvrsn: verser.gvrsn,
166
+ kind: Kinds.cesr,
167
+ size: raw.length,
168
+ },
169
+ consumed,
170
+ };
171
+ }
119
172
  /** Emit the narrowest fixed-width tag family that can carry `text`. */
120
173
  function encodeTag(text) {
121
174
  const code = TAG_CODES_BY_LENGTH.get(text.length);
122
175
  if (!code) {
123
176
  throw new SerializeError(`Unsupported tag length=${text.length}`);
124
177
  }
125
- const pad = code === LabelDex.Tag1 || code === LabelDex.Tag5 || code === LabelDex.Tag9
126
- ? "_"
127
- : "";
178
+ const pad = code === LabelDex.Tag1 || code === LabelDex.Tag5 || code === LabelDex.Tag9 ? "_" : "";
128
179
  return `${code}${pad}${text}`;
129
180
  }
130
181
  /** Emit base64-safe text through the StrB64/Bexter family. */
131
182
  function encodeBext(text) {
132
183
  const rem = text.length % 4;
133
- const code = rem === 0
134
- ? LabelDex.StrB64_L0
135
- : rem === 1
136
- ? LabelDex.StrB64_L1
137
- : LabelDex.StrB64_L2;
184
+ const code = rem === 0 ? LabelDex.StrB64_L0 : rem === 1 ? LabelDex.StrB64_L1 : LabelDex.StrB64_L2;
138
185
  return new Bexter({ code, raw: Bexter.rawify(text) }).qb64;
139
186
  }
140
187
  /** Emit arbitrary UTF-8 text through the bytes label family. */
141
188
  function encodeBytes(text) {
142
189
  const raw = b(text);
143
190
  const rem = raw.length % 3;
144
- const code = rem === 0
145
- ? LabelDex.Bytes_L0
146
- : rem === 1
147
- ? LabelDex.Bytes_L1
148
- : LabelDex.Bytes_L2;
191
+ const code = rem === 0 ? LabelDex.Bytes_L0 : rem === 1 ? LabelDex.Bytes_L1 : LabelDex.Bytes_L2;
149
192
  return new Texter({ code, raw }).qb64;
150
193
  }
151
194
  /**
@@ -237,9 +280,7 @@ function encodePath(path) {
237
280
  function encodeList(entries, gvrsn) {
238
281
  const frame = entries.join("");
239
282
  const count = frame.length / 4;
240
- const code = count < 64 ** 2
241
- ? CtrDexV2.GenericListGroup
242
- : CtrDexV2.BigGenericListGroup;
283
+ const code = count < 64 ** 2 ? CtrDexV2.GenericListGroup : CtrDexV2.BigGenericListGroup;
243
284
  return `${new Counter({ code, count, version: gvrsn ?? Vrsn_2_0 }).qb64}${frame}`;
244
285
  }
245
286
  /**
@@ -527,9 +568,7 @@ function parseNestedSealOrDataListField(raw, offset, gvrsn) {
527
568
  const listCounter = parseCounter(raw.slice(offset), gvrsn, "txt");
528
569
  const total = listCounter.fullSize + listCounter.count * 4;
529
570
  return {
530
- value: listCounter.count === 0
531
- ? []
532
- : decodeList(raw.slice(offset, offset + total), gvrsn),
571
+ value: listCounter.count === 0 ? [] : decodeList(raw.slice(offset, offset + total), gvrsn),
533
572
  nextOffset: offset + total,
534
573
  };
535
574
  }
@@ -1265,9 +1304,7 @@ export function dumpCesrNativeSad(sad) {
1265
1304
  const pvrsn = sad.v[4] === "1"
1266
1305
  ? { major: 1, minor: Number.parseInt(sad.v[5], 16) }
1267
1306
  : { major: 2, minor: 0 };
1268
- const gvrsn = sad.v.includes("CESR") && sad.v.length >= 19
1269
- ? { major: 2, minor: 0 }
1270
- : null;
1307
+ const gvrsn = sad.v.includes("CESR") && sad.v.length >= 19 ? { major: 2, minor: 0 } : null;
1271
1308
  const smellage = {
1272
1309
  proto: sad.v.slice(0, 4),
1273
1310
  pvrsn,
@@ -1300,9 +1337,7 @@ export function dumpCesrNativeSad(sad) {
1300
1337
  frame += encodeLabel(label);
1301
1338
  frame += encodeNativeFieldValue(sad[label], label, spec, version);
1302
1339
  }
1303
- const code = frame.length / 4 < 64 ** 2
1304
- ? CtrDexV2.MapBodyGroup
1305
- : CtrDexV2.BigMapBodyGroup;
1340
+ const code = frame.length / 4 < 64 ** 2 ? CtrDexV2.MapBodyGroup : CtrDexV2.BigMapBodyGroup;
1306
1341
  return `${new Counter({ code, count: frame.length / 4, version }).qb64}${frame}`;
1307
1342
  })()
1308
1343
  : (() => {
@@ -1317,9 +1352,7 @@ export function dumpCesrNativeSad(sad) {
1317
1352
  }
1318
1353
  frame += encodeNativeFieldValue(sad[label], label, spec, version);
1319
1354
  }
1320
- const code = frame.length / 4 < 64 ** 2
1321
- ? CtrDexV2.FixBodyGroup
1322
- : CtrDexV2.BigFixBodyGroup;
1355
+ const code = frame.length / 4 < 64 ** 2 ? CtrDexV2.FixBodyGroup : CtrDexV2.BigFixBodyGroup;
1323
1356
  return `${new Counter({ code, count: frame.length / 4, version }).qb64}${frame}`;
1324
1357
  })();
1325
1358
  return b(body);
@@ -20,7 +20,7 @@ import { Verfer } from "../primitives/verfer.js";
20
20
  import { resolveMUDex } from "../tables/counter-version-registry.js";
21
21
  import { MATTER_SIZES } from "../tables/matter.tables.generated.js";
22
22
  import { Kinds, Protocols, Vrsn_1_0, Vrsn_2_0 } from "../tables/versions.js";
23
- import { dumpCesrNativeSad, parseCesrNativeKed } from "./native.js";
23
+ import { dumpCesrNativeSad, parseCesrNativeKed, reapCesrNativeBody } from "./native.js";
24
24
  import { smell, versify } from "./smell.js";
25
25
  const ACDC_COMPACT_TOP_LEVEL_ILKS = new Set([
26
26
  Ilks.acm,
@@ -101,21 +101,19 @@ function makeNumberPrimitive(value) {
101
101
  if (value === null || value === undefined) {
102
102
  return null;
103
103
  }
104
- const bigint = typeof value === "string"
105
- ? BigInt(`0x${value || "0"}`)
106
- : typeof value === "number"
107
- ? (() => {
108
- if (!Number.isInteger(value) || value < 0) {
109
- throw new SerializeError(`Invalid numeric CESR number=${value}`);
110
- }
111
- return BigInt(value);
112
- })()
113
- : (() => {
114
- if (value < 0n) {
115
- throw new SerializeError(`Negative CESR number=${value}`);
116
- }
117
- return value;
118
- })();
104
+ const bigint = typeof value === "string" ? BigInt(`0x${value || "0"}`) : typeof value === "number"
105
+ ? (() => {
106
+ if (!Number.isInteger(value) || value < 0) {
107
+ throw new SerializeError(`Invalid numeric CESR number=${value}`);
108
+ }
109
+ return BigInt(value);
110
+ })()
111
+ : (() => {
112
+ if (value < 0n) {
113
+ throw new SerializeError(`Negative CESR number=${value}`);
114
+ }
115
+ return value;
116
+ })();
119
117
  const raw = bigintToBytes(bigint);
120
118
  const entry = NUMBER_CAPACITIES.find(({ rawSize }) => raw.length <= rawSize);
121
119
  if (!entry) {
@@ -911,22 +909,24 @@ function computeAcdcFieldVariants(label, value, kind, topLevelCompactable, compa
911
909
  }
912
910
  return { display: cloneDefault(value), compact: cloneDefault(value) };
913
911
  }
914
- function computeAcdcSad(sad, { kind, saids, compactify, }) {
912
+ function computeAcdcSad(sad, { kind, pvrsn, saids, compactify, }) {
915
913
  // This is the heart of ACDC compactification parity. KERIpy's rule is not
916
914
  // "hash the visible sad"; it is "hash the most compact sad, while optionally
917
915
  // preserving an expanded caller-visible sad".
918
916
  const displaySad = shallowCloneSad(sad);
919
917
  const compactSad = shallowCloneSad(sad);
920
918
  const ilk = typeof sad.t === "string" ? sad.t : null;
921
- const topLevelCompactable = isAcdcCompactiveIlk(ilk);
919
+ const topLevelCompactable = pvrsn.major >= 2 && isAcdcCompactiveIlk(ilk);
922
920
  const partialSection = isAcdcPartialSectionIlk(ilk);
923
- for (const label of ["s", "a", "A", "e", "r"]) {
924
- if (!(label in sad)) {
925
- continue;
921
+ if (pvrsn.major >= 2) {
922
+ for (const label of ["s", "a", "A", "e", "r"]) {
923
+ if (!(label in sad)) {
924
+ continue;
925
+ }
926
+ const variants = computeAcdcFieldVariants(label, sad[label], kind, topLevelCompactable, compactify, partialSection);
927
+ displaySad[label] = variants.display;
928
+ compactSad[label] = variants.compact;
926
929
  }
927
- const variants = computeAcdcFieldVariants(label, sad[label], kind, topLevelCompactable, compactify, partialSection);
928
- displaySad[label] = variants.display;
929
- compactSad[label] = variants.compact;
930
930
  }
931
931
  const code = saids.d ?? DigDex.Blake3_256;
932
932
  const sizage = MATTER_SIZES.get(code);
@@ -1166,10 +1166,9 @@ export class Serder {
1166
1166
  return;
1167
1167
  }
1168
1168
  if (isRawInit(init)) {
1169
- const smellage = init.smellage ?? smell(init.raw).smellage;
1170
- const raw = init.raw.length === smellage.size
1171
- ? init.raw
1172
- : init.raw.slice(0, smellage.size);
1169
+ const native = init.smellage ? null : reapCesrNativeBody(init.raw);
1170
+ const smellage = init.smellage ?? native?.smellage ?? smell(init.raw).smellage;
1171
+ const raw = native?.raw ?? (init.raw.length === smellage.size ? init.raw : init.raw.slice(0, smellage.size));
1173
1172
  const parsed = parseRawToKed(raw, smellage);
1174
1173
  this.raw = raw;
1175
1174
  this.kind = smellage.kind;
@@ -1203,6 +1202,7 @@ export class Serder {
1203
1202
  ? resolved.proto === Protocols.acdc
1204
1203
  ? computeAcdcSad(normalized, {
1205
1204
  kind: resolved.kind,
1205
+ pvrsn: resolved.pvrsn,
1206
1206
  saids: resolved.saids,
1207
1207
  compactify: init.compactify ?? false,
1208
1208
  })
@@ -1526,25 +1526,19 @@ export class SerderKERI extends Serder {
1526
1526
  return this.sealRecords.filter(isSealEventRecord);
1527
1527
  }
1528
1528
  get traits() {
1529
- return Array.isArray(this.ked?.c)
1530
- ? this.ked.c.filter((value) => typeof value === "string")
1531
- : [];
1529
+ return Array.isArray(this.ked?.c) ? this.ked.c.filter((value) => typeof value === "string") : [];
1532
1530
  }
1533
1531
  get tholder() {
1534
1532
  return makeThreshold(this.ked?.kt ?? null);
1535
1533
  }
1536
1534
  get keys() {
1537
- return Array.isArray(this.ked?.k)
1538
- ? this.ked.k.filter((value) => typeof value === "string")
1539
- : [];
1535
+ return Array.isArray(this.ked?.k) ? this.ked.k.filter((value) => typeof value === "string") : [];
1540
1536
  }
1541
1537
  get verfers() {
1542
1538
  return this.keys.map((key) => new Verfer({ qb64: key }));
1543
1539
  }
1544
1540
  get ndigs() {
1545
- return Array.isArray(this.ked?.n)
1546
- ? this.ked.n.filter((value) => typeof value === "string")
1547
- : [];
1541
+ return Array.isArray(this.ked?.n) ? this.ked.n.filter((value) => typeof value === "string") : [];
1548
1542
  }
1549
1543
  get ntholder() {
1550
1544
  return makeThreshold(this.ked?.nt ?? null);
@@ -1563,9 +1557,7 @@ export class SerderKERI extends Serder {
1563
1557
  return this.bner ? Number(this.bner.num) : null;
1564
1558
  }
1565
1559
  get backs() {
1566
- return Array.isArray(this.ked?.b)
1567
- ? this.ked.b.filter((value) => typeof value === "string")
1568
- : [];
1560
+ return Array.isArray(this.ked?.b) ? this.ked.b.filter((value) => typeof value === "string") : [];
1569
1561
  }
1570
1562
  get berfers() {
1571
1563
  return this.backs.map((back) => new Verfer({ qb64: back }));
@@ -1577,14 +1569,10 @@ export class SerderKERI extends Serder {
1577
1569
  return this.prior ? b(this.prior) : null;
1578
1570
  }
1579
1571
  get cuts() {
1580
- return Array.isArray(this.ked?.br)
1581
- ? this.ked.br.filter((value) => typeof value === "string")
1582
- : [];
1572
+ return Array.isArray(this.ked?.br) ? this.ked.br.filter((value) => typeof value === "string") : [];
1583
1573
  }
1584
1574
  get adds() {
1585
- return Array.isArray(this.ked?.ba)
1586
- ? this.ked.ba.filter((value) => typeof value === "string")
1587
- : [];
1575
+ return Array.isArray(this.ked?.ba) ? this.ked.ba.filter((value) => typeof value === "string") : [];
1588
1576
  }
1589
1577
  get delpre() {
1590
1578
  return this.ked && typeof this.ked.di === "string" ? this.ked.di : null;
@@ -1630,6 +1618,7 @@ export class SerderACDC extends Serder {
1630
1618
  const { ked, saids } = validateSadAgainstFieldDom(ctor, this);
1631
1619
  const actual = computeAcdcSad(shallowCloneSad(ked), {
1632
1620
  kind: this.kind,
1621
+ pvrsn: this.pvrsn,
1633
1622
  saids,
1634
1623
  compactify: false,
1635
1624
  });
@@ -1,11 +1,5 @@
1
1
  import { ShortageError } from "../core/errors.js";
2
- import { sniff } from "../parser/cold-start.js";
3
- import { parseCounter } from "../primitives/counter.js";
4
- import { parseLabeler } from "../primitives/labeler.js";
5
- import { parseVerser } from "../primitives/verser.js";
6
- import { CtrDexV2 } from "../tables/counter-codex.js";
7
- import { Vrsn_2_0 } from "../tables/versions.js";
8
- import { canonicalizeCesrNativeRaw } from "./native.js";
2
+ import { reapCesrNativeBody } from "./native.js";
9
3
  import { parseSerder } from "./serder.js";
10
4
  import { smell } from "./smell.js";
11
5
  /**
@@ -45,42 +39,12 @@ export class Serdery {
45
39
  * for that final acceptance decision.
46
40
  */
47
41
  reap(input) {
48
- const cold = sniff(input);
49
- if (cold === "txt" || cold === "bny") {
50
- const counter = parseCounter(input, Vrsn_2_0, cold);
51
- if (counter.code === CtrDexV2.FixBodyGroup
52
- || counter.code === CtrDexV2.BigFixBodyGroup
53
- || counter.code === CtrDexV2.MapBodyGroup
54
- || counter.code === CtrDexV2.BigMapBodyGroup) {
55
- const consumed = cold === "txt"
56
- ? counter.fullSize + counter.count * 4
57
- : counter.fullSizeB2 + counter.count * 3;
58
- if (input.length < consumed) {
59
- throw new ShortageError(consumed, input.length);
60
- }
61
- const raw = input.slice(0, consumed);
62
- // Native qb2 bodies are canonicalized to qb64 text before hydration so
63
- // the serder layer sees one stable native representation.
64
- const textRaw = canonicalizeCesrNativeRaw(raw, Vrsn_2_0);
65
- const textCounter = parseCounter(textRaw, Vrsn_2_0, "txt");
66
- let offset = textCounter.fullSize;
67
- if (textCounter.code === CtrDexV2.MapBodyGroup
68
- || textCounter.code === CtrDexV2.BigMapBodyGroup) {
69
- offset += parseLabeler(textRaw.slice(offset), "txt").fullSize;
70
- }
71
- const verser = parseVerser(textRaw.slice(offset), "txt");
72
- const smellage = {
73
- proto: verser.proto,
74
- pvrsn: verser.pvrsn,
75
- gvrsn: verser.gvrsn,
76
- kind: "CESR",
77
- size: textRaw.length,
78
- };
79
- return {
80
- serder: parseSerder(textRaw, smellage),
81
- consumed,
82
- };
83
- }
42
+ const native = reapCesrNativeBody(input);
43
+ if (native) {
44
+ return {
45
+ serder: parseSerder(native.raw, native.smellage),
46
+ consumed: native.consumed,
47
+ };
84
48
  }
85
49
  const { smellage } = smell(input);
86
50
  if (input.length < smellage.size) {
@@ -6,9 +6,9 @@
6
6
  * `src/version.ts` files by hand; edit this template instead.
7
7
  */
8
8
  /** Package semantic version copied from the owning package manifest. */
9
- export const PACKAGE_VERSION = "0.7.0";
9
+ export const PACKAGE_VERSION = "0.9.0";
10
10
  /** Optional build metadata stamp injected by release/CI workflows. */
11
- export const BUILD_METADATA = "build.12.6aeea4790568f27066636c48ec39d2f098e3c26d";
11
+ export const BUILD_METADATA = "build.14.a6b6e2ba5a202ef9b6cd9eaeb62fabdb904cc8f3";
12
12
  /** User-facing version string with build metadata appended when present. */
13
13
  export const DISPLAY_VERSION = BUILD_METADATA
14
14
  ? `${PACKAGE_VERSION}+${BUILD_METADATA}`
@@ -0,0 +1 @@
1
+ export * from "./messaging.js";