machine-bridge-mcp 1.1.5 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/CODE_OF_CONDUCT.md +24 -0
- package/CONTRIBUTING.md +3 -1
- package/GOVERNANCE.md +50 -0
- package/README.md +26 -0
- package/SUPPORT.md +31 -0
- package/browser-extension/browser-operations.js +10 -4
- package/browser-extension/devtools-input.js +2 -2
- package/browser-extension/manifest.json +2 -2
- package/browser-extension/page-automation.js +1 -1
- package/docs/ARCHITECTURE.md +14 -17
- package/docs/AUDIT.md +28 -0
- package/docs/ENGINEERING.md +8 -2
- package/docs/PROJECT_STANDARDS.md +4 -2
- package/docs/TESTING.md +9 -3
- package/docs/UPGRADING.md +32 -0
- package/package.json +12 -4
- package/scripts/coverage-check.mjs +27 -10
- package/src/local/account-access.mjs +7 -5
- package/src/local/agent-context.mjs +7 -148
- package/src/local/agent-contract.mjs +206 -0
- package/src/local/browser-bridge.mjs +30 -281
- package/src/local/browser-extension-protocol.mjs +19 -4
- package/src/local/browser-operation-service.mjs +325 -0
- package/src/local/call-registry.mjs +44 -1
- package/src/local/capability-ranking.mjs +13 -0
- package/src/local/cli-local-admin.mjs +74 -38
- package/src/local/cli-options.mjs +18 -18
- package/src/local/cli-policy.mjs +1 -1
- package/src/local/cli-service.mjs +132 -0
- package/src/local/cli.mjs +27 -109
- package/src/local/daemon-process.mjs +1 -1
- package/src/local/full-access-test.mjs +1 -1
- package/src/local/job-runner.mjs +9 -3
- package/src/local/managed-job-plan.mjs +3 -3
- package/src/local/monotonic-deadline.mjs +7 -0
- package/src/local/numbers.mjs +8 -0
- package/src/local/policy.mjs +97 -16
- package/src/local/project-metadata.mjs +7 -1
- package/src/local/project-package.mjs +1 -1
- package/src/local/records.mjs +6 -0
- package/src/local/resource-operations.mjs +1 -1
- package/src/local/runtime-capabilities.mjs +66 -0
- package/src/local/runtime-diagnostics.mjs +91 -0
- package/src/local/runtime-reporting.mjs +113 -0
- package/src/local/runtime.mjs +54 -191
- package/src/local/service-convergence.mjs +1 -1
- package/src/local/service.mjs +1 -1
- package/src/local/state.mjs +1 -1
- package/src/local/windows-service.mjs +1 -1
- package/src/local/worker-deployment.mjs +15 -10
- package/src/local/worker-health.mjs +8 -4
- package/src/worker/access.ts +8 -7
- package/src/worker/account-admin.ts +2 -2
- package/src/worker/authority.ts +3 -3
- package/src/worker/http.ts +2 -2
- package/src/worker/index.ts +29 -337
- package/src/worker/oauth-controller.ts +343 -0
- package/src/worker/oauth-state.ts +1 -1
- package/src/worker/oauth-tokens.ts +2 -2
- package/src/worker/tool-catalog.ts +1 -1
- package/tsconfig.json +2 -1
- package/tsconfig.local.json +27 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.2.1 - 2026-07-16
|
|
4
|
+
|
|
5
|
+
### Fail-closed input contracts and bounded CLI adapters
|
|
6
|
+
|
|
7
|
+
- Eliminate prototype-chain lookup from externally controlled command, action, account-role, policy-profile, form-field, keyboard, and local-resource keys. Dispatch and enumerations now use `Map`, `Set`, `Object.hasOwn`, or null-prototype records; names such as `constructor` and `__proto__` can no longer become inherited handlers or unauthorized enum members. A malformed current-schema OAuth account role is repaired in place to a disabled reviewer account, its version is advanced, and every existing authorization code and token is revoked so an affected installation remains administrable without granting authority.
|
|
8
|
+
- Make Worker deployment output parsing and health verification share one canonical `workers.dev` origin validator. Wrangler output containing unrelated `/mcp`, `/healthz`, path-bearing, or wrong-name URLs is no longer accepted as deployment evidence and cannot poison the persisted URL or deployment fingerprint.
|
|
9
|
+
- Preserve the exact browser `maxBytes` contract for non-ASCII page source. The DOM serializer now backs off to a complete UTF-8 prefix instead of decoding a split code point into a replacement character whose encoded size exceeds the reported budget; regressions cover emoji and Chinese text at every partial-byte boundary.
|
|
10
|
+
- Replace ordinary browser and service CLI branch trees with named, map-driven adapters. The service adapter is independently injectable and reaches 100% function and over 90% branch coverage; architecture checks are split into module boundaries, repository hygiene, browser/security structure, and release/documentation contracts so source-shape guards remain supplemental to executable behavior tests.
|
|
11
|
+
- Keep local state schema 6, policy revision 5, browser pairing, resources, jobs, and Worker identity unchanged for an in-place upgrade from 1.2.0. Normal startup still converges the versioned Worker and the unpacked extension must be reloaded; no live deployment, credential rotation, daemon replacement, global installation, or npm publication is performed by this source change.
|
|
12
|
+
|
|
13
|
+
## 1.2.0 - 2026-07-16
|
|
14
|
+
|
|
15
|
+
### Typed evolution boundaries and project governance
|
|
16
|
+
|
|
17
|
+
- 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.
|
|
18
|
+
- 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.
|
|
19
|
+
- 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.
|
|
20
|
+
- 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.
|
|
21
|
+
- 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.
|
|
22
|
+
- 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.
|
|
23
|
+
|
|
3
24
|
## 1.1.5 - 2026-07-16
|
|
4
25
|
|
|
5
26
|
### Windows autostart and persisted network environment
|
|
@@ -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
|
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.
|
|
@@ -181,7 +181,7 @@
|
|
|
181
181
|
function boundedDocumentSource(limit) {
|
|
182
182
|
const maxBytes = Math.max(1, Number(limit) || 1);
|
|
183
183
|
const encoder = new TextEncoder();
|
|
184
|
-
const decoder = new TextDecoder();
|
|
184
|
+
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
185
185
|
const chunks = [];
|
|
186
186
|
const VOID_ELEMENTS = new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"]);
|
|
187
187
|
const MAX_NODES = 100000;
|
|
@@ -207,8 +207,14 @@
|
|
|
207
207
|
returnedBytes += bytes.byteLength;
|
|
208
208
|
return true;
|
|
209
209
|
}
|
|
210
|
-
|
|
211
|
-
|
|
210
|
+
let end = remaining;
|
|
211
|
+
let prefix = "";
|
|
212
|
+
while (end > 0) {
|
|
213
|
+
try { prefix = decoder.decode(bytes.slice(0, end)); break; }
|
|
214
|
+
catch { end -= 1; }
|
|
215
|
+
}
|
|
216
|
+
if (prefix) chunks.push(prefix);
|
|
217
|
+
returnedBytes += end;
|
|
212
218
|
budgetExhausted = true;
|
|
213
219
|
return false;
|
|
214
220
|
};
|
|
@@ -496,7 +502,7 @@
|
|
|
496
502
|
}
|
|
497
503
|
|
|
498
504
|
function delay(ms) {
|
|
499
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
505
|
+
return new Promise((resolve) => { setTimeout(resolve, ms); });
|
|
500
506
|
}
|
|
501
507
|
|
|
502
508
|
function boundedRequestTimeout(value) {
|
|
@@ -100,10 +100,10 @@
|
|
|
100
100
|
let modifiers = 0;
|
|
101
101
|
for (const raw of parts) {
|
|
102
102
|
const name = raw === "Ctrl" ? "Control" : raw === "Cmd" || raw === "Command" ? "Meta" : raw;
|
|
103
|
-
if (!(name
|
|
103
|
+
if (!Object.hasOwn(MODIFIERS, name)) throw new Error(`unsupported key modifier: ${raw}`);
|
|
104
104
|
modifiers |= MODIFIERS[name];
|
|
105
105
|
}
|
|
106
|
-
const known = KEY_DATA[keyName];
|
|
106
|
+
const known = Object.hasOwn(KEY_DATA, keyName) ? KEY_DATA[keyName] : null;
|
|
107
107
|
if (known) return {
|
|
108
108
|
key: known.key || keyName,
|
|
109
109
|
code: known.code,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "Machine Bridge Browser",
|
|
4
|
-
"version": "1.1
|
|
4
|
+
"version": "1.2.1",
|
|
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
|
|
33
|
+
"version_name": "1.2.1"
|
|
34
34
|
}
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -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
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
- local
|
|
36
|
-
|
|
37
|
-
|
|
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
|
|
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).
|
package/docs/AUDIT.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Engineering and security audit
|
|
2
2
|
|
|
3
|
+
## 2026-07-16 version 1.2.1 fail-closed input-contract audit
|
|
4
|
+
|
|
5
|
+
The review began from clean `v1.2.0` with the complete repository gate, dependency audit, Worker dry run, and package checks passing. Hostile-input reproduction nevertheless found one shared JavaScript failure mechanism outside those gates: ordinary objects were being used as external string-key maps. Inherited names such as `constructor` and `__proto__` were therefore accepted as account roles, policy profiles, top-level commands, resource actions, and keyboard-table entries. The CLI variants could exit successfully without performing a command; a Worker account could persist an invalid role and later fail during authority calculation. Adjacent review found the same semantic hazard in form-field aggregation and valid local-resource names.
|
|
6
|
+
|
|
7
|
+
The correction removes prototype-chain semantics rather than blacklisting a few names. Command/action dispatch and role registries use `Map` or exact own-key membership; profile and availability contracts use explicit sets/own-key checks; URL-encoded bodies and normalized resource registries use null-prototype records. Regression tests exercise the standard prototype property names at every affected public boundary. A malformed role already persisted under the unchanged current OAuth schema is repaired in place to a disabled `reviewer`, its version advances, and all codes/tokens are pruned. This preserves an operator-recoverable account record while ensuring the upgrade cannot retain or expand authority.
|
|
8
|
+
|
|
9
|
+
The deployment review found a separate validation split: Wrangler output parsing accepted any HTTPS URL containing `/mcp` or `/healthz`, while the health verifier later required an exact root `workers.dev` origin matching the Worker name. Because successful upload evidence is intentionally saved before secondary verification, unrelated output could persist a URL/fingerprint pair that later starts would refuse to verify. Parsing and verification now share one canonical origin function; nonmatching, path-bearing, credential-bearing, ported, queried, or fragmented candidates are ignored and cannot mutate state.
|
|
10
|
+
|
|
11
|
+
The browser source limit had an encoding-level off-by-contract defect. Truncating raw UTF-8 bytes inside a code point and decoding non-fatally produced `U+FFFD`, whose re-encoded size could exceed both the returned count and caller budget. The serializer now backs off to the longest valid prefix and reports its actual encoded byte count. Emoji and Chinese fixtures cover every partial boundary and aggregate source budgeting.
|
|
12
|
+
|
|
13
|
+
Ordinary CLI branching was also brought back into the repository's own architecture standard. Browser actions were split into named handlers; service status/install/start/stop/uninstall/remove moved to an independently injectable adapter with complete action coverage and over ninety percent branch coverage. The former 580-line architecture test was separated into module boundaries, repository hygiene, browser/security structure, and release/documentation contracts. Source-string checks remain useful drift alarms, but the security and lifecycle claims above are enforced by executable behavior and fault-path tests.
|
|
14
|
+
|
|
15
|
+
Version 1.2.1 retains local state schema 6 and policy revision 5. Existing 1.2.0 state upgrades in place; the versioned Worker is converged by normal startup and the unpacked extension must be reloaded. Historical changelog and audit records remain as history, while obsolete runtime fallback semantics and stale migration wording were removed.
|
|
16
|
+
|
|
17
|
+
## 2026-07-16 version 1.2 trustworthy-evolution audit
|
|
18
|
+
|
|
19
|
+
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.
|
|
20
|
+
|
|
21
|
+
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.
|
|
22
|
+
|
|
23
|
+
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.
|
|
24
|
+
|
|
25
|
+
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.
|
|
26
|
+
|
|
27
|
+
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.
|
|
28
|
+
|
|
29
|
+
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.
|
|
30
|
+
|
|
3
31
|
## 2026-07-16 Windows autostart, restart, and workspace-identity incident
|
|
4
32
|
|
|
5
33
|
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.
|
package/docs/ENGINEERING.md
CHANGED
|
@@ -55,6 +55,7 @@ Rules:
|
|
|
55
55
|
- Every protocol control message emitted by one side must be explicitly accepted, rejected, or version-gated by the other side, with an end-to-end contract test covering the message name and semantics.
|
|
56
56
|
- State transitions are explicit; readiness is not inferred from a lower-level event. For example, an open WebSocket is not an authenticated relay until `hello_ack` is received.
|
|
57
57
|
- Every externally controlled input is bounded before expensive allocation, traversal, parsing, storage, or execution.
|
|
58
|
+
- Externally controlled string keys must not use prototype-chain membership or truthiness on ordinary objects. Use `Map`, `Set`, `Object.hasOwn`, or null-prototype records for command dispatch, enums, ACLs, form fields, registries, and other key-addressed contracts.
|
|
58
59
|
- Repository text must not contain invisible ASCII controls other than tab, CR, and LF; architecture tests enforce this even when JavaScript syntax remains valid.
|
|
59
60
|
- Persistent mutations use owner-only files, bounded no-follow reads, flushed atomic replacement, and integrity checks appropriate to the data.
|
|
60
61
|
- Exclusive locks use the shared complete-before-visible hard-link claim. Reclamation requires process identity plus a matching file snapshot/token; do not unlink a path merely because an earlier read looked stale.
|
|
@@ -122,6 +123,8 @@ A higher branch count is acceptable only when the function is an explicit state
|
|
|
122
123
|
|
|
123
124
|
Every defect fix includes a regression test that fails for the original reason. Prefer two layers when applicable:
|
|
124
125
|
|
|
126
|
+
Prototype-shaped strings such as `constructor`, `__proto__`, `hasOwnProperty`, `toString`, and `valueOf` are mandatory negative or ordinary-data cases for any new externally indexed object boundary. Byte-bounded text tests must include non-ASCII input and assert the encoded result size, not only JavaScript string length.
|
|
127
|
+
|
|
125
128
|
1. a deterministic test of the extracted policy or lifecycle;
|
|
126
129
|
2. an integration test proving the adapter uses it correctly.
|
|
127
130
|
|
|
@@ -130,8 +133,8 @@ The required matrix includes:
|
|
|
130
133
|
- Linux, macOS, and Windows on the pinned Node/npm baseline;
|
|
131
134
|
- current-tree and reachable-history privacy gates, release-impact enforcement, and exact-commit CI/CodeQL/Governance/Scorecard release gating;
|
|
132
135
|
- package-manifest and sensitive-artifact inspection;
|
|
133
|
-
- generated type checks
|
|
134
|
-
-
|
|
136
|
+
- generated Worker type checks plus strict opt-in checked-JavaScript contracts for high-risk local policy, lifecycle, configuration, path, protocol, and timing boundaries;
|
|
137
|
+
- recursively discovered JavaScript/shell syntax checks and static correctness lint over all production JavaScript, tests, scripts, and browser-extension code;
|
|
135
138
|
- 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
139
|
- concurrent exclusive-lock/atomic-replacement tests, PID-reuse/age tests, and fail-closed service-lifecycle tests;
|
|
137
140
|
- real process-tree timeout/cancellation tests with descendants that ignore graceful termination;
|
|
@@ -151,6 +154,9 @@ Cross-platform tests must not depend on shell syntax, case-sensitive Windows pat
|
|
|
151
154
|
- LOGGING defines operator-facing event semantics.
|
|
152
155
|
- OPERATIONS contains diagnosis and recovery procedures.
|
|
153
156
|
- TESTING records executable coverage and regression expectations.
|
|
157
|
+
- UPGRADING defines the only supported state/protocol transition and rollback unit.
|
|
158
|
+
- SUPPORT defines supported runtimes, diagnostic requirements, and public/private reporting boundaries.
|
|
159
|
+
- GOVERNANCE defines accountable ownership, succession, review, and release authority.
|
|
154
160
|
- CHANGELOG records externally relevant changes, including documentation and workflow changes.
|
|
155
161
|
- PROJECT_STANDARDS defines collaboration, contract, testing, supply-chain, review, and exception policy.
|
|
156
162
|
- TOOL_REFERENCE is generated from the shared MCP tool catalog and must never be maintained by hand.
|
|
@@ -64,6 +64,7 @@ The architectural dependency direction in [ENGINEERING.md](ENGINEERING.md) is no
|
|
|
64
64
|
- **High cohesion and low coupling:** one source file or function owns one coherent responsibility and reason to change; collaboration occurs through narrow explicit contracts rather than cross-layer reach-through.
|
|
65
65
|
- **KISS:** prefer the simplest explicit implementation that satisfies current requirements. Do not introduce factories, registries, inheritance, generic frameworks, or configuration layers without an observed variation that needs them.
|
|
66
66
|
- **DRY:** extract repeated business rules, validation, security boundaries, or lifecycle logic into one authoritative implementation. Do not merge merely similar code when its semantics or failure policy differ.
|
|
67
|
+
- **Exact key membership:** external string keys used for dispatch, enums, ACLs, forms, or registries use `Map`, `Set`, `Object.hasOwn`, or null-prototype records. Prototype-chain membership and truthy ordinary-object lookup are not contract validation.
|
|
67
68
|
- Design patterns are used only when they remove an observed variation or coupling. A direct function or small module is preferred over speculative abstractions.
|
|
68
69
|
|
|
69
70
|
Any deliberate boundary exception must document the dependency, reason, owner, test coverage, and removal condition.
|
|
@@ -94,6 +95,7 @@ Tests follow risk rather than a repository-wide aggregate percentage:
|
|
|
94
95
|
- Protocol changes include producer-consumer contract tests and malformed-input tests.
|
|
95
96
|
- Supported operating systems run the required suite in CI.
|
|
96
97
|
- 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.
|
|
98
|
+
- 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
99
|
|
|
98
100
|
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
101
|
|
|
@@ -124,7 +126,7 @@ Flaky tests are defects. A retry may diagnose environmental instability but may
|
|
|
124
126
|
## 8. Documentation and comments
|
|
125
127
|
|
|
126
128
|
- 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.
|
|
129
|
+
- Architecture, security, testing, operations, logging, policy, upgrade, support, governance, and release documents each own their designated concern; avoid repeating whole procedures across files.
|
|
128
130
|
- Documentation claims a guarantee only when code, configuration, or a test enforces it.
|
|
129
131
|
- Public behavior changes update the changelog and relevant user documentation in the same pull request.
|
|
130
132
|
- Comments explain non-obvious **why**, invariants, external constraints, and safety ordering. They do not narrate self-explanatory syntax.
|
|
@@ -136,7 +138,7 @@ Flaky tests are defects. A retry may diagnose environmental instability but may
|
|
|
136
138
|
|
|
137
139
|
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
140
|
|
|
139
|
-
This repository currently has one human maintainer. Requiring one independent approval would deadlock maintenance and therefore is not enabled.
|
|
141
|
+
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
142
|
|
|
141
143
|
## 10. Exceptions and evolution
|
|
142
144
|
|
package/docs/TESTING.md
CHANGED
|
@@ -54,6 +54,10 @@ The suite includes:
|
|
|
54
54
|
- owner-only directory enforcement rejecting final symlinks, failing closed on POSIX chmod errors, verifying `0700`, and retaining Windows portability; Worker temporary-secret lifecycle coverage for process-start-bound names, valid stale-owner reclamation, ambiguous-owner retention, `0600` mode, deletion failures, and simultaneous deployment/cleanup failures;
|
|
55
55
|
- SARIF security-gate behavior for unknown findings, exact accepted rule/path matches, path mismatch rejection, rationale quality, and exception expiry;
|
|
56
56
|
- deterministic property tests over hostile browser-protocol byte strings, canonical/custom policy combinations, argv bounds/NULs, and a real direct process proving shell metacharacters remain literal argv;
|
|
57
|
+
- prototype-shaped command, action, role, profile, form-field, keyboard, and resource names proving that inherited object properties are never interpreted as dispatch or authority; current-schema malformed OAuth roles are repaired to disabled reviewer accounts with credential revocation;
|
|
58
|
+
- canonical Worker deployment URL extraction proving unrelated `/mcp`, `/healthz`, path-bearing, and wrong-name URLs cannot be persisted as upload evidence;
|
|
59
|
+
- byte-exact UTF-8 DOM-source truncation across emoji and Chinese partial-code-point boundaries, including equality between the reported byte count and the encoded returned source;
|
|
60
|
+
- independently injected service CLI status/install/start/stop/uninstall/remove paths, including provider failure, no selected workspace, no deployed Worker, aliases, and default output/exit adapters;
|
|
57
61
|
- CLI parsing, policy profiles, and client configuration boundaries;
|
|
58
62
|
- live stdio MCP initialization with session instructions, capability resolution, discovery, calls, rich content, sessions, cancellation, managed-job acceptance, and a detached job/finally phase that survives stdio shutdown;
|
|
59
63
|
- live local Worker OAuth registration, the unauthenticated `resource_metadata` challenge, protected-resource and authorization-server discovery, Streamable transport metadata, consent, URL-constructed `303` callbacks including the ChatGPT and hosted Claude redirect URIs with encoded state, PKCE, `offline_access`, form-encoded authorization-code and refresh-token exchanges, access/refresh rotation, stale refresh replay rejection, account-version refresh revocation, authorization-code replay rejection, pending-registration throttling that excludes already authorized DCR clients, exact built-in ChatGPT/Grok browser origins, additive custom origins, unrelated-origin preflight rejection, no CORS response sharing for unrelated or opaque origins, opaque-origin authorization-form routing, exact per-request redirect-origin CSP with narrowly scoped Microsoft regional-consent and final Copilot Studio handoff exceptions, accessible credential-error rendering, protocol negotiation, HMAC-bound MCP session issuance, two-session same-id concurrency, sessionless same-id independence, session-scoped cancellation isolation, same-session duplicate rejection, daemon-backed session bootstrap, dynamic tool advertisement, rich content, daemon replacement, cancellation, malformed daemon JSON/non-object rejection, duplicate hello rejection, and unknown-message closure. The metadata/refresh contract is the path used by Claude DCR and Copilot Studio Dynamic discovery. The same integration runs an `editor` account against a canonical `full` daemon and proves that `server_info` and remote `project_overview` report effective `edit` authority while retaining the full daemon ceiling only in explicitly scoped fields.
|
|
@@ -75,9 +79,11 @@ For deterministic release validation, perform an isolated-profile smoke test wit
|
|
|
75
79
|
|
|
76
80
|
## Critical-module coverage gate
|
|
77
81
|
|
|
78
|
-
`npm run coverage:test` runs selected in-process and lightweight entrypoint fixtures under V8 coverage and enforces per-module baselines
|
|
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.
|
|
79
83
|
|
|
80
|
-
The
|
|
84
|
+
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
|
+
|
|
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.
|
|
81
87
|
|
|
82
88
|
## Additional release checks
|
|
83
89
|
|
|
@@ -122,4 +128,4 @@ The stdio integration test also sends an oversized line, verifies bounded reject
|
|
|
122
128
|
|
|
123
129
|
## Architecture and documentation regression checks
|
|
124
130
|
|
|
125
|
-
`npm run architecture:test` 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.
|
|
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.
|
|
@@ -0,0 +1,32 @@
|
|
|
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.1 keeps local state schema version 6 and policy revision 5 unchanged. Existing 1.2.0 workspaces, named accounts, resource registrations, managed-job history, Worker identity, and browser pairing state are reused without a schema conversion. The package change affects validation and adapter ownership, not the stored authority model.
|
|
8
|
+
|
|
9
|
+
Version 1.2.0 could accept prototype-shaped account roles through malformed administration input. On the first 1.2.1 Worker access, such an account is preserved for recovery but repaired fail-closed: its role becomes `reviewer`, it is disabled, its account version advances, and its authorization codes and tokens are removed. An operator can then assign a valid role, enable the account, and rotate its password through the normal account administration flow. A local policy record with an unknown profile label is normalized to `custom` while retaining its explicit capability fields; an invalid explicit `--profile` is rejected.
|
|
10
|
+
|
|
11
|
+
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.
|
|
12
|
+
|
|
13
|
+
## Normal upgrade
|
|
14
|
+
|
|
15
|
+
1. Finish or cancel ordinary interactive process sessions. Accepted managed jobs may continue independently, but inspect them before replacing the daemon.
|
|
16
|
+
2. Install the new package with the pinned npm procedure in [Getting started](GETTING_STARTED.md).
|
|
17
|
+
3. Run `machine-mcp doctor`.
|
|
18
|
+
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.
|
|
19
|
+
5. Reload the unpacked browser extension. Protocol and packaged-version equality are mandatory; an old extension cannot replace a working compatible connection.
|
|
20
|
+
6. Reconnect MCP clients if they retain stale tool or session metadata.
|
|
21
|
+
|
|
22
|
+
## Upgrade safety
|
|
23
|
+
|
|
24
|
+
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.
|
|
25
|
+
|
|
26
|
+
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.
|
|
27
|
+
|
|
28
|
+
## Rollback
|
|
29
|
+
|
|
30
|
+
Rollback is supported only when the older package understands every persisted schema and protocol already written by the newer package. Version 1.2.1 does not advance local state or policy schemas, so rollback to 1.2.0 remains structurally possible. A repaired malformed account remains a valid disabled reviewer record that 1.2.0 can read. The preferred recovery is still to fix forward because the browser extension and deployed Worker must match the running package exactly, and rollback would restore the defective input validation.
|
|
31
|
+
|
|
32
|
+
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.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "machine-bridge-mcp",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Cross-client MCP bridge for local agent context, structured browser and application automation, files, Git, processes, resources, and durable jobs over stdio or OAuth relay.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,11 +24,15 @@
|
|
|
24
24
|
"scripts",
|
|
25
25
|
"wrangler.jsonc",
|
|
26
26
|
"tsconfig.json",
|
|
27
|
+
"tsconfig.local.json",
|
|
27
28
|
"README.md",
|
|
28
29
|
"SECURITY.md",
|
|
29
30
|
"CHANGELOG.md",
|
|
30
31
|
"CONTRIBUTING.md",
|
|
31
32
|
"docs",
|
|
33
|
+
"CODE_OF_CONDUCT.md",
|
|
34
|
+
"SUPPORT.md",
|
|
35
|
+
"GOVERNANCE.md",
|
|
32
36
|
"LICENSE"
|
|
33
37
|
],
|
|
34
38
|
"scripts": {
|
|
@@ -41,9 +45,9 @@
|
|
|
41
45
|
"prepack": "npm run version:check && npm run privacy:check && npm run release-impact:check",
|
|
42
46
|
"prepublishOnly": "npm run check && npm run version:check && npm run release:check",
|
|
43
47
|
"worker:types": "node scripts/generate-worker-types.mjs",
|
|
44
|
-
"typecheck": "npm run worker:types && tsc -p tsconfig.json --noEmit",
|
|
48
|
+
"typecheck": "npm run worker:types && tsc -p tsconfig.json --noEmit && npm run typecheck:local",
|
|
45
49
|
"syntax": "node scripts/syntax-check.mjs",
|
|
46
|
-
"check": "npm run privacy:check && npm run privacy:test && npm run release-impact:check && npm run release-impact:test && npm run release-state:test && npm run release-ci:test && npm run network-retry:test && npm run worker-deployment:test && npm run relay:test && npm run secure-file:test && npm run worker-secret-file:test && npm run sarif-security:test && npm run security-properties:test && npm run shell:test && npm run architecture:test && npm run markdown:test && npm run project-metadata:test && npm run numbers:test && npm run records:test && npm run state-inventory:test && npm run commit-message:test && npm run policy:test && npm run account:test && npm run policy-docs:check && npm run tool-docs:check && npm run runtime-infrastructure:test && npm run runtime-handlers:test && npm run cli-entrypoint:test && npm run lifecycle:test && npm run logging-structure:test && npm run coverage:test && npm run worker-runtime-infrastructure:test && npm run lint:test && npm run lint && npm run typecheck && npm run syntax && npm run deadline:test && npm run process-lock:test && npm run service-lifecycle:test && npm run service-environment:test && npm run service-platform:test && npm run catalog:test && npm run agent-context:test && npm run capability-ranking:test && npm run browser-command:test && npm run browser-devtools-input:test && npm run browser-service-worker:test && npm run browser-page-automation:test && npm run browser-bridge:test && npm run app-automation:test && npm run self-test && npm run atomic-fs:test && npm run package:test && npm run install:test && npm run ssh-key:test && npm run full-access:test && npm run managed-jobs:test && npm run stdio:integration-test && npm run worker:integration-test && npm run oauth-browser:test",
|
|
50
|
+
"check": "npm run privacy:check && npm run privacy:test && npm run release-impact:check && npm run release-impact:test && npm run release-state:test && npm run release-ci:test && npm run network-retry:test && npm run worker-deployment:test && npm run relay:test && npm run secure-file:test && npm run worker-secret-file:test && npm run sarif-security:test && npm run security-properties:test && npm run shell:test && npm run architecture:test && npm run markdown:test && npm run project-metadata:test && npm run numbers:test && npm run records:test && npm run state-inventory:test && npm run commit-message:test && npm run policy:test && npm run account:test && npm run worker-oauth-controller:test && npm run policy-docs:check && npm run tool-docs:check && npm run runtime-infrastructure:test && npm run runtime-boundaries:test && npm run runtime-handlers:test && npm run cli-entrypoint:test && npm run cli-service:test && npm run lifecycle:test && npm run logging-structure:test && npm run coverage:test && npm run worker-runtime-infrastructure:test && npm run lint:test && npm run lint && npm run typecheck && npm run syntax && npm run deadline:test && npm run process-lock:test && npm run service-lifecycle:test && npm run service-environment:test && npm run service-platform:test && npm run catalog:test && npm run agent-context:test && npm run capability-ranking:test && npm run browser-command:test && npm run browser-devtools-input:test && npm run browser-service-worker:test && npm run browser-page-automation:test && npm run browser-bridge:test && npm run app-automation:test && npm run self-test && npm run atomic-fs:test && npm run package:test && npm run install:test && npm run ssh-key:test && npm run full-access:test && npm run managed-jobs:test && npm run stdio:integration-test && npm run worker:integration-test && npm run oauth-browser:test",
|
|
47
51
|
"worker:dry-run": "wrangler deploy --dry-run",
|
|
48
52
|
"worker:integration-test": "node tests/worker-integration-test.mjs",
|
|
49
53
|
"release:check": "node scripts/github-release.mjs --check",
|
|
@@ -109,7 +113,11 @@
|
|
|
109
113
|
"shell:test": "node tests/shell-test.mjs",
|
|
110
114
|
"deadline:test": "node tests/monotonic-deadline-test.mjs",
|
|
111
115
|
"oauth-browser:test": "node tests/oauth-browser-navigation-test.mjs",
|
|
112
|
-
"worker-deployment:test": "node tests/worker-deployment-test.mjs"
|
|
116
|
+
"worker-deployment:test": "node tests/worker-deployment-test.mjs",
|
|
117
|
+
"typecheck:local": "tsc -p tsconfig.local.json --noEmit",
|
|
118
|
+
"runtime-boundaries:test": "node tests/runtime-boundaries-test.mjs",
|
|
119
|
+
"worker-oauth-controller:test": "node tests/worker-oauth-controller-test.mjs",
|
|
120
|
+
"cli-service:test": "node tests/cli-service-test.mjs"
|
|
113
121
|
},
|
|
114
122
|
"dependencies": {
|
|
115
123
|
"https-proxy-agent": "9.1.0",
|