machine-bridge-mcp 2.0.0 → 3.0.0-beta.102

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 (473) hide show
  1. package/CHANGELOG.md +1142 -0
  2. package/CONTRIBUTING.md +23 -25
  3. package/GOVERNANCE.md +2 -2
  4. package/README.md +58 -20
  5. package/SECURITY.md +161 -120
  6. package/SUPPORT.md +1 -1
  7. package/browser-extension/broker-auth.js +83 -0
  8. package/browser-extension/broker-liveness.js +35 -0
  9. package/browser-extension/browser-error-boundary.js +96 -0
  10. package/browser-extension/browser-operations.js +1456 -101
  11. package/browser-extension/devtools-input.js +195 -34
  12. package/browser-extension/devtools-observation.js +429 -0
  13. package/browser-extension/devtools-session.js +48 -0
  14. package/browser-extension/manifest.json +4 -3
  15. package/browser-extension/page-automation.js +578 -118
  16. package/browser-extension/pairing-bootstrap.js +42 -0
  17. package/browser-extension/pairing.js +28 -12
  18. package/browser-extension/service-worker.js +126 -106
  19. package/docs/AGENT_CONTEXT.md +13 -10
  20. package/docs/ARCHITECTURE.md +159 -67
  21. package/docs/AUDIT.md +1302 -4
  22. package/docs/CLIENTS.md +19 -6
  23. package/docs/COMPUTER_USE.md +297 -0
  24. package/docs/ENGINEERING.md +72 -13
  25. package/docs/GETTING_STARTED.md +18 -20
  26. package/docs/LOCAL_AUTHORIZATION.md +115 -72
  27. package/docs/LOCAL_AUTOMATION.md +27 -21
  28. package/docs/LOGGING.md +40 -19
  29. package/docs/MANAGED_JOBS.md +37 -34
  30. package/docs/MULTI_ACCOUNT.md +98 -37
  31. package/docs/OPERATIONS.md +145 -51
  32. package/docs/OVERVIEW.md +14 -11
  33. package/docs/POLICY_REFERENCE.md +71 -3
  34. package/docs/PRIVACY.md +41 -2
  35. package/docs/PROJECT_STANDARDS.md +29 -6
  36. package/docs/RELEASING.md +238 -64
  37. package/docs/TESTING.md +150 -39
  38. package/docs/THREAT_MODEL.md +164 -67
  39. package/docs/TOOL_REFERENCE.md +653 -60
  40. package/docs/UPGRADING.md +78 -18
  41. package/native/macos/MachineBridgeBackgroundInput.swift +1051 -0
  42. package/native/macos/MachineBridgeBackgroundInputSmokeFixture.swift +295 -0
  43. package/native/macos/MachineBridgeTrustBroker.swift +233 -0
  44. package/package.json +94 -16
  45. package/scripts/accepted-candidate-tarball.mjs +77 -0
  46. package/scripts/candidate-runtime-store.mjs +93 -0
  47. package/scripts/check-plan.mjs +73 -3
  48. package/scripts/check-runner.mjs +129 -17
  49. package/scripts/commit-message-check.mjs +5 -2
  50. package/scripts/consumer-package-security.mjs +293 -0
  51. package/scripts/coverage-check.mjs +251 -15
  52. package/scripts/coverage-generation.mjs +41 -0
  53. package/scripts/coverage-range-merge.mjs +41 -0
  54. package/scripts/foreground-daemon-recovery.mjs +88 -0
  55. package/scripts/generate-policy-reference.mjs +28 -5
  56. package/scripts/generate-tool-reference.mjs +1 -1
  57. package/scripts/generate-worker-types.mjs +21 -11
  58. package/scripts/github-backlog.mjs +11 -10
  59. package/scripts/github-push.mjs +62 -16
  60. package/scripts/github-release-asset.mjs +58 -0
  61. package/scripts/github-release.mjs +241 -132
  62. package/scripts/global-package-installation.mjs +68 -0
  63. package/scripts/hardened-npm-session.mjs +42 -0
  64. package/scripts/install-published-prerelease.mjs +198 -0
  65. package/scripts/local-release-acceptance.mjs +103 -45
  66. package/scripts/macos-background-input-smoke.mjs +515 -0
  67. package/scripts/network-retry.mjs +8 -1
  68. package/scripts/npm-global-prefix.mjs +27 -0
  69. package/scripts/npm-publication-policy.mjs +17 -0
  70. package/scripts/official-mcp-conformance.mjs +267 -0
  71. package/scripts/persistent-activation-process.mjs +101 -0
  72. package/scripts/prepare-pinned-npm.mjs +12 -69
  73. package/scripts/prerelease-activation.mjs +160 -0
  74. package/scripts/privacy-check.mjs +14 -6
  75. package/scripts/promotion-digest.mjs +128 -0
  76. package/scripts/publish-npm.mjs +260 -0
  77. package/scripts/published-release.mjs +132 -0
  78. package/scripts/release-acceptance.mjs +62 -54
  79. package/scripts/release-browser-extension-store.mjs +172 -0
  80. package/scripts/release-candidate-manifest.mjs +52 -0
  81. package/scripts/release-channel.mjs +106 -0
  82. package/scripts/release-diagnostic.mjs +41 -0
  83. package/scripts/release-impact-check.mjs +12 -22
  84. package/scripts/release-oauth-canary-core.mjs +325 -0
  85. package/scripts/release-oauth-canary-evidence.mjs +100 -0
  86. package/scripts/release-oauth-canary.mjs +127 -0
  87. package/scripts/release-publication-guard.mjs +67 -0
  88. package/scripts/release-soak.mjs +284 -0
  89. package/scripts/release-state.mjs +1 -1
  90. package/scripts/run-checks.mjs +44 -7
  91. package/scripts/run-worker-dry-run.mjs +21 -0
  92. package/scripts/sarif-security-gate.mjs +2 -1
  93. package/scripts/sbom-check.mjs +106 -0
  94. package/scripts/start-release-candidate.mjs +267 -44
  95. package/scripts/syntax-check.mjs +36 -14
  96. package/scripts/verification-generation-guard.mjs +15 -0
  97. package/scripts/verification-idle-sleep-guard.mjs +37 -0
  98. package/scripts/verification-state.mjs +108 -0
  99. package/scripts/wrangler-command-lifecycle.mjs +115 -0
  100. package/src/local/account-access.mjs +13 -1
  101. package/src/local/account-admin-response.mjs +92 -0
  102. package/src/local/account-admin.mjs +52 -19
  103. package/src/local/agent-context-projection.mjs +26 -7
  104. package/src/local/agent-context.mjs +88 -49
  105. package/src/local/agent-skill-discovery.mjs +16 -5
  106. package/src/local/app-automation-macos-jxa.mjs +350 -0
  107. package/src/local/app-automation.mjs +873 -163
  108. package/src/local/application-capability-projection.mjs +24 -0
  109. package/src/local/authority-context.mjs +106 -0
  110. package/src/local/autostart-log-maintenance.mjs +36 -0
  111. package/src/local/browser-bridge-http.mjs +5 -3
  112. package/src/local/browser-bridge.mjs +109 -31
  113. package/src/local/browser-broker-auth-http.mjs +67 -0
  114. package/src/local/browser-broker-auth.mjs +98 -0
  115. package/src/local/browser-broker-routes.mjs +63 -20
  116. package/src/local/browser-broker-server.mjs +17 -7
  117. package/src/local/browser-command.mjs +79 -30
  118. package/src/local/browser-computer-observation-service.mjs +266 -0
  119. package/src/local/browser-extension-identity.mjs +50 -0
  120. package/src/local/browser-extension-path.mjs +22 -0
  121. package/src/local/browser-extension-protocol.mjs +50 -11
  122. package/src/local/browser-operation-service.mjs +147 -117
  123. package/src/local/browser-pairing-grant.mjs +109 -0
  124. package/src/local/browser-pairing-http.mjs +36 -0
  125. package/src/local/browser-pairing-launch.mjs +58 -0
  126. package/src/local/browser-pairing-store.mjs +85 -48
  127. package/src/local/browser-request-registry.mjs +40 -14
  128. package/src/local/browser-request-settlement.mjs +78 -0
  129. package/src/local/browser-resource-input.mjs +74 -0
  130. package/src/local/browser-trusted-input-health.mjs +63 -0
  131. package/src/local/call-authority.mjs +21 -0
  132. package/src/local/call-capacity.mjs +45 -0
  133. package/src/local/call-registry-drain.mjs +54 -0
  134. package/src/local/call-registry.mjs +30 -15
  135. package/src/local/capability-observer.mjs +5 -0
  136. package/src/local/capability-ranking.mjs +3 -2
  137. package/src/local/child-process-settlement.mjs +132 -0
  138. package/src/local/cli-account-admin.mjs +40 -6
  139. package/src/local/cli-activate.mjs +162 -0
  140. package/src/local/cli-local-admin.mjs +20 -45
  141. package/src/local/cli-options.mjs +12 -13
  142. package/src/local/cli-ready-output.mjs +52 -0
  143. package/src/local/cli-service.mjs +91 -11
  144. package/src/local/cli.mjs +232 -150
  145. package/src/local/computer-use-application-observation.mjs +224 -0
  146. package/src/local/computer-use-arguments.mjs +270 -0
  147. package/src/local/computer-use-deadline.mjs +50 -0
  148. package/src/local/computer-use-dispatch-settlement.mjs +40 -0
  149. package/src/local/computer-use-expectation.mjs +171 -0
  150. package/src/local/computer-use-observation.mjs +769 -0
  151. package/src/local/computer-use-recovery.mjs +82 -0
  152. package/src/local/computer-use-result-budget.mjs +145 -0
  153. package/src/local/computer-use-snapshot-store.mjs +67 -0
  154. package/src/local/computer-use.mjs +2255 -0
  155. package/src/local/daemon-http-relay-auth.mjs +26 -0
  156. package/src/local/daemon-http-relay-connection.mjs +298 -0
  157. package/src/local/daemon-http-relay-request.mjs +64 -0
  158. package/src/local/daemon-http-relay-sequence.mjs +49 -0
  159. package/src/local/daemon-process.mjs +40 -7
  160. package/src/local/delegated-process-sandbox.mjs +148 -0
  161. package/src/local/device-identity.mjs +156 -49
  162. package/src/local/device-root-provider.mjs +81 -0
  163. package/src/local/directory-metadata.mjs +47 -0
  164. package/src/local/doctor-reporting.mjs +23 -0
  165. package/src/local/durable-process-spec.mjs +80 -0
  166. package/src/local/errors.mjs +25 -15
  167. package/src/local/exclusive-file.mjs +74 -26
  168. package/src/local/execution-limits.mjs +9 -0
  169. package/src/local/execution-routing.mjs +276 -0
  170. package/src/local/execution-surface.mjs +23 -0
  171. package/src/local/file-mutation-coordinator.mjs +47 -0
  172. package/src/local/file-snapshot-preservation.mjs +24 -0
  173. package/src/local/filesystem-identity.mjs +54 -0
  174. package/src/local/fixed-process-environment.mjs +21 -0
  175. package/src/local/full-access-test.mjs +31 -13
  176. package/src/local/git-commit.mjs +69 -0
  177. package/src/local/git-config-safety.mjs +55 -0
  178. package/src/local/git-log-parser.mjs +41 -0
  179. package/src/local/git-metadata-boundary.mjs +77 -0
  180. package/src/local/git-metadata-tree-safety.mjs +59 -0
  181. package/src/local/git-operation-state.mjs +19 -0
  182. package/src/local/git-service.mjs +165 -30
  183. package/src/local/hardened-npm-download-timeout.mjs +46 -0
  184. package/src/local/hardened-npm-download.mjs +109 -0
  185. package/src/local/hardened-npm-extract.mjs +20 -0
  186. package/src/local/hardened-npm-verification.mjs +104 -0
  187. package/src/local/hardened-npm.mjs +199 -0
  188. package/src/local/job-runner.mjs +244 -89
  189. package/src/local/lifecycle.mjs +6 -0
  190. package/src/local/log.mjs +19 -45
  191. package/src/local/macos-background-input.mjs +398 -0
  192. package/src/local/macos-idle-sleep-assertion.mjs +65 -0
  193. package/src/local/macos-trust-broker.mjs +404 -0
  194. package/src/local/managed-job-cancellation.mjs +42 -0
  195. package/src/local/managed-job-capacity.mjs +16 -0
  196. package/src/local/managed-job-directory-generation.mjs +60 -0
  197. package/src/local/managed-job-directory.mjs +75 -0
  198. package/src/local/managed-job-durable-process.mjs +49 -0
  199. package/src/local/managed-job-lock.mjs +46 -14
  200. package/src/local/managed-job-plan.mjs +38 -14
  201. package/src/local/managed-job-projection.mjs +23 -15
  202. package/src/local/managed-job-retention.mjs +128 -0
  203. package/src/local/managed-job-runner-claim.mjs +70 -0
  204. package/src/local/managed-job-runner.mjs +35 -10
  205. package/src/local/managed-job-storage.mjs +22 -6
  206. package/src/local/managed-job-terminal-maintenance.mjs +40 -0
  207. package/src/local/managed-job-terminal.mjs +150 -0
  208. package/src/local/managed-jobs.mjs +424 -287
  209. package/src/local/npm-cli.mjs +42 -0
  210. package/src/local/npm-environment.mjs +37 -0
  211. package/src/local/operation-authorization.mjs +68 -324
  212. package/src/local/operation-risk.mjs +51 -4
  213. package/src/local/owner-state-lock.mjs +118 -0
  214. package/src/local/package-identity.mjs +9 -0
  215. package/src/local/patch.mjs +20 -18
  216. package/src/local/path-inspection.mjs +23 -0
  217. package/src/local/policy.mjs +19 -0
  218. package/src/local/private-toolchain-integrity.mjs +54 -0
  219. package/src/local/process-execution.mjs +87 -75
  220. package/src/local/process-foreground-timeout.mjs +50 -0
  221. package/src/local/process-identity.mjs +41 -7
  222. package/src/local/process-nonreplayable-settlement.mjs +50 -0
  223. package/src/local/process-result-projection.mjs +22 -0
  224. package/src/local/process-session-events.mjs +47 -0
  225. package/src/local/process-session-remote-activity.mjs +10 -0
  226. package/src/local/process-session-termination.mjs +73 -0
  227. package/src/local/process-sessions.mjs +144 -112
  228. package/src/local/process-tracker.mjs +140 -13
  229. package/src/local/process-tree-ownership-types.d.ts +37 -0
  230. package/src/local/process-tree-ownership.mjs +57 -0
  231. package/src/local/process-tree-signal.mjs +34 -0
  232. package/src/local/process-tree-snapshot.mjs +77 -0
  233. package/src/local/process-tree-supervisor.mjs +69 -0
  234. package/src/local/process-tree.mjs +11 -53
  235. package/src/local/project-metadata.mjs +19 -6
  236. package/src/local/relay-call-recovery.mjs +58 -38
  237. package/src/local/relay-connection-classification.mjs +131 -0
  238. package/src/local/relay-connection-support.mjs +91 -0
  239. package/src/local/relay-connection.mjs +179 -272
  240. package/src/local/relay-diagnostics.mjs +91 -0
  241. package/src/local/relay-heartbeat.mjs +119 -0
  242. package/src/local/relay-liveness.mjs +109 -0
  243. package/src/local/relay-peer-diagnostics.mjs +29 -0
  244. package/src/local/release-runtime-lock.mjs +18 -0
  245. package/src/local/remote-activity-idle-sleep-guard.mjs +77 -0
  246. package/src/local/remote-configuration.mjs +48 -0
  247. package/src/local/resilient-relay-connection.mjs +178 -0
  248. package/src/local/resource-admission-diagnostics.mjs +52 -0
  249. package/src/local/resource-admission-policy.mjs +115 -0
  250. package/src/local/resource-admission.mjs +339 -0
  251. package/src/local/resource-build-root.mjs +83 -0
  252. package/src/local/resource-cargo-concurrency.mjs +38 -0
  253. package/src/local/resource-cmake-concurrency.mjs +42 -0
  254. package/src/local/resource-command-concurrency.mjs +37 -0
  255. package/src/local/resource-command-profile.mjs +176 -0
  256. package/src/local/resource-coordinator-accounting.mjs +21 -0
  257. package/src/local/resource-cpu-window.mjs +20 -0
  258. package/src/local/resource-disk-headroom.mjs +13 -0
  259. package/src/local/resource-elastic-memory.mjs +19 -0
  260. package/src/local/resource-elastic-request.mjs +36 -0
  261. package/src/local/resource-foreground-wait.mjs +29 -0
  262. package/src/local/resource-go-concurrency.mjs +43 -0
  263. package/src/local/resource-gradle-concurrency.mjs +57 -0
  264. package/src/local/resource-host-cache.mjs +39 -0
  265. package/src/local/resource-host-darwin.mjs +54 -0
  266. package/src/local/resource-host-linux.mjs +35 -0
  267. package/src/local/resource-host-sample-file.mjs +23 -0
  268. package/src/local/resource-host-snapshot.mjs +99 -0
  269. package/src/local/resource-lease-accounting.mjs +119 -0
  270. package/src/local/resource-light-command.mjs +6 -0
  271. package/src/local/resource-make-concurrency.mjs +42 -0
  272. package/src/local/resource-maven-concurrency.mjs +38 -0
  273. package/src/local/resource-ninja-command-concurrency.mjs +20 -0
  274. package/src/local/resource-ninja-concurrency.mjs +28 -0
  275. package/src/local/resource-operations.mjs +26 -10
  276. package/src/local/resource-pressure.mjs +67 -0
  277. package/src/local/resource-probe-command.mjs +35 -0
  278. package/src/local/resource-process-admission.mjs +59 -0
  279. package/src/local/resource-process-ancestry-cache.mjs +43 -0
  280. package/src/local/resource-process-ancestry.mjs +32 -0
  281. package/src/local/resource-process-priority.mjs +15 -0
  282. package/src/local/resource-project-key.mjs +53 -0
  283. package/src/local/resource-pytest-concurrency.mjs +33 -0
  284. package/src/local/resource-release-control-classification.mjs +14 -0
  285. package/src/local/resource-release-control-executable.mjs +70 -0
  286. package/src/local/resource-release-control-workspace.mjs +41 -0
  287. package/src/local/resource-request-contract.mjs +30 -0
  288. package/src/local/resource-script-classification.mjs +44 -0
  289. package/src/local/resource-shell-analysis.mjs +58 -0
  290. package/src/local/resource-staging-recovery.mjs +97 -0
  291. package/src/local/resource-swift-concurrency.mjs +31 -0
  292. package/src/local/resource-transaction-lock.mjs +189 -0
  293. package/src/local/resource-wait.mjs +48 -0
  294. package/src/local/resource-waiters.mjs +139 -0
  295. package/src/local/resource-xcode-command.mjs +7 -0
  296. package/src/local/resource-xcode-concurrency.mjs +34 -0
  297. package/src/local/resource-xcode-non-build.mjs +19 -0
  298. package/src/local/runtime-activation.mjs +700 -0
  299. package/src/local/runtime-activity-projection.mjs +48 -0
  300. package/src/local/runtime-capabilities.mjs +48 -15
  301. package/src/local/runtime-diagnostic-state.mjs +14 -0
  302. package/src/local/runtime-diagnostics.mjs +40 -13
  303. package/src/local/runtime-info-projection.mjs +60 -0
  304. package/src/local/runtime-info-relay-projection.mjs +21 -0
  305. package/src/local/runtime-paths.mjs +2 -1
  306. package/src/local/runtime-process-routing.mjs +33 -0
  307. package/src/local/runtime-relay-connection-options.mjs +44 -0
  308. package/src/local/runtime-relay-control.mjs +98 -0
  309. package/src/local/runtime-relay.mjs +26 -50
  310. package/src/local/runtime-reporting.mjs +37 -21
  311. package/src/local/runtime-resource-service.mjs +77 -0
  312. package/src/local/runtime-tool-handlers.mjs +13 -10
  313. package/src/local/runtime.mjs +244 -208
  314. package/src/local/secure-file.mjs +73 -20
  315. package/src/local/security-audit-dispatch.mjs +35 -0
  316. package/src/local/security-audit-log.mjs +215 -0
  317. package/src/local/security-audit-state.mjs +139 -0
  318. package/src/local/security-audit-storage.mjs +135 -0
  319. package/src/local/security-audit-warning.mjs +31 -0
  320. package/src/local/security-audit-worker.mjs +87 -0
  321. package/src/local/service-convergence.mjs +42 -1
  322. package/src/local/service-definition.mjs +24 -0
  323. package/src/local/service-environment.mjs +18 -10
  324. package/src/local/service-owner.mjs +146 -0
  325. package/src/local/service-ownership.mjs +17 -0
  326. package/src/local/service-restart-handoff.mjs +64 -0
  327. package/src/local/service-restart-scheduler.mjs +49 -0
  328. package/src/local/service-runtime-convergence.mjs +52 -0
  329. package/src/local/service-runtime.mjs +105 -0
  330. package/src/local/service-status.mjs +60 -0
  331. package/src/local/service.mjs +385 -92
  332. package/src/local/shell.mjs +39 -19
  333. package/src/local/ssh-key.mjs +158 -42
  334. package/src/local/state-inventory.mjs +50 -24
  335. package/src/local/state-owner-lock-inventory.mjs +23 -0
  336. package/src/local/state-root-owned-namespaces.mjs +83 -0
  337. package/src/local/state-root-retirement.mjs +89 -0
  338. package/src/local/state.mjs +386 -96
  339. package/src/local/stdio.mjs +96 -66
  340. package/src/local/support-state-projection.mjs +30 -0
  341. package/src/local/system-network-route.mjs +76 -0
  342. package/src/local/systemd-removal.mjs +20 -0
  343. package/src/local/tool-executor.mjs +85 -20
  344. package/src/local/tool-result-boundary.mjs +51 -0
  345. package/src/local/toolchain-operation-lock.mjs +41 -0
  346. package/src/local/tools.mjs +7 -5
  347. package/src/local/trusted-executable.mjs +53 -0
  348. package/src/local/trusted-git-executable.mjs +34 -0
  349. package/src/local/trusted-github-cli.mjs +24 -0
  350. package/src/local/windows-service-convergence.mjs +49 -0
  351. package/src/local/windows-service.mjs +52 -45
  352. package/src/local/worker-deployment-fingerprint.mjs +102 -0
  353. package/src/local/worker-deployment.mjs +48 -60
  354. package/src/local/worker-health.mjs +12 -4
  355. package/src/local/worker-secret-file.mjs +37 -17
  356. package/src/local/workspace-file-service.mjs +156 -239
  357. package/src/local/workspace-file-transaction.mjs +189 -0
  358. package/src/local/workspace-search.mjs +55 -0
  359. package/src/local/wrangler-toolchain/package-lock.json +1505 -0
  360. package/src/local/wrangler-toolchain/package.json +23 -0
  361. package/src/local/wrangler-toolchain-verification.mjs +135 -0
  362. package/src/local/wrangler-toolchain.mjs +188 -0
  363. package/src/shared/access-contract.json +7 -1
  364. package/src/shared/activation-recovery.mjs +49 -0
  365. package/src/shared/admin-auth.d.mts +2 -1
  366. package/src/shared/admin-auth.mjs +3 -3
  367. package/src/shared/authority-revocation.d.mts +9 -0
  368. package/src/shared/authority-revocation.mjs +28 -0
  369. package/src/shared/daemon-auth.d.mts +11 -0
  370. package/src/shared/daemon-auth.mjs +17 -0
  371. package/src/shared/device-session-auth.d.mts +20 -0
  372. package/src/shared/device-session-auth.mjs +51 -0
  373. package/src/shared/foreground-timeout.d.mts +15 -0
  374. package/src/shared/foreground-timeout.mjs +70 -0
  375. package/src/shared/log-redaction.d.mts +9 -0
  376. package/src/shared/log-redaction.mjs +51 -0
  377. package/src/shared/mcp-protocol.d.mts +27 -0
  378. package/src/shared/mcp-protocol.mjs +275 -0
  379. package/src/shared/project-overview-projection.d.mts +4 -0
  380. package/src/shared/project-overview-projection.mjs +96 -0
  381. package/src/shared/relay-contract.json +28 -0
  382. package/src/shared/result-projection.d.mts +2 -1
  383. package/src/shared/result-projection.mjs +13 -2
  384. package/src/shared/server-metadata.json +15 -9
  385. package/src/shared/tool-argument-validation.d.mts +17 -0
  386. package/src/shared/tool-argument-validation.mjs +325 -0
  387. package/src/shared/tool-call-capacity.d.mts +41 -0
  388. package/src/shared/tool-call-capacity.mjs +59 -0
  389. package/src/shared/tool-catalog.json +626 -57
  390. package/src/worker/access.ts +12 -0
  391. package/src/worker/account-admin.ts +55 -33
  392. package/src/worker/authority-revocations.ts +174 -0
  393. package/src/worker/authority.ts +52 -6
  394. package/src/worker/daemon-auth.ts +49 -68
  395. package/src/worker/daemon-channel.ts +36 -0
  396. package/src/worker/daemon-http-auth.ts +63 -0
  397. package/src/worker/daemon-http-channel.ts +120 -0
  398. package/src/worker/daemon-http-controller.ts +163 -0
  399. package/src/worker/daemon-http-protocol.ts +62 -0
  400. package/src/worker/daemon-http-registry.ts +82 -0
  401. package/src/worker/daemon-last-observation.ts +30 -0
  402. package/src/worker/daemon-liveness.ts +8 -6
  403. package/src/worker/daemon-ready-dispatch.ts +17 -0
  404. package/src/worker/daemon-ready-messages.ts +73 -0
  405. package/src/worker/daemon-ready-waiters.ts +79 -0
  406. package/src/worker/daemon-recovery-budget.ts +13 -0
  407. package/src/worker/daemon-registry.ts +58 -0
  408. package/src/worker/daemon-relay-diagnostics.ts +127 -0
  409. package/src/worker/daemon-socket-attachment.ts +55 -0
  410. package/src/worker/daemon-sockets.ts +72 -62
  411. package/src/worker/daemon-status.ts +38 -0
  412. package/src/worker/device-session-verifier.ts +129 -0
  413. package/src/worker/dpop.ts +157 -0
  414. package/src/worker/durable-process-timeout.ts +29 -0
  415. package/src/worker/errors.ts +57 -0
  416. package/src/worker/http.ts +112 -26
  417. package/src/worker/index.ts +446 -440
  418. package/src/worker/mcp-access.ts +57 -0
  419. package/src/worker/mcp-controller.ts +188 -0
  420. package/src/worker/mcp-http-accept.ts +11 -0
  421. package/src/worker/mcp-http-contract.ts +322 -0
  422. package/src/worker/mcp-initialization-compat.ts +141 -0
  423. package/src/worker/mcp-jsonrpc.ts +11 -29
  424. package/src/worker/mcp-removed-protocol.ts +17 -0
  425. package/src/worker/mcp-response-proxy.ts +135 -0
  426. package/src/worker/mcp-response-stream.ts +65 -0
  427. package/src/worker/mcp-stale-schema-compat.ts +57 -0
  428. package/src/worker/mcp-stream-proxy-contract.ts +48 -0
  429. package/src/worker/mcp-tool-call-input.ts +23 -0
  430. package/src/worker/nonce-store.ts +33 -35
  431. package/src/worker/oauth-authorization-page.ts +21 -1
  432. package/src/worker/oauth-client-admin.ts +52 -0
  433. package/src/worker/oauth-client-contract.ts +38 -0
  434. package/src/worker/oauth-controller.ts +107 -47
  435. package/src/worker/oauth-field-contract.ts +31 -0
  436. package/src/worker/oauth-record-contract.ts +7 -0
  437. package/src/worker/oauth-refresh-authority.ts +27 -0
  438. package/src/worker/oauth-refresh-exchange.ts +162 -0
  439. package/src/worker/oauth-refresh-families.ts +130 -27
  440. package/src/worker/oauth-refresh-persistence.ts +116 -0
  441. package/src/worker/oauth-state.ts +33 -18
  442. package/src/worker/oauth-store-validation.ts +131 -0
  443. package/src/worker/oauth-token-derivation.ts +33 -0
  444. package/src/worker/oauth-token-issuance.ts +119 -0
  445. package/src/worker/oauth-tokens.ts +56 -190
  446. package/src/worker/observability.ts +38 -5
  447. package/src/worker/pending-admission.ts +15 -0
  448. package/src/worker/pending-call-capacity.ts +108 -0
  449. package/src/worker/pending-call-contract.ts +42 -5
  450. package/src/worker/pending-call-deadlines.ts +75 -0
  451. package/src/worker/pending-calls.ts +131 -125
  452. package/src/worker/runtime-alarm-storage.ts +37 -0
  453. package/src/worker/runtime-alarm.ts +136 -0
  454. package/src/worker/server-info-activity.ts +36 -0
  455. package/src/worker/server-info-tool-delivery.ts +15 -0
  456. package/src/worker/server-info.ts +168 -0
  457. package/src/worker/tool-catalog.ts +47 -1
  458. package/src/worker/tool-timeout.ts +75 -14
  459. package/src/worker/websocket-protocol.ts +26 -2
  460. package/src/worker/worker-edge-guard.ts +90 -0
  461. package/src/worker/worker-edge-log.ts +65 -0
  462. package/src/worker/worker-entry.ts +52 -0
  463. package/src/worker/worker-mcp-config.ts +23 -0
  464. package/src/worker/worker-metadata.ts +48 -0
  465. package/src/worker/worker-rate-limit-key.ts +30 -0
  466. package/src/worker/worker-runtime-config.ts +20 -0
  467. package/src/worker/worker-static-routes.ts +54 -0
  468. package/src/worker/worker-task-lifetime.ts +18 -0
  469. package/tsconfig.local.json +17 -1
  470. package/wrangler.jsonc +13 -0
  471. package/src/local/cli-approval.mjs +0 -117
  472. package/src/local/operation-state-lock.mjs +0 -92
  473. package/src/worker/mcp-session.ts +0 -72
