@kya-os/mcp-i 1.5.3-canary.0 → 1.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/auth/jwt.d.ts +1 -1
  2. package/dist/auth/oauth/router.js +3 -8
  3. package/dist/cli-adapter/index.js +1 -1
  4. package/dist/cli-adapter/kta-registration.d.ts +1 -1
  5. package/dist/cli-adapter/kta-registration.js +2 -2
  6. package/dist/compiler/config/injection.js +2 -2
  7. package/dist/compiler/get-webpack-config/get-entries.js +12 -8
  8. package/dist/providers/node-providers.d.ts +1 -1
  9. package/dist/providers/node-providers.js +4 -4
  10. package/dist/runtime/adapter-express.js +1 -1
  11. package/dist/runtime/adapter-nextjs.js +1 -1
  12. package/dist/runtime/audit.d.ts +287 -3
  13. package/dist/runtime/audit.js +169 -4
  14. package/dist/runtime/auth-handshake.d.ts +1 -1
  15. package/dist/runtime/auth-handshake.js +1 -1
  16. package/dist/runtime/debug.d.ts +2 -2
  17. package/dist/runtime/debug.js +3 -3
  18. package/dist/runtime/delegation/index.d.ts +7 -0
  19. package/dist/runtime/delegation/index.js +23 -0
  20. package/dist/runtime/delegation/vc-issuer.d.ts +119 -0
  21. package/dist/runtime/delegation/vc-issuer.js +220 -0
  22. package/dist/runtime/delegation/vc-verifier.d.ts +193 -0
  23. package/dist/runtime/delegation/vc-verifier.js +387 -0
  24. package/dist/runtime/http.js +1 -1
  25. package/dist/runtime/identity.d.ts +10 -2
  26. package/dist/runtime/identity.js +68 -11
  27. package/dist/runtime/mcpi-runtime.d.ts +28 -1
  28. package/dist/runtime/mcpi-runtime.js +2 -2
  29. package/dist/runtime/migrate-identity.d.ts +16 -0
  30. package/dist/runtime/migrate-identity.js +118 -0
  31. package/dist/runtime/proof.js +2 -2
  32. package/dist/runtime/stdio.js +1 -1
  33. package/dist/runtime/transports/http/index.js +3 -1
  34. package/dist/runtime/utils/time.d.ts +80 -0
  35. package/dist/runtime/utils/time.js +117 -0
  36. package/dist/runtime/utils/tools.js +22 -3
  37. package/dist/runtime/verifier-middleware.js +1 -1
  38. package/dist/runtime/well-known.d.ts +0 -4
  39. package/dist/runtime/well-known.js +12 -26
  40. package/dist/storage/delegation.js +2 -2
  41. package/dist/test/deterministic-keys.d.ts +1 -1
  42. package/dist/test/deterministic-keys.js +6 -6
  43. package/dist/test/examples/test-usage-example.d.ts +6 -6
  44. package/dist/test/examples/test-usage-example.js +5 -5
  45. package/dist/test/local-verification.d.ts +1 -1
  46. package/dist/test/local-verification.js +10 -10
  47. package/dist/test/mock-identity-provider.d.ts +4 -4
  48. package/dist/test/mock-identity-provider.js +7 -7
  49. package/dist/test/runtime-integration.d.ts +2 -2
  50. package/package.json +4 -3
