Permissions
A permission is a dotted string naming an action, e.g. admin.users.create. Permissions are
namespaced by the unit that owns them (an app’s permissions live under <app>.*), so units cannot
collide.
Declared, not evaluated, by apps
Section titled “Declared, not evaluated, by apps”Apps never make authorization decisions themselves. A route declares the permission it requires:
@app.page("/users", permission="admin.users.read")def users(ctx): ...The core’s request adapter enforces permission= before the handler runs, calling the
authorization service’s has_permission(user, required). This keeps the decision in one place and
consistent across every app.
Grants and wildcards
Section titled “Grants and wildcards”A grant is what a role holds. A grant may be a concrete permission (admin.users.create) or a
dotted-prefix wildcard:
admin.users.*— every permission underadmin.users.admin.*— every permission in theadminnamespace.*— everything.
Wildcards are grants only — they are never used as the required permission on a route (a route always requires a concrete permission). A required permission is satisfied if any of the user’s grants matches it.
The decision
Section titled “The decision”has_permission resolves the user’s effective grants through the role chain (see Roles) and
returns whether any grant matches the required permission. A super_user bypasses the check
entirely — they hold everything without enumerating grants.