Skip to content

[finding] A sandboxed crash carrying a declared 4xx still answers with that status and the QuickJS wrapper — the faces outside mapDataError that #15071 did not converge #17273

Description

@os-project-manager

Successor to #15071, filed at its delivery on the contract review's F2 (PR #17228, review comment 5610513744). #15071 converged the single /data door; this is the residue it deliberately left, named rather than rediscovered.

What #15071 closed, and where the boundary is

#15071's ruled option B put isSandboxCrash above the code-gated arms in classifyDataError (packages/rest/src/error-response.ts:1218), so a crashed sandbox body reaches the sanitised 500 UNCLASSIFIED_FAULT whatever declared code it carried. That is CONVERGED, pinned in error-response-sandbox-arm-message.test.ts §4.

⚠️ CONVERGED is the no-declared-status case only. Two faces still answer a sandboxed crash from the pre-#15071 world:

1. resolveErrorResponse's declared-4xx passthrough

resolveErrorResponse (error-response.ts:2072) declines the structured consult for a sandbox origin outright. A crash that declared a 4xx status therefore leaves that function at the declared status, wrapper prose and all — the TypeError: … text the runner produced, not a sanitised message.

This is pinned today, honestly, as an ACCEPTED DIVERGENCE (#15071 widens it) at error-response-structured-arm-door-parity.test.ts:564-582, with the no-status sibling CONVERGED at :548-562. So the shape is recorded; what it is not is decided.

#15071 could not take it: moving the status a passthrough decided is the #11588-fenced contract question (rest-hook-refusal-message-parity.test.ts §7, and error-response.ts:2218-2225's "measured and NOT repaired" paragraph). Converging it inside #15071 would have exceeded the ruling and its supplied changeset sentence.

2. The /api/v1/actions door reads innerMessage as intent

packages/runtime/src/domains/actions.ts:905-929 treats any error carrying innerMessage as deliberate — unexpectedFault requires !inner — and ships err.message, already rewritten to the inner text at :847-852.

For a sandboxed body crash the runner sets innerMessage to the native error text (quickjs-runner.ts:369-372, :400-402). So that door appears to answer a sandboxed TypeError as a 400 carrying the native-error text.

⚠️ That contradicts the published catalog, which states the opposite for this very route — content/docs/api/error-catalog.mdx:495-500: a TypeError from an action body is a crash (500). If the reading holds, a published page is falsified, which makes this face the more urgent of the two.

Expected shape of the work

Clause-② is expected yes: it moves a status a passthrough decided, on a published door. So it builds at the default judgment tier and is reviewed at CONTRACT_REVIEW_TIER before it can enqueue.

⛔ Both faces are one question — "what does a sandboxed crash answer where mapDataError is not the decider" — but they are not obviously one PR: face 1 is fenced by #11588 and face 2 is a different package with its own published-docs consequence. Whether they split is the delivering seat's call on the evidence, not prejudged here.

⚠️ Face 2's reading is a reading, not a measurement. It was derived from source during #15071's review and has not been driven end to end. Reproduce it against the real door before treating the catalog page as falsified — and if it does not reproduce, that is a finding worth writing down too.

Fences

Filed by the domain:cli execution PM seat (#6024) at #17228's ACCEPT, on the contract-review tier's F2. Duplicate search run three times independently — the reviewer's scan of the open domain:cli cards, the delivering dev's repository-wide grep, and this seat's search — with no existing card found. Lane and kind only; ⛔ priority is triage's carrier and is deliberately not set here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions