Add the get_permissions plugin hook (contract 0.10.0)
All checks were successful
CI / backend (push) Successful in 1m20s
CI / naming (push) Successful in 2s
CI / frontend (push) Successful in 8s

Plugins declare their own RBAC permissions instead of core accumulating
them: 36 permissions moved out of the core catalog into the 9 owning
plugins (core keeps the 19 its own blueprints enforce). The catalog is
resolved dynamically (core + enabled plugins) and feeds the roles grid,
the token scope picker and ceiling, and flask seed permissions;
installing or enabling a plugin seeds its permissions automatically. A
disabled plugin drops out of the assignable catalog while existing role
links keep working. New plugins - bundled or external - now bring their
permissions with zero core edits.

781 tests pass; live-verified with a machines.edit-scoped token.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-07-12 09:29:55 -04:00
parent 12175169e4
commit 7dfbe7bf8a
22 changed files with 439 additions and 90 deletions

View File

@@ -156,6 +156,28 @@ def test_plugin_get_reports_is_iterable(plugin_instances, name):
)
def test_baseplugin_has_permissions_hook():
"""The permissions hook is on the contract surface (contract 0.10.0)."""
assert hasattr(BasePlugin, 'get_permissions')
@pytest.mark.parametrize('name', BUNDLED_PLUGINS)
def test_plugin_get_permissions_shape(plugin_instances, name):
"""get_permissions returns a list of (name, description, category) entries."""
plugin = plugin_instances[name]
perms = plugin.get_permissions()
assert isinstance(perms, list)
for entry in perms:
if isinstance(entry, dict):
pname, category = entry['name'], entry.get('category')
else:
assert len(entry) == 3, f'{name}: entry must be a 3-tuple'
pname, _desc, category = entry
assert isinstance(pname, str) and '.' in pname, (
f'{name}: permission name {pname!r} must be dotted')
assert category, f'{name}: permission {pname} needs a category'
def test_baseplugin_has_frontend_contribution_hooks():
"""The four ADR-010 frontend-contribution hooks are on the contract (0.7.0)."""
for hook in ('get_settings_cards', 'get_asset_panels',