@lannguyensi/harness 0.50.0 → 0.52.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.
Files changed (81) hide show
  1. package/CHANGELOG.md +247 -0
  2. package/dist/cli/approve/understanding.d.ts +97 -0
  3. package/dist/cli/approve/understanding.js +67 -24
  4. package/dist/cli/approve/understanding.js.map +1 -1
  5. package/dist/cli/audit.d.ts +29 -0
  6. package/dist/cli/audit.js +130 -17
  7. package/dist/cli/audit.js.map +1 -1
  8. package/dist/cli/delegate/index.d.ts +63 -0
  9. package/dist/cli/delegate/index.js +313 -0
  10. package/dist/cli/delegate/index.js.map +1 -0
  11. package/dist/cli/doctor/auto-approve-mode.d.ts +37 -0
  12. package/dist/cli/doctor/auto-approve-mode.js +80 -0
  13. package/dist/cli/doctor/auto-approve-mode.js.map +1 -0
  14. package/dist/cli/doctor/claude-mcp.d.ts +14 -0
  15. package/dist/cli/doctor/claude-mcp.js +7 -1
  16. package/dist/cli/doctor/claude-mcp.js.map +1 -1
  17. package/dist/cli/doctor/codex-config-drift.d.ts +28 -0
  18. package/dist/cli/doctor/codex-config-drift.js +240 -0
  19. package/dist/cli/doctor/codex-config-drift.js.map +1 -0
  20. package/dist/cli/doctor/format.js +67 -1
  21. package/dist/cli/doctor/format.js.map +1 -1
  22. package/dist/cli/doctor/index.d.ts +20 -0
  23. package/dist/cli/doctor/index.js +84 -1
  24. package/dist/cli/doctor/index.js.map +1 -1
  25. package/dist/cli/doctor/settings-drift.d.ts +25 -0
  26. package/dist/cli/doctor/settings-drift.js +203 -0
  27. package/dist/cli/doctor/settings-drift.js.map +1 -0
  28. package/dist/cli/doctor/types.d.ts +69 -0
  29. package/dist/cli/doctor/types.js.map +1 -1
  30. package/dist/cli/doctor/ug-auto-approvals.d.ts +40 -0
  31. package/dist/cli/doctor/ug-auto-approvals.js +116 -0
  32. package/dist/cli/doctor/ug-auto-approvals.js.map +1 -0
  33. package/dist/cli/doctor/ug-delegations.d.ts +26 -0
  34. package/dist/cli/doctor/ug-delegations.js +112 -0
  35. package/dist/cli/doctor/ug-delegations.js.map +1 -0
  36. package/dist/cli/doctor/understanding-mode-env.d.ts +12 -0
  37. package/dist/cli/doctor/understanding-mode-env.js +16 -1
  38. package/dist/cli/doctor/understanding-mode-env.js.map +1 -1
  39. package/dist/cli/index.js +100 -1
  40. package/dist/cli/index.js.map +1 -1
  41. package/dist/cli/pack/approve-escape.js +16 -7
  42. package/dist/cli/pack/approve-escape.js.map +1 -1
  43. package/dist/cli/pack/auto-approve-path.d.ts +135 -0
  44. package/dist/cli/pack/auto-approve-path.js +400 -0
  45. package/dist/cli/pack/auto-approve-path.js.map +1 -0
  46. package/dist/cli/pack/hook-codex-pre-tool-use.d.ts +9 -0
  47. package/dist/cli/pack/hook-codex-pre-tool-use.js +118 -4
  48. package/dist/cli/pack/hook-codex-pre-tool-use.js.map +1 -1
  49. package/dist/cli/pack/hook-pre-tool-use.d.ts +36 -0
  50. package/dist/cli/pack/hook-pre-tool-use.js +402 -3
  51. package/dist/cli/pack/hook-pre-tool-use.js.map +1 -1
  52. package/dist/cli/pack/transcript-report-scan.d.ts +71 -0
  53. package/dist/cli/pack/transcript-report-scan.js +359 -0
  54. package/dist/cli/pack/transcript-report-scan.js.map +1 -0
  55. package/dist/cli/smoke/index.d.ts +18 -1
  56. package/dist/cli/smoke/index.js +54 -0
  57. package/dist/cli/smoke/index.js.map +1 -1
  58. package/dist/cli/validate/checks.js +81 -0
  59. package/dist/cli/validate/checks.js.map +1 -1
  60. package/dist/policy-packs/builtin/understanding-before-execution/auto-approve.d.ts +210 -0
  61. package/dist/policy-packs/builtin/understanding-before-execution/auto-approve.js +361 -0
  62. package/dist/policy-packs/builtin/understanding-before-execution/auto-approve.js.map +1 -0
  63. package/dist/policy-packs/builtin/understanding-before-execution/delegation-markers.d.ts +223 -0
  64. package/dist/policy-packs/builtin/understanding-before-execution/delegation-markers.js +633 -0
  65. package/dist/policy-packs/builtin/understanding-before-execution/delegation-markers.js.map +1 -0
  66. package/dist/policy-packs/builtin/understanding-before-execution/index.d.ts +3 -1
  67. package/dist/policy-packs/builtin/understanding-before-execution/index.js +10 -1
  68. package/dist/policy-packs/builtin/understanding-before-execution/index.js.map +1 -1
  69. package/dist/policy-packs/builtin/understanding-before-execution/measured-permission-modes.d.ts +29 -0
  70. package/dist/policy-packs/builtin/understanding-before-execution/measured-permission-modes.js +82 -0
  71. package/dist/policy-packs/builtin/understanding-before-execution/measured-permission-modes.js.map +1 -0
  72. package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.d.ts +23 -0
  73. package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.js +29 -0
  74. package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.js.map +1 -1
  75. package/dist/policy-packs/builtin/understanding-before-execution.d.ts +42 -0
  76. package/dist/policy-packs/builtin/understanding-before-execution.js +56 -1
  77. package/dist/policy-packs/builtin/understanding-before-execution.js.map +1 -1
  78. package/dist/runtime/approval-signing.d.ts +22 -0
  79. package/dist/runtime/approval-signing.js +83 -1
  80. package/dist/runtime/approval-signing.js.map +1 -1
  81. package/package.json +1 -1
