@optimuslabs/runtime-staging 0.3.10 → 0.3.11
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/dist/lib/client-event.d.ts.map +1 -1
- package/dist/lib/client-event.js +35 -25
- package/dist/lib/client-event.js.map +1 -1
- package/dist/lib/pii-scrub.d.ts +9 -0
- package/dist/lib/pii-scrub.d.ts.map +1 -0
- package/dist/lib/pii-scrub.js +17 -0
- package/dist/lib/pii-scrub.js.map +1 -0
- package/dist/lib/prompt-collection-policy.d.ts +10 -0
- package/dist/lib/prompt-collection-policy.d.ts.map +1 -1
- package/dist/lib/prompt-collection-policy.js +42 -6
- package/dist/lib/prompt-collection-policy.js.map +1 -1
- package/dist/lib/startup-sync.d.ts.map +1 -1
- package/dist/lib/startup-sync.js +78 -56
- package/dist/lib/startup-sync.js.map +1 -1
- package/dist/lib/telemetry/build-event.d.ts.map +1 -1
- package/dist/lib/telemetry/build-event.js +19 -2
- package/dist/lib/telemetry/build-event.js.map +1 -1
- package/dist/lib/telemetry/index.d.ts +1 -1
- package/dist/lib/telemetry/index.d.ts.map +1 -1
- package/dist/lib/telemetry/index.js +1 -1
- package/dist/lib/telemetry/index.js.map +1 -1
- package/dist/lib/telemetry/prompt-privacy.d.ts +7 -1
- package/dist/lib/telemetry/prompt-privacy.d.ts.map +1 -1
- package/dist/lib/telemetry/prompt-privacy.js +13 -3
- package/dist/lib/telemetry/prompt-privacy.js.map +1 -1
- package/dist/lib/telemetry/types.d.ts +11 -0
- package/dist/lib/telemetry/types.d.ts.map +1 -1
- package/dist/lib/telemetry/wire-metadata.d.ts +21 -6
- package/dist/lib/telemetry/wire-metadata.d.ts.map +1 -1
- package/dist/lib/telemetry/wire-metadata.js +50 -19
- package/dist/lib/telemetry/wire-metadata.js.map +1 -1
- package/dist/lib/tofu.d.ts +1 -0
- package/dist/lib/tofu.d.ts.map +1 -1
- package/dist/lib/tofu.js +1 -1
- package/dist/lib/tofu.js.map +1 -1
- package/dist/test/client-event-scrub.test.d.ts +2 -0
- package/dist/test/client-event-scrub.test.d.ts.map +1 -0
- package/dist/test/client-event-scrub.test.js +36 -0
- package/dist/test/client-event-scrub.test.js.map +1 -0
- package/dist/test/org-fingerprint-key.test.d.ts +2 -0
- package/dist/test/org-fingerprint-key.test.d.ts.map +1 -0
- package/dist/test/org-fingerprint-key.test.js +39 -0
- package/dist/test/org-fingerprint-key.test.js.map +1 -0
- package/dist/test/org-scrub-setting.test.d.ts +2 -0
- package/dist/test/org-scrub-setting.test.d.ts.map +1 -0
- package/dist/test/org-scrub-setting.test.js +42 -0
- package/dist/test/org-scrub-setting.test.js.map +1 -0
- package/dist/test/prompt-privacy.test.js +19 -2
- package/dist/test/prompt-privacy.test.js.map +1 -1
- package/dist/test/startup-sync-scrub.test.d.ts +2 -0
- package/dist/test/startup-sync-scrub.test.d.ts.map +1 -0
- package/dist/test/startup-sync-scrub.test.js +36 -0
- package/dist/test/startup-sync-scrub.test.js.map +1 -0
- package/dist/test/telemetry.test.js +6 -1
- package/dist/test/telemetry.test.js.map +1 -1
- package/dist/test/wire-metadata.test.d.ts +2 -0
- package/dist/test/wire-metadata.test.d.ts.map +1 -0
- package/dist/test/wire-metadata.test.js +105 -0
- package/dist/test/wire-metadata.test.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { persistCollectPromptsFromResponse } from "../lib/prompt-collection-policy.js";
|
|
7
|
+
import { cloneToolCallMetadataForWire } from "../lib/telemetry/wire-metadata.js";
|
|
8
|
+
// Assembled at runtime so no real-looking key sits in the source.
|
|
9
|
+
const ANTHROPIC = `sk-ant-api03-${"A".repeat(40)}`;
|
|
10
|
+
test("cloneToolCallMetadataForWire - secrets in the content never leave the machine; emails and paths go as they are", () => {
|
|
11
|
+
const command = `curl -H "x-api-key: ${ANTHROPIC}" https://api.anthropic.com && mail ada@gmail.com`;
|
|
12
|
+
const wire = cloneToolCallMetadataForWire({
|
|
13
|
+
tool_name: "Bash",
|
|
14
|
+
tool_input: { command },
|
|
15
|
+
raw_event: { hook_event_name: "PreToolUse", command, cwd: "/Users/ada/src" },
|
|
16
|
+
user_prompt: `use OPENAI_API_KEY=sk-${"b".repeat(30)} please`,
|
|
17
|
+
});
|
|
18
|
+
const expected = 'curl -H "x-api-key: sk-ant-api03-[OL_REDACTED:ANTHROPIC_KEY]" https://api.anthropic.com && mail ada@gmail.com';
|
|
19
|
+
assert.deepStrictEqual(wire?.tool_input, { command: expected });
|
|
20
|
+
assert.deepStrictEqual(wire?.raw_event, { hook_event_name: "PreToolUse", command: expected });
|
|
21
|
+
assert.strictEqual(wire?.user_prompt, "use OPENAI_API_KEY=sk-[OL_REDACTED:OPENAI_KEY] please");
|
|
22
|
+
assert.ok(!JSON.stringify(wire).includes(ANTHROPIC));
|
|
23
|
+
assert.match(String(wire?.scrubber_version), /^\d+\.\d+\.\d+$/);
|
|
24
|
+
});
|
|
25
|
+
test("cloneToolCallMetadataForWire - server-owned keys are still dropped", () => {
|
|
26
|
+
const wire = cloneToolCallMetadataForWire({ tool_name: "Read", user_profile: { email: "x@y.z" }, action_type: "read" });
|
|
27
|
+
assert.deepStrictEqual(Object.keys(wire ?? {}).sort(), ["scrubber_version", "tool_name"]);
|
|
28
|
+
});
|
|
29
|
+
test("cloneToolCallMetadataForWire - vendor secrets get the org's fingerprint once its key is stored", () => {
|
|
30
|
+
const saved = process.env.HOME;
|
|
31
|
+
process.env.HOME = fs.mkdtempSync(path.join(os.tmpdir(), "wire-key-"));
|
|
32
|
+
try {
|
|
33
|
+
const command = `export ANTHROPIC_API_KEY=${ANTHROPIC}`;
|
|
34
|
+
assert.deepStrictEqual(cloneToolCallMetadataForWire({ tool_input: { command } })?.tool_input, {
|
|
35
|
+
command: "export ANTHROPIC_API_KEY=sk-ant-api03-[OL_REDACTED:ANTHROPIC_KEY]",
|
|
36
|
+
});
|
|
37
|
+
persistCollectPromptsFromResponse({ fingerprint_key: "ef".repeat(32) });
|
|
38
|
+
const keyed = cloneToolCallMetadataForWire({ tool_input: { command } })?.tool_input;
|
|
39
|
+
assert.match(keyed.command, /^export ANTHROPIC_API_KEY=sk-ant-api03-\[OL_REDACTED:ANTHROPIC_KEY:[0-9a-f]{24}\]$/);
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
process.env.HOME = saved;
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
test("cloneToolCallMetadataForWire - the running identity is sent as it is, never scrubbed", () => {
|
|
46
|
+
const identity = {
|
|
47
|
+
login: { tenant_id: "org-uuid", email: "ada@acme.io" },
|
|
48
|
+
os_user: { uid: 501, username: "ada.lovelace" },
|
|
49
|
+
};
|
|
50
|
+
const wire = cloneToolCallMetadataForWire({ tool_name: "Read", ...identity });
|
|
51
|
+
assert.deepStrictEqual(wire?.login, identity.login);
|
|
52
|
+
assert.deepStrictEqual(wire?.os_user, identity.os_user);
|
|
53
|
+
});
|
|
54
|
+
test("cloneToolCallMetadataForWire - only allowlisted fields are sent; a field added later stays on the Mac", () => {
|
|
55
|
+
const wire = cloneToolCallMetadataForWire({
|
|
56
|
+
tool_name: "Write",
|
|
57
|
+
tool_input: { file_path: "/tmp/a.txt", content: "hello" },
|
|
58
|
+
hook_hash: "a".repeat(64),
|
|
59
|
+
some_future_field: { anything: "x" },
|
|
60
|
+
user_profile: { email: "spoof@x.io" },
|
|
61
|
+
action_type: "spoofed",
|
|
62
|
+
});
|
|
63
|
+
assert.deepStrictEqual(Object.keys(wire ?? {}).sort(), ["hook_hash", "scrubber_version", "tool_input", "tool_name"]);
|
|
64
|
+
});
|
|
65
|
+
test("cloneToolCallMetadataForWire - raw_event keeps only what the backend reads", () => {
|
|
66
|
+
const wire = cloneToolCallMetadataForWire({
|
|
67
|
+
tool_name: "Shell",
|
|
68
|
+
raw_event: {
|
|
69
|
+
hookEventName: "beforeShellExecution",
|
|
70
|
+
tool_name: "Shell",
|
|
71
|
+
command: `curl -H "Authorization: Bearer ${ANTHROPIC}" https://x.io`,
|
|
72
|
+
tool_response: { stdout: "file contents" },
|
|
73
|
+
transcript_path: "/Users/ada/.cursor/transcript.jsonl",
|
|
74
|
+
tool_input: { content: "the agent's own copy" },
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
assert.deepStrictEqual(wire?.raw_event, {
|
|
78
|
+
hookEventName: "beforeShellExecution",
|
|
79
|
+
tool_name: "Shell",
|
|
80
|
+
command: 'curl -H "Authorization: Bearer sk-ant-api03-[OL_REDACTED:ANTHROPIC_KEY]" https://x.io',
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
test("cloneToolCallMetadataForWire - a Cursor write of a file with a key in it is sent scrubbed", () => {
|
|
84
|
+
const wire = cloneToolCallMetadataForWire({
|
|
85
|
+
tool_name: "write",
|
|
86
|
+
tool_input: { file_path: ".env", content: `OPENAI_API_KEY=sk-proj-${"c".repeat(40)}\nDEBUG=1\n` },
|
|
87
|
+
});
|
|
88
|
+
assert.deepStrictEqual(wire?.tool_input, {
|
|
89
|
+
file_path: ".env",
|
|
90
|
+
content: "OPENAI_API_KEY=sk-proj-[OL_REDACTED:OPENAI_KEY]\nDEBUG=1\n",
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
test("cloneToolCallMetadataForWire - home directories, the running account's or another's, are not redacted", () => {
|
|
94
|
+
const wire = cloneToolCallMetadataForWire({
|
|
95
|
+
tool_name: "Read",
|
|
96
|
+
tool_input: { file_path: "/Users/ada/.claude/plugins/cache/tools/deploy/1.0.0/skills/deploy/SKILL.md" },
|
|
97
|
+
user_prompt: "Base directory for this skill: /Users/ada/.claude/skills/deploy and see /Users/bob/notes",
|
|
98
|
+
os_user: { uid: 501, username: "ada" },
|
|
99
|
+
});
|
|
100
|
+
assert.deepStrictEqual(wire?.tool_input, {
|
|
101
|
+
file_path: "/Users/ada/.claude/plugins/cache/tools/deploy/1.0.0/skills/deploy/SKILL.md",
|
|
102
|
+
});
|
|
103
|
+
assert.strictEqual(wire?.user_prompt, "Base directory for this skill: /Users/ada/.claude/skills/deploy and see /Users/bob/notes");
|
|
104
|
+
});
|
|
105
|
+
//# sourceMappingURL=wire-metadata.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire-metadata.test.js","sourceRoot":"","sources":["../../src/test/wire-metadata.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optimuslabs/runtime-staging",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.11",
|
|
4
4
|
"description": "Agentic audit sensor — streams raw tool call metadata; the Optimus backend classifies on ingest",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"scripts": {
|
|
12
12
|
"build": "rm -rf dist && tsc && node ../../../scripts/ensure-bin-executable.mjs",
|
|
13
13
|
"dev": "tsx src/index.ts",
|
|
14
|
-
"pretest": "npm run build --prefix ../tofu && npm run build",
|
|
14
|
+
"pretest": "npm run build --prefix ../tofu && npm run build --prefix ../pii-scrub && npm run build",
|
|
15
15
|
"test": "node --test dist/test/*.test.js",
|
|
16
16
|
"prepare": "npm run build"
|
|
17
17
|
},
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"typescript": "^5.0.0"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
+
"@optimuslabs/pii-scrub-staging": "^0.1.0",
|
|
49
50
|
"@optimuslabs/tofu-staging": "^0.1.18"
|
|
50
51
|
},
|
|
51
52
|
"publishConfig": {
|