@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,490 +1 @@
1
- "use strict";
2
- /**
3
- * @module cancellation
4
- * Cancellation token support for xBind operations
5
- *
6
- * Provides AbortController/AbortSignal integration for enhanced operation control:
7
- * - Cancellable async operations (fetch, agent.call, transport)
8
- * - Timeout management with automatic cleanup
9
- * - Composite signals (multiple cancellation sources)
10
- * - Resource cleanup on cancellation
11
- *
12
- * Architecture:
13
- * - Uses standard AbortController/AbortSignal (Web API + Node.js)
14
- * - Timeout wrapper creates time-limited signals
15
- * - Composite signals combine multiple cancellation sources
16
- * - Cleanup callbacks ensure proper resource disposal
17
- *
18
- * @example
19
- * ```typescript
20
- * // Timeout with cancellation
21
- * const signal = createTimeoutSignal(5000);
22
- * await xfetch('https://api.example.com', { signal });
23
- *
24
- * // Manual cancellation
25
- * const controller = new AbortController();
26
- * setTimeout(() => controller.abort(), 1000);
27
- * await agent.call('tool:action', params, { signal: controller.signal });
28
- *
29
- * // Composite signals
30
- * const timeout = createTimeoutSignal(10000);
31
- * const manual = new AbortController();
32
- * const combined = combineSignals([timeout.signal, manual.signal]);
33
- * await operation({ signal: combined });
34
- * ```
35
- */
36
- Object.defineProperty(exports, "__esModule", { value: true });
37
- exports.CancellationError = void 0;
38
- exports.createTimeoutSignal = createTimeoutSignal;
39
- exports.combineSignals = combineSignals;
40
- exports.onCancellation = onCancellation;
41
- exports.throwIfAborted = throwIfAborted;
42
- exports.withCancellation = withCancellation;
43
- exports.delay = delay;
44
- exports.withRetry = withRetry;
45
- exports.createCancellationController = createCancellationController;
46
- exports.isCancellationError = isCancellationError;
47
- const shared_1 = require("../_deps/shared/index.js");
48
- /**
49
- * Cancellation error thrown when operation is aborted
50
- */
51
- class CancellationError extends Error {
52
- reason;
53
- context;
54
- constructor(message, reason, context) {
55
- super(message);
56
- this.reason = reason;
57
- this.context = context;
58
- this.name = 'CancellationError';
59
- }
60
- }
61
- exports.CancellationError = CancellationError;
62
- /**
63
- * Create an AbortSignal that triggers after a timeout
64
- *
65
- * Automatically aborts the signal after the specified duration.
66
- * Useful for setting time limits on async operations.
67
- *
68
- * @param timeout - Timeout in milliseconds
69
- * @param options - Optional reason and context
70
- * @returns TimeoutController with signal and clear function
71
- *
72
- * @example
73
- * ```typescript
74
- * const timeout = createTimeoutSignal(5000);
75
- * try {
76
- * await fetch('https://api.example.com', { signal: timeout.signal });
77
- * } catch (error) {
78
- * if (error.name === 'AbortError') {
79
- * console.log('Request timed out after 5s');
80
- * }
81
- * } finally {
82
- * timeout.clear(); // Clean up timer
83
- * }
84
- * ```
85
- */
86
- function createTimeoutSignal(timeout, options) {
87
- const controller = new AbortController();
88
- const startTime = Date.now();
89
- const timeoutId = setTimeout(() => {
90
- const reason = options?.reason || `Operation timed out after ${timeout}ms`;
91
- controller.abort(new CancellationError(reason, 'timeout', options?.context));
92
- }, timeout);
93
- return {
94
- signal: controller.signal,
95
- clear: () => {
96
- clearTimeout(timeoutId);
97
- },
98
- remaining: () => {
99
- const elapsed = Date.now() - startTime;
100
- return Math.max(0, timeout - elapsed);
101
- },
102
- };
103
- }
104
- /**
105
- * Combine multiple AbortSignals into a single signal
106
- *
107
- * The combined signal aborts when ANY of the source signals abort.
108
- * Useful for operations with multiple cancellation sources (timeout, user action, etc.).
109
- *
110
- * @param signals - Array of signals to combine
111
- * @returns Combined AbortSignal
112
- *
113
- * @example
114
- * ```typescript
115
- * const timeout = createTimeoutSignal(10000);
116
- * const userCancel = new AbortController();
117
- * const combined = combineSignals([timeout.signal, userCancel.signal]);
118
- *
119
- * // Either timeout OR user cancellation will abort
120
- * await fetch('https://api.example.com', { signal: combined });
121
- * ```
122
- */
123
- function combineSignals(signals) {
124
- // Filter out already-aborted signals and undefined
125
- const activeSignals = signals.filter(s => s && !s.aborted);
126
- // If all signals are already aborted, return an aborted signal
127
- if (activeSignals.length === 0) {
128
- const alreadyAborted = signals.find(s => s?.aborted);
129
- if (alreadyAborted) {
130
- // Return already-aborted signal
131
- return alreadyAborted;
132
- }
133
- // No signals provided - return never-aborts signal
134
- return new AbortController().signal;
135
- }
136
- // If only one active signal, return it directly
137
- if (activeSignals.length === 1) {
138
- return activeSignals[0];
139
- }
140
- // Use AbortSignal.any() if available (Node 20+, modern browsers)
141
- if (typeof AbortSignal.any === 'function') {
142
- return AbortSignal.any(activeSignals);
143
- }
144
- // Fallback: manually combine signals
145
- const controller = new AbortController();
146
- const abortListeners = [];
147
- for (const signal of activeSignals) {
148
- const listener = () => {
149
- controller.abort(signal.reason);
150
- // Remove all listeners after first abort
151
- abortListeners.forEach((remove) => remove());
152
- };
153
- signal.addEventListener('abort', listener, { once: true });
154
- // Store cleanup function
155
- abortListeners.push(() => {
156
- signal.removeEventListener('abort', listener);
157
- });
158
- }
159
- return controller.signal;
160
- }
161
- /**
162
- * Register cleanup callback to run when signal is aborted
163
- *
164
- * Ensures resources are properly disposed when operation is cancelled.
165
- * Cleanup runs immediately if signal is already aborted.
166
- *
167
- * @param signal - AbortSignal to monitor
168
- * @param cleanup - Cleanup callback
169
- *
170
- * @example
171
- * ```typescript
172
- * const controller = new AbortController();
173
- * const connection = await openConnection();
174
- *
175
- * onCancellation(controller.signal, async () => {
176
- * console.log('Cleaning up connection...');
177
- * await connection.close();
178
- * });
179
- *
180
- * // Later...
181
- * controller.abort(); // Cleanup runs automatically
182
- * ```
183
- */
184
- function onCancellation(signal, cleanup) {
185
- // If already aborted, run cleanup immediately
186
- if (signal.aborted) {
187
- void Promise.resolve().then(() => cleanup()).catch(() => {
188
- // Cleanup errors are handled silently to avoid unhandled rejections
189
- });
190
- return;
191
- }
192
- // Register cleanup to run on abort
193
- signal.addEventListener('abort', () => {
194
- // Run cleanup and catch errors silently to avoid unhandled rejections
195
- void Promise.resolve().then(() => cleanup()).catch(() => {
196
- // Cleanup errors are expected and handled silently
197
- // (test can spy on this if needed, but we don't log by default)
198
- });
199
- }, { once: true });
200
- }
201
- /**
202
- * Check if signal is aborted and throw CancellationError if so
203
- *
204
- * Useful for checking cancellation at specific points in long-running operations.
205
- *
206
- * @param signal - AbortSignal to check
207
- * @param context - Optional context for error
208
- * @throws CancellationError if signal is aborted
209
- *
210
- * @example
211
- * ```typescript
212
- * async function processLargeDataset(data: unknown[], signal?: AbortSignal) {
213
- * for (const item of data) {
214
- * throwIfAborted(signal, { item: item.id });
215
- * await processItem(item);
216
- * }
217
- * }
218
- * ```
219
- */
220
- function throwIfAborted(signal, context) {
221
- if (signal?.aborted) {
222
- const reason = signal.reason instanceof Error
223
- ? signal.reason.message
224
- : String(signal.reason || 'Operation was cancelled');
225
- throw new CancellationError(reason, 'aborted', context);
226
- }
227
- }
228
- /**
229
- * Wrap a promise with cancellation support
230
- *
231
- * If signal aborts before promise resolves, returns error result.
232
- * Otherwise returns the promise's result.
233
- *
234
- * @param promise - Promise to wrap
235
- * @param signal - AbortSignal for cancellation
236
- * @returns Result wrapper around promise
237
- *
238
- * @example
239
- * ```typescript
240
- * const timeout = createTimeoutSignal(5000);
241
- * const result = await withCancellation(
242
- * fetch('https://api.example.com'),
243
- * timeout.signal
244
- * );
245
- *
246
- * if (!result.ok) {
247
- * console.error('Request cancelled:', result.error.message);
248
- * }
249
- * ```
250
- */
251
- async function withCancellation(promise, signal) {
252
- if (!signal) {
253
- // No signal - just await promise
254
- try {
255
- const value = await promise;
256
- return (0, shared_1.ok)(value);
257
- }
258
- catch (error) {
259
- return (0, shared_1.err)(new CancellationError(error instanceof Error ? error.message : String(error), 'promise_rejected'));
260
- }
261
- }
262
- // If already aborted, return immediately
263
- if (signal.aborted) {
264
- const reason = signal.reason instanceof Error
265
- ? signal.reason.message
266
- : String(signal.reason || 'Operation was cancelled');
267
- return (0, shared_1.err)(new CancellationError(reason, 'aborted'));
268
- }
269
- // Race promise against abort signal
270
- return new Promise((resolve) => {
271
- // Handle abort
272
- const onAbort = () => {
273
- const reason = signal.reason instanceof Error
274
- ? signal.reason.message
275
- : String(signal.reason || 'Operation was cancelled');
276
- resolve((0, shared_1.err)(new CancellationError(reason, 'aborted')));
277
- };
278
- signal.addEventListener('abort', onAbort, { once: true });
279
- // Handle promise resolution
280
- promise
281
- .then((value) => {
282
- signal.removeEventListener('abort', onAbort);
283
- resolve((0, shared_1.ok)(value));
284
- })
285
- .catch((error) => {
286
- signal.removeEventListener('abort', onAbort);
287
- resolve((0, shared_1.err)(new CancellationError(error instanceof Error ? error.message : String(error), 'promise_rejected')));
288
- });
289
- });
290
- }
291
- /**
292
- * Create a cancellable delay
293
- *
294
- * Returns a promise that resolves after the specified duration,
295
- * but can be cancelled early via signal.
296
- *
297
- * @param ms - Delay in milliseconds
298
- * @param signal - Optional AbortSignal for cancellation
299
- * @returns Promise that resolves after delay or rejects on cancellation
300
- *
301
- * @example
302
- * ```typescript
303
- * const controller = new AbortController();
304
- *
305
- * // Start 10s delay
306
- * const delayPromise = delay(10000, controller.signal);
307
- *
308
- * // Cancel after 2s
309
- * setTimeout(() => controller.abort(), 2000);
310
- *
311
- * try {
312
- * await delayPromise; // Throws CancellationError after 2s
313
- * } catch (error) {
314
- * console.log('Delay cancelled');
315
- * }
316
- * ```
317
- */
318
- function delay(ms, signal) {
319
- return new Promise((resolve, reject) => {
320
- // Check if already aborted
321
- if (signal?.aborted) {
322
- const reason = signal.reason instanceof Error
323
- ? signal.reason.message
324
- : String(signal.reason || 'Delay cancelled');
325
- reject(new CancellationError(reason, 'aborted'));
326
- return;
327
- }
328
- const timeoutId = setTimeout(() => {
329
- if (signal) {
330
- signal.removeEventListener('abort', onAbort);
331
- }
332
- resolve();
333
- }, ms);
334
- const onAbort = () => {
335
- clearTimeout(timeoutId);
336
- const reason = signal.reason instanceof Error
337
- ? signal.reason.message
338
- : String(signal.reason || 'Delay cancelled');
339
- reject(new CancellationError(reason, 'aborted'));
340
- };
341
- if (signal) {
342
- signal.addEventListener('abort', onAbort, { once: true });
343
- }
344
- });
345
- }
346
- /**
347
- * Retry an operation with cancellation support
348
- *
349
- * Attempts operation multiple times with exponential backoff.
350
- * Respects cancellation signal between retry attempts.
351
- *
352
- * @param operation - Async operation to retry
353
- * @param options - Retry configuration
354
- * @returns Result of operation
355
- *
356
- * @example
357
- * ```typescript
358
- * const timeout = createTimeoutSignal(30000);
359
- *
360
- * const result = await withRetry(
361
- * async () => {
362
- * const res = await fetch('https://api.example.com');
363
- * if (!res.ok) throw new Error('Request failed');
364
- * return res.json();
365
- * },
366
- * {
367
- * maxAttempts: 5,
368
- * initialDelay: 1000,
369
- * multiplier: 2,
370
- * signal: timeout.signal,
371
- * }
372
- * );
373
- * ```
374
- */
375
- async function withRetry(operation, options) {
376
- const maxAttempts = options?.maxAttempts ?? 3;
377
- const initialDelay = options?.initialDelay ?? 1000;
378
- const multiplier = options?.multiplier ?? 2;
379
- const signal = options?.signal;
380
- const shouldRetry = options?.shouldRetry ?? (() => true);
381
- let lastError;
382
- let delayMs = initialDelay;
383
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
384
- // Check cancellation before attempt
385
- if (signal?.aborted) {
386
- const reason = signal.reason instanceof Error
387
- ? signal.reason.message
388
- : String(signal.reason || 'Operation was cancelled');
389
- return (0, shared_1.err)(new CancellationError(reason, 'aborted', { attempt }));
390
- }
391
- try {
392
- const value = await operation();
393
- return (0, shared_1.ok)(value);
394
- }
395
- catch (error) {
396
- lastError = error instanceof Error ? error : new Error(String(error));
397
- // On last attempt or if shouldRetry returns false, don't retry
398
- if (attempt >= maxAttempts || !shouldRetry(error, attempt)) {
399
- // No more attempts or predicate said no
400
- break;
401
- }
402
- // Wait before retry (with cancellation support)
403
- try {
404
- await delay(delayMs, signal);
405
- delayMs *= multiplier;
406
- }
407
- catch (cancelError) {
408
- // Cancelled during delay
409
- if (cancelError instanceof CancellationError) {
410
- return (0, shared_1.err)(cancelError);
411
- }
412
- throw cancelError;
413
- }
414
- }
415
- }
416
- // All attempts failed
417
- return (0, shared_1.err)(lastError || new Error('Operation failed after retries'));
418
- }
419
- /**
420
- * Create a manual cancellation controller with helper methods
421
- *
422
- * Extends AbortController with additional utilities for common patterns.
423
- *
424
- * @returns Enhanced controller with helper methods
425
- *
426
- * @example
427
- * ```typescript
428
- * const controller = createCancellationController();
429
- *
430
- * // Start operation
431
- * const promise = longRunningOperation({ signal: controller.signal });
432
- *
433
- * // Cancel with custom reason
434
- * controller.cancel('User requested cancellation');
435
- *
436
- * // Check if cancelled
437
- * if (controller.isCancelled) {
438
- * console.log('Operation was cancelled');
439
- * }
440
- * ```
441
- */
442
- function createCancellationController() {
443
- const controller = new AbortController();
444
- let cancelledReason;
445
- return {
446
- /** Abort signal for cancellation */
447
- signal: controller.signal,
448
- /** True if operation has been cancelled */
449
- get isCancelled() {
450
- return controller.signal.aborted;
451
- },
452
- /** Reason for cancellation (if any) */
453
- get reason() {
454
- return cancelledReason;
455
- },
456
- /** Cancel the operation with optional reason */
457
- cancel(reason) {
458
- cancelledReason = reason || 'Operation cancelled';
459
- controller.abort(new CancellationError(cancelledReason, 'manual'));
460
- },
461
- /** Throw if cancelled */
462
- throwIfCancelled(context) {
463
- throwIfAborted(controller.signal, context);
464
- },
465
- };
466
- }
467
- /**
468
- * Check if an error is a cancellation error
469
- *
470
- * @param error - Error to check
471
- * @returns True if error is from cancellation
472
- *
473
- * @example
474
- * ```typescript
475
- * try {
476
- * await operation({ signal });
477
- * } catch (error) {
478
- * if (isCancellationError(error)) {
479
- * console.log('Operation was cancelled');
480
- * } else {
481
- * console.error('Operation failed:', error);
482
- * }
483
- * }
484
- * ```
485
- */
486
- function isCancellationError(error) {
487
- return error instanceof CancellationError ||
488
- (error instanceof Error && error.name === 'AbortError') ||
489
- (error instanceof Error && error.name === 'CancellationError');
490
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.CancellationError=void 0,exports.createTimeoutSignal=createTimeoutSignal,exports.combineSignals=combineSignals,exports.onCancellation=onCancellation,exports.throwIfAborted=throwIfAborted,exports.withCancellation=withCancellation,exports.delay=delay,exports.withRetry=withRetry,exports.createCancellationController=createCancellationController,exports.isCancellationError=isCancellationError;const shared_1=require("../_deps/shared/index.js");class CancellationError extends Error{reason;context;constructor(e,r,n){super(e),this.reason=r,this.context=n,this.name="CancellationError"}}function createTimeoutSignal(e,r){const n=new AbortController,t=Date.now(),o=setTimeout(()=>{const t=r?.reason||`Operation timed out after ${e}ms`;n.abort(new CancellationError(t,"timeout",r?.context))},e);return{signal:n.signal,clear:()=>{clearTimeout(o)},remaining:()=>{const r=Date.now()-t;return Math.max(0,e-r)}}}function combineSignals(e){const r=e.filter(e=>e&&!e.aborted);if(0===r.length){const r=e.find(e=>e?.aborted);return r||(new AbortController).signal}if(1===r.length)return r[0];if("function"==typeof AbortSignal.any)return AbortSignal.any(r);const n=new AbortController,t=[];for(const e of r){const r=()=>{n.abort(e.reason),t.forEach(e=>e())};e.addEventListener("abort",r,{once:!0}),t.push(()=>{e.removeEventListener("abort",r)})}return n.signal}function onCancellation(e,r){e.aborted?Promise.resolve().then(()=>r()).catch(()=>{}):e.addEventListener("abort",()=>{Promise.resolve().then(()=>r()).catch(()=>{})},{once:!0})}function throwIfAborted(e,r){if(e?.aborted){const n=e.reason instanceof Error?e.reason.message:String(e.reason||"Operation was cancelled");throw new CancellationError(n,"aborted",r)}}async function withCancellation(e,r){if(!r)try{const r=await e;return(0,shared_1.ok)(r)}catch(e){return(0,shared_1.err)(new CancellationError(e instanceof Error?e.message:String(e),"promise_rejected"))}if(r.aborted){const e=r.reason instanceof Error?r.reason.message:String(r.reason||"Operation was cancelled");return(0,shared_1.err)(new CancellationError(e,"aborted"))}return new Promise(n=>{const t=()=>{const e=r.reason instanceof Error?r.reason.message:String(r.reason||"Operation was cancelled");n((0,shared_1.err)(new CancellationError(e,"aborted")))};r.addEventListener("abort",t,{once:!0}),e.then(e=>{r.removeEventListener("abort",t),n((0,shared_1.ok)(e))}).catch(e=>{r.removeEventListener("abort",t),n((0,shared_1.err)(new CancellationError(e instanceof Error?e.message:String(e),"promise_rejected")))})})}function delay(e,r){return new Promise((n,t)=>{if(r?.aborted){const e=r.reason instanceof Error?r.reason.message:String(r.reason||"Delay cancelled");return void t(new CancellationError(e,"aborted"))}const o=setTimeout(()=>{r&&r.removeEventListener("abort",a),n()},e),a=()=>{clearTimeout(o);const e=r.reason instanceof Error?r.reason.message:String(r.reason||"Delay cancelled");t(new CancellationError(e,"aborted"))};r&&r.addEventListener("abort",a,{once:!0})})}async function withRetry(e,r){const n=r?.maxAttempts??3,t=r?.initialDelay??1e3,o=r?.multiplier??2,a=r?.signal,i=r?.shouldRetry??(()=>!0);let s,l=t;for(let r=1;r<=n;r++){if(a?.aborted){const e=a.reason instanceof Error?a.reason.message:String(a.reason||"Operation was cancelled");return(0,shared_1.err)(new CancellationError(e,"aborted",{attempt:r}))}try{const r=await e();return(0,shared_1.ok)(r)}catch(e){if(s=e instanceof Error?e:new Error(String(e)),r>=n||!i(e,r))break;try{await delay(l,a),l*=o}catch(e){if(e instanceof CancellationError)return(0,shared_1.err)(e);throw e}}}return(0,shared_1.err)(s||new Error("Operation failed after retries"))}function createCancellationController(){const e=new AbortController;let r;return{signal:e.signal,get isCancelled(){return e.signal.aborted},get reason(){return r},cancel(n){r=n||"Operation cancelled",e.abort(new CancellationError(r,"manual"))},throwIfCancelled(r){throwIfAborted(e.signal,r)}}}function isCancellationError(e){return e instanceof CancellationError||e instanceof Error&&"AbortError"===e.name||e instanceof Error&&"CancellationError"===e.name}exports.CancellationError=CancellationError;
@@ -1,193 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createCheckpoint = createCheckpoint;
4
- exports.verifyCheckpoint = verifyCheckpoint;
5
- exports.isCacheStale = isCacheStale;
6
- exports.encodeCheckpoint = encodeCheckpoint;
7
- exports.decodeCheckpoint = decodeCheckpoint;
8
- const shared_1 = require("../_deps/shared/index.js");
9
- const identity_js_1 = require("./identity.js");
10
- /* ── Checkpoint Creation (Gateway-side) ── */
11
- /**
12
- * Create a signed checkpoint for a DID (gateway-side operation).
13
- *
14
- * Gateway signs the DID state snapshot using its ML-DSA-65 private key.
15
- * Clients verify this signature using the gateway's published public key.
16
- *
17
- * @param subject - DID being checkpointed
18
- * @param publicKey - Current public key bytes
19
- * @param revoked - Current revocation status
20
- * @param rotationSequence - Current rotation sequence counter
21
- * @param gatewayPrivateKey - Gateway's ML-DSA-65 secret key (32-byte seed or 4032-byte expanded)
22
- * @returns Signed checkpoint or error
23
- *
24
- * @example
25
- * ```typescript
26
- * const checkpoint = await createCheckpoint(
27
- * 'did:key:z6Mk...',
28
- * publicKeyBytes,
29
- * false,
30
- * 5,
31
- * gatewaySecretKey
32
- * );
33
- * if (checkpoint.ok) {
34
- * // Send checkpoint to client for staleness detection
35
- * sendToClient(checkpoint.value);
36
- * }
37
- * ```
38
- */
39
- async function createCheckpoint(subject, publicKey, revoked, rotationSequence, gatewayPrivateKey) {
40
- const timestamp = Date.now();
41
- // Construct canonical message to sign
42
- const publicKeyB64 = Buffer.from(publicKey).toString('base64');
43
- const message = `DIDStateCheckpoint||1.0||${subject}||${publicKeyB64}||${revoked}||${rotationSequence}||${timestamp}`;
44
- const messageBytes = new TextEncoder().encode(message);
45
- // Sign using gateway's ML-DSA-65 key
46
- const sigResult = await (0, identity_js_1.signMlDsa65)(gatewayPrivateKey, messageBytes);
47
- if (!sigResult.ok) {
48
- return (0, shared_1.err)('SIGN_FAILED');
49
- }
50
- return (0, shared_1.ok)({
51
- type: 'DIDStateCheckpoint',
52
- version: '1.0',
53
- subject,
54
- current_public_key: publicKeyB64,
55
- revoked,
56
- rotation_sequence: rotationSequence,
57
- timestamp,
58
- checkpoint_signature_algorithm: 'ML-DSA-65',
59
- checkpoint_signature: Buffer.from(sigResult.value).toString('base64')
60
- });
61
- }
62
- /* ── Checkpoint Verification (Client-side) ── */
63
- /**
64
- * Verify a checkpoint signature (client-side operation).
65
- *
66
- * Clients MUST verify checkpoint signatures before trusting the state.
67
- * Uses gateway's published ML-DSA-65 public key to verify signature.
68
- *
69
- * @param checkpoint - Checkpoint to verify
70
- * @param gatewayPublicKey - Gateway's ML-DSA-65 public key (1952 bytes)
71
- * @returns true if signature valid, false if invalid, error if verification fails
72
- *
73
- * @example
74
- * ```typescript
75
- * const valid = await verifyCheckpoint(checkpoint, gatewayPubKey);
76
- * if (valid.ok && valid.value) {
77
- * // Checkpoint is authentic - safe to use for staleness detection
78
- * if (isCacheStale(localCache, checkpoint)) {
79
- * // Refresh local cache
80
- * }
81
- * }
82
- * ```
83
- */
84
- async function verifyCheckpoint(checkpoint, gatewayPublicKey) {
85
- // Validate checkpoint format
86
- if (checkpoint.type !== 'DIDStateCheckpoint') {
87
- return (0, shared_1.err)('INVALID_FORMAT');
88
- }
89
- if (checkpoint.version !== '1.0') {
90
- return (0, shared_1.err)('INVALID_FORMAT');
91
- }
92
- if (!checkpoint.subject || !checkpoint.current_public_key) {
93
- return (0, shared_1.err)('INVALID_FORMAT');
94
- }
95
- if (typeof checkpoint.rotation_sequence !== 'number' || checkpoint.rotation_sequence < 0) {
96
- return (0, shared_1.err)('INVALID_FORMAT');
97
- }
98
- if (typeof checkpoint.timestamp !== 'number' || checkpoint.timestamp <= 0) {
99
- return (0, shared_1.err)('INVALID_TIMESTAMP');
100
- }
101
- if (checkpoint.checkpoint_signature_algorithm !== 'ML-DSA-65') {
102
- return (0, shared_1.err)('INVALID_FORMAT');
103
- }
104
- // Reconstruct canonical message
105
- const message = `DIDStateCheckpoint||1.0||${checkpoint.subject}||${checkpoint.current_public_key}||${checkpoint.revoked}||${checkpoint.rotation_sequence}||${checkpoint.timestamp}`;
106
- const messageBytes = new TextEncoder().encode(message);
107
- // Decode signature
108
- let signature;
109
- try {
110
- signature = Buffer.from(checkpoint.checkpoint_signature, 'base64');
111
- }
112
- catch {
113
- return (0, shared_1.err)('INVALID_SIGNATURE');
114
- }
115
- // Verify signature using gateway public key
116
- const verifyResult = await (0, identity_js_1.verifyMlDsa65)(gatewayPublicKey, signature, messageBytes);
117
- if (!verifyResult.ok) {
118
- return (0, shared_1.err)('VERIFY_FAILED');
119
- }
120
- return (0, shared_1.ok)(verifyResult.value);
121
- }
122
- /* ── Staleness Detection ── */
123
- /**
124
- * Detect if local cache is stale compared to gateway checkpoint.
125
- *
126
- * Cache is stale if:
127
- * 1. Checkpoint rotation_sequence > local rotationSequence (key rotated)
128
- * 2. Checkpoint revoked !== local revoked (revocation status changed)
129
- * 3. Checkpoint public key !== local publicKey (state drift)
130
- *
131
- * @param localCache - Local cache entry for DID
132
- * @param checkpoint - Verified checkpoint from gateway
133
- * @returns true if cache needs refresh, false if cache is current
134
- *
135
- * @example
136
- * ```typescript
137
- * if (isCacheStale(localCache, checkpoint)) {
138
- * // Local cache is outdated - fetch fresh state from gateway
139
- * const freshState = await registry.getEntry(did);
140
- * }
141
- * ```
142
- */
143
- function isCacheStale(localCache, checkpoint) {
144
- // Sequence number mismatch indicates key rotation
145
- if (checkpoint.rotation_sequence > localCache.rotationSequence) {
146
- return true;
147
- }
148
- // Revocation status changed
149
- if (checkpoint.revoked !== localCache.revoked) {
150
- return true;
151
- }
152
- // Public key mismatch indicates state drift
153
- const checkpointPubKey = Buffer.from(checkpoint.current_public_key, 'base64');
154
- if (!Buffer.from(localCache.publicKey).equals(checkpointPubKey)) {
155
- return true;
156
- }
157
- return false;
158
- }
159
- /* ── Encoding/Decoding ── */
160
- /**
161
- * Encode checkpoint to JSON string for wire transport.
162
- *
163
- * @param checkpoint - Checkpoint to encode
164
- * @returns JSON string
165
- */
166
- function encodeCheckpoint(checkpoint) {
167
- return JSON.stringify(checkpoint);
168
- }
169
- /**
170
- * Decode checkpoint from JSON string.
171
- *
172
- * @param encoded - JSON string
173
- * @returns Parsed checkpoint or error
174
- */
175
- function decodeCheckpoint(encoded) {
176
- try {
177
- const parsed = JSON.parse(encoded);
178
- // Basic validation
179
- if (parsed.type !== 'DIDStateCheckpoint') {
180
- return (0, shared_1.err)('INVALID_FORMAT');
181
- }
182
- if (parsed.version !== '1.0') {
183
- return (0, shared_1.err)('INVALID_FORMAT');
184
- }
185
- if (!parsed.subject || !parsed.current_public_key || !parsed.checkpoint_signature) {
186
- return (0, shared_1.err)('INVALID_FORMAT');
187
- }
188
- return (0, shared_1.ok)(parsed);
189
- }
190
- catch {
191
- return (0, shared_1.err)('INVALID_FORMAT');
192
- }
193
- }
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.createCheckpoint=createCheckpoint,exports.verifyCheckpoint=verifyCheckpoint,exports.isCacheStale=isCacheStale,exports.encodeCheckpoint=encodeCheckpoint,exports.decodeCheckpoint=decodeCheckpoint;const shared_1=require("../_deps/shared/index.js"),identity_js_1=require("./identity.js");async function createCheckpoint(e,r,t,n,i){const o=Date.now(),c=Buffer.from(r).toString("base64"),s=`DIDStateCheckpoint||1.0||${e}||${c}||${t}||${n}||${o}`,a=(new TextEncoder).encode(s),u=await(0,identity_js_1.signMlDsa65)(i,a);return u.ok?(0,shared_1.ok)({type:"DIDStateCheckpoint",version:"1.0",subject:e,current_public_key:c,revoked:t,rotation_sequence:n,timestamp:o,checkpoint_signature_algorithm:"ML-DSA-65",checkpoint_signature:Buffer.from(u.value).toString("base64")}):(0,shared_1.err)("SIGN_FAILED")}async function verifyCheckpoint(e,r){if("DIDStateCheckpoint"!==e.type)return(0,shared_1.err)("INVALID_FORMAT");if("1.0"!==e.version)return(0,shared_1.err)("INVALID_FORMAT");if(!e.subject||!e.current_public_key)return(0,shared_1.err)("INVALID_FORMAT");if("number"!=typeof e.rotation_sequence||e.rotation_sequence<0)return(0,shared_1.err)("INVALID_FORMAT");if("number"!=typeof e.timestamp||e.timestamp<=0)return(0,shared_1.err)("INVALID_TIMESTAMP");if("ML-DSA-65"!==e.checkpoint_signature_algorithm)return(0,shared_1.err)("INVALID_FORMAT");const t=`DIDStateCheckpoint||1.0||${e.subject}||${e.current_public_key}||${e.revoked}||${e.rotation_sequence}||${e.timestamp}`,n=(new TextEncoder).encode(t);let i;try{i=Buffer.from(e.checkpoint_signature,"base64")}catch{return(0,shared_1.err)("INVALID_SIGNATURE")}const o=await(0,identity_js_1.verifyMlDsa65)(r,i,n);return o.ok?(0,shared_1.ok)(o.value):(0,shared_1.err)("VERIFY_FAILED")}function isCacheStale(e,r){if(r.rotation_sequence>e.rotationSequence)return!0;if(r.revoked!==e.revoked)return!0;const t=Buffer.from(r.current_public_key,"base64");return!Buffer.from(e.publicKey).equals(t)}function encodeCheckpoint(e){return JSON.stringify(e)}function decodeCheckpoint(e){try{const r=JSON.parse(e);return"DIDStateCheckpoint"!==r.type||"1.0"!==r.version?(0,shared_1.err)("INVALID_FORMAT"):r.subject&&r.current_public_key&&r.checkpoint_signature?(0,shared_1.ok)(r):(0,shared_1.err)("INVALID_FORMAT")}catch{return(0,shared_1.err)("INVALID_FORMAT")}}