Skip to content

Commit a4681f9

Browse files
hotlongclaude
andcommitted
chore(changeset): the dispatcher's /meta item, route and org-scope parity
Claude-Session: https://claude.ai/code/session_local_1d2a197c-c20e-4e90-9be8-413d4d432289 Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3bf6c80 commit a4681f9

1 file changed

Lines changed: 55 additions & 0 deletions

File tree

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
'@objectstack/rest': minor
3+
'@objectstack/runtime': patch
4+
---
5+
6+
fix(rest, runtime): the runtime dispatcher's `/meta` doors scope a caller to the organization `RestServer` scopes them to, and its item read, book tree and list answer what `RestServer`'s answer (#20408)
7+
8+
Clause-②: yes (widening) — `@objectstack/rest`'s root entry gains seven value exports (`createMetaItemAnswer`, `createMetaBookTreeAnswer`, `metaCallerOrganizationId`, `metaReadOrganizationId`, `projectMetaObjectSchema`, `refuseUnknownMetaListType`, `translateMetaEnvelope`) and five type exports (`MetaItemAnswer`, `MetaItemAnswerSources`, `MetaItemRequest`, `MetaBookTreeAnswer`, `MetaBookTreeSources`), and `MetaListAnswer` gains an optional `cacheControl`. `MetaListAnswerSources`, new in this same release with `createMetaListAnswer`, takes the transport's object-schema masker (`resolveObjectMasker`) instead of a whole-mask port, so the chain decides the cache posture for both transports. Nothing any published version exported is removed, renamed or narrowed. `@objectstack/runtime` publishes no new surface and stays a `patch`.
9+
10+
A host that mounts only the `${prefix}/*` catch-all (`createHonoApp`, and any
11+
adapter written on the public `HttpDispatcher` API) serves `/meta` through the
12+
runtime dispatcher. Until now, on such a host:
13+
14+
- **A member removed from an organization kept its metadata partition.** The
15+
dispatcher's `/meta` doors took the organization from the session's
16+
`activeOrganizationId` as stored. Under a wall-enforcing tenancy posture the
17+
identity resolver DROPS a claim naming an organization the caller no longer
18+
belongs to, and `RestServer` reads that vetted value. The dispatcher did not,
19+
so for the rest of the session the removed member was served that
20+
organization's org-scoped overlays (`view`, `dashboard`, `report`,
21+
`translation`, `email_template`) by the item read, the list, `/published` and
22+
`?state=draft`, listed its pending drafts on `GET /meta/_drafts`, and had a
23+
`PUT /meta/:type/:name` land in its partition. Every `/meta` door here now reads
24+
the vetted organization on the execution context, the value `RestServer` reads.
25+
- **`GET /meta/:type/:name` answered a different body.** Nothing was translated
26+
whatever `Accept-Language` or `?locale=` asked for. A doc kept its whole
27+
`translations` map, in no locale. An object schema came with no
28+
`sortability`. The answer had no `Vary: Accept-Language`.
29+
- **`?preview=DRAFT`** (any casing but lower) from a builder read the published
30+
world on the item read and the list. `RestServer` compares it
31+
case-insensitively.
32+
- **`GET /meta/object/:name?preview=draft`** from a builder answered the ACTIVE
33+
schema, never the pending draft.
34+
- **`GET /meta/totally_invented_type`** answered `200 {"items": []}`. `RestServer`
35+
refuses a segment that names no metadata type with `400 INVALID_REQUEST`.
36+
- **`GET /meta/book/:name/tree`** was no route: `404 ROUTE_NOT_FOUND` to a signed-in
37+
reader and `401` to an anonymous reader of a `public` book (ADR-0046 §6.7).
38+
- **An object schema served under an undetermined field visibility** (ADR-0106
39+
D6 tier 2: served unmasked) carried no `Cache-Control`. `RestServer` answers
40+
`private, no-store`. This was true of the list, the item read, `/published` and
41+
the legacy one-segment object read.
42+
43+
**What changed.** Everything `RestServer`'s `GET /meta/:type/:name` does after
44+
the store read moved, unchanged, into `createMetaItemAnswer`: absence, the item
45+
gate, the doc locale collapse, the object mask and its cache posture, and the
46+
body (the translation and `sortability`, `translateMetaEnvelope`). The book-tree
47+
route's whole answer moved into `createMetaBookTreeAnswer`, and the list's
48+
unknown-type refusal into `refuseUnknownMetaListType`. The list chain now
49+
applies the object mask itself (`projectMetaObjectSchema`) and reports the cache
50+
posture. The dispatcher's `/meta` domain calls each of these, and takes its
51+
organization from `metaCallerOrganizationId` / `metaReadOrganizationId`, which
52+
`RestServer`'s list and item reads ask too.
53+
54+
`RestServer`'s own answers are unchanged: the move is a refactor on that side,
55+
and every existing REST test passes unedited.

0 commit comments

Comments
 (0)