machine-bridge-mcp 3.0.0-beta.195 → 3.0.0-beta.197

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 CHANGED
@@ -1,9 +1,15 @@
1
1
  # Changelog
2
2
 
3
- ## 3.0.0-beta.195 - 2026-09-18
3
+ ## 3.0.0-beta.197 - 2026-09-30
4
4
 
5
- - Update the fast-check development dependency from 4.9.0 to 4.10.0 and refresh its resolved lockfile entry.
6
- - Preserve the beta.194 Wrangler/toolchain and relay changes while advancing release identity to beta.195 so this dependency update receives independent full verification, live candidate canary, and exact acceptance evidence.
5
+ - Pin source tooling and the integrity-verified hardened npm bootstrap to brace-expansion 5.0.12, fixing the newly disclosed parser denial-of-service advisories. Preserve clean global consumer installs without postinstall hooks; declare the audited private Wrangler build provider and supply its executable runner before native cf builds.
6
+
7
+ - Migrate Worker builds and deployments to native cf configuration and prebuilt artifacts; preserve the Worker name, SQLite Durable Object export, rate-limit namespaces, existing variables, and secrets.
8
+ - Require structured cf authentication before unattended activation and bind deployment fingerprints to the exact private source snapshot and pinned toolchain.
9
+
10
+ - Add an isolated, exact cf deployment toolchain with a compatible Wrangler builder and patched Undici.
11
+ - Verify the deterministic compatibility artifact for cf beta.5 before its network factory runs; reject unknown or tampered bundle bytes.
12
+ - Synchronize the package, Worker, and browser extension prerelease version declarations.
7
13
 
8
14
  ## Historical releases
9
15
 
package/README.md CHANGED
@@ -119,7 +119,9 @@ Run the CLI in the workspace to expose:
119
119
  machine-mcp --workspace /path/to/project
