@private.me/xbind 1.3.5 → 3.0.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.
- package/LICENSES.md +212 -0
- package/README.md +388 -6
- package/dist-standalone/_deps/mldsa-wasm/dist/mldsa.js +1 -1920
- package/dist-standalone/_deps/shared/cjs/errors.js +1 -639
- package/dist-standalone/_deps/shared/cjs/index.js +1 -496
- package/dist-standalone/_deps/shared/cjs/types.js +1 -317
- package/dist-standalone/_deps/shared/errors.js +1 -255
- package/dist-standalone/_deps/shared/index.js +1 -74
- package/dist-standalone/_deps/shared/types.js +1 -90
- package/dist-standalone/_deps/ux-helpers/cjs/errors.js +1 -1
- package/dist-standalone/_deps/ux-helpers/cjs/index.js +1 -1
- package/dist-standalone/_deps/ux-helpers/cjs/pagination.js +1 -1
- package/dist-standalone/_deps/ux-helpers/cjs/progress.js +1 -1
- package/dist-standalone/_deps/ux-helpers/cjs/search.js +1 -1
- package/dist-standalone/_deps/ux-helpers/cjs/types.js +1 -1
- package/dist-standalone/_deps/ux-helpers/errors.js +1 -1
- package/dist-standalone/_deps/ux-helpers/index.js +1 -1
- package/dist-standalone/_deps/ux-helpers/pagination.js +1 -1
- package/dist-standalone/_deps/ux-helpers/progress.js +1 -1
- package/dist-standalone/_deps/ux-helpers/search.js +1 -1
- package/dist-standalone/_deps/xchange/auto-accept.js +1 -1
- package/dist-standalone/_deps/xchange/cjs/auto-accept.js +1 -1
- package/dist-standalone/_deps/xchange/cjs/errors.js +1 -1
- package/dist-standalone/_deps/xchange/cjs/index.js +1 -1
- package/dist-standalone/_deps/xchange/cjs/invite-client.js +1 -1
- package/dist-standalone/_deps/xchange/cjs/lazy-init.js +1 -1
- package/dist-standalone/_deps/xchange/cjs/trust-integration.js +1 -1
- package/dist-standalone/_deps/xchange/cjs/xchange.js +1 -1
- package/dist-standalone/_deps/xchange/errors.js +1 -1
- package/dist-standalone/_deps/xchange/index.js +1 -1
- package/dist-standalone/_deps/xchange/invite-client.js +1 -1
- package/dist-standalone/_deps/xchange/lazy-init.js +1 -1
- package/dist-standalone/_deps/xchange/trust-integration.js +1 -1
- package/dist-standalone/_deps/xchange/xchange.js +1 -1
- package/dist-standalone/_deps/xregistry/cjs/discovery.js +1 -1
- package/dist-standalone/_deps/xregistry/cjs/errors.js +1 -1
- package/dist-standalone/_deps/xregistry/cjs/index.js +1 -1
- package/dist-standalone/_deps/xregistry/cjs/registry.js +1 -1
- package/dist-standalone/_deps/xregistry/cjs/schema.js +1 -1
- package/dist-standalone/_deps/xregistry/cjs/types.js +1 -1
- package/dist-standalone/_deps/xregistry/discovery.js +1 -1
- package/dist-standalone/_deps/xregistry/errors.js +1 -1
- package/dist-standalone/_deps/xregistry/index.js +1 -1
- package/dist-standalone/_deps/xregistry/registry.js +1 -1
- package/dist-standalone/_deps/xregistry/schema.js +1 -1
- package/dist-standalone/_deps/xregistry/types.js +1 -1
- package/dist-standalone/agent-call.js +1 -642
- package/dist-standalone/agent-sdk.js +1 -328
- package/dist-standalone/agent.d.ts +95 -5
- package/dist-standalone/agent.js +1 -1545
- package/dist-standalone/approval.js +1 -193
- package/dist-standalone/async-iterators.d.ts +275 -0
- package/dist-standalone/async-iterators.js +1 -0
- package/dist-standalone/auth.js +1 -219
- package/dist-standalone/auto-accept.js +1 -229
- package/dist-standalone/backup-config.js +1 -201
- package/dist-standalone/backup.d.ts +114 -0
- package/dist-standalone/backup.js +1 -0
- package/dist-standalone/batch-operations.d.ts +297 -0
- package/dist-standalone/batch-operations.js +1 -0
- package/dist-standalone/cancellation.d.ts +301 -0
- package/dist-standalone/cancellation.js +1 -0
- package/dist-standalone/checkpoint.js +1 -186
- package/dist-standalone/circuit-breaker.d.ts +351 -0
- package/dist-standalone/circuit-breaker.js +1 -0
- package/dist-standalone/cjs/agent-call.js +1 -651
- package/dist-standalone/cjs/agent-sdk.js +1 -332
- package/dist-standalone/cjs/agent.js +1 -1582
- package/dist-standalone/cjs/approval.js +1 -199
- package/dist-standalone/cjs/async-iterators.js +1 -0
- package/dist-standalone/cjs/auth.js +1 -225
- package/dist-standalone/cjs/auto-accept.js +1 -233
- package/dist-standalone/cjs/backup-config.js +1 -207
- package/dist-standalone/cjs/backup.js +1 -0
- package/dist-standalone/cjs/batch-operations.js +1 -0
- package/dist-standalone/cjs/cancellation.js +1 -0
- package/dist-standalone/cjs/checkpoint.js +1 -193
- package/dist-standalone/cjs/circuit-breaker.js +1 -0
- package/dist-standalone/cjs/cli/init.js +1 -486
- package/dist-standalone/cjs/config-validation.js +1 -0
- package/dist-standalone/cjs/connect.js +1 -312
- package/dist-standalone/cjs/connection-pool.js +1 -0
- package/dist-standalone/cjs/correlation-id.js +1 -339
- package/dist-standalone/cjs/crypto-utils.js +1 -0
- package/dist-standalone/cjs/debug-mode.js +1 -0
- package/dist-standalone/cjs/did-document.js +1 -101
- package/dist-standalone/cjs/did-privateme.js +1 -130
- package/dist-standalone/cjs/did-web.js +1 -201
- package/dist-standalone/cjs/discovery.js +1 -462
- package/dist-standalone/cjs/dual-mode.js +1 -251
- package/dist-standalone/cjs/email-templates.js +1 -313
- package/dist-standalone/cjs/email-transport.js +1 -239
- package/dist-standalone/cjs/envelope.js +1 -510
- package/dist-standalone/cjs/errors.js +1 -826
- package/dist-standalone/cjs/event-emitter.js +1 -0
- package/dist-standalone/cjs/gateway-state.js +1 -55
- package/dist-standalone/cjs/gateway-transport.js +1 -120
- package/dist-standalone/cjs/graceful-degradation.js +1 -0
- package/dist-standalone/cjs/guardrails.js +1 -223
- package/dist-standalone/cjs/health-check.js +1 -0
- package/dist-standalone/cjs/http-compat.js +1 -272
- package/dist-standalone/cjs/http-status-map.js +1 -571
- package/dist-standalone/cjs/identity.js +1 -540
- package/dist-standalone/cjs/index.js +1 -237
- package/dist-standalone/cjs/invitation.js +1 -421
- package/dist-standalone/cjs/invite.js +1 -328
- package/dist-standalone/cjs/key-agreement.js +1 -246
- package/dist-standalone/cjs/lazy-init.js +1 -300
- package/dist-standalone/cjs/logger.js +1 -0
- package/dist-standalone/cjs/mdns-discovery.js +1 -202
- package/dist-standalone/cjs/nonce-store.js +1 -66
- package/dist-standalone/cjs/pairing-manager.js +1 -223
- package/dist-standalone/cjs/plugin-system.js +1 -0
- package/dist-standalone/cjs/plugins/logging.js +1 -0
- package/dist-standalone/cjs/plugins/metrics.js +1 -0
- package/dist-standalone/cjs/plugins/validation.js +1 -0
- package/dist-standalone/cjs/policy.js +1 -320
- package/dist-standalone/cjs/progress-callbacks.js +1 -0
- package/dist-standalone/cjs/redis-nonce-store.js +1 -76
- package/dist-standalone/cjs/registry-middleware.js +1 -50
- package/dist-standalone/cjs/retry-strategies.js +1 -0
- package/dist-standalone/cjs/retry-transport.js +1 -102
- package/dist-standalone/cjs/runtime/browser.js +1 -0
- package/dist-standalone/cjs/runtime/edge.js +1 -0
- package/dist-standalone/cjs/runtime/react-native.js +1 -0
- package/dist-standalone/cjs/security-policy.js +1 -245
- package/dist-standalone/cjs/serialization.js +1 -0
- package/dist-standalone/cjs/split-channel.js +1 -177
- package/dist-standalone/cjs/subscription-proof.js +1 -230
- package/dist-standalone/cjs/succession.js +1 -148
- package/dist-standalone/cjs/timeouts.js +1 -0
- package/dist-standalone/cjs/trace-context.js +1 -0
- package/dist-standalone/cjs/trace-spans.js +1 -0
- package/dist-standalone/cjs/transport.js +1 -63
- package/dist-standalone/cjs/trust-registry.js +1 -742
- package/dist-standalone/cjs/types/error-response.js +1 -56
- package/dist-standalone/cjs/vault-auth.js +1 -0
- package/dist-standalone/cjs/vault-store-loader.js +1 -0
- package/dist-standalone/cjs/verify.js +1 -25
- package/dist-standalone/cjs/version-info.js +1 -0
- package/dist-standalone/cjs/xfetch.js +1 -252
- package/dist-standalone/cli/init.js +1 -449
- package/dist-standalone/cli/setup.js +1 -514
- package/dist-standalone/cli/types.js +1 -27
- package/dist-standalone/cli/xbind.js +1 -148
- package/dist-standalone/config-validation.d.ts +185 -0
- package/dist-standalone/config-validation.js +1 -0
- package/dist-standalone/connect.js +1 -274
- package/dist-standalone/connection-pool.d.ts +251 -0
- package/dist-standalone/connection-pool.js +1 -0
- package/dist-standalone/correlation-id.js +1 -326
- package/dist-standalone/crypto-utils.d.ts +60 -0
- package/dist-standalone/crypto-utils.js +1 -0
- package/dist-standalone/debug-mode.d.ts +286 -0
- package/dist-standalone/debug-mode.js +1 -0
- package/dist-standalone/did-document.js +1 -96
- package/dist-standalone/did-privateme.js +1 -121
- package/dist-standalone/did-web.js +1 -196
- package/dist-standalone/discovery.js +1 -458
- package/dist-standalone/dual-mode.js +1 -247
- package/dist-standalone/email-templates.js +1 -309
- package/dist-standalone/email-transport.js +1 -232
- package/dist-standalone/envelope.d.ts +29 -1
- package/dist-standalone/envelope.js +1 -497
- package/dist-standalone/errors.d.ts +10 -0
- package/dist-standalone/errors.js +1 -811
- package/dist-standalone/event-emitter.d.ts +395 -0
- package/dist-standalone/event-emitter.js +1 -0
- package/dist-standalone/gateway-state.js +1 -51
- package/dist-standalone/gateway-transport.js +1 -116
- package/dist-standalone/graceful-degradation.d.ts +246 -0
- package/dist-standalone/graceful-degradation.js +1 -0
- package/dist-standalone/guardrails.js +1 -216
- package/dist-standalone/health-check.d.ts +150 -0
- package/dist-standalone/health-check.js +1 -0
- package/dist-standalone/http-compat.js +1 -267
- package/dist-standalone/http-status-map.js +1 -561
- package/dist-standalone/identity.d.ts +64 -1
- package/dist-standalone/identity.js +1 -515
- package/dist-standalone/index.d.ts +45 -3
- package/dist-standalone/index.js +1 -52
- package/dist-standalone/invitation.js +1 -415
- package/dist-standalone/invite.js +1 -324
- package/dist-standalone/key-agreement.d.ts +61 -13
- package/dist-standalone/key-agreement.js +1 -236
- package/dist-standalone/lazy-init.js +1 -295
- package/dist-standalone/logger.d.ts +77 -0
- package/dist-standalone/logger.js +1 -0
- package/dist-standalone/mdns-discovery.js +1 -195
- package/dist-standalone/nonce-store.d.ts +16 -3
- package/dist-standalone/nonce-store.js +1 -62
- package/dist-standalone/package.json +0 -1
- package/dist-standalone/pairing-manager.js +1 -219
- package/dist-standalone/plugin-system.d.ts +145 -0
- package/dist-standalone/plugin-system.js +1 -0
- package/dist-standalone/policy.js +1 -315
- package/dist-standalone/progress-callbacks.d.ts +394 -0
- package/dist-standalone/progress-callbacks.js +1 -0
- package/dist-standalone/redis-nonce-store.js +1 -72
- package/dist-standalone/registry-middleware.js +1 -47
- package/dist-standalone/retry-strategies.d.ts +382 -0
- package/dist-standalone/retry-strategies.js +1 -0
- package/dist-standalone/retry-transport.js +1 -98
- package/dist-standalone/security-policy.js +1 -239
- package/dist-standalone/serialization.d.ts +244 -0
- package/dist-standalone/serialization.js +1 -0
- package/dist-standalone/split-channel.d.ts +49 -1
- package/dist-standalone/split-channel.js +1 -171
- package/dist-standalone/subscription-proof.js +1 -224
- package/dist-standalone/succession.js +1 -142
- package/dist-standalone/timeouts.d.ts +275 -0
- package/dist-standalone/timeouts.js +1 -0
- package/dist-standalone/trace-context.d.ts +252 -0
- package/dist-standalone/trace-context.js +1 -0
- package/dist-standalone/trace-spans.d.ts +360 -0
- package/dist-standalone/trace-spans.js +1 -0
- package/dist-standalone/transport.js +1 -59
- package/dist-standalone/trust-registry.d.ts +106 -5
- package/dist-standalone/trust-registry.js +1 -702
- package/dist-standalone/vault-auth.d.ts +91 -0
- package/dist-standalone/vault-auth.js +1 -0
- package/dist-standalone/vault-store-loader.d.ts +110 -0
- package/dist-standalone/vault-store-loader.js +1 -0
- package/dist-standalone/verify.js +1 -16
- package/dist-standalone/version-info.d.ts +259 -0
- package/dist-standalone/version-info.js +1 -0
- package/dist-standalone/xfetch.js +1 -247
- package/llms.txt +1 -0
- package/package.json +65 -5
- package/share1.dat +0 -0
- package/dist-standalone/_deps/crypto/base64.d.ts +0 -29
- package/dist-standalone/_deps/crypto/base64.js +0 -222
- package/dist-standalone/_deps/crypto/cjs/base64.js +0 -665
- package/dist-standalone/_deps/crypto/cjs/errors.js +0 -675
- package/dist-standalone/_deps/crypto/cjs/hmac.js +0 -473
- package/dist-standalone/_deps/crypto/cjs/index.js +0 -852
- package/dist-standalone/_deps/crypto/cjs/package.json +0 -1
- package/dist-standalone/_deps/crypto/cjs/padding.js +0 -511
- package/dist-standalone/_deps/crypto/cjs/share-header.js +0 -372
- package/dist-standalone/_deps/crypto/cjs/shares.js +0 -874
- package/dist-standalone/_deps/crypto/cjs/tlv.js +0 -1021
- package/dist-standalone/_deps/crypto/cjs/uuid.js +0 -443
- package/dist-standalone/_deps/crypto/cjs/verify.js +0 -414
- package/dist-standalone/_deps/crypto/cjs/xorida.js +0 -923
- package/dist-standalone/_deps/crypto/errors.d.ts +0 -51
- package/dist-standalone/_deps/crypto/errors.js +0 -199
- package/dist-standalone/_deps/crypto/hmac.d.ts +0 -39
- package/dist-standalone/_deps/crypto/hmac.js +0 -134
- package/dist-standalone/_deps/crypto/index.d.ts +0 -20
- package/dist-standalone/_deps/crypto/index.js +0 -145
- package/dist-standalone/_deps/crypto/padding.d.ts +0 -19
- package/dist-standalone/_deps/crypto/padding.js +0 -159
- package/dist-standalone/_deps/crypto/share-header.d.ts +0 -44
- package/dist-standalone/_deps/crypto/share-header.js +0 -92
- package/dist-standalone/_deps/crypto/shares.d.ts +0 -27
- package/dist-standalone/_deps/crypto/shares.js +0 -295
- package/dist-standalone/_deps/crypto/tlv.d.ts +0 -26
- package/dist-standalone/_deps/crypto/tlv.js +0 -364
- package/dist-standalone/_deps/crypto/uuid.d.ts +0 -22
- package/dist-standalone/_deps/crypto/uuid.js +0 -136
- package/dist-standalone/_deps/crypto/verify.d.ts +0 -15
- package/dist-standalone/_deps/crypto/verify.js +0 -71
- package/dist-standalone/_deps/crypto/xorida.d.ts +0 -44
- package/dist-standalone/_deps/crypto/xorida.js +0 -366
- package/dist-standalone/_deps/shared/errors.d.ts.map +0 -1
- package/dist-standalone/_deps/shared/errors.js.map +0 -1
- package/dist-standalone/_deps/shared/index.d.ts.map +0 -1
- package/dist-standalone/_deps/shared/index.js.map +0 -1
- package/dist-standalone/_deps/shared/types.d.ts.map +0 -1
- package/dist-standalone/_deps/shared/types.js.map +0 -1
- package/dist-standalone/_deps/ux-helpers/cjs/errors.d.ts.map +0 -1
- package/dist-standalone/_deps/ux-helpers/cjs/errors.js.map +0 -1
- package/dist-standalone/_deps/ux-helpers/cjs/index.d.ts.map +0 -1
- package/dist-standalone/_deps/ux-helpers/cjs/index.js.map +0 -1
- package/dist-standalone/_deps/ux-helpers/cjs/pagination.d.ts.map +0 -1
- package/dist-standalone/_deps/ux-helpers/cjs/pagination.js.map +0 -1
- package/dist-standalone/_deps/ux-helpers/cjs/progress.d.ts.map +0 -1
- package/dist-standalone/_deps/ux-helpers/cjs/progress.js.map +0 -1
- package/dist-standalone/_deps/ux-helpers/cjs/search.d.ts.map +0 -1
- package/dist-standalone/_deps/ux-helpers/cjs/search.js.map +0 -1
- package/dist-standalone/_deps/ux-helpers/cjs/types.d.ts.map +0 -1
- package/dist-standalone/_deps/ux-helpers/cjs/types.js.map +0 -1
- package/dist-standalone/_deps/ux-helpers/errors.d.ts.map +0 -1
- package/dist-standalone/_deps/ux-helpers/errors.js.map +0 -1
- package/dist-standalone/_deps/ux-helpers/index.d.ts.map +0 -1
- package/dist-standalone/_deps/ux-helpers/index.js.map +0 -1
- package/dist-standalone/_deps/ux-helpers/pagination.d.ts.map +0 -1
- package/dist-standalone/_deps/ux-helpers/pagination.js.map +0 -1
- package/dist-standalone/_deps/ux-helpers/progress.d.ts.map +0 -1
- package/dist-standalone/_deps/ux-helpers/progress.js.map +0 -1
- package/dist-standalone/_deps/ux-helpers/search.d.ts.map +0 -1
- package/dist-standalone/_deps/ux-helpers/search.js.map +0 -1
- package/dist-standalone/_deps/ux-helpers/types.d.ts.map +0 -1
- package/dist-standalone/_deps/ux-helpers/types.js.map +0 -1
- package/dist-standalone/_deps/xregistry/discovery.d.ts.map +0 -1
- package/dist-standalone/_deps/xregistry/discovery.js.map +0 -1
- package/dist-standalone/_deps/xregistry/errors.d.ts.map +0 -1
- package/dist-standalone/_deps/xregistry/errors.js.map +0 -1
- package/dist-standalone/_deps/xregistry/index.d.ts.map +0 -1
- package/dist-standalone/_deps/xregistry/index.js.map +0 -1
- package/dist-standalone/_deps/xregistry/registry.d.ts.map +0 -1
- package/dist-standalone/_deps/xregistry/registry.js.map +0 -1
- package/dist-standalone/_deps/xregistry/schema.d.ts.map +0 -1
- package/dist-standalone/_deps/xregistry/schema.js.map +0 -1
- package/dist-standalone/_deps/xregistry/types.d.ts.map +0 -1
- package/dist-standalone/_deps/xregistry/types.js.map +0 -1
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module cancellation
|
|
3
|
+
* Cancellation token support for xBind operations
|
|
4
|
+
*
|
|
5
|
+
* Provides AbortController/AbortSignal integration for enhanced operation control:
|
|
6
|
+
* - Cancellable async operations (fetch, agent.call, transport)
|
|
7
|
+
* - Timeout management with automatic cleanup
|
|
8
|
+
* - Composite signals (multiple cancellation sources)
|
|
9
|
+
* - Resource cleanup on cancellation
|
|
10
|
+
*
|
|
11
|
+
* Architecture:
|
|
12
|
+
* - Uses standard AbortController/AbortSignal (Web API + Node.js)
|
|
13
|
+
* - Timeout wrapper creates time-limited signals
|
|
14
|
+
* - Composite signals combine multiple cancellation sources
|
|
15
|
+
* - Cleanup callbacks ensure proper resource disposal
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // Timeout with cancellation
|
|
20
|
+
* const signal = createTimeoutSignal(5000);
|
|
21
|
+
* await xfetch('https://api.example.com', { signal });
|
|
22
|
+
*
|
|
23
|
+
* // Manual cancellation
|
|
24
|
+
* const controller = new AbortController();
|
|
25
|
+
* setTimeout(() => controller.abort(), 1000);
|
|
26
|
+
* await agent.call('tool:action', params, { signal: controller.signal });
|
|
27
|
+
*
|
|
28
|
+
* // Composite signals
|
|
29
|
+
* const timeout = createTimeoutSignal(10000);
|
|
30
|
+
* const manual = new AbortController();
|
|
31
|
+
* const combined = combineSignals([timeout.signal, manual.signal]);
|
|
32
|
+
* await operation({ signal: combined });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
import type { Result } from '@private.me/shared';
|
|
36
|
+
/**
|
|
37
|
+
* Cancellation error thrown when operation is aborted
|
|
38
|
+
*/
|
|
39
|
+
export declare class CancellationError extends Error {
|
|
40
|
+
reason?: string | undefined;
|
|
41
|
+
context?: Record<string, unknown> | undefined;
|
|
42
|
+
constructor(message: string, reason?: string | undefined, context?: Record<string, unknown> | undefined);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Cleanup callback type for resource disposal
|
|
46
|
+
*/
|
|
47
|
+
export type CleanupCallback = () => void | Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Timeout signal controller with cleanup
|
|
50
|
+
*/
|
|
51
|
+
export interface TimeoutController {
|
|
52
|
+
/** Abort signal that triggers on timeout */
|
|
53
|
+
signal: AbortSignal;
|
|
54
|
+
/** Clear timeout (prevents abort) */
|
|
55
|
+
clear: () => void;
|
|
56
|
+
/** Remaining time in milliseconds */
|
|
57
|
+
remaining: () => number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Options for creating timeout signals
|
|
61
|
+
*/
|
|
62
|
+
export interface TimeoutOptions {
|
|
63
|
+
/** Timeout in milliseconds */
|
|
64
|
+
timeout: number;
|
|
65
|
+
/** Optional reason message */
|
|
66
|
+
reason?: string;
|
|
67
|
+
/** Optional context for debugging */
|
|
68
|
+
context?: Record<string, unknown>;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Create an AbortSignal that triggers after a timeout
|
|
72
|
+
*
|
|
73
|
+
* Automatically aborts the signal after the specified duration.
|
|
74
|
+
* Useful for setting time limits on async operations.
|
|
75
|
+
*
|
|
76
|
+
* @param timeout - Timeout in milliseconds
|
|
77
|
+
* @param options - Optional reason and context
|
|
78
|
+
* @returns TimeoutController with signal and clear function
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const timeout = createTimeoutSignal(5000);
|
|
83
|
+
* try {
|
|
84
|
+
* await fetch('https://api.example.com', { signal: timeout.signal });
|
|
85
|
+
* } catch (error) {
|
|
86
|
+
* if (error.name === 'AbortError') {
|
|
87
|
+
* console.log('Request timed out after 5s');
|
|
88
|
+
* }
|
|
89
|
+
* } finally {
|
|
90
|
+
* timeout.clear(); // Clean up timer
|
|
91
|
+
* }
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare function createTimeoutSignal(timeout: number, options?: Omit<TimeoutOptions, 'timeout'>): TimeoutController;
|
|
95
|
+
/**
|
|
96
|
+
* Combine multiple AbortSignals into a single signal
|
|
97
|
+
*
|
|
98
|
+
* The combined signal aborts when ANY of the source signals abort.
|
|
99
|
+
* Useful for operations with multiple cancellation sources (timeout, user action, etc.).
|
|
100
|
+
*
|
|
101
|
+
* @param signals - Array of signals to combine
|
|
102
|
+
* @returns Combined AbortSignal
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* const timeout = createTimeoutSignal(10000);
|
|
107
|
+
* const userCancel = new AbortController();
|
|
108
|
+
* const combined = combineSignals([timeout.signal, userCancel.signal]);
|
|
109
|
+
*
|
|
110
|
+
* // Either timeout OR user cancellation will abort
|
|
111
|
+
* await fetch('https://api.example.com', { signal: combined });
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export declare function combineSignals(signals: AbortSignal[]): AbortSignal;
|
|
115
|
+
/**
|
|
116
|
+
* Register cleanup callback to run when signal is aborted
|
|
117
|
+
*
|
|
118
|
+
* Ensures resources are properly disposed when operation is cancelled.
|
|
119
|
+
* Cleanup runs immediately if signal is already aborted.
|
|
120
|
+
*
|
|
121
|
+
* @param signal - AbortSignal to monitor
|
|
122
|
+
* @param cleanup - Cleanup callback
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* const controller = new AbortController();
|
|
127
|
+
* const connection = await openConnection();
|
|
128
|
+
*
|
|
129
|
+
* onCancellation(controller.signal, async () => {
|
|
130
|
+
* console.log('Cleaning up connection...');
|
|
131
|
+
* await connection.close();
|
|
132
|
+
* });
|
|
133
|
+
*
|
|
134
|
+
* // Later...
|
|
135
|
+
* controller.abort(); // Cleanup runs automatically
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
export declare function onCancellation(signal: AbortSignal, cleanup: CleanupCallback): void;
|
|
139
|
+
/**
|
|
140
|
+
* Check if signal is aborted and throw CancellationError if so
|
|
141
|
+
*
|
|
142
|
+
* Useful for checking cancellation at specific points in long-running operations.
|
|
143
|
+
*
|
|
144
|
+
* @param signal - AbortSignal to check
|
|
145
|
+
* @param context - Optional context for error
|
|
146
|
+
* @throws CancellationError if signal is aborted
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```typescript
|
|
150
|
+
* async function processLargeDataset(data: unknown[], signal?: AbortSignal) {
|
|
151
|
+
* for (const item of data) {
|
|
152
|
+
* throwIfAborted(signal, { item: item.id });
|
|
153
|
+
* await processItem(item);
|
|
154
|
+
* }
|
|
155
|
+
* }
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export declare function throwIfAborted(signal?: AbortSignal, context?: Record<string, unknown>): void;
|
|
159
|
+
/**
|
|
160
|
+
* Wrap a promise with cancellation support
|
|
161
|
+
*
|
|
162
|
+
* If signal aborts before promise resolves, returns error result.
|
|
163
|
+
* Otherwise returns the promise's result.
|
|
164
|
+
*
|
|
165
|
+
* @param promise - Promise to wrap
|
|
166
|
+
* @param signal - AbortSignal for cancellation
|
|
167
|
+
* @returns Result wrapper around promise
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* const timeout = createTimeoutSignal(5000);
|
|
172
|
+
* const result = await withCancellation(
|
|
173
|
+
* fetch('https://api.example.com'),
|
|
174
|
+
* timeout.signal
|
|
175
|
+
* );
|
|
176
|
+
*
|
|
177
|
+
* if (!result.ok) {
|
|
178
|
+
* console.error('Request cancelled:', result.error.message);
|
|
179
|
+
* }
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
export declare function withCancellation<T>(promise: Promise<T>, signal?: AbortSignal): Promise<Result<T, CancellationError>>;
|
|
183
|
+
/**
|
|
184
|
+
* Create a cancellable delay
|
|
185
|
+
*
|
|
186
|
+
* Returns a promise that resolves after the specified duration,
|
|
187
|
+
* but can be cancelled early via signal.
|
|
188
|
+
*
|
|
189
|
+
* @param ms - Delay in milliseconds
|
|
190
|
+
* @param signal - Optional AbortSignal for cancellation
|
|
191
|
+
* @returns Promise that resolves after delay or rejects on cancellation
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```typescript
|
|
195
|
+
* const controller = new AbortController();
|
|
196
|
+
*
|
|
197
|
+
* // Start 10s delay
|
|
198
|
+
* const delayPromise = delay(10000, controller.signal);
|
|
199
|
+
*
|
|
200
|
+
* // Cancel after 2s
|
|
201
|
+
* setTimeout(() => controller.abort(), 2000);
|
|
202
|
+
*
|
|
203
|
+
* try {
|
|
204
|
+
* await delayPromise; // Throws CancellationError after 2s
|
|
205
|
+
* } catch (error) {
|
|
206
|
+
* console.log('Delay cancelled');
|
|
207
|
+
* }
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
export declare function delay(ms: number, signal?: AbortSignal): Promise<void>;
|
|
211
|
+
/**
|
|
212
|
+
* Retry an operation with cancellation support
|
|
213
|
+
*
|
|
214
|
+
* Attempts operation multiple times with exponential backoff.
|
|
215
|
+
* Respects cancellation signal between retry attempts.
|
|
216
|
+
*
|
|
217
|
+
* @param operation - Async operation to retry
|
|
218
|
+
* @param options - Retry configuration
|
|
219
|
+
* @returns Result of operation
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* ```typescript
|
|
223
|
+
* const timeout = createTimeoutSignal(30000);
|
|
224
|
+
*
|
|
225
|
+
* const result = await withRetry(
|
|
226
|
+
* async () => {
|
|
227
|
+
* const res = await fetch('https://api.example.com');
|
|
228
|
+
* if (!res.ok) throw new Error('Request failed');
|
|
229
|
+
* return res.json();
|
|
230
|
+
* },
|
|
231
|
+
* {
|
|
232
|
+
* maxAttempts: 5,
|
|
233
|
+
* initialDelay: 1000,
|
|
234
|
+
* multiplier: 2,
|
|
235
|
+
* signal: timeout.signal,
|
|
236
|
+
* }
|
|
237
|
+
* );
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
export declare function withRetry<T>(operation: () => Promise<T>, options?: {
|
|
241
|
+
maxAttempts?: number;
|
|
242
|
+
initialDelay?: number;
|
|
243
|
+
multiplier?: number;
|
|
244
|
+
signal?: AbortSignal;
|
|
245
|
+
shouldRetry?: (error: unknown, attempt: number) => boolean;
|
|
246
|
+
}): Promise<Result<T, Error>>;
|
|
247
|
+
/**
|
|
248
|
+
* Create a manual cancellation controller with helper methods
|
|
249
|
+
*
|
|
250
|
+
* Extends AbortController with additional utilities for common patterns.
|
|
251
|
+
*
|
|
252
|
+
* @returns Enhanced controller with helper methods
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```typescript
|
|
256
|
+
* const controller = createCancellationController();
|
|
257
|
+
*
|
|
258
|
+
* // Start operation
|
|
259
|
+
* const promise = longRunningOperation({ signal: controller.signal });
|
|
260
|
+
*
|
|
261
|
+
* // Cancel with custom reason
|
|
262
|
+
* controller.cancel('User requested cancellation');
|
|
263
|
+
*
|
|
264
|
+
* // Check if cancelled
|
|
265
|
+
* if (controller.isCancelled) {
|
|
266
|
+
* console.log('Operation was cancelled');
|
|
267
|
+
* }
|
|
268
|
+
* ```
|
|
269
|
+
*/
|
|
270
|
+
export declare function createCancellationController(): {
|
|
271
|
+
/** Abort signal for cancellation */
|
|
272
|
+
signal: AbortSignal;
|
|
273
|
+
/** True if operation has been cancelled */
|
|
274
|
+
readonly isCancelled: boolean;
|
|
275
|
+
/** Reason for cancellation (if any) */
|
|
276
|
+
readonly reason: string | undefined;
|
|
277
|
+
/** Cancel the operation with optional reason */
|
|
278
|
+
cancel(reason?: string): void;
|
|
279
|
+
/** Throw if cancelled */
|
|
280
|
+
throwIfCancelled(context?: Record<string, unknown>): void;
|
|
281
|
+
};
|
|
282
|
+
/**
|
|
283
|
+
* Check if an error is a cancellation error
|
|
284
|
+
*
|
|
285
|
+
* @param error - Error to check
|
|
286
|
+
* @returns True if error is from cancellation
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```typescript
|
|
290
|
+
* try {
|
|
291
|
+
* await operation({ signal });
|
|
292
|
+
* } catch (error) {
|
|
293
|
+
* if (isCancellationError(error)) {
|
|
294
|
+
* console.log('Operation was cancelled');
|
|
295
|
+
* } else {
|
|
296
|
+
* console.error('Operation failed:', error);
|
|
297
|
+
* }
|
|
298
|
+
* }
|
|
299
|
+
* ```
|
|
300
|
+
*/
|
|
301
|
+
export declare function isCancellationError(error: unknown): error is CancellationError;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ok,err}from"./_deps/shared/index.js";export class CancellationError extends Error{reason;context;constructor(r,e,n){super(r),this.reason=e,this.context=n,this.name="CancellationError"}}export function createTimeoutSignal(r,e){const n=new AbortController,t=Date.now(),o=setTimeout(()=>{const t=e?.reason||`Operation timed out after ${r}ms`;n.abort(new CancellationError(t,"timeout",e?.context))},r);return{signal:n.signal,clear:()=>{clearTimeout(o)},remaining:()=>{const e=Date.now()-t;return Math.max(0,r-e)}}}export function combineSignals(r){const e=r.filter(r=>r&&!r.aborted);if(0===e.length){const e=r.find(r=>r?.aborted);return e||(new AbortController).signal}if(1===e.length)return e[0];if("function"==typeof AbortSignal.any)return AbortSignal.any(e);const n=new AbortController,t=[];for(const r of e){const e=()=>{n.abort(r.reason),t.forEach(r=>r())};r.addEventListener("abort",e,{once:!0}),t.push(()=>{r.removeEventListener("abort",e)})}return n.signal}export function onCancellation(r,e){r.aborted?Promise.resolve().then(()=>e()).catch(()=>{}):r.addEventListener("abort",()=>{Promise.resolve().then(()=>e()).catch(()=>{})},{once:!0})}export function throwIfAborted(r,e){if(r?.aborted){const n=r.reason instanceof Error?r.reason.message:String(r.reason||"Operation was cancelled");throw new CancellationError(n,"aborted",e)}}export async function withCancellation(r,e){if(!e)try{const e=await r;return ok(e)}catch(r){return err(new CancellationError(r instanceof Error?r.message:String(r),"promise_rejected"))}if(e.aborted){const r=e.reason instanceof Error?e.reason.message:String(e.reason||"Operation was cancelled");return err(new CancellationError(r,"aborted"))}return new Promise(n=>{const t=()=>{const r=e.reason instanceof Error?e.reason.message:String(e.reason||"Operation was cancelled");n(err(new CancellationError(r,"aborted")))};e.addEventListener("abort",t,{once:!0}),r.then(r=>{e.removeEventListener("abort",t),n(ok(r))}).catch(r=>{e.removeEventListener("abort",t),n(err(new CancellationError(r instanceof Error?r.message:String(r),"promise_rejected")))})})}export function delay(r,e){return new Promise((n,t)=>{if(e?.aborted){const r=e.reason instanceof Error?e.reason.message:String(e.reason||"Delay cancelled");return void t(new CancellationError(r,"aborted"))}const o=setTimeout(()=>{e&&e.removeEventListener("abort",a),n()},r),a=()=>{clearTimeout(o);const r=e.reason instanceof Error?e.reason.message:String(e.reason||"Delay cancelled");t(new CancellationError(r,"aborted"))};e&&e.addEventListener("abort",a,{once:!0})})}export async function withRetry(r,e){const n=e?.maxAttempts??3,t=e?.initialDelay??1e3,o=e?.multiplier??2,a=e?.signal,i=e?.shouldRetry??(()=>!0);let s,c=t;for(let e=1;e<=n;e++){if(a?.aborted){const r=a.reason instanceof Error?a.reason.message:String(a.reason||"Operation was cancelled");return err(new CancellationError(r,"aborted",{attempt:e}))}try{const e=await r();return ok(e)}catch(r){if(s=r instanceof Error?r:new Error(String(r)),e>=n||!i(r,e))break;try{await delay(c,a),c*=o}catch(r){if(r instanceof CancellationError)return err(r);throw r}}}return err(s||new Error("Operation failed after retries"))}export function createCancellationController(){const r=new AbortController;let e;return{signal:r.signal,get isCancelled(){return r.signal.aborted},get reason(){return e},cancel(n){e=n||"Operation cancelled",r.abort(new CancellationError(e,"manual"))},throwIfCancelled(e){throwIfAborted(r.signal,e)}}}export function isCancellationError(r){return r instanceof CancellationError||r instanceof Error&&"AbortError"===r.name||r instanceof Error&&"CancellationError"===r.name}
|
|
@@ -1,186 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { signMlDsa65, verifyMlDsa65 } from './identity.js';
|
|
3
|
-
/* ── Checkpoint Creation (Gateway-side) ── */
|
|
4
|
-
/**
|
|
5
|
-
* Create a signed checkpoint for a DID (gateway-side operation).
|
|
6
|
-
*
|
|
7
|
-
* Gateway signs the DID state snapshot using its ML-DSA-65 private key.
|
|
8
|
-
* Clients verify this signature using the gateway's published public key.
|
|
9
|
-
*
|
|
10
|
-
* @param subject - DID being checkpointed
|
|
11
|
-
* @param publicKey - Current public key bytes
|
|
12
|
-
* @param revoked - Current revocation status
|
|
13
|
-
* @param rotationSequence - Current rotation sequence counter
|
|
14
|
-
* @param gatewayPrivateKey - Gateway's ML-DSA-65 secret key (32-byte seed or 4032-byte expanded)
|
|
15
|
-
* @returns Signed checkpoint or error
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```typescript
|
|
19
|
-
* const checkpoint = await createCheckpoint(
|
|
20
|
-
* 'did:key:z6Mk...',
|
|
21
|
-
* publicKeyBytes,
|
|
22
|
-
* false,
|
|
23
|
-
* 5,
|
|
24
|
-
* gatewaySecretKey
|
|
25
|
-
* );
|
|
26
|
-
* if (checkpoint.ok) {
|
|
27
|
-
* // Send checkpoint to client for staleness detection
|
|
28
|
-
* sendToClient(checkpoint.value);
|
|
29
|
-
* }
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
32
|
-
export async function createCheckpoint(subject, publicKey, revoked, rotationSequence, gatewayPrivateKey) {
|
|
33
|
-
const timestamp = Date.now();
|
|
34
|
-
// Construct canonical message to sign
|
|
35
|
-
const publicKeyB64 = Buffer.from(publicKey).toString('base64');
|
|
36
|
-
const message = `DIDStateCheckpoint||1.0||${subject}||${publicKeyB64}||${revoked}||${rotationSequence}||${timestamp}`;
|
|
37
|
-
const messageBytes = new TextEncoder().encode(message);
|
|
38
|
-
// Sign using gateway's ML-DSA-65 key
|
|
39
|
-
const sigResult = await signMlDsa65(gatewayPrivateKey, messageBytes);
|
|
40
|
-
if (!sigResult.ok) {
|
|
41
|
-
return err('SIGN_FAILED');
|
|
42
|
-
}
|
|
43
|
-
return ok({
|
|
44
|
-
type: 'DIDStateCheckpoint',
|
|
45
|
-
version: '1.0',
|
|
46
|
-
subject,
|
|
47
|
-
current_public_key: publicKeyB64,
|
|
48
|
-
revoked,
|
|
49
|
-
rotation_sequence: rotationSequence,
|
|
50
|
-
timestamp,
|
|
51
|
-
checkpoint_signature_algorithm: 'ML-DSA-65',
|
|
52
|
-
checkpoint_signature: Buffer.from(sigResult.value).toString('base64')
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
/* ── Checkpoint Verification (Client-side) ── */
|
|
56
|
-
/**
|
|
57
|
-
* Verify a checkpoint signature (client-side operation).
|
|
58
|
-
*
|
|
59
|
-
* Clients MUST verify checkpoint signatures before trusting the state.
|
|
60
|
-
* Uses gateway's published ML-DSA-65 public key to verify signature.
|
|
61
|
-
*
|
|
62
|
-
* @param checkpoint - Checkpoint to verify
|
|
63
|
-
* @param gatewayPublicKey - Gateway's ML-DSA-65 public key (1952 bytes)
|
|
64
|
-
* @returns true if signature valid, false if invalid, error if verification fails
|
|
65
|
-
*
|
|
66
|
-
* @example
|
|
67
|
-
* ```typescript
|
|
68
|
-
* const valid = await verifyCheckpoint(checkpoint, gatewayPubKey);
|
|
69
|
-
* if (valid.ok && valid.value) {
|
|
70
|
-
* // Checkpoint is authentic - safe to use for staleness detection
|
|
71
|
-
* if (isCacheStale(localCache, checkpoint)) {
|
|
72
|
-
* // Refresh local cache
|
|
73
|
-
* }
|
|
74
|
-
* }
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
export async function verifyCheckpoint(checkpoint, gatewayPublicKey) {
|
|
78
|
-
// Validate checkpoint format
|
|
79
|
-
if (checkpoint.type !== 'DIDStateCheckpoint') {
|
|
80
|
-
return err('INVALID_FORMAT');
|
|
81
|
-
}
|
|
82
|
-
if (checkpoint.version !== '1.0') {
|
|
83
|
-
return err('INVALID_FORMAT');
|
|
84
|
-
}
|
|
85
|
-
if (!checkpoint.subject || !checkpoint.current_public_key) {
|
|
86
|
-
return err('INVALID_FORMAT');
|
|
87
|
-
}
|
|
88
|
-
if (typeof checkpoint.rotation_sequence !== 'number' || checkpoint.rotation_sequence < 0) {
|
|
89
|
-
return err('INVALID_FORMAT');
|
|
90
|
-
}
|
|
91
|
-
if (typeof checkpoint.timestamp !== 'number' || checkpoint.timestamp <= 0) {
|
|
92
|
-
return err('INVALID_TIMESTAMP');
|
|
93
|
-
}
|
|
94
|
-
if (checkpoint.checkpoint_signature_algorithm !== 'ML-DSA-65') {
|
|
95
|
-
return err('INVALID_FORMAT');
|
|
96
|
-
}
|
|
97
|
-
// Reconstruct canonical message
|
|
98
|
-
const message = `DIDStateCheckpoint||1.0||${checkpoint.subject}||${checkpoint.current_public_key}||${checkpoint.revoked}||${checkpoint.rotation_sequence}||${checkpoint.timestamp}`;
|
|
99
|
-
const messageBytes = new TextEncoder().encode(message);
|
|
100
|
-
// Decode signature
|
|
101
|
-
let signature;
|
|
102
|
-
try {
|
|
103
|
-
signature = Buffer.from(checkpoint.checkpoint_signature, 'base64');
|
|
104
|
-
}
|
|
105
|
-
catch {
|
|
106
|
-
return err('INVALID_SIGNATURE');
|
|
107
|
-
}
|
|
108
|
-
// Verify signature using gateway public key
|
|
109
|
-
const verifyResult = await verifyMlDsa65(gatewayPublicKey, signature, messageBytes);
|
|
110
|
-
if (!verifyResult.ok) {
|
|
111
|
-
return err('VERIFY_FAILED');
|
|
112
|
-
}
|
|
113
|
-
return ok(verifyResult.value);
|
|
114
|
-
}
|
|
115
|
-
/* ── Staleness Detection ── */
|
|
116
|
-
/**
|
|
117
|
-
* Detect if local cache is stale compared to gateway checkpoint.
|
|
118
|
-
*
|
|
119
|
-
* Cache is stale if:
|
|
120
|
-
* 1. Checkpoint rotation_sequence > local rotationSequence (key rotated)
|
|
121
|
-
* 2. Checkpoint revoked !== local revoked (revocation status changed)
|
|
122
|
-
* 3. Checkpoint public key !== local publicKey (state drift)
|
|
123
|
-
*
|
|
124
|
-
* @param localCache - Local cache entry for DID
|
|
125
|
-
* @param checkpoint - Verified checkpoint from gateway
|
|
126
|
-
* @returns true if cache needs refresh, false if cache is current
|
|
127
|
-
*
|
|
128
|
-
* @example
|
|
129
|
-
* ```typescript
|
|
130
|
-
* if (isCacheStale(localCache, checkpoint)) {
|
|
131
|
-
* // Local cache is outdated - fetch fresh state from gateway
|
|
132
|
-
* const freshState = await registry.getEntry(did);
|
|
133
|
-
* }
|
|
134
|
-
* ```
|
|
135
|
-
*/
|
|
136
|
-
export function isCacheStale(localCache, checkpoint) {
|
|
137
|
-
// Sequence number mismatch indicates key rotation
|
|
138
|
-
if (checkpoint.rotation_sequence > localCache.rotationSequence) {
|
|
139
|
-
return true;
|
|
140
|
-
}
|
|
141
|
-
// Revocation status changed
|
|
142
|
-
if (checkpoint.revoked !== localCache.revoked) {
|
|
143
|
-
return true;
|
|
144
|
-
}
|
|
145
|
-
// Public key mismatch indicates state drift
|
|
146
|
-
const checkpointPubKey = Buffer.from(checkpoint.current_public_key, 'base64');
|
|
147
|
-
if (!Buffer.from(localCache.publicKey).equals(checkpointPubKey)) {
|
|
148
|
-
return true;
|
|
149
|
-
}
|
|
150
|
-
return false;
|
|
151
|
-
}
|
|
152
|
-
/* ── Encoding/Decoding ── */
|
|
153
|
-
/**
|
|
154
|
-
* Encode checkpoint to JSON string for wire transport.
|
|
155
|
-
*
|
|
156
|
-
* @param checkpoint - Checkpoint to encode
|
|
157
|
-
* @returns JSON string
|
|
158
|
-
*/
|
|
159
|
-
export function encodeCheckpoint(checkpoint) {
|
|
160
|
-
return JSON.stringify(checkpoint);
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Decode checkpoint from JSON string.
|
|
164
|
-
*
|
|
165
|
-
* @param encoded - JSON string
|
|
166
|
-
* @returns Parsed checkpoint or error
|
|
167
|
-
*/
|
|
168
|
-
export function decodeCheckpoint(encoded) {
|
|
169
|
-
try {
|
|
170
|
-
const parsed = JSON.parse(encoded);
|
|
171
|
-
// Basic validation
|
|
172
|
-
if (parsed.type !== 'DIDStateCheckpoint') {
|
|
173
|
-
return err('INVALID_FORMAT');
|
|
174
|
-
}
|
|
175
|
-
if (parsed.version !== '1.0') {
|
|
176
|
-
return err('INVALID_FORMAT');
|
|
177
|
-
}
|
|
178
|
-
if (!parsed.subject || !parsed.current_public_key || !parsed.checkpoint_signature) {
|
|
179
|
-
return err('INVALID_FORMAT');
|
|
180
|
-
}
|
|
181
|
-
return ok(parsed);
|
|
182
|
-
}
|
|
183
|
-
catch {
|
|
184
|
-
return err('INVALID_FORMAT');
|
|
185
|
-
}
|
|
186
|
-
}
|
|
1
|
+
import{ok,err}from"./_deps/shared/index.js";import{signMlDsa65,verifyMlDsa65}from"./identity.js";export async function createCheckpoint(e,r,t,n,o){const i=Date.now(),c=Buffer.from(r).toString("base64"),u=`DIDStateCheckpoint||1.0||${e}||${c}||${t}||${n}||${i}`,a=(new TextEncoder).encode(u),s=await signMlDsa65(o,a);return s.ok?ok({type:"DIDStateCheckpoint",version:"1.0",subject:e,current_public_key:c,revoked:t,rotation_sequence:n,timestamp:i,checkpoint_signature_algorithm:"ML-DSA-65",checkpoint_signature:Buffer.from(s.value).toString("base64")}):err("SIGN_FAILED")}export async function verifyCheckpoint(e,r){if("DIDStateCheckpoint"!==e.type)return err("INVALID_FORMAT");if("1.0"!==e.version)return err("INVALID_FORMAT");if(!e.subject||!e.current_public_key)return err("INVALID_FORMAT");if("number"!=typeof e.rotation_sequence||e.rotation_sequence<0)return err("INVALID_FORMAT");if("number"!=typeof e.timestamp||e.timestamp<=0)return err("INVALID_TIMESTAMP");if("ML-DSA-65"!==e.checkpoint_signature_algorithm)return 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 o;try{o=Buffer.from(e.checkpoint_signature,"base64")}catch{return err("INVALID_SIGNATURE")}const i=await verifyMlDsa65(r,o,n);return i.ok?ok(i.value):err("VERIFY_FAILED")}export 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)}export function encodeCheckpoint(e){return JSON.stringify(e)}export function decodeCheckpoint(e){try{const r=JSON.parse(e);return"DIDStateCheckpoint"!==r.type||"1.0"!==r.version?err("INVALID_FORMAT"):r.subject&&r.current_public_key&&r.checkpoint_signature?ok(r):err("INVALID_FORMAT")}catch{return err("INVALID_FORMAT")}}
|