@private.me/xbind 3.0.2 → 3.0.4

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 (222) hide show
  1. package/README.md +2366 -204
  2. package/dist-standalone/_deps/mldsa-wasm/dist/mldsa.js +1 -1920
  3. package/dist-standalone/_deps/shared/cjs/errors.js +1 -729
  4. package/dist-standalone/_deps/shared/cjs/index.js +1 -463
  5. package/dist-standalone/_deps/shared/cjs/types.js +1 -315
  6. package/dist-standalone/_deps/shared/errors.js +1 -244
  7. package/dist-standalone/_deps/shared/index.js +1 -72
  8. package/dist-standalone/_deps/shared/types.js +1 -86
  9. package/dist-standalone/_deps/ux-helpers/cjs/errors.js +1 -1
  10. package/dist-standalone/_deps/ux-helpers/cjs/index.js +1 -1
  11. package/dist-standalone/_deps/ux-helpers/cjs/pagination.js +1 -1
  12. package/dist-standalone/_deps/ux-helpers/cjs/progress.js +1 -1
  13. package/dist-standalone/_deps/ux-helpers/cjs/search.js +1 -1
  14. package/dist-standalone/_deps/ux-helpers/cjs/types.js +1 -1
  15. package/dist-standalone/_deps/ux-helpers/errors.js +1 -1
  16. package/dist-standalone/_deps/ux-helpers/index.js +1 -1
  17. package/dist-standalone/_deps/ux-helpers/pagination.js +1 -1
  18. package/dist-standalone/_deps/ux-helpers/progress.js +1 -1
  19. package/dist-standalone/_deps/ux-helpers/search.js +1 -1
  20. package/dist-standalone/_deps/xchange/auto-accept.js +1 -1
  21. package/dist-standalone/_deps/xchange/cjs/auto-accept.js +1 -1
  22. package/dist-standalone/_deps/xchange/cjs/errors.js +1 -1
  23. package/dist-standalone/_deps/xchange/cjs/index.js +1 -1
  24. package/dist-standalone/_deps/xchange/cjs/invite-client.js +1 -1
  25. package/dist-standalone/_deps/xchange/cjs/lazy-init.js +1 -1
  26. package/dist-standalone/_deps/xchange/cjs/trust-integration.js +1 -1
  27. package/dist-standalone/_deps/xchange/cjs/xchange.js +1 -1
  28. package/dist-standalone/_deps/xchange/errors.js +1 -1
  29. package/dist-standalone/_deps/xchange/index.js +1 -1
  30. package/dist-standalone/_deps/xchange/invite-client.js +1 -1
  31. package/dist-standalone/_deps/xchange/lazy-init.js +1 -1
  32. package/dist-standalone/_deps/xchange/trust-integration.js +1 -1
  33. package/dist-standalone/_deps/xchange/xchange.js +1 -1
  34. package/dist-standalone/_deps/xregistry/cjs/discovery.js +1 -1
  35. package/dist-standalone/_deps/xregistry/cjs/errors.js +1 -1
  36. package/dist-standalone/_deps/xregistry/cjs/index.js +1 -1
  37. package/dist-standalone/_deps/xregistry/cjs/registry.js +1 -1
  38. package/dist-standalone/_deps/xregistry/cjs/schema.js +1 -1
  39. package/dist-standalone/_deps/xregistry/cjs/types.js +1 -1
  40. package/dist-standalone/_deps/xregistry/discovery.js +1 -1
  41. package/dist-standalone/_deps/xregistry/errors.js +1 -1
  42. package/dist-standalone/_deps/xregistry/index.js +1 -1
  43. package/dist-standalone/_deps/xregistry/registry.js +1 -1
  44. package/dist-standalone/_deps/xregistry/schema.js +1 -1
  45. package/dist-standalone/_deps/xregistry/types.js +1 -1
  46. package/dist-standalone/agent-call.d.ts +2 -2
  47. package/dist-standalone/agent-call.js +1 -659
  48. package/dist-standalone/agent-sdk.js +1 -328
  49. package/dist-standalone/agent.d.ts +2 -0
  50. package/dist-standalone/agent.js +1 -1800
  51. package/dist-standalone/approval.js +1 -193
  52. package/dist-standalone/async-iterators.d.ts +3 -3
  53. package/dist-standalone/async-iterators.js +1 -382
  54. package/dist-standalone/auth.js +1 -219
  55. package/dist-standalone/auto-accept.js +1 -229
  56. package/dist-standalone/backup-config.js +1 -201
  57. package/dist-standalone/backup.js +1 -326
  58. package/dist-standalone/batch-operations.js +1 -388
  59. package/dist-standalone/cancellation.js +1 -477
  60. package/dist-standalone/checkpoint.js +1 -186
  61. package/dist-standalone/circuit-breaker.js +1 -468
  62. package/dist-standalone/cjs/agent-call.js +1 -701
  63. package/dist-standalone/cjs/agent-sdk.js +1 -332
  64. package/dist-standalone/cjs/agent.js +1 -1837
  65. package/dist-standalone/cjs/approval.js +1 -199
  66. package/dist-standalone/cjs/async-iterators.js +1 -392
  67. package/dist-standalone/cjs/auth.js +1 -225
  68. package/dist-standalone/cjs/auto-accept.js +1 -233
  69. package/dist-standalone/cjs/backup-config.js +1 -207
  70. package/dist-standalone/cjs/backup.js +1 -330
  71. package/dist-standalone/cjs/batch-operations.js +1 -397
  72. package/dist-standalone/cjs/cancellation.js +1 -490
  73. package/dist-standalone/cjs/checkpoint.js +1 -193
  74. package/dist-standalone/cjs/circuit-breaker.js +1 -476
  75. package/dist-standalone/cjs/cli/init.js +1 -492
  76. package/dist-standalone/cjs/config-validation.js +1 -522
  77. package/dist-standalone/cjs/connect.js +1 -312
  78. package/dist-standalone/cjs/connection-pool.js +1 -506
  79. package/dist-standalone/cjs/correlation-id.js +1 -339
  80. package/dist-standalone/cjs/crypto-utils.js +1 -176
  81. package/dist-standalone/cjs/debug-mode.js +1 -534
  82. package/dist-standalone/cjs/did-document.js +1 -101
  83. package/dist-standalone/cjs/did-privateme.js +1 -130
  84. package/dist-standalone/cjs/did-web.js +1 -201
  85. package/dist-standalone/cjs/discovery.js +1 -462
  86. package/dist-standalone/cjs/dual-mode.js +1 -251
  87. package/dist-standalone/cjs/email-templates.js +1 -313
  88. package/dist-standalone/cjs/email-transport.js +1 -239
  89. package/dist-standalone/cjs/envelope.js +1 -538
  90. package/dist-standalone/cjs/errors.js +1 -913
  91. package/dist-standalone/cjs/event-emitter.js +1 -461
  92. package/dist-standalone/cjs/gateway-state.js +1 -55
  93. package/dist-standalone/cjs/gateway-transport.js +1 -120
  94. package/dist-standalone/cjs/graceful-degradation.js +1 -403
  95. package/dist-standalone/cjs/guardrails.js +1 -223
  96. package/dist-standalone/cjs/health-check.js +1 -336
  97. package/dist-standalone/cjs/http-compat.js +1 -272
  98. package/dist-standalone/cjs/http-status-map.js +1 -571
  99. package/dist-standalone/cjs/identity.js +1 -645
  100. package/dist-standalone/cjs/index.js +1 -406
  101. package/dist-standalone/cjs/invitation.js +1 -421
  102. package/dist-standalone/cjs/invite.js +1 -328
  103. package/dist-standalone/cjs/key-agreement.js +1 -335
  104. package/dist-standalone/cjs/lazy-init.js +1 -300
  105. package/dist-standalone/cjs/logger.js +1 -291
  106. package/dist-standalone/cjs/loopback-transport.js +1 -0
  107. package/dist-standalone/cjs/mdns-discovery.js +1 -202
  108. package/dist-standalone/cjs/nonce-store.js +1 -80
  109. package/dist-standalone/cjs/pairing-manager.js +1 -223
  110. package/dist-standalone/cjs/plugin-system.js +1 -264
  111. package/dist-standalone/cjs/plugins/logging.js +1 -168
  112. package/dist-standalone/cjs/plugins/metrics.js +1 -181
  113. package/dist-standalone/cjs/plugins/validation.js +1 -302
  114. package/dist-standalone/cjs/policy.js +1 -320
  115. package/dist-standalone/cjs/progress-callbacks.js +1 -583
  116. package/dist-standalone/cjs/redis-nonce-store.js +1 -76
  117. package/dist-standalone/cjs/registry-middleware.js +1 -50
  118. package/dist-standalone/cjs/retry-strategies.js +1 -544
  119. package/dist-standalone/cjs/retry-transport.js +1 -102
  120. package/dist-standalone/cjs/runtime/browser.js +1 -533
  121. package/dist-standalone/cjs/runtime/edge.js +1 -526
  122. package/dist-standalone/cjs/runtime/react-native.js +1 -394
  123. package/dist-standalone/cjs/security-policy.js +1 -245
  124. package/dist-standalone/cjs/serialization.js +1 -1040
  125. package/dist-standalone/cjs/split-channel.js +1 -225
  126. package/dist-standalone/cjs/subscription-proof.js +1 -230
  127. package/dist-standalone/cjs/succession.js +1 -148
  128. package/dist-standalone/cjs/timeouts.js +1 -412
  129. package/dist-standalone/cjs/trace-context.js +1 -424
  130. package/dist-standalone/cjs/trace-spans.js +1 -495
  131. package/dist-standalone/cjs/transport.js +1 -63
  132. package/dist-standalone/cjs/trust-registry.js +1 -991
  133. package/dist-standalone/cjs/types/error-response.js +1 -56
  134. package/dist-standalone/cjs/vault-auth.js +1 -178
  135. package/dist-standalone/cjs/vault-store-loader.js +1 -194
  136. package/dist-standalone/cjs/verify.js +1 -25
  137. package/dist-standalone/cjs/version-info.js +1 -543
  138. package/dist-standalone/cjs/xfetch.js +1 -340
  139. package/dist-standalone/cli/init.js +1 -455
  140. package/dist-standalone/cli/setup.js +1 -514
  141. package/dist-standalone/cli/types.js +1 -27
  142. package/dist-standalone/cli/xbind.js +1 -148
  143. package/dist-standalone/config-validation.js +1 -513
  144. package/dist-standalone/connect.js +1 -274
  145. package/dist-standalone/connection-pool.js +1 -500
  146. package/dist-standalone/correlation-id.js +1 -326
  147. package/dist-standalone/crypto-utils.d.ts +2 -7
  148. package/dist-standalone/crypto-utils.js +1 -157
  149. package/dist-standalone/debug-mode.js +1 -510
  150. package/dist-standalone/did-document.js +1 -96
  151. package/dist-standalone/did-privateme.js +1 -121
  152. package/dist-standalone/did-web.js +1 -196
  153. package/dist-standalone/discovery.js +1 -458
  154. package/dist-standalone/dual-mode.js +1 -247
  155. package/dist-standalone/email-templates.js +1 -309
  156. package/dist-standalone/email-transport.d.ts +2 -2
  157. package/dist-standalone/email-transport.js +1 -232
  158. package/dist-standalone/envelope.js +1 -525
  159. package/dist-standalone/errors.d.ts +13 -3
  160. package/dist-standalone/errors.js +1 -896
  161. package/dist-standalone/event-emitter.js +1 -456
  162. package/dist-standalone/gateway-state.d.ts +1 -1
  163. package/dist-standalone/gateway-state.js +1 -51
  164. package/dist-standalone/gateway-transport.js +1 -116
  165. package/dist-standalone/graceful-degradation.js +1 -396
  166. package/dist-standalone/guardrails.js +1 -216
  167. package/dist-standalone/health-check.d.ts +5 -1
  168. package/dist-standalone/health-check.js +1 -332
  169. package/dist-standalone/http-compat.d.ts +1 -1
  170. package/dist-standalone/http-compat.js +1 -267
  171. package/dist-standalone/http-status-map.js +1 -561
  172. package/dist-standalone/identity.js +1 -619
  173. package/dist-standalone/index.d.ts +15 -4
  174. package/dist-standalone/index.js +1 -78
  175. package/dist-standalone/invitation.js +1 -415
  176. package/dist-standalone/invite.js +1 -324
  177. package/dist-standalone/key-agreement.js +1 -325
  178. package/dist-standalone/lazy-init.d.ts +11 -6
  179. package/dist-standalone/lazy-init.js +1 -295
  180. package/dist-standalone/logger.js +1 -285
  181. package/dist-standalone/loopback-transport.d.ts +87 -0
  182. package/dist-standalone/loopback-transport.js +1 -0
  183. package/dist-standalone/mdns-discovery.js +1 -195
  184. package/dist-standalone/nonce-store.js +1 -76
  185. package/dist-standalone/pairing-manager.js +1 -219
  186. package/dist-standalone/plugin-system.js +1 -257
  187. package/dist-standalone/plugins/logging.js +1 -163
  188. package/dist-standalone/plugins/metrics.d.ts +4 -4
  189. package/dist-standalone/plugins/metrics.js +1 -176
  190. package/dist-standalone/plugins/validation.js +1 -297
  191. package/dist-standalone/policy.js +1 -315
  192. package/dist-standalone/progress-callbacks.js +1 -576
  193. package/dist-standalone/redis-nonce-store.js +1 -72
  194. package/dist-standalone/registry-middleware.js +1 -47
  195. package/dist-standalone/retry-strategies.js +1 -534
  196. package/dist-standalone/retry-transport.js +1 -98
  197. package/dist-standalone/runtime/browser.js +1 -516
  198. package/dist-standalone/runtime/edge.js +1 -511
  199. package/dist-standalone/runtime/react-native.d.ts +1 -1
  200. package/dist-standalone/runtime/react-native.js +1 -383
  201. package/dist-standalone/security-policy.js +1 -239
  202. package/dist-standalone/serialization.js +1 -1031
  203. package/dist-standalone/split-channel.d.ts +1 -1
  204. package/dist-standalone/split-channel.js +1 -219
  205. package/dist-standalone/subscription-proof.js +1 -224
  206. package/dist-standalone/succession.js +1 -142
  207. package/dist-standalone/timeouts.js +1 -398
  208. package/dist-standalone/trace-context.js +1 -414
  209. package/dist-standalone/trace-spans.js +1 -488
  210. package/dist-standalone/transport.d.ts +1 -1
  211. package/dist-standalone/transport.js +1 -59
  212. package/dist-standalone/trust-registry.d.ts +3 -3
  213. package/dist-standalone/trust-registry.js +1 -950
  214. package/dist-standalone/types/error-response.js +1 -52
  215. package/dist-standalone/vault-auth.js +1 -174
  216. package/dist-standalone/vault-store-loader.d.ts +9 -0
  217. package/dist-standalone/vault-store-loader.js +1 -187
  218. package/dist-standalone/verify.js +1 -16
  219. package/dist-standalone/version-info.js +1 -530
  220. package/dist-standalone/xfetch.js +1 -335
  221. package/package.json +1 -1
  222. package/share1.dat +0 -0