120
120
  ```
121
121
 
122
- On first remote start, Machine Bridge creates workspace-scoped state, signs in to Wrangler when needed, deploys one stable Worker, creates the initial `owner` account, installs user-level autostart unless disabled, starts the outbound daemon connection, and prints the MCP URL and one-time owner password.
122
+ On first remote start, Machine Bridge creates workspace-scoped state, signs in with `cf auth login --scopes account-settings.read user-details.read workers-scripts.read workers-scripts.write workers-scripts.bind workers-routes.read workers-routes.write workers-observability.read workers-observability.write offline` when needed, builds and deploys one stable Worker through `cf`, creates the initial `owner` account, installs user-level autostart unless disabled, starts the outbound daemon connection, and prints the MCP URL and one-time owner password.
123
+
124
+ Machine Bridge, including Worker deployment, requires Node.js 26 or later. `cf` has its own login, separate from Wrangler. Before unattended activation, complete `cf auth login` in an ordinary owner terminal; for multiple Cloudflare accounts, set `CLOUDFLARE_ACCOUNT_ID` to the existing Worker's account. The pinned deployment tools stay in Machine Bridge's private toolchain, outside the consumer runtime dependencies. Native `cloudflare.config.ts` controls deployment; the retained `wrangler.jsonc` is used for deterministic runtime type generation and legacy maintenance commands.
123
125
 
124
126
  Use the printed endpoint in the hosted client:
125
127
 
@@ -174,7 +176,7 @@ The shared source of truth is `src/shared/policy-contract.json`. The generated m
174
176
 
175
177
  For routine remote health checks, prefer `server_info` with `detail: "summary"`; the empty/default call remains full diagnostics and, for owner/full callers, includes a privacy-bounded durable continuity summary that survives Worker isolate replacement without retaining identities, call IDs, tool arguments, results, endpoints, or close reasons. For routine workspace inventory, `project_overview` also accepts `detail: "summary"`; it preserves policy/tool counts and top-level names/types without repeating exact tool arrays, account identity, routing fingerprints, or per-entry paths/sizes. Its empty/default call likewise remains full for compatibility. For remote calls, `server_info.authorization.effective_policy` and, when exact membership is needed, the full projection's `effective_tools` are authoritative. Daemon policy and tools describe only the local capability ceiling before account-role and host-side filtering.
176
178
 
177
- `tools/list` is the authenticated account's current discovery catalog. Discovery instructions and tool descriptions carry execution/orchestration semantics, so both `server/discover` and `tools/list` advertise `ttlMs=0`. Current MCP 2026-07-28 remote discovery also advertises `tools.listChanged=true`: a client that opts into `toolsListChanged` through `subscriptions/listen` receives a correlated acknowledgement and level-trigger `notifications/tools/list_changed` event, then re-fetches `tools/list`. The request-scoped subscription remains open until explicit cancellation or the advertised bounded server lease expires; the lease is a fail-safe for HTTP disconnects that the Worker runtime cannot reliably observe and does not replace the initial level-trigger/refetch contract. Every host-visible tool description carries `Tool schema generation N`; `server_info.tool_delivery` exposes the current `tool_schema_generation`, `tool_schema_server_version`, and `tool_list_ttl_ms`, while explicitly reporting that Machine Bridge cannot observe which schema generation an external host has actually cached. A generation change therefore requires the subscription/refetch path or another host-side schema refresh plus post-activation verification. Discovery is not authority: every `tools/call` is still intersected with the current end-to-end-ready daemon policy and tool ceiling, and fails retryably with `unavailable` when no daemon is ready. `server_info.tool_delivery` also distinguishes the advertised catalog from the currently effective daemon/account intersection. WebSocket is the preferred daemon transport: verified ready traffic resumes immediately, but reconnect attempt history resets only after five seconds of generation-stable ready uptime so a shorter ready/close flap keeps its prior exponential backoff position. It requests a protocol-level Ping after five seconds and gives an actually dispatched Ping its full ten-second Pong deadline, then uses one independent fifteen-second application-confirmation window before a ready WSS may be terminated as a transport black hole. A protocol Pong or explicit application `pong` during that second stage preserves WSS; ordinary tool/control inbound remains receive-side evidence and cannot clear transport suspicion, while local event-loop stalls cancel remote suspicion and use the separate recovery-grace path. The periodic application heartbeat remains twenty-five/seventy-five seconds after end-to-end readiness, and the Worker keeps a wider ninety-second fallback. WSS connect attempts have a thirty-second outer budget. Signed HTTPS is independent of that budget: on first-stage WSS suspicion the same root-certified ephemeral device identity prewarms HTTPS in standby, and a real WSS loss promotes that path to exact-generation takeover while aborting any obsolete standby request. Fallback requests bind the fixed route/origin/server/version, a short-lived nonce, timestamp, and exact body hash; they use a seven-second request deadline, twelve-second liveness window, one-second ordinary poll cadence, and a 750 ms minimum request-start interval. The first authenticated exchange enters probing immediately, so verified readiness requires at most two bounded exchanges rather than a separate challenge round trip. Candidate → probing → verified-ready handover prevents the Worker from dispatching until the daemon has processed `ready_ack` and returned sequenced `https_ready`; a same-instance takeover may retire a Worker-side zombie WSS only after the signed candidate preconditions pass. Both directions use bounded contiguous transport sequences, so a lost HTTP response retransmits the same transport envelope and duplicates are discarded before business handling; this does not restore MCP sessions, recovery GET, `Last-Event-ID`, or public result persistence. Same-instance `resume_calls` / `resume_calls_ack` remains authoritative for in-flight ownership. A planned daemon shutdown is a different boundary: before a ready runtime closes its relay it sends `daemon_draining`; the Worker settles calls still owned by that daemon with structured `daemon_planned_drain` recovery and acknowledges the drain. In-flight `read_job` is explicitly read-only recoverable with `recovery.mode=read_same_job` plus the original `job_id`; resume by reading that same job after reconnect. This does not transfer an executing call to a new daemon process, whose random instance identity remains intentionally distinct, and it cannot revive an external assistant turn that has already ended. The daemon sends `resume_calls_ack.missing_ids` only after replacement readiness, only for IDs absent from both its active-call set and unacknowledged-result ledger, and only while it still has fail-closed proof that missing ownership means the call did not execute locally. If a completed-but-unacknowledged result expires, `diagnose_runtime.runtime.relay_result_recovery.automatic_redelivery_safe` becomes false and missing-ID automatic redelivery is disabled rather than risking duplicate side effects. A safe proven-undelivered call may be retransmitted with the same call ID, arguments, authority, and a reduced timeout inside the original execution deadline; a call that may have executed is never automatically replayed. Separately, if that same daemon already executed a call and its terminal result is delayed by the transport break, the Worker may retain the original in-memory settlement owner for one fixed fifteen-second window beyond its original settlement deadline, including when that original settlement deadline was already at the ordinary per-tool ceiling. That delivery-only extension cannot authorize redelivery or new execution, cannot accumulate across repeated handovers, and does not create client-visible replay or durable result state. A new call may wait up to fifteen seconds for a verified daemon channel, but measured recovery time is deducted from that call's original execution budget instead of extending the hosted foreground envelope. Hosted synchronous calls otherwise retain their ordinary 20-second execution plus separate five-second Worker settlement margin; configurable browser/application tools retain 20-second ordinary defaults, compound `computer_observe` / `computer_act` retain 30-second defaults, and the explicit remote maximum remains 45 seconds. Remote `exec_command`, `run_process`, and `run_local_command` require a caller-held `idempotency_key`, commit a principal-bound one-step managed job, and remain recoverable through bounded same-response `read_job` follow-up when the current task needs terminal state. Hosted active `read_job` uses a server-side 40-second long-poll by default and returns earlier on meaningful job progress or terminal state; `wait_ms=0` requests an immediate checkpoint, while every public hosted call is capped at 60 seconds. The default remains 40 seconds: live hosted evidence carried both the default and an explicit 60-second read, while beta.151 later reproduced `mcp_network_error` on a second explicit 180-second read even though the Worker-to-daemon WebSocket remained continuously ready. Longer tasks therefore keep the same `job_id` and use another server-paced read rather than one overlong host request. This keeps long-task waiting inside Machine Bridge within the demonstrated per-call host lifetime; the 40-second interval also bounds interaction density to at most 150 reads for a synthetic unchanged 100-minute job, but that arithmetic does not prove that one assistant response can survive the aggregate duration or call count. If a real host/tool boundary ends a response, preserve the durable identifier and resume the same operation later rather than resubmitting its side effect. `start_process` remains daemon-lifetime interactive state; hosted `read_process` permits paced same-response follow-up, defaults an omitted relay `wait_ms` to the one-second blocking cap, and paces another would-block read inside the fifteen-second cooldown within that same MCP call until output/exit or the cooldown boundary. Active job/process reads do not force a user-turn handoff. Callers must not infer or preempt a host/tool deadline from elapsed wall-clock time: while calls continue to be accepted and the task still needs the result, bounded same-response follow-up may continue. Handoff is reserved for an actual observed host/tool boundary, required external input or authorization, or an explicit user checkpoint, while busy loops and status-surface substitution remain prohibited. The durable process façade preserves account/tool authority and delegated workspace sandbox rather than expanding privileges.
179
+ `tools/list` is the authenticated account's current discovery catalog. Discovery instructions and tool descriptions carry execution/orchestration semantics, so both `server/discover` and `tools/list` advertise `ttlMs=0`. Current MCP 2026-07-28 remote discovery also advertises `tools.listChanged=true`: a client that opts into `toolsListChanged` through `subscriptions/listen` receives a correlated acknowledgement and level-trigger `notifications/tools/list_changed` event, then re-fetches `tools/list`. The request-scoped subscription remains open until explicit cancellation or the advertised bounded server lease expires; the lease is a fail-safe for HTTP disconnects that the Worker runtime cannot reliably observe and does not replace the initial level-trigger/refetch contract. Every host-visible tool description carries `Tool schema generation N`; `server_info.tool_delivery` exposes the current `tool_schema_generation`, `tool_schema_server_version`, and `tool_list_ttl_ms`, while explicitly reporting that Machine Bridge cannot observe which schema generation an external host has actually cached. A generation change therefore requires the subscription/refetch path or another host-side schema refresh plus post-activation verification. Discovery is not authority: every `tools/call` is still intersected with the current end-to-end-ready daemon policy and tool ceiling, and fails retryably with `unavailable` when no daemon is ready. `server_info.tool_delivery` also distinguishes the advertised catalog from the currently effective daemon/account intersection. WebSocket is the preferred daemon transport: verified ready traffic resumes immediately, but reconnect attempt history resets only after five seconds of generation-stable ready uptime so a shorter ready/close flap keeps its prior exponential backoff position. It requests a protocol-level Ping after five seconds and gives an actually dispatched Ping its full ten-second Pong deadline, then uses one independent fifteen-second application-confirmation window before a ready WSS may be terminated as a transport black hole. A protocol Pong or explicit application `pong` during that second stage preserves WSS; ordinary tool/control inbound remains receive-side evidence and cannot clear transport suspicion, while local event-loop stalls cancel remote suspicion and use the separate recovery-grace path. The periodic application heartbeat remains twenty-five/seventy-five seconds after end-to-end readiness, and the Worker keeps a wider ninety-second fallback. WSS connect attempts have a thirty-second outer budget. Signed HTTPS is independent of that budget: a verified healthy WSS keeps HTTPS fallback stopped; on first-stage WSS suspicion the same root-certified ephemeral device identity may prewarm HTTPS in standby, verified WSS recovery stops that prewarm, and a real WSS loss promotes the path to exact-generation takeover while aborting any obsolete standby request. Fallback requests bind the fixed route/origin/server/version, a short-lived nonce, timestamp, and exact body hash; they use a seven-second ordinary request deadline, a twelve-second liveness window, a five-second verified-ready idle poll cadence, a thirty-second standby retry cadence, and a 750 ms minimum request-start interval for handshake or queued outbound work. The first authenticated exchange enters probing immediately, so verified readiness requires at most two bounded exchanges rather than a separate challenge round trip. Candidate → probing → verified-ready handover prevents the Worker from dispatching until the daemon has processed `ready_ack` and returned sequenced `https_ready`; a same-instance takeover may retire a Worker-side zombie WSS only after the signed candidate preconditions pass. Both directions use bounded contiguous transport sequences, so a lost HTTP response retransmits the same transport envelope and duplicates are discarded before business handling; this does not restore MCP sessions, recovery GET, `Last-Event-ID`, or public result persistence. Same-instance `resume_calls` / `resume_calls_ack` remains authoritative for in-flight ownership. A planned daemon shutdown is a different boundary: before a ready runtime closes its relay it sends `daemon_draining`; the Worker settles calls still owned by that daemon with structured `daemon_planned_drain` recovery and acknowledges the drain. In-flight `read_job` is explicitly read-only recoverable with `recovery.mode=read_same_job` plus the original `job_id`; resume by reading that same job after reconnect. This does not transfer an executing call to a new daemon process, whose random instance identity remains intentionally distinct, and it cannot revive an external assistant turn that has already ended. The daemon sends `resume_calls_ack.missing_ids` only after replacement readiness, only for IDs absent from both its active-call set and unacknowledged-result ledger, and only while it still has fail-closed proof that missing ownership means the call did not execute locally. If a completed-but-unacknowledged result expires, `diagnose_runtime.runtime.relay_result_recovery.automatic_redelivery_safe` becomes false and missing-ID automatic redelivery is disabled rather than risking duplicate side effects. A safe proven-undelivered call may be retransmitted with the same call ID, arguments, authority, and a reduced timeout inside the original execution deadline; a call that may have executed is never automatically replayed. Separately, if that same daemon already executed a call and its terminal result is delayed by the transport break, the Worker may retain the original in-memory settlement owner for one fixed fifteen-second window beyond its original settlement deadline, including when that original settlement deadline was already at the ordinary per-tool ceiling. That delivery-only extension cannot authorize redelivery or new execution, cannot accumulate across repeated handovers, and does not create client-visible replay or durable result state. A new call may wait up to fifteen seconds for a verified daemon channel, but measured recovery time is deducted from that call's original execution budget instead of extending the hosted foreground envelope. Hosted synchronous calls otherwise retain their ordinary 20-second execution plus separate five-second Worker settlement margin; configurable browser/application tools retain 20-second ordinary defaults, compound `computer_observe` / `computer_act` retain 30-second defaults, and the explicit remote maximum remains 45 seconds. Remote `exec_command`, `run_process`, and `run_local_command` require a caller-held `idempotency_key`, commit a principal-bound one-step managed job, and remain recoverable through bounded same-response `read_job` follow-up when the current task needs terminal state. Hosted active `read_job` uses a server-side 40-second long-poll by default and returns earlier on meaningful job progress or terminal state; `wait_ms=0` requests an immediate checkpoint, while every public hosted call is capped at 60 seconds. The default remains 40 seconds: live hosted evidence carried both the default and an explicit 60-second read, while beta.151 later reproduced `mcp_network_error` on a second explicit 180-second read even though the Worker-to-daemon WebSocket remained continuously ready. Longer tasks therefore keep the same `job_id` and use another server-paced read rather than one overlong host request. This keeps long-task waiting inside Machine Bridge within the demonstrated per-call host lifetime; the 40-second interval also bounds interaction density to at most 150 reads for a synthetic unchanged 100-minute job, but that arithmetic does not prove that one assistant response can survive the aggregate duration or call count. If a real host/tool boundary ends a response, preserve the durable identifier and resume the same operation later rather than resubmitting its side effect. `start_process` remains daemon-lifetime interactive state; hosted `read_process` permits paced same-response follow-up, defaults an omitted relay `wait_ms` to the one-second blocking cap, and paces another would-block read inside the fifteen-second cooldown within that same MCP call until output/exit or the cooldown boundary. Active job/process reads do not force a user-turn handoff. Callers must not infer or preempt a host/tool deadline from elapsed wall-clock time: while calls continue to be accepted and the task still needs the result, bounded same-response follow-up may continue. Handoff is reserved for an actual observed host/tool boundary, required external input or authorization, or an explicit user checkpoint, while busy loops and status-surface substitution remain prohibited. The durable process façade preserves account/tool authority and delegated workspace sandbox rather than expanding privileges.
178
180
 
179
181
  `full` is the daemon capability ceiling. An authenticated owner may exercise it without per-operation approval IDs. Delegated reviewer, editor, and operator accounts remain inside immutable role ceilings; out-of-role operations are denied rather than converted into a temporary elevation workflow. Process sessions, retained output, and managed jobs are additionally bound to account, client, and refresh-token family. See [local authorization](docs/LOCAL_AUTHORIZATION.md).
180
182
 
package/SECURITY.md CHANGED
@@ -247,7 +247,7 @@ Destructive state removal validates marker files, selected workspace, known layo
247
247
 
248
248
  ## Relay and denial of service
249
249
 
250
- Only one verified daemon is active. Candidates have preflight, hello, readiness, and liveness deadlines. A candidate cannot displace the current daemon before authentication and end-to-end readiness.
250
+ Only one verified daemon is active. Candidates have preflight, hello, readiness, and liveness deadlines. Ordinary replacement requires authentication and end-to-end readiness. A signed same-instance HTTPS takeover naming the exact incumbent connection generation may retire a zombie WebSocket after candidate preconditions pass; the replacement still cannot dispatch ordinary calls until end-to-end readiness is verified.
251
251
 
252
252
  Pending calls are bounded, socket-generation-bound, request-bound, timed out, cancellable, and recoverable only for the same verified daemon instance during the documented reconnect grace period. Worker transport/liveness invalidation is retryable and cannot by itself stop the daemon process; unknown protocol messages, authentication rejection, and identity/version mismatch remain fatal.
253
253
 
@@ -281,9 +281,9 @@ No logging policy prevents data from being returned to an authorized client that
281
281
 
282
282
  Machine Bridge cannot make arbitrary local executables safe, identify all sensitive data, guarantee cleanup across every power/storage/security failure, override MCP-host or endpoint-security policy, neutralize prompt injection, protect against root or a fully compromised same-user account, or manufacture production signing and governance controls.
283
283
 
284
- See [docs/AUDIT.md](docs/AUDIT.md) for historical findings and residual limitations.
284
+ See [docs/AUDIT.md](docs/AUDIT.md) for current audit conclusions and residual limitations.
285
285
  ## Request-scoped Streamable HTTP delivery
286
286
 
287
287
  MCP `2026-07-28` response streams are request-scoped and non-resumable. SSE frames carry no event IDs, `GET /mcp` is not a recovery channel, and `Mcp-Session-Id` / `Last-Event-ID` do not create protocol-session or replay state. Closing the public response stream cancels that request through a random internal capability that carries neither Authorization nor DPoP credentials.
288
288
 
289
- A brief relay interruption may rebind an already-dispatched pending call only to the same verified daemon instance within the bounded reconnect grace period. That continuity is in memory and remains owned by the initiating HTTP response; it does not persist a terminal result, create client-visible replay state, or authorize retry after the response has ended. Remote compatibility for the declared older initialization dates is likewise stateless and does not restore the removed session model.
289
+ A brief relay interruption may rebind an already-dispatched pending call only to the same verified daemon instance within the bounded reconnect grace period. That continuity is in memory and remains owned by the initiating HTTP response; it does not persist a terminal result, create client-visible replay state, or authorize retry after the response has ended. Both remote HTTP and stdio reject removed initialization and older protocol dates before tool dispatch; neither transport has an initialization compatibility adapter. Transport recovery does not restore the removed session model.
@@ -30,6 +30,6 @@
30
30
  "action": {
31
31
  "default_title": "Machine Bridge Browser"
32
32
  },
33
- "version_name": "3.0.0-beta.195",
33
+ "version_name": "3.0.0-beta.197",
34
34
  "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxryYkpZhq8+VAQLHcGS9BAHQcyKX8RHGIpIwvtIVRU/rcOcE0bNdnM0aZJ/h6xWQsGDHlhvjT2+1aJaAn/9k8473BRWajzVXld961CdHYVFVHoce2hHiSJ0xydWrHMMZhAm0mN0UzjEpgZ0tMw209efcZHIvSwuxhteZMRy4kyiVjwFlOf5oXFCxRuCJnPj3AK9CmCf4XgEBuPIJ0TZmjGHOOdBvJmbCNnAWXYEo5/mf7MfCGhV4IJ1hNuhpoNQfOFKMUcw9/v/IpT62XpfXdGYTfGYCmCjC+gntK1spbkr2P4/2+sYMQtLpse71mpSNGXfcf3abU55Vpn+gncSxRQIDAQAB"
35
35
  }
@@ -0,0 +1,23 @@
1
+ import { bindings, defineConfig, exports as workerExports } from "cf/config";
2
+
3
+ const name = process.env.MBM_WORKER_NAME || "machine-bridge-mcp";
4
+ export default defineConfig({
5
+ worker: {
6
+ name,
7
+ entrypoint: "src/worker/index.ts",
8
+ compatibilityDate: "2026-07-11",
9
+ compatibilityFlags: ["nodejs_compat", "enable_request_signal", "request_signal_passthrough"],
10
+ workersDev: true,
11
+ previewUrls: false,
12
+ unsafe: { metadata: { keep_bindings: ["plain_text", "json", "secret_text", "secret_key"] } },
13
+ observability: { enabled: true, headSamplingRate: 0.1 },
14
+ exports: { BridgeRoom: workerExports.durableObject({ storage: "sqlite" }) },
15
+ env: {
16
+ MBM_WORKER_MAX_BODY_BYTES: bindings.text("8388608"),
17
+ MBM_ALLOWED_ORIGINS: bindings.text(""),
18
+ BRIDGE: bindings.durableObject({ worker: name, exportName: "BridgeRoom" }),
19
+ STATEFUL_GLOBAL_RATE_LIMITER: bindings.rateLimit({ namespace: "4301702", simple: { limit: 1200, period: 60 } }),
20
+ STATEFUL_RATE_LIMITER: bindings.rateLimit({ namespace: "4301701", simple: { limit: 120, period: 60 } }),
21
+ },
22
+ },
23
+ });
package/docs/AUDIT.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Current audit status
2
2
 
3
+ The source dependency override and private hardened npm bootstrap pin brace-expansion 5.0.12 with the registry SHA-512 artifact integrity, addressing GHSA-q2hr-2g5m-vwhr, GHSA-qhr7-859c-m2p7, and GHSA-6j4f-fj2g-mc7p. Consumer packages have no postinstall hook: the verified cf network transformation runs before private CLI execution. Real private builds declare the exact audited Wrangler provider and receive the executable runner.
4
+
3
5
  This file is a compact statement of current cross-cutting audit conclusions and residual limits. It is intentionally version-agnostic: release identity, candidate acceptance, publication state, and soak state are authoritative only in package metadata, release records, Git history/tags, and the external release systems they describe. This file is not a release-state authority.
4
6
 
5
7
  ## Current conclusions
@@ -9,14 +11,23 @@ This file is a compact statement of current cross-cutting audit conclusions and
9
11
  - **State publication is atomic and identity-sensitive.** Security-sensitive state readers reject symlinks, unexpected hard links, malformed content, permission failures, and persistent identity changes. Bounded retries are reserved for explicitly classified atomic-publication races; durable state is complete before it becomes visible.
10
12
  - **Durable execution owns continuity explicitly.** Managed jobs persist recovery state independently of the hosted MCP response. Idempotency keys bind uncertain acceptance retries only while the retained record exists; cancellation, dependency state, cleanup, output budgets, and terminal persistence have explicit fail-closed boundaries. Callers recover the same accepted job instead of replaying its side effect.
11
13
  - **Daemon-owned Node children use a verified runtime launcher.** A live concrete runtime executable is preferred; if it disappears after a package-manager upgrade, only the original absolute Node launcher is eligible as fallback. Diagnostics expose provenance booleans rather than executable paths, and an unavailable launcher requires service restart instead of PATH guessing.
12
- - **Relay recovery separates transport from execution semantics.** WebSocket and signed HTTPS are transport paths, not permission or replay authorities. Their authenticated handshake/resume state is generation-scoped per transport, ended-generation control messages are discarded before reconciliation or interruption, and a protocol violation is routed only to its originating current transport. Ambiguous side effects are not transparently replayed. Same-daemon terminal-result retention is bounded, cancellation removes ownership, and repeated reconnects cannot accumulate execution time or delivery grace. Fatal protocol diagnostics retain only sanitized error/source/generation-class/stage/disposition fields, while fallback takeover history remains privacy-bounded across both control paths.
14
+ - **Relay recovery separates transport from execution semantics and from quota pacing.** WebSocket and signed HTTPS are transport paths, not permission or replay authorities. Their authenticated handshake/resume state is generation-scoped per transport, ended-generation control messages are discarded before reconciliation or interruption, and a protocol violation is routed only to its originating current transport. Ambiguous side effects are not transparently replayed. A verified healthy WSS schedules no recurring HTTPS fallback traffic; fallback starts only for startup grace, transport suspicion, or actual WSS loss, then uses five-second ready-idle polls and thirty-second successful-standby retries while handshake/queued work retains the 750 ms minimum request-start interval. Each accepted signed HTTP request or WebSocket preflight consumes one bounded Durable Object replay-nonce write, while a replay is rejected without another write. The checked-in native Cloudflare deployment configuration has no Workers KV namespace binding, so repository evidence supports Worker/Durable Object amplification but does not by itself establish a Workers KV quota incident. Same-daemon terminal-result retention is bounded, cancellation removes ownership, and repeated reconnects cannot accumulate execution time or delivery grace. Fatal protocol diagnostics retain only sanitized error/source/generation-class/stage/disposition fields, while fallback takeover history remains privacy-bounded across both control paths.
13
15
  - **Operating-system sleep is an observable suspension boundary, not a network guarantee.** On supported macOS hosts, diagnostics correlate bounded sleep history with runtime stalls and recovered relay outages. Machine Bridge cannot keep JavaScript or a socket executing while the machine is suspended, and sleep correlation does not identify unrelated upstream network causes.
14
16
  - **Browser automation remains existing-profile and snapshot-bound.** The extension controls an already installed Chromium profile; hosted calls bind explicit tab identity, and later Computer Use actions bind the exact observation snapshot. Mutation response loss, timeout, extension replacement, or ambiguous trusted-input settlement yields an unknown/non-retryable boundary that must be inspected before any retry.
15
17
  - **Desktop automation is permission- and evidence-bound.** Application actions use structured Accessibility operations or an explicitly enabled snapshot-bound visual backend. The runtime does not silently substitute arbitrary scripting or unverified pixel guessing when required authority/evidence is unavailable.
16
18
  - **Logging and diagnostics are privacy-minimized by contract.** Runtime logs are structured and must not contain tool arguments, command output, credentials, account identity, arbitrary URLs, private paths, or other user content. Explicit local CLI/tool results are a separate user-requested output surface. Security-audit telemetry is content-free, bounded, and hash-chained; diagnostics expose coarse provenance/health rather than secrets or private values.
17
19
  - **Resource admission is cooperative scheduling, not a hostile-code sandbox.** CPU, memory, I/O, disk-reserve, queue, and result budgets protect service continuity, but ordinary execution still has the daemon OS user's ambient authority unless a dedicated low-privilege account or VM/container supplies the stronger boundary.
20
+ - **Deployment audits cover bundled code as well as the dependency graph.** The consumer runtime excludes cf, Wrangler, and Miniflare. Deployment uses an exact private toolchain whose registry signatures, dependency audit, and artifact bytes are checked before execution. The pinned cf bundle includes an older Undici implementation, so a zero-vulnerability dependency audit is insufficient: a hash-bound deterministic transformation routes that bundle to the patched external Undici, and behavior tests cover custom transport and TLS-verification preservation. Unknown artifact bytes fail closed. Structured cf authentication must be positive before unattended activation can mutate the Worker or service; source snapshots, generated manifests, Worker identity, SQLite export, preserved secrets, and rate-limit bindings are validated before upload. These local controls still require candidate-bound deployed-edge acceptance.
18
21
  - **Release and package evidence remain separate from audit prose.** Shipped-source or packed-document changes require synchronized package identity and fresh verification. Candidate acceptance, publication, activation, and stable promotion must be proven by their dedicated records and external systems; no sentence in this audit summary inherits or confers release authority.
19
22
 
23
+ ## Relay quota incident evidence boundary
24
+
25
+ The quota repair is intentionally split into repository evidence and external-platform evidence. Repository evidence establishes that the prior relay design could generate recurring signed HTTPS traffic even when WebSocket was healthy, that a ready HTTPS fallback polled every second, and that each accepted signed HTTP relay request plus each accepted WebSocket preflight consumed a bounded Durable Object replay-nonce write. The current design keeps HTTPS fallback stopped while WSS is verified healthy, uses a five-second ready-idle HTTPS cadence and thirty-second successful-standby cadence, and keeps handshake/queued traffic on the existing 750 ms minimum start interval. The request/nonce-only regression models idle HTTPS polling alongside continuous failed WSS reconnects; it is not an upper bound across readiness resets or traffic patterns. A separate executed idle-day regression includes the production nonce store and liveness-alarm scheduler, as documented in TESTING.md.
26
+
27
+ The checked-in native Cloudflare deployment configuration contains Durable Object bindings and no Workers KV namespace binding. That fact narrows the repository-level causal claim: source and local runtime evidence support Worker request amplification plus Durable Object persistence amplification, but they cannot prove that a Cloudflare dashboard item labeled KV came from this repository. Account-side usage/resource records remain the authority for that label. Likewise, local full verification proves only the frozen source candidate; candidate activation, public Worker identity, relay readiness, representative durable execution, and post-activation quota-sensitive behavior require separate live evidence.
28
+
29
+ A reported account-wide Workers/KV quota event must be attributed using provider counters by UTC day, script, namespace, and deployed bindings before assigning a project root cause. The checked-in and inspected deployed bridge use SQLite-backed Durable Object storage, not a Workers KV namespace; another workload can exhaust the shared account allowance. HTTP polling and nonce/alarm mutations are separate resource-amplification risks that require their own regression budgets. Provider identifiers, account data, raw credentials, and request contents belong outside public repository evidence. Local scenario counts do not establish provider billing or a completed production soak.
30
+
20
31
  ## Residual limits
21
32
 
22
33
  - The default full profile is intentionally powerful. It is appropriate only where the daemon OS user is itself an acceptable trust boundary; stronger hostile-code isolation requires a separate OS account or VM/container.
package/docs/LOGGING.md CHANGED
@@ -68,7 +68,7 @@ Brief network interruptions are expected on laptop network changes, Worker deplo
68
68
  - `ready_ack` restores ordinary traffic immediately, but reconnect-attempt history is reset only after five seconds of generation-stable ready uptime. A shorter ready/close flap therefore continues the existing exponential backoff rather than repeatedly returning to the shortest reconnect delay; this stability window is retry pacing only and is not an additional readiness or liveness proof;
69
69
  - a verified replacement is a distinct warning and permanently stops the older daemon;
70
70
  - failure to receive `hello_ack` within the handshake deadline, or `ready_ack` within the independent end-to-end readiness deadline, terminates the candidate socket and retries;
71
- - authenticated transports request protocol-level WebSocket Ping every five seconds. A sender callback starts the full ten-second Pong deadline only after actual local dispatch. If that deadline expires on a fully ready WSS, the relay runtime records `relay.transport.suspect`, opens one fifteen-second application-confirmation window, sends a JSON heartbeat, and prewarms HTTPS in standby instead of killing the socket immediately. A later protocol Pong or explicit JSON application `pong` records `relay.transport.recovered` and preserves WSS; ordinary inbound tool/control traffic remains receive-side evidence and cannot clear transport suspicion. Only confirmation expiry records `relay.transport.confirmation_failed` and closes as `relay_transport_timeout`. A thirty-second local Ping-dispatch failure remains the distinct `relay.transport.send_timeout` / `relay_transport_send_timeout` path even if unrelated inbound traffic continues. Send-completion callbacks are exact-WebSocket-generation fenced, so a callback from a superseded socket cannot mutate current relay diagnostics or confirmation state. These anomaly events contain only bounded timing/state fields;
71
+ - authenticated transports request protocol-level WebSocket Ping every five seconds. A sender callback starts the full ten-second Pong deadline only after actual local dispatch. If that deadline expires on a fully ready WSS, the relay runtime records `relay.transport.suspect`, opens one fifteen-second application-confirmation window, sends a JSON heartbeat, and prewarms HTTPS in standby instead of killing the socket immediately. A later protocol Pong or explicit JSON application `pong` records `relay.transport.recovered`, preserves WSS, and stops any HTTPS prewarm started by that suspicion; ordinary inbound tool/control traffic remains receive-side evidence and cannot clear transport suspicion. Only confirmation expiry records `relay.transport.confirmation_failed` and closes as `relay_transport_timeout`. A thirty-second local Ping-dispatch failure remains the distinct `relay.transport.send_timeout` / `relay_transport_send_timeout` path even if unrelated inbound traffic continues. Send-completion callbacks are exact-WebSocket-generation fenced, so a callback from a superseded socket cannot mutate current relay diagnostics or confirmation state. These anomaly events contain only bounded timing/state fields;
72
72
  - a separate periodic twenty-five-second application heartbeat refreshes Worker daemon activity and retains a seventy-five-second application-silence timeout; it begins only after end-to-end readiness, so authenticated probing cannot send a message type that the Worker probing state does not accept. Protocol-level Pong therefore cannot mask a Worker application path that has stopped replying. The Worker queues the heartbeat's JSON `pong` before Durable Object alarm inspection or mutation, then performs one explicit coalesced schedule, so storage latency is not allowed to sit ahead of application-liveness acknowledgement;
73
73
  - a late local transport-watchdog tick is classified as `runtime.event_loop.stall`, sends a fresh transport probe, and defers disconnect for a bounded recovery interval instead of being mislabeled as immediate remote failure; a macOS sleep/wake interval may legitimately produce this warning without a daemon fault. The heartbeat snapshot retains the lag of the last actual stall separately from the rolling maximum. Owner `diagnose_runtime` can compare that end time and duration with a bounded fixed `pmset` sleep-history projection and reports `matched_system_sleep` only when both dimensions agree within the fixed tolerance; an unmatched stall remains unclassified rather than being labeled synchronous JavaScript blockage by elimination. The same diagnostic also intersects the most recent completed relay disconnect interval with that bounded sleep history and reports only outage/overlap timing plus a fixed classification; `majority_system_sleep_overlap` means host suspension dominated the observed outage, so a retained `connection_reset` is aftermath evidence rather than sufficient independent-network evidence. An authorized, schema-valid remote tool call enters macOS activity protection only after policy/account/operation authorization and argument validation succeed; remote process sessions extend that ownership through child settlement. The default `activity` mode keeps the existing shared `/usr/bin/caffeinate -i -s -w <owner-pid>` assertion and fixed thirty-minute rolling inactivity grace. `ac-continuous` adds a daemon-lifetime `-s` assertion, while `continuous` holds `-i -s` for the daemon lifetime and does not arm inactivity grace. Unexpected assertion-child failure retains desired-state ownership and schedules bounded 1/5/30-second recovery; explicit release/shutdown cancels pending recovery. `runtime.idle_sleep_guard.unavailable` still records only a coarse `error_class`, never argv, paths, PID, tool name/content, session identity, or job identity; mode, generation, restart count, recovery-pending state, and bounded unprotected-duration telemetry are exposed through diagnostics rather than logs. Remote account managed-job runners own the same self-healing assertion primitive only after runner-claim confirmation and persisted account ownership validation; local managed jobs do not acquire this remote-continuity assertion. The remote runner fallback stderr diagnostic remains the fixed text `managed job idle-sleep assertion unavailable` plus a sanitized coarse `error_class`, without job name/id, workspace path, argv, environment, or captured output.
74
74
 
@@ -8,7 +8,7 @@ machine-mcp doctor
8
8
  machine-mcp service status
9
9
  ```
