You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Should a nested hook refusal's wire sentence match /data byte-for-byte? The action door still ships the hook NAME threw: wrapper, and closing that needs SANDBOX_ERROR_PASSTHROUGH widened — a declared decision about what sandboxed code may read #17682
Filed by the domain:cli execution PM seat (pm:seat#6024, session session_01TSf4DV7ziu4V5j73e46b7c) out of PR #17679's acceptance, as the open question its delivering dev raised and correctly declined to answer. ⛔ Not graded, no domain:*, no priority, no assignee.
⚠️Deliberately NOT in the decision box yet. It is pre-staged with its analysis complete, because it cannot be answered until objectui#9151 establishes whether the wrapper text ever reaches a user. Putting it to the maintainer now would be asking a question whose premise is unmeasured. ⇒ the Blocked-by: line above is the trigger; when that card resolves, this becomes a one-read decision rather than a fresh investigation.
PR #17679 makes a nested sandboxed hook refusal answer a 4xx with the business sentence instead of 500 INTERNAL_ERROR. What it deliberately did not change is the sentence's shape:
door
what the caller receives for one hook refusal
/api/v1/data/:object/:id
the bare sentence — A contract cannot be submitted without a version file
⇒ two doors, one refusal, two sentences. ⭐ PR #17679 left the action door's sentence byte-identical to what the 500 already carried, which is why it is a status fix and not a message change — and it is pinned as such.
Why closing it is a decision and not a repair
The nested body's clean innerMessage does not survive the VM hop into the action's sandbox. Carrying it across means adding a member to SANDBOX_ERROR_PASSTHROUGH, the host-to-VM marshalling allowlist, and packages/runtime/src/sandbox/script-runner.ts's own docblock makes widening that allowlist a declared decision, never a consumer-side accretion.
⚠️ That allowlist governs what untrusted sandboxed code can read. ⇒ this is a security/permission boundary, which is on the maintainer floor — ⛔ not a domain:cli seat call and ⛔ not a rider on a p2 status fix.
The three routes, and why one is already excluded
A — leave it. The status/code defect is closed; the sentence is exactly what the 500 already carried, so nothing regressed. The wrapper-on-the-wire gap stays recorded.
⭐ The delivering dev's recommendation, and this seat's, for now.
B — widen SANDBOX_ERROR_PASSTHROUGH with innerMessage, so both doors ship one identical sentence. Small diff; a declared decision about the sandbox boundary.
C — strip the wrapper at the action door instead. ⛔ Already excluded on the contract's own words, not on preference: error-response.ts's sandboxBusinessMessage docblock forbids exactly this — "deliberately a READ of a field the sandbox populated, never a pattern-strip of the wrapper off .message" — because it would also rewrite a plain error whose own prose happens to contain threw:. ⇒ ⛔ do not re-propose C.
#17265 (parent) · PR #17679 (the ① fix) · objectui#9151 (the blocker — does the sentence reach a user at all) · #11588 (sandboxBusinessMessage) · #11684 (the /analytics precedent) · #12034 / #17419 (the response-shape surface, separately fenced)
Closed not_planned: a pre-staged p3 decision whose premise is two blocks deep. Route A (leave it, recorded) is today's state, and closing keeps it
Triage seat (objectstack-wide, seat post #6015) · session_01W89enF2dYV7K4N2Fbfj33f · 2026-09-27T16:29Z. ⛔ Not a claim.
Provenance: a triage decision, taken under the maintainer's standing instruction to judge stuck blocked cards directly instead of leaving them to wait on a lane (verbatim 「这些不应该等车道,你应该直接判断」, the maintainer's chat with the triage session session_01W89enF2dYV7K4N2Fbfj33f, 2026-09-27; said of an earlier set of blocked cards). ⛔ Not a maintainer ruling on this card.
This card was kept out of the decision box on purpose, until objectui#9151 measures whether the action door's hook 'x' threw: wrapper ever reaches a user. objectui#9151 is itself pm:blocked and was last touched 2026-09-14. The premise is unmeasured, and nobody is measuring it.
Route A, leave it with the gap recorded, was the recommendation of both the delivering dev and the lane seat, and it is exactly today's state. Closing changes no code and widens nothing: SANDBOX_ERROR_PASSTHROUGH stays as it is. The sandbox-boundary decision (route B) is neither taken nor foreclosed.
The four-facet analysis stays on this thread, so a reopen is a one-read decision.
Reopen when objectui#9151 closes with a reading that the wrapper sentence reaches a user, for example a toast, banner or console surface showing hook 'x' threw:. The question then goes to the maintainer as A or B. ⛔ Route C stays excluded, on sandboxBusinessMessage's own words.
Activity
objectstack-fleet commentedon Sep 27, 2026
Closed
not_planned: a pre-staged p3 decision whose premise is two blocks deep. Route A (leave it, recorded) is today's state, and closing keeps itTriage seat (objectstack-wide, seat post #6015) ·
session_01W89enF2dYV7K4N2Fbfj33f· 2026-09-27T16:29Z. ⛔ Not a claim.Provenance: a triage decision, taken under the maintainer's standing instruction to judge stuck blocked cards directly instead of leaving them to wait on a lane (verbatim 「这些不应该等车道,你应该直接判断」, the maintainer's chat with the triage session
session_01W89enF2dYV7K4N2Fbfj33f, 2026-09-27; said of an earlier set of blocked cards). ⛔ Not a maintainer ruling on this card.hook 'x' threw:wrapper ever reaches a user. objectui#9151 is itselfpm:blockedand was last touched 2026-09-14. The premise is unmeasured, and nobody is measuring it.SANDBOX_ERROR_PASSTHROUGHstays as it is. The sandbox-boundary decision (route B) is neither taken nor foreclosed.Reopen when objectui#9151 closes with a reading that the wrapper sentence reaches a user, for example a toast, banner or console surface showing
hook 'x' threw:. The question then goes to the maintainer as A or B. ⛔ Route C stays excluded, onsandboxBusinessMessage's own words.