Skip to content

feat(plugin-security): ADR-0094 follow-ups — package sets customize via env overlay (D5 revised) + projection dogfood proof + Setup UI alignment - #2905

Merged
os-zhuang merged 5 commits into
mainfrom
claude/sys-permission-set-projection-2c7w0h
Jul 14, 2026
Merged

feat(plugin-security): ADR-0094 follow-ups — package sets customize via env overlay (D5 revised) + projection dogfood proof + Setup UI alignment#2905
os-zhuang merged 5 commits into
mainfrom
claude/sys-permission-set-projection-2c7w0h

Conversation

@os-zhuang

@os-zhuangos-zhuang commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

ADR-0094 的收尾(承接已合并的 #2901),Closes#2898 —— 以"支持"而非"拒绝"的方式解决(维护者 2026-07-14 确认方向反转)。

1. 包集定制走标准元数据覆盖(ADR-0094 D5 修订版)

#2898 最初提议在授权时点拒绝对包持有权限集的环境 overlay。方向反转的理由:拒绝会让 permission 成为唯一一个声明了 allowOrgOverride: true 却说谎的类型;而"克隆再改"是 fork——克隆体永远收不到 vendor 后续的基线更新(含安全收紧),也丢失分层 diff。现在:

  • 投影器:包持有记录的 facets 跟随 effective(overlay-wins)体,managed_by:'package' + package_id provenance 保留——包仍拥有该行,overlay 是对它的定制。
  • 写穿:数据门编辑包集 → 翻译为 env overlay(不再 403);数据门"删除" → 移除 overlay,记录重置为发布基线(行保留)。无元数据层的单店内核保留旧版 two-doors 拒绝(由写穿自身断言)。
  • two-doors 门收窄到仍然结构性成立的部分:禁止伪造包 provenance(insert/update、单条/数组),transfer/restore/purge 在包行上仍拒绝(无 overlay 翻译)。
  • 跨包组合走岗位(并集做加法),overlay 做收窄;package-first authoring(ADR-0070)让运行时新建集有归属包——managed_by:'user' 游离类别可逐步退役。
  • registerAuthoringGate seam 随拒绝方向一并移除(无消费者的 seam 正是 ADR-0049 禁止的 inert 面)。

如实记录的取舍(已写入 ADR-0094 D5 修订版):ADR-0005 overlay 是整文档替换——overlay 钉住期间,vendor 的后续基线变更(含收紧)不生效,直到重置或重新编辑;缓解:Studio 分层 diff、升级时提示已定制的包集、ADR-0091 再认证覆盖。这是所有可覆盖类型共同的取舍,权限集不再被特殊化。

2. Projection dogfood proof + liveness ledger 绑定

showcase-permission-projection.dogfood.test.ts 在真实 showcase 栈证明全部不变量(7 项全绿):数据门 create→元数据+awaited 投影;edit→锁步;声明集编辑→可强制执行 overlay;runtime-only 删除→退役 / artifact-backed 删除→重置;包集 overlay 定制+重置全生命周期(showcase_contributor 实测)。two-doors-permission.dogfood 同步翻转为新语义(5 项全绿)。已注册进 ADR-0054 proof registry(bound:false + 如实 blockedReason)。check:liveness exit 0。

3. Setup UI 对齐(框架对象元数据,objectui 原生 honor)

  • sys_permission_set.namereadonlyWhen: record.id != null——create 可填、edit 锁定,匹配数据门 400 改名拒绝(实测 meta API 返回该 CEL 谓词)。
  • permission-sets.mdx / authorization.mdx 更新为 one-authoritative-store + overlay 定制模型。
  • 已克隆 objectui 核实其 SDUI 表单原生消费 readonlyWhen(ObjectFormfieldRules),无需 objectui 侧改动。

附带

验证

🤖 Generated with Claude Code

https://claude.ai/code/session_01SXjD7g2JkEsdqhZFZgAo1Q

…on sets + projection dogfood proof (ADR-0094 D5)
Closes the last inert-metadata hole from the ADR-0094 pure-projection
refactor (#2898), and binds the invariants into the liveness proof registry.
- metadata-protocol: new registerAuthoringGate(type, fn) seam — a per-type
gate run inside saveMetaItem before persistence; a returned rejection
becomes a thrown Error (code/status). Fail-open on a gate error (this
closes an inert-metadata hole, not a hard boundary — the data-plane
two-doors gate + the projector's refusal already protect the record).
- plugin-security: registers a `permission` gate that refuses an env-scope
saveMetaItem targeting a managed_by:package sys_permission_set record —
previously such an overlay persisted but neither projected nor enforced
(ADR-0049 violation). The package door (save carries the owning packageId)
and env-authored/new sets are unaffected. Error `package_owned` (403).
- dogfood: showcase-permission-projection proves the ADR-0094 invariants on
the real stack (write-through, awaited projection, declared-set edit →
enforced overlay, delete-as-reset, and this authoring gate), registered in
the ADR-0054 proof registry (unbound — a storage invariant has no
authorable ledger property to ratchet, kept honest with a blockedReason).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SXjD7g2JkEsdqhZFZgAo1Q
@vercel

vercelBot commented Jul 14, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJul 14, 2026 9:27am

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling size/m labels Jul 14, 2026
@github-actions

github-actionsBot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/dogfood, @objectstack/plugin-security, @objectstack/spec.

101 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx(via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx(via @objectstack/spec)
  • content/docs/ai/skills.mdx(via @objectstack/spec)
  • content/docs/api/client-sdk.mdx(via @objectstack/spec)
  • content/docs/api/environment-routing.mdx(via @objectstack/spec)
  • content/docs/api/error-catalog.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx(via @objectstack/spec)
  • content/docs/api/index.mdx(via @objectstack/spec)
  • content/docs/automation/approvals.mdx(via packages/spec)
  • content/docs/automation/flows.mdx(via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx(via packages/spec)
  • content/docs/automation/hooks.mdx(via @objectstack/spec)
  • content/docs/automation/index.mdx(via @objectstack/spec)
  • content/docs/automation/webhooks.mdx(via @objectstack/spec)
  • content/docs/automation/workflows.mdx(via @objectstack/spec)
  • content/docs/concepts/architecture.mdx(via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx(via packages/spec)
  • content/docs/concepts/index.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx(via packages/spec)
  • content/docs/concepts/north-star.mdx(via packages/spec)
  • content/docs/data-modeling/analytics.mdx(via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx(via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx(via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx(via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx(via @objectstack/spec)
  • content/docs/data-modeling/index.mdx(via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx(via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx(via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx(via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx(via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx(via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx(via @objectstack/spec)
  • content/docs/getting-started/cli.mdx(via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx(via @objectstack/spec)
  • content/docs/getting-started/examples.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx(via @objectstack/spec)
  • content/docs/getting-started/validating-metadata.mdx(via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/spec)
  • content/docs/kernel/cluster.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx(via packages/spec)
  • content/docs/kernel/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/email-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sharing-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx(via packages/spec)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/spec)
  • content/docs/permissions/access-recipes.mdx(via packages/plugins/plugin-security)
  • content/docs/permissions/authorization.mdx(via packages/dogfood, packages/plugins/plugin-security, @objectstack/spec)
  • content/docs/permissions/delegated-administration.mdx(via packages/dogfood)
  • content/docs/permissions/explain.mdx(via @objectstack/plugin-security)
  • content/docs/permissions/permission-sets.mdx(via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx(via packages/plugins/plugin-security, @objectstack/spec)
  • content/docs/permissions/positions.mdx(via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx(via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx(via @objectstack/spec)
  • content/docs/plugins/development.mdx(via @objectstack/spec)
  • content/docs/plugins/index.mdx(via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/plugins/packages.mdx(via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx(via @objectstack/spec)
  • content/docs/protocol/diagram.mdx(via packages/spec)
  • content/docs/protocol/knowledge.mdx(via @objectstack/spec)
  • content/docs/protocol/objectos/config-resolution.mdx(via @objectstack/spec)
  • content/docs/protocol/objectos/i18n-standard.mdx(via @objectstack/spec)
  • content/docs/protocol/objectos/lifecycle.mdx(via @objectstack/spec)
  • content/docs/protocol/objectos/plugin-spec.mdx(via @objectstack/spec)
  • content/docs/protocol/objectos/runtime-capabilities.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx(via packages/spec)
  • content/docs/protocol/objectql/query-syntax.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx(via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx(via packages/spec)
  • content/docs/protocol/objectui/record-alert.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx(via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx(via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/releases/index.mdx(via @objectstack/spec)
  • content/docs/releases/v12.mdx(via @objectstack/spec)
  • content/docs/releases/v13.mdx(via @objectstack/spec)
  • content/docs/releases/v9.mdx(via @objectstack/spec)
  • content/docs/ui/audience-based-interfaces.mdx(via packages/plugins/plugin-security)
  • content/docs/ui/create-vs-edit-form.mdx(via @objectstack/spec)
  • content/docs/ui/dashboards.mdx(via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/ui/forms.mdx(via @objectstack/spec)
  • content/docs/ui/index.mdx(via @objectstack/spec)
  • content/docs/ui/setup-app.mdx(via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

…document projection UX (ADR-0094)
Setup UI alignment for the ADR-0094 pure-projection behavior. The Setup
surface is SDUI-driven by the object metadata, so both affordances are
object-metadata changes objectui already honors (ObjectForm forwards
`readonlyWhen` to fieldRules; the engine also strips such writes server-side)
— no objectui code change needed:
- sys_permission_set.name gains `readonlyWhen: record.id != null` — the name
is the metadata identity the record projects from, so the create form
accepts it but the edit form locks it, matching the data-door's 400 rename
rejection. Verified the meta API surfaces the CEL predicate and the boot
stack loads it cleanly.
- permission-sets.mdx documents the one-authoritative-store model: Setup edits
of declared sets now enforce, the API name is immutable (clone to rename),
and deleting a packaged set resets it to the shipped definition while a
self-created set is removed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SXjD7g2JkEsdqhZFZgAo1Q
@os-zhuangos-zhuang changed the title feat(plugin-security): authoring gate for package-owned permission sets + projection dogfood proof (ADR-0094 D5)feat(plugin-security): ADR-0094 follow-ups — authoring gate (#2898) + projection dogfood proof + Setup UI alignmentJul 14, 2026
…e to sibling two-store types
Promote the permission-set-specific decision to a classification rule for
every declared-metadata ↔ queryable-record two-store type (sys_position,
sys_sharing_rule, sys_capability), keyed on which store enforcement reads at
request time:
- metadata-authoritative → record is a projection (this ADR's machinery,
reusable via registerMutationProjector / registerAuthoringGate);
- record-authoritative → the record is the authority and declared metadata is
a boot SEED only (seed-not-clobber; do NOT project — that would invert the
real authority).
Records the per-type findings (sys_sharing_rule is record-authoritative —
evaluation reads the row live; sys_position needs the seed-vs-authority
audit), so the follow-up is scoped, not rediscovered. Tracked in framework#2909.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SXjD7g2JkEsdqhZFZgAo1Q
…he standard env metadata overlay (ADR-0094 D5 revised)
Direction confirmed by the maintainers 2026-07-14, reversing the #2898
authoring-time rejection: an env-scope overlay of a package-owned set is the
platform's standard ADR-0005 customization, made FIRST-CLASS instead of
refused — rejecting it would make `permission` the one type whose declared
allowOrgOverride:true is a lie, and clone-to-customize forks away from vendor
baseline updates (including security tightenings).
- projector: a package-owned record's facets follow the EFFECTIVE
(overlay-wins) body; managed_by:'package' + package_id provenance preserved.
- write-through: a data-door edit of a packaged set translates into that
overlay (no more flat 403); data-door "delete" removes the overlay and
RESETS the record to the shipped declaration. Single-store kernels (no
metadata overlay layer) keep the legacy two-doors refusal, now asserted by
the write-through itself.
- two-doors gate narrows to what stays structurally true: provenance forging
refused (insert/update, single/array), and transfer/restore/purge on
package rows refused (no overlay translation exists for them).
- metadata-protocol: the registerAuthoringGate seam is removed again — with
the rejection gone it had no consumer, and an unconsumed seam is exactly
the inert surface ADR-0049 forbids.
- docs: ADR-0094 TL;DR/D2/D5 revised (including the whole-document-overlay
upgrade-pinning trade and its mitigations); authorization.mdx +
permission-sets.mdx updated; dogfood proofs flipped to the new semantics
(overlay customize/reset on showcase_contributor, live).
Closes#2898 (resolved by support, not rejection).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SXjD7g2JkEsdqhZFZgAo1Q
@os-zhuangos-zhuang changed the title feat(plugin-security): ADR-0094 follow-ups — authoring gate (#2898) + projection dogfood proof + Setup UI alignmentfeat(plugin-security): ADR-0094 follow-ups — package sets customize via env overlay (D5 revised) + projection dogfood proof + Setup UI alignmentJul 14, 2026
…dx (ADR-0090 D3)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SXjD7g2JkEsdqhZFZgAo1Q
@os-zhuang
os-zhuang marked this pull request as ready for review July 14, 2026 10:00
@os-zhuang
os-zhuang merged commit 712328a into mainJul 14, 2026
17 checks passed
@os-zhuang
os-zhuang deleted the claude/sys-permission-set-projection-2c7w0h branch July 14, 2026 10:01
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/lteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

metadata-protocol: reject env-scope overlays of package-owned permission sets at authoring time (ADR-0094 D5)

2 participants

@os-zhuang@claude