owlrunkit 0.13.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 (128) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +674 -0
  3. package/NOTICE.md +137 -0
  4. package/README.md +44 -0
  5. package/SOURCE.md +10 -0
  6. package/docs/architecture/OWLCODA_RUN_KIT_CONTRACT_V0_1.md +160 -0
  7. package/docs/architecture/OWLCODA_RUN_KIT_CONTRACT_V0_2.md +459 -0
  8. package/integrations/codex/skills/owlcoda-runkit/SKILL.md +408 -0
  9. package/integrations/codex/skills/owlcoda-runkit/agents/openai.yaml +4 -0
  10. package/integrations/codex/skills/owlcoda-runkit/assets/templates/agents-snippet.md +7 -0
  11. package/integrations/codex/skills/owlcoda-runkit/assets/templates/config.json +10 -0
  12. package/integrations/codex/skills/owlcoda-runkit/assets/templates/coverage-adopt-request.json +26 -0
  13. package/integrations/codex/skills/owlcoda-runkit/assets/templates/execution-delivery-packet.json +13 -0
  14. package/integrations/codex/skills/owlcoda-runkit/assets/templates/finalize-request.json +18 -0
  15. package/integrations/codex/skills/owlcoda-runkit/assets/templates/goal-contract.json +11 -0
  16. package/integrations/codex/skills/owlcoda-runkit/assets/templates/profiles.json +9 -0
  17. package/integrations/codex/skills/owlcoda-runkit/assets/templates/ready-for-commit-request.json +11 -0
  18. package/integrations/codex/skills/owlcoda-runkit/assets/templates/resource-preflight-request.json +56 -0
  19. package/integrations/codex/skills/owlcoda-runkit/assets/templates/resume-request.json +10 -0
  20. package/integrations/codex/skills/owlcoda-runkit/assets/templates/snapshot-request.json +23 -0
  21. package/integrations/codex/skills/owlcoda-runkit/assets/templates/verification-context.json +15 -0
  22. package/integrations/codex/skills/owlcoda-runkit/assets/templates/verification-receipt.json +11 -0
  23. package/integrations/codex/skills/owlcoda-runkit/assets/templates/verify-plan-request.json +31 -0
  24. package/integrations/codex/skills/owlcoda-runkit/assets/templates/visual-smoke-request.json +32 -0
  25. package/integrations/codex/skills/owlcoda-runkit/assets/templates/worker-lease.json +7 -0
  26. package/package.json +24 -0
  27. package/packages/attest/LICENSE +674 -0
  28. package/packages/attest/README.md +63 -0
  29. package/packages/attest/cli/owlcoda-attest.mjs +155 -0
  30. package/packages/attest/consumer-surface-v1.json +255 -0
  31. package/packages/attest/distribution-manifest-v1.json +104 -0
  32. package/packages/attest/fixtures/bad/accepted-authority-leak.json +7 -0
  33. package/packages/attest/fixtures/bad/accepted-failed-receipt.json +7 -0
  34. package/packages/attest/fixtures/bad/active-context-binding-mismatch.json +7 -0
  35. package/packages/attest/fixtures/bad/active-source-binding-mismatch.json +7 -0
  36. package/packages/attest/fixtures/bad/context-fingerprint-mismatch.json +7 -0
  37. package/packages/attest/fixtures/bad/duplicate-object-key.json +8 -0
  38. package/packages/attest/fixtures/bad/multiple-active-leaves.json +10 -0
  39. package/packages/attest/fixtures/bad/orphan-replacement.json +7 -0
  40. package/packages/attest/fixtures/bad/root-shape-extra-property.json +8 -0
  41. package/packages/attest/fixtures/bad/source-fingerprint-mismatch.json +7 -0
  42. package/packages/attest/fixtures/good/accepted-replacement-chain.json +59 -0
  43. package/packages/attest/fixtures/good/blocked-single-leaf.json +9 -0
  44. package/packages/attest/fixtures/index.json +90 -0
  45. package/packages/attest/sbom.spdx.json +33 -0
  46. package/packages/attest/schemas/attestation-ref-v1.schema.json +44 -0
  47. package/packages/attest/schemas/attestation-result-v1.schema.json +163 -0
  48. package/packages/attest/schemas/offline-attestation-bundle-v1.schema.json +30 -0
  49. package/packages/attest/schemas/public-verification-bundle-v1.schema.json +74 -0
  50. package/packages/attest/schemas/quick-verification-receipt-v1.schema.json +219 -0
  51. package/packages/attest/schemas/workspace-snapshot-v1.schema.json +135 -0
  52. package/packages/attest/src/canonical.mjs +12 -0
  53. package/packages/attest/src/formal.mjs +762 -0
  54. package/packages/attest/src/index.mjs +113 -0
  55. package/packages/attest/src/offline-bundle.mjs +108 -0
  56. package/packages/attest/src/quick-receipt-contract.mjs +156 -0
  57. package/packages/attest/src/quick.mjs +274 -0
  58. package/packages/attest/src/reference-contract.mjs +64 -0
  59. package/packages/attest/src/reference.mjs +131 -0
  60. package/packages/attest/src/workspace-snapshot.mjs +171 -0
  61. package/registry-release-policy-v1.json +34 -0
  62. package/sbom.spdx.json +39 -0
  63. package/scripts/runkit-contract/acceptance-evidence.mjs +103 -0
  64. package/scripts/runkit-contract/core-contract.mjs +392 -0
  65. package/scripts/runkit-contract/coverage-adoption.mjs +414 -0
  66. package/scripts/runkit-contract/delivery-create.mjs +252 -0
  67. package/scripts/runkit-contract/delivery-selection.mjs +31 -0
  68. package/scripts/runkit-contract/finalize.mjs +790 -0
  69. package/scripts/runkit-contract/inspect-presentation.mjs +183 -0
  70. package/scripts/runkit-contract/install-codex-skill.mjs +239 -0
  71. package/scripts/runkit-contract/lease-lifecycle.mjs +324 -0
  72. package/scripts/runkit-contract/lifecycle-orchestration.mjs +415 -0
  73. package/scripts/runkit-contract/offline-store.mjs +248 -0
  74. package/scripts/runkit-contract/profile-impact.mjs +223 -0
  75. package/scripts/runkit-contract/provenance-common.mjs +153 -0
  76. package/scripts/runkit-contract/quick-attest.mjs +4 -0
  77. package/scripts/runkit-contract/quick-canonical.mjs +41 -0
  78. package/scripts/runkit-contract/quick-metrics.mjs +86 -0
  79. package/scripts/runkit-contract/quick-receipt.mjs +139 -0
  80. package/scripts/runkit-contract/quick-verify.mjs +201 -0
  81. package/scripts/runkit-contract/quick-workspace-snapshot.mjs +3 -0
  82. package/scripts/runkit-contract/ready-for-commit.mjs +188 -0
  83. package/scripts/runkit-contract/receipt-lineage.mjs +332 -0
  84. package/scripts/runkit-contract/registry-adoption-gate.mjs +117 -0
  85. package/scripts/runkit-contract/repair-execution.mjs +997 -0
  86. package/scripts/runkit-contract/resource-preflight.mjs +829 -0
  87. package/scripts/runkit-contract/resume-execution.mjs +569 -0
  88. package/scripts/runkit-contract/runkit-cli.mjs +1214 -0
  89. package/scripts/runkit-contract/schemas/closeout-receipt-v2.schema.json +42 -0
  90. package/scripts/runkit-contract/schemas/core-artifact-v2.schema.json +23 -0
  91. package/scripts/runkit-contract/schemas/core-artifact.schema.json +23 -0
  92. package/scripts/runkit-contract/schemas/coverage-adopt-request-v1.schema.json +66 -0
  93. package/scripts/runkit-contract/schemas/engine-pin-v2.schema.json +14 -0
  94. package/scripts/runkit-contract/schemas/engine-pin.schema.json +14 -0
  95. package/scripts/runkit-contract/schemas/evidence-coverage-index-v1.schema.json +131 -0
  96. package/scripts/runkit-contract/schemas/finalize-request-v1.schema.json +131 -0
  97. package/scripts/runkit-contract/schemas/profiles.schema.json +47 -0
  98. package/scripts/runkit-contract/schemas/project-config-v2.schema.json +13 -0
  99. package/scripts/runkit-contract/schemas/project-config.schema.json +13 -0
  100. package/scripts/runkit-contract/schemas/ready-for-commit-v1.schema.json +26 -0
  101. package/scripts/runkit-contract/schemas/replayable-evidence-v1.schema.json +82 -0
  102. package/scripts/runkit-contract/schemas/resource-preflight-request-v1.schema.json +178 -0
  103. package/scripts/runkit-contract/schemas/resource-preflight-v1.schema.json +153 -0
  104. package/scripts/runkit-contract/schemas/resume-attempt-v1.schema.json +80 -0
  105. package/scripts/runkit-contract/schemas/resume-request-v1.schema.json +77 -0
  106. package/scripts/runkit-contract/schemas/snapshot-v1.schema.json +71 -0
  107. package/scripts/runkit-contract/schemas/verification-context-v1.schema.json +92 -0
  108. package/scripts/runkit-contract/schemas/verification-plan-v1.schema.json +150 -0
  109. package/scripts/runkit-contract/schemas/verification-receipt-v2.schema.json +118 -0
  110. package/scripts/runkit-contract/schemas/verify-plan-request-v1.schema.json +56 -0
  111. package/scripts/runkit-contract/schemas/visual-smoke-request-v1.schema.json +64 -0
  112. package/scripts/runkit-contract/schemas/visual-smoke-result-v1.schema.json +68 -0
  113. package/scripts/runkit-contract/snapshot.mjs +340 -0
  114. package/scripts/runkit-contract/source-fingerprint.mjs +404 -0
  115. package/scripts/runkit-contract/templates/coverage-adopt-request.json +26 -0
  116. package/scripts/runkit-contract/templates/finalize-request.json +18 -0
  117. package/scripts/runkit-contract/templates/goal-contract.json +11 -0
  118. package/scripts/runkit-contract/templates/ready-for-commit-request.json +11 -0
  119. package/scripts/runkit-contract/templates/resource-preflight-request.json +56 -0
  120. package/scripts/runkit-contract/templates/resume-request.json +10 -0
  121. package/scripts/runkit-contract/templates/snapshot-request.json +23 -0
  122. package/scripts/runkit-contract/templates/verify-plan-request.json +31 -0
  123. package/scripts/runkit-contract/templates/visual-smoke-request.json +32 -0
  124. package/scripts/runkit-contract/templates/worker-lease.json +7 -0
  125. package/scripts/runkit-contract/verification-context.mjs +141 -0
  126. package/scripts/runkit-contract/verification-plan.mjs +608 -0
  127. package/scripts/runkit-contract/verification-receipt-gate.mjs +566 -0
  128. package/scripts/runkit-contract/visual-smoke.mjs +410 -0