@@ -1,41 +1,294 @@
1
1
  /**
2
- * Audit Logging System for XMCP-I Runtime
2
+ * Audit Logging System for MCP-I Runtime
3
3
  *
4
4
  * Handles audit record generation and logging with frozen format
5
- * according to requirements 5.4, 5.5.
5
+ * according to requirements 5.4, 5.5, and 6.7 (configurable retention).
6
+ *
7
+ * ## Privacy Guarantees
8
+ *
9
+ * This system is designed with privacy-first principles:
10
+ *
11
+ * **NEVER Logged:**
12
+ * - Request/response bodies (only SHA-256 hashes)
13
+ * - Secrets (private keys, API keys, tokens, nonces)
14
+ * - PII (names, emails, addresses, phone numbers)
15
+ * - Key material (only key IDs are logged)
16
+ *
17
+ * **ALWAYS Logged:**
18
+ * - Metadata only (DIDs, key IDs, timestamps)
19
+ * - SHA-256 hashes (not plaintext data)
20
+ * - Session IDs (for correlation, not sensitive)
21
+ * - Verification results (yes/no only)
22
+ * - Scope identifiers (application-level)
23
+ *
24
+ * ## Frozen Format
25
+ *
26
+ * The audit.v1 format is **frozen** and will not change:
27
+ *
28
+ * ```
29
+ * audit.v1 ts=<unix> session=<id> audience=<host> did=<did> kid=<kid> reqHash=<sha256:..> resHash=<sha256:..> verified=yes|no scope=<scopeId|->
30
+ * ```
31
+ *
32
+ * ## Event-Driven Rotation
33
+ *
34
+ * This implementation uses **event-driven rotation** (not timers):
35
+ * - Rotation checks happen on each `logAuditRecord()` call
36
+ * - No setInterval/setTimeout (works in Cloudflare Workers)
37
+ * - No cleanup needed (no timers to clear)
38
+ * - Predictable behavior (rotation on activity)
39
+ *
40
+ * @module audit
41
+ * @see {@link https://github.com/kya-os/xmcp-i/docs/concepts/audit-logging.md | Audit Logging Documentation}
6
42
  */
7
43
  import { AuditRecord } from "@kya-os/contracts/proof";
8
44
  import { SessionContext } from "@kya-os/contracts/handshake";
9
45
  import { AgentIdentity } from "./identity";
46
+ /**
47
+ * Audit log rotation strategy
48
+ */
49
+ export type AuditRotationStrategy = "size" | "time" | "count" | "custom";
50
+ /**
51
+ * Audit rotation context passed to hooks
52
+ */
53
+ export interface AuditRotationContext {
54
+ strategy: AuditRotationStrategy;
55
+ trigger: string;
56
+ recordsLogged: number;
57
+ timestamp: number;
58
+ }
59
+ /**
60
+ * Audit log rotation hooks
61
+ */
62
+ export interface AuditRotationHooks {
63
+ /**
64
+ * Called when audit log should be rotated
65
+ * @param context - Rotation context with metadata
66
+ * @returns Promise that resolves when rotation is complete
67
+ */
68
+ onRotation?: (context: AuditRotationContext) => Promise<void>;
69
+ /**
70
+ * Called when audit log reaches size limit
71
+ * @param sizeBytes - Current size in bytes
72
+ * @param limit - Size limit that was exceeded
73
+ */
74
+ onSizeLimit?: (sizeBytes: number, limit: number) => Promise<void>;
75
+ /**
76
+ * Called on time-based rotation (e.g., daily, hourly)
77
+ * @param interval - Rotation interval that triggered (e.g., "daily", "hourly")
78
+ */
79
+ onTimeBased?: (interval: string) => Promise<void>;
80
+ /**
81
+ * Called when record count reaches threshold
82
+ * @param count - Number of records logged
83
+ * @param threshold - Count threshold that was exceeded
84
+ */
85
+ onCountThreshold?: (count: number, threshold: number) => Promise<void>;
86
+ }
10
87
  /**
11
88
  * Audit logging configuration
89
+ *
90
+ * @example Basic configuration
91
+ * ```typescript
92
+ * const config: AuditConfig = {
93
+ * enabled: true,
94
+ * logFunction: console.log,
95
+ * includePayloads: false, // ALWAYS false for privacy
96
+ * };
97
+ * ```
98
+ *
99
+ * @example With rotation
100
+ * ```typescript
101
+ * const config: AuditConfig = {
102
+ * enabled: true,
103
+ * rotation: {
104
+ * strategy: 'size',
105
+ * sizeLimit: 10 * 1024 * 1024, // 10 MB
106
+ * hooks: {
107
+ * onRotation: async (context) => {
108
+ * // Archive old log file
109
+ * },
110
+ * },
111
+ * },
112
+ * };
113
+ * ```
12
114
  */