10
10
 
11
- Routine remote checks should use authenticated `server_info` with `detail: "summary"`; request the default/full projection only when the caller's authority permits and exact effective-tool, OAuth/account, or detailed owner observability is actually needed. Non-owner full responses intentionally retain hidden markers/counts instead of cross-principal activity, resource aliases, stable device-key identity, or daemon-only tool names. Remote `diagnose_runtime` is owner-only because its fixed probes expose machine-wide control-plane activity; narrower roles use `server_info`/`project_overview` for authority-scoped readiness and workspace state. `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, the configured policy, the automatic-without-per-operation-prompts authorization model, and the same fixed local filesystem/process/shell/job-storage/resource probes exposed to the remote owner by `diagnose_runtime`. It constructs an isolated local runtime: `diagnosticScope.running_service_process_inspected=false` and `remote_relay_inspected=false` are deliberate, so a green doctor result is not evidence that the launchd/systemd/Scheduled Task daemon retained its Worker WebSocket. Inspect authenticated `server_info.daemon.relay_transport` for the running service relay. Authenticated `server_info.authorization.execution_model` reports the authority contract and identifies whether the account has daemon-OS-user ambient authority. Public `/healthz` output contains only server identity and version; daemon details require an authenticated `server_info` call.
11
+ Routine remote checks should use authenticated `server_info` with `detail: "summary"`; request the default/full projection only when the caller's authority permits and exact effective-tool, OAuth/account, or detailed owner observability is actually needed. Non-owner full responses intentionally retain hidden markers/counts instead of cross-principal activity, resource aliases, stable device-key identity, or daemon-only tool names. Remote `diagnose_runtime` is owner-only because its fixed probes expose machine-wide control-plane activity; narrower roles use `server_info`/`project_overview` for authority-scoped readiness and workspace state. `status` prints redacted profile state and verifies the deployed Worker version. Resource source paths remain redacted. `doctor` checks Node.js, the audited private cf binary, structured Cloudflare login, Worker health, the configured policy, the automatic-without-per-operation-prompts authorization model, and the same fixed local filesystem/process/shell/job-storage/resource probes exposed to the remote owner by `diagnose_runtime`. It constructs an isolated local runtime: `diagnosticScope.running_service_process_inspected=false` and `remote_relay_inspected=false` are deliberate, so a green doctor result is not evidence that the launchd/systemd/Scheduled Task daemon retained its Worker WebSocket. Inspect authenticated `server_info.daemon.relay_transport` for the running service relay. Authenticated `server_info.authorization.execution_model` reports the authority contract and identifies whether the account has daemon-OS-user ambient authority. Public `/healthz` output contains only server identity and version; daemon details require an authenticated `server_info` call.
12
12
 
