machine-bridge-mcp 1.2.7 → 1.2.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.
Files changed (50) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/CONTRIBUTING.md +37 -19
  3. package/README.md +120 -410
  4. package/SECURITY.md +2 -0
  5. package/browser-extension/manifest.json +2 -2
  6. package/docs/ARCHITECTURE.md +13 -4
  7. package/docs/AUDIT.md +22 -0
  8. package/docs/ENGINEERING.md +2 -2
  9. package/docs/OVERVIEW.md +113 -0
  10. package/docs/PROJECT_STANDARDS.md +9 -5
  11. package/docs/RELEASING.md +78 -33
  12. package/docs/TESTING.md +14 -7
  13. package/docs/THREAT_MODEL.md +142 -0
  14. package/package.json +18 -6
  15. package/scripts/check-plan.mjs +91 -0
  16. package/scripts/coverage-check.mjs +22 -0
  17. package/scripts/github-push.mjs +49 -0
  18. package/scripts/github-release.mjs +15 -8
  19. package/scripts/local-release-acceptance.mjs +186 -0
  20. package/scripts/release-acceptance.mjs +181 -0
  21. package/scripts/release-impact-check.mjs +19 -3
  22. package/scripts/release-state.mjs +1 -1
  23. package/scripts/run-checks.mjs +29 -0
  24. package/scripts/start-release-candidate.mjs +113 -0
  25. package/src/local/agent-context-projection.mjs +158 -0
  26. package/src/local/agent-context.mjs +23 -332
  27. package/src/local/agent-skill-discovery.mjs +230 -0
  28. package/src/local/agent-text-file.mjs +41 -0
  29. package/src/local/browser-bridge-http.mjs +48 -0
  30. package/src/local/browser-bridge.mjs +48 -222
  31. package/src/local/browser-broker-routes.mjs +136 -0
  32. package/src/local/browser-broker-server.mjs +59 -0
  33. package/src/local/browser-request-registry.mjs +67 -0
  34. package/src/local/managed-job-lock.mjs +99 -0
  35. package/src/local/managed-job-projection.mjs +68 -0
  36. package/src/local/managed-job-runner.mjs +73 -0
  37. package/src/local/managed-job-storage.mjs +93 -0
  38. package/src/local/managed-jobs.mjs +12 -297
  39. package/src/local/runtime-paths.mjs +107 -0
  40. package/src/local/runtime-relay.mjs +73 -0
  41. package/src/local/runtime-tool-handlers.mjs +66 -0
  42. package/src/local/runtime.mjs +22 -204
  43. package/src/local/windows-launcher.mjs +57 -0
  44. package/src/local/windows-service.mjs +7 -56
  45. package/src/worker/index.ts +9 -118
  46. package/src/worker/mcp-jsonrpc.ts +94 -0
  47. package/src/worker/oauth-authorization-page.ts +70 -0
  48. package/src/worker/oauth-controller.ts +9 -58
  49. package/src/worker/websocket-protocol.ts +24 -0
  50. package/tsconfig.local.json +6 -1
package/SECURITY.md CHANGED
@@ -27,6 +27,8 @@ CodeQL and OpenSSF Scorecard are enforced as gates, not merely uploaded as advis
27
27
 
28
28
  ## Core trust model
29
29
 
30
+ The concise security model is in [docs/THREAT_MODEL.md](docs/THREAT_MODEL.md), including assets, attacker classes, explicit non-goals, and residual risks.
31
+
30
32
  Trusted components are:
31
33
 
32
34
  1. the local OS user running the runtime;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "Machine Bridge Browser",
4
- "version": "1.2.7",
4
+ "version": "1.2.9",
5
5
  "description": "Connects the current Chromium browser profile to the local Machine Bridge runtime for user-authorized automation.",
6
6
  "permissions": [
7
7
  "tabs",
@@ -30,5 +30,5 @@
30
30
  "action": {
31
31
  "default_title": "Machine Bridge Browser"
32
32
  },
33
- "version_name": "1.2.7"
33
+ "version_name": "1.2.9"
34
34
  }
@@ -1,5 +1,7 @@
1
1
  # Architecture
2
2
 
3
+ For a compact component map, read [System overview](OVERVIEW.md). Security assumptions, attacker models, non-goals, and residual risks are defined in [Threat model](THREAT_MODEL.md).
4
+
3
5
  ## Design goal
4
6
 
5
7
  The system separates three questions that are often conflated:
@@ -32,6 +34,11 @@ A canonical workspace receives an independent profile, Worker name, secret set,
32
34
  - `runtime-reporting.mjs` builds privacy-aware runtime and project snapshots;
33
35
  - `runtime-diagnostics.mjs` owns fixed local probes and their stable interpretation;
34
36
  - `runtime-capabilities.mjs` composes agent, application, and browser capability results;
37
+ - `runtime-tool-handlers.mjs` owns catalog-to-handler registration;
38
+ - `runtime-relay.mjs` owns relay construction and inbound envelope normalization;
39
+ - `runtime-paths.mjs` owns runtime-directory creation, containment checks, and error-path redaction;
40
+ - `managed-job-lock.mjs`, `managed-job-runner.mjs`, `managed-job-storage.mjs`, and `managed-job-projection.mjs` separate transition ownership, detached runner identity, private persistence/diagnostics, and public result shaping from the managed-job lifecycle;
41
+ - `browser-request-registry.mjs`, `browser-broker-routes.mjs`, `browser-broker-server.mjs`, and `browser-bridge-http.mjs` separate direct request ownership, runtime-client proxy routing, authenticated loopback WebSocket upgrades/listening, and loopback HTTP handling from broker startup and extension handover;
35
42
  - managed jobs, local resources, application automation, and browser automation remain separate managers.
36
43
 
37
44
  Architecture tests cap the orchestration module and each extracted service independently and reject a return of low-level process, patch, diagnostic, or capability-scoring logic to `LocalRuntime`. `RelayConnection` owns remote WebSocket transport, `hello_ack` authentication, end-to-end `relay_probe`/`ready_ack` readiness, heartbeat liveness, reconnect backoff, outage logging, and a monotonically increasing in-memory session generation. Every relayed tool result is bound to the generation that delivered its call; a disconnected generation cannot send a late result over its replacement socket. Inbound WebSocket dispatch captures that generation at receive time and passes it to the runtime handler, so a successful local tool execution can publish only on the same generation. Stdio mode invokes `LocalRuntime` directly without that adapter.
@@ -40,7 +47,7 @@ Architecture tests cap the orchestration module and each extracted service indep
40
47
 
41
48
  ### Agent context and capability resolver
42
49
 
