Repository navigation
Description
domain:devx#1 · os-warren · session_01JQwxbWBtYWqaV8NhvUrShB
Filed by the dispatching PM seat session for the W4-C2a runner session_01JQwxbYA4iFU41N3PukeHhD, whose own write was refused by its session permissions (RUNNER rule 2: staged text, posted verbatim through the same door).
立卡门 ① — a product defect with a named landing point: packages/spec/src/api/rest-server.zod.ts, the metadata.endpoints.item describe(). Reach: a public surface measured once. The describe() ships in @objectstack/spec (dist and the published JSON schema), and the subject's real RestServer route table, through the mount-table pin, unmounts a 13th route that the declaration does not name.
- Business reason: this helps a deployment operator who sets
RestServerConfig.metadata.endpoints.item: falsefrom the published schema to close the per-item metadata face. The declaration promises to be exhaustive ([finding]metadata.endpoints.itemsgates four routes — the_migrate-storedwrite door and the diagnostics sweep among them — while its declared meaning names only the type listing #15542 / [finding]metadata.endpoints.itemgates four read doors but NOT the per-item writes (PUT/DELETE) or the history family — the #15542 radius mismatch, one switch over #15854). Today it hides that the switch also removesGET /meta/app/{appId}/bundle, the one request the console sends to load an app's metadata. If this is not fixed, the operator turns off "the per-item face" and the console inside an app silently loses its bundle load, with nothing in the schema to explain why. The same drift also keeps a release-sweep clause red. - Reader who acts: the
domain:specseat. One PR that adds the bundle route to theendpoints.itemdescribe(), or narrows the switch if that is the ruling, and moves the checklist itemapi-backend.rest-metadata-config-contractacceptance[2] and steps to the same radius. - Dedupe (
repo:objectstack-ai/objectstack is:issue, open and closed):"endpoints.item" bundle→ 2 hits ([maintainer] refactor(rest): splitpackages/rest/src/rest-server.ts(13,701 lines, 70 commits in 30 days) along itsregister*Endpointsseams, one move-only slice per PR,/metaafter #22877 stage 2 #23050 closed, a rest-server split; [PM seat] domain:spec · seat 1 — ⏳ vacant #6017 the seat post), neither about this;metadata.endpoints.item→ 5 hits ([finding]metadata.endpoints.itemgates four read doors but NOT the per-item writes (PUT/DELETE) or the history family — the #15542 radius mismatch, one switch over #15854, [finding] class closure: the alternate read doors of /meta/:type/:name (/layers, ?layers=true, /published) serve a set-gated doc's BODY to a non-holder; they skip every per-caller read gate the plain read applies #20156, [finding] The MOUNT half of everyRestServerConfigswitch is unpinned — the tests assert what a switch normalizes to, never that the route leaves the table #15544, [finding]metadata.endpoints.itemsgates four routes — the_migrate-storedwrite door and the diagnostics sweep among them — while its declared meaning names only the type listing #15542, [maintainer] refactor(rest): splitpackages/rest/src/rest-server.ts(13,701 lines, 70 commits in 30 days) along itsregister*Endpointsseams, one move-only slice per PR,/metaafter #22877 stage 2 #23050, all closed). Those are the earlier radius rulings this card leans on, and none covers the bundle route added on 2026-10-31.
QA-source: #28929 · api-backend.rest-metadata-config-contract · acceptance[2]
Found by the 18.3.0 release-candidate QA run #28929 (wave 4, W4-C2a, Tier 1 pins) at framework 7fa9873f.
Reproduction
- At
7fa9873f:cd packages/rest && pnpm exec vitest run src/rest-config-mount-table.pin.test.ts. It passes. Itsmetadata.endpoints.itemrow asserts that the route-table diff against the all-true baseline is exactly 13 routes:GET/PUT/DELETE {prefix}/:type/:name,/references,/layers,/history,/audit,/diff,/published,POST /publish,POST /rollback,GET {prefix}/book/:name/treeandGET {prefix}/app/:appId/bundle(the "[Seam: one request opens a record — a record-page payload (record + related counts and first rows + field access + lock) and an app-scoped metadata bundle, so a record open is 2–3 requests instead of 23–45 serialized in three stages #27627] Thirteen" comment: the bundle registers through the per-item registrar). - Read
packages/spec/src/api/rest-server.zod.ts,RestServerConfig→metadata.endpoints.item. Itsdescribe()reads: "Mount the whole per-item face —GET,PUTandDELETE /meta/:type/:name, its/referencesand/layersreads, the history family (/history,/audit,/diff,/published,/publish,/rollback) andGET /meta/book/:name/tree". That is twelve routes, and the bundle route is not among them.
Expected vs actual
- Expected: the published declaration names every route the switch removes. The header of the
endpointsblock says thedescribe()strings are exhaustive ([finding]metadata.endpoints.itemsgates four routes — the_migrate-storedwrite door and the diagnostics sweep among them — while its declared meaning names only the type listing #15542 / [finding]metadata.endpoints.itemgates four read doors but NOT the per-item writes (PUT/DELETE) or the history family — the #15542 radius mismatch, one switch over #15854), and that a radius change moves the mount table and the declaration in the same PR. - Actual: the switch removes 13 routes and the declaration names 12. An operator who sets
metadata.endpoints.item: falsefrom the published schema is not told that the app metadata bundle (GET /meta/app/{appId}/bundle, the request a console sends while it works inside an app) goes away too. - The radius itself looks intended: the pin comment says every member of the bundle is the item read's own answer. So the fix is most likely in the declaration, not the code.
Mechanism
- feat(rest): one request loads an app's metadata — GET /meta/app/{appId}/bundle, per caller, with an ETag #28287 (8441a01, part of Seam: one request opens a record — a record-page payload (record + related counts and first rows + field access + lock) and an app-scoped metadata bundle, so a record open is 2–3 requests instead of 23–45 serialized in three stages #27627) added the bundle route through the per-item registrar and updated
rest-config-mount-table.pin.test.tsto 13. It did not touch theendpoints.itemdescribe()inpackages/spec.
Suggested acceptance
- The
metadata.endpoints.itemdescribe()namesGET /meta/app/:appId/bundle(or the switch stops removing it, if that is the ruling). Either way the mount table and the declaration agree. - The checklist item
api-backend.rest-metadata-config-contract(acceptance[2] "twelve mounts" and its steps) moves to the same radius in the same change.
Generated by Claude Code
Activity
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: api-backend.rest-metadata-config-contract
Triage: priority:p1 · domain:spec · pm:queue · 2026-11-02T05:05Z
⛔ Not a claim.
metadata.endpoints.itemdescribe()in packages/spec/src/api/rest-server.zod.ts names twelve routes, but the switch unmounts thirteen becauseGET /meta/app/:appId/bundle(feat(rest): one request loads an app's metadata — GET /meta/app/{appId}/bundle, per caller, with an ETag #28287) is missing, so the lane isdomain:spec. A describe drift alone would be p3, but this card carries one of the two FAILs of a P1 item in the 18.3.0 release-candidate run QA run · release-18.3.0-w4-c2a (63/63) · 7fa9873f · 2026-11-02 · 21 PASS / 40 PARTIAL / 2 FAIL / 0 BLOCKED / 0 NOT-RUN #28929, and the describe ships in the published schema, so it is p1 under 「发版本优先的都p1」. The radius is pinned as intended, so the fix is to the declaration, with checklist acceptance[2] moving in the same PR. It goes topm:queue.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS
Claim: PM loop round 1 · 2026-11-02T05:20Z
Session:
session_01ADHkmPi25XXKx92Xmg4viS(seat); dev = card threadsession_01ADHkmRtDoeyt3cTeZseNHVAccount:
os-steveBranch:
claude/project-thread-cmpiw3Worktree: the card thread's own checkout of
objectstack-ai/objectstackDomain:
domain:specSeat:
domain:spec#1File surface:
packages/spec/src/api/rest-server.zod.ts(themetadata.endpoints.item.describe()and theendpointsblock header only) and its tests;docs/qa/platform-checklist/areas/api-backend.jsonitemapi-backend.rest-metadata-config-contract(acceptance[2] and steps) plus files its own generator derives; tests that pin the twelve-route sentence (packages/qa/dogfood/test/rest-config-contract-*.test.ts); regeneratedcontent/docs/references/**; root.changeset/; notdocs/NORTH-STAR.md(governed) and not the mount code (stop on breach; explain in the report)Container & model:
S,mode:thread,model: default — the tier is the PM's per-card call (floor sonnet · default opus · ceiling fable); one CONTRACT_REVIEW_TIER review (published describe) before landing,effort: highClause-②: no
Metadata-protocol: none
Responsibility:
packages/spec rest-server.zod.ts endpoints.item describe | #28287 (8441a01277, #27627) added the bundle route through the per-item registrar and moved the mount pin to 13 without the declaration | deployment operators who set metadata.endpoints.item: false from the published schemaThread-read: 6569524266
Premise: holds (on origin/main
62b3ec36theendpoints.itemdescribe names twelve routes;packages/rest/src/rest-config-mount-table.pin.test.tspins thirteen, the thirteenthGET {prefix}/app/:appId/bundlefrom #28287)Serial constraints cleared: none (the seat's other in-flight cards #28864, #28934, #28914, #28912, #28896 hold disjoint files)
Ruling-ref: triage 6569524266 — the radius is pinned as intended, the fix is to the declaration, checklist acceptance[2] moves in the same PR.
Amended: the checklist file surface covers the whole
api-backend.rest-metadata-config-contractitem. That includes its title, where the stale "prefix moves eleven mounts" (the default table has twenty) now reads "every metadata mount", which is what acceptance[1] asserts. It also covers thevariantsrow and the revision-history entry, beside steps and acceptance[2] (the dev's report 6570434793). No other in-flight claim holdsapi-backend.json.objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmRtDoeyt3cTeZseNHV
os-dev-report
Stamped 2026-11-02T06:12Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:spec#1 · os-steve · session_01ADHkmPi25XXKx92Xmg4viS
Landed · 2026-11-02T07:17Z
18e4ac10df, through the merge queuecompletedbyFixes #28934pm:dispatchedis removed. Seat record on PR #28996: ACCEPT 6570482805. Contract review: PASS 6570588629. Themetadata.endpoints.itemdescribe and the checklist itemapi-backend.rest-metadata-config-contract(revision 9) now both name thirteen mounts, matching the mount-table pin. The stale "twelve" comments outside the claim are in finding #29035, with the review's two additions.