13
13
  For interruption analysis, prefer one owner `diagnose_runtime` call over a chain of inventory probes. It now includes `runtime.managed_jobs.recent_activity`, `runtime.security_audit.recent_activity`, bounded `runtime.resource_admission.waiters.diagnostics`, `runtime.system_sleep`, `runtime.event_loop_pause_analysis`, and `runtime.relay_outage_analysis`. The `runtime-node-executable` check exposes only the executable provenance class and availability booleans, never a local path. `source=original_launcher` means the daemon's concrete Node binary disappeared after startup while the same absolute launcher that started the daemon remains executable; durable child Node processes use that launcher, and a service restart refreshes the concrete runtime identity. The audit aggregate contains only counts, bounded tool names, failure totals, calls-per-minute density, and numeric result-pressure fields (`output_bytes_last_15m`, `maximum_output_bytes_last_15m`, `large_result_calls_last_15m`, and `peak_output_bytes_per_minute_last_15m`) derived from the existing content-free hash-chained audit log; it contains no tool arguments or result content. Its `coverage=daemon_reached_relay_tool_calls_only` and `host_side_events_observable=false` fields make the evidence boundary explicit: host-only discovery/control-plane/final-delivery events are not counted. The waiter projection reports only resource-request shape and the current admission reason. On macOS with shell-capable owner diagnostics, the fixed power probe selects actual timestamped `Sleep` records before applying the bounded tail, then reduces them to a small list of sleep start/end/duration/reason classes; it never returns raw power-log lines. The probe has a bounded 15-second execution budget so normal multi-second `pmset -g log` latency does not erase sleep evidence. If that bounded power-history probe is unavailable or times out, `runtime.system_sleep` remains `supported=true` with `available=false` and an `error_class`, while the `system-sleep-history` check is retained as skipped auxiliary causality evidence. That auxiliary evidence gap does not by itself make `diagnose_runtime.ok=false`; relay readiness, local filesystem/process/shell execution, managed-job storage, resource admission, and registered-resource availability remain health gates. `event_loop_pause_analysis.classification=matched_system_sleep` requires both the recorded runtime-stall end time and duration to match one of those bounded operating-system sleep intervals within a fixed tolerance. `relay_outage_analysis` separately compares the most recent completed `recent_outages[0].disconnected_at` -> `recent_outages[0].ready_at` interval with the same bounded sleep history and reports exact overlap duration/ratio; an active outage uses `outage_started_at` instead of the later `last_disconnected_at`. `majority_system_sleep_overlap` means at least half of that observed relay outage occurred while macOS was suspended. A sleeping JavaScript process may be unable to observe the stale socket until wake, so a zero-overlap close-to-ready interval is not automatically awake-network evidence: `wake_boundary_system_sleep_aftermath` is emitted only when the disconnect occurs within the fixed wake tolerance and that same sleep independently matches the event-loop stall in both end time and duration. Either sleep classification makes a retained `connection_reset`/timeout transport aftermath rather than sufficient evidence of a separate network root cause. `no_matching_recent_system_sleep` remains the classification for an awake reset or a merely coincidental near-wake reset without same-sleep stall evidence; it leaves the cause unassigned rather than guessing a VPN, edge, Worker, or host cause. Full relay diagnostics additionally expose `recent_outages`, a newest-first in-memory history capped at eight completed WebSocket reconnect episodes. Each entry also carries `https_fallback_taken_over` and bounded `https_fallback_takeover_ms`, attributed by the stable WebSocket outage number; a later fallback takeover cannot relabel an earlier or no-takeover episode. The top-level `https_fallback_last_takeover_outage_number` is only a bounded correlation aid for the latest takeover and must not be applied to another outage number. Each entry contains only bounded outage numbering, first/final disconnect and ready timestamps, duration, close/error classes, previous-ready duration/silence, first-disconnect liveness phase/timing, coarse application-route class, and connection-stage timings. `disconnected_at` is the first outage transition and `last_disconnect_at` is the final failed reconnect transition. A protocol/application Pong that clears a liveness suspicion without rebuilding the WebSocket remains heartbeat evidence and is deliberately absent from `recent_outages`; the array is therefore reconnect history, not a list of every transient transport suspicion. ChatGPT host-turn termination/final-message receipt remains explicitly unobservable.
14
14
 
@@ -24,9 +24,9 @@ Process timeout cleanup is ownership-bound rather than parent-liveness-bound. On
24
24
 
25
25
  `/healthz` and `/` are answered by the outer Worker and do not consume Durable Object request volume. If MCP or daemon routes return `503 durable_object_quota_exceeded` (or Cloudflare 1101 with Durable Objects free-tier exhaustion in Worker tails), wait for the daily UTC free-tier reset or move the account off the free DO plan; do not treat that as a failed script deploy when `/healthz` still reports the expected version.
26
26
 
27
- Wrangler upload and public health verification are two separate observations. Once Wrangler reports a successful deployment and supplies the `workers.dev` URL, Machine Bridge immediately records that URL together with the exact deployment fingerprint and package version. Beta.43 upgrades this fingerprint to length-framed v5 and therefore treats earlier hashes as stale once; it verifies or redeploys the same-name Worker rather than creating another Worker. Required Worker/shared/config inputs must be readable ordinary repository files or directories. Missing, inaccessible, symlinked, hard-linked, or special paths stop before upload. It then verifies `/healthz` through the standard `HTTPS_PROXY`/`HTTP_PROXY` and `NO_PROXY` environment route. If that secondary probe times out or encounters a proxy, TLS, network, or temporary HTTP 5xx failure, startup stops with an actionable error, but the successful deployment evidence remains. The next ordinary start verifies the same Worker and does not repeat the upload.
27
+ cf upload and public health verification are two separate observations. Once cf reports a successful deployment and supplies the `workers.dev` URL, Machine Bridge immediately records that URL together with the exact deployment fingerprint and package version. The length-framed v6 fingerprint includes native deployment/build configuration and the exact private toolchain templates, so earlier hashes are treated as stale once; the migration verifies or redeploys the same-name Worker rather than creating another Worker. Required Worker/shared/config inputs must be readable ordinary repository files or directories. Missing, inaccessible, symlinked, hard-linked, or special paths stop before upload. One immutable bounded snapshot supplies both the fingerprint and private `cf build`; generated output must retain the same `BridgeRoom` SQLite export, self-binding, rate-limit namespace identities, and binding-preservation metadata. It then verifies `/healthz` through the standard `HTTPS_PROXY`/`HTTP_PROXY` and `NO_PROXY` environment route. If that secondary probe times out or encounters a proxy, TLS, network, or temporary HTTP 5xx failure, startup stops with an actionable error, but the successful deployment evidence remains. The next ordinary start verifies the same Worker and does not repeat the upload.
28
28
 
29
- Interactive Wrangler login is deliberately unavailable in machine-readable Worker deployment. A normal non-JSON local startup may run login and then must re-run `whoami` before deployment; JSON mode returns `worker_authentication_required` instead. Persistent candidate activation adds an outer authentication preflight before the service handoff: detached managed-job activation requires an already authenticated Wrangler session and fails before live mutation otherwise, while an ordinary owner terminal may complete login before the old login service is stopped. This prevents a ten-minute interactive authentication flow from becoming part of a service-offline transaction or writing non-JSON text into the activation result channel.
29
+ Interactive cf login is deliberately unavailable in machine-readable Worker deployment. Wrangler credentials alone do not establish cf authentication: `cf auth whoami` must return bounded valid JSON with `authenticated === true`, and an explicitly invalid token is rejected. A normal non-JSON local startup may run `cf auth login` with the required Worker scopes and then must re-run structured `whoami` before deployment; JSON mode returns `worker_authentication_required` instead. Persistent candidate activation adds an outer authentication preflight before the service handoff: detached managed-job activation requires an already authenticated cf session and fails before live mutation otherwise, while an ordinary owner terminal may complete login before the old login service is stopped. The selected account must be explicitly accessible or the only accessible account; ambiguous account selection fails before build/upload. This keeps interactive authentication outside the service-offline transaction and preserves the activation JSON result channel.
30
30
 
31
31
  Automatic redeployment is limited to bounded health evidence that the recorded endpoint is genuinely stale: a persistent package-version mismatch, an unexpected Machine Bridge identity, or a persistent `404`/`410`. Unreachability is not proof of absence. `--force-worker` remains the explicit override when an operator deliberately wants an upload despite matching state.
32
32
 