43
- `AgentContextManager` discovers the nearest Git/workspace scope, applies the user configuration and hierarchical `.machine-bridge/agent.json` files, selects built-in/user/root-to-target instructions, discovers bounded filesystem skills, and resolves registered commands. `agent-contract.mjs` is the strict checked-JavaScript boundary for configuration shape, registered-command normalization, encoded-size limits, and configured-path containment; the manager does not maintain a second parser. `project-package.mjs` owns no-follow package metadata parsing, package-manager selection (including fail-closed conflicting-lockfile handling), script-name normalization, bounded workflow-intent aliases, and automatic `package.*` command construction so instruction rendering and command execution do not duplicate package parsing. `default-instructions.mjs` supplies a versioned in-package working-agreement block and derives a small virtual project-context block from root filenames and bounded metadata. It reads package script names but not bodies, does not inspect dependency values or source contents, executes nothing, and writes no user/repository files. A global `model_instructions_file` is a separate user-designated session source and cannot be overridden by a project.
50
+ `AgentContextManager` discovers the nearest Git/workspace scope, applies the user configuration and hierarchical `.machine-bridge/agent.json` files, selects built-in/user/root-to-target instructions, discovers bounded filesystem skills, and resolves registered commands. `agent-context-projection.mjs` owns capability fingerprints, privacy-aware public projections, bounded skill summaries, command rendering, and effective-instruction rendering. `agent-skill-discovery.mjs` owns bounded skill-root traversal, symlink containment, metadata parsing, warnings, and file inventory; `agent-text-file.mjs` owns no-follow bounded UTF-8 reads. Filesystem/config discovery no longer maintains those output and skill-scanning mechanics inline. `agent-contract.mjs` is the strict checked-JavaScript boundary for configuration shape, registered-command normalization, encoded-size limits, and configured-path containment; the manager does not maintain a second parser. `project-package.mjs` owns no-follow package metadata parsing, package-manager selection (including fail-closed conflicting-lockfile handling), script-name normalization, bounded workflow-intent aliases, and automatic `package.*` command construction so instruction rendering and command execution do not duplicate package parsing. `default-instructions.mjs` supplies a versioned in-package working-agreement block and derives a small virtual project-context block from root filenames and bounded metadata. It reads package script names but not bodies, does not inspect dependency values or source contents, executes nothing, and writes no user/repository files. A global `model_instructions_file` is a separate user-designated session source and cannot be overridden by a project.
44
51
 
45
52
  `session_bootstrap` is requested during both stdio and remote MCP initialization. The Worker delegates this read to the connected daemon with a short bounded timeout; failure falls back to static server instructions rather than blocking initialization indefinitely. `resolve_task_capabilities` performs a fresh deterministic scan, rebuilds automatic project facts, and ranks skill/command metadata for the current task. Application and browser capability metadata is added by `LocalRuntime`; installed application inventory uses a short bounded cache. `CapabilityObserver` records only counts, timestamps, source flags, selected metadata, match counts, recommended tool names, and a runtime-keyed task fingerprint so operators can verify routing without creating a task-content log.
46
53
 
@@ -103,7 +110,7 @@ All requests for a deployed Worker route to one named Durable Object. It owns:
103
110
  - policy/tool metadata attached to the active socket;
104
111
  - a bounded in-memory map of pending daemon calls.
105
112
 
106
- `BridgeRoom` owns Durable Object routing, MCP dispatch, daemon WebSocket lifecycle, and pending relay calls. `OAuthController` owns OAuth-store pruning, registration throttling, authorization pages/submission, account-admin routing, token exchange, access-token verification, and the serialization queue for OAuth mutations. Worker-internal TypeScript imports use explicit `.ts` specifiers and JSON import attributes, so the same modules are directly executable under the pinned Node runtime for focused state-machine tests as well as bundled by Wrangler.
113
+ `BridgeRoom` owns Durable Object routing, MCP dispatch, daemon WebSocket lifecycle, and pending relay calls. `mcp-jsonrpc.ts` owns JSON-RPC shape validation, result/error framing, MCP tool-result projection, session-instruction bounds, and protocol-header validation. `websocket-protocol.ts` owns record validation plus best-effort send/close/rejection helpers. `OAuthController` owns OAuth-store pruning, registration throttling, authorization submission, account-admin routing, token exchange, access-token verification, and the serialization queue for OAuth mutations. `oauth-authorization-page.ts` owns escaped authorization-page rendering and redirect-origin CSP input. Worker-internal TypeScript imports use explicit `.ts` specifiers and JSON import attributes, so the same modules are directly executable under the pinned Node runtime for focused state-machine tests as well as bundled by Wrangler.
107
114
 
108
115
  The Worker verifies OAuth, validates MCP envelopes and optional protocol headers, converts `tools/call` into WebSocket messages, correlates cancellation by access-token hash and JSON-RPC ID, and formats text/structured/image results. Pending calls also bind the incoming request `AbortSignal`: an HTTP client disconnect removes the pending indexes and sends a best-effort daemon cancellation. The deployment contract explicitly enables Cloudflare `enable_request_signal` and `request_signal_passthrough` so the signal reaches the named Durable Object. It has no local filesystem or process API.
109
116
 
@@ -255,9 +262,11 @@ Cloudflare sampling is size control rather than an audit log. The project intent
255
262
 
256
263
  ## Release integrity
257
264
 
258
- Repository-local checks are necessary but cannot prove behavior on every supported operating system. `scripts/github-release.mjs` therefore queries `.github/workflows/ci.yml` for the exact `origin/main` commit and requires the newest push-triggered run to be completed with `success` before it creates or verifies a version tag, GitHub Release, or package asset. Pull-request runs, older successful runs, pending runs, and successful runs for another SHA do not satisfy the gate. The selection policy is isolated in `scripts/release-ci.mjs` and tested independently.
265
+ Repository-local automated checks are necessary but cannot prove that the maintainer's ordinary installation path works. `scripts/local-release-acceptance.mjs` builds the exact npm tarball, while `scripts/start-release-candidate.mjs` installs that tarball into an ignored isolated prefix and starts it in the foreground. The helper requires `--allow-worker-deploy` because normal startup may update the configured same-name Worker before relay verification. The repository owner starts the candidate; the coding agent verifies its live Worker version/hash, health, relay connection, local version, readiness, and representative behavior through Machine Bridge before recording both npm hashes outside the package. `scripts/github-push.mjs`, pull-request CI, and `scripts/github-release.mjs` rebuild the package and reject any mismatch. The release helper also requires `HEAD === origin/main`; it cannot silently push `main`.
266
+
267
+ Cross-platform evidence remains independent. `scripts/github-release.mjs` queries CI, CodeQL, Governance, and Scorecard for the exact `origin/main` commit and requires the newest push-triggered run for each workflow to be completed with `success` before it creates or verifies a version tag, GitHub Release, or package asset. Pull-request runs, older successful runs, pending runs, and successful runs for another SHA do not satisfy the gate. The workflow selection policy is isolated in `scripts/release-ci.mjs` and tested independently.
259
268
 
260
- Third-party workflow actions are pinned to immutable commit SHAs. Dependabot proposes reviewed SHA updates, and `architecture:test` rejects a return to movable action tags or removal of the reachable-history package-audit step.
269
+ Third-party workflow actions are pinned to immutable commit SHAs. Dependabot groups GitHub Action updates into one reviewed PR so coupled action families cannot drift across versions. `architecture:test` rejects movable action tags, split update policy, loss of local acceptance verification, or removal of the reachable-history package-audit step.
261
270
 
262
271
  ## Explicit non-goals
263
272
 
package/docs/AUDIT.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Security and privacy audit notes
2
2
 
