@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 +5 -2
- package/dist/index.cjs +27 -2
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +26 -2
- package/package.json +1 -1
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
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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:
|
|
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