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-zhuang os-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

vercel Bot commented Jul 14, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 14, 2026 9:27am

Request Review

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

github-actions Bot 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-zhuang os-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 alignment Jul 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-zhuang os-zhuang changed the title feat(plugin-security): ADR-0094 follow-ups — authoring gate (#2898) + projection dogfood proof + Setup UI alignment feat(plugin-security): ADR-0094 follow-ups — package sets customize via env overlay (D5 revised) + projection dogfood proof + Setup UI alignment Jul 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 main Jul 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 free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l tests tooling

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