@@ -0,0 +1,198 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawnSync } from "node:child_process";
4
+ import { createHash } from "node:crypto";
5
+ import { readFileSync } from "node:fs";
6
+ import { dirname, join, resolve } from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
+ import { defaultStateRoot, expandHome } from "../src/local/state.mjs";
9
+ import { ACTIVATION_SCHEMA_VERSION, writePrereleaseActivation } from "./prerelease-activation.mjs";
10
+ import { computePromotionContentDigest } from "./promotion-digest.mjs";
11
+ import { readGithubPrerelease, readPublishedNpmPrerelease } from "./published-release.mjs";
12
+ import { verifyCurrentReleaseAcceptance } from "./release-acceptance.mjs";
13
+ import { assertSoakEligiblePrerelease } from "./release-channel.mjs";
14
+ import { persistentActivationSpawnOptions, validateActivationRecoveryPayload } from "./persistent-activation-process.mjs";
15
+ import { createHardenedNpmSession, settleHardenedNpmSession } from "./hardened-npm-session.mjs";
16
+ import { nestedNpmEnvironment } from "../src/local/npm-environment.mjs";
17
+ import { inspectGlobalPackageInstallation } from "./global-package-installation.mjs";
18
+ import { resolveNpmGlobalPrefix } from "./npm-global-prefix.mjs";
19
+ import { releaseCommandFailure, releaseDiagnostic, releaseDiagnosticEvent } from "./release-diagnostic.mjs";
20
+ import { withReleaseRuntimeLock } from "../src/local/release-runtime-lock.mjs";
21
+
22
+ const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
23
+ const lifecycleNpmCli = process.env.npm_execpath;
24
+ let npmCli = "";
25
+ let npmSession = null;
26
+ let previousInstallation = null;
27
+ let globalInstallAttempted = false;
28
+ let globalInstallCompleted = false;
29
+ let installedPrerelease = "";
30
+ if (!lifecycleNpmCli) fail("published prerelease installation must run through npm");
31
+
32
+ try {
33
+ if (!process.argv.includes("--allow-worker-deploy")) {
34
+ throw new Error("published prerelease activation updates the global package, same-name Worker, and login daemon; rerun with --allow-worker-deploy");
35
+ }
36
+ const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
37
+ const requested = argumentValue("--version") || pkg.version;
38
+ const prerelease = assertSoakEligiblePrerelease(requested);
39
+ if (pkg.version !== prerelease.raw) {
40
+ throw new Error(`source checkout version ${pkg.version} does not match requested prerelease ${prerelease.raw}`);
41
+ }
42
+ const globalPrefix = resolveNpmGlobalPrefix(lifecycleNpmCli, { cwd: root, env: process.env });
43
+ const acceptance = verifyCurrentReleaseAcceptance(root, { npmCli: lifecycleNpmCli, env: process.env });
44
+ if (!acceptance.required || acceptance.metadata.package_version !== prerelease.raw) {
45
+ throw new Error("published prerelease installation requires the locally accepted exact prerelease source");
46
+ }
47
+ const promotionDigest = computePromotionContentDigest(root, { npmCli: lifecycleNpmCli });
48
+ if (acceptance.record.promotion_content_sha256 !== promotionDigest) {
49
+ throw new Error("current source promotion digest does not match local candidate acceptance");
50
+ }
51
+ readGithubPrerelease(prerelease.raw, { expectedArtifactSha256: acceptance.artifactSha256 });
52
+ npmSession = await createHardenedNpmSession();
53
+ npmCli = npmSession.cli;
54
+ const published = readPublishedNpmPrerelease(pkg.name, prerelease.raw, prerelease.npmTag, { npmCli, env: process.env });
55
+ if (published.integrity !== acceptance.metadata.integrity || published.shasum !== acceptance.metadata.shasum) {
56
+ throw new Error("npm prerelease bytes do not match the locally accepted candidate");
57
+ }
58
+
59
+ const stateRoot = resolve(expandHome(argumentValue("--state-dir") || defaultStateRoot()));
60
+ await withReleaseRuntimeLock(stateRoot, async () => {
61
+ previousInstallation = currentGlobalInstallation(pkg.name, globalPrefix);
62
+ globalInstallAttempted = true;
63
+ runNpm([
64
+ "install", "--dry-run=false", "--workspaces=false", "--ignore-scripts=false",
65
+ "--global", "--prefix", globalPrefix,
66
+ "--omit=optional", "--include=prod", "--package-lock-only=false",
67
+ "--allow-scripts=esbuild,workerd,sharp,fsevents",
68
+ `${pkg.name}@${prerelease.raw}`,
69
+ ]);
70
+ globalInstallCompleted = true;
71
+ const installed = currentGlobalInstallation(pkg.name, globalPrefix);
72
+ if (!installed || installed.version !== prerelease.raw) {
73
+ throw new Error(`global prerelease installation did not converge on ${prerelease.raw}`);
74
+ }
75
+ installedPrerelease = prerelease.raw;
76
+ disposeNpmSession();
77
+
78
+ const forwarded = forwardedActivationArgs();
79
+ const activation = runActivation(installed.entry, ["activate", ...forwarded, "--state-dir", stateRoot, "--json"]);
80
+ if (activation.version !== prerelease.raw || activation.daemon?.version !== prerelease.raw || activation.worker?.health?.version !== prerelease.raw) {
81
+ throw new Error("published prerelease activation did not converge on the exact registry version");
82
+ }
83
+ const recovery = validateActivationRecoveryPayload(activation);
84
+ const recordPath = writePrereleaseActivation({
85
+ schema_version: ACTIVATION_SCHEMA_VERSION,
86
+ package_name: pkg.name,
87
+ package_version: prerelease.raw,
88
+ source: "npm-prerelease",
89
+ shasum: published.shasum,
90
+ integrity: published.integrity,
91
+ promotion_content_sha256: promotionDigest,
92
+ activated_at: new Date().toISOString(),
93
+ published_at: published.publishedAt,
94
+ npm_dist_tag: prerelease.npmTag,
95
+ workspace_hash: workspaceHash(activation.workspace),
96
+ runtime_entry: installed.entry,
97
+ ...(recovery.recovered ? {
98
+ activation_recovered: true,
99
+ activation_recovery_reason: recovery.reason,
100
+ activation_recovery_detail: recovery.detail,
101
+ } : {}),
102
+ ...(previousInstallation ? { global_package_rollback_baseline: previousInstallation } : {}),
103
+ }, stateRoot);
104
+
105
+ if (recovery.recovered) {
106
+ console.warn(`Published prerelease activation used verified candidate-service recovery (${recovery.reason}): ${recovery.detail}`);
107
+ }
108
+ console.log(`Published prerelease activated: ${prerelease.raw}`);
109
+ console.log(`Worker and login daemon version: ${activation.version}`);
110
+ console.log(`Soak activation record: ${recordPath}`);
111
+ console.log("Use this prerelease normally. Any blocking issue requires a new beta/rc version and restarts the soak clock.");
112
+ });
113
+ } catch (error) {
114
+ const settled = settleNpmSession(error);
115
+ const message = releaseDiagnostic(settled?.message || settled, 1600);
116
+ if (installedPrerelease) {
117
+ const previousVersion = previousInstallation?.version || "unknown";
118
+ fail(`${message}. The global package is now ${installedPrerelease}, but Worker/service activation may not have converged. Previous global version: ${previousVersion}. Preserve state and logs; fix forward with the exact prerelease or restore package, Worker, service definition, browser extension, and state as one verified unit.`);
119
+ }
120
+ if (globalInstallAttempted) {
121
+ const previousVersion = previousInstallation?.version || "unknown";
122
+ const installState = globalInstallCompleted
123
+ ? "The global installation command completed, but the exact installed package identity was not verified"
124
+ : "The global installation command was attempted and may have changed the installed package";
125
+ fail(`${message}. ${installState}. Previous global version: ${previousVersion}. Inspect the configured global prefix before retrying or activating any runtime.`);
126
+ }
127
+ fail(message);
128
+ }
129
+
130
+ function disposeNpmSession() {
131
+ const error = settleNpmSession();
132
+ if (error) throw error;
133
+ }
134
+
135
+ function settleNpmSession(primaryError = null) {
136
+ const session = npmSession;
137
+ npmSession = null;
138
+ return settleHardenedNpmSession(session, primaryError, "published prerelease failed and hardened npm temporary cleanup was incomplete");
139
+ }
140
+
141
+ function currentGlobalInstallation(packageName, globalPrefix) {
142
+ const globalRoot = runNpm(["root", "--json=false", "--parseable=false", "--workspaces=false", "--global", "--prefix", globalPrefix]).stdout.trim();
143
+ return inspectGlobalPackageInstallation(globalRoot, packageName);
144
+ }
145
+
146
+ function runActivation(entry, args) {
147
+ const result = spawnSync(
148
+ process.execPath,
149
+ [entry, ...args],
150
+ persistentActivationSpawnOptions({ cwd: root, env: nestedNpmEnvironment(process.env) }),
151
+ );
152
+ if (result.error || result.status !== 0) throw new Error(releaseCommandFailure("machine-mcp", ["activate"], result, { maxChars: 1600 }));
153
+ try { return JSON.parse(result.stdout); } catch { throw new Error("prerelease runtime activation did not return valid JSON"); }
154
+ }
155
+
156
+ function runNpm(args) {
157
+ const result = spawnSync(process.execPath, [npmCli, ...args], {
158
+ cwd: root,
159
+ env: nestedNpmEnvironment(process.env),
160
+ encoding: "utf8",
161
+ timeout: 300_000,
162
+ killSignal: "SIGKILL",
163
+ windowsHide: true,
164
+ });
165
+ if (result.error || result.status !== 0) throw new Error(releaseCommandFailure("npm", args, result, { maxChars: 1600 }));
166
+ return result;
167
+ }
168
+
169
+ function forwardedActivationArgs() {
170
+ const out = [];
171
+ const skipWithValue = new Set(["--version", "--state-dir"]);
172
+ for (let index = 2; index < process.argv.length; index += 1) {
173
+ const value = process.argv[index];
174
+ if (value === "--allow-worker-deploy") continue;
175
+ if (skipWithValue.has(value)) { index += 1; continue; }
176
+ if (["--version=", "--state-dir="].some((prefix) => value.startsWith(prefix))) continue;
177
+ if (value === "--json" || value.startsWith("--json=")) continue;
178
+ out.push(value);
179
+ }
180
+ return out;
181
+ }
182
+
183
+ function argumentValue(name) {
184
+ const exact = process.argv.find((value) => value.startsWith(`${name}=`));
185
+ if (exact) return exact.slice(name.length + 1);
186
+ const index = process.argv.indexOf(name);
187
+ return index >= 0 ? process.argv[index + 1] : "";
188
+ }
189
+
190
+ function workspaceHash(workspace) {
191
+ const value = process.platform === "win32" ? String(workspace).toLowerCase() : String(workspace);
192
+ return createHash("sha256").update(value).digest("hex").slice(0, 24);
193
+ }
194
+
195
+ function fail(message) {
196
+ console.error(JSON.stringify(releaseDiagnosticEvent("prerelease.install.failed", message, 1800)));
197
+ process.exit(1);
198
+ }
@@ -5,7 +5,6 @@ import {
5
5
  mkdtempSync,
6
6
  readFileSync,
7
7
  rmSync,
8
- writeFileSync,
9
8
  } from "node:fs";
