Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
fix(runtime-broker): Close the deferred W0c-2 findings from #12761
- Context installation refuses a Session record that is RELEASING,
  RELEASED or FAILED, and a binding with a drain request, before
  sending. Acquisition installs while the record is still ACQUIRING,
  so the check accepts ACQUIRING and READY rather than READY alone.
- When a managed-context startup fails with a non-retryable error and
  the deadline fires before the call answers, the deadline answers
  that error, including when it finds the block the failure handler
  recorded. It used to answer 409 runtime_broker_recovery_blocked. A
  failure published after the deadline fired, and legacy startup, keep
  the deadline's own answer.
- A block write or read that fails on the deadline path is kept as a
  suppressed exception on the deadline's answer instead of dropped.
- A tool name, or any key or string in the tool input, holding an
  unpaired surrogate is refused instead of reaching the Worker as '?':
  runtime_reference_invalid on create, runtime_payload_invalid on a
  deferred start (raw or escaped), and before sending in the HTTP
  transport, whose check fails closed on values that are not JSON.
- Tests pin addSuppressed on both paths, lone low surrogates in the
  identity fields and Runtime Session IDs, and the deadline races.
- JdbcRuntimeBrokerMySqlIT uses a per-run prefix, so it re-runs on the
  same database.
  • Loading branch information
wenshao committed Sep 29, 2026
commit a2658844c51bb443cfcdc6f8c15083743682bbd8
18 changes: 9 additions & 9 deletions docs/design/2026-09-26-managed-workspace-output-next-slices.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@ Older Broker binaries cannot interpret managed-context rows safely. Upgrade all

## 3. Wire admission and installation

Use the closed [managed-context envelope](2026-09-25-managed-context-envelope.md) and [Worker behavior](2026-09-26-managed-context-worker.md). Validate identifiers, printable storage IDs, canonical positive decimal generation, SHA-256 digests, absolute mount roots, bearer tokens and safe-integer epochs before launching or sending. Preserve Unicode; reject unpaired surrogates instead of silently replacing them. The writer would turn one into `?`, so this also holds for every Runtime Session ID and for the `sessionId`, `promptId`, `callId` and `argsDigest` of a tool v2 reference, which would otherwise reach the Worker as another Session's or call's identity. Tool names and tool input keep their existing handling.
Use the closed [managed-context envelope](2026-09-25-managed-context-envelope.md) and [Worker behavior](2026-09-26-managed-context-worker.md). Validate identifiers, printable storage IDs, canonical positive decimal generation, SHA-256 digests, absolute mount roots, bearer tokens and safe-integer epochs before launching or sending. Preserve Unicode; reject unpaired surrogates instead of silently replacing them. The writer would turn one into `?`, so this also holds for every Runtime Session ID and for the `sessionId`, `promptId`, `callId` and `argsDigest` of a tool v2 reference, which would otherwise reach the Worker as another Session's or call's identity. It also holds for the tool name and for every key and string of the tool input, in a reference or in a deferred payload, where an escaped surrogate passes the check on the payload text: the Worker would otherwise run a call the caller never sent, and `?` is a wildcard in a shell command.

| Surface | Ownership and verification |
| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| boot v2 / ready v2 | Process bootstrap; exact ready keys, managedContext, seed identity and canonical loopback origin. No boot v1 downgrade. |
| POST `/internal/managed-runtime/v3/attest` | Selected Runtime; compare every persisted Workspace/storage/root and seed field, including incarnation. Expose attested storage identity to the Broker's independent admission check. |
| POST `/internal/managed-runtime/v3/context` | Selected Runtime and named Session: the client takes the READY binding record and the Session's record, and requires the Session to have been acquired on that binding at its current generation, and the binding's scope and, under session isolation, its isolation key to be the Session's. Send immutable W0a binding, computed digest and operation ID; verify every receipt field against the original request and receiving incarnation. |
| tool v2 | Existing Session owner and original execution reference. Preserve context-unavailable/conflict refusals so they do not masquerade as Runtime identity replacement. Status/cancel remain available for the original execution. |
| Surface | Ownership and verification |
| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| boot v2 / ready v2 | Process bootstrap; exact ready keys, managedContext, seed identity and canonical loopback origin. No boot v1 downgrade. |
| POST `/internal/managed-runtime/v3/attest` | Selected Runtime; compare every persisted Workspace/storage/root and seed field, including incarnation. Expose attested storage identity to the Broker's independent admission check. |
| POST `/internal/managed-runtime/v3/context` | Selected Runtime and named Session: the client takes the READY binding record and the Session's record, and requires the Session record to be ACQUIRING or READY and to name that binding at its current generation, the binding to have no drain requested, and the binding's scope and, under session isolation, its isolation key to be the Session's. Send immutable W0a binding, computed digest and operation ID; verify every receipt field against the original request and receiving incarnation. |
| tool v2 | Existing Session owner and original execution reference. Preserve context-unavailable/conflict refusals so they do not masquerade as Runtime identity replacement. Status/cancel remain available for the original execution. |

