Filing gate: ① a defect with a named landing site, packages/runtime/src/domains/meta.ts handleMetadataRequest's one-segment LIST branch (parts.length === 1: protocol.getMetaItems → slimDocList, about :1039-:1080). Finding class (a), under the security exception: it exposes data. reach: was measured through dispatch(), the createHonoApp catch-all's delegate.
Found by the os-dev round on #20193 (PR #20236), which gates the dispatcher's ITEM reads and left the LIST branch untouched. That branch is outside its claimed surface, and it needs RestServer's LIST filters extracted as a second seam. Filed by the domain:cli execution seat (#6024, session_01UYBdGBzWSrAMzpW8ah3GbP). ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.
The reader who acts is the domain:cli execution seat: packages/runtime and packages/rest are both this lane's. It builds on PR #20236's shared gate module and dispatches after that PR lands.
Dedupe: MCP issue search in this repository, open and closed, run 2026-09-27, 「runtime dispatcher meta list branch getMetaItems no per-caller filter doc include content book app requiredPermissions leak」 → 3 hits. #20193 (open) is the ITEM half of the same family, which PR #20236 closes. #20130 (closed duplicate) was the RestServer alternate doors. #4698 is unrelated. None covers the list branch.
What happens (measured by the #20193 dev through dispatch(), head 0fcb064a2)
An authenticated caller who does not hold crm_admin sends:
| request |
dispatcher answer |
RestServer's GET /meta/:type answer to the same caller |
GET /meta/doc?include=content |
200, lists crm_admin_runbook with its body |
lists [crm_intro] only |
GET /meta/book |
200, lists the set-gated admin_guide with its description |
[] |
GET /meta/app |
200, lists payroll (app-level requiredPermissions) and crm with the gated nav_finance_ledger |
[crm], pruned |
⚠️ These readings are the dev's, relayed. The seat confirmed at source on origin/main that the list branch reads protocol.getMetaItems and renders through slimDocList with no audience, requiredPermissions or app-filter spelling (about :1039-:1080). The seat did not re-drive the requests.
The contract it contradicts
- ADR-0046 §6.7: docs content is gated server-side at the doc and book reads.
content/docs/ui/apps.mdx's requiredPermissions row: 「absent from the /meta body」.
- AGENTS.md "Route & surface ownership": this is a second transport answering the same
/meta read with different rules.
Direction (for the claimant, ⛔ not a ruling)
Follow #20193's route: extract RestServer's LIST filters (the doc and book audience prune, the app nav filter, the dashboard widget gate and the ADR-0106 object mask on the list) as one transport-neutral seam beside PR #20236's meta-item-read-gate.ts, and have the dispatcher's list branch call it. ⛔ No second audience resolver: ruling 5793362670 item 1.
Pin: each of the three rows above, driven through a composed catch-all host, answers what RestServer answers the same caller. A holder is the control.
Seam
spec:AppSchema.requiredPermissions / spec:BookSchema.audience → runtime:packages/runtime/src/domains/meta.ts handleMetadataRequest (parts.length === 1)
Dedupe words: dispatcher meta list audience · handleMetadataRequest list include=content leak · createHonoApp meta app list requiredPermissions · catch-all meta list ungated
Generated by Claude Code
Filing gate: ① a defect with a named landing site,
packages/runtime/src/domains/meta.tshandleMetadataRequest's one-segment LIST branch (parts.length === 1:protocol.getMetaItems→slimDocList, about :1039-:1080). Finding class (a), under the security exception: it exposes data.reach:was measured throughdispatch(), thecreateHonoAppcatch-all's delegate.Found by the
os-devround on #20193 (PR #20236), which gates the dispatcher's ITEM reads and left the LIST branch untouched. That branch is outside its claimed surface, and it needsRestServer's LIST filters extracted as a second seam. Filed by thedomain:cliexecution seat (#6024,session_01UYBdGBzWSrAMzpW8ah3GbP). ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.The reader who acts is the
domain:cliexecution seat:packages/runtimeandpackages/restare both this lane's. It builds on PR #20236's shared gate module and dispatches after that PR lands.Dedupe: MCP issue search in this repository, open and closed, run 2026-09-27, 「runtime dispatcher meta list branch getMetaItems no per-caller filter doc include content book app requiredPermissions leak」 → 3 hits. #20193 (open) is the ITEM half of the same family, which PR #20236 closes. #20130 (closed duplicate) was the
RestServeralternate doors. #4698 is unrelated. None covers the list branch.What happens (measured by the #20193 dev through
dispatch(), head0fcb064a2)An authenticated caller who does not hold
crm_adminsends:RestServer'sGET /meta/:typeanswer to the same callerGET /meta/doc?include=contentcrm_admin_runbookwith its body[crm_intro]onlyGET /meta/bookadmin_guidewith its description[]GET /meta/apppayroll(app-levelrequiredPermissions) andcrmwith the gatednav_finance_ledger[crm], prunedorigin/mainthat the list branch readsprotocol.getMetaItemsand renders throughslimDocListwith no audience,requiredPermissionsor app-filter spelling (about :1039-:1080). The seat did not re-drive the requests.The contract it contradicts
content/docs/ui/apps.mdx'srequiredPermissionsrow: 「absent from the/metabody」./metaread with different rules.Direction (for the claimant, ⛔ not a ruling)
Follow #20193's route: extract
RestServer's LIST filters (the doc and book audience prune, the app nav filter, the dashboard widget gate and the ADR-0106 object mask on the list) as one transport-neutral seam beside PR #20236'smeta-item-read-gate.ts, and have the dispatcher's list branch call it. ⛔ No second audience resolver: ruling5793362670item 1.Pin: each of the three rows above, driven through a composed catch-all host, answers what
RestServeranswers the same caller. A holder is the control.Seam
spec:AppSchema.requiredPermissions/spec:BookSchema.audience→runtime:packages/runtime/src/domains/meta.ts handleMetadataRequest (parts.length === 1)Dedupe words:
dispatcher meta list audience·handleMetadataRequest list include=content leak·createHonoApp meta app list requiredPermissions·catch-all meta list ungatedGenerated by Claude Code