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
@@ -3,10 +3,10 @@ import { normalizeLogLevel } from "./log.mjs";
3
3
  const BOOLEAN_OPTIONS = new Set([
4
4
  "help", "version", "quiet", "json", "verbose", "rotateSecrets", "forceWorker",
5
5
  "daemonOnly", "noAutostart", "noWrite", "noExec", "fullEnv", "unrestrictedPaths", "absolutePaths",
6
- "yes", "keepWorker", "allowInsecurePermissions", "showPaths", "full",
6
+ "yes", "keepWorker", "allowInsecurePermissions", "showPaths",
7
7
  ]);
8
8
  const VALUE_OPTIONS = new Set([
9
- "workspace", "stateDir", "workerName", "profile", "execMode", "client", "account", "duration", "logLevel", "logFormat",
9
+ "workspace", "stateDir", "workerName", "profile", "execMode", "client", "logLevel", "logFormat",
10
10
  ]);
11
11
 
12
12
  const LOG_FORMATS = new Set(["text", "json"]);
@@ -17,6 +17,10 @@ const COMMAND_OPTIONS = new Map(Object.entries({
17
17
  "daemonOnly", "noAutostart",
18
18
  "profile", "execMode", "noWrite", "noExec", "fullEnv", "unrestrictedPaths", "absolutePaths",
19
19
  ]),
20
+ activate: new Set([
21
+ "workspace", "stateDir", "workerName", "quiet", "json", "verbose", "logLevel", "logFormat", "rotateSecrets", "forceWorker",
22
+ "profile", "execMode", "noWrite", "noExec", "fullEnv", "unrestrictedPaths", "absolutePaths",
23
+ ]),
20
24
  stdio: new Set(["workspace", "stateDir", "profile", "execMode", "noWrite", "noExec", "fullEnv", "unrestrictedPaths", "absolutePaths", "verbose", "quiet", "logLevel", "logFormat"]),
21
25
  "client-config": new Set(["workspace", "stateDir", "profile", "client", "json"]),
22
26
  status: new Set(["workspace", "stateDir"]),
@@ -28,21 +32,19 @@ const COMMAND_OPTIONS = new Map(Object.entries({
28
32
  autostart: new Set(["workspace", "stateDir", "quiet"]),
29
33
  resource: new Set(["workspace", "stateDir", "allowInsecurePermissions", "showPaths", "json"]),
30
34
  account: new Set(["workspace", "stateDir", "json", "yes"]),
31
- approval: new Set(["workspace", "stateDir", "json", "yes", "client", "account", "duration", "full"]),
32
35
  browser: new Set(["workspace", "stateDir", "json"]),
33
36
  job: new Set(["workspace", "stateDir", "json", "yes"]),
34
37
  uninstall: new Set(["stateDir", "keepWorker", "yes"]),
35
38
  }));
36
39
 
37
- const SINGLE_WORKSPACE_POSITIONAL_COMMANDS = new Set(["start", "stdio", "status", "doctor", "full-test", "rotate-secrets"]);
40
+ const SINGLE_WORKSPACE_POSITIONAL_COMMANDS = new Set(["start", "activate", "stdio", "status", "doctor", "full-test", "rotate-secrets"]);
38
41
  const STATIC_POSITIONAL_RULES = new Map([
39
42
  ["client-config", Object.freeze({ max: 1, tooMany: "client-config accepts at most one positional client name" })],
40
43
  ["uninstall", Object.freeze({ max: 0, tooMany: "uninstall does not accept positional arguments" })],
41
44
  ]);
42
45
  const RESOURCE_POSITIONAL_LIMITS = new Map(Object.entries({ add: 3, "generate-ssh-key": 3, remove: 2, check: 2 }));
43
- const JOB_POSITIONAL_LIMITS = new Map(Object.entries({ read: 2, inspect: 2, cancel: 2, approve: 2, submit: 2 }));
44
- const ACCOUNT_POSITIONAL_LIMITS = new Map(Object.entries({ list: 1, add: 3, role: 3, enable: 2, disable: 2, "rotate-password": 2, remove: 2 }));
45
- const APPROVAL_POSITIONAL_LIMITS = new Map(Object.entries({ list: 1, approve: 2, grant: 2, revoke: 2, clear: 1 }));
46
+ const JOB_POSITIONAL_LIMITS = new Map(Object.entries({ read: 2, inspect: 2, cancel: 2, submit: 2 }));
47
+ const ACCOUNT_POSITIONAL_LIMITS = new Map(Object.entries({ list: 1, clients: 1, "revoke-client": 2, add: 3, role: 3, enable: 2, disable: 2, "rotate-password": 2, remove: 2 }));
46
48
  const ACTION_POSITIONAL_RULES = new Map(Object.entries({
47
49
  workspace(args) {
48
50
  const action = String(args._[0] || "show");
@@ -50,7 +52,7 @@ const ACTION_POSITIONAL_RULES = new Map(Object.entries({
50
52
  },
51
53
  service(args) {
52
54
  const action = String(args._[0] || "status");
53
- return { max: ["install", "status", "stop", "uninstall", "remove"].includes(action) ? 2 : 1, tooMany: `service ${action} received too many positional arguments`, workspaceConflictAfter: 1 };
55
+ return { max: ["install", "status", "stop"].includes(action) ? 2 : 1, tooMany: `service ${action} received too many positional arguments`, workspaceConflictAfter: 1 };
54
56
  },
55
57
  autostart(args) { return ACTION_POSITIONAL_RULES.get("service")(args); },
56
58
  resource(args) {
@@ -61,17 +63,14 @@ const ACTION_POSITIONAL_RULES = new Map(Object.entries({
61
63
  const action = String(args._[0] || "list");
62
64
  return { max: ACCOUNT_POSITIONAL_LIMITS.get(action) ?? 1, tooMany: `account ${action} received too many positional arguments` };
63
65
  },
64
- approval(args) {
65
- const action = String(args._[0] || "list");
66
- return { max: APPROVAL_POSITIONAL_LIMITS.get(action) ?? 1, tooMany: `approval ${action} received too many positional arguments` };
67
- },
68
66
  browser(args) {
69
67
  const action = String(args._[0] || "status");
70
68
  return { max: 1, tooMany: `browser ${action} received too many positional arguments` };
71
69
  },
72
70
  job(args) {
73
71
  const action = String(args._[0] || "list");
74
- return { max: JOB_POSITIONAL_LIMITS.get(action) ?? 1, tooMany: `job ${action} received too many positional arguments` };
72
+ const max = JOB_POSITIONAL_LIMITS.get(action);
73
+ return max === undefined ? null : { max, tooMany: `job ${action} received too many positional arguments` };
75
74
  },
76
75
  }));
77
76
 
@@ -0,0 +1,52 @@
1
+ import { createLogger } from "./log.mjs";
2
+
3
+ export function printStartJson(state, { requestedChangesApplied = true, notice = "", initialOwner = null } = {}) {
4
+ createLogger({ component: "ready" }).json({
5
+ mcp: {
6
+ server_url: state.worker.mcpServerUrl,
7
+ worker_url: state.worker.url,
8
+ worker_name: state.worker.name,
9
+ },
10
+ ...(initialOwner ? { initial_owner: initialOwner } : {}),
11
+ workspace: state.workspace.path,
12
+ state_path: state.paths.statePath,
13
+ policy: state.policy,
14
+ requested_changes_applied: requestedChangesApplied,
15
+ ...(notice ? { notice } : {}),
16
+ });
17
+ }
18
+
19
+ export function printMcpConnection(state, { quiet = false, verbose = false, initialOwner = null, logger: readyLogger = null } = {}) {
20
+ const output = readyLogger || createLogger({ component: "ready", quiet, level: quiet ? "error" : verbose ? "debug" : "info" });
21
+ if (output.format === "json" && !initialOwner) {
22
+ output.event("success", "daemon.ready", {
23
+ mcp_server_url: state.worker.mcpServerUrl,
24
+ worker_name: state.worker.name,
25
+ workspace_path: state.workspace.path,
26
+ policy_profile: state.policy.profile,
27
+ policy_origin: state.policy.origin,
28
+ write_enabled: state.policy.allowWrite,
29
+ exec_mode: state.policy.execMode,
30
+ }, "Remote MCP bridge is ready");
31
+ return;
32
+ }
33
+ const logger = output;
34
+ logger.success("Remote MCP bridge is ready");
35
+ logger.plain(` MCP Server URL: ${state.worker.mcpServerUrl}`);
36
+ if (initialOwner) {
37
+ logger.warn("Initial owner account created; save the password now because it is not stored locally or shown again. Do not share this terminal output; rotate the password immediately if it has been exposed.");
38
+ logger.plain(` Account: ${initialOwner.name}`);
39
+ logger.plain(` Password: ${initialOwner.password}`);
40
+ } else {
41
+ logger.safePlain(" Use `machine-mcp account` to manage account access.");
42
+ }
43
+ logger.plain(` Workspace: ${state.workspace.path}`);
44
+ logger.safePlain(` Policy: ${formatPolicySummary(state.policy)}`);
45
+ if (verbose) logger.plain(` State: ${state.paths.statePath}`);
46
+ }
47
+
48
+ export function formatPolicySummary(policy = {}) {
49
+ const scope = policy.unrestrictedPaths ? "all local paths" : "workspace only";
50
+ const environment = policy.minimalEnv ? "isolated env" : "full parent env";
51
+ return `${policy.profile || "custom"} [${policy.origin || "unknown"}; write=${policy.allowWrite ? "on" : "off"}; exec=${policy.execMode || "off"}; ${scope}; ${environment}; absolute_paths=${policy.exposeAbsolutePaths ? "on" : "off"}]`;
52
+ }
@@ -3,12 +3,16 @@ import * as defaultService from "./service.mjs";
3
3
  import { inspectWorkspaceDaemon, stopWorkspaceServiceDaemon } from "./daemon-process.mjs";
4
4
  import { stopAndRemoveAutostart } from "./service-lifecycle.mjs";
5
5
  import { serviceEnvironmentSummary } from "./service-environment.mjs";
6
+ import { scheduleServiceRestart } from "./service-restart-scheduler.mjs";
7
+ import { startOwnedServiceRuntime } from "./service-runtime.mjs";
8
+ import { loadServiceOwner } from "./service-owner.mjs";
6
9
  import { loadState, resolveWorkspace, selectedWorkspace } from "./state.mjs";
7
10
 
8
11
  const SERVICE_ACTION_HANDLERS = new Map([
9
12
  ["status", serviceStatusAction],
10
13
  ["install", serviceInstallAction],
11
14
  ["start", serviceStartAction],
15
+ ["restart", serviceRestartAction],
12
16
  ["stop", serviceStopAction],
13
17
  ["uninstall", serviceUninstallAction],
14
18
  ["remove", serviceUninstallAction],
@@ -19,11 +23,18 @@ export function createServiceCommand(dependencies) {
19
23
  chooseWorkspace: requiredFunction(dependencies.chooseWorkspace, "chooseWorkspace"),
20
24
  stateRootFromArgs: requiredFunction(dependencies.stateRootFromArgs, "stateRootFromArgs"),
21
25
  structuredLogger: requiredFunction(dependencies.structuredLogger, "structuredLogger"),
26
+ currentPackageVersion: requiredFunction(dependencies.currentPackageVersion, "currentPackageVersion"),
22
27
  service: dependencies.service || defaultService,
23
28
  inspectWorkspaceDaemon: dependencies.inspectWorkspaceDaemon || inspectWorkspaceDaemon,
24
29
  stopWorkspaceServiceDaemon: dependencies.stopWorkspaceServiceDaemon || stopWorkspaceServiceDaemon,
25
30
  stopAndRemoveAutostart: dependencies.stopAndRemoveAutostart || stopAndRemoveAutostart,
26
31
  serviceEnvironmentSummary: dependencies.serviceEnvironmentSummary || serviceEnvironmentSummary,
32
+ loadServiceOwner: dependencies.loadServiceOwner || loadServiceOwner,
33
+ scheduleServiceRestart: dependencies.scheduleServiceRestart || scheduleServiceRestart,
34
+ startOwnedServiceRuntime: dependencies.startOwnedServiceRuntime || startOwnedServiceRuntime,
35
+ acquireMachineServiceLockWithWait: requiredFunction(
36
+ dependencies.acquireMachineServiceLockWithWait, "acquireMachineServiceLockWithWait",
37
+ ),
27
38
  loadState: dependencies.loadState || loadState,
28
39
  resolveWorkspace: dependencies.resolveWorkspace || resolveWorkspace,
29
40
  selectedWorkspace: dependencies.selectedWorkspace || selectedWorkspace,
@@ -39,19 +50,46 @@ async function serviceCommand(args, context) {
39
50
  const handler = SERVICE_ACTION_HANDLERS.get(action);
40
51
  if (!handler) throw new Error(`Unknown service action: ${action}`);
41
52
  const stateRoot = context.stateRootFromArgs(args);
42
- return handler({ args, stateRoot, service: context.service, context });
53
+ if (!new Set(["install", "start", "stop", "uninstall", "remove"]).has(action)) {
54
+ return handler({ args, stateRoot, service: context.service, context });
55
+ }
56
+ const lock = await context.acquireMachineServiceLockWithWait({ operation: `service-${action}` });
57
+ if (!lock?.acquired || typeof lock.release !== "function") {
58
+ throw new Error("machine-service operation lock could not be acquired");
59
+ }
60
+ try {
61
+ return await handler({ args, stateRoot, service: context.service, context });
62
+ } finally {
63
+ lock.release();
64
+ }
43
65
  }
44
66
 
45
67
  async function serviceStatusAction({ args, stateRoot, service, context }) {
46
68
  const status = await service.autostartStatus();
47
- const state = optionalServiceState(args, stateRoot, context);
48
- const workspaceDaemon = state ? context.inspectWorkspaceDaemon(state) : null;
69
+ let owner = null;
70
+ let ownerProjection = { status: "missing", version: null };
71
+ try {
72
+ owner = context.loadServiceOwner();
73
+ if (owner) ownerProjection = { status: owner.status, version: owner.version };
74
+ } catch {
75
+ ownerProjection = { status: "invalid", version: null, error_class: "invalid_state" };
76
+ }
77
+ const explicitState = hasExplicitServiceTarget(args) ? optionalServiceState(args, stateRoot, context) : null;
78
+ const ownerState = !explicitState && owner?.status === "committed"
79
+ ? context.loadState(owner.workspace, { stateDir: owner.stateRoot })
80
+ : null;
81
+ const state = explicitState || ownerState || optionalServiceState(args, stateRoot, context);
82
+ const effectiveStateRoot = ownerState ? owner.stateRoot : stateRoot;
83
+ const workspaceDaemon = state ? context.inspectWorkspaceDaemon(state, ownerState ? {
84
+ expectedVersion: owner.version, expectedEntryScript: owner.entryScript,
85
+ } : {}) : null;
49
86
  printServiceResult({
50
87
  ...status,
51
88
  workspace: state?.workspace?.path || null,
52
89
  workspace_daemon: workspaceDaemon,
53
- service_environment: context.serviceEnvironmentSummary(stateRoot),
54
- effective_active: Boolean(status.active || workspaceDaemon?.alive),
90
+ service_owner: ownerProjection,
91
+ service_environment: context.serviceEnvironmentSummary(effectiveStateRoot),
92
+ effective_active: status.active === true || workspaceDaemon?.alive === true ? true : status.active === false ? false : null,
55
93
  orphaned_workspace_daemon: Boolean(status.active === false && workspaceDaemon?.alive && workspaceDaemon?.verified_service_daemon),
56
94
  }, context, false);
57
95
  }
@@ -63,24 +101,49 @@ async function serviceInstallAction({ args, stateRoot, service, context }) {
63
101
  if (!state.worker?.url) {
64
102
  throw new Error("No deployed Worker is recorded for this workspace. Run `machine-mcp` once before `machine-mcp service install`.");
65
103
  }
104
+ const provider = await service.autostartStatus();
105
+ const daemon = context.inspectWorkspaceDaemon(state);
106
+ if (typeof provider?.active !== "boolean") {
107
+ throw new Error("machine service activity could not be verified before installation");
108
+ }
109
+ if (provider.active || daemon?.alive) {
110
+ throw new Error("refusing to replace the machine service definition while a provider or workspace daemon is active");
111
+ }
66
112
  const result = await service.installAutostart({
67
113
  workspace,
68
114
  stateRoot,
69
115
  entryScript: context.entryScript,
116
+ version: context.currentPackageVersion(),
70
117
  logger: context.structuredLogger(Boolean(args.quiet)),
71
118
  });
72
119
  printServiceResult(result, context);
73
120
  }
74
121
 
75
122
  async function serviceStartAction({ args, service, context }) {
76
- const result = await service.startAutostart({ logger: context.structuredLogger(Boolean(args.quiet)) });
123
+ assertGlobalServiceAction(args, "start");
124
+ const logger = context.structuredLogger(Boolean(args.quiet));
125
+ const result = await context.startOwnedServiceRuntime({
126
+ logger,
127
+ readProvider: service.autostartStatus,
128
+ mutateProvider: service.startAutostart,
129
+ stopProvider: service.stopAutostart,
130
+ });
77
131
  printServiceResult(result, context);
78
132
  }
79
133
 
134
+ async function serviceRestartAction({ args, context }) {
135
+ assertGlobalServiceAction(args, "restart");
136
+ const result = await context.scheduleServiceRestart();
137
+ printServiceResult({ ...result, provider: "detached-handoff", reason: "restart_scheduled" }, context);
138
+ }
139
+
80
140
  async function serviceStopAction({ args, stateRoot, service, context }) {
81
141
  const logger = context.structuredLogger(Boolean(args.quiet));
82
- const provider = await service.stopAutostart({ logger });
83
142
  const state = optionalServiceState(args, stateRoot, context);
143
+ const status = await service.autostartStatus();
144
+ const before = state ? context.inspectWorkspaceDaemon(state) : null;
145
+ assertExplicitStopTarget(args, status, before);
146
+ const provider = await service.stopAutostart({ logger });
84
147
  const workspaceDaemon = state
85
148
  ? await context.stopWorkspaceServiceDaemon(state, { logger, reason: "service stop" })
86
149
  : { ok: true, found: false, stopped: false, verified_service_daemon: false, reason: "workspace_not_selected" };
@@ -92,16 +155,17 @@ async function serviceStopAction({ args, stateRoot, service, context }) {
92
155
  }, context);
93
156
  }
94
157
 
95
- async function serviceUninstallAction({ args, stateRoot, service, context }) {
158
+ async function serviceUninstallAction({ args, stateRoot, context }) {
159
+ assertGlobalServiceAction(args, "uninstall");
96
160
  const logger = context.structuredLogger(Boolean(args.quiet));
97
- const state = optionalServiceState(args, stateRoot, context);
161
+ const state = optionalServiceState({ ...args, workspace: undefined, stateDir: undefined }, stateRoot, context);
98
162
  const lifecycle = await context.stopAndRemoveAutostart({
99
163
  states: state ? [state] : [],
100
164
  stateRoot,
101
165
  logger,
102
166
  reason: "service uninstall",
103
- stopAutostart: service.stopAutostart,
104
- uninstallAutostart: service.uninstallAutostart,
167
+ stopAutostart: context.service.stopAutostart,
168
+ uninstallAutostart: context.service.uninstallAutostart,
105
169
  stopWorkspaceServiceDaemon: context.stopWorkspaceServiceDaemon,
106
170
  });
107
171
  printServiceResult({
@@ -112,6 +176,22 @@ async function serviceUninstallAction({ args, stateRoot, service, context }) {
112
176
  }, context);
113
177
  }
114
178
 
179
+ function assertGlobalServiceAction(args, action) {
180
+ if (args.workspace || args.stateDir || args._[1]) {
181
+ throw new Error(`service ${action} acts on the single installed machine service and does not accept workspace or state overrides; use service install to change its owner`);
182
+ }
183
+ }
184
+
185
+ function assertExplicitStopTarget(args, status, workspaceDaemon) {
186
+ if (!hasExplicitServiceTarget(args) || status?.active !== true) return;
187
+ if (workspaceDaemon?.alive === true && workspaceDaemon?.verified_service_daemon === true) return;
188
+ throw new Error("refusing to stop the active machine service because the requested workspace/state does not own its verified daemon; omit the target to stop the installed service globally");
189
+ }
190
+
191
+ function hasExplicitServiceTarget(args) {
192
+ return Boolean(args.workspace || args.stateDir || args._[1]);
193
+ }
194
+
115
195
  function optionalServiceState(args, stateRoot, context) {
116
196
  const requested = args.workspace || args._[1] || context.selectedWorkspace(stateRoot);
117
197
  if (!requested || requested === true) return null;