machine-bridge-mcp 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +18 -8
  3. package/SECURITY.md +10 -3
  4. package/browser-extension/browser-operations.js +515 -0
  5. package/browser-extension/devtools-input.js +17 -2
  6. package/browser-extension/manifest.json +2 -2
  7. package/browser-extension/page-automation.js +245 -60
  8. package/browser-extension/pairing.js +1 -1
  9. package/browser-extension/service-worker.js +151 -354
  10. package/docs/ARCHITECTURE.md +6 -4
  11. package/docs/AUDIT.md +24 -1
  12. package/docs/LOCAL_AUTOMATION.md +10 -10
  13. package/docs/LOGGING.md +7 -1
  14. package/docs/OPERATIONS.md +13 -5
  15. package/docs/POLICY_REFERENCE.md +88 -0
  16. package/docs/TESTING.md +9 -2
  17. package/package.json +16 -3
  18. package/scripts/coverage-check.mjs +108 -0
  19. package/scripts/generate-policy-reference.mjs +95 -0
  20. package/src/local/agent-context.mjs +1 -103
  21. package/src/local/app-automation.mjs +7 -9
  22. package/src/local/browser-bridge.mjs +69 -143
  23. package/src/local/browser-extension-protocol.mjs +75 -0
  24. package/src/local/browser-pairing-store.mjs +83 -0
  25. package/src/local/call-registry.mjs +113 -0
  26. package/src/local/capability-ranking.mjs +103 -0
  27. package/src/local/cli-local-admin.mjs +308 -0
  28. package/src/local/cli-options.mjs +151 -0
  29. package/src/local/cli-policy.mjs +77 -0
  30. package/src/local/cli.mjs +16 -507
  31. package/src/local/errors.mjs +122 -0
  32. package/src/local/git-service.mjs +88 -0
  33. package/src/local/lifecycle.mjs +64 -0
  34. package/src/local/log.mjs +50 -19
  35. package/src/local/managed-job-plan.mjs +235 -0
  36. package/src/local/managed-jobs.mjs +16 -220
  37. package/src/local/observability.mjs +83 -0
  38. package/src/local/policy.mjs +148 -0
  39. package/src/local/process-execution.mjs +153 -0
  40. package/src/local/process-sessions.mjs +10 -20
  41. package/src/local/process-tracker.mjs +55 -0
  42. package/src/local/runtime.mjs +154 -672
  43. package/src/local/service.mjs +8 -3
  44. package/src/local/stdio.mjs +3 -11
  45. package/src/local/tool-executor.mjs +102 -0
  46. package/src/local/tools.mjs +21 -104
  47. package/src/local/workspace-file-service.mjs +451 -0
  48. package/src/shared/policy-contract.json +54 -0
  49. package/src/shared/tool-catalog.json +11 -11
  50. package/src/worker/index.ts +69 -524
