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
@@ -2,6 +2,10 @@
2
2
 
3
3
  This document records project-wide decisions that must survive individual fixes, releases, and maintainers. It is normative for repository changes together with [PROJECT_STANDARDS.md](PROJECT_STANDARDS.md). Machine-specific observations belong in the ignored `.project-local/` directory instead.
4
4
 
5
+ ## Dependency save policy
6
+
7
+ Repository npm saves must preserve exact versions (`save-exact=true`). Root production, development, and optional dependencies are architecture-gated to exact semantic versions and installs remain lockfile-driven. Do not add a blanket `min-release-age` project setting: npm applies it as a version-availability filter and can therefore block a newly published security fix. Supply-chain freshness is handled by explicit reviewed upgrades plus lockfile, audit, signature/attestation, lifecycle-script, and consumer-package gates rather than by making recent versions globally ineligible.
8
+
5
9
  ## Product and security invariants
6
10
 
7
11
  1. **The default profile is intentionally `full`.** This is an explicit product-owner decision prioritizing usability. It must not be changed to a narrower default as an incidental security cleanup. Documentation must continue to explain the authority and risks clearly.
@@ -9,24 +13,50 @@ This document records project-wide decisions that must survive individual fixes,
9
13
  3. **Machine Bridge authority and host authority are separate.** `full` removes Machine Bridge's own policy, path, shell, and environment restrictions. It cannot override an MCP host, connector gateway, operating system, endpoint-security product, cloud IAM, remote authentication, or `sudo`.
10
14
  4. **Publication surfaces contain no real environment metadata.** Source, tests, fixtures, examples, release notes, filenames, package contents, tags, and release assets use synthetic identifiers and reserved example domains.
11
15
  5. **Secrets are never operational log data.** Tool arguments, command text, stdin, stdout, stderr, file content, OAuth bodies, credentials, and local resource values are not logged.
12
- 6. **A release is one owner-authorized, agent-operated and verified package with successful cross-platform evidence.** The repository owner explicitly authorizes the exact npm candidate and any same-name Worker update in the active conversation; the coding agent starts that candidate through Machine Bridge, verifies the connected candidate version, readiness, and representative functionality, and then records the package hashes before the first GitHub push. Package metadata, Worker version, browser-extension version/name, acceptance record, Git tag, GitHub Release, npm version, documentation, and deployed health version must agree, and the exact `origin/main` commit must have completed successful push-triggered CI, CodeQL, Governance, and OpenSSF Scorecard runs before a tag or release is created.
16
+ 6. **Stable release requires a published prerelease soak.** The owner runs one exact persistent candidate activation command; the coding agent verifies the real Worker and daemon before recording acceptance. Version 3 and later use `dev`, `beta`, or `rc`, publish under non-`latest` tags, and complete the policy minimum soak after registry-verified activation. Stable promotion may change only normalized release metadata and requires an identical promotion-content digest, a tracked soak record, repeated stable-candidate verification, and successful exact-commit CI, CodeQL, Governance, Workflow Policy Gate, and Scorecard.
13
17
  7. **Generic local automation is structured, not arbitrary evaluation.** Browser/application features may expose broad user authority under canonical `full`, but must not accept caller-provided JavaScript, AppleScript, JXA, or extension code.
14
18
  8. **Daily-browser integration uses the existing profile.** The supported primary browser path is the packaged authenticated extension and machine-level loopback broker, preserving current tabs/login state; a separate automation profile is not an equivalent replacement.
15
19
  9. **Pairing and resource secrets are not conversation or log data.** Tokens and injected local-resource values must not be returned, embedded in URLs, or written to operational logs.
16
20
  10. **Exclusive claims are complete before visible.** Never create a final lock/PID claim and then populate it. Use the shared exclusive-file primitive, ownership tokens, process-start identity, and snapshot-checked reclamation.
17
21
  11. **Service and state removal are fail-closed state machines.** Stop the platform provider and every verified daemon before removing definitions or recursive state. An unreadable lock, failed stop, active job, or ambiguous identity retains state for diagnosis.
18
- 12. **Read failure is not empty state.** Permission, type, symbolic-link, size, encoding, and I/O errors must propagate. Corrupt backup/reconstruction applies only after a successful read proves that JSON content is invalid.
19
- 13. **The public protocol contract is current-only.** Shared metadata advertises only the current MCP protocol version. Compatibility code for obsolete protocol dates, lock formats, or state schemas is not retained in the final runtime; upgrade safety comes from explicit version negotiation, fail-closed state validation, and bounded operator convergence.
22
+ 12. **Security, persistence, ownership, and reclamation read failure is not empty state.** Permission, type, symbolic-link, size, encoding, and I/O errors on evidence used to authorize, reclaim, delete, replace, or mutate state must propagate. Corrupt backup/reconstruction applies only after a successful read proves that JSON content is invalid. Documented read-only discovery may conservatively omit unavailable or unsupported optional metadata only when that omission cannot grant authority, justify reclamation/removal, or trigger a mutation.
23
+ 13. **MCP `2026-07-28` is the only native state model; remote initialization compatibility is stateless and bounded.** Shared metadata advertises `2026-07-28` as the native protocol and separately declares the remote-HTTP initialization compatibility dates `2025-06-18` and `2025-11-25`. stdio remains current-only. The compatibility adapter may answer only `initialize`, `notifications/initialized`, `ping`, `tools/list`, and `tools/call`; tool methods execute through the current request-scoped `McpController`. It never creates or accepts `Mcp-Session-Id`, recovery GET, `Last-Event-ID`, persisted replay/delivery state, legacy prepare/subscribe descriptors, or an initialization-owned authorization/session state machine. Other removed protocol behavior receives bounded no-side-effect rejection/upgrade guidance rather than execution.
20
24
  14. **Security analysis is a failing gate.** CodeQL or Scorecard execution alone is not success. Generated SARIF must contain no unaccepted result, and missing rule metadata fails closed rather than being interpreted as non-security. An intentional or externally constrained finding requires an exact rule/path record with a substantive rationale and an expiry date.
