Skip to content

Commit 97d881a

Browse files
committed
chore(changeset): 23914 hono — the reader refuses; the forwarded request and the method rows stated as they are
Claude-Session: https://claude.ai/code/session_018t6a5rvqPRvEDMCVVW9kYT Co-authored-by: Claude <noreply@anthropic.com>
1 parent 0cee7c3 commit 97d881a

1 file changed

Lines changed: 7 additions & 6 deletions

File tree

‎.changeset/23914-hono-body-refusal.md‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,26 @@
22
'@objectstack/hono': minor
33
---
44

5-
fix(hono)!: `createHonoApp` refuses a declared JSON body that does not parse with `400 INVALID_REQUEST` before `dispatch()` runs, instead of dispatching it as `{}`
5+
fix(hono)!: `createHonoApp` refuses a declared JSON body that does not parse with `400 INVALID_REQUEST` when the dispatched domain reads it, instead of dispatching it as `{}`
66

77
Clause-②: no (narrowing)
88

9-
<!-- adr-0087: not-required (no-migration-prescription) No metadata moves: no spec key, authorable spelling, object definition or stored shape is added, removed, renamed or re-shaped, no stored row is rewritten or deleted, and no exported declaration is added, removed or narrowed, so there is nothing for `objectstack migrate meta` to rewrite. What narrows is the accept set of the `createHonoApp` catch-all and its `/auth/*` fallback for one input: a body declared as JSON that does not parse, which used to be dispatched as `{}`. The remedy is in the requests a client sends, never a rewrite of a package source or a stored row. The other categories are closed on facts: the package publishes (not unpublished); no ADR-0087 id is named or touched (not registered or already-registered); and nothing exported is removed or narrowed (not runtime-interface-only, type-surface-only or runtime-export-retired). -->
9+
<!-- adr-0087: not-required (no-migration-prescription) No metadata moves: no spec key, authorable spelling, object definition or stored shape is added, removed, renamed or re-shaped, no stored row is rewritten or deleted, and no exported declaration is added, removed or narrowed, so there is nothing for `objectstack migrate meta` to rewrite. What narrows is the accept set of the `createHonoApp` catch-all and its `/auth/*` fallback for one input: a body declared as JSON that does not parse, which used to be dispatched as `{}` and is now refused when a domain reads it. The remedy is in the requests a client sends, never a rewrite of a package source or a stored row. The other categories are closed on facts: the package publishes (not unpublished); no ADR-0087 id is named or touched (not registered or already-registered); and nothing exported is removed or narrowed (not runtime-interface-only, type-surface-only or runtime-export-retired). -->
1010

1111
**BREAKING** (an accept-set narrowing), shipped as `minor` under the launch-window convention for breaking changes.
1212

1313
The `${prefix}/*` catch-all handed `dispatch()` `{}` for a body that did not parse, and the data domain read that as an empty query or an empty update: a truncated `POST /data/OBJECT/query` answered every row the caller could read, and a truncated `PATCH` answered `200` for an update that changed nothing.
1414

1515
What changes for an integrator, on a host that serves `createHonoApp`:
1616

17-
- A `POST`, `PUT` or `PATCH` body sent as `application/json` (matched case-insensitively) that is not blank and does not parse: FROM a dispatch with `{}` and whatever the domain answered for it, TO `400` with `{ "success": false, "error": { "code": "INVALID_REQUEST", "message": "The request body could not be parsed as JSON (it was sent as application/json). It was refused rather than read as an empty body: send a well-formed JSON document, or no body at all." } }`, and no domain runs. The same body, refused with the same status and body, as `@objectstack/plugin-hono-server` answers it.
18-
- The same applies to the `/auth/*` legacy fallback that runs when no auth service is registered.
17+
- A `POST`, `PUT` or `PATCH` body sent as `application/json` (matched case-insensitively) that is not blank and does not parse, to a domain that reads the parsed body (the data, metadata and every other domain that takes `body`): FROM that domain's answer for `{}`, TO `400` with `{ "success": false, "error": { "code": "INVALID_REQUEST", "message": "The request body could not be parsed as JSON (it was sent as application/json). It was refused rather than read as an empty body: send a well-formed JSON document, or no body at all." } }`. The domain acts on nothing past its read of the body, and the dispatcher's own gates still answer first. This is the same status and body `@objectstack/plugin-hono-server` answers for the same request.
18+
- The same applies to the `/auth/*` legacy fallback that runs when no auth service is registered, for every method it hands a body (all but `GET` and `HEAD`).
1919

2020
**Remedy, in one line.** Send a JSON body as well-formed JSON with `Content-Type: application/json`, or send no body.
2121

2222
**Unchanged.**
2323

2424
- An empty or whitespace-only JSON body is dispatched as `{}` (an empty query), as before.
25-
- A body that does not declare JSON is read as before: parsed when it is JSON, `{}` when it is not. The forwarded request still arrives unread, so the `/approvals/act` form `POST` and the inbound automation hooks read their own bytes as before.
26-
- `GET`, `HEAD` and `DELETE` are dispatched with no body, as before.
25+
- A body that does not declare JSON is read as before: parsed when it is JSON, `{}` when it is not.
26+
- The request handed on beside the body still arrives unread, in every case. A domain that forwards it and reads its own bytes answers exactly as before, a malformed JSON body included: `/webhooks/redeliver` and the inbound automation hooks give their own refusal after their own sign-in or signature check, and the `/approvals/act` form `POST` reads its form.
27+
- The catch-all dispatches `GET`, `HEAD` and `DELETE` with no body, and the `/auth/*` fallback hands `GET` and `HEAD` `{}`, as before.

0 commit comments

Comments
 (0)