@@ -95,7 +95,7 @@ After the host path recovers, compare authenticated `server_info`, `machine-mcp
95
95
 
96
96
  A reconnect warning proves a transport interruption, not a daemon crash. When the daemon instead exits on a relay protocol error, inspect the same default service-log entry for the sanitized protocol error code, source transport, coarse generation class, handshake stage, and disposition; those fields distinguish a current-generation fatal WebSocket violation from a retryable HTTPS fallback violation without exposing raw connection identifiers. Compare daemon PID and process start time with `connected_at`, `last_seen_at`, `daemon.relay_transport.last_close_category`, `last_close_code`, `outage_count`, `recent_outages`, `outage_attempts`, `previous_ready_inbound_silence_ms`, `last_connect_milestones_ms`, and the coarse network-route class. In each completed `recent_outages` entry, `disconnected_at` is the first transition into that outage, `last_disconnect_at` is the final failed reconnect/close transition, `ready_at` is verified recovery, and `duration_ms` measures first-disconnect-to-ready time. The bounded `probe_dispatch_pending_at_start`, `probe_dispatch_age_ms_at_start`, `probe_outstanding_at_start`, `probe_age_ms_at_start`, `transport_confirmation_pending_at_start`, and `application_inbound_silence_ms_at_start` fields freeze the liveness phase at that first transition. Use them to test hypotheses such as a failure coinciding with the first five-second protocol Ping, but do not treat that timing correlation as proof that Ping caused the reset. Also distinguish a planned restart from an accidental outage: a current-generation daemon sends `daemon_draining` before relay close, affected calls receive `reason=daemon_planned_drain`, and owner/full `server_info.worker.continuity_evidence` schema 2 durably retains the planned-drain count/time plus bounded socket-disconnect and client-cancellation observations across Worker isolate replacement. Treat `ready_socket_disconnects`, `unplanned_ready_socket_disconnects`, and `last_ready_socket_disconnect` as the qualified durable socket-outage evidence; the broader `socket_disconnects` counters include candidate/probing transport churn. `last_socket_disconnect.role`, `was_ready`, and `connected_at` identify whether the newest first-observed close/error had ever become the authoritative ready channel. Planned-drain intent is serialized into the WebSocket attachment before close so a Durable Object isolate replacement cannot turn a planned shutdown into an unplanned disconnect. Schema-1 disconnect counts are intentionally reset during the schema-2 transition because old isolates could count stale/expired close callbacks more than once. `worker.observability.continuity` remains isolate-local and may reset; use the qualified durable summary for post-incident correlation rather than relying on a later close-1006 inference. For hosted `read_job`, recover with the same returned `job_id` plus its `recovery_key`; do not resubmit the job's underlying mutation. If the job predates capability issuance or its capability was never delivered, use local CLI/stdio administration instead of attempting hosted global discovery. `last_connect_milestones_ms` contains only bounded relative timings for the most recent connection attempt phases such as DNS resolution, TCP connect, TLS establishment, HTTP rejection, and WebSocket open; `last_failed_connect_stage`, `last_failed_connect_duration_ms`, `last_failed_connect_milestones_ms`, and `last_failed_connect_http_status` retain the most recent failed attempt even after a later retry succeeds. `last_transport_error_ready` and `last_transport_error_authenticated` distinguish failure of an already-established channel from a pre-readiness connection failure. `last_transport_error_reason` is a strict privacy-safe allowlist (`connection_reset`, `connection_timeout`, `network_unreachable`, bounded DNS/TLS classes, or `unknown`) rather than the raw operating-system message. The signed HTTPS fallback retains its last error class/reason after a later successful poll while resetting the current `http_poll_failures` count, so post-recovery diagnosis can determine whether WSS and HTTPS failed through the same system-network episode. None of these fields contains a hostname, address, DNS answer, certificate, close reason, or proxy endpoint. While no daemon channel is ready, `server_info.daemon.previous_connection` retains only the last verified channel's transport, connected/last-seen/disconnected timestamps, and sanitized relay diagnostics; it excludes policy, tools, account identity, daemon instance/connection identity, call IDs, arguments, and results, and it never participates in routing or authorization. `outage_duration_ms` measures the close-to-ready recovery episode; `previous_ready_inbound_silence_ms` measures how long the preceding ready socket had stopped producing inbound transport proof before it actually closed. The second value is therefore the field that exposes a black-holed OPEN WebSocket whose visible reconnect later completes quickly. A VPN/TUN UI may remain “connected” while its upstream route is unusable. Local OS logs can be compared with the exact `last_disconnected_at` timestamp, but an interface-quality change or tunnel-process correlation is not by itself proof of which product, node, edge, or upstream failed. Correlated failure of an independent HTTPS client at the same timestamp—for example an external API `unexpected EOF` while the relay records WebSocket 1006/`connection_reset`—is stronger evidence of a shared system-network/VPN/TUN episode than of a Machine Bridge event-loop or resource-admission failure; it still does not identify the failing tunnel node or upstream provider. Machine Bridge reports only coarse route/proxy classes and never sends or logs interface names, addresses, DNS answers, proxy credentials, or Worker secrets.
97
97
 
98
- Brief retryable outages recover automatically. On a verified current daemon channel, `server_info.daemon.relay_transport.outage_active=false`; retained fields describe the immediately preceding transport episode rather than claiming a current outage. WebSocket remains preferred and requests a protocol-level probe after five seconds. Calling `ws.ping()` only queues the control frame; it is not treated as remote-probe dispatch until the WebSocket sender's write callback confirms that the Ping actually left the local send queue. The local sender has a separate thirty-second bounded dispatch window, while a confirmed Ping retains its full ten-second Pong deadline. This deliberately prevents compression/backpressure or a slow local socket queue from spending the remote-response budget before any probe was transmitted. A protocol Pong that arrives while a Ping callback is still pending records bidirectional proof for that dispatch round; if the local write callback then completes inside the thirty-second dispatch budget, it does not arm a stale future Pong deadline. Unrelated application inbound is receive-side evidence only and cannot prove the daemon-to-Worker direction. A local queue whose Ping write callback still has not completed after thirty seconds is classified as `relay_transport_send_timeout` even if unrelated inbound traffic continues. One dispatched Ping that reaches the ten-second response deadline does not hard-kill an otherwise ready WSS: the relay runtime enters a fifteen-second `transport_confirmation_pending` window, sends the existing JSON application heartbeat as an independent path check, and prewarms signed HTTPS in standby without taking ownership away from the still-ready WSS. A protocol Pong or the explicit JSON application `pong` clears suspicion and stops standby prewarm; ordinary tool/control traffic does not, because it proves only the Worker-to-daemon receive direction. Only a second-stage confirmation window that receives no application `pong` becomes `relay_transport_timeout` and terminates the WSS. This keeps a true black hole bounded while no longer amplifying a roughly ten-to-fifteen-second persistent-flow stall into an immediate reconnect storm. `heartbeat.probe_dispatch_*`, `heartbeat.transport_confirmation_*`, and bounded sender-backlog fields distinguish local send delay, first-stage response loss, successful second-stage recovery, and confirmed two-stage failure. The separate periodic JSON application heartbeat remains twenty-five seconds with a seventy-five-second application-silence timeout, begins only after verified relay readiness, and the Worker keeps a wider ninety-second WebSocket liveness fallback. This is a detection/recovery bound, not a guarantee that a degraded network can complete another WebSocket handshake inside the same interval. WebSocket connect attempts have a thirty-second outer budget so a degraded but still valid DNS/TCP/TLS/WebSocket upgrade is not misclassified by an unrealistically narrow connection cutoff. The daemon also explicitly disables client `permessage-deflate`: the relay carries bounded control/JSON traffic, while `ws` enables compression by default on clients and compression adds sender-state/CPU overhead that can queue later frames; the stability path does not need that optional negotiation. The fallback still begins independently rather than waiting thirty seconds for WSS. On first-stage WSS liveness suspicion, the same root-certified ephemeral daemon identity prewarms signed HTTPS in standby; if WSS proves live during the second-stage confirmation, that standby poller stops. If the WSS actually disconnects, fallback switches to exact-generation takeover immediately; an in-flight standby request is aborted and replaced rather than being allowed to consume up to its own request deadline before takeover can start. That in-memory session certificate intentionally has a 24-hour maximum lifetime. For the default portable JWK root, the runtime derives a fresh root-certified ephemeral session ten minutes before expiry, swaps the shared WSS/HTTPS authentication provider, and reconnects the same daemon instance so existing reconnect reconciliation can resume in-flight relay calls without `runtime.stop()`. If the machine was suspended across the renewal timer, the next authentication boundary synchronously renews before signing instead of first attempting an expired certificate. `server_info.runtime.trust.daemon_session` exposes only coarse renewal state such as `automatic_renewal`, `session_generation`, `expires_at`, `renewal_due_at`, and failure class/count; it never exposes session keys or certificate material. A Secure Enclave root does not receive unattended renewal because signing may require user presence. If unattended renewal is unavailable or repeatedly fails until the session is truly expired, the existing fail-closed path still terminates with `relay_device_session_expired` rather than retrying forever with unusable credentials; installed launchd/systemd/Windows supervision may then restart the daemon and obtain a new root-signed session, while a manually run daemon requires operator restart. Ordinary standby/ready fallback requests retain the seven-second deadline; exact-generation takeover requests use a three-second deadline until verified readiness. The ordinary one-second ready poll cadence, five-second standby-prewarm cadence, bounded one/two/four/five-second retry backoff, 750 ms hard minimum request-start interval, and twelve-second liveness window are unchanged. A new daemon-backed call waits at most fifteen seconds for some verified daemon channel, and the measured wait is deducted from that call's original execution budget; the takeover budget is deliberately small enough for one fully timed-out stale request, the first retry backoff, and two further takeover exchanges to fit inside that ceiling. After an established WSS disappears, the daemon explicitly marks its signed HTTP request as a takeover of the Worker-issued `connection_id` for that exact disconnected WebSocket generation. Once candidate preconditions pass, HTTPS may retire only that targeted same-instance zombie WSS that the Worker has not yet observed closing. If a newer same-instance WSS is already ready before the HTTP request arrives, the old generation no longer matches and the stale takeover remains standby instead of retiring the recovered socket. A takeover request without the exact Worker-issued WebSocket connection ID is invalid rather than being treated as an instance-only legacy takeover. Malformed, stale, wrongly targeted, or different-instance requests cannot preempt a healthy incumbent. During replacement, the daemon reconciles `resume_calls`, processes `ready_ack`, proves local readiness, and only then returns `resume_calls_ack.missing_ids`. A missing ID therefore proves both that the same daemon has no active/unacknowledged-result ownership for that call and that the replacement channel is ready. If the initiating MCP response is still open and at least one second remains in the original execution budget, the Worker may transparently retransmit exactly that same call ID, arguments, authority, and a reduced timeout. `read_job` is stricter: redelivery requires the full ten-second reconciliation headroom to remain, otherwise the Worker declines redelivery and returns retryable recovery failure rather than rewriting the call into an under-budget immediate read. If safe redelivery cannot be accepted, the call falls back to retryable `unavailable` with `side_effects_started=false`. Calls that may have executed, retained terminal results, different-daemon calls, and ambiguous mutations are never automatically replayed. Completed relay results that are still waiting for Worker acknowledgement remain bounded in daemon memory and consume the same recovery-ownership capacity as active calls: 16 total with two control-plane slots reserved for `diagnose_runtime`/`list_roots`. When ordinary recovery ownership reaches 14, another ordinary relay call is rejected before execution with retryable `limit_exceeded` and `side_effects_started=false`; the two reserved diagnostic/recovery calls remain available until total capacity reaches 16. The retained-result implementation also keeps one non-admission emergency ownership slot solely for a violated internal capacity invariant: if an already-executed result reaches retention after the normal 16-entry ceiling is unexpectedly full, that one result remains retained for acknowledgement/reconnect ownership instead of being sent unowned and later misclassified as safe to redeliver. Use of that slot emits an error-level capacity event and may make diagnostics temporarily report ownership above the normal maximum; a second such overflow is not sent. This slot is not usable admission capacity and must never be counted to raise the 16-call execution ceiling. An acknowledgement that is permanently lost cannot pin a result forever: first retention is monotonic and the result expires after the 315-second maximum Worker settlement lifetime on the next live relay heartbeat; the disconnected path still uses the shorter reconnect-grace cleanup. `diagnose_runtime.runtime.relay_result_recovery` exposes only aggregate `active_calls`, `retained_results`, active ownership, and capacity counts—never call IDs, tool arguments, or results. Compare outage intervals with sleep/wake records and `diagnose_runtime.runtime.relay.heartbeat` before classifying them as active network faults; local stdio `server_info.runtime.relay.heartbeat` exposes the same state. On macOS, authorized relay activity is protected only after policy/account/operation authorization and argument validation succeed, and relay heartbeats do not count as user activity. The persisted idle-sleep mode is `activity` by default, `ac-continuous`, or `continuous`: `activity` retains the existing shared `/usr/bin/caffeinate -i -s -w <daemon-pid>` assertion plus fixed thirty-minute inactivity grace; `ac-continuous` adds a daemon-lifetime `-s -w <daemon-pid>` assertion while keeping that activity lease; `continuous` holds `-i -s -w <daemon-pid>` for the daemon lifetime and does not arm inactivity grace. A remote `start_process` extends activity ownership only after resource admission and through child settlement. Remote account managed-job runners independently hold the same `-i -s -w <runner-pid>` primitive after runner-claim/account-ownership validation and through admission, steps, cleanup, and terminal persistence. Every assertion retains desired-state recovery after unexpected child failure with fixed 1/5/30-second backoff; explicit release/shutdown disables recovery before terminating the child. `diagnose_runtime.runtime.idle_sleep_guard` reports only coarse mode/activity/recovery ownership and bounded unprotected-duration telemetry; it does not enumerate process-session or job identities. Runtime shutdown terminates process sessions before releasing daemon assertions. None of these modes claims to prevent explicit sleep, lid-close sleep, power loss, or operating-system behavior outside `caffeinate` contracts. A nonzero `event_loop_stall_count` with a large `max_event_loop_lag_ms` means the local daemon was not scheduled promptly; a short stall enters recovery grace, sends a fresh transport probe, and deliberately postpones disconnect. A large stall that aligns with `pmset` Sleep/Wake is suspension evidence. Independently, `relay_outage_analysis` can show either that a close-to-ready interval was itself dominated by system sleep or that the socket failure was first observable at the wake boundary while the same sleep matches the runtime pause; a genuinely awake outage without either evidence remains real transport evidence without identifying which network/host layer caused it. A large `previous_ready_inbound_silence_ms` without a matching local stall remains useful pre-close half-open evidence. Use `--verbose` only when close codes, liveness deadlines, and retry delays are required.
98
+ Brief retryable outages recover automatically. On a verified current daemon channel, `server_info.daemon.relay_transport.outage_active=false`; retained fields describe the immediately preceding transport episode rather than claiming a current outage. WebSocket remains preferred and requests a protocol-level probe after five seconds. Calling `ws.ping()` only queues the control frame; it is not treated as remote-probe dispatch until the WebSocket sender's write callback confirms that the Ping actually left the local send queue. The local sender has a separate thirty-second bounded dispatch window, while a confirmed Ping retains its full ten-second Pong deadline. This deliberately prevents compression/backpressure or a slow local socket queue from spending the remote-response budget before any probe was transmitted. A protocol Pong that arrives while a Ping callback is still pending records bidirectional proof for that dispatch round; if the local write callback then completes inside the thirty-second dispatch budget, it does not arm a stale future Pong deadline. Unrelated application inbound is receive-side evidence only and cannot prove the daemon-to-Worker direction. A local queue whose Ping write callback still has not completed after thirty seconds is classified as `relay_transport_send_timeout` even if unrelated inbound traffic continues. One dispatched Ping that reaches the ten-second response deadline does not hard-kill an otherwise ready WSS: the relay runtime enters a fifteen-second `transport_confirmation_pending` window, sends the existing JSON application heartbeat as an independent path check, and prewarms signed HTTPS in standby without taking ownership away from the still-ready WSS. A protocol Pong or the explicit JSON application `pong` clears suspicion and stops standby prewarm; ordinary tool/control traffic does not, because it proves only the Worker-to-daemon receive direction. Only a second-stage confirmation window that receives no application `pong` becomes `relay_transport_timeout` and terminates the WSS. This keeps a true black hole bounded while no longer amplifying a roughly ten-to-fifteen-second persistent-flow stall into an immediate reconnect storm. `heartbeat.probe_dispatch_*`, `heartbeat.transport_confirmation_*`, and bounded sender-backlog fields distinguish local send delay, first-stage response loss, successful second-stage recovery, and confirmed two-stage failure. The separate periodic JSON application heartbeat remains twenty-five seconds with a seventy-five-second application-silence timeout, begins only after verified relay readiness, and the Worker keeps a wider ninety-second WebSocket liveness fallback. This is a detection/recovery bound, not a guarantee that a degraded network can complete another WebSocket handshake inside the same interval. WebSocket connect attempts have a thirty-second outer budget so a degraded but still valid DNS/TCP/TLS/WebSocket upgrade is not misclassified by an unrealistically narrow connection cutoff. The daemon also explicitly disables client `permessage-deflate`: the relay carries bounded control/JSON traffic, while `ws` enables compression by default on clients and compression adds sender-state/CPU overhead that can queue later frames; the stability path does not need that optional negotiation. The fallback still begins independently rather than waiting thirty seconds for WSS. On first-stage WSS liveness suspicion, the same root-certified ephemeral daemon identity prewarms signed HTTPS in standby; if WSS proves live during the second-stage confirmation, that standby poller stops. If the WSS actually disconnects, fallback switches to exact-generation takeover immediately; an in-flight standby request is aborted and replaced rather than being allowed to consume up to its own request deadline before takeover can start. That in-memory session certificate intentionally has a 24-hour maximum lifetime. For the default portable JWK root, the runtime derives a fresh root-certified ephemeral session ten minutes before expiry, swaps the shared WSS/HTTPS authentication provider, and reconnects the same daemon instance so existing reconnect reconciliation can resume in-flight relay calls without `runtime.stop()`. If the machine was suspended across the renewal timer, the next authentication boundary synchronously renews before signing instead of first attempting an expired certificate. `server_info.runtime.trust.daemon_session` exposes only coarse renewal state such as `automatic_renewal`, `session_generation`, `expires_at`, `renewal_due_at`, and failure class/count; it never exposes session keys or certificate material. A Secure Enclave root does not receive unattended renewal because signing may require user presence. If unattended renewal is unavailable or repeatedly fails until the session is truly expired, the existing fail-closed path still terminates with `relay_device_session_expired` rather than retrying forever with unusable credentials; installed launchd/systemd/Windows supervision may then restart the daemon and obtain a new root-signed session, while a manually run daemon requires operator restart. Ordinary standby/ready fallback requests retain the seven-second deadline; exact-generation takeover requests use a three-second deadline until verified readiness. Verified healthy WSS operation keeps HTTPS fallback stopped. When fallback is needed, the ready-idle poll cadence is five seconds, successful standby probes retry after thirty seconds, network failures retain the bounded one/two/four/five-second retry backoff, handshake or queued outbound work retains the 750 ms hard minimum request-start interval, and the twelve-second liveness window is unchanged. A new daemon-backed call waits at most fifteen seconds for some verified daemon channel, and the measured wait is deducted from that call's original execution budget; the takeover budget is deliberately small enough for one fully timed-out stale request, the first retry backoff, and two further takeover exchanges to fit inside that ceiling. After an established WSS disappears, the daemon explicitly marks its signed HTTP request as a takeover of the Worker-issued `connection_id` for that exact disconnected WebSocket generation. Once candidate preconditions pass, HTTPS may retire only that targeted same-instance zombie WSS that the Worker has not yet observed closing. If a newer same-instance WSS is already ready before the HTTP request arrives, the old generation no longer matches and the stale takeover remains standby instead of retiring the recovered socket. A takeover request without the exact Worker-issued WebSocket connection ID is invalid rather than being treated as an instance-only legacy takeover. Malformed, stale, wrongly targeted, or different-instance requests cannot preempt a healthy incumbent. During replacement, the daemon reconciles `resume_calls`, processes `ready_ack`, proves local readiness, and only then returns `resume_calls_ack.missing_ids`. A missing ID therefore proves both that the same daemon has no active/unacknowledged-result ownership for that call and that the replacement channel is ready. If the initiating MCP response is still open and at least one second remains in the original execution budget, the Worker may transparently retransmit exactly that same call ID, arguments, authority, and a reduced timeout. `read_job` is stricter: redelivery requires the full ten-second reconciliation headroom to remain, otherwise the Worker declines redelivery and returns retryable recovery failure rather than rewriting the call into an under-budget immediate read. If safe redelivery cannot be accepted, the call falls back to retryable `unavailable` with `side_effects_started=false`. Calls that may have executed, retained terminal results, different-daemon calls, and ambiguous mutations are never automatically replayed. Completed relay results that are still waiting for Worker acknowledgement remain bounded in daemon memory and consume the same recovery-ownership capacity as active calls: 16 total with two control-plane slots reserved for `diagnose_runtime`/`list_roots`. When ordinary recovery ownership reaches 14, another ordinary relay call is rejected before execution with retryable `limit_exceeded` and `side_effects_started=false`; the two reserved diagnostic/recovery calls remain available until total capacity reaches 16. The retained-result implementation also keeps one non-admission emergency ownership slot solely for a violated internal capacity invariant: if an already-executed result reaches retention after the normal 16-entry ceiling is unexpectedly full, that one result remains retained for acknowledgement/reconnect ownership instead of being sent unowned and later misclassified as safe to redeliver. Use of that slot emits an error-level capacity event and may make diagnostics temporarily report ownership above the normal maximum; a second such overflow is not sent. This slot is not usable admission capacity and must never be counted to raise the 16-call execution ceiling. An acknowledgement that is permanently lost cannot pin a result forever: first retention is monotonic and the result expires after the 315-second maximum Worker settlement lifetime on the next live relay heartbeat; the disconnected path still uses the shorter reconnect-grace cleanup. `diagnose_runtime.runtime.relay_result_recovery` exposes only aggregate `active_calls`, `retained_results`, active ownership, and capacity counts—never call IDs, tool arguments, or results. Compare outage intervals with sleep/wake records and `diagnose_runtime.runtime.relay.heartbeat` before classifying them as active network faults; local stdio `server_info.runtime.relay.heartbeat` exposes the same state. On macOS, authorized relay activity is protected only after policy/account/operation authorization and argument validation succeed, and relay heartbeats do not count as user activity. The persisted idle-sleep mode is `activity` by default, `ac-continuous`, or `continuous`: `activity` retains the existing shared `/usr/bin/caffeinate -i -s -w <daemon-pid>` assertion plus fixed thirty-minute inactivity grace; `ac-continuous` adds a daemon-lifetime `-s -w <daemon-pid>` assertion while keeping that activity lease; `continuous` holds `-i -s -w <daemon-pid>` for the daemon lifetime and does not arm inactivity grace. A remote `start_process` extends activity ownership only after resource admission and through child settlement. Remote account managed-job runners independently hold the same `-i -s -w <runner-pid>` primitive after runner-claim/account-ownership validation and through admission, steps, cleanup, and terminal persistence. Every assertion retains desired-state recovery after unexpected child failure with fixed 1/5/30-second backoff; explicit release/shutdown disables recovery before terminating the child. `diagnose_runtime.runtime.idle_sleep_guard` reports only coarse mode/activity/recovery ownership and bounded unprotected-duration telemetry; it does not enumerate process-session or job identities. Runtime shutdown terminates process sessions before releasing daemon assertions. None of these modes claims to prevent explicit sleep, lid-close sleep, power loss, or operating-system behavior outside `caffeinate` contracts. A nonzero `event_loop_stall_count` with a large `max_event_loop_lag_ms` means the local daemon was not scheduled promptly; a short stall enters recovery grace, sends a fresh transport probe, and deliberately postpones disconnect. A large stall that aligns with `pmset` Sleep/Wake is suspension evidence. Independently, `relay_outage_analysis` can show either that a close-to-ready interval was itself dominated by system sleep or that the socket failure was first observable at the wake boundary while the same sleep matches the runtime pause; a genuinely awake outage without either evidence remains real transport evidence without identifying which network/host layer caused it. A large `previous_ready_inbound_silence_ms` without a matching local stall remains useful pre-close half-open evidence. Use `--verbose` only when close codes, liveness deadlines, and retry delays are required.
99
99
 
100
100
  A foreground MCP response is not durable delivery. For an active hosted `start_job`, `ui_monitor_candidate=true` plus `ui_monitor_render_tool=render_job_monitor` and a fresh `ui_monitor_id` means the host advertised MCP Apps support, but `start_job` itself remains data-only and does not mount UI. **Job polling ownership is not task ownership.** If the current assistant still has task-local work that depends on this job's terminal result, do not render the monitor merely to shorten the response; preserve `job_id` + `recovery_key` and continue bounded server-paced `read_job` calls in the same response while calls are accepted. Render only when the current task can deliberately transfer this job's status polling without needing its terminal result for remaining same-response work. When intentionally rendering, preserve the start-result ID, call `render_job_monitor` once with the exact accepted `job_id` + `recovery_key` + `ui_monitor_id`; it verifies existing read authority, activates that pre-issued correlation ID, and mounts the Job Monitor resource. Do not depend on the render tool result being visible to the initiating planner. Immediately call `read_job` with the same `job_id`, `recovery_key`, and start-result `ui_monitor_id`. A matching current View claim on an ordinary job reports `ui_monitor_claimed=true`, `status_polling_mode=ui_monitor`, `host_turn_handoff_recommended=false`, and `follow_up_read_required=false`; that proves the View can own subsequent status polling for this job only. The sole exception is a persisted `continuation_mode=task_supervisor` whose reviewed durable plan already encapsulates all remaining noninteractive task work: a later active claimed read may report `host_turn_handoff_recommended=true`, allowing the host turn to end because the supervisor job owns the remaining execution lifecycle. Machine Bridge can prove the persisted declaration, active state, and current View claim, but not conversation-level completeness; that remains an owner/caller semantic assertion. The monitor itself remains status-only. The mounted View then uses app-only `read_job_monitor`, not the model-visible `read_job`, for its fixed 40-second status long-polls. That app-only call verifies the same principal-bound `recovery_key`, strips the recovery/monitor values before daemon dispatch, and uses a 60-second client response watchdog and may be retried by the View for at most six attempts with bounded 1/2/4/8/15/30-second backoff after a missing/transport-failed response or an explicitly retryable tool error; it never re-submits the managed job. Exhausted retries and non-retryable status errors pause the View for manual inspection. An older View claim with another monitor ID is not handoff evidence. Hosted synchronous calls reserve room for Worker and host settlement instead of occupying the complete interaction window: ordinary daemon-backed tools default to 20 seconds of remote execution plus a separate five-second Worker settlement margin; ordinary configurable browser/application foreground tools also default to 20 seconds, while compound `computer_observe` and `computer_act` default to 30 seconds; all configurable browser/application foreground tools retain their explicit 45-second maximum. Remote `exec_command`, `run_process`, and `run_local_command` no longer keep the child process inside that response lifetime. Each remote process request must carry a unique caller-held `idempotency_key` before dispatch; reuse that same key only when recovering an ambiguous acceptance response. The daemon commits the authorized operation as a principal-bound one-step managed job, launches it with interactive resource-admission priority, and returns a `job_id` inside a 10-second acceptance budget; the Worker keeps a separate five-second settlement margin and adds principal-bound `recovery_key`/`control_key` capabilities to the hosted result. Preserve all three together: hosted `read_job` requires the read capability, hosted `cancel_job` requires the control capability, and a bare `job_id` is not remote recovery authority. If that acceptance response is lost to settlement timeout, HTTP response cancellation, or relay reconnect expiry after dispatch, the public error remains non-retryable for generic callers but carries the original key and the explicit recovery action `retry_same_tool_arguments_with_same_idempotency_key`; this reconciles against the retained job instead of authorizing a blind duplicate. The detached child may execute for up to 600 seconds after admission, but the managed runner can separately wait up to thirty minutes for cooperative machine-user resource admission before the child is spawned; the child execution deadline begins only after that admission succeeds. The shared ceiling is exposed machine-readably as `server_info.tool_delivery.managed_job_resource_admission_wait_max_ms`, because the same pre-spawn boundary applies to ordinary durable process jobs and owner `start_job` steps rather than to process tools alone. While the runner is in this pre-spawn state, `read_job.current_phase` is `resource_admission`; no command has started yet. An owner can correlate a long-running status at that phase with `diagnose_runtime.runtime.resource_admission` rather than interpreting it as a slow child process; a delegated non-owner should treat the phase itself as evidence that the child has not spawned, retain the same `job_id`, and avoid blind replay rather than attempting the owner-only machine-wide diagnostic. After admission, the phase returns to `steps`, `finally_steps`, or `recovery-cleanup` as appropriate. Completed step records preserve `duration_ms` as the total orchestration duration. Local/owner reads additionally expose `resource_admission_ms` as the pre-spawn portion so a delayed successful child can be distinguished from slow execution after the fact; delegated non-owner reads omit that machine-user scheduling timing rather than turning shared-host contention into a more precise cross-workload signal. The detached job survives MCP disconnect, relay reconnect, daemon restart, or service replacement. Non-owner process authority is unchanged: automatic durable execution still uses the delegated workspace sandbox and does not grant owner-only `start_job`. If a cached host schema omits a current required field, the Worker rejects before daemon dispatch with a normal no-side-effect tool error and requests a `tools/list` refresh rather than surfacing a protocol-only validation failure. Discovery instructions and tool descriptions both carry orchestration semantics, so `server/discover` and `tools/list` each advertise `ttlMs=0` and every host-visible tool description carries `Tool schema generation N`. `server_info.tool_delivery.tool_schema_generation`, `tool_schema_server_version`, `discovery_ttl_ms`, and `tool_list_ttl_ms` identify the live contract; `host_visible_schema_known_to_server=false` is equally important because a healthy new daemon/Worker cannot prove that an external host discarded an older cached action/tool snapshot. `host_turn_deadline_observable=false` means Machine Bridge cannot pre-compute the external assistant-turn deadline, while `managed_jobs_detached_from_mcp_response=true` records that an accepted durable job is not owned by that response lifetime. After an activation that changes hosted semantics, compare the live `server_info` generation and changed invocation behavior with the governed Workspace Action control snapshot when that product layer is applicable; automation may perform the supported refresh/review path without another conversational approval. Host-internal cache inspection is intentionally excluded from operational release verification. `start_process` remains the explicit daemon-lifetime path when interactive stdin or session-style incremental output is required, but hosted calls use a 10-second execution / 15-second settlement envelope and do not queue behind resource pressure: the first failed admission returns retryable `unavailable`; owner-local callers retain the cooperative wait. Hosted `read_process` supports paced same-response follow-up: each actual output/exit blocking wait lasts at most one second. If another would-block remote read arrives inside the fifteen-second blocking cooldown, the daemon keeps that same MCP call open until output/exit or the cooldown boundary rather than returning an immediate running checkpoint; the Worker reserves enough execution/settlement headroom for that server-side pacing. Results use `status_polling_mode=paced_followup` while the process remains live, plus `blocking_poll_throttled` and `next_blocking_poll_after_ms`; callers must not busy-loop and should respect that cooldown. A new hosted call waits at most fifteen seconds for daemon readiness, but that wait is charged against the call's existing execution budget. For an already-dispatched call, a disconnect never pauses or extends the original execution/redelivery deadline. The Worker may separately retain the same in-memory result-settlement owner for one fixed fifteen-second window beyond its original settlement deadline, including when that original settlement deadline was already at the ordinary per-tool ceiling, solely so an already-executed terminal result from the verified same daemon can still reach the original request. Repeated disconnect/rebind cycles cannot accumulate that delivery grace, cancellation still removes the owner, and the longer settlement deadline is never used to authorize another execution. Reconnect retention is bounded by reconnect grace and that fixed delivery deadline. Diagnostics distinguish `original call deadline expired during reconnect`, `terminal result delivery grace expired during reconnect`, and a true full `reconnect grace expired` rather than collapsing those separate boundaries. Owner-local stdio/CLI calls retain their synchronous local contract because they do not depend on a hosted response stream. Keep unrelated mutations and verification independently terminal, and never infer task success merely because a durable launch was accepted. For one coherent non-interactive sequence, prefer a repository umbrella command or multi-step `start_job` rather than creating many one-step durable process carriers. If the current task needs the result, hosted `read_job` may follow the known durable `job_id` with its preserved `recovery_key` repeatedly in the same assistant response until terminal state while calls continue to be accepted; active relay reads report `status_polling_mode=bounded_followup` and no longer recommend forced handoff. The normal hosted read is a 40-second server-side long-poll. Terminal settlement returns on the next bounded five-second internal poll; nonterminal status/phase/dependency progress is coalesced for at least 30 seconds by default, and `current_step`-only churn does not wake the hosted call. `wait_ms=0` is the explicit immediate-checkpoint mode, while public hosted `wait_ms` is capped at 60 seconds. The default stays at 40 seconds because live host evidence showed that overlong single requests can outlive the host invocation even though the durable job itself remains healthy; beta.151 reproduced that class with a second explicit 180-second `read_job` returning `mcp_network_error` while generation-18 continuity evidence recorded zero unplanned ready-socket disconnects. The coalescing floor reduces host-visible event density and does not shorten the managed job, the assistant task, or the six-hour managed-step ceiling. Do not busy-loop, do not replace server-side pacing with rapid immediate reads, do not use repeated `list_jobs`, `server_info`, or `diagnose_runtime` calls as substitute polling surfaces, and do not infer or preempt a host/tool deadline from elapsed wall-clock time. Hosted `list_jobs` is aggregate-only and intentionally cannot rediscover lost job IDs/names/recovery handles; detailed global inventory remains local CLI/stdio administration. Return the `job_id`, status, and current phase for later recovery only after an actual host/tool boundary is observed, external input or authorization is required, or the user explicitly requested a checkpoint; only a terminal status is task-completion evidence.
101
101
 
@@ -171,7 +171,7 @@ npm --version
171
171
  machine-mcp --verbose
172
172
  ```
