Skip to content

feat(spec,plugin-security): A5 — 包级 capability 声明 API (#2920) - #2932

Merged
os-zhuang merged 3 commits into
mainfrom
claude/authz-a5-capability-declaration
Jul 15, 2026
Merged

feat(spec,plugin-security): A5 — 包级 capability 声明 API (#2920)#2932
os-zhuang merged 3 commits into
mainfrom
claude/authz-a5-capability-declaration

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

A5 — 包级 capability 声明 API (tracking #2920)

包/应用一个正式、显式的 capability 声明入口,让包自带的授权 capability 带 managed_by:'package' + package_id provenance 流入 sys_capability registry,而不是依赖「从 permission set 的 systemPermissions[] 隐式派生一个无标题 placeholder」这条暗道。呼应 ADR-0066 D1("packages declare their capabilities")与 ADR-0094 D5(逐步退役隐式 managed_by 猜测)。

⚠️ 对 issue 原描述前提的修正

原 issue 说「应用声明 capability 又复制进 framework spec」——核实后该重复不存在:capability 早已是单一真源 packages/spec/src/security/capabilities.tsPLATFORM_CAPABILITIES)。真正缺的是包的显式声明入口 + provenance,本 PR 补齐的是这条链路,而非去重。契约保持 requiredPermissions(资源引用)/ systemPermissions(权限集授出);capability 不是 contract,没有 inputs

新 API 形状

import{defineCapability}from'@objectstack/spec';exportconstExportDataCapability=defineCapability({name: 'export_data',label: 'Export Data',description: 'Bulk-export records to CSV/XLSX.',scope: 'org',// 'platform' | 'org'});defineStack({capabilities: [ExportDataCapability],// DEFINE(包定义)permissions: [{name: 'billing_admin',objects: {},systemPermissions: ['export_data']}],// GRANT// 资源: requiredPermissions: ['export_data'] // REQUIRE});

设计与改动

  • @objectstack/specdefineCapability / CapabilityDeclarationSchema{ name, label?, description?, scope, packageId? });stack 定义新增 capabilities 数组(并入 composeStacks concat)。
  • @objectstack/plugin-security
    • sys-capability.object.ts 新增 package_id provenance 字段 + 索引。
    • bootstrapDeclaredCapabilities:把声明 seed 进 sys_capabilitymanaged_by:'package' + package_id。幂等、升级感知;拒绝劫持 curated 平台 capability、拒绝写入他包的行、从不覆盖 admin 行;对既有「派生 placeholder」行执行 claim(升级为 package provenance + 作者元数据)。
    • bootstrapSystemCapabilities 新增 declaredCapabilityNames:back-compat 的派生路径跳过已显式声明的名字,避免用 humanized placeholder 覆盖作者元数据。
    • boot 顺序:先 bootstrapDeclaredCapabilities(拿到 declaredNames),再 bootstrapSystemCapabilities 带 declaredNames。
  • @objectstack/runtimeapp-plugin.ts 把 stack 声明的 capabilities 注册进 metadata registry(类型 capability),供 boot seeder 读取(复用 permissions→permission 的既有机制)。
  • @objectstack/lintvalidateCapabilityReferencesstack.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/spec build ✅;spec stack 测试 132 通过、新 capabilities 测试 6 通过。
  • plugin-security 新 bootstrap-declared-capabilities + 更新的 bootstrap-system-capabilities 测试 14 通过;rbac-objects 15 通过(新字段不破坏断言)。
  • lint validate-capability-references 9 通过(含新「declared capability 不误报」用例)。
  • 端到端:defineStack({ capabilities: [...] }) strict parse 保留字段(已跑通)。
  • 受影响包 tsc 仅剩 worktree 未构建依赖的 module-not-found(非本改动)。

存疑/取舍

  • 命名:stack 上的 capabilities(授权 capability)与 requires(平台 service capability,如 ai/automation)及运行时 ObjectStackCapabilities 描述符是不同概念,已在字段/文档 doc 注中显式区分。
  • 「claim 派生 placeholder」仅对 managed_by:'platform' 且非 curated 名字生效(curated 名字在入口即被拒),admin 行永不动。

Closes part of #2920.

🤖 Generated with Claude Code


Generated by Claude Code

… 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
@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 15, 2026 12:00am

Request Review

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

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 4 package(s): @objectstack/lint, @objectstack/plugin-security, @objectstack/runtime, @objectstack/spec.

108 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/runtime, @objectstack/spec)
  • content/docs/api/wire-format.mdx(via @objectstack/runtime)
  • content/docs/automation/approvals.mdx(via packages/spec)
  • content/docs/automation/flows.mdx(via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx(via @objectstack/runtime, 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/runtime, packages/spec)
  • content/docs/data-modeling/analytics.mdx(via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/runtime, @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/index.mdx(via @objectstack/runtime)
  • content/docs/deployment/production-readiness.mdx(via @objectstack/runtime)
  • content/docs/deployment/single-project-mode.mdx(via @objectstack/runtime)
  • content/docs/deployment/troubleshooting.mdx(via @objectstack/spec)
  • content/docs/deployment/vercel.mdx(via @objectstack/runtime)
  • 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/runtime, @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/authentication.mdx(via @objectstack/runtime)
  • content/docs/permissions/authorization.mdx(via @objectstack/lint, packages/plugins/plugin-security, @objectstack/spec)
  • 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/runtime, @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/http-protocol.mdx(via @objectstack/runtime)
  • content/docs/protocol/objectos/i18n-standard.mdx(via @objectstack/spec)
  • content/docs/protocol/objectos/index.mdx(via @objectstack/runtime)
  • content/docs/protocol/objectos/lifecycle.mdx(via @objectstack/runtime, @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/runtime, @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.

…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
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.

2 participants

@os-zhuang@claude