@@ -1,225 +1 @@
1
- "use strict";
2
- /**
3
- * Xlock auth challenge module for Agent SDK.
4
- *
5
- * Provides requestAuth(), respondToChallenge(), and onChallenge()
6
- * functions that work with an Agent instance and the XBind gateway.
7
- *
8
- * These functions are also re-exported as thin methods on the Agent class.
9
- */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.requestAuth = requestAuth;
12
- exports.respondToChallenge = respondToChallenge;
13
- exports.onChallenge = onChallenge;
14
- exports.generateRegistrationQR = generateRegistrationQR;
15
- const shared_1 = require("../_deps/shared/index.js");
16
- const envelope_js_1 = require("./envelope.js");
17
- /** Default poll interval for challenge status. */
18
- const DEFAULT_POLL_INTERVAL_MS = 2_000;
19
- /** Default TTL for challenges (5 minutes). */
20
- const DEFAULT_TTL_MS = 5 * 60 * 1000;
21
- /** Max poll iterations (TTL / pollInterval + safety margin). */
22
- const MAX_POLL_ITERATIONS = 200;
23
- /**
24
- * Create an auth challenge and poll until the user responds.
25
- *
26
- * Sends a challenge via the XBind gateway, then polls the status
27
- * endpoint until the challenge is approved, denied, or expires.
28
- *
29
- * @param agent - The Agent requesting authorization.
30
- * @param request - Auth request details (recipient DID, action, metadata).
31
- * @param gateway - Gateway connection options.
32
- * @returns Auth result (approved/denied) or error.
33
- */
34
- async function requestAuth(agent, request, gateway) {
35
- const ttlMs = request.ttlMs ?? DEFAULT_TTL_MS;
36
- const pollIntervalMs = request.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
37
- // Build the challenge payload
38
- const payload = {
39
- recipientDid: request.to,
40
- action: request.action,
41
- metadata: request.metadata ?? {},
42
- ttlMs,
43
- };
44
- // Create a signed envelope wrapping the challenge request
45
- const envelopeResult = await (0, envelope_js_1.createSignedEnvelope)({
46
- senderDid: agent.did,
47
- recipientDid: request.to,
48
- scope: 'xlock:challenge',
49
- plaintext: new TextEncoder().encode(JSON.stringify(payload)),
50
- privateKey: agent.identity.privateKey,
51
- });
52
- if (!envelopeResult.ok) {
53
- return (0, shared_1.err)('INVALID_REQUEST');
54
- }
55
- // POST to gateway
56
- let challengeId;
57
- let expiresAt;
58
- try {
59
- const response = await fetch(`${gateway.gatewayUrl}/gateway/auth/challenge`, {
60
- method: 'POST',
61
- headers: { 'Content-Type': 'application/json' },
62
- body: JSON.stringify(envelopeResult.value),
63
- });
64
- if (response.status === 429)
65
- return (0, shared_1.err)('RATE_LIMITED');
66
- if (!response.ok) {
67
- const body = await response.json().catch(() => null);
68
- const code = body
69
- ?.error?.code;
70
- return (0, shared_1.err)(code ?? 'INVALID_REQUEST');
71
- }
72
- const data = await response.json();
73
- challengeId = data.challengeId;
74
- expiresAt = data.expiresAt;
75
- }
76
- catch {
77
- return (0, shared_1.err)('INVALID_REQUEST');
78
- }
79
- // Poll for status
80
- return pollChallengeStatus(challengeId, expiresAt, pollIntervalMs, gateway);
81
- }
82
- /**
83
- * Respond to an incoming auth challenge (approve or deny).
84
- *
85
- * Sends a signed response envelope to the gateway.
86
- *
87
- * @param agent - The Agent responding to the challenge.
88
- * @param challengeId - The challenge ID to respond to.
89
- * @param approved - Whether the user approved the challenge.
90
- * @param gateway - Gateway connection options.
91
- * @returns Success or error.
92
- */
93
- async function respondToChallenge(agent, challengeId, approved, gateway) {
94
- const payload = {
95
- challengeId,
96
- approved,
97
- timestamp: Date.now(),
98
- };
99
- // Create a signed envelope for the response
100
- const envelopeResult = await (0, envelope_js_1.createSignedEnvelope)({
101
- senderDid: agent.did,
102
- recipientDid: agent.did, // Self-addressed (gateway verifies recipient match)
103
- scope: 'xlock:respond',
104
- plaintext: new TextEncoder().encode(JSON.stringify(payload)),
105
- privateKey: agent.identity.privateKey,
106
- });
107
- if (!envelopeResult.ok) {
108
- return (0, shared_1.err)('INVALID_REQUEST');
109
- }
110
- try {
111
- const response = await fetch(`${gateway.gatewayUrl}/gateway/auth/respond`, {
112
- method: 'POST',
113
- headers: { 'Content-Type': 'application/json' },
114
- body: JSON.stringify({
115
- ...envelopeResult.value,
116
- // Include response fields at top level for the server
117
- challengeId,
118
- approved,
119
- responseEnvelope: envelopeResult.value,
120
- }),
121
- });
122
- if (!response.ok) {
123
- const body = await response.json().catch(() => null);
124
- const code = body
125
- ?.error?.code;
126
- return (0, shared_1.err)(code ?? 'INVALID_REQUEST');
127
- }
128
- return (0, shared_1.ok)(undefined);
129
- }
130
- catch {
131
- return (0, shared_1.err)('INVALID_REQUEST');
132
- }
133
- }
134
- /**
135
- * Register a callback for incoming auth challenges via WebSocket.
136
- *
137
- * The callback fires when an `auth:challenge` message arrives
138
- * over the gateway WebSocket connection.
139
- *
140
- * @param ws - The WebSocket connection to the gateway.
141
- * @param callback - Handler for incoming challenges.
142
- * @returns Cleanup function to unregister the listener.
143
- */
144
- function onChallenge(ws, callback) {
145
- const handler = (event) => {
146
- try {
147
- const msg = JSON.parse(event.data);
148
- if (msg.type === 'auth:challenge' && msg.data) {
149
- callback(msg.data);
150
- }
151
- }
152
- catch {
153
- // Skip non-JSON messages
154
- }
155
- };
156
- ws.addEventListener('message', handler);
157
- return () => ws.removeEventListener('message', handler);
158
- }
159
- /**
160
- * Generate a registration QR code URI for TOTP migration.
161
- *
162
- * Creates a `xlock://register` URI that replaces `otpauth://` for
163
- * asymmetric DID-based registration.
164
- *
165
- * @param options - Registration options.
166
- * @returns The registration URI string.
167
- */
168
- function generateRegistrationQR(options) {
169
- const params = new URLSearchParams({
170
- app: options.appName,
171
- did: options.appDid,
172
- registry: options.registryUrl,
173
- callback: options.callbackUrl,
174
- });
175
- if (options.appIcon)
176
- params.set('icon', options.appIcon);
177
- return `xlock://register?${params.toString()}`;
178
- }
179
- /** Poll the gateway for challenge status until resolved or expired. */
180
- async function pollChallengeStatus(challengeId, expiresAt, pollIntervalMs, gateway) {
181
- for (let i = 0; i < MAX_POLL_ITERATIONS; i++) {
182
- if (Date.now() > expiresAt) {
183
- return (0, shared_1.err)('CHALLENGE_EXPIRED');
184
- }
185
- await sleep(pollIntervalMs);
186
- try {
187
- const response = await fetch(`${gateway.gatewayUrl}/gateway/auth/status/${challengeId}`, {
188
- headers: { Authorization: `Bearer ${gateway.accessToken}` },
189
- });
190
- if (!response.ok) {
191
- if (response.status === 404)
192
- return (0, shared_1.err)('CHALLENGE_NOT_FOUND');
193
- continue; // Retry on transient errors
194
- }
195
- const data = await response.json();
196
- if (data.status === 'approved') {
197
- return (0, shared_1.ok)({
198
- challengeId: data.challengeId,
199
- approved: true,
200
- respondedAt: data.respondedAt,
201
- envelope: data.envelope,
202
- });
203
- }
204
- if (data.status === 'denied') {
205
- return (0, shared_1.ok)({
206
- challengeId: data.challengeId,
207
- approved: false,
208
- respondedAt: data.respondedAt,
209
- });
210
- }
211
- if (data.status === 'expired') {
212
- return (0, shared_1.err)('CHALLENGE_EXPIRED');
213
- }
214
- // Still pending — continue polling
215
- }
216
- catch {
217
- // Network error — continue polling
218
- }
219
- }
220
- return (0, shared_1.err)('CHALLENGE_TIMEOUT');
221
- }
222
- /** Promise-based sleep. */
223
- function sleep(ms) {
224
- return new Promise((resolve) => setTimeout(resolve, ms));
225
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.requestAuth=requestAuth,exports.respondToChallenge=respondToChallenge,exports.onChallenge=onChallenge,exports.generateRegistrationQR=generateRegistrationQR;const shared_1=require("../_deps/shared/index.js"),envelope_js_1=require("./envelope.js"),DEFAULT_POLL_INTERVAL_MS=2e3,DEFAULT_TTL_MS=3e5,MAX_POLL_ITERATIONS=200;async function requestAuth(e,t,r){const a=t.ttlMs??DEFAULT_TTL_MS,n=t.pollIntervalMs??DEFAULT_POLL_INTERVAL_MS,s={recipientDid:t.to,action:t.action,metadata:t.metadata??{},ttlMs:a},o=await(0,envelope_js_1.createSignedEnvelope)({senderDid:e.did,recipientDid:t.to,scope:"xlock:challenge",plaintext:(new TextEncoder).encode(JSON.stringify(s)),privateKey:e.identity.privateKey});if(!o.ok)return(0,shared_1.err)("INVALID_REQUEST");let i,d;try{const e=await fetch(`${r.gatewayUrl}/gateway/auth/challenge`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o.value)});if(429===e.status)return(0,shared_1.err)("RATE_LIMITED");if(!e.ok){const t=await e.json().catch(()=>null),r=t?.error?.code;return(0,shared_1.err)(r??"INVALID_REQUEST")}const t=await e.json();i=t.challengeId,d=t.expiresAt}catch{return(0,shared_1.err)("INVALID_REQUEST")}return pollChallengeStatus(i,d,n,r)}async function respondToChallenge(e,t,r,a){const n={challengeId:t,approved:r,timestamp:Date.now()},s=await(0,envelope_js_1.createSignedEnvelope)({senderDid:e.did,recipientDid:e.did,scope:"xlock:respond",plaintext:(new TextEncoder).encode(JSON.stringify(n)),privateKey:e.identity.privateKey});if(!s.ok)return(0,shared_1.err)("INVALID_REQUEST");try{const e=await fetch(`${a.gatewayUrl}/gateway/auth/respond`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({...s.value,challengeId:t,approved:r,responseEnvelope:s.value})});if(!e.ok){const t=await e.json().catch(()=>null),r=t?.error?.code;return(0,shared_1.err)(r??"INVALID_REQUEST")}return(0,shared_1.ok)(void 0)}catch{return(0,shared_1.err)("INVALID_REQUEST")}}function onChallenge(e,t){const r=e=>{try{const r=JSON.parse(e.data);"auth:challenge"===r.type&&r.data&&t(r.data)}catch{}};return e.addEventListener("message",r),()=>e.removeEventListener("message",r)}function generateRegistrationQR(e){const t=new URLSearchParams({app:e.appName,did:e.appDid,registry:e.registryUrl,callback:e.callbackUrl});return e.appIcon&&t.set("icon",e.appIcon),`xlock://register?${t.toString()}`}async function pollChallengeStatus(e,t,r,a){for(let n=0;n<200;n++){if(Date.now()>t)return(0,shared_1.err)("CHALLENGE_EXPIRED");await sleep(r);try{const t=await fetch(`${a.gatewayUrl}/gateway/auth/status/${e}`,{headers:{Authorization:`Bearer ${a.accessToken}`}});if(!t.ok){if(404===t.status)return(0,shared_1.err)("CHALLENGE_NOT_FOUND");continue}const r=await t.json();if("approved"===r.status)return(0,shared_1.ok)({challengeId:r.challengeId,approved:!0,respondedAt:r.respondedAt,envelope:r.envelope});if("denied"===r.status)return(0,shared_1.ok)({challengeId:r.challengeId,approved:!1,respondedAt:r.respondedAt});if("expired"===r.status)return(0,shared_1.err)("CHALLENGE_EXPIRED")}catch{}}return(0,shared_1.err)("CHALLENGE_TIMEOUT")}function sleep(e){return new Promise(t=>setTimeout(t,e))}
@@ -1,233 +1 @@
1
- "use strict";
2
- /**
3
- * @module auto-accept
4
- * Auto-accept invite on first SDK call for zero-click onboarding.
5
- *
6
- * Enables services to accept invites automatically without explicit
7
- * accept commands. Invite code comes from environment variable.
8
- *
9
- * @example
10
- * ```ts
11
- * // Environment: XBIND_INVITE_CODE=XBD-abc123, XBIND_AUTO_ACCEPT=true
12
- *
13
- * // Auto-accept happens on first Agent method call:
14
- * const agent = Agent.lazy({ name: 'my-service' });
15
- * await agent.send({ to: partnerDid, payload: data, scope: 'test' });
16
- * // ↑ Invite auto-accepted before send()
17
- * ```
18
- */
19
- Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.AutoAcceptErrorCode = void 0;
21
- exports.autoAcceptInvite = autoAcceptInvite;
22
- const shared_1 = require("../_deps/shared/index.js");
23
- const invite_js_1 = require("./invite.js");
24
- const trust_registry_js_1 = require("./trust-registry.js");
25
- const crypto_utils_js_1 = require("./crypto-utils.js");
26
- const identity_js_1 = require("./identity.js");
27
- /**
28
- * Auto-accept error codes.
29
- */
30
- var AutoAcceptErrorCode;
31
- (function (AutoAcceptErrorCode) {
32
- AutoAcceptErrorCode["NO_INVITE_CODE"] = "AUTO_ACCEPT_NO_INVITE_CODE";
33
- AutoAcceptErrorCode["DISABLED"] = "AUTO_ACCEPT_DISABLED";
34
- AutoAcceptErrorCode["INVITE_FAILED"] = "AUTO_ACCEPT_INVITE_FAILED";
35
- AutoAcceptErrorCode["REGISTRY_SETUP_FAILED"] = "AUTO_ACCEPT_REGISTRY_SETUP_FAILED";
36
- })(AutoAcceptErrorCode || (exports.AutoAcceptErrorCode = AutoAcceptErrorCode = {}));
37
- /**
38
- * Auto-accept an invite on first SDK call.
39
- *
40
- * Reads invite code from config or environment variable `XBIND_INVITE_CODE`.
41
- * If `XBIND_AUTO_ACCEPT` is false, returns error with code DISABLED.
42
- *
43
- * When successful:
44
- * 1. Fetches invite details from invite server
45
- * 2. Adds inviter to trust registry
46
- * 3. Auto-detects registry endpoint from invite metadata (if present)
47
- * 4. Marks invite as accepted
48
- *
49
- * This is called internally by `Agent.lazy()` before the first send/receive.
50
- *
51
- * @param config - Auto-accept configuration
52
- * @param acceptorInfo - Acceptor service info (DID, endpoint, publicKey)
53
- * @returns Accept details or error
54
- *
55
- * @example
56
- * ```ts
57
- * // Manual usage (typically called internally by Agent.lazy):
58
- * const result = await autoAcceptInvite(
59
- * { inviteCode: 'XBD-abc123' },
60
- * {
61
- * name: 'my-service',
62
- * did: 'did:key:z6Mk...',
63
- * endpoint: 'https://my-service.com',
64
- * publicKey: '...',
65
- * }
66
- * );
67
- *
68
- * if (result.ok) {
69
- * console.log('Auto-accepted invite from:', result.value.from.name);
70
- * }
71
- * ```
72
- */
73
- async function autoAcceptInvite(config, acceptorInfo) {
74
- // Step 1: Check if auto-accept is enabled
75
- const autoAcceptEnabled = config.enabled ?? getEnvFlag('XBIND_AUTO_ACCEPT', true);
76
- if (!autoAcceptEnabled) {
77
- return (0, shared_1.err)({
78
- code: AutoAcceptErrorCode.DISABLED,
79
- message: 'Auto-accept is disabled',
80
- hint: 'Set XBIND_AUTO_ACCEPT=true or pass { enabled: true } in config',
81
- });
82
- }
83
- // Step 2: Get invite code
84
- const inviteCode = config.inviteCode ?? getEnv('XBIND_INVITE_CODE');
85
- if (!inviteCode) {
86
- return (0, shared_1.err)({
87
- code: AutoAcceptErrorCode.NO_INVITE_CODE,
88
- message: 'No invite code provided',
89
- hint: 'Set XBIND_INVITE_CODE environment variable or pass inviteCode in config',
90
- });
91
- }
92
- // Step 3: Fetch invite details
93
- const inviteService = new invite_js_1.InviteService({
94
- inviteApiUrl: config.inviteApiUrl ?? getEnv('XBIND_INVITE_API_URL') ?? 'https://xbind.to',
95
- });
96
- const inviteUrl = normalizeInviteCode(inviteCode);
97
- const inviteResult = await inviteService.get(inviteUrl);
98
- if (!inviteResult.ok) {
99
- return (0, shared_1.err)({
100
- code: AutoAcceptErrorCode.INVITE_FAILED,
101
- message: `Failed to fetch invite: ${inviteResult.error.message}`,
102
- hint: inviteResult.error.hint,
103
- cause: inviteResult.error,
104
- });
105
- }
106
- const invite = inviteResult.value;
107
- // Step 4: Add inviter to trust registry
108
- const registry = config.registry ?? await autoConfigureRegistry(invite);
109
- try {
110
- // Import public key from base64
111
- const publicKeyBytes = (0, crypto_utils_js_1.fromBase64)(invite.from.publicKey);
112
- const publicKeyResult = await (0, identity_js_1.importPublicKey)(publicKeyBytes);
113
- if (!publicKeyResult.ok) {
114
- return (0, shared_1.err)({
115
- code: AutoAcceptErrorCode.REGISTRY_SETUP_FAILED,
116
- message: 'Invalid inviter public key',
117
- hint: 'The invite may be corrupted',
118
- cause: publicKeyResult.error,
119
- });
120
- }
121
- // Add to registry
122
- const addResult = await registry.register(invite.from.did, publicKeyBytes, invite.from.name, invite.permissions, invite.from.x25519PublicKey ? (0, crypto_utils_js_1.fromBase64)(invite.from.x25519PublicKey) : undefined, invite.from.mlKemPublicKey ? (0, crypto_utils_js_1.fromBase64)(invite.from.mlKemPublicKey) : undefined, undefined, // mlDsaPublicKey (not in invite yet)
123
- false);
124
- if (!addResult.ok) {
125
- // If already registered, that's OK (idempotent)
126
- if (addResult.error !== 'ALREADY_REGISTERED') {
127
- return (0, shared_1.err)({
128
- code: AutoAcceptErrorCode.REGISTRY_SETUP_FAILED,
129
- message: `Failed to add inviter to registry: ${addResult.error}`,
130
- cause: addResult.error,
131
- });
132
- }
133
- }
134
- }
135
- catch (error) {
136
- return (0, shared_1.err)({
137
- code: AutoAcceptErrorCode.REGISTRY_SETUP_FAILED,
138
- message: 'Failed to configure trust registry',
139
- cause: error,
140
- });
141
- }
142
- // Step 5: Accept the invite (marks as accepted on server)
143
- const acceptResult = await inviteService.accept({ inviteUrl, acceptor: acceptorInfo });
144
- if (!acceptResult.ok) {
145
- // Non-fatal: invite acceptance is for tracking/notification only
146
- // The connection is still established locally via registry add
147
- }
148
- return (0, shared_1.ok)({
149
- invite,
150
- from: invite.from,
151
- registryUrl: extractRegistryUrl(invite),
152
- registryAutoconfigured: config.registry === undefined,
153
- });
154
- }
155
- /**
156
- * Auto-configure trust registry from invite metadata.
157
- *
158
- * Attempts to extract registry URL from invite. If found, creates HttpTrustRegistry.
159
- * Otherwise falls back to MemoryTrustRegistry.
160
- *
161
- * @param invite - Invite details
162
- * @returns Trust registry instance
163
- */
164
- async function autoConfigureRegistry(invite) {
165
- const registryUrl = extractRegistryUrl(invite);
166
- if (registryUrl) {
167
- return new trust_registry_js_1.HttpTrustRegistry({ baseUrl: registryUrl });
168
- }
169
- return new trust_registry_js_1.MemoryTrustRegistry();
170
- }
171
- /**
172
- * Extract registry URL from invite metadata.
173
- *
174
- * Checks for registry URL in invite.from.endpoint or custom metadata fields.
175
- *
176
- * @param invite - Invite details
177
- * @returns Registry URL or undefined
178
- */
179
- function extractRegistryUrl(invite) {
180
- // Check if endpoint is a registry URL (heuristic: contains /registry or /trust)
181
- if (invite.from.endpoint.includes('/registry') || invite.from.endpoint.includes('/trust')) {
182
- return invite.from.endpoint;
183
- }
184
- // Future: check invite.metadata.registryUrl when invite system adds it
185
- return undefined;
186
- }
187
- /**
188
- * Normalize invite code to full URL.
189
- *
190
- * If code is already a URL, returns as-is.
191
- * If code is short form (e.g., 'XBD-abc123'), converts to https://xbind.to/invite/{code}.
192
- *
193
- * @param code - Invite code or URL
194
- * @returns Full invite URL
195
- */
196
- function normalizeInviteCode(code) {
197
- if (code.startsWith('http://') || code.startsWith('https://')) {
198
- return code;
199
- }
200
- // Short form: XBD-abc123 or just abc123
201
- const cleanCode = code.replace(/^XBD-/i, '');
202
- return `https://xbind.to/invite/${cleanCode}`;
203
- }
204
- /**
205
- * Get environment variable value.
206
- *
207
- * @param key - Environment variable name
208
- * @param defaultValue - Default value if not set
209
- * @returns Environment variable value or default
210
- */
211
- function getEnv(key, defaultValue) {
212
- // SAFETY: Check for Node.js environment before accessing process
213
- if (typeof process !== 'undefined' && typeof process.env !== 'undefined') {
214
- return process.env[key] ?? defaultValue;
215
- }
216
- return defaultValue;
217
- }
218
- /**
219
- * Get environment variable as boolean flag.
220
- *
221
- * Treats 'true', '1', 'yes' as true. Everything else as false.
222
- *
223
- * @param key - Environment variable name
224
- * @param defaultValue - Default value if not set
225
- * @returns Boolean flag
226
- */
227
- function getEnvFlag(key, defaultValue) {
228
- const value = getEnv(key);
229
- if (value === undefined)
230
- return defaultValue;
231
- const normalized = value.toLowerCase().trim();
232
- return normalized === 'true' || normalized === '1' || normalized === 'yes';
233
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AutoAcceptErrorCode=void 0,exports.autoAcceptInvite=autoAcceptInvite;const shared_1=require("../_deps/shared/index.js"),invite_js_1=require("./invite.js"),trust_registry_js_1=require("./trust-registry.js"),crypto_utils_js_1=require("./crypto-utils.js"),identity_js_1=require("./identity.js");var AutoAcceptErrorCode;async function autoAcceptInvite(e,r){if(!(e.enabled??getEnvFlag("XBIND_AUTO_ACCEPT",!0)))return(0,shared_1.err)({code:AutoAcceptErrorCode.DISABLED,message:"Auto-accept is disabled",hint:"Set XBIND_AUTO_ACCEPT=true or pass { enabled: true } in config"});const t=e.inviteCode??getEnv("XBIND_INVITE_CODE");if(!t)return(0,shared_1.err)({code:AutoAcceptErrorCode.NO_INVITE_CODE,message:"No invite code provided",hint:"Set XBIND_INVITE_CODE environment variable or pass inviteCode in config"});const i=new invite_js_1.InviteService({inviteApiUrl:e.inviteApiUrl??getEnv("XBIND_INVITE_API_URL")??"https://xbind.to"}),o=normalizeInviteCode(t),s=await i.get(o);if(!s.ok)return(0,shared_1.err)({code:AutoAcceptErrorCode.INVITE_FAILED,message:`Failed to fetch invite: ${s.error.message}`,hint:s.error.hint,cause:s.error});const n=s.value,c=e.registry??await autoConfigureRegistry(n);try{const e=(0,crypto_utils_js_1.fromBase64)(n.from.publicKey),r=await(0,identity_js_1.importPublicKey)(e);if(!r.ok)return(0,shared_1.err)({code:AutoAcceptErrorCode.REGISTRY_SETUP_FAILED,message:"Invalid inviter public key",hint:"The invite may be corrupted",cause:r.error});const t=await c.register(n.from.did,e,n.from.name,n.permissions,n.from.x25519PublicKey?(0,crypto_utils_js_1.fromBase64)(n.from.x25519PublicKey):void 0,n.from.mlKemPublicKey?(0,crypto_utils_js_1.fromBase64)(n.from.mlKemPublicKey):void 0,void 0,!1);if(!t.ok&&"ALREADY_REGISTERED"!==t.error)return(0,shared_1.err)({code:AutoAcceptErrorCode.REGISTRY_SETUP_FAILED,message:`Failed to add inviter to registry: ${t.error}`,cause:t.error})}catch(e){return(0,shared_1.err)({code:AutoAcceptErrorCode.REGISTRY_SETUP_FAILED,message:"Failed to configure trust registry",cause:e})}return(await i.accept({inviteUrl:o,acceptor:r})).ok,(0,shared_1.ok)({invite:n,from:n.from,registryUrl:extractRegistryUrl(n),registryAutoconfigured:void 0===e.registry})}async function autoConfigureRegistry(e){const r=extractRegistryUrl(e);return r?new trust_registry_js_1.HttpTrustRegistry({baseUrl:r}):new trust_registry_js_1.MemoryTrustRegistry}function extractRegistryUrl(e){if(e.from.endpoint.includes("/registry")||e.from.endpoint.includes("/trust"))return e.from.endpoint}function normalizeInviteCode(e){if(e.startsWith("http://")||e.startsWith("https://"))return e;return`https://xbind.to/invite/${e.replace(/^XBD-/i,"")}`}function getEnv(e,r){return"undefined"!=typeof process&&void 0!==process.env?process.env[e]??r:r}function getEnvFlag(e,r){const t=getEnv(e);if(void 0===t)return r;const i=t.toLowerCase().trim();return"true"===i||"1"===i||"yes"===i}!function(e){e.NO_INVITE_CODE="AUTO_ACCEPT_NO_INVITE_CODE",e.DISABLED="AUTO_ACCEPT_DISABLED",e.INVITE_FAILED="AUTO_ACCEPT_INVITE_FAILED",e.REGISTRY_SETUP_FAILED="AUTO_ACCEPT_REGISTRY_SETUP_FAILED"}(AutoAcceptErrorCode||(exports.AutoAcceptErrorCode=AutoAcceptErrorCode={}));
@@ -1,207 +1 @@
1
- "use strict";
2
- /**
3
- * XorIDA Backup Configuration for Key Splitting
4
- *
5
- * Provides default backup configuration (k=2, n=3) and utilities for
6
- * splitting cryptographic keys across multiple shares using information-
7
- * theoretic threshold secret sharing.
8
- *
9
- * @module backup-config
10
- */
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.DEFAULT_BACKUP_CONFIG = void 0;
13
- exports.validateBackupConfig = validateBackupConfig;
14
- exports.splitKeyWithBackup = splitKeyWithBackup;
15
- exports.reconstructKeyFromBackup = reconstructKeyFromBackup;
16
- const shared_1 = require("../_deps/shared/index.js");
17
- const crypto_utils_js_1 = require("./crypto-utils.js");
18
- /* ── Constants ── */
19
- /**
20
- * Default backup configuration: 2-of-3 threshold sharing.
21
- *
22
- * - 3 shares generated
23
- * - Any 2 shares can reconstruct the key
24
- * - Lose 1 share and still recover (fault tolerance)
25
- * - Information-theoretic security (each share reveals zero information)
26
- */
27
- exports.DEFAULT_BACKUP_CONFIG = {
28
- threshold: 2,
29
- totalShares: 3,
30
- };
31
- /* ── Validation ── */
32
- /**
33
- * Validate backup configuration parameters.
34
- *
35
- * Rules:
36
- * - threshold must be >= 2 (single share = no threshold)
37
- * - totalShares must be >= threshold
38
- * - totalShares must be <= 255 (XorIDA limit)
39
- *
40
- * @param config - Backup configuration to validate.
41
- * @returns Ok if valid, error otherwise.
42
- */
43
- function validateBackupConfig(config) {
44
- if (config.threshold < 2) {
45
- return (0, shared_1.err)('INVALID_CONFIG');
46
- }
47
- if (config.totalShares < config.threshold) {
48
- return (0, shared_1.err)('INVALID_CONFIG');
49
- }
50
- if (config.totalShares > 255) {
51
- return (0, shared_1.err)('INVALID_CONFIG');
52
- }
53
- return (0, shared_1.ok)(undefined);
54
- }
55
- /* ── Key Splitting ── */
56
- /**
57
- * Split a cryptographic key into backup shares using XorIDA.
58
- *
59
- * The key is padded, split via information-theoretic threshold sharing,
60
- * and returned as BackupShare objects with HMAC integrity protection.
61
- *
62
- * Any `threshold` shares can reconstruct the original key. Each share
63
- * reveals zero information about the key (information-theoretic security).
64
- *
65
- * @param key - The key to split (32 or 64 bytes typical).
66
- * @param config - Backup configuration (defaults to 2-of-3).
67
- * @returns Array of backup shares or error.
68
- *
69
- * @example
70
- * ```typescript
71
- * import { splitKeyWithBackup, DEFAULT_BACKUP_CONFIG } from '@private.me/xbind';
72
- *
73
- * const key = crypto.getRandomValues(new Uint8Array(32));
74
- *
75
- * // Use defaults (2-of-3)
76
- * const shares = await splitKeyWithBackup(key);
77
- *
78
- * // Custom config (3-of-5)
79
- * const shares2 = await splitKeyWithBackup(key, {
80
- * threshold: 3,
81
- * totalShares: 5
82
- * });
83
- *
84
- * if (shares.ok) {
85
- * // Store shares in separate locations
86
- * shares.value.forEach((share, i) => {
87
- * storeShare(`backup-${i}.json`, JSON.stringify(share));
88
- * });
89
- * }
90
- * ```
91
- */
92
- async function splitKeyWithBackup(key, config = exports.DEFAULT_BACKUP_CONFIG) {
93
- const validation = validateBackupConfig(config);
94
- if (!validation.ok)
95
- return validation;
96
- if (key.length === 0) {
97
- return (0, shared_1.err)('INVALID_KEY_LENGTH');
98
- }
99
- const n = config.totalShares;
100
- const k = config.threshold;
101
- const p = (0, crypto_utils_js_1.nextOddPrime)(n);
102
- const blockSize = p - 1;
103
- // Pad to block size
104
- const padded = (0, crypto_utils_js_1.pkcs7Pad)(key, blockSize);
105
- // Generate HMAC for integrity verification
106
- const { key: hmacKey, signature: hmacSig } = await (0, crypto_utils_js_1.generateHMAC)(padded);
107
- const hmacKeyB64 = (0, crypto_utils_js_1.toBase64)(hmacKey);
108
- const hmacSigB64 = (0, crypto_utils_js_1.toBase64)(hmacSig);
109
- // Split via XorIDA
110
- let shareArrays;
111
- try {
112
- shareArrays = (0, crypto_utils_js_1.splitXorIDA)(padded, n, k);
113
- }
114
- catch {
115
- return (0, shared_1.err)('SPLIT_FAILED');
116
- }
117
- // Package as BackupShare objects
118
- const shares = shareArrays.map((data, index) => ({
119
- index,
120
- data: (0, crypto_utils_js_1.toBase64)(data),
121
- total: n,
122
- threshold: k,
123
- hmacKey: hmacKeyB64,
124
- hmacSig: hmacSigB64,
125
- }));
126
- return (0, shared_1.ok)(shares);
127
- }
128
- /* ── Key Reconstruction ── */
129
- /**
130
- * Reconstruct a cryptographic key from backup shares.
131
- *
132
- * Requires at least `threshold` shares. Verifies HMAC before returning
133
- * the reconstructed key to prevent tampering.
134
- *
135
- * @param shares - Backup shares (must be >= threshold).
136
- * @returns Reconstructed key or error.
137
- *
138
- * @example
139
- * ```typescript
140
- * import { reconstructKeyFromBackup } from '@private.me/xbind';
141
- *
142
- * // Load shares from storage
143
- * const share0 = JSON.parse(loadShare('backup-0.json'));
144
- * const share1 = JSON.parse(loadShare('backup-1.json'));
145
- *
146
- * // Reconstruct from any 2 shares (threshold=2)
147
- * const key = await reconstructKeyFromBackup([share0, share1]);
148
- *
149
- * if (key.ok) {
150
- * // Use reconstructed key
151
- * const agent = await Agent.fromSeed(key.value, opts);
152
- * } else {
153
- * console.error('Reconstruction failed:', key.error);
154
- * }
155
- * ```
156
- */
157
- async function reconstructKeyFromBackup(shares) {
158
- if (shares.length === 0) {
159
- return (0, shared_1.err)('INSUFFICIENT_SHARES');
160
- }
161
- const threshold = shares[0].threshold;
162
- const total = shares[0].total;
163
- if (shares.length < threshold) {
164
- return (0, shared_1.err)('INSUFFICIENT_SHARES');
165
- }
166
- // Use first `threshold` shares
167
- const usedShares = shares.slice(0, threshold);
168
- // Decode share data
169
- let shareData;
170
- try {
171
- shareData = usedShares.map((s) => (0, crypto_utils_js_1.fromBase64)(s.data));
172
- }
173
- catch {
174
- return (0, shared_1.err)('INVALID_SHARE_DATA');
175
- }
176
- const indices = usedShares.map((s) => s.index);
177
- // Reconstruct padded key
178
- let padded;
179
- try {
180
- padded = (0, crypto_utils_js_1.reconstructXorIDA)(shareData, indices, total, threshold);
181
- }
182
- catch {
183
- return (0, shared_1.err)('RECONSTRUCT_FAILED');
184
- }
185
- // Verify HMAC
186
- let hmacKey;
187
- let hmacSig;
188
- try {
189
- hmacKey = (0, crypto_utils_js_1.fromBase64)(usedShares[0].hmacKey);
190
- hmacSig = (0, crypto_utils_js_1.fromBase64)(usedShares[0].hmacSig);
191
- }
192
- catch {
193
- return (0, shared_1.err)('INVALID_SHARE_DATA');
194
- }
195
- const hmacValid = await (0, crypto_utils_js_1.verifyHMAC)(hmacKey, padded, hmacSig);
196
- if (!hmacValid) {
197
- return (0, shared_1.err)('HMAC_VERIFICATION_FAILED');
198
- }
199
- // Unpad to recover original key
200
- const p = (0, crypto_utils_js_1.nextOddPrime)(total);
201
- const blockSize = p - 1;
202
- const unpadResult = (0, crypto_utils_js_1.pkcs7Unpad)(padded, blockSize);
203
- if (!unpadResult.ok) {
204
- return (0, shared_1.err)('RECONSTRUCT_FAILED');
205
- }
206
- return (0, shared_1.ok)(unpadResult.value);
207
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.DEFAULT_BACKUP_CONFIG=void 0,exports.validateBackupConfig=validateBackupConfig,exports.splitKeyWithBackup=splitKeyWithBackup,exports.reconstructKeyFromBackup=reconstructKeyFromBackup;const shared_1=require("../_deps/shared/index.js"),crypto_utils_js_1=require("./crypto-utils.js");function validateBackupConfig(t){return t.threshold<2||t.totalShares<t.threshold||t.totalShares>255?(0,shared_1.err)("INVALID_CONFIG"):(0,shared_1.ok)(void 0)}async function splitKeyWithBackup(t,r=exports.DEFAULT_BACKUP_CONFIG){const e=validateBackupConfig(r);if(!e.ok)return e;if(0===t.length)return(0,shared_1.err)("INVALID_KEY_LENGTH");const s=r.totalShares,_=r.threshold,a=(0,crypto_utils_js_1.nextOddPrime)(s)-1,o=(0,crypto_utils_js_1.pkcs7Pad)(t,a),{key:c,signature:i}=await(0,crypto_utils_js_1.generateHMAC)(o),u=(0,crypto_utils_js_1.toBase64)(c),n=(0,crypto_utils_js_1.toBase64)(i);let l;try{l=(0,crypto_utils_js_1.splitXorIDA)(o,s,_)}catch{return(0,shared_1.err)("SPLIT_FAILED")}const h=l.map((t,r)=>({index:r,data:(0,crypto_utils_js_1.toBase64)(t),total:s,threshold:_,hmacKey:u,hmacSig:n}));return(0,shared_1.ok)(h)}async function reconstructKeyFromBackup(t){if(0===t.length)return(0,shared_1.err)("INSUFFICIENT_SHARES");const r=t[0].threshold,e=t[0].total;if(t.length<r)return(0,shared_1.err)("INSUFFICIENT_SHARES");const s=t.slice(0,r);let _;try{_=s.map(t=>(0,crypto_utils_js_1.fromBase64)(t.data))}catch{return(0,shared_1.err)("INVALID_SHARE_DATA")}const a=s.map(t=>t.index);let o,c,i;try{o=(0,crypto_utils_js_1.reconstructXorIDA)(_,a,e,r)}catch{return(0,shared_1.err)("RECONSTRUCT_FAILED")}try{c=(0,crypto_utils_js_1.fromBase64)(s[0].hmacKey),i=(0,crypto_utils_js_1.fromBase64)(s[0].hmacSig)}catch{return(0,shared_1.err)("INVALID_SHARE_DATA")}if(!await(0,crypto_utils_js_1.verifyHMAC)(c,o,i))return(0,shared_1.err)("HMAC_VERIFICATION_FAILED");const u=(0,crypto_utils_js_1.nextOddPrime)(e)-1,n=(0,crypto_utils_js_1.pkcs7Unpad)(o,u);return n.ok?(0,shared_1.ok)(n.value):(0,shared_1.err)("RECONSTRUCT_FAILED")}exports.DEFAULT_BACKUP_CONFIG={threshold:2,totalShares:3};