173
173
 
174
- The published runtime package does not install Wrangler or Miniflare into its global dependency tree. On the first start or deployment, Machine Bridge first constructs a private hardened npm 12.0.2 from exact integrity-pinned npm, undici 6.28.0, and brace-expansion 5.0.9 registry tarballs, then uses that CLI to install the exact private Wrangler toolchain under its owner-only state root. It audits the resulting production tree and verifies registry signatures before contacting Cloudflare. This requires npm registry access and may add one bounded setup step; do not manually edit either private toolchain directory. Candidate installation, published global installation, GitHub Release publication checks, and npm publication also create temporary hardened/private staging sessions. Published installation preserves the global prefix selected by the owner's npm. GitHub and npm artifacts must match the accepted candidate digest/hash evidence before service mutation. GitHub release publication after merge does not reinstall the source dependency tree or repeat local `check:full`: it first fetches `origin/main`, requires local `HEAD` to equal that exact commit, and requires every configured push-triggered provider workflow for that commit to have succeeded. It then uses the hardened npm session to recheck synchronized versions and rematerialize the accepted candidate bytes/promotion digest. Immediately before any tag or GitHub Release mutation it fetches `origin/main` again and requires the same CI-verified commit; publication aborts if main moved. Remote asset SHA-256 reconciliation remains mandatory after upload. Permission, I/O, quota, memory, retry, stale-handle, storage, read-only-filesystem, or timeout errors are not treated as an empty/corrupt tree and must be corrected without deleting the state root.
174
+ The published runtime package does not install cf, Wrangler, or Miniflare into its global dependency tree. On the first start or deployment, Machine Bridge first constructs a private hardened npm 12.0.2 from exact integrity-pinned npm, undici 6.28.0, and brace-expansion 5.0.12 registry tarballs, then uses that CLI to install the exact private cf/Wrangler toolchain under its owner-only state root. It audits the resulting production tree, verifies registry signatures, and validates the exact deterministic cf network-compatibility transformation before contacting Cloudflare. This requires npm registry access and may add one bounded setup step; do not manually edit either private toolchain directory. Candidate installation, published global installation, GitHub Release publication checks, and npm publication also create temporary hardened/private staging sessions. Published installation preserves the global prefix selected by the owner's npm. GitHub and npm artifacts must match the accepted candidate digest/hash evidence before service mutation. GitHub release publication after merge does not reinstall the source dependency tree or repeat local `check:full`: it first fetches `origin/main`, requires local `HEAD` to equal that exact commit, and requires every configured push-triggered provider workflow for that commit to have succeeded. It then uses the hardened npm session to recheck synchronized versions and rematerialize the accepted candidate bytes/promotion digest. Immediately before any tag or GitHub Release mutation it fetches `origin/main` again and requires the same CI-verified commit; publication aborts if main moved. Remote asset SHA-256 reconciliation remains mandatory after upload. Permission, I/O, quota, memory, retry, stale-handle, storage, read-only-filesystem, or timeout errors are not treated as an empty/corrupt tree and must be corrected without deleting the state root.
175
175
 
