machine-bridge-mcp 0.4.2 → 0.6.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.
@@ -0,0 +1,82 @@
1
+ # Logging and observability
2
+
3
+ ## Goals
4
+
5
+ Operational logs should answer four questions without becoming a transcript of user activity:
6
+
7
+ 1. Did deployment and relay connection succeed?
8
+ 2. Is the daemon reconnecting, superseded, or unhealthy?
9
+ 3. Did a tool call fail, time out, or become unusually slow?
10
+ 4. Which component and coarse error class should be investigated?
11
+
12
+ Logs are not a command history, content audit trail, or substitute for MCP client approvals.
13
+
14
+ ## Levels
15
+
16
+ The CLI accepts:
17
+
18
+ ```text
19
+ --log-level error|warn|info|debug
20
+ --quiet # alias for error
21
+ --verbose # alias for debug
22
+ ```
23
+
24
+ The default foreground level is `info`. Platform autostart services use `warn`.
25
+
26
+ | Level | Intended events |
27
+ |---|---|
28
+ | `error` | Broken request handlers, relay transport errors, unrecoverable local failures |
29
+ | `warn` | Failed tool calls, disconnections, malformed/oversized relay messages, superseded daemons |
30
+ | `info` | Deployment/startup transitions, successful relay connection, successful calls slower than 30 seconds |
31
+ | `debug` | Routine successful calls, shortened correlation IDs, reconnect timing, cancellation correlation |
32
+
33
+ Routine successful calls are deliberately absent from `info`. A normal sequence of hundreds of tool invocations should not fill the user's terminal or service logs.
34
+
35
+ ## Event fields
36
+
37
+ Default warning/error and slow-call events may include:
38
+
39
+ - component;
40
+ - tool name;
41
+ - duration in milliseconds;
42
+ - coarse error class;
43
+ - relay close code;
44
+ - bounded reconnect delay.
45
+
46
+ Shortened random call identifiers are debug-only. They are useful only for correlating adjacent local events and are not stable audit identifiers.
47
+
48
+ The implementation intentionally omits:
49
+
50
+ - tool arguments;
51
+ - command text or argv;
52
+ - stdin, stdout, and stderr;
53
+ - file, patch, or image content;
54
+ - OAuth request bodies;
55
+ - connection passwords, daemon secrets, authorization codes, and access tokens.
56
+
57
+ Unexpected daemon and Worker failures are reduced to coarse error classes in normal logs. Client-facing tool errors may contain more detail according to the active path-display policy, but those details are not copied into normal operational logs.
58
+
59
+ ## Bounding and redaction
60
+
61
+ Messages, strings, object depth, object key counts, array item counts, and serialized field payloads are bounded. Control characters are neutralized. Fields with secret-like names and known token formats are recursively redacted.
62
+
63
+ This is defense in depth, not content classification. A previously unknown secret format embedded in an ordinary non-secret-named field may evade pattern redaction. For that reason, tool arguments and outputs are omitted rather than merely filtered.
64
+
65
+ ## Files
66
+
67
+ Autostart logs are stored below the state root:
68
+
69
+ ```text
70
+ logs/daemon.out.log
71
+ logs/daemon.err.log
72
+ ```
73
+
74
+ They are owner-only where the platform supports Unix-style permissions. Existing files are tail-trimmed on UTF-8/line boundaries before daemon startup. Because background services use `warn`, normal successful tool traffic should not cause sustained log growth.
75
+
76
+ Each managed job also has owner-only `runner.out.log` and `runner.err.log` files for runner startup/crash diagnostics. Child-step stdout and stderr are captured into bounded job results according to `capture_output`; they are not copied into runner or daemon operational logs. Runner logs are retained with the bounded job directory and removed by job retention cleanup.
77
+
78
+ ## MCP host boundary
79
+
80
+ Machine Bridge does not classify filenames as sensitive and does not block `.env`, password, key, or credential-looking names. The active local policy, local OS permissions, and endpoint-security controls determine what the server itself can read or execute.
81
+
82
+ An MCP host, model provider, desktop application, or platform execution layer may independently deny a request involving credentials or sensitive files. Such a denial occurs before or outside Machine Bridge's file resolver and cannot be disabled by selecting the local `full` profile. Use `server_info`, `machine-mcp status`, and `machine-mcp doctor` to distinguish the active local policy from host-side enforcement.
@@ -0,0 +1,274 @@
1
+ # Managed jobs and local resources
2
+
3
+ ## Problem addressed
4
+
5
+ An MCP conversation is not a durable execution coordinator. A host or connector may reject a later tool call, an approval may be withdrawn, the network may disconnect, or local endpoint-security software may begin denying process creation. A sequence such as:
6
+
7
+ 1. create a helper script;
8
+ 2. connect to a remote server;
9
+ 3. repair the service;
10
+ 4. remove the helper;
11
+
12
+ can therefore stop after step 2 or 3 and leave local or remote temporary state behind.
13
+
14
+ Machine Bridge managed jobs reduce this failure mode by accepting the complete execution and cleanup plan in one call. After acceptance, an independent local runner owns the lifecycle. It does not depend on the MCP socket remaining connected.
15
+
16
+ This mechanism does **not** bypass host, operating-system, or endpoint-security policy. A job snapshots its execution policy/environment at acceptance; later profile changes affect new jobs, while accepted jobs continue until completion or explicit cancellation. The initial `start_job` request must still be permitted, and every local child process remains subject to local security controls.
17
+
18
+ ## Diagnose the blocking layer
19
+
20
+ Use the MCP tool:
21
+
22
+ ```text
23
+ diagnose_runtime
24
+ ```
25
+
26
+ or the local terminal:
27
+
28
+ ```sh
29
+ machine-mcp doctor
30
+ ```
31
+
32
+ Interpretation:
33
+
34
+ | Observation | Likely boundary |
35
+ |---|---|
36
+ | The tool call is rejected before any structured response | MCP host, connector gateway, approval system, or transport |
37
+ | `diagnose_runtime` responds, but `local-process-spawn` fails | Local OS permissions, endpoint security, executable policy, or broken runtime |
38
+ | Process spawn passes but `local-shell` fails | Shell configuration or shell-specific local policy |
39
+ | Managed-job storage fails | State-root permissions, disk, filesystem policy, or endpoint security |
40
+ | A job was accepted and later MCP calls are rejected | The detached job continues; inspect it through local CLI |
41
+
42
+ A successful diagnostic response proves that particular request reached the local daemon. It cannot retrospectively identify a request that the host blocked before delivery.
43
+
44
+ ## Register local resources
45
+
46
+ Secrets and other local-only files should be registered from the user's terminal, not read into the model context:
47
+
48
+ ```sh
49
+ chmod 600 ~/.ssh/racknerd_ed25519
50
+ machine-mcp resource add racknerd-key ~/.ssh/racknerd_ed25519
51
+ machine-mcp resource list
52
+ machine-mcp resource check racknerd-key
53
+ ```
54
+
55
+ Registration stores only canonical path and bounded metadata in owner-only state. It reads the file locally to validate accessibility and size but does not print or send its contents. New jobs see registry changes immediately; the daemon does not need a restart.
56
+
57
+ Unix-like systems reject group/other-readable resource files by default. `--allow-insecure-permissions` is an explicit override. Windows ACLs and extended Unix ACLs cannot be fully represented by the portable mode check, so operators must still inspect platform permissions.
58
+
59
+ Remove an alias with:
60
+
61
+ ```sh
62
+ machine-mcp resource remove racknerd-key
63
+ ```
64
+
65
+ Removing an alias affects new jobs. A job already accepted has an owner-only resource snapshot specification and continues independently.
66
+
67
+ ## Resource injection modes
68
+
69
+ A managed step is argv-based and supports three local resource modes:
70
+
71
+ ### File-path placeholder
72
+
73
+ ```json
74
+ {
75
+ "argv": ["ssh", "-i", "{{resource:racknerd-key}}", "root@example", "true"]
76
+ }
77
+ ```
78
+
79
+ The runner copies the resource into the private job runtime with mode `0600`, substitutes that copy's path, and removes the runtime after cleanup.
80
+
81
+ ### Standard input
82
+
83
+ ```json
84
+ {
85
+ "argv": ["some-program", "--password-stdin"],
86
+ "stdin_resource": "service-password",
87
+ "capture_output": "discard"
88
+ }
89
+ ```
90
+
91
+ ### Environment variable
92
+
93
+ ```json
94
+ {
95
+ "argv": ["some-program"],
96
+ "env_resources": {
97
+ "SERVICE_TOKEN": "service-token"
98
+ },
99
+ "capture_output": "discard"
100
+ }
101
+ ```
102
+
103
+ Environment injection is convenient but may expose a value to same-user process inspection or child processes. Prefer a file path or stdin when the target program supports it.
104
+
105
+ At job acceptance, referenced resources are reopened, bounded, hashed, and recorded in the owner-only active plan. The runner reopens and verifies the hash before copying. A changed resource causes the job to fail rather than silently using different content.
106
+
107
+ ## Job-scoped temporary files
108
+
109
+ Do not create ad hoc helpers in the workspace when the file exists only for one operation. Include it in the job:
110
+
111
+ ```json
112
+ {
113
+ "temporary_files": [
114
+ {
115
+ "name": "repair.js",
116
+ "content": "console.log('repair')"
117
+ }
118
+ ],
119
+ "steps": [
120
+ {
121
+ "argv": ["node", "{{temp:repair.js}}"]
122
+ }
123
+ ]
124
+ }
125
+ ```
126
+
127
+ Available placeholders are:
128
+
129
+ ```text
130
+ {{temp:name}}
131
+ {{resource:name}}
132
+ {{job:runtime}}
133
+ {{job:workspace}}
134
+ ```
135
+
136
+ Temporary files live only below the private job runtime and are removed in the runner's final cleanup path. This is preferable to writing into `Codex/daily/ops`, `/tmp`, or a remote home directory and relying on a later MCP call to delete the file.
137
+
138
+ For a remote shell program, avoid a remote helper entirely when possible:
139
+
140
+ ```json
141
+ {
142
+ "steps": [
143
+ {
144
+ "argv": [
145
+ "ssh",
146
+ "-i",
147
+ "{{resource:racknerd-key}}",
148
+ "root@example",
149
+ "sh",
150
+ "-s"
151
+ ],
152
+ "stdin": "set -eu\n# repair commands here\n"
153
+ }
154
+ ]
155
+ }
156
+ ```
157
+
158
+ The script travels through the SSH process stdin and is not stored as a remote file.
159
+
160
+ ## Finally steps
161
+
162
+ A job can contain ordered main steps and ordered `finally_steps`:
163
+
164
+ ```json
165
+ {
166
+ "name": "remote maintenance",
167
+ "steps": [
168
+ {
169
+ "argv": ["ssh", "root@example", "perform-maintenance"]
170
+ }
171
+ ],
172
+ "finally_steps": [
173
+ {
174
+ "argv": ["ssh", "root@example", "rm", "-f", "/tmp/maintenance-helper"],
175
+ "allow_failure": true
176
+ }
177
+ ]
178
+ }
179
+ ```
180
+
181
+ Finally steps are attempted after success, failure, timeout, or cancellation. Cancellation is delivered through an owner-only marker polled by the runner; the runner terminates the current child process tree and remains alive to execute cleanup. This avoids platform-specific signal behavior killing the coordinator itself. If a runner is interrupted, the next daemon start or local `machine-mcp job ...` command detects the dead runner, removes stale private resource copies, and runs the finally phase in recovery mode.
182
+
183
+ Automatic dead-runner recovery is attempted at most three times; persistent failure becomes `recovery_exhausted` to avoid an endless restart loop. Cleanup is best effort, not mathematically guaranteed. Power loss, disk failure, permanent account loss, or a local security product that denies the cleanup executable can still prevent it. Finally steps should therefore be idempotent and safe to run more than once.
184
+
185
+ ## Two-phase local approval
186
+
187
+ If the MCP host rejects execution-class tools but still allows state changes, use:
188
+
189
+ ```text
190
+ stage_job
191
+ ```
192
+
193
+ This performs the same schema, cwd, resource, size, and permission validation as `start_job`, but records status `staged` and launches no process. The response includes the local approval command:
194
+
195
+ ```sh
196
+ machine-mcp job inspect JOB_ID
197
+ machine-mcp job approve JOB_ID
198
+ # or after a separate review, non-interactively:
199
+ machine-mcp job approve JOB_ID --yes
200
+ ```
201
+
202
+ `job inspect` displays the reviewable plan, including argv, ordinary environment overrides, stdin, temporary helper content, and finally steps, while omitting registered resource source paths and per-resource hashes. The overall `plan_sha256` can be compared with the value returned by `stage_job`.
203
+
204
+ Local approval is a new operator authorization. It intentionally does not depend on the current MCP execution profile: a plan staged under a write-capable profile can be reviewed and approved from the terminal even when the connector is not allowed to execute. The plan retains the filesystem scope and environment mode captured when it was staged.
205
+
206
+ Before approval:
207
+
208
+ - no main step runs;
209
+ - no finally step runs;
210
+ - no resource is copied into a runtime directory;
211
+ - cancelling produces `cancelled_before_start` and deletes the plan.
212
+
213
+ Staged plans count toward the 50-item retention limit and expire with the seven-day job retention policy. They are not considered active processes and do not independently block uninstall after the normal uninstall confirmation.
214
+
215
+ ## Submit and inspect
216
+
217
+ Through MCP:
218
+
219
+ ```text
220
+ stage_job
221
+ start_job
222
+ list_jobs
223
+ read_job
224
+ cancel_job
225
+ ```
226
+
227
+ From the local terminal, including after an MCP host blocks further execution calls:
228
+
229
+ ```sh
230
+ machine-mcp job list
231
+ machine-mcp job inspect JOB_ID
232
+ machine-mcp job approve JOB_ID [--yes]
233
+ machine-mcp job cancel JOB_ID
234
+ ```
235
+
236
+ A local JSON fallback is also available:
237
+
238
+ ```sh
239
+ machine-mcp job submit plan.json
240
+ ```
241
+
242
+ The plan format is the same object accepted by `start_job`.
243
+
244
+ ## Output and secret handling
245
+
246
+ Step output is bounded to 64 KiB per stream and a shared 256 KiB capture budget per job, then stored in owner-only job results. Exact registered resource paths and exact resource content are replaced before results are returned. Common exact base64 and hexadecimal forms are also replaced for bounded resources.
247
+
248
+ This redaction is defense in depth, not a data-loss-prevention guarantee. It cannot reliably detect:
249
+
250
+ - partial secrets;
251
+ - encrypted, compressed, hashed, or otherwise transformed values;
252
+ - values copied from the full inherited environment rather than registered resources;
253
+ - application-specific encodings.
254
+
255
+ Use:
256
+
257
+ ```json
258
+ { "capture_output": "discard" }
259
+ ```
260
+
261
+ for any step that may echo a credential. In discard mode stdout and stderr are consumed but not retained or returned.
262
+
263
+ Never place a secret directly in `argv`, `env`, `stdin`, a temporary file's `content`, or a plan JSON file. Use a registered resource alias.
264
+
265
+ ## Persistence and privacy
266
+
267
+ Per-workspace jobs are stored below the owner-only profile directory. Active jobs retain an owner-only plan for crash recovery. After a terminal status is committed, the full plan is deleted, including argv, stdin, embedded temporary-file content, and resource source paths.
268
+
269
+ Retained public job data contains bounded status and redacted results. Up to 50 jobs are retained for up to seven days. Private runtime copies are removed after the finally phase. Runner stdout/stderr log files contain only runner-level diagnostics; step output is not written to those operational logs.
270
+
271
+ Process sessions and managed jobs have different semantics:
272
+
273
+ - process sessions are interactive, memory-only, and die with the daemon connection;
274
+ - managed jobs are non-interactive, persistent, detached, and designed to survive MCP disconnection.
@@ -8,30 +8,70 @@ machine-mcp doctor
8
8
  machine-mcp service status
