@kya-os/mcp-i 1.5.9-canary.8 → 1.5.9-canary.9

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.
@@ -257,6 +257,38 @@ export interface AuditContext {
257
257
  */
258
258
  scopeId?: string;
259
259
  }
260
+ /**
261
+ * Event context for logging events that bypass session deduplication
262
+ *
263
+ * Used for consent events where multiple events occur in the same session.
264
+ * Unlike AuditContext, this allows multiple events per session.
265
+ */
266
+ export interface AuditEventContext {
267
+ /**
268
+ * Event type identifier
269
+ *
270
+ * @example "consent:page_viewed", "consent:approved", "runtime:initialized"
271
+ */
272
+ eventType: string;
273
+ /**
274
+ * Agent identity
275
+ *
276
+ * Only `did` and `keyId` are logged. Private key is NEVER logged.
277
+ */
278
+ identity: AgentIdentity;
279
+ /**
280
+ * Session context
281
+ *
282
+ * Only `sessionId` and `audience` are logged. Nonce is NEVER logged.
283
+ */
284
+ session: SessionContext;
285
+ /**
286
+ * Optional event-specific data
287
+ *
288
+ * Used for generating event hash. Not logged directly.
289
+ */
290
+ eventData?: Record<string, any>;
291
+ }
260
292
  /**
261
293
  * Audit logger class with event-driven rotation support
262
294
  *
@@ -291,6 +323,23 @@ export declare class AuditLogger {
291
323
  * 4. Triggers rotation hooks if threshold met
292
324
  */
293
325
  logAuditRecord(context: AuditContext): Promise<void>;
