machine-bridge-mcp 1.1.4 → 1.2.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 (57) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/CODE_OF_CONDUCT.md +24 -0
  3. package/CONTRIBUTING.md +3 -1
  4. package/GOVERNANCE.md +50 -0
  5. package/README.md +30 -2
  6. package/SECURITY.md +1 -1
  7. package/SUPPORT.md +31 -0
  8. package/browser-extension/browser-operations.js +1 -1
  9. package/browser-extension/manifest.json +2 -2
  10. package/browser-extension/page-automation.js +1 -1
  11. package/docs/ARCHITECTURE.md +17 -18
  12. package/docs/AUDIT.md +28 -0
  13. package/docs/ENGINEERING.md +5 -2
  14. package/docs/LOGGING.md +2 -0
  15. package/docs/OPERATIONS.md +7 -3
  16. package/docs/PROJECT_STANDARDS.md +3 -2
  17. package/docs/TESTING.md +7 -4
  18. package/docs/UPGRADING.md +30 -0
  19. package/package.json +15 -7
  20. package/scripts/coverage-check.mjs +24 -9
  21. package/src/local/agent-context.mjs +7 -148
  22. package/src/local/agent-contract.mjs +206 -0
  23. package/src/local/browser-bridge.mjs +30 -281
  24. package/src/local/browser-extension-protocol.mjs +19 -4
  25. package/src/local/browser-operation-service.mjs +325 -0
  26. package/src/local/call-registry.mjs +44 -1
  27. package/src/local/capability-ranking.mjs +13 -0
  28. package/src/local/cli-account-admin.mjs +1 -1
  29. package/src/local/cli.mjs +16 -7
  30. package/src/local/daemon-process.mjs +1 -1
  31. package/src/local/full-access-test.mjs +1 -1
  32. package/src/local/job-runner.mjs +9 -3
  33. package/src/local/monotonic-deadline.mjs +7 -0
  34. package/src/local/numbers.mjs +8 -0
  35. package/src/local/policy.mjs +88 -12
  36. package/src/local/project-metadata.mjs +7 -1
  37. package/src/local/records.mjs +6 -0
  38. package/src/local/runtime-capabilities.mjs +66 -0
  39. package/src/local/runtime-diagnostics.mjs +91 -0
  40. package/src/local/runtime-reporting.mjs +113 -0
  41. package/src/local/runtime.mjs +53 -190
  42. package/src/local/service-convergence.mjs +1 -1
  43. package/src/local/service-environment.mjs +129 -0
  44. package/src/local/service.mjs +22 -53
  45. package/src/local/state.mjs +2 -2
  46. package/src/local/windows-service.mjs +248 -0
  47. package/src/local/worker-health.mjs +1 -1
  48. package/src/worker/access.ts +4 -4
  49. package/src/worker/account-admin.ts +2 -2
  50. package/src/worker/authority.ts +3 -3
  51. package/src/worker/index.ts +29 -337
  52. package/src/worker/oauth-controller.ts +334 -0
  53. package/src/worker/oauth-state.ts +1 -1
  54. package/src/worker/oauth-tokens.ts +2 -2
  55. package/src/worker/tool-catalog.ts +1 -1
  56. package/tsconfig.json +2 -1
  57. package/tsconfig.local.json +27 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.2.0 - 2026-07-16
4
+
5
+ ### Typed evolution boundaries and project governance
6
+
7
+ - Split the highest-change orchestration modules along real lifecycle boundaries. Worker OAuth storage, registration, authorization, account administration, token verification, and mutation serialization now live in `OAuthController`; local runtime reporting, fixed diagnostics, and capability composition have dedicated services; Agent configuration/path validation and browser MCP operation semantics no longer share files with discovery or loopback broker transport. Persisted state schema 6, policy revision 5, token records, browser pairing, resources, and managed-job data remain unchanged for an in-place upgrade from 1.1.5.
8
+ - Make Worker TypeScript imports explicit and directly executable under Node 26, including `.ts` specifiers and JSON import attributes. Add a focused OAuth-controller state-machine suite covering registration throttling, authorization failure/success, resource-bound access tokens, expiry pruning, schema mismatch, and missing identity keys while retaining the real workerd OAuth/MCP integration.
9
+ - Add a strict checked-JavaScript contract gate for local policy, call lifecycle, Agent configuration and path containment, browser handshake parsing, capability ranking, monotonic deadlines, record/number normalization, and bounded metadata reads. Expand correctness linting to reject async Promise executors, returned Promise-executor values, unsafe `finally`, useless catches, invalid `typeof`, self-assignment, and invalid NaN comparisons, and unused imports/variables; fix every newly detected occurrence rather than waiving the rules.
10
+ - Raise risk-directed coverage gates and include Agent, browser, runtime-boundary, and OAuth-controller fixtures. Worker pending-call and policy modules now have branch floors; the extracted runtime reporting, diagnostics, capability, browser operation, browser protocol, Agent contract, and capability-ranking modules have independent function and branch minima. Lower architecture line caps prevent the orchestration modules from regaining the extracted responsibilities.
11
+ - Add a five-minute README path, explicit Node 26/npm 12 support boundaries, a current-only upgrade and rollback contract, support/reporting guidance, project governance and succession rules, and a code of conduct. The first control required after a second active maintainer joins is non-author and last-push approval for security-sensitive code and release surfaces.
12
+ - Preserve release and supply-chain behavior: no live npm publication, Worker deployment, secret rotation, or daemon/service replacement is performed by this source release. Trusted npm publishing with GitHub OIDC still requires the external package-owner trust relationship and remains the next publication-control improvement.
13
+
14
+ ## 1.1.5 - 2026-07-16
15
+
16
+ ### Windows autostart and persisted network environment
17
+
18
+ - Replace the oversized Windows Scheduled Task `/TR` invocation with a short private launcher. The launcher contains the full quoted Node/CLI/workspace argv, routes output to the normal service logs, exits on success, and restarts nonzero daemon exits after five seconds. Register it for current-user logon at `LIMITED` run level, and reject a custom state path when even the short action exceeds Task Scheduler's 262-character boundary.
19
+ - Query Windows task state and last result through fixed PowerShell object properties instead of localized `schtasks` text. Creation, start, stop, and removal are verified against observed state; an installed `Ready` task is no longer reported as active, and localized nonzero stop/delete output cannot create a false failure after the requested state is reached. Default reboot recovery occurs after that Windows user signs in, not before login or as `SYSTEM`.
20
+ - Persist an owner-only allowlist of proxy and custom-CA environment variables for autostart daemons. Session-only PowerShell proxy settings now survive logon/reboot, environment-free later starts do not erase them, explicit case-insensitive replacements remove stale variants, and status/logging expose only configured key names. Unrelated environment secrets, oversized values, and control characters are rejected.
21
+ - Extend Worker idempotency coverage through a real disk-state reload to prove that a successful Wrangler upload followed by health timeout is not repeated by a new process. Clarify that a different canonical `--workspace` intentionally selects a different profile and Worker, and add terminal guidance to rotate any one-time account password exposed in shared output.
22
+ - Refresh the exact `ws` and Wrangler pins. The `ws` patch tightens fragment buffering limits, while Wrangler advances its bundled `workerd`; update the reviewed install-script allowlist to the exact new `workerd` version and retain zero high-severity or production audit findings.
23
+
3
24
  ## 1.1.4 - 2026-07-15
4
25
 
5
26
  ### File integrity and contract corrections
