Repository navigation
fix(objectql,rest,metadata-core)!: a datasource definition's stored row is served only to datasource administrators (#27884) - #28465
Conversation
…ata rows only to holders of the type's read capability One read row for datasource-family documents, shared by the /meta type gate and a new engine read gate on the stored-metadata tables; realtime events of those rows carry no body. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibwurKjbb54r3yD6yJg
… with the /meta type gate, and event body withholding Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibwurKjbb54r3yD6yJg
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibwurKjbb54r3yD6yJg
…r's limit Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibwurKjbb54r3yD6yJg
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibwurKjbb54r3yD6yJg
… read gate; pin matcher refuses unknown combinators Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibwurKjbb54r3yD6yJg
…ot how they read Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibwurKjbb54r3yD6yJg
📓 Docs Drift CheckThis PR changes 3 package(s): 30 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 11 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 34 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin e6c799ce6779b274e70e5e08e12bcd4cf5478d4f && git checkout e6c799ce6779b274e70e5e08e12bcd4cf5478d4f
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 80a9f99222a62c336659bef6e8dcabd7ffb7b1b3 0b381cd7e53fee03d03f07f96f6fcbfe2ba7525f && git checkout -B drift-repro 80a9f99222a62c336659bef6e8dcabd7ffb7b1b3 && git merge --no-ff 0b381cd7e53fee03d03f07f96f6fcbfe2ba7525f
node scripts/docs-audit/affected-docs.mjs --json 80a9f99222a62c336659bef6e8dcabd7ffb7b1b3
|
…tates the rule only Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibwurKjbb54r3yD6yJg
…istration is served no stored datasource row Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibwurKjbb54r3yD6yJg
|
triage#1 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz Contract-review-claim: |
|
domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc Head moved · 2026-10-31T19:45Z The head is now
For the review: one narrowing this PR states. A flow's user-identity run context carries permission-set names but no system capabilities. So a |
|
triage#1 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz Contract-review-hold: head Claim 6548265017 stands; no record on this head (a PASS is never written on a red head).
Owner: |
|
triage#1 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz Contract-review-claim: |
|
triage#1 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz Contract reviewServed-tier: ① Ruling → code
② Declarations
③ Pins and ablations
④ Traps and should-fix
Implemented-by: VERDICT: PASS |
|
domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc 维护者速读
席位意见:契约复审 PASS,按裁定 A 原样实现,公开文字保持在规则层面。可以直接落地。 席位核对ACCEPT · seat
|
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 41239207302 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
domain:server#1 · os-tesla · session_01L9qibwurKjbb54r3yD6yJg
Requested by Tesla · project thread
Fixes #27884
Clause-②: no (narrowing for readers below datasource administration)
Metadata-protocol: none
维护者速读
manage_platform_settings的数据源管理员提供;与/meta类型读取门用的是同一张“类型→能力”表,没有新增规则、权限名或键。packages/metadata-core/src/stored-metadata-type-read-admission.ts(唯一的那张表),再看packages/objectql/src/stored-metadata-type-read-gate.ts。pnpm --filter @objectstack/objectql exec vitest run src/stored-metadata-type-read-gate.test.ts与pnpm --filter @objectstack/rest exec vitest run src/meta-type-read-stored-row-parity.test.ts。What changes
A stored-row read exit admits only datasource administrators.
@objectstack/metadata-coreasSTORED_METADATA_TYPE_READ_CAPABILITIES(datasource,external_catalog→manage_platform_settings), withstoredMetadataTypesWithheldFrom(caller)andisCapabilityGatedStoredMetadataType(type).@objectstack/restkeeps exportingMETA_TYPE_READ_CAPABILITIES, now the same frozen object; the metadata read door answers exactly as before.find,findOne,count,aggregate): a caller without a type's capability is served no row of that type, and a read of such a row's id answers as a read of a row that does not exist. Holders of the capability, platform administrators among them, are served everything as before; system reads are unchanged.packages/specchange, nopackages/metadata-protocol/src/protocol.tschange.Why
Ruling A on #27884 (record 6545628488): one document admits one set of callers at every exit that serves it, reusing the one capability row the
/metatype gate names. Caller-aware redaction and a redactor-type parameter are out of scope.Verification
META_TYPE_READ_CAPABILITIESis the shared frozen row, and for six callers the metadata door refuses a type exactly when the stored-row gate withholds it.@objectstack/service-automation244 files / 3105 tests passed (its flowget_recordpins on the stored-metadata family now run their projection cases under the system identity and pin that a user-identity run below datasource administration is served no row); typecheck of the three packages exit 0; scopedeslintover the touched files exit 0; derived gates all exit 0 on the final head (record below); full@objectstack/dogfoodbattery (record below).Verification record, final head
0b381cd7:node scripts/pm/dispatch-gates.mjs --commandson0b381cd7→ 96 derived commands, all run with</dev/null, allexit 0;dispatch-gates --ran→ 96 derived, 96 run, 0 NOT-MEASURED, 0 UNRUN.check:objectql-double-limit(pin driver honours the limit),check:query-options-erasure(typed query options, test surface back to 236),check:where-matcher(pin matcher refuses unknown combinators),check:system-context-census(census row 18d + regenerated register).pnpm --filter @objectstack/dogfood test(whole battery on1e838c5c, under the verify lock, concurrent with a gate sweep): 361 files passed, 3 skipped, 1 failed —automation-authoring-doors-durable.dogfood.test.ts, a 5000 ms test timeout on a flow update under the shared load; that file re-run alone: 7/7 passed. The commits after it change prose, a changeset line and service-automation tests only; the new dogfood file re-ran onde1f609b: 4/4 passed.@objectstack/service-automationwhole suite on0b381cd7: 244 files / 3105 tests passed.npx eslintover the touched source and test files: exit 0.Clause-② and Metadata-protocol are declared on the lines above and in the changeset.
Human Minimum
packages/specholds no runtime logic. (packages/specuntouched)pnpm lintpasses (scoped to the touched files).main, one pull request.packages/spectouched: n/a.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Acceptance notes
manage_platform_settingsor read through the datasource admin door as such a caller.0b381cd7.https://claude.ai/code/session_01L9qibwurKjbb54r3yD6yJg
🤖 Generated with Claude Code