@joe-broadhead/messaging 0.0.0-stage → 0.7.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 (257) hide show
  1. package/CHANGELOG.md +175 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE +12 -0
  4. package/README.md +36 -2
  5. package/dist/bin/messaging-mcp.js +25887 -0
  6. package/dist/bin/messaging-relay.js +19014 -0
  7. package/dist/bin/messaging.js +14732 -0
  8. package/dist/bin/messagingd.js +28682 -0
  9. package/dist/lib/core-testing.js +1 -0
  10. package/dist/lib/core.js +1 -0
  11. package/dist/lib/ipc-testing.js +1 -0
  12. package/dist/lib/ipc.js +1 -0
  13. package/dist/lib/modules/core/address.js +42 -0
  14. package/dist/lib/modules/core/agent/operations.js +595 -0
  15. package/dist/lib/modules/core/agent/present.js +244 -0
  16. package/dist/lib/modules/core/agent/text.js +79 -0
  17. package/dist/lib/modules/core/agent-tools.js +458 -0
  18. package/dist/lib/modules/core/b64u.js +20 -0
  19. package/dist/lib/modules/core/cards.js +55 -0
  20. package/dist/lib/modules/core/check.js +20 -0
  21. package/dist/lib/modules/core/consent.js +199 -0
  22. package/dist/lib/modules/core/contact-card.js +74 -0
  23. package/dist/lib/modules/core/delegation.js +174 -0
  24. package/dist/lib/modules/core/directory/device-log.js +258 -0
  25. package/dist/lib/modules/core/directory/epoch.js +103 -0
  26. package/dist/lib/modules/core/directory/handle.js +29 -0
  27. package/dist/lib/modules/core/directory/jelly-device.js +204 -0
  28. package/dist/lib/modules/core/directory/jelly-issuer.js +12 -0
  29. package/dist/lib/modules/core/directory/jelly-token.js +305 -0
  30. package/dist/lib/modules/core/directory/keys-statement.js +43 -0
  31. package/dist/lib/modules/core/directory/link.js +81 -0
  32. package/dist/lib/modules/core/directory/merkle-log.js +250 -0
  33. package/dist/lib/modules/core/directory/person-view.js +197 -0
  34. package/dist/lib/modules/core/directory/person.js +40 -0
  35. package/dist/lib/modules/core/directory/realm.js +59 -0
  36. package/dist/lib/modules/core/directory/smt.js +266 -0
  37. package/dist/lib/modules/core/envelope.js +320 -0
  38. package/dist/lib/modules/core/hash.js +5 -0
  39. package/dist/lib/modules/core/head.js +27 -0
  40. package/dist/lib/modules/core/identity.js +71 -0
  41. package/dist/lib/modules/core/index.js +44 -0
  42. package/dist/lib/modules/core/jcs.js +96 -0
  43. package/dist/lib/modules/core/jelly-host-double.js +35 -0
  44. package/dist/lib/modules/core/jelly-host.js +211 -0
  45. package/dist/lib/modules/core/keys.js +79 -0
  46. package/dist/lib/modules/core/peer-text.js +563 -0
  47. package/dist/lib/modules/core/realm.js +1 -0
  48. package/dist/lib/modules/core/roster.js +454 -0
  49. package/dist/lib/modules/core/schema/a2a.js +85 -0
  50. package/dist/lib/modules/core/schema/common.js +254 -0
  51. package/dist/lib/modules/core/schema/consent.js +120 -0
  52. package/dist/lib/modules/core/schema/delegation.js +58 -0
  53. package/dist/lib/modules/core/schema/directory-frames.js +270 -0
  54. package/dist/lib/modules/core/schema/directory.js +169 -0
  55. package/dist/lib/modules/core/schema/envelope.js +211 -0
  56. package/dist/lib/modules/core/schema/errors.js +65 -0
  57. package/dist/lib/modules/core/schema/index.js +15 -0
  58. package/dist/lib/modules/core/schema/ipc/consent.js +181 -0
  59. package/dist/lib/modules/core/schema/ipc/device.js +276 -0
  60. package/dist/lib/modules/core/schema/ipc/jelly.js +189 -0
  61. package/dist/lib/modules/core/schema/ipc/shapes.js +185 -0
  62. package/dist/lib/modules/core/schema/ipc/surfaces.js +223 -0
  63. package/dist/lib/modules/core/schema/ipc.js +451 -0
  64. package/dist/lib/modules/core/schema/jelly.js +122 -0
  65. package/dist/lib/modules/core/schema/realm.js +27 -0
  66. package/dist/lib/modules/core/schema/relay.js +112 -0
  67. package/dist/lib/modules/core/schema/roster.js +126 -0
  68. package/dist/lib/modules/core/sign.js +43 -0
  69. package/dist/lib/modules/core/task.js +37 -0
  70. package/dist/lib/modules/core/testing.js +20 -0
  71. package/dist/lib/modules/core/ulid.js +36 -0
  72. package/dist/lib/modules/core/version.js +6 -0
  73. package/dist/lib/modules/core/wire.js +255 -0
  74. package/dist/lib/modules/ipc/client.js +289 -0
  75. package/dist/lib/modules/ipc/framing.js +33 -0
  76. package/dist/lib/modules/ipc/index.js +6 -0
  77. package/dist/lib/modules/ipc/paths.js +102 -0
  78. package/dist/lib/modules/ipc/pipes.js +65 -0
  79. package/dist/lib/modules/ipc/rpc.js +8 -0
  80. package/dist/lib/modules/ipc/server.js +317 -0
  81. package/dist/lib/modules/ipc/testing.js +145 -0
  82. package/dist/lib/modules/ipc/trust.js +166 -0
  83. package/dist/lib/modules/ipc/windows-acl.js +275 -0
  84. package/dist/lib/modules/vendor/zod/index.js +7 -0
  85. package/dist/lib/modules/vendor/zod/v4/classic/checks.js +1 -0
  86. package/dist/lib/modules/vendor/zod/v4/classic/coerce.js +17 -0
  87. package/dist/lib/modules/vendor/zod/v4/classic/compat.js +31 -0
  88. package/dist/lib/modules/vendor/zod/v4/classic/deep-partial.js +13 -0
  89. package/dist/lib/modules/vendor/zod/v4/classic/errors.js +57 -0
  90. package/dist/lib/modules/vendor/zod/v4/classic/external.js +17 -0
  91. package/dist/lib/modules/vendor/zod/v4/classic/from-json-schema.js +881 -0
  92. package/dist/lib/modules/vendor/zod/v4/classic/in-out.js +36 -0
  93. package/dist/lib/modules/vendor/zod/v4/classic/iso.js +15 -0
  94. package/dist/lib/modules/vendor/zod/v4/classic/parse.js +16 -0
  95. package/dist/lib/modules/vendor/zod/v4/classic/schemas.js +1535 -0
  96. package/dist/lib/modules/vendor/zod/v4/core/api.js +1107 -0
  97. package/dist/lib/modules/vendor/zod/v4/core/checks.js +516 -0
  98. package/dist/lib/modules/vendor/zod/v4/core/compile.js +1866 -0
  99. package/dist/lib/modules/vendor/zod/v4/core/core.js +141 -0
  100. package/dist/lib/modules/vendor/zod/v4/core/doc.js +38 -0
  101. package/dist/lib/modules/vendor/zod/v4/core/errors.js +267 -0
  102. package/dist/lib/modules/vendor/zod/v4/core/index.js +19 -0
  103. package/dist/lib/modules/vendor/zod/v4/core/json-schema-generator.js +99 -0
  104. package/dist/lib/modules/vendor/zod/v4/core/json-schema-processors.js +843 -0
  105. package/dist/lib/modules/vendor/zod/v4/core/json-schema.js +1 -0
  106. package/dist/lib/modules/vendor/zod/v4/core/memoizer.js +311 -0
  107. package/dist/lib/modules/vendor/zod/v4/core/parse.js +175 -0
  108. package/dist/lib/modules/vendor/zod/v4/core/regexes.js +156 -0
  109. package/dist/lib/modules/vendor/zod/v4/core/registries.js +51 -0
  110. package/dist/lib/modules/vendor/zod/v4/core/schemas.js +2636 -0
  111. package/dist/lib/modules/vendor/zod/v4/core/to-json-schema.js +651 -0
  112. package/dist/lib/modules/vendor/zod/v4/core/util.js +873 -0
  113. package/dist/lib/modules/vendor/zod/v4/core/versions.js +5 -0
  114. package/dist/lib/modules/vendor/zod/v4/core/visit.js +169 -0
  115. package/dist/lib/modules/vendor/zod/v4/locales/ar.js +111 -0
  116. package/dist/lib/modules/vendor/zod/v4/locales/az.js +110 -0
  117. package/dist/lib/modules/vendor/zod/v4/locales/be.js +168 -0
  118. package/dist/lib/modules/vendor/zod/v4/locales/bg.js +125 -0
  119. package/dist/lib/modules/vendor/zod/v4/locales/bn.js +113 -0
  120. package/dist/lib/modules/vendor/zod/v4/locales/ca.js +112 -0
  121. package/dist/lib/modules/vendor/zod/v4/locales/ckb.js +133 -0
  122. package/dist/lib/modules/vendor/zod/v4/locales/cs.js +116 -0
  123. package/dist/lib/modules/vendor/zod/v4/locales/da.js +120 -0
  124. package/dist/lib/modules/vendor/zod/v4/locales/de.js +113 -0
  125. package/dist/lib/modules/vendor/zod/v4/locales/el.js +112 -0
  126. package/dist/lib/modules/vendor/zod/v4/locales/en.js +125 -0
  127. package/dist/lib/modules/vendor/zod/v4/locales/eo.js +114 -0
  128. package/dist/lib/modules/vendor/zod/v4/locales/es.js +136 -0
  129. package/dist/lib/modules/vendor/zod/v4/locales/fa.js +119 -0
  130. package/dist/lib/modules/vendor/zod/v4/locales/fi.js +117 -0
  131. package/dist/lib/modules/vendor/zod/v4/locales/fr-CA.js +112 -0
  132. package/dist/lib/modules/vendor/zod/v4/locales/fr.js +129 -0
  133. package/dist/lib/modules/vendor/zod/v4/locales/gu.js +113 -0
  134. package/dist/lib/modules/vendor/zod/v4/locales/he.js +221 -0
  135. package/dist/lib/modules/vendor/zod/v4/locales/hi.js +111 -0
  136. package/dist/lib/modules/vendor/zod/v4/locales/hr.js +126 -0
  137. package/dist/lib/modules/vendor/zod/v4/locales/hu.js +113 -0
  138. package/dist/lib/modules/vendor/zod/v4/locales/hy.js +158 -0
  139. package/dist/lib/modules/vendor/zod/v4/locales/id.js +111 -0
  140. package/dist/lib/modules/vendor/zod/v4/locales/index.js +63 -0
  141. package/dist/lib/modules/vendor/zod/v4/locales/is.js +114 -0
  142. package/dist/lib/modules/vendor/zod/v4/locales/it.js +113 -0
  143. package/dist/lib/modules/vendor/zod/v4/locales/ja.js +112 -0
  144. package/dist/lib/modules/vendor/zod/v4/locales/ka.js +117 -0
  145. package/dist/lib/modules/vendor/zod/v4/locales/kh.js +5 -0
  146. package/dist/lib/modules/vendor/zod/v4/locales/km.js +115 -0
  147. package/dist/lib/modules/vendor/zod/v4/locales/kn.js +116 -0
  148. package/dist/lib/modules/vendor/zod/v4/locales/ko.js +116 -0
  149. package/dist/lib/modules/vendor/zod/v4/locales/lt.js +207 -0
  150. package/dist/lib/modules/vendor/zod/v4/locales/mk.js +114 -0
  151. package/dist/lib/modules/vendor/zod/v4/locales/ms.js +112 -0
  152. package/dist/lib/modules/vendor/zod/v4/locales/ne.js +111 -0
  153. package/dist/lib/modules/vendor/zod/v4/locales/nl.js +115 -0
  154. package/dist/lib/modules/vendor/zod/v4/locales/nn.js +113 -0
  155. package/dist/lib/modules/vendor/zod/v4/locales/no.js +113 -0
  156. package/dist/lib/modules/vendor/zod/v4/locales/ota.js +114 -0
  157. package/dist/lib/modules/vendor/zod/v4/locales/pl.js +114 -0
  158. package/dist/lib/modules/vendor/zod/v4/locales/ps.js +119 -0
  159. package/dist/lib/modules/vendor/zod/v4/locales/pt-BR.js +143 -0
  160. package/dist/lib/modules/vendor/zod/v4/locales/pt.js +142 -0
  161. package/dist/lib/modules/vendor/zod/v4/locales/ro.js +122 -0
  162. package/dist/lib/modules/vendor/zod/v4/locales/ru.js +168 -0
  163. package/dist/lib/modules/vendor/zod/v4/locales/sk.js +116 -0
  164. package/dist/lib/modules/vendor/zod/v4/locales/sl.js +114 -0
  165. package/dist/lib/modules/vendor/zod/v4/locales/sv.js +115 -0
  166. package/dist/lib/modules/vendor/zod/v4/locales/ta.js +115 -0
  167. package/dist/lib/modules/vendor/zod/v4/locales/tg.js +117 -0
  168. package/dist/lib/modules/vendor/zod/v4/locales/th.js +115 -0
  169. package/dist/lib/modules/vendor/zod/v4/locales/tk.js +107 -0
  170. package/dist/lib/modules/vendor/zod/v4/locales/tr.js +110 -0
  171. package/dist/lib/modules/vendor/zod/v4/locales/ua.js +5 -0
  172. package/dist/lib/modules/vendor/zod/v4/locales/uk.js +113 -0
  173. package/dist/lib/modules/vendor/zod/v4/locales/ur.js +115 -0
  174. package/dist/lib/modules/vendor/zod/v4/locales/uz.js +113 -0
  175. package/dist/lib/modules/vendor/zod/v4/locales/vi.js +113 -0
  176. package/dist/lib/modules/vendor/zod/v4/locales/yo.js +112 -0
  177. package/dist/lib/modules/vendor/zod/v4/locales/zh-CN.js +114 -0
  178. package/dist/lib/modules/vendor/zod/v4/locales/zh-TW.js +112 -0
  179. package/dist/lib/testing-jelly-id.js +1219 -0
  180. package/dist/lib/zod.js +1 -0
  181. package/dist/spec/messaging-v1.md +3426 -0
  182. package/dist/third-party-notices.md +239 -0
  183. package/dist/third-party.json +88 -0
  184. package/dist/types/core/address.d.ts +16 -0
  185. package/dist/types/core/agent/operations.d.ts +129 -0
  186. package/dist/types/core/agent/present.d.ts +57 -0
  187. package/dist/types/core/agent/text.d.ts +62 -0
  188. package/dist/types/core/agent-tools.d.ts +948 -0
  189. package/dist/types/core/b64u.d.ts +6 -0
  190. package/dist/types/core/cards.d.ts +21 -0
  191. package/dist/types/core/check.d.ts +10 -0
  192. package/dist/types/core/consent.d.ts +132 -0
  193. package/dist/types/core/contact-card.d.ts +34 -0
  194. package/dist/types/core/delegation.d.ts +71 -0
  195. package/dist/types/core/directory/device-log.d.ts +119 -0
  196. package/dist/types/core/directory/epoch.d.ts +53 -0
  197. package/dist/types/core/directory/handle.d.ts +11 -0
  198. package/dist/types/core/directory/jelly-device.d.ts +88 -0
  199. package/dist/types/core/directory/jelly-issuer.d.ts +8 -0
  200. package/dist/types/core/directory/jelly-token.d.ts +116 -0
  201. package/dist/types/core/directory/keys-statement.d.ts +22 -0
  202. package/dist/types/core/directory/link.d.ts +36 -0
  203. package/dist/types/core/directory/merkle-log.d.ts +40 -0
  204. package/dist/types/core/directory/person-view.d.ts +90 -0
  205. package/dist/types/core/directory/person.d.ts +8 -0
  206. package/dist/types/core/directory/realm.d.ts +23 -0
  207. package/dist/types/core/directory/smt.d.ts +52 -0
  208. package/dist/types/core/envelope.d.ts +68 -0
  209. package/dist/types/core/hash.d.ts +2 -0
  210. package/dist/types/core/head.d.ts +34 -0
  211. package/dist/types/core/identity.d.ts +35 -0
  212. package/dist/types/core/index.d.ts +38 -0
  213. package/dist/types/core/jcs.d.ts +12 -0
  214. package/dist/types/core/jelly-host-double.d.ts +21 -0
  215. package/dist/types/core/jelly-host.d.ts +86 -0
  216. package/dist/types/core/keys.d.ts +16 -0
  217. package/dist/types/core/peer-text.d.ts +87 -0
  218. package/dist/types/core/realm.d.ts +36 -0
  219. package/dist/types/core/roster.d.ts +146 -0
  220. package/dist/types/core/schema/a2a.d.ts +251 -0
  221. package/dist/types/core/schema/common.d.ts +272 -0
  222. package/dist/types/core/schema/consent.d.ts +140 -0
  223. package/dist/types/core/schema/delegation.d.ts +58 -0
  224. package/dist/types/core/schema/directory-frames.d.ts +1301 -0
  225. package/dist/types/core/schema/directory.d.ts +375 -0
  226. package/dist/types/core/schema/envelope.d.ts +750 -0
  227. package/dist/types/core/schema/errors.d.ts +104 -0
  228. package/dist/types/core/schema/index.d.ts +15 -0
  229. package/dist/types/core/schema/ipc/consent.d.ts +555 -0
  230. package/dist/types/core/schema/ipc/device.d.ts +729 -0
  231. package/dist/types/core/schema/ipc/jelly.d.ts +501 -0
  232. package/dist/types/core/schema/ipc/shapes.d.ts +411 -0
  233. package/dist/types/core/schema/ipc/surfaces.d.ts +674 -0
  234. package/dist/types/core/schema/ipc.d.ts +3131 -0
  235. package/dist/types/core/schema/jelly.d.ts +160 -0
  236. package/dist/types/core/schema/realm.d.ts +38 -0
  237. package/dist/types/core/schema/relay.d.ts +1122 -0
  238. package/dist/types/core/schema/roster.d.ts +347 -0
  239. package/dist/types/core/sign.d.ts +13 -0
  240. package/dist/types/core/task.d.ts +6 -0
  241. package/dist/types/core/testing.d.ts +18 -0
  242. package/dist/types/core/ulid.d.ts +5 -0
  243. package/dist/types/core/version.d.ts +6 -0
  244. package/dist/types/core/wire.d.ts +14 -0
  245. package/dist/types/ipc/client.d.ts +85 -0
  246. package/dist/types/ipc/framing.d.ts +12 -0
  247. package/dist/types/ipc/index.d.ts +6 -0
  248. package/dist/types/ipc/paths.d.ts +39 -0
  249. package/dist/types/ipc/pipes.d.ts +16 -0
  250. package/dist/types/ipc/rpc.d.ts +13 -0
  251. package/dist/types/ipc/server.d.ts +94 -0
  252. package/dist/types/ipc/testing.d.ts +89 -0
  253. package/dist/types/ipc/trust.d.ts +49 -0
  254. package/dist/types/ipc/windows-acl.d.ts +56 -0
  255. package/dist/types/testing/jelly-id.d.ts +518 -0
  256. package/dist/types/zod.d.ts +1 -0
  257. package/package.json +77 -4
