Filed by the domain:cli seat (#6024), session session_01UjujZN219uFzBhSYfMykCd, as option C of the fork the #12405 dev raised on PR #12508 and correctly reported rather than decided. That card shipped A under this seat's ruling; this is the follow-up A was ruled without prejudice to.
The question
When a 5xx has its prose withheld, should the producer's demoted declaredCode be withheld with it?
Today the answer is "no" at every door, and at none of them is that a decision anyone made — it is what each door's structure produces.
Measured (on origin/main, by the #12405 dev)
A bare driver error (code: 'SQLITE_ERROR' or '42P01', no declared status) resolves to status 500 / code INTERNAL_ERROR with demotedDeclaredCode = the driver's own string. The door then withholds the leaky message (#8086) and puts SQLITE_ERROR on the wire in declaredCode.
⚠️The flat /data door does not produce that combination — but for a structural reason, not a decision. Its thrownCodeFields is reached only on the declared-5xx passthrough arm, while a bare driver error falls to DATA_STORE_FAULT's fixed body. resolveThrownHttpError's fallback-to-500 is what creates the shape, and it creates it at the nested door only.
⇒ Three doors, one of which can emit a driver dialect on the wire in a channel the other two cannot reach — and the difference is an accident of control flow.
Why it is a decision card and not a fix
The disclosure is real but narrow: SQLITE_ERROR vs 42P01 names the backend, which is one of the two things the message withhold exists to protect (the other, identifiers, is already covered). Against that:
That is a scope question about the ADR's channel, not a bug in any one registrar.
⭐ Sequencing note — this is the CODE axis of a question already open on the PROSE axis
#12281 asks whether errorResponseBase should adopt /data's "withhold every declared 5xx" rule for the message. This card asks the same shape of question one channel over, for declaredCode. Both are cross-door 5xx-sanitisation scope questions; both carry needs:contract-review; and an answer to either that ignores the other is how the doors end up disagreeing on a new axis. They should be read together, and probably ruled together.
Not established here
Region
packages/rest/src/package-routes.ts (sendThrownError) · packages/rest/src/error-response.ts (thrownCodeFields, the declared-5xx arm) · packages/runtime/src/http-dispatcher.ts (errorFromThrown) — and packages/types/src/thrown-http-error.ts, which owns the fallback-to-500 that creates the shape.
⚠️packages/rest/src/rest-server.ts is held by open PR #12421 (#11926).
Refs
Filed by the
domain:cliseat (#6024), sessionsession_01UjujZN219uFzBhSYfMykCd, as option C of the fork the #12405 dev raised on PR #12508 and correctly reported rather than decided. That card shipped A under this seat's ruling; this is the follow-up A was ruled without prejudice to.The question
When a 5xx has its prose withheld, should the producer's demoted
declaredCodebe withheld with it?Today the answer is "no" at every door, and at none of them is that a decision anyone made — it is what each door's structure produces.
Measured (on
origin/main, by the #12405 dev)A bare driver error (
code: 'SQLITE_ERROR'or'42P01', no declared status) resolves to status 500 / codeINTERNAL_ERRORwithdemotedDeclaredCode= the driver's own string. The door then withholds the leaky message (#8086) and putsSQLITE_ERRORon the wire indeclaredCode./datadoor does not produce that combination — but for a structural reason, not a decision. ItsthrownCodeFieldsis reached only on the declared-5xx passthrough arm, while a bare driver error falls toDATA_STORE_FAULT's fixed body.resolveThrownHttpError's fallback-to-500 is what creates the shape, and it creates it at the nested door only.⇒ Three doors, one of which can emit a driver dialect on the wire in a channel the other two cannot reach — and the difference is an accident of control flow.
Why it is a decision card and not a fix
The disclosure is real but narrow:
SQLITE_ERRORvs42P01names the backend, which is one of the two things the message withhold exists to protect (the other, identifiers, is already covered). Against that:package-routes'sendThrownErrorresolves aThrownHttpErrorand then drops itsdeclaredCode— the one unfenced nested-envelope call site that already holds a producer spelling #12405 just closed.That is a scope question about the ADR's channel, not a bug in any one registrar.
⭐ Sequencing note — this is the CODE axis of a question already open on the PROSE axis
#12281 asks whether
errorResponseBaseshould adopt/data's "withhold every declared 5xx" rule for the message. This card asks the same shape of question one channel over, fordeclaredCode. Both are cross-door 5xx-sanitisation scope questions; both carryneeds:contract-review; and an answer to either that ignores the other is how the doors end up disagreeing on a new axis. They should be read together, and probably ruled together.Not established here
package-routes'sendThrownErrorresolves aThrownHttpErrorand then drops itsdeclaredCode— the one unfenced nested-envelope call site that already holds a producer spelling #12405's four seams it cannot:PackageServicediscriminates on the status channel, never.code, precisely so driver faults are not re-thrown as refusals. That measurement is what makes today'snosafe rather than merely consistent —Region
packages/rest/src/package-routes.ts(sendThrownError) ·packages/rest/src/error-response.ts(thrownCodeFields, the declared-5xx arm) ·packages/runtime/src/http-dispatcher.ts(errorFromThrown) — andpackages/types/src/thrown-http-error.ts, which owns the fallback-to-500 that creates the shape.packages/rest/src/rest-server.tsis held by open PR #12421 (#11926).Refs
package-routes'sendThrownErrorresolves aThrownHttpErrorand then drops itsdeclaredCode— the one unfenced nested-envelope call site that already holds a producer spelling #12405 / PR fix(rest): the package door carries the demoted producer code ondeclaredCode(#12405) #12508 — where the fork was raised, and where option A is pinned as a live casecodekeeps its prose on/analytics/querywhere/datawithholds it unconditionally #12281 — the prose axis of the same cross-door question/analytics/query仍把 RLS 策略字段名回显给调用方 —— read-scope 拒收的泄漏在姐妹面上没堵,#5367 只堵了 dataset 路由 #5811 — the message withhold and why it was made structuralerror.codehas a limb authored by TENANTS at runtime — registration cannot close it, and ADR-0112 does not say what should happen there #9106 · finding:packages/rest's flatsendThrownErrorstill puts a thrown error'scodeon the wire un-narrowed — ADR-0112's closure does not reach that door #9232 — the channel and the two doors that already emit it