3
+ ## 2026-07-18 version 1.2.9 interactive release-handoff correction
4
+
5
+ The release-integrity mechanism correctly bound acceptance to exact package bytes, but the operational role split was wrong. Documentation and repository guards required the owner to run the acceptance command personally and prohibited the coding agent from recording it. That contradicted the established working process: the owner should perform the one action the agent cannot perform honestly—start the exact candidate on the maintainer machine—while the agent should connect to that candidate, verify its version, readiness, and representative functionality, then record acceptance and complete source release operations.
6
+
7
+ Version 1.2.9 codifies that flow. `npm run release:candidate:start -- --allow-worker-deploy` verifies and installs the pending tarball into an ignored isolated prefix and launches it in the foreground without replacing the normal global installation. The explicit flag acknowledges that normal candidate startup may update the configured same-name Worker in place. The owner runs that command and leaves the process active. The coding agent must observe the live candidate through Machine Bridge; automated checks or an unobserved process are insufficient. After successful observation, the agent records the new `owner-started-agent-verified-local-candidate` marker, commits, pushes through the guarded command, completes the pull request, and runs `npm run release` to create or verify the annotated tag and GitHub Release. The old 1.2.8 owner-recorded marker remains accepted only for historical compatibility.
8
+
9
+ npm publication and Worker deployment remain owner-operated live release actions. The coding agent does not perform either as part of `npm run release`. Any packaged-byte change after candidate preparation invalidates the pending or recorded acceptance and requires another owner-started, agent-observed candidate run.
10
+
11
+ The first PR run exposed two release-infrastructure defects that local macOS validation could not certify. The layered runner spawned `npm.cmd` directly and failed with `EINVAL` under Node 26 on Windows; it now executes the integrity-pinned npm CLI through the current Node binary on every platform. The acceptance recorder also omitted the portable Git-content digest required by CI. It now constructs a temporary Git index from `HEAD` plus the complete working tree, computes the same canonical package digest used by CI, deletes the temporary index without changing the maintainer staging area, and makes local acceptance verification reject a missing digest. Both failures invalidate the earlier candidate and require a regenerated, re-observed candidate before release.
12
+
13
+ ## 2026-07-17 version 1.2.8 release-integrity and dependency-automation audit
14
+
15
+ The core failure was procedural rather than a missing unit test: the repository treated a green automated suite as sufficient evidence for source publication, and `release:publish` could push a locally tested commit directly to `main`. That model cannot satisfy the reported history of formally released builds failing on the maintainer's real installation. It also assigned the coding agent authority to infer release acceptance, even though only the repository owner can observe the ordinary local environment and decide whether the product is usable.
16
+
17
+ Version 1.2.8 separates automated verification from owner acceptance. The candidate command runs the full suite and packs the exact artifact. The owner tests that tarball and records a fixed confirmation; a second pack must have identical npm SHA-1 and SHA-512 integrity before the tracked record is written. The record is outside the package manifest, so adding it and squash-merging do not alter the accepted bytes. Any packaged source, script, metadata, browser-extension, or shipped-documentation change invalidates the record. The guarded push command checks cleanliness, branch safety, tracking, and package hashes. CI repeats the hash check. Final release creation requires the same acceptance plus exact-commit CI, CodeQL, Governance, and Scorecard success, and it no longer contains a path that pushes `main`. The acceptance record is a reviewed process assertion, not a cryptographic identity signature; automation is explicitly prohibited from creating it on the owner's behalf.
18
+
19
+ The five open Dependabot PRs exposed a second design defect. The three CodeQL sub-actions were proposed independently even though CodeQL rejects mixed action versions, while every Action-only PR was forced through an npm release-impact gate that considered all repository files package changes. The combined update now keeps all CodeQL components on 4.37.1, updates setup-node to 7.0.0 and upload-artifact to 7.0.1, groups future GitHub Action updates, and derives npm release relevance from the package manifest. GitHub-only workflow maintenance can therefore be reviewed without inventing an npm version, while package content remains fail-closed. Official tag objects were resolved through GitHub and match every pinned SHA. The setup-node and upload-artifact majors move their action runtimes to Node 24/ESM without changing the inputs used here; CodeQL 4.37.1 advances the default bundle to 2.26.1. Architecture tests now require all three CodeQL action roles to share one immutable commit even if dependency automation regresses.
20
+
21
+ The broader pass rechecked dependency health, install-script policy, package contents, release scripts, workflow permissions, immutable Action pinning, source and test size guardrails, process/network boundary inventory, privacy scanning, documentation ownership, and existing architecture limits. Both complete and production npm audits report zero vulnerabilities, the dependency tree reports no structural problems, and Wrangler's only available patch was advanced to 4.112.0 with the exact new workerd install script reviewed and allowlisted. No credential-like tracked artifact beyond the deliberate non-secret repository `.npmrc` was found. Existing execution, relay, browser, state, ACL, logging, and lifecycle behavior remains covered by the prior risk-directed suites; this change does not claim OS CPU/memory/network isolation that the runtime does not implement.
22
+
23
+ No branch, tag, GitHub Release, npm package, Worker deployment, global installation, daemon/service replacement, credential change, or live state mutation is performed before the repository owner tests and accepts the 1.2.8 candidate.
24
+
3
25
  ## 2026-07-17 version 1.2.7 process-supervision and lifecycle audit
4
26
 
5
27
  The core question in this review was not whether the existing green suite covered many paths; it was whether failure and ownership boundaries remained truthful when processes resist termination, startup is interrupted, proxy state is hostile, or the operating system refuses a spawn. The audit found that generic argv validation and process-tree termination had drifted into the interactive-session module, while shell and managed-job paths maintained adjacent termination branches. This created a dependency inversion: one-shot execution and process accounting depended on an adapter whose responsibility should have been only interactive session state.
@@ -9,7 +9,7 @@ This document records project-wide decisions that must survive individual fixes,
9
9
  3. **Machine Bridge authority and host authority are separate.** `full` removes Machine Bridge's own policy, path, shell, and environment restrictions. It cannot override an MCP host, connector gateway, operating system, endpoint-security product, cloud IAM, remote authentication, or `sudo`.
10
10
  4. **Publication surfaces contain no real environment metadata.** Source, tests, fixtures, examples, release notes, filenames, package contents, tags, and release assets use synthetic identifiers and reserved example domains.
11
11
  5. **Secrets are never operational log data.** Tool arguments, command text, stdin, stdout, stderr, file content, OAuth bodies, credentials, and local resource values are not logged.
12
- 6. **A release is one version with successful cross-platform evidence.** Package metadata, Worker version, browser-extension version/name, Git tag, GitHub Release, npm version, documentation, and deployed health version must agree, and the exact `origin/main` commit must have completed successful push-triggered CI, CodeQL, Governance, and OpenSSF Scorecard runs before a tag or release is created.
12
+ 6. **A release is one owner-started, agent-verified package with successful cross-platform evidence.** The repository owner starts the exact npm candidate on the maintainer machine; the coding agent verifies the connected candidate version, readiness, and representative functionality through Machine Bridge and then records the package hashes before the first GitHub push. Package metadata, Worker version, browser-extension version/name, acceptance record, Git tag, GitHub Release, npm version, documentation, and deployed health version must agree, and the exact `origin/main` commit must have completed successful push-triggered CI, CodeQL, Governance, and OpenSSF Scorecard runs before a tag or release is created.
13
13
  7. **Generic local automation is structured, not arbitrary evaluation.** Browser/application features may expose broad user authority under canonical `full`, but must not accept caller-provided JavaScript, AppleScript, JXA, or extension code.