21
- 15. **Ambiguous health is not permission to repeat a remote write.** A successful Wrangler deployment is recorded before secondary health verification. Timeout, proxy, TLS, network, and temporary service failures preserve the deployment fingerprint and fail for diagnosis; only bounded evidence of a stale identity/version permits automatic same-name redeployment. Changing the Worker name is an explicit remote-resource transition, not a retry strategy.
25
+ 15. **Ambiguous health is not permission to repeat a remote write.** A successful Wrangler deployment is recorded before secondary health verification. Timeout, proxy, TLS, network, and temporary service failures preserve the deployment fingerprint and fail for diagnosis; only bounded evidence of a stale identity/version permits ordinary automatic same-name redeployment. During owner-authorized candidate activation, an explicit cryptographic device-authentication rejection after current-version health is separate positive evidence that deployment secrets did not converge; it permits one same-name redeployment with the unchanged selected identity, never rotation or resource renaming. Changing the Worker name remains an explicit remote-resource transition, not a retry strategy.
26
+ 16. **Execution continuity and delivery continuity are separate proof obligations.** Current request-scoped HTTP work treats response-stream closure as cancellation and retains no replay record. Same-daemon relay reconnect may rebind an already-dispatched transient call only because the verified daemon still owns that execution; it must never create a client-visible replay/session identity. Work that must survive client delivery loss uses an explicit durable managed-job handle rather than transport replay.
27
+ 17. **Remote compound commands are not persistence evidence.** When a remote edit and a long test share one relay call, a transport interruption can obscure whether the edit completed. High-impact writes must be followed by an independent read of stable anchors or a Git diff before tests and conclusions rely on them.
28
+ 18. **MCP delivery state is request-scoped, not durable.** One Durable Object fetch owns the current response, the outer Worker keeps an open SSE response observable with bounded comments, and a random private capability indexes only the already-active transient pending call so public stream closure can request cancellation. Public control headers are stripped and private cancel controls carry no OAuth/DPoP credential. MCP code must not add prepare/subscribe delivery descriptors, terminal-result retention, session stores, recovery GETs, replay IDs, or cross-event terminal Promise registries. Durable execution belongs to the managed-job subsystem, whose persisted state machine and deadlines are independent of MCP transport delivery.
29
+ 19. **Validation cost is part of the input contract.** Schema compilation and runtime validation have independent depth/node/pattern/issue/work budgets. Every traversed array item and own object property consumes work before recursive validation; code must not allocate an unbounded key/value inventory and only then check limits.
30
+ 20. **A pending release candidate is valid only against the current packaged source.** Candidate start/activation must compare package identity and promotion digest before tarball verification, installation, deployment, or service mutation. Tarball-to-manifest integrity alone is insufficient after later edits.
31
+ 21. **GitHub publication requires explicit current-task owner authorization and one publication process.** Candidate activation, acceptance, merge, and green CI are evidence, not standing permission to create a tag or Release. Publication must present the explicit `--owner-confirm` acknowledgement and hold the repository publication lock through tag/Release synchronization. The owner may execute the command directly or authorize an agent to do so; a TTY is optional and is not an authorization boundary. Automation must not infer publication permission from an earlier acceptance, merge, or conversation, and an agent must not race an operation the owner says they will execute themselves.
32
+ 22. **Capability routing advises; effective policy authorizes.** The resolver may shortlist tool sets, report ambiguity, and suggest fallbacks, but it must neither hide an allowed escape hatch nor recommend a tool outside the request's effective account/daemon intersection. Canonical full continues to expose direct Bash. A routing fallback is not a safety-policy bypass.
33
+ 23. **Capability fingerprints reduce repetition, not freshness checks.** A matching client-supplied fingerprint may omit unchanged static instructions, but task-specific ranking, application discovery, and route computation must still run. The fingerprint is not conversation identity, authorization, or a cached execution result.
34
+ 24. **Read-only fan-out may be concurrent only when observable order stays sequential.** Independent metadata/file reads may use a small bounded batch, but scheduling count and externally visible visited count are separate. Results and errors are consumed in canonical walk/enumeration order; work prefetched beyond an already-satisfied output/limit stop cannot retroactively fail the completed result. Cancellation is checked before scheduling and before consuming prefetched results.
35
+ 25. **Hot read models have semantic output budgets.** A compact/summary projection is computed only after canonical state and authorization decisions. Tests bind required semantic fields, forbidden cold/private fields, absolute size ceilings, and high-cardinality growth behavior. Do not satisfy a size budget by deleting the authority/readiness/inventory facts that make the projection useful.
36
+ 26. **Diagnose before changing semantics.** Production failures are classified from exact deployed identity plus privacy-bounded stage evidence before speculative behavior changes. Working notes distinguish observed fact, inference, falsified hypothesis, and unresolved external cause. A generic host error, successful compilation, or green local test is not root-cause evidence.
37
+ 27. **Falsified fixes do not silently accumulate.** A live-disproved hypothesis patch is removed before the final candidate unless an independent invariant and regression test justify retaining it. Security or identity mutations such as password/token/device rotation, authentication weakening, state deletion, forced redeployment, or remote-resource renaming are never generic diagnostic resets.
38
+ 28. **Hosted-runtime behavior requires hosted-runtime evidence.** Memory fakes and local Wrangler/workerd are necessary regression layers but do not prove deployed-edge storage, request-lifecycle, WebSocket, quota, proxy, or provider behavior. Changes in those domains require a bounded live canary or explicitly documented residual uncertainty before acceptance.
39
+ 29. **Multi-record authority state commits through one explicit transaction boundary.** OAuth/account/authority mutations that must become visible together write each named record inside one Durable Object storage transaction and fail atomically. Do not reintroduce a convenience bulk-object `put()` at this security boundary merely because the local emulator accepts it; the transaction path is the production-proven contract and its failure stages remain low-cardinality diagnostics.
40
+ 30. **Persistent-state size and cardinality are budgets, not implementation details.** Every high-cardinality map/queue has a hard count bound, a retention/pruning rule, and a serialized-size or row-budget regression where provider limits matter. Retry-only payload is compacted when its retry window ends; a nominal item-count cap is insufficient when one aggregated value can exceed the backend value limit. OAuth refresh consumed-token replay state therefore persists in 8 fixed hash shards with a 1024-record per-shard ceiling while the main refresh value retains active tokens and family tombstones only; all migration and mutation paths reconstruct the same in-memory state and commit main/shards atomically.
41
+ 31. **Verification runs require an immutable source snapshot.** A test or release gate that observes a source hot reload, concurrent packaged-file edit, regenerated artifact, or changed candidate identity is invalid evidence even if most tasks passed. Finish writes first, then run the complete gate against the final tree; any later packaged-byte change requires a clean rerun and a new candidate.
42
+ 32. **OAuth persistence is a deployed acceptance boundary.** Any change to OAuth grant handling, token storage, account/client trust, replay state, or Durable Object persistence must prove an authorization-code exchange, persisted access and refresh credentials, an authenticated MCP request, and successful refresh rotation against the deployed candidate before acceptance. Relevant TTL/soak survival is verified separately rather than inferred from the initial exchange.
43
+ 33. **Computer Use mutation authority is snapshot-bound and one-shot.** `computer_act` may mutate only from the exact bounded snapshot produced by `computer_observe`; preflight is read-only, and the snapshot generation is atomically consumed before backend mutation handoff. Browser document/frame/ref/backend identity and application process/window identity are private authority evidence, not caller-selected parameters. A snapshot ID alone is not authorization and never bypasses ordinary role/policy checks.
44
+ 34. **A PID or coercible scalar is never Computer Use authority.** Application snapshots bind PID to the exact public libproc process-birth generation and fail closed when that identity is unavailable or changes. Browser/application actions, coordinates, digests, window IDs/bounds, process generations, resource names, and settlement fields must retain their native producer type; arrays/objects that JavaScript could stringify or numerically coerce are malformed evidence, not alternate encodings.
45
+ 35. **Ambiguous UI mutation is never replay evidence.** Once a browser mutation has been handed to the extension transport, or a fixed launch/JXA/native helper has started its process, timeout, cancellation, connection loss, malformed response, process error, or missing settlement cannot be treated as definite non-execution. The public result is non-retryable unknown/pending settlement and the caller inspects post-state or observes again. Pre-dispatch validation and pre-spawn failure remain distinct definite failures. Result-size compaction must preserve this settlement and a usable continuation handle where available; it must not turn an already-issued mutation into a generic size error.
22
46
 