10
9
  import { spawnSync } from "node:child_process";
11
10
  import { tmpdir } from "node:os";
@@ -16,74 +15,120 @@ import {
16
15
  ACCEPTANCE_SCHEMA_VERSION,
17
16
  acceptancePath,
18
17
  packProject,
19
- requiresLocalAcceptance,
20
18
  verifyAcceptanceRecord,
21
19
  verifyCurrentReleaseAcceptance,
22
20
  verifyTarball,
23
21
  } from "./release-acceptance.mjs";
22
+ import { computePromotionContentDigest } from "./promotion-digest.mjs";
23
+ import { parseReleaseVersion } from "./release-channel.mjs";
24
+ import { validateCandidateManifest } from "./release-candidate-manifest.mjs";
25
+ import { replaceFileAtomicallySync } from "../src/local/exclusive-file.mjs";
26
+ import { resolveTrustedGitExecutable } from "../src/local/trusted-git-executable.mjs";
27
+ import { nestedNpmEnvironment } from "../src/local/npm-environment.mjs";
28
+ import { releaseCommandFailure, releaseDiagnosticEvent } from "./release-diagnostic.mjs";
29
+ import { createHardenedNpmSession } from "./hardened-npm-session.mjs";
30
+ import { readReleaseOAuthCanaryEvidence } from "./release-oauth-canary-evidence.mjs";
31
+ import { assertFreshFullVerificationReceipt } from "./verification-state.mjs";
24
32
 
