@kungfu-tech/buildchain 3.0.9-alpha.8 → 4.0.0-alpha.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 (255) hide show
  1. package/AGENTS.md +39 -0
  2. package/README.md +17 -13
  3. package/actions/promote-buildchain-ref/README.md +0 -10
  4. package/actions/release-tail/README.md +6 -10
  5. package/architecture/internal-capabilities.json +502 -0
  6. package/architecture/maintainability-baseline.json +59 -0
  7. package/architecture/maintainability-policy.json +1384 -0
  8. package/architecture/release-tail-contract-inventory.json +587 -0
  9. package/architecture/v3-core-mechanism-inventory.json +1043 -0
  10. package/architecture/v3-core-mechanism-inventory.md +67 -0
  11. package/architecture/v4-adopter-delivery-parity.json +47 -0
  12. package/architecture/v4-architecture-constitution.md +210 -0
  13. package/architecture/v4-bootstrap-authority.json +56 -0
  14. package/architecture/v4-canonical-contract-fixtures.json +105 -0
  15. package/architecture/v4-capability-state-machine-manifest.json +480 -0
  16. package/architecture/v4-capability-state-machine-manifest.schema.json +202 -0
  17. package/architecture/v4-delivery-warrant-shadow-bootstrap-plan.json +830 -0
  18. package/architecture/v4-delivery-warrant-shadow-bootstrap-plan.md +223 -0
  19. package/architecture/v4-delivery-warrant-shadow-bootstrap-plan.schema.json +318 -0
  20. package/architecture/v4-delivery-warrant-shadow-fixtures.json +227 -0
  21. package/architecture/v4-delivery-warrant-shadow-fixtures.schema.json +67 -0
  22. package/architecture/v4-exception-ledger.json +5 -0
  23. package/architecture/v4-exception-ledger.schema.json +56 -0
  24. package/architecture/v4-partial-mutation-recovery-qualification.json +65 -0
  25. package/architecture/v4-platform-stage-checkpoints.json +97 -0
  26. package/architecture/v4-provider-operation-journal-contract.json +113 -0
  27. package/architecture/v4-release-activation-shadow-domain.json +61 -0
  28. package/architecture/v4-release-train-parity.json +68 -0
  29. package/architecture/v4-rust-libnode-bridge-evaluation.json +107 -0
  30. package/architecture/v4-rust-libnode-bridge-spike.md +85 -0
  31. package/architecture/v4-stable-publication-fence.json +66 -0
  32. package/architecture/v4-stage-capsule-contract.json +90 -0
  33. package/architecture/v4-stage-capsule-qualification.json +99 -0
  34. package/architecture/v4-stage-capsule-resume-planner.json +52 -0
  35. package/architecture/v4-stage-capsule-store-contract.json +72 -0
  36. package/bin/buildchain.mjs +15 -6
  37. package/contracts/auditable-demo-scenario-v1.schema.json +1 -1
  38. package/contracts/buildchain-v2-residuals-v1.json +2 -2
  39. package/contracts/fixtures/v4-delivery-warrant-trace-v1/golden.json +158 -0
  40. package/contracts/fixtures/v4-delivery-warrant-trace-v1/property.json +380 -0
  41. package/contracts/fixtures/v4-delivery-warrant-trace-v1/replay.json +163 -0
  42. package/contracts/fixtures/v4-partial-mutation-recovery-v1/shared.json +155 -0
  43. package/contracts/fixtures/v4-provider-operation-journal-v1/shared.json +457 -0
  44. package/contracts/fixtures/v4-provider-readback-idempotency-v1/shared.json +682 -0
  45. package/contracts/fixtures/v4-release-activation-shadow-v1/shared.json +53 -0
  46. package/contracts/fixtures/v4-stable-publication-fence-v1/shared.json +56 -0
  47. package/contracts/fixtures/v4-stage-capsule-resume-v1/late-platform-failure.json +176 -0
  48. package/contracts/fixtures/v4-stage-capsule-store-v1/shared.json +132 -0
  49. package/contracts/fixtures/v4-stage-capsule-v1/shared.json +111 -0
  50. package/contracts/v4-canonical-contracts-v1.schema.json +182 -0
  51. package/contracts/v4-delivery-warrant-semantic-diff-report-v1.schema.json +284 -0
  52. package/contracts/v4-delivery-warrant-trace-v1.schema.json +215 -0
  53. package/contracts/v4-host-contract-v1.schema.json +135 -0
  54. package/contracts/v4-partial-mutation-recovery-v1.schema.json +168 -0
  55. package/contracts/v4-provider-operation-journal-v1.schema.json +381 -0
  56. package/contracts/v4-release-activation-shadow-v1.schema.json +186 -0
  57. package/contracts/v4-stable-publication-fence-v1.schema.json +125 -0
  58. package/contracts/v4-stage-capsule-resume-v1.schema.json +225 -0
  59. package/contracts/v4-stage-capsule-store-v1.schema.json +154 -0
  60. package/contracts/v4-stage-capsule-v1.schema.json +178 -0
  61. package/crates/buildchain-v4-bridge/Cargo.lock +213 -0
  62. package/crates/buildchain-v4-bridge/Cargo.toml +12 -0
  63. package/crates/buildchain-v4-bridge/src/main.rs +495 -0
  64. package/dist/site/agent-index.json +0 -3
  65. package/dist/site/artifact-schemas.json +0 -6
  66. package/dist/site/buildchain-contract.json +103 -397
  67. package/dist/site/buildchain-site.json +302 -270
  68. package/dist/site/capability-registry.json +9 -11
  69. package/dist/site/cli-registry.json +8 -30
  70. package/dist/site/controller-registry.json +48 -8
  71. package/dist/site/kfd-claims.json +129 -142
  72. package/dist/site/kfd-upstream-aggregate.json +9 -9
  73. package/dist/site/manual-registry.json +18 -49
  74. package/dist/site/node-api-registry.json +1882 -4118
  75. package/dist/site/page-registry.json +278 -230
  76. package/dist/site/public-surface-audit.json +87 -185
  77. package/dist/site/publication-authority-registry.json +11 -1
  78. package/dist/site/publication-registry.json +4 -4
  79. package/dist/site/release-provenance.json +3 -7
  80. package/dist/site/schemas/kfd-support-projection-v1.schema.json +106 -0
  81. package/dist/site/site-manifest.json +22 -38
  82. package/dist/site/workflow-registry.json +80 -35
  83. package/docs/MAP.md +8 -4
  84. package/docs/auditable-demo.md +2 -2
  85. package/docs/aws-us-elastic-runner-burst-plane.md +7 -59
  86. package/docs/cli-reference.md +15 -92
  87. package/docs/cli.md +14 -14
  88. package/docs/dev-alpha-candidate-patrol.md +3 -11
  89. package/docs/dev-delivery-warrant.md +28 -100
  90. package/docs/engineering-housekeeper.md +12 -4
  91. package/docs/getting-started.md +1 -1
  92. package/docs/install.md +5 -5
  93. package/docs/kfd-support.md +2 -7
  94. package/docs/lifecycle-protocol.md +2 -4
  95. package/docs/node-api-reference.md +414 -523
  96. package/docs/release-flow.md +31 -31
  97. package/docs/release-governance.md +16 -28
  98. package/docs/release-passport.md +2 -15
  99. package/docs/release-tail-contract.md +13 -6
  100. package/docs/release-tail-provider-plane.md +13 -19
  101. package/docs/release-train.md +4 -4
  102. package/docs/reusable-build-surface.md +14 -27
  103. package/docs/site-bundle-contract.md +1 -5
  104. package/docs/stable-candidate-patrol.md +7 -7
  105. package/docs/v4-canonical-contracts.md +92 -0
  106. package/docs/v4-delivery-warrant-read-candidate.md +73 -0
  107. package/docs/v4-delivery-warrant-semantic-diff.md +75 -0
  108. package/docs/v4-production-release.md +63 -0
  109. package/docs/v4-stage-capsule.md +193 -0
  110. package/docs/versioning.md +3 -3
  111. package/package.json +19 -17
  112. package/packages/core/adopter-delivery-gate.js +576 -0
  113. package/packages/core/adopter-delivery-json.js +66 -0
  114. package/packages/core/artifact-signing.js +0 -61
  115. package/packages/core/artifact-verification-envelope.js +5 -5
  116. package/packages/core/build-facts.js +12 -4
  117. package/packages/core/buildchain-agent-manuals.js +0 -2
  118. package/packages/core/buildchain-config.js +4 -69
  119. package/packages/core/buildchain-contract.js +232 -46
  120. package/packages/core/buildchain-kfd-claims.js +1 -1
  121. package/packages/core/channel-candidate.js +0 -8
  122. package/packages/core/channel-promotion-baseline.js +0 -52
  123. package/packages/core/controller-evidence.js +3 -4
  124. package/packages/core/dev-alpha-candidate-selection.js +2 -10
  125. package/packages/core/dev-delivery-warrant-cancellation.js +0 -1
  126. package/packages/core/dev-delivery-warrant-settlement.js +1 -5
  127. package/packages/core/dev-delivery-warrant.js +12 -52
  128. package/packages/core/diagnostics.js +3 -8
  129. package/packages/core/github-governance-authority.js +3 -1
  130. package/packages/core/kfd-adopter-category-driver.js +167 -0
  131. package/packages/core/kfd-adopter-manifest.js +47 -46
  132. package/packages/core/kfd-gate.js +15 -45
  133. package/packages/core/paper-agent-entry.js +7 -16
  134. package/packages/core/paper-fleet.js +2 -2
  135. package/packages/core/paper-repository.js +2 -3
  136. package/packages/core/paper-scaffold-content.js +2 -23
  137. package/packages/core/paper.js +11 -43
  138. package/packages/core/publication-reproducibility.js +4 -4
  139. package/packages/core/release-line-bootstrap.js +21 -8
  140. package/packages/core/release-passport-contract.js +5 -5
  141. package/packages/core/release-passport.js +20 -131
  142. package/packages/core/self-dogfood-version.js +48 -35
  143. package/packages/core/spawn-command.js +232 -8
  144. package/packages/core/v4-adopter-delivery-parity.js +219 -0
  145. package/packages/core/v4-canonical-contracts.js +284 -0
  146. package/packages/core/v4-delivery-warrant-fixture-runner.js +371 -0
  147. package/packages/core/v4-delivery-warrant-read-candidate.js +279 -0
  148. package/packages/core/v4-delivery-warrant-semantic-diff-gate.js +352 -0
  149. package/packages/core/v4-delivery-warrant-shadow-adapter.js +447 -0
  150. package/packages/core/v4-partial-mutation-recovery-qualification.js +395 -0
  151. package/packages/core/v4-platform-stage-checkpoints.js +471 -0
  152. package/packages/core/v4-provider-operation-journal.js +531 -0
  153. package/packages/core/v4-provider-readback-idempotency.js +394 -0
  154. package/packages/core/v4-release-activation-shadow.js +519 -0
  155. package/packages/core/v4-stable-publication-fence.js +357 -0
  156. package/packages/core/v4-stage-capsule-local-store.js +426 -0
  157. package/packages/core/v4-stage-capsule-qualification-campaign.js +512 -0
  158. package/packages/core/v4-stage-capsule-qualification.js +456 -0
  159. package/packages/core/v4-stage-capsule-resume-planner.js +397 -0
  160. package/packages/core/v4-stage-capsule-store.js +401 -0
  161. package/packages/core/v4-stage-capsule.js +319 -0
  162. package/scripts/assemble-self-publication-admission.mjs +1 -1
  163. package/scripts/audit-publication-control-plane.mjs +5 -5
  164. package/scripts/auditable-demo-bundle-verification.mjs +3 -2
  165. package/scripts/auditable-demo-platform.mjs +2 -2
  166. package/scripts/auditable-demo-renditions.mjs +1 -1
  167. package/scripts/auditable-demo.mjs +2 -2
  168. package/scripts/aws-macos-jit-controller-core.mjs +13 -346
  169. package/scripts/aws-macos-jit-controller-runtime.mjs +2 -210
  170. package/scripts/aws-macos-jit-controller.mjs +37 -275
  171. package/scripts/aws-macos-jit-core.mjs +3 -41
  172. package/scripts/aws-macos-jit.mjs +0 -12
  173. package/scripts/aws-windows-jit-campaign.mjs +2 -2
  174. package/scripts/aws-windows-jit-controller-core.mjs +1 -1
  175. package/scripts/aws-windows-jit-controller.mjs +3 -3
  176. package/scripts/build-contract-core.mjs +3 -8
  177. package/scripts/build-standalone-binary.mjs +3 -14
  178. package/scripts/buildchain-channel-router.mjs +4 -0
  179. package/scripts/buildchain-cli-help.mjs +7 -13
  180. package/scripts/buildchain-contract-lock.mjs +0 -6
  181. package/scripts/check-action-bundles.mjs +3 -4
  182. package/scripts/check-internal-architecture.mjs +7 -6
  183. package/scripts/check-inventory.mjs +30 -25
  184. package/scripts/check-v4-public-dogfood-contract.mjs +270 -0
  185. package/scripts/create-release-bundle.mjs +8 -4
  186. package/scripts/dev-alpha-candidate-patrol.mjs +1 -22
  187. package/scripts/dev-delivery-proof.mjs +2 -54
  188. package/scripts/dev-delivery-warrant.mjs +59 -77
  189. package/scripts/dev-pr-auto-merge.mjs +4 -30
  190. package/scripts/dev-pr-delivery-warrant.mjs +0 -55
  191. package/scripts/dispatch-artifact-signing-authority.mjs +7 -4
  192. package/scripts/generate-buildchain-kfd-witnesses.mjs +94 -88
  193. package/scripts/generate-channel-build-workflow.mjs +54 -24
  194. package/scripts/generate-channel-promotion-workflow.mjs +15 -6
  195. package/scripts/generate-site-bundle.mjs +5 -21
  196. package/scripts/git-fetch-process-tree.mjs +34 -1
  197. package/scripts/init-repo.mjs +64 -159
  198. package/scripts/inspect-artifact-signing-requests.mjs +0 -6
  199. package/scripts/locked-source-checkout.mjs +3 -4
  200. package/scripts/maintainability-metrics.mjs +8 -2
  201. package/scripts/npm-publish-dry-run.mjs +2 -2
  202. package/scripts/npm-publish-transaction.mjs +2 -2
  203. package/scripts/publication-commit-evidence.mjs +23 -69
  204. package/scripts/release-candidate-resolver.mjs +11 -17
  205. package/scripts/release-tail.mjs +3 -49
  206. package/scripts/resume-from-candidate-run.mjs +9 -123
  207. package/scripts/run-lifecycle-core.mjs +12 -13
  208. package/scripts/seal-artifact-signing-requests.mjs +17 -21
  209. package/scripts/site-capability-metadata.mjs +2 -7
  210. package/scripts/stable-candidate-qualification.mjs +10 -10
  211. package/scripts/v4-architecture.mjs +12 -2
  212. package/scripts/v4-bridge-bootstrap.mjs +141 -0
  213. package/scripts/v4-bridge-evidence.mjs +141 -0
  214. package/scripts/v4-host-adapter.mjs +182 -0
  215. package/scripts/v4-platform-stage-checkpoint-rehearsal.mjs +207 -0
  216. package/scripts/v4-stage-capsule-qualification.mjs +528 -0
  217. package/scripts/v4-stage-capsule-resume-rehearsal.mjs +57 -0
  218. package/scripts/v4-warrant-shadow-plan.mjs +601 -0
  219. package/scripts/verify-golden-path.mjs +5 -5
  220. package/scripts/web-surface-cloudfront-rewrite.mjs +15 -15
  221. package/scripts/web-surface-core.mjs +2 -8
  222. package/scripts/workflow-call-contract.mjs +5 -184
  223. package/contracts/fixtures/kfd-adopter-release-v1/kfd-4-perspective.json +0 -16
  224. package/contracts/fixtures/kfd-adopter-release-v1/kfd-4-replay.json +0 -57
  225. package/contracts/fixtures/next-development-transition-v1/anchored-manual-waiting.json +0 -47
  226. package/contracts/fixtures/next-development-transition-v1/semver-auto-planned.json +0 -47
  227. package/contracts/fixtures/next-development-transition-v1/version-model-cases.json +0 -40
  228. package/contracts/next-development-request-v1.schema.json +0 -66
  229. package/contracts/next-development-transition-v1.schema.json +0 -292
  230. package/contracts/publication-rehearsal-capsule-v1.schema.json +0 -173
  231. package/dist/site/schemas/publication-rehearsal-capsule-v1.schema.json +0 -269
  232. package/dist/site/schemas/release-tail-capabilities-v1.schema.json +0 -353
  233. package/dist/site/schemas/release-tail-provider-bindings-v1.schema.json +0 -94
  234. package/docs/next-development-transition.md +0 -119
  235. package/docs/publication-rehearsal.md +0 -94
  236. package/packages/core/buildchain-compatibility-proof.js +0 -631
  237. package/packages/core/dev-delivery-native-proof.js +0 -333
  238. package/packages/core/dev-delivery-warrant-shadow.js +0 -502
  239. package/packages/core/next-development-candidate-reservation.js +0 -186
  240. package/packages/core/next-development-controller.js +0 -726
  241. package/packages/core/next-development-projection.js +0 -288
  242. package/packages/core/next-development-transition.js +0 -738
  243. package/packages/core/publication-rehearsal-projection.js +0 -173
  244. package/packages/core/publication-rehearsal-runtime.js +0 -921
  245. package/scripts/aws-macos-jit-instance-rehydrate.mjs +0 -260
  246. package/scripts/aws-macos-jit-source-rebind.mjs +0 -724
  247. package/scripts/dev-delivery-native-run.mjs +0 -187
  248. package/scripts/dev-delivery-two-phase.mjs +0 -598
  249. package/scripts/generate-next-development-guidance.mjs +0 -49
  250. package/scripts/materialize-self-release-candidate-version.mjs +0 -137
  251. package/scripts/next-development-self-dogfood-harness.mjs +0 -409
  252. package/scripts/next-development-self-dogfood.mjs +0 -532
  253. package/scripts/next-development-transition.mjs +0 -47
  254. package/scripts/release-candidate-tail-reseal.mjs +0 -426
  255. package/templates/native-dev-delivery.yml +0 -82