13
115
  export interface AuditConfig {
116
+ /**
117
+ * Enable audit logging (default: true)
118
+ */
14
119
  enabled?: boolean;
120
+ /**
121
+ * Custom log function (default: console.log)
122
+ *
123
+ * @param record - The formatted audit line (frozen format)
124
+ *
125
+ * @example File-based logging
126
+ * ```typescript
127
+ * logFunction: (record) => {
128
+ * fs.appendFileSync('/var/log/audit.log', record + '\n');
129
+ * }
130
+ * ```
131
+ */
15
132
  logFunction?: (record: string) => void;
133
+ /**
134
+ * Include payloads in logs (default: false)
135
+ *
136
+ * **WARNING:** This should ALWAYS be false. The frozen format ensures
137
+ * that even if set to true, no request/response bodies will be logged.
138
+ * This flag exists for compatibility but has no effect on the frozen format.
139
+ *
140
+ * @deprecated This flag has no effect due to frozen format privacy guarantees
141
+ */
16
142
  includePayloads?: boolean;
143
+ /**
144
+ * Log rotation configuration (event-driven, no timers)
145
+ */
146
+ rotation?: {
147
+ /**
148
+ * Rotation strategy
149
+ * - 'size': Rotate when log reaches size limit (checked on each call)
150
+ * - 'time': Rotate based on elapsed time (checked on each call)
151
+ * - 'count': Rotate after N records
152
+ * - 'custom': Custom rotation logic via hooks only
153
+ */
154
+ strategy?: AuditRotationStrategy;
155
+ /**
156
+ * Size limit in bytes (for size-based rotation)
157
+ *
158
+ * @example 10 MB limit
159
+ * ```typescript
160
+ * sizeLimit: 10 * 1024 * 1024
161
+ * ```
162
+ */
163
+ sizeLimit?: number;
164
+ /**
165
+ * Time interval in milliseconds (for time-based rotation)
166
+ * Rotation is checked on each logAuditRecord() call, not via timer.
167
+ *
168
+ * @example Daily rotation
169
+ * ```typescript
170
+ * timeInterval: 24 * 60 * 60 * 1000
171
+ * ```
172
+ */
173
+ timeInterval?: number;
174
+ /**
175
+ * Record count threshold (for count-based rotation)
176
+ *
177
+ * @example Rotate after 10k records
178
+ * ```typescript
179
+ * countThreshold: 10000
180
+ * ```
181
+ */
182
+ countThreshold?: number;
183
+ /**
184
+ * Custom rotation hooks
185
+ */
186
+ hooks?: AuditRotationHooks;
187
+ };
17
188
  }
18
189
  /**
19
190
  * Audit context for logging
191
+ *
192
+ * Contains all metadata needed to generate an audit record.
193
+ *
194
+ * **Privacy Note:** Only metadata is extracted from these objects.
195
+ * The identity's private key, session's nonce, and other sensitive
196
+ * fields are NEVER included in the audit log.
197
+ *
198
+ * @example
199
+ * ```typescript
200
+ * const context: AuditContext = {
201
+ * identity: {
202
+ * did: 'did:web:example.com:agents:agent-1',
203
+ * keyId: 'key-20241014-abc123',
204
+ * // ... private key NOT logged
205
+ * },
206
+ * session: {
207
+ * sessionId: 'sess_abc123',
208
+ * audience: 'example.com',
209
+ * // ... nonce NOT logged
210
+ * },
211
+ * requestHash: 'sha256:1234567890abcdef...',
212
+ * responseHash: 'sha256:fedcba0987654321...',
213
+ * verified: 'yes',
214
+ * scopeId: 'orders.create',
215
+ * };
216
+ * ```
20
217
  */
21
218
  export interface AuditContext {
219
+ /**
220
+ * Agent identity
221
+ *
222
+ * Only `did` and `keyId` are logged. Private key is NEVER logged.
223
+ */
22
224
  identity: AgentIdentity;
225
+ /**
226
+ * Session context
227
+ *
228
+ * Only `sessionId` and `audience` are logged. Nonce is NEVER logged.
229
+ */
23
230
  session: SessionContext;
231
+ /**
232
+ * Request hash (SHA-256 with `sha256:` prefix)
233
+ *
234
+ * @example 'sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
235
+ */
24
236
  requestHash: string;
237
+ /**
238
+ * Response hash (SHA-256 with `sha256:` prefix)
239
+ *
240
+ * @example 'sha256:fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321'
241
+ */
25
242
  responseHash: string;
243
+ /**
244
+ * Verification result
245
+ *
246
+ * - 'yes': Proof was verified successfully
247
+ * - 'no': Proof verification failed
248
+ */
26
249
  verified: "yes" | "no";
250
+ /**
251
+ * Optional scope identifier
252
+ *
253
+ * Application-level scope (e.g., 'orders.create', 'users.read').
254
+ * If not provided, '-' is used in the audit log.
255
+ *
256
+ * @example 'orders.create'
257
+ */
27
258
  scopeId?: string;
28
259
  }
