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,23 @@
1
+ {
2
+ "name": "machine-bridge-mcp-wrangler-toolchain",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "description": "Integrity-locked private Wrangler control-plane toolchain for Machine Bridge.",
6
+ "engines": {
7
+ "node": ">=26.0.0",
8
+ "npm": ">=12.0.0"
9
+ },
10
+ "dependencies": {
11
+ "wrangler": "4.120.0"
12
+ },
13
+ "overrides": {
14
+ "sharp": "0.35.3",
15
+ "undici": "7.29.0"
16
+ },
17
+ "allowScripts": {
18
+ "esbuild@0.28.1": true,
19
+ "fsevents": false,
20
+ "sharp@0.35.3": true,
21
+ "workerd@1.20260801.1": true
22
+ }
23
+ }
@@ -0,0 +1,135 @@
1
+ import { lstatSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { replaceFileAtomicallySync } from "./exclusive-file.mjs";
4
+ import {
5
+ isPrivateToolchainIntegrityError,
6
+ privateToolchainIntegrityError,
7
+ throwOperationalOrIntegrity,
8
+ } from "./private-toolchain-integrity.mjs";
9
+ import { ensureOwnerOnlyDirectorySync, readBoundedRegularFileSync } from "./secure-file.mjs";
10
+
11
+ const TOOLCHAIN_SCHEMA_VERSION = 1;
12
+ const TOOLCHAIN_MARKER = ".machine-bridge-mcp-toolchain.json";
13
+ const MAX_TEMPLATE_BYTES = 2 * 1024 * 1024;
14
+ const MAX_TREE_NODES = 20_000;
15
+
16
+ export async function verifyWranglerToolchain(descriptor, execute, required = false) {
17
+ try {
18
+ let info;
19
+ try { info = lstatSync(descriptor.root); }
20
+ catch (error) { throwOperationalOrIntegrity(error, "Wrangler toolchain directory is missing or structurally invalid"); }
21
+ if (info.isSymbolicLink() || !info.isDirectory()) {
22
+ throw privateToolchainIntegrityError("Wrangler toolchain path is not a real directory");
23
+ }
24
+ ensureOwnerOnlyDirectorySync(descriptor.root);
25
+ requireExactFile(path.join(descriptor.root, "package.json"), descriptor.packageBytes, "Wrangler toolchain package manifest");
26
+ requireExactFile(path.join(descriptor.root, "package-lock.json"), descriptor.lockBytes, "Wrangler toolchain lockfile");
27
+ const versionResult = await execute(["--version"]);
28
+ if (Number(String(versionResult.stdout).trim().split(".")[0]) < 12) throw new Error("Wrangler toolchain requires npm 12 or newer");
29
+ const treeResult = await execute(
30
+ ["ls", "wrangler", "undici", "sharp", "--workspaces=false", "--all", "--json"],
31
+ true,
32
+ );
33
+ if (treeResult.code === 124) {
34
+ const timeout = new Error("Wrangler toolchain npm ls timed out");
35
+ timeout.code = "ETIMEDOUT";
36
+ throw timeout;
37
+ }
38
+ let tree;
39
+ try { tree = JSON.parse(treeResult.stdout); }
40
+ catch {
41
+ throw new Error(`Wrangler toolchain npm ls failed (${treeResult.code}): ${String(treeResult.stderr || "invalid JSON").slice(0, 600)}`);
42
+ }
43
+ validateInstalledTree(tree, descriptor.versions);
44
+ if (treeResult.code !== 0) throw new Error(`Wrangler toolchain npm ls exited ${treeResult.code} without dependency problems`);
45
+ return true;
46
+ } catch (error) {
47
+ if (required || !isPrivateToolchainIntegrityError(error)) throw error;
48
+ return false;
49
+ }
50
+ }
51
+
52
+ export function readWranglerToolchainMarker(root) {
53
+ let bytes;
54
+ try {
55
+ bytes = readBoundedRegularFileSync(
56
+ path.join(root, TOOLCHAIN_MARKER), 16 * 1024, "Wrangler toolchain marker",
57
+ { verifyPathIdentity: true, rejectMultipleLinks: true },
58
+ );
59
+ } catch (error) {
60
+ if (error?.code === "ENOENT") return null;
61
+ throwOperationalOrIntegrity(error, "Wrangler toolchain marker is structurally invalid");
62
+ }
63
+ try { return parseJsonObject(bytes, "Wrangler toolchain marker"); }
64
+ catch (error) { throw privateToolchainIntegrityError(error.message, error); }
65
+ }
66
+
67
+ export function wranglerToolchainMarkerMatches(marker, descriptor) {
68
+ return Boolean(marker)
69
+ && marker.schema_version === TOOLCHAIN_SCHEMA_VERSION
70
+ && marker.digest === descriptor.digest
71
+ && marker.wrangler === descriptor.versions.wrangler
72
+ && marker.undici === descriptor.versions.undici
73
+ && marker.sharp === descriptor.versions.sharp
74
+ && Number.isFinite(Date.parse(String(marker.audited_at || "")));
75
+ }
76
+
77
+ export function writeWranglerToolchainMarker(descriptor, nowMs) {
78
+ const auditedAt = new Date(Number(nowMs)).toISOString();
79
+ if (!Number.isFinite(Date.parse(auditedAt))) throw new Error("Wrangler toolchain audit timestamp is invalid");
80
+ replaceFileAtomicallySync(path.join(descriptor.root, TOOLCHAIN_MARKER), `${JSON.stringify({
81
+ schema_version: TOOLCHAIN_SCHEMA_VERSION,
82
+ digest: descriptor.digest,
83
+ wrangler: descriptor.versions.wrangler,
84
+ undici: descriptor.versions.undici,
85
+ sharp: descriptor.versions.sharp,
86
+ audited_at: auditedAt,
87
+ }, null, 2)}\n`, { mode: 0o600 });
88
+ }
89
+
90
+ function validateInstalledTree(tree, versions) {
91
+ if (!tree || typeof tree !== "object" || Array.isArray(tree)) throw privateToolchainIntegrityError("Wrangler toolchain dependency tree is invalid");
92
+ if (Array.isArray(tree.problems) && tree.problems.length) throw privateToolchainIntegrityError("Wrangler toolchain dependency tree contains invalid edges");
93
+ const found = new Map([["wrangler", []], ["undici", []], ["sharp", []]]);
94
+ const counter = { value: 0 };
95
+ visitDependencyTree(tree.dependencies, found, counter, 0);
96
+ for (const [name, expected] of Object.entries(versions)) {
97
+ const actual = found.get(name) || [];
98
+ if (!actual.length || actual.some((version) => version !== expected)) {
99
+ throw privateToolchainIntegrityError(`Wrangler toolchain ${name} versions ${actual.join(",") || "missing"} do not match ${expected}`);
100
+ }
101
+ }
102
+ }
103
+
104
+ function visitDependencyTree(dependencies, found, counter, depth) {
105
+ if (!dependencies || typeof dependencies !== "object" || Array.isArray(dependencies)) return;
106
+ if (depth > 64) throw privateToolchainIntegrityError("Wrangler toolchain dependency tree exceeds the depth limit");
107
+ for (const [name, value] of Object.entries(dependencies)) {
108
+ if (!value || typeof value !== "object" || Array.isArray(value)) continue;
109
+ counter.value += 1;
110
+ if (counter.value > MAX_TREE_NODES) throw privateToolchainIntegrityError("Wrangler toolchain dependency tree exceeds the node limit");
111
+ if (found.has(name)) found.get(name).push(String(value.version || ""));
112
+ visitDependencyTree(value.dependencies, found, counter, depth + 1);
113
+ }
114
+ }
115
+
116
+ function requireExactFile(file, expected, label) {
117
+ let actual;
118
+ try {
119
+ actual = readBoundedRegularFileSync(file, MAX_TEMPLATE_BYTES, label, {
120
+ verifyPathIdentity: true,
121
+ rejectMultipleLinks: true,
122
+ });
123
+ } catch (error) {
124
+ throwOperationalOrIntegrity(error, `${label} is missing or structurally invalid`);
125
+ }
126
+ if (!actual.equals(expected)) throw privateToolchainIntegrityError(`${label} does not match the packaged template`);
127
+ }
128
+
129
+ function parseJsonObject(bytes, label) {
130
+ let value;
131
+ try { value = JSON.parse(Buffer.from(bytes).toString("utf8")); }
132
+ catch { throw new Error(`${label} is not valid JSON`); }
133
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object`);
134
+ return value;
135
+ }
@@ -0,0 +1,188 @@
1
+ import { createHash } from "node:crypto";
2
+ import {
3
+ existsSync,
4
+ rmSync,
5
+ writeFileSync,
6
+ } from "node:fs";
7
+ import path from "node:path";
8
+ import { ensureHardenedNpm } from "./hardened-npm.mjs";
9
+ import { withOwnerStateLock } from "./owner-state-lock.mjs";
10
+ import { nestedNpmEnvironment } from "./npm-environment.mjs";
11
+ import { resolveNpmCli } from "./npm-cli.mjs";
12
+ import { isPrivateToolchainIntegrityError } from "./private-toolchain-integrity.mjs";
13
+ import {
14
+ readWranglerToolchainMarker,
15
+ verifyWranglerToolchain,
16
+ wranglerToolchainMarkerMatches,
17
+ writeWranglerToolchainMarker,
18
+ } from "./wrangler-toolchain-verification.mjs";
19
+ import { ensureOwnerOnlyDirectorySync, readBoundedRegularFileSync } from "./secure-file.mjs";
20
+ import { defaultStateRoot } from "./state.mjs";
21
+ import { withToolchainOperationLock } from "./toolchain-operation-lock.mjs";
22
+ import { packageRoot as defaultPackageRoot } from "./package-identity.mjs";
23
+
24
+ const TOOLCHAIN_DIRECTORY = "toolchains";
25
+ const TOOLCHAIN_LOCK = "wrangler-toolchain.lock";
26
+ const DEFAULT_AUDIT_MAX_AGE_MS = 24 * 60 * 60 * 1000;
27
+ const MAX_CLOCK_SKEW_MS = 5 * 60 * 1000;
28
+ const INSTALL_TIMEOUT_MS = 10 * 60 * 1000;
29
+ const AUDIT_TIMEOUT_MS = 2 * 60 * 1000;
30
+ const MAX_TEMPLATE_BYTES = 2 * 1024 * 1024, MAX_COMMAND_OUTPUT_BYTES = 4 * 1024 * 1024;
31
+
32
+ export async function ensureWranglerToolchain(options = {}) {
33
+ const runCommand = options.runCommand;
34
+ if (typeof runCommand !== "function") throw new TypeError("Wrangler toolchain requires an executable runner");
35
+ const descriptor = wranglerToolchainDescriptor(options);
36
+ const explicitNpmCli = options.npmCli ? resolveNpmCli(options) : "";
37
+ const now = typeof options.now === "function" ? options.now : Date.now;
38
+ const auditMaxAgeMs = positiveInteger(options.auditMaxAgeMs, DEFAULT_AUDIT_MAX_AGE_MS);
39
+ const parent = path.join(descriptor.stateRoot, TOOLCHAIN_DIRECTORY);
40
+
41
+ return withToolchainOperationLock(descriptor.stateRoot, async () => {
42
+ ensureOwnerOnlyDirectorySync(parent);
43
+ return withOwnerStateLock(parent, async () => {
44
+ const npmCli = explicitNpmCli || (await ensureHardenedNpm(parent, options.hardenedNpm || {})).cli;
45
+ let marker = null;
46
+ let installed = false;
47
+ try {
48
+ marker = readWranglerToolchainMarker(descriptor.root);
49
+ installed = await verifyWranglerToolchain(descriptor, (args, allowFailure = false) => runNpm(npmCli, args, descriptor.root, runCommand, options, AUDIT_TIMEOUT_MS, allowFailure));
50
+ } catch (error) {
51
+ if (!isPrivateToolchainIntegrityError(error)) throw error;
52
+ }
53
+ if (!installed) {
54
+ installToolchain(descriptor);
55
+ await runNpm(npmCli, [
56
+ "ci",
57
+ "--dry-run=false",
58
+ "--workspaces=false",
59
+ "--ignore-scripts=false",
60
+ "--package-lock=true",
61
+ "--package-lock-only=false",
62
+ "--omit=dev",
63
+ "--no-fund",
64
+ "--audit=false",
65
+ ], descriptor.root, runCommand, options, INSTALL_TIMEOUT_MS);
66
+ await verifyWranglerToolchain(descriptor, (args, allowFailure = false) => runNpm(npmCli, args, descriptor.root, runCommand, options, AUDIT_TIMEOUT_MS, allowFailure), true);
67
+ await auditToolchain(descriptor, npmCli, runCommand, options);
68
+ writeWranglerToolchainMarker(descriptor, now());
69
+ return descriptor.root;
70
+ }
71
+
72
+ const checkedAt = now();
73
+ const auditAgeMs = checkedAt - Date.parse(String(marker?.audited_at || ""));
74
+ if (!wranglerToolchainMarkerMatches(marker, descriptor) || auditAgeMs < -MAX_CLOCK_SKEW_MS || auditAgeMs >= auditMaxAgeMs) {
75
+ await auditToolchain(descriptor, npmCli, runCommand, options);
76
+ writeWranglerToolchainMarker(descriptor, checkedAt);
77
+ }
78
+ return descriptor.root;
79
+ }, {
80
+ purpose: "wrangler-toolchain",
81
+ fileName: TOOLCHAIN_LOCK,
82
+ label: "Wrangler toolchain",
83
+ timeoutMs: options.lockTimeoutMs,
84
+ });
85
+ }, {
86
+ controlRoot: options.controlRoot,
87
+ timeoutMs: options.operationLockTimeoutMs,
88
+ });
89
+ }
90
+ export function wranglerToolchainDescriptor(options = {}) {
91
+ const packageRoot = path.resolve(String(options.packageRoot || defaultPackageRoot));
92
+ const stateRoot = path.resolve(String(options.stateRoot || defaultStateRoot()));
93
+ const templateRoot = path.join(packageRoot, "src", "local", "wrangler-toolchain");
94
+ const packageBytes = readBoundedRegularFileSync(
95
+ path.join(templateRoot, "package.json"), MAX_TEMPLATE_BYTES, "Wrangler toolchain package manifest",
96
+ { verifyPathIdentity: true, rejectMultipleLinks: true },
97
+ );
98
+ const lockBytes = readBoundedRegularFileSync(
99
+ path.join(templateRoot, "package-lock.json"), MAX_TEMPLATE_BYTES, "Wrangler toolchain lockfile",
100
+ { verifyPathIdentity: true, rejectMultipleLinks: true },
101
+ );
102
+ const manifest = parseJsonObject(packageBytes, "Wrangler toolchain package manifest");
103
+ const lock = parseJsonObject(lockBytes, "Wrangler toolchain lockfile");
104
+ validateTemplate(manifest, lock);
105
+ const digest = createHash("sha256").update(packageBytes).update("\0").update(lockBytes).digest("hex");
106
+ const root = path.join(stateRoot, TOOLCHAIN_DIRECTORY, `wrangler-${manifest.dependencies.wrangler}-${digest.slice(0, 16)}`);
107
+ return Object.freeze({
108
+ packageRoot,
109
+ stateRoot,
110
+ templateRoot,
111
+ root,
112
+ digest,
113
+ packageBytes,
114
+ lockBytes,
115
+ versions: Object.freeze({
116
+ wrangler: String(manifest.dependencies.wrangler),
117
+ undici: String(manifest.overrides.undici),
118
+ sharp: String(manifest.overrides.sharp),
119
+ }),
120
+ });
121
+ }
122
+ function installToolchain(descriptor) {
123
+ const parent = path.dirname(descriptor.root);
124
+ ensureOwnerOnlyDirectorySync(parent);
125
+ if (existsSync(descriptor.root)) rmSync(descriptor.root, { recursive: true, force: true });
126
+ ensureOwnerOnlyDirectorySync(descriptor.root);
127
+ writeFileSync(path.join(descriptor.root, "package.json"), descriptor.packageBytes, { mode: 0o600 });
128
+ writeFileSync(path.join(descriptor.root, "package-lock.json"), descriptor.lockBytes, { mode: 0o600 });
129
+ }
130
+
131
+ async function auditToolchain(descriptor, npmCli, runCommand, options) {
132
+ const audit = await runNpm(npmCli, ["audit", "--workspaces=false", "--omit=dev", "--audit-level=low", "--json"], descriptor.root, runCommand, options, AUDIT_TIMEOUT_MS, true);
133
+ let report;
134
+ try { report = JSON.parse(audit.stdout); } catch { throw new Error("Wrangler toolchain npm audit did not return valid JSON"); }
135
+ const vulnerabilities = report?.metadata?.vulnerabilities;
136
+ const total = Number(vulnerabilities?.total);
137
+ if (audit.code !== 0 || !Number.isFinite(total) || total !== 0) {
138
+ throw new Error(`Wrangler toolchain dependency audit failed (${auditSummary(vulnerabilities)})`);
139
+ }
140
+ await runNpm(npmCli, ["audit", "signatures", "--workspaces=false"], descriptor.root, runCommand, options, AUDIT_TIMEOUT_MS);
141
+ }
142
+
143
+ async function runNpm(npmCli, args, cwd, runCommand, options, timeoutMs, allowFailure = false) {
144
+ return runCommand(process.execPath, [npmCli, ...args], {
145
+ cwd,
146
+ env: nestedNpmEnvironment(options.env || process.env),
147
+ capture: true,
148
+ allowFailure,
149
+ timeoutMs,
150
+ maxOutputBytes: MAX_COMMAND_OUTPUT_BYTES,
151
+ });
152
+ }
153
+
154
+ function validateTemplate(manifest, lock) {
155
+ if (manifest.private !== true || manifest.dependencies?.wrangler !== "4.120.0") {
156
+ throw new Error("Wrangler toolchain manifest lost its exact private Wrangler dependency");
157
+ }
158
+ if (manifest.overrides?.undici !== "7.29.0" || manifest.overrides?.sharp !== "0.35.3") {
159
+ throw new Error("Wrangler toolchain manifest lost its security overrides");
160
+ }
161
+ const expectedScripts = { "esbuild@0.28.1": true, fsevents: false, "sharp@0.35.3": true, "workerd@1.20260801.1": true };
162
+ if (JSON.stringify(manifest.allowScripts) !== JSON.stringify(expectedScripts)) {
163
+ throw new Error("Wrangler toolchain manifest lost its exact install-script policy");
164
+ }
165
+ if (lock.lockfileVersion !== 3
166
+ || lock.packages?.["node_modules/wrangler"]?.version !== manifest.dependencies.wrangler
167
+ || lock.packages?.["node_modules/undici"]?.version !== manifest.overrides.undici
168
+ || lock.packages?.["node_modules/sharp"]?.version !== manifest.overrides.sharp) {
169
+ throw new Error("Wrangler toolchain lockfile does not match the exact security contract");
170
+ }
171
+ }
172
+
173
+ function parseJsonObject(bytes, label) {
174
+ let value;
175
+ try { value = JSON.parse(Buffer.from(bytes).toString("utf8")); } catch { throw new Error(`${label} is not valid JSON`); }
176
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object`);
177
+ return value;
178
+ }
179
+
180
+ function auditSummary(value = {}) {
181
+ return ["critical", "high", "moderate", "low", "info"]
182
+ .map((key) => `${key}=${Number(value?.[key]) || 0}`).join(", ");
183
+ }
184
+
185
+ function positiveInteger(value, fallback) {
186
+ const number = Number(value);
187
+ return Number.isFinite(number) && number > 0 ? Math.floor(number) : fallback;
188
+ }
@@ -1,7 +1,13 @@
1
1
  {
2
- "revision": 1,
2
+ "revision": 4,
3
3
  "defaultRole": "reviewer",
4
4
  "ownerRole": "owner",
5
+ "ownerOnlyTools": [
6
+ "diagnose_runtime",
7
+ "list_local_resources",
8
+ "stage_job",
9
+ "start_job"
10
+ ],
5
11
  "roles": {
6
12
  "reviewer": {
7
13
  "profile": "review",
@@ -0,0 +1,49 @@
1
+ // @ts-check
2
+
3
+ /** @type {Readonly<Record<string, string>>} */
4
+ const DETAIL_BY_REASON = Object.freeze({
5
+ relay_authentication_failed: "candidate relay authentication failed after readiness",
6
+ autostart_install_failed: "candidate autostart installation failed after readiness",
7
+ autostart_start_failed: "candidate autostart start failed after readiness",
8
+ });
9
+
10
+ /** @param {unknown} value */
11
+ export function isActivationRecoveryReason(value) {
12
+ return typeof value === "string" && Object.hasOwn(DETAIL_BY_REASON, value);
13
+ }
14
+
15
+ /** @param {unknown} reason */
16
+ export function canonicalActivationRecoveryDetail(reason) {
17
+ if (typeof reason !== "string") throw new Error("activation recovery reason is invalid");
18
+ const detail = DETAIL_BY_REASON[reason];
19
+ if (!detail) throw new Error("activation recovery reason is invalid");
20
+ return detail;
21
+ }
22
+
23
+ /**
24
+ * Normalize recovered-activation metadata without retaining lower-layer error text.
25
+ * `detail` is still validated so historical schema-2 records fail closed when their
26
+ * bounded shape is corrupt, but every accepted record/result projects the fixed
27
+ * reason-owned detail instead of replaying the stored text.
28
+ * @param {{recovered: unknown, reason?: unknown, detail?: unknown}} value
29
+ */
30
+ export function normalizeActivationRecovery(value) {
31
+ if (typeof value.recovered !== "boolean") throw new Error("activation recovery flag is invalid");
32
+ const reason = value.reason === null || value.reason === undefined ? "" : value.reason;
33
+ const detail = value.detail === null || value.detail === undefined ? "" : value.detail;
34
+ if (!value.recovered) {
35
+ if (reason || detail) throw new Error("activation recovery metadata is inconsistent");
36
+ return Object.freeze({ recovered: false, reason: "", detail: "" });
37
+ }
38
+ if (typeof reason !== "string") throw new Error("activation recovery reason is invalid");
39
+ if (typeof detail !== "string") throw new Error("activation recovery detail is invalid");
40
+ if (!isActivationRecoveryReason(reason)) throw new Error("activation recovery reason is invalid");
41
+ if (!detail || detail.length > 600 || /[\r\n\t]/.test(detail)) {
42
+ throw new Error("activation recovery detail is invalid");
43
+ }
44
+ return Object.freeze({
45
+ recovered: true,
46
+ reason,
47
+ detail: canonicalActivationRecoveryDetail(reason),
48
+ });
49
+ }
@@ -1,10 +1,11 @@
1
- export const ADMIN_AUTH_SCHEME: "hmac-sha256-v1";
1
+ export const ADMIN_AUTH_SCHEME: "device-admin-signature-v1";
2
2
  export const ADMIN_AUTH_TTL_SECONDS: number;
3
3
  export function adminAuthTranscript(input: {
4
4
  origin: unknown;
5
5
  method: unknown;
6
6
  pathname: unknown;
7
7
  bodyHash: unknown;
8
+ keyId: unknown;
8
9
  issuedAt: unknown;
9
10
  nonce: unknown;
10
11
  }): string;
@@ -1,4 +1,4 @@
1
- export const ADMIN_AUTH_SCHEME = "hmac-sha256-v1";
1
+ export const ADMIN_AUTH_SCHEME = "device-admin-signature-v1";
2
2
  export const ADMIN_AUTH_TTL_SECONDS = 5 * 60;
3
3
 
4
4
  export function adminAuthTranscript(input = {}) {
@@ -6,12 +6,12 @@ export function adminAuthTranscript(input = {}) {
6
6
  const method = requiredToken(input.method, "method", /^[A-Z]{3,10}$/);
7
7
  const pathname = requiredToken(input.pathname, "pathname", /^\/[A-Za-z0-9/_-]{1,255}$/);
8
8
  const bodyHash = requiredToken(input.bodyHash, "body hash", /^[a-f0-9]{64}$/);
9
+ const keyId = requiredToken(input.keyId, "session key id", /^device_[A-Za-z0-9_-]{32}$/);
9
10
  const issuedAt = requiredInteger(input.issuedAt, "issued at");
10
11
  const nonce = requiredToken(input.nonce, "nonce", /^[A-Za-z0-9_-]{32,128}$/);
11
- return [ADMIN_AUTH_SCHEME, origin, method, pathname, bodyHash, issuedAt, nonce].join("\0");
12
+ return [ADMIN_AUTH_SCHEME, origin, method, pathname, bodyHash, keyId, issuedAt, nonce].join("\0");
12
13
  }
13
14
 
14
-
15
15
  function requiredOrigin(value) {
16
16
  let url;
17
17
  try { url = new URL(String(value || "")); } catch { throw new Error("admin authentication origin is invalid"); }
@@ -0,0 +1,9 @@
1
+ export type AuthorityRevocation = Readonly<{
2
+ accountId: string;
3
+ accountVersion: number;
4
+ clientId?: string;
5
+ familyId?: string;
6
+ }>;
7
+
8
+ export function normalizeAuthorityRevocation(value: unknown): AuthorityRevocation | null;
9
+ export function recordMatchesAuthorityRevocation(record: object, revocation: AuthorityRevocation): boolean;
@@ -0,0 +1,28 @@
1
+ const ACCOUNT_ID = /^acct_[A-Za-z0-9_-]{20,96}$/;
2
+ const CLIENT_ID = /^mcp_client_[A-Za-z0-9_-]{43}$/;
3
+ const FAMILY_ID = /^mcp_family_[A-Za-z0-9_-]{43}$/;
4
+
5
+ export function normalizeAuthorityRevocation(value) {
6
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
7
+ const accountId = String(value.account_id || "");
8
+ const accountVersion = Number(value.account_version);
9
+ const clientId = value.client_id === undefined ? "" : String(value.client_id || "");
10
+ const familyId = value.family_id === undefined ? "" : String(value.family_id || "");
11
+ if (!ACCOUNT_ID.test(accountId) || !Number.isSafeInteger(accountVersion) || accountVersion <= 0) return null;
12
+ if (clientId && !CLIENT_ID.test(clientId)) return null;
13
+ if (familyId && (!clientId || !FAMILY_ID.test(familyId))) return null;
14
+ return Object.freeze({
15
+ accountId,
16
+ accountVersion,
17
+ ...(clientId ? { clientId } : {}),
18
+ ...(familyId ? { familyId } : {}),
19
+ });
20
+ }
21
+
22
+ export function recordMatchesAuthorityRevocation(record, revocation) {
23
+ if (!record || !revocation || record.owner_kind !== "account") return false;
24
+ if (record.owner_account_id !== revocation.accountId || record.owner_account_version !== revocation.accountVersion) return false;
25
+ if (revocation.clientId && record.owner_client_id !== revocation.clientId) return false;
26
+ if (revocation.familyId && record.owner_family_id !== revocation.familyId) return false;
27
+ return true;
28
+ }
@@ -1,7 +1,9 @@
1
1
  export const DAEMON_AUTH_SCHEME: "device-signature-v1";
2
2
  export const DAEMON_PREFLIGHT_SCHEME: "device-preflight-v1";
3
+ export const DAEMON_HTTP_RELAY_SCHEME: "device-http-relay-v1";
3
4
  export const DAEMON_AUTH_CHALLENGE_TTL_SECONDS: number;
4
5
  export const DAEMON_PREFLIGHT_TTL_SECONDS: number;
6
+ export const DAEMON_HTTP_RELAY_TTL_SECONDS: number;
5
7
  export function daemonAuthTranscript(input: {
6
8
  challenge: unknown;
7
9
  workerOrigin: unknown;
@@ -18,3 +20,12 @@ export function daemonPreflightTranscript(input: {
18
20
  nonce: unknown;
19
21
  issuedAt: unknown;
20
22
  }): string;
23
+
24
+ export function daemonHttpRelayTranscript(input: {
25
+ workerOrigin: unknown;
26
+ server: unknown;
27
+ version: unknown;
28
+ nonce: unknown;
29
+ issuedAt: unknown;
30
+ bodySha256: unknown;
31
+ }): string;
@@ -1,7 +1,9 @@
1
1
  export const DAEMON_AUTH_SCHEME = "device-signature-v1";
2
2
  export const DAEMON_PREFLIGHT_SCHEME = "device-preflight-v1";
3
+ export const DAEMON_HTTP_RELAY_SCHEME = "device-http-relay-v1";
3
4
  export const DAEMON_AUTH_CHALLENGE_TTL_SECONDS = 30;
4
5
  export const DAEMON_PREFLIGHT_TTL_SECONDS = 5 * 60;
6
+ export const DAEMON_HTTP_RELAY_TTL_SECONDS = 30;
5
7
 
6
8
 
7
9
  export function daemonPreflightTranscript(input = {}) {
@@ -29,6 +31,21 @@ export function daemonAuthTranscript(input = {}) {
29
31
  return values.join("\0");
30
32
  }
31
33
 
34
+ export function daemonHttpRelayTranscript(input = {}) {
35
+ const values = [
36
+ DAEMON_HTTP_RELAY_SCHEME,
37
+ "POST",
38
+ "/daemon/http",
39
+ requiredOrigin(input.workerOrigin),
40
+ requiredText(input.server, "server", 1, 128),
41
+ requiredText(input.version, "version", 1, 64),
42
+ requiredText(input.nonce, "HTTP relay nonce", 24, 128),
43
+ requiredInteger(input.issuedAt, "HTTP relay issued at"),
44
+ requiredText(input.bodySha256, "HTTP relay body SHA-256", 43, 43),
45
+ ];
46
+ return values.join("\0");
47
+ }
48
+
32
49
  function requiredText(value, label, minimum, maximum) {
33
50
  const text = String(value || "");
34
51
  if (text.length < minimum || text.length > maximum || /[\0\r\n]/.test(text)) {
@@ -0,0 +1,20 @@
1
+ export const DEVICE_SESSION_CERTIFICATE_SCHEME: "device-session-certificate-v1";
2
+ export const DEVICE_SESSION_MAX_LIFETIME_SECONDS: number;
3
+
4
+ export function deviceSessionCertificateTranscript(input?: {
5
+ workerOrigin?: unknown;
6
+ server?: unknown;
7
+ version?: unknown;
8
+ rootKeyId?: unknown;
9
+ publicJwk?: unknown;
10
+ issuedAt?: unknown;
11
+ expiresAt?: unknown;
12
+ nonce?: unknown;
13
+ }): string;
14
+
15
+ export function canonicalPublicJwk(value: unknown): {
16
+ kty: "EC";
17
+ crv: "P-256";
18
+ x: string;
19
+ y: string;
20
+ };
@@ -0,0 +1,51 @@
1
+ export const DEVICE_SESSION_CERTIFICATE_SCHEME = "device-session-certificate-v1";
2
+ export const DEVICE_SESSION_MAX_LIFETIME_SECONDS = 24 * 60 * 60;
3
+
4
+ export function deviceSessionCertificateTranscript(input = {}) {
5
+ const publicJwk = canonicalPublicJwk(input.publicJwk);
6
+ return [
7
+ DEVICE_SESSION_CERTIFICATE_SCHEME,
8
+ requiredOrigin(input.workerOrigin),
9
+ requiredText(input.server, "server", 1, 128),
10
+ requiredText(input.version, "version", 1, 64),
11
+ requiredText(input.rootKeyId, "root key id", 16, 128),
12
+ JSON.stringify(publicJwk),
13
+ requiredInteger(input.issuedAt, "issued at"),
14
+ requiredInteger(input.expiresAt, "expires at"),
15
+ requiredText(input.nonce, "nonce", 24, 128),
16
+ ].join("\0");
17
+ }
18
+
19
+ export function canonicalPublicJwk(value) {
20
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("device session public key is invalid");
21
+ if (value.kty !== "EC" || value.crv !== "P-256" || typeof value.x !== "string" || typeof value.y !== "string" || value.d !== undefined) {
22
+ throw new Error("device session public key is invalid");
23
+ }
24
+ if (!/^[A-Za-z0-9_-]{42,44}$/.test(value.x) || !/^[A-Za-z0-9_-]{42,44}$/.test(value.y)) {
25
+ throw new Error("device session public key is invalid");
26
+ }
27
+ return { crv: "P-256", kty: "EC", x: value.x, y: value.y };
28
+ }
29
+
30
+ function requiredOrigin(value) {
31
+ let url;
32
+ try { url = new URL(String(value || "")); } catch { throw new Error("device session Worker origin is invalid"); }
33
+ const secure = url.protocol === "https:";
34
+ const loopback = url.protocol === "http:" && ["127.0.0.1", "localhost", "[::1]"].includes(url.hostname);
35
+ if ((!secure && !loopback) || url.username || url.password || url.pathname !== "/" || url.search || url.hash) {
36
+ throw new Error("device session Worker origin is invalid");
37
+ }
38
+ return url.origin;
39
+ }
40
+
41
+ function requiredText(value, label, minimum, maximum) {
42
+ const text = String(value || "");
43
+ if (text.length < minimum || text.length > maximum || /[\0\r\n]/.test(text)) throw new Error(`device session ${label} is invalid`);
44
+ return text;
45
+ }
46
+
47
+ function requiredInteger(value, label) {
48
+ const number = Number(value);
49
+ if (!Number.isSafeInteger(number) || number <= 0) throw new Error(`device session ${label} is invalid`);
50
+ return String(number);
51
+ }
@@ -0,0 +1,15 @@
1
+ export const REMOTE_FOREGROUND_TIMEOUT_SECONDS: number;
2
+ export const REMOTE_DURABLE_PROCESS_DEFAULT_TIMEOUT_SECONDS: number;
3
+ export const REMOTE_DURABLE_PROCESS_MAXIMUM_TIMEOUT_SECONDS: number;
4
+ export function isConfigurableForegroundTool(name: string): boolean;
5
+ export function isRemoteDurableProcessTool(name: string): boolean;
6
+ export function remoteDurableProcessTimeoutSeconds(value: unknown): number;
7
+ export function remoteForegroundDefaultSeconds(name: string): number;
8
+ export function remoteForegroundMaximumSeconds(name: string): number;
9
+ export function effectiveForegroundTimeoutSeconds(input: Readonly<{
10
+ tool: string;
11
+ value: unknown;
12
+ remote: boolean;
13
+ localDefault: number;
14
+ localMaximum: number;
15
+ }>): number;