@cygnuxlabs/tracekit 1.3.0 → 1.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 +13 -1
- package/bin/tracekit.mjs +14 -12
- package/dist/v2/launcher.js +1 -1
- package/dist/v2/rpc_schema.d.ts +1 -1
- package/dist/v2/rpc_schema.js +6 -4
- package/dist/verify/cli.js +4 -4
- package/dist/verify/explain.d.ts +46 -0
- package/dist/verify/explain.js +212 -0
- package/dist/verify/index.d.ts +20 -4
- package/dist/verify/index.js +434 -67
- package/dist/verify/jcs.d.ts +2 -0
- package/dist/verify/jcs.js +10 -2
- package/dist/verify/primitives.d.ts +2 -1
- package/dist/verify/primitives.js +3 -2
- package/dist/verify/schema.d.ts +3 -3
- package/dist/verify/schema.js +5 -3
- package/dist/verify/tracekit.event.v2.json +244 -3
- package/dist/verify/web.d.ts +1 -0
- package/dist/verify/web.js +215 -0
- package/dist/verify/zip.d.ts +0 -5
- package/dist/verify/zip.js +10 -5
- package/dist/verify.html +2799 -0
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @cygnuxlabs/tracekit
|
|
2
2
|
|
|
3
|
+
> **Experimental:** the client and its Vercel AI SDK integration work and are tested, but may change and get less
|
|
4
|
+
> hardening than the [stable core](https://github.com/Cygnux-Labs/Tracekit/wiki/Support). Its verifier
|
|
5
|
+
> (`src/verify/`) is stable.
|
|
6
|
+
|
|
3
7
|
Tracekit for TypeScript and JavaScript agents: every tool call is decided by the Tracekit signer before it runs and
|
|
4
8
|
recorded after, and model responses become signed evidence. The client talks to the signer directly; it needs no Python
|
|
5
9
|
at runtime (the same-user dev signer is started with Python when none is running).
|
|
@@ -14,7 +18,7 @@ npm install @cygnuxlabs/tracekit
|
|
|
14
18
|
|
|
15
19
|
npm also installs the signer package for your platform (`@cygnuxlabs/tracekit-signer-<platform>`: Apple Silicon
|
|
16
20
|
macOS, Linux x64 and arm64 with glibc, Windows x64), which bundles a Python, so `npx @cygnuxlabs/tracekit up` starts a
|
|
17
|
-
dev signer without one. On an Intel Mac or Alpine there is none: `pip install
|
|
21
|
+
dev signer without one. On an Intel Mac or Alpine there is none: `pip install tracekit-ai`.
|
|
18
22
|
|
|
19
23
|
Or build it from a checkout and install the file it makes:
|
|
20
24
|
|
|
@@ -91,6 +95,14 @@ It does not check SLH-DSA checkpoint lines, Rekor anchors or certified record ke
|
|
|
91
95
|
`UNVERIFIABLE (not checked by this verifier: ...)`, never `VERIFIED`. Monitor reports, revocations and the v1 format
|
|
92
96
|
bridge need the Python verifier.
|
|
93
97
|
|
|
98
|
+
`verify(bundle, null)`, with no trust config, runs every check that needs no pinned key and is never `VERIFIED`: a
|
|
99
|
+
changed record still fails, an intact bundle is `UNVERIFIABLE (no trust config: ...)`.
|
|
100
|
+
|
|
101
|
+
In a browser: `dist/verify.html` in this package (and a release asset) is this verifier as one self-contained page.
|
|
102
|
+
Drop in a bundle and its trust config; its Content Security Policy lets it load and send nothing, so neither file
|
|
103
|
+
leaves the browser ([verify in your browser](../../docs/verdicts.md#verify-in-your-browser)). `make verify-page` builds
|
|
104
|
+
it from a checkout.
|
|
105
|
+
|
|
94
106
|
## v2 framework adapters
|
|
95
107
|
|
|
96
108
|
One call registers a run (the dev signer is started if none answers), closes it when the process is about to exit,
|
package/bin/tracekit.mjs
CHANGED
|
@@ -15,16 +15,18 @@ if (args[0] === "verify" && args.includes("--trust") && !args.some((a) => PYTHON
|
|
|
15
15
|
process.exit(2);
|
|
16
16
|
}
|
|
17
17
|
const { main } = await import("../dist/verify/cli.js");
|
|
18
|
-
process.exit(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
18
|
+
// not process.exit(): it would cut off a report still being written to a pipe (past 64 KiB)
|
|
19
|
+
process.exitCode = await main(args.slice(1));
|
|
20
|
+
} else {
|
|
21
|
+
const cmd = signerCommand();
|
|
22
|
+
if (!cmd) {
|
|
23
|
+
console.error(`tracekit: ${INSTALL_HINT}`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
const r = spawnSync(cmd[0], [...cmd.slice(1), ...args], { stdio: "inherit", env: signerEnv(cmd) });
|
|
27
|
+
if (r.error) {
|
|
28
|
+
console.error(`tracekit: ${cmd[0]}: ${r.error.message}`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
process.exit(r.status ?? 1);
|
|
29
32
|
}
|
|
30
|
-
process.exit(r.status ?? 1);
|
package/dist/v2/launcher.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { existsSync } from "node:fs";
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import { delimiter, dirname, join } from "node:path";
|
|
9
|
-
export const INSTALL_HINT = "no Tracekit signer found. Install one: `pip install
|
|
9
|
+
export const INSTALL_HINT = "no Tracekit signer found. Install one: `pip install tracekit-ai` (puts `tracekit` " +
|
|
10
10
|
"on PATH), or reinstall @cygnuxlabs/tracekit without --omit=optional so npm adds the signer package for this platform";
|
|
11
11
|
/** This platform's signer package suffix, as the optionalDependencies name them; null where none is built. */
|
|
12
12
|
export function platformKey() {
|
package/dist/v2/rpc_schema.d.ts
CHANGED
package/dist/v2/rpc_schema.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export const RPC_VERSION =
|
|
1
|
+
export const RPC_VERSION = 19;
|
|
2
2
|
export const REQUESTS = {
|
|
3
|
-
"register_run": { "type": "object", "additionalProperties": false, "required": ["request_id", "agent"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "tenant": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "principal": { "type": "string", "maxLength": 256 }, "principal_token": { "type": "string", "maxLength": 16384 }, "source": { "const": "migrated" }, "analyzes": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "replay_of": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "investigation": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "parent": { "type": "object", "additionalProperties": false, "required": ["run_id", "run_token"], "properties": { "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 } } }, "agent": { "type": "object", "additionalProperties": false, "required": ["name"], "properties": { "name": { "type": "string", "maxLength": 128, "minLength": 1 }, "version": { "type": "string", "maxLength": 64 } } } } },
|
|
3
|
+
"register_run": { "type": "object", "additionalProperties": false, "required": ["request_id", "agent"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "tenant": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "principal": { "type": "string", "maxLength": 256 }, "principal_token": { "type": "string", "maxLength": 16384 }, "source": { "const": "migrated" }, "analyzes": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "replay_of": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "investigation": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "parent": { "type": "object", "additionalProperties": false, "required": ["run_id", "run_token"], "properties": { "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 } } }, "caller": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" }, "agent": { "type": "object", "additionalProperties": false, "required": ["name"], "properties": { "name": { "type": "string", "maxLength": 128, "minLength": 1 }, "version": { "type": "string", "maxLength": 64 } } } } },
|
|
4
4
|
"decide": { "type": "object", "additionalProperties": false, "required": ["request_id", "run_id", "run_token", "stream", "client_seq", "tool_call_id", "tool", "args_source", "args"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "stream": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "client_seq": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "caller": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" }, "tool_call_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "attempt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "tool": { "type": "string", "maxLength": 256, "minLength": 1 }, "tool_class_hint": { "type": "string", "maxLength": 64 }, "args_source": { "enum": ["raw", "parsed", "coerced"] }, "args": {} }, "if": { "properties": { "args_source": { "const": "raw" } } }, "then": { "properties": { "args": { "type": "string", "maxLength": 1048576 } } } },
|
|
5
5
|
"complete": { "type": "object", "additionalProperties": false, "required": ["request_id", "run_id", "run_token", "stream", "client_seq", "tool_call_id", "decision_id", "args_digest", "status"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "stream": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "client_seq": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "caller": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" }, "tool_call_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "attempt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "decision_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "args_digest": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" }, "status": { "enum": ["ok", "error"] }, "result": {}, "error": { "type": "string", "maxLength": 4096 }, "redacted": { "const": true }, "redaction": { "type": "object", "additionalProperties": false, "required": [], "properties": { "rules": { "type": "array", "maxItems": 32, "items": { "type": "string", "maxLength": 64 } }, "count": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } },
|
|
6
6
|
"observe": { "type": "object", "additionalProperties": false, "required": ["request_id", "run_id", "run_token", "stream", "client_seq", "source", "trust", "value"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "stream": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "client_seq": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "caller": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" }, "source": { "type": "string", "maxLength": 256, "minLength": 1 }, "trust": { "enum": ["trusted", "untrusted"] }, "value": {} } },
|
|
7
7
|
"state_write": { "type": "object", "additionalProperties": false, "required": ["request_id", "run_id", "run_token", "stream", "client_seq", "key", "value_digest"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "stream": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "client_seq": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "key": { "type": "string", "maxLength": 256, "minLength": 1 }, "value_digest": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" }, "prev_digest": { "oneOf": [{ "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" }, { "type": "null" }] } } },
|
|
8
|
-
"model_event": { "type": "object", "additionalProperties": false, "required": ["request_id", "run_id", "run_token", "stream", "client_seq", "provider", "model", "phase"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "stream": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "client_seq": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "provider": { "type": "string", "maxLength": 64 }, "model": { "type": "string", "maxLength": 128 }, "phase": { "enum": ["request", "response"] }, "content_digest": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" }, "exchange_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "streamed": { "type": "boolean" }, "stop_reason": { "type": "string", "maxLength": 100 }, "error": { "type": "string", "maxLength": 1024 }, "usage": { "type": "object", "additionalProperties": false, "required": [], "properties": { "input_tokens": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "output_tokens": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "cache_read_tokens": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "cache_write_tokens": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "reasoning_tokens": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } }, "tool_uses": { "type": "array", "maxItems": 128, "items": { "type": "object", "additionalProperties": false, "required": ["id", "name", "executed_by"], "properties": { "id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "name": { "type": "string", "maxLength": 256, "minLength": 1 }, "executed_by": { "enum": ["client", "provider"] }, "args_source": { "enum": ["raw", "parsed", "coerced"] }, "args_digest": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" }, "args_unparseable": { "const": true }, "id_synthetic": { "const": true } }, "oneOf": [{ "additionalProperties": false, "properties": { "id": {}, "name": {}, "executed_by": { "const": "provider" }, "id_synthetic": {} } }, { "required": ["args_source", "args_digest"], "additionalProperties": false, "properties": { "id": {}, "name": {}, "executed_by": { "const": "provider" }, "id_synthetic": {}, "args_source": {}, "args_digest": {} } }, { "required": ["args_source", "args_digest"], "properties": { "executed_by": { "const": "client" } } }, { "required": ["args_source", "args_unparseable"], "properties": { "executed_by": { "const": "client" } } }] } }, "tool_results_sent": { "type": "array", "maxItems": 1024, "items": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" } }, "tool_results": { "type": "array", "maxItems": 1024, "items": { "type": "object", "additionalProperties": false, "required": ["id", "forms"], "properties": { "id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "forms": { "type": "array", "minItems": 1, "maxItems": 3, "items": { "type": "object", "additionalProperties": false, "required": ["digest", "result_digest"], "properties": { "digest": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" }, "result_digest": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" } } } } } } }, "caller": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" }, "body": {} } },
|
|
8
|
+
"model_event": { "type": "object", "additionalProperties": false, "required": ["request_id", "run_id", "run_token", "stream", "client_seq", "provider", "model", "phase"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "stream": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "client_seq": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "provider": { "type": "string", "maxLength": 64 }, "model": { "type": "string", "maxLength": 128 }, "phase": { "enum": ["request", "response"] }, "content_digest": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" }, "exchange_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "streamed": { "type": "boolean" }, "stop_reason": { "type": "string", "maxLength": 100 }, "error": { "type": "string", "maxLength": 1024 }, "usage": { "type": "object", "additionalProperties": false, "required": [], "properties": { "input_tokens": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "output_tokens": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "cache_read_tokens": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "cache_write_tokens": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "reasoning_tokens": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } }, "tool_uses": { "type": "array", "maxItems": 128, "items": { "type": "object", "additionalProperties": false, "required": ["id", "name", "executed_by"], "properties": { "id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "name": { "type": "string", "maxLength": 256, "minLength": 1 }, "executed_by": { "enum": ["client", "provider"] }, "args_source": { "enum": ["raw", "parsed", "coerced"] }, "args_digest": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" }, "args_unparseable": { "const": true }, "id_synthetic": { "const": true } }, "oneOf": [{ "additionalProperties": false, "properties": { "id": {}, "name": {}, "executed_by": { "const": "provider" }, "id_synthetic": {} } }, { "required": ["args_source", "args_digest"], "additionalProperties": false, "properties": { "id": {}, "name": {}, "executed_by": { "const": "provider" }, "id_synthetic": {}, "args_source": {}, "args_digest": {} } }, { "required": ["args_source", "args_digest"], "properties": { "executed_by": { "const": "client" } } }, { "required": ["args_source", "args_unparseable"], "properties": { "executed_by": { "const": "client" } } }] } }, "said_only": { "const": true }, "tool_results_sent": { "type": "array", "maxItems": 1024, "items": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" } }, "tool_results": { "type": "array", "maxItems": 1024, "items": { "type": "object", "additionalProperties": false, "required": ["id", "forms"], "properties": { "id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "forms": { "type": "array", "minItems": 1, "maxItems": 3, "items": { "type": "object", "additionalProperties": false, "required": ["digest", "result_digest"], "properties": { "digest": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" }, "result_digest": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" } } } } } } }, "caller": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" }, "amended": { "type": "array", "minItems": 1, "maxItems": 16, "items": { "type": "string", "maxLength": 256, "pattern": "^(/([^~/]|~[01])*)+(?![\\s\\S])" } }, "body": {} } },
|
|
9
9
|
"approval_request": { "type": "object", "additionalProperties": false, "required": ["request_id", "run_id", "run_token", "tool_call_id"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "caller": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" }, "tool_call_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "attempt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "reason": { "type": "string", "maxLength": 1024 } } },
|
|
10
10
|
"approval_decide": { "type": "object", "additionalProperties": false, "required": ["request_id", "approval_id", "decision"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "approval_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "decision": { "enum": ["approve", "reject", "escalate"] }, "reason": { "type": "string", "maxLength": 1024 }, "on_behalf": { "type": "object", "additionalProperties": false, "required": ["subject", "person"], "properties": { "subject": { "type": "string", "maxLength": 256, "minLength": 1 }, "person": { "type": "string", "maxLength": 256, "minLength": 1 }, "groups": { "type": "array", "maxItems": 64, "items": { "type": "string", "maxLength": 256 } }, "tenant": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" } } }, "passkey": { "type": "object", "additionalProperties": false, "required": ["credential_id", "client_data_json", "authenticator_data", "signature"], "properties": { "credential_id": { "type": "string", "maxLength": 4096, "minLength": 1, "pattern": "^[A-Za-z0-9_-]+(?![\\s\\S])" }, "client_data_json": { "type": "string", "maxLength": 4096, "minLength": 1, "pattern": "^[A-Za-z0-9_-]+(?![\\s\\S])" }, "authenticator_data": { "type": "string", "maxLength": 4096, "minLength": 1, "pattern": "^[A-Za-z0-9_-]+(?![\\s\\S])" }, "signature": { "type": "string", "maxLength": 4096, "minLength": 1, "pattern": "^[A-Za-z0-9_-]+(?![\\s\\S])" } } }, "asserted": { "type": "object", "additionalProperties": false, "required": [], "properties": { "model": { "type": "string", "maxLength": 128 }, "version": { "type": "string", "maxLength": 64 }, "prompt_hash": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" } } } } },
|
|
11
11
|
"approval_decide_on_behalf": { "type": "object", "additionalProperties": false, "required": ["request_id", "approval_id", "decision", "approver"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "approval_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "decision": { "enum": ["approve", "reject"] }, "approver": { "type": "string", "maxLength": 64, "pattern": "^slack:[A-Z0-9]+/[A-Z0-9]+(?![\\s\\S])" }, "groups": { "type": "array", "maxItems": 32, "items": { "type": "string", "maxLength": 64, "pattern": "^slack:[A-Z0-9]+/[A-Z0-9]+(?![\\s\\S])" } } } },
|
|
@@ -21,7 +21,7 @@ export const REQUESTS = {
|
|
|
21
21
|
"delegate_run": { "type": "object", "additionalProperties": false, "required": ["run_id", "run_token", "identity"], "properties": { "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "identity": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" } } },
|
|
22
22
|
"tailer_lost": { "type": "object", "additionalProperties": false, "required": ["request_id", "run_id", "run_token", "reason", "offset"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "reason": { "type": "string", "maxLength": 1024 }, "offset": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } },
|
|
23
23
|
"tailer_heartbeat": { "type": "object", "additionalProperties": false, "required": ["run_id", "run_token"], "properties": { "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 } } },
|
|
24
|
-
"observe_effect": { "type": "object", "additionalProperties": false, "required": ["request_id", "instance", "effects"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "instance": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "effects": { "type": "array", "maxItems": 256, "items": { "type": "object", "additionalProperties": false, "required": ["kind", "host", "port", "bytes_out", "bytes_in", "connections", "first_ts", "last_ts"], "properties": { "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "caller": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" }, "kind": { "const": "net" }, "host": { "type": "string", "maxLength": 253, "minLength": 1, "pattern": "^[a-z0-9._:-]+(?![\\s\\S])" }, "port": { "type": "integer", "minimum": 1, "maximum": 65535 }, "bytes_out": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "bytes_in": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "connections": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "first_ts": { "type": "string", "maxLength": 27, "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{6}Z(?![\\s\\S])" }, "last_ts": { "type": "string", "maxLength": 27, "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{6}Z(?![\\s\\S])" } } } }, "check": { "type": "object", "additionalProperties": false, "required": ["run_id", "run_token"], "properties": { "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 } } } } },
|
|
24
|
+
"observe_effect": { "type": "object", "additionalProperties": false, "required": ["request_id", "instance", "effects"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "instance": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "effects": { "type": "array", "maxItems": 256, "items": { "oneOf": [{ "type": "object", "additionalProperties": false, "required": ["kind", "host", "port", "bytes_out", "bytes_in", "connections", "first_ts", "last_ts"], "properties": { "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "caller": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" }, "kind": { "const": "net" }, "host": { "type": "string", "maxLength": 253, "minLength": 1, "pattern": "^[a-z0-9._:-]+(?![\\s\\S])" }, "port": { "type": "integer", "minimum": 1, "maximum": 65535 }, "bytes_out": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "bytes_in": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "connections": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "first_ts": { "type": "string", "maxLength": 27, "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{6}Z(?![\\s\\S])" }, "last_ts": { "type": "string", "maxLength": 27, "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{6}Z(?![\\s\\S])" } } }, { "type": "object", "additionalProperties": false, "required": ["kind", "ts", "pid", "binary"], "properties": { "kind": { "const": "exec" }, "args_digest": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" }, "parent_exec_id": { "type": "string", "maxLength": 256, "minLength": 1 }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "caller": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" }, "ts": { "type": "string", "maxLength": 27, "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{6}Z(?![\\s\\S])" }, "pid": { "type": "integer", "minimum": 0, "maximum": 4294967295 }, "binary": { "type": "string", "maxLength": 4096, "minLength": 1 }, "exec_id": { "type": "string", "maxLength": 256, "minLength": 1 }, "tool_call_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "denied": { "const": true } } }, { "type": "object", "additionalProperties": false, "required": ["kind", "ts", "pid", "binary"], "properties": { "kind": { "const": "exit" }, "status": { "type": "integer", "minimum": 0, "maximum": 4294967295 }, "signal": { "type": "string", "maxLength": 32 }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "caller": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" }, "ts": { "type": "string", "maxLength": 27, "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{6}Z(?![\\s\\S])" }, "pid": { "type": "integer", "minimum": 0, "maximum": 4294967295 }, "binary": { "type": "string", "maxLength": 4096, "minLength": 1 }, "exec_id": { "type": "string", "maxLength": 256, "minLength": 1 }, "tool_call_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "denied": { "const": true } } }, { "type": "object", "additionalProperties": false, "required": ["kind", "ts", "pid", "binary", "host", "port"], "properties": { "kind": { "const": "connect" }, "host": { "type": "string", "maxLength": 253, "minLength": 1, "pattern": "^[a-z0-9._:-]+(?![\\s\\S])" }, "port": { "type": "integer", "minimum": 0, "maximum": 65535 }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "caller": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" }, "ts": { "type": "string", "maxLength": 27, "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{6}Z(?![\\s\\S])" }, "pid": { "type": "integer", "minimum": 0, "maximum": 4294967295 }, "binary": { "type": "string", "maxLength": 4096, "minLength": 1 }, "exec_id": { "type": "string", "maxLength": 256, "minLength": 1 }, "tool_call_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "denied": { "const": true } } }, { "type": "object", "additionalProperties": false, "required": ["kind", "ts", "pid", "binary", "path"], "properties": { "kind": { "const": "file" }, "path": { "type": "string", "maxLength": 4096, "minLength": 1 }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "caller": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" }, "ts": { "type": "string", "maxLength": 27, "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{6}Z(?![\\s\\S])" }, "pid": { "type": "integer", "minimum": 0, "maximum": 4294967295 }, "binary": { "type": "string", "maxLength": 4096, "minLength": 1 }, "exec_id": { "type": "string", "maxLength": 256, "minLength": 1 }, "tool_call_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "denied": { "const": true } } }, { "type": "object", "additionalProperties": false, "required": ["kind", "ts", "change"], "properties": { "kind": { "const": "policy" }, "ts": { "type": "string", "maxLength": 27, "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{6}Z(?![\\s\\S])" }, "change": { "type": "string", "maxLength": 64, "minLength": 1, "pattern": "^[a-z0-9_.-]+(?![\\s\\S])" }, "policy_hash": { "type": "string", "maxLength": 128, "minLength": 1 }, "by": { "type": "string", "maxLength": 256, "minLength": 1 }, "detail_digest": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "caller": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" } } }, { "type": "object", "additionalProperties": false, "required": ["kind", "reason"], "properties": { "kind": { "const": "lost" }, "reason": { "type": "string", "maxLength": 1024, "minLength": 1 }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "caller": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" } } }] } }, "check": { "type": "object", "additionalProperties": false, "required": ["run_id", "run_token"], "properties": { "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 } } }, "sensor": { "enum": ["tetragon", "falco", "openshell"] }, "callers": { "type": "array", "maxItems": 256, "items": { "type": "string", "maxLength": 256, "pattern": "^[a-z0-9_]+:.+(?![\\s\\S])" } }, "lost": { "type": "string", "maxLength": 1024 } } },
|
|
25
25
|
"status": { "type": "object", "additionalProperties": false, "required": [], "properties": {} },
|
|
26
26
|
"read": { "type": "object", "additionalProperties": false, "required": ["run_id", "run_token"], "properties": { "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "from_seq": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "limit": { "type": "integer", "minimum": 1, "maximum": 1000 } } },
|
|
27
27
|
"checkpoint_nudge": { "type": "object", "additionalProperties": false, "required": [], "properties": {} },
|
|
@@ -30,6 +30,8 @@ export const REQUESTS = {
|
|
|
30
30
|
"content_get": { "type": "object", "additionalProperties": false, "required": ["run_id", "seqs", "purpose"], "properties": { "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "seqs": { "type": "array", "maxItems": 1000, "items": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "purpose": { "type": "string", "maxLength": 512, "minLength": 1 } } },
|
|
31
31
|
"content_erase": { "type": "object", "additionalProperties": false, "required": ["request_id", "run_id"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "reason": { "type": "string", "maxLength": 1024 } } },
|
|
32
32
|
"why_finding": { "type": "object", "additionalProperties": false, "required": ["request_id", "run_id", "run_token", "finding"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "finding": { "type": "object", "additionalProperties": false, "required": ["target", "intervention", "n", "p_with", "p_without", "effect", "interval", "verdict", "replay_runs", "models", "rung", "off_tape", "investigation", "looks", "family", "min_effect", "applied", "stopped"], "properties": { "target": { "type": "string", "maxLength": 1024 }, "intervention": { "type": "string", "maxLength": 1024 }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "p_with": { "type": "number", "minimum": 0, "maximum": 1 }, "p_without": { "type": "number", "minimum": 0, "maximum": 1 }, "effect": { "type": "number", "minimum": -1, "maximum": 1 }, "interval": { "type": "array", "minItems": 2, "maxItems": 2, "items": { "type": "number", "minimum": -1, "maximum": 1 } }, "verdict": { "enum": ["causal", "suppressive", "ruled-out", "inconclusive", "not-applied"] }, "replay_runs": { "type": "array", "maxItems": 4096, "items": { "type": "object", "additionalProperties": false, "required": ["run_id", "arm", "hit"], "properties": { "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "arm": { "enum": ["control", "ablated"] }, "hit": { "type": "boolean" } } } }, "models": { "type": "array", "maxItems": 32, "items": { "type": "string", "maxLength": 128 } }, "rung": { "enum": [1, 2] }, "off_tape": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "investigation": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "looks": { "type": "integer", "minimum": 1, "maximum": 4096 }, "family": { "type": "integer", "minimum": 1, "maximum": 4096 }, "min_effect": { "type": "number", "minimum": 0, "maximum": 1 }, "applied": { "type": "boolean" }, "stopped": { "enum": ["decisive", "futility", "n_max", "budget"] }, "uncounted": { "type": "array", "maxItems": 4096, "items": { "type": "object", "additionalProperties": false, "required": ["run_id", "reason"], "properties": { "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "reason": { "enum": ["ranking", "budget"] } } } } } } } },
|
|
33
|
+
"review_finding": { "type": "object", "additionalProperties": false, "required": ["request_id", "run_id", "run_token", "review"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "review": { "type": "object", "additionalProperties": false, "required": ["reviewer", "verdict", "cites"], "properties": { "reviewer": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._/+-]+(?![\\s\\S])" }, "cites": { "type": "array", "maxItems": 256, "items": { "type": "object", "additionalProperties": false, "required": ["run_seq", "hash"], "properties": { "run_seq": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "hash": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" } } } }, "verdict": { "oneOf": [{ "type": "object", "additionalProperties": false, "required": ["kind", "rule", "severity"], "properties": { "kind": { "const": "finding" }, "rule": { "enum": ["TK-X201", "TK-X202", "TK-X203", "TK-X204", "TK-X205", "TK-X206", "TK-X207", "TK-X208", "TK-X210", "TK-X101", "TK-X102", "TK-X103", "TK-X104", "TK-X111", "TK-X112", "TK-X113", "TK-X114", "TK-X120", "TK-X211"] }, "severity": { "enum": ["info", "low", "medium", "high", "critical"] }, "tier": { "enum": ["gateway", "harness", "transcript", "sdk"] }, "order": { "enum": ["signed_before", "transcript_order", "after"] }, "redacted": { "type": "boolean" }, "lifted": { "type": "boolean" }, "digests": { "type": "array", "maxItems": 32, "items": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" } }, "alignment": { "enum": ["ok", "drift", "misaligned"] }, "reason": { "enum": ["none", "unrequested_action", "unexplained_action", "contradicted_reasoning", "scope_creep", "workaround", "false_success", "followed_tool_output", "injection", "other"] }, "asserted": { "type": "object", "additionalProperties": false, "required": ["model", "version", "prompt_hash"], "properties": { "model": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:/@+-]+(?![\\s\\S])" }, "version": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:/@+-]+(?![\\s\\S])" }, "prompt_hash": { "type": "string", "maxLength": 71, "pattern": "^sha256:[0-9a-f]{64}(?![\\s\\S])" } } }, "families": { "type": "object", "additionalProperties": false, "required": ["reviewer", "agent"], "properties": { "reviewer": { "enum": ["anthropic", "openai", "google", "meta", "mistral", "deepseek", "qwen", "xai", null] }, "agent": { "type": "array", "maxItems": 8, "items": { "enum": ["anthropic", "openai", "google", "meta", "mistral", "deepseek", "qwen", "xai"] } } } }, "window": { "type": "object", "additionalProperties": false, "required": ["grace_s", "skew_s"], "properties": { "grace_s": { "type": "number", "minimum": 0, "maximum": 86400 }, "skew_s": { "type": "number", "minimum": 0, "maximum": 86400 } } } } }, { "type": "object", "additionalProperties": false, "required": ["kind", "rule", "severity", "checks"], "properties": { "kind": { "const": "coverage" }, "rule": { "const": "TK-X200" }, "severity": { "const": "info" }, "checks": { "type": "object", "additionalProperties": false, "required": [], "properties": { "TK-X201": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X202": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X203": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X204": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X205": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X206": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X207": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X208": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X210": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X101": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X102": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X103": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X104": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X111": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X112": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X113": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X114": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X120": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } }, "TK-X211": { "type": "object", "additionalProperties": false, "required": ["checked", "found"], "properties": { "checked": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "found": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "not_checkable": { "type": "array", "maxItems": 16, "items": { "type": "object", "additionalProperties": false, "required": ["reason", "n"], "properties": { "reason": { "type": "string", "maxLength": 32, "minLength": 1, "pattern": "^[a-z][a-z_]*(?![\\s\\S])" }, "n": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } } } } }, "partial": { "type": "boolean" }, "reasoning": { "type": "object", "additionalProperties": false, "required": [], "properties": { "full": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "summary": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "withheld": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "none": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } } } } }] } } } } },
|
|
34
|
+
"constraint_add": { "type": "object", "additionalProperties": false, "required": ["request_id", "run_id", "run_token", "constraint"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "run_token": { "type": "string", "maxLength": 1024, "minLength": 1 }, "constraint": { "type": "object", "additionalProperties": false, "required": ["kind"], "properties": { "kind": { "enum": ["keep_away", "only_change", "read_only", "no_push", "no_network"] }, "object": { "type": "string", "maxLength": 256, "minLength": 1 } } } } },
|
|
33
35
|
"incident_list": { "type": "object", "additionalProperties": false, "required": [], "properties": { "state": { "enum": ["open", "resolved"] }, "cursor": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "limit": { "type": "integer", "minimum": 1, "maximum": 1000 } } },
|
|
34
36
|
"incident_show": { "type": "object", "additionalProperties": false, "required": ["incident_id"], "properties": { "incident_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" } } },
|
|
35
37
|
"incident_resolve": { "type": "object", "additionalProperties": false, "required": ["request_id", "incident_id"], "properties": { "request_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "incident_id": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9._:-]+(?![\\s\\S])" }, "reason": { "type": "string", "maxLength": 1024 } } },
|
package/dist/verify/cli.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* CLI's report and exit codes (0 verified, 1 failed, 2 unusable or unverifiable, 3 a warning under --strict).
|
|
4
4
|
*/
|
|
5
5
|
import { readFile } from "node:fs/promises";
|
|
6
|
+
import { asJson } from "./explain.js";
|
|
6
7
|
import { EXIT_BAD, EXIT_OK, EXIT_WARN, formatReport, verify } from "./index.js";
|
|
7
8
|
const USAGE = "usage: tracekit verify BUNDLE --trust TRUST.json [--json] [--strict]";
|
|
8
9
|
export async function main(argv) {
|
|
@@ -19,7 +20,7 @@ export async function main(argv) {
|
|
|
19
20
|
bundle = a;
|
|
20
21
|
else {
|
|
21
22
|
console.error(`tracekit verify: ${a} is not supported by the TypeScript verifier (the format bridge, monitor reports `
|
|
22
|
-
+ `and revocations need the reference verifier: pip install tracekit)\n${USAGE}`);
|
|
23
|
+
+ `and revocations need the reference verifier: pip install tracekit-ai)\n${USAGE}`);
|
|
23
24
|
return EXIT_BAD;
|
|
24
25
|
}
|
|
25
26
|
}
|
|
@@ -35,11 +36,10 @@ export async function main(argv) {
|
|
|
35
36
|
console.error(`tracekit verify: ${e.message}`);
|
|
36
37
|
return EXIT_BAD;
|
|
37
38
|
}
|
|
38
|
-
const { report, code: verdict } = await verify(...data);
|
|
39
|
+
const { report, code: verdict } = await verify(...data, { bundle, trust });
|
|
39
40
|
const code = verdict === EXIT_OK && strict && report.warnings.length ? EXIT_WARN : verdict;
|
|
40
41
|
if (json)
|
|
41
|
-
console.log(JSON.stringify(
|
|
42
|
-
warnings: report.warnings, integrity: report.integrity, assurance: report.assurance, notes: report.notes }, null, 2));
|
|
42
|
+
console.log(JSON.stringify(asJson(report, code), null, 2));
|
|
43
43
|
else
|
|
44
44
|
process.stdout.write(formatReport(report));
|
|
45
45
|
return code;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the browser verifier (web.ts) says about a report, in plain words: the verdict and what it does and doesn't
|
|
3
|
+
* mean, what to do next, a line per check on what it means (docs/verdicts.md, shortened), and a summary of the bundle's
|
|
4
|
+
* runs. The report itself is the CLI's, unchanged: this module only reads it. No DOM, so Node tests it.
|
|
5
|
+
*/
|
|
6
|
+
import { type Report } from "./index.js";
|
|
7
|
+
export type Names = {
|
|
8
|
+
bundle: string;
|
|
9
|
+
trust: string | null;
|
|
10
|
+
};
|
|
11
|
+
export type Verdict = {
|
|
12
|
+
word: "VERIFIED" | "FAILED" | "UNVERIFIABLE";
|
|
13
|
+
means: string;
|
|
14
|
+
notMeans: string;
|
|
15
|
+
};
|
|
16
|
+
/** A step: what to do, and the command to run for it, if any. */
|
|
17
|
+
export type Step = {
|
|
18
|
+
text: string;
|
|
19
|
+
command?: string;
|
|
20
|
+
};
|
|
21
|
+
/** `s` as one shell argument (POSIX shells; the page doesn't know the reader's). */
|
|
22
|
+
export declare const sh: (s: string) => string;
|
|
23
|
+
/** The report as `tracekit verify --json` prints it (cli.ts prints this). */
|
|
24
|
+
export declare const asJson: (rep: Report, code: number) => {
|
|
25
|
+
findings?: string | undefined;
|
|
26
|
+
exit_code: number;
|
|
27
|
+
checks: import("./index.js").Check[];
|
|
28
|
+
failures: string[];
|
|
29
|
+
warnings: string[];
|
|
30
|
+
integrity: string;
|
|
31
|
+
assurance: string;
|
|
32
|
+
notes: string[];
|
|
33
|
+
};
|
|
34
|
+
/** The report as `tracekit verify` prints it, then its exit code. */
|
|
35
|
+
export declare const asText: (rep: Report, code: number) => string;
|
|
36
|
+
/** What the command-line verifiers exit with for the same files, where that is known: they refuse a v2 bundle without a
|
|
37
|
+
* trust file, and the Python one checks what this verifier doesn't (and v1 bundles, against signer.pub). */
|
|
38
|
+
export declare function cliExit(rep: Report): string;
|
|
39
|
+
export declare function verdict(rep: Report, code: number): Verdict;
|
|
40
|
+
/** What to do after a result that isn't plainly VERIFIED: what to check or ask for, with the commands that do it. */
|
|
41
|
+
export declare function nextSteps(rep: Report, code: number, names: Names): Step[];
|
|
42
|
+
/** One line per check: what it means (docs/verdicts.md#lines). */
|
|
43
|
+
export declare const MEANING: Record<string, string>;
|
|
44
|
+
/** A few plain facts about the bundle's runs, from their records ({name: bytes}, the runs/ files, a run's parts read as
|
|
45
|
+
* one), cleaned as the report is; names an agent chose are quoted, so they can't read as the signer's words around them. */
|
|
46
|
+
export declare function summarize(files: Map<string, Uint8Array>, rep: Report): [string, string][];
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the browser verifier (web.ts) says about a report, in plain words: the verdict and what it does and doesn't
|
|
3
|
+
* mean, what to do next, a line per check on what it means (docs/verdicts.md, shortened), and a summary of the bundle's
|
|
4
|
+
* runs. The report itself is the CLI's, unchanged: this module only reads it. No DOM, so Node tests it.
|
|
5
|
+
*/
|
|
6
|
+
import { EXIT_FAIL, EXIT_OK, VERSION, clean, formatReport, runFiles } from "./index.js";
|
|
7
|
+
/** `s` as one shell argument (POSIX shells; the page doesn't know the reader's). */
|
|
8
|
+
export const sh = (s) => /^[\w@%+=:,./-]+$/.test(s) ? s : `'${s.replace(/'/g, `'"'"'`)}'`;
|
|
9
|
+
const TRUST_FILE = "the sender's trust file: a small .json that names their signer's log key (tracekit last writes it next "
|
|
10
|
+
+ "to the bundle, as <name>.trust.json)";
|
|
11
|
+
/** The report as `tracekit verify --json` prints it (cli.ts prints this). */
|
|
12
|
+
export const asJson = (rep, code) => ({ exit_code: code, checks: rep.checks, failures: rep.failures,
|
|
13
|
+
warnings: rep.warnings, integrity: rep.integrity, assurance: rep.assurance, notes: rep.notes,
|
|
14
|
+
...rep.findings ? { findings: rep.findings } : {} });
|
|
15
|
+
/** The report as `tracekit verify` prints it, then its exit code. */
|
|
16
|
+
export const asText = (rep, code) => formatReport(rep) + `\nExit code ${code}`
|
|
17
|
+
+ (code === EXIT_OK && rep.warnings.length ? ` (3 with --strict: ${rep.warnings.length} warning(s))` : "") + ".\n";
|
|
18
|
+
const failed = (rep, name) => rep.checks.find((c) => c.check === name && c.status === "fail");
|
|
19
|
+
const anchored = (rep) => !rep.checks.some((c) => c.check === "trust config" && c.status === "warn");
|
|
20
|
+
const v1 = (rep) => rep.checks.some((c) => c.check === "bundle readable"
|
|
21
|
+
&& c.problems.some((p) => p.startsWith("a format v1 bundle")));
|
|
22
|
+
/** What the command-line verifiers exit with for the same files, where that is known: they refuse a v2 bundle without a
|
|
23
|
+
* trust file, and the Python one checks what this verifier doesn't (and v1 bundles, against signer.pub). */
|
|
24
|
+
export function cliExit(rep) {
|
|
25
|
+
if (v1(rep))
|
|
26
|
+
return "";
|
|
27
|
+
if (!anchored(rep))
|
|
28
|
+
return " The command-line verifiers need the trust file: without one they exit 2.";
|
|
29
|
+
return rep.unsupported.length ? " The TypeScript command-line verifier exits with the same code; the Python one checks "
|
|
30
|
+
+ "what this page doesn't." : " The command-line verifiers exit with the same code.";
|
|
31
|
+
}
|
|
32
|
+
export function verdict(rep, code) {
|
|
33
|
+
const behaved = "It doesn't mean the agent behaved well, or that the record holds everything it did: the summary, "
|
|
34
|
+
+ "findings and warnings below tell you that.";
|
|
35
|
+
if (code === EXIT_OK) {
|
|
36
|
+
const head = rep.integrity.match(/^VERIFIED TO HEAD (\d+)/);
|
|
37
|
+
return { word: "VERIFIED", means: "The record is intact and signed by the signer your trust file names: nothing was "
|
|
38
|
+
+ "edited, removed, reordered or added after signing."
|
|
39
|
+
+ (head ? ` The run was still open when it was exported: its records up to number ${head[1]} are verified.` : ""),
|
|
40
|
+
notMeans: behaved };
|
|
41
|
+
}
|
|
42
|
+
if (code === EXIT_FAIL) {
|
|
43
|
+
if (failed(rep, "checkpoint") && anchored(rep))
|
|
44
|
+
return { word: "FAILED", means: "This bundle is not signed by the signer your trust file names, or its checkpoint "
|
|
45
|
+
+ "was changed.", notMeans: "It doesn't say who made the bundle. If the trust file is the right one, don't rely "
|
|
46
|
+
+ "on the bundle." };
|
|
47
|
+
return { word: "FAILED", means: "This bundle doesn't match what was signed: something in it was changed, removed or "
|
|
48
|
+
+ `added after signing. Failed: ${rep.failures.join(", ")}.`,
|
|
49
|
+
notMeans: "It doesn't say who changed it or why: the failed lines below show what doesn't match." };
|
|
50
|
+
}
|
|
51
|
+
const readable = rep.checks.find((c) => c.check === "bundle readable");
|
|
52
|
+
const nothing = "Nothing failed: it doesn't mean the bundle is bad.";
|
|
53
|
+
if (failed(rep, "trust config"))
|
|
54
|
+
return { word: "UNVERIFIABLE", means: "The trust file couldn't be used, so nothing was checked.", notMeans: nothing };
|
|
55
|
+
if (v1(rep))
|
|
56
|
+
return { word: "UNVERIFIABLE", means: "This is a format v1 bundle (from Tracekit's laptop signer); this page checks "
|
|
57
|
+
+ "format v2 bundles, so nothing was checked.", notMeans: nothing };
|
|
58
|
+
if (rep.integrity.startsWith("UNVERIFIABLE (needs"))
|
|
59
|
+
return { word: "UNVERIFIABLE", means: `This bundle needs a newer verifier than this page (Tracekit ${VERSION}).`,
|
|
60
|
+
notMeans: nothing };
|
|
61
|
+
if (readable)
|
|
62
|
+
return { word: "UNVERIFIABLE", means: "This file couldn't be read as a Tracekit bundle, so nothing in it was checked.",
|
|
63
|
+
notMeans: "Nothing in it can be relied on until a readable copy verifies." };
|
|
64
|
+
if (!anchored(rep))
|
|
65
|
+
return { word: "UNVERIFIABLE", means: "Signatures are intact, but you haven't said whose signer you trust.",
|
|
66
|
+
notMeans: "It doesn't mean the bundle is genuine: anyone can sign a bundle with keys of their own. The sender's "
|
|
67
|
+
+ "trust file says whose signer made it." };
|
|
68
|
+
return { word: "UNVERIFIABLE", means: "This page doesn't implement a check this bundle relies on: "
|
|
69
|
+
+ `${rep.integrity.replace(/^UNVERIFIABLE \(not checked by this verifier: (.*)\)$/, "$1")}.`, notMeans: nothing };
|
|
70
|
+
}
|
|
71
|
+
/** What to do after a result that isn't plainly VERIFIED: what to check or ask for, with the commands that do it. */
|
|
72
|
+
export function nextSteps(rep, code, names) {
|
|
73
|
+
const b = sh(names.bundle), t = sh(names.trust ?? "trust.json");
|
|
74
|
+
const cli = { text: "Check the same files with the command-line verifier (it needs Node.js, nothing else):",
|
|
75
|
+
command: `npx -y @cygnuxlabs/tracekit@latest verify ${b} --trust ${t}` };
|
|
76
|
+
const readable = rep.checks.find((c) => c.check === "bundle readable");
|
|
77
|
+
if (code === EXIT_OK)
|
|
78
|
+
return rep.warnings.length ? [{ text: `Read the ${rep.warnings.length} warning(s) below: each says what to look at. `
|
|
79
|
+
+ "They don't change the verdict (with --strict the command line exits 3)." }] : [];
|
|
80
|
+
if (failed(rep, "trust config"))
|
|
81
|
+
return [{ text: `Choose the trust file again: it must be a Tracekit v2 trust config (a .json with "logs"). Ask for ${TRUST_FILE}.` }];
|
|
82
|
+
if (readable?.problems.length)
|
|
83
|
+
return readable.problems.map((p) => {
|
|
84
|
+
const at = p.search(/(npx|uvx) /);
|
|
85
|
+
const text = at < 0 ? p.replace(/^or open (\S+) /, "open the latest page, $1, ")
|
|
86
|
+
: at ? p.slice(0, at).trimEnd() : p.startsWith("npx") ? "with Node.js:" : "or with Python, using uv:";
|
|
87
|
+
return { text: text[0].toUpperCase() + text.slice(1), ...at < 0 ? {} : { command: p.slice(at) } };
|
|
88
|
+
});
|
|
89
|
+
if (readable)
|
|
90
|
+
return [{ text: `Check that you chose the .tkb file itself (not a renamed archive or a saved web page), then ask the `
|
|
91
|
+
+ "sender to export it again: a damaged or cut-short copy reads like this." }];
|
|
92
|
+
if (code === EXIT_FAIL) {
|
|
93
|
+
const steps = [];
|
|
94
|
+
if (failed(rep, "checkpoint") && anchored(rep))
|
|
95
|
+
steps.push({ text: `Make sure the trust file is ${TRUST_FILE.replace("the sender's", "the sender's own")}. With `
|
|
96
|
+
+ "the right one, this bundle isn't theirs: don't rely on it." });
|
|
97
|
+
else
|
|
98
|
+
steps.push({ text: "Don't rely on this bundle's contents. Ask the sender for the original and compare its SHA-256 "
|
|
99
|
+
+ "with theirs:", command: `shasum -a 256 ${b}` });
|
|
100
|
+
if (anchored(rep))
|
|
101
|
+
steps.push(cli);
|
|
102
|
+
else
|
|
103
|
+
steps.push({ text: `Add ${TRUST_FILE}, to see whose signer made it.` });
|
|
104
|
+
return steps;
|
|
105
|
+
}
|
|
106
|
+
if (!anchored(rep))
|
|
107
|
+
return [{ text: `Ask for ${TRUST_FILE}, and add it above. Get it from the sender directly, not inside the bundle's `
|
|
108
|
+
+ "own folder or message: the trust file is what makes the check mean something." }];
|
|
109
|
+
return [{ text: "Verify it with the reference verifier, which checks this:",
|
|
110
|
+
command: `uvx --from tracekit-ai tracekit verify ${b} --trust ${t}` }];
|
|
111
|
+
}
|
|
112
|
+
/** One line per check: what it means (docs/verdicts.md#lines). */
|
|
113
|
+
export const MEANING = {
|
|
114
|
+
"trust config": "Your trust file: the log key and witnesses you trust, never ones the bundle brings.",
|
|
115
|
+
"bundle readable": "The file is a Tracekit v2 bundle this verifier can read.",
|
|
116
|
+
"bundle structure": "The bundle is well formed; a failure here means it is malformed in a way no other line covers.",
|
|
117
|
+
"manifest": "The files in the bundle are exactly those its manifest lists, with those hashes.",
|
|
118
|
+
"checkpoint": "The log's checkpoint (the signed root of every record) is signed by the log key your trust file pins.",
|
|
119
|
+
"witness quorum": "Enough witnesses your trust file pins cosigned the checkpoint: they vouch it was not rolled back.",
|
|
120
|
+
"keys": "The record keys were declared by records the checkpoint includes, in order, and retired keys stop signing.",
|
|
121
|
+
"run parts": "A long run comes in numbered parts: none is missing between the first and the last, extra or out of "
|
|
122
|
+
+ "order, so they read as one run. Parts cut off its end leave it open, never VERIFIED.",
|
|
123
|
+
"signatures": "Every record's signature verifies under a key valid at its position: no record was edited after signing.",
|
|
124
|
+
"run chain": "Each run's records follow one another without a gap from the first: none deleted, swapped or added.",
|
|
125
|
+
"inclusion": "Each run's first and last records are in the checkpointed tree: the run wasn't rebuilt.",
|
|
126
|
+
"policy snapshot": "The bundled policy file is named by its own hash: it wasn't edited.",
|
|
127
|
+
"policy": "A tool call ran against a deny, or an ask nobody approved, and the signer recorded it.",
|
|
128
|
+
"held calls": "A call held for a gateway or executor got no result before its run ended.",
|
|
129
|
+
"gaps": "The signer recorded something a person should read: a gap, a tamper attempt or a mismatched approval.",
|
|
130
|
+
"external decisions": "Decisions imported from another policy system, and whether they disagreed with the signer's.",
|
|
131
|
+
"coverage": "Which capture layers reported, and calls the signer could not match across them.",
|
|
132
|
+
"coverage matrix": "How each kind of action was covered: enforced, observed, only reported by the agent, or not at all.",
|
|
133
|
+
"observers": "An observer outside the agent went silent or restarted while the run was open.",
|
|
134
|
+
"reviews": "Signed findings about the run, each labelled by who wrote it: independent, unpinned or self-asserted.",
|
|
135
|
+
"reviews counted": "Findings whose analysed run isn't in the bundle, so their citations weren't checked.",
|
|
136
|
+
"incidents": "Detections the signer opened, recomputed from the run's records where the bundle allows.",
|
|
137
|
+
"incident policies": "Policies an incident cites that aren't in the bundle: those incidents are the signer's word.",
|
|
138
|
+
"content vault": "Who read or erased retained content, as the signer recorded it.",
|
|
139
|
+
"tiers": "Tool calls by how they were captured: T2 gateway or executor, T1 adapter, T3 import (receipt only).",
|
|
140
|
+
"args source": "Whether recorded arguments are the model's exact bytes (raw), parsed, or changed by a framework.",
|
|
141
|
+
"isolation": "How the signer measured its separation from the agent: separate-user and remote are out of its reach.",
|
|
142
|
+
"principals": "The person or service each run acted for, attested by the signer or asserted by the app.",
|
|
143
|
+
"harness": "The agent harness the signer bound each run to.",
|
|
144
|
+
"fail-open classes": "Tool classes allowed to run while the signer is down, so such calls may be unrecorded.",
|
|
145
|
+
"key assurance": "Whether the record keys are only declared by the log (asserted) or certified by an issuer.",
|
|
146
|
+
"approvals by people": "Held calls approved by people.",
|
|
147
|
+
"approvals by agents": "Held calls approved by agents (model output), checked against the rules that allow it.",
|
|
148
|
+
"break-glass approvals": "Approvals given under the break-glass role, with who and why.",
|
|
149
|
+
"not interpreted": "Records carry an extension this verifier doesn't read. They verified like every other record.",
|
|
150
|
+
"gateway amendments": "Requests the LLM gateway changed so the provider shows its reasoning; each record commits to "
|
|
151
|
+
+ "the request as sent.",
|
|
152
|
+
"openshell policy": "Changes of the sandbox's policy or configuration that NVIDIA OpenShell reported, signed into "
|
|
153
|
+
+ "the run as OpenShell's report.",
|
|
154
|
+
"constraints": "What the person's request said not to do, added while the run was open, and the calls it held.",
|
|
155
|
+
"run-set": "Every run of the tenant in the registry range is in the bundle (COMPLETE), or what is missing.",
|
|
156
|
+
"tenant-level gaps": "Signer gaps in the range that concern every tenant, such as witness failures.",
|
|
157
|
+
"log tail": "Whether records after the checkpoint are proven absent (a log.closed) or simply unproven.",
|
|
158
|
+
"rekor anchor": "A Rekor transparency-log anchor of the checkpoint, which this page can't check.",
|
|
159
|
+
"SLH-DSA-SHA2-128s checkpoint signature": "A post-quantum checkpoint signature, which browsers can't check yet.",
|
|
160
|
+
"record-key certificates": "Certificates of the record keys, which this page doesn't check.",
|
|
161
|
+
"tracekit why findings": "tracekit why investigation findings, which this page doesn't check.",
|
|
162
|
+
};
|
|
163
|
+
const day = (ts) => ts.slice(0, 19).replace("T", " ") + " UTC";
|
|
164
|
+
/** A few plain facts about the bundle's runs, from their records ({name: bytes}, the runs/ files, a run's parts read as
|
|
165
|
+
* one), cleaned as the report is; names an agent chose are quoted, so they can't read as the signer's words around them. */
|
|
166
|
+
export function summarize(files, rep) {
|
|
167
|
+
const text = new TextDecoder();
|
|
168
|
+
const runs = [...runFiles(files.keys()).values()].map((parts) => parts.flatMap((n) => text.decode(files.get(n))
|
|
169
|
+
.split("\n").filter(Boolean).map((l) => JSON.parse(l).event)));
|
|
170
|
+
const events = runs.flat(), of = (t) => events.filter((e) => e.type === t);
|
|
171
|
+
const times = events.map((e) => e.ts).filter((t) => typeof t === "string").sort();
|
|
172
|
+
const out = [];
|
|
173
|
+
const [first, end] = [times[0], times[times.length - 1]], secs = (Date.parse(end) - Date.parse(first)) / 1000;
|
|
174
|
+
out.push(["Records", `${events.length} signed record(s) in ${runs.length} run(s)` + (times.length ? `, ${day(first)}`
|
|
175
|
+
+ ` to ${day(end)} (${secs < 120 ? `${Math.round(secs)} s` : secs < 7200 ? `${Math.round(secs / 60)} min`
|
|
176
|
+
: `${Math.round(secs / 3600)} h`})` : "")]);
|
|
177
|
+
const cp = rep.checks.find((c) => c.check === "checkpoint")?.detail.split(" at tree size")[0];
|
|
178
|
+
if (cp)
|
|
179
|
+
out.push(["Signer", `log ${cp}` + (anchored(rep) ? ", the key your trust file pins" : ", not checked (no trust file)")]);
|
|
180
|
+
const level = rep.assurance.split(";")[0];
|
|
181
|
+
out.push(["Assurance", level === "witnessed" ? "witnessed: independent witnesses cosigned the checkpoint"
|
|
182
|
+
: level === "local" ? "local: only witnesses the log's operator runs cosigned the checkpoint"
|
|
183
|
+
: level === "dev" ? "dev: no independent witness vouches for the checkpoint (or a run holds a self-approval)"
|
|
184
|
+
: level]);
|
|
185
|
+
const agents = runs.map((rs) => rs[0]).filter((e) => e?.type === "run.registered").map((e) => {
|
|
186
|
+
const id = e.data?.identity;
|
|
187
|
+
return `${JSON.stringify(String(e.data?.agent?.name ?? "agent"))}` + (id ? ` (${id.scheme}:${id.subject})` : "");
|
|
188
|
+
});
|
|
189
|
+
const named = [...new Set(agents)];
|
|
190
|
+
if (named.length)
|
|
191
|
+
out.push(["Agents", named.slice(0, 5).join(", ") + (named.length > 5 ? ", ..." : "")]);
|
|
192
|
+
const decisions = of("policy.decision").map((e) => e.data?.decision);
|
|
193
|
+
out.push(["Tool calls", `${decisions.length} decided` + (decisions.length ? ": " + ["allow", "deny", "ask"]
|
|
194
|
+
.map((d) => `${decisions.filter((x) => x === d).length} ${d}`).join(", ") : "")]);
|
|
195
|
+
const answers = new Map(of("approval").map((e) => [e.data?.approval_id, e.data]));
|
|
196
|
+
const held = of("approval.request").map((e) => {
|
|
197
|
+
const a = answers.get(e.data?.approval_id);
|
|
198
|
+
const who = a ? `${a.decision === "approve" ? "approved" : a.decision === "reject" ? "rejected" : a.decision} by `
|
|
199
|
+
+ `${a.person ?? a.approver}` + (a.approver_kind === "agent" ? " (an agent)" : "")
|
|
200
|
+
+ (a.self_approved ? " (self-approved)" : "") + (a.break_glass ? " (break-glass)" : "") : "no answer recorded";
|
|
201
|
+
const tool = e.data?.binding?.tool ?? e.tool_call_id;
|
|
202
|
+
return `${tool == null ? "a call" : JSON.stringify(String(tool))}: ${who}`;
|
|
203
|
+
});
|
|
204
|
+
out.push(["Held for approval", held.length ? held.slice(0, 10).join("; ") + (held.length > 10 ? "; ..." : "") : "none"]);
|
|
205
|
+
const gaps = new Map();
|
|
206
|
+
for (const e of of("capture.gap"))
|
|
207
|
+
gaps.set(e.data?.kind, (gaps.get(e.data?.kind) ?? 0) + 1);
|
|
208
|
+
out.push(["Gaps", gaps.size ? [...gaps].map(([k, n]) => `${k} ${n}`).join(", ") : "none recorded"]);
|
|
209
|
+
const findings = ["reviews", "incidents"].map((n) => rep.checks.find((c) => c.check === n)?.detail).filter(Boolean);
|
|
210
|
+
out.push(["Findings", findings.length ? findings.join("; ") : "none recorded"]);
|
|
211
|
+
return out.map(([k, v]) => [k, clean(v)]);
|
|
212
|
+
}
|