package/CHANGELOG.md CHANGED
@@ -1,5 +1,44 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.16.0 - 2026-07-13
4
+
5
+ ### Runtime boundaries and lifecycle
6
+
7
+ - Replace the monolithic local tool dispatcher with a middleware-based execution pipeline covering policy authorization, bounded call registration, cancellation/deadlines, stable error normalization, structured lifecycle events, and per-tool metrics. Add explicit runtime lifecycle states and a process tracker so stop/cancel paths release calls and child ownership deterministically.
8
+ - Extract workspace filesystem transactions, process/shell execution, Git operations, CLI option/policy parsing, local resource/browser/job administration, capability ranking, managed-job plan/resource validation, browser extension protocol handling, and browser pairing persistence into focused modules. Add executable line-count and dependency-direction limits so these responsibilities cannot silently return to `LocalRuntime`, the CLI entrypoint, or browser manager.
9
+ - Split the Worker Durable Object into HTTP/CORS boundaries, OAuth state/PKCE helpers, shared policy evaluation, structured errors, pending-call indexing, and observability. Replace the linear pending-call scan with an atomic ID/request-key registry so completed, cancelled, timed-out, send-failed, and disconnected calls clear both indexes before settling; JSON-RPC request IDs can be reused immediately after completion.
10
+
11
+ ### Policy, errors, logging, and observability
12
+
13
+ - Define policy revision 4 in one shared contract consumed by the local daemon, Worker, generated documentation, tests, and architecture checks. Fix `start_job` to require both write and direct-execution capabilities, keep `cancel_job` write-gated, and expose read-only resource/job inventory to review-mode clients without granting mutation authority.
14
+ - Introduce typed `BridgeError`/Worker errors with allowlisted stable codes and retryability. Centralize legacy error classification at adapters instead of making transports and tests depend on free-form English messages. Unknown programming errors are no longer silently converted into ordinary managed-resource unavailability; a failing timeout callback still settles and clears its pending indexes.
15
+ - Add structured JSON lifecycle logging and in-memory observability for calls, durations, errors, active processes, pending request indexes, daemon candidates, socket transitions, and per-tool outcomes. Autostart services now use warning-level JSON logs by default while foreground output remains human-readable; local and Worker structured-field redaction is behavior-tested.
16
+
17
+ ### Tests, documentation, and audit follow-up
18
+
19
+ - Add behavior tests for policy parity, compound ACLs, middleware order, runtime lifecycle transitions, process ownership, pending-ID reuse, socket cleanup, Worker/local error serialization, structured log privacy, bilingual capability ranking, and generated policy documentation. Replace brittle source-string and monkeypatched happy-path tests with production-path deadline, process-tree, OAuth/MCP, and resource-reload coverage.
20
+ - Add a critical-module V8 coverage gate with per-module function/branch baselines, rather than a single aggregate percentage that hides weak orchestration coverage. Generate `docs/POLICY_REFERENCE.md` from the shared policy contract and tool catalog; CI rejects stale generated documentation.
21
+ - Correct an extraction defect where a re-exported resource inspector was not locally bound and a broad catch disguised the resulting `ReferenceError` as `resource_unavailable`. File availability now degrades only for classified filesystem conditions; unexpected implementation faults remain visible.
22
+
23
+ ## 0.15.0 - 2026-07-13
24
+
25
+ ### Daily-profile browser verification and protocol safety
26
+
27
+ - Verify the unpacked extension in the user's ordinary Chrome profile with a localhost-only live smoke test covering the acknowledged protocol handshake, real tab lifecycle, semantic inspection, open Shadow DOM, complex form fill, fixed DevTools text/click input, waits, screenshot capture, and cleanup. `browser status` and loopback health now report extension version/protocol, that Machine Bridge did not launch the browser, and the fact that daily-vs-isolated profile identity is not machine-verifiable.
28
+ - Upgrade the extension protocol to an acknowledged `hello`/`hello_ack` state machine with exact packaged-version, protocol, and capability equality. WebSocket open is no longer treated as authenticated readiness, pairing material is persisted only after a successful capability handshake, failed candidate pairing preserves the prior configuration, pairing-page and broker ports must match, and extension WebSocket origins require a canonical 32-character Chromium extension ID.
29
+ - Prevent duplicate side effects after an ambiguous trusted-input failure. `auto` falls back to DOM only before any DevTools `Input` command starts; after dispatch begins, the operation fails with an explicit unknown-outcome instruction to inspect the page before retrying. Screenshot capture temporarily activates only the requested tab, never focuses its window, and restores the previous active tab unless the user changed it concurrently.
30
+
31
+ ### Bounded page processing and extension architecture
32
+
33
+ - Apply `max_bytes` and `max_elements` as aggregate request budgets across at most 64 accessible frames. Replace full `outerHTML` construction with a bounded iterative DOM serializer, cap page scans at 100,000 nodes, bound page-controlled metadata/text, cap reusable refs at 10,000 per frame, redact URL userinfo, mark contenteditable secret controls as sensitive, and report frame/node/text/ref truncation explicitly.
34
+ - Report partial multi-field form mutation precisely when a later field or submission fails. Navigation waits now inherit the bounded request deadline rather than using a hidden fixed 30-second timer.
35
+ - Extract tab/page/wait/source/screenshot orchestration into fixed `browser-operations.js`; the Manifest V3 service worker now owns only pairing, transport, acknowledged readiness, cancellation, and response routing. Architecture tests enforce this responsibility boundary.
36
+
37
+ ### Cross-platform audit and regression coverage
38
+
39
+ - Replace ad-hoc Windows Scheduled Task argument quoting with the Windows CRT-compatible backslash/quote algorithm, including drive-root and trailing-backslash paths.
40
+ - Add behavior tests for handshake readiness, provisional pairing persistence, trusted-input replay prevention, focus restoration, aggregate frame/source budgets, hostile DOM/text bounds, partial form failure, strict extension origins, and Windows command-line quoting. Synchronize architecture, security, operations, testing, audit, and tool documentation.
41
+
3
42
  ## 0.14.0 - 2026-07-13
4
43
 
5
44
  ### Windows installation and OAuth callback reliability