@@ -0,0 +1,24 @@
1
+ # Code of conduct
2
+
3
+ ## Expected behavior
4
+
5
+ Project participation must remain technical, evidence-based, and respectful. Contributors and maintainers are expected to:
6
+
7
+ - discuss the causal mechanism of a problem rather than attacking the person reporting it;
8
+ - distinguish verified behavior from assumptions and speculation;
9
+ - disclose relevant conflicts of interest;
10
+ - avoid publishing credentials, private paths, account identifiers, or other sensitive environment data;
11
+ - accept correction when tests, specifications, or reproducible evidence contradict a claim;
12
+ - keep review focused on correctness, security, privacy, compatibility, and maintainability.
13
+
14
+ Harassment, threats, discriminatory language, doxxing, deliberate disruption, and repeated bad-faith interaction are not accepted in project spaces.
15
+
16
+ ## Scope
17
+
18
+ This policy applies to repository issues, pull requests, discussions, release channels, security-report interactions, and other spaces where a person represents this project.
19
+
20
+ ## Reporting and enforcement
21
+
22
+ Security vulnerabilities must follow [SECURITY.md](SECURITY.md). Other conduct concerns should be reported privately to the repository owner through the contact method on the maintainer's GitHub profile. Do not open a public issue containing private conduct reports or personal information.
23
+
24
+ The maintainer may edit or remove content, lock conversations, reject contributions, or temporarily or permanently restrict participation. Enforcement decisions should identify the violated rule and preserve private information. A maintainer who is directly involved in a report must seek review from another trusted maintainer when one is available.
package/CONTRIBUTING.md CHANGED
@@ -4,7 +4,7 @@ This repository treats every Git-tracked or nonignored repository file as releas
4
4
 
5
5
  ## Development workflow
6
6
 
7
- Read [docs/PROJECT_STANDARDS.md](docs/PROJECT_STANDARDS.md) and the relevant domain documentation before changing behavior. This repository uses GitHub Flow: branch from current `main`, keep the change coherent, open a pull request, satisfy required checks, squash-merge, and delete the branch. Permanent `develop` or generic release integration branches are not used unless an independently maintained release line creates a concrete need. Repository automation performs GitHub operations only through local `git`, `gh`, and `gh api` commands executed by Machine Bridge; hosted GitHub connectors and ChatGPT GitHub plugins are prohibited for this repository.
7
+ Read [docs/PROJECT_STANDARDS.md](docs/PROJECT_STANDARDS.md), [GOVERNANCE.md](GOVERNANCE.md), and the relevant domain documentation before changing behavior. This repository uses GitHub Flow: branch from current `main`, keep the change coherent, open a pull request, satisfy required checks, squash-merge, and delete the branch. Permanent `develop` or generic release integration branches are not used unless an independently maintained release line creates a concrete need. Repository automation performs GitHub operations only through local `git`, `gh`, and `gh api` commands executed by Machine Bridge; hosted GitHub connectors and ChatGPT GitHub plugins are prohibited for this repository.
8
8
 
9
9
  Branch names use a category and purpose such as `feat/browser-downloads`, `fix/relay-timeout`, or `chore/dependency-policy`.
10
10
 
@@ -28,6 +28,8 @@ Before the reviewed code is pushed to `main`:
28
28
 
29
29
  After all required pull-request checks pass, repository automation completes the source release under [AGENTS.md](AGENTS.md): squash-merge through local `gh`, verify the exact `main` push CI, CodeQL, Governance, and Scorecard runs, create the annotated version tag, and create or update the matching final GitHub Release. The release operator separately publishes the same version to npm and performs any live machine update. Automation must not publish, deprecate, or unpublish npm packages; install the CLI globally; deploy the Worker; rotate credentials; mutate live deployment state; or start/stop/install/remove the daemon or autostart service without explicit user authorization.
30
30
 