23
47
  A proposed change that conflicts with an invariant requires an explicit owner decision and corresponding documentation update. It must not be hidden inside an unrelated refactor.
24
48
 
25
49
  ## Change and release-operation ownership
26
50
 
27
- Repository implementation, interactive candidate acceptance, source release completion, and live release operations are separate responsibilities. Under `AGENTS.md`, coding automation may edit, test, and commit locally, generate an exact candidate tarball, and, after explicit owner authorization in the active conversation, start the exact isolated candidate through Machine Bridge. The agent verifies the deployed Worker version/hash, remote health, relay readiness, and connected local candidate through Machine Bridge and may then record `release-acceptance/v<version>.json`, push only through `npm run github:push`, complete the pull request through local `git`/`gh`, and create the annotated version tag plus final GitHub Release with `npm run release` after the accepted package hash and exact `main` checks pass. The owner is not required to copy approval IDs or run release-authorization commands in a terminal. Automated checks without an observed live candidate do not authorize acceptance. `npm run release` never pushes `main`. Automation must not publish or alter npm packages, install globally outside the isolated candidate prefix, deploy or reconfigure a Worker as a release operation, rotate credentials, mutate live deployment state, or replace daemon/service state without explicit user authorization.
51
+ Repository implementation, candidate preparation, observed live verification, acceptance recording, source pull requests, and explicitly authorized release operations are distinct workflow stages. External/live mutations are not inferred from a version change; they require a current explicit owner request, but they do not require a particular human-vs-agent execution surface.
52
+
53
+ For each package change, automation runs one complete frozen-tree verification. A successful full run records an ignored owner-local receipt bound to the exact verification generation, package/runtime identity, and a short freshness window; beginning another full run clears prior evidence before tests start. `release:candidate` must consume that matching receipt and therefore does not repeat the same complete suite on the same machine. It then prepares the exact prerelease tarball, and immediately before live activation automation runs `node scripts/start-release-candidate.mjs --install-only` to re-prove current source/package modes, tarball integrity, and disposable installability without live activation. A stale receipt or failed preflight returns ownership to automation to repair, rerun full verification when required, and regenerate the candidate. Only after that succeeds and the owner explicitly authorizes activation may the owner or authorized agent execute `npm run release:candidate:activate -- --allow-worker-deploy`. After that command updates the Worker, verifies candidate relay readiness, replaces the login daemon, and verifies service handoff, the coding agent derives `<activated-runtime-package>` from activation `runtime_entry` and runs `node <activated-runtime-package>/scripts/release-oauth-canary.mjs --allow-live-oauth-canary` as direct argv from the checkout cwd. This bounded synthetic canary is candidate-bound, creates only a temporary reviewer account/client, retains no credential/token evidence, and must prove authorization-code exchange, authenticated MCP, refresh rotation, refreshed MCP, and cleanup. The coding agent then inspects the connected system through Machine Bridge. Only after both proofs may it record candidate acceptance and push through `npm run github:push`.
54
+
55
+ After merge and exact-commit checks, GitHub tag/Release publication requires explicit owner authorization and uses `npm run prerelease:release -- --owner-confirm`. The command accepts local automation/Machine Bridge execution, but retains exact acceptance, CI, digest, main-head, remote-state reconciliation, and publication-lock gates. npm publication and registry activation are separate explicitly authorized operations through `npm run prerelease:publish` and `npm run prerelease:install -- --allow-worker-deploy`. The owner uses the prerelease for the required interval and explicitly reports whether blocking issues remain. Automation must not infer soak success from elapsed time.
28
56
 
29
- The normal handoff is: the repository owner publishes the reviewed npm version, then runs `npm install -g --omit=optional --allow-scripts=esbuild,workerd,sharp,fsevents machine-bridge-mcp@latest && machine-mcp`. The npm command updates the global CLI but cannot hot-reload an existing Node process. The subsequent normal foreground startup validates the Worker deployment hash, expected version, and health, requests shutdown of an active autostart daemon, waits a bounded interval for its lock, redeploys when necessary, and then takes over with the installed version. Live operations require explicit authorization even when they appear to be the obvious next release step.
57
+ Stable promotion is content-preserving. `release:soak:verify` compares the packaged functional digest with the accepted prerelease. A mismatch requires another prerelease and a restarted soak. After stable candidate activation and observed verification, explicitly authorized source publication uses `npm run release -- --owner-confirm`; stable npm publication remains a separate explicit authorization through `npm run stable:publish`.
58
+
59
+ GitHub/npm publication, global installation, Worker/service replacement, credential mutation, and unrelated live-state changes remain explicit owner decisions. Once a specific operation is explicitly authorized, automation may execute it through the repository's guarded local command unless the owner says they will perform it themselves. GitHub release commands never push `main`.
30
60
 
31
61
  ## Default instruction invariant
32
62
 
@@ -50,21 +80,44 @@ Rules:
50
80
 
51
81
  - Transport lifecycle, domain execution, persistence, and presentation are separate modules.
52
82
  - Domain modules must not import CLI, service, stdio, or relay adapters. Architecture tests enforce this dependency direction for agent context, package metadata, default instructions, capability observation, application automation, process sessions, and proxy selection.
83
+ - Static package identity stays outside persistence ownership: `package-identity.mjs` is the single source for installed package name/version/root and the shared server name. State-root/profile/workspace path and hash semantics remain in `state.mjs` because they depend on platform/environment injection, canonical workspace identity, and case-folding rules used by persistence and locks. Do not create a parallel path helper unless real consumers migrate to it and parity tests bind it to the live persistence contract.
53
84
  - Pure classification and normalization functions are exported and tested directly when practical.
54
85
  - Adapters may translate data but should not duplicate policy or schemas.
55
86
  - Every protocol control message emitted by one side must be explicitly accepted, rejected, or version-gated by the other side, with an end-to-end contract test covering the message name and semantics.
56
87
  - State transitions are explicit; readiness is not inferred from a lower-level event. An open WebSocket is not authenticated until `hello_ack`, and authenticated transport is not service readiness until an end-to-end result probe has returned on the same relay session. Pre-ready work and premature readiness acknowledgements fail closed.
