| @objectstack/spec | minor |
|---|---|
| @objectstack/plugin-security | minor |
| @objectstack/runtime | minor |
| @objectstack/lint | minor |
feat(spec,plugin-security): package-level capability declaration API (ADR-0066 D1)
Packages can now DEFINE their own authorization capabilities explicitly via the
new defineCapability factory and a stack's capabilities array, instead of
relying on the implicit "derive an untitled capability from whatever a permission
set references in systemPermissions[]" back-door.
@objectstack/spec: newdefineCapability/CapabilityDeclarationSchema({ name, label?, description?, scope, packageId? }) and acapabilitiesfield on the stack definition.@objectstack/plugin-security: newbootstrapDeclaredCapabilitiesseeds declared capabilities intosys_capabilitywithmanaged_by:'package'+package_idprovenance (newpackage_idfield on the object). Idempotent, upgrade-aware; refuses to hijack curated platform capabilities or another package's rows, never clobbers admin-authored rows, and CLAIMS a pre-existing derived placeholder (upgrading it to package provenance). The implicit derive-from-systemPermissionspath still runs for back-compat but now skips any explicitly-declared name so it can't clobber authored metadata.@objectstack/runtime: stack-declaredcapabilitiesare registered into the metadata registry (typecapability) so the boot seeder can read them.@objectstack/lint:validateCapabilityReferencestreatsstack.capabilitiesnames as a known capability source.
A capability is not a contract: DEFINE it (defineCapability), GRANT it
(systemPermissions), REQUIRE it (requiredPermissions) — no inputs.
Aligns with ADR-0094 D5 (retire implicit managed_by-guessing back-doors).