25
33
  const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
26
34
  const candidateDirectory = join(root, ".release-candidate");
27
35
  const candidateManifestPath = join(candidateDirectory, "manifest.json");
28
36
  const mode = process.argv[2] || "--verify";
37
+ const git = resolveTrustedGitExecutable({ workspace: root });
29
38
 
30
39
  try {
31
- if (mode === "--prepare") prepareCandidate();
32
- else if (mode === "--record") recordAcceptance();
33
- else if (mode === "--verify") verifyAcceptance();
34
- else fail("usage: node scripts/local-release-acceptance.mjs [--prepare|--record|--verify]");
40
+ await runWithHardenedNpm();
35
41
  } catch (error) {
36
42
  fail(error?.message || error);
37
43
  }
38
44
 
39
- function prepareCandidate() {
40
- const pkg = readPackage();
41
- if (!requiresLocalAcceptance(pkg.version)) {
42
- throw new Error(`local acceptance policy begins at ${pkg.name} 1.2.8; current version is ${pkg.version}`);
45
+ async function runWithHardenedNpm() {
46
+ let session = null;
47
+ let primaryError = null;
48
+ try {
49
+ session = await createHardenedNpmSession();
50
+ if (mode === "--prepare") prepareCandidate(session.cli);
51
+ else if (mode === "--record") recordAcceptance(session.cli);
52
+ else if (mode === "--verify") verifyAcceptance(session.cli);
53
+ else throw new Error("usage: node scripts/local-release-acceptance.mjs [--prepare|--record|--verify]");
54
+ } catch (error) {
55
+ primaryError = error;
56
+ }
57
+ let cleanupError = null;
58
+ try { session?.dispose(); } catch (error) { cleanupError = error; }
59
+ if (primaryError && cleanupError) {
60
+ throw new AggregateError([primaryError, cleanupError], "local release acceptance failed and hardened npm cleanup was incomplete");
43
61
  }
44
- rmSync(candidateDirectory, { recursive: true, force: true });
62
+ if (primaryError) throw primaryError;
63
+ if (cleanupError) throw cleanupError;
64
+ }
65
+
66
+ function prepareCandidate(npmCli) {
67
+ const pkg = readPackage();
68
+ const fullVerification = assertFreshFullVerificationReceipt(root);
69
+ rmSync(candidateDirectory, { recursive: true, force: true, maxRetries: 3, retryDelay: 50 });
45
70
  mkdirSync(candidateDirectory, { recursive: true });
46
- const metadata = packProject(root, candidateDirectory);
71
+ const metadata = packProject(root, candidateDirectory, { npmCli, env: process.env });
47
72
  const manifest = {
48
73
  schema_version: ACCEPTANCE_SCHEMA_VERSION,
49
74
  result: "pending",
50
75
  ...metadata,
76
+ promotion_content_sha256: computePromotionContentDigest(root, { npmCli }),
51
77
  prepared_at: new Date().toISOString(),
52
78
  };
53
- writeFileSync(candidateManifestPath, `${JSON.stringify(manifest, null, 2)}\n`, { mode: 0o600 });
79
+ replaceFileAtomicallySync(candidateManifestPath, `${JSON.stringify(manifest, null, 2)}\n`, { mode: 0o600 });
54
80
  const phrase = confirmationPhrase(pkg.name, pkg.version);
55
81
  console.log(`Release candidate created: ${join(candidateDirectory, metadata.filename)}`);
56
- console.log("After the repository owner explicitly authorizes this exact candidate in the active conversation, the coding agent starts it through Machine Bridge with:");
57
- console.log("npm run release:candidate:start -- --allow-worker-deploy");
58
- console.log("The owner does not need to run a terminal authorization command. The coding agent keeps the candidate running while verifying connection readiness and representative functionality through Machine Bridge.");
59
- console.log("After that observed live verification succeeds, the coding agent records acceptance with:");
82
+ console.log(`Reused exact-tree full verification from ${fullVerification.verified_at}.`);
83
+ parseReleaseVersion(pkg.version);
84
+ console.log("Before live activation, the coding agent must reverify current source identity, package modes, tarball integrity, and disposable installability with direct Node argv (not npm lifecycle):");
85
+ console.log("node scripts/start-release-candidate.mjs --install-only");
86
+ console.log("Only after that non-live preflight succeeds and the repository owner explicitly authorizes activation may the owner or authorized agent run this exact persistent command:");
87
+ console.log("npm run release:candidate:activate -- --allow-worker-deploy");
88
+ console.log("The guarded command installs the exact candidate in the private state root, updates the same-name Worker, verifies candidate relay readiness, replaces the login daemon, verifies the background handoff, and exits while the service remains active.");
89
+ console.log("After activation, the coding agent derives the activated package root from the activation record runtime_entry and runs its packaged canary as direct Node argv from this repository cwd:");
90
+ console.log("node <activated-runtime-package>/scripts/release-oauth-canary.mjs --allow-live-oauth-canary");
91
+ console.log("For prereleases, the workspace script and npm lifecycle forms are source/developer paths only: they receive ordinary accounting and fail runtime-provenance evidence because the executing package must match activation runtime_entry.");
92
+ console.log("Only after the canary and observed live verification succeed does the coding agent record acceptance with:");
60
93
  console.log(`npm run release:accept -- --confirm \"${phrase}\"`);
61
94
  console.log("Automated tests alone do not authorize acceptance or the first GitHub push.");
62
95
  }
63
96
 
64
- function recordAcceptance() {
97
+ function recordAcceptance(npmCli) {
65
98
  const pkg = readPackage();
66
99
  const supplied = argumentValue("--confirm");
67
100
  const expected = confirmationPhrase(pkg.name, pkg.version);
68
101
  if (supplied !== expected) {
69
- throw new Error(`interactive candidate verification confirmation must exactly match: ${expected}`);
70
- }
71
- const pending = readJson(candidateManifestPath, "release candidate manifest");
72
- if (pending.result !== "pending" || pending.package_name !== pkg.name || pending.package_version !== pkg.version) {
73
- throw new Error("release candidate manifest does not match the current package");
102
+ throw new Error(`candidate verification confirmation must exactly match: ${expected}`);
74
103
  }
104
+ const pending = validateCandidateManifest(readJson(candidateManifestPath, "release candidate manifest"), {
105
+ packageName: pkg.name,
106
+ packageVersion: pkg.version,
107
+ });
75
108
  verifyTarball(join(candidateDirectory, pending.filename), pending);
109
+ readReleaseOAuthCanaryEvidence(root, {
110
+ package_name: pending.package_name,
111
+ package_version: pending.package_version,
112
+ shasum: pending.shasum,
113
+ integrity: pending.integrity,
114
+ promotion_content_sha256: pending.promotion_content_sha256,
115
+ });
76
116
 
77
117
  const verificationDirectory = join(candidateDirectory, "verification");
78
- rmSync(verificationDirectory, { recursive: true, force: true });
118
+ rmSync(verificationDirectory, { recursive: true, force: true, maxRetries: 3, retryDelay: 50 });
79
119
  mkdirSync(verificationDirectory, { recursive: true });
80
- const current = packProject(root, verificationDirectory);
120
+ const current = packProject(root, verificationDirectory, { npmCli, env: process.env });
81
121
  for (const key of ["package_name", "package_version", "filename", "shasum", "integrity"]) {
82
122
  if (pending[key] !== current[key]) {
83
123
  throw new Error(`source changed after candidate preparation: ${key} no longer matches`);
84
124
  }
85
125
  }
86
126
 
127
+ const promotionDigest = computePromotionContentDigest(root, { npmCli });
128
+ if (pending.promotion_content_sha256 !== promotionDigest) {
129
+ throw new Error("source changed after candidate preparation: promotion content digest no longer matches");
130
+ }
131
+
87
132
  const record = {
88
133
  schema_version: ACCEPTANCE_SCHEMA_VERSION,
89
134
  result: "passed",
@@ -94,18 +139,19 @@ function recordAcceptance() {
94
139
  shasum: current.shasum,
95
140
  integrity: current.integrity,
96
141
  accepted_at: new Date().toISOString(),
97
- package_content_sha256: computePortablePackageDigest(),
142
+ package_content_sha256: computePortablePackageDigest(npmCli),
143
+ promotion_content_sha256: promotionDigest,
98
144
  };
99
145
  verifyAcceptanceRecord(record, current);
100
146
  const path = acceptancePath(root, pkg.version);
101
147
  mkdirSync(dirname(path), { recursive: true });
102
- writeFileSync(path, `${JSON.stringify(record, null, 2)}\n`, "utf8");
103
- console.log(`Interactive local candidate acceptance recorded: ${path}`);
148
+ replaceFileAtomicallySync(path, `${JSON.stringify(record, null, 2)}\n`, { mode: 0o644 });
149
+ console.log(`Local candidate acceptance recorded: ${path}`);
104
150
  console.log("Commit this record with the candidate. Any packaged-file change invalidates it.");
105
151
  }
106
152
 
107
- function verifyAcceptance() {
108
- const result = verifyCurrentReleaseAcceptance(root);
153
+ function verifyAcceptance(npmCli) {
154
+ const result = verifyCurrentReleaseAcceptance(root, { npmCli, env: process.env });
109
155
  if (!result.required) {
110
156
  console.log(`Local release acceptance is not required for ${result.version}.`);
111
157
  return;
@@ -113,18 +159,22 @@ function verifyAcceptance() {
113
159
  console.log(`Local release acceptance matches ${result.metadata.filename} (${result.metadata.shasum}).`);
114
160
  }
115
161
 
116
- function computePortablePackageDigest() {
117
- const npmCli = process.env.npm_execpath;
118
- if (!npmCli) throw new Error("portable package digest requires npm_execpath");
162
+ function computePortablePackageDigest(npmCli) {
163
+ if (!npmCli) throw new Error("portable package digest requires a hardened npm CLI");
119
164
  const temporary = mkdtempSync(join(tmpdir(), "mbm-release-index-"));
120
165
  const indexPath = join(temporary, "index");
121
- const env = { ...process.env, GIT_INDEX_FILE: indexPath };
166
+ const env = { ...nestedNpmEnvironment(process.env), GIT_INDEX_FILE: indexPath };
167
+ let digest = "";
168
+ let primaryError = null;
122
169
  try {
123
- runChecked("git", ["read-tree", "HEAD"], { env });
124
- runChecked("git", ["add", "--all", "--", "."], { env });
170
+ runChecked(git, ["read-tree", "HEAD"], { env });
171
+ runChecked(git, ["add", "--all", "--", "."], { env });
125
172
  const packed = runChecked(process.execPath, [
126
173
  npmCli,
127
174
  "pack",
175
+ "--workspaces=false",
176
+ "--global=false",
177
+ "--prefix", root,
128
178
  "--ignore-scripts",
129
179
  "--silent",
130
180
  "--dry-run",
@@ -134,12 +184,20 @@ function computePortablePackageDigest() {
134
184
  join(root, ".github", "scripts", "verify-release-acceptance.mjs"),
135
185
  "--print-digest",
136
186
  ], { env, input: packed.stdout });
137
- const digest = verifier.stdout.trim();
187
+ digest = verifier.stdout.trim();
138
188
  if (!/^[0-9a-f]{64}$/.test(digest)) throw new Error("portable package digest output is invalid");
139
- return digest;
140
- } finally {
141
- rmSync(temporary, { recursive: true, force: true });
189
+ } catch (error) {
190
+ primaryError = error;
191
+ }
192
+ let cleanupError = null;
193
+ try { rmSync(temporary, { recursive: true, force: true }); }
194
+ catch (error) { cleanupError = error; }
195
+ if (primaryError && cleanupError) {
196
+ throw new AggregateError([primaryError, cleanupError], "portable package digest failed and temporary cleanup was incomplete");
142
197
  }
198
+ if (primaryError) throw primaryError;
199
+ if (cleanupError) throw cleanupError;
200
+ return digest;
143
201
  }
144
202
 
145
203
  function runChecked(file, args, { env = process.env, input } = {}) {
@@ -148,12 +206,12 @@ function runChecked(file, args, { env = process.env, input } = {}) {
148
206
  encoding: "utf8",
149
207
  env,
150
208
  input,
209
+ timeout: 5 * 60 * 1000,
210
+ killSignal: "SIGKILL",
211
+ maxBuffer: 32 * 1024 * 1024,
151
212
  windowsHide: true,
152
213
  });
153
- if (result.error) throw result.error;
154
- if (result.status !== 0) {
155
- throw new Error(`${file} ${args[0] || ""} failed: ${String(result.stderr || result.stdout).trim()}`);
156
- }
214
+ if (result.error || result.status !== 0) throw new Error(releaseCommandFailure(file, args, result));
157
215
  return result;
158
216
  }
159
217
 
@@ -181,6 +239,6 @@ function confirmationPhrase(name, version) {
181
239
  }
182
240
 
183
241
  function fail(message) {
184
- console.error(`local release acceptance failed: ${message}`);
242
+ console.error(JSON.stringify(releaseDiagnosticEvent("release.acceptance.failed", message, 1200)));
185
243
  process.exit(1);
186
244
  }