@wytness/sdk 0.3.1 → 0.4.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 CHANGED
@@ -30,9 +30,11 @@ await sendEmail("team@company.com", "Report", "Weekly summary");
30
30
 
31
31
  ## Features
32
32
 
33
+ - **Response capture** — AI agent responses are automatically captured, truncated to 5K chars, and PII-redacted
34
+ - **PII redaction** — emails, SSN, TFN, credit cards, and phone numbers are automatically redacted from responses and parameter values
33
35
  - **Cryptographic signing** — every event is signed with Ed25519 (tweetnacl)
34
36
  - **Hash chaining** — tamper-evident chain of events per agent session
35
- - **Automatic redaction** — secrets in parameters are automatically redacted
37
+ - **Automatic secret redaction** — secrets in parameter names are automatically redacted
36
38
  - **HTTP transport** — stream events to api.wytness.dev over HTTPS
37
39
  - **File fallback** — events are saved locally if the API is unreachable
38
40
 
@@ -66,7 +68,7 @@ const client = new AuditClient({
66
68
 
67
69
  ### `auditTool(client, fn, options)`
68
70
 
69
- Wraps a function to automatically log audit events. Captures function name, parameters, execution duration, success/failure status, cryptographic signature, and hash chain link.
71
+ Wraps a function to automatically log audit events. Captures function name, parameters, **response text** (truncated to 5K chars, PII-redacted), execution duration, success/failure status, cryptographic signature, and hash chain link.
70
72
 
71
73
  ### `client.sessionId`
72
74
 
@@ -114,6 +116,7 @@ import {
114
116
  AuditClientOptions,
115
117
  auditTool,
116
118
  hashValue,
119
+ redactPii,
117
120
  AuditEvent,
118
121
  AuditEventSchema,
119
122
  generateKeypair,
package/dist/index.cjs CHANGED
@@ -38,6 +38,7 @@ __export(src_exports, {
38
38
  createHttpEmitter: () => createHttpEmitter,
39
39
  generateKeypair: () => generateKeypair,
40
40
  hashValue: () => hashValue,
41
+ redactPii: () => redactPii,
41
42
  signEvent: () => signEvent,
42
43
  verifyChain: () => verifyChain,
43
44
  verifyEvent: () => verifyEvent
@@ -72,6 +73,7 @@ var AuditEventSchema = import_zod.z.object({
72
73
  inputs_source: import_zod.z.string().default(""),
73
74
  outputs_hash: import_zod.z.string().default(""),
74
75
  outputs_destination: import_zod.z.string().default(""),
76
+ response: import_zod.z.string().default(""),
75
77
  // Layer 5: Outcome
76
78
  status: import_zod.z.string().default("success"),
77
79
  error_code: import_zod.z.string().nullable().default(null),
@@ -299,10 +301,29 @@ var AuditClient = class {
299
301
  // src/decorator.ts
300
302
  var import_crypto4 = require("crypto");
301
303
  var SECRET_PATTERN = /key|secret|token|password|passwd|pwd|credential|auth/i;
304
+ var PII_PATTERNS = [
305
+ [/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g, "[EMAIL_REDACTED]"],
306
+ [/\b\d{3}[-.\s]?\d{2}[-.\s]?\d{4}\b/g, "[SSN_REDACTED]"],
307
+ [/\b\d{3}[-.\s]?\d{3}[-.\s]?\d{3}\b/g, "[TFN_REDACTED]"],
308
+ [/\b(?:\d{4}[-\s]?){3}\d{4}\b/g, "[CARD_REDACTED]"],
309
+ [/\b(?:\+?\d{1,3}[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g, "[PHONE_REDACTED]"]
310
+ ];
311
+ var RESPONSE_MAX_CHARS = 5e3;
312
+ function redactPii(text) {
313
+ for (const [pattern, replacement] of PII_PATTERNS) {
314
+ pattern.lastIndex = 0;
315
+ text = text.replace(pattern, replacement);
316
+ }
317
+ return text;
318
+ }
302
319
  function sanitise(params) {
303
320
  const result = {};
304
321
  for (const [k, v] of Object.entries(params)) {
305
- result[k] = SECRET_PATTERN.test(k) ? "[REDACTED]" : String(v).slice(0, 500);
322
+ if (SECRET_PATTERN.test(k)) {
323
+ result[k] = "[REDACTED]";
324
+ } else {
325
+ result[k] = redactPii(String(v).slice(0, 500));
326
+ }
306
327
  }
307
328
  return result;
308
329
  }
@@ -314,6 +335,8 @@ function recordEvent(client, toolName, taskId, prompt, args, start, status, erro
314
335
  args.forEach((arg, i) => {
315
336
  params[`arg${i}`] = arg;
316
337
  });
338
+ const outputsHash = result != null ? hashValue(result) : "";
339
+ const response = result != null ? redactPii(String(result).slice(0, RESPONSE_MAX_CHARS)) : "";
317
340
  const event = AuditEventSchema.parse({
318
341
  agent_id: client.agentId,
319
342
  agent_version: client.agentVersion,
@@ -324,7 +347,8 @@ function recordEvent(client, toolName, taskId, prompt, args, start, status, erro
324
347
  tool_parameters: sanitise(params),
325
348
  prompt,
326
349
  inputs_hash: hashValue(args),
327
- outputs_hash: result != null ? hashValue(result) : "",
350
+ outputs_hash: outputsHash,
351
+ response,
328
352
  status,
329
353
  error_code: errorCode,
330
354
  duration_ms: Math.round(performance.now() - start)
@@ -381,6 +405,7 @@ function auditTool(client, fnOrTaskId, options) {
381
405
  createHttpEmitter,
382
406
  generateKeypair,
383
407
  hashValue,
408
+ redactPii,
384
409
  signEvent,
385
410
  verifyChain,
386
411
  verifyEvent
package/dist/index.d.cts CHANGED
@@ -21,6 +21,7 @@ declare const AuditEventSchema: z.ZodObject<{
21
21
  inputs_source: z.ZodDefault<z.ZodString>;
22
22
  outputs_hash: z.ZodDefault<z.ZodString>;
23
23
  outputs_destination: z.ZodDefault<z.ZodString>;
24
+ response: z.ZodDefault<z.ZodString>;
24
25
  status: z.ZodDefault<z.ZodString>;
25
26
  error_code: z.ZodDefault<z.ZodNullable<z.ZodString>>;
26
27
  duration_ms: z.ZodDefault<z.ZodNumber>;
@@ -49,6 +50,7 @@ declare const AuditEventSchema: z.ZodObject<{
49
50
  inputs_source: string;
50
51
  outputs_hash: string;
51
52
  outputs_destination: string;
53
+ response: string;
52
54
  error_code: string | null;
53
55
  duration_ms: number;
54
56
  retry_count: number;
@@ -76,6 +78,7 @@ declare const AuditEventSchema: z.ZodObject<{
76
78
  inputs_source?: string | undefined;
77
79
  outputs_hash?: string | undefined;
78
80
  outputs_destination?: string | undefined;
81
+ response?: string | undefined;
79
82
  error_code?: string | null | undefined;
80
83
  duration_ms?: number | undefined;
81
84
  retry_count?: number | undefined;
@@ -133,6 +136,7 @@ declare class AuditClient {
133
136
  flush(): Promise<void>;
134
137
  }
135
138
 
139
+ declare function redactPii(text: string): string;
136
140
  declare function hashValue(value: unknown): string;
137
141
  interface AuditToolOptions {
138
142
  toolName?: string;
@@ -153,4 +157,4 @@ interface AuditToolOptions {
153
157
  */
154
158
  declare function auditTool(client: AuditClient, fnOrTaskId?: ((...args: unknown[]) => unknown) | string, options?: AuditToolOptions | string): any;
155
159
 
156
- export { AuditClient, type AuditClientOptions, type AuditEvent, AuditEventSchema, auditTool, computeEventHash, createFileEmitter, createHttpEmitter, generateKeypair, hashValue, signEvent, verifyChain, verifyEvent };
160
+ export { AuditClient, type AuditClientOptions, type AuditEvent, AuditEventSchema, auditTool, computeEventHash, createFileEmitter, createHttpEmitter, generateKeypair, hashValue, redactPii, signEvent, verifyChain, verifyEvent };
package/dist/index.d.ts CHANGED
@@ -21,6 +21,7 @@ declare const AuditEventSchema: z.ZodObject<{
21
21
  inputs_source: z.ZodDefault<z.ZodString>;
22
22
  outputs_hash: z.ZodDefault<z.ZodString>;
23
23
  outputs_destination: z.ZodDefault<z.ZodString>;
24
+ response: z.ZodDefault<z.ZodString>;
24
25
  status: z.ZodDefault<z.ZodString>;
25
26
  error_code: z.ZodDefault<z.ZodNullable<z.ZodString>>;
26
27
  duration_ms: z.ZodDefault<z.ZodNumber>;
@@ -49,6 +50,7 @@ declare const AuditEventSchema: z.ZodObject<{
49
50
  inputs_source: string;
50
51
  outputs_hash: string;
51
52
  outputs_destination: string;
53
+ response: string;
52
54
  error_code: string | null;
53
55
  duration_ms: number;
54
56
  retry_count: number;
@@ -76,6 +78,7 @@ declare const AuditEventSchema: z.ZodObject<{
76
78
  inputs_source?: string | undefined;
77
79
  outputs_hash?: string | undefined;
78
80
  outputs_destination?: string | undefined;
81
+ response?: string | undefined;
79
82
  error_code?: string | null | undefined;
80
83
  duration_ms?: number | undefined;
81
84
  retry_count?: number | undefined;
@@ -133,6 +136,7 @@ declare class AuditClient {
133
136
  flush(): Promise<void>;
134
137
  }
135
138
 
139
+ declare function redactPii(text: string): string;
136
140
  declare function hashValue(value: unknown): string;
137
141
  interface AuditToolOptions {
138
142
  toolName?: string;
@@ -153,4 +157,4 @@ interface AuditToolOptions {
153
157
  */
154
158
  declare function auditTool(client: AuditClient, fnOrTaskId?: ((...args: unknown[]) => unknown) | string, options?: AuditToolOptions | string): any;
155
159
 
156
- export { AuditClient, type AuditClientOptions, type AuditEvent, AuditEventSchema, auditTool, computeEventHash, createFileEmitter, createHttpEmitter, generateKeypair, hashValue, signEvent, verifyChain, verifyEvent };
160
+ export { AuditClient, type AuditClientOptions, type AuditEvent, AuditEventSchema, auditTool, computeEventHash, createFileEmitter, createHttpEmitter, generateKeypair, hashValue, redactPii, signEvent, verifyChain, verifyEvent };
package/dist/index.js CHANGED
@@ -26,6 +26,7 @@ var AuditEventSchema = z.object({
26
26
  inputs_source: z.string().default(""),
27
27
  outputs_hash: z.string().default(""),
28
28
  outputs_destination: z.string().default(""),
29
+ response: z.string().default(""),
29
30
  // Layer 5: Outcome
30
31
  status: z.string().default("success"),
31
32
  error_code: z.string().nullable().default(null),
@@ -253,10 +254,29 @@ var AuditClient = class {
253
254
  // src/decorator.ts
254
255
  import { createHash as createHash2 } from "crypto";
255
256
  var SECRET_PATTERN = /key|secret|token|password|passwd|pwd|credential|auth/i;
257
+ var PII_PATTERNS = [
258
+ [/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g, "[EMAIL_REDACTED]"],
259
+ [/\b\d{3}[-.\s]?\d{2}[-.\s]?\d{4}\b/g, "[SSN_REDACTED]"],
260
+ [/\b\d{3}[-.\s]?\d{3}[-.\s]?\d{3}\b/g, "[TFN_REDACTED]"],
261
+ [/\b(?:\d{4}[-\s]?){3}\d{4}\b/g, "[CARD_REDACTED]"],
262
+ [/\b(?:\+?\d{1,3}[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g, "[PHONE_REDACTED]"]
263
+ ];
264
+ var RESPONSE_MAX_CHARS = 5e3;
265
+ function redactPii(text) {
266
+ for (const [pattern, replacement] of PII_PATTERNS) {
267
+ pattern.lastIndex = 0;
268
+ text = text.replace(pattern, replacement);
269
+ }
270
+ return text;
271
+ }
256
272
  function sanitise(params) {
257
273
  const result = {};
258
274
  for (const [k, v] of Object.entries(params)) {
259
- result[k] = SECRET_PATTERN.test(k) ? "[REDACTED]" : String(v).slice(0, 500);
275
+ if (SECRET_PATTERN.test(k)) {
276
+ result[k] = "[REDACTED]";
277
+ } else {
278
+ result[k] = redactPii(String(v).slice(0, 500));
279
+ }
260
280
  }
261
281
  return result;
262
282
  }
@@ -268,6 +288,8 @@ function recordEvent(client, toolName, taskId, prompt, args, start, status, erro
268
288
  args.forEach((arg, i) => {
269
289
  params[`arg${i}`] = arg;
270
290
  });
291
+ const outputsHash = result != null ? hashValue(result) : "";
292
+ const response = result != null ? redactPii(String(result).slice(0, RESPONSE_MAX_CHARS)) : "";
271
293
  const event = AuditEventSchema.parse({
272
294
  agent_id: client.agentId,
273
295
  agent_version: client.agentVersion,
@@ -278,7 +300,8 @@ function recordEvent(client, toolName, taskId, prompt, args, start, status, erro
278
300
  tool_parameters: sanitise(params),
279
301
  prompt,
280
302
  inputs_hash: hashValue(args),
281
- outputs_hash: result != null ? hashValue(result) : "",
303
+ outputs_hash: outputsHash,
304
+ response,
282
305
  status,
283
306
  error_code: errorCode,
284
307
  duration_ms: Math.round(performance.now() - start)
@@ -334,6 +357,7 @@ export {
334
357
  createHttpEmitter,
335
358
  generateKeypair,
336
359
  hashValue,
360
+ redactPii,
337
361
  signEvent,
338
362
  verifyChain,
339
363
  verifyEvent
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wytness/sdk",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "TypeScript SDK for Wytness — audit logging for AI agents with cryptographic signing and chain integrity",
5
5
  "license": "MIT",
6
6
  "author": "Wytness <hello@wytness.dev>",