@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
|
@@ -1,239 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Security policy interface for automatic risk-based Xorida activation.
|
|
3
|
-
*
|
|
4
|
-
* Determines when to apply information-theoretic security (XorIDA split-channel)
|
|
5
|
-
* vs standard encrypted transport based on action semantics and parameters.
|
|
6
|
-
*
|
|
7
|
-
* Design principle: Security should be invisible to users. The policy classifies
|
|
8
|
-
* risk automatically so developers don't need to understand threshold cryptography.
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* Default security policy for basic XBind.
|
|
12
|
-
*
|
|
13
|
-
* Rules:
|
|
14
|
-
* - Explicit risk tags: low → 2-of-2, medium → 2-of-3, high/critical → 3-of-5
|
|
15
|
-
* - Fiat transfers: USD/EUR/GBP >$100k → 2-of-3, >$1M → 3-of-5
|
|
16
|
-
* - Crypto transfers: Require explicit risk tag (no numeric auto-detection)
|
|
17
|
-
* - Sensitive scopes: custody/admin/settlement → 2-of-3
|
|
18
|
-
* - Cross-entity communication: 2-of-3
|
|
19
|
-
* - Explicit 'high' override: 2-of-3, 'critical' override: 3-of-5
|
|
20
|
-
* - Everything else: Standard encrypted transport (V3 hybrid PQ)
|
|
21
|
-
*
|
|
22
|
-
* Enterprise and Government variants extend this with custom rules.
|
|
23
|
-
*/
|
|
24
|
-
export class DefaultSecurityPolicy {
|
|
25
|
-
options;
|
|
26
|
-
/**
|
|
27
|
-
* Create a default security policy.
|
|
28
|
-
*
|
|
29
|
-
* @param options - Optional configuration
|
|
30
|
-
* @param options.highValueThreshold - Amount threshold for high security (default: 100000)
|
|
31
|
-
* @param options.criticalValueThreshold - Amount threshold for critical security (default: 1000000)
|
|
32
|
-
* @param options.enableXchange - Allow Xchange mode for performance (default: false)
|
|
33
|
-
*/
|
|
34
|
-
constructor(options = {}) {
|
|
35
|
-
this.options = options;
|
|
36
|
-
}
|
|
37
|
-
classify(context) {
|
|
38
|
-
const { action, params, securityOverride } = context;
|
|
39
|
-
const highThreshold = this.options.highValueThreshold ?? 100_000;
|
|
40
|
-
const criticalThreshold = this.options.criticalValueThreshold ?? 1_000_000;
|
|
41
|
-
// Explicit override: critical
|
|
42
|
-
if (securityOverride === 'critical') {
|
|
43
|
-
return {
|
|
44
|
-
mode: { type: 'split', shares: 5, threshold: 3 },
|
|
45
|
-
reason: 'User requested critical security level (5 shares, 3-of-5 threshold)',
|
|
46
|
-
wasOverridden: true,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
// Explicit override: high
|
|
50
|
-
if (securityOverride === 'high') {
|
|
51
|
-
return {
|
|
52
|
-
mode: { type: 'split', shares: 3, threshold: 2 },
|
|
53
|
-
reason: 'User requested high security level (3 shares, 2-of-3 threshold)',
|
|
54
|
-
wasOverridden: true,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
// Explicit override: standard
|
|
58
|
-
if (securityOverride === 'standard') {
|
|
59
|
-
return {
|
|
60
|
-
mode: { type: 'standard' },
|
|
61
|
-
reason: 'User requested standard security level (encrypted transport)',
|
|
62
|
-
wasOverridden: true,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
// Risk tag detection (preferred for crypto: BTC, ETH, etc.)
|
|
66
|
-
const riskTag = typeof params.risk === 'string' ? params.risk.toLowerCase() : undefined;
|
|
67
|
-
if (riskTag) {
|
|
68
|
-
if (riskTag === 'critical' || riskTag === 'high') {
|
|
69
|
-
return {
|
|
70
|
-
mode: { type: 'split', shares: 5, threshold: 3 },
|
|
71
|
-
reason: `Explicit risk tag "${riskTag}" requires 3-of-5 threshold`,
|
|
72
|
-
wasOverridden: false,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
else if (riskTag === 'medium') {
|
|
76
|
-
return {
|
|
77
|
-
mode: { type: 'split', shares: 3, threshold: 2 },
|
|
78
|
-
reason: `Explicit risk tag "medium" requires 2-of-3 threshold`,
|
|
79
|
-
wasOverridden: false,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
else if (riskTag === 'low') {
|
|
83
|
-
return {
|
|
84
|
-
mode: { type: 'split', shares: 2, threshold: 2 },
|
|
85
|
-
reason: `Explicit risk tag "low" requires 2-of-2 threshold`,
|
|
86
|
-
wasOverridden: false,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
// Numeric thresholds ONLY for fiat currencies (USD, EUR, GBP)
|
|
91
|
-
// Crypto (BTC, ETH) should use risk tags instead
|
|
92
|
-
if ((action === 'transfer' || action === 'execute') && typeof params.amount === 'number') {
|
|
93
|
-
const currency = typeof params.currency === 'string' ? params.currency.toUpperCase() : 'USD';
|
|
94
|
-
const isFiat = ['USD', 'EUR', 'GBP'].includes(currency);
|
|
95
|
-
if (isFiat) {
|
|
96
|
-
if (params.amount >= criticalThreshold) {
|
|
97
|
-
return {
|
|
98
|
-
mode: { type: 'split', shares: 5, threshold: 3 },
|
|
99
|
-
reason: `Critical-value transfer (${currency} ${params.amount.toLocaleString()}) requires 3-of-5 threshold`,
|
|
100
|
-
wasOverridden: false,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
else if (params.amount >= highThreshold) {
|
|
104
|
-
return {
|
|
105
|
-
mode: { type: 'split', shares: 3, threshold: 2 },
|
|
106
|
-
reason: `High-value transfer (${currency} ${params.amount.toLocaleString()}) requires 2-of-3 threshold`,
|
|
107
|
-
wasOverridden: false,
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
// Auto-detection: Cross-entity communication
|
|
113
|
-
if (params.crossEntity === true) {
|
|
114
|
-
return {
|
|
115
|
-
mode: { type: 'split', shares: 3, threshold: 2 },
|
|
116
|
-
reason: 'Cross-organization communication requires multi-party approval (2 of 3)',
|
|
117
|
-
wasOverridden: false,
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
// Auto-detection: Sensitive scopes
|
|
121
|
-
if (context.scope.includes('admin') ||
|
|
122
|
-
context.scope.includes('custody') ||
|
|
123
|
-
context.scope.includes('settlement')) {
|
|
124
|
-
return {
|
|
125
|
-
mode: { type: 'split', shares: 3, threshold: 2 },
|
|
126
|
-
reason: `Sensitive scope "${context.scope}" requires multi-party approval (2 of 3)`,
|
|
127
|
-
wasOverridden: false,
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
// Xchange mode: opt-in performance mode (if enabled)
|
|
131
|
-
if (this.options.enableXchange && params.xchange === true) {
|
|
132
|
-
return {
|
|
133
|
-
mode: { type: 'xchange' },
|
|
134
|
-
reason: 'Xchange mode enabled for performance (~180x faster)',
|
|
135
|
-
wasOverridden: false,
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
// Default: Standard encrypted transport
|
|
139
|
-
return {
|
|
140
|
-
mode: { type: 'standard' },
|
|
141
|
-
reason: 'Standard encrypted transport (hybrid post-quantum)',
|
|
142
|
-
wasOverridden: false,
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Get a human-readable security mode description.
|
|
148
|
-
*
|
|
149
|
-
* Used for logging and user feedback.
|
|
150
|
-
*
|
|
151
|
-
* @param mode - Security mode
|
|
152
|
-
* @returns User-friendly description
|
|
153
|
-
*
|
|
154
|
-
* @deprecated Use describeSecurityModeStructured() for new code. This function remains for backward compatibility.
|
|
155
|
-
*/
|
|
156
|
-
export function describeSecurityMode(mode) {
|
|
157
|
-
switch (mode.type) {
|
|
158
|
-
case 'standard':
|
|
159
|
-
return 'Standard (encrypted)';
|
|
160
|
-
case 'split':
|
|
161
|
-
return `Multi-party approval (${mode.threshold} of ${mode.shares})`;
|
|
162
|
-
case 'xchange':
|
|
163
|
-
return 'Xchange (fast mode)';
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Get a structured security mode description with multiple formats.
|
|
168
|
-
*
|
|
169
|
-
* Returns an object with the security classification and formatted descriptions
|
|
170
|
-
* optimized for different use cases (display, logging, APIs, docs).
|
|
171
|
-
*
|
|
172
|
-
* @param mode - Security mode
|
|
173
|
-
* @returns Security mode description with formats
|
|
174
|
-
*
|
|
175
|
-
* @example
|
|
176
|
-
* ```typescript
|
|
177
|
-
* const mode: SecurityMode = { type: 'split', shares: 3, threshold: 2 };
|
|
178
|
-
* const description = describeSecurityModeStructured(mode);
|
|
179
|
-
*
|
|
180
|
-
* console.log(description.formats.singleline);
|
|
181
|
-
* // "high | split | 2-of-3"
|
|
182
|
-
*
|
|
183
|
-
* console.log(description.formats.multiline);
|
|
184
|
-
* // "Security Level: High
|
|
185
|
-
* // Mode: Split-channel (XorIDA)
|
|
186
|
-
* // Shares: 3 total, 2 required"
|
|
187
|
-
*
|
|
188
|
-
* console.log(description.shares);
|
|
189
|
-
* // { total: 3, threshold: 2 }
|
|
190
|
-
* ```
|
|
191
|
-
*/
|
|
192
|
-
export function describeSecurityModeStructured(mode) {
|
|
193
|
-
let level;
|
|
194
|
-
let multiline;
|
|
195
|
-
let singleline;
|
|
196
|
-
let markdown;
|
|
197
|
-
let shares;
|
|
198
|
-
switch (mode.type) {
|
|
199
|
-
case 'standard':
|
|
200
|
-
level = 'standard';
|
|
201
|
-
multiline = 'Security Level: Standard\nMode: Encrypted transport (hybrid post-quantum)';
|
|
202
|
-
singleline = 'standard | encrypted';
|
|
203
|
-
markdown = '**Security Level:** Standard\n\n**Mode:** Encrypted transport (hybrid post-quantum)';
|
|
204
|
-
break;
|
|
205
|
-
case 'split':
|
|
206
|
-
// Classify split mode as high or critical based on threshold
|
|
207
|
-
level = mode.shares >= 5 ? 'critical' : 'high';
|
|
208
|
-
shares = { total: mode.shares, threshold: mode.threshold };
|
|
209
|
-
multiline = `Security Level: ${level === 'critical' ? 'Critical' : 'High'}\nMode: Split-channel (XorIDA)\nShares: ${mode.shares} total, ${mode.threshold} required`;
|
|
210
|
-
singleline = `${level} | split | ${mode.threshold}-of-${mode.shares}`;
|
|
211
|
-
markdown = `**Security Level:** ${level === 'critical' ? 'Critical' : 'High'}\n\n**Mode:** Split-channel (XorIDA)\n\n**Shares:** ${mode.shares} total, ${mode.threshold} required`;
|
|
212
|
-
break;
|
|
213
|
-
case 'xchange':
|
|
214
|
-
level = 'performance';
|
|
215
|
-
multiline = 'Security Level: Performance\nMode: Xchange (single IT layer, ~180x faster)';
|
|
216
|
-
singleline = 'performance | xchange';
|
|
217
|
-
markdown = '**Security Level:** Performance\n\n**Mode:** Xchange (single IT layer, ~180x faster)';
|
|
218
|
-
break;
|
|
219
|
-
}
|
|
220
|
-
const jsonObj = {
|
|
221
|
-
type: mode.type,
|
|
222
|
-
level,
|
|
223
|
-
};
|
|
224
|
-
if (shares) {
|
|
225
|
-
jsonObj.shares = shares;
|
|
226
|
-
}
|
|
227
|
-
const json = JSON.stringify(jsonObj);
|
|
228
|
-
return {
|
|
229
|
-
type: mode.type,
|
|
230
|
-
level,
|
|
231
|
-
shares,
|
|
232
|
-
formats: {
|
|
233
|
-
multiline,
|
|
234
|
-
singleline,
|
|
235
|
-
json,
|
|
236
|
-
markdown,
|
|
237
|
-
},
|
|
238
|
-
};
|
|
239
|
-
}
|
|
1
|
+
export class DefaultSecurityPolicy{options;constructor(e={}){this.options=e}classify(e){const{action:r,params:t,securityOverride:s}=e,a=this.options.highValueThreshold??1e5,i=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>=i)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>=a)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}}}export 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)"}}export function describeSecurityModeStructured(e){let r,t,s,a,i;switch(e.type){case"standard":r="standard",t="Security Level: Standard\nMode: Encrypted transport (hybrid post-quantum)",s="standard | encrypted",a="**Security Level:** Standard\n\n**Mode:** Encrypted transport (hybrid post-quantum)";break;case"split":r=e.shares>=5?"critical":"high",i={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}`,a=`**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",a="**Security Level:** Performance\n\n**Mode:** Xchange (single IT layer, ~180x faster)"}const o={type:e.type,level:r};i&&(o.shares=i);const n=JSON.stringify(o);return{type:e.type,level:r,shares:i,formats:{multiline:t,singleline:s,json:n,markdown:a}}}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Alternative Serialization Formats (API-14)
|
|
3
|
+
*
|
|
4
|
+
* Pluggable serialization system supporting JSON, MessagePack, and CBOR.
|
|
5
|
+
* Provides format negotiation, backward compatibility, and performance benchmarks.
|
|
6
|
+
*
|
|
7
|
+
* @module serialization
|
|
8
|
+
*/
|
|
9
|
+
import type { Result } from '@private.me/shared';
|
|
10
|
+
/**
|
|
11
|
+
* Supported serialization formats.
|
|
12
|
+
*/
|
|
13
|
+
export type SerializationFormat = 'json' | 'msgpack' | 'cbor';
|
|
14
|
+
/**
|
|
15
|
+
* Serialization options for format negotiation.
|
|
16
|
+
*/
|
|
17
|
+
export interface SerializationOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Preferred format for serialization.
|
|
20
|
+
* @default 'json'
|
|
21
|
+
*/
|
|
22
|
+
format?: SerializationFormat;
|
|
23
|
+
/**
|
|
24
|
+
* List of acceptable formats for deserialization (in preference order).
|
|
25
|
+
* Used for format negotiation with peers.
|
|
26
|
+
* @default ['json', 'msgpack', 'cbor']
|
|
27
|
+
*/
|
|
28
|
+
acceptFormats?: SerializationFormat[];
|
|
29
|
+
/**
|
|
30
|
+
* Enable pretty-printing for JSON format (debugging only).
|
|
31
|
+
* @default false
|
|
32
|
+
*/
|
|
33
|
+
pretty?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Enable performance metrics collection.
|
|
36
|
+
* @default false
|
|
37
|
+
*/
|
|
38
|
+
collectMetrics?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Serialization result with format metadata.
|
|
42
|
+
*/
|
|
43
|
+
export interface SerializedData {
|
|
44
|
+
/** Serialized bytes */
|
|
45
|
+
readonly data: Uint8Array;
|
|
46
|
+
/** Format used for serialization */
|
|
47
|
+
readonly format: SerializationFormat;
|
|
48
|
+
/** Size in bytes */
|
|
49
|
+
readonly size: number;
|
|
50
|
+
/** Content-Type header value */
|
|
51
|
+
readonly contentType: string;
|
|
52
|
+
/** Performance metrics (if collectMetrics enabled) */
|
|
53
|
+
readonly metrics?: SerializationMetrics;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Performance metrics for serialization operations.
|
|
57
|
+
*/
|
|
58
|
+
export interface SerializationMetrics {
|
|
59
|
+
/** Serialization duration in milliseconds */
|
|
60
|
+
readonly serializeDuration: number;
|
|
61
|
+
/** Size in bytes */
|
|
62
|
+
readonly size: number;
|
|
63
|
+
/** Format used */
|
|
64
|
+
readonly format: SerializationFormat;
|
|
65
|
+
/** Timestamp */
|
|
66
|
+
readonly timestamp: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Deserialization result with format detection.
|
|
70
|
+
*/
|
|
71
|
+
export interface DeserializedData<T = unknown> {
|
|
72
|
+
/** Deserialized value */
|
|
73
|
+
readonly value: T;
|
|
74
|
+
/** Detected format */
|
|
75
|
+
readonly format: SerializationFormat;
|
|
76
|
+
/** Performance metrics (if collectMetrics enabled) */
|
|
77
|
+
readonly metrics?: SerializationMetrics;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Error types for serialization operations.
|
|
81
|
+
*/
|
|
82
|
+
export type SerializationError = {
|
|
83
|
+
code: 'UNSUPPORTED_FORMAT';
|
|
84
|
+
format: string;
|
|
85
|
+
} | {
|
|
86
|
+
code: 'SERIALIZATION_FAILED';
|
|
87
|
+
reason: string;
|
|
88
|
+
format: SerializationFormat;
|
|
89
|
+
} | {
|
|
90
|
+
code: 'DESERIALIZATION_FAILED';
|
|
91
|
+
reason: string;
|
|
92
|
+
} | {
|
|
93
|
+
code: 'FORMAT_DETECTION_FAILED';
|
|
94
|
+
reason: string;
|
|
95
|
+
} | {
|
|
96
|
+
code: 'INVALID_DATA';
|
|
97
|
+
reason: string;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Serializer interface for pluggable format implementations.
|
|
101
|
+
*/
|
|
102
|
+
export interface Serializer {
|
|
103
|
+
/** Format identifier */
|
|
104
|
+
readonly format: SerializationFormat;
|
|
105
|
+
/** Content-Type header value */
|
|
106
|
+
readonly contentType: string;
|
|
107
|
+
/** Serialize value to bytes */
|
|
108
|
+
serialize(value: unknown, options?: SerializationOptions): Result<Uint8Array, SerializationError>;
|
|
109
|
+
/** Deserialize bytes to value */
|
|
110
|
+
deserialize<T = unknown>(data: Uint8Array): Result<T, SerializationError>;
|
|
111
|
+
/** Detect if data is in this format */
|
|
112
|
+
detect(data: Uint8Array): boolean;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Serialize a value using the specified format.
|
|
116
|
+
*
|
|
117
|
+
* @param value - Value to serialize
|
|
118
|
+
* @param options - Serialization options
|
|
119
|
+
* @returns Serialized data with metadata
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```typescript
|
|
123
|
+
* const data = { message: 'Hello', timestamp: Date.now() };
|
|
124
|
+
*
|
|
125
|
+
* // JSON (default, human-readable)
|
|
126
|
+
* const json = serialize(data);
|
|
127
|
+
*
|
|
128
|
+
* // MessagePack (compact binary)
|
|
129
|
+
* const msgpack = serialize(data, { format: 'msgpack' });
|
|
130
|
+
*
|
|
131
|
+
* // CBOR (standard binary)
|
|
132
|
+
* const cbor = serialize(data, { format: 'cbor' });
|
|
133
|
+
*
|
|
134
|
+
* console.log('JSON:', json.value.size, 'bytes');
|
|
135
|
+
* console.log('MessagePack:', msgpack.value.size, 'bytes');
|
|
136
|
+
* console.log('CBOR:', cbor.value.size, 'bytes');
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
export declare function serialize(value: unknown, options?: SerializationOptions): Result<SerializedData, SerializationError>;
|
|
140
|
+
/**
|
|
141
|
+
* Deserialize bytes using format auto-detection or explicit format.
|
|
142
|
+
*
|
|
143
|
+
* @param data - Serialized bytes
|
|
144
|
+
* @param options - Deserialization options
|
|
145
|
+
* @returns Deserialized value with format metadata
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* // Auto-detect format
|
|
150
|
+
* const result = deserialize(bytes);
|
|
151
|
+
* if (result.ok) {
|
|
152
|
+
* console.log('Format:', result.value.format);
|
|
153
|
+
* console.log('Data:', result.value.value);
|
|
154
|
+
* }
|
|
155
|
+
*
|
|
156
|
+
* // Explicit format (faster, skips detection)
|
|
157
|
+
* const json = deserialize(bytes, { format: 'json' });
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
export declare function deserialize<T = unknown>(data: Uint8Array, options?: SerializationOptions): Result<DeserializedData<T>, SerializationError>;
|
|
161
|
+
/**
|
|
162
|
+
* Detect serialization format from bytes.
|
|
163
|
+
*
|
|
164
|
+
* @param data - Serialized bytes
|
|
165
|
+
* @returns Detected format
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* const format = detectFormat(bytes);
|
|
170
|
+
* if (format.ok) {
|
|
171
|
+
* console.log('Detected format:', format.value); // 'json' | 'msgpack' | 'cbor'
|
|
172
|
+
* }
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
export declare function detectFormat(data: Uint8Array): Result<SerializationFormat, SerializationError>;
|
|
176
|
+
/**
|
|
177
|
+
* Negotiate format between client and server.
|
|
178
|
+
*
|
|
179
|
+
* @param clientFormats - Formats accepted by client (in preference order)
|
|
180
|
+
* @param serverFormats - Formats supported by server
|
|
181
|
+
* @returns Best matching format
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```typescript
|
|
185
|
+
* const client = ['msgpack', 'cbor', 'json'];
|
|
186
|
+
* const server = ['json', 'cbor'];
|
|
187
|
+
* const format = negotiateFormat(client, server);
|
|
188
|
+
* console.log(format.value); // 'cbor' (first match)
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
export declare function negotiateFormat(clientFormats: SerializationFormat[], serverFormats: SerializationFormat[]): Result<SerializationFormat, SerializationError>;
|
|
192
|
+
/**
|
|
193
|
+
* Compare serialization performance across formats.
|
|
194
|
+
*
|
|
195
|
+
* @param value - Value to benchmark
|
|
196
|
+
* @param formats - Formats to compare
|
|
197
|
+
* @returns Performance comparison
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```typescript
|
|
201
|
+
* const data = { message: 'Hello', items: [1, 2, 3, 4, 5] };
|
|
202
|
+
* const comparison = compareFormats(data);
|
|
203
|
+
*
|
|
204
|
+
* if (comparison.ok) {
|
|
205
|
+
* for (const result of comparison.value) {
|
|
206
|
+
* console.log(`${result.format}: ${result.size} bytes, ${result.duration}ms`);
|
|
207
|
+
* }
|
|
208
|
+
* }
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
export declare function compareFormats(value: unknown, formats?: SerializationFormat[]): Result<Array<{
|
|
212
|
+
format: SerializationFormat;
|
|
213
|
+
size: number;
|
|
214
|
+
duration: number;
|
|
215
|
+
}>, SerializationError>;
|
|
216
|
+
/**
|
|
217
|
+
* Get Content-Type header for a serialization format.
|
|
218
|
+
*
|
|
219
|
+
* @param format - Serialization format
|
|
220
|
+
* @returns Content-Type header value
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```typescript
|
|
224
|
+
* const contentType = getContentType('msgpack');
|
|
225
|
+
* console.log(contentType); // 'application/msgpack'
|
|
226
|
+
* ```
|
|
227
|
+
*/
|
|
228
|
+
export declare function getContentType(format: SerializationFormat): string;
|
|
229
|
+
/**
|
|
230
|
+
* Parse Content-Type header to serialization format.
|
|
231
|
+
*
|
|
232
|
+
* @param contentType - Content-Type header value
|
|
233
|
+
* @returns Serialization format or undefined
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```typescript
|
|
237
|
+
* const format = parseContentType('application/json');
|
|
238
|
+
* console.log(format); // 'json'
|
|
239
|
+
*
|
|
240
|
+
* const format2 = parseContentType('application/msgpack');
|
|
241
|
+
* console.log(format2); // 'msgpack'
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
export declare function parseContentType(contentType: string): SerializationFormat | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ok,err}from"./_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 ok((new TextEncoder).encode(r))}catch(e){return err({code:"SERIALIZATION_FAILED",reason:e instanceof Error?e.message:String(e),format:"json"})}}deserialize(e){try{const t=(new TextDecoder).decode(e);return ok(JSON.parse(t))}catch(e){return 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 ok(this.encode(e))}catch(e){return err({code:"SERIALIZATION_FAILED",reason:e instanceof Error?e.message:String(e),format:"msgpack"})}}deserialize(e){try{return ok(this.decode(e))}catch(e){return 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 ok(this.encode(e))}catch(e){return err({code:"SERIALIZATION_FAILED",reason:e instanceof Error?e.message:String(e),format:"cbor"})}}deserialize(e){try{return ok(this.decode(e))}catch(e){return 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]]);export function serialize(e,t={}){const r=t.format??"json",n=serializers.get(r);if(!n)return 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 ok({data:o.value,format:r,size:o.value.length,contentType:n.contentType,metrics:i})}export 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 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 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 ok({value:o.value,format:n,metrics:i})}export function detectFormat(e){const t=serializers.get("json");if(t?.detect(e))return ok("json");if(0===e.length)return err({code:"FORMAT_DETECTION_FAILED",reason:"Empty data"});const r=serializers.get("cbor");if(r?.detect(e))return ok("cbor");const n=serializers.get("msgpack");return n?.detect(e)?ok("msgpack"):err({code:"FORMAT_DETECTION_FAILED",reason:"No serializer recognized the data format"})}export function negotiateFormat(e,t){for(const r of e)if(t.includes(r))return ok(r);return err({code:"UNSUPPORTED_FORMAT",format:`No common format (client: ${e.join(",")}, server: ${t.join(",")})`})}export 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 ok(r)}export function getContentType(e){const t=serializers.get(e);return t?.contentType??"application/octet-stream"}export function parseContentType(e){const t=e.toLowerCase().split(";")[0]?.trim()??"";for(const e of serializers.values())if(e.contentType===t)return e.format}
|
|
@@ -43,9 +43,35 @@ export declare const DEFAULT_SPLIT_CONFIG: SplitChannelConfig;
|
|
|
43
43
|
*
|
|
44
44
|
* Pipeline: pad(PKCS#7) -> HMAC(padded) -> XorIDA split -> ChannelShare[]
|
|
45
45
|
*
|
|
46
|
+
* Information-theoretic security: Any k shares can reconstruct the plaintext,
|
|
47
|
+
* but k-1 shares reveal ZERO information (proven secure).
|
|
48
|
+
*
|
|
46
49
|
* @param plaintext - Raw plaintext bytes to split
|
|
47
50
|
* @param config - Split configuration (totalShares, threshold)
|
|
48
51
|
* @returns Array of n ChannelShare objects ready for envelope wrapping
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* import { splitForChannel, DEFAULT_SPLIT_CONFIG } from '@private.me/xbind';
|
|
56
|
+
*
|
|
57
|
+
* const plaintext = new TextEncoder().encode('Sensitive data');
|
|
58
|
+
*
|
|
59
|
+
* // Default: 3 shares, need 2 to reconstruct
|
|
60
|
+
* const shares = await splitForChannel(plaintext);
|
|
61
|
+
* if (!shares.ok) throw new Error(shares.error);
|
|
62
|
+
*
|
|
63
|
+
* console.log('Created shares:', shares.value.length);
|
|
64
|
+
* // Send each share through different channels (email, SMS, push)
|
|
65
|
+
* shares.value.forEach((share, i) => {
|
|
66
|
+
* console.log(`Share ${i}: ${share.groupId}`);
|
|
67
|
+
* });
|
|
68
|
+
*
|
|
69
|
+
* // Custom configuration: 5 shares, need 3
|
|
70
|
+
* const customShares = await splitForChannel(plaintext, {
|
|
71
|
+
* totalShares: 5,
|
|
72
|
+
* threshold: 3
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
49
75
|
*/
|
|
50
76
|
export declare function splitForChannel(plaintext: Uint8Array, config?: SplitChannelConfig): Promise<Result<ChannelShare[], SplitChannelError>>;
|
|
51
77
|
/**
|
|
@@ -63,7 +89,29 @@ export declare function splitForChannelWithGroupId(plaintext: Uint8Array, config
|
|
|
63
89
|
* Pipeline: validate -> XorIDA reconstruct -> HMAC verify -> unpad -> plaintext
|
|
64
90
|
* HMAC verification happens BEFORE the data is trusted.
|
|
65
91
|
*
|
|
66
|
-
* @param shares - Array of at least k ChannelShare objects
|
|
92
|
+
* @param shares - Array of at least k ChannelShare objects (must have same groupId)
|
|
67
93
|
* @returns Reconstructed plaintext bytes
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* import { reconstructFromChannel, type ChannelShare } from '@private.me/xbind';
|
|
98
|
+
*
|
|
99
|
+
* // Collect shares from different channels
|
|
100
|
+
* const receivedShares: ChannelShare[] = [
|
|
101
|
+
* emailShare, // Received via email
|
|
102
|
+
* smsShare, // Received via SMS
|
|
103
|
+
* // Only need 2 shares (threshold = 2)
|
|
104
|
+
* ];
|
|
105
|
+
*
|
|
106
|
+
* // Reconstruct original message
|
|
107
|
+
* const plaintext = await reconstructFromChannel(receivedShares);
|
|
108
|
+
* if (!plaintext.ok) {
|
|
109
|
+
* console.error('Reconstruction failed:', plaintext.error);
|
|
110
|
+
* return;
|
|
111
|
+
* }
|
|
112
|
+
*
|
|
113
|
+
* const message = new TextDecoder().decode(plaintext.value);
|
|
114
|
+
* console.log('Reconstructed message:', message);
|
|
115
|
+
* ```
|
|
68
116
|
*/
|
|
69
117
|
export declare function reconstructFromChannel(shares: readonly ChannelShare[]): Promise<Result<Uint8Array, SplitChannelError>>;
|