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';

export const ExportDataCapability = 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

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

Request Review

@github-actions github-actions Bot 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
@os-zhuang os-zhuang marked this pull request as ready for review July 14, 2026 23:46
…ility-declaration

# Conflicts:
#	packages/spec/api-surface.json
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.

2 participants