176
176
  ### Ambiguous publication outcome
177
177
 
@@ -444,3 +444,7 @@ Current audit conclusions and residual review requirements are in [AUDIT.md](AUD
444
444
  ### Worker pending-call budget
445
445
 
446
446
  `server_info.worker.pending_calls` reports bounded aggregate in-memory dispatched ownership, pre-dispatch daemon waiters, and their shared capacity. MCP request bodies and terminal results are not written as a delivery/replay log, and there is no `durable_budget` MCP stream counter. Unexpected growth in active/detached pending calls or pre-dispatch waiters, repeated reconnect expiry, or sustained admission pressure should block release and be diagnosed against daemon readiness and relay health.
447
+
448
+ ### Quota attribution and cooldowns
449
+
450
+ Attribute an account quota event by UTC day, Worker script, KV namespace, and deployed bindings before assigning a project root cause. Workers KV and SQLite-backed Durable Object storage are different products. Idle relay scenario counts include nonce writes and recurring liveness-alarm schedules; they do not bound business traffic, other daemons, WSS reconnects, or other account workloads. The source repository testing guide describes the executed idle-day scenario and its exclusions. HTTP 429/503 `Retry-After` applies a monotonic cooldown bounded to one hour; queue activity and relay lifecycle changes cannot shorten it. A cooldown beyond liveness invalidates readiness until a fresh successful handshake.
package/docs/PRIVACY.md CHANGED
@@ -111,4 +111,4 @@ The MCP Apps managed-job monitor keeps that bearer boundary narrow rather than c
111
111
 
112
112
  Durable Object monitor coordination is metadata-only and remains subordinate to the durable job/authority result it decorates. A storage failure while issuing optional monitor metadata after `start_job` acceptance returns the already-projected accepted job without a UI candidate; a storage failure while probing claim evidence after a successful `read_job` means “no proven handoff” and retains normal model-side continuation. Authority revocation does not become dependent on best-effort monitor-record cleanup: the core revocation still completes, cleanup failure is represented only by bounded operation/error-class telemetry, and the principal-bound recovery capability continues to be revalidated on every app read. Monitor coordination therefore cannot turn an already accepted job or completed revocation into an ambiguous business operation, and neither logs nor persistent monitor state acquire job output or bearer material.
113
113
 
114
- The signed daemon HTTPS fallback does not change those persistence rules. It carries the same daemon control/tool envelopes over TLS when WSS is unavailable and retains only bounded in-memory transport queues on each side. An unacknowledged envelope may be retransmitted with the same transport sequence after response loss, but duplicate sequences are discarded before business handling; no public MCP replay identifier or persisted fallback result store is created. Fallback authentication headers contain a short-lived root-certified session certificate, one-time nonce, timestamp, body hash, and signature; they are validated but not written to operational logs. Relay diagnosis retains only bounded numeric connect/probe timing, sender-backlog byte counts, and strict allowlisted transport reasons such as `connection_timeout` or `network_unreachable`; it never stores the raw socket error, hostname, address, DNS answer, certificate, VPN interface/node, proxy endpoint, arguments, or results. The fallback may retain its last coarse error class/reason after recovery so a later operator can correlate WSS and HTTPS failure windows, while current health remains represented separately by readiness and the current failure count. Browser broker ping/Pong carries only a bounded sequence number and is not content logging.
114
+ The signed daemon HTTPS fallback does not change those persistence rules. It carries the same daemon control/tool envelopes over TLS when WSS is unavailable and retains only bounded in-memory transport queues on each side. An unacknowledged envelope may be retransmitted with the same transport sequence after response loss, but duplicate sequences are discarded before business handling; no public MCP replay identifier or persisted fallback result store is created. Fallback authentication headers contain a short-lived root-certified session certificate, one-time nonce, timestamp, body hash, and signature; they are validated but not written to operational logs. Replay protection does persist only the accepted nonce plus expiry inside bounded Durable Object nonce maps: HTTP relay nonces and WebSocket preflight nonces use separate keys and fixed entry ceilings, expired entries are pruned on consumption, a replay is rejected without another write, and certificate/signature/body-hash values are not copied into that replay store. Relay diagnosis retains only bounded numeric connect/probe timing, sender-backlog byte counts, and strict allowlisted transport reasons such as `connection_timeout` or `network_unreachable`; it never stores the raw socket error, hostname, address, DNS answer, certificate, VPN interface/node, proxy endpoint, arguments, or results. The fallback may retain its last coarse error class/reason after recovery so a later operator can correlate WSS and HTTPS failure windows, while current health remains represented separately by readiness and the current failure count. Browser broker ping/Pong carries only a bounded sequence number and is not content logging.
@@ -37,14 +37,14 @@ The hosted MCP client, its prompts, tools, extensions, and retrieved content are
37
37
  - OAuth state, PKCE, redirect URI, resource binding, and request size;
38
38
  - account status, account version, account role, trusted client binding, token expiry, and refresh-family state;
39
39
  - DPoP proof method, target URL, timestamp, unique identifier, access-token hash, and key thumbprint when DPoP is used;
40
- - Native MCP `2026-07-28` per-request protocol metadata, valid positive `Accept` quality values, actual `/mcp` Origin, header/body consistency for version/method/name/declared primitive parameters, request IDs, role-visible tool exposure, raw argument schemas, and response-stream cancellation. Remote HTTP initialization compatibility is limited to the declared `2025-06-18`/`2025-11-25` dates and the bounded `initialize`/`notifications/initialized`/`ping`/`tools/list`/`tools/call` method set; it dispatches tools only through the current controller and cannot create `Mcp-Session-Id`, recovery/replay state, or a second authorization/session model. Other removed initialization/session requests receive bounded upgrade guidance only.
41
- - The daemon HTTPS fallback is a transport failover surface, not an MCP endpoint or alternate authority. Each POST is authenticated by the same root-certified ephemeral P-256 device session as the daemon, and its signature binds the fixed route, Worker origin, server/version, a 30-second nonce/timestamp window, and exact body SHA-256. Nonces are one-time and bounded; request/response bodies, queue count/bytes, request frequency, and liveness are bounded independently. The Worker admits the fallback only when no verified-ready WSS exists, preserves the same daemon-instance/pending-call ownership, and does not expose the fallback as ready until the daemon has acknowledged all probing controls and returned the sequenced `https_ready` proof. Bidirectional contiguous transport sequences reject gaps and suppress duplicate delivery before business side effects, so an HTTP response retry does not become a mutation retry.
40
+ - MCP `2026-07-28` per-request protocol metadata, valid positive `Accept` quality values, actual `/mcp` Origin, header/body consistency for version/method/name/declared primitive parameters, request IDs, role-visible tool exposure, raw argument schemas, and response-stream cancellation. Removed initialization/session/replay requests receive bounded upgrade guidance and cannot dispatch tool work.
41
+ - The daemon HTTPS fallback is a transport failover surface, not an MCP endpoint or alternate authority. Each POST is authenticated by the same root-certified ephemeral P-256 device session as the daemon, and its signature binds the fixed route, Worker origin, server/version, a 30-second nonce/timestamp window, and exact body SHA-256. Nonces are one-time and bounded; request/response bodies, queue count/bytes, request frequency, and liveness are bounded independently. The Worker normally admits the fallback only when no verified-ready WSS exists. A signed same-instance takeover naming the exact incumbent connection generation may retire a zombie WSS after candidate preconditions pass; a stale generation or invalid candidate cannot evict it. The fallback preserves the same daemon-instance/pending-call ownership, and does not expose the fallback as ready until the daemon has acknowledged all probing controls and returned the sequenced `https_ready` proof. Bidirectional contiguous transport sequences reject gaps and suppress duplicate delivery before business side effects, so an HTTP response retry does not become a mutation retry.
42
42
 
43
43
  A client registration is not authority. Authority begins only after successful account authorization binds the client to one account and role version.
44
44
 
45
45
  Capability discovery is also an authorization boundary. Task routing and application/browser metadata are built from the effective account/daemon policy intersection, not from the daemon ceiling. Route scores and fallbacks are advisory and cannot manufacture authority; direct Bash remains available only when the effective policy already exposes it. A restricted account must not learn hidden local application inventory or receive names of unavailable execution tools through the resolver.
46
46
 
47
- Mirrored MCP headers are an intermediary-routing boundary. The Worker compares every required native current header with the JSON-RPC body before authorization-dependent dispatch; a mismatch fails with `-32020` before the daemon can observe the call. Stateless initialization-compatibility clients may omit the newer method/name/declared-parameter mirrors, but any such current mirror they do send is binding and must match the same JSON-RPC body before compatibility dispatch. The reserved mirror namespace is closed as well: an inapplicable `Mcp-Name` or a `Mcp-Param-*` header that is not declared by the selected tool schema is rejected rather than ignored. Tool schemas are compiled from a bounded JSON Schema 2020-12 subset at startup and runtime traversal charges every array item and own object property to a fixed work budget. Open request metadata/capability JSON also has a fixed structural-node/depth/key budget. This server advertises no change notifications, so `subscriptions/listen` validates and bounds the requested filter, acknowledges an empty supported notification subset, emits the correlated completion result, and closes immediately without retaining subscription state. Unsupported dialects or keywords fail closed, external network `$ref` values are not dereferenced, and validation diagnostics omit argument values and unbounded caller identifiers.
47
+ Mirrored MCP headers are an intermediary-routing boundary. The Worker compares every required native current header with the JSON-RPC body before authorization-dependent dispatch; a mismatch fails with `-32020` before the daemon can observe the call. The reserved mirror namespace is closed as well: an inapplicable `Mcp-Name` or a `Mcp-Param-*` header that is not declared by the selected tool schema is rejected rather than ignored. Tool schemas are compiled from a bounded JSON Schema 2020-12 subset at startup and runtime traversal charges every array item and own object property to a fixed work budget. Open request metadata/capability JSON also has a fixed structural-node/depth/key budget. Remote HTTP advertises `tools.listChanged=true`. A supported `toolsListChanged` subscription receives the correlated acknowledgement and an initial list-change notification, then retains only bounded authority-scoped in-memory stream state until cancellation, revocation, observable abort, or the advertised ten-second lease. A request with no supported notification filter is acknowledged with an empty subset and completed immediately. Stdio advertises `listChanged=false` and completes validated subscription requests immediately. Unsupported dialects or keywords fail closed, external network `$ref` values are not dereferenced, and validation diagnostics omit argument values and unbounded caller identifiers.
48
48
 
49
49
  Current response-stream cancellation deliberately crosses the OAuth boundary only through an unguessable internal stream capability. The public Worker strips caller-provided control headers before the service binding, the cancellation request contains no bearer token or DPoP proof, and the Durable Object consumes the capability before OAuth only to cancel a currently indexed call. Guessing remains bounded by 256-bit randomness; a compromised service binding or Worker runtime is already inside this trust boundary.
50
50
 
@@ -82,6 +82,12 @@ The broker is loopback-only, but loopback is not treated as a per-user authentic
82
82
 
83
83
  The extension still operates inside a real browser profile. It can reach tabs, authenticated sessions, and origins granted by browser permissions. Only the `owner` role may use browser-session control or export local data into it. Computer Use does not increase that role ceiling: its browser observations bind semantic refs, document/frame epochs, optional screenshot evidence, and private backend-node identity to one bounded snapshot, then consume that snapshot as one-shot mutation authority. Transport loss after a browser mutation is attempted is explicitly unknown and never safe replay evidence. Screenshot-bound point actions additionally require exact current screenshot/viewport/document evidence; callers cannot submit raw CDP methods, backend-node IDs, or coordinates that are not bound to the referenced snapshot.
84
84
 
85
+ ### Package runtime to Cloudflare deployment
86
+
87
+ The deployment toolchain has local-owner code execution and Cloudflare upload authority. The published consumer dependency graph excludes cf, Wrangler, and Miniflare; a private owner-only toolchain retains exact registry-backed versions and lockfile bytes. Registry signatures and a dependency audit do not prove bundled-code safety. The pinned cf artifact therefore has a hash-bound, bounded, atomic compatibility transformation that routes its embedded network factory to patched external Undici; unknown bytes or filesystem identity/mode violations stop execution. Regression evidence includes custom connector and TLS-verification behavior without external network access.
88
+
89
+ Unattended activation requires positive structured cf authentication before any live Worker/service mutation. CLI exit status alone, Wrangler login, malformed/truncated JSON, a truthy non-boolean value, or an explicitly invalid token cannot satisfy that gate. Account ambiguity is rejected. A bounded immutable source snapshot supplies both the deployment HMAC and the private build, and the generated manifest must retain the selected Worker name, the `BridgeRoom` SQLite export/self-binding, rate-limit identities, and explicit secret/plain-text/JSON binding preservation. Successful upload evidence is recorded before the subsequent health read; a transient health failure cannot authorize a duplicate upload. Local output checks cannot prove provider-side namespace continuity or successful live authentication, so candidate-bound deployed-edge canary and acceptance remain separate requirements.
90
+
85
91
  ### Local runtime to persistent state
86
92
 
87
93
  State paths, roots, locks, plans, resources, native broker files, and service definitions are security-sensitive.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "machine-bridge-mcp",
3
- "version": "3.0.0-beta.195",
3
+ "version": "3.0.0-beta.197",
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",
@@ -86,7 +86,9 @@
86
86
  "docs/THREAT_MODEL.md",
87
87
  "docs/TOOL_REFERENCE.md",
88
88
  "docs/UPGRADING.md",
89
- "LICENSE"
89
+ "LICENSE",
90
+ "cloudflare.config.ts",
91
+ "wrangler.config.ts"
90
92
  ],
