fix(objectql,metadata-protocol): 租户自己写的覆盖层不该被当成代码包产物 - #4429
Merged
Conversation
…ead back as a code artifact `saveMetaItem` refuses to write an artifact-backed item of a type that has not opted into overlay writes (`not_overridable`), and it asks `registry.getArtifactItem` who is artifact-backed. That answer was "anything whose `_packageId` is not the literal string `sys_metadata`" — a sentinel that only holds on the save path. The boot-time rehydration of `sys_metadata` registers each row under its REAL package id (`app.<slug>`), which every runtime-authored item has carried since packages became mandatory. So an app the user had just built through Studio (or the AI build agent) came back from the next kernel rebuild looking code-shipped, and the following edit was refused with a 403 — permanently. Live capture: two identical `modify_field` calls on the same object seconds apart, the first published LIVE and the second `not_overridable`, because the first one's auto-publish triggered the rebuild in between (cloud#970). It is also why the AI authoring skill's "after apply_blueprint, update_metadata to add the roll-up config" instruction pointed at a road that does not exist. Provenance is the axis that actually separates the two (ADR-0010 `_provenance`: `'package'` for loader-introduced, `'org'` for tenant-authored), so ask it: the `sys_metadata` hydration stamps `_provenance: 'org'`, and `getArtifactItem` no longer treats such an item as an artifact. An item with NO provenance under a real package id keeps the old answer, so nothing that was protected silently becomes writable. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 14 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
59 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
saveMetaItem会拒绝写入「artifact-backed 且该类型没开启 overlay 写」的元数据(not_overridable),而它判断谁是 artifact-backed 靠的是registry.getArtifactItem。这个判据一直是「_packageId不等于字面量sys_metadata就算代码产物」—— 但这个哨兵只在 save 路径上成立。启动时
loadMetaFromDb把sys_metadata的每一行按它真实的 packageId(app.<slug>)注册进 registry,而自从 package 成为强制项之后,所有运行时创作的条目都带着这样一个 packageId。结果:用户刚在 Studio(或 AI 搭建 agent)里建好的应用,经过下一次 kernel 重建之后,看起来就像是代码包发布的产物 —— 于是之后对它的任何修改都被 403 拒绝,且是永久性的。
线上实测(objectstack-ai/cloud#970):对同一个对象、相隔几秒的两次
modify_field,第一次status: published成功上线,第二次直接[not_overridable]—— 因为第一次的 auto-publish 在中间触发了 kernel 重建。这也正是 AI 授权 skill 里那条「apply_blueprint 之后你必须 update_metadata 把汇总配置补上」的指示为什么是空话:它指向的那条路根本走不通。
改动
真正区分两者的轴是 provenance(ADR-0010:
'package'= loader 引入,'org'= 租户自己写的),所以就问它:loadMetaFromDb注册 object 时打上_provenance: 'org'—— 这些行按定义就来自sys_metadata,是租户的覆盖层。getArtifactItem的四个分支都不再把_provenance === 'org'的条目当作 artifact。没有 provenance 的条目在真实 packageId 下维持原判定,所以本来受保护的东西不会悄悄变成可写。
测试
新增
registry-tenant-authored-artifact.test.ts(5 例):租户覆盖层不再被当 artifact;代码包产物仍然是 artifact;无 provenance 维持原状;sys_metadata哨兵仍生效;非 object 类型同理。去掉 registry 改动后其中 2 例会失败(已验证)。packages/objectql92 files / 1506 tests、packages/metadata-protocol21 files / 139 tests 全绿。🤖 Generated with Claude Code