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/TESTING.md
CHANGED
|
@@ -23,6 +23,10 @@ The suite includes:
|
|
|
23
23
|
- one-shot process output preview/continuation, completed-session paging, bounded nonzero-exit details, UTF-8-safe head/tail diagnostics, compact local/Worker MCP text mirrors, and quiet-success/bounded-failure verification-runner behavior;
|
|
24
24
|
- GitHub backlog enforcement that paginates all open issues and pull requests, permits only the current branch PR, and requires standard closing keywords for every open issue before a guarded push;
|
|
25
25
|
- release-impact enforcement requiring a new package version and CHANGELOG section for release-relevant changes;
|
|
26
|
+
- strict dev/beta/rc/stable channel parsing and npm dist-tag enforcement;
|
|
27
|
+
- persistent candidate relay/service handoff ordering and fault cleanup;
|
|
28
|
+
- owner-only local and registry prerelease activation records;
|
|
29
|
+
- npm/GitHub prerelease metadata validation, minimum soak timing, blocking-issue rejection, and stable-promotion content/file-mode identity;
|
|
26
30
|
- release-state diagnostics distinguishing missing local/remote version tags from tags that point to the wrong commit, plus a release-CI gate that rejects missing, pending, failed, pull-request-only, stale, or wrong-commit runs;
|
|
27
31
|
- generated Cloudflare Worker types under ignored `.wrangler/` state and strict TypeScript checking, including unused-local and unused-parameter rejection; packaging rejects generated declarations;
|
|
28
32
|
- Conventional Commit title validation, shared Markdown escaping regression coverage, and generated MCP tool-reference drift detection;
|
|
@@ -32,7 +36,7 @@ The suite includes:
|
|
|
32
36
|
- default working-agreement injection without user files, bounded automatic project metadata, script-body non-disclosure, user-global opt-out, repository opt-out rejection, global `model_instructions_file` injection in stdio/remote initialization, hierarchical precedence, `.agents/skills` and `.codex/skills` compatibility discovery, live project/skill rescanning and fingerprints, automatic task ranking/loading with English inflection normalization, bounded Chinese/English intent aliases, capability-name weighting, and selected-skill instruction loading; automatic `package.*` commands with English/Chinese workflow-intent matching and Windows command-shim execution, explicit command override/removal, direct argv handling, timeout ceilings, runtime-keyed routing-telemetry privacy, and execution-profile denial;
|
|
33
37
|
- concurrent complete-before-visible lock claims, atomic replacement under active readers, malformed-lock grace, snapshot/token-safe reclamation, absolute-age expiry, PID-reuse detection, bounded startup-lock waiting, and wall-clock rollback injection proving duration deadlines remain monotonic;
|
|
34
38
|
- foreground takeover of active and orphaned background daemons with current service-lock metadata, foreground-process protection, bounded final lock-handoff retry, actual-PID exit waiting, POSIX non-escalating timeout behavior, Windows verified-daemon stop semantics, daemon lock mode/version/process-start metadata, launchd service-target semantics, and silent idempotent duplicate service starts; daemon fixture subprocesses intentionally do not inherit V8 coverage because their purpose is ownership timing rather than code measurement;
|
|
35
|
-
- fail-closed service lifecycle ordering for provider-stop, all-workspace daemon-stop, and definition removal, including platform/daemon/removal failure injection and normalized macOS/systemd/Windows results; Windows coverage reproduces an inline `/TR` command above 262 characters, proves the short launcher action remains bounded, verifies least-privilege logon registration, restart/log routing, language-independent `Ready`/`Running` observation, and state-observed stop/removal despite localized nonzero command output;
|
|
39
|
+
- fail-closed service lifecycle ordering for provider-stop, all-workspace daemon-stop, and definition removal, including platform/daemon/removal failure injection and normalized macOS/systemd/Windows results; service-PATH coverage reproduces two nested npm run-script prefixes plus a stale prior candidate runtime and proves the current Node/runtime and inherited user tools remain while npm-private and inactive-runtime entries are removed; Windows coverage reproduces an inline `/TR` command above 262 characters, proves the short launcher action remains bounded, verifies least-privilege logon registration, restart/log routing, language-independent `Ready`/`Running` observation, and state-observed stop/removal despite localized nonzero command output;
|
|
36
40
|
- private service-environment capture/load coverage for exact allowlisting, value bounds and control-character rejection, non-proxy secret exclusion, runtime-value precedence, Windows case-insensitive replacement, explicit empty-value clearing, and preservation across a later environment-free startup;
|
|
37
41
|
- machine-level browser-broker ownership/client proxying, authenticated extension origin/subprotocol, non-cacheable local pairing, pairing-token non-disclosure, resource-backed upload routing, broker result redaction, pre-registered runtime-handshake listeners, bounded socket/HTTP waits, direct loopback health despite hostile environment-proxy settings, stop-during-start generation invalidation, frozen-wall-clock browser deadline coverage, installed-application discovery caching, and name-based task matching;
|
|
38
42
|
- Worker health direct/proxy routing through a real local HTTP CONNECT proxy, `NO_PROXY` bypass, exact `workers.dev` origin/name validation, redirect rejection, body/deadline bounds, error classification, bounded propagation retry, and invalid proxy fail-fast behavior without endpoint or credential disclosure;
|
|
@@ -45,6 +49,8 @@ The suite includes:
|
|
|
45
49
|
- UTF-8 and binary handling;
|
|
46
50
|
- image content formatting;
|
|
47
51
|
- nested Git repository detection and helper suppression;
|
|
52
|
+
- explicit effective-policy versus daemon-ceiling fields in local/remote `project_overview`, reviewer/editor Git metadata through the fixed internal command boundary, and compatibility fallback for older daemon snapshots;
|
|
53
|
+
- fixed internal command execution with validated argv, no shell, isolated HOME/temp/cache, bounded output/deadlines, and ordinary cancellation/process tracking while arbitrary delegated process tools remain sandbox-gated;
|
|
48
54
|
- author-email privacy in `git_log`;
|
|
49
55
|
- isolated command HOME/temp/cache behavior;
|
|
50
56
|
- one-shot timeout, descendant process-group/tree termination including descendants that ignore graceful shutdown after the direct child has already exited, cancellation, and process-session interaction;
|
|
@@ -54,11 +60,11 @@ The suite includes:
|
|
|
54
60
|
- real-machine canonical-full sandbox acceptance for outside-workspace I/O, direct/shell execution, full environment inheritance, SSH prerequisites, temporary authorized-key writing, and detached cleanup without external state changes;
|
|
55
61
|
- deterministic injected atomic-replace failures, sustained transient Windows sharing contention beyond the old retry budget, bounded exponential delay selection, and repeated Windows full-sandbox runs;
|
|
56
62
|
- canonical named-profile repair and full-only tool exposure parity between local and Worker policy filters;
|
|
57
|
-
- managed-job staging
|
|
63
|
+
- managed-job non-executing staging, rejection of the removed terminal promotion path, cancel-before-start, trusted direct start, detachment, job-scoped temporary files, resource hash verification/redaction, discard capture, finally execution, descendant-tree escalation, token/snapshot-safe transition locks, runner process identity, spawn-without-PID rejection, asynchronous runner-error observability, plan scrubbing, PID-reuse-safe dead-runner recovery, and rejection of numeric-only runner records;
|
|
58
64
|
- daemon/startup locking, successfully-read corrupt-JSON recovery, and explicit propagation/preservation of oversized, symbolic-link, permission, and I/O failures;
|
|
59
65
|
- guarded state-root removal, unsafe state-root/workspace overlap rejection before creation, all-profile lock/daemon scanning, strict current-schema validation, corrupt-JSON isolation, and policy-origin persistence;
|
|
60
66
|
- no filename-based sensitive-file denial under unrestricted policy;
|
|
61
|
-
- log redaction, control-character handling, message/field bounds, suppression of both successful and failed per-tool events outside debug, service warning-level configuration, current-schema reset, and bounded tail trimming;
|
|
67
|
+
- log redaction, control-character handling, message/field bounds, suppression of both successful and failed per-tool events outside debug, service warning-level configuration, JSON-mode parity across event and direct logger methods with timestamp/stream/redaction assertions, current-schema reset, and bounded tail trimming;
|
|
62
68
|
- deterministic relay connection lifecycle coverage for transport construction/error/deadline, pre-handshake `welcome` validation, separate `hello_ack` authentication and `ready_ack` end-to-end readiness, session-bound probe return, pre-ready tool rejection, premature-ready rejection, identity/version mismatch, retryable Worker hello/readiness errors, fatal protocol errors, autonomous outage-reminder backoff, handshake/readiness/heartbeat timeout, brief-outage suppression, sustained-outage escalation, recovery summaries, and supersession;
|
|
63
69
|
- shared no-follow bounded-file reads for normal files, over-limit data, directories, and symbolic links;
|
|
64
70
|
- owner-only directory enforcement rejecting final symlinks, failing closed on POSIX chmod errors, verifying `0700`, and retaining Windows portability; Worker temporary-secret lifecycle coverage for process-start-bound names, valid stale-owner reclamation, ambiguous-owner retention, `0600` mode, deletion failures, and simultaneous deployment/cleanup failures;
|
|
@@ -69,11 +75,12 @@ The suite includes:
|
|
|
69
75
|
- byte-exact UTF-8 DOM-source truncation across emoji and Chinese partial-code-point boundaries, including equality between the reported byte count and the encoded returned source;
|
|
70
76
|
- independently injected service CLI status/install/start/stop/uninstall/remove paths, including provider failure, no selected workspace, no deployed Worker, aliases, and default output/exit adapters;
|
|
71
77
|
- CLI parsing, policy profiles, and client configuration boundaries;
|
|
78
|
+
- installed-package zero-argument startup with an isolated HOME/state/workspace and a service-manager trap, proving the smoke test reaches the controlled Wrangler boundary without querying, stopping, or replacing the operator's machine-global launchd/systemd/Scheduled Task service;
|
|
72
79
|
- live stdio MCP initialization with session instructions, capability resolution, discovery, calls, rich content, sessions, cancellation, managed-job acceptance, and a detached job/finally phase that survives stdio shutdown;
|
|
73
|
-
- P-256
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
- live local Worker OAuth registration, the unauthenticated `resource_metadata` challenge, protected-resource and authorization-server discovery, Streamable transport metadata, consent, URL-constructed `303` callbacks including the ChatGPT and hosted Claude redirect URIs with encoded state, PKCE, `offline_access`, form-encoded authorization-code and refresh-token exchanges, fifteen-minute access tokens, refresh-family idle/absolute limits, bounded consumed-token/revoked-family replay state, record-level schema validation, access/refresh rotation, stale refresh replay rejection with whole-family access/refresh revocation, account-version refresh revocation, authorization-code replay rejection, pending-registration throttling that excludes already authorized DCR clients, exact built-in ChatGPT/Grok browser origins, additive custom origins, unrelated-origin preflight rejection, no CORS response sharing for unrelated or opaque origins, opaque-origin authorization-form routing, exact per-request redirect-origin CSP with narrowly scoped Microsoft regional-consent and final Copilot Studio handoff exceptions, accessible credential-error rendering, protocol negotiation, HMAC-bound MCP session issuance, two-session same-id concurrency, sessionless same-id independence, session-scoped cancellation isolation, same-session duplicate rejection, daemon-backed session bootstrap, dynamic tool advertisement, rich content, candidate/probing/ready transitions, invalid readiness-result rejection, incumbent preservation until verified handover, daemon replacement, cancellation, malformed daemon JSON/non-object rejection, duplicate hello rejection, and unknown-message closure. The metadata/refresh contract is the path used by Claude DCR and Copilot Studio Dynamic discovery. The same integration runs an `editor` account against a canonical `full` daemon and proves that `server_info` and remote `project_overview` report effective `edit` authority while retaining the full daemon ceiling only in explicitly scoped fields.
|
|
80
|
+
- P-256 root generation, root-certified ephemeral session issuance, macOS trust-broker build/signature checks, signed WebSocket preflight, one-time transactional nonce consumption, challenge transcript binding, wrong-root/session/tamper/expiry/replay rejection, and prevention of unauthenticated candidate churn;
|
|
81
|
+
- request-scoped effective authority and catalog-wide risk review; non-escalatable reviewer/editor/operator ceilings; authenticated-owner direct execution; control-plane root denial; external and sensitive path composition; persistence-target rejection; symbolic-link ancestor and patch-move canonicalization; owner-only browser/application/data-export and persistent-plan effects; account/client/refresh-family ownership of processes, output sessions, and jobs; delegated sandbox fail-closed behavior; legacy-lease non-consumption; and malformed-record rejection;
|
|
82
|
+
- root-certified ephemeral P-256 account-administration requests with origin/method/path/body/key/time/nonce binding, transactional one-time nonce consumption, removal of the long-lived administration secret, certificate/signature/body tamper rejection, nonce replay rejection, and malformed nonce-state fail-closed behavior;
|
|
83
|
+
- live local Worker OAuth registration, the unauthenticated `resource_metadata` challenge, protected-resource and authorization-server discovery, Streamable transport metadata, consent, URL-constructed `303` callbacks including the ChatGPT and hosted Claude redirect URIs with encoded state, PKCE, `offline_access`, form-encoded authorization-code and refresh-token exchanges, fifteen-minute access tokens, trusted single-account client binding, optional DPoP proof and token-family binding, unsupported critical-header rejection, proof-verification non-consumption, post-authorization replay consumption, invalid-grant cache-exhaustion resistance, independent client revocation, refresh-family idle/absolute limits, bounded consumed-token/revoked-family replay state, record-level schema validation, access/refresh rotation, stale refresh replay rejection with whole-family access/refresh revocation, account-version refresh revocation, authorization-code replay rejection, pending-registration throttling that excludes already authorized DCR clients, exact built-in ChatGPT/Grok browser origins, additive custom origins, unrelated-origin preflight rejection, no CORS response sharing for unrelated or opaque origins, opaque-origin authorization-form routing, exact per-request redirect-origin CSP with narrowly scoped Microsoft regional-consent and final Copilot Studio handoff exceptions, accessible credential-error rendering, protocol negotiation, HMAC-bound MCP session issuance, two-session same-id concurrency, sessionless same-id independence, session-scoped cancellation isolation, same-session duplicate rejection, daemon-backed session bootstrap, dynamic tool advertisement, rich content, candidate/probing/ready transitions, invalid readiness-result rejection, incumbent preservation until verified handover, daemon replacement, cancellation, malformed daemon JSON/non-object rejection, duplicate hello rejection, and unknown-message closure. The metadata/refresh contract is the path used by Claude DCR and Copilot Studio Dynamic discovery. The same integration runs an `editor` account against a canonical `full` daemon and proves that `server_info` and remote `project_overview` report effective `edit` authority while retaining the full daemon ceiling only in explicitly scoped fields.
|
|
77
84
|
- local runtime proof that one blocked tool handler does not serialize an independent handler, plus relay fault injection proving an undeliverable terminal result interrupts the ambiguous socket and enters reconnect backoff.
|
|
78
85
|
- a real headless-Chrome OAuth navigation regression with four cases: `form-action 'self'` blocks the first cross-origin callback, allowing only the registered callback blocks the regional redirect, allowing the registered and regional callbacks blocks the final Copilot Studio redirect, and the complete policy preserves `code` and `state` through all three cross-origin hops. Linux CI fails if Chrome is unavailable; other environments skip only this browser executable check while retaining the Worker CSP assertions.
|
|
79
86
|
|
|
@@ -90,6 +97,11 @@ It opens Calculator, activates it through the fixed JXA helper, verifies structu
|
|
|
90
97
|
For deterministic release validation, perform an isolated-profile smoke test with the packaged unpacked extension; a Playwright persistent Chromium context is acceptable only as that isolated harness. When the requirement is specifically to prove control of the user's ordinary browser, the user must load the same unpacked directory into that known daily Chromium profile; status can verify the extension version/protocol and that Machine Bridge did not launch a browser, but cannot infer profile identity. Then use a localhost no-store fixture in a newly created tab. Do not enumerate, read, or mutate unrelated existing tabs. In both modes, inspect and reuse refs, exercise waits/forms/trusted input/open Shadow DOM/screenshots, verify final live DOM, and close the fixture tab.
|
|
91
98
|
|
|
92
99
|
|
|
100
|
+
- relay outage diagnostics and recovery: application-proxy versus OS-network scope, timestamped close/outage/recovery fields, fifteen-second maximum reconnect delay, heartbeat timeout, same-instance call continuation, Worker pong/welcome send failure, and `diagnose_runtime` relay history;
|
|
101
|
+
- recoverable managed-job terminal commits under injected result/status/delete/confirmation failures, result-only terminal reconstruction, private runtime/plan scrubbing, 24-hour staged-plan expiry, and minimal/full runner-environment inheritance;
|
|
102
|
+
- cross-process security-audit serialization, continuous hash-chain sequence, uninstall blocking for audit/authorization/job transition/recovery locks, workspace recovery-envelope validation, and symlink/multiple-hard-link rejection at owner state and operational logs;
|
|
103
|
+
- browser fixed identity, role-separated credentials, legacy migration, socket replacement/reconnect/timer cleanup, duplicate request rejection, response-delivery failure, and read-only broker load projection;
|
|
104
|
+
|
|
93
105
|
## Critical-module coverage gate
|
|
94
106
|
|
|
95
107
|
`npm run coverage:test` runs selected in-process and lightweight entrypoint fixtures under V8 coverage and enforces per-module function and branch baselines. The measured set includes policy, typed errors, call registration, execution middleware, lifecycle/observability, logging, Runtime/CLI orchestration, state persistence, relay lifecycle, managed-job lifecycle/runner/storage/projection, browser broker/direct-request/runtime-client routing and loopback upgrade handling, the independently injected service CLI adapter, Agent configuration/projection/skill discovery and bounded text reads, capability ranking, runtime path redaction, browser protocol/operation boundaries, runtime reporting/diagnostics/capability composition, and Worker OAuth state/authorization-page/pending/policy/error/JSON-RPC/WebSocket protocol modules. The full stdio and workerd OAuth/MCP integration still runs separately.
|
package/docs/THREAT_MODEL.md
CHANGED
|
@@ -1,142 +1,213 @@
|
|
|
1
1
|
# Threat model
|
|
2
2
|
|
|
3
|
-
This document defines the security claims Machine Bridge is designed to make and the claims it explicitly does not make. It complements [SECURITY.md](../SECURITY.md) and
|
|
3
|
+
This document defines the security claims Machine Bridge is designed to make and the claims it explicitly does not make. It complements [SECURITY.md](../SECURITY.md), [LOCAL_AUTHORIZATION.md](LOCAL_AUTHORIZATION.md), and [ARCHITECTURE.md](ARCHITECTURE.md).
|
|
4
4
|
|
|
5
5
|
## Scope
|
|
6
6
|
|
|
7
|
-
Machine Bridge combines
|
|
7
|
+
Machine Bridge combines:
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- a public OAuth and MCP endpoint on a Cloudflare Worker;
|
|
10
|
+
- an authenticated relay to a high-authority local daemon;
|
|
11
|
+
- optional local stdio transport;
|
|
12
|
+
- filesystem, Git, process, browser, and application automation;
|
|
13
|
+
- persistent managed jobs and registered local resources;
|
|
14
|
+
- a browser extension operating in an existing user profile.
|
|
15
|
+
|
|
16
|
+
The local runtime executes as the current OS user. Application policies restrict Machine Bridge behavior, but they do not replace kernel, account, VM, container, browser-profile, or endpoint-security isolation.
|
|
10
17
|
|
|
11
18
|
## Assets
|
|
12
19
|
|
|
13
|
-
|
|
20
|
+
Protected assets include:
|
|
14
21
|
|
|
15
|
-
- workspace and local
|
|
16
|
-
- process execution authority and inherited environment values;
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
- logs and diagnostics that could reveal paths, credentials, arguments, results, or user content.
|
|
22
|
+
- workspace files and other files reachable by the local OS user;
|
|
23
|
+
- process execution authority, process sessions, retained output, and inherited environment values;
|
|
24
|
+
- the device root, root-certified ephemeral session keys, OAuth account password verifiers, authorization codes, access tokens, refresh-token families, DPoP bindings, and trusted-client records;
|
|
25
|
+
- Machine Bridge state, locks, service metadata, native broker files, audit-chain state, registered-resource metadata, and managed-job plans/output;
|
|
26
|
+
- browser pairing state, cookies, authenticated sessions, tabs, page content, form values, screenshots, and upload authority;
|
|
27
|
+
- Worker and Durable Object routing, nonce, account, client, token, and pending-call state;
|
|
28
|
+
- release candidate hashes, package contents, acceptance records, and source-release integrity;
|
|
29
|
+
- logs and diagnostics that could reveal paths, credentials, arguments, output, or user content.
|
|
24
30
|
|
|
25
31
|
## Trust boundaries
|
|
26
32
|
|
|
27
33
|
### Hosted client to Worker
|
|
28
34
|
|
|
29
|
-
The hosted client
|
|
35
|
+
The hosted MCP client, its prompts, tools, extensions, and retrieved content are not automatically trusted. The Worker validates:
|
|
36
|
+
|
|
37
|
+
- OAuth state, PKCE, redirect URI, resource binding, and request size;
|
|
38
|
+
- account status, account version, account role, trusted client binding, token expiry, and refresh-family state;
|
|
39
|
+
- DPoP proof method, target URL, timestamp, unique identifier, access-token hash, and key thumbprint when DPoP is used;
|
|
40
|
+
- MCP session state, protocol version, method shape, request IDs, cancellation, and allowed tool exposure.
|
|
41
|
+
|
|
42
|
+
A client registration is not authority. Authority begins only after successful account authorization binds the client to one account and role version.
|
|
30
43
|
|
|
31
44
|
### Worker to local daemon
|
|
32
45
|
|
|
33
|
-
The Worker is a relay and authorization layer, not
|
|
46
|
+
The Worker is a relay and authorization layer, not the source of local OS authority.
|
|
47
|
+
|
|
48
|
+
The daemon connection requires:
|
|
49
|
+
|
|
50
|
+
1. a root-signed ephemeral device-session certificate;
|
|
51
|
+
2. a signed, nonce-bound WebSocket preflight using that session key;
|
|
52
|
+
3. a fresh Worker challenge bound to the daemon instance;
|
|
53
|
+
4. version compatibility;
|
|
54
|
+
5. an end-to-end readiness probe delivered through the same result path as real calls.
|
|
55
|
+
|
|
56
|
+
A replacement candidate does not displace a healthy daemon until those checks complete.
|
|
57
|
+
|
|
58
|
+
Each remote tool call carries account ID, account version, OAuth client ID, refresh-family ID, and role. The local runtime recomputes effective authority and applies object ownership and operation classification before dispatch.
|
|
34
59
|
|
|
35
60
|
### MCP host to local stdio process
|
|
36
61
|
|
|
37
|
-
|
|
62
|
+
Stdio is a local-owner transport. It does not use remote OAuth accounts or the relay device root. The local MCP host can invoke every tool allowed by the selected local policy.
|
|
63
|
+
|
|
64
|
+
The host, model output, repository instructions, and retrieved content may be malicious or prompt-injected. A permissive local policy therefore grants meaningful local-user authority.
|
|
38
65
|
|
|
39
66
|
### Local runtime to operating system
|
|
40
67
|
|
|
41
|
-
The runtime relies on
|
|
68
|
+
The runtime relies on OS-user identity, filesystem permissions, process controls, macOS TCC/SIP, Windows ACLs, endpoint controls, and any VM/container boundary.
|
|
69
|
+
|
|
70
|
+
For delegated process execution, Machine Bridge requires a behaviorally verified OS sandbox. If the negative boundary cannot be demonstrated, delegated execution fails closed. Owner execution is not sandboxed by Machine Bridge. Fixed implementation-owned Git metadata probes are not caller-selected process authority: they use code-constructed argv, no shell, an isolated minimal environment, bounded deadlines/output, and ordinary cancellation/process tracking.
|
|
42
71
|
|
|
43
72
|
### Local runtime to browser extension
|
|
44
73
|
|
|
45
|
-
The broker is loopback-only and pairing-token protected.
|
|
74
|
+
The broker is loopback-only and pairing-token protected. Extension origin, protocol/build version, capabilities, owner/client route, and handshake state are validated.
|
|
75
|
+
|
|
76
|
+
The extension still operates inside a real browser profile. It can reach tabs, authenticated sessions, and origins granted by browser permissions. Only the `owner` role may use browser-session control or export local data into it.
|
|
46
77
|
|
|
47
78
|
### Local runtime to persistent state
|
|
48
79
|
|
|
49
|
-
State paths, locks, plans, resources, and service definitions are security-sensitive.
|
|
80
|
+
State paths, roots, locks, plans, resources, native broker files, and service definitions are security-sensitive.
|
|
81
|
+
|
|
82
|
+
Machine Bridge uses bounded reads, canonical path resolution, owner-only modes where supported, atomic replacement, process-identity locks, schema validation, and explicit lifecycle transitions. Generic path-based tools cannot target Machine Bridge control-plane roots, even under `owner/full`. An authorized owner shell remains equivalent to same-user code execution and is outside that path boundary.
|
|
83
|
+
|
|
84
|
+
### Device root to ephemeral session
|
|
85
|
+
|
|
86
|
+
The default root is portable owner-only P-256 material, including on macOS, and is therefore readable by a determined same-user process. A non-exportable Secure Enclave root is available only through an explicitly configured app-like broker with provisioning-profile-validated Keychain access, a strict Apple code signature, stable Team ID, canonical non-symlink path with no group/other write access, and a successful real key probe. Either root signs one bounded ephemeral session certificate at daemon startup. WebSocket reconnect and account-administration requests use the in-memory session key, not the root.
|
|
87
|
+
|
|
88
|
+
The portable provider stores an exportable private JWK in owner-only state and therefore provides weaker theft resistance. `server_info` reports the provider and exportability.
|
|
89
|
+
|
|
90
|
+
Broker binding detects path, identifier, Team ID, signature, and capability drift. It does not protect against a malicious replacement signed by the same trusted Apple team and identifier. Production broker installations should therefore be root-owned or otherwise non-writable by the daemon user, with signing-key protection and update governance treated as external trust dependencies.
|
|
50
91
|
|
|
51
92
|
### Maintainer to release infrastructure
|
|
52
93
|
|
|
53
|
-
Repository checks reduce
|
|
94
|
+
Repository checks reduce package drift and accidental release mistakes. Source hosting, npm ownership, Apple signing identities, protected environments, maintainer accounts, and independent review remain external trust dependencies.
|
|
95
|
+
|
|
96
|
+
The local signature binds the self-hosted broker bytes used by this installation. Public third-party binary distribution would be a separate trust model and is outside the current package workflow.
|
|
54
97
|
|
|
55
98
|
## Attacker models
|
|
56
99
|
|
|
57
|
-
Machine Bridge considers
|
|
100
|
+
Machine Bridge considers:
|
|
58
101
|
|
|
59
|
-
1. **
|
|
60
|
-
2. **
|
|
61
|
-
3. **Malicious repository content** including instructions, package scripts, Git configuration,
|
|
62
|
-
4. **Malicious
|
|
63
|
-
5. **
|
|
64
|
-
6. **
|
|
65
|
-
7. **
|
|
66
|
-
8. **Operational
|
|
102
|
+
1. **A malicious or compromised hosted MCP client** attempting unauthorized tools, account switching, token theft/replay, OAuth redirect abuse, request duplication, cancellation races, or resource exhaustion.
|
|
103
|
+
2. **A malicious local MCP host or model output** attempting destructive operations, credential access, shell injection, persistence, or data export through an allowed local-owner policy.
|
|
104
|
+
3. **Malicious repository content** including instructions, package scripts, Git hooks/configuration, symlinks, generated metadata, or files designed to influence an agent or execution boundary.
|
|
105
|
+
4. **Malicious web or browser content** attempting prompt injection, deceptive selectors, sensitive-field disclosure, unsafe navigation, ambiguous input dispatch, or extension-protocol abuse.
|
|
106
|
+
5. **A local same-user process** attempting to read state, race locks, replace files, inspect memory, impersonate stale processes, or interfere with loopback services.
|
|
107
|
+
6. **A network attacker or misconfigured proxy** attempting interception, redirect manipulation, stale deployment evidence, connection truncation, replay, or ambiguous timeout outcomes.
|
|
108
|
+
7. **A compromised dependency or build input** attempting package substitution, install-script abuse, workflow mutation, release drift, or sensitive artifact inclusion.
|
|
109
|
+
8. **Operational faults** including abrupt termination, PID reuse, clock anomalies, partial writes, permission errors, Keychain failures, service-manager races, stale extension builds, and daemon replacement during active calls.
|
|
67
110
|
|
|
68
111
|
## Security objectives
|
|
69
112
|
|
|
70
113
|
The implementation aims to preserve these invariants:
|
|
71
114
|
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
-
|
|
81
|
-
-
|
|
82
|
-
-
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
-
|
|
115
|
+
- unknown, malformed, stale, replayed, duplicated, unauthorized, and over-limit input is rejected;
|
|
116
|
+
- remote authority is the intersection of daemon policy and account role, never the union;
|
|
117
|
+
- no approval record, token refresh, or local migration state can elevate a delegated role;
|
|
118
|
+
- OAuth clients are bound to one account/version/role and can be revoked independently;
|
|
119
|
+
- long-lived runtime objects are bound to account, account version, OAuth client, and refresh family;
|
|
120
|
+
- generic path-based remote tools cannot target Machine Bridge control-plane state;
|
|
121
|
+
- sensitive paths, persistence targets, browser/desktop control, data export, and persistent job creation are owner-only;
|
|
122
|
+
- delegated process execution is accepted only when an OS sandbox is behaviorally verified;
|
|
123
|
+
- direct argv execution is used unless the explicit shell tool is authorized;
|
|
124
|
+
- confined paths are canonicalized and symbolic-link write escape is rejected;
|
|
125
|
+
- request bodies, files, messages, output, logs, state, retained results, and concurrency are bounded;
|
|
126
|
+
- cancellation, timeout, disconnect, replacement, and shutdown have explicit process ownership and cleanup semantics;
|
|
127
|
+
- candidate daemons and browser extensions cannot replace healthy incumbents before compatibility and readiness verification;
|
|
128
|
+
- default logs and audit records omit secrets, arguments, contents, raw paths, form values, and output;
|
|
129
|
+
- multi-stage mutations are atomic or recoverable and do not silently claim partial success;
|
|
130
|
+
- device-root rotation is two-phase and does not promote an undeployed key;
|
|
131
|
+
- supply-chain actions are pinned, minimally permissioned, reviewed, and separately gated.
|
|
86
132
|
|
|
87
133
|
## Non-goals
|
|
88
134
|
|
|
89
|
-
Machine Bridge does
|
|
135
|
+
Machine Bridge does not claim to provide:
|
|
90
136
|
|
|
91
|
-
- kernel-enforced sandboxing
|
|
92
|
-
-
|
|
137
|
+
- kernel-enforced sandboxing for `owner`, universal syscall filtering, or universal network isolation;
|
|
138
|
+
- OS CPU, memory, disk, or bandwidth quotas;
|
|
139
|
+
- hard multi-tenant isolation between mutually untrusted humans sharing one daemon and OS account;
|
|
93
140
|
- protection from root, an administrator, or a fully compromised same-user account;
|
|
94
|
-
- complete prevention of prompt injection
|
|
141
|
+
- complete prevention of prompt injection when an authorized tool can perform the requested action;
|
|
95
142
|
- semantic detection of every secret, transformed credential, private document, or dangerous command;
|
|
96
|
-
- proof that the browser extension is loaded in
|
|
97
|
-
- rollback of a browser or external-system action after
|
|
143
|
+
- proof that the browser extension is loaded in an isolated profile;
|
|
144
|
+
- rollback of a browser or external-system action after ambiguous dispatch;
|
|
145
|
+
- an atomic rollback transaction spanning Cloudflare Worker deployment and every local service manager;
|
|
146
|
+
- repair or node selection inside a third-party system VPN/TUN;
|
|
98
147
|
- guaranteed cleanup after power loss, kernel failure, filesystem corruption, or an uncooperative external platform;
|
|
99
|
-
-
|
|
100
|
-
-
|
|
148
|
+
- hardware-backed key storage on every operating system;
|
|
149
|
+
- third-party public binary-store identity or independent distributor attestations;
|
|
150
|
+
- independent human review while the project has only one active maintainer.
|
|
101
151
|
|
|
102
152
|
## Residual risks
|
|
103
153
|
|
|
104
|
-
###
|
|
154
|
+
### Owner and canonical `full`
|
|
105
155
|
|
|
106
|
-
`full` intentionally preserves the complete catalog, unrestricted local-user paths, shell execution, parent environment, browser/application authority, and absolute path output.
|
|
156
|
+
`full` intentionally preserves the complete catalog, unrestricted local-user paths, shell execution, parent environment, browser/application authority, managed jobs, and absolute path output.
|
|
107
157
|
|
|
108
|
-
|
|
158
|
+
A compromised active owner client can exercise the daemon ceiling without a second per-operation prompt. The design reduces prompt fatigue and avoids insecure copy-and-retry approval ceremonies, but it makes client trust, token protection, DPoP support, account revocation, and endpoint isolation critical.
|
|
109
159
|
|
|
110
|
-
|
|
160
|
+
Use a narrower profile, separate OS account, container, or VM when prompts, repositories, clients, or workloads are mutually untrusted.
|
|
111
161
|
|
|
112
|
-
###
|
|
162
|
+
### Bearer clients
|
|
113
163
|
|
|
114
|
-
|
|
164
|
+
DPoP is optional for interoperability. A Bearer token can be used by whoever possesses it until expiry or revocation. Short access-token lifetime, rotating refresh families, client binding, account versioning, and replay-family revocation reduce but do not eliminate token theft risk.
|
|
115
165
|
|
|
116
166
|
### Same-user interference
|
|
117
167
|
|
|
118
|
-
Owner-only permissions
|
|
168
|
+
Owner-only permissions, optional provisioned Secure Enclave roots, control-plane path denial, process-identity locks, and audit chains reduce several attacks. They cannot prevent a determined same-user process from reading portable credentials, inspecting process memory, changing source before execution, or interfering with local services.
|
|
169
|
+
|
|
170
|
+
### Delegated sandbox availability
|
|
171
|
+
|
|
172
|
+
Delegated execution is unavailable when the platform sandbox cannot pass the negative-boundary probe. This is an intentional availability trade-off. Replacing fail-closed behavior with an unverified path blacklist would create false isolation.
|
|
173
|
+
|
|
174
|
+
### Browser and application automation
|
|
175
|
+
|
|
176
|
+
UI state can change between inspection and action. Pages can present deceptive content, and authenticated profiles may contain high-value sessions. Protocol checks and trusted-input handling do not make arbitrary web content trustworthy.
|
|
177
|
+
|
|
178
|
+
### Managed jobs
|
|
179
|
+
|
|
180
|
+
Managed jobs outlive MCP calls and daemon reconnects. Plans and resources are validated and ownership-bound, but an authorized owner plan can still consume resources or perform destructive work. Finally steps must be idempotent because recovery may retry them.
|
|
119
181
|
|
|
120
182
|
### Availability and resource exhaustion
|
|
121
183
|
|
|
122
|
-
|
|
184
|
+
Application-level limits bound many requests and outputs. An authorized owner process can still exhaust CPU, memory, disk, network, or external service quotas.
|
|
185
|
+
|
|
186
|
+
### System VPN/TUN and distributed activation
|
|
187
|
+
|
|
188
|
+
A system VPN/TUN can remain administratively connected while its selected upstream route, synthetic DNS mapping, or transport path is temporarily unusable. Machine Bridge can detect missing inbound relay traffic, classify the socket close, bound retry delay, and report outage history, but it cannot select or repair a third-party VPN node. `system-network-stack` is therefore not a claim of direct routing.
|
|
189
|
+
|
|
190
|
+
Candidate activation verifies the foreground candidate before service handoff and records exact package/deployment evidence. It does not provide an atomic transaction spanning Cloudflare deployment and every local service manager. If the Worker changes and the local handoff later fails, the operator may need the recorded previous runtime/deployment evidence to complete rollback. Local cleanup errors are aggregated rather than hidden, but remote rollback is not fabricated.
|
|
123
191
|
|
|
124
192
|
### External governance and publication
|
|
125
193
|
|
|
126
|
-
Code cannot create a second independent reviewer, npm OIDC trust relationship, protected environment,
|
|
194
|
+
Code cannot create a second independent reviewer, npm OIDC trust relationship, protected publication environment, Apple Developer identity, or external certification. These remain explicit operational requirements.
|
|
127
195
|
|
|
128
196
|
## Validation map
|
|
129
197
|
|
|
130
|
-
|
|
198
|
+
Regression suites cover:
|
|
131
199
|
|
|
132
|
-
-
|
|
133
|
-
-
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
-
|
|
200
|
+
- account roles, trusted clients, account-version revocation, refresh-family rotation/replay, DPoP proofs, and non-escalatable effective authority;
|
|
201
|
+
- root-certified ephemeral sessions, preflight nonce replay, daemon challenge binding, readiness, reconnect, and candidate replacement;
|
|
202
|
+
- signed account administration, client revocation, and removal of the long-lived administration secret;
|
|
203
|
+
- control-plane path denial, path canonicalization, symlink handling, sensitive/persistence targets, and object ownership;
|
|
204
|
+
- delegated sandbox behavior and fail-closed platform detection;
|
|
205
|
+
- process/session cleanup, managed-job lifecycle and recovery, state locks, atomic persistence, and destructive removal;
|
|
206
|
+
- browser pairing, version/capability handshake, broker routing, sensitive input, and navigation controls;
|
|
207
|
+
- audit-chain integrity, privacy redaction, package contents, installation, release impact, dependency integrity, CodeQL, and Scorecard findings;
|
|
137
208
|
- malformed, over-limit, concurrent, replayed, stale, and fault-injected inputs.
|
|
138
209
|
|
|
139
|
-
See [TESTING.md](TESTING.md) for the
|
|
210
|
+
See [TESTING.md](TESTING.md) for the test inventory and [AUDIT.md](AUDIT.md) for historical findings and residual limitations.
|
|
140
211
|
|
|
141
212
|
## Reporting
|
|
142
213
|
|
package/docs/TOOL_REFERENCE.md
CHANGED
|
@@ -2293,9 +2293,9 @@ Generate or reuse an Ed25519 SSH key pair on the local machine and register the
|
|
|
2293
2293
|
|
|
2294
2294
|
## `stage_job`
|
|
2295
2295
|
|
|
2296
|
-
**Stage managed job
|
|
2296
|
+
**Stage managed job draft**
|
|
2297
2297
|
|
|
2298
|
-
Validate and persist a managed-job
|
|
2298
|
+
Validate and persist a durable managed-job draft without starting any process. This is a non-executing record only; a trusted owner client starts work with start_job after reviewing or reconstructing the plan.
|
|
2299
2299
|
|
|
2300
2300
|
| Contract field | Value |
|
|
2301
2301
|
|---|---|
|
package/docs/UPGRADING.md
CHANGED
|
@@ -2,37 +2,121 @@
|
|
|
2
2
|
|
|
3
3
|
## Supported upgrade contract
|
|
4
4
|
|
|
5
|
-
Machine Bridge
|
|
5
|
+
Machine Bridge supports direct upgrade from the immediately preceding published release. Obsolete transport, state, lock, browser-extension, and authorization implementations are not retained as hidden compatibility paths.
|
|
6
6
|
|
|
7
|
-
Version
|
|
7
|
+
Version 3.0.0 is a coordinated Worker, daemon, CLI, and browser-extension security upgrade. Mixed 2.x and 3.x components are intentionally unavailable.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
The major changes are:
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
- account roles become non-escalatable hard ceilings;
|
|
12
|
+
- terminal approval IDs and runtime capability leases are removed from authorization;
|
|
13
|
+
- OAuth clients become persistently bound to one account and role version;
|
|
14
|
+
- process sessions, retained output, and managed jobs bind to account, client, and refresh-token family;
|
|
15
|
+
- account administration moves from a long-lived symmetric secret to root-certified ephemeral P-256 session signatures;
|
|
16
|
+
- daemon connections use a root-certified 24-hour in-memory session key;
|
|
17
|
+
- macOS can use a non-exportable Secure Enclave root only through an explicitly configured, provisioning-profile-validated broker; otherwise it retains the portable owner-only root;
|
|
18
|
+
- supported OAuth clients may use DPoP-bound access and refresh tokens;
|
|
19
|
+
- generic path-based remote file access to Machine Bridge control-plane state is denied even to `owner`; arbitrary owner shell execution remains local-user authority;
|
|
20
|
+
- delegated process execution requires a behaviorally verified OS sandbox and otherwise fails closed;
|
|
21
|
+
- local security events form a bounded, privacy-preserving hash chain.
|
|
12
22
|
|
|
13
|
-
Version
|
|
23
|
+
## Version 2 to version 3
|
|
14
24
|
|
|
15
|
-
|
|
25
|
+
### Device-root migration
|
|
26
|
+
|
|
27
|
+
`3.0.0-beta.1`, `3.0.0-beta.2`, `3.0.0-beta.3`, `3.0.0-beta.4`, `3.0.0-beta.5`, and `3.0.0-beta.6` are blocked and must not be activated, accepted, published, or promoted. Beta.1 changed the canonical JWK member order used by version 2 device identifiers. Beta.2 repaired that compatibility issue but attempted to create a persistent Secure Enclave key from an ad-hoc-signed runtime helper, which macOS rejected with `errSecMissingEntitlement` (`-34018`). Beta.3 completed owner activation but exposed delegated project/Git authority defects. Beta.4 corrected those defects, yet continued owner-machine auditing found service-control self-termination, timestamp-less mixed-format logs, system-VPN relay outages amplified by a sixty-second reconnect cap, and additional state/browser/job/process boundaries. Beta.5 corrected those findings and passed live Worker/daemon/start/restart verification, but its launchd definition captured npm lifecycle PATH injection and the prior candidate runtime that activation then removed. Beta.6 removed stale candidate paths but selected only the first npm marker; nested npm activation retained an inner project-bin prefix. None of the blocked candidates intentionally rotated or invalidated the existing portable device root.
|
|
28
|
+
|
|
29
|
+
`3.0.0-beta.7` retains the portable P-256 root by default and is the next supported candidate path. It includes the beta.5 authority, relay, state, browser, managed-job, process-tree, audit-lock, hard-link, and service-lifecycle corrections, then makes the persistent service PATH independent of nested npm lifecycle injection and inactive candidate runtimes. Normal startup performs no Keychain operation and requests no user presence unless an explicitly provisioned broker is configured.
|
|
30
|
+
|
|
31
|
+
Secure Enclave enrollment is optional and explicit. Set `MBM_MACOS_TRUST_BROKER` to the absolute executable path inside an app-like broker that is signed by an Apple development or distribution identity and whose data-protection Keychain entitlements are validated by an embedded provisioning profile. Machine Bridge then verifies that the path is a non-symlink regular executable, rejects group/other-writable files, verifies the strict code signature, records the signing identifier and Team ID, and performs an end-to-end create/delete probe with a temporary Secure Enclave key. A source-built or ad-hoc-signed helper is intentionally rejected.
|
|
32
|
+
|
|
33
|
+
When a provisioned broker is configured, migration remains two-phase:
|
|
34
|
+
|
|
35
|
+
1. the broker creates the non-exportable key and Machine Bridge stores only its canonical broker binding, public JWK, key ID, and Keychain tag as `pendingDeviceIdentity`;
|
|
36
|
+
2. the Worker is deployed with that pending public key;
|
|
37
|
+
3. Worker health and exact-version convergence are verified;
|
|
38
|
+
4. only then is the pending root promoted to active state.
|
|
39
|
+
|
|
40
|
+
A failed probe, upload, interrupted process, or failed health check leaves the old active root intact. `--daemon-only` refuses to activate an undeployed pending root. Every later public-key check and signature revalidates the canonical broker path, code-signing identifier, and Team ID.
|
|
41
|
+
|
|
42
|
+
Other platforms, and macOS installations without a provisioned broker, use the portable P-256 provider. Its private JWK remains owner-only local state and is explicitly reported as exportable.
|
|
43
|
+
|
|
44
|
+
### OAuth clients and tokens
|
|
45
|
+
|
|
46
|
+
Existing clients may need to authorize again so the Worker can record the new trusted account binding. A refresh token whose client record is not bound to the current account version and role fails closed.
|
|
47
|
+
|
|
48
|
+
Access tokens remain short-lived. Refresh tokens remain one-time rotating and family-bound. Reuse of an already-rotated refresh token revokes the complete family, including active access tokens.
|
|
49
|
+
|
|
50
|
+
DPoP is optional. A client that supports DPoP may bind its token family to a P-256 key; clients without DPoP continue with Bearer tokens under the same account, client, role, and family checks.
|
|
51
|
+
|
|
52
|
+
### Removed authorization workflows
|
|
53
|
+
|
|
54
|
+
Version 3 does not create or consume pending approval IDs. The following workflows are obsolete:
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
machine-mcp approval approve ...
|
|
58
|
+
machine-mcp approval grant ...
|
|
59
|
+
machine-mcp job approve ...
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Legacy version 2 lease state may be listed, revoked, or cleared for cleanup, but it has no effect on runtime authority.
|
|
63
|
+
|
|
64
|
+
`stage_job` is a non-executing draft and cannot be promoted by a terminal approval command. A trusted owner uses `start_job`; a local machine operator may submit a reviewed plan with `machine-mcp job submit PLAN.json`.
|
|
65
|
+
|
|
66
|
+
### Removed administration secret
|
|
67
|
+
|
|
68
|
+
`ACCOUNT_ADMIN_SECRET` is deleted from local state and is no longer deployed to the Worker. Account and OAuth-client administration uses the same root-certified ephemeral session established for daemon startup or an independently authorized local administration command.
|
|
16
69
|
|
|
17
70
|
## Normal upgrade
|
|
18
71
|
|
|
19
|
-
1.
|
|
20
|
-
2.
|
|
21
|
-
3.
|
|
22
|
-
4.
|
|
23
|
-
5.
|
|
24
|
-
6.
|
|
25
|
-
7.
|
|
26
|
-
8.
|
|
72
|
+
1. Inspect or cancel interactive processes and managed jobs that should not survive daemon replacement.
|
|
73
|
+
2. Back up the owner-only state directory with an operating-system tool that preserves permissions. Do not upload or publish the backup.
|
|
74
|
+
3. Install the version 3 package.
|
|
75
|
+
4. Run `machine-mcp doctor`.
|
|
76
|
+
5. Start each workspace normally in the foreground. Without a provisioned broker, macOS reuses the portable root and does not prompt.
|
|
77
|
+
6. When `MBM_MACOS_TRUST_BROKER` is intentionally configured, verify the broker deployment first and complete the single user-presence request used to sign the daemon session certificate. Do not start with `--daemon-only` during this optional root migration.
|
|
78
|
+
7. Allow Machine Bridge to deploy and verify the matching version 3 Worker. A pending root is promoted only after health convergence.
|
|
79
|
+
8. Reconnect each hosted MCP client and complete OAuth authorization when requested.
|
|
80
|
+
9. Inspect trusted clients with `machine-mcp account clients` and revoke stale or duplicate records.
|
|
81
|
+
10. Reload the version 3 browser extension.
|
|
82
|
+
11. Verify one safe workspace read, one ordinary edit, and one owner-only action appropriate for the deployment.
|
|
83
|
+
12. Restore background service operation only after the foreground path is healthy.
|
|
84
|
+
|
|
85
|
+
## Verification
|
|
86
|
+
|
|
87
|
+
After upgrade, `server_info` should report:
|
|
88
|
+
|
|
89
|
+
- matching Worker and daemon version;
|
|
90
|
+
- end-to-end relay readiness;
|
|
91
|
+
- the authenticated account role and effective policy;
|
|
92
|
+
- a current OAuth client and refresh family;
|
|
93
|
+
- device-root provider and exportability;
|
|
94
|
+
- ephemeral session use for reconnect signing;
|
|
95
|
+
- delegated sandbox status;
|
|
96
|
+
- security-audit chain health.
|
|
97
|
+
|
|
98
|
+
A full daemon policy is not proof that a delegated account has full authority. Use `authorization.effective_policy` and `authorization.effective_tools` for the current request.
|
|
27
99
|
|
|
28
100
|
## Upgrade safety
|
|
29
101
|
|
|
30
|
-
|
|
102
|
+
Machine Bridge rejects unreadable, malformed, foreign-schema, or ambiguous state rather than silently initializing replacement state.
|
|
103
|
+
|
|
104
|
+
Worker deployment records upload success separately from health convergence. A post-upload network failure does not trigger an uncontrolled repeated write, and a pending root is not promoted merely because Wrangler returned success.
|
|
31
105
|
|
|
32
|
-
|
|
106
|
+
The packaged Swift broker source is a development and protocol-conformance fixture only. The local build is ad-hoc signed and is deliberately rejected by the production validator because it cannot obtain a provisioning-profile-validated data-protection Keychain access group. A production Secure Enclave broker must be shipped as an app-like, correctly signed and provisioned component outside the npm runtime build.
|
|
33
107
|
|
|
34
108
|
## Rollback
|
|
35
109
|
|
|
36
|
-
Rollback is supported only
|
|
110
|
+
Rollback is supported only as a complete unit from a verified pre-upgrade backup.
|
|
111
|
+
|
|
112
|
+
Version 3 changes daemon authentication, account administration, OAuth client trust, object ownership, local authorization, and device-root storage. Copying an older package over version 3 state produces a mixed system that should fail closed.
|
|
113
|
+
|
|
114
|
+
A rollback must restore together:
|
|
115
|
+
|
|
116
|
+
- the complete prior owner-only state root;
|
|
117
|
+
- the prior package;
|
|
118
|
+
- the prior Worker build and secrets;
|
|
119
|
+
- the prior service definition;
|
|
120
|
+
- the prior browser extension.
|
|
37
121
|
|
|
38
|
-
|
|
122
|
+
Do not roll back by editing version or schema fields, copying selected credential files, or restoring only the Worker. Prefer fixing forward when a complete backup is unavailable.
|