57
- - Every externally controlled input is bounded before expensive allocation, traversal, parsing, storage, or execution.
88
+ - Every externally controlled input is bounded before expensive allocation, traversal, parsing, storage, or execution. A byte limit constrains bytes actually consumed and duration work, not only the subset retained in memory; once a declared or observed bound is crossed, cancel or close the source immediately.
58
89
  - Externally controlled string keys must not use prototype-chain membership or truthiness on ordinary objects. Use `Map`, `Set`, `Object.hasOwn`, or null-prototype records for command dispatch, enums, ACLs, form fields, registries, and other key-addressed contracts.
59
90
  - Repository text must not contain invisible ASCII controls other than tab, CR, and LF; architecture tests enforce this even when JavaScript syntax remains valid.
60
- - Persistent mutations use owner-only files, bounded no-follow reads, flushed atomic replacement, and integrity checks appropriate to the data.
61
- - Exclusive locks use the shared complete-before-visible hard-link claim. Reclamation requires process identity plus a matching file snapshot/token; do not unlink a path merely because an earlier read looked stale.
62
- - Service providers normalize success/failure to one result contract. Definition removal follows the shared platform-stop → verified-daemon-stop → remove order.
91
+ - Validate authority and object identity before mutation. If a multi-step operation must compensate after partial success, rollback must act on a transaction token, descriptor/snapshot identity, or other object-specific proof; a pathname plus the fact that an earlier step succeeded is not deletion authority. State read-modify-write operations must load their authoritative state after acquiring the mutation lock rather than saving a snapshot read while waiting for the lock. Machine-global service definition/owner/environment mutation must additionally hold the machine-service lock at the actual mutation point; a prior takeover check does not authorize a later unlocked install after network work.
92
+ - Complete-before-visible exclusive publication uses a flushed staging inode plus a no-replace hard link, so a legitimate competing reader can briefly observe the publisher's own second link before staging cleanup. Only readers that are explicitly coupled to this publication protocol may retry the stable `MBM_MULTIPLE_HARD_LINKS` classification, and only for the shared fixed four-attempt/1 ms budget. Persistent hard links remain invalid ownership evidence; ordinary/destructive readers must not convert this retry into general hard-link acceptance.
93
+ - Persistent mutations use owner-only files, bounded no-follow reads, flushed atomic/no-overwrite publication, and integrity checks appropriate to the data. Filesystem device/inode identity is never routed through an unsafe JavaScript Number: security-sensitive comparisons use the shared lossless identity boundary with BigInt default observations, retain exact change-time generation when the platform exposes it, and fail closed when injected metadata cannot be represented exactly. Same `(dev, ino)` after unlink/recreate is not sufficient identity evidence when a generation is known.
94
+ - A transport-surviving operation exposes either authenticated replay or a durable inspection handle. A response stream alone is not durable delivery.
95
+ - After a remote mutation, inspect the persisted file/Git anchors in a separate call before treating a subsequent test as evidence for that exact change.
96
+ - Exclusive locks use the shared complete-before-visible hard-link claim. Ownership bytes plus device/inode/change-time/size/mtime evidence come from one opened descriptor snapshot; ownership locks reject multiple hard links, and release/reclamation rechecks the path generation/identity/token before unlink. Do not combine bytes from one open with identity from a prior path stat, treat an inode number as a permanent generation, or unlink a path merely because an earlier read looked stale.
97
+ - Lock/recovery and destructive-inventory readers distinguish absence, successfully read malformed metadata, and storage failure. Only ENOENT is absence; only bytes that were successfully read and then proved malformed may enter a documented stale-corruption policy. Size, permission, I/O, descriptor, hard-link, and identity failures must propagate and must never become evidence that an owner is absent, reclaimable, or safe to delete. A read path with a legitimate concurrent atomic publisher may explicitly retry the stable `MBM_IDENTITY_CHANGED` condition, but only with a fixed small attempt budget and only when the final stable snapshot is the intended authority; destructive pre-action snapshots must not silently slide to a later object generation.
98
+ - Service providers normalize success/failure to one result contract. Definition removal follows the shared platform-stop → verified-daemon-stop → remove order. Destructive provider cleanup is decided from exit status plus structured pre/post provider state, never by matching localized stderr prose; a missing local definition is not evidence that an in-memory provider process is inactive.
63
99
  - Retry is limited to classified transient failures. Authentication, authorization, validation, integrity, and policy errors fail immediately.
64
- - Cleanup-only catches may be best effort, but primary failures must not be silently discarded.
100
+ - Cleanup-only catches may be best effort only after the primary result is already unambiguous. Before commit, cleanup failure must preserve the primary failure and every relevant cleanup cause. After commit, cleanup failure must not retroactively report the side effect as failed; surface fixed bounded cleanup evidence instead, and fail closed before continuing whenever the leftover artifact can contain credentials, keys, or other sensitive bytes. Rollback of newly created credentials, keys, or other sensitive artifacts is part of the primary integrity result and must attempt every cleanup target.
65
101
  - New work should not increase an already broad orchestration module when the behavior has an independent lifecycle or test surface. Extract the domain first.
66
102
 
67
- `runtime.mjs` owns local tool semantics. `relay-connection.mjs` owns authenticated relay connection lifecycle. The CLI orchestrates them; it must not become the second implementation of either.
103
+ `runtime.mjs` owns local tool orchestration, not filesystem lock mechanics. A tool handler returning successfully is the local settlement point: cancellation must be observed at explicit safe/cancellable checkpoints before that point, not used afterward to retroactively replace a completed result. Relay/result ownership may still suppress delivery when a remote caller has stopped waiting; that transport fact is separate from whether local work committed. File mutations coordinate on already-resolved canonical paths: the same path is serialized, independent paths may proceed concurrently, and a multi-path transaction must reserve every source/destination before awaiting any prior reservation. A cancellation signal must not release a reservation while an already-started filesystem operation can still settle. `relay-connection.mjs` owns authenticated relay connection lifecycle, while `relay-connection-classification.mjs` owns close/error classification, handshake/readiness validation, user-facing relay causes, and reconnect backoff. The CLI orchestrates them; it must not become the second implementation of either.
104
+
105
+ ## MCP and tool-schema contract
106
+
107
+ MCP protocol identity is request-scoped. Domain execution must not depend on connection history, an HTTP socket, or a process as conversation identity. Native requests are interpreted solely from current per-request metadata. The declared remote-HTTP initialization compatibility may recognize `2025-06-18`/`2025-11-25` initialize-era metadata and dispatch only its bounded stateless method set through the current controller; it must not create protocol state, participate in request identity/cancellation/caching as a session, or reintroduce a second domain protocol implementation. All other removed initialization/session shapes receive bounded upgrade guidance only.
108
+
109
+ The shared tool catalog is executable schema:
110
+
111
+ - absent `$schema` means JSON Schema 2020-12;
112
+ - only the explicitly implemented bounded keyword set may be used;
113
+ - unsupported dialects/keywords fail process/module initialization rather than being ignored;
114
+ - external `$ref` values are rejected and never fetched;
115
+ - schema depth, total nodes, regular-expression length, and returned issue count are bounded;
116
+ - Worker validation occurs before daemon dispatch, and local validation remains defense in depth for every transport;
117
+ - validation errors contain paths and constraints, never argument values;
118
+ - a schema or validation change requires direct validator tests plus Worker and stdio integration when observable protocol behavior changes.
119
+
120
+ `structuredContent` is arbitrary JSON, not object-only. Code must distinguish absence from the valid value `null`; truthiness is not a presence check for structured protocol fields.
68
121
 
