@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,102 @@
1
+ /**
2
+ * @module auto-accept
3
+ * Auto-accept invite on first SDK call for zero-click onboarding.
4
+ *
5
+ * Enables services to accept invites automatically without explicit
6
+ * accept commands. Invite code comes from environment variable.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * // Environment: XBIND_INVITE_CODE=XBD-abc123, XBIND_AUTO_ACCEPT=true
11
+ *
12
+ * // Auto-accept happens on first Agent method call:
13
+ * const agent = Agent.lazy({ name: 'my-service' });
14
+ * await agent.send({ to: partnerDid, payload: data, scope: 'test' });
15
+ * // ↑ Invite auto-accepted before send()
16
+ * ```
17
+ */
18
+ import { Result } from '@private.me/shared';
19
+ import type { Invite } from './invite.js';
20
+ import type { ServiceInfo } from './discovery.js';
21
+ import type { TrustRegistry } from './trust-registry.js';
22
+ /**
23
+ * Auto-accept configuration options.
24
+ */
25
+ export interface AutoAcceptConfig {
26
+ /** Invite code (e.g., 'XBD-abc123') or URL. If omitted, reads from XBIND_INVITE_CODE env var. */
27
+ inviteCode?: string;
28
+ /** Whether to enable auto-accept. Default: true if XBIND_INVITE_CODE is set. */
29
+ enabled?: boolean;
30
+ /** Custom invite API URL (default: https://xbind.to). */
31
+ inviteApiUrl?: string;
32
+ /** Custom trust registry (default: auto-detect from invite or use memory registry). */
33
+ registry?: TrustRegistry;
34
+ }
35
+ /**
36
+ * Auto-accept error codes.
37
+ */
38
+ export declare enum AutoAcceptErrorCode {
39
+ NO_INVITE_CODE = "AUTO_ACCEPT_NO_INVITE_CODE",
40
+ DISABLED = "AUTO_ACCEPT_DISABLED",
41
+ INVITE_FAILED = "AUTO_ACCEPT_INVITE_FAILED",
42
+ REGISTRY_SETUP_FAILED = "AUTO_ACCEPT_REGISTRY_SETUP_FAILED"
43
+ }
44
+ /**
45
+ * Auto-accept error.
46
+ */
47
+ export interface AutoAcceptError {
48
+ code: AutoAcceptErrorCode;
49
+ message: string;
50
+ hint?: string;
51
+ cause?: unknown;
52
+ }
53
+ /**
54
+ * Result of auto-accept operation.
55
+ */
56
+ export interface AcceptDetails {
57
+ /** The invite that was accepted. */
58
+ invite: Invite;
59
+ /** Service info of the inviter. */
60
+ from: ServiceInfo;
61
+ /** Trust registry URL (if provided in invite). */
62
+ registryUrl?: string;
63
+ /** Whether registry was auto-configured. */
64
+ registryAutoconfigured: boolean;
65
+ }
66
+ /**
67
+ * Auto-accept an invite on first SDK call.
68
+ *
69
+ * Reads invite code from config or environment variable `XBIND_INVITE_CODE`.
70
+ * If `XBIND_AUTO_ACCEPT` is false, returns error with code DISABLED.
71
+ *
72
+ * When successful:
73
+ * 1. Fetches invite details from invite server
74
+ * 2. Adds inviter to trust registry
75
+ * 3. Auto-detects registry endpoint from invite metadata (if present)
76
+ * 4. Marks invite as accepted
77
+ *
78
+ * This is called internally by `Agent.lazy()` before the first send/receive.
79
+ *
80
+ * @param config - Auto-accept configuration
81
+ * @param acceptorInfo - Acceptor service info (DID, endpoint, publicKey)
82
+ * @returns Accept details or error
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * // Manual usage (typically called internally by Agent.lazy):
87
+ * const result = await autoAcceptInvite(
88
+ * { inviteCode: 'XBD-abc123' },
89
+ * {
90
+ * name: 'my-service',
91
+ * did: 'did:key:z6Mk...',
92
+ * endpoint: 'https://my-service.com',
93
+ * publicKey: '...',
94
+ * }
95
+ * );
96
+ *
97
+ * if (result.ok) {
98
+ * console.log('Auto-accepted invite from:', result.value.from.name);
99
+ * }
100
+ * ```
101
+ */
102
+ export declare function autoAcceptInvite(config: AutoAcceptConfig, acceptorInfo: ServiceInfo): Promise<Result<AcceptDetails, AutoAcceptError>>;
@@ -0,0 +1,229 @@
1
+ /**
2
+ * @module auto-accept
3
+ * Auto-accept invite on first SDK call for zero-click onboarding.
4
+ *
5
+ * Enables services to accept invites automatically without explicit
6
+ * accept commands. Invite code comes from environment variable.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * // Environment: XBIND_INVITE_CODE=XBD-abc123, XBIND_AUTO_ACCEPT=true
11
+ *
12
+ * // Auto-accept happens on first Agent method call:
13
+ * const agent = Agent.lazy({ name: 'my-service' });
14
+ * await agent.send({ to: partnerDid, payload: data, scope: 'test' });
15
+ * // ↑ Invite auto-accepted before send()
16
+ * ```
17
+ */
18
+ import { ok, err } from"./_deps/shared/index.js";
19
+ import { InviteService } from './invite.js';
20
+ import { HttpTrustRegistry, MemoryTrustRegistry } from './trust-registry.js';
21
+ import { fromBase64 } from"./_deps/crypto/index.js";
22
+ import { importPublicKey } from './identity.js';
23
+ /**
24
+ * Auto-accept error codes.
25
+ */
26
+ export var AutoAcceptErrorCode;
27
+ (function (AutoAcceptErrorCode) {
28
+ AutoAcceptErrorCode["NO_INVITE_CODE"] = "AUTO_ACCEPT_NO_INVITE_CODE";
29
+ AutoAcceptErrorCode["DISABLED"] = "AUTO_ACCEPT_DISABLED";
30
+ AutoAcceptErrorCode["INVITE_FAILED"] = "AUTO_ACCEPT_INVITE_FAILED";
31
+ AutoAcceptErrorCode["REGISTRY_SETUP_FAILED"] = "AUTO_ACCEPT_REGISTRY_SETUP_FAILED";
32
+ })(AutoAcceptErrorCode || (AutoAcceptErrorCode = {}));
33
+ /**
34
+ * Auto-accept an invite on first SDK call.
35
+ *
36
+ * Reads invite code from config or environment variable `XBIND_INVITE_CODE`.
37
+ * If `XBIND_AUTO_ACCEPT` is false, returns error with code DISABLED.
38
+ *
39
+ * When successful:
40
+ * 1. Fetches invite details from invite server
41
+ * 2. Adds inviter to trust registry
42
+ * 3. Auto-detects registry endpoint from invite metadata (if present)
43
+ * 4. Marks invite as accepted
44
+ *
45
+ * This is called internally by `Agent.lazy()` before the first send/receive.
46
+ *
47
+ * @param config - Auto-accept configuration
48
+ * @param acceptorInfo - Acceptor service info (DID, endpoint, publicKey)
49
+ * @returns Accept details or error
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * // Manual usage (typically called internally by Agent.lazy):
54
+ * const result = await autoAcceptInvite(
55
+ * { inviteCode: 'XBD-abc123' },
56
+ * {
57
+ * name: 'my-service',
58
+ * did: 'did:key:z6Mk...',
59
+ * endpoint: 'https://my-service.com',
60
+ * publicKey: '...',
61
+ * }
62
+ * );
63
+ *
64
+ * if (result.ok) {
65
+ * console.log('Auto-accepted invite from:', result.value.from.name);
66
+ * }
67
+ * ```
68
+ */
69
+ export async function autoAcceptInvite(config, acceptorInfo) {
70
+ // Step 1: Check if auto-accept is enabled
71
+ const autoAcceptEnabled = config.enabled ?? getEnvFlag('XBIND_AUTO_ACCEPT', true);
72
+ if (!autoAcceptEnabled) {
73
+ return err({
74
+ code: AutoAcceptErrorCode.DISABLED,
75
+ message: 'Auto-accept is disabled',
76
+ hint: 'Set XBIND_AUTO_ACCEPT=true or pass { enabled: true } in config',
77
+ });
78
+ }
79
+ // Step 2: Get invite code
80
+ const inviteCode = config.inviteCode ?? getEnv('XBIND_INVITE_CODE');
81
+ if (!inviteCode) {
82
+ return err({
83
+ code: AutoAcceptErrorCode.NO_INVITE_CODE,
84
+ message: 'No invite code provided',
85
+ hint: 'Set XBIND_INVITE_CODE environment variable or pass inviteCode in config',
86
+ });
87
+ }
88
+ // Step 3: Fetch invite details
89
+ const inviteService = new InviteService({
90
+ inviteApiUrl: config.inviteApiUrl ?? getEnv('XBIND_INVITE_API_URL') ?? 'https://xbind.to',
91
+ });
92
+ const inviteUrl = normalizeInviteCode(inviteCode);
93
+ const inviteResult = await inviteService.get(inviteUrl);
94
+ if (!inviteResult.ok) {
95
+ return err({
96
+ code: AutoAcceptErrorCode.INVITE_FAILED,
97
+ message: `Failed to fetch invite: ${inviteResult.error.message}`,
98
+ hint: inviteResult.error.hint,
99
+ cause: inviteResult.error,
100
+ });
101
+ }
102
+ const invite = inviteResult.value;
103
+ // Step 4: Add inviter to trust registry
104
+ const registry = config.registry ?? await autoConfigureRegistry(invite);
105
+ try {
106
+ // Import public key from base64
107
+ const publicKeyBytes = fromBase64(invite.from.publicKey);
108
+ const publicKeyResult = await importPublicKey(publicKeyBytes);
109
+ if (!publicKeyResult.ok) {
110
+ return err({
111
+ code: AutoAcceptErrorCode.REGISTRY_SETUP_FAILED,
112
+ message: 'Invalid inviter public key',
113
+ hint: 'The invite may be corrupted',
114
+ cause: publicKeyResult.error,
115
+ });
116
+ }
117
+ // Add to registry
118
+ const addResult = await registry.register(invite.from.did, publicKeyBytes, invite.from.name, invite.permissions, invite.from.x25519PublicKey ? fromBase64(invite.from.x25519PublicKey) : undefined, invite.from.mlKemPublicKey ? fromBase64(invite.from.mlKemPublicKey) : undefined, undefined, // mlDsaPublicKey (not in invite yet)
119
+ false);
120
+ if (!addResult.ok) {
121
+ // If already registered, that's OK (idempotent)
122
+ if (addResult.error !== 'ALREADY_REGISTERED') {
123
+ return err({
124
+ code: AutoAcceptErrorCode.REGISTRY_SETUP_FAILED,
125
+ message: `Failed to add inviter to registry: ${addResult.error}`,
126
+ cause: addResult.error,
127
+ });
128
+ }
129
+ }
130
+ }
131
+ catch (error) {
132
+ return err({
133
+ code: AutoAcceptErrorCode.REGISTRY_SETUP_FAILED,
134
+ message: 'Failed to configure trust registry',
135
+ cause: error,
136
+ });
137
+ }
138
+ // Step 5: Accept the invite (marks as accepted on server)
139
+ const acceptResult = await inviteService.accept({ inviteUrl, acceptor: acceptorInfo });
140
+ if (!acceptResult.ok) {
141
+ // Non-fatal: invite acceptance is for tracking/notification only
142
+ // The connection is still established locally via registry add
143
+ }
144
+ return ok({
145
+ invite,
146
+ from: invite.from,
147
+ registryUrl: extractRegistryUrl(invite),
148
+ registryAutoconfigured: config.registry === undefined,
149
+ });
150
+ }
151
+ /**
152
+ * Auto-configure trust registry from invite metadata.
153
+ *
154
+ * Attempts to extract registry URL from invite. If found, creates HttpTrustRegistry.
155
+ * Otherwise falls back to MemoryTrustRegistry.
156
+ *
157
+ * @param invite - Invite details
158
+ * @returns Trust registry instance
159
+ */
160
+ async function autoConfigureRegistry(invite) {
161
+ const registryUrl = extractRegistryUrl(invite);
162
+ if (registryUrl) {
163
+ return new HttpTrustRegistry({ baseUrl: registryUrl });
164
+ }
165
+ return new MemoryTrustRegistry();
166
+ }
167
+ /**
168
+ * Extract registry URL from invite metadata.
169
+ *
170
+ * Checks for registry URL in invite.from.endpoint or custom metadata fields.
171
+ *
172
+ * @param invite - Invite details
173
+ * @returns Registry URL or undefined
174
+ */
175
+ function extractRegistryUrl(invite) {
176
+ // Check if endpoint is a registry URL (heuristic: contains /registry or /trust)
177
+ if (invite.from.endpoint.includes('/registry') || invite.from.endpoint.includes('/trust')) {
178
+ return invite.from.endpoint;
179
+ }
180
+ // Future: check invite.metadata.registryUrl when invite system adds it
181
+ return undefined;
182
+ }
183
+ /**
184
+ * Normalize invite code to full URL.
185
+ *
186
+ * If code is already a URL, returns as-is.
187
+ * If code is short form (e.g., 'XBD-abc123'), converts to https://xbind.to/invite/{code}.
188
+ *
189
+ * @param code - Invite code or URL
190
+ * @returns Full invite URL
191
+ */
192
+ function normalizeInviteCode(code) {
193
+ if (code.startsWith('http://') || code.startsWith('https://')) {
194
+ return code;
195
+ }
196
+ // Short form: XBD-abc123 or just abc123
197
+ const cleanCode = code.replace(/^XBD-/i, '');
198
+ return `https://xbind.to/invite/${cleanCode}`;
199
+ }
200
+ /**
201
+ * Get environment variable value.
202
+ *
203
+ * @param key - Environment variable name
204
+ * @param defaultValue - Default value if not set
205
+ * @returns Environment variable value or default
206
+ */
207
+ function getEnv(key, defaultValue) {
208
+ // SAFETY: Check for Node.js environment before accessing process
209
+ if (typeof process !== 'undefined' && typeof process.env !== 'undefined') {
210
+ return process.env[key] ?? defaultValue;
211
+ }
212
+ return defaultValue;
213
+ }
214
+ /**
215
+ * Get environment variable as boolean flag.
216
+ *
217
+ * Treats 'true', '1', 'yes' as true. Everything else as false.
218
+ *
219
+ * @param key - Environment variable name
220
+ * @param defaultValue - Default value if not set
221
+ * @returns Boolean flag
222
+ */
223
+ function getEnvFlag(key, defaultValue) {
224
+ const value = getEnv(key);
225
+ if (value === undefined)
226
+ return defaultValue;
227
+ const normalized = value.toLowerCase().trim();
228
+ return normalized === 'true' || normalized === '1' || normalized === 'yes';
229
+ }
@@ -0,0 +1,150 @@
1
+ /**
2
+ * XorIDA Backup Configuration for Key Splitting
3
+ *
4
+ * Provides default backup configuration (k=2, n=3) and utilities for
5
+ * splitting cryptographic keys across multiple shares using information-
6
+ * theoretic threshold secret sharing.
7
+ *
8
+ * @module backup-config
9
+ */
10
+ import type { Result } from '@private.me/shared';
11
+ /**
12
+ * Configuration for XorIDA backup key splitting.
13
+ *
14
+ * Threshold sharing requires k shares to reconstruct the original key.
15
+ * Total n shares are generated - up to n-k can be lost without data loss.
16
+ */
17
+ export interface BackupConfig {
18
+ /**
19
+ * Threshold: minimum number of shares required for reconstruction.
20
+ *
21
+ * Default: 2 (any 2 shares can reconstruct)
22
+ */
23
+ readonly threshold: number;
24
+ /**
25
+ * Total shares: number of shares to generate.
26
+ *
27
+ * Default: 3 (3 shares generated, lose 1 and still recover)
28
+ */
29
+ readonly totalShares: number;
30
+ }
31
+ /**
32
+ * A single backup share containing key data and metadata.
33
+ */
34
+ export interface BackupShare {
35
+ /**
36
+ * Share index (0-based).
37
+ */
38
+ readonly index: number;
39
+ /**
40
+ * Share data (base64-encoded).
41
+ */
42
+ readonly data: string;
43
+ /**
44
+ * Total shares in the set.
45
+ */
46
+ readonly total: number;
47
+ /**
48
+ * Threshold required for reconstruction.
49
+ */
50
+ readonly threshold: number;
51
+ /**
52
+ * HMAC key for integrity verification (base64).
53
+ */
54
+ readonly hmacKey: string;
55
+ /**
56
+ * HMAC signature (base64).
57
+ */
58
+ readonly hmacSig: string;
59
+ }
60
+ /**
61
+ * Error codes for backup operations.
62
+ */
63
+ export type BackupError = 'INVALID_CONFIG' | 'INVALID_KEY_LENGTH' | 'SPLIT_FAILED' | 'RECONSTRUCT_FAILED' | 'HMAC_VERIFICATION_FAILED' | 'INSUFFICIENT_SHARES' | 'INVALID_SHARE_DATA';
64
+ /**
65
+ * Default backup configuration: 2-of-3 threshold sharing.
66
+ *
67
+ * - 3 shares generated
68
+ * - Any 2 shares can reconstruct the key
69
+ * - Lose 1 share and still recover (fault tolerance)
70
+ * - Information-theoretic security (each share reveals zero information)
71
+ */
72
+ export declare const DEFAULT_BACKUP_CONFIG: BackupConfig;
73
+ /**
74
+ * Validate backup configuration parameters.
75
+ *
76
+ * Rules:
77
+ * - threshold must be >= 2 (single share = no threshold)
78
+ * - totalShares must be >= threshold
79
+ * - totalShares must be <= 255 (XorIDA limit)
80
+ *
81
+ * @param config - Backup configuration to validate.
82
+ * @returns Ok if valid, error otherwise.
83
+ */
84
+ export declare function validateBackupConfig(config: BackupConfig): Result<void, BackupError>;
85
+ /**
86
+ * Split a cryptographic key into backup shares using XorIDA.
87
+ *
88
+ * The key is padded, split via information-theoretic threshold sharing,
89
+ * and returned as BackupShare objects with HMAC integrity protection.
90
+ *
91
+ * Any `threshold` shares can reconstruct the original key. Each share
92
+ * reveals zero information about the key (information-theoretic security).
93
+ *
94
+ * @param key - The key to split (32 or 64 bytes typical).
95
+ * @param config - Backup configuration (defaults to 2-of-3).
96
+ * @returns Array of backup shares or error.
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * import { splitKeyWithBackup, DEFAULT_BACKUP_CONFIG } from '@private.me/xbind';
101
+ *
102
+ * const key = crypto.getRandomValues(new Uint8Array(32));
103
+ *
104
+ * // Use defaults (2-of-3)
105
+ * const shares = await splitKeyWithBackup(key);
106
+ *
107
+ * // Custom config (3-of-5)
108
+ * const shares2 = await splitKeyWithBackup(key, {
109
+ * threshold: 3,
110
+ * totalShares: 5
111
+ * });
112
+ *
113
+ * if (shares.ok) {
114
+ * // Store shares in separate locations
115
+ * shares.value.forEach((share, i) => {
116
+ * storeShare(`backup-${i}.json`, JSON.stringify(share));
117
+ * });
118
+ * }
119
+ * ```
120
+ */
121
+ export declare function splitKeyWithBackup(key: Uint8Array, config?: BackupConfig): Promise<Result<BackupShare[], BackupError>>;
122
+ /**
123
+ * Reconstruct a cryptographic key from backup shares.
124
+ *
125
+ * Requires at least `threshold` shares. Verifies HMAC before returning
126
+ * the reconstructed key to prevent tampering.
127
+ *
128
+ * @param shares - Backup shares (must be >= threshold).
129
+ * @returns Reconstructed key or error.
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * import { reconstructKeyFromBackup } from '@private.me/xbind';
134
+ *
135
+ * // Load shares from storage
136
+ * const share0 = JSON.parse(loadShare('backup-0.json'));
137
+ * const share1 = JSON.parse(loadShare('backup-1.json'));
138
+ *
139
+ * // Reconstruct from any 2 shares (threshold=2)
140
+ * const key = await reconstructKeyFromBackup([share0, share1]);
141
+ *
142
+ * if (key.ok) {
143
+ * // Use reconstructed key
144
+ * const agent = await Agent.fromSeed(key.value, opts);
145
+ * } else {
146
+ * console.error('Reconstruction failed:', key.error);
147
+ * }
148
+ * ```
149
+ */
150
+ export declare function reconstructKeyFromBackup(shares: BackupShare[]): Promise<Result<Uint8Array, BackupError>>;
@@ -0,0 +1,201 @@
1
+ /**
2
+ * XorIDA Backup Configuration for Key Splitting
3
+ *
4
+ * Provides default backup configuration (k=2, n=3) and utilities for
5
+ * splitting cryptographic keys across multiple shares using information-
6
+ * theoretic threshold secret sharing.
7
+ *
8
+ * @module backup-config
9
+ */
10
+ import { ok, err } from"./_deps/shared/index.js";
11
+ import { splitXorIDA, reconstructXorIDA, nextOddPrime, pkcs7Pad, pkcs7Unpad, generateHMAC, verifyHMAC, toBase64, fromBase64, } from"./_deps/crypto/index.js";
12
+ /* ── Constants ── */
13
+ /**
14
+ * Default backup configuration: 2-of-3 threshold sharing.
15
+ *
16
+ * - 3 shares generated
17
+ * - Any 2 shares can reconstruct the key
18
+ * - Lose 1 share and still recover (fault tolerance)
19
+ * - Information-theoretic security (each share reveals zero information)
20
+ */
21
+ export const DEFAULT_BACKUP_CONFIG = {
22
+ threshold: 2,
23
+ totalShares: 3,
24
+ };
25
+ /* ── Validation ── */
26
+ /**
27
+ * Validate backup configuration parameters.
28
+ *
29
+ * Rules:
30
+ * - threshold must be >= 2 (single share = no threshold)
31
+ * - totalShares must be >= threshold
32
+ * - totalShares must be <= 255 (XorIDA limit)
33
+ *
34
+ * @param config - Backup configuration to validate.
35
+ * @returns Ok if valid, error otherwise.
36
+ */
37
+ export function validateBackupConfig(config) {
38
+ if (config.threshold < 2) {
39
+ return err('INVALID_CONFIG');
40
+ }
41
+ if (config.totalShares < config.threshold) {
42
+ return err('INVALID_CONFIG');
43
+ }
44
+ if (config.totalShares > 255) {
45
+ return err('INVALID_CONFIG');
46
+ }
47
+ return ok(undefined);
48
+ }
49
+ /* ── Key Splitting ── */
50
+ /**
51
+ * Split a cryptographic key into backup shares using XorIDA.
52
+ *
53
+ * The key is padded, split via information-theoretic threshold sharing,
54
+ * and returned as BackupShare objects with HMAC integrity protection.
55
+ *
56
+ * Any `threshold` shares can reconstruct the original key. Each share
57
+ * reveals zero information about the key (information-theoretic security).
58
+ *
59
+ * @param key - The key to split (32 or 64 bytes typical).
60
+ * @param config - Backup configuration (defaults to 2-of-3).
61
+ * @returns Array of backup shares or error.
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * import { splitKeyWithBackup, DEFAULT_BACKUP_CONFIG } from '@private.me/xbind';
66
+ *
67
+ * const key = crypto.getRandomValues(new Uint8Array(32));
68
+ *
69
+ * // Use defaults (2-of-3)
70
+ * const shares = await splitKeyWithBackup(key);
71
+ *
72
+ * // Custom config (3-of-5)
73
+ * const shares2 = await splitKeyWithBackup(key, {
74
+ * threshold: 3,
75
+ * totalShares: 5
76
+ * });
77
+ *
78
+ * if (shares.ok) {
79
+ * // Store shares in separate locations
80
+ * shares.value.forEach((share, i) => {
81
+ * storeShare(`backup-${i}.json`, JSON.stringify(share));
82
+ * });
83
+ * }
84
+ * ```
85
+ */
86
+ export async function splitKeyWithBackup(key, config = DEFAULT_BACKUP_CONFIG) {
87
+ const validation = validateBackupConfig(config);
88
+ if (!validation.ok)
89
+ return validation;
90
+ if (key.length === 0) {
91
+ return err('INVALID_KEY_LENGTH');
92
+ }
93
+ const n = config.totalShares;
94
+ const k = config.threshold;
95
+ const p = nextOddPrime(n);
96
+ const blockSize = p - 1;
97
+ // Pad to block size
98
+ const padded = pkcs7Pad(key, blockSize);
99
+ // Generate HMAC for integrity verification
100
+ const { key: hmacKey, signature: hmacSig } = await generateHMAC(padded);
101
+ const hmacKeyB64 = toBase64(hmacKey);
102
+ const hmacSigB64 = toBase64(hmacSig);
103
+ // Split via XorIDA
104
+ let shareArrays;
105
+ try {
106
+ shareArrays = splitXorIDA(padded, n, k);
107
+ }
108
+ catch {
109
+ return err('SPLIT_FAILED');
110
+ }
111
+ // Package as BackupShare objects
112
+ const shares = shareArrays.map((data, index) => ({
113
+ index,
114
+ data: toBase64(data),
115
+ total: n,
116
+ threshold: k,
117
+ hmacKey: hmacKeyB64,
118
+ hmacSig: hmacSigB64,
119
+ }));
120
+ return ok(shares);
121
+ }
122
+ /* ── Key Reconstruction ── */
123
+ /**
124
+ * Reconstruct a cryptographic key from backup shares.
125
+ *
126
+ * Requires at least `threshold` shares. Verifies HMAC before returning
127
+ * the reconstructed key to prevent tampering.
128
+ *
129
+ * @param shares - Backup shares (must be >= threshold).
130
+ * @returns Reconstructed key or error.
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * import { reconstructKeyFromBackup } from '@private.me/xbind';
135
+ *
136
+ * // Load shares from storage
137
+ * const share0 = JSON.parse(loadShare('backup-0.json'));
138
+ * const share1 = JSON.parse(loadShare('backup-1.json'));
139
+ *
140
+ * // Reconstruct from any 2 shares (threshold=2)
141
+ * const key = await reconstructKeyFromBackup([share0, share1]);
142
+ *
143
+ * if (key.ok) {
144
+ * // Use reconstructed key
145
+ * const agent = await Agent.fromSeed(key.value, opts);
146
+ * } else {
147
+ * console.error('Reconstruction failed:', key.error);
148
+ * }
149
+ * ```
150
+ */
151
+ export async function reconstructKeyFromBackup(shares) {
152
+ if (shares.length === 0) {
153
+ return err('INSUFFICIENT_SHARES');
154
+ }
155
+ const threshold = shares[0].threshold;
156
+ const total = shares[0].total;
157
+ if (shares.length < threshold) {
158
+ return err('INSUFFICIENT_SHARES');
159
+ }
160
+ // Use first `threshold` shares
161
+ const usedShares = shares.slice(0, threshold);
162
+ // Decode share data
163
+ let shareData;
164
+ try {
165
+ shareData = usedShares.map((s) => fromBase64(s.data));
166
+ }
167
+ catch {
168
+ return err('INVALID_SHARE_DATA');
169
+ }
170
+ const indices = usedShares.map((s) => s.index);
171
+ // Reconstruct padded key
172
+ let padded;
173
+ try {
174
+ padded = reconstructXorIDA(shareData, indices, total, threshold);
175
+ }
176
+ catch {
177
+ return err('RECONSTRUCT_FAILED');
178
+ }
179
+ // Verify HMAC
180
+ let hmacKey;
181
+ let hmacSig;
182
+ try {
183
+ hmacKey = fromBase64(usedShares[0].hmacKey);
184
+ hmacSig = fromBase64(usedShares[0].hmacSig);
185
+ }
186
+ catch {
187
+ return err('INVALID_SHARE_DATA');
188
+ }
189
+ const hmacValid = await verifyHMAC(hmacKey, padded, hmacSig);
190
+ if (!hmacValid) {
191
+ return err('HMAC_VERIFICATION_FAILED');
192
+ }
193
+ // Unpad to recover original key
194
+ const p = nextOddPrime(total);
195
+ const blockSize = p - 1;
196
+ const unpadResult = pkcs7Unpad(padded, blockSize);
197
+ if (!unpadResult.ok) {
198
+ return err('RECONSTRUCT_FAILED');
199
+ }
200
+ return ok(unpadResult.value);
201
+ }