@@ -0,0 +1,633 @@
1
+ // Signed DELEGATION markers for `claude -p` child sessions: slice 3 of
2
+ // docs/decisions/2026-08-27-ug-auto-mode-approval.md ("Delegation marker
3
+ // shape", "TTL, cwd, and subagents", "Audit and doctor").
4
+ //
5
+ // A delegation is a PRE-AUTHORIZATION, not an approval. It is key one of
6
+ // the ADR's two-key design: the parent, already approved, hands the child
7
+ // session a signed artifact that supplies the trusted signal and the
8
+ // parent linkage. Key two (the child's own Understanding Report) is
9
+ // checked elsewhere; nothing in this module ever opens a gate on its own.
10
+ //
11
+ // WHY ITS OWN DIRECTORY AND ITS OWN VERIFIER. The file lives at
12
+ // `<generatedDir>/.delegations/<child-sid>`, never in `.approvals/`:
13
+ // keeping pre-authorizations out of the approvals directory keeps every
14
+ // existing marker scan and the doctor `approvedBy`-prefix listing free of
15
+ // artifacts that never opened a gate. `checkApprovalMarker` cannot consume
16
+ // a delegation anyway: the signature is computed over the markerId
17
+ // `delegation-<child-sid>`, so a delegation copied onto `.approvals/<sid>`
18
+ // fails that reader's signature check exactly like a forgery, and an
19
+ // approval marker copied into `.delegations/` fails this module's check
20
+ // for the mirror-image reason. Both directions are pinned by
21
+ // tests/policy-packs/understanding-before-execution-delegation.test.ts.
22
+ //
23
+ // WHY EVERY BINDING TRAVELS INSIDE `approvedBy`. The signing primitive
24
+ // signs exactly the tuple (markerId, approvedAt, approvedBy,
25
+ // reportContentHash) (src/runtime/approval-signing.ts), and adding a
26
+ // signed field would change `canonicalPayload`, which under that module's
27
+ // strict no-migration precedent means a `SIGNING_ALG` bump and forced
28
+ // re-approval on every install. So the delegation packs parent, cwd, task
29
+ // and expiry into `approvedBy`, the one free-text field inside the signed
30
+ // tuple:
31
+ //
32
+ // delegated:<parent-sid>;cwd=<sha256|->;task=<id|->;expires=<iso>[;report=<sha256>]
33
+ //
34
+ // All of it is therefore tamper-evident with no schema change. The cwd is
35
+ // hashed rather than written literally so the file carries no machine
36
+ // path. `approvedAt` records ISSUE time only, never the expiry:
37
+ // `verifyMarkerSignature` rejects a marker with a missing/empty
38
+ // `approvedAt` before it computes any HMAC, so the field must be there,
39
+ // and the marker readers keep no `expiresAt` field for anything to
40
+ // enforce, which is exactly why the lifetime rides in the `expires`
41
+ // segment above and why this module ships its own verifier.
42
+ //
43
+ // FAIL CLOSED THROUGHOUT. Every refusal in `verifyDelegation` carries a
44
+ // distinct reason; no branch turns a missing, malformed, unparseable or
45
+ // unbound delegation into an `ok` result. `parseDelegationApprovedBy`
46
+ // never fills in a default for an absent segment: a delegation whose
47
+ // bindings cannot be read in full is not a delegation.
48
+ import * as fs from "node:fs";
49
+ import * as path from "node:path";
50
+ import { atomicWriteFile } from "../../../io/atomic-write.js";
51
+ import { readRegularFileRejectingSymlink } from "../../../io/read-regular-file.js";
52
+ import { safeJsonParse } from "../../../io/safe-json-parse.js";
53
+ import { sha256Hex, signMarker, signingKeyExists, signingKeyPathFor, verifyMarkerSignature, } from "../../../runtime/approval-signing.js";
54
+ import { rejectMalformedSessionId } from "../../../runtime/reject-malformed-session-id.js";
55
+ /** Directory holding delegation markers, a sibling of `.approvals/` under `generatedDir`. */
56
+ export const DELEGATION_MARKER_DIRNAME = ".delegations";
57
+ /** Prefix of the signed markerId, mirroring `task-<id>` for task markers. */
58
+ const DELEGATION_MARKER_ID_PREFIX = "delegation-";
59
+ /** The `approvedBy` segment carrying the parent linkage. Colon-separated, unlike the `key=value` segments after it. */
60
+ const DELEGATED_SEGMENT_PREFIX = "delegated:";
61
+ /** Literal written for a binding the delegation deliberately leaves open (`cwd=-`, `task=-`). */
62
+ const UNBOUND = "-";
63
+ const SHA256_HEX = /^[0-9a-f]{64}$/;
64
+ // Control characters (including NUL and DEL) are rejected from the parent
65
+ // linkage in both directions: the writer refuses to encode one and the
66
+ // reader refuses to accept one it finds, mirroring `;`/`=`.
67
+ const CONTROL_CHARS = /[\x00-\x1f\x7f]/;
68
+ // Deliberately narrower than `Date.parse`, which accepts plenty of
69
+ // non-ISO input ("March 3 2026") and, worse, timezone-less strings whose
70
+ // meaning depends on the reader's local zone. An expiry must mean the
71
+ // same instant in the parent's process and in the child's.
72
+ const ISO_INSTANT = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/;
73
+ /**
74
+ * The signed markerId for a child session: `delegation-<child-sid>`.
75
+ * Binding it into the signed payload is what stops a validly signed
76
+ * delegation from being copied onto another child id, or onto a session
77
+ * marker's id, and still verifying (`task-markers.ts` precedent).
78
+ */
79
+ export function delegationMarkerIdFor(childSessionId) {
80
+ return `${DELEGATION_MARKER_ID_PREFIX}${childSessionId}`;
81
+ }
82
+ /**
83
+ * Filesystem path of a child session's delegation marker. Rejects a
84
+ * malformed session id the same way `approvalMarkerPathFor` does (the
85
+ * value lands in a `path.join` verbatim).
86
+ */
87
+ export function delegationMarkerPathFor(generatedDir, childSessionId) {
88
+ rejectMalformedSessionId(childSessionId);
89
+ return path.join(generatedDir, DELEGATION_MARKER_DIRNAME, childSessionId);
90
+ }
91
+ /**
92
+ * sha256 hex of a filesystem path, canonicalized through `realpathSync`
93
+ * when the path exists and through `path.resolve` when it does not.
94
+ *
95
+ * The canonicalization is the point, not an optimization: the parent
96
+ * writing the delegation and the child reporting its cwd routinely spell
97
+ * the same directory differently (on macOS `os.tmpdir()` hands out
98
+ * `/var/folders/...` while the process reports `/private/var/folders/...`,
99
+ * because `/var` is a symlink), and an uncanonicalized comparison would
100
+ * refuse a perfectly legitimate delegation. Falling back to `resolve` for
101
+ * a non-existent path keeps the function total: a path that cannot be
102
+ * canonicalized still hashes deterministically, and a delegation bound to
103
+ * it simply will not match a cwd that resolves elsewhere.
104
+ *
105
+ * Named for its primary use; the fallback shape hashes the launcher-
106
+ * supplied report file's PATH with the same function, so that WHERE the
107
+ * parent put the report is part of what was signed.
108
+ */
109
+ export function hashDelegationCwd(targetPath) {
110
+ let canonical;
111
+ try {
112
+ canonical = fs.realpathSync(targetPath);
113
+ }
114
+ catch {
115
+ canonical = path.resolve(targetPath);
116
+ }
117
+ return sha256Hex(canonical);
118
+ }
119
+ function rejectUnsafeSegmentValue(field, value) {
120
+ if (value.length === 0) {
121
+ throw new Error(`${field} is empty`);
122
+ }
123
+ if (value.includes(";") || value.includes("=")) {
124
+ throw new Error(`${field} contains a delegation-segment delimiter (";" or "="): ${JSON.stringify(value)}`);
125
+ }
126
+ }
127
+ function rejectNonSha256(field, value) {
128
+ if (!SHA256_HEX.test(value)) {
129
+ throw new Error(`${field} is not a sha256 hex digest: ${JSON.stringify(value)}`);
130
+ }
131
+ }
132
+ function rejectNonIsoInstant(field, value) {
133
+ if (!ISO_INSTANT.test(value) || !Number.isFinite(Date.parse(value))) {
134
+ throw new Error(`${field} is not an ISO-8601 instant: ${JSON.stringify(value)}`);
135
+ }
136
+ }
137
+ /**
138
+ * Build the `approvedBy` string a delegation signs:
139
+ * `delegated:<parent>;cwd=<sha256|->;task=<id|->;expires=<iso>` plus
140
+ * `;report=<sha256>` in the fallback shape.
141
+ *
142
+ * Throws on any input that would corrupt the encoding (an empty value, a
143
+ * value carrying a `;` or `=` delimiter or a control character, a
144
+ * malformed parent session id (`rejectMalformedSessionId`), a cwd/report
145
+ * hash that is not a sha256 digest, a non-ISO expiry, or the literal `-`
146
+ * as a task id, which would round-trip as "no task bound"). A silently
147
+ * mis-encoded delegation would be signed and then read back with
148
+ * different bindings than the caller intended, so this fails loudly at
149
+ * the only place that can still tell the difference.
150
+ */
151
+ export function buildDelegationApprovedBy(fields) {
152
+ const { parentSessionId, cwdHash, taskId, expiresAt, reportPathHash } = fields;
153
+ // Same shape check the CHILD session id already gets in
154
+ // `delegationMarkerPathFor`: the parent id never reaches a `path.join`
155
+ // here, but it is still a session id, and a value carrying `/`, `\`, or
156
+ // `..` has no business inside a signed audit field either.
157
+ rejectMalformedSessionId(parentSessionId);
158
+ rejectUnsafeSegmentValue("parentSessionId", parentSessionId);
159
+ if (CONTROL_CHARS.test(parentSessionId)) {
160
+ throw new Error(`parentSessionId contains a control character: ${JSON.stringify(parentSessionId)}`);
161
+ }
162
+ if (cwdHash !== null)
163
+ rejectNonSha256("cwdHash", cwdHash);
164
+ if (taskId !== null) {
165
+ rejectUnsafeSegmentValue("taskId", taskId);
166
+ if (taskId === UNBOUND) {
167
+ throw new Error(`taskId is the reserved unbound literal ${JSON.stringify(UNBOUND)}`);
168
+ }
169
+ }
170
+ rejectNonIsoInstant("expiresAt", expiresAt);
171
+ if (reportPathHash !== undefined)
172
+ rejectNonSha256("reportPathHash", reportPathHash);
173
+ const segments = [
174
+ `${DELEGATED_SEGMENT_PREFIX}${parentSessionId}`,
175
+ `cwd=${cwdHash ?? UNBOUND}`,
176
+ `task=${taskId ?? UNBOUND}`,
177
+ `expires=${expiresAt}`,
178
+ ];
179
+ if (reportPathHash !== undefined) {
180
+ segments.push(`report=${reportPathHash}`);
181
+ }
182
+ return segments.join(";");
183
+ }
184
+ /**
185
+ * Strict inverse of {@link buildDelegationApprovedBy}. All four of
186
+ * `delegated`, `cwd`, `task` and `expires` are required and `report` is
187
+ * optional; a missing, duplicated, unknown, empty or malformed segment is
188
+ * an error RESULT, never a default. Segment order is not enforced (the
189
+ * signature already pins the exact bytes), but every other deviation is
190
+ * refused: this string is the only place a delegation's bindings live, so
191
+ * "read it partially and assume the rest" is the one failure mode that
192
+ * would quietly widen a delegation past what the parent signed.
193
+ */
194
+ export function parseDelegationApprovedBy(approvedBy) {
195
+ if (typeof approvedBy !== "string" || approvedBy.length === 0) {
196
+ return {
197
+ ok: false,
198
+ reason: `approvedBy is not a non-empty string (got ${typeof approvedBy})`,
199
+ };
200
+ }
201
+ let parentSessionId;
202
+ let cwdRaw;
203
+ let taskRaw;
204
+ let expiresRaw;
205
+ let reportRaw;
206
+ for (const segment of approvedBy.split(";")) {
207
+ if (segment.startsWith(DELEGATED_SEGMENT_PREFIX)) {
208
+ if (parentSessionId !== undefined) {
209
+ return { ok: false, reason: `duplicate "delegated" segment` };
210
+ }
211
+ const value = segment.slice(DELEGATED_SEGMENT_PREFIX.length);
212
+ if (value.length === 0) {
213
+ return { ok: false, reason: `empty value for segment "delegated"` };
214
+ }
215
+ // Mirror of the writer's checks (`buildDelegationApprovedBy`): the
216
+ // reader must never accept a parent linkage the writer could not
217
+ // have produced. `;` cannot survive the `split(";")` above without
218
+ // becoming a second, unrecognized segment, but `=` and control
219
+ // characters can, so they are checked explicitly here.
220
+ if (value.includes("=") || CONTROL_CHARS.test(value)) {
221
+ return {
222
+ ok: false,
223
+ reason: `"delegated" value contains "=" or a control character: ${JSON.stringify(value)}`,
224
+ };
225
+ }
226
+ try {
227
+ rejectMalformedSessionId(value);
228
+ }
229
+ catch (err) {
230
+ return {
231
+ ok: false,
232
+ reason: `"delegated" value is not a well-formed session id: ${err instanceof Error ? err.message : String(err)}`,
233
+ };
234
+ }
235
+ parentSessionId = value;
236
+ continue;
237
+ }
238
+ const eq = segment.indexOf("=");
239
+ if (eq <= 0) {
240
+ return { ok: false, reason: `unrecognized delegation segment ${JSON.stringify(segment)}` };
241
+ }
242
+ const key = segment.slice(0, eq);
243
+ const value = segment.slice(eq + 1);
244
+ if (value.length === 0) {
245
+ return { ok: false, reason: `empty value for segment ${JSON.stringify(key)}` };
246
+ }
247
+ switch (key) {
248
+ case "cwd":
249
+ if (cwdRaw !== undefined)
250
+ return { ok: false, reason: `duplicate "cwd" segment` };
251
+ cwdRaw = value;
252
+ break;
253
+ case "task":
254
+ if (taskRaw !== undefined)
255
+ return { ok: false, reason: `duplicate "task" segment` };
256
+ taskRaw = value;
257
+ break;
258
+ case "expires":
259
+ if (expiresRaw !== undefined)
260
+ return { ok: false, reason: `duplicate "expires" segment` };
261
+ expiresRaw = value;
262
+ break;
263
+ case "report":
264
+ if (reportRaw !== undefined)
265
+ return { ok: false, reason: `duplicate "report" segment` };
266
+ reportRaw = value;
267
+ break;
268
+ default:
269
+ return { ok: false, reason: `unknown delegation segment key ${JSON.stringify(key)}` };
270
+ }
271
+ }
272
+ if (parentSessionId === undefined)
273
+ return { ok: false, reason: `missing "delegated" segment` };
274
+ if (cwdRaw === undefined)
275
+ return { ok: false, reason: `missing "cwd" segment` };
276
+ if (taskRaw === undefined)
277
+ return { ok: false, reason: `missing "task" segment` };
278
+ if (expiresRaw === undefined)
279
+ return { ok: false, reason: `missing "expires" segment` };
280
+ let cwdHash = null;
281
+ if (cwdRaw !== UNBOUND) {
282
+ if (!SHA256_HEX.test(cwdRaw)) {
283
+ return { ok: false, reason: `"cwd" is not a sha256 hex digest: ${JSON.stringify(cwdRaw)}` };
284
+ }
285
+ cwdHash = cwdRaw;
286
+ }
287
+ let taskId = null;
288
+ if (taskRaw !== UNBOUND) {
289
+ if (taskRaw.includes("=")) {
290
+ return { ok: false, reason: `"task" contains a segment delimiter: ${JSON.stringify(taskRaw)}` };
291
+ }
292
+ taskId = taskRaw;
293
+ }
294
+ if (!ISO_INSTANT.test(expiresRaw) || !Number.isFinite(Date.parse(expiresRaw))) {
295
+ return {
296
+ ok: false,
297
+ reason: `"expires" is not an ISO-8601 instant: ${JSON.stringify(expiresRaw)}`,
298
+ };
299
+ }
300
+ if (reportRaw !== undefined && !SHA256_HEX.test(reportRaw)) {
301
+ return { ok: false, reason: `"report" is not a sha256 hex digest: ${JSON.stringify(reportRaw)}` };
302
+ }
303
+ const value = {
304
+ parentSessionId,
305
+ cwdHash,
306
+ taskId,
307
+ expiresAt: expiresRaw,
308
+ ...(reportRaw !== undefined ? { reportPathHash: reportRaw } : {}),
309
+ };
310
+ return { ok: true, value };
311
+ }
312
+ /**
313
+ * Write a signed delegation marker through the shared `signMarker` path,
314
+ * under markerId `delegation-<child-sid>`, at
315
+ * `<generatedDir>/.delegations/<child-sid>`. Atomic and mode 0600, like
316
+ * every other marker write.
317
+ *
318
+ * NEVER CREATES THE SIGNING KEY. `signMarker` -> `getOrCreateSigningKey`
319
+ * treats a missing key as a case to REPAIR, generating one and signing
320
+ * with it; key creation is an operator-side act (`harness init`,
321
+ * `harness approve`), and a delegation minted on a machine that never had
322
+ * a key would be a marker signed by whoever asked for it. So this
323
+ * prechecks `signingKeyExists` and returns `signing-key-absent` without
324
+ * reaching the write path at all (ADR threat model (b) item 5, the same
325
+ * rule slice 1's auto path follows).
326
+ *
327
+ * Returns a result rather than throwing, for every failure mode: the
328
+ * callers are a CLI verb and, later, a hook, and both must fail closed
329
+ * with a diagnostic instead of unwinding.
330
+ *
331
+ * Deliberately does NOT refuse a delegation that binds neither cwd nor
332
+ * task. That refusal belongs to the issuing verb (ADR slice 3 acceptance
333
+ * criterion 1) and to `verifyDelegation`, which reports `no_binding`;
334
+ * keeping the writer able to produce one is what lets the test suite
335
+ * exercise that verifier branch against a genuinely signed artifact
336
+ * rather than a hand-rolled fake.
337
+ */
338
+ export function writeDelegationMarker(opts) {
339
+ const reportPathHash = opts.reportPathHash;
340
+ const reportContentHash = opts.reportContentHash ?? null;
341
+ if ((reportPathHash === undefined) !== (reportContentHash === null)) {
342
+ // The fallback shape binds the launcher-supplied report by BOTH its
343
+ // path and its content. Half a binding is worse than none: a `report=`
344
+ // segment with no content hash, or a content hash with no `report=`
345
+ // segment, reads as "bound" to a human and enforces only one half.
346
+ return {
347
+ ok: false,
348
+ reason: "invalid-input",
349
+ detail: "the fallback shape requires reportPathHash AND reportContentHash together (one without the other would leave half the report binding unenforced)",
350
+ };
351
+ }
352
+ if (reportContentHash !== null) {
353
+ try {
354
+ rejectNonSha256("reportContentHash", reportContentHash);
355
+ }
356
+ catch (err) {
357
+ return {
358
+ ok: false,
359
+ reason: "invalid-input",
360
+ detail: err instanceof Error ? err.message : String(err),
361
+ };
362
+ }
363
+ }
364
+ let filePath;
365
+ let approvedBy;
366
+ try {
367
+ filePath = delegationMarkerPathFor(opts.generatedDir, opts.childSessionId);
368
+ approvedBy = buildDelegationApprovedBy({
369
+ parentSessionId: opts.parentSessionId,
370
+ cwdHash: opts.cwdHash,
371
+ taskId: opts.taskId,
372
+ expiresAt: opts.expiresAt,
373
+ reportPathHash,
374
+ });
375
+ }
376
+ catch (err) {
377
+ return {
378
+ ok: false,
379
+ reason: "invalid-input",
380
+ detail: err instanceof Error ? err.message : String(err),
381
+ };
382
+ }
383
+ if (!signingKeyExists(opts.generatedDir)) {
384
+ return {
385
+ ok: false,
386
+ reason: "signing-key-absent",
387
+ detail: `no operator signing key at ${signingKeyPathFor(opts.generatedDir)}; refusing to mint a delegation (key creation is an operator-side act, never a side effect of delegating)`,
388
+ };
389
+ }
390
+ const approvedAt = (opts.now ?? new Date()).toISOString();
391
+ const markerId = delegationMarkerIdFor(opts.childSessionId);
392
+ const signed = signMarker(opts.generatedDir, markerId, {
393
+ approvedAt,
394
+ approvedBy,
395
+ reportContentHash,
396
+ });
397
+ try {
398
+ atomicWriteFile(filePath, `${JSON.stringify(signed, null, 2)}\n`, { mode: 0o600 });
399
+ }
400
+ catch (err) {
401
+ return {
402
+ ok: false,
403
+ reason: "write-failed",
404
+ detail: err instanceof Error ? err.message : String(err),
405
+ };
406
+ }
407
+ return { ok: true, filePath, markerId, approvedAt, approvedBy };
408
+ }
409
+ /**
410
+ * Gate-side: is there a valid, unexpired, matching delegation for this
411
+ * child session? Checks, in order (ADR slice 3 acceptance criterion 2):
412
+ *
413
+ * 1. the file is present and JSON-readable,
414
+ * 2. its signature verifies against markerId `delegation-<child-sid>`,
415
+ * 3. its `approvedBy` segments parse in full,
416
+ * 4. it binds at least one of cwd / task,
417
+ * 5. it has not expired,
418
+ * 6. the bound cwd hash-matches the caller's cwd,
419
+ * 7. the bound task equals the caller's task,
420
+ * 8. in the fallback shape, the launcher report sits at the bound path
421
+ * AND hashes to the bound content.
422
+ *
423
+ * Reads only `.delegations/`; an artifact in `.approvals/` is `missing`
424
+ * here, whatever it contains.
425
+ *
426
+ * NEVER CREATES THE SIGNING KEY, on the READ path either.
427
+ * `verifyMarkerSignature` obtains the key through
428
+ * `getOrCreateSigningKey`, which treats a missing key as a case to
429
+ * REPAIR and generates one; on a machine the operator never initialized
430
+ * that would make a mere gate-time read perform the operator-side act of
431
+ * minting the key. It cannot make a foreign-signed delegation verify, but
432
+ * it does leave a key behind that every LATER write path would then
433
+ * happily sign with, so the never-create rule applies here exactly as it
434
+ * does to `writeDelegationMarker` and to slice 1's auto path. An absent
435
+ * key is reported as `unreadable` (we could not check, not "we checked
436
+ * and it is a forgery"), the same class `verifyMarkerSignature`'s own
437
+ * `key-unavailable` lands in below.
438
+ */
439
+ export function verifyDelegation(opts) {
440
+ const { generatedDir, childSessionId } = opts;
441
+ let filePath;
442
+ try {
443
+ filePath = delegationMarkerPathFor(generatedDir, childSessionId);
444
+ }
445
+ catch (err) {
446
+ // A session id that cannot name a file has no delegation, by
447
+ // construction. Fail closed here rather than throwing out of a hook.
448
+ return {
449
+ ok: false,
450
+ reason: "missing",
451
+ detail: `invalid childSessionId for delegation marker: ${err instanceof Error ? err.message : String(err)}`,
452
+ };
453
+ }
454
+ const read = readRegularFileRejectingSymlink(filePath);
455
+ if (read.kind === "missing") {
456
+ return { ok: false, reason: "missing", detail: `no delegation marker at ${filePath}` };
457
+ }
458
+ if (read.kind === "symlink") {
459
+ return {
460
+ ok: false,
461
+ reason: "unreadable",
462
+ detail: `delegation marker is a symlink, refusing for safety: ${filePath}`,
463
+ };
464
+ }
465
+ if (read.kind === "not-regular") {
466
+ return {
467
+ ok: false,
468
+ reason: "unreadable",
469
+ detail: `delegation marker path is not a regular file: ${filePath}`,
470
+ };
471
+ }
472
+ if (read.kind === "unreadable") {
473
+ return {
474
+ ok: false,
475
+ reason: "unreadable",
476
+ detail: `delegation marker at ${filePath} exists but could not be read (I/O error); treating as no delegation since its signature cannot be verified`,
477
+ };
478
+ }
479
+ const parsed = safeJsonParse(read.content);
480
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
481
+ return {
482
+ ok: false,
483
+ reason: "forged",
484
+ detail: `forged/unsigned delegation rejected: body at ${filePath} is not a JSON object`,
485
+ };
486
+ }
487
+ const body = parsed;
488
+ // Key precheck BEFORE `verifyMarkerSignature`, which would otherwise
489
+ // mint the key it is supposed to require (see the doc comment above).
490
+ // Placed after the file read so a session with no delegation at all
491
+ // still reports `missing` rather than this stronger, misleading reason.
492
+ if (!signingKeyExists(generatedDir)) {
493
+ return {
494
+ ok: false,
495
+ reason: "unreadable",
496
+ detail: `signing key absent at ${signingKeyPathFor(generatedDir)}; the delegation at ${filePath} cannot be verified and no key is created to verify it (key creation is an operator-side act)`,
497
+ };
498
+ }
499
+ const markerId = delegationMarkerIdFor(childSessionId);
500
+ const verification = verifyMarkerSignature(generatedDir, markerId, body);
501
+ if (!verification.ok) {
502
+ if (verification.kind === "key-unavailable") {
503
+ // Fail-closed I/O problem, not evidence of tampering (the same
504
+ // distinction `checkApprovalMarker` draws).
505
+ return {
506
+ ok: false,
507
+ reason: "unreadable",
508
+ detail: `delegation at ${filePath} could not be verified: ${verification.reason}`,
509
+ };
510
+ }
511
+ return {
512
+ ok: false,
513
+ reason: "forged",
514
+ detail: `forged/unsigned delegation rejected: ${verification.reason} (${filePath})`,
515
+ };
516
+ }
517
+ const segments = parseDelegationApprovedBy(body["approvedBy"]);
518
+ if (!segments.ok) {
519
+ return {
520
+ ok: false,
521
+ reason: "unparseable",
522
+ detail: `delegation at ${filePath} has an unparseable approvedBy: ${segments.reason}`,
523
+ };
524
+ }
525
+ const { parentSessionId, cwdHash, taskId, expiresAt, reportPathHash } = segments.value;
526
+ if (cwdHash === null && taskId === null) {
527
+ return {
528
+ ok: false,
529
+ reason: "no_binding",
530
+ detail: `delegation at ${filePath} binds neither a cwd nor a task; refusing an unbound pre-authorization`,
531
+ };
532
+ }
533
+ const nowMs = (opts.now ?? new Date()).getTime();
534
+ const expiresMs = Date.parse(expiresAt);
535
+ // `nowMs` is caller-supplied (`opts.now`, a test-only override); an
536
+ // invalid Date's `.getTime()` is NaN, and NaN fails every `<=`
537
+ // comparison, which would otherwise fail this check OPEN (a clock that
538
+ // cannot report the time would silently pass every delegation as
539
+ // unexpired). Fail closed instead: an unusable clock is treated the same
540
+ // as an already-expired one.
541
+ if (!Number.isFinite(nowMs) || expiresMs <= nowMs) {
542
+ return {
543
+ ok: false,
544
+ reason: "expired",
545
+ detail: Number.isFinite(nowMs)
546
+ ? `delegation at ${filePath} expired at ${expiresAt} (now ${new Date(nowMs).toISOString()})`
547
+ : `delegation at ${filePath} cannot be checked for expiry: the supplied clock is unusable (now getTime() => ${nowMs})`,
548
+ };
549
+ }
550
+ if (cwdHash !== null) {
551
+ if (opts.cwd === null) {
552
+ return {
553
+ ok: false,
554
+ reason: "cwd_mismatch",
555
+ detail: `delegation at ${filePath} is bound to a cwd but the caller supplied none`,
556
+ };
557
+ }
558
+ const actual = hashDelegationCwd(opts.cwd);
559
+ if (actual !== cwdHash) {
560
+ return {
561
+ ok: false,
562
+ reason: "cwd_mismatch",
563
+ detail: `delegation at ${filePath} is bound to a different cwd (bound ${cwdHash}, got ${actual} for ${opts.cwd})`,
564
+ };
565
+ }
566
+ }
567
+ if (taskId !== null) {
568
+ if (opts.taskId === null) {
569
+ return {
570
+ ok: false,
571
+ reason: "task_mismatch",
572
+ detail: `delegation at ${filePath} is bound to task ${taskId} but the caller supplied none`,
573
+ };
574
+ }
575
+ if (opts.taskId !== taskId) {
576
+ return {
577
+ ok: false,
578
+ reason: "task_mismatch",
579
+ detail: `delegation at ${filePath} is bound to task ${taskId}, not ${opts.taskId}`,
580
+ };
581
+ }
582
+ }
583
+ if (reportPathHash !== undefined) {
584
+ if (opts.launcherReportPath === undefined) {
585
+ return {
586
+ ok: false,
587
+ reason: "report_path_mismatch",
588
+ detail: `delegation at ${filePath} binds a launcher-supplied report but no report path was offered`,
589
+ };
590
+ }
591
+ const actualPathHash = hashDelegationCwd(opts.launcherReportPath);
592
+ if (actualPathHash !== reportPathHash) {
593
+ return {
594
+ ok: false,
595
+ reason: "report_path_mismatch",
596
+ detail: `delegation at ${filePath} binds a report at a different path (bound ${reportPathHash}, got ${actualPathHash} for ${opts.launcherReportPath})`,
597
+ };
598
+ }
599
+ const boundContentHash = typeof body["reportContentHash"] === "string" ? body["reportContentHash"] : null;
600
+ if (boundContentHash === null) {
601
+ return {
602
+ ok: false,
603
+ reason: "report_content_mismatch",
604
+ detail: `delegation at ${filePath} carries a report path binding but no reportContentHash to check the file against`,
605
+ };
606
+ }
607
+ const reportRead = readRegularFileRejectingSymlink(opts.launcherReportPath);
608
+ if (reportRead.kind !== "ok") {
609
+ return {
610
+ ok: false,
611
+ reason: "report_content_mismatch",
612
+ detail: `launcher-supplied report at ${opts.launcherReportPath} could not be read (${reportRead.kind}); its content cannot be checked against the bound hash`,
613
+ };
614
+ }
615
+ const actualContentHash = sha256Hex(reportRead.content);
616
+ if (actualContentHash !== boundContentHash) {
617
+ return {
618
+ ok: false,
619
+ reason: "report_content_mismatch",
620
+ detail: `launcher-supplied report at ${opts.launcherReportPath} does not match the bound content hash (bound ${boundContentHash}, got ${actualContentHash})`,
621
+ };
622
+ }
623
+ }
624
+ return {
625
+ ok: true,
626
+ parentSessionId,
627
+ expiresAt,
628
+ boundCwdHash: cwdHash,
629
+ boundTaskId: taskId,
630
+ ...(reportPathHash !== undefined ? { reportPathHash } : {}),
631
+ };
632
+ }
633
+ //# sourceMappingURL=delegation-markers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegation-markers.js","sourceRoot":"","sources":["../../../../src/policy-packs/builtin/understanding-before-execution/delegation-markers.ts"],"names":[],"mappings":"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"}