@private.me/xbind 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/AGENTS.md +778 -0
  2. package/LICENSE.md +27 -0
  3. package/README.md +400 -0
  4. package/dist-standalone/_deps/crypto/base64.d.ts +29 -0
  5. package/dist-standalone/_deps/crypto/base64.js +97 -0
  6. package/dist-standalone/_deps/crypto/cjs/base64.js +103 -0
  7. package/dist-standalone/_deps/crypto/cjs/errors.js +119 -0
  8. package/dist-standalone/_deps/crypto/cjs/hmac.js +71 -0
  9. package/dist-standalone/_deps/crypto/cjs/index.js +86 -0
  10. package/dist-standalone/_deps/crypto/cjs/padding.js +57 -0
  11. package/dist-standalone/_deps/crypto/cjs/share-header.js +68 -0
  12. package/dist-standalone/_deps/crypto/cjs/shares.js +152 -0
  13. package/dist-standalone/_deps/crypto/cjs/tlv.js +199 -0
  14. package/dist-standalone/_deps/crypto/cjs/uuid.js +61 -0
  15. package/dist-standalone/_deps/crypto/cjs/verify.js +24 -0
  16. package/dist-standalone/_deps/crypto/cjs/xorida.js +221 -0
  17. package/dist-standalone/_deps/crypto/errors.d.ts +51 -0
  18. package/dist-standalone/_deps/crypto/errors.js +109 -0
  19. package/dist-standalone/_deps/crypto/hmac.d.ts +39 -0
  20. package/dist-standalone/_deps/crypto/hmac.js +66 -0
  21. package/dist-standalone/_deps/crypto/index.d.ts +20 -0
  22. package/dist-standalone/_deps/crypto/index.js +45 -0
  23. package/dist-standalone/_deps/crypto/padding.d.ts +19 -0
  24. package/dist-standalone/_deps/crypto/padding.js +53 -0
  25. package/dist-standalone/_deps/crypto/share-header.d.ts +44 -0
  26. package/dist-standalone/_deps/crypto/share-header.js +63 -0
  27. package/dist-standalone/_deps/crypto/shares.d.ts +27 -0
  28. package/dist-standalone/_deps/crypto/shares.js +148 -0
  29. package/dist-standalone/_deps/crypto/tlv.d.ts +26 -0
  30. package/dist-standalone/_deps/crypto/tlv.js +195 -0
  31. package/dist-standalone/_deps/crypto/uuid.d.ts +22 -0
  32. package/dist-standalone/_deps/crypto/uuid.js +56 -0
  33. package/dist-standalone/_deps/crypto/verify.d.ts +15 -0
  34. package/dist-standalone/_deps/crypto/verify.js +15 -0
  35. package/dist-standalone/_deps/crypto/xorida.d.ts +44 -0
  36. package/dist-standalone/_deps/crypto/xorida.js +215 -0
  37. package/dist-standalone/_deps/mldsa-wasm/LICENSE +24 -0
  38. package/dist-standalone/_deps/mldsa-wasm/dist/mldsa.js +1920 -0
  39. package/dist-standalone/_deps/mldsa-wasm/package.json +46 -0
  40. package/dist-standalone/_deps/mldsa-wasm/types/mldsa.d.ts +30 -0
  41. package/dist-standalone/_deps/shared/cjs/errors.js +582 -0
  42. package/dist-standalone/_deps/shared/cjs/index.js +492 -0
  43. package/dist-standalone/_deps/shared/cjs/package.json +1 -0
  44. package/dist-standalone/_deps/shared/cjs/types.js +403 -0
  45. package/dist-standalone/_deps/shared/errors.d.ts +48 -0
  46. package/dist-standalone/_deps/shared/errors.d.ts.map +1 -0
  47. package/dist-standalone/_deps/shared/errors.js +192 -0
  48. package/dist-standalone/_deps/shared/errors.js.map +1 -0
  49. package/dist-standalone/_deps/shared/index.d.ts +4 -0
  50. package/dist-standalone/_deps/shared/index.d.ts.map +1 -0
  51. package/dist-standalone/_deps/shared/index.js +78 -0
  52. package/dist-standalone/_deps/shared/index.js.map +1 -0
  53. package/dist-standalone/_deps/shared/types.d.ts +1097 -0
  54. package/dist-standalone/_deps/shared/types.d.ts.map +1 -0
  55. package/dist-standalone/_deps/shared/types.js +89 -0
  56. package/dist-standalone/_deps/shared/types.js.map +1 -0
  57. package/dist-standalone/_deps/ux-helpers/cjs/errors.d.ts +115 -0
  58. package/dist-standalone/_deps/ux-helpers/cjs/errors.d.ts.map +1 -0
  59. package/dist-standalone/_deps/ux-helpers/cjs/errors.js +1 -0
  60. package/dist-standalone/_deps/ux-helpers/cjs/errors.js.map +1 -0
  61. package/dist-standalone/_deps/ux-helpers/cjs/index.d.ts +13 -0
  62. package/dist-standalone/_deps/ux-helpers/cjs/index.d.ts.map +1 -0
  63. package/dist-standalone/_deps/ux-helpers/cjs/index.js +1 -0
  64. package/dist-standalone/_deps/ux-helpers/cjs/index.js.map +1 -0
  65. package/dist-standalone/_deps/ux-helpers/cjs/package.json +1 -0
  66. package/dist-standalone/_deps/ux-helpers/cjs/pagination.d.ts +39 -0
  67. package/dist-standalone/_deps/ux-helpers/cjs/pagination.d.ts.map +1 -0
  68. package/dist-standalone/_deps/ux-helpers/cjs/pagination.js +83 -0
  69. package/dist-standalone/_deps/ux-helpers/cjs/pagination.js.map +1 -0
  70. package/dist-standalone/_deps/ux-helpers/cjs/progress.d.ts +99 -0
  71. package/dist-standalone/_deps/ux-helpers/cjs/progress.d.ts.map +1 -0
  72. package/dist-standalone/_deps/ux-helpers/cjs/progress.js +143 -0
  73. package/dist-standalone/_deps/ux-helpers/cjs/progress.js.map +1 -0
  74. package/dist-standalone/_deps/ux-helpers/cjs/search.d.ts +32 -0
  75. package/dist-standalone/_deps/ux-helpers/cjs/search.d.ts.map +1 -0
  76. package/dist-standalone/_deps/ux-helpers/cjs/search.js +119 -0
  77. package/dist-standalone/_deps/ux-helpers/cjs/search.js.map +1 -0
  78. package/dist-standalone/_deps/ux-helpers/cjs/types.d.ts +109 -0
  79. package/dist-standalone/_deps/ux-helpers/cjs/types.d.ts.map +1 -0
  80. package/dist-standalone/_deps/ux-helpers/cjs/types.js +8 -0
  81. package/dist-standalone/_deps/ux-helpers/cjs/types.js.map +1 -0
  82. package/dist-standalone/_deps/ux-helpers/errors.d.ts +115 -0
  83. package/dist-standalone/_deps/ux-helpers/errors.d.ts.map +1 -0
  84. package/dist-standalone/_deps/ux-helpers/errors.js +253 -0
  85. package/dist-standalone/_deps/ux-helpers/errors.js.map +1 -0
  86. package/dist-standalone/_deps/ux-helpers/index.d.ts +13 -0
  87. package/dist-standalone/_deps/ux-helpers/index.d.ts.map +1 -0
  88. package/dist-standalone/_deps/ux-helpers/index.js +16 -0
  89. package/dist-standalone/_deps/ux-helpers/index.js.map +1 -0
  90. package/dist-standalone/_deps/ux-helpers/pagination.d.ts +39 -0
  91. package/dist-standalone/_deps/ux-helpers/pagination.d.ts.map +1 -0
  92. package/dist-standalone/_deps/ux-helpers/pagination.js +79 -0
  93. package/dist-standalone/_deps/ux-helpers/pagination.js.map +1 -0
  94. package/dist-standalone/_deps/ux-helpers/progress.d.ts +99 -0
  95. package/dist-standalone/_deps/ux-helpers/progress.d.ts.map +1 -0
  96. package/dist-standalone/_deps/ux-helpers/progress.js +138 -0
  97. package/dist-standalone/_deps/ux-helpers/progress.js.map +1 -0
  98. package/dist-standalone/_deps/ux-helpers/search.d.ts +32 -0
  99. package/dist-standalone/_deps/ux-helpers/search.d.ts.map +1 -0
  100. package/dist-standalone/_deps/ux-helpers/search.js +116 -0
  101. package/dist-standalone/_deps/ux-helpers/search.js.map +1 -0
  102. package/dist-standalone/_deps/ux-helpers/types.d.ts +109 -0
  103. package/dist-standalone/_deps/ux-helpers/types.d.ts.map +1 -0
  104. package/dist-standalone/_deps/ux-helpers/types.js +7 -0
  105. package/dist-standalone/_deps/ux-helpers/types.js.map +1 -0
  106. package/dist-standalone/_deps/xchange/auto-accept.d.ts +127 -0
  107. package/dist-standalone/_deps/xchange/auto-accept.js +1 -0
  108. package/dist-standalone/_deps/xchange/cjs/auto-accept.js +1 -0
  109. package/dist-standalone/_deps/xchange/cjs/errors.js +1 -0
  110. package/dist-standalone/_deps/xchange/cjs/index.js +1 -0
  111. package/dist-standalone/_deps/xchange/cjs/invite-client.js +1 -0
  112. package/dist-standalone/_deps/xchange/cjs/lazy-init.js +1 -0
  113. package/dist-standalone/_deps/xchange/cjs/package.json +1 -0
  114. package/dist-standalone/_deps/xchange/cjs/trust-integration.js +1 -0
  115. package/dist-standalone/_deps/xchange/cjs/xchange.js +1 -0
  116. package/dist-standalone/_deps/xchange/errors.d.ts +69 -0
  117. package/dist-standalone/_deps/xchange/errors.js +1 -0
  118. package/dist-standalone/_deps/xchange/index.d.ts +15 -0
  119. package/dist-standalone/_deps/xchange/index.js +1 -0
  120. package/dist-standalone/_deps/xchange/invite-client.d.ts +178 -0
  121. package/dist-standalone/_deps/xchange/invite-client.js +1 -0
  122. package/dist-standalone/_deps/xchange/lazy-init.d.ts +176 -0
  123. package/dist-standalone/_deps/xchange/lazy-init.js +1 -0
  124. package/dist-standalone/_deps/xchange/trust-integration.d.ts +102 -0
  125. package/dist-standalone/_deps/xchange/trust-integration.js +1 -0
  126. package/dist-standalone/_deps/xchange/xchange.d.ts +60 -0
  127. package/dist-standalone/_deps/xchange/xchange.js +1 -0
  128. package/dist-standalone/_deps/xregistry/cjs/discovery.js +1 -0
  129. package/dist-standalone/_deps/xregistry/cjs/errors.js +1 -0
  130. package/dist-standalone/_deps/xregistry/cjs/index.js +1 -0
  131. package/dist-standalone/_deps/xregistry/cjs/package.json +1 -0
  132. package/dist-standalone/_deps/xregistry/cjs/registry.js +1 -0
  133. package/dist-standalone/_deps/xregistry/cjs/schema.js +1 -0
  134. package/dist-standalone/_deps/xregistry/cjs/types.js +1 -0
  135. package/dist-standalone/_deps/xregistry/discovery.d.ts +126 -0
  136. package/dist-standalone/_deps/xregistry/discovery.d.ts.map +1 -0
  137. package/dist-standalone/_deps/xregistry/discovery.js +1 -0
  138. package/dist-standalone/_deps/xregistry/discovery.js.map +1 -0
  139. package/dist-standalone/_deps/xregistry/errors.d.ts +41 -0
  140. package/dist-standalone/_deps/xregistry/errors.d.ts.map +1 -0
  141. package/dist-standalone/_deps/xregistry/errors.js +1 -0
  142. package/dist-standalone/_deps/xregistry/errors.js.map +1 -0
  143. package/dist-standalone/_deps/xregistry/index.d.ts +8 -0
  144. package/dist-standalone/_deps/xregistry/index.d.ts.map +1 -0
  145. package/dist-standalone/_deps/xregistry/index.js +1 -0
  146. package/dist-standalone/_deps/xregistry/index.js.map +1 -0
  147. package/dist-standalone/_deps/xregistry/registry.d.ts +85 -0
  148. package/dist-standalone/_deps/xregistry/registry.d.ts.map +1 -0
  149. package/dist-standalone/_deps/xregistry/registry.js +1 -0
  150. package/dist-standalone/_deps/xregistry/registry.js.map +1 -0
  151. package/dist-standalone/_deps/xregistry/schema.d.ts +81 -0
  152. package/dist-standalone/_deps/xregistry/schema.d.ts.map +1 -0
  153. package/dist-standalone/_deps/xregistry/schema.js +1 -0
  154. package/dist-standalone/_deps/xregistry/schema.js.map +1 -0
  155. package/dist-standalone/_deps/xregistry/types.d.ts +95 -0
  156. package/dist-standalone/_deps/xregistry/types.d.ts.map +1 -0
  157. package/dist-standalone/_deps/xregistry/types.js +1 -0
  158. package/dist-standalone/_deps/xregistry/types.js.map +1 -0
  159. package/dist-standalone/agent-call.d.ts +286 -0
  160. package/dist-standalone/agent-call.js +642 -0
  161. package/dist-standalone/agent-sdk.d.ts +207 -0
  162. package/dist-standalone/agent-sdk.js +328 -0
  163. package/dist-standalone/agent.d.ts +670 -0
  164. package/dist-standalone/agent.js +1529 -0
  165. package/dist-standalone/approval.d.ts +145 -0
  166. package/dist-standalone/approval.js +193 -0
  167. package/dist-standalone/auth.d.ts +75 -0
  168. package/dist-standalone/auth.js +219 -0
  169. package/dist-standalone/auto-accept.d.ts +102 -0
  170. package/dist-standalone/auto-accept.js +229 -0
  171. package/dist-standalone/backup-config.d.ts +150 -0
  172. package/dist-standalone/backup-config.js +201 -0
  173. package/dist-standalone/checkpoint.d.ts +125 -0
  174. package/dist-standalone/checkpoint.js +186 -0
  175. package/dist-standalone/cjs/agent-call.js +651 -0
  176. package/dist-standalone/cjs/agent-sdk.js +332 -0
  177. package/dist-standalone/cjs/agent.js +1566 -0
  178. package/dist-standalone/cjs/approval.js +199 -0
  179. package/dist-standalone/cjs/auth.js +225 -0
  180. package/dist-standalone/cjs/auto-accept.js +233 -0
  181. package/dist-standalone/cjs/backup-config.js +207 -0
  182. package/dist-standalone/cjs/checkpoint.js +193 -0
  183. package/dist-standalone/cjs/cli/init.js +487 -0
  184. package/dist-standalone/cjs/connect.js +312 -0
  185. package/dist-standalone/cjs/did-document.js +101 -0
  186. package/dist-standalone/cjs/did-privateme.js +130 -0
  187. package/dist-standalone/cjs/did-web.js +201 -0
  188. package/dist-standalone/cjs/discovery.js +462 -0
  189. package/dist-standalone/cjs/dual-mode.js +251 -0
  190. package/dist-standalone/cjs/email-templates.js +313 -0
  191. package/dist-standalone/cjs/email-transport.js +239 -0
  192. package/dist-standalone/cjs/envelope.js +510 -0
  193. package/dist-standalone/cjs/errors.js +562 -0
  194. package/dist-standalone/cjs/gateway-state.js +55 -0
  195. package/dist-standalone/cjs/gateway-transport.js +120 -0
  196. package/dist-standalone/cjs/guardrails.js +223 -0
  197. package/dist-standalone/cjs/http-compat.js +272 -0
  198. package/dist-standalone/cjs/identity.js +541 -0
  199. package/dist-standalone/cjs/index.js +224 -0
  200. package/dist-standalone/cjs/invitation.js +421 -0
  201. package/dist-standalone/cjs/invite.js +328 -0
  202. package/dist-standalone/cjs/key-agreement.js +246 -0
  203. package/dist-standalone/cjs/lazy-init.js +300 -0
  204. package/dist-standalone/cjs/mdns-discovery.js +202 -0
  205. package/dist-standalone/cjs/nonce-store.js +66 -0
  206. package/dist-standalone/cjs/package.json +3 -0
  207. package/dist-standalone/cjs/pairing-manager.js +223 -0
  208. package/dist-standalone/cjs/policy.js +320 -0
  209. package/dist-standalone/cjs/redis-nonce-store.js +76 -0
  210. package/dist-standalone/cjs/registry-middleware.js +50 -0
  211. package/dist-standalone/cjs/retry-transport.js +102 -0
  212. package/dist-standalone/cjs/security-policy.js +204 -0
  213. package/dist-standalone/cjs/split-channel.js +177 -0
  214. package/dist-standalone/cjs/subscription-proof.js +230 -0
  215. package/dist-standalone/cjs/succession.js +148 -0
  216. package/dist-standalone/cjs/transport.js +63 -0
  217. package/dist-standalone/cjs/trust-registry.js +742 -0
  218. package/dist-standalone/cjs/verify.js +25 -0
  219. package/dist-standalone/cjs/xfetch.js +252 -0
  220. package/dist-standalone/cli/init.d.ts +63 -0
  221. package/dist-standalone/cli/init.js +450 -0
  222. package/dist-standalone/connect.d.ts +143 -0
  223. package/dist-standalone/connect.js +274 -0
  224. package/dist-standalone/did-document.d.ts +65 -0
  225. package/dist-standalone/did-document.js +96 -0
  226. package/dist-standalone/did-privateme.d.ts +70 -0
  227. package/dist-standalone/did-privateme.js +121 -0
  228. package/dist-standalone/did-web.d.ts +73 -0
  229. package/dist-standalone/did-web.js +196 -0
  230. package/dist-standalone/discovery.d.ts +176 -0
  231. package/dist-standalone/discovery.js +458 -0
  232. package/dist-standalone/dual-mode.d.ts +145 -0
  233. package/dist-standalone/dual-mode.js +247 -0
  234. package/dist-standalone/email-templates.d.ts +41 -0
  235. package/dist-standalone/email-templates.js +309 -0
  236. package/dist-standalone/email-transport.d.ts +139 -0
  237. package/dist-standalone/email-transport.js +232 -0
  238. package/dist-standalone/envelope.d.ts +288 -0
  239. package/dist-standalone/envelope.js +497 -0
  240. package/dist-standalone/errors.d.ts +74 -0
  241. package/dist-standalone/errors.js +548 -0
  242. package/dist-standalone/gateway-state.d.ts +32 -0
  243. package/dist-standalone/gateway-state.js +51 -0
  244. package/dist-standalone/gateway-transport.d.ts +59 -0
  245. package/dist-standalone/gateway-transport.js +116 -0
  246. package/dist-standalone/guardrails.d.ts +136 -0
  247. package/dist-standalone/guardrails.js +216 -0
  248. package/dist-standalone/http-compat.d.ts +150 -0
  249. package/dist-standalone/http-compat.js +267 -0
  250. package/dist-standalone/identity.d.ts +176 -0
  251. package/dist-standalone/identity.js +516 -0
  252. package/dist-standalone/index.d.ts +83 -0
  253. package/dist-standalone/index.js +51 -0
  254. package/dist-standalone/invitation.d.ts +211 -0
  255. package/dist-standalone/invitation.js +415 -0
  256. package/dist-standalone/invite.d.ts +192 -0
  257. package/dist-standalone/invite.js +324 -0
  258. package/dist-standalone/key-agreement.d.ts +122 -0
  259. package/dist-standalone/key-agreement.js +236 -0
  260. package/dist-standalone/lazy-init.d.ts +167 -0
  261. package/dist-standalone/lazy-init.js +295 -0
  262. package/dist-standalone/mdns-discovery.d.ts +117 -0
  263. package/dist-standalone/mdns-discovery.js +195 -0
  264. package/dist-standalone/nonce-store.d.ts +39 -0
  265. package/dist-standalone/nonce-store.js +62 -0
  266. package/dist-standalone/package.json +11 -0
  267. package/dist-standalone/pairing-manager.d.ts +147 -0
  268. package/dist-standalone/pairing-manager.js +219 -0
  269. package/dist-standalone/policy.d.ts +150 -0
  270. package/dist-standalone/policy.js +315 -0
  271. package/dist-standalone/redis-nonce-store.d.ts +93 -0
  272. package/dist-standalone/redis-nonce-store.js +72 -0
  273. package/dist-standalone/registry-middleware.d.ts +38 -0
  274. package/dist-standalone/registry-middleware.js +47 -0
  275. package/dist-standalone/retry-transport.d.ts +76 -0
  276. package/dist-standalone/retry-transport.js +98 -0
  277. package/dist-standalone/security-policy.d.ts +146 -0
  278. package/dist-standalone/security-policy.js +198 -0
  279. package/dist-standalone/split-channel.d.ts +69 -0
  280. package/dist-standalone/split-channel.js +171 -0
  281. package/dist-standalone/subscription-proof.d.ts +103 -0
  282. package/dist-standalone/subscription-proof.js +224 -0
  283. package/dist-standalone/succession.d.ts +57 -0
  284. package/dist-standalone/succession.js +142 -0
  285. package/dist-standalone/transport.d.ts +50 -0
  286. package/dist-standalone/transport.js +59 -0
  287. package/dist-standalone/trust-registry.d.ts +286 -0
  288. package/dist-standalone/trust-registry.js +702 -0
  289. package/dist-standalone/verify.d.ts +16 -0
  290. package/dist-standalone/verify.js +16 -0
  291. package/dist-standalone/xfetch.d.ts +129 -0
  292. package/dist-standalone/xfetch.js +247 -0
  293. package/llms.txt +800 -0
  294. package/package.json +79 -0
  295. package/share1.dat +0 -0
