Skip to content

Commit 53555aa

Browse files
committed
docs(permissions): curated capabilities are registry declarations with no sys_capability row
Claude-Session: https://claude.ai/code/session_0113mDBBZPBFzvZqbJqfaFMv Co-authored-by: Claude <noreply@anthropic.com>
1 parent f42a1dd commit 53555aa

3 files changed

Lines changed: 18 additions & 12 deletions

File tree

‎content/docs/permissions/authorization.mdx‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,10 @@ to write into another package's capability.
204204

205205
This **replaces the implicit back-door** where a capability existed only as an
206206
untitled placeholder derived from whatever a permission set happened to reference
207-
in `systemPermissions[]`. That derivation still runs for back-compat (a
208-
reference with no declaration keeps resolving as a `managed_by:'platform'`
209-
placeholder), but an explicit `defineCapability` takes precedence and — for a
210-
pre-existing derived placeholder — **claims** it, upgrading the row to package
207+
in `systemPermissions[]`. That derivation is retired: a reference with no
208+
declaration still matches by name at runtime but gets no `sys_capability` row.
209+
An explicit `defineCapability` takes precedence and — for a derived placeholder
210+
an older database still holds — **claims** it, upgrading the row to package
211211
provenance with the authored label/description/scope. This is the ADR-0066 D1
212212
direction: retire the implicit `managed_by`-guessing back-doors in favour of
213213
explicit, attributable declarations.
@@ -537,15 +537,17 @@ The complete, prioritized gap map lives in issue **#2561** (the production
537537

538538
- **Deny/muting layer** (ADR-0066 ⑦⑧) — union-only grants can't take access
539539
away; needed for large-org governance and packaged-set adjustment.
540-
- **Capability registry** (ADR-0066 D1) — **landed**: capabilities are seeded
541-
as first-class `sys_capability` records from the canonical list in
540+
- **Capability registry** (ADR-0066 D1, ADR-0131 D3) — **landed**: the
541+
platform's curated capabilities, from the canonical list in
542542
`@objectstack/spec` (`security/capabilities.ts` → `PLATFORM_CAPABILITIES`),
543-
seeded by `packages/plugins/plugin-security/src/bootstrap-system-capabilities.ts`.
543+
are declared `capability` metadata served by the registry
544+
(`registerBuiltinCapabilities`, `GET /api/v1/meta/capability`), with no
545+
`sys_capability` row.
544546
A **package** now DEFINES its own capabilities explicitly via
545547
[`defineCapability` / `stack.capabilities`](#package-capability-declaration-adr-0066-d1),
546548
seeded with `managed_by:'package'` + `package_id` provenance by
547549
`bootstrap-declared-capabilities.ts` — replacing the implicit
548-
derive-from-`systemPermissions` back-door (which stays for back-compat).
550+
derive-from-`systemPermissions` back-door (now retired).
549551
The authoring lint (ADR-0066 ⑨) is also **landed**: `validateCapabilityReferences`
550552
(`@objectstack/lint`) warns at author time (`os validate` / `os lint`) when a
551553
`requiredPermissions` names a capability registered nowhere — no built-in, no

‎content/docs/permissions/capabilities.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ behind that behaviour are set out in
218218
the scope and the provenance that make a capability reviewable, attributable and
219219
uninstallable — but no authorization check reads it. Permission-set grants and
220220
resource `requiredPermissions` match capability names **as strings**; the only
221-
production readers of the table are the two boot seeders. The row's `active`
221+
production reader of the table is the declared-capability boot seeder. The row's `active`
222222
flag is a catalogue/visibility flag with no authorization effect: clearing it
223223
revokes nothing. Withdraw a capability by withdrawing the **grant**.
224224
</Callout>

‎content/docs/permissions/permission-sets.mdx‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export const SalesUser = definePermissionSet({
4040
// Tab/app visibility
4141
tabPermissions: { app_crm: 'default_on', app_admin: 'hidden' },
4242

43-
// System capabilities (flat strings, resolved against sys_capability)
43+
// System capabilities (flat strings, matched by capability name)
4444
systemPermissions: ['export_reports'],
4545
});
4646
```
@@ -147,8 +147,12 @@ the anchor decides *which* unit `unit*` means.
147147
148148
## Capabilities & required permissions (ADR-0066)
149149

150-
- **Capabilities** are first-class `sys_capability` records — named privileges
151-
such as `manage_users`, `manage_metadata`, `setup.access`, `studio.access`.
150+
- **Capabilities** are named privileges such as `manage_users`,
151+
`manage_metadata`, `setup.access`, `studio.access`. The platform's curated
152+
ones are declared `capability` metadata served by the registry
153+
(`GET /api/v1/meta/capability`) and have no `sys_capability` row; a
154+
capability a package declares with `defineCapability` is also seeded as a
155+
`sys_capability` row.
152156
Grant them via `systemPermissions`; declare them as prerequisites via an
153157
object/field/app `requiredPermissions` (an **AND**-gate checked before any
154158
CRUD grant).

0 commit comments

Comments
 (0)