package/README.md CHANGED
@@ -32,7 +32,7 @@ A newly selected workspace starts with the maximum-permission `full` profile for
32
32
  - tool results may return absolute paths;
33
33
  - child processes inherit the complete parent environment.
34
34
 
35
- Policy state records whether it came from the default, an explicit named profile, or custom overrides. Named profiles are canonical contracts: a stored `full` profile is repaired on load to enable writes, shell execution, unrestricted paths, full parent environment, absolute path output, and the complete tool catalog. Any explicit per-capability narrowing is stored as `custom`. Policy revision 3 refreshes default/migrated state and preserves explicit restrictive/custom profiles.
35
+ Policy state records whether it came from the default, an explicit named profile, or custom overrides. Named profiles are canonical contracts: a stored `full` profile is repaired on load to enable writes, shell execution, unrestricted paths, full parent environment, absolute path output, and the complete tool catalog. Any explicit per-capability narrowing is stored as `custom`. Policy revision 4 normalizes named profiles from the shared contract, refreshes default/migrated state, preserves explicit restrictive/custom profiles, and applies compound tool requirements consistently in the local daemon and Worker.
36
36
 
37
37
  | Profile | File edits | Direct argv processes | Shell commands | Filesystem scope | Process environment |
38
38
  |---|---:|---:|---:|---|---|
@@ -185,7 +185,7 @@ Skill discovery follows Codex-style progressive disclosure. Default project root
185
185
  Under canonical `full`, Machine Bridge also exposes structured local automation:
186
186
 
187
187
  - installed application discovery/opening and macOS Accessibility inspection/actions;
188
- - a packaged Chromium extension that controls the user's existing daily browser profile, active tabs, login state, and windows;
188
+ - a packaged Chromium extension that controls the profile into which the user loads it, including that profile's tabs, login state, and windows; Machine Bridge does not launch a separate browser process;
189
189
  - current DOM source and frame/open-Shadow-DOM inspection, stable semantic element references, actionability waits, fixed trusted mouse/keyboard input, explicit browser waits, tab management, complex multi-field forms, resource-backed secret fields, resource-backed file uploads, and screenshots.
190
190
 
191
191
  One-time browser setup:
@@ -195,12 +195,21 @@ machine-mcp browser setup
195
195
  machine-mcp browser status
196
196
  ```
197
197
 
198
- Load the printed unpacked-extension directory once in Chrome, Edge, Brave, Vivaldi, or another compatible Chromium browser. After an upgrade that adds permissions, reload the unpacked extension and accept the browser prompt; trusted input uses the Chromium `debugger` permission only for fixed, short-lived DevTools Input commands. The extension badge reports connection state, and clicking it opens the saved local pairing page. The local pairing token remains in owner-only state and the loopback pairing page; it is not returned through MCP. For a mass-market release, distribute the same extension as a signed browser-store build rather than asking end users to enable Developer mode. See [Local application and browser automation](docs/LOCAL_AUTOMATION.md).
198
+ Load the printed unpacked-extension directory in the Chromium profile you actually use; Machine Bridge does not install it into Playwright or a separate automation profile. After every Machine Bridge upgrade, reload the unpacked extension and accept any new browser permission. `machine-mcp browser status` reports both the expected packaged extension build and the authenticated connected build/protocol, and states that Machine Bridge did not launch the browser. It cannot infer whether the extension was loaded into a daily or isolated profile; that is determined by where the user installed it. Trusted input uses the Chromium `debugger` permission only for fixed, short-lived DevTools Input commands. The badge shows `ON` only after the broker acknowledges the version/capability handshake. The local pairing token remains in owner-only state and non-cacheable loopback HTML; it is not returned through MCP. For a mass-market release, distribute the same extension as a signed browser-store build rather than asking end users to enable Developer mode. See [Local application and browser automation](docs/LOCAL_AUTOMATION.md).
199
199
 
200
200
  Machine Bridge can discover, refresh, rank, and load capabilities automatically. The ChatGPT/MCP host still owns tool selection and approval, so the server cannot force a host to expose or invoke a recommended skill, command, app, or browser operation. Check `server_info.observability.capability_routing` or `project_overview.capabilityRouting` to distinguish “the host never called the resolver” from “the resolver ran but found no relevant capability.”
201
201
 
202
+
203
+ ## Runtime lifecycle and observability
204
+
205
+ Every tool call passes through one execution pipeline: bounded call registration and deadline/cancellation ownership, structured observability, shared policy authorization, then the typed handler. Errors use stable codes and retryability metadata instead of transport-specific message parsing. `server_info` exposes the local lifecycle state, in-flight calls, active process ownership, per-tool outcomes, durations, and error-code counts. The Worker adds pending internal/request-key indexes, daemon candidate/socket counters, and Worker-side per-tool outcomes.
206
+
207
+ Foreground logging defaults to human-readable text. Installed background services use warning-level JSON events by default. Use `--log-format json` for machine-readable foreground logs; arguments, outputs, credentials, resource contents, and local paths remain excluded or redacted.
208
+
202
209
  ## Policy controls
203
210
 
211
+ Policy revision 4 is defined once in `src/shared/policy-contract.json`. The local runtime, Worker advertisement filter, manager-level defense-in-depth checks, tests, and generated [policy reference](docs/POLICY_REFERENCE.md) consume that same contract. A custom policy is authorized by capabilities rather than its display name; compound classes such as `write+direct-exec` require every capability.
212
+
204
213
  The default is `full`. Narrow or customize it with explicit flags:
205
214
 
206
215
  ```text