91
93
  "scripts": {
92
94
  "start": "node bin/machine-mcp.mjs start",
@@ -262,7 +264,8 @@
262
264
  "browser-pairing-launch:test": "node tests/browser-pairing-launch-test.mjs",
263
265
  "browser-cli-pairing:test": "node tests/browser-cli-pairing-test.mjs",
264
266
  "resource-admission:test": "node tests/resource-admission-test.mjs",
265
- "resource-build-root:test": "node tests/resource-build-root-test.mjs"
267
+ "resource-build-root:test": "node tests/resource-build-root-test.mjs",
268
+ "cf-network:test": "node tests/cf-network-compatibility-test.mjs"
266
269
  },
267
270
  "dependencies": {
268
271
  "https-proxy-agent": "9.1.0",
@@ -275,7 +278,9 @@
275
278
  "fast-check": "4.10.0",
276
279
  "globals": "17.11.0",
277
280
  "typescript": "7.0.2",
278
- "wrangler": "4.131.2"
281
+ "wrangler": "4.144.0",
282
+ "cf": "1.0.0-beta.5",
283
+ "undici": "7.29.1"
279
284
  },
280
285
  "keywords": [
281
286
  "mcp",
@@ -307,7 +312,7 @@
307
312
  "esbuild@0.28.1": true,
308
313
  "fsevents": false,
309
314
  "sharp@0.35.4": true,
310
- "workerd@1.20260911.1": true
315
+ "workerd@1.20260926.1": true
311
316
  },
312
317
  "packageManager": "npm@12.0.2",
313
318
  "devEngines": {
@@ -324,7 +329,7 @@
324
329
  },
325
330
  "overrides": {
326
331
  "sharp": "0.35.4",
327
- "brace-expansion": "5.0.9",
328
- "undici": "7.29.0"
332
+ "brace-expansion": "5.0.12",
333
+ "undici": "7.29.1"
329
334
  }
330
335
  }
@@ -1,6 +1,7 @@
1
1
  import { normalizeActivationRecovery } from "../src/shared/activation-recovery.mjs";
2
2
  import { EXECUTION_SURFACE, executionSurface } from "../src/local/execution-surface.mjs";
3
- import { runWrangler as defaultRunWrangler } from "../src/local/shell.mjs";
3
+ import { runCf as defaultRunCf } from "../src/local/shell.mjs";
4
+ import { ensureCfAuthenticated } from "../src/local/cf-authentication.mjs";
4
5
 
5
6
  export function assertPersistentActivationExecutionSurface(environment = process.env) {
6
7
  const surface = executionSurface(environment);
@@ -27,31 +28,18 @@ export function persistentActivationSpawnOptions({ cwd, env = process.env } = {}
27
28
  }
28
29
 
29
30
  export async function preflightPersistentActivationWorkerAuth({
30
- surface = "local",
31
- stateRoot,
32
- packageRoot,
33
- npmCli,
34
- env = process.env,
35
- runWrangler = defaultRunWrangler,
31
+ surface = "local", stateRoot, packageRoot, npmCli, env = process.env, runCf = defaultRunCf,
36
32
  } = {}) {
37
33
  if (surface !== "local" && surface !== EXECUTION_SURFACE.managedJob) {
38
- throw new TypeError("persistent activation Wrangler preflight requires a local or managed-job execution surface");
34
+ throw new TypeError("persistent activation cf preflight requires a local or managed-job execution surface");
39
35
  }
40
- if (typeof stateRoot !== "string" || !stateRoot) throw new TypeError("persistent activation Wrangler preflight requires stateRoot");
41
- if (typeof packageRoot !== "string" || !packageRoot) throw new TypeError("persistent activation Wrangler preflight requires packageRoot");
42
- if (typeof runWrangler !== "function") throw new TypeError("persistent activation Wrangler preflight requires runWrangler");
43
- const shared = { stateRoot, packageRoot, npmCli, env };
44
- const whoami = await runWrangler(["whoami"], { ...shared, capture: true, allowFailure: true });
45
- if (whoami?.code === 0) return { authenticated: true, login_performed: false };
46
- if (surface === EXECUTION_SURFACE.managedJob) throw workerAuthenticationRequiredError(
47
- "persistent activation cannot start interactive Wrangler login from a detached managed job; authenticate Cloudflare Wrangler in an ordinary owner terminal before retrying",
48
- );
49
- await runWrangler(["login"], shared);
50
- const verified = await runWrangler(["whoami"], { ...shared, capture: true, allowFailure: true });
51
- if (verified?.code !== 0) throw workerAuthenticationRequiredError(
52
- "Cloudflare Wrangler login completed without a verifiable authenticated session; the persistent activation was not started",
53
- );
54
- return { authenticated: true, login_performed: true };
36
+ if (typeof stateRoot !== "string" || !stateRoot) throw new TypeError("persistent activation cf preflight requires stateRoot");
37
+ if (typeof packageRoot !== "string" || !packageRoot) throw new TypeError("persistent activation cf preflight requires packageRoot");
38
+ if (typeof runCf !== "function") throw new TypeError("persistent activation cf preflight requires runCf");
39
+ const auth = await ensureCfAuthenticated({
40
+ runCf, shared: { stateRoot, packageRoot, npmCli, env }, interactive: surface === "local",
41
+ });
42
+ return { authenticated: true, login_performed: auth.login_performed };
55
43
  }
56
44
 
57
45
  export function persistentCandidateFailureMessage(output, { cli, stateRoot, previousRuntime = null } = {}) {
@@ -92,10 +80,3 @@ export function validateActivationRecoveryPayload(value) {
92
80
  throw new Error(`persistent ${String(error?.message || "activation recovery metadata is invalid")}`, { cause: error });
93
81
  }
94
82
  }
95
-
96
- function workerAuthenticationRequiredError(message) {
97
- const error = new Error(message);
98
- error.code = "worker_authentication_required";
99
- error.sideEffectsStarted = false;
100
- return error;
101
- }