@@ -0,0 +1,415 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import {
3
+ existsSync,
4
+ lstatSync,
5
+ mkdirSync,
6
+ readFileSync,
7
+ readdirSync,
8
+ realpathSync,
9
+ } from "node:fs";
10
+ import { arch, type } from "node:os";
11
+ import path from "node:path";
12
+
13
+ import { createDeliveryFromLeaseWithinControlTransaction } from "./delivery-create.mjs";
14
+ import { collapseByteIdenticalDeliveryCandidates } from "./delivery-selection.mjs";
15
+ import { runFinalize } from "./finalize.mjs";
16
+ import { withControlTransaction } from "./lease-lifecycle.mjs";
17
+ import {
18
+ loadActiveExecution,
19
+ readJson,
20
+ relativeToWorkspace,
21
+ safeIdentifier,
22
+ safeRelativePath,
23
+ sha256,
24
+ writeJsonExclusiveAtomically,
25
+ } from "./provenance-common.mjs";
26
+ import { validateReceiptLineage } from "./receipt-lineage.mjs";
27
+ import {
28
+ runSnapshot,
29
+ verifySnapshotEvidence,
30
+ verifySnapshotSourceBinding,
31
+ } from "./snapshot.mjs";
32
+ import { verifyDeliveryPacket } from "./source-fingerprint.mjs";
33
+ import { validateVerificationReceiptGate } from "./verification-receipt-gate.mjs";
34
+
35
+ const LOCKFILES = [
36
+ "package-lock.json",
37
+ "pnpm-lock.yaml",
38
+ "yarn.lock",
39
+ "bun.lock",
40
+ "bun.lockb",
41
+ "Cargo.lock",
42
+ "poetry.lock",
43
+ "uv.lock",
44
+ ];
45
+
46
+ function entryExists(filePath) {
47
+ try {
48
+ lstatSync(filePath);
49
+ return true;
50
+ } catch (error) {
51
+ if (error?.code === "ENOENT") return false;
52
+ throw error;
53
+ }
54
+ }
55
+
56
+ function within(root, candidate) {
57
+ const relative = path.relative(root, candidate);
58
+ return relative === ""
59
+ || (relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative));
60
+ }
61
+
62
+ function regularFile(filePath, label) {
63
+ const stat = lstatSync(filePath);
64
+ if (stat.isSymbolicLink() || !stat.isFile()) throw new Error(`${label} must be a regular file, not a symlink.`);
65
+ return realpathSync(filePath);
66
+ }
67
+
68
+ function regularDirectory(directoryPath, label) {
69
+ const stat = lstatSync(directoryPath);
70
+ if (stat.isSymbolicLink() || !stat.isDirectory()) {
71
+ throw new Error(`${label} must be a regular directory, not a symlink.`);
72
+ }
73
+ return realpathSync(directoryPath);
74
+ }
75
+
76
+ function projectTruthDirectory({ workspaceRoot, executionRoot, directoryPath, label }) {
77
+ const real = regularDirectory(directoryPath, label);
78
+ if (real !== path.resolve(directoryPath) || !within(realpathSync(executionRoot), real)) {
79
+ throw new Error(`${label} must remain a real directory inside the execution, without symlinks.`);
80
+ }
81
+ if (!within(realpathSync(workspaceRoot), real)) {
82
+ throw new Error(`${label} escapes the RunKit workspace.`);
83
+ }
84
+ return real;
85
+ }
86
+
87
+ function ensureRegularDirectory(directoryPath, label) {
88
+ if (!entryExists(directoryPath)) mkdirSync(directoryPath);
89
+ return regularDirectory(directoryPath, label);
90
+ }
91
+
92
+ function gitVersion() {
93
+ return execFileSync("git", ["--version"], { encoding: "utf8" })
94
+ .trim()
95
+ .replace(/^git version /, "");
96
+ }
97
+
98
+ export function derivedVerificationContext(workspaceRoot) {
99
+ const lockfiles = LOCKFILES
100
+ .filter(filePath => existsSync(path.join(workspaceRoot, filePath)))
101
+ .map(filePath => ({
102
+ path: filePath,
103
+ sha256: sha256(readFileSync(regularFile(path.join(workspaceRoot, filePath), `Lockfile ${filePath}`))),
104
+ }));
105
+ return {
106
+ schemaVersion: "OwlCodaRunKitVerificationContextV1",
107
+ reusePolicy: "platform_bound",
108
+ platform: { os: type(), arch: arch() },
109
+ toolchains: [
110
+ { name: "git", version: gitVersion() },
111
+ { name: "node", version: process.versions.node },
112
+ ],
113
+ lockfiles,
114
+ fixtures: [],
115
+ services: [],
116
+ environment: [],
117
+ };
118
+ }
119
+
120
+ function requestDirectoryPath(executionRoot, verificationId) {
121
+ const requestsRoot = path.join(executionRoot, "verification-requests");
122
+ if (entryExists(requestsRoot)) {
123
+ const stat = lstatSync(requestsRoot);
124
+ if (stat.isSymbolicLink() || !stat.isDirectory()) {
125
+ throw new Error("Verification requests root must be a regular directory, not a symlink.");
126
+ }
127
+ }
128
+ const outputRoot = path.join(requestsRoot, verificationId);
129
+ if (entryExists(outputRoot)) throw new Error(`verification-id already exists: ${verificationId}`);
130
+ return { requestsRoot, outputRoot };
131
+ }
132
+
133
+ function createRequestDirectory({ requestsRoot, outputRoot }) {
134
+ if (!entryExists(requestsRoot)) mkdirSync(requestsRoot);
135
+ mkdirSync(outputRoot);
136
+ }
137
+
138
+ function reusableDelivery({ workspaceRoot, executionRoot, runId, workItemId }) {
139
+ const deliveryRoot = path.join(executionRoot, "delivery-packets");
140
+ regularDirectory(deliveryRoot, "Delivery packet directory");
141
+ const fresh = [];
142
+ for (const entry of readdirSync(deliveryRoot, { withFileTypes: true })) {
143
+ if (!entry.name.endsWith(".json")) continue;
144
+ if (entry.isSymbolicLink() || !entry.isFile()) {
145
+ throw new Error(`Delivery packet must be a regular file, not a symlink: ${entry.name}`);
146
+ }
147
+ const packetPath = path.join(deliveryRoot, entry.name);
148
+ const packet = readJson(regularFile(packetPath, `Delivery packet ${entry.name}`));
149
+ if (packet.runId !== runId || packet.discovery?.fromLease !== workItemId) continue;
150
+ const sourceGate = verifyDeliveryPacket({ workspaceRoot, packet });
151
+ if (sourceGate.status === "valid") fresh.push({ packetPath, packet, sourceGate });
152
+ }
153
+ const distinct = collapseByteIdenticalDeliveryCandidates(fresh);
154
+ if (distinct.length > 1) {
155
+ throw new Error("Multiple fresh delivery packets require explicit repair before high-level verify.");
156
+ }
157
+ if (distinct.length === 0) return null;
158
+ return {
159
+ status: "delivery_packet_reused",
160
+ exitCode: 0,
161
+ runId,
162
+ deliveryPacketPath: relativeToWorkspace(workspaceRoot, distinct[0].packetPath),
163
+ sourceFingerprint: distinct[0].sourceGate.recomputedFingerprint,
164
+ authorizationGranted: false,
165
+ };
166
+ }
167
+
168
+ function snapshotRequest({ workspaceRoot, packet, verificationId, cwd, commandArgv, context }) {
169
+ const [executable, ...argv] = commandArgv;
170
+ if (!path.isAbsolute(executable)) throw new Error("verify executable after -- must be an absolute path.");
171
+ regularFile(executable, "verify executable");
172
+ const selectedPaths = Object.keys(packet.changedFiles?.wholeFileSha256 ?? {}).sort();
173
+ if (selectedPaths.length === 0) throw new Error("verify requires a non-empty DeliveryPacket.");
174
+ return {
175
+ schemaVersion: "OwlCodaRunKitSnapshotRequestV1",
176
+ snapshotId: `${verificationId}-snapshot`,
177
+ mode: "project",
178
+ targetRoot: workspaceRoot,
179
+ cwd,
180
+ executable,
181
+ argv,
182
+ launcherVersion: "runkit-verify-v1",
183
+ toolVersions: structuredClone(context.toolchains),
184
+ selectedPaths,
185
+ statusMode: "porcelain-v1-z-untracked-all-runkit-excluded",
186
+ verificationContext: context,
187
+ };
188
+ }
189
+
190
+ function runHighLevelVerifyWithinControlTransaction({
191
+ workspaceRoot,
192
+ runId,
193
+ workItemId,
194
+ verificationId,
195
+ cwd = ".",
196
+ commandArgv,
197
+ }) {
198
+ safeIdentifier(verificationId, "verification-id");
199
+ safeRelativePath(cwd, "verify cwd", { allowDot: true });
200
+ if (!Array.isArray(commandArgv) || commandArgv.length === 0) {
201
+ throw new Error("verify requires an exact command after --.");
202
+ }
203
+ const { executionRoot, pinGate } = loadActiveExecution(workspaceRoot, runId);
204
+ if (pinGate.status !== "valid") return { ...pinGate, authorizationGranted: false };
205
+ regularDirectory(executionRoot, "Execution directory");
206
+ for (const [name, label, create] of [
207
+ ["delivery-packets", "Delivery packet directory", false],
208
+ ["snapshots", "Snapshot directory", true],
209
+ ["snapshot-evidence", "Snapshot evidence directory", true],
210
+ ["verification-receipts", "Verification receipts directory", false],
211
+ ]) {
212
+ const directoryPath = path.join(executionRoot, name);
213
+ if (create) ensureRegularDirectory(directoryPath, label);
214
+ else regularDirectory(directoryPath, label);
215
+ }
216
+ const [executable] = commandArgv;
217
+ if (!path.isAbsolute(executable)) throw new Error("verify executable after -- must be an absolute path.");
218
+ regularFile(executable, "verify executable");
219
+ const realCwd = realpathSync(cwd === "." ? workspaceRoot : path.join(workspaceRoot, cwd));
220
+ if (!within(workspaceRoot, realCwd)) throw new Error("verify cwd escapes the workspace through a symlink.");
221
+ for (const outputPath of [
222
+ path.join(executionRoot, "snapshots", `${verificationId}-snapshot.json`),
223
+ path.join(executionRoot, "snapshot-evidence", `${verificationId}-snapshot.stdout`),
224
+ path.join(executionRoot, "snapshot-evidence", `${verificationId}-snapshot.stderr`),
225
+ path.join(executionRoot, "verification-receipts", `${verificationId}-receipt`),
226
+ ]) {
227
+ if (entryExists(outputPath)) throw new Error(`verification-id output already exists: ${verificationId}`);
228
+ }
229
+ const requestPaths = requestDirectoryPath(executionRoot, verificationId);
230
+ const delivery = reusableDelivery({ workspaceRoot, executionRoot, runId, workItemId })
231
+ ?? createDeliveryFromLeaseWithinControlTransaction({
232
+ workspaceRoot,
233
+ runId,
234
+ workItemId,
235
+ packetId: `${verificationId}-delivery`,
236
+ });
237
+ if (!new Set(["delivery_packet_created", "delivery_packet_reused"]).has(delivery.status)) return delivery;
238
+
239
+ const packet = readJson(path.join(workspaceRoot, delivery.deliveryPacketPath));
240
+ const context = derivedVerificationContext(workspaceRoot);
241
+ createRequestDirectory(requestPaths);
242
+ const { outputRoot } = requestPaths;
243
+ const snapshotRequestPath = path.join(outputRoot, "snapshot-request.json");
244
+ const snapshot = snapshotRequest({ workspaceRoot, packet, verificationId, cwd, commandArgv, context });
245
+ writeJsonExclusiveAtomically(snapshotRequestPath, snapshot);
246
+ const snapshotResult = runSnapshot({ workspaceRoot, runId, request: snapshot });
247
+ if (snapshotResult.status !== "snapshot_passed") {
248
+ const savedSnapshot = readJson(path.join(workspaceRoot, snapshotResult.snapshotPath));
249
+ return {
250
+ status: "verification_failed",
251
+ exitCode: 2,
252
+ runId,
253
+ deliveryPacketPath: delivery.deliveryPacketPath,
254
+ snapshotRequestPath: relativeToWorkspace(workspaceRoot, snapshotRequestPath),
255
+ snapshotPath: snapshotResult.snapshotPath,
256
+ commandExitCode: savedSnapshot.command.exitCode,
257
+ nextAllowedAction: "repair_source_or_command_then_verify_with_new_id",
258
+ authorizationGranted: false,
259
+ };
260
+ }
261
+
262
+ const finalizeRequestPath = path.join(outputRoot, "finalize-request.json");
263
+ const finalizeRequest = {
264
+ schemaVersion: "OwlCodaRunKitFinalizeRequestV1",
265
+ receiptId: `${verificationId}-receipt`,
266
+ deliveryPacketPath: delivery.deliveryPacketPath,
267
+ verificationContext: context,
268
+ snapshotPaths: [snapshotResult.snapshotPath],
269
+ };
270
+ writeJsonExclusiveAtomically(finalizeRequestPath, finalizeRequest);
271
+ const finalized = runFinalize({ workspaceRoot, runId, request: finalizeRequest });
272
+ if (finalized.status !== "accepted_passed") return finalized;
273
+ return {
274
+ status: "verified",
275
+ exitCode: 0,
276
+ gateDecision: finalized.status,
277
+ runId,
278
+ deliveryPacketPath: delivery.deliveryPacketPath,
279
+ snapshotRequestPath: relativeToWorkspace(workspaceRoot, snapshotRequestPath),
280
+ snapshotPath: snapshotResult.snapshotPath,
281
+ finalizeRequestPath: relativeToWorkspace(workspaceRoot, finalizeRequestPath),
282
+ receiptPath: finalized.receiptPath,
283
+ gateInputPath: finalized.gateInputPath,
284
+ gateOutputPath: finalized.gateOutputPath,
285
+ activeReceiptSha256: finalized.activeReceiptSha256,
286
+ sourceFingerprint: delivery.sourceFingerprint,
287
+ authorizationGranted: false,
288
+ };
289
+ }
290
+
291
+ export function runHighLevelVerify(options) {
292
+ return withControlTransaction(
293
+ options.workspaceRoot,
294
+ () => runHighLevelVerifyWithinControlTransaction(options),
295
+ );
296
+ }
297
+
298
+ export function activeAcceptedGate({ workspaceRoot, runId }) {
299
+ const { executionRoot, pinGate } = loadActiveExecution(workspaceRoot, runId);
300
+ if (pinGate.status !== "valid") return { ...pinGate, authorizationGranted: false };
301
+ projectTruthDirectory({
302
+ workspaceRoot,
303
+ executionRoot,
304
+ directoryPath: executionRoot,
305
+ label: "Execution directory",
306
+ });
307
+ const receiptsRoot = path.join(executionRoot, "verification-receipts");
308
+ projectTruthDirectory({
309
+ workspaceRoot,
310
+ executionRoot,
311
+ directoryPath: receiptsRoot,
312
+ label: "Verification receipts directory",
313
+ });
314
+ const lineagePath = path.join(receiptsRoot, "receipt-lineage.json");
315
+ if (!existsSync(lineagePath)) throw new Error("Accepted finish requires one active verification gate.");
316
+ regularFile(lineagePath, "Receipt lineage");
317
+ const lineage = readJson(lineagePath);
318
+ const validated = validateReceiptLineage(lineage);
319
+ if (!validated.valid || validated.active?.receipt?.status !== "passed") {
320
+ throw new Error("Accepted finish requires one valid passed active verification gate.");
321
+ }
322
+ if (validated.active.receipt.runId !== runId) {
323
+ throw new Error("Active verification gate belongs to another execution.");
324
+ }
325
+ const receiptId = safeIdentifier(validated.active.receipt.receiptId, "active receiptId");
326
+ const gateInputPath = path.join(
327
+ receiptsRoot,
328
+ receiptId,
329
+ "verification-gate-input.json",
330
+ );
331
+ projectTruthDirectory({
332
+ workspaceRoot,
333
+ executionRoot,
334
+ directoryPath: path.dirname(gateInputPath),
335
+ label: "Active receipt directory",
336
+ });
337
+ regularFile(gateInputPath, "Active verification gate input");
338
+ const gateInput = readJson(gateInputPath);
339
+ const gate = validateVerificationReceiptGate(gateInput);
340
+ if (gate.contractVersion !== "0.2" || gateInput.contractVersion !== "0.2") {
341
+ throw new Error("Accepted finish requires a Contract v0.2 verification gate.");
342
+ }
343
+ if (!gate.accepted || gate.activeReceiptSha256 !== validated.active.receiptSha256) {
344
+ throw new Error("Accepted finish requires one valid passed active verification gate.");
345
+ }
346
+ const deliveryRoot = path.join(executionRoot, "delivery-packets");
347
+ projectTruthDirectory({
348
+ workspaceRoot,
349
+ executionRoot,
350
+ directoryPath: deliveryRoot,
351
+ label: "Delivery packet directory",
352
+ });
353
+ const matchingPackets = [];
354
+ for (const entry of readdirSync(deliveryRoot, { withFileTypes: true })) {
355
+ if (!entry.name.endsWith(".json")) continue;
356
+ if (entry.isSymbolicLink() || !entry.isFile()) {
357
+ throw new Error(`Delivery packet must be a regular file, not a symlink: ${entry.name}`);
358
+ }
359
+ const packetPath = path.join(deliveryRoot, entry.name);
360
+ const packet = readJson(regularFile(packetPath, `Delivery packet ${entry.name}`));
361
+ if (packet.runId === runId
362
+ && packet.sourceFingerprint?.sha256 === validated.active.receipt.sourceFingerprint) {
363
+ matchingPackets.push({ packetPath, packet, sourceGate: verifyDeliveryPacket({ workspaceRoot, packet }) });
364
+ }
365
+ }
366
+ const distinctMatchingPackets = collapseByteIdenticalDeliveryCandidates(matchingPackets);
367
+ if (distinctMatchingPackets.length !== 1
368
+ || distinctMatchingPackets[0].sourceGate.status !== "valid") {
369
+ throw new Error("Accepted finish requires one fresh delivery packet matching the active verification gate; source drift remains unresolved.");
370
+ }
371
+ const [matchingPacket] = distinctMatchingPackets;
372
+ const snapshotsRoot = path.join(executionRoot, "snapshots");
373
+ const evidenceRoot = path.join(executionRoot, "snapshot-evidence");
374
+ projectTruthDirectory({ workspaceRoot, executionRoot, directoryPath: snapshotsRoot, label: "Snapshot directory" });
375
+ projectTruthDirectory({ workspaceRoot, executionRoot, directoryPath: evidenceRoot, label: "Snapshot evidence directory" });
376
+ for (const commandReceipt of validated.active.receipt.commandReceipts) {
377
+ const snapshotId = safeIdentifier(commandReceipt.id, "active snapshot id");
378
+ const snapshotPath = path.join(snapshotsRoot, `${snapshotId}.json`);
379
+ const snapshot = readJson(regularFile(snapshotPath, `Active snapshot ${snapshotId}`));
380
+ const sourceBinding = verifySnapshotSourceBinding({
381
+ snapshot,
382
+ expectedFiles: matchingPacket.packet.changedFiles?.files
383
+ ?? matchingPacket.packet.changedFiles?.wholeFileSha256,
384
+ expectedFingerprint: validated.active.receipt.sourceFingerprint,
385
+ });
386
+ if (!sourceBinding.valid) {
387
+ throw new Error(`Accepted finish requires snapshot source bound to the DeliveryPacket: ${snapshotId}; ${sourceBinding.issues.join("; ")}`);
388
+ }
389
+ const expectedStdoutPath = relativeToWorkspace(workspaceRoot, path.join(evidenceRoot, `${snapshotId}.stdout`));
390
+ const expectedStderrPath = relativeToWorkspace(workspaceRoot, path.join(evidenceRoot, `${snapshotId}.stderr`));
391
+ if (snapshot.command?.stdoutPath !== expectedStdoutPath
392
+ || snapshot.command?.stderrPath !== expectedStderrPath) {
393
+ throw new Error(`Accepted finish requires snapshot evidence inside the execution: ${snapshotId}`);
394
+ }
395
+ regularFile(path.join(workspaceRoot, expectedStdoutPath), `Active snapshot stdout ${snapshotId}`);
396
+ regularFile(path.join(workspaceRoot, expectedStderrPath), `Active snapshot stderr ${snapshotId}`);
397
+ const evidence = verifySnapshotEvidence({ workspaceRoot, runId, snapshot });
398
+ const receiptMatchesSnapshot = snapshot.command?.exitCode === commandReceipt.exitCode
399
+ && snapshot.command?.stdoutSha256 === commandReceipt.stdoutSha256
400
+ && snapshot.command?.stderrSha256 === commandReceipt.stderrSha256
401
+ && JSON.stringify(snapshot.command?.evidence) === JSON.stringify(commandReceipt.evidence)
402
+ && snapshot.verificationContextFingerprint === validated.active.receipt.verificationContextFingerprint;
403
+ if (!evidence.valid || !receiptMatchesSnapshot) {
404
+ throw new Error(`Accepted finish requires intact snapshot evidence: ${snapshotId}; ${evidence.issues.join("; ")}`);
405
+ }
406
+ }
407
+ return {
408
+ status: "valid",
409
+ gateInputPath,
410
+ gateInputRelativePath: relativeToWorkspace(workspaceRoot, gateInputPath),
411
+ deliveryPacketPath: relativeToWorkspace(workspaceRoot, matchingPacket.packetPath),
412
+ activeReceiptSha256: gate.activeReceiptSha256,
413
+ authorizationGranted: false,
414
+ };
415
+ }
@@ -0,0 +1,248 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import {
3
+ linkSync,
4
+ lstatSync,
5
+ mkdirSync,
6
+ readFileSync,
7
+ realpathSync,
8
+ rmSync,
9
+ writeFileSync,
10
+ } from "node:fs";
11
+ import path from "node:path";
12
+
13
+ import {
14
+ canonicalJson,
15
+ sha256Bytes,
16
+ } from "../../packages/attest/src/formal.mjs";
17
+ import {
18
+ createOfflineAttestationBundle,
19
+ parseOfflineAttestationBundle,
20
+ } from "../../packages/attest/src/offline-bundle.mjs";
21
+
22
+ function withinRoot(root, candidate) {
23
+ const relative = path.relative(root, candidate);
24
+ return relative !== ""
25
+ && relative !== ".."
26
+ && !relative.startsWith(`..${path.sep}`)
27
+ && !path.isAbsolute(relative);
28
+ }
29
+
30
+ function existingPathWithoutSymlinks(selectedPath, expectedType) {
31
+ const absolute = path.resolve(selectedPath);
32
+ const parsed = path.parse(absolute);
33
+ let current = parsed.root;
34
+ const segments = path.relative(parsed.root, absolute).split(path.sep).filter(Boolean);
35
+ try {
36
+ const rootStat = lstatSync(current);
37
+ if (rootStat.isSymbolicLink() || !rootStat.isDirectory()) return null;
38
+ for (const [index, segment] of segments.entries()) {
39
+ current = path.join(current, segment);
40
+ const stat = lstatSync(current);
41
+ if (stat.isSymbolicLink()) return null;
42
+ const isLeaf = index === segments.length - 1;
43
+ if (!isLeaf && !stat.isDirectory()) return null;
44
+ if (isLeaf && expectedType === "directory" && !stat.isDirectory()) return null;
45
+ if (isLeaf && expectedType === "file" && !stat.isFile()) return null;
46
+ }
47
+ return realpathSync(absolute);
48
+ } catch {
49
+ return null;
50
+ }
51
+ }
52
+
53
+ function safeReceiptPath(workspaceRoot, receiptPath) {
54
+ const root = existingPathWithoutSymlinks(workspaceRoot, "directory");
55
+ const candidate = existingPathWithoutSymlinks(receiptPath, "file");
56
+ return root !== null && candidate !== null && withinRoot(root, candidate)
57
+ ? candidate
58
+ : null;
59
+ }
60
+
61
+ function writeBytesExclusiveAtomically(targetPath, bytes) {
62
+ const temporaryPath = `${targetPath}.tmp-${randomUUID()}`;
63
+ try {
64
+ writeFileSync(temporaryPath, bytes, { flag: "wx", mode: 0o600 });
65
+ linkSync(temporaryPath, targetPath);
66
+ } finally {
67
+ rmSync(temporaryPath, { force: true });
68
+ }
69
+ }
70
+
71
+ function ensureStoreReceiptRoot(storeRoot, receiptId) {
72
+ if (!/^[A-Za-z0-9._-]+$/.test(receiptId)) {
73
+ throw new Error("offline receipt id is not path-safe");
74
+ }
75
+ const root = existingPathWithoutSymlinks(storeRoot, "directory");
76
+ if (root === null) return null;
77
+ let current = root;
78
+ for (const segment of ["quick", "receipts", receiptId]) {
79
+ current = path.join(current, segment);
80
+ let currentStat = null;
81
+ try {
82
+ currentStat = lstatSync(current);
83
+ } catch (error) {
84
+ if (error?.code !== "ENOENT") return null;
85
+ mkdirSync(current, { mode: 0o700 });
86
+ currentStat = lstatSync(current);
87
+ }
88
+ if (currentStat.isSymbolicLink() || !currentStat.isDirectory()) return null;
89
+ if (realpathSync(current) !== current) return null;
90
+ if (existingPathWithoutSymlinks(current, "directory") !== current) return null;
91
+ }
92
+ return withinRoot(root, current) ? current : null;
93
+ }
94
+
95
+ export function exportOfflineReceipt({
96
+ workspaceRoot,
97
+ receiptPath,
98
+ outputPath,
99
+ }) {
100
+ const receipt = safeReceiptPath(workspaceRoot, receiptPath);
101
+ if (receipt === null) {
102
+ return {
103
+ status: "offline_receipt_invalid",
104
+ exitCode: 3,
105
+ authorizationGranted: false,
106
+ networkRequests: 0,
107
+ };
108
+ }
109
+ const requestedOutput = path.resolve(outputPath);
110
+ try {
111
+ const existing = lstatSync(requestedOutput);
112
+ return {
113
+ status: existing.isSymbolicLink() ? "offline_output_invalid" : "offline_output_exists",
114
+ exitCode: existing.isSymbolicLink() ? 3 : 1,
115
+ outputPath: requestedOutput,
116
+ authorizationGranted: false,
117
+ networkRequests: 0,
118
+ };
119
+ } catch (error) {
120
+ if (error?.code !== "ENOENT") {
121
+ return {
122
+ status: "offline_output_invalid",
123
+ exitCode: 3,
124
+ outputPath: requestedOutput,
125
+ authorizationGranted: false,
126
+ networkRequests: 0,
127
+ };
128
+ }
129
+ }
130
+ const parent = existingPathWithoutSymlinks(path.dirname(requestedOutput), "directory");
131
+ if (parent === null) {
132
+ return {
133
+ status: "offline_output_invalid",
134
+ exitCode: 3,
135
+ outputPath: requestedOutput,
136
+ authorizationGranted: false,
137
+ networkRequests: 0,
138
+ };
139
+ }
140
+ const output = path.join(parent, path.basename(requestedOutput));
141
+ const bundle = createOfflineAttestationBundle(receipt);
142
+ const bundleBytes = Buffer.from(`${canonicalJson(bundle)}\n`);
143
+ writeBytesExclusiveAtomically(output, bundleBytes);
144
+ return {
145
+ status: "offline_bundle_exported",
146
+ exitCode: 0,
147
+ outputPath: output,
148
+ bundleSha256: sha256Bytes(bundleBytes),
149
+ reference: bundle.reference,
150
+ authorizationGranted: false,
151
+ networkRequests: 0,
152
+ };
153
+ }
154
+
155
+ export function importOfflineReceipt({
156
+ workspaceRoot,
157
+ bundlePath,
158
+ storeRoot,
159
+ }) {
160
+ if (existingPathWithoutSymlinks(workspaceRoot, "directory") === null) {
161
+ return {
162
+ status: "offline_workspace_invalid",
163
+ exitCode: 3,
164
+ authorizationGranted: false,
165
+ networkRequests: 0,
166
+ };
167
+ }
168
+ const bundle = existingPathWithoutSymlinks(bundlePath, "file");
169
+ if (bundle === null) {
170
+ return {
171
+ status: "offline_bundle_invalid",
172
+ exitCode: 3,
173
+ authorizationGranted: false,
174
+ networkRequests: 0,
175
+ };
176
+ }
177
+ const parsed = parseOfflineAttestationBundle(readFileSync(bundle, "utf8"));
178
+ const receiptRoot = ensureStoreReceiptRoot(storeRoot, parsed.reference.receiptId);
179
+ if (receiptRoot === null) {
180
+ return {
181
+ status: "offline_store_invalid",
182
+ exitCode: 3,
183
+ reference: parsed.reference,
184
+ authorizationGranted: false,
185
+ networkRequests: 0,
186
+ };
187
+ }
188
+ const receiptPath = path.join(receiptRoot, "receipt.json");
189
+ let existingReceiptStat = null;
190
+ try {
191
+ existingReceiptStat = lstatSync(receiptPath);
192
+ } catch (error) {
193
+ if (error?.code !== "ENOENT") {
194
+ return {
195
+ status: "offline_store_invalid",
196
+ exitCode: 3,
197
+ reference: parsed.reference,
198
+ authorizationGranted: false,
199
+ networkRequests: 0,
200
+ };
201
+ }
202
+ }
203
+ if (existingReceiptStat !== null) {
204
+ if (
205
+ existingReceiptStat.isSymbolicLink()
206
+ || !existingReceiptStat.isFile()
207
+ || existingPathWithoutSymlinks(receiptPath, "file") !== receiptPath
208
+ ) {
209
+ return {
210
+ status: "offline_store_invalid",
211
+ exitCode: 3,
212
+ reference: parsed.reference,
213
+ authorizationGranted: false,
214
+ networkRequests: 0,
215
+ };
216
+ }
217
+ const existing = readFileSync(receiptPath);
218
+ if (!existing.equals(parsed.receiptBytes)) {
219
+ return {
220
+ status: "offline_store_conflict",
221
+ exitCode: 1,
222
+ receiptPath,
223
+ reference: parsed.reference,
224
+ authorizationGranted: false,
225
+ networkRequests: 0,
226
+ };
227
+ }
228
+ return {
229
+ status: "offline_receipt_already_present",
230
+ exitCode: 0,
231
+ receiptPath,
232
+ receiptSha256: sha256Bytes(existing),
233
+ reference: parsed.reference,
234
+ authorizationGranted: false,
235
+ networkRequests: 0,
236
+ };
237
+ }
238
+ writeBytesExclusiveAtomically(receiptPath, parsed.receiptBytes);
239
+ return {
240
+ status: "offline_receipt_imported",
241
+ exitCode: 0,
242
+ receiptPath,
243
+ receiptSha256: sha256Bytes(parsed.receiptBytes),
244
+ reference: parsed.reference,
245
+ authorizationGranted: false,
246
+ networkRequests: 0,
247
+ };
248
+ }