@@ -212,6 +221,7 @@ The default is `full`. Narrow or customize it with explicit flags:
212
221
  --unrestricted-paths
213
222
  --absolute-paths
214
223
  --log-level error|warn|info|debug
224
+ --log-format text|json
215
225
  --verbose
216
226
  --quiet
217
227
  ```
@@ -347,13 +357,13 @@ The exact `tools/list` response reflects the active local policy. Definitions co
347
357
  - `pair_browser_extension`
348
358
  - `browser_list_tabs`
349
359
  - `browser_manage_tabs` — create, activate, or close tabs
350
- - `browser_get_source` — bounded current DOM HTML, including selected frames
351
- - `browser_inspect_page` — semantic controls, stable per-document refs, state, and geometry
360
+ - `browser_get_source` — bounded current DOM HTML with one aggregate byte budget across up to 64 accessible frames
361
+ - `browser_inspect_page` — semantic controls, bounded LRU refs, state, geometry, and explicit frame/node/ref truncation metadata
352
362
  - `browser_wait` — bounded URL/load/text/element-state waits
353
- - `browser_action` — actionability checks plus `auto`, `trusted`, or `dom` input mode
363
+ - `browser_action` — actionability checks plus `auto`, `trusted`, or `dom` input mode; ambiguous post-dispatch failures are never replayed through DOM
354
364
  - `browser_fill_form`
355
365
  - `browser_upload_files` — registered local resources to file inputs
356
- - `browser_screenshot`
366
+ - `browser_screenshot` — restores the prior active tab and does not focus another window
357
367
 
358
368
 
359
369
  ### Mutation
@@ -432,7 +442,7 @@ Remote mode supports:
432
442
  - Linux `systemd --user`, with best-effort lingering;
433
443
  - Windows Scheduled Task at logon.
434
444
 
435
- The service definition contains neither credentials nor a duplicate policy. It loads the selected policy from owner-only local state and uses the documented `full` default if policy state is absent. launchd/systemd definitions persist a sanitized absolute-only PATH captured during installation, including the stable Node/CLI directories, so background `full` mode does not lose Homebrew or other developer command locations. Background services run at log level `warn`: relay, protocol, and service problems are retained, while all per-tool success/failure/cancellation/timing events remain debug-only. Logs are owner-only where supported and bounded by tail trimming.
445
+ The service definition contains neither credentials nor a duplicate policy. It loads the selected policy from owner-only local state and uses the documented `full` default if policy state is absent. launchd/systemd definitions persist a sanitized absolute-only PATH captured during installation, including the stable Node/CLI directories, so background `full` mode does not lose Homebrew or other developer command locations. Background services run at log level `warn` with JSON output: relay, protocol, and service problems are retained as bounded structured events, while all per-tool success/failure/cancellation/timing events remain debug-only. Logs are owner-only where supported and bounded by tail trimming.
436
446
 
437
447
  ## Secret rotation
438
448
 
package/SECURITY.md CHANGED
@@ -73,11 +73,18 @@ The global `model_instructions_file` is an explicit user trust decision. It is r
73
73
 
74
74
  Canonical `full` exposes structured browser and desktop UI authority. The browser extension operates the user's existing Chromium profile, including active login state, and has broad host access plus Chromium `debugger` permission so it can inspect arbitrary pages, fill complex forms, and issue trusted input. An authorized client may therefore read page content, click controls, submit forms, upload registered files, and cause transactions with the user's browser identity. macOS Accessibility actions similarly operate applications with the local user's UI authority.
75
75
 
76
- The browser loopback broker validates loopback `Host`, requires a random owner-only bearer subprotocol, accepts extension sockets only with a `chrome-extension://` origin, and authenticates additional local runtimes separately. Initial extension pairing is trust-on-first-use; after pairing, a different localhost page cannot replace the stored broker unless the user clicks the extension action while the genuine pairing page is active. The pairing token is never returned by MCP or written to operational logs. These controls defend against casual cross-origin and DNS-rebinding access; they do not protect against malicious code already running as the same OS user or a compromised browser extension profile.
76
+ The browser loopback broker validates loopback `Host`, requires a random owner-only bearer subprotocol, accepts extension sockets only from a canonical 32-character Chromium extension ID, requires the pairing page and WebSocket endpoint to use the same loopback port, and authenticates additional local runtimes separately. Initial extension pairing is trust-on-first-use; after pairing, a different localhost page cannot replace the stored broker unless the user clicks the extension action while the genuine pairing page is active. The pairing token is never returned by MCP or written to operational logs. These controls defend against casual cross-origin and DNS-rebinding access; they do not protect against malicious code already running as the same OS user or a compromised browser extension profile.
77
77
 