14
14
  8. **Daily-browser integration uses the existing profile.** The supported primary browser path is the packaged authenticated extension and machine-level loopback broker, preserving current tabs/login state; a separate automation profile is not an equivalent replacement.
15
15
  9. **Pairing and resource secrets are not conversation or log data.** Tokens and injected local-resource values must not be returned, embedded in URLs, or written to operational logs.
@@ -24,7 +24,7 @@ A proposed change that conflicts with an invariant requires an explicit owner de
24
24
 
25
25
  ## Change and release-operation ownership
26
26
 
27
- Repository source release completion and live release operations are separate responsibilities. Under the standing repository contract in `AGENTS.md`, coding automation may edit source, tests, documentation, package metadata, and changelog entries; run repository-local checks; commit and push; complete the reviewed pull request through local `git`/`gh`; and create the annotated version tag plus final GitHub Release only after the exact `main` commit passes push-triggered CI. It must not publish, deprecate, or unpublish npm packages; install the package globally; deploy or reconfigure a Cloudflare Worker; rotate credentials; mutate live deployment state; or start/stop/install/remove the daemon or autostart service without explicit user authorization.
27
+ Repository implementation, interactive candidate acceptance, source release completion, and live release operations are separate responsibilities. Under `AGENTS.md`, coding automation may edit, test, and commit locally, generate an exact candidate tarball, and give the owner `npm run release:candidate:start -- --allow-worker-deploy`. The owner explicitly authorizes the in-place update of the configured same-name Worker, starts that candidate, and leaves it running. The agent verifies the deployed Worker version/hash, remote health, relay readiness, and connected local candidate through Machine Bridge and may then record `release-acceptance/v<version>.json`, push only through `npm run github:push`, complete the pull request through local `git`/`gh`, and create the annotated version tag plus final GitHub Release with `npm run release` after the accepted package hash and exact `main` checks pass. Automated checks without an observed live candidate do not authorize acceptance. `npm run release` never pushes `main`. Automation must not publish or alter npm packages, install globally outside the isolated candidate prefix, deploy or reconfigure a Worker as a release operation, rotate credentials, mutate live deployment state, or replace daemon/service state without explicit user authorization.
28
28
 
29
29
  The normal handoff is: the repository owner publishes the reviewed npm version, then runs `npm install -g --omit=optional --allow-scripts=esbuild,workerd,sharp,fsevents machine-bridge-mcp@latest && machine-mcp`. The npm command updates the global CLI but cannot hot-reload an existing Node process. The subsequent normal foreground startup validates the Worker deployment hash, expected version, and health, requests shutdown of an active autostart daemon, waits a bounded interval for its lock, redeploys when necessary, and then takes over with the installed version. Live operations require explicit authorization even when they appear to be the obvious next release step.
30
30
 
@@ -0,0 +1,113 @@
1
+ # System overview
2
+
3
+ Machine Bridge is one local authority surface with two MCP transports. The architecture is organized around three independent questions:
4
+
5
+ 1. **Who may request an operation?** Remote OAuth account identity and role, or the local process identity that launched stdio.
6
+ 2. **Which tools are exposed?** The shared tool catalog, policy profile, and account-role intersection.
7
+ 3. **What can an exposed tool actually do?** The local runtime, workspace/path rules, operating-system user authority, and platform security controls.
8
+
9
+ Transport authentication does not create an operating-system sandbox. The local daemon executes with the authority of its OS user.
10
+
11
+ ## Components
12
+
13
+ ```mermaid
14
+ flowchart LR
15
+ HC[Hosted MCP client] -->|HTTPS + OAuth 2.1 / PKCE| W[Cloudflare Worker]
16
+ W --> DO[Durable Object room]
17
+ DO -->|Authenticated outbound WebSocket| R[LocalRuntime]
18
+
19
+ LC[Local MCP client] -->|stdio| S[stdio adapter]
20
+ S --> R
21
+
22
+ R --> PG[PolicyGate + account access]
23
+ PG --> TE[ToolExecutor]
24
+ TE --> FS[Workspace file service]
25
+ TE --> PS[Process services]
26
+ TE --> MJ[Managed jobs]
27
+ TE --> AC[Agent context]
28
+ TE --> BA[Browser/app automation]
29
+
30
+ BA --> BB[Loopback browser broker]
31
+ BB --> EX[Packaged Chromium extension]
32
+
33
+ R --> OS[Local OS user authority]
34
+ MJ --> ST[Owner-only local state]
35
+ ```
36
+
37
+ ## Authority flow
38
+
39
+ ### Remote transport
40
+
41
+ 1. The Worker validates OAuth client, token, account state, role, resource binding, and MCP session state.
42
+ 2. The Worker filters advertised tools by account role and the daemon-reported capability ceiling.
43
+ 3. The Durable Object relays a bounded tool envelope over the authenticated daemon socket.
44
+ 4. The local runtime revalidates account authorization, policy, call lifecycle, timeout, and cancellation.
45
+ 5. The selected local service executes with the daemon OS user's authority.
46
+
47
+ The Worker never receives ambient filesystem or process authority. It receives only explicit request/result messages.
48
+
49
+ ### Local stdio transport
50
+
51
+ The MCP host launches the package as a subprocess. There is no remote OAuth layer. The selected local policy still controls catalog exposure and execution, while the OS process identity supplies the underlying filesystem and process authority.
52
+
53
+ ## Shared contracts
54
+
55
+ The main protocol and policy single sources of truth are:
56
+
57
+ - `src/shared/tool-catalog.json` — tool names, schemas, policy requirements, and annotations;
58
+ - `src/shared/policy-contract.json` — canonical profiles and capability composition;
59
+ - `src/shared/server-metadata.json` — server identity and protocol metadata.
60
+
61
+ Local and Worker code consume these contracts. Generated references and drift tests prevent documentation and implementation from silently diverging.
62
+
63
+ ## Local runtime boundaries
64
+
65
+ `LocalRuntime` is an orchestrator, not a low-level implementation module. It composes:
66
+
67
+ - policy and account authorization;
68
+ - call registration, timeout, cancellation, and observability;
69
+ - workspace and path services;
70
+ - direct and shell process execution;
71
+ - Git operations;
72
+ - managed jobs and local resources;
73
+ - Agent context and capability resolution;
74
+ - application and browser automation;
75
+ - remote relay adaptation.
76
+
77
+ Low-level responsibilities remain in focused modules. Architecture tests enforce an acyclic local import graph, domain/adapter direction, and module-size budgets. Behavior and fault-injection tests remain authoritative; source-shape checks are supplementary.
78
+
79
+ ## State and lifecycle
80
+
81
+ Each canonical workspace has independent profile state, Worker identity, credentials, locks, service metadata, and managed jobs. State mutations use owner-only files where supported, bounded reads, atomic replacement, and process-identity-aware locks.
82
+
83
+ The relay distinguishes connectivity, authentication, readiness probing, and active service. A candidate daemon must complete an end-to-end probe before replacing an incumbent. Disconnect cancels relay-owned calls and terminates associated local processes.
84
+
85
+ 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.
86
+
87
+ ## Browser execution model
88
+
89
+ The local browser broker binds only to loopback and authenticates the packaged extension with local pairing state and a versioned capability handshake. Additional runtime processes may proxy through the machine-level broker rather than opening competing extension connections.
90
+
91
+ The extension controls the Chromium profile into which it is loaded. Machine Bridge does not launch, isolate, or prove the identity of that profile. Browser cookies, sessions, tabs, and page content therefore remain part of the local user's browser authority.
92
+
93
+ ## Verification layers
94
+
95
+ The repository uses several complementary layers:
96
+
97
+ - unit and behavior tests for policy, parsing, state, lifecycle, and services;
98
+ - fault injection and property tests for security-sensitive boundaries;
99
+ - live stdio and Worker/OAuth/MCP integration tests;
100
+ - cross-platform service and installation tests;
101
+ - per-module critical coverage thresholds;
102
+ - architecture/import/line-budget checks;
103
+ - privacy, package, release-impact, interactive-candidate-acceptance, CodeQL, dependency, and Scorecard gates.
104
+
105
+ `npm run check:fast` is the development feedback loop. `npm run check` runs the complete release-relevant suite.
106
+
107
+ ## Read next
108
+
109
+ - [Architecture](ARCHITECTURE.md) for detailed invariants and protocol flow
110
+ - [Threat model](THREAT_MODEL.md) for assets, attackers, non-goals, and residual risks
111
+ - [Security policy](../SECURITY.md) for reporting and supported security boundaries
112
+ - [Engineering](ENGINEERING.md) for implementation rules
113
+ - [Testing](TESTING.md) for verification design
@@ -18,11 +18,15 @@ 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
21
+ ### Completion ownership and local acceptance
22
22
 
