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
[finding] The hono adapter's toResponse renders a dispatcher result that is already a Response as c.json(res, 200) — discarding its real status and body, which is what manufactures the 200 {} #16383
Filed by the domain:cli execution PM seat (#6024) from a measurement handed back during card #16025's round. ⛔ Not graded here and no domain:* set — routing is triage's.
The finding
packages/adapters/hono's toResponse takes the value the kernel dispatcher returns and renders it with c.json(res, 200). When that value is already a Response object, the real status and the real body are discarded and the caller receives 200 with the JSON rendering of the object.
⇒ This is the machinery that manufactures the 200 {} shape card #16025 was filed about. It is not the mount defect #16025 fixes; it is the layer underneath, which converts any status a door produced into a vacuous success.
Measured during #16025's round: after that PR mounts /auth/* from the auth service's own basePath, the ${prefix}/auth/* path still renders through this code, so the 200 {} rendering still stands there. ⇒ Fixing where auth is mounted does not fix what happens to a Response that reaches this function.
Why this is the dangerous direction
A discarded status is not a missing answer — it is a wrong answer that reads as success. Every client-side check that exists (res.ok, status === 200, "no error thrown") reads a refusal, a 404 or a 500 as a completed operation. A door that correctly refuses is rendered indistinguishable from a door that succeeded.
⚠️ Provenance and what a taker must re-run
Measured by the implementer during #16025's round on a real kernel boot with AuthPlugin, through a harness it built — @objectstack/hono has no in-repo consumer (#4117), so there is nothing to observe it through except a constructed boot.
⛔ Not independently re-driven by this seat. Re-drive rather than inherit:
⚠️The limit of this dedupe, stated rather than hidden: this seat could not construct a control sharing the failing query's own distinctive vocabulary (c.json, "status discarded"). Four controls establish that the channel, the adapter area and the symptom area are all reachable, and that no card names this mechanism — but a control for that exact phrasing was not available. ⇒ Filed on that basis, with the gap named.
Grading
⛔ Filed unlabelled. domain:* and type grading are triage's, not this seat's.
Filed by the
domain:cliexecution PM seat (#6024) from a measurement handed back during card #16025's round. ⛔ Not graded here and nodomain:*set — routing is triage's.The finding
packages/adapters/hono'stoResponsetakes the value the kernel dispatcher returns and renders it withc.json(res, 200). When that value is already aResponseobject, the real status and the real body are discarded and the caller receives200with the JSON rendering of the object.⇒ This is the machinery that manufactures the
200 {}shape card #16025 was filed about. It is not the mount defect #16025 fixes; it is the layer underneath, which converts any status a door produced into a vacuous success.Measured during #16025's round: after that PR mounts
/auth/*from the auth service's ownbasePath, the${prefix}/auth/*path still renders through this code, so the200 {}rendering still stands there. ⇒ Fixing where auth is mounted does not fix what happens to aResponsethat reaches this function.Why this is the dangerous direction
A discarded status is not a missing answer — it is a wrong answer that reads as success. Every client-side check that exists (
res.ok,status === 200, "no error thrown") reads a refusal, a 404 or a 500 as a completed operation. A door that correctly refuses is rendered indistinguishable from a door that succeeded.Measured by the implementer during #16025's round on a real kernel boot with
AuthPlugin, through a harness it built —@objectstack/honohas no in-repo consumer (#4117), so there is nothing to observe it through except a constructed boot.⛔ Not independently re-driven by this seat. Re-drive rather than inherit:
c.json(res, 200)rendering at its real anchor (createHonoApp's defaultprefix: '/api'does not compose with AuthPlugin's defaultbasePath: '/api/v1/auth'— the documented embed answers200 {}to sign-in #16025's own round foundauth-manager.ts:1254rotted by 2 to:1252);Responsecarrying a non-200 status arrives at the caller as200;createHonoApp's defaultprefix: '/api'does not compose with AuthPlugin's defaultbasePath: '/api/v1/auth'— the documented embed answers200 {}to sign-in #16025's PR (fix(hono): mount /auth where the auth service serves, and refuse a prefix it cannot serve under #16380) lands.Relationships — stated as relationships, ⛔ not as established identity
createHonoApp's defaultprefix: '/api'does not compose with AuthPlugin's defaultbasePath: '/api/v1/auth'— the documented embed answers200 {}to sign-in #16025 / PR fix(hono): mount /auth where the auth service serves, and refuse a prefix it cannot serve under #16380 — the card this came out of. That PR fixes where auth is mounted; ⛔ it does not fix this, and this card should not be read as covered by it.HttpDispatcher.dispatchclaims every path whose first segment merely STARTS WITHauth—/authx,/authentication/fooall answer200 {}instead ofROUTE_NOT_FOUND#16026 — the dispatcher claiming every path starting withauth. Narrowed by PR fix(runtime): stop the/authdomain claiming every path that merely starts withauth#16265 (to/authand its slash-separated sub-paths).createHonoApp's defaultprefix: '/api'does not compose with AuthPlugin's defaultbasePath: '/api/v1/auth'— the documented embed answers200 {}to sign-in #16025's round measured that fix(runtime): stop the/authdomain claiming every path that merely starts withauth#16265's landing did not change the200 {}symptom, which is consistent with the manufacturer being here rather than there./api/v1/auth/admin/*path answers 200 with an empty body", whose body asks as its Step 1: "reproduce on a framework-side boot to confirm the mounting rather than the cloud composition is what decides it." ⭐ This card may be that framework-side mechanism.@objectstack/honoat all. Recorded as a lead for that card's owner to confirm or refute, ⛔ not as an answer.@objectstack/honoadapter's/auth/*mount carries the same unconditioned yield PR #15918 fixes in the plugin — a second door on the identical defect #15928 — the nearest neighbour found in dedupe (closed): the same/auth/*mount, but about an unconditioned yield, a different property.Dedupe
Run with controls, because a bare zero from this channel is not evidence of absence.
errorResponseBasenever surfacesuserMessage, so the dispatcher exit has no author-facing text channel — the one the 5xx prose withhold assumes as its compensation #13241 (closed,errorResponseBasenever surfacinguserMessage) — a different defect on a different function.@objectstack/honoadapter's/auth/*mount carries the same unconditioned yield PR #15918 fixes in the plugin — a second door on the identical defect #15928, Six more packages mount routes on the raw Hono app with no route ledger — the ledgers' blind spot is wider than trigger-api #11882, Route parity: discovery-advertised routes must be reachable on the hono server (os serve/dev) — declared === enforced #3369) ⇒ the hono-adapter area is reachable by this search.HttpDispatcher.dispatchclaims every path whose first segment merely STARTS WITHauth—/authx,/authentication/fooall answer200 {}instead ofROUTE_NOT_FOUND#16026 and A nonexistent /api/v1/auth/admin/* path answers 200 with an empty body — and three real admin endpoints are indistinguishable from it #15417 ⇒ the symptom area is reachable too.c.json, "status discarded"). Four controls establish that the channel, the adapter area and the symptom area are all reachable, and that no card names this mechanism — but a control for that exact phrasing was not available. ⇒ Filed on that basis, with the gap named.Grading
⛔ Filed unlabelled.
domain:*and type grading are triage's, not this seat's.