@@ -0,0 +1,116 @@
1
+ import type { MachineId } from "../schema/common.js";
2
+ import { ArchivedJellyKey, CnfJwk, JellyClaims, JellyTokenHeader } from "../schema/jelly.js";
3
+ /** Contract v1.1 §5 step 5: a token lives at most 900 s, and its `iat` may be at most 60 s ahead of now. */
4
+ export declare const JELLY_MAX_LIFETIME_S = 900;
5
+ export declare const JELLY_IAT_LEEWAY_S = 60;
6
+ /** Contract v1.1 §5 step 2: Jelly's key set is believed for 24 h; the key history for 5 min. */
7
+ export declare const JELLY_JWKS_TTL_MS: number;
8
+ export declare const JELLY_HISTORY_TTL_MS: number;
9
+ /** An archived key's revocation is rechecked against the key history when older than this (spec §15.2). */
10
+ export declare const JELLY_REVOCATION_CHECK_MS: number;
11
+ /** An unknown `kid` refetches a key set at most this often, so a stream of unknown `kid`s cannot loop. */
12
+ export declare const JELLY_REFETCH_MIN_MS: number;
13
+ /** A decoded, not yet verified, resource token. */
14
+ export interface JellyToken {
15
+ readonly header: JellyTokenHeader;
16
+ readonly claims: JellyClaims;
17
+ /** `header.payload`, the bytes the signature covers. */
18
+ readonly signingInput: Uint8Array;
19
+ readonly signature: Uint8Array;
20
+ }
21
+ /** A Jelly key with what the key history says of it; a key seen only in the key set has no window. */
22
+ export interface JellyKey {
23
+ readonly kid: string;
24
+ readonly x: string;
25
+ /** Seconds: first published (key history). */
26
+ readonly nbf?: number | undefined;
27
+ /** Seconds: dropped from the key set; null while published (key history). */
28
+ readonly retiredAt?: number | null | undefined;
29
+ /** Seconds: revoked by an operator (key history). */
30
+ readonly revokedAt?: number | null | undefined;
31
+ }
32
+ /**
33
+ * Decodes a compact resource token: three base64url segments, a header with `alg: EdDSA`, `typ:
34
+ * jelly-resource+jwt` and a printable `kid`, and claims of the contract's shape (contract v1.1 §4, §5 step 1;
35
+ * `cnf`, when present, exactly `{jwk: {kty, crv, x}}`). Verifies nothing. Throws `binding_invalid`.
36
+ */
37
+ export declare function decodeJellyToken(token: string): JellyToken;
38
+ /**
39
+ * True when a key may have signed a token issued at `iat` (seconds): always for a key seen only in the key set;
40
+ * for a key the history describes, `iat ∈ [nbf, retired_at)` (an open end while `retired_at` is null) and
41
+ * before any `revoked_at` (contract v1.1 §5 step 2, §11).
42
+ */
43
+ export declare function jellyKeyCovers(key: JellyKey, iat: number): boolean;
44
+ /** True when `x` is a key Jelly ID would bind (contract v1.1 §3): a canonical Ed25519 point not of small order. */
45
+ export declare function isBindableKey(x: string): boolean;
46
+ /** The `cnf_jwk` a host asks Jelly ID to bind for `device` (contract v1.1 §3, §6). Throws `invalid_request` for an unusable key. */
47
+ export declare function cnfJwk(device: MachineId): CnfJwk;
48
+ export interface JellyVerifyOptions {
49
+ /** The realm's issuer and resource, compared exactly with `iss` and `aud`. */
50
+ readonly issuer: string;
51
+ readonly audience: string;
52
+ /** The key with this `kid`, as `JellyKeyring.prepare` found it; undefined when no source knows it. */
53
+ readonly key: (kid: string) => JellyKey | undefined;
54
+ /** The device the token must be bound to (`cnf.jwk.x`). Without it, `cnf` is checked for shape only. */
55
+ readonly cnf?: MachineId | undefined;
56
+ /**
57
+ * Now, in milliseconds, to check a token as it is presented (contract v1.1 §5 step 5: `exp` in the future, `iat`
58
+ * at most 60 s ahead). Omit it to check a token kept in a log, whose freshness is judged at its append (§15.3).
59
+ */
60
+ readonly now?: number | undefined;
61
+ }
62
+ /**
63
+ * Verifies a resource token (contract v1.1 §5; spec §15.2 steps 1–6): the header, the key and its window, the
64
+ * signature, `iss` and `aud`, the lifetime, `sub`, how it was minted (`hst`, or `src: "device"` with no `hst`), and
65
+ * `cnf`. Returns the decoded token. Throws
66
+ * `binding_invalid`; never reports a missing key as anything else (finding it is `JellyKeyring`'s).
67
+ */
68
+ export declare function verifyJellyToken(token: string, options: JellyVerifyOptions): JellyToken;
69
+ export interface JellyKeySources {
70
+ /** `<issuer>/.well-known/jwks.json`, as text. Rejects when it cannot be fetched. */
71
+ readonly fetchJwks: () => Promise<string>;
72
+ /** `<issuer>/.well-known/jwks-history.json`, as text. Rejects when it cannot be fetched. */
73
+ readonly fetchHistory: () => Promise<string>;
74
+ }
75
+ /**
76
+ * Finds the keys of resource tokens, in the order of spec §15.2: the client's own archive of every key it has
77
+ * verified, then Jelly ID's key set (cached 24 h; an unknown `kid` refetches it at most once a minute), then the
78
+ * key history (cached 5 min). A key found in the key set or the history joins the archive, with the history's
79
+ * window. An archived key whose revocation was last checked over 24 h ago is checked again, and keeps its archived
80
+ * window if the history cannot be fetched. Persist `archive()`; pass it back to the constructor.
81
+ */
82
+ export declare class JellyKeyring {
83
+ #private;
84
+ constructor(sources: JellyKeySources, archive?: readonly ArchivedJellyKey[]);
85
+ /** Every key this client has verified, to persist. */
86
+ archive(): ArchivedJellyKey[];
87
+ /** The archived key with this `kid`, without fetching. */
88
+ archived(kid: string): JellyKey | undefined;
89
+ /**
90
+ * Finds the keys of these tokens (a token that does not decode is skipped: verifying it fails anyway) and
91
+ * returns the synchronous lookup `verifyJellyToken` takes. Throws `jelly_unavailable` when a `kid` is in no
92
+ * source and a source it needed could not be fetched: never `binding_invalid` for an unreachable Jelly ID.
93
+ */
94
+ prepare(tokens: readonly string[], now: number): Promise<(kid: string) => JellyKey | undefined>;
95
+ /** Finds one key (see the class). Returns undefined when every source answered and none knows it. */
96
+ resolve(kid: string, now: number): Promise<JellyKey | undefined>;
97
+ }
98
+ /** What a refusal to mint a bound token means for the daemon (contract v1.1 §3, §6, and Jelly's change of 2026-11-05). */
99
+ export type JellyMintRefusal =
100
+ /** `invalid_target` with `detail: "invalid_cnf_jwk"`: Jelly would not bind this key. A daemon bug: alarm, never retry. */
101
+ "unbindable_key"
102
+ /** `invalid_target` without a detail: the realm's Jelly ID offers no such resource. Say so in status; do not retry. */
103
+ | "no_resource"
104
+ /** `access_denied`: the account is disabled or being deleted. Final. */
105
+ | "denied"
106
+ /** `not_enrolled` or `invalid_client`: this host is not (or no longer) enrolled. Final until it is. */
107
+ | "not_enrolled"
108
+ /** `invalid_request`: the ask was malformed. A daemon or plugin bug: alarm, never retry. */
109
+ | "bad_request"
110
+ /** `unavailable`, `temporarily_unavailable`, `slow_down` or anything else: hold 30 s, then retry. */
111
+ | "retry";
112
+ /**
113
+ * Reads a refusal from Jelly ID's mint route (`{error, detail?}`) or the engine accessor (an `Error` with
114
+ * `code` and `detail`). Branches on `detail`: a plain `invalid_target` still means no such resource.
115
+ */
116
+ export declare function jellyMintRefusal(code: string, detail?: string): JellyMintRefusal;
@@ -0,0 +1,22 @@
1
+ import type { Identity } from "../identity.js";
2
+ import { type Hash, type HostedPersonId } from "../schema/common.js";
3
+ import { KeysStatement } from "../schema/directory.js";
4
+ import type { RealmId } from "../schema/realm.js";
5
+ /** `SHA-256(JCS(statement))`, the signature included: what the map commits to. */
6
+ export declare function keysStatementHash(statement: KeysStatement): Hash;
7
+ /** This device's statement of its current encryption key. Throws `invalid_request`. */
8
+ export declare function createKeysStatement(identity: Identity, args: {
9
+ realm: RealmId;
10
+ person: HostedPersonId;
11
+ seq: number;
12
+ ts: number;
13
+ }): KeysStatement;
14
+ /**
15
+ * Checks a keys statement: the schema and `LIMITS.keysStatementBytes` (`invalid_request`, `too_large`), then
16
+ * the realm, the person, and the device's signature (`binding_invalid`). Whether the device is current, and
17
+ * whether `seq` is above the last one seen, are the caller's (`verifyPersonView` checks both).
18
+ */
19
+ export declare function verifyKeysStatement(statement: unknown, context: {
20
+ realm: RealmId;
21
+ person: HostedPersonId;
22
+ }): KeysStatement;
@@ -0,0 +1,36 @@
1
+ import type { Identity } from "../identity.js";
2
+ import { type MachineLabel } from "../schema/common.js";
3
+ import { LinkRequest, type DeviceKind } from "../schema/directory.js";
4
+ import type { RealmId } from "../schema/realm.js";
5
+ /** The prefix of a link request's text form. A link is not a secret, but it should not travel through chat. */
6
+ export declare const LINK_PREFIX = "messaging-link.";
7
+ export interface LinkArgs {
8
+ readonly realm: RealmId;
9
+ readonly label: MachineLabel;
10
+ readonly kind: DeviceKind;
11
+ /** 16 random bytes. */
12
+ readonly nonce: Uint8Array;
13
+ readonly ts: number;
14
+ }
15
+ /** The new device's signed link request. Throws `invalid_request`. */
16
+ export declare function createLinkRequest(identity: Identity, args: LinkArgs): LinkRequest;
17
+ /** `messaging-link.` and the base64url of the request's JCS. */
18
+ export declare function encodeLink(link: LinkRequest): string;
19
+ /** Reads a link's text (surrounding whitespace ignored), with `parseWire`. Verifies nothing. Throws `invalid_request`. */
20
+ export declare function decodeLink(text: string): LinkRequest;
21
+ /** True when the request's signature is its device's. Never throws. */
22
+ export declare function verifyLinkSignature(link: LinkRequest): boolean;
23
+ /**
24
+ * What an approving device checks before it shows the request (§15.3): the schema (`invalid_request`), the
25
+ * signature and the realm (`binding_invalid`), and `ts` no older than `LIMITS.linkTtlMs` and no later than the
26
+ * clock skew ahead of `now` (`expired`).
27
+ */
28
+ export declare function verifyLinkRequest(link: unknown, context: {
29
+ realm: RealmId;
30
+ now: number;
31
+ }): LinkRequest;
32
+ /**
33
+ * The six-digit short authentication string both devices show: the first four bytes of SHA-256(JCS(request)),
34
+ * big-endian, modulo 1,000,000, zero-padded. The person compares the two before approving.
35
+ */
36
+ export declare function linkSas(link: LinkRequest): string;
@@ -0,0 +1,40 @@
1
+ import type { Hash } from "../schema/common.js";
2
+ type Bytes = Uint8Array;
3
+ /** `SHA-256(0x00 ‖ data)`, the hash of a leaf. */
4
+ export declare function merkleLeafHash(data: Bytes): Hash;
5
+ /**
6
+ * The leaf hashes of a log, appended in order. It answers the tree head at any size it holds, and the audit
7
+ * path and consistency proof between sizes (RFC 9162 §2.1.1-§2.1.4). Subtree roots are cached, so a proof
8
+ * costs O(log² n) hashes after the first.
9
+ */
10
+ export declare class MerkleLog {
11
+ #private;
12
+ /** A log of these leaf hashes (from `merkleLeafHash`), in order. */
13
+ static fromLeafHashes(hashes: readonly Hash[]): MerkleLog;
14
+ get size(): number;
15
+ /** Appends the leaf whose data is `data`; returns its index. */
16
+ append(data: Bytes): number;
17
+ /** Appends a leaf by its hash; returns its index. */
18
+ appendLeafHash(hash: Hash): number;
19
+ /** The root the log would have with the leaf `hash` appended; the log itself does not change. */
20
+ rootWith(hash: Hash): Hash;
21
+ leafHash(index: number): Hash;
22
+ /** MTH of the first `size` leaves (default: all). The empty tree's root is SHA-256 of nothing. */
23
+ root(size?: number): Hash;
24
+ /** The audit path of leaf `index` in the tree of the first `size` leaves, bottom up (RFC 9162 §2.1.3.1). */
25
+ inclusionProof(index: number, size?: number): Hash[];
26
+ /** The consistency proof from the tree of `from` leaves to the tree of `size` leaves (RFC 9162 §2.1.4.1). */
27
+ consistencyProof(from: number, size?: number): Hash[];
28
+ }
29
+ /**
30
+ * True when `proof` is the audit path of the leaf with hash `leafHash` at `index` in a tree of `size` leaves
31
+ * whose root is `root` (RFC 9162 §2.1.3.2). Never throws.
32
+ */
33
+ export declare function verifyInclusion(index: number, size: number, leafHash: Hash, proof: readonly Hash[], root: Hash): boolean;
34
+ /**
35
+ * True when `proof` shows that the tree of `size1` leaves with root `root1` is a prefix of the tree of `size2`
36
+ * leaves with root `root2` (RFC 9162 §2.1.4.2). Equal sizes need an empty proof and equal roots; a proof from
37
+ * the empty tree proves nothing and is false. Never throws.
38
+ */
39
+ export declare function verifyConsistency(size1: number, size2: number, proof: readonly Hash[], root1: Hash, root2: Hash): boolean;
40
+ export {};
@@ -0,0 +1,90 @@
1
+ import type { Hash, HostedPersonId } from "../schema/common.js";
2
+ import { type EpochProof, type KeysStatement, type LogEntry, type MapValue, type STH } from "../schema/directory.js";
3
+ import { MessagingError } from "../schema/errors.js";
4
+ import type { DeviceId } from "../schema/directory.js";
5
+ import { DeviceLog, type DeviceLogContext } from "./device-log.js";
6
+ /** What a client keeps evidence of when the directory contradicts itself or what the client holds. */
7
+ export type DirectoryEvidence =
8
+ /** Two signed entries at one `seq` of one log. */
9
+ {
10
+ readonly kind: "fork";
11
+ readonly seq: number;
12
+ readonly ours: LogEntry;
13
+ readonly theirs: LogEntry;
14
+ }
15
+ /**
16
+ * The directory serves an older keys statement than the client holds (`theirs` −1: none), or, at a later tree head,
17
+ * a shorter log than it served at an earlier one (`what: "log"`: the two lengths).
18
+ */
19
+ | {
20
+ readonly kind: "rollback";
21
+ readonly what: "keys" | "log";
22
+ readonly ours: number;
23
+ readonly theirs: number;
24
+ }
25
+ /** The map at the STH does not commit to what was served. */
26
+ | {
27
+ readonly kind: "map";
28
+ readonly sth: STH;
29
+ readonly head: EpochProof;
30
+ };
31
+ /** `directory_inconsistent`, with the evidence a client keeps and shows in its alarm. Its message never holds values. */
32
+ export declare class DirectoryInconsistency extends MessagingError {
33
+ readonly evidence: DirectoryEvidence;
34
+ constructor(message: string, evidence: DirectoryEvidence);
35
+ }
36
+ /** What a client holds of one person: their verified log and their devices' latest keys statements. */
37
+ export interface PersonState {
38
+ readonly person: HostedPersonId;
39
+ readonly log: DeviceLog;
40
+ /** The latest statement of each current device that published one. */
41
+ readonly keys: ReadonlyMap<DeviceId, KeysStatement>;
42
+ /** The person was erased: the map holds the tombstone. */
43
+ readonly erased: boolean;
44
+ }
45
+ export interface PersonViewContext extends Omit<DeviceLogContext, "person"> {
46
+ /** The STH the view is at, adopted (`adoptSth`). */
47
+ readonly sth: STH;
48
+ /** The STH's last epoch leaf (index `size − 1`) with its audit path: `dir.sthIs`'s `head`. */
49
+ readonly head: unknown;
50
+ /** What the client already holds of the person, if anything. */
51
+ readonly known?: PersonState | undefined;
52
+ }
53
+ /**
54
+ * Verifies one person's view and returns their new state (spec §15.7). Errors: `invalid_request` (shapes),
55
+ * `binding_invalid` (an entry, a keys statement, or a binding that first appeared in an epoch after its token's
56
+ * life), the log's own codes, and `directory_inconsistent` (a `DirectoryInconsistency` with evidence when the
57
+ * directory contradicts what the client holds; a plain one for a proof that fails).
58
+ */
59
+ export declare function verifyPersonView(view: unknown, context: PersonViewContext): PersonState;
60
+ /**
61
+ * Two states of one person, each verified (`verifyPersonView`) at its own tree head of one adopted epoch log, `earlier`
62
+ * at a size at most `later`'s (spec §15.9, "One tree head per view"). The later must extend the earlier: the same
63
+ * entries at every seq the earlier holds, and, for each device still current, a keys statement at least as new.
64
+ * A client that verified two views of a person concurrently checks them against each other with this instead of
65
+ * one against the other's tree head. An erased state on either side is not compared (an erase drops the log).
66
+ * Throws a `DirectoryInconsistency` with the evidence.
67
+ */
68
+ export declare function checkPersonSuccession(earlier: PersonState, later: PersonState): void;
69
+ /** What a person's head (`PersonHead`) proves at an STH: absent from the map, erased, or this log head and these keys. */
70
+ export type VerifiedHead = {
71
+ readonly person: HostedPersonId;
72
+ readonly state: "absent";
73
+ } | {
74
+ readonly person: HostedPersonId;
75
+ readonly state: "erased";
76
+ } | {
77
+ readonly person: HostedPersonId;
78
+ readonly state: "live";
79
+ readonly log: MapValue["log"];
80
+ readonly keys: readonly Hash[];
81
+ };
82
+ /**
83
+ * Verifies one person's head (spec §7, `dir.heads`) against the STH a client adopted: the map at its last epoch holds
84
+ * exactly that value (`mapValue` of the preimage), the tombstone, or nothing. It proves the log head a device binding
85
+ * to the person extends (`seq + 1`, `prev` = `hash`), and nothing about the entries before it.
86
+ */
87
+ export declare function verifyPersonHead(view: unknown, context: {
88
+ sth: STH;
89
+ head: unknown;
90
+ }): VerifiedHead;
@@ -0,0 +1,8 @@
1
+ import { type HostedPersonId } from "../schema/common.js";
2
+ /** RFC 4648 §6 base32 in lower case, without padding. */
3
+ export declare function base32Lower(bytes: Uint8Array): string;
4
+ /**
5
+ * `"p_" + base32lower(SHA-256(UTF-8("messaging/1/person\n") ‖ UTF-8(JCS({iss, sub}))))[0..26]`. `iss` is the
6
+ * issuer exactly as the token states it; `sub` must be a Jelly account id (`acc_…`). Throws `invalid_request`.
7
+ */
8
+ export declare function personId(iss: string, sub: string): HostedPersonId;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * A directory realm (spec §15.8): what a daemon home pins of its key directory, and the realm id that follows
3
+ * from it. The id commits to the directory's origin, the Jelly issuer that vouches for its persons and the epoch
4
+ * key that signs its tree heads, so two directories never share a realm and a client can tell which one an
5
+ * envelope belongs to.
6
+ */
7
+ import { z } from "zod";
8
+ import type { RealmId } from "../schema/realm.js";
9
+ /** What a daemon's `config.json` pins of a directory realm (design §1.1): its relay, issuer, resource and epoch key. */
10
+ export declare const DirectoryRealmConfig: z.ZodObject<{
11
+ kind: z.ZodLiteral<"directory">;
12
+ url: z.ZodString;
13
+ issuer: z.ZodString;
14
+ resource: z.ZodString;
15
+ key: z.ZodString;
16
+ orgDomains: z.ZodOptional<z.ZodArray<z.ZodString>>;
17
+ }, z.core.$strip>;
18
+ export type DirectoryRealmConfig = z.infer<typeof DirectoryRealmConfig>;
19
+ /**
20
+ * `base64url(SHA-256(JCS({kind: "directory", origin, issuer, key})))`, where `origin` is the WHATWG origin of the
21
+ * relay URL. Throws `invalid_request` for a config that does not parse or a key that is not a usable Ed25519 key.
22
+ */
23
+ export declare function directoryRealmId(config: Omit<DirectoryRealmConfig, "kind" | "resource" | "orgDomains"> & Partial<DirectoryRealmConfig>): RealmId;
@@ -0,0 +1,52 @@
1
+ import { type Hash } from "../schema/common.js";
2
+ import { MapValue, type MapProof } from "../schema/directory.js";
3
+ export declare const MAP_DEPTH = 256;
4
+ /** The hash of an empty subtree of height `h` (0 ≤ h ≤ 256), base64url. */
5
+ export declare function emptyMapHash(height: number): Hash;
6
+ /** The map key of a person: `SHA-256(UTF-8(person))`, base64url. */
7
+ export declare function mapKey(person: string): Hash;
8
+ /**
9
+ * The value a live person's leaf holds: `SHA-256(JCS({log: {seq, hash}, keys}))`, where `log` is the head of
10
+ * their device log and `keys` the hashes of the current devices' keys statements, ordered by device.
11
+ */
12
+ export declare function mapValue(value: MapValue): Hash;
13
+ /** The value an erased person's leaf holds: `SHA-256(UTF-8("messaging/1/tombstone"))`. */
14
+ export declare const TOMBSTONE: Hash;
15
+ /**
16
+ * The map, in memory. `set` costs about 256 hashes plus the branches above the person; `prove` reads siblings
17
+ * from the trie. A person never leaves the map: an erased person's value becomes `TOMBSTONE`.
18
+ */
19
+ export declare class SparseMerkleTree {
20
+ #private;
21
+ /**
22
+ * A map of these persons and values, built at once: each leaf's path is hashed once. This is the way to load
23
+ * a large map (about 2.4 million hashes for 10,000 persons). A person given twice keeps the last value.
24
+ */
25
+ static from(entries: Iterable<readonly [person: string, value: Hash]>): SparseMerkleTree;
26
+ get size(): number;
27
+ root(): Hash;
28
+ get(person: string): Hash | undefined;
29
+ /** Sets a person's value (from `mapValue`, or `TOMBSTONE`). */
30
+ set(person: string, value: Hash): void;
31
+ /**
32
+ * The map as it is now, for `root` and `prove` only: a later `set` on this tree does not change it. Cheap: the trie
33
+ * is persistent, so the snapshot shares every node.
34
+ */
35
+ snapshot(): SparseMerkleTree;
36
+ /**
37
+ * A tree that starts as this one and changes on its own: a `set` on either leaves the other as it was. The trie is
38
+ * shared (it is persistent); only the person index is copied. A directory prepares an epoch on a copy and adopts it
39
+ * once the epoch is stored.
40
+ */
41
+ copy(): SparseMerkleTree;
42
+ /** The proof for `person`, present or absent, against `root()`. */
43
+ prove(person: string): MapProof;
44
+ }
45
+ /**
46
+ * The root that `proof` gives for `person` holding `value` (undefined: no leaf, an absent person). Throws
47
+ * `invalid_request` for a malformed proof: a bitmap that is not 32 bytes, a sibling count that differs from
48
+ * the bitmap's, or a sibling equal to the empty hash of its height (a proof names only non-empty siblings).
49
+ */
50
+ export declare function mapRootFromProof(person: string, value: Hash | undefined, proof: MapProof): Hash;
51
+ /** True when `proof` shows `person` holding `value` (undefined: absent) in the map with root `root`. Never throws. */
52
+ export declare function verifyMapProof(root: Hash, person: string, value: Hash | undefined, proof: MapProof): boolean;
@@ -0,0 +1,68 @@
1
+ import type { Identity } from "./identity.js";
2
+ import type { RealmView } from "./realm.js";
3
+ import { type EncKey, type MachineId, Ulid } from "./schema/common.js";
4
+ import { Envelope, type EnvelopeClass, EnvelopeType, type PayloadByType, type Recipient, type Sender } from "./schema/envelope.js";
5
+ import type { Anchor, RealmId } from "./schema/realm.js";
6
+ import type { Member } from "./schema/roster.js";
7
+ export interface SealArgs<T extends EnvelopeType = EnvelopeType> {
8
+ identity: Identity;
9
+ realm: RealmId;
10
+ type: T;
11
+ from: Sender;
12
+ to: Recipient;
13
+ /** The recipient device's X25519 key. Required for every type except presence. */
14
+ recipientEnc?: EncKey;
15
+ /** The sender's current view of the realm (spec §5); the receiver catches up to it or reports a divergence. */
16
+ anchor: Anchor;
17
+ payload: PayloadByType[T];
18
+ replyTo?: Ulid;
19
+ /** Default and maximum `LIMITS.ttlMs`. */
20
+ ttlMs?: number;
21
+ now?: number;
22
+ id?: Ulid;
23
+ }
24
+ /** Fixed sealing randomness: the ephemeral X25519 private key (32 raw bytes) and the 12-byte nonce. */
25
+ export interface SealRandomness {
26
+ ephemeral: Uint8Array;
27
+ nonce: Uint8Array;
28
+ }
29
+ export interface VerifyContext {
30
+ /** The locally verified realm: a `Roster` for a roster realm. */
31
+ realm: RealmView;
32
+ /** This device. When given, every envelope except presence must be addressed to it and to its person in `realm`. */
33
+ self?: MachineId;
34
+ now: number;
35
+ }
36
+ /** Builds, seals (spec §5) and signs an envelope. Presence is signed but not sealed. */
37
+ export declare function sealEnvelope<T extends EnvelopeType>(args: SealArgs<T>): Envelope;
38
+ /**
39
+ * `sealEnvelope` with caller-chosen ephemeral key and nonce, for test vectors and tests only; exported from
40
+ * `@messaging/core/testing`. Reusing an ephemeral key and nonce for real traffic breaks confidentiality.
41
+ */
42
+ export declare function sealEnvelopeWith<T extends EnvelopeType>(args: SealArgs<T>, randomness: SealRandomness): Envelope;
43
+ /**
44
+ * Seals arbitrary `plaintext` bytes as the body of a sealed type, with a valid header and signature but no
45
+ * payload validation or canonicalization, so tests can build envelopes a conforming sender never makes.
46
+ * Tests only; exported from `@messaging/core/testing`.
47
+ */
48
+ export declare function sealPlaintext(args: Omit<SealArgs, "payload"> & {
49
+ class?: EnvelopeClass;
50
+ }, plaintext: Uint8Array, randomness?: SealRandomness): Envelope;
51
+ /**
52
+ * Receiver checks, spec §5 steps 1–6. Membership is checked against the locally verified realm and the
53
+ * signature over the raw JSON value, so unknown fields from newer peers stay covered. Returns the raw
54
+ * envelope; deduplication and recipient policy are the caller's. Throws only MessagingError.
55
+ */
56
+ export declare function verifyEnvelope(raw: unknown, ctx: VerifyContext): {
57
+ env: Envelope;
58
+ sender: Member;
59
+ };
60
+ /**
61
+ * Decrypts (or, for presence, reads) the body and validates it against `PAYLOAD_BY_TYPE[type]`.
62
+ * A seal failure is `bad_signature`; an oversized body is `too_large`; a body that decrypts but is not
63
+ * UTF-8 I-JSON (`parseWire`, then `canonicalize`) or not a valid payload is `invalid_request`, so every
64
+ * payload returned canonicalizes. Throws only MessagingError, and never chains the plaintext as a cause.
65
+ */
66
+ export declare function openEnvelope<T extends EnvelopeType>(env: Envelope & {
67
+ type: T;
68
+ }, identity: Identity): PayloadByType[T];
@@ -0,0 +1,2 @@
1
+ /** SHA-256, base64url. Strings are hashed as UTF-8. */
2
+ export declare function sha256(data: string | Uint8Array): string;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Roster head commitments (spec §5). Every envelope's anchor is the sender's roster head, so a
3
+ * receiver can tell whether the sender saw entries it has not (sync first), or a different chain (a
4
+ * divergence: the relay showed the two machines different branches).
5
+ */
6
+ import type { AnchorRelation } from "./realm.js";
7
+ import type { Roster } from "./roster.js";
8
+ import { type MachineId, type PersonName, type Ulid } from "./schema/common.js";
9
+ import type { RealmId, RosterAnchor } from "./schema/realm.js";
10
+ import type { RosterHead } from "./schema/roster.js";
11
+ /**
12
+ * How a head relates to a roster:
13
+ * - `ahead`: past the roster's head; the sender knows entries this roster does not;
14
+ * - `consistent`: an entry of this chain, its head or an earlier one (a peer may lag);
15
+ * - `diverged`: this chain has another entry at that seq, whose hash is `ours`.
16
+ */
17
+ export type HeadRelation = AnchorRelation;
18
+ export declare function headRelation(roster: Roster, head: RosterHead): HeadRelation;
19
+ /** The anchor a roster realm's envelopes carry: the roster's head (spec §5). */
20
+ export declare function rosterAnchor(roster: Roster): RosterAnchor;
21
+ /** The head an envelope commits to, with the machine whose signature covers it. */
22
+ export interface SignedHead {
23
+ head: RosterHead;
24
+ machine: MachineId;
25
+ person: PersonName;
26
+ id: Ulid;
27
+ }
28
+ /**
29
+ * The roster head `raw` commits to, if `raw` is an envelope of `realm` (schema) whose signature over the
30
+ * raw JSON verifies under `from.device`. Membership and the time window are not checked: a receiver
31
+ * uses this to bring its roster up to the head before it checks membership (a new joiner is not in a
32
+ * stale roster), and to check stored evidence. Never throws; anything else is undefined.
33
+ */
34
+ export declare function signedHead(raw: unknown, realm: RealmId): SignedHead | undefined;
@@ -0,0 +1,35 @@
1
+ import { type KeyObject } from "node:crypto";
2
+ import { z } from "zod";
3
+ import { EncKey, MachineId } from "./schema/common.js";
4
+ /** `$MESSAGING_HOME/identity.json`. `signingKey` and `encKey` are the private JWK `d` values. */
5
+ export declare const IdentityFile: z.ZodObject<{
6
+ v: z.ZodLiteral<"messaging/1">;
7
+ machine: z.ZodString;
8
+ enc: z.ZodString;
9
+ signingKey: z.ZodString;
10
+ encKey: z.ZodString;
11
+ }, z.core.$strip>;
12
+ export type IdentityFile = z.infer<typeof IdentityFile>;
13
+ /**
14
+ * A machine identity: an Ed25519 signing key and an X25519 encryption key. The public ids are
15
+ * derived from the private keys, so they always match. The private keys are held in private
16
+ * fields and never appear in `JSON.stringify`, `String()` or `util.inspect` output.
17
+ */
18
+ export declare class Identity {
19
+ #private;
20
+ readonly machine: MachineId;
21
+ readonly enc: EncKey;
22
+ constructor(signingKey: KeyObject, encKey: KeyObject);
23
+ get signingKey(): KeyObject;
24
+ get encKey(): KeyObject;
25
+ toJSON(): {
26
+ machine: MachineId;
27
+ enc: EncKey;
28
+ };
29
+ toString(): string;
30
+ }
31
+ export declare function generateIdentity(): Identity;
32
+ /** The identity file contents. This is the only API that returns private key material. */
33
+ export declare function exportIdentity(identity: Identity): IdentityFile;
34
+ /** Validates an identity file and checks that its public keys belong to its private keys. */
35
+ export declare function importIdentity(file: unknown): Identity;
@@ -0,0 +1,38 @@
1
+ export * from "./schema/index.js";
2
+ export { b64u } from "./b64u.js";
3
+ export { VERSION } from "./version.js";
4
+ export { canonicalize } from "./jcs.js";
5
+ export { parseWire } from "./wire.js";
6
+ export { sha256 } from "./hash.js";
7
+ export { ulid } from "./ulid.js";
8
+ export { Identity, IdentityFile, generateIdentity, exportIdentity, importIdentity } from "./identity.js";
9
+ export { sign, verify } from "./sign.js";
10
+ export { sealEnvelope, verifyEnvelope, openEnvelope, type SealArgs, type VerifyContext } from "./envelope.js";
11
+ export { type AnchorRelation, type RealmView } from "./realm.js";
12
+ export { headRelation, rosterAnchor, signedHead, type HeadRelation, type SignedHead } from "./head.js";
13
+ export { Roster, entryHash, createGenesis, createEntry, createInvite, decodeTicket, createRedeem, relayAuthPayload, inviteJoinPayload, inviteJoinProof, type ApplyOptions, type RosterBody, type InviteState, } from "./roster.js";
14
+ export { ACT_GRANT_MAX_S, ACTION_CLASSES, HOST_GRANT_MAX_S, JELLY_HOST_SKEW_S, SESSION_TICKET_MAX_S, actionClass, grantInput, parseActKey, readWakeTicket, verifyActGrant, verifySessionTicket, type ActGrant, type ActGrantCheck, type ActionClass, type WakeTicketClaims, type SessionTicket, } from "./jelly-host.js";
15
+ export { personId } from "./directory/person.js";
16
+ export { DirectoryRealmConfig, directoryRealmId } from "./directory/realm.js";
17
+ export { emailOrg, hostedHandle } from "./directory/handle.js";
18
+ export { JELLY_HISTORY_TTL_MS, JELLY_IAT_LEEWAY_S, JELLY_JWKS_TTL_MS, JELLY_MAX_LIFETIME_S, JELLY_REFETCH_MIN_MS, JELLY_REVOCATION_CHECK_MS, JellyKeyring, cnfJwk, decodeJellyToken, isBindableKey, jellyKeyCovers, jellyMintRefusal, verifyJellyToken, type JellyKey, type JellyKeySources, type JellyMintRefusal, type JellyToken, type JellyVerifyOptions, } from "./directory/jelly-token.js";
19
+ export { DeviceLog, logEntryHash, signLogEntry, type AppendOptions, type DeviceLogContext, type DeviceRecord, type JellyProfile, type UnsignedLogEntry, type Vouch, } from "./directory/device-log.js";
20
+ export { DEVICE_GRANT_TYPE, JELLY_ANSWER_BYTES, LOGIN_INTERVAL_MAX_S, LOGIN_SLOW_DOWN_S, deviceCodeForm, devicePollForm, jellyKeyFingerprint, jellyKeyThumbprint, readDeviceCodeAnswer, readDevicePoll, readDeviceSignIn, type DeviceCodeAnswer, type DevicePoll, type DeviceSignIn, } from "./directory/jelly-device.js";
21
+ export { LINK_PREFIX, createLinkRequest, decodeLink, encodeLink, linkSas, verifyLinkRequest, verifyLinkSignature, type LinkArgs } from "./directory/link.js";
22
+ export { createKeysStatement, keysStatementHash, verifyKeysStatement } from "./directory/keys-statement.js";
23
+ export { adoptSth, epochAnchor, epochLeafHash, signKeyRotation, signSth, verifyEpochProof, verifySthSignature, type AdoptArgs, type AdoptedHead, } from "./directory/epoch.js";
24
+ export { checkPersonSuccession, DirectoryInconsistency, verifyPersonHead, verifyPersonView, type DirectoryEvidence, type PersonState, type PersonViewContext, type VerifiedHead, } from "./directory/person-view.js";
25
+ export { MerkleLog, merkleLeafHash, verifyConsistency, verifyInclusion } from "./directory/merkle-log.js";
26
+ export { MAP_DEPTH, SparseMerkleTree, TOMBSTONE, emptyMapHash, mapKey, mapRootFromProof, mapValue, verifyMapProof } from "./directory/smt.js";
27
+ export { parseAddress, formatAddress, type ParsedAddress } from "./address.js";
28
+ export { decodeAdmitCard, decodeTeamCard, encodeAdmitCard, encodeTeamCard, type AdmitCard, type TeamCard, } from "./cards.js";
29
+ export { decide, effectivePolicy, grantSubjectKey, levelsOf, preferGrant, resignGrant, restrictingLevels, signConsentGrant, verifyConsentGrant, wideningLevels, type ConsentClass, type ConsentDecision, type ConsentGrantArgs, type DecideArgs, type EffectivePolicy, type Inbound, type Relation, } from "./consent.js";
30
+ export { cardCan, signContactCard, verifyContactCard, type ContactCardArgs } from "./contact-card.js";
31
+ export { createGrant, verifyChain, type GrantArgs, type ChainHop, type ChainContext, type VerifiedChain } from "./delegation.js";
32
+ export { canTransition, isTerminal, isInterrupted } from "./task.js";
33
+ export { TERMINAL_STATES } from "./schema/a2a.js";
34
+ export { cleanPeerText, createFence, terminalSafe, displayWidth, HOST_TAGS, PEER_FENCE_TAG, PEER_DATA_NOTICE, provenanceOf, type CleanOptions, type Fence, type FenceAttributes, type FenceOptions, type TerminalOptions } from "./peer-text.js";
35
+ export { AgentTool, TOOL_VERBS, TOOL_DESCRIPTIONS, ToolExpect, UNTRUSTED_SENTENCE, TOOL_REMEDIES, DONE_STATES, TaskStateName, ToolErrorBody, ToolFiles, a2aTaskState, conversationOf, decodeToolCursor, encodeToolCursor, formatToolAddress, parseToolAddress, taskStateName, toolErrorBody, toolName, type ToolAddress, type ToolAuthor, type ToolChain, type ToolConsent, type ToolCursor, type ToolInput, type ToolOutput, type ToolPart, type ToolTask, type ToolVerb, } from "./agent-tools.js";
36
+ export { Operations, type CallSession, type ChatAccess, type OperationsContext, type OperationsHooks, type SendPlan, type ToolLink, } from "./agent/operations.js";
37
+ export { agentCan, consentOf, conversationOfPeer, followUpRead, isoOf, presentAgent, presentConvEntry, presentInboxItem, presentLine, presentMail, presentSent, presentTask, presentTaskItem, presentTaskView, } from "./agent/present.js";
38
+ export { chainPath, compact, delegated, delegationPrompt, EXPECT_TEXT, isSafeId, messageAttributes, validatedAddress, type SessionAddressParts, type ToolFramer, } from "./agent/text.js";
@@ -0,0 +1,12 @@
1
+ /**
2
+ * RFC 8785 JSON Canonicalization Scheme over the I-JSON subset Messaging signs.
3
+ * Object members whose value is `undefined` are dropped. Throws `invalid_request` for anything
4
+ * that is not I-JSON: NaN, ±Infinity, integers beyond ±(2^53 − 1), bigint, functions, symbols,
5
+ * `undefined` array elements or top-level values, lone surrogates, cycles, and non-plain objects.
6
+ * It also throws `invalid_request` for arrays and objects nested deeper than `LIMITS.jsonDepth`.
7
+ *
8
+ * The cost is linear in the size of the value, and the result never depends on the call stack: each
9
+ * node is visited once with O(1) bookkeeping, recursion stops at `LIMITS.jsonDepth`, and a cycle is
10
+ * caught by that same limit (sorting member names is the only superlinear step).
11
+ */
12
+ export declare function canonicalize(value: unknown): string;
@@ -0,0 +1,21 @@
1
+ import { type ActKeyJwk } from "./schema/jelly.js";
2
+ export interface JellyHostDouble {
3
+ /** The public action key, as the host writes it for `--act-key`. */
4
+ readonly key: ActKeyJwk;
5
+ /** `key` as file text. */
6
+ readonly keyText: string;
7
+ /**
8
+ * A method grant for one call: `act` = `method`, `in` = the params' digest, `cls` = the method's class
9
+ * (`actionClass`), 60 s. A claim set to `undefined` in `claims` is left out.
10
+ */
11
+ act(method: string, params?: unknown, claims?: Record<string, unknown>, header?: Record<string, unknown>): string;
12
+ /** A host-scope grant: `act: "host"`, ten minutes. */
13
+ host(claims?: Record<string, unknown>): string;
14
+ /** A session ticket for agent `agt` and session `name`: seven days. */
15
+ ticket(agt: string, name: string, claims?: Record<string, unknown>, header?: Record<string, unknown>): string;
16
+ }
17
+ /** A host double with a fresh action key, signing at `now()` (milliseconds; default the wall clock). */
18
+ export declare function jellyHostDouble(options?: {
19
+ now?: () => number;
20
+ kid?: string;
21
+ }): JellyHostDouble;