69
122
  ## Logging contract
70
123
 
@@ -142,7 +195,7 @@ The required matrix includes:
142
195
  - stdio JSON-RPC integration;
143
196
  - Worker OAuth/WebSocket/MCP integration;
144
197
  - managed-job integrity, recovery, cancellation, cleanup, and redaction;
145
- - dependency audit, registry signatures/attestations, SBOM, and Worker dry run.
198
+ - dependency audit, registry signatures/attestations, the first-party `sbom:test` CycloneDX identity/graph/privacy check, and Worker dry run.
146
199
 
147
200
  Cross-platform tests must not depend on shell syntax, case-sensitive Windows paths, Unix-only executable shims, or timing races when a deterministic scheduler can be injected. Local success cannot substitute for the required Linux/macOS/Windows push CI result used by the release gate.
148
201
 
@@ -197,3 +250,9 @@ A thorough review asks:
197
250
  - Does the change require a new npm version and deployment?
198
251
 
199
252
  The goal is not cleverness or minimum line count. The goal is explicit boundaries, small state machines, predictable failure behavior, and tests that make future regressions difficult.
253
+
254
+ ### Validation-before-allocation and validation-before-destruction
255
+
256
+ Security-sensitive state transitions follow two related ordering rules. First, prove authority before allocating scarce state: browser HMAC authentication validates a client init proof before reserving a pending challenge slot, and identical retries are idempotent. Second, validate ownership before destructive mutation: file/service/SSH rollback paths bind deletion to descriptor/generation identity rather than pathname alone. Do not move validation after pending-state insertion, unlink, rename, chmod, or other externally visible mutation merely to simplify control flow.
257
+
258
+ Approval and authorization parsers also distinguish omission from malformed explicit input. Optional fields may receive documented defaults only when absent; a provided value of the wrong type or unsupported enum must be rejected rather than silently coerced. Persisted security/recovery markers whose `false` value relaxes a safety gate must be type-checked explicitly instead of normalized with `=== true`.
@@ -16,7 +16,7 @@ Remote and stdio modes use the same local runtime and policy model. The remote W
16
16
 
17
17
  ## 2. Understand the authority you are granting
18
18
 
19
- A new workspace uses the `full` profile unless another profile is selected explicitly. `full` preserves the complete tool catalog, shell execution, paths outside the selected workspace, absolute paths, browser/application automation, and the complete parent process environment. It is intended for a trusted owner using a trusted MCP host. An authenticated owner account may use the `full` ceiling directly without terminal approval. Delegated non-owner accounts require local time-bounded capability leases for high-impact effects; their normal workspace reads/edits and project inspection remain automatic. See [LOCAL_AUTHORIZATION.md](LOCAL_AUTHORIZATION.md).
19
+ A new workspace uses the `full` profile unless another profile is selected explicitly. `full` preserves the complete tool catalog, shell execution, paths outside the selected workspace, absolute paths, browser/application automation, and the complete parent process environment. It is intended for a trusted owner using a trusted MCP host. Delegated accounts remain permanently inside their role ceilings; unsupported effects are denied and cannot be enabled by a terminal approval or lease. The default portable root does not access Keychain or request user presence. A separately installed and provisioned macOS trust broker may request user presence once when its Secure Enclave root signs an ephemeral daemon session. See [LOCAL_AUTHORIZATION.md](LOCAL_AUTHORIZATION.md).
20
20
 
21
21
  For a first connection to an unfamiliar host, start with a narrower profile:
22
22
 
@@ -159,17 +159,18 @@ machine-mcp --workspace /path/to/project --profile review
159
159
  The first start performs these operations:
160
160
 
161
161
  1. canonicalizes and remembers the workspace;
162
- 2. creates owner-only per-workspace state and credentials;
163
- 3. opens the Wrangler/Cloudflare sign-in flow when required;
164
- 4. deploys a Worker and Durable Object for that workspace;
165
- 5. installs a platform-native login service unless `--no-autostart` is supplied;
166
- 6. starts an outbound authenticated WebSocket from the local daemon to the Worker;
167
- 7. creates the initial `owner` account when no account exists and prints its generated password once;
168
- 8. prints the remote `/mcp` URL.
162
+ 2. creates owner-only per-workspace state and a deployment token version;
163
+ 3. retains or creates the owner-only portable device root; when `MBM_MACOS_TRUST_BROKER` explicitly selects a validated provisioned broker, performs the optional two-phase Secure Enclave enrollment and requests user presence only when that root signs the ephemeral daemon session;
164
+ 4. opens the Wrangler/Cloudflare sign-in flow when required;
165
+ 5. deploys the Worker with the active or pending root public key and verifies health before promoting a pending root;
166
+ 6. installs a platform-native login service unless `--no-autostart` is supplied;
167
+ 7. starts an outbound WebSocket authenticated by the root-certified in-memory session key;
168
+ 8. creates the initial `owner` account when no account exists and prints its generated password once;
169
+ 9. prints the remote `/mcp` URL.
169
170
 
170
171
  The foreground command remains attached to the terminal. Keep it running while testing. The remote Worker cannot execute local tools when no authenticated daemon is connected.
171
172
 
172
- The Worker name is a persistent workspace identity, not a retry counter. A successful Wrangler upload is recorded before health verification, so a later timeout does not require a new name and does not make the next start upload again. Supplying a different `--worker-name` for an initialized workspace requires `--force-worker` because it intentionally creates/replaces a separate Cloudflare Worker identity.
173
+ The Worker name is a persistent workspace identity, not a retry counter. A successful Wrangler upload is recorded before health verification, so a later timeout does not require a new name and does not make the next start upload again. Supplying a different `--worker-name` for an initialized workspace requires `--force-worker` because it intentionally creates/replaces a separate Cloudflare Worker identity. The printed `workers.dev` MCP URL is the standard public endpoint and requires no separately owned domain.
173
174
 
174
175
  To run only in the background after setup:
175
176
 
@@ -196,18 +197,15 @@ Password: account_password_...
196
197
 
197
198
  Save the generated password in a password manager. It is not stored locally or shown again. Do not place it in a repository, issue, screenshot, chat message, shell history note, or shared document.
198
199
 