23
- Repository automation owns the complete source-change lifecycle. After required checks pass, it updates the pull-request branch when necessary, squash-merges through local `gh`, verifies the resulting `main` commit, and removes the merged branch. A completed change must not remain indefinitely as an open pull request.
23
+ Repository automation owns implementation, local validation, observed candidate verification, acceptance recording, and pull-request completion. For every npm-package change, automation generates the exact candidate tarball with `npm run release:candidate` and stops before the first GitHub push. The repository owner explicitly authorizes the live candidate Worker update and runs `npm run release:candidate:start -- --allow-worker-deploy` on the maintainer machine and leaves the candidate running. The coding agent verifies the deployed Worker version/hash, remote health, relay readiness, connected local version, and representative functionality through Machine Bridge, then records a passing decision with `npm run release:accept -- --confirm "I VERIFIED machine-bridge-mcp <version> CANDIDATE ON THE OWNER MACHINE AND IT WORKS"`. Automated checks or an unobserved process are not sufficient evidence.
24
24
 
25
- Every release-relevant change advances the package version and is completed by an annotated `v<version>` tag plus a final GitHub Release for the exact successful `main` commit. The coding agent performs that tag and GitHub Release work by default through local `git`, `gh`, and `gh api`; repeated per-task authorization is not required. npm publication, Worker deployment, credential mutation, global installation, and daemon/service replacement remain separate live operations requiring explicit authorization.
25
+ The tracked `release-acceptance/v<version>.json` record binds the observed result to the npm tarball SHA-1 and SHA-512 integrity value. The record is excluded from the package, so a content-preserving squash merge does not invalidate it; any source, executable script, package metadata, or packaged-documentation change produces a different package hash and requires a regenerated candidate and another observed live verification. `npm run github:push`, pull-request CI, and `npm run release` verify the record. Raw direct pushes of release-relevant branches are prohibited.
26
+
27
+ After interactive acceptance, repository automation may push only through `npm run github:push`, open and complete the pull request, verify the resulting `main` commit, remove the merged branch, and run `npm run release`. Every npm-package change advances the package version and is completed by an annotated `v<version>` tag plus a final GitHub Release for the exact successful `main` commit. GitHub-only repository infrastructure changes that do not alter npm package contents do not require a synthetic npm version or local runtime acceptance, but they still require review and their applicable CI/security checks.
28
+
29
+ The coding agent performs the acceptance-record, tag, and GitHub Release work only after observed live verification and exact-commit checks succeed. npm publication, Worker deployment, credential mutation, non-isolated global installation, and daemon/service replacement remain separate live operations performed by the repository owner.
26
30
 
27
31
  ### Local GitHub control plane
28
32
 
@@ -115,10 +119,10 @@ Flaky tests are defects. A retry may diagnose environmental instability but may
115
119
  ## 7. Security and software supply chain
116
120
 
117
121
  - GitHub workflow permissions default to read-only and are expanded per job only when required.
118
- - Third-party Actions are pinned to immutable commit SHAs and reviewed when Dependabot updates them.
122
+ - Third-party Actions are pinned to immutable commit SHAs and reviewed when Dependabot updates them. GitHub Action updates are grouped into one atomic pull request so coupled suites such as CodeQL cannot be split across incompatible versions.
119
123
  - npm dependencies use exact versions and a committed lockfile. Source bootstrap uses `npm ci`; the CI npm baseline itself is downloaded from an exact URL and verified against a pinned SHA-512 SRI before use. Registry signatures and attestations are verified in CI.
120
124
  - Dependency review blocks newly introduced vulnerable dependencies. CodeQL performs JavaScript/TypeScript and workflow analysis. OpenSSF Scorecard audits supply-chain posture, and both SARIF streams are failing gates with exact, expiring exceptions rather than advisory-only uploads.
121
- - CI generates and validates a CycloneDX SBOM. Release artifacts must be reproducible from a reviewed commit and tied to successful exact-commit CI, CodeQL, Governance, and Scorecard evidence.
125
+ - CI generates and validates a CycloneDX SBOM. Release artifacts must match the repository-owner-tested tarball hash, be reproducible from a reviewed commit, and be tied to successful exact-commit CI, CodeQL, Governance, and Scorecard evidence.
122
126
  - Secret scanning and push protection are enabled. Repository examples use synthetic identities and reserved domains; reachable history is scanned before release.
123
127
  - Long-lived publication tokens should be replaced by npm trusted publishing with GitHub OIDC. Until that external registry configuration is completed, release credentials remain an explicit operator responsibility and must never be stored in the repository.
124
128
  - Security reports follow [SECURITY.md](../SECURITY.md), not public issue templates.
package/docs/RELEASING.md CHANGED
@@ -2,58 +2,105 @@
2
2
 
3
3
  The release invariant is:
4
4
 
5
- - `main` points to the release commit, and the exact commit has a completed successful push-triggered `.github/workflows/ci.yml` run.
6
- - `v<package version>` points to that same commit locally and on GitHub.
7
- - A final GitHub Release exists for the tag.
8
- - The GitHub Release contains the npm tarball generated from that commit.
9
- - `package.json`, `package-lock.json`, the Worker-reported version, and `browser-extension/manifest.json` (`version`/`version_name`) agree.
10
- - Every release-relevant change since the prior version tag has a higher package version and matching CHANGELOG section.
11
- - The same reviewed change is present on GitHub and in a new npm version.
5
+ - the repository owner started the exact npm tarball represented by `release-acceptance/v<version>.json` on the maintainer machine, and the coding agent observed the live candidate through Machine Bridge before recording a passing result;
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.
12
13
 
