Skip to content

v0.85.0: site-declared role vocabularies over three capability levels

Choose a tag to compare

@glw907 glw907 released this 15 Jul 00:00

The extensible-roles window: sites now declare their own role vocabulary and map each role onto one of the engine's three fixed capability levels.

Added

  • Site-declared roles. defineRoles on the adapter's new roles member validates a vocabulary at construction; each role maps to owner (manages the roster), editor (writes and publishes), or none (an authenticated identity with no engine content access). A site that declares nothing keeps the implicit { owner, editor } pair, so a zero-config site sees no change anywhere in this release.
  • Typed read-side. The new CairnRolesRegister interface (root export) lets a site augment Role in its own app.d.ts, narrowing locals.editor.role to its declared names on custom admin routes. Editor gains a resolved capability field, carried through the guard, the shell payload, and the editor log events.
  • The none contract. The new requireEditor guard refuses a none-capability session with 403 on the engine's own content and roster surfaces while still authenticating it: the session carries a populated, typed locals.editor and passes through the CairnAdminShell custom-route seam untouched, so a site can grant such a role its own screens. The shell shows a none session only the site's custom nav.
  • Role-aware landing. A role can declare a home, the /admin route it lands on. A none-capability role with no home gets a calm signed-in welcome view instead of the content list.
  • ManageEditors renders the vocabulary. The default pair keeps the owner/editor toggle; a larger vocabulary renders a labeled select naming each role's capability. The last-owner guard now counts owner-capability rows (set-based, still one atomic statement), not the literal owner string.
  • Bootstrap owner. CairnAdminDeps.auth.bootstrapOwner seeds the very first owner row on an empty editor table from the ordinary magic-link request flow, no wrangler d1 execute required.
  • Migration 0001 (migrations/0001_roles.sql) drops the editor.role CHECK constraint; role validity moves to the app layer, validated against the declared vocabulary. A zero-config site can skip it.
  • Doctor checks auth.role-vocabulary and auth.email-normalization; the owner-count diagnostic now counts owner-capability rows. New log events auth.role.unknown and editor.bootstrapped.
  • Docs. A new guide, Give a role its own admin area, plus the roles reference, the site-contract updates in the architecture explanation and the adapter guide, and the upgrade-guide entry.

No consumer action needed for an existing site: the implicit owner/editor vocabulary behaves exactly as before. To open a larger vocabulary, declare roles with defineRoles, apply migration 0001, and augment CairnRolesRegister if you want the narrowed Role type. See the upgrade guide.