31
+ Supported upgrade and rollback behavior is defined in [docs/UPGRADING.md](docs/UPGRADING.md). Support requests must follow [SUPPORT.md](SUPPORT.md), and repository participation follows [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
32
+
31
33
  After npm publication, the standard machine update is:
32
34
 
33
35
  ```bash
package/GOVERNANCE.md ADDED
@@ -0,0 +1,50 @@
1
+ # Project governance
2
+
3
+ ## Current ownership
4
+
5
+ The project currently has one human maintainer, `@YuLeiFuYun`. Repository automation may complete reviewed source changes under [AGENTS.md](AGENTS.md), but automation is not an independent reviewer and cannot replace accountable human ownership.
6
+
7
+ The maintainer owns product direction, security policy, repository administration, npm package ownership, Cloudflare deployment decisions, and release credentials. Live npm publication, Worker deployment, credential rotation, and daemon/service replacement remain explicit operator actions.
8
+
9
+ ## Decision model
10
+
11
+ Changes are accepted on technical evidence. The deciding criteria are, in order:
12
+
13
+ 1. preservation of authorization, integrity, privacy, and recovery invariants;
14
+ 2. correctness across supported platforms and failure paths;
15
+ 3. clarity of public contracts and upgrade behavior;
16
+ 4. cohesion, coupling, and long-term maintenance cost;
17
+ 5. user value relative to operational complexity.
18
+
19
+ A product or security invariant may change only through an explicit documented decision with tests, migration consequences, and release notes.
20
+
21
+ ## Maintainer admission and succession
22
+
23
+ A second maintainer should have a sustained history of high-quality review or contributions, understand the trust boundaries in `SECURITY.md` and `docs/ARCHITECTURE.md`, and be able to operate the release process without access to another person's credentials.
24
+
25
+ Before granting write or publication authority:
26
+
27
+ - require hardware-backed multifactor authentication where the platform supports it;
28
+ - add the person to CODEOWNERS for the areas they can review;
29
+ - verify recovery access for GitHub and npm through separate principals;
30
+ - rehearse a release from a protected branch and a non-production test deployment;
31
+ - document how access is revoked if the maintainer becomes unavailable or leaves.
32
+
33
+ Once a second active maintainer exists, branch protection must require one non-author approval and approval of the last push for changes affecting Worker authorization, policy contracts, process execution, browser automation, persistent state, workflows, security policy, or release tooling.
34
+
35
+ ## Release authority
36
+
37
+ Source release completion requires the exact `main` commit to pass CI, CodeQL, Governance, and OpenSSF Scorecard gates. The annotated Git tag, GitHub Release, release asset, package version, Worker version, and extension version must identify the same source state.
38
+
39
+ npm publication should move to trusted publishing with GitHub OIDC and a protected release environment. Until the external npm trust relationship is configured, publication remains a deliberate local operator action and no long-lived npm token may be stored in the repository.
40
+
41
+ ## Inactivity and transfer
42
+
43
+ If the sole maintainer expects to be unavailable, the preferred order is:
44
+
45
+ 1. appoint and verify a successor before transferring publication or repository authority;
46
+ 2. publish a maintenance notice and freeze feature work;
47
+ 3. preserve security-report access and package deprecation/recovery capability;
48
+ 4. archive the repository only when no qualified successor exists.
49
+
50
+ No contributor acquires release authority solely through commit volume. Access must be explicit, least-privilege, reviewable, and reversible.
package/README.md CHANGED
@@ -2,6 +2,32 @@
2
2
 
3
3
  `machine-bridge-mcp` exposes a selected local workspace to MCP clients through one shared, policy-controlled runtime.
4
4
 
5
+ > [!WARNING]
6
+ > The default `full` profile can read and modify local-user-accessible files, run shell commands, control the existing browser profile, and inherit the parent environment. It is not an operating-system sandbox. Use `review`, `edit`, or `agent`, or an isolated OS account/VM, when any client or repository is not fully trusted.
7
+
8
+ ## Start here
9
+
10
+ Machine Bridge requires **Node.js 26+ and npm 12+**. Older runtimes and obsolete MCP protocol versions are not supported.
11
+
12
+ 1. Follow [Installation and first use](docs/GETTING_STARTED.md).
13
+ 2. Run `machine-mcp doctor`.
14
+ 3. Start `machine-mcp` in the workspace you intend to expose.
15
+ 4. Connect the printed remote MCP URL, or configure [local stdio](#optional-local-stdio-mcp).
16
+ 5. For browser control, load and pair the packaged extension, then reload it after every package upgrade.
17
+
18
+ Choose the documentation path that matches the task:
19
+
20
+ | Role | Start with |
21
+ |---|---|
22
+ | New user | [Getting started](docs/GETTING_STARTED.md) |
23
+ | Upgrading an installation | [Upgrading](docs/UPGRADING.md) |
24
+ | MCP client integrator | [Clients](docs/CLIENTS.md) |
25
+ | Operator or incident responder | [Operations](docs/OPERATIONS.md) |
26
+ | Security reviewer | [Security policy](SECURITY.md) and [Architecture](docs/ARCHITECTURE.md) |
27
+ | Contributor or maintainer | [Contributing](CONTRIBUTING.md), [Engineering](docs/ENGINEERING.md), and [Governance](GOVERNANCE.md) |
28
+
29
+ Support boundaries and safe diagnostic requirements are in [SUPPORT.md](SUPPORT.md). Project participation follows [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
30
+
5
31
  It supports two transports:
6
32
 
7
33
  ```text
@@ -466,7 +492,7 @@ machine-mcp job submit|inspect|approve|list|read|cancel
466
492
  machine-mcp uninstall [--keep-worker] [--yes]
467
493
  ```
468
494
 
469
- Each canonical workspace has an independent profile, Worker name, credential set, state file, startup lock, and daemon lock.
495
+ Each canonical workspace has an independent profile, Worker name, credential set, state file, startup lock, and daemon lock. Supplying a genuinely different `--workspace` therefore selects or creates a different Worker; junctions and symbolic links are canonicalized before the workspace identity is hashed. Use `machine-mcp workspace show` and `machine-mcp status` before treating two Worker names as duplicates.
470
496
 
471
497
  ## Autostart
472
498
 
@@ -476,7 +502,9 @@ Remote mode supports:
476
502
  - Linux `systemd --user`, with best-effort lingering;
477
503
  - Windows Scheduled Task at logon.
478
504
 
479
- 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.
505
+ The service definition contains neither Worker/account 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. A private, allowlisted service-environment snapshot preserves proxy and custom-CA variables needed by a background daemon; status reports only configured key names, never values. Re-run `machine-mcp service install` after changing those variables. Custom Windows state paths used for autostart must also remain within the Task Scheduler path limit and must not contain a literal `%`.
506
+
507
+ Windows uses a short private launcher instead of putting the full Node command in Task Scheduler's bounded `/TR` field. The launcher routes output to the normal service logs and restarts a nonzero daemon exit after a delay. The task runs with least privilege when that Windows user signs in. Thus a reboot followed by normal user sign-in needs no command, but the default installation deliberately does not claim pre-login availability and does not store a Windows password or run as `SYSTEM`. 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.
480
508
 
481
509
  ## Secret rotation
482
510
 
package/SECURITY.md CHANGED
@@ -69,7 +69,7 @@ Repository and user instruction files remain untrusted content from the model's
69
69
 
70
70
  Automatic `package.*` commands expose only validated script names and fixed package-manager argv; they do not expose script bodies. Executing one still runs repository-controlled package-script code with local-user authority and is not a sandbox or trust upgrade.
71
71
 
72
- Relay proxy selection honors `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY`. Only HTTP(S) proxy URLs are accepted. Proxy endpoints, credentials, and authorization headers are not returned through MCP or written to operational logs; status exposes only coarse route state.
72
+ Relay proxy selection honors `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY`. Only HTTP(S) proxy URLs are accepted. Autostart installation persists an allowlist of proxy and custom-CA environment values in `service-environment.json` so a background daemon can reproduce the foreground network route; a proxy URL may itself contain credentials, so this file is sensitive local state and must remain protected with the rest of the state root. Proxy endpoints, credentials, certificate paths, and authorization headers are not returned through MCP or written to operational logs; service status exposes only configured environment key names and relay status exposes only coarse route state.
73
73
 
74
74
  Skill loading is non-executing. `load_local_skill` returns an entrypoint and bounded file inventory; scripts remain inert until a separate process or command tool is called. Symlinked skill directories are followed only after canonical path-policy validation, while symbolic-link `SKILL.md` entrypoints are rejected. Traversal, cycles, content, summaries, and inventory are bounded.
75
75
 
package/SUPPORT.md ADDED
@@ -0,0 +1,31 @@
1
+ # Support policy
2
+
3
+ ## Supported environment
4
+
5
+ The supported runtime is the pinned Node.js 26 and npm 12 baseline on current GitHub-hosted Linux, macOS, and Windows environments. Older Node/npm releases and obsolete MCP protocol versions are not compatibility targets.
6
+
7
+ The project supports the current package version and a direct upgrade from the immediately preceding published version when both use the current local state and policy schemas. See [Upgrading](docs/UPGRADING.md).
8
+
9
+ ## Where to ask
10
+
11
+ - Reproducible defects: use the bug report template.
12
+ - Feature proposals: use the feature request template.
13
+ - Security vulnerabilities or suspected credential exposure: follow [SECURITY.md](SECURITY.md), not a public issue.
14
+ - General installation and recovery: consult [Getting started](docs/GETTING_STARTED.md) and [Operations](docs/OPERATIONS.md) before filing an issue.
15
+
16
+ ## Required diagnostic information
17
+
18
+ A useful report includes:
19
+
20
+ - package version, operating system, Node version, and npm version;
21
+ - whether the transport is remote OAuth relay or local stdio;
22
+ - the active policy profile;
23
+ - the exact command or MCP operation that failed;
24
+ - sanitized output from `machine-mcp doctor` and, when available, `diagnose_runtime`;
25
+ - a minimal reproduction and whether the failure persists in a fresh disposable workspace.
26
+
27
+ Never include passwords, bearer tokens, private keys, browser pairing material, raw state files, real home/workspace paths, or unredacted logs. Replace them with synthetic values before posting.
28
+
29
+ ## Response expectations
30
+
31
+ This is currently a single-maintainer project. There is no guaranteed response time or commercial support commitment. Security reports and regressions affecting data integrity, authorization, or release integrity receive priority over feature requests.
@@ -496,7 +496,7 @@
496
496
  }
497
497
 
498
498
  function delay(ms) {
499
- return new Promise((resolve) => setTimeout(resolve, ms));
499
+ return new Promise((resolve) => { setTimeout(resolve, ms); });
500
500
  }
501
501
 
502
502
  function boundedRequestTimeout(value) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "Machine Bridge Browser",
4
- "version": "1.1.4",
4
+ "version": "1.2.0",
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.1.4"
33
+ "version_name": "1.2.0"
34
34
  }
@@ -703,7 +703,7 @@
703
703
  }
704
704
 
705
705
  function delay(ms) {
706
- return new Promise((resolve) => setTimeout(resolve, ms));
706
+ return new Promise((resolve) => { setTimeout(resolve, ms); });
707
707
  }
708
708
 
709
709
  Object.defineProperty(globalThis, "__machineBridgePageAutomation", {
@@ -25,27 +25,22 @@ A canonical workspace receives an independent profile, Worker name, secret set,
25
25
 
26
26
  ### Local runtime
27
27
 
28
- `LocalRuntime` is the transport-independent local tool engine. It owns:
29
-
30
- - canonical path resolution and display-path privacy;
31
- - file, text search, image, patch, and Git operations;
32
- - direct and shell process execution;
33
- - process-session buffers and stdin lifecycle;
34
- - layered fixed runtime diagnostics;
35
- - local resource aliases and detached managed-job coordination;
36
- - session/bootstrap instruction discovery, live capability ranking, and registered-command execution coordination;
37
- - structured local application and existing-profile browser automation coordination;
38
- - mutation serialization;
39
- - child-process tracking and cancellation;
40
- - output, traversal, concurrency, and time limits.
41
-
42
- `RelayConnection` owns remote WebSocket transport, authenticated `hello_ack` readiness, heartbeat liveness, reconnect backoff, and outage logging. Stdio mode invokes `LocalRuntime` directly without that adapter.
28
+ `LocalRuntime` is the transport-independent local tool orchestrator. It owns the shared authorization/execution pipeline, manager construction, mutation serialization, cancellation, and the narrow delegation surface used by stdio and relay transports. Domain behavior remains in focused services:
29
+
30
+ - `workspace-file-service.mjs` and `git-service.mjs` own canonical filesystem/Git operations;
31
+ - `process-execution.mjs`, `process-sessions.mjs`, and `process-tracker.mjs` own child-process authority and lifecycle;
32
+ - `runtime-reporting.mjs` builds privacy-aware runtime and project snapshots;
33
+ - `runtime-diagnostics.mjs` owns fixed local probes and their stable interpretation;
34
+ - `runtime-capabilities.mjs` composes agent, application, and browser capability results;
35
+ - managed jobs, local resources, application automation, and browser automation remain separate managers.
36
+
37
+ 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, authenticated `hello_ack` readiness, heartbeat liveness, reconnect backoff, and outage logging. Stdio mode invokes `LocalRuntime` directly without that adapter.
43
38
 
44
39
  `daemon-process.mjs` owns workspace-daemon inspection and takeover. It distinguishes platform service state from the lock-owning Node process, validates PID and process-start identity, canonicalizes workspace/state paths before comparison, parses bounded process command lines without executing them, and sends `SIGTERM` only to a verified same-workspace `--daemon-only` process. POSIX daemons may ignore that signal and reach the bounded non-escalating timeout; Node's Windows signal mapping terminates the verified process directly. CLI orchestration never treats a missing launchd/systemd job as proof that the process exited.
45
40
 
46
41
  ### Agent context and capability resolver
47
42
 
48
- `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. `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.
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.
49
44
 
50
45
  `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.
51
46
 
@@ -59,7 +54,7 @@ See [Session instructions, skills, commands, and capability discovery](AGENT_CON
59
54
 
60
55
  ### Browser extension and machine broker
61
56
 
62
- `BrowserBridgeManager` owns connection orchestration for a loopback HTTP/WebSocket broker. Extension version/capability parsing lives in `browser-extension-protocol.mjs`; pairing files and local HTML/Host/Origin helpers live in `browser-pairing-store.mjs`. The first runtime for the machine-level state root becomes broker owner; additional workspaces and stdio runtimes authenticate to `/runtime` and proxy through the same extension socket. This preserves one extension pairing while allowing multiple local MCP runtimes.
57
+ `BrowserBridgeManager` owns only connection orchestration for the loopback HTTP/WebSocket broker, owner/client failover, routed requests, cancellation, and extension replacement. `browser-operation-service.mjs` owns MCP-facing browser argument normalization, resource-backed values/uploads, form semantics, screenshot conversion, and status presentation. Extension version/capability parsing lives in the strict checked `browser-extension-protocol.mjs`; pairing files and local HTML/Host/Origin helpers live in `browser-pairing-store.mjs`. The first runtime for the machine-level state root becomes broker owner; additional workspaces and stdio runtimes authenticate to `/runtime` and proxy through the same extension socket. This preserves one extension pairing while allowing multiple local MCP runtimes.
63
58
 
64
59
  The packaged Manifest V3 extension runs in the user's existing Chromium profile. Its service worker is limited to pairing, transport, acknowledged protocol readiness, cancellation, and response routing. Fixed `browser-operations.js` owns tab lifecycle, aggregate frame/source budgets, waits, screenshots, and input-backend selection; fixed `page-automation.js` is injected into selected frames for snapshot-version-2 semantics, stable refs, bounded DOM/text traversal, actionability checks, open-Shadow-DOM traversal, structured DOM operations, multi-field forms, and resource-backed file inputs. Fixed `devtools-input.js` exposes only bounded mouse, keyboard, and text sequences through the Chromium debugger API; callers cannot select CDP methods. Trusted sessions attach for one action and detach in `finally`; DOM fallback is allowed only before any DevTools Input dispatch, preventing duplicate side effects after an ambiguous command failure. Protocol 3 requires bidirectional `hello`/`hello_ack` plus exact packaged-version and capability equality; pairing state and replacement are committed only after validation, so an invalid candidate cannot displace or overwrite the working configuration. The broker validates loopback hostnames, canonical extension IDs, matching pairing/broker ports, bearer subprotocols, message sizes, concurrency, and deadlines. Pairing material is owner-only and omitted from MCP/log output.
65
60
 
@@ -108,6 +103,8 @@ All requests for a deployed Worker route to one named Durable Object. It owns:
108
103
  - policy/tool metadata attached to the active socket;
109
104
  - a bounded in-memory map of pending daemon calls.
110
105
 
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.
107
+
111
108
  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. It has no local filesystem or process API.
112
109
 
113
110
  The primary OAuth store separates client registrations and named accounts from authorization codes and access-token records. A separate Durable Object key owns refresh-token records so refresh support can be added without rewriting the live primary-store schema. A `client_id` identifies an MCP application and redirect URIs; account records identify the authorized human or service identity. Codes, access tokens, and refresh tokens bind client ID, account ID, account version, role, scope, resource, token version, and expiration. Only hashes of bearer tokens are persisted, and every public-client refresh invalidates the presented refresh token while returning a replacement. The Worker intersects the role with the active daemon policy before advertising or relaying tools, and the local runtime validates the relayed role again. One bridge-specific Durable Object and one local runtime remain the normal topology for a workspace/trust domain; see [MULTI_ACCOUNT.md](MULTI_ACCOUNT.md).
@@ -116,7 +113,9 @@ The daemon attachment deliberately omits workspace path/name/hash and process ID
116
113
 
117
114
  ### Autostart layer
118
115
 
119
- The service layer emits launchd, systemd-user, or Windows Scheduled Task definitions. Credentials are not embedded in service definitions; the daemon loads owner-only state. The exact policy is stored in owner-only state. launchd/systemd definitions contain the workspace/state-root selectors, `warn` plus JSON log settings, and a sanitized absolute-only PATH captured at installation so background `full` mode can resolve the same developer tools without accepting relative PATH entries.
116
+ The service layer emits launchd, systemd-user, or Windows Scheduled Task definitions. Worker/account credentials are not embedded in service definitions; the daemon loads owner-only state. The exact policy is stored in owner-only state. An allowlisted `service-environment.json` separately persists only network-proxy and custom-CA variables needed by a background daemon, because shell-session environment is not inherited reliably by login managers; values are loaded only for `--daemon-only`, never logged, and status exposes key names only. launchd/systemd definitions contain the workspace/state-root selectors, `warn` plus JSON log settings, and a sanitized absolute-only PATH captured at installation so background `full` mode can resolve the same developer tools without accepting relative PATH entries.
117
+
118
+ The Windows adapter owns a short private restart launcher because Task Scheduler's `/TR` action is substantially smaller than the Windows process command-line limit and the full installed Node/CLI/workspace argv can exceed it. The scheduled action therefore contains only the launcher path. The launcher performs the full quoted invocation, redirects to service logs, and restarts only nonzero exits. A fixed PowerShell object query supplies language-independent `Ready`/`Running` state; provider installation is not equated with process activity. The trigger is least-privilege current-user logon, not boot-time `SYSTEM` execution.
120
119
 
121
120
  The platform adapters normalize launchd, systemd, and Windows Scheduled Task operations to one `{ok, provider}` result contract. Removal is not a provider-specific sequence: `service-lifecycle.mjs` first stops the provider, then every verified workspace daemon in scope, and only then removes the definition. A failed stop or unverifiable process prevents definition/state deletion.
122
121
 
package/docs/AUDIT.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Engineering and security audit
2
2
 
3
+ ## 2026-07-16 version 1.2 trustworthy-evolution audit
4
+
5
+ The review began from clean released commit `58d54c21a0ac37f8e5f82a6f895738508efad0c6` (`v1.1.5`). The complete local gate, exact-commit Linux/macOS/Windows CI, CodeQL, Governance, and OpenSSF Scorecard were green; dependency audits reported zero vulnerabilities; and the GitHub Release asset, npm registry tarball, and a fresh local pack were byte-identical. That evidence ruled out an immediate release-integrity incident but did not answer whether the project could continue evolving safely: the main Worker, runtime, Agent-context, and browser-broker modules were all above ninety-seven percent of their own architecture limits, while high-authority local JavaScript had almost no static shape checking and several critical Worker modules had no branch floor.
6
+
7
+ The causal correction is responsibility extraction rather than a line-count shuffle. `OAuthController` now owns OAuth persistence, pruning, registration throttling, authorization UI/submission, account administration, exchange delegation, token verification, and its mutation queue. `LocalRuntime` delegates privacy-aware reporting, fixed diagnostics, and capability composition to dedicated services. Agent configuration/path validation and browser MCP action semantics moved into their own domain modules, leaving discovery and loopback transport with one reason to change. Architecture tests lower the old composition-root limits and independently cap every extracted module; source guards reject a return of OAuth, diagnostics, capability scoring, browser operation validation, low-level process, or patch responsibilities to the orchestrators.
8
+
9
+ Static assurance now follows authority rather than file extension. A focused strict checked-JavaScript gate covers local policy, call registration/cancellation, Agent configuration and path containment, browser handshake parsing, capability ranking, monotonic deadlines, basic normalization, and bounded metadata reads. Worker imports use explicit `.ts` specifiers and JSON attributes, allowing the same OAuth state machine to run directly under the pinned Node 26 baseline and under Wrangler. The new test reproduces registration throttling, invalid and valid authorization, HMAC source identity, resource-bound token authority, token expiry deletion, schema mismatch, and missing identity configuration. No `@ts-ignore`, implicit-`any` waiver, alternative TypeScript runtime, or duplicate test-only implementation was introduced.
10
+
11
+ Risk-directed coverage now includes the extracted Agent, browser, and runtime services. The runtime composition root rose to roughly eighty-one percent function and sixty-five percent branch coverage; reporting, diagnostics, and capability composition have independent thresholds; Worker pending calls and policy gained branch floors. A new lint pass found thirty-eight concise Promise executors that accidentally returned timer/listener handles and one cleanup throw inside `finally`; all were corrected rather than excepted. The first remote CodeQL pass then found four extraction leftovers; they were removed and `no-unused-vars` became a local failing gate so this class no longer waits for remote analysis. The cleanup test now records a final best-effort deletion failure without replacing the primary browser-test result.
12
+
13
+ Upgrade safety is intentionally current-only. Version 1.2 retains local state schema 6 and policy revision 5, and does not alter OAuth record formats, resource registrations, managed-job envelopes, Worker identity, or browser pairing. A normal 1.1.5 installation therefore upgrades in place; unsupported older schemas remain rejected rather than guessed. The new upgrade document defines the daemon/Worker/extension as one rollback unit and prohibits hand-editing version fields. No npm publication, Worker deployment, credential rotation, global installation, or live service replacement was performed during source work.
14
+
15
+ The remaining controls cannot be completed honestly by repository automation alone. npm trusted publishing needs the package owner's external OIDC trust configuration and protected publication environment. Independent review needs a second active human maintainer. Governance now defines admission, succession, and the exact protected paths that must require non-author and last-push approval once that person exists; the existing expiring Scorecard exceptions remain visible until those external conditions change.
16
+
17
+ ## 2026-07-16 Windows autostart, restart, and workspace-identity incident
18
+
19
+ The reported transcript combined two distinct questions that the previous Worker fix did not answer. The first ordinary `machine-mcp` invocation addressed the remembered workspace, while the next command explicitly supplied another `--workspace`. Machine Bridge intentionally assigns one profile and one Worker to each canonical workspace, so that sequence is not by itself evidence that a retry duplicated the same resource. The existing deployment code did persist successful Wrangler evidence before health verification, but its regression reused one in-memory object. The new test performs an actual atomic state write, reconstructs state from disk as a new process would, repeats an ambiguous timeout, and proves Wrangler deploy is still called exactly once. Documentation now requires comparing canonical workspace, profile, Worker name, and URL before deleting any apparent duplicate.
20
+
21
+ The Windows autostart warning was a separate confirmed defect. The adapter placed the complete Node executable, globally installed CLI entrypoint, workspace, state root, and logging arguments in `schtasks /TR`. Representative installed paths exceed Task Scheduler's 262-character action-path boundary, so task creation could fail consistently even though foreground relay startup succeeded. The generic startup warning discarded the provider reason, and `service status` compounded diagnosis by equating a successful task query with a running task. Stop and removal also depended on English fragments in `schtasks` output, which is invalid on non-English Windows.
22
+
23
+ Windows now stores the long invocation in a private state-root launcher and registers only that short launcher path. The launcher uses bounded fixed arguments, redirects to the standard service logs, exits after a successful daemon exit, and restarts a nonzero exit after five seconds. Registration uses the current user and `LIMITED` run level. Creation, start, stop, and removal are accepted only after fixed PowerShell object queries observe the actual Task Scheduler state and last result, so localized text is not a control signal and an installed `Ready` task is no longer reported as active. Tests reproduce an inline action above 262 characters, verify the replacement action is below the limit, exercise running/completed states, and inject localized nonzero command output.
24
+
25
+ A third lifecycle gap explained why a foreground connection repaired by PowerShell `$env:` variables could fail after reboot. Login managers do not preserve that terminal's process environment. Autostart installation now snapshots only an explicit proxy/custom-CA allowlist into private local state; `--daemon-only` fills missing runtime variables from that snapshot. A later environment-free startup preserves the snapshot, case-insensitive replacements remove stale Windows variants, explicit empty values can clear settings, and status/logging reveal only key names. Tests prove unrelated secret variables are excluded and values are bounded and control-character safe. A proxy URL may contain credentials, so the snapshot is treated as sensitive state rather than a service-definition or log field.
26
+
27
+ The resulting reboot contract is intentionally narrower than “available before anyone logs in.” The Windows task is `ONLOGON`: after the configured user signs in, no terminal action is required and the launcher self-recovers nonzero daemon exits. Pre-login operation would require a materially different Windows service account, stored-credential, or `SYSTEM` boundary and is not silently introduced. The audit also identified the exposed one-time owner password in the supplied screenshot as compromised operational output; CLI guidance now warns against sharing credential-bearing terminal output, but the affected account must be rotated by the operator because repository changes cannot revoke a displayed live credential.
28
+
29
+ Dependency review found no npm audit findings in either the complete or production graph. Two exact patch pins were stale: `ws` contained a fragment-limit correction and Wrangler carried a newer `workerd` plus unrelated tooling changes. Both pins were updated, the exact install-script allowlist was advanced to the reviewed `workerd` build, and the full packaging/install/Worker suites remain the acceptance boundary rather than treating “latest” as sufficient evidence.
30
+
3
31
  ## 2026-07-15 Windows Worker deployment convergence incident
4
32
 
5
33
  A Windows report showed Wrangler creating a Worker successfully, followed by `Worker deployment did not become healthy at the expected version: timeout`. Re-running startup, and then changing the name to a suffixed `-r2` variant, left multiple Workers in the Cloudflare account. The causal defect was not Worker creation itself: Wrangler and the long-lived relay already followed standard proxy routing, while the independent health verifier used a direct global `fetch`. On networks where outbound HTTPS required an environment proxy, deployment could succeed and health verification could time out.
@@ -130,8 +130,8 @@ The required matrix includes:
130
130
  - Linux, macOS, and Windows on the pinned Node/npm baseline;
131
131
  - current-tree and reachable-history privacy gates, release-impact enforcement, and exact-commit CI/CodeQL/Governance/Scorecard release gating;
132
132
  - package-manifest and sensitive-artifact inspection;
133
- - generated type checks and recursively discovered JavaScript/shell syntax checks;
134
- - static undefined-identifier/redeclaration checks over all production JavaScript, tests, scripts, and browser-extension code;
133
+ - generated Worker type checks plus strict opt-in checked-JavaScript contracts for high-risk local policy, lifecycle, configuration, path, protocol, and timing boundaries;
134
+ - recursively discovered JavaScript/shell syntax checks and static correctness lint over all production JavaScript, tests, scripts, and browser-extension code;
135
135
  - a real packed-tarball isolated global installation whose zero-argument CLI startup initializes state and reaches a controlled external Worker-deployment boundary; `--version` or import-only smoke tests are insufficient release evidence;
136
136
  - concurrent exclusive-lock/atomic-replacement tests, PID-reuse/age tests, and fail-closed service-lifecycle tests;
137
137
  - real process-tree timeout/cancellation tests with descendants that ignore graceful termination;
@@ -151,6 +151,9 @@ Cross-platform tests must not depend on shell syntax, case-sensitive Windows pat
151
151
  - LOGGING defines operator-facing event semantics.
152
152
  - OPERATIONS contains diagnosis and recovery procedures.
153
153
  - TESTING records executable coverage and regression expectations.
154
+ - UPGRADING defines the only supported state/protocol transition and rollback unit.
155
+ - SUPPORT defines supported runtimes, diagnostic requirements, and public/private reporting boundaries.
156
+ - GOVERNANCE defines accountable ownership, succession, review, and release authority.
154
157
  - CHANGELOG records externally relevant changes, including documentation and workflow changes.
155
158
  - PROJECT_STANDARDS defines collaboration, contract, testing, supply-chain, review, and exception policy.
156
159
  - TOOL_REFERENCE is generated from the shared MCP tool catalog and must never be maintained by hand.
package/docs/LOGGING.md CHANGED
@@ -39,6 +39,8 @@ Wrangler upload and `/healthz` verification are logged as separate state transit
39
39
 
40
40
  Health routing records only `direct` or `proxy` at debug level. Proxy URLs, credentials, request headers, Worker secrets, and raw response bodies are never fields. Repeated per-attempt health failures remain debug-only; the terminal startup error contains one user-readable classification and corrective commands.
41
41
 
42
+ Autostart installation and daemon startup may report the names of allowlisted proxy/custom-CA environment variables that were saved or loaded. Their values, source environment, proxy endpoints, embedded credentials, and certificate paths are prohibited log fields. Windows task failures use stable reasons such as `task_create_failed` or `task_status_unavailable`; localized command output is retained only in an explicitly requested service-command result, not repeated in default startup warnings.
43
+
42
44
  ## Relay connection event policy
43
45
 
44
46
  A TCP/WebSocket `open` event is only transport availability. The daemon is reported as connected only after the Worker returns `hello_ack` for the authenticated `hello` message.
@@ -16,7 +16,7 @@ Wrangler upload and public health verification are two separate observations. On
16
16
 
17
17
  Automatic redeployment is limited to bounded health evidence that the recorded endpoint is genuinely stale: a persistent package-version mismatch, an unexpected Machine Bridge identity, or a persistent `404`/`410`. Unreachability is not proof of absence. `--force-worker` remains the explicit override when an operator deliberately wants an upload despite matching state.
18
18
 
19
- Each workspace has one stable Worker name. A command that supplies a different `--worker-name` after initialization is rejected unless `--force-worker` is present. A name such as `mbm-example-r2` is a separate Cloudflare Worker, not a revision of `mbm-example`. If an older release already created duplicates, first run `machine-mcp status` and verify the active URL/name, then remove only the confirmed unused Workers in the Cloudflare dashboard or with Wrangler. Source upgrades do not delete ambiguous live deployments automatically.
19
+ Each canonical workspace has one stable Worker name. A command that supplies a different `--worker-name` after initialization is rejected unless `--force-worker` is present. A name such as `mbm-example-r2` is a separate Cloudflare Worker, not a revision of `mbm-example`. A different `--workspace` is also a separate identity by design; Windows junctions and symbolic links are resolved before hashing. A transcript that runs `machine-mcp` and later runs `machine-mcp --workspace OTHER_PATH` does not by itself prove a same-workspace duplicate. Compare `machine-mcp workspace show`, `machine-mcp status`, the canonical workspace path, and the recorded Worker URL first. If an older release already created duplicates, remove only the confirmed unused Workers in the Cloudflare dashboard or with Wrangler. Source upgrades do not delete ambiguous live deployments automatically.
20
20
 
21
21
  For a health timeout on Windows or a managed network:
22
22
 
@@ -26,7 +26,7 @@ machine-mcp doctor
26
26
  machine-mcp --verbose
27
27
  ```
28
28
 
29
- Run these commands from the same environment used for startup so `HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY` are identical. Debug logs expose only the selected route and classified error; they never print a proxy endpoint or credentials.
29
+ Run these commands from the same environment used for startup so `HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY` are identical. After the foreground connection succeeds, run `machine-mcp service install` from that same PowerShell session. Installation stores only an allowlisted proxy/custom-CA environment snapshot in private local state so the logon task does not lose session-only `$env:` settings after reboot. A later start with no proxy variables does not erase the saved snapshot; set a variable explicitly to an empty value and reinstall to clear it. `machine-mcp service status` reports only the saved key names. Debug logs expose only the selected route and classified error; they never print a proxy endpoint or credentials.
30
30
 
31
31
  ### Blocking-layer decision table
32
32
 
@@ -149,7 +149,11 @@ Uninstall acquires a state-root `maintenance.lock` that blocks new profile/state
149
149
  Stable errors include `policy_denied`, `invalid_request`, `timeout`, `cancelled`, `network_error`, `unavailable`, `limit_exceeded`, and `integrity_error`, with retryability metadata. Diagnose by code first; free-form messages are guidance, not an API contract.
150
150
 
151
151
 
152
- Windows Scheduled Task command lines use CRT-compatible quoting, including trailing backslashes and drive-root paths. Remote autostart definitions prefer a stable PATH alias that resolves to the currently running Node executable and persist a sanitized absolute-only service `PATH` containing the Node/CLI directories, the installer's absolute PATH entries, and platform defaults. This avoids versioned Homebrew-style paths becoming invalid after upgrades and prevents launchd/systemd from falling back to a minimal system-only PATH. Re-run `machine-mcp service install` after changing Node installation families or PATH layout. A service-style `--daemon-only` start that finds the same workspace daemon already running is an idempotent no-op: it exits successfully without repeating warnings or readiness output; explicit policy/secret/change requests still report that changes were not applied. Autostart logs are stored under the state root in `logs/daemon.out.log` and `logs/daemon.err.log`. Installed services pass `--log-level warn --log-format json`, so each active line is a bounded JSON event suitable for ingestion. Files are owner-only where supported and tail-trimmed before daemon startup. If the log schema marker does not match the current format, the active files are cleared before startup and the current marker is written. Runtime code reads and maintains only the active filenames.
152
+ Windows Task Scheduler limits the `/TR` action text, so the platform adapter writes a short private `service-launcher.cmd` under the state root rather than embedding the full Node, package, workspace, state, and logging argv in the task action. The launcher uses CRT-compatible argument quoting, sends stdout/stderr to the normal service logs, exits on a successful daemon exit, and restarts a nonzero exit after five seconds. Task creation is accepted only after a separate state query observes the task. Start, stop, and removal likewise query the Task Scheduler state through fixed PowerShell object properties instead of parsing localized `schtasks` messages; an installed `Ready` task is not mislabeled as currently running.
153
+
154
+ The Windows trigger is current-user `ONLOGON` with `LIMITED` run level. After a reboot, signing in to that user is sufficient; no terminal command is required. Pre-login operation is intentionally not provided by the default design because it would require a different service-account/credential boundary. Remote autostart definitions prefer a stable PATH alias that resolves to the currently running Node executable and persist a sanitized absolute-only service `PATH` containing the Node/CLI directories, the installer's absolute PATH entries, and platform defaults. A private allowlisted `service-environment.json` preserves `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`, matching lowercase forms, optional `ALL_PROXY`, Node proxy selection, and custom-CA path variables. Existing saved values survive an environment-free reinstall, while explicitly supplied values replace case-insensitive prior variants. Values may include proxy credentials, so the file stays in owner-only state and is never returned or logged; status exposes key names only. Re-run `machine-mcp service install` after changing Node installation families, PATH layout, proxy, or CA configuration. Custom Windows state paths used for autostart must also remain within the Task Scheduler path limit and must not contain a literal `%`.
155
+
156
+ A service-style `--daemon-only` start that finds the same workspace daemon already running is an idempotent no-op: it exits successfully without repeating warnings or readiness output; explicit policy/secret/change requests still report that changes were not applied. Autostart logs are stored under the state root in `logs/daemon.out.log` and `logs/daemon.err.log`. Installed services pass `--log-level warn --log-format json`, so each active line is a bounded JSON event suitable for ingestion. Files are owner-only where supported and tail-trimmed before daemon startup. If the log schema marker does not match the current format, the active files are cleared before startup and the current marker is written. Runtime code reads and maintains only the active filenames.
153
157
 
154
158
  Logging is level-based:
155
159
 
@@ -94,6 +94,7 @@ Tests follow risk rather than a repository-wide aggregate percentage:
94
94
  - Protocol changes include producer-consumer contract tests and malformed-input tests.
95
95
  - Supported operating systems run the required suite in CI.
96
96
  - Critical modules have explicit function and branch baselines. Thresholds may rise after better tests or extraction; lowering one requires an audit note explaining why the old measurement was misleading.
97
+ - High-risk JavaScript contract modules opt into strict TypeScript checking through `tsconfig.local.json`; implicit `any`, `@ts-ignore`, and untyped duplicate protocol/configuration shapes are not acceptable substitutes for a defined boundary.
97
98
 
98
99
  An 80% aggregate coverage target is not a repository requirement: it can hide untested critical branches behind trivial files. New or materially changed pure business modules should normally achieve at least 80% function coverage and meaningful branch coverage, but risk-specific tests remain the acceptance criterion.
99
100
 
@@ -124,7 +125,7 @@ Flaky tests are defects. A retry may diagnose environmental instability but may
124
125
  ## 8. Documentation and comments
125
126
 
126
127
  - README covers supported setup, operation, major capabilities, limitations, and risk.
127
- - Architecture, security, testing, operations, logging, policy, and release documents each own their designated concern; avoid repeating whole procedures across files.
128
+ - Architecture, security, testing, operations, logging, policy, upgrade, support, governance, and release documents each own their designated concern; avoid repeating whole procedures across files.
128
129
  - Documentation claims a guarantee only when code, configuration, or a test enforces it.
129
130
  - Public behavior changes update the changelog and relevant user documentation in the same pull request.
130
131
  - Comments explain non-obvious **why**, invariants, external constraints, and safety ordering. They do not narrate self-explanatory syntax.
@@ -136,7 +137,7 @@ Flaky tests are defects. A retry may diagnose environmental instability but may
136
137
 
137
138
  Review examines correctness, causal completeness, security/privacy boundaries, compatibility, failure paths, observability, test evidence, and maintainability. Style preferences do not override a simpler correct design without a documented project rule.
138
139
 
139
- This repository currently has one human maintainer. Requiring one independent approval would deadlock maintenance and therefore is not enabled. The first governance priority when another active maintainer is added is to require one non-author approval for security-sensitive, release, policy, Worker, browser, and execution changes.
140
+ This repository currently has one human maintainer. Requiring one independent approval would deadlock maintenance and therefore is not enabled. [GOVERNANCE.md](../GOVERNANCE.md) defines admission, succession, release authority, and the first mandatory control after another active maintainer is added: one non-author approval plus last-push approval for security-sensitive, release, policy, Worker, browser, state, and execution changes.
140
141
 
141
142
  ## 10. Exceptions and evolution
142
143
 
package/docs/TESTING.md CHANGED
@@ -22,10 +22,11 @@ The suite includes:
22
22
  - default working-agreement injection without user files, bounded automatic project metadata, script-body non-disclosure, user-global opt-out, repository opt-out rejection, global `model_instructions_file` injection in stdio/remote initialization, hierarchical precedence, `.agents/skills` and `.codex/skills` compatibility discovery, live project/skill rescanning and fingerprints, automatic task ranking/loading with English inflection normalization, bounded Chinese/English intent aliases, capability-name weighting, and selected-skill instruction loading; automatic `package.*` commands with English/Chinese workflow-intent matching and Windows command-shim execution, explicit command override/removal, direct argv handling, timeout ceilings, runtime-keyed routing-telemetry privacy, and execution-profile denial;
23
23
  - concurrent complete-before-visible lock claims, atomic replacement under active readers, malformed-lock grace, snapshot/token-safe reclamation, absolute-age expiry, PID-reuse detection, bounded startup-lock waiting, and wall-clock rollback injection proving duration deadlines remain monotonic;
24
24
  - foreground takeover of active and orphaned background daemons with current service-lock metadata, foreground-process protection, bounded final lock-handoff retry, actual-PID exit waiting, POSIX non-escalating timeout behavior, Windows verified-daemon stop semantics, daemon lock mode/version/process-start metadata, launchd service-target semantics, and silent idempotent duplicate service starts; daemon fixture subprocesses intentionally do not inherit V8 coverage because their purpose is ownership timing rather than code measurement;
25
- - fail-closed service lifecycle ordering for provider-stop, all-workspace daemon-stop, and definition removal, including platform/daemon/removal failure injection and normalized macOS/systemd/Windows results;
25
+ - fail-closed service lifecycle ordering for provider-stop, all-workspace daemon-stop, and definition removal, including platform/daemon/removal failure injection and normalized macOS/systemd/Windows results; Windows coverage reproduces an inline `/TR` command above 262 characters, proves the short launcher action remains bounded, verifies least-privilege logon registration, restart/log routing, language-independent `Ready`/`Running` observation, and state-observed stop/removal despite localized nonzero command output;
26
+ - private service-environment capture/load coverage for exact allowlisting, value bounds and control-character rejection, non-proxy secret exclusion, runtime-value precedence, Windows case-insensitive replacement, explicit empty-value clearing, and preservation across a later environment-free startup;
26
27
  - machine-level browser-broker ownership/client proxying, authenticated extension origin/subprotocol, non-cacheable local pairing, pairing-token non-disclosure, resource-backed upload routing, broker result redaction, pre-registered runtime-handshake listeners, bounded socket/HTTP waits, frozen-wall-clock browser deadline coverage, installed-application discovery caching, and name-based task matching;
27
28
  - Worker health direct/proxy routing through a real local HTTP CONNECT proxy, `NO_PROXY` bypass, exact `workers.dev` origin/name validation, redirect rejection, body/deadline bounds, error classification, bounded propagation retry, and invalid proxy fail-fast behavior without endpoint or credential disclosure;
28
- - Worker deployment ambiguity/idempotency: a successful Wrangler result followed by health timeout persists the fingerprint, a second start performs no upload, definitive stale-version evidence redeploys under the same name, accidental name changes are rejected, forced replacements clear current endpoint state, and prior names remain in uninstall inventory;
29
+ - Worker deployment ambiguity/idempotency: a successful Wrangler result followed by health timeout persists the fingerprint, a second start performs no upload, an actual process restart and disk-state reload still performs no upload, definitive stale-version evidence redeploys under the same name, accidental name changes are rejected, forced replacements clear current endpoint state, and prior names remain in uninstall inventory;
29
30
  - relay environment-proxy direct/bypass/agent selection, unsupported proxy rejection, fail-fast invalid configuration, and route observability without endpoint or credential disclosure;
30
31
  - canonical path and symbolic-link escape tests;
31
32
  - relative-path privacy and error-path redaction tests;
@@ -74,9 +75,11 @@ For deterministic release validation, perform an isolated-profile smoke test wit
74
75
 
75
76
  ## Critical-module coverage gate
76
77
 
77
- `npm run coverage:test` runs selected in-process and lightweight entrypoint fixtures under V8 coverage and enforces per-module baselines for policy, typed errors, call registration, execution middleware, lifecycle/observability, logging, Runtime/CLI orchestration, and Worker pending/policy/error modules. The full stdio and Worker OAuth/MCP integrations run separately in the main suite and are not duplicated inside coverage collection. The gate deliberately reports each module rather than one aggregate percentage. JavaScript modules enforce function and branch minima; Node's direct TypeScript stripping does not expose trustworthy branch ranges, so TypeScript modules enforce function coverage plus explicit state-machine tests and the real workerd integration suite.
78
+ `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, 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.
78
79
 
79
- The current CLI entrypoint remains the weakest covered orchestration surface; its baseline is therefore reported and locked independently, while extracted `cli-options`, `cli-policy`, `records`, `state-inventory`, `network-proxy`, `worker-health`, and `worker-deployment` modules carry substantially higher thresholds. The Worker convergence extraction and expanded command fixtures raised the CLI function floor from 40% to 45% and branch floor from 10% to 20%; a refactor may raise a threshold, but must not lower one merely to make CI green without an explicit audit explanation.
80
+ 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.
81
+
82
+ `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.
80
83
 
81
84
  ## Additional release checks
82
85
 
@@ -0,0 +1,30 @@
1
+ # Upgrading
2
+
3
+ ## Supported upgrade contract
4
+
5
+ Machine Bridge does not retain parallel implementations for obsolete MCP protocol dates, policy revisions, state schemas, lock formats, or browser-extension protocols. The supported path is a direct upgrade from the immediately preceding published package while its state already uses the current schema.
6
+
7
+ Version 1.2 keeps local state schema version 6 and policy revision 5 unchanged. Existing 1.1.5 workspaces, named accounts, resource registrations, managed-job history, Worker identity, and browser pairing state are reused without conversion. The architecture refactor changes module ownership, not persisted formats or authority.
8
+
9
+ A state file from an older unsupported schema is rejected rather than guessed or silently rewritten. Upgrade an old installation through the last release that understands its schema, or initialize a new workspace and re-register resources. Do not edit schema numbers by hand.
10
+
11
+ ## Normal upgrade
12
+
13
+ 1. Finish or cancel ordinary interactive process sessions. Accepted managed jobs may continue independently, but inspect them before replacing the daemon.
14
+ 2. Install the new package with the pinned npm procedure in [Getting started](GETTING_STARTED.md).
15
+ 3. Run `machine-mcp doctor`.
16
+ 4. Start `machine-mcp` normally for each workspace. Startup verifies state, stops only a verified same-workspace daemon, converges the Worker deployment, and takes over using the installed version.
17
+ 5. Reload the unpacked browser extension. Protocol and packaged-version equality are mandatory; an old extension cannot replace a working compatible connection.
18
+ 6. Reconnect MCP clients if they retain stale tool or session metadata.
19
+
20
+ ## Upgrade safety
21
+
22
+ Before replacing live software, copy the owner-only state directory using operating-system tools that preserve permissions. Do not publish or attach that backup: it contains credentials and private resource metadata.
23
+
24
+ Machine Bridge never treats an unreadable or foreign-schema state file as empty state. It also records a successful Worker upload before secondary health verification, so a network or proxy failure after deployment does not trigger an uncontrolled repeated write.
25
+
26
+ ## Rollback
27
+
28
+ Rollback is supported only when the older package understands every persisted schema and protocol already written by the newer package. Version 1.2 does not advance local state or policy schemas, so rollback to 1.1.5 remains structurally possible, but the preferred recovery is to fix forward because the browser extension and deployed Worker must match the running package exactly.
29
+
30
+ Never roll back by copying only selected state files or changing version fields. Restore one complete verified state backup, package version, Worker build, and browser extension as a single operational unit.