@private.me/xbind 3.0.1 → 3.0.3
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/README.md +2419 -216
- package/README.md.backup +2121 -0
- package/dist-standalone/_deps/shared/cjs/errors.js +1 -1
- package/dist-standalone/_deps/shared/cjs/index.js +1 -1
- package/dist-standalone/_deps/shared/cjs/types.js +1 -1
- package/dist-standalone/_deps/shared/errors.js +1 -1
- package/dist-standalone/_deps/shared/index.js +1 -1
- package/dist-standalone/_deps/shared/types.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.d.ts +2 -2
- package/dist-standalone/agent-call.js +1 -1
- package/dist-standalone/agent.d.ts +2 -0
- package/dist-standalone/agent.js +1 -1
- package/dist-standalone/async-iterators.d.ts +3 -3
- package/dist-standalone/backup.js +1 -1
- package/dist-standalone/cjs/agent-call.js +1 -1
- package/dist-standalone/cjs/agent.js +1 -1
- package/dist-standalone/cjs/backup.js +1 -1
- package/dist-standalone/cjs/cli/init.js +1 -1
- package/dist-standalone/cjs/connection-pool.js +1 -1
- package/dist-standalone/cjs/crypto-utils.js +1 -1
- package/dist-standalone/cjs/debug-mode.js +1 -1
- package/dist-standalone/cjs/email-transport.js +1 -1
- package/dist-standalone/cjs/errors.js +1 -1
- package/dist-standalone/cjs/http-compat.js +1 -1
- package/dist-standalone/cjs/index.js +1 -1
- package/dist-standalone/cjs/lazy-init.js +1 -1
- package/dist-standalone/cjs/loopback-transport.js +1 -0
- package/dist-standalone/cjs/mdns-discovery.js +1 -1
- package/dist-standalone/cjs/plugins/logging.js +1 -1
- package/dist-standalone/cjs/runtime/edge.js +1 -1
- package/dist-standalone/cjs/security-policy.js +1 -1
- package/dist-standalone/cjs/serialization.js +1 -1
- package/dist-standalone/cjs/transport.js +1 -1
- package/dist-standalone/cjs/trust-registry.js +1 -1
- package/dist-standalone/cjs/vault-store-loader.js +1 -1
- package/dist-standalone/cjs/version-info.js +1 -1
- package/dist-standalone/cjs/xfetch.js +1 -1
- package/dist-standalone/cli/init.js +1 -1
- package/dist-standalone/cli/setup.js +1 -1
- package/dist-standalone/cli/xbind.js +1 -1
- package/dist-standalone/connection-pool.js +1 -1
- package/dist-standalone/crypto-utils.d.ts +2 -7
- package/dist-standalone/crypto-utils.js +1 -1
- package/dist-standalone/debug-mode.js +1 -1
- package/dist-standalone/email-transport.d.ts +2 -2
- package/dist-standalone/email-transport.js +1 -1
- package/dist-standalone/errors.d.ts +13 -3
- package/dist-standalone/errors.js +1 -1
- package/dist-standalone/gateway-state.d.ts +1 -1
- package/dist-standalone/health-check.d.ts +5 -1
- package/dist-standalone/http-compat.d.ts +1 -1
- package/dist-standalone/http-compat.js +1 -1
- package/dist-standalone/index.d.ts +15 -4
- package/dist-standalone/index.js +1 -1
- package/dist-standalone/lazy-init.d.ts +11 -6
- package/dist-standalone/lazy-init.js +1 -1
- package/dist-standalone/loopback-transport.d.ts +87 -0
- package/dist-standalone/loopback-transport.js +1 -0
- package/dist-standalone/mdns-discovery.js +1 -1
- package/dist-standalone/plugins/logging.js +1 -1
- package/dist-standalone/plugins/metrics.d.ts +4 -4
- package/dist-standalone/runtime/edge.js +1 -1
- package/dist-standalone/runtime/react-native.d.ts +1 -1
- package/dist-standalone/security-policy.js +1 -1
- package/dist-standalone/serialization.js +1 -1
- package/dist-standalone/transport.js +1 -1
- package/dist-standalone/trust-registry.d.ts +3 -3
- package/dist-standalone/trust-registry.js +1 -1
- package/dist-standalone/vault-store-loader.d.ts +9 -0
- package/dist-standalone/vault-store-loader.js +1 -1
- package/dist-standalone/version-info.js +1 -1
- package/dist-standalone/xfetch.js +1 -1
- package/package.json +4 -13
- package/share1.dat +0 -0
- package/dist-standalone/_deps/mldsa-wasm/LICENSE +0 -24
- package/dist-standalone/_deps/mldsa-wasm/package.json +0 -46
- package/dist-standalone/_deps/shared/cjs/package.json +0 -1
- package/dist-standalone/_deps/ux-helpers/cjs/package.json +0 -1
- package/dist-standalone/_deps/xchange/cjs/package.json +0 -1
- package/dist-standalone/_deps/xregistry/cjs/package.json +0 -1
- package/dist-standalone/cjs/package.json +0 -3
- package/dist-standalone/package.json +0 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
import{xfetch}from"./xfetch.js";export function createAxiosCompat(){async function t(t){const e="string"==typeof t?{url:t}:t,a=e.method?.toUpperCase()??"GET",r=e.baseURL?new URL(e.url??"",e.baseURL).toString():e.url??"",o={...e.headers};let n,s=r;if(e.params){const t=new URLSearchParams;for(const[a,r]of Object.entries(e.params))t.append(a,String(r));s=`${r}?${t.toString()}`}e.data&&("string"==typeof e.data?n=e.data:(n=JSON.stringify(e.data),o["Content-Type"]="application/json"));const i={method:a,headers:o,body:n,timeout:e.timeout,forceXBind:e.forceXBind,disableXBind:e.disableXBind},c=await xfetch(s,i);let u;switch(e.responseType??"json"){case"json":default:u=await c.json();break;case"text":u=await c.text();break;case"blob":u=await c.blob();break;case"arraybuffer":u=await c.arrayBuffer()}if(e.validateStatus&&!e.validateStatus(c.status))throw new Error(`Request failed with status ${c.status}`);const d={};return c.headers.forEach((t,e)=>{d[e]=t}),{data:u,status:c.status,statusText:c.statusText,headers:d,config:e,xbind:{used:c.usedXBind,protocol:c.transport.protocol,latency:c.transport.latency,peerDID:c.transport.peerDID}}}return{request:t,get:async function(e,a){return t({...a,url:e,method:"GET"})},post:async function(e,a,r){return t({...r,url:e,method:"POST",data:a})},put:async function(e,a,r){return t({...r,url:e,method:"PUT",data:a})},patch:async function(e,a,r){return t({...r,url:e,method:"PATCH",data:a})},delete:async function(e,a){return t({...a,url:e,method:"DELETE"})}}}export function createGotCompat(){async function t(t,e){const a="string"==typeof t?{...e,url:t}:t,r=a.method?.toUpperCase()??"GET",o=a.url??"",n={...a.headers};let s,i=o;if(a.searchParams){const t=new URLSearchParams;for(const[e,r]of Object.entries(a.searchParams))t.append(e,String(r));i=`${o}?${t.toString()}`}a.json?(s=JSON.stringify(a.json),n["Content-Type"]="application/json"):a.body&&(s=a.body instanceof Buffer?a.body.toString():a.body);const c={method:r,headers:n,body:s,timeout:"number"==typeof a.timeout?a.timeout:a.timeout?.request,forceXBind:a.forceXBind,disableXBind:a.disableXBind},u=await xfetch(i,c);let d;switch(a.responseType??"text"){case"json":d=await u.json();break;case"text":default:d=await u.text();break;case"buffer":const t=await u.arrayBuffer();d=Buffer.from(t)}const f={};return u.headers.forEach((t,e)=>{f[e]=t}),{body:d,statusCode:u.status,headers:f,url:u.url,requestUrl:i,xbind:{used:u.usedXBind,protocol:u.transport.protocol,latency:u.transport.latency,peerDID:u.transport.peerDID}}}return t.get=(e,a)=>t(e,{...a,method:"GET"}),t.post=(e,a)=>t(e,{...a,method:"POST"}),t.put=(e,a)=>t(e,{...a,method:"PUT"}),t.patch=(e,a)=>t(e,{...a,method:"PATCH"}),t.delete=(e,a)=>t(e,{...a,method:"DELETE"}),t}export function wrapFetch(){return xfetch}
|
|
1
|
+
import{xfetch}from"./xfetch.js";export function createAxiosCompat(){async function t(t){const e="string"==typeof t?{url:t}:t,a=e.method?.toUpperCase()??"GET",r=e.baseURL?new URL(e.url??"",e.baseURL).toString():e.url??"",o={...e.headers};let n,s=r;if(e.params){const t=new URLSearchParams;for(const[a,r]of Object.entries(e.params))t.append(a,String(r));s=`${r}?${t.toString()}`}e.data&&("string"==typeof e.data?n=e.data:(n=JSON.stringify(e.data),o["Content-Type"]="application/json"));const i={method:a,headers:o,body:n,timeout:e.timeout,forceXBind:e.forceXBind,disableXBind:e.disableXBind},c=await xfetch(s,i);let u;switch(e.responseType??"json"){case"json":default:u=await c.json();break;case"text":u=await c.text();break;case"blob":u=await c.blob();break;case"arraybuffer":u=await c.arrayBuffer()}if(e.validateStatus&&!e.validateStatus(c.status))throw new Error(`Request failed with status ${c.status}`);const d={};return c.headers.forEach((t,e)=>{d[e]=t}),{data:u,status:c.status,statusText:c.statusText,headers:d,config:e,xbind:{used:c.usedXBind,protocol:c.transport.protocol,latency:c.transport.latency,peerDID:c.transport.peerDID}}}return{request:t,get:async function(e,a){return t({...a,url:e,method:"GET"})},post:async function(e,a,r){return t({...r,url:e,method:"POST",data:a})},put:async function(e,a,r){return t({...r,url:e,method:"PUT",data:a})},patch:async function(e,a,r){return t({...r,url:e,method:"PATCH",data:a})},delete:async function(e,a){return t({...a,url:e,method:"DELETE"})}}}export function createGotCompat(){async function t(t,e){const a="string"==typeof t?{...e,url:t}:t,r=a.method?.toUpperCase()??"GET",o=a.url??"",n={...a.headers};let s,i=o;if(a.searchParams){const t=new URLSearchParams;for(const[e,r]of Object.entries(a.searchParams))t.append(e,String(r));i=`${o}?${t.toString()}`}a.json?(s=JSON.stringify(a.json),n["Content-Type"]="application/json"):a.body&&(s=a.body instanceof Buffer?a.body.toString():a.body);const c={method:r,headers:n,body:s,timeout:"number"==typeof a.timeout?a.timeout:a.timeout?.request,forceXBind:a.forceXBind,disableXBind:a.disableXBind},u=await xfetch(i,c);let d;switch(a.responseType??"text"){case"json":d=await u.json();break;case"text":default:d=await u.text();break;case"buffer":{const t=await u.arrayBuffer();d=Buffer.from(t);break}}const f={};return u.headers.forEach((t,e)=>{f[e]=t}),{body:d,statusCode:u.status,headers:f,url:u.url,requestUrl:i,xbind:{used:u.usedXBind,protocol:u.transport.protocol,latency:u.transport.latency,peerDID:u.transport.peerDID}}}return t.get=(e,a)=>t(e,{...a,method:"GET"}),t.post=(e,a)=>t(e,{...a,method:"POST"}),t.put=(e,a)=>t(e,{...a,method:"PUT"}),t.patch=(e,a)=>t(e,{...a,method:"PATCH"}),t.delete=(e,a)=>t(e,{...a,method:"DELETE"}),t}export function wrapFetch(){return xfetch}
|
|
@@ -10,6 +10,7 @@ export type { RedisClient, RedisNonceStoreOptions } from './redis-nonce-store.js
|
|
|
10
10
|
export { RedisNonceStore } from './redis-nonce-store.js';
|
|
11
11
|
export type { XailTransportAdapter, TransportError, EnvelopeHandler, HttpsTransportOptions, } from './transport.js';
|
|
12
12
|
export { HttpsTransportAdapter } from './transport.js';
|
|
13
|
+
export { LoopbackTransport } from './loopback-transport.js';
|
|
13
14
|
export type { RetryOptions } from './retry-transport.js';
|
|
14
15
|
export { RetryTransportAdapter } from './retry-transport.js';
|
|
15
16
|
export type { RetryContext, RetryDecision, ExponentialBackoffConfig, LinearBackoffConfig, FixedDelayConfig, CircuitBreakerConfig, CircuitState, CircuitBreakerStats, IRetryStrategy, } from './retry-strategies.js';
|
|
@@ -19,7 +20,7 @@ export { TimeoutConfig, OperationTimeoutController, TimeoutError, createTimeoutC
|
|
|
19
20
|
export type { QoSLevel, OperationContext, CacheConfig, RetryConfig, CacheEntry, ServiceStatus, } from './graceful-degradation.js';
|
|
20
21
|
export { GracefulDegradationManager, registryLookupWithFallback, sendWithTransportFallback, enhanceError, } from './graceful-degradation.js';
|
|
21
22
|
export type { TrustRegistry, RegistryEntry, RegistryError, HttpTrustRegistryOptions, FileTrustRegistryOptions, } from './trust-registry.js';
|
|
22
|
-
export { MemoryTrustRegistry, HttpTrustRegistry, FileTrustRegistry, createEnterpriseTrustRegistry, } from './trust-registry.js';
|
|
23
|
+
export { MemoryTrustRegistry, HttpTrustRegistry, FileTrustRegistry, createEnterpriseTrustRegistry, RegistrationRateLimiter, } from './trust-registry.js';
|
|
23
24
|
export type { EphemeralKeyPair, KeyAgreementResult, HybridKeyAgreementResult, KeyAgreementError, } from './key-agreement.js';
|
|
24
25
|
export { generateEphemeralKeyPair, importX25519PublicKey, deriveSharedKeyECDH, senderKeyAgreement, receiverKeyAgreement, combineSharedSecrets, senderHybridKeyAgreement, receiverHybridKeyAgreement, } from './key-agreement.js';
|
|
25
26
|
export type { AgentOptions, AgentCreateOptions, AgentSendOptions, AgentMessage, AgentError, AgentReceiveOptions, AgentErrorDetail, } from './agent.js';
|
|
@@ -34,8 +35,8 @@ export type { XFetchOptions, XFetchResponse, } from './xfetch.js';
|
|
|
34
35
|
export { xfetch, isXBindSupported, getXBindCapability, } from './xfetch.js';
|
|
35
36
|
export type { AxiosRequestConfig, AxiosResponse, GotOptions, GotResponse, } from './http-compat.js';
|
|
36
37
|
export { createAxiosCompat, createGotCompat, wrapFetch, } from './http-compat.js';
|
|
37
|
-
export type { SecurityPolicy, SecurityMode, SecurityLevel, SecurityContext, SecurityDecision, } from './security-policy.js';
|
|
38
|
-
export { DefaultSecurityPolicy, describeSecurityMode } from './security-policy.js';
|
|
38
|
+
export type { SecurityPolicy, SecurityMode, SecurityLevel, SecurityContext, SecurityDecision, SecurityModeDescription, } from './security-policy.js';
|
|
39
|
+
export { DefaultSecurityPolicy, describeSecurityMode, describeSecurityModeStructured } from './security-policy.js';
|
|
39
40
|
export type { PolicyResult, PolicyViolationDetails, PolicyLimits } from './policy.js';
|
|
40
41
|
export { PolicyEngine, getGlobalPolicyEngine } from './policy.js';
|
|
41
42
|
export type { ApprovalOptions, ApprovalToken, ApprovalResult, ApprovalPresenter, } from './approval.js';
|
|
@@ -56,7 +57,15 @@ export { requestAuth, respondToChallenge, onChallenge, generateRegistrationQR, }
|
|
|
56
57
|
export type { XchangeKey, XchangeError } from '@private.me/xchange';
|
|
57
58
|
export { generateXchangeKey, xchangeEncrypt, xchangeDecrypt } from '@private.me/xchange';
|
|
58
59
|
export { AES_KEY_BYTES, AES_IV_BYTES, BUNDLE_HEADER_BYTES } from '@private.me/xchange';
|
|
59
|
-
export {
|
|
60
|
+
export { setMockCrypto, clearCryptoCache } from './crypto-utils.js';
|
|
61
|
+
export type { CryptoPackage } from './vault-store-loader.js';
|
|
62
|
+
export { XBindError, XBindIdentityError, XBindEnvelopeError, XBindTransportError, XBindRegistryError, XBindKeyAgreementError, XBindSplitChannelError, XBindAgentError, XBindBillingError, VaultStoreError, QuotaExceededError, toXBindError, isXBindError, createXBindErrorDetail, } from './errors.js';
|
|
63
|
+
import type { XBindTransportError, XBindIdentityError, XBindEnvelopeError, XBindBillingError, XBindAgentError } from './errors.js';
|
|
64
|
+
export type ConnectionError = XBindTransportError;
|
|
65
|
+
export type AuthenticationError = XBindIdentityError;
|
|
66
|
+
export type ValidationError = XBindEnvelopeError;
|
|
67
|
+
export type RateLimitError = XBindBillingError;
|
|
68
|
+
export type ServerError = XBindAgentError;
|
|
60
69
|
export type { ValidationResult } from './config-validation.js';
|
|
61
70
|
export { ConfigValidationError, validateAgentOptions, validateAgentCreateOptions, getValidationDetails, assertValidConfig, assertValidCreateConfig, AGENT_OPTIONS_DEFAULTS, AGENT_CREATE_OPTIONS_DEFAULTS, } from './config-validation.js';
|
|
62
71
|
export type { ProgressCallback, ACIErrorDetail, ACIErrorOptions, PaginationOptions, PaginatedResult, SearchOptions, } from '@private.me/ux-helpers';
|
|
@@ -125,3 +134,5 @@ export type { SerializationFormat, SerializationOptions, SerializedData, Deseria
|
|
|
125
134
|
export { serialize, deserialize, detectFormat, negotiateFormat, compareFormats, getContentType, parseContentType, } from './serialization.js';
|
|
126
135
|
export type { ConnectionPoolOptions, ConnectionPoolMetrics, } from './connection-pool.js';
|
|
127
136
|
export { ConnectionPool, getGlobalPool, resetGlobalPool, } from './connection-pool.js';
|
|
137
|
+
export type { Result } from '@private.me/shared';
|
|
138
|
+
export { err, ok } from '@private.me/shared';
|
package/dist-standalone/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{initCommand,main as cliMain}from"./cli/init.js";export{generateIdentity,sign,verify,importPublicKey,publicKeyToDid,didToPublicKeyBytes,exportPKCS8,exportX25519PKCS8,importFromPKCS8,importIdentity,identityFromSeed,extractRawEd25519,extractRawX25519,exportMlKemSecretKey,exportMlKemPublicKey,signMlDsa65,verifyMlDsa65,exportMlDsaSecretKey,exportMlDsaPublicKey,rotateKeys,ML_DSA65_SIG_BYTES,ML_DSA65_PK_BYTES,ML_DSA65_SK_BYTES}from"./identity.js";export{createEnvelope,createEnvelopeV2,createEnvelopeV3,createEnvelopeV4,decryptPayload,serializeEnvelope,deserializeEnvelope,validateEnvelope,generateSharedKey,createSignedEnvelope,openSignedEnvelope}from"./envelope.js";export{MemoryNonceStore}from"./nonce-store.js";export{RedisNonceStore}from"./redis-nonce-store.js";export{HttpsTransportAdapter}from"./transport.js";export{RetryTransportAdapter}from"./retry-transport.js";export{ExponentialBackoffStrategy,LinearBackoffStrategy,FixedDelayStrategy,NoRetryStrategy,CircuitBreaker,RetryStrategy,executeWithRetry}from"./retry-strategies.js";export{TimeoutConfig,OperationTimeoutController,TimeoutError,createTimeoutController,withTimeout,withTimeoutResult,createOperationTimeoutSignal,createOperationTimeout,isTimeoutError,getTimeoutFromError,createTimeoutConfigFromEnv,globalTimeoutConfig,DEFAULT_TIMEOUTS}from"./timeouts.js";export{GracefulDegradationManager,registryLookupWithFallback,sendWithTransportFallback,enhanceError}from"./graceful-degradation.js";export{MemoryTrustRegistry,HttpTrustRegistry,FileTrustRegistry,createEnterpriseTrustRegistry}from"./trust-registry.js";export{generateEphemeralKeyPair,importX25519PublicKey,deriveSharedKeyECDH,senderKeyAgreement,receiverKeyAgreement,combineSharedSecrets,senderHybridKeyAgreement,receiverHybridKeyAgreement}from"./key-agreement.js";export{Agent,parseAgentError}from"./agent.js";export{MessageStream,collectMessages,mapStream,filterStream,takeStream,mergeStreams,installAsyncIterators}from"./async-iterators.js";export{call,batchCall,stream,AgentErrorCode,ERROR_DETAILS,setToolRegistry,getToolRegistry}from"./agent-call.js";export{AgentError as AgentCallError}from"./agent-call.js";export{xfetch,isXBindSupported,getXBindCapability}from"./xfetch.js";export{createAxiosCompat,createGotCompat,wrapFetch}from"./http-compat.js";export{DefaultSecurityPolicy,describeSecurityMode}from"./security-policy.js";export{PolicyEngine,getGlobalPolicyEngine}from"./policy.js";export{ApprovalFlow,CLIApprovalPresenter,ApprovalError,ApprovalErrorCode}from"./approval.js";export{PolicyDenied,Guardrails,extractSuggestion,toPolicyDenied}from"./guardrails.js";export{createRegistryAuthMiddleware}from"./registry-middleware.js";export{GatewayTransport}from"./gateway-transport.js";export{DidWebResolver,didWebToUrl}from"./did-web.js";export{generateDidDocument,resolveDid,getServiceEndpoints}from"./did-document.js";export{publicKeyToPrivateMeDid,privateMeDidToPublicKeyBytes,isPrivateMeDid,isDidKeyFormat,convertDidFormat,normalizeDid,parseDid}from"./did-privateme.js";export{splitForChannel,splitForChannelWithGroupId,reconstructFromChannel,DEFAULT_SPLIT_CONFIG}from"./split-channel.js";export{requestAuth,respondToChallenge,onChallenge,generateRegistrationQR}from"./auth.js";export{generateXchangeKey,xchangeEncrypt,xchangeDecrypt}from"./_deps/xchange/index.js";export{AES_KEY_BYTES,AES_IV_BYTES,BUNDLE_HEADER_BYTES}from"./_deps/xchange/index.js";export{XBindError,XBindIdentityError,XBindEnvelopeError,XBindTransportError,XBindRegistryError,XBindKeyAgreementError,XBindSplitChannelError,XBindAgentError,toXBindError,isXBindError,createXBindErrorDetail}from"./errors.js";export{ConfigValidationError,validateAgentOptions,validateAgentCreateOptions,getValidationDetails,assertValidConfig,assertValidCreateConfig,AGENT_OPTIONS_DEFAULTS,AGENT_CREATE_OPTIONS_DEFAULTS}from"./config-validation.js";export{ProgressReporter,createStagedProgress,createDetailedError,formatErrorForUser,formatErrorForLog,isACIError,toACIError,paginate,createPaginationMetadata,search}from"./_deps/ux-helpers/index.js";export{OperationProgressTracker,TransferProgressTracker,ShareDistributionTracker,EncryptionProgressTracker}from"./progress-callbacks.js";export{ServiceDiscovery,DiscoveryErrorCode}from"./discovery.js";export{MdnsDiscoveryManager}from"./mdns-discovery.js";export{InviteService,InviteErrorCode}from"./invite.js";export{DualModeAdapter,DualModeErrorCode}from"./dual-mode.js";export{PairingManager}from"./pairing-manager.js";export{connect,acceptInvite,ConnectErrorCode}from"./connect.js";export{autoAcceptInvite,AutoAcceptErrorCode}from"./auto-accept.js";export{LazyAgent,createLazyAgent,LazyAgentErrorCode}from"./lazy-init.js";export{InvitationErrorCode,InvitationClient,InvitationStore,generateInvitationToken}from"./invitation.js";export{AgentBuilder}from"./agent-sdk.js";export{createSuccession,verifySuccession,encodeSuccession,decodeSuccession}from"./succession.js";export{GatewayConnectionState}from"./gateway-state.js";export{createCheckpoint,verifyCheckpoint,isCacheStale,encodeCheckpoint,decodeCheckpoint}from"./checkpoint.js";export{createSubscriptionProof,verifySubscriptionProof,resumeSubscription,hashBloomFilter}from"./subscription-proof.js";export{DEFAULT_BACKUP_CONFIG,validateBackupConfig,splitKeyWithBackup,reconstructKeyFromBackup}from"./backup-config.js";export{exportBackup,importBackup}from"./backup.js";export{generateCorrelationId,validateCorrelationId,parseCorrelationId,attachCorrelationId,extractCorrelationId,getOrCreateCorrelationId,createCorrelationIdFromTimestamp,getCorrelationIdAge,isCorrelationIdExpired,correlationIdMiddleware,CORRELATION_ID_HEADER,CORRELATION_ID_ALIASES}from"./correlation-id.js";export{createLogger,LogLevel,getGlobalLogger,setGlobalLogger,logger}from"./logger.js";export{CancellationError,createTimeoutSignal,combineSignals,onCancellation,throwIfAborted,withCancellation,delay,withRetry,createCancellationController,isCancellationError}from"./cancellation.js";export{enableDebugMode,disableDebugMode,isDebugEnabled,getDebugOptions,createDebugLogger,startProfiling,endProfiling,getPerformanceMeasurements,clearPerformanceMeasurements,traceNetworkRequest,traceNetworkResponse,getNetworkTraces,clearNetworkTraces,traceCryptoOperation,getCryptoTraces,clearCryptoTraces,dumpState,getStateSnapshots,clearStateSnapshots,exportDebugData,clearAllDebugData,generateDebugReport}from"./debug-mode.js";export{getVersion,hasCapability,getCapabilities,getDeprecationInfo,warnIfDeprecated,parseVersion,compareVersions,checkCompatibility,getMinimumVersionFor,assertMinimumVersion,Capability}from"./version-info.js";export{createHealthChecker,healthEndpoint}from"./health-check.js";export{batchSend,batchReceive,batchRegistryOps,batchResolve,batchGetEntries,BatchOperationError}from"./batch-operations.js";export{detectRuntime,isBrowser,isNode,isServiceWorker,getRandomBytes,generateUUID,LocalStorageAdapter,IndexedDBAdapter,MemoryStorageAdapter,isWasmSupported,loadWasmModule,detectCapabilities,installNodePolyfills,initServiceWorker,DEFAULT_SERVICE_WORKER_CONFIG}from"./runtime/browser.js";import{installAsyncIterators as _installAsyncIterators}from"./async-iterators.js";import{Agent as _Agent}from"./agent.js";_installAsyncIterators(_Agent);export{XBindEventEmitter,createScopedEmitter}from"./event-emitter.js";export{MiddlewareChain,createPluginContext,createPlugin,PluginBuilder}from"./plugin-system.js";export{LoggingPlugin,createLoggingPlugin}from"./plugins/logging.js";export{MetricsPlugin,createMetricsPlugin}from"./plugins/metrics.js";export{ValidationPlugin,createValidationPlugin,CommonRules}from"./plugins/validation.js";export{serialize,deserialize,detectFormat,negotiateFormat,compareFormats,getContentType,parseContentType}from"./serialization.js";export{ConnectionPool,getGlobalPool,resetGlobalPool}from"./connection-pool.js";
|
|
1
|
+
export{initCommand,main as cliMain}from"./cli/init.js";export{generateIdentity,sign,verify,importPublicKey,publicKeyToDid,didToPublicKeyBytes,exportPKCS8,exportX25519PKCS8,importFromPKCS8,importIdentity,identityFromSeed,extractRawEd25519,extractRawX25519,exportMlKemSecretKey,exportMlKemPublicKey,signMlDsa65,verifyMlDsa65,exportMlDsaSecretKey,exportMlDsaPublicKey,rotateKeys,ML_DSA65_SIG_BYTES,ML_DSA65_PK_BYTES,ML_DSA65_SK_BYTES}from"./identity.js";export{createEnvelope,createEnvelopeV2,createEnvelopeV3,createEnvelopeV4,decryptPayload,serializeEnvelope,deserializeEnvelope,validateEnvelope,generateSharedKey,createSignedEnvelope,openSignedEnvelope}from"./envelope.js";export{MemoryNonceStore}from"./nonce-store.js";export{RedisNonceStore}from"./redis-nonce-store.js";export{HttpsTransportAdapter}from"./transport.js";export{LoopbackTransport}from"./loopback-transport.js";export{RetryTransportAdapter}from"./retry-transport.js";export{ExponentialBackoffStrategy,LinearBackoffStrategy,FixedDelayStrategy,NoRetryStrategy,CircuitBreaker,RetryStrategy,executeWithRetry}from"./retry-strategies.js";export{TimeoutConfig,OperationTimeoutController,TimeoutError,createTimeoutController,withTimeout,withTimeoutResult,createOperationTimeoutSignal,createOperationTimeout,isTimeoutError,getTimeoutFromError,createTimeoutConfigFromEnv,globalTimeoutConfig,DEFAULT_TIMEOUTS}from"./timeouts.js";export{GracefulDegradationManager,registryLookupWithFallback,sendWithTransportFallback,enhanceError}from"./graceful-degradation.js";export{MemoryTrustRegistry,HttpTrustRegistry,FileTrustRegistry,createEnterpriseTrustRegistry,RegistrationRateLimiter}from"./trust-registry.js";export{generateEphemeralKeyPair,importX25519PublicKey,deriveSharedKeyECDH,senderKeyAgreement,receiverKeyAgreement,combineSharedSecrets,senderHybridKeyAgreement,receiverHybridKeyAgreement}from"./key-agreement.js";export{Agent,parseAgentError}from"./agent.js";export{MessageStream,collectMessages,mapStream,filterStream,takeStream,mergeStreams,installAsyncIterators}from"./async-iterators.js";export{call,batchCall,stream,AgentErrorCode,ERROR_DETAILS,setToolRegistry,getToolRegistry}from"./agent-call.js";export{AgentError as AgentCallError}from"./agent-call.js";export{xfetch,isXBindSupported,getXBindCapability}from"./xfetch.js";export{createAxiosCompat,createGotCompat,wrapFetch}from"./http-compat.js";export{DefaultSecurityPolicy,describeSecurityMode,describeSecurityModeStructured}from"./security-policy.js";export{PolicyEngine,getGlobalPolicyEngine}from"./policy.js";export{ApprovalFlow,CLIApprovalPresenter,ApprovalError,ApprovalErrorCode}from"./approval.js";export{PolicyDenied,Guardrails,extractSuggestion,toPolicyDenied}from"./guardrails.js";export{createRegistryAuthMiddleware}from"./registry-middleware.js";export{GatewayTransport}from"./gateway-transport.js";export{DidWebResolver,didWebToUrl}from"./did-web.js";export{generateDidDocument,resolveDid,getServiceEndpoints}from"./did-document.js";export{publicKeyToPrivateMeDid,privateMeDidToPublicKeyBytes,isPrivateMeDid,isDidKeyFormat,convertDidFormat,normalizeDid,parseDid}from"./did-privateme.js";export{splitForChannel,splitForChannelWithGroupId,reconstructFromChannel,DEFAULT_SPLIT_CONFIG}from"./split-channel.js";export{requestAuth,respondToChallenge,onChallenge,generateRegistrationQR}from"./auth.js";export{generateXchangeKey,xchangeEncrypt,xchangeDecrypt}from"./_deps/xchange/index.js";export{AES_KEY_BYTES,AES_IV_BYTES,BUNDLE_HEADER_BYTES}from"./_deps/xchange/index.js";export{setMockCrypto,clearCryptoCache}from"./crypto-utils.js";export{XBindError,XBindIdentityError,XBindEnvelopeError,XBindTransportError,XBindRegistryError,XBindKeyAgreementError,XBindSplitChannelError,XBindAgentError,XBindBillingError,VaultStoreError,QuotaExceededError,toXBindError,isXBindError,createXBindErrorDetail}from"./errors.js";export{ConfigValidationError,validateAgentOptions,validateAgentCreateOptions,getValidationDetails,assertValidConfig,assertValidCreateConfig,AGENT_OPTIONS_DEFAULTS,AGENT_CREATE_OPTIONS_DEFAULTS}from"./config-validation.js";export{ProgressReporter,createStagedProgress,createDetailedError,formatErrorForUser,formatErrorForLog,isACIError,toACIError,paginate,createPaginationMetadata,search}from"./_deps/ux-helpers/index.js";export{OperationProgressTracker,TransferProgressTracker,ShareDistributionTracker,EncryptionProgressTracker}from"./progress-callbacks.js";export{ServiceDiscovery,DiscoveryErrorCode}from"./discovery.js";export{MdnsDiscoveryManager}from"./mdns-discovery.js";export{InviteService,InviteErrorCode}from"./invite.js";export{DualModeAdapter,DualModeErrorCode}from"./dual-mode.js";export{PairingManager}from"./pairing-manager.js";export{connect,acceptInvite,ConnectErrorCode}from"./connect.js";export{autoAcceptInvite,AutoAcceptErrorCode}from"./auto-accept.js";export{LazyAgent,createLazyAgent,LazyAgentErrorCode}from"./lazy-init.js";export{InvitationErrorCode,InvitationClient,InvitationStore,generateInvitationToken}from"./invitation.js";export{AgentBuilder}from"./agent-sdk.js";export{createSuccession,verifySuccession,encodeSuccession,decodeSuccession}from"./succession.js";export{GatewayConnectionState}from"./gateway-state.js";export{createCheckpoint,verifyCheckpoint,isCacheStale,encodeCheckpoint,decodeCheckpoint}from"./checkpoint.js";export{createSubscriptionProof,verifySubscriptionProof,resumeSubscription,hashBloomFilter}from"./subscription-proof.js";export{DEFAULT_BACKUP_CONFIG,validateBackupConfig,splitKeyWithBackup,reconstructKeyFromBackup}from"./backup-config.js";export{exportBackup,importBackup}from"./backup.js";export{generateCorrelationId,validateCorrelationId,parseCorrelationId,attachCorrelationId,extractCorrelationId,getOrCreateCorrelationId,createCorrelationIdFromTimestamp,getCorrelationIdAge,isCorrelationIdExpired,correlationIdMiddleware,CORRELATION_ID_HEADER,CORRELATION_ID_ALIASES}from"./correlation-id.js";export{createLogger,LogLevel,getGlobalLogger,setGlobalLogger,logger}from"./logger.js";export{CancellationError,createTimeoutSignal,combineSignals,onCancellation,throwIfAborted,withCancellation,delay,withRetry,createCancellationController,isCancellationError}from"./cancellation.js";export{enableDebugMode,disableDebugMode,isDebugEnabled,getDebugOptions,createDebugLogger,startProfiling,endProfiling,getPerformanceMeasurements,clearPerformanceMeasurements,traceNetworkRequest,traceNetworkResponse,getNetworkTraces,clearNetworkTraces,traceCryptoOperation,getCryptoTraces,clearCryptoTraces,dumpState,getStateSnapshots,clearStateSnapshots,exportDebugData,clearAllDebugData,generateDebugReport}from"./debug-mode.js";export{getVersion,hasCapability,getCapabilities,getDeprecationInfo,warnIfDeprecated,parseVersion,compareVersions,checkCompatibility,getMinimumVersionFor,assertMinimumVersion,Capability}from"./version-info.js";export{createHealthChecker,healthEndpoint}from"./health-check.js";export{batchSend,batchReceive,batchRegistryOps,batchResolve,batchGetEntries,BatchOperationError}from"./batch-operations.js";export{detectRuntime,isBrowser,isNode,isServiceWorker,getRandomBytes,generateUUID,LocalStorageAdapter,IndexedDBAdapter,MemoryStorageAdapter,isWasmSupported,loadWasmModule,detectCapabilities,installNodePolyfills,initServiceWorker,DEFAULT_SERVICE_WORKER_CONFIG}from"./runtime/browser.js";import{installAsyncIterators as _installAsyncIterators}from"./async-iterators.js";import{Agent as _Agent}from"./agent.js";_installAsyncIterators(_Agent);export{XBindEventEmitter,createScopedEmitter}from"./event-emitter.js";export{MiddlewareChain,createPluginContext,createPlugin,PluginBuilder}from"./plugin-system.js";export{LoggingPlugin,createLoggingPlugin}from"./plugins/logging.js";export{MetricsPlugin,createMetricsPlugin}from"./plugins/metrics.js";export{ValidationPlugin,createValidationPlugin,CommonRules}from"./plugins/validation.js";export{serialize,deserialize,detectFormat,negotiateFormat,compareFormats,getContentType,parseContentType}from"./serialization.js";export{ConnectionPool,getGlobalPool,resetGlobalPool}from"./connection-pool.js";export{err,ok}from"./_deps/shared/index.js";
|
|
@@ -76,12 +76,14 @@ export declare class LazyAgent {
|
|
|
76
76
|
private agent;
|
|
77
77
|
private initPromise;
|
|
78
78
|
private lastError;
|
|
79
|
-
|
|
79
|
+
private _did;
|
|
80
|
+
private _identity;
|
|
81
|
+
constructor(config: LazyAgentConfig, identity: import('./identity.js').AgentIdentity);
|
|
80
82
|
/**
|
|
81
83
|
* Get the agent's DID.
|
|
82
84
|
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
+
* Returns the pre-generated DID immediately (no initialization required).
|
|
86
|
+
* This allows accessing `agent.did` right after `Agent.lazy()` returns.
|
|
85
87
|
*/
|
|
86
88
|
get did(): string;
|
|
87
89
|
/**
|
|
@@ -154,9 +156,12 @@ export declare class LazyAgent {
|
|
|
154
156
|
* ```ts
|
|
155
157
|
* // Environment: XBIND_INVITE_CODE=XBD-abc123
|
|
156
158
|
*
|
|
157
|
-
* const agent =
|
|
159
|
+
* const agent = await Agent.lazy({ name: 'my-service' });
|
|
158
160
|
*
|
|
159
|
-
* //
|
|
161
|
+
* // DID is available immediately:
|
|
162
|
+
* console.log(agent.did); // did:key:z6Mk...
|
|
163
|
+
*
|
|
164
|
+
* // Full initialization happens on first send:
|
|
160
165
|
* await agent.send({
|
|
161
166
|
* to: 'did:key:z6Mk...',
|
|
162
167
|
* payload: { action: 'test' },
|
|
@@ -164,4 +169,4 @@ export declare class LazyAgent {
|
|
|
164
169
|
* });
|
|
165
170
|
* ```
|
|
166
171
|
*/
|
|
167
|
-
export declare function createLazyAgent(config: LazyAgentConfig): LazyAgent
|
|
172
|
+
export declare function createLazyAgent(config: LazyAgentConfig): Promise<LazyAgent>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ok,err}from"./_deps/shared/index.js";import{
|
|
1
|
+
import{ok,err}from"./_deps/shared/index.js";import{autoAcceptInvite}from"./auto-accept.js";import{MemoryTrustRegistry}from"./trust-registry.js";import{HttpsTransportAdapter}from"./transport.js";import{toBase64}from"./crypto-utils.js";export var LazyAgentErrorCode;!function(t){t.INIT_FAILED="LAZY_AGENT_INIT_FAILED",t.AUTO_ACCEPT_FAILED="LAZY_AGENT_AUTO_ACCEPT_FAILED",t.AGENT_CREATION_FAILED="LAZY_AGENT_AGENT_CREATION_FAILED"}(LazyAgentErrorCode||(LazyAgentErrorCode={}));export class LazyAgent{config;agent=null;initPromise=null;lastError=null;_did;_identity;constructor(t,e){this.config=t,this._identity=e,this._did=e.did}get did(){return this._did}isReady(){return null!==this.agent}getLastError(){return this.lastError}async ensureInitialized(){if(this.agent)return ok(this.agent);if(this.initPromise)return this.initPromise;this.initPromise=this.initialize();const t=await this.initPromise;return this.initPromise=null,t.ok?(this.agent=t.value,this.lastError=null):this.lastError={code:LazyAgentErrorCode.INIT_FAILED,message:`Agent initialization failed: ${t.error}`,cause:t.error},t}async initialize(){const t=this.config.inviteCode??this.getEnv("XBIND_INVITE_CODE");let e=this.config.registry,i=this.config.transport;const r=this.config.endpoint??this.getEnv("XBIND_ENDPOINT")??"";if(t){const n=toBase64(this._identity.rawPublicKey),s=this._identity.rawX25519PublicKey?toBase64(this._identity.rawX25519PublicKey):void 0,o=await autoAcceptInvite({inviteCode:t,enabled:!0,registry:this.config.autoAccept?.registry,inviteApiUrl:this.config.autoAccept?.inviteApiUrl},{name:this.config.name,did:this._identity.did,endpoint:r,publicKey:n,x25519PublicKey:s});o.ok?(!e&&o.value.registryAutoconfigured&&(e=this.config.autoAccept?.registry??new MemoryTrustRegistry),i||(i=new HttpsTransportAdapter({baseUrl:o.value.from.endpoint}))):this.lastError={code:LazyAgentErrorCode.AUTO_ACCEPT_FAILED,message:o.error.message,hint:o.error.hint,cause:o.error}}const n=e??new MemoryTrustRegistry,s=i??new HttpsTransportAdapter({baseUrl:r||"http://localhost"}),o=await n.register(this._identity.did,this._identity.rawPublicKey,this.config.name,void 0,this._identity.rawX25519PublicKey,this._identity.mlKemPublicKey,this._identity.mlDsaPublicKey,this.config.xchange??!1);if(!o.ok){this.lastError={code:LazyAgentErrorCode.AGENT_CREATION_FAILED,message:`Agent registration failed: ${o.error}`,cause:o.error};const t="ALREADY_REGISTERED"===o.error?"REGISTRATION_FAILED:ALREADY_REGISTERED":"NETWORK_ERROR"===o.error?"REGISTRATION_FAILED:NETWORK_ERROR":"REGISTRATION_FAILED";return err(t)}const{MemoryNonceStore:a}=await import("./nonce-store.js"),{DefaultSecurityPolicy:c}=await import("./security-policy.js"),d=new a,u=Array.isArray(s)?s:[s],l=new(0,(await import("./agent.js")).Agent)(this._identity,this.config.name,n,u,d,3e4,new c,void 0);return this.agent=l,ok(l)}async send(t){const e=await this.ensureInitialized();return e.ok?e.value.send(t):e}async receive(t,e){const i=await this.ensureInitialized();return i.ok?i.value.receive(t,e):err(i.error)}async receiveSplitShare(t){const e=await this.ensureInitialized();return e.ok?e.value.receiveSplitShare(t):err(e.error)}getEnv(t){return"undefined"!=typeof process&&void 0!==process.env?process.env[t]??"":""}getAgent(){if(!this.agent)throw new Error("Agent not initialized. Call send/receive first or await ensureInitialized().");return this.agent}}export async function createLazyAgent(t){const{generateIdentity:e}=await import("./identity.js"),i=await e({postQuantumSig:t.postQuantumSig});if(!i.ok)throw new Error(`Failed to generate identity: ${i.error}`);return new LazyAgent(t,i.value)}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { XailTransportAdapter, EnvelopeHandler } from './transport.js';
|
|
2
|
+
import type { TransportEnvelope } from './envelope.js';
|
|
3
|
+
/**
|
|
4
|
+
* In-memory loopback transport for testing send/receive flows.
|
|
5
|
+
*
|
|
6
|
+
* LoopbackTransport enables testing Agent communication without network dependencies.
|
|
7
|
+
* Messages sent through this transport are immediately delivered to all registered handlers
|
|
8
|
+
* within the same process.
|
|
9
|
+
*
|
|
10
|
+
* **Use Cases:**
|
|
11
|
+
* - Unit testing Agent send/receive functionality
|
|
12
|
+
* - Integration testing multi-agent workflows (Alice → Bob)
|
|
13
|
+
* - Development/debugging of Agent communication patterns
|
|
14
|
+
* - CI/CD pipelines (no external dependencies)
|
|
15
|
+
*
|
|
16
|
+
* **Features:**
|
|
17
|
+
* - Zero network latency (synchronous delivery)
|
|
18
|
+
* - Message history tracking (`.sent` array)
|
|
19
|
+
* - Multiple handler support (broadcast to all receivers)
|
|
20
|
+
* - Clean disposal (removes all handlers)
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { Agent, MemoryTrustRegistry, LoopbackTransport } from '@private.me/xbind';
|
|
25
|
+
*
|
|
26
|
+
* const registry = new MemoryTrustRegistry();
|
|
27
|
+
* const transport = new LoopbackTransport();
|
|
28
|
+
*
|
|
29
|
+
* // Create two agents sharing the same transport
|
|
30
|
+
* const alice = await Agent.quickstart({ name: 'Alice', registry, transport });
|
|
31
|
+
* const bob = await Agent.quickstart({ name: 'Bob', registry, transport });
|
|
32
|
+
*
|
|
33
|
+
* // Alice sends to Bob
|
|
34
|
+
* await alice.send({
|
|
35
|
+
* to: bob.did,
|
|
36
|
+
* payload: { type: 'greeting', text: 'Hello Bob!' },
|
|
37
|
+
* scope: 'chat',
|
|
38
|
+
* });
|
|
39
|
+
*
|
|
40
|
+
* // Bob receives (via transport.onReceive handler)
|
|
41
|
+
* const envelope = transport.sent[0]!;
|
|
42
|
+
* const msg = await bob.receive(envelope);
|
|
43
|
+
* console.log(msg.value.payload); // { type: 'greeting', text: 'Hello Bob!' }
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @see {@link https://private.me/docs/xbind.html#getting-started} - Getting Started guide
|
|
47
|
+
* @see {@link Agent.quickstart} - Zero-config Agent creation
|
|
48
|
+
* @see {@link MemoryTrustRegistry} - In-memory trust registry for testing
|
|
49
|
+
*/
|
|
50
|
+
export declare class LoopbackTransport implements XailTransportAdapter {
|
|
51
|
+
/**
|
|
52
|
+
* Array of all envelopes sent through this transport.
|
|
53
|
+
* Useful for testing/debugging to inspect message history.
|
|
54
|
+
*/
|
|
55
|
+
readonly sent: {
|
|
56
|
+
envelope: TransportEnvelope;
|
|
57
|
+
to: string;
|
|
58
|
+
}[];
|
|
59
|
+
private handlers;
|
|
60
|
+
/**
|
|
61
|
+
* Sends an envelope to a recipient DID.
|
|
62
|
+
*
|
|
63
|
+
* In LoopbackTransport, this immediately delivers the envelope to all registered
|
|
64
|
+
* handlers (via `onReceive`). The envelope is also stored in the `.sent` array.
|
|
65
|
+
*
|
|
66
|
+
* @param envelope - The transport envelope to send
|
|
67
|
+
* @param recipientDid - The DID of the recipient
|
|
68
|
+
* @returns Always succeeds with `ok(undefined)`
|
|
69
|
+
*/
|
|
70
|
+
send(envelope: TransportEnvelope, recipientDid: string): Promise<import("@private.me/shared").Result<undefined, never>>;
|
|
71
|
+
/**
|
|
72
|
+
* Registers a handler to be called when envelopes are received.
|
|
73
|
+
*
|
|
74
|
+
* Multiple handlers can be registered. All handlers will be called
|
|
75
|
+
* for each envelope sent through this transport.
|
|
76
|
+
*
|
|
77
|
+
* @param handler - Function to call with received envelopes
|
|
78
|
+
*/
|
|
79
|
+
onReceive(handler: EnvelopeHandler): void;
|
|
80
|
+
/**
|
|
81
|
+
* Cleans up the transport by removing all handlers.
|
|
82
|
+
*
|
|
83
|
+
* Call this method when done with the transport to prevent memory leaks
|
|
84
|
+
* in long-running test suites.
|
|
85
|
+
*/
|
|
86
|
+
dispose(): void;
|
|
87
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ok}from"./_deps/shared/index.js";export class LoopbackTransport{sent=[];handlers=[];async send(s,e){this.sent.push({envelope:s,to:e});for(const e of this.handlers)e(s);return ok(void 0)}onReceive(s){this.handlers.push(s)}dispose(){this.handlers=[]}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import Bonjour from"bonjour-service";import{ok,err}from"./_deps/shared/index.js";export var DiscoveryErrorCode;!function(e){e.NETWORK_ERROR="NETWORK_ERROR",e.TIMEOUT="TIMEOUT",e.NO_SERVICES="NO_SERVICES",e.INVALID_SERVICE="INVALID_SERVICE"}(DiscoveryErrorCode||(DiscoveryErrorCode={}));export class MdnsDiscoveryManager{bonjour;service=null;serviceType="privateme";protocol="tcp";port=58472;constructor(){this.bonjour=new Bonjour}advertise(e,o,r=this.port){this.service&&this.service.stop?.(),this.service=this.bonjour.publish({name:e,type:this.serviceType,protocol:this.protocol,port:r,txt:{did:o,endpoint:`http://localhost:${r}`,name:e}})}async scan(e,o=5e3){return new Promise(r=>{const t=new Map;let s=!1;const i=this.bonjour.find({type:this.serviceType,protocol:this.protocol});i.on("up",o=>{try{const r=o.txt;if(!r||!r.did||!r.name)return;if(r.did===e)return;const s=r.endpoint||`http://${o.host||"localhost"}:${o.port}`,i=(o.addresses||[]).filter(e=>e.includes(".")&&!e.includes(":")),n={name:r.name,did:r.did,endpoint:s,addresses:i,port:o.port||this.port};t.set(r.did,n)}catch
|
|
1
|
+
import Bonjour from"bonjour-service";import{ok,err}from"./_deps/shared/index.js";export var DiscoveryErrorCode;!function(e){e.NETWORK_ERROR="NETWORK_ERROR",e.TIMEOUT="TIMEOUT",e.NO_SERVICES="NO_SERVICES",e.INVALID_SERVICE="INVALID_SERVICE"}(DiscoveryErrorCode||(DiscoveryErrorCode={}));export class MdnsDiscoveryManager{bonjour;service=null;serviceType="privateme";protocol="tcp";port=58472;constructor(){this.bonjour=new Bonjour}advertise(e,o,r=this.port){this.service&&this.service.stop?.(),this.service=this.bonjour.publish({name:e,type:this.serviceType,protocol:this.protocol,port:r,txt:{did:o,endpoint:`http://localhost:${r}`,name:e}})}async scan(e,o=5e3){return new Promise(r=>{const t=new Map;let s=!1;const i=this.bonjour.find({type:this.serviceType,protocol:this.protocol});i.on("up",o=>{try{const r=o.txt;if(!r||!r.did||!r.name)return;if(r.did===e)return;const s=r.endpoint||`http://${o.host||"localhost"}:${o.port}`,i=(o.addresses||[]).filter(e=>e.includes(".")&&!e.includes(":")),n={name:r.name,did:r.did,endpoint:s,addresses:i,port:o.port||this.port};t.set(r.did,n)}catch{}});const n=setTimeout(()=>{s||(s=!0,i.stop(),0===t.size?r(err({code:DiscoveryErrorCode.NO_SERVICES,message:"No devices found on local network",hint:"Ensure both devices are on the same Wi-Fi network"})):r(ok(Array.from(t.values()))))},o);i.on("error",e=>{s||(s=!0,clearTimeout(n),i.stop(),r(err({code:DiscoveryErrorCode.NETWORK_ERROR,message:e.message,hint:"Check firewall settings and network connectivity"})))})})}stopAdvertising(){this.service&&(this.service.stop?.(),this.service=null)}destroy(){this.stopAdvertising(),this.bonjour.destroy()}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ok}from"../_deps/shared/index.js";export var LogLevel;!function(e){e.DEBUG="debug",e.INFO="info",e.WARN="warn",e.ERROR="error"}(LogLevel||(LogLevel={}));export class LoggingPlugin{name="logging";version="1.0.0";description="Captures message processing events for debugging and audit trails";priority=10;options;logs=[];constructor(e={}){this.options={level:e.level??LogLevel.INFO,includeSize:e.includeSize??!0,includeMetadata:e.includeMetadata??!1,logHandler:e.logHandler??(e=>console.log(JSON.stringify(e))),filter:e.filter??(()=>!0)}}onInit(){return this.log({timestamp:(new Date).toISOString(),level:LogLevel.INFO,event:"send",agent:"system",metadata:{message:"Logging plugin initialized"}}),ok(void 0)}onDestroy(){return this.log({timestamp:(new Date).toISOString(),level:LogLevel.INFO,event:"send",agent:"system",metadata:{message:"Logging plugin destroyed",totalLogs:this.logs.length}}),this.logs=[],ok(void 0)}onSend(e,t){const i=this.options.includeSize?this.estimateSize(e):void 0;return this.log({timestamp:(new Date).toISOString(),level:LogLevel.INFO,event:"send",agent:t.agent.did,recipient:t.recipient,scope:t.scope,payloadSize:i,metadata:this.options.includeMetadata?t.metadata:void 0}),ok({payload:e})}onReceive(e,t){const i=this.options.includeSize?this.estimateSize(e):void 0;return this.log({timestamp:(new Date).toISOString(),level:LogLevel.INFO,event:"receive",agent:t.agent.did,recipient:e.sender,scope:t.scope,payloadSize:i,metadata:this.options.includeMetadata?t.metadata:void 0}),ok({payload:e})}onEncrypt(e,t){return this.log({timestamp:(new Date).toISOString(),level:LogLevel.DEBUG,event:"encrypt",agent:t.agent.did,recipient:t.recipient,scope:t.scope,payloadSize:this.options.includeSize?e.length:void 0,metadata:this.options.includeMetadata?t.metadata:void 0}),ok({payload:e})}onDecrypt(e,t){return this.log({timestamp:(new Date).toISOString(),level:LogLevel.DEBUG,event:"decrypt",agent:t.agent.did,scope:t.scope,payloadSize:this.options.includeSize?e.length:void 0,metadata:this.options.includeMetadata?t.metadata:void 0}),ok({payload:e})}getLogs(){return[...this.logs]}clearLogs(){this.logs=[]}getFilteredLogs(e){return this.logs.filter(e)}log(e){this.shouldLog(e.level)&&this.options.filter(e)&&(this.logs.push(e),this.options.logHandler(e))}shouldLog(e){const t=[LogLevel.DEBUG,LogLevel.INFO,LogLevel.WARN,LogLevel.ERROR],i=t.indexOf(this.options.level);return t.indexOf(e)>=i}estimateSize(e){if(e instanceof Uint8Array)return e.length;try{return JSON.stringify(e).length}catch{return 0}}}export function createLoggingPlugin(e){return new LoggingPlugin(e)}
|
|
1
|
+
import{ok}from"../_deps/shared/index.js";export var LogLevel;!function(e){e.DEBUG="debug",e.INFO="info",e.WARN="warn",e.ERROR="error"}(LogLevel||(LogLevel={}));export class LoggingPlugin{name="logging";version="1.0.0";description="Captures message processing events for debugging and audit trails";priority=10;options;logs=[];constructor(e={}){this.options={level:e.level??LogLevel.INFO,includeSize:e.includeSize??!0,includeMetadata:e.includeMetadata??!1,logHandler:e.logHandler??(e=>{console.log(JSON.stringify(e))}),filter:e.filter??(()=>!0)}}onInit(){return this.log({timestamp:(new Date).toISOString(),level:LogLevel.INFO,event:"send",agent:"system",metadata:{message:"Logging plugin initialized"}}),ok(void 0)}onDestroy(){return this.log({timestamp:(new Date).toISOString(),level:LogLevel.INFO,event:"send",agent:"system",metadata:{message:"Logging plugin destroyed",totalLogs:this.logs.length}}),this.logs=[],ok(void 0)}onSend(e,t){const i=this.options.includeSize?this.estimateSize(e):void 0;return this.log({timestamp:(new Date).toISOString(),level:LogLevel.INFO,event:"send",agent:t.agent.did,recipient:t.recipient,scope:t.scope,payloadSize:i,metadata:this.options.includeMetadata?t.metadata:void 0}),ok({payload:e})}onReceive(e,t){const i=this.options.includeSize?this.estimateSize(e):void 0;return this.log({timestamp:(new Date).toISOString(),level:LogLevel.INFO,event:"receive",agent:t.agent.did,recipient:e.sender,scope:t.scope,payloadSize:i,metadata:this.options.includeMetadata?t.metadata:void 0}),ok({payload:e})}onEncrypt(e,t){return this.log({timestamp:(new Date).toISOString(),level:LogLevel.DEBUG,event:"encrypt",agent:t.agent.did,recipient:t.recipient,scope:t.scope,payloadSize:this.options.includeSize?e.length:void 0,metadata:this.options.includeMetadata?t.metadata:void 0}),ok({payload:e})}onDecrypt(e,t){return this.log({timestamp:(new Date).toISOString(),level:LogLevel.DEBUG,event:"decrypt",agent:t.agent.did,scope:t.scope,payloadSize:this.options.includeSize?e.length:void 0,metadata:this.options.includeMetadata?t.metadata:void 0}),ok({payload:e})}getLogs(){return[...this.logs]}clearLogs(){this.logs=[]}getFilteredLogs(e){return this.logs.filter(e)}log(e){this.shouldLog(e.level)&&this.options.filter(e)&&(this.logs.push(e),this.options.logHandler(e))}shouldLog(e){const t=[LogLevel.DEBUG,LogLevel.INFO,LogLevel.WARN,LogLevel.ERROR],i=t.indexOf(this.options.level);return t.indexOf(e)>=i}estimateSize(e){if(e instanceof Uint8Array)return e.length;try{return JSON.stringify(e).length}catch{return 0}}}export function createLoggingPlugin(e){return new LoggingPlugin(e)}
|
|
@@ -74,10 +74,10 @@ export declare class MetricsPlugin implements Plugin {
|
|
|
74
74
|
constructor(options?: MetricsPluginOptions);
|
|
75
75
|
onInit(): Result<void, string>;
|
|
76
76
|
onDestroy(): Result<void, string>;
|
|
77
|
-
onSend(payload: unknown,
|
|
78
|
-
onReceive(envelope: AnyTransportEnvelope,
|
|
79
|
-
onEncrypt(plaintext: Uint8Array,
|
|
80
|
-
onDecrypt(plaintext: Uint8Array,
|
|
77
|
+
onSend(payload: unknown, _context: PluginContext): Result<HookResult<unknown>, string>;
|
|
78
|
+
onReceive(envelope: AnyTransportEnvelope, _context: PluginContext): Result<HookResult<AnyTransportEnvelope>, string>;
|
|
79
|
+
onEncrypt(plaintext: Uint8Array, _context: PluginContext): Result<HookResult<Uint8Array>, string>;
|
|
80
|
+
onDecrypt(plaintext: Uint8Array, _context: PluginContext): Result<HookResult<Uint8Array>, string>;
|
|
81
81
|
/**
|
|
82
82
|
* Get all captured metrics.
|
|
83
83
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ok,err}from"../_deps/shared/index.js";export 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"}export function isEdgeRuntime(){const e=detectRuntime();return"cloudflare"===e||"vercel"===e||"deno"===e}export function validateEdgeRuntime(){if(void 0===globalThis.crypto)return err("Missing globalThis.crypto");if(void 0===globalThis.crypto.subtle)return err("Missing crypto.subtle");if("function"!=typeof globalThis.crypto.getRandomValues)return 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 err(`Missing crypto.subtle.${t}`);return void 0===globalThis.TextEncoder?err("Missing TextEncoder"):void 0===globalThis.TextDecoder?err("Missing TextDecoder"):"function"!=typeof globalThis.fetch?err("Missing fetch API"):ok(void 0)}export 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)}}export 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}}export 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}}export 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(){}}export class KVTrustRegistry{kv;constructor(e){this.kv=e}buildKey(e){return`xbind:trust:${e}`}async register(e,t,r,s,n,i,o,c,a,l,u,d,p){const y=this.buildKey(e),h=e=>btoa(String.fromCharCode(...Array.from(e))),m={did:e,publicKey:h(t),name:r,scopes:s??[],x25519PublicKey:n?h(n):void 0,mlKemPublicKey:i?h(i):void 0,mlDsaPublicKey:o?h(o):void 0,xchange:c??!1,receiveScopes:a??[],sdkVersion:l,minEnvelopeVersion:u,maxEnvelopeVersion:d,registeredAt:Date.now(),rotation_sequence:0};try{const e=p?Math.floor(p/1e3):void 0;return await this.kv.put(y,JSON.stringify(m),e),ok(void 0)}catch
|
|
1
|
+
import{ok,err}from"../_deps/shared/index.js";export 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"}export function isEdgeRuntime(){const e=detectRuntime();return"cloudflare"===e||"vercel"===e||"deno"===e}export function validateEdgeRuntime(){if(void 0===globalThis.crypto)return err("Missing globalThis.crypto");if(void 0===globalThis.crypto.subtle)return err("Missing crypto.subtle");if("function"!=typeof globalThis.crypto.getRandomValues)return 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 err(`Missing crypto.subtle.${t}`);return void 0===globalThis.TextEncoder?err("Missing TextEncoder"):void 0===globalThis.TextDecoder?err("Missing TextDecoder"):"function"!=typeof globalThis.fetch?err("Missing fetch API"):ok(void 0)}export 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)}}export 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}}export 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}}export 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(){}}export class KVTrustRegistry{kv;constructor(e){this.kv=e}buildKey(e){return`xbind:trust:${e}`}async register(e,t,r,s,n,i,o,c,a,l,u,d,p){const y=this.buildKey(e),h=e=>btoa(String.fromCharCode(...Array.from(e))),m={did:e,publicKey:h(t),name:r,scopes:s??[],x25519PublicKey:n?h(n):void 0,mlKemPublicKey:i?h(i):void 0,mlDsaPublicKey:o?h(o):void 0,xchange:c??!1,receiveScopes:a??[],sdkVersion:l,minEnvelopeVersion:u,maxEnvelopeVersion:d,registeredAt:Date.now(),rotation_sequence:0};try{const e=p?Math.floor(p/1e3):void 0;return await this.kv.put(y,JSON.stringify(m),e),ok(void 0)}catch{return err("NETWORK_ERROR")}}async resolve(e){const t=this.buildKey(e);try{const e=await this.kv.get(t);if(null===e)return err("NOT_FOUND");const r=JSON.parse(e);return ok((e=>Uint8Array.from(atob(e),e=>e.charCodeAt(0)))(r.publicKey))}catch{return 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),ok(void 0)}catch{return 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 err("NOT_FOUND");const r=JSON.parse(e),s=e=>Uint8Array.from(atob(e),e=>e.charCodeAt(0)),n={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 ok(n)}catch{return err("NETWORK_ERROR")}}async getFullEntry(e){const t=this.buildKey(e);try{const e=await this.kv.get(t);if(null===e)return err("NOT_FOUND");const r=JSON.parse(e);return ok(r)}catch{return err("NETWORK_ERROR")}}dispose(){}}export 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),n=await globalThis.fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),signal:t.signal});return clearTimeout(s),n.ok?ok(void 0):err(404===n.status?"RECIPIENT_UNREACHABLE":"SEND_FAILED")}catch(e){return e instanceof DOMException&&"AbortError"===e.name?err("TIMEOUT"):err("NETWORK_ERROR")}}onReceive(e){this.handlers.push(e)}dispatch(e){for(const t of this.handlers)t(e)}dispose(){this.handlers=[]}}export 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})}}export function checkBundleSize(e){const t=1048576;if(e>t){const t=(e/1024/1024).toFixed(2),r=1..toFixed(2);return err(`Bundle size ${t}MB exceeds edge runtime limit of ${r}MB. Consider using tree-shaking or dynamic imports.`)}return ok(void 0)}export 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"]}
|
|
@@ -120,7 +120,7 @@ export declare function sha256(data: Uint8Array, crypto?: ReactNativeCrypto): Pr
|
|
|
120
120
|
* Uses global Buffer if available, otherwise provides minimal implementation
|
|
121
121
|
*/
|
|
122
122
|
export declare class BufferPolyfill {
|
|
123
|
-
static isBuffer(obj:
|
|
123
|
+
static isBuffer(obj: unknown): boolean;
|
|
124
124
|
static from(data: string | Uint8Array | number[], encoding?: string): Uint8Array;
|
|
125
125
|
static toString(buffer: Uint8Array, encoding?: string): string;
|
|
126
126
|
static concat(buffers: Uint8Array[]): Uint8Array;
|
|
@@ -1 +1 @@
|
|
|
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
|
|
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 n="string"==typeof t.risk?t.risk.toLowerCase():void 0;if(n){if("critical"===n||"high"===n)return{mode:{type:"split",shares:5,threshold:3},reason:`Explicit risk tag "${n}" requires 3-of-5 threshold`,wasOverridden:!1};if("medium"===n)return{mode:{type:"split",shares:3,threshold:2},reason:'Explicit risk tag "medium" requires 2-of-3 threshold',wasOverridden:!1};if("low"===n)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}}}if(!0===t.crossEntity)return{mode:{type:"split",shares:3,threshold:2},reason:"Cross-organization communication requires multi-party approval (2 of 3)",wasOverridden:!1};const o=e.scope??"default";return o.includes("admin")||o.includes("custody")||o.includes("settlement")?{mode:{type:"split",shares:3,threshold:2},reason:`Sensitive scope "${o}" 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 n={type:e.type,level:r};i&&(n.shares=i);const o=JSON.stringify(n);return{type:e.type,level:r,shares:i,formats:{multiline:t,singleline:s,json:o,markdown:a}}}
|
|
@@ -1 +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}
|
|
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;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}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ok,err}from"./_deps/shared/index.js";export class HttpsTransportAdapter{baseUrl;timeoutMs;fetchFn;handlers=[];constructor(t){this.baseUrl=t.baseUrl.replace(/\/$/,""),this.timeoutMs=t.timeoutMs??1e4,this.fetchFn=t.fetch??globalThis.fetch.bind(globalThis)}async send(t,
|
|
1
|
+
import{ok,err}from"./_deps/shared/index.js";export class HttpsTransportAdapter{baseUrl;timeoutMs;fetchFn;handlers=[];constructor(t){if(!t.baseUrl||"string"!=typeof t.baseUrl)throw new TypeError("HttpsTransportOptions.baseUrl is required and must be a string");if(0===t.baseUrl.trim().length)throw new TypeError("HttpsTransportOptions.baseUrl cannot be empty");try{if("https:"!==new URL(t.baseUrl).protocol)throw new TypeError("HttpsTransportOptions.baseUrl must use HTTPS protocol")}catch(r){if(r instanceof TypeError&&r.message.includes("HTTPS protocol"))throw r;throw new TypeError(`HttpsTransportOptions.baseUrl is not a valid URL: ${t.baseUrl}`)}this.baseUrl=t.baseUrl.replace(/\/$/,""),this.timeoutMs=t.timeoutMs??1e4,this.fetchFn=t.fetch??globalThis.fetch.bind(globalThis)}async send(t,r){const e=`${this.baseUrl}/deliver/${encodeURIComponent(r)}`;try{const r=new AbortController,s=setTimeout(()=>r.abort(),this.timeoutMs),o=await this.fetchFn(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),signal:r.signal});return clearTimeout(s),o.ok?ok(void 0):err(404===o.status?"RECIPIENT_UNREACHABLE":"SEND_FAILED")}catch(t){return t instanceof DOMException&&"AbortError"===t.name?err("TIMEOUT"):err("NETWORK_ERROR")}}onReceive(t){this.handlers.push(t)}dispatch(t){for(const r of this.handlers)r(t)}dispose(){this.handlers=[]}}
|
|
@@ -82,7 +82,7 @@ export interface RegistryEntry {
|
|
|
82
82
|
readonly publicKey: Uint8Array;
|
|
83
83
|
readonly name: string;
|
|
84
84
|
readonly scopes: ReadonlySet<string>;
|
|
85
|
-
/** Scopes this agent accepts for incoming messages. Undefined =
|
|
85
|
+
/** Scopes this agent accepts for incoming messages. Undefined = defaults to send scopes. */
|
|
86
86
|
readonly receiveScopes?: ReadonlySet<string>;
|
|
87
87
|
readonly revoked: boolean;
|
|
88
88
|
/** Optional X25519 public key for ECDH forward secrecy. */
|
|
@@ -222,7 +222,7 @@ export declare class HttpTrustRegistry implements TrustRegistry {
|
|
|
222
222
|
constructor(opts: HttpTrustRegistryOptions);
|
|
223
223
|
/** Clear all cached entries. Call after registration or revocation. */
|
|
224
224
|
clearCache(): void;
|
|
225
|
-
register(did: string, publicKey: Uint8Array, name: string, scopes?: string[], x25519PublicKey?: Uint8Array, mlKemPublicKey?: Uint8Array, mlDsaPublicKey?: Uint8Array, xchange?: boolean, receiveScopes?: string[], sdkVersion?: string, minEnvelopeVersion?: number, maxEnvelopeVersion?: number, ttlMs?: number,
|
|
225
|
+
register(did: string, publicKey: Uint8Array, name: string, scopes?: string[], x25519PublicKey?: Uint8Array, mlKemPublicKey?: Uint8Array, mlDsaPublicKey?: Uint8Array, xchange?: boolean, receiveScopes?: string[], sdkVersion?: string, minEnvelopeVersion?: number, maxEnvelopeVersion?: number, ttlMs?: number, _clientIP?: string): Promise<Result<void, RegistryError>>;
|
|
226
226
|
resolve(did: string): Promise<Result<Uint8Array, RegistryError>>;
|
|
227
227
|
hasScope(did: string, scope: string): Promise<boolean>;
|
|
228
228
|
hasReceiveScope(did: string, scope: string): Promise<boolean>;
|
|
@@ -322,7 +322,7 @@ export declare class FileTrustRegistry implements TrustRegistry {
|
|
|
322
322
|
private init;
|
|
323
323
|
/** Append record to JSONL file. */
|
|
324
324
|
private append;
|
|
325
|
-
register(did: string, publicKey: Uint8Array, name: string, scopes?: string[], x25519PublicKey?: Uint8Array, mlKemPublicKey?: Uint8Array, mlDsaPublicKey?: Uint8Array, xchange?: boolean, receiveScopes?: string[], sdkVersion?: string, minEnvelopeVersion?: number, maxEnvelopeVersion?: number, ttlMs?: number,
|
|
325
|
+
register(did: string, publicKey: Uint8Array, name: string, scopes?: string[], x25519PublicKey?: Uint8Array, mlKemPublicKey?: Uint8Array, mlDsaPublicKey?: Uint8Array, xchange?: boolean, receiveScopes?: string[], sdkVersion?: string, minEnvelopeVersion?: number, maxEnvelopeVersion?: number, ttlMs?: number, _clientIP?: string): Promise<Result<void, RegistryError>>;
|
|
326
326
|
resolve(did: string): Promise<Result<Uint8Array, RegistryError>>;
|
|
327
327
|
hasScope(did: string, scope: string): Promise<boolean>;
|
|
328
328
|
hasReceiveScope(did: string, scope: string): Promise<boolean>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ok,err}from"./_deps/shared/index.js";import*as fs from"node:fs/promises";import*as path from"node:path";function isExpired(e){return!!e.expiresAt&&Date.now()>e.expiresAt}export class RegistrationRateLimiter{perIPTimestamps=new Map;globalTimestamps=[];perIPLimit;globalLimit;windowMs;cleanupInterval=null;constructor(e=10,t=1e3,i=36e5){this.perIPLimit=e,this.globalLimit=t,this.windowMs=i,this.cleanupInterval=setInterval(()=>this.cleanup(),3e5)}checkLimit(e){const t=Date.now()-this.windowMs;if((this.perIPTimestamps.get(e)||[]).filter(e=>e>t).length>=this.perIPLimit)return!1;return!(this.globalTimestamps.filter(e=>e>t).length>=this.globalLimit)}recordRegistration(e){const t=Date.now(),i=this.perIPTimestamps.get(e)||[];i.push(t),this.perIPTimestamps.set(e,i),this.globalTimestamps.push(t)}getRemainingForIP(e){const t=Date.now()-this.windowMs,i=(this.perIPTimestamps.get(e)||[]).filter(e=>e>t);return Math.max(0,this.perIPLimit-i.length)}getRemainingGlobal(){const e=Date.now()-this.windowMs,t=this.globalTimestamps.filter(t=>t>e);return Math.max(0,this.globalLimit-t.length)}getResetTimeForIP(e){const t=this.perIPTimestamps.get(e)||[];if(0===t.length)return null;const i=t[0];return i?i+this.windowMs:null}cleanup(){const e=Date.now()-this.windowMs;for(const[t,i]of this.perIPTimestamps.entries()){const s=i.filter(t=>t>e);0===s.length?this.perIPTimestamps.delete(t):this.perIPTimestamps.set(t,s)}const t=this.globalTimestamps.filter(t=>t>e);this.globalTimestamps.length=0,this.globalTimestamps.push(...t)}destroy(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=null)}reset(){this.perIPTimestamps.clear(),this.globalTimestamps.length=0}}export class MemoryTrustRegistry{entries=new Map;rateLimiter;constructor(e){e?.enableRateLimiting&&(this.rateLimiter=e.rateLimiter||new RegistrationRateLimiter)}async register(e,t,i,s,r,n,o,a,c,l,h,p,u,d){if(this.rateLimiter&&d&&!this.rateLimiter.checkLimit(d))return err("RATE_LIMIT_EXCEEDED");if(this.entries.has(e))return err("ALREADY_REGISTERED");const y=u?Date.now()+u:void 0;return this.entries.set(e,{did:e,publicKey:t,name:i,scopes:new Set(s??[]),receiveScopes:c?new Set(c):void 0,revoked:!1,rotation_sequence:1,x25519PublicKey:r,mlKemPublicKey:n,mlDsaPublicKey:o,xchange:a,sdkVersion:l,minEnvelopeVersion:h,maxEnvelopeVersion:p,expiresAt:y}),this.rateLimiter&&d&&this.rateLimiter.recordRegistration(d),ok(void 0)}async resolve(e){const t=this.entries.get(e);return t?isExpired(t)?err("EXPIRED"):t.revoked?err("REVOKED"):ok(t.publicKey):err("NOT_FOUND")}async hasScope(e,t){const i=this.entries.get(e);return!(!i||isExpired(i)||i.revoked)&&i.scopes.has(t)}async hasReceiveScope(e,t){const i=this.entries.get(e);return!(!i||isExpired(i)||i.revoked)&&(!i.receiveScopes||i.receiveScopes.has(t))}async revoke(e){const t=this.entries.get(e);return t?(this.entries.set(e,{...t,revoked:!0}),ok(void 0)):err("NOT_FOUND")}async getEntry(e){const t=this.entries.get(e);return t?isExpired(t)?err("EXPIRED"):ok(t):err("NOT_FOUND")}async updateScopes(e,t){const i=this.entries.get(e);return i?isExpired(i)?err("EXPIRED"):i.revoked?err("REVOKED"):(this.entries.set(e,{...i,scopes:new Set(t)}),ok(void 0)):err("NOT_FOUND")}async cleanup(){let e=0;const t=Date.now();for(const[i,s]of this.entries)s.expiresAt&&t>s.expiresAt&&(this.entries.delete(i),e++);return e}get size(){return this.entries.size}}export class HttpTrustRegistry{baseUrl;fetchFn;cacheTtlMs;cacheFailureMode;enablePush;bloomFilterSize;bloomFilterFpr;resolveCache=new Map;entryCache=new Map;constructor(e){this.baseUrl=e.baseUrl.replace(/\/$/,""),this.fetchFn=e.fetch??globalThis.fetch.bind(globalThis),this.cacheTtlMs=e.cacheTtlMs??3e4,this.cacheFailureMode=e.cacheFailureMode??"fail-secure",this.enablePush=e.enablePush??!1,this.bloomFilterSize=e.bloomFilterSize??1e4,this.bloomFilterFpr=e.bloomFilterFpr??.01}clearCache(){this.resolveCache.clear(),this.entryCache.clear()}async register(e,t,i,s,r,n,o,a,c,l,h,p,u,d){try{const d=await this.fetchFn(`${this.baseUrl}/registry/register`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({did:e,publicKey:Array.from(t),name:i,scopes:s??[],...c?{receiveScopes:c}:{},...r?{x25519PublicKey:Array.from(r)}:{},...n?{mlKemPublicKey:Array.from(n)}:{},...o?{mlDsaPublicKey:Array.from(o)}:{},...void 0!==a?{xchange:a}:{},...void 0!==l?{sdkVersion:l}:{},...void 0!==h?{minEnvelopeVersion:h}:{},...void 0!==p?{maxEnvelopeVersion:p}:{},...void 0!==u?{ttlMs:u}:{}})});return 409===d.status?err("ALREADY_REGISTERED"):429===d.status?err("RATE_LIMIT_EXCEEDED"):d.ok?ok(void 0):err("NETWORK_ERROR")}catch{return err("NETWORK_ERROR")}}async resolve(e){if(this.cacheTtlMs>0){const t=this.resolveCache.get(e);if(t&&t.expiry>Date.now())return t.value}let t;try{const i=await this.fetchFn(`${this.baseUrl}/registry/resolve/${encodeURIComponent(e)}`);if(404===i.status)t=err("NOT_FOUND");else if(408===i.status)t=err("EXPIRED");else if(410===i.status)t=err("REVOKED");else if(i.ok){const e=await i.json();t=ok(new Uint8Array(e.publicKey))}else t=err("NETWORK_ERROR")}catch{const i=this.resolveCache.get(e);if("fail-secure"===this.cacheFailureMode)t=err("NETWORK_ERROR");else{if(i)return i.value;t=err("NETWORK_ERROR")}}return this.cacheTtlMs>0&&this.resolveCache.set(e,{value:t,expiry:Date.now()+this.cacheTtlMs}),t}async hasScope(e,t){try{return(await this.fetchFn(`${this.baseUrl}/registry/scope/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)).ok}catch{return!1}}async hasReceiveScope(e,t){try{return(await this.fetchFn(`${this.baseUrl}/registry/receive-scope/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)).ok}catch{return!1}}async revoke(e){try{const t=await this.fetchFn(`${this.baseUrl}/registry/revoke/${encodeURIComponent(e)}`,{method:"POST"});return 404===t.status?err("NOT_FOUND"):t.ok?ok(void 0):err("NETWORK_ERROR")}catch{return err("NETWORK_ERROR")}}async getEntry(e){if(this.cacheTtlMs>0){const t=this.entryCache.get(e);if(t&&t.expiry>Date.now())return t.value}let t;try{const i=await this.fetchFn(`${this.baseUrl}/registry/entry/${encodeURIComponent(e)}`);if(404===i.status)t=err("NOT_FOUND");else if(408===i.status)t=err("EXPIRED");else if(i.ok){const e=await i.json();t=ok({did:e.did,publicKey:new Uint8Array(e.publicKey),name:e.name,scopes:new Set(e.scopes),receiveScopes:e.receiveScopes?new Set(e.receiveScopes):void 0,revoked:e.revoked,rotation_sequence:e.rotation_sequence??1,x25519PublicKey:e.x25519PublicKey?new Uint8Array(e.x25519PublicKey):void 0,mlKemPublicKey:e.mlKemPublicKey?new Uint8Array(e.mlKemPublicKey):void 0,mlDsaPublicKey:e.mlDsaPublicKey?new Uint8Array(e.mlDsaPublicKey):void 0,xchange:e.xchange,sdkVersion:e.sdkVersion,minEnvelopeVersion:e.minEnvelopeVersion,maxEnvelopeVersion:e.maxEnvelopeVersion,expiresAt:e.expiresAt})}else t=err("NETWORK_ERROR")}catch{t=err("NETWORK_ERROR")}return this.cacheTtlMs>0&&this.entryCache.set(e,{value:t,expiry:Date.now()+this.cacheTtlMs}),t}async rotate(e,t,i,s){const r=await this.fetchFn(`${this.baseUrl}/registry/rotate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({did:e,newPublicKey:Array.from(t),proof:Array.from(i),rotationSequence:s})});if(!r.ok)throw new Error(`Key rotation failed: ${r.status} ${r.statusText}`);this.resolveCache.delete(e),this.entryCache.delete(e)}async subscribe(e,t){if(!this.enablePush)throw new Error("Push notifications not enabled (set enablePush: true in HttpTrustRegistryOptions)");const i=new Set(e.map(e=>this.hashDid(e))),s=this.baseUrl.replace(/^http/,"ws")+"/trust/events",r=new globalThis.WebSocket(s);return r.addEventListener("open",()=>{r.send(JSON.stringify({type:"subscribe",dids:e,bloomSize:this.bloomFilterSize,bloomFpr:this.bloomFilterFpr}))}),r.addEventListener("message",e=>{try{const s=JSON.parse(e.data),r=this.hashDid(s.did);i.has(r)&&("revocation"!==s.type&&"succession"!==s.type||(this.resolveCache.delete(s.did),this.entryCache.delete(s.did)),t(s))}catch(e){console.warn("Failed to parse trust event:",e)}}),r.addEventListener("error",e=>{console.error("WebSocket error:",e)}),()=>{r.readyState===globalThis.WebSocket.OPEN&&r.close()}}hashDid(e){let t=0;for(let i=0;i<e.length;i++)t=(t<<5)-t+e.charCodeAt(i),t&=t;return t}async resumeSubscriptions(e){try{return(await this.fetchFn(`${this.baseUrl}/trust/resume-batch`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({proofs:e})})).ok?ok(void 0):err("NETWORK_ERROR")}catch{return err("NETWORK_ERROR")}}async fetchCheckpoint(e){try{const t=await this.fetchFn(`${this.baseUrl}/registry/checkpoint/${encodeURIComponent(e)}`);if(404===t.status)return err("NOT_FOUND");if(!t.ok)return err("NETWORK_ERROR");const i=await t.json();return ok(i)}catch{return err("NETWORK_ERROR")}}async updateScopes(e,t){try{const i=await this.fetchFn(`${this.baseUrl}/registry/${encodeURIComponent(e)}/scopes`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({scopes:t})});return 404===i.status?err("NOT_FOUND"):410===i.status?err("REVOKED"):i.ok?(this.resolveCache.delete(e),this.entryCache.delete(e),ok(void 0)):err("NETWORK_ERROR")}catch{return err("NETWORK_ERROR")}}}export class FileTrustRegistry{path;entries=new Map;initialized=!1;constructor(e){this.path=e.path}async init(){if(!this.initialized){try{await fs.mkdir(path.dirname(this.path),{recursive:!0});const e=(await fs.readFile(this.path,"utf-8").catch(()=>"")).split("\n").filter(e=>e.trim());for(const t of e){const e=JSON.parse(t);if("register"===e.type&&e.publicKey&&e.name)this.entries.set(e.did,{did:e.did,publicKey:new Uint8Array(e.publicKey),name:e.name,scopes:new Set(e.scopes??[]),receiveScopes:e.receiveScopes?new Set(e.receiveScopes):void 0,revoked:!1,rotation_sequence:e.rotation_sequence??1,x25519PublicKey:e.x25519PublicKey?new Uint8Array(e.x25519PublicKey):void 0,mlKemPublicKey:e.mlKemPublicKey?new Uint8Array(e.mlKemPublicKey):void 0,mlDsaPublicKey:e.mlDsaPublicKey?new Uint8Array(e.mlDsaPublicKey):void 0,xchange:e.xchange,sdkVersion:e.sdkVersion,minEnvelopeVersion:e.minEnvelopeVersion,maxEnvelopeVersion:e.maxEnvelopeVersion,expiresAt:e.expiresAt});else if("revoke"===e.type){const t=this.entries.get(e.did);t&&this.entries.set(e.did,{...t,revoked:!0})}else if("update-scopes"===e.type){const t=this.entries.get(e.did);t&&this.entries.set(e.did,{...t,scopes:new Set(e.scopes??[])})}else if("rotate"===e.type&&e.publicKey&&e.rotation_sequence){const t=this.entries.get(e.did);t&&e.rotation_sequence>t.rotation_sequence&&this.entries.set(e.did,{...t,publicKey:new Uint8Array(e.publicKey),rotation_sequence:e.rotation_sequence})}}}catch(e){}this.initialized=!0}}async append(e){await fs.appendFile(this.path,JSON.stringify(e)+"\n","utf-8")}async register(e,t,i,s,r,n,o,a,c,l,h,p,u,d){if(await this.init(),this.entries.has(e))return err("ALREADY_REGISTERED");const y=u?Date.now()+u:void 0,m={did:e,publicKey:t,name:i,scopes:new Set(s??[]),receiveScopes:c?new Set(c):void 0,revoked:!1,rotation_sequence:1,x25519PublicKey:r,mlKemPublicKey:n,mlDsaPublicKey:o,xchange:a,sdkVersion:l,minEnvelopeVersion:h,maxEnvelopeVersion:p,expiresAt:y};return this.entries.set(e,m),await this.append({type:"register",did:e,publicKey:Array.from(t),name:i,scopes:s??[],rotation_sequence:1,...c?{receiveScopes:c}:{},...r?{x25519PublicKey:Array.from(r)}:{},...n?{mlKemPublicKey:Array.from(n)}:{},...o?{mlDsaPublicKey:Array.from(o)}:{},...void 0!==a?{xchange:a}:{},...void 0!==l?{sdkVersion:l}:{},...void 0!==h?{minEnvelopeVersion:h}:{},...void 0!==p?{maxEnvelopeVersion:p}:{},...void 0!==y?{expiresAt:y}:{}}),ok(void 0)}async resolve(e){await this.init();const t=this.entries.get(e);return t?isExpired(t)?err("EXPIRED"):t.revoked?err("REVOKED"):ok(t.publicKey):err("NOT_FOUND")}async hasScope(e,t){await this.init();const i=this.entries.get(e);return!(!i||isExpired(i)||i.revoked)&&i.scopes.has(t)}async hasReceiveScope(e,t){await this.init();const i=this.entries.get(e);return!(!i||isExpired(i)||i.revoked)&&(!i.receiveScopes||i.receiveScopes.has(t))}async revoke(e){await this.init();const t=this.entries.get(e);return t?(this.entries.set(e,{...t,revoked:!0}),await this.append({type:"revoke",did:e}),ok(void 0)):err("NOT_FOUND")}async getEntry(e){await this.init();const t=this.entries.get(e);return t?isExpired(t)?err("EXPIRED"):ok(t):err("NOT_FOUND")}async updateScopes(e,t){await this.init();const i=this.entries.get(e);return i?isExpired(i)?err("EXPIRED"):i.revoked?err("REVOKED"):(this.entries.set(e,{...i,scopes:new Set(t)}),await this.append({type:"update-scopes",did:e,scopes:t}),ok(void 0)):err("NOT_FOUND")}async cleanup(){await this.init();let e=0;const t=Date.now();for(const[i,s]of this.entries)s.expiresAt&&t>s.expiresAt&&(this.entries.delete(i),e++);return e}async rotate(e,t,i,s){await this.init();const r=this.entries.get(e);if(!r)throw new Error(`DID not found: ${e}`);if(s<=r.rotation_sequence)throw new Error(`Rotation sequence ${s} must be > current ${r.rotation_sequence} (rollback attack prevented)`);await this.append({type:"rotate",did:e,publicKey:Array.from(t),proof:Array.from(i),rotation_sequence:s,timestamp:Date.now()}),this.entries.set(e,{...r,publicKey:t,rotation_sequence:s})}get size(){return this.entries.size}}export async function createEnterpriseTrustRegistry(e){let t;if("file"===e.storage){if(!e.path)throw new Error("FileTrustRegistry requires path option");t=new FileTrustRegistry({path:e.path})}else if("http"===e.storage){if(!e.baseUrl)throw new Error("HttpTrustRegistry requires baseUrl option");t=new HttpTrustRegistry({baseUrl:e.baseUrl})}else t=new MemoryTrustRegistry;if(e.preload)for(const i of e.preload)await t.register(i.did,i.publicKey,i.name,i.scopes,i.x25519PublicKey,i.mlKemPublicKey,i.mlDsaPublicKey,i.xchange,i.receiveScopes,i.sdkVersion,i.minEnvelopeVersion,i.maxEnvelopeVersion);return t}
|
|
1
|
+
import{ok,err}from"./_deps/shared/index.js";import*as fs from"node:fs/promises";import*as path from"node:path";function isExpired(e){return!!e.expiresAt&&Date.now()>e.expiresAt}export class RegistrationRateLimiter{perIPTimestamps=new Map;globalTimestamps=[];perIPLimit;globalLimit;windowMs;cleanupInterval=null;constructor(e=10,t=1e3,i=36e5){this.perIPLimit=e,this.globalLimit=t,this.windowMs=i,this.cleanupInterval=setInterval(()=>this.cleanup(),3e5)}checkLimit(e){const t=Date.now()-this.windowMs;if((this.perIPTimestamps.get(e)||[]).filter(e=>e>t).length>=this.perIPLimit)return!1;return!(this.globalTimestamps.filter(e=>e>t).length>=this.globalLimit)}recordRegistration(e){const t=Date.now(),i=this.perIPTimestamps.get(e)||[];i.push(t),this.perIPTimestamps.set(e,i),this.globalTimestamps.push(t)}getRemainingForIP(e){const t=Date.now()-this.windowMs,i=(this.perIPTimestamps.get(e)||[]).filter(e=>e>t);return Math.max(0,this.perIPLimit-i.length)}getRemainingGlobal(){const e=Date.now()-this.windowMs,t=this.globalTimestamps.filter(t=>t>e);return Math.max(0,this.globalLimit-t.length)}getResetTimeForIP(e){const t=this.perIPTimestamps.get(e)||[];if(0===t.length)return null;const i=t[0];return i?i+this.windowMs:null}cleanup(){const e=Date.now()-this.windowMs;for(const[t,i]of this.perIPTimestamps.entries()){const s=i.filter(t=>t>e);0===s.length?this.perIPTimestamps.delete(t):this.perIPTimestamps.set(t,s)}const t=this.globalTimestamps.filter(t=>t>e);this.globalTimestamps.length=0,this.globalTimestamps.push(...t)}destroy(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=null)}reset(){this.perIPTimestamps.clear(),this.globalTimestamps.length=0}}export class MemoryTrustRegistry{entries=new Map;rateLimiter;constructor(e){e?.enableRateLimiting&&(this.rateLimiter=e.rateLimiter||new RegistrationRateLimiter)}async register(e,t,i,s,r,n,o,a,c,l,h,p,u,d){if(this.rateLimiter&&d&&!this.rateLimiter.checkLimit(d))return err("RATE_LIMIT_EXCEEDED");if(this.entries.has(e))return err("ALREADY_REGISTERED");const y=u?Date.now()+u:void 0;return this.entries.set(e,{did:e,publicKey:t,name:i,scopes:new Set(s??[]),receiveScopes:c?new Set(c):void 0,revoked:!1,rotation_sequence:1,x25519PublicKey:r,mlKemPublicKey:n,mlDsaPublicKey:o,xchange:a,sdkVersion:l,minEnvelopeVersion:h,maxEnvelopeVersion:p,expiresAt:y}),this.rateLimiter&&d&&this.rateLimiter.recordRegistration(d),ok(void 0)}async resolve(e){const t=this.entries.get(e);return t?isExpired(t)?err("EXPIRED"):t.revoked?err("REVOKED"):ok(t.publicKey):err("NOT_FOUND")}async hasScope(e,t){const i=this.entries.get(e);return!(!i||isExpired(i)||i.revoked)&&i.scopes.has(t)}async hasReceiveScope(e,t){const i=this.entries.get(e);return!(!i||isExpired(i)||i.revoked)&&(!i.receiveScopes||i.receiveScopes.has(t))}async revoke(e){const t=this.entries.get(e);return t?(this.entries.set(e,{...t,revoked:!0}),ok(void 0)):err("NOT_FOUND")}async getEntry(e){const t=this.entries.get(e);return t?isExpired(t)?err("EXPIRED"):ok(t):err("NOT_FOUND")}async updateScopes(e,t){const i=this.entries.get(e);return i?isExpired(i)?err("EXPIRED"):i.revoked?err("REVOKED"):(this.entries.set(e,{...i,scopes:new Set(t)}),ok(void 0)):err("NOT_FOUND")}async cleanup(){let e=0;const t=Date.now();for(const[i,s]of this.entries)s.expiresAt&&t>s.expiresAt&&(this.entries.delete(i),e++);return e}get size(){return this.entries.size}}export class HttpTrustRegistry{baseUrl;fetchFn;cacheTtlMs;cacheFailureMode;enablePush;bloomFilterSize;bloomFilterFpr;resolveCache=new Map;entryCache=new Map;constructor(e){this.baseUrl=e.baseUrl.replace(/\/$/,""),this.fetchFn=e.fetch??globalThis.fetch.bind(globalThis),this.cacheTtlMs=e.cacheTtlMs??3e4,this.cacheFailureMode=e.cacheFailureMode??"fail-secure",this.enablePush=e.enablePush??!1,this.bloomFilterSize=e.bloomFilterSize??1e4,this.bloomFilterFpr=e.bloomFilterFpr??.01}clearCache(){this.resolveCache.clear(),this.entryCache.clear()}async register(e,t,i,s,r,n,o,a,c,l,h,p,u,d){try{const d=await this.fetchFn(`${this.baseUrl}/registry/register`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({did:e,publicKey:Array.from(t),name:i,scopes:s??[],...c?{receiveScopes:c}:{},...r?{x25519PublicKey:Array.from(r)}:{},...n?{mlKemPublicKey:Array.from(n)}:{},...o?{mlDsaPublicKey:Array.from(o)}:{},...void 0!==a?{xchange:a}:{},...void 0!==l?{sdkVersion:l}:{},...void 0!==h?{minEnvelopeVersion:h}:{},...void 0!==p?{maxEnvelopeVersion:p}:{},...void 0!==u?{ttlMs:u}:{}})});return 409===d.status?err("ALREADY_REGISTERED"):429===d.status?err("RATE_LIMIT_EXCEEDED"):d.ok?ok(void 0):err("NETWORK_ERROR")}catch{return err("NETWORK_ERROR")}}async resolve(e){if(this.cacheTtlMs>0){const t=this.resolveCache.get(e);if(t&&t.expiry>Date.now())return t.value}let t;try{const i=await this.fetchFn(`${this.baseUrl}/registry/resolve/${encodeURIComponent(e)}`);if(404===i.status)t=err("NOT_FOUND");else if(408===i.status)t=err("EXPIRED");else if(410===i.status)t=err("REVOKED");else if(i.ok){const e=await i.json();t=ok(new Uint8Array(e.publicKey))}else t=err("NETWORK_ERROR")}catch{const i=this.resolveCache.get(e);if("fail-secure"===this.cacheFailureMode)t=err("NETWORK_ERROR");else{if(i)return i.value;t=err("NETWORK_ERROR")}}return this.cacheTtlMs>0&&this.resolveCache.set(e,{value:t,expiry:Date.now()+this.cacheTtlMs}),t}async hasScope(e,t){try{return(await this.fetchFn(`${this.baseUrl}/registry/scope/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)).ok}catch{return!1}}async hasReceiveScope(e,t){try{return(await this.fetchFn(`${this.baseUrl}/registry/receive-scope/${encodeURIComponent(e)}/${encodeURIComponent(t)}`)).ok}catch{return!1}}async revoke(e){try{const t=await this.fetchFn(`${this.baseUrl}/registry/revoke/${encodeURIComponent(e)}`,{method:"POST"});return 404===t.status?err("NOT_FOUND"):t.ok?ok(void 0):err("NETWORK_ERROR")}catch{return err("NETWORK_ERROR")}}async getEntry(e){if(this.cacheTtlMs>0){const t=this.entryCache.get(e);if(t&&t.expiry>Date.now())return t.value}let t;try{const i=await this.fetchFn(`${this.baseUrl}/registry/entry/${encodeURIComponent(e)}`);if(404===i.status)t=err("NOT_FOUND");else if(408===i.status)t=err("EXPIRED");else if(i.ok){const e=await i.json();t=ok({did:e.did,publicKey:new Uint8Array(e.publicKey),name:e.name,scopes:new Set(e.scopes),receiveScopes:e.receiveScopes?new Set(e.receiveScopes):void 0,revoked:e.revoked,rotation_sequence:e.rotation_sequence??1,x25519PublicKey:e.x25519PublicKey?new Uint8Array(e.x25519PublicKey):void 0,mlKemPublicKey:e.mlKemPublicKey?new Uint8Array(e.mlKemPublicKey):void 0,mlDsaPublicKey:e.mlDsaPublicKey?new Uint8Array(e.mlDsaPublicKey):void 0,xchange:e.xchange,sdkVersion:e.sdkVersion,minEnvelopeVersion:e.minEnvelopeVersion,maxEnvelopeVersion:e.maxEnvelopeVersion,expiresAt:e.expiresAt})}else t=err("NETWORK_ERROR")}catch{t=err("NETWORK_ERROR")}return this.cacheTtlMs>0&&this.entryCache.set(e,{value:t,expiry:Date.now()+this.cacheTtlMs}),t}async rotate(e,t,i,s){const r=await this.fetchFn(`${this.baseUrl}/registry/rotate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({did:e,newPublicKey:Array.from(t),proof:Array.from(i),rotationSequence:s})});if(!r.ok)throw new Error(`Key rotation failed: ${r.status} ${r.statusText}`);this.resolveCache.delete(e),this.entryCache.delete(e)}async subscribe(e,t){if(!this.enablePush)throw new Error("Push notifications not enabled (set enablePush: true in HttpTrustRegistryOptions)");const i=new Set(e.map(e=>this.hashDid(e))),s=this.baseUrl.replace(/^http/,"ws")+"/trust/events",r=new globalThis.WebSocket(s);return r.addEventListener("open",()=>{r.send(JSON.stringify({type:"subscribe",dids:e,bloomSize:this.bloomFilterSize,bloomFpr:this.bloomFilterFpr}))}),r.addEventListener("message",e=>{try{const s=JSON.parse(e.data),r=this.hashDid(s.did);i.has(r)&&("revocation"!==s.type&&"succession"!==s.type||(this.resolveCache.delete(s.did),this.entryCache.delete(s.did)),t(s))}catch(e){console.warn("Failed to parse trust event:",e)}}),r.addEventListener("error",e=>{console.error("WebSocket error:",e)}),()=>{r.readyState===globalThis.WebSocket.OPEN&&r.close()}}hashDid(e){let t=0;for(let i=0;i<e.length;i++)t=(t<<5)-t+e.charCodeAt(i),t&=t;return t}async resumeSubscriptions(e){try{return(await this.fetchFn(`${this.baseUrl}/trust/resume-batch`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({proofs:e})})).ok?ok(void 0):err("NETWORK_ERROR")}catch{return err("NETWORK_ERROR")}}async fetchCheckpoint(e){try{const t=await this.fetchFn(`${this.baseUrl}/registry/checkpoint/${encodeURIComponent(e)}`);if(404===t.status)return err("NOT_FOUND");if(!t.ok)return err("NETWORK_ERROR");const i=await t.json();return ok(i)}catch{return err("NETWORK_ERROR")}}async updateScopes(e,t){try{const i=await this.fetchFn(`${this.baseUrl}/registry/${encodeURIComponent(e)}/scopes`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({scopes:t})});return 404===i.status?err("NOT_FOUND"):410===i.status?err("REVOKED"):i.ok?(this.resolveCache.delete(e),this.entryCache.delete(e),ok(void 0)):err("NETWORK_ERROR")}catch{return err("NETWORK_ERROR")}}}export class FileTrustRegistry{path;entries=new Map;initialized=!1;constructor(e){this.path=e.path}async init(){if(!this.initialized){try{await fs.mkdir(path.dirname(this.path),{recursive:!0});const e=(await fs.readFile(this.path,"utf-8").catch(()=>"")).split("\n").filter(e=>e.trim());for(const t of e){const e=JSON.parse(t);if("register"===e.type&&e.publicKey&&e.name)this.entries.set(e.did,{did:e.did,publicKey:new Uint8Array(e.publicKey),name:e.name,scopes:new Set(e.scopes??[]),receiveScopes:e.receiveScopes?new Set(e.receiveScopes):void 0,revoked:!1,rotation_sequence:e.rotation_sequence??1,x25519PublicKey:e.x25519PublicKey?new Uint8Array(e.x25519PublicKey):void 0,mlKemPublicKey:e.mlKemPublicKey?new Uint8Array(e.mlKemPublicKey):void 0,mlDsaPublicKey:e.mlDsaPublicKey?new Uint8Array(e.mlDsaPublicKey):void 0,xchange:e.xchange,sdkVersion:e.sdkVersion,minEnvelopeVersion:e.minEnvelopeVersion,maxEnvelopeVersion:e.maxEnvelopeVersion,expiresAt:e.expiresAt});else if("revoke"===e.type){const t=this.entries.get(e.did);t&&this.entries.set(e.did,{...t,revoked:!0})}else if("update-scopes"===e.type){const t=this.entries.get(e.did);t&&this.entries.set(e.did,{...t,scopes:new Set(e.scopes??[])})}else if("rotate"===e.type&&e.publicKey&&e.rotation_sequence){const t=this.entries.get(e.did);t&&e.rotation_sequence>t.rotation_sequence&&this.entries.set(e.did,{...t,publicKey:new Uint8Array(e.publicKey),rotation_sequence:e.rotation_sequence})}}}catch{}this.initialized=!0}}async append(e){await fs.appendFile(this.path,JSON.stringify(e)+"\n","utf-8")}async register(e,t,i,s,r,n,o,a,c,l,h,p,u,d){if(await this.init(),this.entries.has(e))return err("ALREADY_REGISTERED");const y=u?Date.now()+u:void 0,m={did:e,publicKey:t,name:i,scopes:new Set(s??[]),receiveScopes:c?new Set(c):void 0,revoked:!1,rotation_sequence:1,x25519PublicKey:r,mlKemPublicKey:n,mlDsaPublicKey:o,xchange:a,sdkVersion:l,minEnvelopeVersion:h,maxEnvelopeVersion:p,expiresAt:y};return this.entries.set(e,m),await this.append({type:"register",did:e,publicKey:Array.from(t),name:i,scopes:s??[],rotation_sequence:1,...c?{receiveScopes:c}:{},...r?{x25519PublicKey:Array.from(r)}:{},...n?{mlKemPublicKey:Array.from(n)}:{},...o?{mlDsaPublicKey:Array.from(o)}:{},...void 0!==a?{xchange:a}:{},...void 0!==l?{sdkVersion:l}:{},...void 0!==h?{minEnvelopeVersion:h}:{},...void 0!==p?{maxEnvelopeVersion:p}:{},...void 0!==y?{expiresAt:y}:{}}),ok(void 0)}async resolve(e){await this.init();const t=this.entries.get(e);return t?isExpired(t)?err("EXPIRED"):t.revoked?err("REVOKED"):ok(t.publicKey):err("NOT_FOUND")}async hasScope(e,t){await this.init();const i=this.entries.get(e);return!(!i||isExpired(i)||i.revoked)&&i.scopes.has(t)}async hasReceiveScope(e,t){await this.init();const i=this.entries.get(e);return!(!i||isExpired(i)||i.revoked)&&(!i.receiveScopes||i.receiveScopes.has(t))}async revoke(e){await this.init();const t=this.entries.get(e);return t?(this.entries.set(e,{...t,revoked:!0}),await this.append({type:"revoke",did:e}),ok(void 0)):err("NOT_FOUND")}async getEntry(e){await this.init();const t=this.entries.get(e);return t?isExpired(t)?err("EXPIRED"):ok(t):err("NOT_FOUND")}async updateScopes(e,t){await this.init();const i=this.entries.get(e);return i?isExpired(i)?err("EXPIRED"):i.revoked?err("REVOKED"):(this.entries.set(e,{...i,scopes:new Set(t)}),await this.append({type:"update-scopes",did:e,scopes:t}),ok(void 0)):err("NOT_FOUND")}async cleanup(){await this.init();let e=0;const t=Date.now();for(const[i,s]of this.entries)s.expiresAt&&t>s.expiresAt&&(this.entries.delete(i),e++);return e}async rotate(e,t,i,s){await this.init();const r=this.entries.get(e);if(!r)throw new Error(`DID not found: ${e}`);if(s<=r.rotation_sequence)throw new Error(`Rotation sequence ${s} must be > current ${r.rotation_sequence} (rollback attack prevented)`);await this.append({type:"rotate",did:e,publicKey:Array.from(t),proof:Array.from(i),rotation_sequence:s,timestamp:Date.now()}),this.entries.set(e,{...r,publicKey:t,rotation_sequence:s})}get size(){return this.entries.size}}export async function createEnterpriseTrustRegistry(e){let t;if("file"===e.storage){if(!e.path)throw new Error("FileTrustRegistry requires path option");t=new FileTrustRegistry({path:e.path})}else if("http"===e.storage){if(!e.baseUrl)throw new Error("HttpTrustRegistry requires baseUrl option");t=new HttpTrustRegistry({baseUrl:e.baseUrl})}else t=new MemoryTrustRegistry;if(e.preload)for(const i of e.preload)await t.register(i.did,i.publicKey,i.name,i.scopes,i.x25519PublicKey,i.mlKemPublicKey,i.mlDsaPublicKey,i.xchange,i.receiveScopes,i.sdkVersion,i.minEnvelopeVersion,i.maxEnvelopeVersion);return t}
|
|
@@ -108,3 +108,12 @@ export declare function getCacheStatus(): {
|
|
|
108
108
|
expiresAt?: number;
|
|
109
109
|
ttlRemaining?: number;
|
|
110
110
|
};
|
|
111
|
+
/**
|
|
112
|
+
* Set mock crypto package for testing.
|
|
113
|
+
*
|
|
114
|
+
* @internal For test use only
|
|
115
|
+
* @param crypto - Mock crypto package
|
|
116
|
+
* @param version - Version identifier
|
|
117
|
+
* @param ttlMs - Cache TTL in milliseconds (default: 7 days)
|
|
118
|
+
*/
|
|
119
|
+
export declare function setMockCrypto(crypto: CryptoPackage, version?: string, ttlMs?: number): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ok,err}from"./_deps/shared/index.js";import{signVaultRequest}from"./vault-auth.js";const VAULT_STORE_URL=process.env.VAULT_STORE_URL||"https://private.me/api/vault-store",CACHE_TTL_MS=6048e5;let cryptoCache=null;export async function loadCryptoPackage(identity){if(cryptoCache&&Date.now()<cryptoCache.expiresAt)return ok(cryptoCache.module);const signatureResult=await signVaultRequest(identity,"/api/vault-store/crypto",{requestedVersion:"latest",clientVersion:"1.5.0"});if(!signatureResult.ok)return err("VAULT_AUTH_FAILED");const{signature:signature,timestamp:timestamp,nonce:nonce}=signatureResult.value;let response,vaultData,cryptoModule;try{response=await fetch(`${VAULT_STORE_URL}/crypto`,{method:"POST",headers:{"Content-Type":"application/json","X-DID":identity.did,"X-Signature":signature,"X-Timestamp":timestamp.toString(),"X-Nonce":nonce},body:JSON.stringify({requestedVersion:"latest",clientVersion:"1.5.0"})})}catch
|
|
1
|
+
import{ok,err}from"./_deps/shared/index.js";import{signVaultRequest}from"./vault-auth.js";const VAULT_STORE_URL=process.env.VAULT_STORE_URL||"https://private.me/api/vault-store",CACHE_TTL_MS=6048e5;let cryptoCache=null;export async function loadCryptoPackage(identity){if(cryptoCache&&Date.now()<cryptoCache.expiresAt)return ok(cryptoCache.module);const signatureResult=await signVaultRequest(identity,"/api/vault-store/crypto",{requestedVersion:"latest",clientVersion:"1.5.0"});if(!signatureResult.ok)return err("VAULT_AUTH_FAILED");const{signature:signature,timestamp:timestamp,nonce:nonce}=signatureResult.value;let response,vaultData,cryptoModule;try{response=await fetch(`${VAULT_STORE_URL}/crypto`,{method:"POST",headers:{"Content-Type":"application/json","X-DID":identity.did,"X-Signature":signature,"X-Timestamp":timestamp.toString(),"X-Nonce":nonce},body:JSON.stringify({requestedVersion:"latest",clientVersion:"1.5.0"})})}catch{return err("VAULT_FETCH_FAILED")}if(!response.ok)return 402===response.status?err("VAULT_QUOTA_EXCEEDED"):401===response.status||403===response.status?err("VAULT_AUTH_FAILED"):451===response.status?err("VAULT_PAYMENT_REQUIRED"):err("VAULT_FETCH_FAILED");try{vaultData=await response.json()}catch{return err("VAULT_INVALID_RESPONSE")}if(!vaultData.cryptoBundle||!vaultData.version)return err("VAULT_INVALID_RESPONSE");try{const bundleCode=atob(vaultData.cryptoBundle),moduleExports=eval(`(function() {\n const exports = {};\n ${bundleCode}\n return exports;\n })()`);if(cryptoModule=moduleExports,"function"!=typeof cryptoModule.splitXorIDA||"function"!=typeof cryptoModule.reconstructXorIDA)return err("VAULT_LOAD_FAILED")}catch{return err("VAULT_LOAD_FAILED")}const ttlMs=vaultData.cacheTtl?1e3*vaultData.cacheTtl:CACHE_TTL_MS;return cryptoCache={module:cryptoModule,expiresAt:Date.now()+ttlMs,version:vaultData.version},ok(cryptoModule)}export function getCrypto(){return cryptoCache&&Date.now()<cryptoCache.expiresAt?cryptoCache.module:null}export function isCryptoLoaded(){return null!==cryptoCache&&Date.now()<cryptoCache.expiresAt}export function clearCryptoCache(){cryptoCache=null}export function getCacheStatus(){if(!cryptoCache)return{loaded:!1};const t=Date.now();return{loaded:t<cryptoCache.expiresAt,version:cryptoCache.version,expiresAt:cryptoCache.expiresAt,ttlRemaining:Math.max(0,cryptoCache.expiresAt-t)}}export function setMockCrypto(t,e="mock-1.0.0",r=CACHE_TTL_MS){cryptoCache={module:t,expiresAt:Date.now()+r,version:e}}
|