78
- Caller-supplied JavaScript, AppleScript, JXA source, and arbitrary DevTools methods are deliberately unsupported. Actions use fixed implementation code and structured selectors. The debugger adapter is restricted to fixed `Input` commands, attaches only around one trusted action, and detaches in `finally`; `input_mode` makes fallback behavior explicit. The broker validates a versioned extension capability hello before activating a connection and does not let an invalid replacement candidate displace an already compatible extension. This removes an avoidable arbitrary-evaluation surface but does not make DOM or Accessibility actions safe. Pages can contain prompt injection, misleading labels, hidden consequences, cross-origin frames unavailable to inspection, or state that changes between inspection and submission. High-impact account, financial, legal, medical, publishing, deletion, and purchase actions require contextual review and any host/user confirmation the client provides.
78
+ Caller-supplied JavaScript, AppleScript, JXA source, and arbitrary DevTools methods are deliberately unsupported. Actions use fixed implementation code and structured selectors. The debugger adapter is restricted to fixed `Input` commands, attaches only around one trusted action, and detaches in `finally`. `auto` falls back only before any Input dispatch; after dispatch begins, failure is reported as an unknown outcome and is never replayed through DOM. The broker and extension require a protocol-3 `hello`/`hello_ack` exchange plus exact packaged-version and capability equality before either reports readiness. Pairing material is persisted only after acknowledgement, and an invalid replacement candidate cannot displace the current connection or overwrite its stored endpoint/token. This removes an avoidable arbitrary-evaluation surface but does not make DOM or Accessibility actions safe. Pages can contain prompt injection, misleading labels, hidden consequences, cross-origin frames unavailable to inspection, or state that changes between inspection and submission. High-impact account, financial, legal, medical, publishing, deletion, and purchase actions require contextual review and any host/user confirmation the client provides.
79
79
 
80
- Text and file resources can be injected locally so their contents do not appear in MCP arguments or results. The destination page/application still receives the value, and remote tool metadata/results still traverse the Worker and host. Page source and screenshots can themselves contain secrets. Browser/app tool arguments, source, screenshots, field values, and results are intentionally omitted from operational logs.
80
+ Text and file resources can be injected locally so their contents do not appear in MCP arguments or results. The destination page/application still receives the value, and remote tool metadata/results still traverse the Worker and host. Page source and screenshots can themselves contain secrets. Source/inspection budgets are aggregate across frames, page-controlled metadata is bounded, URL userinfo is removed from semantic snapshots, and contenteditable controls with secret-like identity are treated as sensitive; these limits reduce accidental exposure but do not classify every possible secret. Browser/app tool arguments, source, screenshots, field values, and results are intentionally omitted from operational logs.
81
+
82
+
83
+ ## Shared authorization contract
84
+
85
+ Policy revision 4 is a single source of truth shared by the local daemon and Worker. The catalog availability class controls both advertisement and execution; manager-level checks invoke the same gate as defense in depth. Custom policies are evaluated by capabilities, so a label cannot impersonate `full`. Persistent job start requires both write and direct-execution authority; read-only job/resource inventory does not imply mutation authority.
86
+
87
+ Transport-visible failures use stable error codes and retryability. Unexpected implementation errors are not downgraded to ordinary resource state, and raw internal exceptions are not returned by the Worker. This reduces both authorization drift and accidental disclosure through error strings.
81
88
 
82
89
  ## Filesystem exposure
83
90