Skip to content

feat(runtime): package-scoped single-item metadata resolution via ?package= (ADR-0048)#1816

Merged
xuyushun441-sys merged 2 commits into
mainfrom
feat/adr-0048-meta-getitem-package
Jun 13, 2026
Merged

feat(runtime): package-scoped single-item metadata resolution via ?package= (ADR-0048)#1816
xuyushun441-sys merged 2 commits into
mainfrom
feat/adr-0048-meta-getitem-package

Conversation

@xuyushun441-sys

@xuyushun441-sys xuyushun441-sys commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

What

Make a single-item metadata GET (/meta/:type/:name?package=<id>) actually resolve package-scoped (prefer-local): when two installed packages ship an item of the same type/name, the requester's own package wins.

The bug this fixes

The first commit threaded ?package= into the runtime HTTP dispatcher, but the live serving path (RestAPI + ObjectQL protocol) still dropped it for cacheable types. Browser verification surfaced the real gap:

  • rest-server — the cacheable single-item GET called getMetaItemCached (ETag keyed on type+name only) and never passed packageId. So a ?package= read on a doc/page/etc. was served package-blind, and two same-named items shared one cache entry. A ?package= read now bypasses that cache and takes the disambiguating getMetaItem(type, name, packageId) path.
  • protocol.getMetaItem — forwards packageId to the sys_metadata overlay query (package_id prefer-local filter), to metadataService.get, and to registry.getItem.
  • metadata-facadeget() gained an optional currentPackageId, forwarded to registry.getItem.
  • runtime dispatcher + spec doc.zod comments (first commit).

Why it matters

Lets the doc viewer (/apps/:packageId/docs/:name) resolve one doc scoped to its app, so doc names no longer need a namespace prefix for uniqueness (the prefix becomes a recommended convention, like page/dashboard/report).

Frontend counterpart: objectui#1708.

Verification

  • Unit: package-scoped prefer-local in getMetaItem (registry + overlay paths); REST cache-bypass on ?package=. objectql 600 / rest 108 / runtime 370 green.
  • Live (real registry-level collision — two packages each shipping doc/showcase_index):
    • curl .../doc/showcase_index?package=com.example.showcase → Showcase
    • curl .../doc/showcase_index?package=com.objectstack.studio → "STUDIO VERSION"
    • Browser: /apps/<pkg>/docs/showcase_index renders each package's own doc, no console errors.

🤖 Generated with Claude Code

…ckage= (ADR-0048)

REST single-item GET /meta/:type/:name now passes its `?package=` query into
`getItem(type, name, currentPackageId)` — the package-scoped (prefer-local)
resolution added with the namespace gate. Single-item fetch was previously
context-free (only list + protocol paths were package-aware).

Enables package-scoped single-doc resolution (doc content lives only on the
single-item endpoint), so `doc` names no longer need a namespace prefix for
uniqueness — prefix demoted to a recommended convention (doc.zod comments
updated), matching page/dashboard/report.

Verified: curl `/api/v1/meta/doc/showcase_index?package=com.example.showcase`
returns the doc with content; the package param reaches getItem's 3rd arg.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 13, 2026 2:46pm

Request Review

…(ADR-0048)

The prior commit threaded ?package= into the runtime dispatcher, but the live
serving path (RestAPI + ObjectQL protocol) still dropped it for cacheable types:

- rest-server: the cacheable single-item GET called getMetaItemCached (ETag
  keyed on type+name only) and never passed packageId, so a ?package= read on a
  doc/page/etc. was served package-blind. Now a ?package= read bypasses that
  cache and takes getMetaItem(type, name, packageId).
- protocol.getMetaItem: forward packageId to the sys_metadata overlay query
  (package_id filter, prefer-local), to metadataService.get, and to
  registry.getItem.
- metadata-facade: get() gained optional currentPackageId, forwarded to
  registry.getItem.

Verified live: two packages (com.example.showcase, com.objectstack.studio) each
shipping doc/showcase_index now resolve to their own item via
?package=<id>, and the doc viewer route /apps/:packageId/docs/:name renders the
correct per-package content in the browser.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@xuyushun441-sys
xuyushun441-sys merged commit 0856476 into main Jun 13, 2026
12 checks passed
@xuyushun441-sys
xuyushun441-sys deleted the feat/adr-0048-meta-getitem-package branch June 13, 2026 14:53
os-zhuang added a commit to objectstack-ai/objectui that referenced this pull request Jun 14, 2026
…x optional) (#1701)

DocPage now passes the route's package (`/apps/:appName/docs/:name`, where
:appName is the package id) to `meta.getItem('doc', name, { packageId })`. The
client SDK already sends `?package=`; the framework REST endpoint now honors it
(objectstack-ai/objectstack#1816), resolving the single doc package-scoped
(prefer-local) — so doc names no longer need a namespace prefix for uniqueness.
Legacy top-level /docs/:name (no :appName) stays context-free.

Browser-verified: /apps/com.example.showcase/docs/showcase_index issues
GET …/meta/doc/showcase_index?package=com.example.showcase → 200 and renders.

Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:system size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants