@private.me/xbind 2.3.4 → 3.0.1
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 +10 -3
- package/dist-standalone/cjs/version-info.js +1 -1
- package/dist-standalone/plugins/logging.d.ts +84 -0
- package/dist-standalone/plugins/logging.js +1 -0
- package/dist-standalone/plugins/metrics.d.ts +111 -0
- package/dist-standalone/plugins/metrics.js +1 -0
- package/dist-standalone/plugins/validation.d.ts +104 -0
- package/dist-standalone/plugins/validation.js +1 -0
- package/dist-standalone/runtime/browser.d.ts +311 -0
- package/dist-standalone/runtime/browser.js +1 -0
- package/dist-standalone/runtime/edge.d.ts +282 -0
- package/dist-standalone/runtime/edge.js +1 -0
- package/dist-standalone/runtime/react-native.d.ts +157 -0
- package/dist-standalone/runtime/react-native.js +1 -0
- package/dist-standalone/types/error-response.d.ts +209 -0
- package/dist-standalone/types/error-response.js +1 -0
- package/dist-standalone/version-info.js +1 -1
- package/package.json +4 -1
- package/share1.dat +0 -0
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @private.me/xbind
|
|
2
2
|
|
|
3
3
|

|
|
4
|
-

|
|
5
5
|

|
|
6
6
|

|
|
7
7
|

|
|
@@ -12,7 +12,14 @@ Build AI agents that communicate securely using ML-DSA-65 DID identity, ML-KEM-7
|
|
|
12
12
|
|
|
13
13
|
Part of the **Private.Me** platform—where APIs have keys, but ACIs have identity.
|
|
14
14
|
|
|
15
|
-
**Version
|
|
15
|
+
**Version 3.0.1** — **Major Features:** Full Control IP Protection (PLAN-13) - Vault Store architecture with payment-gated algorithm delivery. Store Front (npm) contains Share 1 only, Vault Store (EC2) contains Share 2 (payment-gated). Runtime crypto loading, 4-layer security (DID auth + usage quotas + rate limiting + audit logging). Usage-based model: Free tier 100K ops/month (includes vault access), Pro tier unlimited. Previous v1.4.2: Runtime compatibility, API enhancements. Previous v1.3.5: ML-KEM deterministic key generation fix.
|
|
16
|
+
|
|
17
|
+
## Pricing
|
|
18
|
+
|
|
19
|
+
**Free tier:** 100,000 operations/month (includes Vault Store access)
|
|
20
|
+
**Pro tier:** Unlimited operations
|
|
21
|
+
|
|
22
|
+
See [pricing](https://private.me/pricing) for current rates and purchase flow.
|
|
16
23
|
|
|
17
24
|
## Install
|
|
18
25
|
|
|
@@ -563,7 +570,7 @@ Zero key management, zero cascade failures, zero bearer credentials. Cryptograph
|
|
|
563
570
|
|
|
564
571
|
## Bundle Size Optimization (Tree-Shaking)
|
|
565
572
|
|
|
566
|
-
**New in
|
|
573
|
+
**New in v3.0.0:** Full Control IP Protection - cryptographic algorithms delivered via payment-gated Vault Store. Share 1 in npm (useless alone), Share 2 in EC2 (completes algorithm). Information-theoretic security for proprietary IP.
|
|
567
574
|
|
|
568
575
|
### Full Import (Convenience)
|
|
569
576
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Capability=void 0,exports.getVersion=getVersion,exports.hasCapability=hasCapability,exports.getCapabilities=getCapabilities,exports.getDeprecationInfo=getDeprecationInfo,exports.warnIfDeprecated=warnIfDeprecated,exports.parseVersion=parseVersion,exports.compareVersions=compareVersions,exports.checkCompatibility=checkCompatibility,exports.getMinimumVersionFor=getMinimumVersionFor,exports.assertMinimumVersion=assertMinimumVersion;const logger_js_1=require("./logger.js"),logger=(0,logger_js_1.createLogger)("version-info");var Capability;!function(e){e.ENVELOPE_V1="envelope-v1",e.ENVELOPE_V2="envelope-v2",e.ENVELOPE_V3="envelope-v3",e.ENVELOPE_V4="envelope-v4",e.ML_KEM_768="ml-kem-768",e.ML_DSA_65="ml-dsa-65",e.X25519_ECDH="x25519-ecdh",e.ED25519_SIG="ed25519-sig",e.XORIDA="xorida",e.SPLIT_CHANNEL="split-channel",e.TRUST_REGISTRY="trust-registry",e.SERVICE_DISCOVERY="service-discovery",e.INVITE_SYSTEM="invite-system",e.AGENT_CALL="agent-call",e.XFETCH="xfetch",e.DUAL_MODE="dual-mode",e.BACKUP_RESTORE="backup-restore",e.CORRELATION_ID="correlation-id",e.STRUCTURED_LOGGING="structured-logging",e.DID_SUCCESSION="did-succession",e.GATEWAY_STATE="gateway-state",e.SUBSCRIPTION_PROOF="subscription-proof",e.POLICY_ENGINE="policy-engine",e.APPROVAL_FLOW="approval-flow",e.GUARDRAILS="guardrails",e.HTTP_COMPAT="http-compat",e.DID_WEB="did-web",e.DID_PRIVATEME="did:privateme",e.REDIS_NONCE="redis-nonce",e.RETRY_TRANSPORT="retry-transport"}(Capability||(exports.Capability=Capability={}));const VERSION_METADATA={semver:"
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Capability=void 0,exports.getVersion=getVersion,exports.hasCapability=hasCapability,exports.getCapabilities=getCapabilities,exports.getDeprecationInfo=getDeprecationInfo,exports.warnIfDeprecated=warnIfDeprecated,exports.parseVersion=parseVersion,exports.compareVersions=compareVersions,exports.checkCompatibility=checkCompatibility,exports.getMinimumVersionFor=getMinimumVersionFor,exports.assertMinimumVersion=assertMinimumVersion;const logger_js_1=require("./logger.js"),logger=(0,logger_js_1.createLogger)("version-info");var Capability;!function(e){e.ENVELOPE_V1="envelope-v1",e.ENVELOPE_V2="envelope-v2",e.ENVELOPE_V3="envelope-v3",e.ENVELOPE_V4="envelope-v4",e.ML_KEM_768="ml-kem-768",e.ML_DSA_65="ml-dsa-65",e.X25519_ECDH="x25519-ecdh",e.ED25519_SIG="ed25519-sig",e.XORIDA="xorida",e.SPLIT_CHANNEL="split-channel",e.TRUST_REGISTRY="trust-registry",e.SERVICE_DISCOVERY="service-discovery",e.INVITE_SYSTEM="invite-system",e.AGENT_CALL="agent-call",e.XFETCH="xfetch",e.DUAL_MODE="dual-mode",e.BACKUP_RESTORE="backup-restore",e.CORRELATION_ID="correlation-id",e.STRUCTURED_LOGGING="structured-logging",e.DID_SUCCESSION="did-succession",e.GATEWAY_STATE="gateway-state",e.SUBSCRIPTION_PROOF="subscription-proof",e.POLICY_ENGINE="policy-engine",e.APPROVAL_FLOW="approval-flow",e.GUARDRAILS="guardrails",e.HTTP_COMPAT="http-compat",e.DID_WEB="did-web",e.DID_PRIVATEME="did:privateme",e.REDIS_NONCE="redis-nonce",e.RETRY_TRANSPORT="retry-transport"}(Capability||(exports.Capability=Capability={}));const VERSION_METADATA={semver:"3.0.0",major:1,minor:4,patch:2,prerelease:void 0,build:void 0,features:[Capability.ENVELOPE_V1,Capability.ENVELOPE_V2,Capability.ENVELOPE_V3,Capability.ENVELOPE_V4,Capability.ML_KEM_768,Capability.ML_DSA_65,Capability.X25519_ECDH,Capability.ED25519_SIG,Capability.XORIDA,Capability.SPLIT_CHANNEL,Capability.TRUST_REGISTRY,Capability.SERVICE_DISCOVERY,Capability.INVITE_SYSTEM,Capability.AGENT_CALL,Capability.XFETCH,Capability.DUAL_MODE,Capability.BACKUP_RESTORE,Capability.CORRELATION_ID,Capability.STRUCTURED_LOGGING,Capability.DID_SUCCESSION,Capability.GATEWAY_STATE,Capability.SUBSCRIPTION_PROOF,Capability.POLICY_ENGINE,Capability.APPROVAL_FLOW,Capability.GUARDRAILS,Capability.HTTP_COMPAT,Capability.DID_WEB,Capability.DID_PRIVATEME,Capability.REDIS_NONCE,Capability.RETRY_TRANSPORT],deprecated:[{name:"envelope-v1",since:"1.2.0",removedIn:"2.0.0",migration:"Use createEnvelopeV2() or higher for split-channel support",docs:"https://private.me/docs/xbind/migration-v2"}],buildDate:(new Date).toISOString(),nodeVersion:process.version};function getVersion(){return Object.freeze({...VERSION_METADATA})}function hasCapability(e){return VERSION_METADATA.features.includes(e)}function getCapabilities(){return Object.freeze([...VERSION_METADATA.features])}function getDeprecationInfo(e){return VERSION_METADATA.deprecated.find(i=>i.name===e)}const warnedFeatures=new Set;function warnIfDeprecated(e){if(warnedFeatures.has(e))return;const i=getDeprecationInfo(e);if(!i)return;warnedFeatures.add(e);const r=[`Feature "${e}" is deprecated since v${i.since}`,i.removedIn?`and will be removed in v${i.removedIn}.`:".",i.migration].join(" ");logger.warn(r,{feature:e,deprecatedSince:i.since,removedIn:i.removedIn,docs:i.docs}),"undefined"!=typeof console&&console.warn&&(console.warn(`[xBind] ${r}`),i.docs&&console.warn(`[xBind] See: ${i.docs}`))}function parseVersion(e){const i=e.match(/^(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9.-]+))?(?:\+([a-zA-Z0-9.-]+))?$/);if(!(i&&i[1]&&i[2]&&i[3]))throw new Error(`Invalid semantic version: ${e}`);return{major:parseInt(i[1],10),minor:parseInt(i[2],10),patch:parseInt(i[3],10),prerelease:i[4]||void 0,build:i[5]||void 0}}function compareVersions(e,i){const r=parseVersion(e),a=parseVersion(i);if(r.major<a.major)return-1;if(r.major>a.major)return 1;if(r.minor<a.minor)return-1;if(r.minor>a.minor)return 1;if(r.patch<a.patch)return-1;if(r.patch>a.patch)return 1;if(r.prerelease&&!a.prerelease)return-1;if(!r.prerelease&&a.prerelease)return 1;if(r.prerelease&&a.prerelease){if(r.prerelease<a.prerelease)return-1;if(r.prerelease>a.prerelease)return 1}return 0}function checkCompatibility(e){const i=VERSION_METADATA.semver;if(e.startsWith("^")){const r=e.slice(1),a=parseVersion(r);return parseVersion(i).major!==a.major?{compatible:!1,message:`Incompatible major version. Required: ^${r}, Current: ${i}`,severity:"error",required:e,actual:i}:compareVersions(i,r)<0?{compatible:!1,message:`SDK version too old. Required: ^${r}, Current: ${i}`,severity:"error",required:e,actual:i}:{compatible:!0,message:`Compatible (${i} satisfies ^${r})`,severity:"info",required:e,actual:i}}if(e.startsWith("~")){const r=e.slice(1),a=parseVersion(r),t=parseVersion(i);return t.major!==a.major||t.minor!==a.minor?{compatible:!1,message:`Incompatible version. Required: ~${r}, Current: ${i}`,severity:"error",required:e,actual:i}:compareVersions(i,r)<0?{compatible:!1,message:`SDK version too old. Required: ~${r}, Current: ${i}`,severity:"error",required:e,actual:i}:{compatible:!0,message:`Compatible (${i} satisfies ~${r})`,severity:"info",required:e,actual:i}}let r,a,t;try{r=compareVersions(i,e)}catch(r){return{compatible:!1,message:`Invalid version format: ${e}`,severity:"error",required:e,actual:i}}if(0===r)return{compatible:!0,message:`Exact version match (${i})`,severity:"info",required:e,actual:i};if(r<0)return{compatible:!1,message:`SDK version too old. Required: ${e}, Current: ${i}`,severity:"error",required:e,actual:i};try{a=parseVersion(e),t=parseVersion(i)}catch(r){return{compatible:!0,message:`Compatible (${i} is newer than ${e})`,severity:"info",required:e,actual:i}}return t.major>a.major?{compatible:!1,message:`Breaking changes in SDK. Required: ${e}, Current: ${i}`,severity:"warning",required:e,actual:i}:{compatible:!0,message:`Compatible (${i} is newer than ${e})`,severity:"info",required:e,actual:i}}function getMinimumVersionFor(e){return{[Capability.ENVELOPE_V1]:"1.0.0",[Capability.ENVELOPE_V2]:"1.1.0",[Capability.ENVELOPE_V3]:"1.2.0",[Capability.ENVELOPE_V4]:"1.3.0",[Capability.ML_KEM_768]:"1.2.0",[Capability.ML_DSA_65]:"1.3.0",[Capability.X25519_ECDH]:"1.0.0",[Capability.ED25519_SIG]:"1.0.0",[Capability.XORIDA]:"1.0.0",[Capability.SPLIT_CHANNEL]:"1.1.0",[Capability.TRUST_REGISTRY]:"1.0.0",[Capability.SERVICE_DISCOVERY]:"1.1.0",[Capability.INVITE_SYSTEM]:"1.1.0",[Capability.AGENT_CALL]:"1.0.0",[Capability.XFETCH]:"1.2.0",[Capability.DUAL_MODE]:"1.2.0",[Capability.BACKUP_RESTORE]:"1.3.0",[Capability.CORRELATION_ID]:"1.3.0",[Capability.STRUCTURED_LOGGING]:"1.3.0",[Capability.DID_SUCCESSION]:"1.2.0",[Capability.GATEWAY_STATE]:"1.2.0",[Capability.SUBSCRIPTION_PROOF]:"1.2.0",[Capability.POLICY_ENGINE]:"1.1.0",[Capability.APPROVAL_FLOW]:"1.1.0",[Capability.GUARDRAILS]:"1.2.0",[Capability.HTTP_COMPAT]:"1.2.0",[Capability.DID_WEB]:"1.1.0",[Capability.DID_PRIVATEME]:"1.2.0",[Capability.REDIS_NONCE]:"1.1.0",[Capability.RETRY_TRANSPORT]:"1.1.0"}[e]}function assertMinimumVersion(e,i){const r=checkCompatibility(e);if(!r.compatible&&"error"===r.severity){const a=i?`${i} requires xBind >= ${e} (current: ${VERSION_METADATA.semver})`:r.message;throw new Error(a)}}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module plugins/logging
|
|
3
|
+
* Logging plugin for xBind plugin system
|
|
4
|
+
*
|
|
5
|
+
* Captures send, receive, encrypt, and decrypt events for debugging and audit trails.
|
|
6
|
+
*/
|
|
7
|
+
import type { Result } from '@private.me/shared';
|
|
8
|
+
import type { Plugin, PluginContext, HookResult } from '../plugin-system.js';
|
|
9
|
+
import type { AnyTransportEnvelope } from '../envelope.js';
|
|
10
|
+
/**
|
|
11
|
+
* Log level enum.
|
|
12
|
+
*/
|
|
13
|
+
export declare enum LogLevel {
|
|
14
|
+
DEBUG = "debug",
|
|
15
|
+
INFO = "info",
|
|
16
|
+
WARN = "warn",
|
|
17
|
+
ERROR = "error"
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Log entry structure.
|
|
21
|
+
*/
|
|
22
|
+
export interface LogEntry {
|
|
23
|
+
timestamp: string;
|
|
24
|
+
level: LogLevel;
|
|
25
|
+
event: 'send' | 'receive' | 'encrypt' | 'decrypt';
|
|
26
|
+
agent: string;
|
|
27
|
+
recipient?: string;
|
|
28
|
+
scope?: string;
|
|
29
|
+
payloadSize?: number;
|
|
30
|
+
metadata?: Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Logging plugin options.
|
|
34
|
+
*/
|
|
35
|
+
export interface LoggingPluginOptions {
|
|
36
|
+
/** Log level threshold (default: INFO) */
|
|
37
|
+
level?: LogLevel;
|
|
38
|
+
/** Include payload sizes in logs (default: true) */
|
|
39
|
+
includeSize?: boolean;
|
|
40
|
+
/** Include metadata in logs (default: false) */
|
|
41
|
+
includeMetadata?: boolean;
|
|
42
|
+
/** Custom log handler (default: console.log) */
|
|
43
|
+
logHandler?: (entry: LogEntry) => void;
|
|
44
|
+
/** Filter function to exclude certain logs */
|
|
45
|
+
filter?: (entry: LogEntry) => boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Logging plugin implementation.
|
|
49
|
+
* Captures all message processing events and outputs structured logs.
|
|
50
|
+
*/
|
|
51
|
+
export declare class LoggingPlugin implements Plugin {
|
|
52
|
+
readonly name = "logging";
|
|
53
|
+
readonly version = "1.0.0";
|
|
54
|
+
readonly description = "Captures message processing events for debugging and audit trails";
|
|
55
|
+
readonly priority = 10;
|
|
56
|
+
private options;
|
|
57
|
+
private logs;
|
|
58
|
+
constructor(options?: LoggingPluginOptions);
|
|
59
|
+
onInit(): Result<void, string>;
|
|
60
|
+
onDestroy(): Result<void, string>;
|
|
61
|
+
onSend(payload: unknown, context: PluginContext): Result<HookResult<unknown>, string>;
|
|
62
|
+
onReceive(envelope: AnyTransportEnvelope, context: PluginContext): Result<HookResult<AnyTransportEnvelope>, string>;
|
|
63
|
+
onEncrypt(plaintext: Uint8Array, context: PluginContext): Result<HookResult<Uint8Array>, string>;
|
|
64
|
+
onDecrypt(plaintext: Uint8Array, context: PluginContext): Result<HookResult<Uint8Array>, string>;
|
|
65
|
+
/**
|
|
66
|
+
* Get all captured logs.
|
|
67
|
+
*/
|
|
68
|
+
getLogs(): readonly LogEntry[];
|
|
69
|
+
/**
|
|
70
|
+
* Clear all logs.
|
|
71
|
+
*/
|
|
72
|
+
clearLogs(): void;
|
|
73
|
+
/**
|
|
74
|
+
* Get logs filtered by criteria.
|
|
75
|
+
*/
|
|
76
|
+
getFilteredLogs(filter: (entry: LogEntry) => boolean): LogEntry[];
|
|
77
|
+
private log;
|
|
78
|
+
private shouldLog;
|
|
79
|
+
private estimateSize;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Create a logging plugin with options.
|
|
83
|
+
*/
|
|
84
|
+
export declare function createLoggingPlugin(options?: LoggingPluginOptions): LoggingPlugin;
|
|
@@ -0,0 +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)}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module plugins/metrics
|
|
3
|
+
* Metrics plugin for xBind plugin system
|
|
4
|
+
*
|
|
5
|
+
* Tracks performance metrics, message counts, and error rates.
|
|
6
|
+
*/
|
|
7
|
+
import type { Result } from '@private.me/shared';
|
|
8
|
+
import type { Plugin, PluginContext, HookResult } from '../plugin-system.js';
|
|
9
|
+
import type { AnyTransportEnvelope } from '../envelope.js';
|
|
10
|
+
/**
|
|
11
|
+
* Metric entry structure.
|
|
12
|
+
*/
|
|
13
|
+
export interface MetricEntry {
|
|
14
|
+
timestamp: number;
|
|
15
|
+
event: 'send' | 'receive' | 'encrypt' | 'decrypt';
|
|
16
|
+
duration: number;
|
|
17
|
+
success: boolean;
|
|
18
|
+
error?: string;
|
|
19
|
+
metadata?: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Aggregated metrics.
|
|
23
|
+
*/
|
|
24
|
+
export interface AggregatedMetrics {
|
|
25
|
+
/** Total number of send operations */
|
|
26
|
+
totalSends: number;
|
|
27
|
+
/** Total number of receive operations */
|
|
28
|
+
totalReceives: number;
|
|
29
|
+
/** Total number of encrypt operations */
|
|
30
|
+
totalEncrypts: number;
|
|
31
|
+
/** Total number of decrypt operations */
|
|
32
|
+
totalDecrypts: number;
|
|
33
|
+
/** Average send duration (ms) */
|
|
34
|
+
avgSendDuration: number;
|
|
35
|
+
/** Average receive duration (ms) */
|
|
36
|
+
avgReceiveDuration: number;
|
|
37
|
+
/** Average encrypt duration (ms) */
|
|
38
|
+
avgEncryptDuration: number;
|
|
39
|
+
/** Average decrypt duration (ms) */
|
|
40
|
+
avgDecryptDuration: number;
|
|
41
|
+
/** Total errors */
|
|
42
|
+
totalErrors: number;
|
|
43
|
+
/** Error rate (0-1) */
|
|
44
|
+
errorRate: number;
|
|
45
|
+
/** Uptime (ms) */
|
|
46
|
+
uptime: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Metrics plugin options.
|
|
50
|
+
*/
|
|
51
|
+
export interface MetricsPluginOptions {
|
|
52
|
+
/** Enable high-resolution timing (default: true) */
|
|
53
|
+
highResolution?: boolean;
|
|
54
|
+
/** Maximum metrics to store in memory (default: 10000) */
|
|
55
|
+
maxMetrics?: number;
|
|
56
|
+
/** Metrics export callback */
|
|
57
|
+
onExport?: (metrics: MetricEntry[]) => void;
|
|
58
|
+
/** Export interval in milliseconds (default: 60000 - 1 minute) */
|
|
59
|
+
exportInterval?: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Metrics plugin implementation.
|
|
63
|
+
* Tracks performance and usage statistics for all operations.
|
|
64
|
+
*/
|
|
65
|
+
export declare class MetricsPlugin implements Plugin {
|
|
66
|
+
readonly name = "metrics";
|
|
67
|
+
readonly version = "1.0.0";
|
|
68
|
+
readonly description = "Tracks performance metrics, message counts, and error rates";
|
|
69
|
+
readonly priority = 20;
|
|
70
|
+
private options;
|
|
71
|
+
private metrics;
|
|
72
|
+
private startTime;
|
|
73
|
+
private exportTimer?;
|
|
74
|
+
constructor(options?: MetricsPluginOptions);
|
|
75
|
+
onInit(): Result<void, string>;
|
|
76
|
+
onDestroy(): Result<void, string>;
|
|
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
|
+
/**
|
|
82
|
+
* Get all captured metrics.
|
|
83
|
+
*/
|
|
84
|
+
getMetrics(): readonly MetricEntry[];
|
|
85
|
+
/**
|
|
86
|
+
* Get aggregated metrics summary.
|
|
87
|
+
*/
|
|
88
|
+
getAggregatedMetrics(): AggregatedMetrics;
|
|
89
|
+
/**
|
|
90
|
+
* Clear all metrics.
|
|
91
|
+
*/
|
|
92
|
+
clearMetrics(): void;
|
|
93
|
+
/**
|
|
94
|
+
* Export metrics using the configured callback.
|
|
95
|
+
*/
|
|
96
|
+
export(): void;
|
|
97
|
+
/**
|
|
98
|
+
* Get metrics for a specific time range.
|
|
99
|
+
*/
|
|
100
|
+
getMetricsInRange(startTime: number, endTime: number): MetricEntry[];
|
|
101
|
+
/**
|
|
102
|
+
* Get metrics for a specific event type.
|
|
103
|
+
*/
|
|
104
|
+
getMetricsByEvent(event: 'send' | 'receive' | 'encrypt' | 'decrypt'): MetricEntry[];
|
|
105
|
+
private record;
|
|
106
|
+
private now;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Create a metrics plugin with options.
|
|
110
|
+
*/
|
|
111
|
+
export declare function createMetricsPlugin(options?: MetricsPluginOptions): MetricsPlugin;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ok}from"../_deps/shared/index.js";export class MetricsPlugin{name="metrics";version="1.0.0";description="Tracks performance metrics, message counts, and error rates";priority=20;options;metrics=[];startTime=Date.now();exportTimer;constructor(t={}){this.options={highResolution:t.highResolution??!0,maxMetrics:t.maxMetrics??1e4,onExport:t.onExport??(()=>{}),exportInterval:t.exportInterval??6e4}}onInit(){return this.startTime=Date.now(),this.options.exportInterval>0&&(this.exportTimer=setInterval(()=>{this.export()},this.options.exportInterval)),ok(void 0)}onDestroy(){return this.exportTimer&&(clearInterval(this.exportTimer),this.exportTimer=void 0),this.export(),this.metrics=[],ok(void 0)}onSend(t,e){const r=this.now(),i=this.now();return this.record({timestamp:Date.now(),event:"send",duration:i-r,success:!0}),ok({payload:t})}onReceive(t,e){const r=this.now(),i=this.now();return this.record({timestamp:Date.now(),event:"receive",duration:i-r,success:!0}),ok({payload:t})}onEncrypt(t,e){const r=this.now(),i=this.now();return this.record({timestamp:Date.now(),event:"encrypt",duration:i-r,success:!0}),ok({payload:t})}onDecrypt(t,e){const r=this.now(),i=this.now();return this.record({timestamp:Date.now(),event:"decrypt",duration:i-r,success:!0}),ok({payload:t})}getMetrics(){return[...this.metrics]}getAggregatedMetrics(){const t=this.metrics.filter(t=>"send"===t.event),e=this.metrics.filter(t=>"receive"===t.event),r=this.metrics.filter(t=>"encrypt"===t.event),i=this.metrics.filter(t=>"decrypt"===t.event),s=this.metrics.filter(t=>!t.success),n=t=>0===t.length?0:t.reduce((t,e)=>t+e.duration,0)/t.length,o=this.metrics.length;return{totalSends:t.length,totalReceives:e.length,totalEncrypts:r.length,totalDecrypts:i.length,avgSendDuration:n(t),avgReceiveDuration:n(e),avgEncryptDuration:n(r),avgDecryptDuration:n(i),totalErrors:s.length,errorRate:o>0?s.length/o:0,uptime:Date.now()-this.startTime}}clearMetrics(){this.metrics=[],this.startTime=Date.now()}export(){this.metrics.length>0&&this.options.onExport([...this.metrics])}getMetricsInRange(t,e){return this.metrics.filter(r=>r.timestamp>=t&&r.timestamp<=e)}getMetricsByEvent(t){return this.metrics.filter(e=>e.event===t)}record(t){this.metrics.push(t),this.metrics.length>this.options.maxMetrics&&this.metrics.shift()}now(){return this.options.highResolution&&"undefined"!=typeof performance?performance.now():Date.now()}}export function createMetricsPlugin(t){return new MetricsPlugin(t)}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module plugins/validation
|
|
3
|
+
* Validation plugin for xBind plugin system
|
|
4
|
+
*
|
|
5
|
+
* Validates payloads, envelopes, and ensures data integrity before processing.
|
|
6
|
+
*/
|
|
7
|
+
import type { Result } from '@private.me/shared';
|
|
8
|
+
import type { Plugin, PluginContext, HookResult } from '../plugin-system.js';
|
|
9
|
+
import type { AnyTransportEnvelope } from '../envelope.js';
|
|
10
|
+
/**
|
|
11
|
+
* Validation rule.
|
|
12
|
+
*/
|
|
13
|
+
export interface ValidationRule {
|
|
14
|
+
/** Rule name */
|
|
15
|
+
name: string;
|
|
16
|
+
/** Validate function - returns error message on failure, null on success */
|
|
17
|
+
validate: (value: unknown, context: PluginContext) => string | null;
|
|
18
|
+
/** Apply to send operations */
|
|
19
|
+
appliesTo?: ('send' | 'receive' | 'encrypt' | 'decrypt')[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Validation plugin options.
|
|
23
|
+
*/
|
|
24
|
+
export interface ValidationPluginOptions {
|
|
25
|
+
/** Maximum payload size in bytes (default: 10MB) */
|
|
26
|
+
maxPayloadSize?: number;
|
|
27
|
+
/** Maximum envelope size in bytes (default: 15MB) */
|
|
28
|
+
maxEnvelopeSize?: number;
|
|
29
|
+
/** Allowed scopes (empty = all allowed) */
|
|
30
|
+
allowedScopes?: string[];
|
|
31
|
+
/** Custom validation rules */
|
|
32
|
+
customRules?: ValidationRule[];
|
|
33
|
+
/** Strict mode - reject any validation warning (default: false) */
|
|
34
|
+
strictMode?: boolean;
|
|
35
|
+
/** Enable payload schema validation (default: false) */
|
|
36
|
+
validateSchema?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Validation plugin implementation.
|
|
40
|
+
* Validates all data before processing to ensure integrity and compliance.
|
|
41
|
+
*/
|
|
42
|
+
export declare class ValidationPlugin implements Plugin {
|
|
43
|
+
readonly name = "validation";
|
|
44
|
+
readonly version = "1.0.0";
|
|
45
|
+
readonly description = "Validates payloads and envelopes before processing";
|
|
46
|
+
readonly priority = 5;
|
|
47
|
+
private options;
|
|
48
|
+
private validationErrors;
|
|
49
|
+
constructor(options?: ValidationPluginOptions);
|
|
50
|
+
onInit(): Result<void, string>;
|
|
51
|
+
onDestroy(): Result<void, string>;
|
|
52
|
+
onSend(payload: unknown, context: PluginContext): Result<HookResult<unknown>, string>;
|
|
53
|
+
onReceive(envelope: AnyTransportEnvelope, context: PluginContext): Result<HookResult<AnyTransportEnvelope>, string>;
|
|
54
|
+
onEncrypt(plaintext: Uint8Array, context: PluginContext): Result<HookResult<Uint8Array>, string>;
|
|
55
|
+
onDecrypt(plaintext: Uint8Array, context: PluginContext): Result<HookResult<Uint8Array>, string>;
|
|
56
|
+
/**
|
|
57
|
+
* Get all validation errors.
|
|
58
|
+
*/
|
|
59
|
+
getValidationErrors(): ReadonlyArray<{
|
|
60
|
+
timestamp: number;
|
|
61
|
+
rule: string;
|
|
62
|
+
error: string;
|
|
63
|
+
}>;
|
|
64
|
+
/**
|
|
65
|
+
* Clear validation errors.
|
|
66
|
+
*/
|
|
67
|
+
clearErrors(): void;
|
|
68
|
+
/**
|
|
69
|
+
* Add a custom validation rule.
|
|
70
|
+
*/
|
|
71
|
+
addRule(rule: ValidationRule): void;
|
|
72
|
+
/**
|
|
73
|
+
* Remove a custom validation rule by name.
|
|
74
|
+
*/
|
|
75
|
+
removeRule(name: string): boolean;
|
|
76
|
+
private validatePayloadSize;
|
|
77
|
+
private validateEnvelopeSize;
|
|
78
|
+
private validateScope;
|
|
79
|
+
private validatePayloadStructure;
|
|
80
|
+
private validateEnvelopeStructure;
|
|
81
|
+
private estimateSize;
|
|
82
|
+
private recordError;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Create a validation plugin with options.
|
|
86
|
+
*/
|
|
87
|
+
export declare function createValidationPlugin(options?: ValidationPluginOptions): ValidationPlugin;
|
|
88
|
+
/**
|
|
89
|
+
* Common validation rules.
|
|
90
|
+
*/
|
|
91
|
+
export declare const CommonRules: {
|
|
92
|
+
/**
|
|
93
|
+
* Validate payload contains required fields.
|
|
94
|
+
*/
|
|
95
|
+
requireFields(fields: string[]): ValidationRule;
|
|
96
|
+
/**
|
|
97
|
+
* Validate DID format.
|
|
98
|
+
*/
|
|
99
|
+
validateDIDFormat(): ValidationRule;
|
|
100
|
+
/**
|
|
101
|
+
* Validate timestamp is recent.
|
|
102
|
+
*/
|
|
103
|
+
validateTimestamp(maxAgeMs?: number): ValidationRule;
|
|
104
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ok,err}from"../_deps/shared/index.js";export class ValidationPlugin{name="validation";version="1.0.0";description="Validates payloads and envelopes before processing";priority=5;options;validationErrors=[];constructor(e={}){this.options={maxPayloadSize:e.maxPayloadSize??10485760,maxEnvelopeSize:e.maxEnvelopeSize??15728640,allowedScopes:e.allowedScopes??[],customRules:e.customRules??[],strictMode:e.strictMode??!1,validateSchema:e.validateSchema??!1}}onInit(){return ok(void 0)}onDestroy(){return this.validationErrors=[],ok(void 0)}onSend(e,r){const t=this.validatePayloadSize(e);if(!1===t.ok)return this.recordError("payload_size",t.error),err(t.error);if(r.scope){const e=this.validateScope(r.scope);if(!1===e.ok)return this.recordError("scope",e.error),err(e.error)}const o=this.validatePayloadStructure(e);if(!1===o.ok)return this.recordError("payload_structure",o.error),err(o.error);for(const t of this.options.customRules)if(!t.appliesTo||t.appliesTo.includes("send")){const o=t.validate(e,r);if(o)return this.recordError(t.name,o),err(`VALIDATION_FAILED:${t.name}:${o}`)}return ok({payload:e})}onReceive(e,r){const t=this.validateEnvelopeSize(e);if(!1===t.ok)return this.recordError("envelope_size",t.error),err(t.error);const o=this.validateEnvelopeStructure(e);if(!1===o.ok)return this.recordError("envelope_structure",o.error),err(o.error);for(const t of this.options.customRules)if(!t.appliesTo||t.appliesTo.includes("receive")){const o=t.validate(e,r);if(o)return this.recordError(t.name,o),err(`VALIDATION_FAILED:${t.name}:${o}`)}return ok({payload:e})}onEncrypt(e,r){if(0===e.length)return this.recordError("plaintext_empty","Plaintext cannot be empty"),err("VALIDATION_FAILED:PLAINTEXT_EMPTY");if(e.length>this.options.maxPayloadSize)return this.recordError("plaintext_size",`Plaintext exceeds max size: ${e.length} bytes`),err(`VALIDATION_FAILED:PLAINTEXT_TOO_LARGE:${e.length}`);for(const t of this.options.customRules)if(!t.appliesTo||t.appliesTo.includes("encrypt")){const o=t.validate(e,r);if(o)return this.recordError(t.name,o),err(`VALIDATION_FAILED:${t.name}:${o}`)}return ok({payload:e})}onDecrypt(e,r){if(0===e.length)return this.recordError("plaintext_empty","Decrypted plaintext is empty"),err("VALIDATION_FAILED:DECRYPTED_EMPTY");for(const t of this.options.customRules)if(!t.appliesTo||t.appliesTo.includes("decrypt")){const o=t.validate(e,r);if(o)return this.recordError(t.name,o),err(`VALIDATION_FAILED:${t.name}:${o}`)}return ok({payload:e})}getValidationErrors(){return[...this.validationErrors]}clearErrors(){this.validationErrors=[]}addRule(e){this.options.customRules.push(e)}removeRule(e){const r=this.options.customRules.findIndex(r=>r.name===e);return-1!==r&&(this.options.customRules.splice(r,1),!0)}validatePayloadSize(e){const r=this.estimateSize(e);return r>this.options.maxPayloadSize?err(`VALIDATION_FAILED:PAYLOAD_TOO_LARGE:${r}>${this.options.maxPayloadSize}`):ok(void 0)}validateEnvelopeSize(e){const r=this.estimateSize(e);return r>this.options.maxEnvelopeSize?err(`VALIDATION_FAILED:ENVELOPE_TOO_LARGE:${r}>${this.options.maxEnvelopeSize}`):ok(void 0)}validateScope(e){return this.options.allowedScopes.length>0&&!this.options.allowedScopes.includes(e)?err(`VALIDATION_FAILED:SCOPE_NOT_ALLOWED:${e}`):ok(void 0)}validatePayloadStructure(e){if(null==e)return err("VALIDATION_FAILED:PAYLOAD_NULL_OR_UNDEFINED");try{JSON.stringify(e)}catch(e){return err(`VALIDATION_FAILED:PAYLOAD_NOT_SERIALIZABLE:${String(e)}`)}return ok(void 0)}validateEnvelopeStructure(e){return"v"in e||"version"in e?e.sender?e.recipient?"payload"in e||"ciphertext"in e?ok(void 0):err("VALIDATION_FAILED:ENVELOPE_MISSING_CIPHERTEXT"):err("VALIDATION_FAILED:ENVELOPE_MISSING_RECIPIENT"):err("VALIDATION_FAILED:ENVELOPE_MISSING_SENDER"):err("VALIDATION_FAILED:ENVELOPE_MISSING_VERSION")}estimateSize(e){if(e instanceof Uint8Array)return e.length;try{return JSON.stringify(e).length}catch{return 0}}recordError(e,r){this.validationErrors.push({timestamp:Date.now(),rule:e,error:r}),this.validationErrors.length>1e3&&this.validationErrors.shift()}}export function createValidationPlugin(e){return new ValidationPlugin(e)}export const CommonRules={requireFields:e=>({name:"require_fields",appliesTo:["send"],validate:r=>{if("object"!=typeof r||null===r)return"Payload must be an object";const t=r,o=e.filter(e=>!(e in t));return o.length>0?`Missing required fields: ${o.join(", ")}`:null}}),validateDIDFormat:()=>({name:"did_format",appliesTo:["send","receive"],validate:(e,r)=>r.recipient&&!r.recipient.startsWith("did:")?`Invalid DID format: ${r.recipient}`:null}),validateTimestamp:(e=3e5)=>({name:"timestamp_freshness",appliesTo:["receive"],validate:(r,t)=>{const o=Date.now()-t.timestamp;return o>e?`Timestamp too old: ${o}ms > ${e}ms`:null}})};
|