9
9
  ```
10
10
 
11
- `status` prints redacted profile state and verifies the deployed Worker version. `doctor` checks Node.js, the package-installed Wrangler binary, Cloudflare login, and Worker health. Public `/healthz` output contains only server identity and version; daemon details require an authenticated `server_info` call.
11
+ `status` prints redacted profile state and verifies the deployed Worker version. Resource source paths remain redacted. `doctor` checks Node.js, the package-installed Wrangler binary, Cloudflare login, Worker health, and the same fixed local filesystem/process/shell/job-storage/resource probes exposed by `diagnose_runtime`. Public `/healthz` output contains only server identity and version; daemon details require an authenticated `server_info` call.
12
+
13
+ ### Blocking-layer decision table
14
+
15
+ | Result | Interpretation |
16
+ |---|---|
17
+ | No structured result because the host rejects the call | Host/connector approval or safety layer, or transport before daemon delivery |
18
+ | `mcp-host-to-daemon` passes but `local-filesystem` fails | Local state/runtime permissions, disk policy, sandbox, or endpoint security |
19
+ | Filesystem passes but `local-process-spawn` fails | Local executable policy, endpoint security, OS permissions, or damaged Node runtime |
20
+ | Direct spawn passes but `local-shell` fails | Shell path/profile/policy problem |
21
+ | `managed-job-storage` fails | Owner-only profile/job directory cannot be used |
22
+ | Registered resource is unavailable | File moved, permissions changed, size exceeded, or local access denied |
23
+
24
+ A successful diagnostic result applies only to that probe. An MCP host can still deny a later call based on its own request context.
12
25
 
13
26
  ## Logs
14
27
 
15
28
  Remote autostart logs are stored under the state root in `logs/daemon.out.log` and `logs/daemon.err.log`. Files are owner-only where supported and tail-trimmed before daemon startup.
16
29
 
17
- Structured operational events may include:
30
+ Logging is level-based:
31
+
32
+ ```text
33
+ error unrecoverable local/transport failures
34
+ warn failed calls, disconnects, malformed relay events
35
+ info startup/deploy/connect transitions and calls slower than 30 seconds
36
+ debug routine successful calls, shortened correlation IDs, cancellation/reconnect details
37
+ ```
38
+
39
+ Foreground mode defaults to `info`; autostart uses `warn`. Use `--verbose` or `--log-level debug` only for diagnosis. `--quiet` is an alias for `--log-level error`.
40
+
41
+ Normal logs intentionally omit tool arguments, file/patch/image content, command text and argv, stdin/stdout/stderr, OAuth request bodies, connection credentials, authorization codes, and tokens. Unexpected daemon and Worker failures use coarse error classes rather than raw exception messages. Messages and structured fields are bounded and secret-like fields/token formats are redacted.
18
42
 
19
- - component and severity;
20
- - tool name;
21
- - shortened random call identifier;
22
- - duration and success/failure;
23
- - coarse error class;
24
- - connection/reconnect status.
43
+ See [LOGGING.md](LOGGING.md) for the event contract and MCP-host boundary. Cloudflare observability is sampled and is not a complete audit log.
25
44
 
26
- They intentionally omit:
45
+ ## Managed jobs and local recovery
27
46
 
28
- - file contents and image data;
29
- - write, edit, or patch payloads;
30
- - command argv, shell text, stdin, stdout, and stderr;
31
- - MCP connection passwords, daemon secrets, authorization codes, and access tokens;
32
- - full request bodies.
47
+ Register local-only resources from the terminal:
48
+
49
+ ```sh
50
+ machine-mcp resource add NAME FILE_PATH
51
+ machine-mcp resource list
52
+ machine-mcp resource check NAME
53
+ machine-mcp resource remove NAME
54
+ ```
55
+
56
+ Inspect detached jobs even when the MCP host no longer permits execution tools:
57
+
58
+ ```sh
59
+ machine-mcp job list
60
+ machine-mcp job inspect JOB_ID
61
+ machine-mcp job approve JOB_ID [--yes]
62
+ machine-mcp job cancel JOB_ID
63
+ machine-mcp job submit plan.json
64
+ ```
33
65
 
34
- Unexpected Worker failures log endpoint path and error class rather than raw exception messages. Cloudflare observability is sampled and is not a complete audit log.
66
+ Registry changes apply to newly submitted jobs without restarting the daemon. Active jobs use the resource snapshot accepted with their plan.
67
+
68
+ Policy changes affect new direct submissions. Cancel accepted running jobs explicitly when revoking execution authority. A staged plan launches only after local `job approve`, which is an independent operator authorization. A managed job transitions through `queued`, `running`, `cleaning`, and a terminal status such as `succeeded`, `failed`, or `cancelled`. Cleanup-specific terminal variants report a failed finally phase. If a runner PID dies, the next daemon/job-CLI start marks the job interrupted, removes stale private runtime copies, and runs the finally phase in recovery mode. Automatic recovery is capped at three attempts; persistent failure becomes `recovery_exhausted`.
69
+
70
+ Use job-scoped `temporary_files` for local helpers. For remote maintenance, prefer `ssh ... sh -s` with the remote script in step `stdin`; this avoids remote temporary scripts. Explicit remote cleanup belongs in idempotent `finally_steps`.
71
+
72
+ Uninstall refuses to remove local state while any managed job remains active. Active plans are needed for recovery and are owner-only. Terminal jobs delete their full plans. Bounded redacted results and runner-level diagnostics remain for up to seven days/50 jobs. Step output is never copied to ordinary daemon logs.
73
+
74
+ See [MANAGED_JOBS.md](MANAGED_JOBS.md).
35
75
 
36
76
  ## Reconnect and replacement
37
77
 
@@ -58,26 +98,43 @@ Defense-in-depth limits include:
58
98
  - command timeout: 1–600 seconds;
59
99
  - process-session read wait: at most 30 seconds;
60
100
  - direct directory result: 10,000 entries and 4 MiB of path metadata;
61
- - recursive walk: 200,000 visited entries.
101
+ - recursive walk: 200,000 visited entries;
102
+ - managed jobs: 50 retained, seven-day retention;
103
+ - managed-job steps: 16 main plus 16 finally;
104
+ - managed-job timeout: 1–3,600 seconds per step;
105
+ - managed-job output: 64 KiB per stream and 256 KiB total captured across one job;
106
+ - registered resources: 64, 1 MiB each, 8 MiB referenced per job;
107
+ - job-scoped temporary files: 16 files, 512 KiB total content.
62
108
 
63
109
  ## Upgrade behavior
64
110
 
65
- Version 0.4.1 changes the default for newly selected workspaces to the maximum-permission `full` profile. Existing state retains its saved policy. To intentionally migrate an older workspace to the new default:
111
+ Version 0.5 records policy origin and revision. A state entry matching the exact legacy implicit-default shape—write enabled, shell enabled, workspace-confined paths, isolated environment, and relative output—is migrated once to the current `full` default. Explicit named profiles and identified custom policies are preserved.
112
+
113
+ `full` enables writes, direct processes, process sessions, shell execution, unrestricted direct filesystem paths, absolute path output, and the complete parent environment. It does not override operating-system access controls or independent MCP-host/platform policy.
114
+
115
+ Inspect effective policy with:
66
116
 
67
117
  ```sh