@@ -0,0 +1,236 @@
1
+ import { ok, err } from"./_deps/shared/index.js";
2
+ import { MlKem768 } from 'mlkem';
3
+ /* -- Constants -- */
4
+ const X25519_RAW_KEY_BYTES = 32;
5
+ const AES_KEY_BITS = 256;
6
+ /* -- Helpers -- */
7
+ /** Copy Uint8Array to fresh ArrayBuffer. */
8
+ function toArrayBuffer(data) {
9
+ const buf = new ArrayBuffer(data.byteLength);
10
+ new Uint8Array(buf).set(data);
11
+ return buf;
12
+ }
13
+ /* -- Key Generation -- */
14
+ /**
15
+ * Generate an ephemeral X25519 key pair for ECDH key agreement.
16
+ *
17
+ * Uses Web Crypto API to generate a fresh X25519 key pair.
18
+ * The key pair is ephemeral -- it should be used for a single
19
+ * key agreement and then discarded.
20
+ *
21
+ * @returns Result containing the ephemeral key pair or error.
22
+ */
23
+ export async function generateEphemeralKeyPair() {
24
+ try {
25
+ // SAFETY: X25519 generateKey always returns CryptoKeyPair
26
+ const keyPair = await crypto.subtle.generateKey({ name: 'X25519' }, true, ['deriveBits']);
27
+ const rawPub = new Uint8Array(await crypto.subtle.exportKey('raw', keyPair.publicKey));
28
+ return ok({
29
+ privateKey: keyPair.privateKey,
30
+ publicKey: keyPair.publicKey,
31
+ rawPublicKey: rawPub,
32
+ });
33
+ }
34
+ catch {
35
+ return err('KEYGEN_FAILED');
36
+ }
37
+ }
38
+ /* -- Key Import -- */
39
+ /**
40
+ * Import a raw 32-byte X25519 public key into a CryptoKey.
41
+ *
42
+ * Used by the receiver to import the sender's ephemeral public
43
+ * key from the envelope for ECDH derivation.
44
+ *
45
+ * @param rawPublicKey - Raw 32-byte X25519 public key.
46
+ * @returns Result containing the imported CryptoKey or error.
47
+ */
48
+ export async function importX25519PublicKey(rawPublicKey) {
49
+ if (rawPublicKey.length !== X25519_RAW_KEY_BYTES) {
50
+ return err('INVALID_KEY_LENGTH:EXPECTED_32');
51
+ }
52
+ try {
53
+ const key = await crypto.subtle.importKey('raw', toArrayBuffer(rawPublicKey), { name: 'X25519' }, true, []);
54
+ return ok(key);
55
+ }
56
+ catch {
57
+ return err('IMPORT_FAILED');
58
+ }
59
+ }
60
+ /* -- ECDH Key Derivation -- */
61
+ /**
62
+ * Derive a shared AES-256-GCM key via X25519 ECDH.
63
+ *
64
+ * Performs ECDH key agreement between a local private key and a
65
+ * remote public key, producing 256 bits of shared secret that
66
+ * are imported as an AES-256-GCM key.
67
+ *
68
+ * @param localPrivateKey - Local X25519 private key.
69
+ * @param remotePublicKey - Remote X25519 public key (CryptoKey).
70
+ * @returns Result containing the derived AES-256-GCM key or error.
71
+ */
72
+ export async function deriveSharedKeyECDH(localPrivateKey, remotePublicKey) {
73
+ try {
74
+ const sharedBits = await crypto.subtle.deriveBits({ name: 'X25519', public: remotePublicKey }, localPrivateKey, AES_KEY_BITS);
75
+ const aesKey = await crypto.subtle.importKey('raw', sharedBits, { name: 'AES-GCM', length: AES_KEY_BITS }, false, ['encrypt', 'decrypt']);
76
+ return ok(aesKey);
77
+ }
78
+ catch {
79
+ return err('DERIVE_FAILED');
80
+ }
81
+ }
82
+ /* -- High-Level API -- */
83
+ /**
84
+ * Perform sender-side ECDH key agreement.
85
+ *
86
+ * Generates an ephemeral X25519 key pair, derives a shared key
87
+ * with the recipient's static X25519 public key, and returns
88
+ * both the shared key and the ephemeral public key to include
89
+ * in the envelope.
90
+ *
91
+ * @param recipientX25519PubKey - Recipient's static X25519 public key.
92
+ * @returns Result containing the key agreement result or error.
93
+ */
94
+ export async function senderKeyAgreement(recipientX25519PubKey) {
95
+ const ephemeral = await generateEphemeralKeyPair();
96
+ if (!ephemeral.ok)
97
+ return ephemeral;
98
+ const shared = await deriveSharedKeyECDH(ephemeral.value.privateKey, recipientX25519PubKey);
99
+ if (!shared.ok)
100
+ return shared;
101
+ return ok({
102
+ sharedKey: shared.value,
103
+ ephemeralPublicKey: ephemeral.value.rawPublicKey,
104
+ });
105
+ }
106
+ /**
107
+ * Perform receiver-side ECDH key agreement.
108
+ *
109
+ * Imports the sender's ephemeral public key from the envelope
110
+ * and derives the shared key using the receiver's static X25519
111
+ * private key.
112
+ *
113
+ * @param receiverPrivateKey - Receiver's static X25519 private key.
114
+ * @param senderEphemeralPubRaw - Sender's ephemeral public key (raw bytes).
115
+ * @returns Result containing the derived AES-256-GCM key or error.
116
+ */
117
+ export async function receiverKeyAgreement(receiverPrivateKey, senderEphemeralPubRaw) {
118
+ const imported = await importX25519PublicKey(senderEphemeralPubRaw);
119
+ if (!imported.ok)
120
+ return imported;
121
+ return deriveSharedKeyECDH(receiverPrivateKey, imported.value);
122
+ }
123
+ /* -- Hybrid Key Agreement (X25519 + ML-KEM-768) -- */
124
+ const HYBRID_HKDF_INFO = 'xail-hybrid-kem-v2';
125
+ /**
126
+ * Combine X25519 and ML-KEM shared secrets via HKDF-SHA256.
127
+ *
128
+ * Concatenates 32B X25519 + 32B ML-KEM shared secrets, runs HKDF
129
+ * with zero salt and 'xail-hybrid-kem-v2' info, outputs 256-bit AES key.
130
+ * Secure as long as either X25519 OR ML-KEM remains unbroken.
131
+ *
132
+ * @param x25519Shared - 32-byte raw X25519 ECDH shared bits.
133
+ * @param mlKemShared - 32-byte ML-KEM-768 shared secret.
134
+ * @returns AES-256-GCM CryptoKey derived from both secrets.
135
+ */
136
+ export async function combineSharedSecrets(x25519Shared, mlKemShared) {
137
+ try {
138
+ const combined = new Uint8Array(x25519Shared.length + mlKemShared.length);
139
+ combined.set(x25519Shared);
140
+ combined.set(mlKemShared, x25519Shared.length);
141
+ const baseKey = await crypto.subtle.importKey('raw', toArrayBuffer(combined), 'HKDF', false, ['deriveBits']);
142
+ const derived = await crypto.subtle.deriveBits({
143
+ name: 'HKDF',
144
+ hash: 'SHA-256',
145
+ salt: new Uint8Array(32),
146
+ info: new TextEncoder().encode(HYBRID_HKDF_INFO),
147
+ }, baseKey, AES_KEY_BITS);
148
+ const aesKey = await crypto.subtle.importKey('raw', derived, { name: 'AES-GCM', length: AES_KEY_BITS }, false, ['encrypt', 'decrypt']);
149
+ return ok(aesKey);
150
+ }
151
+ catch {
152
+ return err('HKDF_FAILED');
153
+ }
154
+ }
155
+ /**
156
+ * Perform sender-side hybrid key agreement (X25519 + ML-KEM-768).
157
+ *
158
+ * 1. Generate ephemeral X25519, ECDH → x25519SharedBits
159
+ * 2. ML-KEM-768 encapsulate → kemCiphertext + mlKemShared
160
+ * 3. HKDF(x25519Shared || mlKemShared) → AES-256-GCM key
161
+ *
162
+ * @param recipientX25519Pub - Recipient's static X25519 public key.
163
+ * @param recipientMlKemPub - Recipient's ML-KEM-768 public key (1184B).
164
+ * @returns Hybrid key agreement result with shared key, ephemeral pub, and KEM ciphertext.
165
+ */
166
+ export async function senderHybridKeyAgreement(recipientX25519Pub, recipientMlKemPub) {
167
+ // Step 1: Ephemeral X25519 ECDH
168
+ const ephemeral = await generateEphemeralKeyPair();
169
+ if (!ephemeral.ok)
170
+ return ephemeral;
171
+ let x25519Shared;
172
+ try {
173
+ x25519Shared = new Uint8Array(await crypto.subtle.deriveBits({ name: 'X25519', public: recipientX25519Pub }, ephemeral.value.privateKey, AES_KEY_BITS));
174
+ }
175
+ catch {
176
+ return err('DERIVE_FAILED');
177
+ }
178
+ // Step 2: ML-KEM-768 encapsulate
179
+ let kemCipherText;
180
+ let kemSharedSecret;
181
+ try {
182
+ const mlkem = new MlKem768();
183
+ const [cipherText, sharedSecret] = await mlkem.encap(recipientMlKemPub);
184
+ kemCipherText = cipherText;
185
+ kemSharedSecret = sharedSecret;
186
+ }
187
+ catch {
188
+ return err('KEM_ENCAPSULATE_FAILED');
189
+ }
190
+ // Step 3: Combine via HKDF
191
+ const combined = await combineSharedSecrets(x25519Shared, kemSharedSecret);
192
+ if (!combined.ok)
193
+ return combined;
194
+ return ok({
195
+ sharedKey: combined.value,
196
+ ephemeralPublicKey: ephemeral.value.rawPublicKey,
197
+ kemCiphertext: kemCipherText,
198
+ });
199
+ }
200
+ /**
201
+ * Perform receiver-side hybrid key agreement (X25519 + ML-KEM-768).
202
+ *
203
+ * 1. Import ephemeral X25519, ECDH → x25519SharedBits
204
+ * 2. ML-KEM-768 decapsulate → mlKemShared
205
+ * 3. HKDF(x25519Shared || mlKemShared) → same AES-256-GCM key
206
+ *
207
+ * @param x25519PrivateKey - Receiver's static X25519 private key.
208
+ * @param ephPubRaw - Sender's ephemeral X25519 public key (32B).
209
+ * @param kemCiphertext - ML-KEM-768 ciphertext from sender (1088B).
210
+ * @param mlKemSecretKey - Receiver's ML-KEM-768 secret key (2400B).
211
+ * @returns AES-256-GCM shared key or error.
212
+ */
213
+ export async function receiverHybridKeyAgreement(x25519PrivateKey, ephPubRaw, kemCiphertext, mlKemSecretKey) {
214
+ // Step 1: X25519 ECDH
215
+ const imported = await importX25519PublicKey(ephPubRaw);
216
+ if (!imported.ok)
217
+ return imported;
218
+ let x25519Shared;
219
+ try {
220
+ x25519Shared = new Uint8Array(await crypto.subtle.deriveBits({ name: 'X25519', public: imported.value }, x25519PrivateKey, AES_KEY_BITS));
221
+ }
222
+ catch {
223
+ return err('DERIVE_FAILED');
224
+ }
225
+ // Step 2: ML-KEM-768 decapsulate
226
+ let mlKemShared;
227
+ try {
228
+ const mlkem = new MlKem768();
229
+ mlKemShared = await mlkem.decap(kemCiphertext, mlKemSecretKey);
230
+ }
231
+ catch {
232
+ return err('KEM_DECAPSULATE_FAILED');
233
+ }
234
+ // Step 3: Combine via HKDF
235
+ return combineSharedSecrets(x25519Shared, mlKemShared);
236
+ }
@@ -0,0 +1,167 @@
1
+ /**
2
+ * @module lazy-init
3
+ * Lazy agent initialization for zero-click onboarding.
4
+ *
5
+ * Defers invite acceptance and identity generation until first
6
+ * send/receive call. Enables: `Agent.lazy({ name: 'my-service' })`
7
+ * with no async/await at construction time.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * // Environment: XBIND_INVITE_CODE=XBD-abc123
12
+ *
13
+ * // Old way (explicit):
14
+ * const agent = await Agent.create({ name: 'my-service', registry, transport });
15
+ *
16
+ * // New way (lazy):
17
+ * const agent = Agent.lazy({ name: 'my-service' });
18
+ * // No await, no async — agent is constructed synchronously.
19
+ * // Invite auto-accepts on first send/receive:
20
+ * await agent.send({ to: partnerDid, payload: data, scope: 'test' });
21
+ * ```
22
+ */
23
+ import { Result } from '@private.me/shared';
24
+ import { Agent } from './agent.js';
25
+ import type { AgentError, AgentSendOptions, AgentMessage, AgentReceiveOptions } from './agent.js';
26
+ import type { AnyTransportEnvelope } from './envelope.js';
27
+ import type { AutoAcceptConfig } from './auto-accept.js';
28
+ import type { TrustRegistry } from './trust-registry.js';
29
+ import type { XailTransportAdapter } from './transport.js';
30
+ /**
31
+ * Lazy agent configuration options.
32
+ */
33
+ export interface LazyAgentConfig {
34
+ /** Service name (required). */
35
+ name: string;
36
+ /** Invite code or URL. If omitted, reads from XBIND_INVITE_CODE. */
37
+ inviteCode?: string;
38
+ /** Auto-accept config (optional). */
39
+ autoAccept?: AutoAcceptConfig;
40
+ /** Custom trust registry (optional, auto-configured from invite if omitted). */
41
+ registry?: TrustRegistry;
42
+ /** Custom transport adapter (optional, auto-configured from invite if omitted). */
43
+ transport?: XailTransportAdapter | XailTransportAdapter[];
44
+ /** Enable post-quantum signatures (default: false). */
45
+ postQuantumSig?: boolean;
46
+ /** Enable Xchange mode support (default: false). */
47
+ xchange?: boolean;
48
+ /** Service endpoint URL (required for invite acceptance). */
49
+ endpoint?: string;
50
+ }
51
+ /**
52
+ * Lazy agent error codes.
53
+ */
54
+ export declare enum LazyAgentErrorCode {
55
+ INIT_FAILED = "LAZY_AGENT_INIT_FAILED",
56
+ AUTO_ACCEPT_FAILED = "LAZY_AGENT_AUTO_ACCEPT_FAILED",
57
+ AGENT_CREATION_FAILED = "LAZY_AGENT_AGENT_CREATION_FAILED"
58
+ }
59
+ /**
60
+ * Lazy agent error.
61
+ */
62
+ export interface LazyAgentError {
63
+ code: LazyAgentErrorCode;
64
+ message: string;
65
+ hint?: string;
66
+ cause?: unknown;
67
+ }
68
+ /**
69
+ * Lazy agent wrapper.
70
+ *
71
+ * Proxies all Agent methods and initializes on first call.
72
+ * Caches the initialized agent for subsequent calls.
73
+ */
74
+ export declare class LazyAgent {
75
+ private config;
76
+ private agent;
77
+ private initPromise;
78
+ private lastError;
79
+ constructor(config: LazyAgentConfig);
80
+ /**
81
+ * Get the agent's DID.
82
+ *
83
+ * Triggers initialization if not already initialized.
84
+ * Throws if initialization fails.
85
+ */
86
+ get did(): string;
87
+ /**
88
+ * Check if agent is ready (initialized).
89
+ */
90
+ isReady(): boolean;
91
+ /**
92
+ * Get last initialization error (if any).
93
+ */
94
+ getLastError(): LazyAgentError | null;
95
+ /**
96
+ * Ensure agent is initialized.
97
+ *
98
+ * Can be called explicitly to trigger init before first send/receive.
99
+ * Safe to call multiple times — subsequent calls return cached agent.
100
+ *
101
+ * @returns Agent instance or error
102
+ */
103
+ ensureInitialized(): Promise<Result<Agent, AgentError>>;
104
+ /**
105
+ * Internal initialization logic.
106
+ *
107
+ * 1. Auto-accept invite (if XBIND_INVITE_CODE set)
108
+ * 2. Create agent identity
109
+ * 3. Configure registry and transport
110
+ * 4. Return initialized agent
111
+ */
112
+ private initialize;
113
+ /**
114
+ * Send a message (proxied to underlying agent).
115
+ *
116
+ * Automatically initializes agent on first call.
117
+ */
118
+ send(opts: AgentSendOptions): Promise<Result<void, AgentError>>;
119
+ /**
120
+ * Receive a message (proxied to underlying agent).
121
+ *
122
+ * Automatically initializes agent on first call.
123
+ */
124
+ receive(envelope: AnyTransportEnvelope, opts?: AgentReceiveOptions): Promise<Result<AgentMessage, AgentError>>;
125
+ /**
126
+ * Receive a split-channel share (proxied to underlying agent).
127
+ *
128
+ * Automatically initializes agent on first call.
129
+ */
130
+ receiveSplitShare(envelope: AnyTransportEnvelope): Promise<Result<AgentMessage | null, AgentError>>;
131
+ /**
132
+ * Get environment variable value.
133
+ *
134
+ * @param key - Environment variable name
135
+ * @returns Environment variable value or empty string
136
+ */
137
+ private getEnv;
138
+ /**
139
+ * Export the underlying agent (for advanced use cases).
140
+ *
141
+ * Throws if agent is not initialized.
142
+ */
143
+ getAgent(): Agent;
144
+ }
145
+ /**
146
+ * Create a lazy agent that initializes on first use.
147
+ *
148
+ * Extension method for Agent class. Adds `Agent.lazy()` factory.
149
+ *
150
+ * @param config - Lazy agent configuration
151
+ * @returns Lazy agent wrapper
152
+ *
153
+ * @example
154
+ * ```ts
155
+ * // Environment: XBIND_INVITE_CODE=XBD-abc123
156
+ *
157
+ * const agent = createLazyAgent({ name: 'my-service' });
158
+ *
159
+ * // No initialization yet — happens on first send:
160
+ * await agent.send({
161
+ * to: 'did:key:z6Mk...',
162
+ * payload: { action: 'test' },
163
+ * scope: 'test',
164
+ * });
165
+ * ```
166
+ */
167
+ export declare function createLazyAgent(config: LazyAgentConfig): LazyAgent;
@@ -0,0 +1,295 @@
1
+ /**
2
+ * @module lazy-init
3
+ * Lazy agent initialization for zero-click onboarding.
4
+ *
5
+ * Defers invite acceptance and identity generation until first
6
+ * send/receive call. Enables: `Agent.lazy({ name: 'my-service' })`
7
+ * with no async/await at construction time.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * // Environment: XBIND_INVITE_CODE=XBD-abc123
12
+ *
13
+ * // Old way (explicit):
14
+ * const agent = await Agent.create({ name: 'my-service', registry, transport });
15
+ *
16
+ * // New way (lazy):
17
+ * const agent = Agent.lazy({ name: 'my-service' });
18
+ * // No await, no async — agent is constructed synchronously.
19
+ * // Invite auto-accepts on first send/receive:
20
+ * await agent.send({ to: partnerDid, payload: data, scope: 'test' });
21
+ * ```
22
+ */
23
+ import { ok, err } from"./_deps/shared/index.js";
24
+ import { Agent } from './agent.js';
25
+ import { autoAcceptInvite } from './auto-accept.js';
26
+ import { MemoryTrustRegistry } from './trust-registry.js';
27
+ import { HttpsTransportAdapter } from './transport.js';
28
+ import { toBase64 } from"./_deps/crypto/index.js";
29
+ /**
30
+ * Lazy agent error codes.
31
+ */
32
+ export var LazyAgentErrorCode;
33
+ (function (LazyAgentErrorCode) {
34
+ LazyAgentErrorCode["INIT_FAILED"] = "LAZY_AGENT_INIT_FAILED";
35
+ LazyAgentErrorCode["AUTO_ACCEPT_FAILED"] = "LAZY_AGENT_AUTO_ACCEPT_FAILED";
36
+ LazyAgentErrorCode["AGENT_CREATION_FAILED"] = "LAZY_AGENT_AGENT_CREATION_FAILED";
37
+ })(LazyAgentErrorCode || (LazyAgentErrorCode = {}));
38
+ /**
39
+ * Lazy agent wrapper.
40
+ *
41
+ * Proxies all Agent methods and initializes on first call.
42
+ * Caches the initialized agent for subsequent calls.
43
+ */
44
+ export class LazyAgent {
45
+ config;
46
+ agent = null;
47
+ initPromise = null;
48
+ lastError = null;
49
+ constructor(config) {
50
+ this.config = config;
51
+ }
52
+ /**
53
+ * Get the agent's DID.
54
+ *
55
+ * Triggers initialization if not already initialized.
56
+ * Throws if initialization fails.
57
+ */
58
+ get did() {
59
+ if (!this.agent) {
60
+ throw new Error('Agent not initialized. Call send/receive first or await ensureInitialized().');
61
+ }
62
+ return this.agent.did;
63
+ }
64
+ /**
65
+ * Check if agent is ready (initialized).
66
+ */
67
+ isReady() {
68
+ return this.agent !== null;
69
+ }
70
+ /**
71
+ * Get last initialization error (if any).
72
+ */
73
+ getLastError() {
74
+ return this.lastError;
75
+ }
76
+ /**
77
+ * Ensure agent is initialized.
78
+ *
79
+ * Can be called explicitly to trigger init before first send/receive.
80
+ * Safe to call multiple times — subsequent calls return cached agent.
81
+ *
82
+ * @returns Agent instance or error
83
+ */
84
+ async ensureInitialized() {
85
+ // If already initialized, return cached agent
86
+ if (this.agent) {
87
+ return ok(this.agent);
88
+ }
89
+ // If initialization is in progress, wait for it
90
+ if (this.initPromise) {
91
+ return this.initPromise;
92
+ }
93
+ // Start initialization
94
+ this.initPromise = this.initialize();
95
+ const result = await this.initPromise;
96
+ // Clear promise after completion (success or failure)
97
+ this.initPromise = null;
98
+ if (result.ok) {
99
+ this.agent = result.value;
100
+ this.lastError = null;
101
+ }
102
+ else {
103
+ this.lastError = {
104
+ code: LazyAgentErrorCode.INIT_FAILED,
105
+ message: `Agent initialization failed: ${result.error}`,
106
+ cause: result.error,
107
+ };
108
+ }
109
+ return result;
110
+ }
111
+ /**
112
+ * Internal initialization logic.
113
+ *
114
+ * 1. Auto-accept invite (if XBIND_INVITE_CODE set)
115
+ * 2. Create agent identity
116
+ * 3. Configure registry and transport
117
+ * 4. Return initialized agent
118
+ */
119
+ async initialize() {
120
+ // Step 1: Attempt auto-accept if invite code is available
121
+ const inviteCode = this.config.inviteCode ?? this.getEnv('XBIND_INVITE_CODE');
122
+ let registry = this.config.registry;
123
+ let transport = this.config.transport;
124
+ const endpoint = this.config.endpoint ?? this.getEnv('XBIND_ENDPOINT') ?? '';
125
+ if (inviteCode) {
126
+ // Create temporary agent to get DID and public key for invite acceptance
127
+ const tempAgentResult = await Agent.create({
128
+ name: this.config.name,
129
+ registry: new MemoryTrustRegistry(),
130
+ transport: new HttpsTransportAdapter({ baseUrl: 'http://localhost' }), // Placeholder
131
+ postQuantumSig: this.config.postQuantumSig,
132
+ xchange: this.config.xchange,
133
+ });
134
+ if (!tempAgentResult.ok) {
135
+ return err(tempAgentResult.error);
136
+ }
137
+ const tempAgent = tempAgentResult.value;
138
+ // Export public key for invite acceptance
139
+ const seedsResult = await tempAgent.exportSeeds();
140
+ if (!seedsResult.ok) {
141
+ return err('IDENTITY_FAILED');
142
+ }
143
+ const publicKey = toBase64(tempAgent.identity.rawPublicKey);
144
+ const x25519PublicKey = tempAgent.identity.rawX25519PublicKey
145
+ ? toBase64(tempAgent.identity.rawX25519PublicKey)
146
+ : undefined;
147
+ // Auto-accept invite
148
+ const acceptResult = await autoAcceptInvite({
149
+ inviteCode,
150
+ enabled: true,
151
+ registry: this.config.autoAccept?.registry,
152
+ inviteApiUrl: this.config.autoAccept?.inviteApiUrl,
153
+ }, {
154
+ name: this.config.name,
155
+ did: tempAgent.did,
156
+ endpoint,
157
+ publicKey,
158
+ x25519PublicKey,
159
+ });
160
+ if (!acceptResult.ok) {
161
+ this.lastError = {
162
+ code: LazyAgentErrorCode.AUTO_ACCEPT_FAILED,
163
+ message: acceptResult.error.message,
164
+ hint: acceptResult.error.hint,
165
+ cause: acceptResult.error,
166
+ };
167
+ // Non-fatal: continue with temp agent even if auto-accept fails
168
+ // (registry may already be configured)
169
+ }
170
+ else {
171
+ // Use auto-configured registry if not provided
172
+ if (!registry && acceptResult.value.registryAutoconfigured) {
173
+ // Registry was already configured by autoAcceptInvite
174
+ registry = this.config.autoAccept?.registry ?? new MemoryTrustRegistry();
175
+ }
176
+ // Use inviter's endpoint as default transport if not provided
177
+ if (!transport) {
178
+ transport = new HttpsTransportAdapter({
179
+ baseUrl: acceptResult.value.from.endpoint,
180
+ });
181
+ }
182
+ }
183
+ // Return temp agent as initialized agent
184
+ this.agent = tempAgent;
185
+ return ok(tempAgent);
186
+ }
187
+ // Step 2: No invite code — create agent normally
188
+ const defaultRegistry = registry ?? new MemoryTrustRegistry();
189
+ const defaultTransport = transport ?? new HttpsTransportAdapter({
190
+ baseUrl: endpoint || 'http://localhost',
191
+ });
192
+ const agentResult = await Agent.create({
193
+ name: this.config.name,
194
+ registry: defaultRegistry,
195
+ transport: defaultTransport,
196
+ postQuantumSig: this.config.postQuantumSig,
197
+ xchange: this.config.xchange,
198
+ });
199
+ if (!agentResult.ok) {
200
+ this.lastError = {
201
+ code: LazyAgentErrorCode.AGENT_CREATION_FAILED,
202
+ message: `Agent creation failed: ${agentResult.error}`,
203
+ cause: agentResult.error,
204
+ };
205
+ return agentResult;
206
+ }
207
+ this.agent = agentResult.value;
208
+ return ok(this.agent);
209
+ }
210
+ /**
211
+ * Send a message (proxied to underlying agent).
212
+ *
213
+ * Automatically initializes agent on first call.
214
+ */
215
+ async send(opts) {
216
+ const agentResult = await this.ensureInitialized();
217
+ if (!agentResult.ok) {
218
+ return agentResult;
219
+ }
220
+ return agentResult.value.send(opts);
221
+ }
222
+ /**
223
+ * Receive a message (proxied to underlying agent).
224
+ *
225
+ * Automatically initializes agent on first call.
226
+ */
227
+ async receive(envelope, opts) {
228
+ const agentResult = await this.ensureInitialized();
229
+ if (!agentResult.ok) {
230
+ return err(agentResult.error);
231
+ }
232
+ return agentResult.value.receive(envelope, opts);
233
+ }
234
+ /**
235
+ * Receive a split-channel share (proxied to underlying agent).
236
+ *
237
+ * Automatically initializes agent on first call.
238
+ */
239
+ async receiveSplitShare(envelope) {
240
+ const agentResult = await this.ensureInitialized();
241
+ if (!agentResult.ok) {
242
+ return err(agentResult.error);
243
+ }
244
+ return agentResult.value.receiveSplitShare(envelope);
245
+ }
246
+ /**
247
+ * Get environment variable value.
248
+ *
249
+ * @param key - Environment variable name
250
+ * @returns Environment variable value or empty string
251
+ */
252
+ getEnv(key) {
253
+ // SAFETY: Check for Node.js environment before accessing process
254
+ if (typeof process !== 'undefined' && typeof process.env !== 'undefined') {
255
+ return process.env[key] ?? '';
256
+ }
257
+ return '';
258
+ }
259
+ /**
260
+ * Export the underlying agent (for advanced use cases).
261
+ *
262
+ * Throws if agent is not initialized.
263
+ */
264
+ getAgent() {
265
+ if (!this.agent) {
266
+ throw new Error('Agent not initialized. Call send/receive first or await ensureInitialized().');
267
+ }
268
+ return this.agent;
269
+ }
270
+ }
271
+ /**
272
+ * Create a lazy agent that initializes on first use.
273
+ *
274
+ * Extension method for Agent class. Adds `Agent.lazy()` factory.
275
+ *
276
+ * @param config - Lazy agent configuration
277
+ * @returns Lazy agent wrapper
278
+ *
279
+ * @example
280
+ * ```ts
281
+ * // Environment: XBIND_INVITE_CODE=XBD-abc123
282
+ *
283
+ * const agent = createLazyAgent({ name: 'my-service' });
284
+ *
285
+ * // No initialization yet — happens on first send:
286
+ * await agent.send({
287
+ * to: 'did:key:z6Mk...',
288
+ * payload: { action: 'test' },
289
+ * scope: 'test',
290
+ * });
291
+ * ```
292
+ */
293
+ export function createLazyAgent(config) {
294
+ return new LazyAgent(config);
295
+ }