326
+ /**
327
+ * Log an event using the frozen audit format WITHOUT session deduplication.
328
+ *
329
+ * Unlike logAuditRecord(), this method ALWAYS logs the event, regardless
330
+ * of whether an event has already been logged for this session. This is
331
+ * necessary for consent events where multiple events occur in the same session.
332
+ *
333
+ * The event still uses the frozen audit.v1 format for consistency, but
334
+ * bypasses the "once per session" constraint.
335
+ *
336
+ * @param context - Event context including eventType, identity, session, and eventData
337
+ */
338
+ logEvent(context: AuditEventContext): Promise<void>;
339
+ /**
340
+ * Generate deterministic hash for event
341
+ */
342
+ private hashEvent;
294
343
  /**
295
344
  * Format audit record as frozen audit line
296
345
  * Format: audit.v1 ts=<unix> session=<id> audience=<host> did=<did> kid=<kid> reqHash=<sha256:..> resHash=<sha256:..> verified=yes|no scope=<scopeId|->
@@ -47,6 +47,7 @@ exports.logKeyRotationAudit = logKeyRotationAudit;
47
47
  exports.parseAuditLine = parseAuditLine;
48
48
  exports.validateAuditRecord = validateAuditRecord;
49
49
  const time_1 = require("./utils/time");
50
+ const crypto_1 = require("crypto");
50
51
  /**
51
52
  * Audit logger class with event-driven rotation support
52
53
  *
@@ -133,6 +134,63 @@ class AuditLogger {
133
134
  // Check if rotation is needed (event-driven)
134
135
  await this.checkRotation();
135
136
  }
137
+ /**
138
+ * Log an event using the frozen audit format WITHOUT session deduplication.
139
+ *
140
+ * Unlike logAuditRecord(), this method ALWAYS logs the event, regardless
141
+ * of whether an event has already been logged for this session. This is
142
+ * necessary for consent events where multiple events occur in the same session.
143
+ *
144
+ * The event still uses the frozen audit.v1 format for consistency, but
145
+ * bypasses the "once per session" constraint.
146
+ *
147
+ * @param context - Event context including eventType, identity, session, and eventData
148
+ */
149
+ async logEvent(context) {
150
+ if (this.destroyed) {
151
+ throw new Error("AuditLogger has been destroyed");
152
+ }
153
+ if (!this.config.enabled) {
154
+ return;
155
+ }
156
+ // Generate event hash
157
+ const eventHash = this.hashEvent(context.eventType, context.eventData);
158
+ // Create audit record (same format as regular audit logs)
159
+ const auditRecord = {
160
+ version: "audit.v1",
161
+ ts: Math.floor(Date.now() / 1000),
162
+ session: context.session.sessionId,
163
+ audience: context.session.audience,
164
+ did: context.identity.did,
165
+ kid: context.identity.kid,
166
+ reqHash: `sha256:${eventHash}`,
167
+ resHash: `sha256:${eventHash}`, // Same hash for events
168
+ verified: "yes",
169
+ scope: context.eventType, // Use eventType as scope
170
+ };
171
+ // Format and log (NO session deduplication check)
172
+ const auditLine = this.formatAuditLine(auditRecord);
173
+ // Track size and count
174
+ const sizeBytes = Buffer.byteLength(auditLine, "utf8");
175
+ this.currentLogSize += sizeBytes;
176
+ this.totalRecordsLogged++;
177
+ // Emit audit record
178
+ this.config.logFunction(auditLine);
179
+ // Check rotation
180
+ await this.checkRotation();
181
+ }
182
+ /**
183
+ * Generate deterministic hash for event
184
+ */
185
+ hashEvent(type, data) {
186
+ const content = JSON.stringify({
187
+ type,
188
+ data,
189
+ ts: Date.now(),
190
+ nonce: (0, crypto_1.randomBytes)(16).toString('hex')
191
+ });
192
+ return (0, crypto_1.createHash)('sha256').update(content).digest('hex');
193
+ }
136
194
  /**
137
195
  * Format audit record as frozen audit line
138
196
  * Format: audit.v1 ts=<unix> session=<id> audience=<host> did=<did> kid=<kid> reqHash=<sha256:..> resHash=<sha256:..> verified=yes|no scope=<scopeId|->
@@ -10,7 +10,7 @@ export { RuntimeFactory, RUNTIME_ERRORS, type MCPIRuntimeConfig, type RuntimeEnv
10
10
  export { IdentityManager, defaultIdentityManager, ensureIdentity, IDENTITY_ERRORS, type AgentIdentity, type DevIdentityFile, type ProdEnvironment, type RuntimeIdentityManagerConfig, } from "./identity";
11
11
  export { SessionManager, defaultSessionManager, createHandshakeRequest, validateHandshakeFormat, type SessionConfig, type HandshakeResult, } from "./session";
12
12
  export { ProofGenerator, createProofResponse, extractCanonicalData, type ToolRequest, type ToolResponse, type ProofOptions, } from "./proof";
13
- export { AuditLogger, defaultAuditLogger, logKeyRotationAudit, parseAuditLine, validateAuditRecord, type AuditConfig, type AuditContext, type KeyRotationAuditContext, } from "./audit";
13
+ export { AuditLogger, defaultAuditLogger, logKeyRotationAudit, parseAuditLine, validateAuditRecord, type AuditConfig, type AuditContext, type AuditEventContext, type KeyRotationAuditContext, } from "./audit";
14
14
  export { WellKnownManager, createWellKnownHandler, validateDIDDocument, validateAgentDocument, extractDIDFromPath, type DIDDocument, type VerificationMethod, type ServiceEndpoint, type AgentDocument, type WellKnownConfig, type WellKnownHandler, } from "./well-known";
15
15
  export { DebugManager, createDebugEndpoint, type DebugVerificationResult, type DebugPageData, } from "./debug";
16
16
  export { DemoManager, createDemoManager, DemoConsole, formatVerifyLink, type DemoConfig, } from "./demo";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kya-os/mcp-i",
3
- "version": "1.5.9-canary.8",
3
+ "version": "1.5.9-canary.9",
4
4
  "description": "The TypeScript MCP framework with identity features built-in",
5
5
  "type": "commonjs",
6
6
  "main": "dist/index.js",
@@ -35,6 +35,11 @@
35
35
  "require": "./dist/config.js",
36
36
  "import": "./dist/config.js",
37
37
  "types": "./dist/config.d.ts"
38
+ },
39
+ "./runtime": {
40
+ "require": "./dist/runtime/index.js",
41
+ "import": "./dist/runtime/index.js",
42
+ "types": "./dist/runtime/index.d.ts"
38
43
  }
39
44
  },
40
45
  "files": [
@@ -58,8 +63,8 @@
58
63
  "model-context-protocol"
59
64
  ],
60
65
  "dependencies": {
61
- "@kya-os/contracts": "^1.5.3-canary.5",
62
- "@kya-os/mcp-i-core": "^1.2.2-canary.6",
66
+ "@kya-os/contracts": "^1.5.3-canary.6",
67
+ "@kya-os/mcp-i-core": "^1.2.2-canary.7",
63
68
  "@modelcontextprotocol/sdk": "^1.11.4",
64
69
  "@swc/core": "^1.11.24",
65
70
  "@types/express": "^5.0.1",