68
- machine-mcp --workspace /path/to/project --profile full
118
+ machine-mcp status
119
+ machine-mcp doctor
69
120
  ```
70
121
 
71
- `full` enables writes, direct processes, process sessions, shell execution, unrestricted direct filesystem paths, absolute path output, and the complete parent environment. Use `agent`, `edit`, or `review` when that authority is unnecessary.
122
+ Select a policy explicitly with:
123
+
124
+ ```sh
125
+ machine-mcp --workspace /path/to/project --profile full
126
+ machine-mcp --workspace /path/to/project --profile agent
127
+ ```
72
128
 
73
- A remote policy change is saved locally, propagated in the daemon handshake, and persisted in the autostart definition.
129
+ A remote policy change is saved locally, propagated in the daemon handshake, and loaded by autostart from owner-only state.
74
130
 
75
131
  ## Incident response
76
132
 
77
133
  After suspected credential or client compromise:
78
134
 
79
135
  1. stop foreground and autostart daemons;
80
- 2. run `machine-mcp rotate-secrets --no-print-credentials`;
136
+ 2. run `machine-mcp rotate-secrets`;
81
137
  3. restart without broad flags and redeploy;
82
- 4. inspect Cloudflare account access, Worker configuration, local state permissions, and service logs;
83
- 5. remove the Worker and local state if continued remote access is unnecessary.
138
+ 4. inspect Cloudflare account access, Worker configuration, local state/resource permissions, managed-job results, and service logs;
139
+ 5. cancel active managed jobs and remove compromised resource aliases;
140
+ 6. remove the Worker and local state if continued remote access is unnecessary.
package/docs/TESTING.md CHANGED
@@ -23,23 +23,28 @@ The suite includes:
23
23
  - author-email privacy in `git_log`;
24
24
  - isolated command HOME/temp/cache behavior;
25
25
  - one-shot timeout, descendant termination, cancellation, and process-session interaction;
26
+ - layered fixed runtime diagnostics for filesystem, direct process, shell, managed-job storage, and resource availability;
27
+ - local resource CLI registration, permission checks, dynamic reload, state-path redaction, and content non-disclosure;
28
+ - managed-job staging/local approval/cancel-before-start, detachment, job-scoped temporary files, resource hash verification/redaction, discard capture, finally execution, cancellation escalation, plan scrubbing, and dead-runner recovery;
26
29
  - daemon/startup locking and state corruption recovery;
27
- - guarded state-root removal and legacy-state migration;
28
- - log redaction, control-character handling, and service-log trimming;
30
+ - guarded state-root removal, schema migration, policy-origin persistence, and legacy implicit-default migration;
31
+ - no filename-based sensitive-file denial under unrestricted policy;
32
+ - log redaction, control-character handling, message/field bounds, default success-log suppression, and service warning-level configuration;
29
33
  - CLI parsing, policy profiles, and client configuration boundaries;
30
- - live stdio MCP initialization, discovery, calls, rich content, sessions, cancellation, and continued responsiveness;
34
+ - live stdio MCP initialization, discovery, calls, rich content, sessions, cancellation, managed-job acceptance, and a detached job/finally phase that survives stdio shutdown;
31
35
  - live local Worker OAuth registration, consent, PKCE, token replay rejection, throttling, CORS, protocol negotiation, dynamic tool advertisement, rich content, daemon replacement, and cancellation.
32
36
 
33
37
  ## Additional release checks
34
38
 
35
39
  ```sh