13
- `npm publish` runs `release:check` through `prepublishOnly`, so npm publication is blocked until all GitHub state is synchronized.
14
+ A green automated suite is necessary but is not evidence that the maintainer's ordinary installation path works. The repository therefore separates automated validation from observed live candidate verification and binds both to the final package bytes.
14
15
 
15
- ## Default automation responsibility
16
+ ## Change classification
16
17
 
17
- For every reviewed release-relevant change, repository automation completes the source release without requiring the owner to repeat the instruction: it merges the pull request, waits for successful push-triggered CI on the exact `main` commit, creates and pushes the annotated version tag, creates or updates the final GitHub Release, uploads the generated npm tarball, and verifies that all references identify the same commit. These GitHub operations use only local `git`, `gh`, and `gh api` through Machine Bridge.
18
+ A change is **npm-package relevant** when it alters `package.json`, `package-lock.json`, or a path included by the package `files` manifest. Source, runtime scripts, browser extension files, shared contracts, shipped documentation, and package metadata therefore require a new version and local acceptance.
18
19
 
19
- This standing responsibility does not authorize npm publication, Cloudflare Worker deployment, credential changes, global package installation, or local daemon/service replacement. Those operations change a registry or live machine and require explicit authorization.
20
+ A repository-only change under paths such as `.github/` may be merged without a synthetic npm version when the package bytes are unchanged. It still requires review and all applicable GitHub checks. `scripts/release-impact-check.mjs` implements this distinction from the package manifest rather than from a duplicated path list.
20
21
 
21
- ## Prepare a version
22
+ ## Prepare the candidate locally
22
23
 
23
- 1. Set the new version without creating an automatic npm tag. The npm version hook synchronizes the Worker and packaged browser-extension versions:
24
+ 1. Set the new version without creating a tag. The npm version hook synchronizes the Worker and browser-extension versions:
24
25
 
25
26
  ```sh
26
27
  npm version <version> --no-git-tag-version
27
28
  ```
28
29
 
29
- 2. Add the matching dated `CHANGELOG.md` section.
30
- 3. Run `npm run release-impact:check`, `npm run privacy:check`, review `npm run privacy:history`, run `npm run check`, both dependency audits, `npm audit signatures`, and generate a CycloneDX `npm sbom`.
31
- 4. Inspect the complete diff and `npm pack --dry-run`, including packaged file modes and every helper referenced by package scripts, then commit and push all release changes to `main`. Wait for the push-triggered Linux/macOS/Windows and package-audit checks to complete successfully.
30
+ 2. Add the matching dated `CHANGELOG.md` section and update affected documentation and audit notes.
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:
32
34
 
33
- A privacy/security documentation correction is not “docs only” for release purposes. It requires a replacement npm version and, when appropriate, deprecation or unpublication of the affected version.
35
+ ```sh
36
+ npm run release:candidate
37
+ ```
34
38
 
35
- ## Publish GitHub source and release
39
+ `release:candidate` runs the complete repository suite and then writes the exact npm tarball plus a bounded pending manifest under ignored `.release-candidate/`. Do not modify a packaged file after generating the candidate without regenerating and retesting it.
36
40
 
37
- From a clean `main` worktree:
41
+ ## Interactive local candidate acceptance
42
+
43
+ The repository owner starts the exact `.release-candidate/*.tgz` artifact on the maintainer machine with:
38
44
 
39
45
  ```sh
40
- npm run release:publish
46
+ npm run release:candidate:start -- --allow-worker-deploy
41
47
  ```
42
48
 
43
- The command validates the project, including repository privacy checks, fast-forwards `origin/main` when needed, then requires the latest push-triggered CI run for that exact commit to be completed successfully before it creates or verifies the annotated version tag. It then pushes the tag, builds the npm tarball, creates or updates the GitHub Release, uploads the tarball, and verifies the resulting state. Read-only GitHub operations, Git pushes, and idempotent release updates use bounded retries only for classified transient network failures; ambiguous Release creation responses are resolved by querying server state before continuing.
49
+ This command verifies the pending tarball hashes, installs it into the ignored `.release-candidate/runtime/` prefix without replacing the normal global installation, explicitly authorizes startup to update the configured same-name Worker when its version or deployment hash differs, and starts the installed candidate in the foreground. This is an in-place live candidate deployment, not an isolated staging Worker. The owner leaves that process running. The coding agent then connects through Machine Bridge and verifies at minimum:
50
+
51
+ - the remote Worker reports the candidate version and the persisted deployment hash matches the candidate Worker bundle;
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.
44
57
 
45
- To verify without changing anything:
58
+ The owner does not run the acceptance command. After the coding agent has observed the live candidate passing those checks, the agent records the decision using the exact phrase printed by `release:candidate`, for example:
59
+
60
+ ```sh
61
+ npm run release:accept -- --confirm "I VERIFIED machine-bridge-mcp 1.2.9 CANDIDATE ON THE OWNER MACHINE AND IT WORKS"
62
+ ```
63
+
64
+ This creates `release-acceptance/v<version>.json` containing package identity, npm tarball hashes, a portable Git-content digest, timestamp, result, and a fixed observed-verification marker. The portable digest is computed with a temporary Git index containing `HEAD` plus the complete working tree; the real staging area is not modified. The record does not store a personal name, machine path, command output, credential, or user content. It is intentionally excluded from the npm package, so adding it does not change the tested tarball.
65
+
66
+ The command repacks the current tree and refuses to record acceptance if any packaged byte changed after candidate preparation. Automated tests alone, a prepared tarball, a process the agent did not observe, or an ambiguous owner response do not authorize acceptance. Version 1.2.8 owner-recorded acceptance remains supported as a historical marker; version 1.2.9 and later require the owner-started, agent-observed workflow.
67
+
68
+ ## Push and review
69
+
70
+ Commit the candidate changes and acceptance record, then push the branch only through:
71
+
72
+ ```sh
73
+ npm run github:push
74
+ ```
75
+
76
+ The command requires a clean non-`main` branch, verifies that the acceptance record is tracked, rebuilds the npm package, compares both hashes, and only then executes a non-force push of the current branch. Direct pushes to `main` remain prohibited. Any packaged-file change after acceptance invalidates the hash and blocks the next push until the owner retests a regenerated candidate.
77
+
78
+ Open a pull request, satisfy the required checks, and squash-merge. Pull-request CI repeats the acceptance verification. A content-preserving squash changes the Git commit but not the package bytes, so the accepted hash remains valid.
79
+
80
+ ## Complete the GitHub source release
81
+
82
+ From a clean, fast-forwarded `main` worktree whose `HEAD` exactly equals `origin/main`:
83
+
84
+ ```sh
85
+ npm run release
86
+ ```
87
+
88
+ `npm run release` never pushes `main`. `release:publish` remains a compatibility alias. It verifies the interactive candidate acceptance, runs the complete project and version checks, requires successful exact-commit push runs for CI, CodeQL, Governance, and Scorecard, creates or verifies the annotated version tag, pushes only the version tag when absent, builds the npm tarball, creates or updates the final GitHub Release, uploads the tarball, and verifies the resulting state.
89
+
90
+ To verify an already completed source release without changing anything:
46
91
 
47
92
  ```sh
48
93
  npm run release:check
49
94
  ```
50
95
 
