machine-bridge-mcp 2.0.0 → 3.0.0-beta.9
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.
- package/CHANGELOG.md +101 -0
- package/CONTRIBUTING.md +20 -25
- package/README.md +21 -14
- package/SECURITY.md +147 -123
- package/browser-extension/manifest.json +3 -2
- package/browser-extension/service-worker.js +31 -12
- package/docs/ARCHITECTURE.md +27 -13
- package/docs/AUDIT.md +85 -2
- package/docs/CLIENTS.md +2 -2
- package/docs/ENGINEERING.md +9 -3
- package/docs/GETTING_STARTED.md +10 -9
- package/docs/LOCAL_AUTHORIZATION.md +115 -72
- package/docs/LOGGING.md +12 -3
- package/docs/MANAGED_JOBS.md +24 -29
- package/docs/MULTI_ACCOUNT.md +98 -37
- package/docs/OPERATIONS.md +33 -22
- package/docs/OVERVIEW.md +7 -7
- package/docs/PROJECT_STANDARDS.md +9 -5
- package/docs/RELEASING.md +171 -64
- package/docs/TESTING.md +19 -7
- package/docs/THREAT_MODEL.md +138 -67
- package/docs/TOOL_REFERENCE.md +2 -2
- package/docs/UPGRADING.md +102 -18
- package/native/macos/MachineBridgeTrustBroker.swift +233 -0
- package/package.json +36 -5
- package/scripts/candidate-runtime-store.mjs +38 -0
- package/scripts/check-plan.mjs +19 -0
- package/scripts/check-runner.mjs +4 -1
- package/scripts/commit-message-check.mjs +5 -2
- package/scripts/coverage-check.mjs +30 -2
- package/scripts/github-push.mjs +11 -0
- package/scripts/github-release.mjs +38 -7
- package/scripts/install-published-prerelease.mjs +167 -0
- package/scripts/local-release-acceptance.mjs +23 -12
- package/scripts/npm-publication-policy.mjs +16 -0
- package/scripts/prerelease-activation.mjs +79 -0
- package/scripts/privacy-check.mjs +7 -5
- package/scripts/promotion-digest.mjs +121 -0
- package/scripts/publish-npm.mjs +51 -0
- package/scripts/published-release.mjs +80 -0
- package/scripts/release-acceptance.mjs +30 -1
- package/scripts/release-candidate-manifest.mjs +40 -0
- package/scripts/release-channel.mjs +106 -0
- package/scripts/release-impact-check.mjs +12 -22
- package/scripts/release-soak.mjs +237 -0
- package/scripts/start-release-candidate.mjs +113 -7
- package/src/local/account-access.mjs +6 -0
- package/src/local/account-admin.mjs +34 -16
- package/src/local/agent-context.mjs +45 -42
- package/src/local/app-automation.mjs +9 -4
- package/src/local/authority-context.mjs +106 -0
- package/src/local/browser-bridge-http.mjs +4 -1
- package/src/local/browser-bridge.mjs +14 -9
- package/src/local/browser-broker-routes.mjs +4 -0
- package/src/local/browser-broker-server.mjs +5 -4
- package/src/local/browser-extension-identity.mjs +50 -0
- package/src/local/browser-extension-protocol.mjs +9 -4
- package/src/local/browser-operation-service.mjs +7 -0
- package/src/local/browser-pairing-http.mjs +36 -0
- package/src/local/browser-pairing-store.mjs +56 -47
- package/src/local/cli-account-admin.mjs +41 -7
- package/src/local/cli-activate.mjs +90 -0
- package/src/local/cli-approval.mjs +14 -58
- package/src/local/cli-local-admin.mjs +5 -15
- package/src/local/cli-options.mjs +11 -7
- package/src/local/cli-service.mjs +35 -5
- package/src/local/cli.mjs +112 -58
- package/src/local/daemon-process.mjs +6 -0
- package/src/local/delegated-process-sandbox.mjs +147 -0
- package/src/local/device-identity.mjs +157 -48
- package/src/local/device-root-provider.mjs +87 -0
- package/src/local/errors.mjs +25 -3
- package/src/local/git-service.mjs +16 -15
- package/src/local/job-runner.mjs +35 -27
- package/src/local/log.mjs +14 -1
- package/src/local/macos-trust-broker.mjs +320 -0
- package/src/local/managed-job-lock.mjs +18 -0
- package/src/local/managed-job-projection.mjs +9 -1
- package/src/local/managed-job-runner.mjs +13 -1
- package/src/local/managed-job-storage.mjs +2 -1
- package/src/local/managed-job-terminal.mjs +138 -0
- package/src/local/managed-jobs.mjs +88 -32
- package/src/local/operation-authorization.mjs +75 -239
- package/src/local/operation-risk.mjs +28 -0
- package/src/local/operation-state-lock.mjs +7 -86
- package/src/local/owner-state-lock.mjs +104 -0
- package/src/local/policy.mjs +19 -0
- package/src/local/process-execution.mjs +21 -9
- package/src/local/process-sessions.mjs +27 -17
- package/src/local/process-tracker.mjs +30 -6
- package/src/local/process-tree-ownership.mjs +59 -0
- package/src/local/process-tree.mjs +22 -18
- package/src/local/relay-connection.mjs +47 -35
- package/src/local/relay-diagnostics.mjs +65 -0
- package/src/local/remote-configuration.mjs +48 -0
- package/src/local/runtime-activation.mjs +141 -0
- package/src/local/runtime-diagnostics.mjs +21 -0
- package/src/local/runtime-relay.mjs +9 -8
- package/src/local/runtime-reporting.mjs +8 -3
- package/src/local/runtime-tool-handlers.mjs +8 -8
- package/src/local/runtime.mjs +73 -39
- package/src/local/secure-file.mjs +5 -1
- package/src/local/security-audit-log.mjs +204 -0
- package/src/local/service-convergence.mjs +17 -1
- package/src/local/service-ownership.mjs +17 -0
- package/src/local/service-restart-handoff.mjs +50 -0
- package/src/local/service-restart-scheduler.mjs +49 -0
- package/src/local/service-status.mjs +47 -0
- package/src/local/service.mjs +142 -43
- package/src/local/state-inventory.mjs +21 -3
- package/src/local/state.mjs +155 -17
- package/src/local/stdio.mjs +5 -0
- package/src/local/tool-executor.mjs +39 -6
- package/src/local/tool-result-boundary.mjs +51 -0
- package/src/local/tools.mjs +1 -0
- package/src/local/trusted-executable.mjs +53 -0
- package/src/local/trusted-git-executable.mjs +34 -0
- package/src/local/trusted-github-cli.mjs +24 -0
- package/src/local/windows-service.mjs +20 -0
- package/src/local/worker-deployment.mjs +3 -4
- package/src/local/worker-secret-file.mjs +2 -2
- package/src/local/workspace-file-service.mjs +34 -31
- package/src/shared/admin-auth.d.mts +2 -1
- package/src/shared/admin-auth.mjs +3 -3
- package/src/shared/device-session-auth.d.mts +20 -0
- package/src/shared/device-session-auth.mjs +51 -0
- package/src/shared/server-metadata.json +1 -1
- package/src/shared/tool-catalog.json +2 -2
- package/src/worker/account-admin.ts +23 -22
- package/src/worker/authority.ts +9 -2
- package/src/worker/daemon-auth.ts +45 -67
- package/src/worker/daemon-sockets.ts +12 -2
- package/src/worker/device-session-verifier.ts +129 -0
- package/src/worker/dpop.ts +151 -0
- package/src/worker/http.ts +47 -16
- package/src/worker/index.ts +53 -16
- package/src/worker/nonce-store.ts +1 -5
- package/src/worker/oauth-client-admin.ts +45 -0
- package/src/worker/oauth-controller.ts +55 -6
- package/src/worker/oauth-refresh-families.ts +21 -7
- package/src/worker/oauth-state.ts +6 -0
- package/src/worker/oauth-tokens.ts +28 -8
- package/src/worker/websocket-protocol.ts +8 -2
package/docs/OPERATIONS.md
CHANGED
|
@@ -57,11 +57,13 @@ Machine Bridge supports concurrent calls: the Worker admits up to 32 pending dae
|
|
|
57
57
|
|
|
58
58
|
### Relay interruption messages
|
|
59
59
|
|
|
60
|
+
A reconnect warning is evidence of a transport outage, not proof that the daemon process exited. Compare daemon PID/process start, `connected_at`, `last_seen_at`, `runtime.relay.last_disconnected_at`, close category/code, and outage count. A system VPN/TUN may remain shown as connected while its internal route is unavailable; Machine Bridge reports that route only as `system-network-stack` with application-proxy scope. The reconnect schedule now tops out at fifteen seconds.
|
|
61
|
+
|
|
60
62
|
A brief relay interruption is retried automatically and is visible only with `--verbose`. Default logs do not print raw WebSocket values such as `code=1006` with an empty reason. If a transient outage persists for 10 seconds, the daemon emits a readable duration/cause/reconnect summary; later reminders use autonomous exponential backoff capped at 15 minutes, and recovery produces one readable summary. Each transport connection attempt also has a deadline, so a socket stuck in `CONNECTING` cannot freeze retries. Identity/version mismatch, authentication rejection, and unexpected protocol messages are not retried as ordinary network faults: the daemon emits an immediate actionable error and exits, requiring upgrade/redeployment or credential repair. Worker-side hello and end-to-end readiness timeouts remain retryable. Authentication is not reported as usable service readiness until a session-bound probe result returns.
|
|
61
63
|
|
|
62
64
|
Use `--verbose` only when close codes, close reasons, heartbeat timeouts, and retry delays are needed for diagnosis. A close code of 1006 means the transport ended without a normal close handshake; it does not by itself identify the cause.
|
|
63
65
|
|
|
64
|
-
The daemon honors `HTTPS_PROXY`/`HTTP_PROXY` and `NO_PROXY` through standard environment-proxy resolution for remote Worker health and relay traffic. `wss:` targets use HTTPS proxy selection and `ws:` targets use HTTP proxy selection. Only HTTP and HTTPS proxy URLs are accepted. Invalid URLs or unsupported protocols fail startup with corrective guidance instead of entering the reconnect loop. `server_info.runtime.relay.network_route` reports
|
|
66
|
+
The daemon honors `HTTPS_PROXY`/`HTTP_PROXY` and `NO_PROXY` through standard environment-proxy resolution for remote Worker health and relay traffic. `wss:` targets use HTTPS proxy selection and `ws:` targets use HTTP proxy selection. Only HTTP and HTTPS proxy URLs are accepted. Invalid URLs or unsupported protocols fail startup with corrective guidance instead of entering the reconnect loop. `server_info.runtime.relay.network_route` reports `system-network-stack`, `application-http-proxy`, or `invalid-application-proxy-configuration`. This field describes only Machine Bridge application-level proxy selection: an operating-system VPN/TUN may still intercept `system-network-stack` traffic. `network_route_scope`, outage timestamps/durations, close category/code, transport error class, and next retry timing make that distinction explicit; proxy endpoints and credentials are never returned or logged. The browser-broker CLI health probe is a separate loopback-only path: it accepts only canonical `127.0.0.1`, uses direct Node HTTP with no proxy agent, and does not depend on `NO_PROXY`.
|
|
65
67
|
|
|
66
68
|
## Browser extension setup and diagnosis
|
|
67
69
|
|
|
@@ -123,9 +125,15 @@ machine-mcp --verbose
|
|
|
123
125
|
|
|
124
126
|
After global installation, Windows users may open any `cmd.exe` window and run `machine-mcp`; they do not need to navigate to a project or package directory. On the first interactive start, the CLI asks for a workspace folder and displays `%USERPROFILE%\MachineBridge` as the default. Pressing Enter creates and remembers that folder. This avoids inheriting an arbitrary Command Prompt current directory such as `C:\Windows\System32`. Typing another folder in the prompt creates that folder when necessary. Explicit `--workspace PATH` remains a strict automation interface and requires an existing path.
|
|
125
127
|
|
|
126
|
-
|
|
128
|
+
### Start, restart, and cross-workspace ownership
|
|
129
|
+
|
|
130
|
+
`service start` is an idempotent ensure-running operation. It does not stop a verified already-running daemon, so calling it through that daemon cannot destroy the control connection. `service restart` is separate: macOS and systemd-user use a detached service-manager handoff so the command can return before the old daemon exits. Windows restart is fail closed from inside the running task because Task Scheduler `/End` may terminate the helper with the daemon; use an independent terminal stop/start sequence until a behaviorally verified Windows handoff exists.
|
|
131
|
+
|
|
132
|
+
A workspace/state selector does not grant authority over the machine-global service label. Stop, restart, foreground takeover, secret rotation, and uninstall require the exact live verified `service` daemon ownership record. Service status returns only provider, installed/loaded/active state, PID, bounded run count, and classified termination state; provider environment dumps are never returned.
|
|
133
|
+
|
|
134
|
+
## Current upgrade convergence
|
|
127
135
|
|
|
128
|
-
|
|
136
|
+
The current release advertises only MCP protocol `2025-11-25`. Upgrade the MCP client or host if it cannot negotiate that version; Machine Bridge does not retain an obsolete protocol dispatcher. Version 3 also requires matching Worker, daemon, CLI, and browser-extension components and may perform a two-phase device-root migration. Preserve the state root and follow [UPGRADING.md](UPGRADING.md); do not delete state to force apparent convergence.
|
|
129
137
|
|
|
130
138
|
Use this sequence:
|
|
131
139
|
|
|
@@ -154,7 +162,7 @@ Stable errors include `policy_denied`, `invalid_request`, `timeout`, `cancelled`
|
|
|
154
162
|
|
|
155
163
|
Windows Task Scheduler limits the `/TR` action text, so the platform adapter writes a short private `service-launcher.cmd` under the state root rather than embedding the full Node, package, workspace, state, and logging argv in the task action. The launcher uses CRT-compatible argument quoting, sends stdout/stderr to the normal service logs, exits on a successful daemon exit, and restarts a nonzero exit after five seconds. Task creation is accepted only after a separate state query observes the task. Start, stop, and removal likewise query the Task Scheduler state through fixed PowerShell object properties instead of parsing localized `schtasks` messages; an installed `Ready` task is not mislabeled as currently running.
|
|
156
164
|
|
|
157
|
-
The Windows trigger is current-user `ONLOGON` with `LIMITED` run level. After a reboot, signing in to that user is sufficient; no terminal command is required. Pre-login operation is intentionally not provided by the default design because it would require a different service-account/credential boundary. Remote autostart definitions prefer a stable PATH alias that resolves to the currently running Node executable and persist a sanitized absolute-only service `PATH` containing the Node/
|
|
165
|
+
The Windows trigger is current-user `ONLOGON` with `LIMITED` run level. After a reboot, signing in to that user is sufficient; no terminal command is required. Pre-login operation is intentionally not provided by the default design because it would require a different service-account/credential boundary. Remote autostart definitions prefer a stable PATH alias that resolves to the currently running Node executable and persist a sanitized absolute-only service `PATH` containing the current Node/package directories, the operator's inherited absolute PATH entries, and platform defaults. When installation runs through npm, all nested run-script prefixes through the final npm private `node-gyp-bin` marker are discarded; paths belonging to inactive candidate runtimes are also removed. This prevents prerelease activation from persisting source-repository shims or the prior runtime that activation subsequently prunes, while an ordinary user-supplied `node_modules/.bin` remains valid. A private allowlisted `service-environment.json` preserves `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`, matching lowercase forms, optional `ALL_PROXY`, Node proxy selection, and custom-CA path variables. Existing saved values survive an environment-free reinstall, while explicitly supplied values replace case-insensitive prior variants. Values may include proxy credentials, so the file stays in owner-only state and is never returned or logged; status exposes key names only. Re-run `machine-mcp service install` after changing Node installation families, PATH layout, proxy, or CA configuration. Custom Windows state paths used for autostart must also remain within the Task Scheduler path limit and must not contain a literal `%`.
|
|
158
166
|
|
|
159
167
|
A service-style `--daemon-only` start that finds the same workspace daemon already running is an idempotent no-op: it exits successfully without repeating warnings or readiness output; explicit policy/secret/change requests still report that changes were not applied. Autostart logs are stored under the state root in `logs/daemon.out.log` and `logs/daemon.err.log`. Installed services pass `--log-level warn --log-format json`, so each active line is a bounded JSON event suitable for ingestion. Files are owner-only where supported and tail-trimmed before daemon startup. If the log schema marker does not match the current format, the active files are cleared before startup and the current marker is written. Runtime code reads and maintains only the active filenames.
|
|
160
168
|
|
|
@@ -208,14 +216,13 @@ Inspect detached jobs even when the MCP host no longer permits execution tools:
|
|
|
208
216
|
```sh
|
|
209
217
|
machine-mcp job list
|
|
210
218
|
machine-mcp job inspect JOB_ID
|
|
211
|
-
machine-mcp job approve JOB_ID [--yes]
|
|
212
219
|
machine-mcp job cancel JOB_ID
|
|
213
220
|
machine-mcp job submit plan.json
|
|
214
221
|
```
|
|
215
222
|
|
|
216
223
|
Registry changes apply to newly submitted jobs without restarting the daemon. Active jobs use the resource snapshot accepted with their plan.
|
|
217
224
|
|
|
218
|
-
Policy changes affect new
|
|
225
|
+
Policy changes affect new submissions. Cancel accepted running jobs explicitly when revoking execution authority. A staged plan is a non-running draft and has no terminal promotion path. A trusted owner uses `start_job`; an explicit local operator may submit a reviewed JSON plan with `job submit`. A managed job transitions through `queued`, `running`, `cleaning`, and a terminal status such as `succeeded`, `failed`, or `cancelled`. Cleanup-specific terminal variants report a failed finally phase. If a runner PID dies, the next daemon/job-CLI start marks the job interrupted, removes stale private runtime copies, and runs the finally phase in recovery mode. Automatic recovery is capped at three attempts; persistent failure becomes `recovery_exhausted`.
|
|
219
226
|
|
|
220
227
|
Use job-scoped `temporary_files` for local helpers. For remote maintenance, prefer `ssh ... sh -s` with the remote script in step `stdin`; this avoids remote temporary scripts. Explicit remote cleanup belongs in idempotent `finally_steps`.
|
|
221
228
|
|
|
@@ -293,40 +300,44 @@ machine-mcp --workspace /path/to/project --profile agent
|
|
|
293
300
|
|
|
294
301
|
A remote policy change is saved locally, propagated in the daemon handshake, and loaded by autostart from owner-only state.
|
|
295
302
|
|
|
296
|
-
### Remote authority and
|
|
303
|
+
### Remote authority and client trust
|
|
297
304
|
|
|
298
|
-
The saved profile defines the capability ceiling.
|
|
305
|
+
The saved profile defines the daemon capability ceiling. Remote authority additionally requires the authenticated account role, trusted OAuth client binding, current account version and refresh family, and ownership of any long-lived object.
|
|
306
|
+
|
|
307
|
+
Inspect accounts and trusted clients with:
|
|
299
308
|
|
|
300
309
|
```sh
|
|
301
|
-
machine-mcp --workspace /path/to/project
|
|
310
|
+
machine-mcp --workspace /path/to/project account list
|
|
311
|
+
machine-mcp --workspace /path/to/project account clients
|
|
302
312
|
```
|
|
303
313
|
|
|
304
|
-
|
|
314
|
+
Revoke a compromised or stale client independently:
|
|
305
315
|
|
|
306
316
|
```sh
|
|
307
|
-
machine-mcp --workspace /path/to/project
|
|
308
|
-
machine-mcp --workspace /path/to/project approval approve APPROVAL_ID --full
|
|
317
|
+
machine-mcp --workspace /path/to/project account revoke-client CLIENT_ID --yes
|
|
309
318
|
```
|
|
310
319
|
|
|
311
|
-
|
|
320
|
+
Delegated roles cannot be elevated by an approval ID or lease. Legacy version 2 leases may be inspected or removed only for migration cleanup:
|
|
312
321
|
|
|
313
322
|
```sh
|
|
323
|
+
machine-mcp --workspace /path/to/project approval list
|
|
314
324
|
machine-mcp --workspace /path/to/project approval revoke LEASE_ID
|
|
315
|
-
machine-mcp --workspace /path/to/project approval clear
|
|
325
|
+
machine-mcp --workspace /path/to/project approval clear --yes
|
|
316
326
|
```
|
|
317
327
|
|
|
318
|
-
The
|
|
328
|
+
The current runtime never consumes legacy leases. Full details are in [LOCAL_AUTHORIZATION.md](LOCAL_AUTHORIZATION.md).
|
|
319
329
|
|
|
320
330
|
## Incident response
|
|
321
331
|
|
|
322
|
-
After suspected credential or
|
|
332
|
+
After suspected credential, client, or device compromise:
|
|
323
333
|
|
|
324
334
|
1. stop foreground and autostart daemons;
|
|
325
|
-
2.
|
|
326
|
-
3.
|
|
327
|
-
4.
|
|
328
|
-
5.
|
|
329
|
-
6.
|
|
330
|
-
7.
|
|
335
|
+
2. revoke the affected OAuth client, or disable/rotate the affected account;
|
|
336
|
+
3. clear any legacy version 2 leases as migration hygiene;
|
|
337
|
+
4. run `machine-mcp rotate-secrets` when device-root or deployment-wide token compromise is possible;
|
|
338
|
+
5. restart with the intended profile, deploy the matching Worker, and reconnect only trusted clients;
|
|
339
|
+
6. inspect Cloudflare access, Worker configuration, device-root provider, audit-chain health, local state/resource permissions, process-lock owners, managed-job results, and service logs;
|
|
340
|
+
7. cancel active managed jobs and remove compromised resource aliases;
|
|
341
|
+
8. remove the Worker and local state if continued remote access is unnecessary.
|
|
331
342
|
|
|
332
343
|
The detailed 0.12.0 audit record and residual operational limits are in [AUDIT.md](AUDIT.md).
|
package/docs/OVERVIEW.md
CHANGED
|
@@ -4,7 +4,7 @@ Machine Bridge is one local authority surface with two MCP transports. The archi
|
|
|
4
4
|
|
|
5
5
|
1. **Who may request an operation?** Remote OAuth account/client identity and role, or the local process identity that launched stdio.
|
|
6
6
|
2. **Which tools are exposed?** The shared tool catalog, policy profile, and account-role intersection.
|
|
7
|
-
3. **Is this remote effect
|
|
7
|
+
3. **Is this remote effect inside the current authority?** The daemon ceiling, account role, trusted client, account version, refresh family, operation invariants, and object owner must all agree.
|
|
8
8
|
4. **What can an authorized tool actually do?** The local runtime, workspace/path rules, operating-system user authority, and platform security controls.
|
|
9
9
|
|
|
10
10
|
Transport authentication does not create an operating-system sandbox. The local daemon executes with the authority of its OS user.
|
|
@@ -15,7 +15,7 @@ Transport authentication does not create an operating-system sandbox. The local
|
|
|
15
15
|
flowchart LR
|
|
16
16
|
HC[Hosted MCP client] -->|HTTPS + OAuth 2.1 / PKCE| W[Cloudflare Worker]
|
|
17
17
|
W --> DO[Durable Object room]
|
|
18
|
-
DO -->|P-256
|
|
18
|
+
DO -->|root-certified ephemeral P-256 session| R[LocalRuntime]
|
|
19
19
|
|
|
20
20
|
LC[Local MCP client] -->|stdio| S[stdio adapter]
|
|
21
21
|
S --> R
|
|
@@ -42,9 +42,9 @@ flowchart LR
|
|
|
42
42
|
|
|
43
43
|
1. The Worker validates OAuth client, token, account state, role, resource binding, and MCP session state.
|
|
44
44
|
2. The Worker filters advertised tools by account role and the daemon-reported capability ceiling.
|
|
45
|
-
3. The Durable Object relays a bounded tool envelope carrying account
|
|
45
|
+
3. The Durable Object relays a bounded tool envelope carrying account, account-version, OAuth-client, refresh-family, and role identity over the root-certified ephemeral daemon socket.
|
|
46
46
|
4. The local runtime revalidates account authorization, policy, call lifecycle, timeout, and cancellation.
|
|
47
|
-
5. The local
|
|
47
|
+
5. The local authority gate permits work only inside the immutable role ceiling. Consequential effects are classified for hard enforcement and audit; they never create a temporary elevation path.
|
|
48
48
|
6. The selected local service executes with the daemon OS user's authority.
|
|
49
49
|
|
|
50
50
|
The Worker never receives ambient filesystem or process authority. It receives only explicit request/result messages.
|
|
@@ -68,7 +68,7 @@ Local and Worker code consume these contracts. Generated references and drift te
|
|
|
68
68
|
`LocalRuntime` is an orchestrator, not a low-level implementation module. It composes:
|
|
69
69
|
|
|
70
70
|
- policy and account authorization;
|
|
71
|
-
-
|
|
71
|
+
- request-scoped effective authority, hard role ceilings, operation classification, and principal-bound object ownership;
|
|
72
72
|
- call registration, timeout, cancellation, and observability;
|
|
73
73
|
- workspace and path services;
|
|
74
74
|
- direct and shell process execution;
|
|
@@ -82,9 +82,9 @@ Low-level responsibilities remain in focused modules. Architecture tests enforce
|
|
|
82
82
|
|
|
83
83
|
## State and lifecycle
|
|
84
84
|
|
|
85
|
-
Each canonical workspace has independent profile state, Worker identity,
|
|
85
|
+
Each canonical workspace has independent profile state, Worker identity, trusted clients, account/token state, legacy-lease cleanup state, audit-chain state, locks, service metadata, and managed jobs. State mutations use owner-only files where supported, bounded reads, atomic replacement, and process-identity-aware locks.
|
|
86
86
|
|
|
87
|
-
The relay distinguishes signed preflight, challenge authentication, readiness probing, and active service. A candidate daemon must prove possession of the
|
|
87
|
+
The relay distinguishes a root-certified ephemeral session, signed preflight, challenge authentication, readiness probing, and active service. A candidate daemon must prove possession of the certified session key and complete an end-to-end probe before replacing an incumbent. Disconnect cancels relay-owned calls and terminates associated local processes.
|
|
88
88
|
|
|
89
89
|
Managed jobs use a separate durable lifecycle. Their plans are integrity-bound, runners are process-identity checked, transitions are lock-protected, terminal plans are scrubbed, and recovery is bounded.
|
|
90
90
|
|
|
@@ -18,15 +18,19 @@ Branch names use a short category and purpose, for example `feat/browser-downloa
|
|
|
18
18
|
|
|
19
19
|
Direct pushes to `main`, force pushes, and branch deletion are blocked by repository protection. An exception requires an incident record and an explicit owner decision.
|
|
20
20
|
|
|
21
|
-
### Completion ownership and
|
|
21
|
+
### Completion ownership, prerelease activation, and soak
|
|
22
22
|
|
|
23
|
-
Repository automation owns implementation, local validation, observed
|
|
23
|
+
Repository automation owns implementation, local validation, candidate preparation, observed verification, acceptance recording, and pull-request completion. Package work for version 3 or later must use a `dev`, `beta`, or `rc` version before stable promotion. Direct implementation-to-stable release is prohibited.
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
`npm run release:candidate` creates the exact tarball. The repository owner executes `npm run release:candidate:activate -- --allow-worker-deploy`; the command installs that tarball under the private state root, updates the same-name Worker, verifies candidate relay readiness, replaces the login daemon, verifies the background handoff, and exits. The coding agent then performs observed live verification through Machine Bridge and records acceptance only after that observed success. No per-operation terminal approval is involved.
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
The tracked `release-acceptance/v<version>.json` binds npm hashes, a portable package digest, and a version-normalized promotion digest. Any packaged change invalidates acceptance. `npm run github:push`, CI, and source-release commands verify the record. Raw pushes of package branches are prohibited.
|
|
28
28
|
|
|
29
|
-
The
|
|
29
|
+
The accepted prerelease is released with `npm run prerelease:release`; npm publication remains an explicit owner operation through `npm run prerelease:publish`. The owner installs the exact registry version with `npm run prerelease:install -- --allow-worker-deploy`. Formal soak begins only from this registry-verified activation. Minimum soak is seven days for major, three days for minor, and one day for patch releases. A blocking defect increments the prerelease number and restarts the soak interval.
|
|
30
|
+
|
|
31
|
+
Stable promotion requires a tracked `release-soak/v<stable>.json` and identical promotion-content digest. Only normalized release metadata may differ from the soaked prerelease. The stable candidate is activated and observed again before `npm run release`; npm stable publication remains an explicit owner operation through `npm run stable:publish`.
|
|
32
|
+
|
|
33
|
+
GitHub-only repository infrastructure changes that do not alter npm package contents do not require a synthetic version, candidate activation, or soak. They still require review and applicable checks.
|
|
30
34
|
|
|
31
35
|
### Local GitHub control plane
|
|
32
36
|
|
package/docs/RELEASING.md
CHANGED
|
@@ -1,124 +1,231 @@
|
|
|
1
1
|
# Release process
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Machine Bridge uses a mandatory prerelease-and-soak process. A release candidate is not a stable release, and a green automated suite is not evidence that a real Worker, daemon, browser extension, service manager, and ordinary client remain healthy over time.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- the current package produces the same SHA-1 and SHA-512 integrity values as that accepted tarball;
|
|
7
|
-
- `main` points to the release commit, and that exact commit has completed successful push-triggered CI, CodeQL, Governance, and OpenSSF Scorecard runs;
|
|
8
|
-
- `v<package version>` points to that same commit locally and on GitHub;
|
|
9
|
-
- a final GitHub Release exists for the tag and contains the accepted npm tarball;
|
|
10
|
-
- `package.json`, `package-lock.json`, the Worker-reported version, and `browser-extension/manifest.json` (`version`/`version_name`) agree;
|
|
11
|
-
- every npm-package change since the prior version tag has a higher package version and matching CHANGELOG section;
|
|
12
|
-
- the same accepted package content is present on GitHub and in a new npm version.
|
|
5
|
+
The invariant for version 3 and later is:
|
|
13
6
|
|
|
14
|
-
|
|
7
|
+
1. every package change is first assigned a `dev`, `beta`, or `rc` semantic version;
|
|
8
|
+
2. the exact npm tarball is activated on the owner machine with one command that updates the same-name Worker and persistently replaces the login daemon;
|
|
9
|
+
3. the coding agent verifies the connected candidate through Machine Bridge before recording package acceptance;
|
|
10
|
+
4. the accepted prerelease is published under a non-`latest` npm dist-tag and as a GitHub Prerelease;
|
|
11
|
+
5. the owner installs that exact published prerelease and uses it for the required soak period;
|
|
12
|
+
6. every blocking defect produces a new prerelease version and restarts the soak clock;
|
|
13
|
+
7. stable promotion is allowed only when the packaged functional content matches the soaked prerelease; only synchronized version metadata may differ;
|
|
14
|
+
8. the exact stable commit must pass cross-platform CI, CodeQL, Governance, and OpenSSF Scorecard before the stable tag and final GitHub Release are created.
|
|
15
15
|
|
|
16
|
-
##
|
|
16
|
+
## Release channels
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Supported versions and registry channels are:
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
| Version form | npm dist-tag | GitHub release type | Purpose |
|
|
21
|
+
|---|---|---|---|
|
|
22
|
+
| `x.y.z-dev.n` | `dev` | Prerelease | short-lived development integration |
|
|
23
|
+
| `x.y.z-beta.n` | `beta` | Prerelease | normal real-world testing channel |
|
|
24
|
+
| `x.y.z-rc.n` | `next` | Prerelease | optional final candidate after beta |
|
|
25
|
+
| `x.y.z` | `latest` | final release | stable users only |
|
|
21
26
|
|
|
22
|
-
|
|
27
|
+
Do not assign the final `x.y.z` version while implementation is still under candidate testing. A major or behaviorally risky change normally starts at `beta.1`. A release candidate may use `rc.n` after beta when a final freeze checkpoint is useful.
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
Minimum published-prerelease soak periods are:
|
|
25
30
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
- major release: seven days;
|
|
32
|
+
- minor release: three days;
|
|
33
|
+
- patch release: one day.
|
|
29
34
|
|
|
30
|
-
|
|
31
|
-
3. Run the required dependency, privacy, Worker, and package checks while iterating.
|
|
32
|
-
4. Inspect the complete diff.
|
|
33
|
-
5. Generate the final candidate:
|
|
35
|
+
These are lower bounds, not automatic approval. Continue the soak when use has been too light to exercise the changed behavior.
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
npm run release:candidate
|
|
37
|
-
```
|
|
37
|
+
## 1. Prepare an exact prerelease candidate
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
Complete implementation, tests, documentation, audit notes, and changelog. Set the prerelease version without creating a Git tag:
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
```sh
|
|
42
|
+
npm version 3.0.0-beta.1 --no-git-tag-version
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The version hook synchronizes package metadata, Worker version, and browser-extension metadata.
|
|
46
|
+
|
|
47
|
+
Run the complete local gate and inspect the diff:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
npm run check
|
|
51
|
+
npm audit --audit-level=high
|
|
52
|
+
npm audit --omit=dev --audit-level=high
|
|
53
|
+
npm run worker:dry-run
|
|
54
|
+
npm pack --dry-run
|
|
55
|
+
```
|
|
42
56
|
|
|
43
|
-
|
|
57
|
+
Generate the exact tarball:
|
|
44
58
|
|
|
45
59
|
```sh
|
|
46
|
-
npm run release:candidate
|
|
60
|
+
npm run release:candidate
|
|
47
61
|
```
|
|
48
62
|
|
|
49
|
-
The
|
|
63
|
+
The candidate manifest records npm SHA-1/SHA-512 values and a promotion-content digest. Any packaged-file change invalidates the candidate.
|
|
50
64
|
|
|
51
|
-
|
|
52
|
-
- the remote health route succeeds without redirect;
|
|
53
|
-
- the connected runtime reports the candidate package version;
|
|
54
|
-
- relay readiness is healthy through the deployed Worker for the intended transport;
|
|
55
|
-
- one representative read-only operation succeeds;
|
|
56
|
-
- representative changed functionality succeeds, including browser, application, service, proxy, credential, or platform-specific behavior when relevant.
|
|
65
|
+
## 2. Owner activates the exact candidate
|
|
57
66
|
|
|
58
|
-
The
|
|
67
|
+
The coding agent must stop and present this command. The repository owner executes it:
|
|
59
68
|
|
|
60
69
|
```sh
|
|
61
|
-
npm run release:
|
|
70
|
+
npm run release:candidate:activate -- --allow-worker-deploy
|
|
62
71
|
```
|
|
63
72
|
|
|
64
|
-
|
|
73
|
+
The command:
|
|
74
|
+
|
|
75
|
+
- verifies the exact pending tarball;
|
|
76
|
+
- installs it under the owner-only Machine Bridge state root, separate from the normal global installation;
|
|
77
|
+
- stops only a verified existing service daemon;
|
|
78
|
+
- updates the configured same-name Worker;
|
|
79
|
+
- starts the candidate in-process and verifies device authentication plus relay readiness;
|
|
80
|
+
- installs the candidate as the login service runtime;
|
|
81
|
+
- performs a controlled foreground-to-service handoff;
|
|
82
|
+
- verifies that both the Worker and verified background daemon report the candidate version;
|
|
83
|
+
- exits while the background daemon continues running.
|
|
84
|
+
|
|
85
|
+
It may request one macOS user-presence or Touch ID operation to certify the daemon session key. It does not ask for per-tool approval.
|
|
86
|
+
|
|
87
|
+
The private candidate runtime is not stored under the Git checkout, so cleaning `.release-candidate/`, switching branches, or regenerating a candidate cannot delete the daemon currently under test. The previous global installation remains available as recovery information.
|
|
88
|
+
|
|
89
|
+
## 3. Coding agent verifies the live candidate
|
|
90
|
+
|
|
91
|
+
After the owner command completes, the coding agent verifies through Machine Bridge:
|
|
65
92
|
|
|
66
|
-
|
|
93
|
+
- `server_info` reports the exact candidate version;
|
|
94
|
+
- Worker health reports the same version and deployment identity;
|
|
95
|
+
- the connected daemon is the verified login-service process;
|
|
96
|
+
- relay readiness succeeds through the deployed Worker;
|
|
97
|
+
- a representative read succeeds;
|
|
98
|
+
- changed functionality and relevant failure paths succeed;
|
|
99
|
+
- browser, application, proxy, credential, service, and platform-specific behavior are tested when affected;
|
|
100
|
+
- logs contain no sensitive arguments, output, tokens, or raw user paths.
|
|
67
101
|
|
|
68
|
-
|
|
102
|
+
Only observed live evidence counts. A green unit suite, prepared tarball, unobserved process, or ambiguous response does not count.
|
|
69
103
|
|
|
70
|
-
|
|
104
|
+
After successful verification, the coding agent records acceptance using the exact phrase emitted by `release:candidate`:
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
npm run release:accept -- --confirm "I VERIFIED machine-bridge-mcp <version> CANDIDATE ON THE OWNER MACHINE AND IT WORKS"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The resulting `release-acceptance/v<version>.json` binds the exact tarball hashes, portable Git package digest, promotion-content digest, timestamp, and fixed verification marker. It contains no personal machine path, command output, account credential, or user content.
|
|
111
|
+
|
|
112
|
+
## 4. Review and publish the prerelease
|
|
113
|
+
|
|
114
|
+
Commit the prerelease changes and acceptance record. Push only through:
|
|
71
115
|
|
|
72
116
|
```sh
|
|
73
117
|
npm run github:push
|
|
74
118
|
```
|
|
75
119
|
|
|
76
|
-
|
|
120
|
+
Create/update the pull request, satisfy required checks, squash-merge, fetch, and fast-forward local `main`.
|
|
77
121
|
|
|
78
|
-
|
|
122
|
+
Create the annotated prerelease tag, GitHub Prerelease, and exact tarball asset:
|
|
79
123
|
|
|
80
|
-
|
|
124
|
+
```sh
|
|
125
|
+
npm run prerelease:release
|
|
126
|
+
```
|
|
81
127
|
|
|
82
|
-
|
|
128
|
+
Publish npm through the repository-controlled channel command:
|
|
83
129
|
|
|
84
130
|
```sh
|
|
85
|
-
npm run
|
|
131
|
+
npm run prerelease:publish
|
|
86
132
|
```
|
|
87
133
|
|
|
88
|
-
|
|
134
|
+
The command derives `dev`, `beta`, or `next` from the package version. `prepublishOnly` rejects an incorrect or implicit `latest` tag and rechecks the package, GitHub prerelease, exact commit, and candidate acceptance.
|
|
89
135
|
|
|
90
|
-
|
|
136
|
+
## 5. Activate the published prerelease and begin soak
|
|
137
|
+
|
|
138
|
+
From the exact accepted source checkout, the owner runs:
|
|
91
139
|
|
|
92
140
|
```sh
|
|
93
|
-
npm run
|
|
141
|
+
npm run prerelease:install -- --allow-worker-deploy
|
|
94
142
|
```
|
|
95
143
|
|
|
96
|
-
|
|
144
|
+
This command verifies that the npm registry tarball SHA-1/SHA-512 and dist-tag match the locally accepted candidate, installs that exact published version globally, updates the Worker and login daemon, verifies both versions, and writes an owner-only `npm-prerelease` activation record. The formal soak clock starts from this activation record, not from a local unpublished candidate.
|
|
145
|
+
|
|
146
|
+
Use the prerelease normally. Exercise the changed areas under real workloads. A crash, authorization anomaly, data-loss risk, repeated relay failure, incorrect service lifecycle, significant compatibility regression, or security/privacy defect is blocking.
|
|
147
|
+
|
|
148
|
+
When a blocking problem is found:
|
|
149
|
+
|
|
150
|
+
1. fix it on a new branch;
|
|
151
|
+
2. increment `beta.n` or `rc.n`;
|
|
152
|
+
3. regenerate and reactivate the exact candidate;
|
|
153
|
+
4. repeat live verification and prerelease publication;
|
|
154
|
+
5. install the new published prerelease;
|
|
155
|
+
6. restart the full minimum soak interval.
|
|
156
|
+
|
|
157
|
+
Never edit or replace an already published prerelease version.
|
|
158
|
+
|
|
159
|
+
## 6. Record successful soak
|
|
160
|
+
|
|
161
|
+
After the minimum interval and adequate real use, the owner reports that no blocking issue remains. The coding agent records that explicit result with the exact phrase printed by the command, for example:
|
|
162
|
+
|
|
163
|
+
```sh
|
|
164
|
+
npm run prerelease:soak:accept -- --confirm "I SOAK-TESTED machine-bridge-mcp 3.0.0-beta.1 FOR AT LEAST 7d WITH NO BLOCKING ISSUES"
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
The command verifies:
|
|
168
|
+
|
|
169
|
+
- the installed activation came from the published npm prerelease, not a local candidate;
|
|
170
|
+
- the published npm hashes and dist-tag match the accepted tarball;
|
|
171
|
+
- the GitHub release is marked prerelease;
|
|
172
|
+
- the required elapsed time has passed;
|
|
173
|
+
- the promotion-content digest still matches;
|
|
174
|
+
- no blocking issue is recorded.
|
|
175
|
+
|
|
176
|
+
It writes `release-soak/v<stable-version>.json`. This record is reviewable, contains no private machine path, and is excluded from the npm package.
|
|
177
|
+
|
|
178
|
+
## 7. Promote to stable
|
|
179
|
+
|
|
180
|
+
Create a stable-promotion branch. Change only synchronized release metadata from `x.y.z-beta.n` or `x.y.z-rc.n` to `x.y.z`, retain the same functional package content, add the tracked soak record, and update release wording only where it is normalized by the promotion digest.
|
|
181
|
+
|
|
182
|
+
Any source, runtime, dependency, packaged documentation, script, policy, browser-extension behavior, or Worker behavior change causes `release:soak:verify` to fail. Such a change requires a new prerelease and a new soak period.
|
|
183
|
+
|
|
184
|
+
Verify the promotion:
|
|
97
185
|
|
|
98
186
|
```sh
|
|
99
|
-
npm run release:
|
|
187
|
+
npm run release:soak:verify
|
|
188
|
+
npm run check
|
|
189
|
+
npm run release:candidate
|
|
100
190
|
```
|
|
101
191
|
|
|
102
|
-
|
|
192
|
+
The owner activates the exact stable candidate with the same persistent command:
|
|
103
193
|
|
|
104
|
-
|
|
194
|
+
```sh
|
|
195
|
+
npm run release:candidate:activate -- --allow-worker-deploy
|
|
196
|
+
```
|
|
105
197
|
|
|
106
|
-
|
|
198
|
+
The coding agent verifies the live stable candidate and records its exact acceptance. Then commit, push with `npm run github:push`, merge, and run:
|
|
107
199
|
|
|
108
200
|
```sh
|
|
109
|
-
npm
|
|
201
|
+
npm run release
|
|
202
|
+
npm run stable:publish
|
|
110
203
|
```
|
|
111
204
|
|
|
112
|
-
`
|
|
205
|
+
`npm run release` creates the final annotated tag and GitHub Release only after the soak record, promotion digest, exact candidate acceptance, exact `origin/main`, and all required push-triggered checks pass. `stable:publish` always uses `latest` and repeats the same gates.
|
|
206
|
+
|
|
207
|
+
## Rollback and recovery
|
|
208
|
+
|
|
209
|
+
Candidate and prerelease activation retain the previous global installation metadata, but rollback across a state or protocol migration is not assumed safe. If activation fails:
|
|
210
|
+
|
|
211
|
+
- preserve the state root and service logs;
|
|
212
|
+
- do not delete locks or edit versions by hand;
|
|
213
|
+
- inspect `machine-mcp service status`, `machine-mcp status`, and `machine-mcp doctor` using the intended runtime;
|
|
214
|
+
- fix forward when Worker/state protocol has changed;
|
|
215
|
+
- restore a complete pre-upgrade backup only when package, Worker, browser extension, service definition, and local state can be restored as one unit.
|
|
216
|
+
|
|
217
|
+
The activation state machine verifies candidate relay readiness before service handoff and cleans up its temporary runtime and locks on installation failure. A failure after the Worker has changed is reported explicitly rather than hidden by an unsafe automatic downgrade.
|
|
113
218
|
|
|
114
|
-
##
|
|
219
|
+
## External credentials and controls
|
|
115
220
|
|
|
116
|
-
|
|
221
|
+
Live npm publication, global installation, and Worker/service replacement require explicit owner authorization. Repository automation does not infer that authorization from a version change.
|
|
117
222
|
|
|
118
|
-
|
|
119
|
-
- an authenticated GitHub CLI session with pull-request and release permission;
|
|
120
|
-
- an npm account that owns the package or has maintainer permission for the separate registry publication step.
|
|
223
|
+
Required external controls remain:
|
|
121
224
|
|
|
122
|
-
|
|
225
|
+
- authenticated local `git`/`gh` access;
|
|
226
|
+
- npm package-owner or maintainer access;
|
|
227
|
+
- Cloudflare account protection;
|
|
228
|
+
- successful exact-commit CI, CodeQL, Governance, and Scorecard;
|
|
229
|
+
- protected npm publication credentials or trusted publishing when configured.
|
|
123
230
|
|
|
124
|
-
|
|
231
|
+
Never place npm, GitHub, Cloudflare, OAuth, account, or device credentials in source files, workflow YAML, acceptance/soak records, logs, screenshots, or project notes.
|