@private.me/xbind 1.3.0 → 2.3.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.
- 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 -275
- package/dist-standalone/_deps/shared/cjs/index.js +1 -138
- package/dist-standalone/_deps/shared/cjs/types.js +1 -90
- package/dist-standalone/_deps/shared/errors.js +1 -262
- package/dist-standalone/_deps/shared/index.js +1 -77
- package/dist-standalone/_deps/shared/types.js +1 -91
- 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 -541
- 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 -516
- 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 +66 -5
- package/share1.dat +0 -0
- package/dist-standalone/_deps/crypto/base64.d.ts +0 -29
- package/dist-standalone/_deps/crypto/base64.js +0 -209
- package/dist-standalone/_deps/crypto/cjs/base64.js +0 -103
- package/dist-standalone/_deps/crypto/cjs/errors.js +0 -119
- package/dist-standalone/_deps/crypto/cjs/hmac.js +0 -71
- package/dist-standalone/_deps/crypto/cjs/index.js +0 -86
- package/dist-standalone/_deps/crypto/cjs/padding.js +0 -57
- package/dist-standalone/_deps/crypto/cjs/share-header.js +0 -68
- package/dist-standalone/_deps/crypto/cjs/shares.js +0 -152
- package/dist-standalone/_deps/crypto/cjs/tlv.js +0 -199
- package/dist-standalone/_deps/crypto/cjs/uuid.js +0 -61
- package/dist-standalone/_deps/crypto/cjs/verify.js +0 -24
- package/dist-standalone/_deps/crypto/cjs/xorida.js +0 -221
- package/dist-standalone/_deps/crypto/errors.d.ts +0 -51
- package/dist-standalone/_deps/crypto/errors.js +0 -109
- package/dist-standalone/_deps/crypto/hmac.d.ts +0 -39
- package/dist-standalone/_deps/crypto/hmac.js +0 -66
- package/dist-standalone/_deps/crypto/index.d.ts +0 -20
- package/dist-standalone/_deps/crypto/index.js +0 -45
- package/dist-standalone/_deps/crypto/padding.d.ts +0 -19
- package/dist-standalone/_deps/crypto/padding.js +0 -53
- package/dist-standalone/_deps/crypto/share-header.d.ts +0 -44
- package/dist-standalone/_deps/crypto/share-header.js +0 -63
- package/dist-standalone/_deps/crypto/shares.d.ts +0 -27
- package/dist-standalone/_deps/crypto/shares.js +0 -148
- package/dist-standalone/_deps/crypto/tlv.d.ts +0 -26
- package/dist-standalone/_deps/crypto/tlv.js +0 -195
- package/dist-standalone/_deps/crypto/uuid.d.ts +0 -22
- package/dist-standalone/_deps/crypto/uuid.js +0 -56
- package/dist-standalone/_deps/crypto/verify.d.ts +0 -15
- package/dist-standalone/_deps/crypto/verify.js +0 -15
- package/dist-standalone/_deps/crypto/xorida.d.ts +0 -44
- package/dist-standalone/_deps/crypto/xorida.js +0 -215
- 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
|
@@ -1,76 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/* -- RedisNonceStore -- Cross-Node Replay Prevention -- */
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.RedisNonceStore = void 0;
|
|
5
|
-
/** Default TTL for nonce entries: 600 seconds (10 minutes). */
|
|
6
|
-
const DEFAULT_TTL_SECONDS = 600;
|
|
7
|
-
/** Default key prefix for Redis nonce keys. */
|
|
8
|
-
const DEFAULT_KEY_PREFIX = 'nonce:';
|
|
9
|
-
/**
|
|
10
|
-
* Redis-backed nonce store for multi-node deployments.
|
|
11
|
-
*
|
|
12
|
-
* Uses Redis SET NX with TTL for atomic, distributed nonce deduplication.
|
|
13
|
-
* Nonce expiry is handled by Redis TTL -- no manual cleanup needed.
|
|
14
|
-
* Zero npm dependencies: users provide their own RedisClient implementation.
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```typescript
|
|
18
|
-
* import { RedisNonceStore } from '@private.me/xbind';
|
|
19
|
-
* import Redis from 'ioredis';
|
|
20
|
-
*
|
|
21
|
-
* const redis = new Redis();
|
|
22
|
-
* const store = new RedisNonceStore({
|
|
23
|
-
* client: {
|
|
24
|
-
* setNX: (key, value, ttl) =>
|
|
25
|
-
* redis.set(key, value, 'EX', ttl, 'NX'),
|
|
26
|
-
* del: (key) => redis.del(key),
|
|
27
|
-
* quit: () => redis.quit(),
|
|
28
|
-
* },
|
|
29
|
-
* });
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
32
|
-
class RedisNonceStore {
|
|
33
|
-
client;
|
|
34
|
-
ttlSeconds;
|
|
35
|
-
keyPrefix;
|
|
36
|
-
constructor(opts) {
|
|
37
|
-
this.client = opts.client;
|
|
38
|
-
this.ttlSeconds = opts.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
39
|
-
this.keyPrefix = opts.keyPrefix ?? DEFAULT_KEY_PREFIX;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Check if a nonce is fresh and record it atomically via Redis SET NX.
|
|
43
|
-
*
|
|
44
|
-
* Uses Redis SET with NX (set-if-not-exists) and EX (TTL in seconds)
|
|
45
|
-
* for atomic, distributed deduplication. If the key already exists in
|
|
46
|
-
* any Redis-connected node, the nonce is rejected as a duplicate.
|
|
47
|
-
*
|
|
48
|
-
* @param nonce - The nonce string to check.
|
|
49
|
-
* @param senderDid - The DID of the sender.
|
|
50
|
-
* @returns true if the nonce is new (accepted), false if duplicate (rejected).
|
|
51
|
-
*/
|
|
52
|
-
async check(nonce, senderDid) {
|
|
53
|
-
const key = `${this.keyPrefix}${senderDid}:${nonce}`;
|
|
54
|
-
const result = await this.client.setNX(key, '1', this.ttlSeconds);
|
|
55
|
-
return result === 'OK';
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* No-op for Redis store -- TTL-based expiry is handled automatically.
|
|
59
|
-
*
|
|
60
|
-
* This method exists to satisfy the NonceStore interface. Redis keys
|
|
61
|
-
* expire based on the TTL set during setNX, so no manual cleanup is needed.
|
|
62
|
-
*/
|
|
63
|
-
cleanup() {
|
|
64
|
-
// No-op: Redis TTL handles expiry automatically
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Disconnect from Redis gracefully.
|
|
68
|
-
*
|
|
69
|
-
* Calls the underlying RedisClient quit() method to close the connection.
|
|
70
|
-
* After calling dispose(), the store should not be used.
|
|
71
|
-
*/
|
|
72
|
-
dispose() {
|
|
73
|
-
void this.client.quit();
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
exports.RedisNonceStore = RedisNonceStore;
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.RedisNonceStore=void 0;const DEFAULT_TTL_SECONDS=600,DEFAULT_KEY_PREFIX="nonce:";class RedisNonceStore{client;ttlSeconds;keyPrefix;constructor(e){this.client=e.client,this.ttlSeconds=e.ttlSeconds??600,this.keyPrefix=e.keyPrefix??"nonce:"}async check(e,t){const s=`${this.keyPrefix}${t}:${e}`;return"OK"===await this.client.setNX(s,"1",this.ttlSeconds)}cleanup(){}dispose(){this.client.quit()}}exports.RedisNonceStore=RedisNonceStore;
|
|
@@ -1,50 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Express middleware for protecting trust registry endpoints with bearer auth.
|
|
4
|
-
*
|
|
5
|
-
* GET/HEAD requests pass through (public reads). POST/PUT/DELETE require
|
|
6
|
-
* a valid Bearer token matching the configured admin token.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```ts
|
|
10
|
-
* import express from 'express';
|
|
11
|
-
* import { createRegistryAuthMiddleware } from '@private.me/xbind';
|
|
12
|
-
*
|
|
13
|
-
* const app = express();
|
|
14
|
-
* app.use('/registry', createRegistryAuthMiddleware(process.env.REGISTRY_ADMIN_TOKEN!));
|
|
15
|
-
* ```
|
|
16
|
-
*/
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.createRegistryAuthMiddleware = createRegistryAuthMiddleware;
|
|
19
|
-
/**
|
|
20
|
-
* Create an Express-compatible middleware that protects write operations
|
|
21
|
-
* on registry endpoints with bearer token authentication.
|
|
22
|
-
*
|
|
23
|
-
* GET and HEAD requests pass through without authentication.
|
|
24
|
-
* POST, PUT, and DELETE require `Authorization: Bearer <token>`.
|
|
25
|
-
*
|
|
26
|
-
* @param token - The admin token to validate against.
|
|
27
|
-
* @returns Express middleware function.
|
|
28
|
-
*/
|
|
29
|
-
function createRegistryAuthMiddleware(token) {
|
|
30
|
-
return (req, res, next) => {
|
|
31
|
-
const method = req.method.toUpperCase();
|
|
32
|
-
if (method === 'GET' || method === 'HEAD') {
|
|
33
|
-
next();
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
const authHeader = typeof req.headers['authorization'] === 'string'
|
|
37
|
-
? req.headers['authorization']
|
|
38
|
-
: undefined;
|
|
39
|
-
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
|
40
|
-
res.status(401).json({ error: 'UNAUTHORIZED' });
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
const provided = authHeader.slice('Bearer '.length);
|
|
44
|
-
if (provided !== token) {
|
|
45
|
-
res.status(401).json({ error: 'UNAUTHORIZED' });
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
next();
|
|
49
|
-
};
|
|
50
|
-
}
|
|
1
|
+
"use strict";function createRegistryAuthMiddleware(e){return(t,r,s)=>{const i=t.method.toUpperCase();if("GET"===i||"HEAD"===i)return void s();const o="string"==typeof t.headers.authorization?t.headers.authorization:void 0;if(!o||!o.startsWith("Bearer "))return void r.status(401).json({error:"UNAUTHORIZED"});o.slice(7)===e?s():r.status(401).json({error:"UNAUTHORIZED"})}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.createRegistryAuthMiddleware=createRegistryAuthMiddleware;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.RetryStrategy=exports.CircuitBreaker=exports.NoRetryStrategy=exports.FixedDelayStrategy=exports.LinearBackoffStrategy=exports.ExponentialBackoffStrategy=void 0,exports.executeWithRetry=executeWithRetry;const shared_1=require("../_deps/shared/index.js");class ExponentialBackoffStrategy{name="ExponentialBackoff";maxAttempts;initialDelayMs;maxDelayMs;multiplier;jitter;jitterFactor;retryableErrors;constructor(t={}){this.maxAttempts=t.maxAttempts??3,this.initialDelayMs=t.initialDelayMs??1e3,this.maxDelayMs=t.maxDelayMs??3e4,this.multiplier=t.multiplier??2,this.jitter=t.jitter??!0,this.jitterFactor=t.jitterFactor??.2,this.retryableErrors=t.retryableErrors?new Set(t.retryableErrors):new Set(["SEND_FAILED","NETWORK_ERROR","RECIPIENT_UNREACHABLE","TIMEOUT"])}shouldRetry(t){if(t.attempt>=this.maxAttempts)return{shouldRetry:!1,reason:`Maximum attempts (${this.maxAttempts}) exceeded`};if(!this.retryableErrors.has(t.error))return{shouldRetry:!1,reason:`Error type '${t.error}' is not retryable`};const e=this.initialDelayMs*Math.pow(this.multiplier,t.attempt),s=Math.min(e,this.maxDelayMs),r=this.jitter?this.applyJitter(s):s;return{shouldRetry:!0,delayMs:Math.round(r),reason:`Attempt ${t.attempt+1}/${this.maxAttempts}`}}applyJitter(t){const e=new Uint32Array(1);crypto.getRandomValues(e);return t+(2*(e[0]/4294967295)-1)*(t*this.jitterFactor)}}exports.ExponentialBackoffStrategy=ExponentialBackoffStrategy;class LinearBackoffStrategy{name="LinearBackoff";maxAttempts;delayIncrementMs;initialDelayMs;maxDelayMs;jitter;jitterFactor;retryableErrors;constructor(t={}){this.maxAttempts=t.maxAttempts??3,this.delayIncrementMs=t.delayIncrementMs??1e3,this.initialDelayMs=t.initialDelayMs??1e3,this.maxDelayMs=t.maxDelayMs??3e4,this.jitter=t.jitter??!0,this.jitterFactor=t.jitterFactor??.1,this.retryableErrors=t.retryableErrors?new Set(t.retryableErrors):new Set(["SEND_FAILED","NETWORK_ERROR","RECIPIENT_UNREACHABLE","TIMEOUT"])}shouldRetry(t){if(t.attempt>=this.maxAttempts)return{shouldRetry:!1,reason:`Maximum attempts (${this.maxAttempts}) exceeded`};if(!this.retryableErrors.has(t.error))return{shouldRetry:!1,reason:`Error type '${t.error}' is not retryable`};const e=this.initialDelayMs+t.attempt*this.delayIncrementMs,s=Math.min(e,this.maxDelayMs),r=this.jitter?this.applyJitter(s):s;return{shouldRetry:!0,delayMs:Math.round(r),reason:`Attempt ${t.attempt+1}/${this.maxAttempts}`}}applyJitter(t){const e=new Uint32Array(1);crypto.getRandomValues(e);return t+(2*(e[0]/4294967295)-1)*(t*this.jitterFactor)}}exports.LinearBackoffStrategy=LinearBackoffStrategy;class FixedDelayStrategy{name="FixedDelay";maxAttempts;delayMs;jitter;jitterFactor;retryableErrors;constructor(t={}){this.maxAttempts=t.maxAttempts??3,this.delayMs=t.delayMs??1e3,this.jitter=t.jitter??!1,this.jitterFactor=t.jitterFactor??.1,this.retryableErrors=t.retryableErrors?new Set(t.retryableErrors):new Set(["SEND_FAILED","NETWORK_ERROR","RECIPIENT_UNREACHABLE","TIMEOUT"])}shouldRetry(t){if(t.attempt>=this.maxAttempts)return{shouldRetry:!1,reason:`Maximum attempts (${this.maxAttempts}) exceeded`};if(!this.retryableErrors.has(t.error))return{shouldRetry:!1,reason:`Error type '${t.error}' is not retryable`};const e=this.jitter?this.applyJitter(this.delayMs):this.delayMs;return{shouldRetry:!0,delayMs:Math.round(e),reason:`Attempt ${t.attempt+1}/${this.maxAttempts}`}}applyJitter(t){const e=new Uint32Array(1);crypto.getRandomValues(e);return t+(2*(e[0]/4294967295)-1)*(t*this.jitterFactor)}}exports.FixedDelayStrategy=FixedDelayStrategy;class NoRetryStrategy{name="NoRetry";shouldRetry(t){return{shouldRetry:!1,reason:"No retry policy - fail immediately"}}}exports.NoRetryStrategy=NoRetryStrategy;class CircuitBreaker{state="CLOSED";consecutiveFailures=0;consecutiveSuccesses=0;openedAt;totalRequests=0;totalFailures=0;totalSuccesses=0;failureTimestamps=[];failureThreshold;resetTimeoutMs;successThreshold;windowMs;constructor(t={}){this.failureThreshold=t.failureThreshold??5,this.resetTimeoutMs=t.resetTimeoutMs??6e4,this.successThreshold=t.successThreshold??2,this.windowMs=t.windowMs??6e4}allowRequest(){const t=Date.now();return this.failureTimestamps=this.failureTimestamps.filter(e=>t-e<this.windowMs),"CLOSED"===this.state||("OPEN"!==this.state||!!(this.openedAt&&t-this.openedAt>=this.resetTimeoutMs)&&(this.state="HALF_OPEN",this.consecutiveSuccesses=0,!0))}recordSuccess(){this.totalRequests++,this.totalSuccesses++,this.consecutiveFailures=0,"HALF_OPEN"===this.state&&(this.consecutiveSuccesses++,this.consecutiveSuccesses>=this.successThreshold&&(this.state="CLOSED",this.consecutiveSuccesses=0,this.openedAt=void 0))}recordFailure(){this.totalRequests++,this.totalFailures++,this.consecutiveFailures++,this.consecutiveSuccesses=0;const t=Date.now();if(this.failureTimestamps.push(t),"CLOSED"===this.state||"HALF_OPEN"===this.state){this.failureTimestamps.filter(e=>t-e<this.windowMs).length>=this.failureThreshold&&(this.state="OPEN",this.openedAt=t)}}getStats(){return{state:this.state,consecutiveFailures:this.consecutiveFailures,consecutiveSuccesses:this.consecutiveSuccesses,openedAt:this.openedAt,totalRequests:this.totalRequests,totalFailures:this.totalFailures,totalSuccesses:this.totalSuccesses}}reset(){this.state="CLOSED",this.consecutiveFailures=0,this.consecutiveSuccesses=0,this.openedAt=void 0,this.totalRequests=0,this.totalFailures=0,this.totalSuccesses=0,this.failureTimestamps=[]}forceOpen(){this.state="OPEN",this.openedAt=Date.now()}forceClose(){this.state="CLOSED",this.consecutiveFailures=0,this.consecutiveSuccesses=0,this.openedAt=void 0}}exports.CircuitBreaker=CircuitBreaker;class RetryStrategy{static exponentialBackoff(t){return new ExponentialBackoffStrategy(t)}static linearBackoff(t){return new LinearBackoffStrategy(t)}static fixedDelay(t){return new FixedDelayStrategy(t)}static noRetry(){return new NoRetryStrategy}static aggressive(){return new ExponentialBackoffStrategy({maxAttempts:5,initialDelayMs:500,maxDelayMs:1e4,multiplier:2,jitter:!0})}static conservative(){return new LinearBackoffStrategy({maxAttempts:2,initialDelayMs:2e3,delayIncrementMs:1e3,maxDelayMs:5e3,jitter:!0})}static default(){return new ExponentialBackoffStrategy({maxAttempts:3,initialDelayMs:1e3,maxDelayMs:3e4,multiplier:2,jitter:!0})}}async function executeWithRetry(t,e,s){const r=Date.now();let a=0,i="NETWORK_ERROR";for(;;){if(s&&!s.allowRequest())return(0,shared_1.err)("SEND_FAILED");const o=await t();if(o.ok)return s?.recordSuccess(),o;i=o.error,s?.recordFailure();const l={attempt:a,error:i,startTime:r,elapsedMs:Date.now()-r},n=e.shouldRetry(l);if(!n.shouldRetry)return(0,shared_1.err)(i);n.delayMs&&n.delayMs>0&&await sleep(n.delayMs),a++}}function sleep(t){return new Promise(e=>setTimeout(e,t))}exports.RetryStrategy=RetryStrategy;
|
|
@@ -1,102 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RetryTransportAdapter = void 0;
|
|
4
|
-
/* ── Implementation ── */
|
|
5
|
-
/**
|
|
6
|
-
* Decorator that adds exponential backoff retry logic to any transport adapter.
|
|
7
|
-
*
|
|
8
|
-
* Retry delays follow exponential backoff with jitter:
|
|
9
|
-
* - Formula: 2^attempt * baseDelay + jitter
|
|
10
|
-
* - Jitter: Math.random() * maxJitter * 2 - maxJitter
|
|
11
|
-
* - Default delays: 1s, 2s, 4s (with ±200ms jitter)
|
|
12
|
-
*
|
|
13
|
-
* Use case: Push notification delivery failures requiring automatic retry.
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```typescript
|
|
17
|
-
* const transport = new RetryTransportAdapter(baseTransport, {
|
|
18
|
-
* maxRetries: 3,
|
|
19
|
-
* baseDelayMs: 1000,
|
|
20
|
-
* maxJitterMs: 200
|
|
21
|
-
* });
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
class RetryTransportAdapter {
|
|
25
|
-
inner;
|
|
26
|
-
maxRetries;
|
|
27
|
-
baseDelayMs;
|
|
28
|
-
maxJitterMs;
|
|
29
|
-
/**
|
|
30
|
-
* Create a new RetryTransportAdapter wrapping an existing transport.
|
|
31
|
-
*
|
|
32
|
-
* @param inner - The transport adapter to wrap with retry logic
|
|
33
|
-
* @param options - Retry configuration options
|
|
34
|
-
*/
|
|
35
|
-
constructor(inner, options = {}) {
|
|
36
|
-
this.inner = inner;
|
|
37
|
-
this.maxRetries = options.maxRetries ?? 3;
|
|
38
|
-
this.baseDelayMs = options.baseDelayMs ?? 1000;
|
|
39
|
-
this.maxJitterMs = options.maxJitterMs ?? 200;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Send an envelope with exponential backoff retry logic.
|
|
43
|
-
*
|
|
44
|
-
* Retries on all error types (SEND_FAILED, NETWORK_ERROR, RECIPIENT_UNREACHABLE, TIMEOUT).
|
|
45
|
-
* Throws error after all retries are exhausted.
|
|
46
|
-
*
|
|
47
|
-
* @param envelope - The envelope to send
|
|
48
|
-
* @param recipientDid - The recipient's DID
|
|
49
|
-
* @returns Result with void on success, or TransportError on failure
|
|
50
|
-
* @throws Error if all retry attempts are exhausted
|
|
51
|
-
*/
|
|
52
|
-
async send(envelope, recipientDid) {
|
|
53
|
-
let lastError;
|
|
54
|
-
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
55
|
-
const result = await this.inner.send(envelope, recipientDid);
|
|
56
|
-
// Success - return immediately
|
|
57
|
-
if (result.ok) {
|
|
58
|
-
return result;
|
|
59
|
-
}
|
|
60
|
-
// Store error for final throw
|
|
61
|
-
lastError = result.error;
|
|
62
|
-
// Don't delay after final attempt
|
|
63
|
-
if (attempt < this.maxRetries) {
|
|
64
|
-
// Exponential backoff: 2^attempt * baseDelay + jitter
|
|
65
|
-
const delay = Math.pow(2, attempt) * this.baseDelayMs;
|
|
66
|
-
// SAFETY: Using crypto.getRandomValues for OWASP-compliant secure random jitter
|
|
67
|
-
const jitterArray = new Uint32Array(1);
|
|
68
|
-
crypto.getRandomValues(jitterArray);
|
|
69
|
-
const jitter = (jitterArray[0] / 0xffffffff) * this.maxJitterMs * 2 -
|
|
70
|
-
this.maxJitterMs;
|
|
71
|
-
await this.sleep(delay + jitter);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
// All retries exhausted - throw error with clear message
|
|
75
|
-
throw new Error(`Failed after ${this.maxRetries} retries: ${lastError ?? 'unknown error'}`);
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Register a handler for incoming envelopes.
|
|
79
|
-
* Delegates directly to the inner transport.
|
|
80
|
-
*
|
|
81
|
-
* @param handler - The envelope handler function
|
|
82
|
-
*/
|
|
83
|
-
onReceive(handler) {
|
|
84
|
-
this.inner.onReceive(handler);
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Shut down the transport.
|
|
88
|
-
* Delegates directly to the inner transport.
|
|
89
|
-
*/
|
|
90
|
-
dispose() {
|
|
91
|
-
this.inner.dispose();
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Sleep for a specified duration.
|
|
95
|
-
*
|
|
96
|
-
* @param ms - Duration in milliseconds
|
|
97
|
-
*/
|
|
98
|
-
sleep(ms) {
|
|
99
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
exports.RetryTransportAdapter = RetryTransportAdapter;
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.RetryTransportAdapter=void 0;class RetryTransportAdapter{inner;maxRetries;baseDelayMs;maxJitterMs;constructor(e,t={}){this.inner=e,this.maxRetries=t.maxRetries??3,this.baseDelayMs=t.baseDelayMs??1e3,this.maxJitterMs=t.maxJitterMs??200}async send(e,t){let r;for(let s=0;s<=this.maxRetries;s++){const i=await this.inner.send(e,t);if(i.ok)return i;if(r=i.error,s<this.maxRetries){const e=Math.pow(2,s)*this.baseDelayMs,t=new Uint32Array(1);crypto.getRandomValues(t);const r=t[0]/4294967295*this.maxJitterMs*2-this.maxJitterMs;await this.sleep(e+r)}}throw new Error(`Failed after ${this.maxRetries} retries: ${r??"unknown error"}`)}onReceive(e){this.inner.onReceive(e)}dispose(){this.inner.dispose()}sleep(e){return new Promise(t=>setTimeout(t,e))}}exports.RetryTransportAdapter=RetryTransportAdapter;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.DEFAULT_SERVICE_WORKER_CONFIG=exports.MemoryStorageAdapter=exports.IndexedDBAdapter=exports.LocalStorageAdapter=void 0,exports.detectRuntime=detectRuntime,exports.isBrowser=isBrowser,exports.isNode=isNode,exports.isServiceWorker=isServiceWorker,exports.getRandomBytes=getRandomBytes,exports.generateUUID=generateUUID,exports.isWasmSupported=isWasmSupported,exports.loadWasmModule=loadWasmModule,exports.detectCapabilities=detectCapabilities,exports.installNodePolyfills=installNodePolyfills,exports.initServiceWorker=initServiceWorker;const shared_1=require("../../_deps/shared/index.js");function detectRuntime(){return"undefined"!=typeof self&&"ServiceWorkerGlobalScope"in self?"service-worker":"undefined"!=typeof self&&"WorkerGlobalScope"in self&&"importScripts"in self?"web-worker":"undefined"!=typeof window&&"undefined"!=typeof document?"browser":"undefined"!=typeof process&&process.versions&&process.versions.node?"node":"unknown"}function isBrowser(){const e=detectRuntime();return"browser"===e||"service-worker"===e||"web-worker"===e}function isNode(){return"node"===detectRuntime()}function isServiceWorker(){return"service-worker"===detectRuntime()}function getRandomBytes(e){if("undefined"==typeof crypto||!crypto.getRandomValues)throw new Error("Web Crypto API not available - secure random generation impossible");const t=new Uint8Array(e);return crypto.getRandomValues(t),t}function generateUUID(){if("undefined"!=typeof crypto&&crypto.randomUUID)return crypto.randomUUID();const e=getRandomBytes(16),t=e[6],r=e[8];void 0!==t&&(e[6]=15&t|64),void 0!==r&&(e[8]=63&r|128);const o=Array.from(e).map(e=>e.toString(16).padStart(2,"0")).join("");return[o.slice(0,8),o.slice(8,12),o.slice(12,16),o.slice(16,20),o.slice(20,32)].join("-")}class LocalStorageAdapter{prefix;constructor(e="xbind:"){if(this.prefix=e,"undefined"==typeof localStorage)throw new Error("localStorage not available in this environment")}async setItem(e,t){const r=this.prefix+e,o=JSON.stringify(t);localStorage.setItem(r,o)}async getItem(e){const t=this.prefix+e,r=localStorage.getItem(t);if(null===r)return null;try{return JSON.parse(r)}catch{return null}}async removeItem(e){const t=this.prefix+e;localStorage.removeItem(t)}async clear(){Object.keys(localStorage).filter(e=>e.startsWith(this.prefix)).forEach(e=>localStorage.removeItem(e))}}exports.LocalStorageAdapter=LocalStorageAdapter;class IndexedDBAdapter{dbName;storeName;version;db=null;constructor(e="xbind-storage",t="keyval",r=1){this.dbName=e,this.storeName=t,this.version=r}async ensureDB(){return this.db?this.db:new Promise((e,t)=>{const r=indexedDB.open(this.dbName,this.version);r.onerror=()=>t(r.error),r.onsuccess=()=>{this.db=r.result,e(r.result)},r.onupgradeneeded=e=>{const t=e.target.result;t.objectStoreNames.contains(this.storeName)||t.createObjectStore(this.storeName)}})}async setItem(e,t){const r=(await this.ensureDB()).transaction(this.storeName,"readwrite").objectStore(this.storeName);return new Promise((o,s)=>{const n=r.put(t,e);n.onerror=()=>s(n.error),n.onsuccess=()=>o()})}async getItem(e){const t=(await this.ensureDB()).transaction(this.storeName,"readonly").objectStore(this.storeName);return new Promise((r,o)=>{const s=t.get(e);s.onerror=()=>o(s.error),s.onsuccess=()=>{const e=s.result;r(void 0===e?null:e)}})}async removeItem(e){const t=(await this.ensureDB()).transaction(this.storeName,"readwrite").objectStore(this.storeName);return new Promise((r,o)=>{const s=t.delete(e);s.onerror=()=>o(s.error),s.onsuccess=()=>r()})}async clear(){const e=(await this.ensureDB()).transaction(this.storeName,"readwrite").objectStore(this.storeName);return new Promise((t,r)=>{const o=e.clear();o.onerror=()=>r(o.error),o.onsuccess=()=>t()})}close(){this.db&&(this.db.close(),this.db=null)}}exports.IndexedDBAdapter=IndexedDBAdapter;class MemoryStorageAdapter{store=new Map;async setItem(e,t){this.store.set(e,t)}async getItem(e){const t=this.store.get(e);return void 0===t?null:t}async removeItem(e){this.store.delete(e)}async clear(){this.store.clear()}}function isWasmSupported(){try{if("undefined"==typeof WebAssembly)return!1;const e=new WebAssembly.Module(new Uint8Array([0,97,115,109,1,0,0,0]));if(!(e instanceof WebAssembly.Module))return!1;return new WebAssembly.Instance(e)instanceof WebAssembly.Instance}catch{return!1}}async function loadWasmModule(e,t){if(!isWasmSupported())return(0,shared_1.err)("WASM_NOT_SUPPORTED");try{if(void 0!==WebAssembly.instantiateStreaming){const r=await fetch(e),o=await WebAssembly.instantiateStreaming(r,t);return(0,shared_1.ok)(o.instance)}const r=await fetch(e),o=await r.arrayBuffer(),s=await WebAssembly.instantiate(o,t);return(0,shared_1.ok)(s.instance)}catch(e){return console.error("WASM load failed:",e),(0,shared_1.err)("WASM_LOAD_FAILED")}}async function detectCapabilities(){const e={webCrypto:"undefined"!=typeof crypto&&!!crypto.subtle,subtleCrypto:"undefined"!=typeof crypto&&!!crypto.subtle,ed25519:!1,x25519:!1,wasm:isWasmSupported(),indexedDB:"undefined"!=typeof indexedDB,localStorage:"undefined"!=typeof localStorage,serviceWorker:"undefined"!=typeof navigator&&"serviceWorker"in navigator,webWorker:"undefined"!=typeof Worker,fetch:"undefined"!=typeof fetch,textEncoding:"undefined"!=typeof TextEncoder&&"undefined"!=typeof TextDecoder};if(e.subtleCrypto)try{await crypto.subtle.generateKey({name:"Ed25519"},!0,["sign","verify"]),e.ed25519=!0}catch{e.ed25519=!1}if(e.subtleCrypto)try{await crypto.subtle.generateKey({name:"X25519"},!0,["deriveBits"]),e.x25519=!0}catch{e.x25519=!1}return e}function installNodePolyfills(){isBrowser()&&(void 0===globalThis.process&&(globalThis.process={env:{},versions:{},nextTick:e=>Promise.resolve().then(e)}),void 0===globalThis.Buffer&&(globalThis.Buffer={from:(e,t)=>{if(e instanceof Uint8Array)return e;if("base64"===t){const t=atob(e);return new Uint8Array(t.split("").map(e=>e.charCodeAt(0)))}return(new TextEncoder).encode(e)},alloc:e=>new Uint8Array(e)}),void 0===globalThis.global&&(globalThis.global=globalThis))}function initServiceWorker(e={}){const t={...exports.DEFAULT_SERVICE_WORKER_CONFIG,...e};if(!isServiceWorker())throw new Error("initServiceWorker() must be called from service worker context");self.__xbind_sw_config=t,console.log("[xBind] Service worker initialized with config:",t)}exports.MemoryStorageAdapter=MemoryStorageAdapter,exports.DEFAULT_SERVICE_WORKER_CONFIG={wasmCacheStrategy:"cache-first",wasmCacheMaxAge:864e5,enableBackgroundSync:!0};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.EdgeTransportAdapter=exports.KVTrustRegistry=exports.KVNonceStore=exports.DenoKVAdapter=exports.VercelKVAdapter=exports.CloudflareKVAdapter=void 0,exports.detectRuntime=detectRuntime,exports.isEdgeRuntime=isEdgeRuntime,exports.validateEdgeRuntime=validateEdgeRuntime,exports.createEdgeAgent=createEdgeAgent,exports.checkBundleSize=checkBundleSize,exports.getOptimizationTips=getOptimizationTips;const shared_1=require("../../_deps/shared/index.js");function detectRuntime(){const e=globalThis;return void 0!==e.caches&&"string"==typeof e.EdgeRuntime?"cloudflare":"string"==typeof e.EdgeRuntime&&"undefined"!=typeof process&&"1"===process.env?.VERCEL?"vercel":void 0!==e.Deno?"deno":"undefined"!=typeof process&&"string"==typeof process.versions?.node?"node":"unknown"}function isEdgeRuntime(){const e=detectRuntime();return"cloudflare"===e||"vercel"===e||"deno"===e}function validateEdgeRuntime(){if(void 0===globalThis.crypto)return(0,shared_1.err)("Missing globalThis.crypto");if(void 0===globalThis.crypto.subtle)return(0,shared_1.err)("Missing crypto.subtle");if("function"!=typeof globalThis.crypto.getRandomValues)return(0,shared_1.err)("Missing crypto.getRandomValues");const e=["generateKey","sign","verify","encrypt","decrypt","deriveBits","importKey","exportKey"];for(const t of e)if("function"!=typeof globalThis.crypto.subtle[t])return(0,shared_1.err)(`Missing crypto.subtle.${t}`);return void 0===globalThis.TextEncoder?(0,shared_1.err)("Missing TextEncoder"):void 0===globalThis.TextDecoder?(0,shared_1.err)("Missing TextDecoder"):"function"!=typeof globalThis.fetch?(0,shared_1.err)("Missing fetch API"):(0,shared_1.ok)(void 0)}class CloudflareKVAdapter{namespace;constructor(e){this.namespace=e}async get(e){return await this.namespace.get(e)}async put(e,t,r){const s=r?{expirationTtl:r}:void 0;await this.namespace.put(e,t,s)}async delete(e){await this.namespace.delete(e)}async list(e,t){return(await this.namespace.list({prefix:e,limit:t})).keys.map(e=>e.name)}}exports.CloudflareKVAdapter=CloudflareKVAdapter;class VercelKVAdapter{client;constructor(e){this.client=e}async get(e){return await this.client.get(e)}async put(e,t,r){const s=r?{ex:r}:void 0;await this.client.set(e,t,s)}async delete(e){await this.client.del(e)}async list(e,t){const r=e?`${e}*`:"*",s=await this.client.keys(r);return t?s.slice(0,t):s}}exports.VercelKVAdapter=VercelKVAdapter;class DenoKVAdapter{kv;constructor(e){this.kv=e}async get(e){return(await this.kv.get([e])).value}async put(e,t,r){const s=r?{expireIn:1e3*r}:void 0;await this.kv.set([e],t,s)}async delete(e){await this.kv.delete([e])}async list(e,t){const r={prefix:e?[e]:[]},s=[];for await(const e of this.kv.list(r))if(s.push(e.key.join("/")),t&&s.length>=t)break;return s}}exports.DenoKVAdapter=DenoKVAdapter;class KVNonceStore{kv;ttlSeconds;constructor(e,t=6e5){this.kv=e,this.ttlSeconds=Math.floor(t/1e3)}buildKey(e,t,r){const s=`xbind:nonce:${t}:${e}`;if(!r)return s;return`${s}:${r.shareGroupId??""}:${void 0!==r.shareIndex?String(r.shareIndex):""}`}async check(e,t,r){const s=this.buildKey(e,t,r);return null===await this.kv.get(s)&&(await this.kv.put(s,Date.now().toString(),this.ttlSeconds),!0)}cleanup(){}dispose(){}}exports.KVNonceStore=KVNonceStore;class KVTrustRegistry{kv;constructor(e){this.kv=e}buildKey(e){return`xbind:trust:${e}`}async register(e,t,r,s,i,n,o,a,c,d,l,u,p){const h=this.buildKey(e),y=e=>btoa(String.fromCharCode(...Array.from(e))),g={did:e,publicKey:y(t),name:r,scopes:s??[],x25519PublicKey:i?y(i):void 0,mlKemPublicKey:n?y(n):void 0,mlDsaPublicKey:o?y(o):void 0,xchange:a??!1,receiveScopes:c??[],sdkVersion:d,minEnvelopeVersion:l,maxEnvelopeVersion:u,registeredAt:Date.now(),rotation_sequence:0};try{const e=p?Math.floor(p/1e3):void 0;return await this.kv.put(h,JSON.stringify(g),e),(0,shared_1.ok)(void 0)}catch(e){return(0,shared_1.err)("NETWORK_ERROR")}}async resolve(e){const t=this.buildKey(e);try{const e=await this.kv.get(t);if(null===e)return(0,shared_1.err)("NOT_FOUND");const r=JSON.parse(e),s=e=>Uint8Array.from(atob(e),e=>e.charCodeAt(0));return(0,shared_1.ok)(s(r.publicKey))}catch(e){return(0,shared_1.err)("NETWORK_ERROR")}}async hasScope(e,t){const r=this.buildKey(e);try{const e=await this.kv.get(r);if(null===e)return!1;const s=JSON.parse(e);return s.scopes?.includes(t)??!1}catch{return!1}}async hasReceiveScope(e,t){const r=this.buildKey(e);try{const e=await this.kv.get(r);if(null===e)return!1;const s=JSON.parse(e);return s.receiveScopes?.includes(t)??!1}catch{return!1}}async revoke(e){const t=this.buildKey(e);try{return await this.kv.delete(t),(0,shared_1.ok)(void 0)}catch(e){return(0,shared_1.err)("NETWORK_ERROR")}}async list(){try{return(await this.kv.list("xbind:trust:",1e3)).map(e=>e.replace("xbind:trust:",""))}catch{return[]}}async getEntry(e){const t=this.buildKey(e);try{const e=await this.kv.get(t);if(null===e)return(0,shared_1.err)("NOT_FOUND");const r=JSON.parse(e),s=e=>Uint8Array.from(atob(e),e=>e.charCodeAt(0)),i={did:r.did,publicKey:s(r.publicKey),name:r.name,scopes:new Set(r.scopes),receiveScopes:r.receiveScopes?new Set(r.receiveScopes):void 0,revoked:!1,x25519PublicKey:r.x25519PublicKey?s(r.x25519PublicKey):void 0,mlKemPublicKey:r.mlKemPublicKey?s(r.mlKemPublicKey):void 0,mlDsaPublicKey:r.mlDsaPublicKey?s(r.mlDsaPublicKey):void 0,xchange:r.xchange,rotation_sequence:r.rotation_sequence,sdkVersion:r.sdkVersion,minEnvelopeVersion:r.minEnvelopeVersion,maxEnvelopeVersion:r.maxEnvelopeVersion};return(0,shared_1.ok)(i)}catch(e){return(0,shared_1.err)("NETWORK_ERROR")}}async getFullEntry(e){const t=this.buildKey(e);try{const e=await this.kv.get(t);if(null===e)return(0,shared_1.err)("NOT_FOUND");const r=JSON.parse(e);return(0,shared_1.ok)(r)}catch(e){return(0,shared_1.err)("NETWORK_ERROR")}}dispose(){}}exports.KVTrustRegistry=KVTrustRegistry;class EdgeTransportAdapter{baseUrl;timeoutMs;handlers=[];constructor(e){this.baseUrl=e.baseUrl.replace(/\/$/,""),this.timeoutMs=e.timeoutMs??1e4}async send(e,t){const r=`${this.baseUrl}/deliver/${encodeURIComponent(t)}`;try{const t=new AbortController,s=setTimeout(()=>t.abort(),this.timeoutMs),i=await globalThis.fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),signal:t.signal});return clearTimeout(s),i.ok?(0,shared_1.ok)(void 0):(0,shared_1.err)(404===i.status?"RECIPIENT_UNREACHABLE":"SEND_FAILED")}catch(e){return e instanceof DOMException&&"AbortError"===e.name?(0,shared_1.err)("TIMEOUT"):(0,shared_1.err)("NETWORK_ERROR")}}onReceive(e){this.handlers.push(e)}dispatch(e){for(const t of this.handlers)t(e)}dispose(){this.handlers=[]}}function createEdgeAgent(e){return{nonceStore:new KVNonceStore(e.kv,e.nonceTtlMs),trustRegistry:new KVTrustRegistry(e.kv),transport:new EdgeTransportAdapter({baseUrl:e.baseUrl,timeoutMs:e.timeoutMs})}}function checkBundleSize(e){const t=1048576;if(e>t){const t=(e/1024/1024).toFixed(2),r=1..toFixed(2);return(0,shared_1.err)(`Bundle size ${t}MB exceeds edge runtime limit of ${r}MB. Consider using tree-shaking or dynamic imports.`)}return(0,shared_1.ok)(void 0)}function getOptimizationTips(){return["1. Use tree-shaking: Import only required functions","2. Enable minification in bundler config","3. Use dynamic imports for large dependencies (mlkem, mldsa)","4. Exclude Node.js polyfills (crypto, fs, process)","5. Use Brotli compression for Cloudflare Workers","6. Consider splitting post-quantum crypto into separate bundle","7. Use KV storage instead of in-memory caches"]}exports.EdgeTransportAdapter=EdgeTransportAdapter;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.BufferPolyfill=exports.AsyncStorageAdapter=void 0,exports.detectCrypto=detectCrypto,exports.getRandomBytes=getRandomBytes,exports.sha256=sha256,exports.isReactNative=isReactNative,exports.detectPlatform=detectPlatform,exports.initializeReactNative=initializeReactNative;const shared_1=require("../../_deps/shared/index.js");class AsyncStorageAdapter{storage;prefix;debug;constructor(t){this.storage=t.storage,this.prefix=t.storagePrefix||"@xbind:",this.debug=t.debug||!1}async get(t){try{const e=this.prefix+t,r=await this.storage.getItem(e);return this.debug&&console.log(`[AsyncStorage] GET ${e}:`,r?"found":"not found"),(0,shared_1.ok)(r)}catch(t){return(0,shared_1.err)(new Error(`AsyncStorage get failed: ${t}`))}}async set(t,e){try{const r=this.prefix+t;return await this.storage.setItem(r,e),this.debug&&console.log(`[AsyncStorage] SET ${r}:`,e.length,"bytes"),(0,shared_1.ok)(void 0)}catch(t){return(0,shared_1.err)(new Error(`AsyncStorage set failed: ${t}`))}}async remove(t){try{const e=this.prefix+t;return await this.storage.removeItem(e),this.debug&&console.log(`[AsyncStorage] REMOVE ${e}`),(0,shared_1.ok)(void 0)}catch(t){return(0,shared_1.err)(new Error(`AsyncStorage remove failed: ${t}`))}}async keys(){try{const t=(await this.storage.getAllKeys()).filter(t=>t.startsWith(this.prefix)).map(t=>t.substring(this.prefix.length));return this.debug&&console.log("[AsyncStorage] KEYS:",t.length,"items"),(0,shared_1.ok)(t)}catch(t){return(0,shared_1.err)(new Error(`AsyncStorage keys failed: ${t}`))}}async multiGet(t){try{const e=t.map(t=>this.prefix+t),r=(await this.storage.multiGet(e)).map(([t,e])=>[t.substring(this.prefix.length),e]);return this.debug&&console.log("[AsyncStorage] MULTI_GET:",t.length,"keys"),(0,shared_1.ok)(r)}catch(t){return(0,shared_1.err)(new Error(`AsyncStorage multiGet failed: ${t}`))}}async multiSet(t){try{const e=t.map(([t,e])=>[this.prefix+t,e]);return await this.storage.multiSet(e),this.debug&&console.log("[AsyncStorage] MULTI_SET:",t.length,"pairs"),(0,shared_1.ok)(void 0)}catch(t){return(0,shared_1.err)(new Error(`AsyncStorage multiSet failed: ${t}`))}}async clear(){try{const t=await this.keys();if(!t.ok)return(0,shared_1.err)(t.error);const e=t.value.map(t=>this.prefix+t);return e.length>0&&await this.storage.multiRemove(e),this.debug&&console.log("[AsyncStorage] CLEAR:",e.length,"items removed"),(0,shared_1.ok)(void 0)}catch(t){return(0,shared_1.err)(new Error(`AsyncStorage clear failed: ${t}`))}}}function detectCrypto(){if("undefined"!=typeof global&&global.crypto)return global.crypto;try{return require("react-native-quick-crypto")}catch{}try{const t=require("expo-crypto");return{getRandomValues:e=>{const r=t.getRandomBytes(e.length);e.set(r)}}}catch{}return null}function getRandomBytes(t,e){const r=e||detectCrypto();if(!r)throw new Error("No crypto implementation available. Install react-native-quick-crypto or expo-crypto.");const o=new Uint8Array(t);return r.getRandomValues(o),o}async function sha256(t,e){const r=e||detectCrypto();if(!r?.subtle)throw new Error("No SubtleCrypto implementation available. Install react-native-quick-crypto.");const o=new Uint8Array(t).buffer,a=await r.subtle.digest("SHA-256",o);return new Uint8Array(a)}exports.AsyncStorageAdapter=AsyncStorageAdapter;class BufferPolyfill{static isBuffer(t){return t instanceof Uint8Array}static from(t,e){if("string"==typeof t){if("base64"===e)return this.fromBase64(t);if("hex"===e)return this.fromHex(t);return(new TextEncoder).encode(t)}return Array.isArray(t),new Uint8Array(t)}static toString(t,e){if("base64"===e)return this.toBase64(t);if("hex"===e)return this.toHex(t);return(new TextDecoder).decode(t)}static concat(t){const e=t.reduce((t,e)=>t+e.length,0),r=new Uint8Array(e);let o=0;for(const e of t)r.set(e,o),o+=e.length;return r}static alloc(t,e){const r=new Uint8Array(t);return void 0!==e&&r.fill(e),r}static fromBase64(t){const e=atob(t),r=new Uint8Array(e.length);for(let t=0;t<e.length;t++)r[t]=e.charCodeAt(t);return r}static toBase64(t){let e="";for(let r=0;r<t.length;r++){const o=t[r];void 0!==o&&(e+=String.fromCharCode(o))}return btoa(e)}static fromHex(t){const e=new Uint8Array(t.length/2);for(let r=0;r<e.length;r++)e[r]=parseInt(t.substr(2*r,2),16);return e}static toHex(t){return Array.from(t).map(t=>t.toString(16).padStart(2,"0")).join("")}}function isReactNative(){return"undefined"!=typeof navigator&&"ReactNative"===navigator.product}function detectPlatform(){if("undefined"==typeof navigator)return"unknown";const t=navigator.userAgent||"";return/iPhone|iPad|iPod/.test(t)?"ios":/Android/.test(t)?"android":"unknown"}function initializeReactNative(t){try{if(!t.storage)return(0,shared_1.err)(new Error("AsyncStorage is required for React Native runtime"));const e=t.crypto||detectCrypto();return e?(global.crypto||(global.crypto=e),global.Buffer||(global.Buffer=BufferPolyfill),t.debug&&console.log("[xBind] React Native runtime initialized:",{platform:detectPlatform(),crypto:e.subtle?"full":"basic",storage:"AsyncStorage",prefix:t.storagePrefix||"@xbind:"}),(0,shared_1.ok)(void 0)):(0,shared_1.err)(new Error("No crypto implementation found. Install react-native-quick-crypto or expo-crypto."))}catch(t){return(0,shared_1.err)(new Error(`React Native initialization failed: ${t}`))}}exports.BufferPolyfill=BufferPolyfill,exports.default={AsyncStorageAdapter:AsyncStorageAdapter,detectCrypto:detectCrypto,getRandomBytes:getRandomBytes,sha256:sha256,BufferPolyfill:BufferPolyfill,isReactNative:isReactNative,detectPlatform:detectPlatform,initializeReactNative:initializeReactNative};
|
|
@@ -1,245 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Security policy interface for automatic risk-based Xorida activation.
|
|
4
|
-
*
|
|
5
|
-
* Determines when to apply information-theoretic security (XorIDA split-channel)
|
|
6
|
-
* vs standard encrypted transport based on action semantics and parameters.
|
|
7
|
-
*
|
|
8
|
-
* Design principle: Security should be invisible to users. The policy classifies
|
|
9
|
-
* risk automatically so developers don't need to understand threshold cryptography.
|
|
10
|
-
*/
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.DefaultSecurityPolicy = void 0;
|
|
13
|
-
exports.describeSecurityMode = describeSecurityMode;
|
|
14
|
-
exports.describeSecurityModeStructured = describeSecurityModeStructured;
|
|
15
|
-
/**
|
|
16
|
-
* Default security policy for basic XBind.
|
|
17
|
-
*
|
|
18
|
-
* Rules:
|
|
19
|
-
* - Explicit risk tags: low → 2-of-2, medium → 2-of-3, high/critical → 3-of-5
|
|
20
|
-
* - Fiat transfers: USD/EUR/GBP >$100k → 2-of-3, >$1M → 3-of-5
|
|
21
|
-
* - Crypto transfers: Require explicit risk tag (no numeric auto-detection)
|
|
22
|
-
* - Sensitive scopes: custody/admin/settlement → 2-of-3
|
|
23
|
-
* - Cross-entity communication: 2-of-3
|
|
24
|
-
* - Explicit 'high' override: 2-of-3, 'critical' override: 3-of-5
|
|
25
|
-
* - Everything else: Standard encrypted transport (V3 hybrid PQ)
|
|
26
|
-
*
|
|
27
|
-
* Enterprise and Government variants extend this with custom rules.
|
|
28
|
-
*/
|
|
29
|
-
class DefaultSecurityPolicy {
|
|
30
|
-
options;
|
|
31
|
-
/**
|
|
32
|
-
* Create a default security policy.
|
|
33
|
-
*
|
|
34
|
-
* @param options - Optional configuration
|
|
35
|
-
* @param options.highValueThreshold - Amount threshold for high security (default: 100000)
|
|
36
|
-
* @param options.criticalValueThreshold - Amount threshold for critical security (default: 1000000)
|
|
37
|
-
* @param options.enableXchange - Allow Xchange mode for performance (default: false)
|
|
38
|
-
*/
|
|
39
|
-
constructor(options = {}) {
|
|
40
|
-
this.options = options;
|
|
41
|
-
}
|
|
42
|
-
classify(context) {
|
|
43
|
-
const { action, params, securityOverride } = context;
|
|
44
|
-
const highThreshold = this.options.highValueThreshold ?? 100_000;
|
|
45
|
-
const criticalThreshold = this.options.criticalValueThreshold ?? 1_000_000;
|
|
46
|
-
// Explicit override: critical
|
|
47
|
-
if (securityOverride === 'critical') {
|
|
48
|
-
return {
|
|
49
|
-
mode: { type: 'split', shares: 5, threshold: 3 },
|
|
50
|
-
reason: 'User requested critical security level (5 shares, 3-of-5 threshold)',
|
|
51
|
-
wasOverridden: true,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
// Explicit override: high
|
|
55
|
-
if (securityOverride === 'high') {
|
|
56
|
-
return {
|
|
57
|
-
mode: { type: 'split', shares: 3, threshold: 2 },
|
|
58
|
-
reason: 'User requested high security level (3 shares, 2-of-3 threshold)',
|
|
59
|
-
wasOverridden: true,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
// Explicit override: standard
|
|
63
|
-
if (securityOverride === 'standard') {
|
|
64
|
-
return {
|
|
65
|
-
mode: { type: 'standard' },
|
|
66
|
-
reason: 'User requested standard security level (encrypted transport)',
|
|
67
|
-
wasOverridden: true,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
// Risk tag detection (preferred for crypto: BTC, ETH, etc.)
|
|
71
|
-
const riskTag = typeof params.risk === 'string' ? params.risk.toLowerCase() : undefined;
|
|
72
|
-
if (riskTag) {
|
|
73
|
-
if (riskTag === 'critical' || riskTag === 'high') {
|
|
74
|
-
return {
|
|
75
|
-
mode: { type: 'split', shares: 5, threshold: 3 },
|
|
76
|
-
reason: `Explicit risk tag "${riskTag}" requires 3-of-5 threshold`,
|
|
77
|
-
wasOverridden: false,
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
else if (riskTag === 'medium') {
|
|
81
|
-
return {
|
|
82
|
-
mode: { type: 'split', shares: 3, threshold: 2 },
|
|
83
|
-
reason: `Explicit risk tag "medium" requires 2-of-3 threshold`,
|
|
84
|
-
wasOverridden: false,
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
else if (riskTag === 'low') {
|
|
88
|
-
return {
|
|
89
|
-
mode: { type: 'split', shares: 2, threshold: 2 },
|
|
90
|
-
reason: `Explicit risk tag "low" requires 2-of-2 threshold`,
|
|
91
|
-
wasOverridden: false,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
// Numeric thresholds ONLY for fiat currencies (USD, EUR, GBP)
|
|
96
|
-
// Crypto (BTC, ETH) should use risk tags instead
|
|
97
|
-
if ((action === 'transfer' || action === 'execute') && typeof params.amount === 'number') {
|
|
98
|
-
const currency = typeof params.currency === 'string' ? params.currency.toUpperCase() : 'USD';
|
|
99
|
-
const isFiat = ['USD', 'EUR', 'GBP'].includes(currency);
|
|
100
|
-
if (isFiat) {
|
|
101
|
-
if (params.amount >= criticalThreshold) {
|
|
102
|
-
return {
|
|
103
|
-
mode: { type: 'split', shares: 5, threshold: 3 },
|
|
104
|
-
reason: `Critical-value transfer (${currency} ${params.amount.toLocaleString()}) requires 3-of-5 threshold`,
|
|
105
|
-
wasOverridden: false,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
else if (params.amount >= highThreshold) {
|
|
109
|
-
return {
|
|
110
|
-
mode: { type: 'split', shares: 3, threshold: 2 },
|
|
111
|
-
reason: `High-value transfer (${currency} ${params.amount.toLocaleString()}) requires 2-of-3 threshold`,
|
|
112
|
-
wasOverridden: false,
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
// Auto-detection: Cross-entity communication
|
|
118
|
-
if (params.crossEntity === true) {
|
|
119
|
-
return {
|
|
120
|
-
mode: { type: 'split', shares: 3, threshold: 2 },
|
|
121
|
-
reason: 'Cross-organization communication requires multi-party approval (2 of 3)',
|
|
122
|
-
wasOverridden: false,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
// Auto-detection: Sensitive scopes
|
|
126
|
-
if (context.scope.includes('admin') ||
|
|
127
|
-
context.scope.includes('custody') ||
|
|
128
|
-
context.scope.includes('settlement')) {
|
|
129
|
-
return {
|
|
130
|
-
mode: { type: 'split', shares: 3, threshold: 2 },
|
|
131
|
-
reason: `Sensitive scope "${context.scope}" requires multi-party approval (2 of 3)`,
|
|
132
|
-
wasOverridden: false,
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
// Xchange mode: opt-in performance mode (if enabled)
|
|
136
|
-
if (this.options.enableXchange && params.xchange === true) {
|
|
137
|
-
return {
|
|
138
|
-
mode: { type: 'xchange' },
|
|
139
|
-
reason: 'Xchange mode enabled for performance (~180x faster)',
|
|
140
|
-
wasOverridden: false,
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
// Default: Standard encrypted transport
|
|
144
|
-
return {
|
|
145
|
-
mode: { type: 'standard' },
|
|
146
|
-
reason: 'Standard encrypted transport (hybrid post-quantum)',
|
|
147
|
-
wasOverridden: false,
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
exports.DefaultSecurityPolicy = DefaultSecurityPolicy;
|
|
152
|
-
/**
|
|
153
|
-
* Get a human-readable security mode description.
|
|
154
|
-
*
|
|
155
|
-
* Used for logging and user feedback.
|
|
156
|
-
*
|
|
157
|
-
* @param mode - Security mode
|
|
158
|
-
* @returns User-friendly description
|
|
159
|
-
*
|
|
160
|
-
* @deprecated Use describeSecurityModeStructured() for new code. This function remains for backward compatibility.
|
|
161
|
-
*/
|
|
162
|
-
function describeSecurityMode(mode) {
|
|
163
|
-
switch (mode.type) {
|
|
164
|
-
case 'standard':
|
|
165
|
-
return 'Standard (encrypted)';
|
|
166
|
-
case 'split':
|
|
167
|
-
return `Multi-party approval (${mode.threshold} of ${mode.shares})`;
|
|
168
|
-
case 'xchange':
|
|
169
|
-
return 'Xchange (fast mode)';
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Get a structured security mode description with multiple formats.
|
|
174
|
-
*
|
|
175
|
-
* Returns an object with the security classification and formatted descriptions
|
|
176
|
-
* optimized for different use cases (display, logging, APIs, docs).
|
|
177
|
-
*
|
|
178
|
-
* @param mode - Security mode
|
|
179
|
-
* @returns Security mode description with formats
|
|
180
|
-
*
|
|
181
|
-
* @example
|
|
182
|
-
* ```typescript
|
|
183
|
-
* const mode: SecurityMode = { type: 'split', shares: 3, threshold: 2 };
|
|
184
|
-
* const description = describeSecurityModeStructured(mode);
|
|
185
|
-
*
|
|
186
|
-
* console.log(description.formats.singleline);
|
|
187
|
-
* // "high | split | 2-of-3"
|
|
188
|
-
*
|
|
189
|
-
* console.log(description.formats.multiline);
|
|
190
|
-
* // "Security Level: High
|
|
191
|
-
* // Mode: Split-channel (XorIDA)
|
|
192
|
-
* // Shares: 3 total, 2 required"
|
|
193
|
-
*
|
|
194
|
-
* console.log(description.shares);
|
|
195
|
-
* // { total: 3, threshold: 2 }
|
|
196
|
-
* ```
|
|
197
|
-
*/
|
|
198
|
-
function describeSecurityModeStructured(mode) {
|
|
199
|
-
let level;
|
|
200
|
-
let multiline;
|
|
201
|
-
let singleline;
|
|
202
|
-
let markdown;
|
|
203
|
-
let shares;
|
|
204
|
-
switch (mode.type) {
|
|
205
|
-
case 'standard':
|
|
206
|
-
level = 'standard';
|
|
207
|
-
multiline = 'Security Level: Standard\nMode: Encrypted transport (hybrid post-quantum)';
|
|
208
|
-
singleline = 'standard | encrypted';
|
|
209
|
-
markdown = '**Security Level:** Standard\n\n**Mode:** Encrypted transport (hybrid post-quantum)';
|
|
210
|
-
break;
|
|
211
|
-
case 'split':
|
|
212
|
-
// Classify split mode as high or critical based on threshold
|
|
213
|
-
level = mode.shares >= 5 ? 'critical' : 'high';
|
|
214
|
-
shares = { total: mode.shares, threshold: mode.threshold };
|
|
215
|
-
multiline = `Security Level: ${level === 'critical' ? 'Critical' : 'High'}\nMode: Split-channel (XorIDA)\nShares: ${mode.shares} total, ${mode.threshold} required`;
|
|
216
|
-
singleline = `${level} | split | ${mode.threshold}-of-${mode.shares}`;
|
|
217
|
-
markdown = `**Security Level:** ${level === 'critical' ? 'Critical' : 'High'}\n\n**Mode:** Split-channel (XorIDA)\n\n**Shares:** ${mode.shares} total, ${mode.threshold} required`;
|
|
218
|
-
break;
|
|
219
|
-
case 'xchange':
|
|
220
|
-
level = 'performance';
|
|
221
|
-
multiline = 'Security Level: Performance\nMode: Xchange (single IT layer, ~180x faster)';
|
|
222
|
-
singleline = 'performance | xchange';
|
|
223
|
-
markdown = '**Security Level:** Performance\n\n**Mode:** Xchange (single IT layer, ~180x faster)';
|
|
224
|
-
break;
|
|
225
|
-
}
|
|
226
|
-
const jsonObj = {
|
|
227
|
-
type: mode.type,
|
|
228
|
-
level,
|
|
229
|
-
};
|
|
230
|
-
if (shares) {
|
|
231
|
-
jsonObj.shares = shares;
|
|
232
|
-
}
|
|
233
|
-
const json = JSON.stringify(jsonObj);
|
|
234
|
-
return {
|
|
235
|
-
type: mode.type,
|
|
236
|
-
level,
|
|
237
|
-
shares,
|
|
238
|
-
formats: {
|
|
239
|
-
multiline,
|
|
240
|
-
singleline,
|
|
241
|
-
json,
|
|
242
|
-
markdown,
|
|
243
|
-
},
|
|
244
|
-
};
|
|
245
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.DefaultSecurityPolicy=void 0,exports.describeSecurityMode=describeSecurityMode,exports.describeSecurityModeStructured=describeSecurityModeStructured;class DefaultSecurityPolicy{options;constructor(e={}){this.options=e}classify(e){const{action:r,params:t,securityOverride:s}=e,i=this.options.highValueThreshold??1e5,a=this.options.criticalValueThreshold??1e6;if("critical"===s)return{mode:{type:"split",shares:5,threshold:3},reason:"User requested critical security level (5 shares, 3-of-5 threshold)",wasOverridden:!0};if("high"===s)return{mode:{type:"split",shares:3,threshold:2},reason:"User requested high security level (3 shares, 2-of-3 threshold)",wasOverridden:!0};if("standard"===s)return{mode:{type:"standard"},reason:"User requested standard security level (encrypted transport)",wasOverridden:!0};const o="string"==typeof t.risk?t.risk.toLowerCase():void 0;if(o){if("critical"===o||"high"===o)return{mode:{type:"split",shares:5,threshold:3},reason:`Explicit risk tag "${o}" requires 3-of-5 threshold`,wasOverridden:!1};if("medium"===o)return{mode:{type:"split",shares:3,threshold:2},reason:'Explicit risk tag "medium" requires 2-of-3 threshold',wasOverridden:!1};if("low"===o)return{mode:{type:"split",shares:2,threshold:2},reason:'Explicit risk tag "low" requires 2-of-2 threshold',wasOverridden:!1}}if(("transfer"===r||"execute"===r)&&"number"==typeof t.amount){const e="string"==typeof t.currency?t.currency.toUpperCase():"USD";if(["USD","EUR","GBP"].includes(e)){if(t.amount>=a)return{mode:{type:"split",shares:5,threshold:3},reason:`Critical-value transfer (${e} ${t.amount.toLocaleString()}) requires 3-of-5 threshold`,wasOverridden:!1};if(t.amount>=i)return{mode:{type:"split",shares:3,threshold:2},reason:`High-value transfer (${e} ${t.amount.toLocaleString()}) requires 2-of-3 threshold`,wasOverridden:!1}}}return!0===t.crossEntity?{mode:{type:"split",shares:3,threshold:2},reason:"Cross-organization communication requires multi-party approval (2 of 3)",wasOverridden:!1}:e.scope.includes("admin")||e.scope.includes("custody")||e.scope.includes("settlement")?{mode:{type:"split",shares:3,threshold:2},reason:`Sensitive scope "${e.scope}" requires multi-party approval (2 of 3)`,wasOverridden:!1}:this.options.enableXchange&&!0===t.xchange?{mode:{type:"xchange"},reason:"Xchange mode enabled for performance (~180x faster)",wasOverridden:!1}:{mode:{type:"standard"},reason:"Standard encrypted transport (hybrid post-quantum)",wasOverridden:!1}}}function describeSecurityMode(e){switch(e.type){case"standard":return"Standard (encrypted)";case"split":return`Multi-party approval (${e.threshold} of ${e.shares})`;case"xchange":return"Xchange (fast mode)"}}function describeSecurityModeStructured(e){let r,t,s,i,a;switch(e.type){case"standard":r="standard",t="Security Level: Standard\nMode: Encrypted transport (hybrid post-quantum)",s="standard | encrypted",i="**Security Level:** Standard\n\n**Mode:** Encrypted transport (hybrid post-quantum)";break;case"split":r=e.shares>=5?"critical":"high",a={total:e.shares,threshold:e.threshold},t=`Security Level: ${"critical"===r?"Critical":"High"}\nMode: Split-channel (XorIDA)\nShares: ${e.shares} total, ${e.threshold} required`,s=`${r} | split | ${e.threshold}-of-${e.shares}`,i=`**Security Level:** ${"critical"===r?"Critical":"High"}\n\n**Mode:** Split-channel (XorIDA)\n\n**Shares:** ${e.shares} total, ${e.threshold} required`;break;case"xchange":r="performance",t="Security Level: Performance\nMode: Xchange (single IT layer, ~180x faster)",s="performance | xchange",i="**Security Level:** Performance\n\n**Mode:** Xchange (single IT layer, ~180x faster)"}const o={type:e.type,level:r};a&&(o.shares=a);const n=JSON.stringify(o);return{type:e.type,level:r,shares:a,formats:{multiline:t,singleline:s,json:n,markdown:i}}}exports.DefaultSecurityPolicy=DefaultSecurityPolicy;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.serialize=serialize,exports.deserialize=deserialize,exports.detectFormat=detectFormat,exports.negotiateFormat=negotiateFormat,exports.compareFormats=compareFormats,exports.getContentType=getContentType,exports.parseContentType=parseContentType;const shared_1=require("../_deps/shared/index.js");class JSONSerializer{format="json";contentType="application/json";serialize(e,t){try{const r=t?.pretty?JSON.stringify(e,null,2):JSON.stringify(e);return(0,shared_1.ok)((new TextEncoder).encode(r))}catch(e){return(0,shared_1.err)({code:"SERIALIZATION_FAILED",reason:e instanceof Error?e.message:String(e),format:"json"})}}deserialize(e){try{const t=(new TextDecoder).decode(e);return(0,shared_1.ok)(JSON.parse(t))}catch(e){return(0,shared_1.err)({code:"DESERIALIZATION_FAILED",reason:e instanceof Error?e.message:String(e)})}}detect(e){if(0===e.length)return!1;const t=e[0];if(void 0===t)return!1;if(123===t||91===t||34===t)return!0;if(32===t||9===t||10===t||13===t)for(let t=1;t<Math.min(e.length,10);t++){const r=e[t];if(void 0===r)return!1;if(123===r||91===r||34===r)return!0;if(32!==r&&9!==r&&10!==r&&13!==r)return!1}return!1}}class MessagePackSerializer{format="msgpack";contentType="application/msgpack";serialize(e,t){try{return(0,shared_1.ok)(this.encode(e))}catch(e){return(0,shared_1.err)({code:"SERIALIZATION_FAILED",reason:e instanceof Error?e.message:String(e),format:"msgpack"})}}deserialize(e){try{return(0,shared_1.ok)(this.decode(e))}catch(e){return(0,shared_1.err)({code:"DESERIALIZATION_FAILED",reason:e instanceof Error?e.message:String(e)})}}detect(e){if(0===e.length)return!1;const t=e[0];if(void 0===t)return!1;if(t>=224&&t<=255&&e.length<2)return!1;try{const t={offset:0};return this.decodeValue(e,t),!0}catch{return!1}}encode(e){const t=[];this.encodeValue(e,t);const r=t.reduce((e,t)=>e+t.length,0),n=new Uint8Array(r);let s=0;for(const e of t)n.set(e,s),s+=e.length;return n}encodeValue(e,t){if(null==e)t.push(new Uint8Array([192]));else if("boolean"==typeof e)t.push(new Uint8Array([e?195:194]));else if("number"==typeof e)this.encodeNumber(e,t);else if("string"==typeof e)this.encodeString(e,t);else if(e instanceof Uint8Array)this.encodeBinary(e,t);else if(Array.isArray(e))this.encodeArray(e,t);else{if("object"!=typeof e)throw new Error("Unsupported type: "+typeof e);this.encodeObject(e,t)}}encodeNumber(e,t){if(Number.isInteger(e))if(e>=0&&e<=127)t.push(new Uint8Array([e]));else if(e>=-32&&e<0)t.push(new Uint8Array([224|31&e]));else if(e>=0&&e<=255)t.push(new Uint8Array([204,e]));else if(e>=0&&e<=65535)t.push(new Uint8Array([205,e>>8,255&e]));else if(e>=0&&e<=4294967295){const r=new Uint8Array(5);r[0]=206,new DataView(r.buffer).setUint32(1,e,!1),t.push(r)}else{const r=new Uint8Array(9);r[0]=203,new DataView(r.buffer).setFloat64(1,e,!1),t.push(r)}else{const r=new Uint8Array(9);r[0]=203,new DataView(r.buffer).setFloat64(1,e,!1),t.push(r)}}encodeString(e,t){const r=(new TextEncoder).encode(e),n=r.length;if(n<=31)t.push(new Uint8Array([160|n]));else if(n<=255)t.push(new Uint8Array([217,n]));else if(n<=65535)t.push(new Uint8Array([218,n>>8,255&n]));else{const e=new Uint8Array(5);e[0]=219,new DataView(e.buffer).setUint32(1,n,!1),t.push(e)}t.push(r)}encodeBinary(e,t){const r=e.length;if(r<=255)t.push(new Uint8Array([196,r]));else if(r<=65535)t.push(new Uint8Array([197,r>>8,255&r]));else{const e=new Uint8Array(5);e[0]=198,new DataView(e.buffer).setUint32(1,r,!1),t.push(e)}t.push(e)}encodeArray(e,t){const r=e.length;if(r<=15)t.push(new Uint8Array([144|r]));else if(r<=65535)t.push(new Uint8Array([220,r>>8,255&r]));else{const e=new Uint8Array(5);e[0]=221,new DataView(e.buffer).setUint32(1,r,!1),t.push(e)}for(const r of e)this.encodeValue(r,t)}encodeObject(e,t){const r=Object.keys(e),n=r.length;if(n<=15)t.push(new Uint8Array([128|n]));else if(n<=65535)t.push(new Uint8Array([222,n>>8,255&n]));else{const e=new Uint8Array(5);e[0]=223,new DataView(e.buffer).setUint32(1,n,!1),t.push(e)}for(const n of r)this.encodeValue(n,t),this.encodeValue(e[n],t)}decode(e){return this.decodeValue(e,{offset:0})}decodeValue(e,t){if(t.offset>=e.length)throw new Error("Unexpected end of data");const r=e[t.offset++];if(void 0===r)throw new Error("Unexpected end of data");if(r<=127)return r;if(r>=128&&r<=143){const n=15&r;return this.decodeMap(e,t,n)}if(r>=144&&r<=159){const n=15&r;return this.decodeArray(e,t,n)}if(r>=160&&r<=191){const n=31&r;return this.decodeString(e,t,n)}if(r>=224)return(31&r)-32;switch(r){case 192:return null;case 194:return!1;case 195:return!0;case 196:{const r=e[t.offset++];if(void 0===r)throw new Error("Unexpected end of data");return this.decodeBinary(e,t,r)}case 197:return this.decodeBinary(e,t,this.readUint16(e,t));case 198:return this.decodeBinary(e,t,this.readUint32(e,t));case 202:return this.readFloat32(e,t);case 203:return this.readFloat64(e,t);case 204:{const r=e[t.offset++];if(void 0===r)throw new Error("Unexpected end of data");return r}case 205:return this.readUint16(e,t);case 206:return this.readUint32(e,t);case 208:return this.readInt8(e,t);case 209:return this.readInt16(e,t);case 210:return this.readInt32(e,t);case 217:{const r=e[t.offset++];if(void 0===r)throw new Error("Unexpected end of data");return this.decodeString(e,t,r)}case 218:return this.decodeString(e,t,this.readUint16(e,t));case 219:return this.decodeString(e,t,this.readUint32(e,t));case 220:return this.decodeArray(e,t,this.readUint16(e,t));case 221:return this.decodeArray(e,t,this.readUint32(e,t));case 222:return this.decodeMap(e,t,this.readUint16(e,t));case 223:return this.decodeMap(e,t,this.readUint32(e,t));default:throw new Error(`Unknown MessagePack type: 0x${r.toString(16)}`)}}decodeString(e,t,r){const n=e.slice(t.offset,t.offset+r);return t.offset+=r,(new TextDecoder).decode(n)}decodeBinary(e,t,r){const n=e.slice(t.offset,t.offset+r);return t.offset+=r,n}decodeArray(e,t,r){const n=[];for(let s=0;s<r;s++)n.push(this.decodeValue(e,t));return n}decodeMap(e,t,r){const n={};for(let s=0;s<r;s++){const r=this.decodeValue(e,t),s=this.decodeValue(e,t);n[String(r)]=s}return n}readUint16(e,t){const r=new DataView(e.buffer,e.byteOffset).getUint16(t.offset,!1);return t.offset+=2,r}readUint32(e,t){const r=new DataView(e.buffer,e.byteOffset).getUint32(t.offset,!1);return t.offset+=4,r}readInt8(e,t){if(t.offset>=e.length)throw new Error("Unexpected end of data");const r=new DataView(e.buffer,e.byteOffset).getInt8(t.offset);return t.offset+=1,r}readInt16(e,t){const r=new DataView(e.buffer,e.byteOffset).getInt16(t.offset,!1);return t.offset+=2,r}readInt32(e,t){const r=new DataView(e.buffer,e.byteOffset).getInt32(t.offset,!1);return t.offset+=4,r}readFloat32(e,t){const r=new DataView(e.buffer,e.byteOffset).getFloat32(t.offset,!1);return t.offset+=4,r}readFloat64(e,t){const r=new DataView(e.buffer,e.byteOffset).getFloat64(t.offset,!1);return t.offset+=8,r}}class CBORSerializer{format="cbor";contentType="application/cbor";serialize(e,t){try{return(0,shared_1.ok)(this.encode(e))}catch(e){return(0,shared_1.err)({code:"SERIALIZATION_FAILED",reason:e instanceof Error?e.message:String(e),format:"cbor"})}}deserialize(e){try{return(0,shared_1.ok)(this.decode(e))}catch(e){return(0,shared_1.err)({code:"DESERIALIZATION_FAILED",reason:e instanceof Error?e.message:String(e)})}}detect(e){if(0===e.length)return!1;e[0];try{const t={offset:0};return this.decodeValue(e,t),!0}catch{return!1}}encode(e){const t=[];this.encodeValue(e,t);const r=t.reduce((e,t)=>e+t.length,0),n=new Uint8Array(r);let s=0;for(const e of t)n.set(e,s),s+=e.length;return n}encodeValue(e,t){if(null==e)t.push(new Uint8Array([246]));else if("boolean"==typeof e)t.push(new Uint8Array([e?245:244]));else if("number"==typeof e)this.encodeNumber(e,t);else if("string"==typeof e)this.encodeString(e,t);else if(e instanceof Uint8Array)this.encodeBinary(e,t);else if(Array.isArray(e))this.encodeArray(e,t);else{if("object"!=typeof e)throw new Error("Unsupported type: "+typeof e);this.encodeObject(e,t)}}encodeNumber(e,t){if(Number.isInteger(e))if(e>=0)if(e<=23)t.push(new Uint8Array([e]));else if(e<=255)t.push(new Uint8Array([24,e]));else if(e<=65535)t.push(new Uint8Array([25,e>>8,255&e]));else if(e<=4294967295){const r=new Uint8Array(5);r[0]=26,new DataView(r.buffer).setUint32(1,e,!1),t.push(r)}else{const r=new Uint8Array(9);r[0]=251,new DataView(r.buffer).setFloat64(1,e,!1),t.push(r)}else{const r=-1-e;if(r<=23)t.push(new Uint8Array([32|r]));else if(r<=255)t.push(new Uint8Array([56,r]));else if(r<=65535)t.push(new Uint8Array([57,r>>8,255&r]));else{const e=new Uint8Array(5);e[0]=58,new DataView(e.buffer).setUint32(1,r,!1),t.push(e)}}else{const r=new Uint8Array(9);r[0]=251,new DataView(r.buffer).setFloat64(1,e,!1),t.push(r)}}encodeString(e,t){const r=(new TextEncoder).encode(e),n=r.length;if(n<=23)t.push(new Uint8Array([96|n]));else if(n<=255)t.push(new Uint8Array([120,n]));else if(n<=65535)t.push(new Uint8Array([121,n>>8,255&n]));else{const e=new Uint8Array(5);e[0]=122,new DataView(e.buffer).setUint32(1,n,!1),t.push(e)}t.push(r)}encodeBinary(e,t){const r=e.length;if(r<=23)t.push(new Uint8Array([64|r]));else if(r<=255)t.push(new Uint8Array([88,r]));else if(r<=65535)t.push(new Uint8Array([89,r>>8,255&r]));else{const e=new Uint8Array(5);e[0]=90,new DataView(e.buffer).setUint32(1,r,!1),t.push(e)}t.push(e)}encodeArray(e,t){const r=e.length;if(r<=23)t.push(new Uint8Array([128|r]));else if(r<=255)t.push(new Uint8Array([152,r]));else if(r<=65535)t.push(new Uint8Array([153,r>>8,255&r]));else{const e=new Uint8Array(5);e[0]=154,new DataView(e.buffer).setUint32(1,r,!1),t.push(e)}for(const r of e)this.encodeValue(r,t)}encodeObject(e,t){const r=Object.keys(e),n=r.length;if(n<=23)t.push(new Uint8Array([160|n]));else if(n<=255)t.push(new Uint8Array([184,n]));else if(n<=65535)t.push(new Uint8Array([185,n>>8,255&n]));else{const e=new Uint8Array(5);e[0]=186,new DataView(e.buffer).setUint32(1,n,!1),t.push(e)}for(const n of r)this.encodeValue(n,t),this.encodeValue(e[n],t)}decode(e){return this.decodeValue(e,{offset:0})}decodeValue(e,t){if(t.offset>=e.length)throw new Error("Unexpected end of data");const r=e[t.offset++];if(void 0===r)throw new Error("Unexpected end of data");const n=r>>5&7,s=31&r;switch(n){case 0:return this.decodeInteger(e,t,s);case 1:return-1-this.decodeInteger(e,t,s);case 2:return this.decodeBinary(e,t,s);case 3:return this.decodeString(e,t,s);case 4:return this.decodeArray(e,t,s);case 5:return this.decodeMap(e,t,s);case 7:return this.decodeSpecial(e,t,s);default:throw new Error(`Unsupported CBOR major type: ${n}`)}}decodeInteger(e,t,r){if(r<=23)return r;if(24===r){const r=e[t.offset++];if(void 0===r)throw new Error("Unexpected end of data");return r}if(25===r)return this.readUint16(e,t);if(26===r)return this.readUint32(e,t);throw new Error("Unsupported integer size")}decodeString(e,t,r){let n;n=r<=23?r:this.decodeInteger(e,t,r);const s=e.slice(t.offset,t.offset+n);return t.offset+=n,(new TextDecoder).decode(s)}decodeBinary(e,t,r){let n;n=r<=23?r:this.decodeInteger(e,t,r);const s=e.slice(t.offset,t.offset+n);return t.offset+=n,s}decodeArray(e,t,r){let n;n=r<=23?r:this.decodeInteger(e,t,r);const s=[];for(let r=0;r<n;r++)s.push(this.decodeValue(e,t));return s}decodeMap(e,t,r){let n;n=r<=23?r:this.decodeInteger(e,t,r);const s={};for(let r=0;r<n;r++){const r=this.decodeValue(e,t),n=this.decodeValue(e,t);s[String(r)]=n}return s}decodeSpecial(e,t,r){switch(r){case 20:return!1;case 21:return!0;case 22:return null;case 23:return;case 27:return this.readFloat64(e,t);default:throw new Error(`Unsupported CBOR special: ${r}`)}}readUint16(e,t){const r=new DataView(e.buffer,e.byteOffset).getUint16(t.offset,!1);return t.offset+=2,r}readUint32(e,t){const r=new DataView(e.buffer,e.byteOffset).getUint32(t.offset,!1);return t.offset+=4,r}readFloat64(e,t){const r=new DataView(e.buffer,e.byteOffset).getFloat64(t.offset,!1);return t.offset+=8,r}}const serializers=new Map([["json",new JSONSerializer],["cbor",new CBORSerializer],["msgpack",new MessagePackSerializer]]);function serialize(e,t={}){const r=t.format??"json",n=serializers.get(r);if(!n)return(0,shared_1.err)({code:"UNSUPPORTED_FORMAT",format:r});const s=t.collectMetrics?performance.now():0,o=n.serialize(e,t);if(!o.ok)return o;const i=t.collectMetrics?{serializeDuration:performance.now()-s,size:o.value.length,format:r,timestamp:Date.now()}:void 0;return(0,shared_1.ok)({data:o.value,format:r,size:o.value.length,contentType:n.contentType,metrics:i})}function deserialize(e,t={}){const r=t.collectMetrics?performance.now():0;let n,s;if(t.format){if(n=t.format,s=serializers.get(n),!s)return(0,shared_1.err)({code:"UNSUPPORTED_FORMAT",format:n})}else{const t=detectFormat(e);if(!t.ok)return t;if(n=t.value,s=serializers.get(n),!s)return(0,shared_1.err)({code:"UNSUPPORTED_FORMAT",format:n})}const o=s.deserialize(e);if(!o.ok)return o;const i=t.collectMetrics?{serializeDuration:performance.now()-r,size:e.length,format:n,timestamp:Date.now()}:void 0;return(0,shared_1.ok)({value:o.value,format:n,metrics:i})}function detectFormat(e){const t=serializers.get("json");if(t?.detect(e))return(0,shared_1.ok)("json");if(0===e.length)return(0,shared_1.err)({code:"FORMAT_DETECTION_FAILED",reason:"Empty data"});const r=serializers.get("cbor");if(r?.detect(e))return(0,shared_1.ok)("cbor");const n=serializers.get("msgpack");return n?.detect(e)?(0,shared_1.ok)("msgpack"):(0,shared_1.err)({code:"FORMAT_DETECTION_FAILED",reason:"No serializer recognized the data format"})}function negotiateFormat(e,t){for(const r of e)if(t.includes(r))return(0,shared_1.ok)(r);return(0,shared_1.err)({code:"UNSUPPORTED_FORMAT",format:`No common format (client: ${e.join(",")}, server: ${t.join(",")})`})}function compareFormats(e,t=["json","msgpack","cbor"]){const r=[];for(const n of t){const t=serialize(e,{format:n,collectMetrics:!0});if(!t.ok)return t;r.push({format:n,size:t.value.size,duration:t.value.metrics?.serializeDuration??0})}return(0,shared_1.ok)(r)}function getContentType(e){const t=serializers.get(e);return t?.contentType??"application/octet-stream"}function parseContentType(e){const t=e.toLowerCase().split(";")[0]?.trim()??"";for(const e of serializers.values())if(e.contentType===t)return e.format}
|