@@ -0,0 +1,447 @@
1
+ import { spawn } from "node:child_process";
2
+ import crypto from "node:crypto";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ import { runV4DeliveryWarrantTraceFixture } from "./v4-delivery-warrant-fixture-runner.js";
7
+
8
+ export const V4_DELIVERY_WARRANT_SHADOW_OBSERVATION_CONTRACT =
9
+ "buildchain-v4-delivery-warrant-shadow-observation/v1";
10
+ export const V4_DELIVERY_WARRANT_SHADOW_RESULT_CONTRACT =
11
+ "buildchain-v4-delivery-warrant-shadow-result/v1";
12
+
13
+ const HOST_REQUEST_CONTRACT = "kungfu-buildchain-v4-host-request";
14
+ const HOST_RESPONSE_CONTRACT = "kungfu-buildchain-v4-host-response";
15
+ const PROJECTION_CONTRACT =
16
+ "buildchain-v4-delivery-warrant-semantic-projection/v1";
17
+ const REQUIRED_CAPABILITIES = Object.freeze([
18
+ "canonical-input-v1",
19
+ "delivery-warrant-trace-projection-v1",
20
+ "diagnostics-v1",
21
+ "effects-disabled-v1",
22
+ "structured-result-v1",
23
+ ]);
24
+ const MAX_RESPONSE_BYTES = 8 * 1024 * 1024;
25
+ const MAX_TIMEOUT_MS = 30_000;
26
+ const RETENTION_DAYS = 90;
27
+ const ROOT_PATTERN = /^sha256:[0-9a-f]{64}$/u;
28
+ const REVISION_PATTERN = /^[0-9a-f]{40,64}$/u;
29
+ const root = path.resolve(
30
+ path.dirname(fileURLToPath(import.meta.url)),
31
+ "../..",
32
+ );
33
+
34
+ class ShadowHostFault extends Error {
35
+ constructor(code, message) {
36
+ super(message);
37
+ this.name = "ShadowHostFault";
38
+ this.code = code;
39
+ }
40
+ }
41
+
42
+ function inputBytes(value) {
43
+ if (Buffer.isBuffer(value)) return Buffer.from(value);
44
+ if (value instanceof Uint8Array) return Buffer.from(value);
45
+ if (typeof value === "string") return Buffer.from(value, "utf8");
46
+ throw new TypeError("shadow input must be bytes or a UTF-8 string");
47
+ }
48
+
49
+ function sha256(bytes) {
50
+ return `sha256:${crypto.createHash("sha256").update(bytes).digest("hex")}`;
51
+ }
52
+
53
+ function diagnostic(code, retryable = false) {
54
+ const messages = {
55
+ "host-cancelled": "the non-authoritative Rust projection was cancelled",
56
+ "host-crashed": "the non-authoritative Rust projection host exited",
57
+ "host-response-invalid": "the Rust host response was malformed",
58
+ "host-response-mismatch": "the Rust host response correlation was invalid",
59
+ "host-spawn-failed":
60
+ "the non-authoritative Rust projection host could not start",
61
+ "host-timeout":
62
+ "the non-authoritative Rust projection exceeded its bounded timeout",
63
+ "input-not-public-safe":
64
+ "shadow input was not eligible for public-safe retention",
65
+ "retention-failed":
66
+ "the caller-owned shadow observation sink rejected the observation",
67
+ "rust-projection-failed":
68
+ "the Rust host did not produce a usable projection",
69
+ "shadow-config-invalid":
70
+ "the non-authoritative shadow configuration was invalid",
71
+ "shadow-disabled": "the non-authoritative Rust shadow is disabled",
72
+ "unsupported-capability":
73
+ "the Rust host did not support the effect-disabled projection contract",
74
+ };
75
+ return {
76
+ code,
77
+ message: messages[code] || "the Rust shadow was unavailable",
78
+ retryable,
79
+ };
80
+ }
81
+
82
+ function enabledByDefault(environment = process.env) {
83
+ return environment.BUILDCHAIN_V4_WARRANT_SHADOW === "enabled";
84
+ }
85
+
86
+ function publicRetention(retention = {}) {
87
+ if (retention.kind === "fixture") {
88
+ return { classification: "public-safe-fixture", publicSafe: true };
89
+ }
90
+ if (retention.kind === "captured-replay" && retention.publicSafe === true) {
91
+ return { classification: "public-safe-captured-replay", publicSafe: true };
92
+ }
93
+ throw new ShadowHostFault(
94
+ "input-not-public-safe",
95
+ "only fixtures and explicitly public-safe captured replays may enter shadow retention",
96
+ );
97
+ }
98
+
99
+ function exactSource(value, label) {
100
+ if (typeof value !== "string" || !REVISION_PATTERN.test(value)) {
101
+ throw new TypeError(`${label} must be an exact lowercase Git revision`);
102
+ }
103
+ return value;
104
+ }
105
+
106
+ function exactValidator(value) {
107
+ if (typeof value !== "string" || !/^[a-z0-9][a-z0-9._-]*$/u.test(value)) {
108
+ throw new TypeError("validatorVersion must be a public ASCII identifier");
109
+ }
110
+ return value;
111
+ }
112
+
113
+ function retainUntil(recordedAt) {
114
+ const time = Date.parse(recordedAt);
115
+ if (!Number.isFinite(time))
116
+ throw new TypeError("recordedAt must be an ISO timestamp");
117
+ return new Date(time + RETENTION_DAYS * 24 * 60 * 60 * 1000).toISOString();
118
+ }
119
+
120
+ export function createV4DeliveryWarrantShadowRequest(
121
+ bytes,
122
+ { requestId = crypto.randomUUID(), timeoutMs = 5_000 } = {},
123
+ ) {
124
+ if (
125
+ !Number.isInteger(timeoutMs) ||
126
+ timeoutMs < 1 ||
127
+ timeoutMs > MAX_TIMEOUT_MS
128
+ ) {
129
+ throw new RangeError(`timeoutMs must be between 1 and ${MAX_TIMEOUT_MS}`);
130
+ }
131
+ return {
132
+ schemaVersion: 1,
133
+ contract: HOST_REQUEST_CONTRACT,
134
+ protocolVersion: "1.0",
135
+ requestId,
136
+ command: { id: "delivery-warrant.trace-project", arguments: [] },
137
+ input: { encoding: "base64", bytes: inputBytes(bytes).toString("base64") },
138
+ requiredCapabilities: [...REQUIRED_CAPABILITIES],
139
+ timeoutMs,
140
+ };
141
+ }
142
+
143
+ function validateHostResponse(response, request) {
144
+ if (
145
+ !response ||
146
+ response.schemaVersion !== 1 ||
147
+ response.contract !== HOST_RESPONSE_CONTRACT ||
148
+ response.protocolVersion !== "1.0"
149
+ ) {
150
+ throw new ShadowHostFault(
151
+ "host-response-invalid",
152
+ "unsupported host response contract",
153
+ );
154
+ }
155
+ if (
156
+ response.requestId !== request.requestId ||
157
+ response.command?.id !== request.command.id
158
+ ) {
159
+ throw new ShadowHostFault(
160
+ "host-response-mismatch",
161
+ "host response correlation mismatch",
162
+ );
163
+ }
164
+ if (!Array.isArray(response.host?.capabilities)) {
165
+ throw new ShadowHostFault(
166
+ "host-response-invalid",
167
+ "host capabilities are missing",
168
+ );
169
+ }
170
+ const missing = REQUIRED_CAPABILITIES.filter(
171
+ (capability) => !response.host.capabilities.includes(capability),
172
+ );
173
+ if (response.status === "unsupported" || missing.length > 0) {
174
+ throw new ShadowHostFault(
175
+ "unsupported-capability",
176
+ "required host capability is missing",
177
+ );
178
+ }
179
+ if (response.status !== "ok") {
180
+ throw new ShadowHostFault(
181
+ "rust-projection-failed",
182
+ "Rust projection status was not ok",
183
+ );
184
+ }
185
+ const result = response.structuredResult;
186
+ if (
187
+ result?.projection?.schema !== PROJECTION_CONTRACT ||
188
+ !ROOT_PATTERN.test(String(result?.projectionRoot || ""))
189
+ ) {
190
+ throw new ShadowHostFault(
191
+ "host-response-invalid",
192
+ "Rust projection shape is invalid",
193
+ );
194
+ }
195
+ return result;
196
+ }
197
+
198
+ function defaultHost() {
199
+ return {
200
+ command: "cargo",
201
+ arguments: [
202
+ "run",
203
+ "--locked",
204
+ "--quiet",
205
+ "--manifest-path",
206
+ path.join(root, "crates", "buildchain-v4-contracts", "Cargo.toml"),
207
+ "--",
208
+ "host",
209
+ ],
210
+ };
211
+ }
212
+
213
+ export function invokeV4RustShadowHost(
214
+ request,
215
+ { command, arguments: commandArguments, cwd = root, signal } = {},
216
+ ) {
217
+ const selected = defaultHost();
218
+ const executable = command || selected.command;
219
+ const args = commandArguments || selected.arguments;
220
+ return new Promise((resolve, reject) => {
221
+ if (signal?.aborted) {
222
+ reject(
223
+ new ShadowHostFault(
224
+ "host-cancelled",
225
+ "shadow signal was already aborted",
226
+ ),
227
+ );
228
+ return;
229
+ }
230
+ let settled = false;
231
+ let terminationCode = "";
232
+ let stdoutBytes = 0;
233
+ const stdout = [];
234
+ const child = spawn(executable, args, {
235
+ cwd,
236
+ env: process.env,
237
+ stdio: ["pipe", "pipe", "ignore"],
238
+ });
239
+ const finish = (callback) => {
240
+ if (settled) return;
241
+ settled = true;
242
+ clearTimeout(timeout);
243
+ signal?.removeEventListener("abort", cancel);
244
+ callback();
245
+ };
246
+ const terminate = (code) => {
247
+ if (terminationCode) return;
248
+ terminationCode = code;
249
+ child.kill("SIGTERM");
250
+ const force = setTimeout(() => child.kill("SIGKILL"), 100);
251
+ force.unref?.();
252
+ };
253
+ const cancel = () => terminate("host-cancelled");
254
+ const timeout = setTimeout(
255
+ () => terminate("host-timeout"),
256
+ request.timeoutMs,
257
+ );
258
+ timeout.unref?.();
259
+ signal?.addEventListener("abort", cancel, { once: true });
260
+ child.once("error", () => {
261
+ finish(() =>
262
+ reject(new ShadowHostFault("host-spawn-failed", "host spawn failed")),
263
+ );
264
+ });
265
+ child.stdout.on("data", (chunk) => {
266
+ stdoutBytes += chunk.length;
267
+ if (stdoutBytes > MAX_RESPONSE_BYTES) {
268
+ terminate("host-response-invalid");
269
+ return;
270
+ }
271
+ stdout.push(chunk);
272
+ });
273
+ child.stdin.on("error", () => {
274
+ terminate("host-crashed");
275
+ });
276
+ child.once("close", (code) => {
277
+ finish(() => {
278
+ if (terminationCode) {
279
+ reject(
280
+ new ShadowHostFault(
281
+ terminationCode,
282
+ "shadow host terminated and reaped",
283
+ ),
284
+ );
285
+ return;
286
+ }
287
+ if (code !== 0) {
288
+ reject(
289
+ new ShadowHostFault(
290
+ "host-crashed",
291
+ "shadow host exited before a response",
292
+ ),
293
+ );
294
+ return;
295
+ }
296
+ try {
297
+ resolve(JSON.parse(Buffer.concat(stdout).toString("utf8")));
298
+ } catch {
299
+ reject(
300
+ new ShadowHostFault(
301
+ "host-response-invalid",
302
+ "shadow host returned invalid JSON",
303
+ ),
304
+ );
305
+ }
306
+ });
307
+ });
308
+ child.stdin.end(`${JSON.stringify(request)}\n`);
309
+ });
310
+ }
311
+
312
+ function skippedShadow(inputRoot, code) {
313
+ return {
314
+ status: "skipped",
315
+ authority: "typescript-v3",
316
+ rustAuthority: "none",
317
+ rustEffects: "disabled",
318
+ inputRoot,
319
+ observation: null,
320
+ diagnostics: [diagnostic(code)],
321
+ retention: { status: "not-attempted" },
322
+ };
323
+ }
324
+
325
+ export async function runV4DeliveryWarrantShadow(
326
+ value,
327
+ {
328
+ enabled = enabledByDefault(),
329
+ invokeLegacy = runV4DeliveryWarrantTraceFixture,
330
+ invokeRust = invokeV4RustShadowHost,
331
+ host = {},
332
+ requestId,
333
+ timeoutMs = 5_000,
334
+ signal,
335
+ retention = { kind: "fixture" },
336
+ retain,
337
+ recordedAt = new Date().toISOString(),
338
+ sources = {},
339
+ } = {},
340
+ ) {
341
+ const bytes = inputBytes(value);
342
+ const authoritativeResult = await invokeLegacy(Buffer.from(bytes));
343
+ const inputRoot = sha256(bytes);
344
+ if (!enabled) {
345
+ return {
346
+ schema: V4_DELIVERY_WARRANT_SHADOW_RESULT_CONTRACT,
347
+ authoritativeResult,
348
+ shadow: skippedShadow(inputRoot, "shadow-disabled"),
349
+ };
350
+ }
351
+
352
+ let retentionScope;
353
+ try {
354
+ retentionScope = publicRetention(retention);
355
+ } catch (error) {
356
+ return {
357
+ schema: V4_DELIVERY_WARRANT_SHADOW_RESULT_CONTRACT,
358
+ authoritativeResult,
359
+ shadow: skippedShadow(inputRoot, error.code || "input-not-public-safe"),
360
+ };
361
+ }
362
+
363
+ let sourceBinding;
364
+ let request;
365
+ try {
366
+ sourceBinding = {
367
+ typescriptRevision: exactSource(
368
+ sources.typescriptRevision,
369
+ "typescriptRevision",
370
+ ),
371
+ rustRevision: exactSource(sources.rustRevision, "rustRevision"),
372
+ validatorVersion: exactValidator(sources.validatorVersion),
373
+ };
374
+ request = createV4DeliveryWarrantShadowRequest(bytes, {
375
+ requestId,
376
+ timeoutMs,
377
+ });
378
+ } catch {
379
+ return {
380
+ schema: V4_DELIVERY_WARRANT_SHADOW_RESULT_CONTRACT,
381
+ authoritativeResult,
382
+ shadow: skippedShadow(inputRoot, "shadow-config-invalid"),
383
+ };
384
+ }
385
+ let rustProjection = null;
386
+ let status = "observed";
387
+ const diagnostics = [];
388
+ try {
389
+ const response = await invokeRust(request, { ...host, signal });
390
+ rustProjection = validateHostResponse(response, request);
391
+ } catch (error) {
392
+ const code =
393
+ error instanceof ShadowHostFault ? error.code : "rust-projection-failed";
394
+ diagnostics.push(diagnostic(code, code === "host-timeout"));
395
+ status = code === "host-cancelled" ? "cancelled" : "unavailable";
396
+ }
397
+
398
+ const observation = {
399
+ schema: V4_DELIVERY_WARRANT_SHADOW_OBSERVATION_CONTRACT,
400
+ authority: "typescript-v3",
401
+ rustAuthority: "none",
402
+ rustEffects: "disabled",
403
+ status,
404
+ recordedAt,
405
+ retainUntil: retainUntil(recordedAt),
406
+ retention: retentionScope,
407
+ input: {
408
+ encoding: "base64",
409
+ bytes: bytes.toString("base64"),
410
+ root: inputRoot,
411
+ },
412
+ sources: sourceBinding,
413
+ legacy: {
414
+ sourceRevision: sourceBinding.typescriptRevision,
415
+ projection: authoritativeResult,
416
+ },
417
+ rust: {
418
+ sourceRevision: sourceBinding.rustRevision,
419
+ projection: rustProjection,
420
+ },
421
+ diagnostics,
422
+ };
423
+ let retentionResult = { status: "returned-to-caller" };
424
+ if (retain) {
425
+ try {
426
+ await retain(structuredClone(observation));
427
+ retentionResult = { status: "retained" };
428
+ } catch {
429
+ diagnostics.push(diagnostic("retention-failed", true));
430
+ retentionResult = { status: "failed" };
431
+ }
432
+ }
433
+ return {
434
+ schema: V4_DELIVERY_WARRANT_SHADOW_RESULT_CONTRACT,
435
+ authoritativeResult,
436
+ shadow: {
437
+ status,
438
+ authority: "typescript-v3",
439
+ rustAuthority: "none",
440
+ rustEffects: "disabled",
441
+ inputRoot,
442
+ observation,
443
+ diagnostics,
444
+ retention: retentionResult,
445
+ },
446
+ };
447
+ }