Repository navigation
v0.1.0 — Roles and permissions, held at a scope
Roles and permissions for a NAF application, scoped to whatever the application says a scope is.
The first release. What it does, and the three decisions behind it.
Grants are held at a scope
A permission is not simply held. It is held somewhere: everywhere, on every project, or on project 7. A Scope is that place, written as type:id — the empty string for the installation, project:* for every one of a kind, project:7 for one. Asking whether somebody may do something is asking at a scope, and a grant held wider covers a narrower question.
That is what lets an administrator's rights reach inside a board they were never added to, without the board having a second idea of what administration means.
A declared role is a starting point, not a standing instruction
Packages declare roles in code, and rbac:sync writes the ones that are missing. It does not rewrite the ones that are there: an installation that took a permission away from its own editor role meant it, and an upgrade must not hand it back.
The price of that rule used to be silent. A permission declared after the roles were written reaches nobody, so the feature behind it is dead on arrival and the only symptom is a button that does nothing for everybody. rbac:sync now compares the two lists it has always had and names the difference:
6 declared role(s); nothing to add
24 permission(s) declared across 6 group(s).
owner is missing delete, export
manager is missing export
The roles above no longer carry everything their packages declare. …
It repairs nothing, which is the point: which side is right is a decision, and the installation is entitled to make it. The message names both ways out — grant it in the role editor, or rbac:sync --reapply and take the packages' word for everything.
Only declared roles are compared, and each only against its own declaration. A permission that no role carries at all is ordinary, because packages ship permissions meant for roles an installation builds itself, and counting those would bury the one line that matters.
You cannot lock yourself out
The privilege policy refuses any change that would leave nobody able to administer the system — withdrawing the last grant, deleting the last role that carries it, or removing yourself from it. The refusal names which of those it was.
What is in it
Scopewithparse(),covers()and a string form, so a scope survives being stored and read back- Role and permission registries that packages declare into, and repositories that persist them
rbac:sync, with--reapplyfor taking the packages' word and drift reporting for when you do not- A
GrantWriterthat returns what moved instead of dispatching, so the service stays framework-free and the caller announces - Screens for editing roles, shipped as assets a host publishes
49 tests, 71 assertions. PER Coding Style 3.0.
Requires
naf/framework ^0.2, naf/auth ^0.2, naf/database ^0.2, PHP 8.3, ext-pdo.