29
260
  /**
30
- * Audit logger class
261
+ * Audit logger class with event-driven rotation support
262
+ *
263
+ * Privacy Guarantees:
264
+ * - NEVER logs request/response bodies (only SHA-256 hashes)
265
+ * - NEVER logs secrets (private keys, API keys, tokens, nonces)
266
+ * - NEVER logs PII (personal information)
267
+ * - Only logs metadata: DIDs, key IDs, timestamps, hashes, session IDs
268
+ * - Frozen format: audit.v1 with fixed field order
269
+ *
270
+ * Rotation Strategy:
271
+ * - Event-driven (no timers) - rotation checks on each logAuditRecord() call
272
+ * - Works in all environments (Node.js, Cloudflare Workers, Vercel Edge)
273
+ * - No cleanup needed (no timers to clear)
31
274
  */
32
275
  export declare class AuditLogger {
33
276
  private config;
34
277
  private sessionAuditLog;
278
+ private totalRecordsLogged;
279
+ private currentLogSize;
280
+ private lastRotationTime;
281
+ private destroyed;
35
282
  constructor(config?: AuditConfig);
36
283
  /**
37
284
  * Emit audit record on first call per session
38
285
  * Requirements: 5.4, 5.5
286
+ *
287
+ * This method:
288
+ * 1. Checks if logger is destroyed
289
+ * 2. Logs audit record (first call per session)
290
+ * 3. Checks if rotation is needed (event-driven)
291
+ * 4. Triggers rotation hooks if threshold met
39
292
  */
40
293
  logAuditRecord(context: AuditContext): Promise<void>;
41
294
  /**
@@ -43,6 +296,34 @@ export declare class AuditLogger {
43
296
  * Format: audit.v1 ts=<unix> session=<id> audience=<host> did=<did> kid=<kid> reqHash=<sha256:..> resHash=<sha256:..> verified=yes|no scope=<scopeId|->
44
297
  */
45
298
  private formatAuditLine;
299
+ /**
300
+ * Check if rotation is needed and trigger if necessary (event-driven)
301
+ *
302
+ * This method is called on each logAuditRecord() call.
303
+ * No timers are used - rotation is checked based on current state.
304
+ */
305
+ private checkRotation;
306
+ /**
307
+ * Rotate audit log now (manually triggered)
308
+ *
309
+ * This method:
310
+ * 1. Calls onRotation hook (for user to archive/rotate log file)
311
+ * 2. Resets rotation counters (size, time, count)
312
+ *
313
+ * @param trigger - Reason for rotation (e.g., "manual", "size-limit")
314
+ */
315
+ rotateNow(trigger?: string): Promise<void>;
316
+ /**
317
+ * Destroy audit logger and cleanup resources
318
+ *
319
+ * This method:
320
+ * 1. Clears session tracking (memory)
321
+ * 2. Resets statistics
322
+ * 3. Marks logger as destroyed
323
+ *
324
+ * Note: No timers to clear (event-driven rotation)
325
+ */
326
+ destroy(): void;
46
327
  /**
47
328
  * Clear session audit log (useful for testing)
48
329
  */
@@ -54,6 +335,9 @@ export declare class AuditLogger {
54
335
  enabled: boolean;
55
336
  sessionsLogged: number;
56
337
  includePayloads: boolean;
338
+ totalRecordsLogged: number;
339
+ currentLogSize: number;
340
+ lastRotationTime: number;
57
341
  };
58
342
  /**
59
343
  * Update configuration
@@ -1,34 +1,104 @@
1
1
  "use strict";
2
2
  /**
3
- * Audit Logging System for XMCP-I Runtime
3
+ * Audit Logging System for MCP-I Runtime
4
4
  *
5
5
  * Handles audit record generation and logging with frozen format
6
- * according to requirements 5.4, 5.5.
6
+ * according to requirements 5.4, 5.5, and 6.7 (configurable retention).
7
+ *
8
+ * ## Privacy Guarantees
9
+ *
10
+ * This system is designed with privacy-first principles:
11
+ *
12
+ * **NEVER Logged:**
13
+ * - Request/response bodies (only SHA-256 hashes)
14
+ * - Secrets (private keys, API keys, tokens, nonces)
15
+ * - PII (names, emails, addresses, phone numbers)
16
+ * - Key material (only key IDs are logged)
17
+ *
18
+ * **ALWAYS Logged:**
19
+ * - Metadata only (DIDs, key IDs, timestamps)
20
+ * - SHA-256 hashes (not plaintext data)
21
+ * - Session IDs (for correlation, not sensitive)
22
+ * - Verification results (yes/no only)
23
+ * - Scope identifiers (application-level)
24
+ *
25
+ * ## Frozen Format
26
+ *
27
+ * The audit.v1 format is **frozen** and will not change:
28
+ *
29
+ * ```
30
+ * audit.v1 ts=<unix> session=<id> audience=<host> did=<did> kid=<kid> reqHash=<sha256:..> resHash=<sha256:..> verified=yes|no scope=<scopeId|->
31
+ * ```
32
+ *
33
+ * ## Event-Driven Rotation
34
+ *
35
+ * This implementation uses **event-driven rotation** (not timers):
36
+ * - Rotation checks happen on each `logAuditRecord()` call
37
+ * - No setInterval/setTimeout (works in Cloudflare Workers)
38
+ * - No cleanup needed (no timers to clear)
39
+ * - Predictable behavior (rotation on activity)
40
+ *
41
+ * @module audit
42
+ * @see {@link https://github.com/kya-os/xmcp-i/docs/concepts/audit-logging.md | Audit Logging Documentation}
7
43
  */
8
44
  Object.defineProperty(exports, "__esModule", { value: true });
9
45
  exports.defaultAuditLogger = exports.AuditLogger = void 0;
10
46
  exports.logKeyRotationAudit = logKeyRotationAudit;
11
47
  exports.parseAuditLine = parseAuditLine;
12
48
  exports.validateAuditRecord = validateAuditRecord;
49
+ const time_1 = require("./utils/time");
13
50
  /**
14
- * Audit logger class
51
+ * Audit logger class with event-driven rotation support
52
+ *
53
+ * Privacy Guarantees:
54
+ * - NEVER logs request/response bodies (only SHA-256 hashes)
55
+ * - NEVER logs secrets (private keys, API keys, tokens, nonces)
56
+ * - NEVER logs PII (personal information)
57
+ * - Only logs metadata: DIDs, key IDs, timestamps, hashes, session IDs
58
+ * - Frozen format: audit.v1 with fixed field order
59
+ *
60
+ * Rotation Strategy:
61
+ * - Event-driven (no timers) - rotation checks on each logAuditRecord() call
62
+ * - Works in all environments (Node.js, Cloudflare Workers, Vercel Edge)
63
+ * - No cleanup needed (no timers to clear)
15
64
  */
16
65
  class AuditLogger {
17
66
  config;
18
67
  sessionAuditLog = new Set(); // Track first call per session
68
+ totalRecordsLogged = 0; // Total records logged (for count rotation)
69
+ currentLogSize = 0; // Current log size in bytes (for size rotation)
70
+ lastRotationTime = Date.now(); // Last rotation timestamp (for time rotation)
71
+ destroyed = false; // Track if logger has been destroyed
19
72
  constructor(config = {}) {
73
+ // Merge rotation config carefully to preserve defaults
74
+ const rotationConfig = config.rotation
75
+ ? {
76
+ strategy: "custom",
77
+ ...config.rotation,
78
+ }
79
+ : undefined;
20
80
  this.config = {
21
81
  enabled: true,
22
82
  logFunction: console.log,
23
83
  includePayloads: false, // Keep identity/proof data out by default
24
84
  ...config,
85
+ rotation: rotationConfig,
25
86
  };
26
87
  }
27
88
  /**
28
89
  * Emit audit record on first call per session
29
90
  * Requirements: 5.4, 5.5
91
+ *
92
+ * This method:
93
+ * 1. Checks if logger is destroyed
94
+ * 2. Logs audit record (first call per session)
95
+ * 3. Checks if rotation is needed (event-driven)
96
+ * 4. Triggers rotation hooks if threshold met
30
97
  */
31
98
  async logAuditRecord(context) {
99
+ if (this.destroyed) {
100
+ throw new Error("AuditLogger has been destroyed");
101
+ }
32
102
  if (!this.config.enabled) {
33
103
  return;
34
104
  }
@@ -46,7 +116,7 @@ class AuditLogger {
46
116
  session: context.session.sessionId,
47
117
  audience: context.session.audience,
48
118
  did: context.identity.did,
49
- kid: context.identity.keyId,
119
+ kid: context.identity.kid,
50
120
  reqHash: context.requestHash,
51
121
  resHash: context.responseHash,
52
122
  verified: context.verified,
@@ -54,8 +124,14 @@ class AuditLogger {
54
124
  };
55
125
  // Format as frozen audit line
56
126
  const auditLine = this.formatAuditLine(auditRecord);
127
+ // Track size in bytes (UTF-8)
128
+ const sizeBytes = Buffer.byteLength(auditLine, "utf8");
129
+ this.currentLogSize += sizeBytes;
130
+ this.totalRecordsLogged++;
57
131
  // Emit audit record
58
132
  this.config.logFunction(auditLine);
133
+ // Check if rotation is needed (event-driven)
134
+ await this.checkRotation();
59
135
  }
60
136
  /**
61
137
  * Format audit record as frozen audit line
@@ -76,6 +152,92 @@ class AuditLogger {
76
152
  ];
77
153
  return fields.join(" ");
78
154
  }
155
+ /**
156
+ * Check if rotation is needed and trigger if necessary (event-driven)
157
+ *
158
+ * This method is called on each logAuditRecord() call.
159
+ * No timers are used - rotation is checked based on current state.
160
+ */
161
+ async checkRotation() {
162
+ if (!this.config.rotation) {
163
+ return;
164
+ }
165
+ const { strategy, sizeLimit, timeInterval, countThreshold, hooks } = this.config.rotation;
166
+ let shouldRotate = false;
167
+ let trigger = "";
168
+ // Size-based rotation
169
+ if (strategy === "size" && sizeLimit && this.currentLogSize >= sizeLimit) {
170
+ shouldRotate = true;
171
+ trigger = "size-limit";
172
+ await hooks?.onSizeLimit?.(this.currentLogSize, sizeLimit);
173
+ }
174
+ // Time-based rotation (event-driven, not timer-based)
175
+ if (strategy === "time" &&
176
+ timeInterval &&
177
+ Date.now() - this.lastRotationTime >= timeInterval) {
178
+ shouldRotate = true;
179
+ trigger = "time-interval";
180
+ const interval = (0, time_1.formatTimeInterval)(timeInterval);
181
+ await hooks?.onTimeBased?.(interval);
182
+ }
183
+ // Count-based rotation
184
+ if (strategy === "count" &&
185
+ countThreshold &&
186
+ this.totalRecordsLogged >= countThreshold) {
187
+ shouldRotate = true;
188
+ trigger = "count-threshold";
189
+ await hooks?.onCountThreshold?.(this.totalRecordsLogged, countThreshold);
190
+ }
191
+ // Trigger rotation if needed
192
+ if (shouldRotate) {
193
+ await this.rotateNow(trigger);
194
+ }
195
+ }
196
+ /**
197
+ * Rotate audit log now (manually triggered)
198
+ *
199
+ * This method:
200
+ * 1. Calls onRotation hook (for user to archive/rotate log file)
201
+ * 2. Resets rotation counters (size, time, count)
202
+ *
203
+ * @param trigger - Reason for rotation (e.g., "manual", "size-limit")
204
+ */
205
+ async rotateNow(trigger = "manual") {
206
+ if (!this.config.rotation?.hooks?.onRotation) {
207
+ return;
208
+ }
209
+ const context = {
210
+ strategy: this.config.rotation.strategy || "custom",
211
+ trigger,
212
+ recordsLogged: this.totalRecordsLogged,
213
+ timestamp: Date.now(),
214
+ };
215
+ // Call rotation hook (user implements log file rotation)
216
+ await this.config.rotation.hooks.onRotation(context);
217
+ // Reset rotation counters
218
+ this.currentLogSize = 0;
219
+ this.lastRotationTime = Date.now();
220
+ this.totalRecordsLogged = 0;
221
+ }
222
+ /**
223
+ * Destroy audit logger and cleanup resources
224
+ *
225
+ * This method:
226
+ * 1. Clears session tracking (memory)
227
+ * 2. Resets statistics
228
+ * 3. Marks logger as destroyed
229
+ *
230
+ * Note: No timers to clear (event-driven rotation)
231
+ */
232
+ destroy() {
233
+ if (this.destroyed) {
234
+ return; // Idempotent
235
+ }
236
+ this.sessionAuditLog.clear();
237
+ this.totalRecordsLogged = 0;
238
+ this.currentLogSize = 0;
239
+ this.destroyed = true;
240
+ }
79
241
  /**
80
242
  * Clear session audit log (useful for testing)
81
243
  */
@@ -90,6 +252,9 @@ class AuditLogger {
90
252
  enabled: this.config.enabled,
91
253
  sessionsLogged: this.sessionAuditLog.size,
92
254
  includePayloads: this.config.includePayloads,
255
+ totalRecordsLogged: this.totalRecordsLogged,
256
+ currentLogSize: this.currentLogSize,
257
+ lastRotationTime: this.lastRotationTime,
93
258
  };
94
259
  }
95
260
  /**
@@ -136,7 +136,7 @@ export declare class MemoryResumeTokenStore implements ResumeTokenStore {
136
136
  * @param resumeToken - Optional resume token from previous authorization
137
137
  * @returns Verification result with delegation or auth error
138
138
  */
139
- export declare function verifyOrHints(agentDid: string, scopes: string[], config: AuthHandshakeConfig, resumeToken?: string): Promise<VerifyOrHintsResult>;
139
+ export declare function verifyOrHints(agentDid: string, scopes: string[], config: AuthHandshakeConfig, _resumeToken?: string): Promise<VerifyOrHintsResult>;
140
140
  /**
141
141
  * Helper: Check if scopes are sensitive and require authorization
142
142
  *
@@ -81,7 +81,7 @@ exports.MemoryResumeTokenStore = MemoryResumeTokenStore;
81
81
  * @param resumeToken - Optional resume token from previous authorization
82
82
  * @returns Verification result with delegation or auth error
83
83
  */
84
- async function verifyOrHints(agentDid, scopes, config, resumeToken) {
84
+ async function verifyOrHints(agentDid, scopes, config, _resumeToken) {
85
85
  const startTime = Date.now();
86
86
  if (config.debug) {
87
87
  console.log(`[AuthHandshake] Verifying ${agentDid} for scopes: ${scopes.join(', ')}`);
@@ -16,7 +16,7 @@ export interface DebugVerificationResult {
16
16
  signature: {
17
17
  valid: boolean;
18
18
  algorithm: string;
19
- keyId: string;
19
+ kid: string;
20
20
  };
21
21
  proof: {
22
22
  valid: boolean;
@@ -43,7 +43,7 @@ export interface DebugVerificationResult {
43
43
  export interface DebugPageData {
44
44
  identity: {
45
45
  did: string;
46
- keyId: string;
46
+ kid: string;
47
47
  didDocumentUrl: string;
48
48
  };
49
49
  registry: {
@@ -46,7 +46,7 @@ class DebugManager {
46
46
  const data = {
47
47
  identity: {
48
48
  did: this.identity.did,
49
- keyId: this.identity.keyId,
49
+ kid: this.identity.kid,
50
50
  didDocumentUrl: this.generateDIDDocumentUrl(this.identity.did),
51
51
  },
52
52
  registry: {
@@ -115,7 +115,7 @@ class DebugManager {
115
115
  signature: {
116
116
  valid: false,
117
117
  algorithm: "EdDSA",
118
- keyId: proof.meta.kid,
118
+ kid: proof.meta.kid,
119
119
  },
120
120
  proof: {
121
121
  valid: false,
@@ -366,7 +366,7 @@ class DebugManager {
366
366
  </div>
367
367
  <div class="field">
368
368
  <label>Key ID</label>
369
- <div class="value">${data.identity.keyId}</div>
369
+ <div class="value">${data.identity.kid}</div>
370
370
  </div>
371
371
  <div class="field">
372
372
  <label>DID Document</label>
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Delegation Module Exports
3
+ *
4
+ * W3C VC-based delegation issuance and verification
5
+ */
6
+ export * from './vc-issuer';
7
+ export * from './vc-verifier';
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /**
3
+ * Delegation Module Exports
4
+ *
5
+ * W3C VC-based delegation issuance and verification
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ __exportStar(require("./vc-issuer"), exports);
23
+ __exportStar(require("./vc-verifier"), exports);