199
- Current ChatGPT developer-mode flow, as documented in OpenAI's [Connect from ChatGPT](https://developers.openai.com/apps-sdk/deploy/connect-chatgpt) guide:
200
+ Current ChatGPT custom-app flow, as documented in OpenAI's Apps/Apps SDK guidance:
200
201
 
201
- 1. Open ChatGPT settings.
202
- 2. Under **Security and login**, enable **Developer mode** if the account or workspace permits it.
203
- 3. Open **Plugins** and create a developer-mode app.
204
- 4. Enter a descriptive name and the exact printed `/mcp` URL.
205
- 5. Start the connection.
206
- 6. On the Machine Bridge authorization page, verify the displayed client name, redirect URI, and resource.
207
- 7. Enter the Machine Bridge account name and password only after those values are recognized.
208
- 8. Create a new chat and enable the app for that conversation.
202
+ 1. In the ChatGPT workspace app settings, create a custom app for the exact printed `/mcp` URL if one does not already exist.
203
+ 2. Complete the Machine Bridge OAuth flow. On the authorization page, verify the displayed client name, redirect URI, and resource before entering the Machine Bridge account name and password.
204
+ 3. Publish/enable the app for the intended workspace users and review its allowed actions according to workspace policy.
205
+ 4. In a supported chat surface, invoke the enabled app using the host's current app-selection or explicit app-routing affordance. ChatGPT UI labels and whether the app is visibly attached before the first invocation can vary by surface and host version.
206
+ 5. After changing the MCP tool catalog or input schemas, use the workspace app's refresh/review flow so the host action snapshot matches the running server before relying on new actions.
209
207
 
210
- ChatGPT navigation labels can change. The invariant is that the client must connect to the public `/mcp` endpoint and complete the OAuth authorization page served by the Worker. The same public `/mcp` URL can be entered in Grok where remote MCP configuration is available. Machine Bridge grants CORS response access to the exact `https://grok.com` and `https://x.com` browser origins as well as ChatGPT's current and legacy origins without requiring a Wrangler command. OAuth navigation and form POST requests are not failed solely because an embedded authorization container reports an opaque or different origin. After validation, the consent page CSP includes only the exact registered callback origin so the browser can complete the `303` return.
208
+ An enabled workspace app is not evidence that every existing conversation has the same host-side app route or cached action/tool snapshot. If a fresh supported conversation can call `server_info` but an older conversation fails before any structured Machine Bridge response, do not diagnose the local daemon as platform-disabled; inspect the host conversation/surface route and app/action snapshot first. The transport invariant remains that ChatGPT connects to the public `/mcp` endpoint and completes the OAuth authorization page served by the Worker. The same public `/mcp` URL can be entered in Grok where remote MCP configuration is available. Machine Bridge grants CORS response access to the exact `https://chatgpt.com`, `https://grok.com`, and `https://x.com` browser origins without requiring a Wrangler command. OAuth navigation and form POST requests are not failed solely because an embedded authorization container reports an opaque or different origin. After validation, the consent page CSP includes only the exact registered callback origin so the browser can complete the `303` return.
211
209
 
212
210
  ### Claude custom connector
213
211
 
@@ -336,7 +334,7 @@ Do not point two logical trust domains at one broad parent directory merely to r
336
334
 
337
335
  ## 13. Upgrade
338
336
 
339
- Version 1 supports only MCP protocol `2025-11-25`; upgrade or reconnect clients that still request an older date. The current 0.18.x state schema remains valid and should be preserved.
337
+ Version 3 supports the current MCP protocol contract advertised by the server and rejects incompatible mixed-version Worker/daemon combinations. Preserve the owner-only state root when upgrading from the immediately preceding supported release; malformed, obsolete, or ambiguous trust state fails closed instead of being guessed or silently regenerated. Follow [UPGRADING.md](UPGRADING.md) for blocked prereleases and coordinated Worker/daemon/browser-extension replacement.
340
338
 
341
339
 
342
340
  Repeat the isolated global installation, then start Machine Bridge in the target workspace:
@@ -1,111 +1,154 @@
1
- # Local transaction authorization
1
+ # Local authorization model
2
2
 
3
- Machine Bridge separates **available capability** from **current remote authority**.
3
+ Machine Bridge treats **capability**, **identity**, and **object ownership** as separate controls. A tool is executable only when every control permits it.
4
4
 
5
- The canonical `full` profile still exposes the complete tool catalog, unrestricted local-user paths, shell execution, browser and application automation, managed jobs, absolute paths, and the complete parent environment. It remains the default for a trusted owner. Version 2.0 does not redefine or narrow that profile.
5
+ For a remote request, effective authority is:
6
6
 
7
- An authenticated `owner` account activates the capabilities permitted by the daemon policy ceiling without a second terminal approval step. This preserves uninterrupted owner automation while retaining OAuth identity binding, account-version revocation, device authentication, and the daemon policy as hard boundaries.
8
-
9
- For delegated `reviewer`, `editor`, and `operator` accounts, the local daemon applies a final transaction gate after the Worker and local runtime have checked the account role and daemon policy. Ordinary project work remains automatic; an operation that crosses a consequential boundary requires a short-lived local capability lease.
10
-
11
- Local stdio calls are not affected by this remote transaction gate. They remain governed by the selected local policy and the MCP host's own approval model.
12
-
13
- ## What remains automatic
14
-
15
- Remote calls do not require a lease for:
7
+ ```text
8
+ daemon capability ceiling
9
+ ∩ authenticated account role
10
+ ∩ trusted OAuth client binding
11
+ ∩ current account version and refresh-token family
12
+ ∩ per-object ownership checks
13
+ ```
16
14
 
17
- - project discovery, status, diagnostics, ordinary metadata, and owner-configured Machine Bridge Agent guidance intended for MCP clients;
18
- - reads inside the selected workspace, except credential-sensitive paths;
19
- - ordinary source and configuration writes inside the selected workspace, excluding credential- and persistence-sensitive targets;
20
- - transactional patches whose source, destination, and move targets remain inside the selected workspace and outside sensitive targets;
21
- - Git inspection;
22
- - browser broker status without reading profile content;
23
- - installed-application discovery without inspecting an application UI;
24
- - registered-resource metadata inspection.
15
+ No approval record, token refresh, client reconnect, or local command can expand the account role. A narrower layer always wins.
25
16
 
26
- This is the normal delegated-account coding and review path. A trusted owner is not interrupted by local approval prompts. For non-owner browser work, one reusable profile-session lease covers the session rather than prompting per page read, field, or click.
17
+ Local stdio does not use remote OAuth accounts. It runs as the local owner under the selected local policy and remains subject to the MCP host and operating-system controls.
27
18
 
28
- ## What requires a lease
19
+ ## Account roles
29
20
 
