@cygnuxlabs/tracekit 1.2.3 → 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/client.d.ts +3 -0
- package/dist/v2/client.js +9 -3
- 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 +267 -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 +11 -7
package/dist/verify/jcs.d.ts
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* integer tokens (no `.` or exponent) outside ±(2^53-1) are refused, and so are arrays and objects nested deeper than
|
|
5
5
|
* MAX_DEPTH. No node: imports: browsers load this too.
|
|
6
6
|
*/
|
|
7
|
+
/** A string as Python's repr() writes it, as the reference verifier's messages quote names and keys. */
|
|
8
|
+
export declare function repr(s: string): string;
|
|
7
9
|
/** `code` is one of: invalid_utf8, syntax, duplicate_key, non_finite, int_range, lone_surrogate, depth. */
|
|
8
10
|
export declare class StrictJSONError extends Error {
|
|
9
11
|
readonly code: string;
|
package/dist/verify/jcs.js
CHANGED
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
* integer tokens (no `.` or exponent) outside ±(2^53-1) are refused, and so are arrays and objects nested deeper than
|
|
5
5
|
* MAX_DEPTH. No node: imports: browsers load this too.
|
|
6
6
|
*/
|
|
7
|
+
/** A string as Python's repr() writes it, as the reference verifier's messages quote names and keys. */
|
|
8
|
+
export function repr(s) {
|
|
9
|
+
const q = s.includes("'") && !s.includes('"') ? '"' : "'";
|
|
10
|
+
const named = { "\\": "\\\\", "\n": "\\n", "\r": "\\r", "\t": "\\t", [q]: "\\" + q };
|
|
11
|
+
// lean: control characters only; Python also escapes other code points it can't print (U+0080..U+009F, U+2028...)
|
|
12
|
+
return q + s.replace(/[\\'"\x00-\x1f\x7f]/g, (c) => named[c] ?? (c === "'" || c === '"' ? c
|
|
13
|
+
: "\\x" + c.charCodeAt(0).toString(16).padStart(2, "0"))) + q;
|
|
14
|
+
}
|
|
7
15
|
/** `code` is one of: invalid_utf8, syntax, duplicate_key, non_finite, int_range, lone_surrogate, depth. */
|
|
8
16
|
export class StrictJSONError extends Error {
|
|
9
17
|
code;
|
|
@@ -62,7 +70,7 @@ export function strictParse(text, floats) {
|
|
|
62
70
|
match(WS);
|
|
63
71
|
const c = text[i];
|
|
64
72
|
if ((c === "{" || c === "[") && depth === MAX_DEPTH)
|
|
65
|
-
fail("depth", `nesting deeper than ${MAX_DEPTH}
|
|
73
|
+
fail("depth", `nesting deeper than ${MAX_DEPTH}`);
|
|
66
74
|
if (c === "{") {
|
|
67
75
|
i++;
|
|
68
76
|
const o = {};
|
|
@@ -73,7 +81,7 @@ export function strictParse(text, floats) {
|
|
|
73
81
|
match(WS);
|
|
74
82
|
const k = str();
|
|
75
83
|
if (Object.hasOwn(o, k))
|
|
76
|
-
fail("duplicate_key",
|
|
84
|
+
fail("duplicate_key", repr(k));
|
|
77
85
|
expect(":");
|
|
78
86
|
Object.defineProperty(o, k, { value: value(depth + 1), enumerable: true, writable: true, configurable: true }); // "__proto__" too
|
|
79
87
|
mark(o, k);
|
|
@@ -47,8 +47,9 @@ export type Note = {
|
|
|
47
47
|
/**
|
|
48
48
|
* Open a checkpoint note with pinned vkeys: a pinned Ed25519 log key named after the origin must sign it, and each
|
|
49
49
|
* pinned hybrid key of the origin must have a line. Web Crypto has no SLH-DSA, so a hybrid line is left `unchecked`.
|
|
50
|
+
* `anchored` false (no trust config, so `logKeys` is empty): no log signature is required.
|
|
50
51
|
*/
|
|
51
|
-
export declare function openNote(data: Uint8Array, logKeys: string[], witnessKeys: string[]): Promise<Note>;
|
|
52
|
+
export declare function openNote(data: Uint8Array, logKeys: string[], witnessKeys: string[], anchored?: boolean): Promise<Note>;
|
|
52
53
|
export declare const LEAF_TYPES: string[];
|
|
53
54
|
export declare const SIGNER_LEAVES: string[];
|
|
54
55
|
export declare const registryOrigin: (logOrigin: string, tsalt: Uint8Array) => Promise<string>;
|
|
@@ -194,8 +194,9 @@ export async function parseVkey(text) {
|
|
|
194
194
|
/**
|
|
195
195
|
* Open a checkpoint note with pinned vkeys: a pinned Ed25519 log key named after the origin must sign it, and each
|
|
196
196
|
* pinned hybrid key of the origin must have a line. Web Crypto has no SLH-DSA, so a hybrid line is left `unchecked`.
|
|
197
|
+
* `anchored` false (no trust config, so `logKeys` is empty): no log signature is required.
|
|
197
198
|
*/
|
|
198
|
-
export async function openNote(data, logKeys, witnessKeys) {
|
|
199
|
+
export async function openNote(data, logKeys, witnessKeys, anchored = true) {
|
|
199
200
|
if (data.length > MAX_NOTE)
|
|
200
201
|
throw new NoteError("note too large");
|
|
201
202
|
let note;
|
|
@@ -279,7 +280,7 @@ export async function openNote(data, logKeys, witnessKeys) {
|
|
|
279
280
|
cosigs.push([k, ts]);
|
|
280
281
|
}
|
|
281
282
|
}
|
|
282
|
-
if (!logged)
|
|
283
|
+
if (!logged && anchored)
|
|
283
284
|
throw new NoteError(`no signature from a pinned log key for origin ${origin}`);
|
|
284
285
|
if (hybrids.size)
|
|
285
286
|
throw new NoteError(`no SLH-DSA signature from the pinned hybrid key for origin ${origin}`);
|
package/dist/verify/schema.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The JSON Schema 2020-12 subset tracekit.event.v2.json uses (docs/format-v2.md §3): type, const, enum, required,
|
|
3
|
-
* properties, additionalProperties, items, oneOf, allOf, if/then, $ref to #/$defs, pattern (full match,
|
|
4
|
-
* minimum, maximum, minLength, maxLength (code points), minItems, maxItems. "integer" excludes number tokens
|
|
5
|
-
* fraction or exponent. Any other keyword throws, so the schema can't silently lose a check.
|
|
3
|
+
* properties, additionalProperties, propertyNames, items, oneOf, allOf, if/then, $ref to #/$defs, pattern (full match,
|
|
4
|
+
* ASCII), minimum, maximum, minLength, maxLength (code points), minItems, maxItems. "integer" excludes number tokens
|
|
5
|
+
* written with a fraction or exponent. Any other keyword throws, so the schema can't silently lose a check.
|
|
6
6
|
*/
|
|
7
7
|
import type { Floats } from "./jcs.js";
|
|
8
8
|
/** JSON equality with numbers and booleans compared as numbers, as the reference's Python does. */
|
package/dist/verify/schema.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import SCHEMA from "./tracekit.event.v2.json" with { type: "json" };
|
|
2
|
-
const KEYWORDS = new Set(["type", "const", "enum", "required", "properties", "additionalProperties", "
|
|
3
|
-
"allOf", "if", "then", "$ref", "pattern", "minimum", "maximum", "minLength", "maxLength", "minItems",
|
|
4
|
-
"$defs", "title", "description"]);
|
|
2
|
+
const KEYWORDS = new Set(["type", "const", "enum", "required", "properties", "additionalProperties", "propertyNames",
|
|
3
|
+
"items", "oneOf", "allOf", "if", "then", "$ref", "pattern", "minimum", "maximum", "minLength", "maxLength", "minItems",
|
|
4
|
+
"maxItems", "$schema", "$id", "$defs", "title", "description"]);
|
|
5
5
|
const isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
6
6
|
const isNumber = (v) => typeof v === "number";
|
|
7
7
|
const PATTERNS = new Map();
|
|
@@ -68,6 +68,8 @@ function check(v, s, path, errs, float, floats) {
|
|
|
68
68
|
errs.push(`${path}: unexpected field '${k}'`);
|
|
69
69
|
else if (isObject(ap))
|
|
70
70
|
check(x, ap, `${path}.${k}`, errs, f, floats);
|
|
71
|
+
if ("propertyNames" in s)
|
|
72
|
+
check(k, s.propertyNames, `${path}.${k}`, errs, false, floats);
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
if (Array.isArray(v) && "items" in s)
|
|
@@ -126,6 +126,7 @@
|
|
|
126
126
|
"reconcile.result_without_call",
|
|
127
127
|
"reconcile.unexplained_effect",
|
|
128
128
|
"reconcile.args_unparseable",
|
|
129
|
+
"reconcile.result_mismatch",
|
|
129
130
|
"refusal.summary",
|
|
130
131
|
"policy.external",
|
|
131
132
|
"content.accessed",
|
|
@@ -141,7 +142,9 @@
|
|
|
141
142
|
"incident.resolved",
|
|
142
143
|
"incident.response",
|
|
143
144
|
"identity.suspension",
|
|
144
|
-
"effect.observed"
|
|
145
|
+
"effect.observed",
|
|
146
|
+
"constraint.added",
|
|
147
|
+
"ext"
|
|
145
148
|
]
|
|
146
149
|
},
|
|
147
150
|
"data": {
|
|
@@ -283,6 +286,13 @@
|
|
|
283
286
|
"maxLength": 128,
|
|
284
287
|
"pattern": "^[A-Za-z0-9._-]+@[A-Za-z0-9._+-]+$",
|
|
285
288
|
"description": "Policy engine id@version."
|
|
289
|
+
},
|
|
290
|
+
"ext": {
|
|
291
|
+
"type": "object",
|
|
292
|
+
"propertyNames": {
|
|
293
|
+
"$ref": "#/$defs/ext_name"
|
|
294
|
+
},
|
|
295
|
+
"description": "Non-critical fields (format 1.4), on any record: {name: any strict JSON value}. A verifier that does not interpret a name still checks the record's signature, chain and inclusion, and says it did not interpret the name (docs/format-v2.md section 9)."
|
|
286
296
|
}
|
|
287
297
|
},
|
|
288
298
|
"allOf": [
|
|
@@ -894,6 +904,22 @@
|
|
|
894
904
|
}
|
|
895
905
|
}
|
|
896
906
|
},
|
|
907
|
+
{
|
|
908
|
+
"if": {
|
|
909
|
+
"properties": {
|
|
910
|
+
"type": {
|
|
911
|
+
"const": "reconcile.result_mismatch"
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
},
|
|
915
|
+
"then": {
|
|
916
|
+
"properties": {
|
|
917
|
+
"data": {
|
|
918
|
+
"$ref": "#/$defs/reconcile"
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
},
|
|
897
923
|
{
|
|
898
924
|
"if": {
|
|
899
925
|
"properties": {
|
|
@@ -1145,7 +1171,46 @@
|
|
|
1145
1171
|
"then": {
|
|
1146
1172
|
"properties": {
|
|
1147
1173
|
"data": {
|
|
1148
|
-
"
|
|
1174
|
+
"oneOf": [
|
|
1175
|
+
{
|
|
1176
|
+
"$ref": "#/$defs/effect_observed"
|
|
1177
|
+
},
|
|
1178
|
+
{
|
|
1179
|
+
"$ref": "#/$defs/sensor_effect"
|
|
1180
|
+
}
|
|
1181
|
+
]
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
"if": {
|
|
1188
|
+
"properties": {
|
|
1189
|
+
"type": {
|
|
1190
|
+
"const": "constraint.added"
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
},
|
|
1194
|
+
"then": {
|
|
1195
|
+
"properties": {
|
|
1196
|
+
"data": {
|
|
1197
|
+
"$ref": "#/$defs/constraint_added"
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
},
|
|
1202
|
+
{
|
|
1203
|
+
"if": {
|
|
1204
|
+
"properties": {
|
|
1205
|
+
"type": {
|
|
1206
|
+
"const": "ext"
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
},
|
|
1210
|
+
"then": {
|
|
1211
|
+
"properties": {
|
|
1212
|
+
"data": {
|
|
1213
|
+
"$ref": "#/$defs/ext"
|
|
1149
1214
|
}
|
|
1150
1215
|
}
|
|
1151
1216
|
}
|
|
@@ -1990,6 +2055,29 @@
|
|
|
1990
2055
|
},
|
|
1991
2056
|
"verdict": {
|
|
1992
2057
|
"type": "object"
|
|
2058
|
+
},
|
|
2059
|
+
"cites": {
|
|
2060
|
+
"type": "array",
|
|
2061
|
+
"maxItems": 256,
|
|
2062
|
+
"items": {
|
|
2063
|
+
"type": "object",
|
|
2064
|
+
"additionalProperties": false,
|
|
2065
|
+
"required": [
|
|
2066
|
+
"run_seq",
|
|
2067
|
+
"hash"
|
|
2068
|
+
],
|
|
2069
|
+
"properties": {
|
|
2070
|
+
"run_seq": {
|
|
2071
|
+
"type": "integer",
|
|
2072
|
+
"minimum": 0,
|
|
2073
|
+
"maximum": 9007199254740991
|
|
2074
|
+
},
|
|
2075
|
+
"hash": {
|
|
2076
|
+
"$ref": "#/$defs/hash"
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
},
|
|
2080
|
+
"description": "A signed finding (format 1.4; review_finding), in a findings run: the records of the analysed run it rests on, by run_seq and record hash. A review without cites (a migrated v1 judge verdict) is imported, not checked."
|
|
1993
2081
|
}
|
|
1994
2082
|
}
|
|
1995
2083
|
},
|
|
@@ -2121,7 +2209,9 @@
|
|
|
2121
2209
|
"reask_after_reject",
|
|
2122
2210
|
"held_call_unresolved",
|
|
2123
2211
|
"observer_lost",
|
|
2124
|
-
"effect_outside_run"
|
|
2212
|
+
"effect_outside_run",
|
|
2213
|
+
"result_unchecked",
|
|
2214
|
+
"constraint_refused"
|
|
2125
2215
|
],
|
|
2126
2216
|
"description": "Gap and tamper kinds (signer-written only)."
|
|
2127
2217
|
},
|
|
@@ -2135,6 +2225,14 @@
|
|
|
2135
2225
|
"null"
|
|
2136
2226
|
],
|
|
2137
2227
|
"maxLength": 4096
|
|
2228
|
+
},
|
|
2229
|
+
"sensor": {
|
|
2230
|
+
"enum": [
|
|
2231
|
+
"tetragon",
|
|
2232
|
+
"falco",
|
|
2233
|
+
"openshell"
|
|
2234
|
+
],
|
|
2235
|
+
"description": "format 1.4: the sensor (a kernel sensor, or OpenShell) whose import an observer_lost gap is about"
|
|
2138
2236
|
}
|
|
2139
2237
|
}
|
|
2140
2238
|
},
|
|
@@ -2322,6 +2420,10 @@
|
|
|
2322
2420
|
},
|
|
2323
2421
|
"maxItems": 1024
|
|
2324
2422
|
},
|
|
2423
|
+
"said_only": {
|
|
2424
|
+
"const": true,
|
|
2425
|
+
"description": "format 1.4: a response recorded with what the model said and without the calls it asked for (a harness whose hooks name no call); reconciliation reads no call from it"
|
|
2426
|
+
},
|
|
2325
2427
|
"tool_results_sent": {
|
|
2326
2428
|
"type": "array",
|
|
2327
2429
|
"items": {
|
|
@@ -2693,6 +2795,11 @@
|
|
|
2693
2795
|
"type": "integer",
|
|
2694
2796
|
"minimum": 1,
|
|
2695
2797
|
"maximum": 9007199254740991
|
|
2798
|
+
},
|
|
2799
|
+
"result_mismatch": {
|
|
2800
|
+
"type": "integer",
|
|
2801
|
+
"minimum": 1,
|
|
2802
|
+
"maximum": 9007199254740991
|
|
2696
2803
|
}
|
|
2697
2804
|
}
|
|
2698
2805
|
}
|
|
@@ -4503,6 +4610,117 @@
|
|
|
4503
4610
|
}
|
|
4504
4611
|
}
|
|
4505
4612
|
},
|
|
4613
|
+
"sensor_effect": {
|
|
4614
|
+
"type": "object",
|
|
4615
|
+
"additionalProperties": false,
|
|
4616
|
+
"required": [
|
|
4617
|
+
"observer",
|
|
4618
|
+
"sensor",
|
|
4619
|
+
"kind",
|
|
4620
|
+
"ts",
|
|
4621
|
+
"pid",
|
|
4622
|
+
"binary",
|
|
4623
|
+
"attribution"
|
|
4624
|
+
],
|
|
4625
|
+
"description": "format 1.4: what a kernel sensor (Tetragon, Falco) reported a process of the run did, or what OpenShell reported of its sandbox (its connections allowed and blocked, its entrypoint's start), imported under the import's own signer identity (an observer's assertion); signer-written",
|
|
4626
|
+
"properties": {
|
|
4627
|
+
"observer": {
|
|
4628
|
+
"type": "string",
|
|
4629
|
+
"maxLength": 256,
|
|
4630
|
+
"description": "the import's signer identity (scheme:subject)"
|
|
4631
|
+
},
|
|
4632
|
+
"sensor": {
|
|
4633
|
+
"enum": [
|
|
4634
|
+
"tetragon",
|
|
4635
|
+
"falco",
|
|
4636
|
+
"openshell"
|
|
4637
|
+
]
|
|
4638
|
+
},
|
|
4639
|
+
"kind": {
|
|
4640
|
+
"enum": [
|
|
4641
|
+
"exec",
|
|
4642
|
+
"exit",
|
|
4643
|
+
"connect",
|
|
4644
|
+
"file"
|
|
4645
|
+
],
|
|
4646
|
+
"description": "exec: the process started; exit: it ended; connect: it connected to host:port; file: the sensor's policy selected a file event of it (a write outside the workspace, in the shipped samples)"
|
|
4647
|
+
},
|
|
4648
|
+
"ts": {
|
|
4649
|
+
"type": "string",
|
|
4650
|
+
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{6}Z$",
|
|
4651
|
+
"maxLength": 27
|
|
4652
|
+
},
|
|
4653
|
+
"pid": {
|
|
4654
|
+
"type": "integer",
|
|
4655
|
+
"minimum": 0,
|
|
4656
|
+
"maximum": 4294967295
|
|
4657
|
+
},
|
|
4658
|
+
"binary": {
|
|
4659
|
+
"type": "string",
|
|
4660
|
+
"minLength": 1,
|
|
4661
|
+
"maxLength": 4096
|
|
4662
|
+
},
|
|
4663
|
+
"exec_id": {
|
|
4664
|
+
"type": "string",
|
|
4665
|
+
"minLength": 1,
|
|
4666
|
+
"maxLength": 256,
|
|
4667
|
+
"description": "the sensor's id of the process (Tetragon's exec_id)"
|
|
4668
|
+
},
|
|
4669
|
+
"parent_exec_id": {
|
|
4670
|
+
"type": "string",
|
|
4671
|
+
"minLength": 1,
|
|
4672
|
+
"maxLength": 256,
|
|
4673
|
+
"description": "exec: the sensor's id of the process that started this one (Tetragon's parent_exec_id)"
|
|
4674
|
+
},
|
|
4675
|
+
"args_commitment": {
|
|
4676
|
+
"$ref": "#/$defs/commitment",
|
|
4677
|
+
"description": "commitment to sha256 of the arguments string as the sensor reported it"
|
|
4678
|
+
},
|
|
4679
|
+
"salt_id": {
|
|
4680
|
+
"$ref": "#/$defs/id",
|
|
4681
|
+
"description": "the signer's salt id for this record's commitments (salt label <type>:<salt_id>)"
|
|
4682
|
+
},
|
|
4683
|
+
"status": {
|
|
4684
|
+
"type": "integer",
|
|
4685
|
+
"minimum": 0,
|
|
4686
|
+
"maximum": 4294967295
|
|
4687
|
+
},
|
|
4688
|
+
"signal": {
|
|
4689
|
+
"type": "string",
|
|
4690
|
+
"maxLength": 32
|
|
4691
|
+
},
|
|
4692
|
+
"host": {
|
|
4693
|
+
"type": "string",
|
|
4694
|
+
"minLength": 1,
|
|
4695
|
+
"maxLength": 253
|
|
4696
|
+
},
|
|
4697
|
+
"port": {
|
|
4698
|
+
"type": "integer",
|
|
4699
|
+
"minimum": 0,
|
|
4700
|
+
"maximum": 65535
|
|
4701
|
+
},
|
|
4702
|
+
"path": {
|
|
4703
|
+
"type": "string",
|
|
4704
|
+
"minLength": 1,
|
|
4705
|
+
"maxLength": 4096
|
|
4706
|
+
},
|
|
4707
|
+
"tool_call_id": {
|
|
4708
|
+
"$ref": "#/$defs/id",
|
|
4709
|
+
"description": "the tool call id the process's environment carried (CODEX_TOOL_CALL_ID): the agent's claim, recorded as it came and checked by no signer (TK-X206 checks it)"
|
|
4710
|
+
},
|
|
4711
|
+
"denied": {
|
|
4712
|
+
"const": true,
|
|
4713
|
+
"description": "the sensor (OpenShell's network policy) blocked it"
|
|
4714
|
+
},
|
|
4715
|
+
"attribution": {
|
|
4716
|
+
"enum": [
|
|
4717
|
+
"token",
|
|
4718
|
+
"identity"
|
|
4719
|
+
],
|
|
4720
|
+
"description": "identity: the import mapped the process to the run's owner and the signer picked that owner's latest open run"
|
|
4721
|
+
}
|
|
4722
|
+
}
|
|
4723
|
+
},
|
|
4506
4724
|
"reconcile_effect": {
|
|
4507
4725
|
"type": "object",
|
|
4508
4726
|
"additionalProperties": false,
|
|
@@ -4583,6 +4801,52 @@
|
|
|
4583
4801
|
"description": "the status rests on the operator's posture (signer.yaml), not on anything the signer measured"
|
|
4584
4802
|
}
|
|
4585
4803
|
}
|
|
4804
|
+
},
|
|
4805
|
+
"constraint_added": {
|
|
4806
|
+
"type": "object",
|
|
4807
|
+
"additionalProperties": false,
|
|
4808
|
+
"required": [
|
|
4809
|
+
"kind"
|
|
4810
|
+
],
|
|
4811
|
+
"description": "format 1.4: a live constraint of the run (constraint_add): what the person's request said not to do in the rest of it, as its client reported it (the Claude Code hook, at UserPromptSubmit). From then on the signer raises a call that breaks it to an ask (rule TK-CONSTRAINT) and never lowers a decision, so a made-up constraint can only hold more calls",
|
|
4812
|
+
"properties": {
|
|
4813
|
+
"kind": {
|
|
4814
|
+
"enum": [
|
|
4815
|
+
"keep_away",
|
|
4816
|
+
"only_change",
|
|
4817
|
+
"read_only",
|
|
4818
|
+
"no_push",
|
|
4819
|
+
"no_network"
|
|
4820
|
+
],
|
|
4821
|
+
"description": "keep_away: writes of the file; only_change: writes of any other file; read_only: any write; no_push: a git push; no_network: a call that reaches the network"
|
|
4822
|
+
},
|
|
4823
|
+
"object_commitment": {
|
|
4824
|
+
"$ref": "#/$defs/commitment",
|
|
4825
|
+
"description": "keep_away and only_change: commitment to sha256 of the file's lower-cased basename; never the name"
|
|
4826
|
+
},
|
|
4827
|
+
"salt_id": {
|
|
4828
|
+
"$ref": "#/$defs/id",
|
|
4829
|
+
"description": "the signer's salt id for this record's commitment (salt label <type>:<salt_id>)"
|
|
4830
|
+
}
|
|
4831
|
+
}
|
|
4832
|
+
},
|
|
4833
|
+
"ext_name": {
|
|
4834
|
+
"type": "string",
|
|
4835
|
+
"pattern": "^[a-z][a-z0-9_.-]*$",
|
|
4836
|
+
"maxLength": 64,
|
|
4837
|
+
"description": "The name of a non-critical field or record (format 1.4)."
|
|
4838
|
+
},
|
|
4839
|
+
"ext": {
|
|
4840
|
+
"type": "object",
|
|
4841
|
+
"required": [
|
|
4842
|
+
"name"
|
|
4843
|
+
],
|
|
4844
|
+
"properties": {
|
|
4845
|
+
"name": {
|
|
4846
|
+
"$ref": "#/$defs/ext_name"
|
|
4847
|
+
}
|
|
4848
|
+
},
|
|
4849
|
+
"description": "A non-critical record (format 1.4): its name and any other strict JSON fields, checked as the ext field is."
|
|
4586
4850
|
}
|
|
4587
4851
|
}
|
|
4588
4852
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|