51
- To create GitHub Release records for existing remote version tags that lack releases:
96
+ To create GitHub Release records for historical remote tags that lack releases:
52
97
 
53
98
  ```sh
54
99
  npm run release:backfill
55
100
  ```
56
101
 
102
+ Backfill is historical metadata repair. It does not retroactively claim that releases predating the 1.2.8 acceptance policy had a recorded local acceptance.
103
+
57
104
  ## Publish npm
58
105
 
59
106
  Only after `release:check` succeeds:
@@ -62,18 +109,16 @@ Only after `release:check` succeeds:
62
109
  npm publish --access public
63
110
  ```
64
111
 
65
- The npm lifecycle repeats the full project checks and the GitHub synchronization check before upload. Do not leave a code or documentation fix only on GitHub; the corresponding npm version must be published, and the operator should be explicitly reminded until registry publication is confirmed.
66
-
67
- ## Authentication requirements
112
+ `prepublishOnly` repeats the complete checks and GitHub synchronization check. npm publication remains a deliberate release-operator action and is not authorized by an ordinary source change.
68
113
 
69
- - Git push access to `origin`.
70
- - An authenticated GitHub CLI session with repository release permission.
71
- - An npm account that owns the package or has maintainer permission.
114
+ ## Authentication and external controls
72
115
 
73
- GitHub Actions is a required publication boundary. The authenticated GitHub CLI must be able to read Actions runs, and a missing, pending, cancelled, skipped, or failed exact-commit push run blocks both `release:publish` and `release:check`. This prevents a machine-specific local pass from publishing a version that fails another supported platform.
116
+ Required local access:
74
117
 
75
- ## Registry publication hardening
118
+ - Git push access to `origin` for the accepted branch and version tag;
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.
76
121
 
77
- The preferred target is npm trusted publishing from a narrowly scoped GitHub Actions release workflow using OIDC and a protected GitHub environment. This removes the need for a long-lived npm publication token and allows npm to generate provenance automatically. Enabling it requires an explicit package-owner configuration in npm and a reviewed change to the release workflow; repository code alone cannot complete that trust relationship.
122
+ GitHub Actions remains a required cross-platform boundary. Missing, pending, cancelled, skipped, failed, pull-request-only, stale, or wrong-commit runs do not satisfy release publication. Observed local candidate acceptance and successful GitHub checks are complementary evidence; neither substitutes for the other.
78
123
 
79
- Until trusted publishing is configured, publication remains a deliberate local operator step after `release:check`. Do not add an npm token to repository or environment files, workflow YAML, logs, or local project notes. Restrict any fallback token to the shortest practical lifetime and minimum package scope.
124
+ The preferred registry target remains npm trusted publishing from a narrowly scoped GitHub Actions workflow using OIDC and a protected GitHub environment. Enabling it requires package-owner configuration in npm and a reviewed workflow change. Until then, never place an npm token in repository files, workflow YAML, logs, local acceptance records, or project notes.
package/docs/TESTING.md CHANGED
@@ -2,16 +2,22 @@
2
2
 
3
3
  The project treats transport, authorization, local authority, and state removal as separate failure domains.
4
4
 
5
- ## Required suite
5
+ ## Required suites
6
6
 
7
7
  ```sh
8
- npm run check
8
+ npm run check:fast # static, unit, contract, and architecture feedback
9
+ npm run check:platform # fast plan plus cross-platform behavior and real-machine tests
10
+ npm run check # complete suite; equivalent to check:full
9
11
  ```
10
12
 
13
+ The explicit task lists live in `scripts/check-plan.mjs`. The fast plan retains static analysis, policy, architecture, contracts, and focused unit behavior. The platform plan adds process, service, browser/application, state, managed-job, cryptographic, and real-machine behavior tests needed on macOS and Windows. The full-only plan adds coverage, browser-broker integration, package/install, stdio, Worker/OAuth, and real-browser navigation suites. `npm run check` remains the authoritative complete gate.
14
+
11
15
  The repository requires Node.js 26 and npm 12. `.node-version`, `.nvmrc`, `packageManager`, `devEngines`, and strict engine checks keep local and CI execution on the same baseline.
12
16
 
13
17
  The suite includes:
14
18
 
19
+ - package-impact classification derived from the npm package manifest, allowing repository-only GitHub workflow maintenance without weakening version requirements for shipped content;
20
+ - interactive candidate acceptance hashing, including owner-authorized in-place Worker deployment plus owner-started candidate verification, exact tarball SHA-1/SHA-512 matching, acceptance-record exclusion from the package, legacy 1.2.8 marker compatibility, and invalidation after any packaged-byte change;
15
21
  - release-impact enforcement requiring a new package version and CHANGELOG section for release-relevant changes;
16
22
  - 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;
17
23
  - generated Cloudflare Worker types under ignored `.wrangler/` state and strict TypeScript checking, including unused-local and unused-parameter rejection; packaging rejects generated declarations;
@@ -79,11 +85,11 @@ For deterministic release validation, perform an isolated-profile smoke test wit
79
85
 
80
86
  ## Critical-module coverage gate
81
87
 
82
- `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 now includes policy, typed errors, call registration, execution middleware, lifecycle/observability, logging, Runtime/CLI orchestration, the independently injected service CLI adapter, Agent configuration, capability ranking, browser protocol/operation boundaries, runtime reporting/diagnostics/capability composition, and Worker pending/policy/error modules. The full stdio and workerd OAuth/MCP integration still runs separately; a focused direct Node test covers `OAuthController` registration throttling, authorization failure/success, resource-bound access tokens, expiry pruning, invalid-state rejection, and identity-key failure.
88
+ `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.
83
89
 
84
90
  The gate deliberately reports each module rather than one aggregate percentage. New extracted pure/domain modules carry explicit branch floors, while the broad CLI entrypoint remains reported and locked independently. Worker pending calls and policy now have branch minima instead of function-only gates. A refactor may raise a threshold, but must not lower one merely to make CI green without an explicit audit explanation.
85
91
 
86
- `npm run typecheck` combines strict Worker TypeScript with a focused `tsconfig.local.json` gate. High-risk JavaScript contracts opt in with `// @ts-check` and JSDoc types; the gate currently covers policy, call lifecycle, Agent configuration/path resolution, browser handshake parsing, capability ranking, monotonic deadlines, number/record normalization, and bounded metadata reads. `@ts-ignore`, implicit `any`, or unchecked parallel contract shapes are not accepted as migration shortcuts.
92
+ `npm run typecheck` combines strict Worker TypeScript with a focused `tsconfig.local.json` gate. High-risk JavaScript contracts opt in with `// @ts-check` and JSDoc types; the gate currently covers policy, call lifecycle, Agent configuration/path resolution, public projection, skill discovery, bounded Agent text reads, runtime path redaction, browser handshake parsing, capability ranking, monotonic deadlines, number/record normalization, and bounded metadata reads. `@ts-ignore`, implicit `any`, or unchecked parallel contract shapes are not accepted as migration shortcuts.
87
93
 
88
94
  ## Additional release checks
89
95
 
@@ -97,9 +103,10 @@ npm sbom --sbom-format cyclonedx
97
103
  npm pack --dry-run
98
104
  npm run version:check
99
105
  npm run release-impact:check