30
- The daemon requests local authorization for these remote effects:
21
+ | Role | Effective purpose | Important limits |
22
+ |---|---|---|
23
+ | `reviewer` | Read-only inspection of the selected workspace | No mutation or process execution |
24
+ | `editor` | Workspace reads and deterministic file mutation | No process execution |
25
+ | `operator` | Workspace-confined editing and direct process execution | No unrestricted paths, credentials, browser/desktop control, or persistent job creation |
26
+ | `owner` | Complete bridge authority within the daemon policy ceiling | Generic path-based tools cannot target Machine Bridge control-plane state; owner shell remains OS-user authority |
31
27
 
32
- | Scope | Examples |
33
- |---|---|
34
- | `shell` | shell commands, direct process launch, process output continuation, interactive process input or termination, registered local commands |
35
- | `external-read` | reading, searching, imaging, or inspecting a path outside the selected workspace |
36
- | `sensitive-read` | reading credential-sensitive locations or names such as SSH/AWS/Keychain state, `.env`, tokens, secrets, or private keys |
37
- | `external-write` | writing, editing, patching, or moving a patch target outside the selected workspace |
38
- | `sensitive-write` | writing credentials, live `.env` files, SSH/privilege files, shell startup files, Git hooks, LaunchAgents/LaunchDaemons, or other persistence-sensitive paths even when they are inside the selected workspace |
39
- | `browser-session` | listing or reading tabs, source, screenshots, waits, navigation, form input, clicks, submission, tab management, or extension pairing in the existing browser profile |
40
- | `data-export` | uploading a file, inserting a registered local resource into a browser or desktop application, or filling an explicitly sensitive browser field |
41
- | `persistent-job` | staging, starting, listing, reading output from, or cancelling a managed job |
42
- | `application-control` | opening, inspecting, or operating a desktop application |
43
- | `credential-operation` | generating an SSH key resource |
44
- | `full` | all of the above for one explicit temporary automation window |
28
+ The package catalog defines the stable discovery surface. The Worker filters `tools/list` by account role without rewriting it during a brief daemon outage. The live daemon advertisement remains the execution ceiling, and the local runtime independently recomputes and validates the role and policy boundary before dispatch.
45
29
 
46
- Classification uses canonicalized paths and bounded operation metadata. A single operation may require more than one scope: for example, a browser upload requires both `browser-session` and `data-export`, and an external credential read requires both `external-read` and `sensitive-read`. Existing leases may satisfy those scopes independently. A pending approval contains only the scopes still missing, and approving it creates one compound lease for those missing scopes. Pending records contain a SHA-256 target digest, not command text, file contents, form values, or uploaded bytes.
30
+ ## Trusted OAuth clients
47
31
 
48
- Write targets are canonicalized through their nearest existing ancestor even under `full`. A path that enters an in-workspace symbolic-link directory is classified by the real destination, while overwriting a final symbolic link is rejected. Patch `Move to` destinations are classified alongside add/update/delete paths. This preserves unrestricted-path capability without allowing path aliases to weaken the lease boundary.
32
+ Dynamic OAuth registration creates an untrusted client record. The first successful account authorization binds that client to:
49
33
 
50
- The browser boundary is intentionally session-granular. The packaged extension controls whichever Chromium profile the user loaded it into; Machine Bridge cannot prove that the profile is isolated. Requiring one `browser-session` lease protects tab metadata and authenticated page content without degrading into per-click prompts. Once granted, ordinary browser reads, navigation, filling, and clicks proceed continuously until expiry. Exporting registered local data remains separately gated.
34
+ - one account ID;
35
+ - the account version at authorization time;
36
+ - the account role;
37
+ - the OAuth client ID.
51
38
 
52
- ## Optional delegated-account approval flow
39
+ A client cannot silently switch to another account. Account disablement, role changes, password rotation, client revocation, token-version rotation, and refresh-token replay outside the bounded concurrent-refresh window invalidate the relevant credentials.
53
40
 
54
- Owner requests never create pending approval IDs. When a lease is missing for a non-owner account, the tool call fails with `local_approval_required` and a command containing a random pending approval ID. List pending requests and active leases locally:
41
+ Inspect trusted clients locally:
55
42
 
56
43
  ```sh
57
- machine-mcp --workspace /path/to/project approval list
44
+ machine-mcp account clients --workspace /path/to/project
58
45
  ```
59
46
 
60
- Approve only the requested scope for one hour:
47
+ Revoke one client and all of its authorization codes, access tokens, and refresh tokens:
61
48
 
62
49
  ```sh
63
- machine-mcp --workspace /path/to/project approval approve APPROVAL_ID --duration 1h
50
+ machine-mcp account revoke-client CLIENT_ID --workspace /path/to/project
64
51
  ```
65
52
 
66
- Then retry the original task. Further matching operations from the same account and OAuth client run without interruption until the lease expires.
53
+ Account-management requests are signed by a root-certified ephemeral device session. Machine Bridge does not deploy or retain a long-lived account-administration bearer or HMAC secret.
67
54
 
68
- For a trusted, intensive automation session, convert the same pending request into an explicit temporary `full` window:
55
+ ## Automatic execution
69
56
 
70
- ```sh
71
- machine-mcp --workspace /path/to/project approval approve APPROVAL_ID --full
72
- ```
57
+ There is no per-operation approval prompt in the current runtime.
73
58
 
74
- `--full` defaults to eight hours and cannot exceed eight hours. It is local, account-bound, client-bound, time-bounded, and revocable. It does not change the saved policy profile or extend itself remotely.
59
+ Within the effective role and daemon ceiling, calls execute automatically. Outside that intersection, calls fail immediately with `authorization_denied`; the response does not contain an approval ID or a command to retry.
75
60
 
76
- A specific scope can also be granted in advance. Account and OAuth client IDs are available from `approval list --json` after the client has produced a pending request. Wildcards are supported only when entered explicitly:
61
+ Examples:
77
62
 
78
- ```sh
79
- machine-mcp --workspace /path/to/project approval grant shell \
80
- --account ACCOUNT_ID --client CLIENT_ID --duration 2h
81
- ```
63
+ - a reviewer may inspect files inside the selected workspace;
64
+ - an editor may update ordinary workspace files;
65
+ - an operator may run a workspace-confined process only when the delegated process sandbox is behaviorally verified;
66
+ - an owner may use shell, unrestricted paths, browser/application automation, resources, and managed jobs when enabled by the daemon policy.
82
67
 
83
- ## Revocation
68
+ Risk classification still runs for every consequential request. It supplies structured audit metadata and enforces hard boundaries; it is not a mechanism for temporary privilege escalation.
84
69
 
85
- Revoke one lease:
70
+ ## Hard boundaries
86
71
 
87
- ```sh
88
- machine-mcp --workspace /path/to/project approval revoke LEASE_ID
89
- ```
72
+ ### Machine Bridge control plane
90
73
 
91
- Revoke every active remote capability lease for the workspace:
74
+ Generic path-based file, image, search, and patch tools cannot target Machine Bridge state, device-root metadata, account-management state, audit-chain state, service metadata, or other protected roots. This applies to `owner` as well as delegated accounts.
92
75
 