Context requests and responses are bounded to 16 KiB, have JSON UTF-8 and no-store response requirements, and reject redirects/incompatible peers. Installation is an explicit transport operation, not automatically invoked by acquire: W0c-2 has no authority to choose frozen Session configuration. A successful receipt proves context installation only, not activation or permission to execute.

## 4. Bounded startup and recovery

For managed-context requests, persist a resource handle before process launch. A binding with such a handle but without an attested lease may not automatically launch again. A failed or ambiguous first attempt transitions to `RECOVERY_BLOCKED`; repeated warm requests and Broker restarts cannot allocate a replacement generation. Once the block is recorded, a call that failed with a retryable error answers 409 `runtime_broker_recovery_blocked` instead, including when the attempt outlives its deadline; a non-retryable error is answered as is. If the block cannot be recorded, the call keeps its original answer; the next call then blocks if the resource handle was persisted. Even a crash between handle persistence and process launch blocks automatic retry. Legacy startup policy remains unchanged.
For managed-context requests, persist a resource handle before process launch. A binding with such a handle but without an attested lease may not automatically launch again. A failed or ambiguous first attempt transitions to `RECOVERY_BLOCKED`; repeated warm requests and Broker restarts cannot allocate a replacement generation. Once the block is recorded, a call that failed with a retryable error answers 409 `runtime_broker_recovery_blocked` instead, including when the attempt outlives its deadline; a non-retryable error that arrives before the deadline is answered as is, even when the deadline fires while the block is being recorded. If the block cannot be recorded, the call keeps its original answer, and the repository failure is kept as a suppressed exception of that answer or, when the answer wraps the launch failure, of its cause; the next call then blocks if the resource handle was persisted. Even a crash between handle persistence and process launch blocks automatic retry. Legacy startup policy remains unchanged.

Ready and attestation incompatibility fail closed. Failed children are terminated by the provisioner. Recovery requires evidence that the original process cannot execute and an authorized lifecycle action; this slice adds no public retry endpoint. Runtime-ready reconciliation remains observational and uses the saved request/seed.

Expand All @@ -51,7 +51,7 @@ Changes are limited to Java Runtime Broker request/provisioner, local worker boo
- Verify installation replay, Session conflict, missing directory refusal and unchanged legacy boot v1 against real processes.
- Pin legacy request/scope hashes; test existing-schema upgrade, storage roundtrip and tamper rejection across repository instances.
- Prove repeated warm and restart after an ambiguous launch do not spawn another process; cover the crash-before-launch marker and the deadline.
- Refuse installation on a binding other than the one the Session was acquired on, on another placement's Runtime or on a binding that is not READY, and ill-formed Session or reference IDs, before sending; tolerate a concurrent schema upgrade.
- Refuse installation for a Session record that is not ACQUIRING or READY, on a binding other than the one the Session record names, on another placement's Runtime or on a binding that is not READY or has a drain requested, and ill-formed Session or reference IDs, before sending; tolerate a concurrent schema upgrade.
- Run focused tests, Java Checkstyle, and two clean self-audit passes before pushing.

The E2E plan and observations are maintained in `.qwen/e2e-tests/managed-context-broker.md`. Baseline tests use the global CLI first; final tests use the local bundle. No model credentials or external model calls are needed.
Expand Down
Loading
Loading