Skip to content

Give the built-in Editor and Author the default grants of plugins - #3128

Open
pournasserian wants to merge 1 commit into
mainfrom
3103-builtin-role-plugin-grants
Open

pournasserian wants to merge 1 commit into
mainfrom
3103-builtin-role-plugin-grants

Conversation

@pournasserian

@pournasserian pournasserian commented Nov 15, 2026 •

Copy link
Copy Markdown
Member

A permission can now name the built-in roles that get it by default (Permission.DefaultRoles, SDK). At each start the host applies the defaults the instance has not applied yet and records each one in a new system table, cms_default_grant, so a default is given once per instance. The media plugin gives media.read and media.upload to Editor and Author and media.update to Editor; AI assist gives ai.use to both. Spec 4.8 lists the defaults.

Closes #3103

Decisions

  • Record. A table cms_default_grant (role_id, permission, plugin, applied_at), keyed on role and permission, rather than a settings area like seeding's. A settings area would add a settings.{area}.manage permission and a Management route that can rewrite the record, and a settings write cannot share the save of the grants (FCMS2807). The grants, their records and the role stamp go in one save through RoleService. If two instances start at the same time, the one that saves second fails on the key, reads again and finds nothing left to do.
  • Once per role and permission. A recorded default is never applied again. A grant an operator removes stays removed. A plugin added to an existing instance gets its defaults at its first start. If a later version of a plugin names a new default, only that one is applied, once.
  • Held already. If the role already holds a grant whose pattern matches the permission, limited or not (for example media.read limited to folders, or media.*), the default is recorded but nothing is added. A default never widens a limit an operator set.
  • Roles. BuiltInRole is only Editor or Author. Super Admin already holds *, and Public and Member are left out so a plugin cannot open anonymous or member access by itself. Built-in roles have fixed ids and cannot be deleted or renamed, so a default names its role by id. A row for a role that is missing is skipped.
  • Multi-site. Editor and Author are instance-wide, so a default grant has no site limit. A site where the plugin is disabled still answers 404 on the plugin's routes.
  • Providers the host registers itself get their defaults applied the same way, recorded with a null plugin.
  • Audit and cache. Each role that gets grants gets a role.updated activity row from the system (with added) and log event 9238, the next free id in the plugin host block (9230 to 9239). No new error code. The grants go through the role version interceptor like any other role edit, so the start that applies them evicts every site's Delivery copies once. Tests that count evictions or role.updated rows on hosts with the media plugin (two media delivery tests, the site locale cache tests, one Super Admin test) now leave out what the start did.
  • Model. The tag v1.0.0-preview.1 does not exist, so the table is folded into the Initial system migration of SQLite, PostgreSQL and SQL Server (one migration per stream and provider, H5). BaselineTests leaves tables added since the squash out of the comparison with the old chain, after checking that the baseline creates them. Local databases built from the earlier baseline have to be recreated.
  • SDK. BuiltInRole and Permission.DefaultRoles (an init property, empty by default) are in PublicAPI.Unshipped.txt. This is additive, so existing providers still compile.

Tests

  • Data tests (all providers in CI): a new instance with media and AI assist gives Editor and Author their defaults, raises each role's stamp once and writes the activity rows. A removed grant is not given again at the next start. A plugin added to an existing instance gives its defaults once. A default added in a later version is given once and earlier ones are not given again. A role that already holds a limited or wildcard grant keeps it. A host-registered provider's default is recorded with no plugin.
  • Media: the built-in Editor and Author list and upload media. Only Editor changes metadata, and neither can delete.
  • AI assist: the built-in Editor and Author run an action.
  • SDK: DefaultRoles is empty by default, keeps each role once, and rejects null or an unknown value.

Full CI run: https://github.com/fluentcms/FluentCMS/actions/runs/43732415125 (success; data jobs on SQLite, PostgreSQL and SQL Server).

@pournasserian pournasserian added type:feature New capability area:authorization Roles, permissions and row rules labels Nov 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:authorization Roles, permissions and row rules type:feature New capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Let the built-in Editor and Author roles use media and AI assist

1 participant