feat(spec,plugin-security): A5 — 包级 capability 声明 API (#2920)#2932
Merged
Conversation
… API (#2920) Give packages a formal, EXPLICIT entry point to DEFINE their own authorization capabilities, so package-owned capabilities flow into the sys_capability registry with managed_by:'package' + package_id provenance instead of relying on the implicit "derive an untitled capability from a permission set's systemPermissions[]" back-door (ADR-0066 D1; aligns with ADR-0094 D5). - spec: new defineCapability / CapabilityDeclarationSchema ({ name, label?, description?, scope, packageId? }); new `capabilities` field on the stack definition (+ compose concat). - plugin-security: new bootstrapDeclaredCapabilities seeds declared capabilities with package provenance (new package_id field + index on sys_capability). Idempotent, upgrade-aware; refuses to hijack curated platform capabilities or a foreign package's rows, never clobbers admin rows, and CLAIMS a pre-existing derived placeholder. bootstrapSystemCapabilities gains declaredCapabilityNames so its back-compat derivation skips (never clobbers) declared capabilities. - runtime: stack-declared `capabilities` registered into the metadata registry (type `capability`) for the boot seeder to read. - lint: validateCapabilityReferences treats stack.capabilities as a known source. - docs: authorization.mdx + ADR-0066 D1 note; app-showcase example (define + grant the showcase.export_data capability). Note: corrects the tracking issue's premise — capability was already a single source of truth (no app→framework duplication); this task adds the missing explicit package DECLARATION path + provenance, not a de-dup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019QRUvVfpvSycAHMMF2xTxs
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 4 package(s): 108 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
…orts The A5 branch added defineCapability + CapabilityDeclaration* exports but did not commit the regenerated api-surface snapshot; CI check:api-surface flagged 6 unregistered exports. Regenerated against a fresh dts build. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019QRUvVfpvSycAHMMF2xTxs
…ility-declaration # Conflicts: # packages/spec/api-surface.json
This was referenced Jul 15, 2026
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.
A5 — 包级 capability 声明 API (tracking #2920)
给包/应用一个正式、显式的 capability 声明入口,让包自带的授权 capability 带
managed_by:'package'+package_idprovenance 流入sys_capabilityregistry,而不是依赖「从 permission set 的systemPermissions[]隐式派生一个无标题 placeholder」这条暗道。呼应 ADR-0066 D1("packages declare their capabilities")与 ADR-0094 D5(逐步退役隐式managed_by猜测)。原 issue 说「应用声明 capability 又复制进 framework spec」——核实后该重复不存在:capability 早已是单一真源
packages/spec/src/security/capabilities.ts(PLATFORM_CAPABILITIES)。真正缺的是包的显式声明入口 + provenance,本 PR 补齐的是这条链路,而非去重。契约保持requiredPermissions(资源引用)/systemPermissions(权限集授出);capability 不是 contract,没有inputs。新 API 形状
设计与改动
@objectstack/spec:defineCapability/CapabilityDeclarationSchema({ name, label?, description?, scope, packageId? });stack 定义新增capabilities数组(并入composeStacksconcat)。@objectstack/plugin-security:sys-capability.object.ts新增package_idprovenance 字段 + 索引。bootstrapDeclaredCapabilities:把声明 seed 进sys_capability,managed_by:'package'+package_id。幂等、升级感知;拒绝劫持 curated 平台 capability、拒绝写入他包的行、从不覆盖 admin 行;对既有「派生 placeholder」行执行 claim(升级为 package provenance + 作者元数据)。bootstrapSystemCapabilities新增declaredCapabilityNames:back-compat 的派生路径跳过已显式声明的名字,避免用 humanized placeholder 覆盖作者元数据。bootstrapDeclaredCapabilities(拿到 declaredNames),再bootstrapSystemCapabilities带 declaredNames。@objectstack/runtime:app-plugin.ts把 stack 声明的capabilities注册进 metadata registry(类型capability),供 boot seeder 读取(复用permissions→permission的既有机制)。@objectstack/lint:validateCapabilityReferences把stack.capabilities计入已知 capability 来源集(对已声明 capability 不再误报)。content/docs/permissions/authorization.mdx新增「Package capability declaration」小节 + 三分法澄清;ADR-0066 D1 补注 landed 状态。examples/app-showcase声明showcase.export_data并在OpsPermissionSet.systemPermissions授出,演示 define→grant 全链(access-matrix 快照不含 systemPermissions,无 drift)。向后兼容
隐式派生路径保留:无声明的引用仍解析为
managed_by:'platform'placeholder;显式声明优先并接管既有 placeholder。验证
@objectstack/specbuild ✅;specstack测试 132 通过、新capabilities测试 6 通过。bootstrap-declared-capabilities+ 更新的bootstrap-system-capabilities测试 14 通过;rbac-objects15 通过(新字段不破坏断言)。validate-capability-references9 通过(含新「declared capability 不误报」用例)。defineStack({ capabilities: [...] })strict parse 保留字段(已跑通)。tsc仅剩 worktree 未构建依赖的 module-not-found(非本改动)。存疑/取舍
capabilities(授权 capability)与requires(平台 service capability,如ai/automation)及运行时ObjectStackCapabilities描述符是不同概念,已在字段/文档 doc 注中显式区分。managed_by:'platform'且非 curated 名字生效(curated 名字在入口即被拒),admin 行永不动。Closes part of #2920.
🤖 Generated with Claude Code
Generated by Claude Code