93
- ```sh
94
- machine-mcp --workspace /path/to/project approval clear
95
- ```
76
+ This is an application-level path boundary, not an arbitrary-code sandbox. An authorized `owner` shell or interpreter has the daemon OS user's ambient filesystem authority. Control-plane administration uses local CLI interfaces; mutually untrusted owner execution requires external OS isolation.
77
+
78
+ ### Sensitive and persistent targets
79
+
80
+ Non-owner accounts cannot access credential- or persistence-sensitive targets, including live environment files, private keys, token stores, shell startup files, Git hooks, privilege configuration, LaunchAgents, LaunchDaemons, and equivalent persistence locations.
81
+
82
+ Final symbolic-link overwrites are rejected. Existing ancestors and patch move destinations are canonicalized before classification so a workspace alias cannot conceal an external or sensitive destination.
83
+
84
+ ### Browser, desktop, and data export
85
+
86
+ Only `owner` may control the existing browser profile or desktop applications, upload local files, or inject registered resources into an interactive session. Browser and application actions operate on the user's logged-in session and therefore are not delegated to lower roles.
87
+
88
+ ### Persistent jobs
96
89
 
97
- Stopping the daemon prevents execution while it is offline, but leases remain in owner-only state until expiry or explicit revocation. Incident response should therefore stop the daemon, clear leases, revoke or rotate affected OAuth credentials, and inspect account/client state.
90
+ Only `owner` may create persistent execution plans with `start_job` or non-executing drafts with `stage_job`.
98
91
 
99
- ## Binding and storage
92
+ `stage_job` does not execute and is not an approval workflow. The removed `machine-mcp job approve` path cannot turn a draft into a running job. Execution requires a trusted owner request through `start_job`, or an explicit local `job submit` operation performed by the machine operator.
100
93
 
101
- Every lease binds:
94
+ ## Delegated process isolation
95
+
96
+ An `operator` process is not accepted merely because its current directory and environment are restricted. Machine Bridge requires a behaviorally verified OS sandbox that:
97
+
98
+ - exposes the selected workspace and an isolated runtime directory;
99
+ - blocks the real user home and Machine Bridge state;
100
+ - blocks Keychain and desktop automation access;
101
+ - preserves the minimum system runtime needed by ordinary tools.
102
+
103
+ The probe is fail-closed. The presence of a sandbox executable is not sufficient.
104
+
105
+ On platforms where the negative security boundary cannot be verified, delegated process execution is unavailable. Owner execution remains governed by the selected daemon policy. For mutually untrusted workloads, use a separate OS account, container, or VM.
106
+
107
+ Implementation-owned metadata probes are a separate boundary from delegated arbitrary execution. `project_overview` and the read-only Git tools use fixed argv selected by Machine Bridge, never a caller-provided executable or shell string. Those probes run with a minimal isolated environment, bounded output and deadlines, cancellation/process-tree tracking, and the request’s path-visibility rules. They do not grant `run_process`, registered-command, or shell authority to reviewer/editor accounts.
108
+
109
+ ## Object ownership
110
+
111
+ Long-lived runtime objects bind to the principal that created them:
102
112
 
103
113
  - account ID;
114
+ - account version;
104
115
  - OAuth client ID;
105
- - one or more explicitly approved scopes, or the standalone `full` scope;
106
- - creation and expiration times;
107
- - an optional source pending-approval ID.
116
+ - refresh-token family ID.
117
+
118
+ The binding applies to interactive processes, retained command-output sessions, and managed jobs. Another account, client, or refresh family cannot read, continue, send input to, cancel, or terminate those objects.
119
+
120
+ ## Device-root authorization
121
+
122
+ The default root on every platform is a portable owner-only P-256 key. It signs the 24-hour ephemeral session certificate without Keychain access or a user-presence prompt. On macOS, `MBM_MACOS_TRUST_BROKER` may explicitly select a separately provisioned app-like broker; only after its code signature, Team ID, canonical non-symlink path with no group/other write access, and real Secure Enclave key probe validate does a non-exportable root replace the portable provider. That provider requests user presence once when signing the daemon session certificate. The private session key remains in memory and handles WebSocket preflight, challenge authentication, reconnects, and local account administration for that daemon lifetime.
123
+
124
+ Expected interaction frequency:
125
+
126
+ - ordinary tool calls: no local prompt;
127
+ - portable-root daemon startup: no prompt;
128
+ - provisioned Secure Enclave daemon startup: one user-presence prompt;
129
+ - network reconnect: no prompt;
130
+ - an independent account-management command: no prompt with a portable root, or one prompt with a provisioned Secure Enclave root;
131
+ - root rotation: one explicit operation, with user presence only when the provisioned broker requires it.
132
+
133
+ Every platform uses the portable P-256 provider unless an explicitly configured non-exportable platform provider has been installed and validated. `server_info.security.device_root` reports the active provider and whether the root key is exportable.
134
+
135
+ ## DPoP
136
+
137
+ OAuth clients that support DPoP may bind access and refresh tokens to their own P-256 key. The Worker validates the proof method, URL, timestamp, nonce identifier, access-token hash, and key thumbprint. A copied token is insufficient without the client private key.
138
+
139
+ Bearer remains available for MCP hosts that do not implement DPoP. Client trust, account versioning, refresh-family rotation, and role ceilings still apply.
140
+
141
+ ## Audit and incident response
142
+
143
+ The local security audit is a bounded SHA-256 hash chain. It records operation class, outcome, duration, byte counts, and pseudonymous target/principal references. Target and account/client/family identifiers are HMAC-keyed with fresh per-daemon runtime keys before persistent state applies its per-file salt; the resulting references remain useful for within-runtime correlation without making the stored public salt sufficient for offline identifier/path enumeration. They are not stable cross-restart identities. The audit does not record command text, file paths, file contents, form values, or tool output.
144
+
145
+ For incident response:
108
146
 
109
- Normal scopes may last at most twelve hours. `full` may last at most eight hours. Pending requests expire after ten minutes. Lease and pending files are size-bounded, owner-only, atomically replaced, schema-validated, and validated record by record. Daemon-created pending requests and separate CLI approval/revocation processes serialize mutations through an owner-only process-identity lock, preventing lost updates during concurrent use. Malformed state or lock metadata fails closed.
147
+ 1. stop the daemon;
148
+ 2. revoke the affected OAuth client or disable the account;
149
+ 3. rotate the account password or global token version when appropriate;
150
+ 4. rotate the device root when device identity may be compromised;
151
+ 5. inspect the audit-chain health and local endpoint logs;
152
+ 6. restart and reconnect only trusted clients.
110
153
 
111
- This is an application-level control, not an OS sandbox. A process already running as the same OS user can interfere with local files and memory. Use a separate OS account, VM, or container when the client, repository, or instructions are mutually untrusted.
154
+ Legacy capability-lease files from version 2 may still be listed, revoked, or cleared by the local CLI for migration cleanup. The version 3 runtime never consumes them and never creates pending approval IDs.