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
Commit f78a83e
Browse filesBrowse the repository at this point in the historyBrowse files
feat(runtime): envelope the dispatcher's two discovery bodies (#9813)
Inherits the #9436 maintainer ruling (2026-08-18, option A) with its reason
intact: machine-read discovery bodies are the envelope's core constituency
and the migration is one additive key. Adds success: true to both
GET /.well-known/objectstack and the REST-less GET {prefix}/discovery
fallback, pins the shape in dispatcher-plugin.routes.test.ts, updates the
two documenting pages, and grows check-route-envelope.mjs an enumerated
fourth scan population for express-style res.json writes on an IHttpServer
(dispatcher-plugin.ts: unenveloped 1, ratcheted to #9936; the discovery
walk for the dialect is #9937).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WeN7F6jQFpcqW2BN56RdPa
Copy file name to clipboardExpand all lines: content/docs/api/index.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -151,7 +151,7 @@ send an atomic batch or fall back to client-side sequencing, instead of probing
151
151
152
152
### `GET /.well-known/objectstack`
153
153
154
-
Served by the runtime dispatcher (`@objectstack/runtime`), not `@objectstack/rest` — its body is wrapped as `{ "data": { ... } }` and includes fields (`name`, `environment`, `features`, `locale`) that the `@objectstack/rest`-served `/api/v1` response above does not. The client SDK's `connect()` tries `/api/v1/discovery` first and falls back to this endpoint, unwrapping either `body.data` or the bare `body`.
154
+
Served by the runtime dispatcher (`@objectstack/runtime`), not `@objectstack/rest` — its body is wrapped in the response envelope as `{ "success": true, "data": { ... } }` and includes fields (`name`, `environment`, `features`, `locale`) that the `@objectstack/rest`-served `/api/v1` response above does not. The client SDK's `connect()` tries `/api/v1/discovery` first and falls back to this endpoint, unwrapping either `body.data` or the bare `body`.
155
155
156
156
<Callouttype="info">
157
157
**Service Status Values**: `available` (fully operational), `registered` (route declared but handler unverified — may return 501), `degraded` (partial functionality), `unavailable` (not installed), `stub` (placeholder that throws errors)
* Surface 4 (#9813): modules that write express-style `res.json(…)` responses
688
+
* on an `IHttpServer` — the dialect none of the other three surfaces can see.
689
+
* `dispatcher-plugin.ts` served the exact `{ data }` discovery shape #9436 was
690
+
* ruled on for a day with no counter anywhere, because it writes through `res`
691
+
* rather than a Hono context and returns nothing to a central sender.
692
+
*
693
+
* ⚠ ENUMERATED, not discovered. The other populations refuse an undeclared
694
+
* response-writing module; this one audits only the files named here, because
695
+
* a discovery walk for this dialect first needs a read/write discriminator —
696
+
* fetch's `Response.json()` is a zero-argument READ on the same receiver name
697
+
* (`const res = await fetch(…); await res.json()`), and 20 non-test files
698
+
* under packages/ carry the `res.json(` spelling today, most of them fetch
699
+
* readers. Growing the walk is #9937; adding a NEW express-style route module
700
+
* to this table is part of adding the module.
701
+
*
702
+
* Entries carry the same counters, `ratchet`/`exempt`/`note` grammar and
703
+
* audit (`auditPluginRouteModule`) as PLUGIN_ROUTE_MODULES — one grammar, two
704
+
* receiver dialects.
705
+
*/
706
+
constIHTTP_ROUTE_MODULES={
707
+
// Ten bodies. The two discovery bodies (`/.well-known/objectstack`,
708
+
// unconditional, and the REST-less `${prefix}/discovery` fallback) were
709
+
// enveloped by #9813 under the #9436 maintainer ruling (2026-08-18, option
710
+
// A, inherited with its reason intact: machine-read discovery bodies are
711
+
// the envelope's core constituency and the migration is one additive key —
712
+
// deliberately NOT #9389's pre-auth exemption, whose closed SPA-read list
713
+
// these sites are not on). The two `{ success: false, error: buildApiError(…) }`
714
+
// exits are conformant, and five relayed bodies (`result.body`,
715
+
// `ANONYMOUS_DENY_BODY`, …) are deliberately invisible, as everywhere.
716
+
'packages/runtime/src/dispatcher-plugin.ts': {
717
+
unenveloped: 1,
718
+
ratchet: '#9936 (envelope or rule on the SSE-fallback `{ events }` body)',
719
+
note: 'the streaming branch\'s JSON fallback — a transport whose `res` cannot stream gets the collected events as a bare `{ events }`, no `success` flag and the payload beside the envelope rather than under `data`. A different consumer population from the discovery bodies (callers that asked for an SSE stream), so #9813\'s inherited ruling does not reach it; #9936 carries the fork',
720
+
},
721
+
};
722
+
684
723
/**
685
724
* Count the ways one plugin-route module's hand-built Hono bodies depart from
686
725
* the declared envelope.
687
726
*
688
727
* Only `<ctx>.json(<objectLiteral>, …)` is judged — see the header on why
689
728
* relayed bodies are deliberately invisible here.
690
729
*
730
+
* `receivers` names the identifiers that count as a response receiver. The
731
+
* default is the Hono pair; passing `EXPRESS_RESPONSE_RECEIVERS` reads the
732
+
* express-style `res.json(…)` dialect instead (#9813) — same body grammar,
733
+
* different receiver, so the counters and their meanings are shared.
734
+
*
691
735
* @param {string} source TypeScript source text.
736
+
* @param {string} fileName reported in sites.
737
+
* @param {Set<string>} receivers identifiers judged as response receivers.
0 commit comments