36
40
  npm run worker:dry-run
41
+ npm audit --audit-level=high
37
42
  npm audit --omit=dev --audit-level=high
38
43
  npm pack --dry-run
39
44
  npm run version:check
40
45
  ```
41
46
 
42
- GitHub Actions executes the main suite on Linux, macOS, and Windows. Node 22 and 24 are covered on Linux; Node 22 is covered on macOS and Windows. A separate package-audit job runs production dependency auditing and a dry-run package build. Dependency and GitHub Actions updates are monitored by Dependabot.
47
+ GitHub Actions executes the main suite on Linux, macOS, and Windows. Node 22 and 24 are covered on Linux; Node 22 is covered on macOS and Windows. A separate package-audit job audits both the complete dependency graph and the production-only graph, then performs a dry-run package build. Dependency and GitHub Actions updates are monitored by Dependabot.
43
48
 
44
49
  ## Test design rules
45
50
 
@@ -48,4 +53,7 @@ GitHub Actions executes the main suite on Linux, macOS, and Windows. Node 22 and
48
53
  - Every bounded resource needs an over-limit test.
49
54
  - Every multi-stage mutation needs a no-partial-commit test.
50
55
  - Every remote call correlation change needs daemon replacement and cancellation coverage.
51
- - Logs and public metadata should be tested for absence of sensitive fields, not only presence of expected fields.
56
+ - Every durable workflow needs disconnect, cancellation, cleanup-failure, dead-runner, and plan-scrubbing coverage.
57
+ - Secret-bearing resource tests must assert absence of raw, path, base64, and hex forms from MCP-visible results.
58
+ - Logs and public metadata should be tested for absence of sensitive fields, arguments, outputs, and routine success noise—not only presence of expected fields.
59
+ - Cross-platform tests must avoid shell syntax, URL-path conversion, and executable-shim assumptions specific to one operating system.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "machine-bridge-mcp",
3
- "version": "0.4.2",
3
+ "version": "0.6.0",
4
4
  "description": "Cross-client MCP bridge for policy-controlled local files, Git, images, patches, and processes over stdio or OAuth-protected remote relay.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -39,23 +39,24 @@
39
39
  "prepublishOnly": "npm run check && npm run version:check && npm run release:check",
40
40
  "worker:types": "wrangler types src/worker/worker-configuration.d.ts",
41
41
  "typecheck": "npm run worker:types && tsc -p tsconfig.json --noEmit",
42
- "syntax": "sh -n mbm && node --check bin/machine-mcp.mjs && node --check src/local/cli.mjs && node --check src/local/daemon.mjs && node --check src/local/patch.mjs && node --check src/local/process-sessions.mjs && node --check src/local/tools.mjs && node --check src/local/stdio.mjs && node --check src/local/state.mjs && node --check src/local/shell.mjs && node --check src/local/service.mjs && node --check src/local/log.mjs && node --check scripts/sync-worker-version.mjs && node --check scripts/github-release.mjs && node --check tests/worker-integration-test.mjs && node --check tests/stdio-integration-test.mjs && node --check tests/catalog-test.mjs && node --check tests/local-self-test.mjs && node --check tests/daemon-self-test.mjs",
43
- "check": "npm run typecheck && npm run syntax && npm run catalog:test && npm run self-test && npm run stdio:integration-test && npm run worker:integration-test",
42
+ "syntax": "sh -n mbm && node --check bin/machine-mcp.mjs && node --check src/local/cli.mjs && node --check src/local/daemon.mjs && node --check src/local/patch.mjs && node --check src/local/process-sessions.mjs && node --check src/local/tools.mjs && node --check src/local/stdio.mjs && node --check src/local/state.mjs && node --check src/local/shell.mjs && node --check src/local/service.mjs && node --check src/local/log.mjs && node --check src/local/managed-jobs.mjs && node --check src/local/job-runner.mjs && node --check scripts/sync-worker-version.mjs && node --check scripts/github-release.mjs && node --check tests/worker-integration-test.mjs && node --check tests/stdio-integration-test.mjs && node --check tests/catalog-test.mjs && node --check tests/local-self-test.mjs && node --check tests/daemon-self-test.mjs && node --check tests/managed-jobs-test.mjs",
43
+ "check": "npm run typecheck && npm run syntax && npm run catalog:test && npm run self-test && npm run managed-jobs:test && npm run stdio:integration-test && npm run worker:integration-test",
44
44
  "worker:dry-run": "wrangler deploy --dry-run",
45
45
  "worker:integration-test": "node tests/worker-integration-test.mjs",
46
46
  "release:check": "node scripts/github-release.mjs --check",
47
47
  "release:publish": "node scripts/github-release.mjs --publish",
48
48
  "release:backfill": "node scripts/github-release.mjs --backfill",
49
49
  "stdio:integration-test": "node tests/stdio-integration-test.mjs",
50
- "catalog:test": "node tests/catalog-test.mjs"
50
+ "catalog:test": "node tests/catalog-test.mjs",
51
+ "managed-jobs:test": "node tests/managed-jobs-test.mjs"
51
52
  },
52
53
  "dependencies": {
53
- "wrangler": "^4.110.0",
54
- "ws": "^8.18.3"
54
+ "wrangler": "4.110.0",
55
+ "ws": "8.21.0"
55
56
  },
56
57
  "devDependencies": {
57
58
  "@types/node": "^22.20.1",
58
- "typescript": "^5.9.3"
59
+ "typescript": "^7.0.2"
59
60
  },
60
61
  "keywords": [
61
62
  "mcp",