@kya-os/mcp-i 1.11.1 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -7
- package/dist/365.js +1 -0
- package/dist/runtime/160.js +1 -0
- package/dist/runtime/adapter-express.js +3 -3
- package/dist/runtime/adapter-nextjs.js +3 -3
- package/dist/runtime/http.js +3 -3
- package/dist/runtime/index.d.ts +1 -2
- package/dist/runtime/index.js +3 -10
- package/dist/runtime/mcpi-runtime-wrapper.js +1 -8
- package/dist/runtime/mcpi-runtime.d.ts +4 -12
- package/dist/runtime/mcpi-runtime.js +38 -31
- package/dist/runtime/stdio.js +3 -3
- package/dist/runtime/utils/time.d.ts +1 -1
- package/dist/runtime/utils/time.js +1 -1
- package/package.json +5 -5
- package/dist/342.js +0 -1
- package/dist/runtime/337.js +0 -1
- package/dist/runtime/audit.d.ts +0 -430
- package/dist/runtime/audit.js +0 -439
package/dist/runtime/audit.d.ts
DELETED
|
@@ -1,430 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Audit Logging System for MCP-I Runtime
|
|
3
|
-
*
|
|
4
|
-
* TODO: Update AuditLogger to implement IAuditLogger from @kya-os/mcp-i-core/runtime/audit-logger.
|
|
5
|
-
* Currently using Node.js-specific implementation. This will allow the interface to be used
|
|
6
|
-
* across all platform implementations while maintaining platform-specific crypto implementations.
|
|
7
|
-
*
|
|
8
|
-
* Handles audit record generation and logging with frozen format
|
|
9
|
-
* according to requirements 5.4, 5.5, and 6.7 (configurable retention).
|
|
10
|
-
*
|
|
11
|
-
* ## Privacy Guarantees
|
|
12
|
-
*
|
|
13
|
-
* This system is designed with privacy-first principles:
|
|
14
|
-
*
|
|
15
|
-
* **NEVER Logged:**
|
|
16
|
-
* - Request/response bodies (only SHA-256 hashes)
|
|
17
|
-
* - Secrets (private keys, API keys, tokens, nonces)
|
|
18
|
-
* - PII (names, emails, addresses, phone numbers)
|
|
19
|
-
* - Key material (only key IDs are logged)
|
|
20
|
-
*
|
|
21
|
-
* **ALWAYS Logged:**
|
|
22
|
-
* - Metadata only (DIDs, key IDs, timestamps)
|
|
23
|
-
* - SHA-256 hashes (not plaintext data)
|
|
24
|
-
* - Session IDs (for correlation, not sensitive)
|
|
25
|
-
* - Verification results (yes/no only)
|
|
26
|
-
* - Scope identifiers (application-level)
|
|
27
|
-
*
|
|
28
|
-
* ## Frozen Format
|
|
29
|
-
*
|
|
30
|
-
* The audit.v1 format is **frozen** and will not change:
|
|
31
|
-
*
|
|
32
|
-
* ```
|
|
33
|
-
* audit.v1 ts=<unix> session=<id> audience=<host> did=<did> kid=<kid> reqHash=<sha256:..> resHash=<sha256:..> verified=yes|no scope=<scopeId|->
|
|
34
|
-
* ```
|
|
35
|
-
*
|
|
36
|
-
* ## Event-Driven Rotation
|
|
37
|
-
*
|
|
38
|
-
* This implementation uses **event-driven rotation** (not timers):
|
|
39
|
-
* - Rotation checks happen on each `logAuditRecord()` call
|
|
40
|
-
* - No setInterval/setTimeout (works in Cloudflare Workers)
|
|
41
|
-
* - No cleanup needed (no timers to clear)
|
|
42
|
-
* - Predictable behavior (rotation on activity)
|
|
43
|
-
*
|
|
44
|
-
* @module audit
|
|
45
|
-
* @see {@link https://github.com/kya-os/xmcp-i/docs/concepts/audit-logging.md | Audit Logging Documentation}
|
|
46
|
-
*/
|
|
47
|
-
import type { AuditRecord } from "@kya-os/mcp/types" with { "resolution-mode": "import" };
|
|
48
|
-
import { SessionContext } from "@kya-os/contracts/handshake";
|
|
49
|
-
import { AgentIdentity } from "./identity";
|
|
50
|
-
/**
|
|
51
|
-
* Audit log rotation strategy
|
|
52
|
-
*/
|
|
53
|
-
export type AuditRotationStrategy = "size" | "time" | "count" | "custom";
|
|
54
|
-
/**
|
|
55
|
-
* Audit rotation context passed to hooks
|
|
56
|
-
*/
|
|
57
|
-
export interface AuditRotationContext {
|
|
58
|
-
strategy: AuditRotationStrategy;
|
|
59
|
-
trigger: string;
|
|
60
|
-
recordsLogged: number;
|
|
61
|
-
timestamp: number;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Audit log rotation hooks
|
|
65
|
-
*/
|
|
66
|
-
export interface AuditRotationHooks {
|
|
67
|
-
/**
|
|
68
|
-
* Called when audit log should be rotated
|
|
69
|
-
* @param context - Rotation context with metadata
|
|
70
|
-
* @returns Promise that resolves when rotation is complete
|
|
71
|
-
*/
|
|
72
|
-
onRotation?: (context: AuditRotationContext) => Promise<void>;
|
|
73
|
-
/**
|
|
74
|
-
* Called when audit log reaches size limit
|
|
75
|
-
* @param sizeBytes - Current size in bytes
|
|
76
|
-
* @param limit - Size limit that was exceeded
|
|
77
|
-
*/
|
|
78
|
-
onSizeLimit?: (sizeBytes: number, limit: number) => Promise<void>;
|
|
79
|
-
/**
|
|
80
|
-
* Called on time-based rotation (e.g., daily, hourly)
|
|
81
|
-
* @param interval - Rotation interval that triggered (e.g., "daily", "hourly")
|
|
82
|
-
*/
|
|
83
|
-
onTimeBased?: (interval: string) => Promise<void>;
|
|
84
|
-
/**
|
|
85
|
-
* Called when record count reaches threshold
|
|
86
|
-
* @param count - Number of records logged
|
|
87
|
-
* @param threshold - Count threshold that was exceeded
|
|
88
|
-
*/
|
|
89
|
-
onCountThreshold?: (count: number, threshold: number) => Promise<void>;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Audit logging configuration
|
|
93
|
-
*
|
|
94
|
-
* @example Basic configuration
|
|
95
|
-
* ```typescript
|
|
96
|
-
* const config: AuditConfig = {
|
|
97
|
-
* enabled: true,
|
|
98
|
-
* logFunction: console.log,
|
|
99
|
-
* includePayloads: false, // ALWAYS false for privacy
|
|
100
|
-
* };
|
|
101
|
-
* ```
|
|
102
|
-
*
|
|
103
|
-
* @example With rotation
|
|
104
|
-
* ```typescript
|
|
105
|
-
* const config: AuditConfig = {
|
|
106
|
-
* enabled: true,
|
|
107
|
-
* rotation: {
|
|
108
|
-
* strategy: 'size',
|
|
109
|
-
* sizeLimit: 10 * 1024 * 1024, // 10 MB
|
|
110
|
-
* hooks: {
|
|
111
|
-
* onRotation: async (context) => {
|
|
112
|
-
* // Archive old log file
|
|
113
|
-
* },
|
|
114
|
-
* },
|
|
115
|
-
* },
|
|
116
|
-
* };
|
|
117
|
-
* ```
|
|
118
|
-
*/
|
|
119
|
-
export interface AuditConfig {
|
|
120
|
-
/**
|
|
121
|
-
* Enable audit logging (default: true)
|
|
122
|
-
*/
|
|
123
|
-
enabled?: boolean;
|
|
124
|
-
/**
|
|
125
|
-
* Custom log function (default: console.log)
|
|
126
|
-
*
|
|
127
|
-
* @param record - The formatted audit line (frozen format)
|
|
128
|
-
*
|
|
129
|
-
* @example File-based logging
|
|
130
|
-
* ```typescript
|
|
131
|
-
* logFunction: (record) => {
|
|
132
|
-
* fs.appendFileSync('/var/log/audit.log', record + '\n');
|
|
133
|
-
* }
|
|
134
|
-
* ```
|
|
135
|
-
*/
|
|
136
|
-
logFunction?: (record: string) => void;
|
|
137
|
-
/**
|
|
138
|
-
* Include payloads in logs (default: false)
|
|
139
|
-
*
|
|
140
|
-
* **WARNING:** This should ALWAYS be false. The frozen format ensures
|
|
141
|
-
* that even if set to true, no request/response bodies will be logged.
|
|
142
|
-
* This flag exists for compatibility but has no effect on the frozen format.
|
|
143
|
-
*
|
|
144
|
-
* @deprecated This flag has no effect due to frozen format privacy guarantees
|
|
145
|
-
*/
|
|
146
|
-
includePayloads?: boolean;
|
|
147
|
-
/**
|
|
148
|
-
* Log rotation configuration (event-driven, no timers)
|
|
149
|
-
*/
|
|
150
|
-
rotation?: {
|
|
151
|
-
/**
|
|
152
|
-
* Rotation strategy
|
|
153
|
-
* - 'size': Rotate when log reaches size limit (checked on each call)
|
|
154
|
-
* - 'time': Rotate based on elapsed time (checked on each call)
|
|
155
|
-
* - 'count': Rotate after N records
|
|
156
|
-
* - 'custom': Custom rotation logic via hooks only
|
|
157
|
-
*/
|
|
158
|
-
strategy?: AuditRotationStrategy;
|
|
159
|
-
/**
|
|
160
|
-
* Size limit in bytes (for size-based rotation)
|
|
161
|
-
*
|
|
162
|
-
* @example 10 MB limit
|
|
163
|
-
* ```typescript
|
|
164
|
-
* sizeLimit: 10 * 1024 * 1024
|
|
165
|
-
* ```
|
|
166
|
-
*/
|
|
167
|
-
sizeLimit?: number;
|
|
168
|
-
/**
|
|
169
|
-
* Time interval in milliseconds (for time-based rotation)
|
|
170
|
-
* Rotation is checked on each logAuditRecord() call, not via timer.
|
|
171
|
-
*
|
|
172
|
-
* @example Daily rotation
|
|
173
|
-
* ```typescript
|
|
174
|
-
* timeInterval: 24 * 60 * 60 * 1000
|
|
175
|
-
* ```
|
|
176
|
-
*/
|
|
177
|
-
timeInterval?: number;
|
|
178
|
-
/**
|
|
179
|
-
* Record count threshold (for count-based rotation)
|
|
180
|
-
*
|
|
181
|
-
* @example Rotate after 10k records
|
|
182
|
-
* ```typescript
|
|
183
|
-
* countThreshold: 10000
|
|
184
|
-
* ```
|
|
185
|
-
*/
|
|
186
|
-
countThreshold?: number;
|
|
187
|
-
/**
|
|
188
|
-
* Custom rotation hooks
|
|
189
|
-
*/
|
|
190
|
-
hooks?: AuditRotationHooks;
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
|
-
* Audit context for logging
|
|
195
|
-
*
|
|
196
|
-
* Contains all metadata needed to generate an audit record.
|
|
197
|
-
*
|
|
198
|
-
* **Privacy Note:** Only metadata is extracted from these objects.
|
|
199
|
-
* The identity's private key, session's nonce, and other sensitive
|
|
200
|
-
* fields are NEVER included in the audit log.
|
|
201
|
-
*
|
|
202
|
-
* @example
|
|
203
|
-
* ```typescript
|
|
204
|
-
* const context: AuditContext = {
|
|
205
|
-
* identity: {
|
|
206
|
-
* did: 'did:web:example.com:agents:agent-1',
|
|
207
|
-
* keyId: 'key-20241014-abc123',
|
|
208
|
-
* // ... private key NOT logged
|
|
209
|
-
* },
|
|
210
|
-
* session: {
|
|
211
|
-
* sessionId: 'sess_abc123',
|
|
212
|
-
* audience: 'example.com',
|
|
213
|
-
* // ... nonce NOT logged
|
|
214
|
-
* },
|
|
215
|
-
* requestHash: 'sha256:1234567890abcdef...',
|
|
216
|
-
* responseHash: 'sha256:fedcba0987654321...',
|
|
217
|
-
* verified: 'yes',
|
|
218
|
-
* scopeId: 'orders.create',
|
|
219
|
-
* };
|
|
220
|
-
* ```
|
|
221
|
-
*/
|
|
222
|
-
export interface AuditContext {
|
|
223
|
-
/**
|
|
224
|
-
* Agent identity
|
|
225
|
-
*
|
|
226
|
-
* Only `did` and `keyId` are logged. Private key is NEVER logged.
|
|
227
|
-
*/
|
|
228
|
-
identity: AgentIdentity;
|
|
229
|
-
/**
|
|
230
|
-
* Session context
|
|
231
|
-
*
|
|
232
|
-
* Only `sessionId` and `audience` are logged. Nonce is NEVER logged.
|
|
233
|
-
*/
|
|
234
|
-
session: SessionContext;
|
|
235
|
-
/**
|
|
236
|
-
* Request hash (SHA-256 with `sha256:` prefix)
|
|
237
|
-
*
|
|
238
|
-
* @example 'sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
|
|
239
|
-
*/
|
|
240
|
-
requestHash: string;
|
|
241
|
-
/**
|
|
242
|
-
* Response hash (SHA-256 with `sha256:` prefix)
|
|
243
|
-
*
|
|
244
|
-
* @example 'sha256:fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321'
|
|
245
|
-
*/
|
|
246
|
-
responseHash: string;
|
|
247
|
-
/**
|
|
248
|
-
* Verification result
|
|
249
|
-
*
|
|
250
|
-
* - 'yes': Proof was verified successfully
|
|
251
|
-
* - 'no': Proof verification failed
|
|
252
|
-
*/
|
|
253
|
-
verified: "yes" | "no";
|
|
254
|
-
/**
|
|
255
|
-
* Optional scope identifier
|
|
256
|
-
*
|
|
257
|
-
* Application-level scope (e.g., 'orders.create', 'users.read').
|
|
258
|
-
* If not provided, '-' is used in the audit log.
|
|
259
|
-
*
|
|
260
|
-
* @example 'orders.create'
|
|
261
|
-
*/
|
|
262
|
-
scopeId?: string;
|
|
263
|
-
}
|
|
264
|
-
/**
|
|
265
|
-
* Event context for logging events that bypass session deduplication
|
|
266
|
-
*
|
|
267
|
-
* Used for consent events where multiple events occur in the same session.
|
|
268
|
-
* Unlike AuditContext, this allows multiple events per session.
|
|
269
|
-
*/
|
|
270
|
-
export interface AuditEventContext {
|
|
271
|
-
/**
|
|
272
|
-
* Event type identifier
|
|
273
|
-
*
|
|
274
|
-
* @example "consent:page_viewed", "consent:approved", "runtime:initialized"
|
|
275
|
-
*/
|
|
276
|
-
eventType: string;
|
|
277
|
-
/**
|
|
278
|
-
* Agent identity
|
|
279
|
-
*
|
|
280
|
-
* Only `did` and `keyId` are logged. Private key is NEVER logged.
|
|
281
|
-
*/
|
|
282
|
-
identity: AgentIdentity;
|
|
283
|
-
/**
|
|
284
|
-
* Session context
|
|
285
|
-
*
|
|
286
|
-
* Only `sessionId` and `audience` are logged. Nonce is NEVER logged.
|
|
287
|
-
*/
|
|
288
|
-
session: SessionContext;
|
|
289
|
-
/**
|
|
290
|
-
* Optional event-specific data
|
|
291
|
-
*
|
|
292
|
-
* Used for generating event hash. Not logged directly.
|
|
293
|
-
*/
|
|
294
|
-
eventData?: Record<string, any>;
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* Audit logger class with event-driven rotation support
|
|
298
|
-
*
|
|
299
|
-
* Privacy Guarantees:
|
|
300
|
-
* - NEVER logs request/response bodies (only SHA-256 hashes)
|
|
301
|
-
* - NEVER logs secrets (private keys, API keys, tokens, nonces)
|
|
302
|
-
* - NEVER logs PII (personal information)
|
|
303
|
-
* - Only logs metadata: DIDs, key IDs, timestamps, hashes, session IDs
|
|
304
|
-
* - Frozen format: audit.v1 with fixed field order
|
|
305
|
-
*
|
|
306
|
-
* Rotation Strategy:
|
|
307
|
-
* - Event-driven (no timers) - rotation checks on each logAuditRecord() call
|
|
308
|
-
* - Works in all environments (Node.js, Cloudflare Workers, Vercel Edge)
|
|
309
|
-
* - No cleanup needed (no timers to clear)
|
|
310
|
-
*/
|
|
311
|
-
export declare class AuditLogger {
|
|
312
|
-
private config;
|
|
313
|
-
private sessionAuditLog;
|
|
314
|
-
private totalRecordsLogged;
|
|
315
|
-
private currentLogSize;
|
|
316
|
-
private lastRotationTime;
|
|
317
|
-
private destroyed;
|
|
318
|
-
constructor(config?: AuditConfig);
|
|
319
|
-
/**
|
|
320
|
-
* Emit audit record on first call per session
|
|
321
|
-
* Requirements: 5.4, 5.5
|
|
322
|
-
*
|
|
323
|
-
* This method:
|
|
324
|
-
* 1. Checks if logger is destroyed
|
|
325
|
-
* 2. Logs audit record (first call per session)
|
|
326
|
-
* 3. Checks if rotation is needed (event-driven)
|
|
327
|
-
* 4. Triggers rotation hooks if threshold met
|
|
328
|
-
*/
|
|
329
|
-
logAuditRecord(context: AuditContext): Promise<void>;
|
|
330
|
-
/**
|
|
331
|
-
* Log an event using the frozen audit format WITHOUT session deduplication.
|
|
332
|
-
*
|
|
333
|
-
* Unlike logAuditRecord(), this method ALWAYS logs the event, regardless
|
|
334
|
-
* of whether an event has already been logged for this session. This is
|
|
335
|
-
* necessary for consent events where multiple events occur in the same session.
|
|
336
|
-
*
|
|
337
|
-
* The event still uses the frozen audit.v1 format for consistency, but
|
|
338
|
-
* bypasses the "once per session" constraint.
|
|
339
|
-
*
|
|
340
|
-
* @param context - Event context including eventType, identity, session, and eventData
|
|
341
|
-
*/
|
|
342
|
-
logEvent(context: AuditEventContext): Promise<void>;
|
|
343
|
-
/**
|
|
344
|
-
* Generate deterministic hash for event
|
|
345
|
-
*/
|
|
346
|
-
private hashEvent;
|
|
347
|
-
/**
|
|
348
|
-
* Format audit record as frozen audit line
|
|
349
|
-
* Format: audit.v1 ts=<unix> session=<id> audience=<host> did=<did> kid=<kid> reqHash=<sha256:..> resHash=<sha256:..> verified=yes|no scope=<scopeId|->
|
|
350
|
-
*/
|
|
351
|
-
private formatAuditLine;
|
|
352
|
-
/**
|
|
353
|
-
* Check if rotation is needed and trigger if necessary (event-driven)
|
|
354
|
-
*
|
|
355
|
-
* This method is called on each logAuditRecord() call.
|
|
356
|
-
* No timers are used - rotation is checked based on current state.
|
|
357
|
-
*/
|
|
358
|
-
private checkRotation;
|
|
359
|
-
/**
|
|
360
|
-
* Rotate audit log now (manually triggered)
|
|
361
|
-
*
|
|
362
|
-
* This method:
|
|
363
|
-
* 1. Calls onRotation hook (for user to archive/rotate log file)
|
|
364
|
-
* 2. Resets rotation counters (size, time, count)
|
|
365
|
-
*
|
|
366
|
-
* @param trigger - Reason for rotation (e.g., "manual", "size-limit")
|
|
367
|
-
*/
|
|
368
|
-
rotateNow(trigger?: string): Promise<void>;
|
|
369
|
-
/**
|
|
370
|
-
* Destroy audit logger and cleanup resources
|
|
371
|
-
*
|
|
372
|
-
* This method:
|
|
373
|
-
* 1. Clears session tracking (memory)
|
|
374
|
-
* 2. Resets statistics
|
|
375
|
-
* 3. Marks logger as destroyed
|
|
376
|
-
*
|
|
377
|
-
* Note: No timers to clear (event-driven rotation)
|
|
378
|
-
*/
|
|
379
|
-
destroy(): void;
|
|
380
|
-
/**
|
|
381
|
-
* Clear session audit log (useful for testing)
|
|
382
|
-
*/
|
|
383
|
-
clearSessionLog(): void;
|
|
384
|
-
/**
|
|
385
|
-
* Get audit statistics
|
|
386
|
-
*/
|
|
387
|
-
getStats(): {
|
|
388
|
-
enabled: boolean;
|
|
389
|
-
sessionsLogged: number;
|
|
390
|
-
includePayloads: boolean;
|
|
391
|
-
totalRecordsLogged: number;
|
|
392
|
-
currentLogSize: number;
|
|
393
|
-
lastRotationTime: number;
|
|
394
|
-
};
|
|
395
|
-
/**
|
|
396
|
-
* Update configuration
|
|
397
|
-
*/
|
|
398
|
-
updateConfig(config: Partial<AuditConfig>): void;
|
|
399
|
-
}
|
|
400
|
-
/**
|
|
401
|
-
* Key rotation audit logging
|
|
402
|
-
*/
|
|
403
|
-
export interface KeyRotationAuditContext {
|
|
404
|
-
identity: AgentIdentity;
|
|
405
|
-
oldKeyId: string;
|
|
406
|
-
newKeyId: string;
|
|
407
|
-
mode: "dev" | "prod";
|
|
408
|
-
delegated: "yes" | "no";
|
|
409
|
-
force: "yes" | "no";
|
|
410
|
-
}
|
|
411
|
-
/**
|
|
412
|
-
* Log key rotation audit record
|
|
413
|
-
* Format: keys.rotate.v1 ts=<unix> did=<did> oldKid=<kid> newKid=<kid> mode=dev|prod delegated=yes|no force=yes|no
|
|
414
|
-
*/
|
|
415
|
-
export declare function logKeyRotationAudit(context: KeyRotationAuditContext, logFunction?: (record: string) => void): void;
|
|
416
|
-
/**
|
|
417
|
-
* Default audit logger instance
|
|
418
|
-
*/
|
|
419
|
-
export declare const defaultAuditLogger: AuditLogger;
|
|
420
|
-
/**
|
|
421
|
-
* Utility functions
|
|
422
|
-
*/
|
|
423
|
-
/**
|
|
424
|
-
* Parse audit line back to record (for testing/analysis)
|
|
425
|
-
*/
|
|
426
|
-
export declare function parseAuditLine(line: string): AuditRecord | null;
|
|
427
|
-
/**
|
|
428
|
-
* Validate audit record format
|
|
429
|
-
*/
|
|
430
|
-
export declare function validateAuditRecord(record: any): record is AuditRecord;
|