106
+ npm run release:acceptance:verify
100
107
  ```
101
108
 
102
- GitHub Actions executes the main suite on Linux, macOS, and Windows using the pinned Node 26/npm 12 baseline. Because Node 26 currently bundles npm 11, CI downloads the exact npm 12.0.1 tarball from the canonical registry, rejects redirects, verifies its recorded SHA-512 SRI, and exposes that verified CLI through `GITHUB_PATH` before any project-local npm command can trigger strict `devEngines`. Checkout fetches version tags so the release-impact gate can compare the branch with the latest release. A separate package-audit job scans reachable Git history, audits both the complete dependency graph and the production-only graph, verifies registry signatures and attestations, validates a CycloneDX SBOM written under the runner temporary directory, exercises the documented isolated global installation, then performs a dry-run package build. Separate pinned workflows validate governance titles, review dependency changes, run CodeQL over JavaScript/TypeScript and GitHub Actions, and run OpenSSF Scorecard. The SARIF gate fails closed when rule metadata is absent, CodeQL permits only one exact, expiring non-shell process-boundary result, and Scorecard permits only exact reviewed governance/time-dependent findings; new dependency-pinning, fuzzing, or other supply-chain results fail before upload. Scorecard's signed analysis job contains only pinned `uses` steps, while a dependent gate job downloads the SARIF, enforces the accepted inventory, and uploads it to code scanning. Security property tests use a `.js` `fast-check` suite with deterministic seeds because the pinned Scorecard scanner recognizes JavaScript property testing only in `*.js`/`*.jsx`. The installed zero-argument startup smoke test also verifies that Windows creates and remembers `%USERPROFILE%\MachineBridge` while other platforms retain the package-free current directory. The macOS matrix job also runs the installation smoke test because Wrangler's optional `fsevents` resolution is platform-specific. Third-party Actions are pinned to immutable 40-character commit SHAs; architecture tests reject movable tags, and Dependabot monitors both action and dependency updates. Source release creation additionally requires successful push-triggered CI, CodeQL, Governance, and Scorecard runs for the exact `main` commit.
109
+ GitHub Actions uses the pinned Node 26/npm 12 baseline in three execution paths. Ubuntu runs `check:full` and verifies interactive candidate acceptance. macOS and Windows run `check:platform` plus the installed-package smoke test, preserving platform coverage without repeating every Worker, browser, and package integration fixture three times. A separate package-audit job scans reachable Git history, audits complete and production dependency graphs, verifies registry signatures and attestations, validates a CycloneDX SBOM under the runner temporary directory, repeats the isolated installation test, and performs a package dry run. Because Node 26 currently bundles npm 11, every npm execution job downloads the exact npm 12.0.1 tarball, rejects redirects, verifies its recorded SHA-512 SRI, and exposes that verified CLI through `GITHUB_PATH`. Separate pinned workflows validate governance titles, dependency changes, CodeQL, and OpenSSF Scorecard. Third-party Actions remain pinned to immutable commits, SARIF findings fail closed unless exactly reviewed, and source release creation requires successful push-triggered CI, CodeQL, Governance, and Scorecard runs for the exact `main` commit.
103
110
 
104
111
  ## Test design rules
105
112
 
@@ -120,7 +127,7 @@ Run `npm run privacy:check` before committing and before packaging. Run and revi
120
127
 
121
128
  ## Package manifest
122
129
 
123
- `npm run package:test` executes a real silent `npm pack --dry-run --json`, requires clean parseable JSON, rejects sensitive local artifacts, credential-like file classes, and generated Worker type declarations, validates every packaged mode as `0644` or `0755`, and verifies that privacy/engineering guidance, runtime/relay/secure-file/lock/service/browser/app modules, all package-script helpers, the packaged browser extension, contribution discipline, and privacy/release-impact checkers are present. `npm run install:test` requires npm 12, installs the real tarball from a package-free directory into an isolated global prefix with the documented options, verifies the packaged npm engine requirement, rejects blocked-script warnings, confirms optional `fsevents` is absent, verifies `--version`, then runs the installed CLI with zero arguments from an isolated workspace/state root. A fake Wrangler JavaScript entrypoint terminates at a controlled deployment boundary, so the probe executes default command normalization, state initialization, deployment fingerprint collection, and Wrangler dispatch without changing a live account; any undefined identifier or earlier crash fails the release. The test is part of `npm run check` and runs on Linux, macOS, and Windows CI.
130
+ `npm run package:test` executes a real silent `npm pack --dry-run --json`, requires clean parseable JSON, rejects sensitive local artifacts, credential-like file classes, and generated Worker type declarations, validates every packaged mode as `0644` or `0755`, and verifies that required runtime, script, browser-extension, privacy, governance, and release files are present. `npm run install:test` requires npm 12, installs the real tarball from a package-free directory into an isolated global prefix with the documented options, verifies the packaged npm engine requirement, rejects blocked-script warnings, confirms optional `fsevents` is absent, verifies `--version`, then runs the installed CLI with zero arguments from an isolated workspace/state root. A fake Wrangler JavaScript entrypoint terminates at a controlled deployment boundary, so the probe exercises startup without mutating a live account. Package testing is full-plan-only; installation smoke runs in the Ubuntu full plan, the macOS/Windows platform plan, and package audit.
124
131
 
125
132
  `npm run lint` uses ESLint as a semantic JavaScript correctness gate rather than a style formatter. It covers the Node CLI/runtime, repository scripts, tests, and packaged browser extension and rejects undefined identifiers in function bodies that `node --check` cannot detect. A dedicated lint-gate self-test proves that both Node and browser configurations reject a synthetic undefined binding while accepting the service-worker `importScripts` global. A focused `shell:test` requires Wrangler to run through the current Node executable and its package JavaScript entrypoint rather than a `.cmd` or shell shim. Architecture tests require `shell:test`, `lint:test`, `lint`, and `install:test` to remain in the complete check pipeline and reject non-exact direct dependency ranges.
126
133
 
@@ -128,4 +135,4 @@ The stdio integration test also sends an oversized line, verifies bounded reject
128
135
 
129
136
  ## Architecture and documentation regression checks
130
137
 
131
- `npm run architecture:test` runs independent module-boundary, repository-hygiene, browser/security-structure, and release/documentation-contract checks. It rejects movable GitHub Action references and loss of the CI history scan, release-gate script drift, local-module dependency cycles, missing static or dynamic relative imports, package scripts that reference missing files, drift from the recursive syntax scanner, incomplete executable package directories, inconsistent installation guidance, obsolete `LocalDaemon`/`daemon.mjs` naming, broken relative Markdown links, invisible ASCII control bytes in repository text, removal of the owner-required default-`full` engineering invariant, and accidental publication of `.project-local/` notes.
138
+ `npm run architecture:test` runs independent module-boundary, repository-hygiene, browser/security-structure, and release/documentation-contract checks. It validates the explicit fast/full check plans, local import graph, domain/adapter direction, module headroom budgets, immutable workflow references, package-script targets, documentation links, publication inventory, and selected security-shape invariants. These source-shape checks are deliberately supplementary: behavior, denial, race, and fault-injection tests remain authoritative for semantic guarantees. Tests must not depend on a fixed CI job count when the actual invariant is that every npm job uses the same verified bootstrap.