• Applicable Software: MokoNtfy
  • Max Version Number: Not Applicable

The role hierarchy: owner > admin > user

Every account has one coarse role:

  • user — a normal account; access is governed entirely by topic ACLs (its own grants, group grants and the Everyone grant).
  • admin — bypasses every access-control check and can open the Site Administration area.
  • owner — the single highest account. An owner is a superset of admin (also bypasses every check) and additionally holds the owner-only powers, chiefly role management.

Both admin and owner bypass capability checks, so custom roles (below) only ever gate delegated, non-admin access.

How the owner role is minted

Owner is deliberately hard to obtain — it cannot be set like a normal role. The ordinary role-setting paths (creating a user, changing a role in the admin UI or via ntfy user change-role) accept only user or admin; owner is rejected there.

  • Bootstrap (one time). On a server with no owner yet, an existing admin is promoted with the CLI-only ntfy user set-owner USERNAME. This succeeds only while no owner exists and only if the target is already an admin.
  • Transfer (after that). Once an owner exists, ownership moves only through the ownership-transfer flow (POST /v1/account/owner/transfer), which hands the owner role to another admin. Trying to bootstrap again is rejected because an owner already exists.

Last-owner protection

There is always exactly one owner. The last owner cannot be demoted and cannot be deleted — both are blocked at the server. To step down, an owner transfers ownership to another admin first; the transfer itself performs the swap.

Custom roles (RBAC)

Beside the coarse role, an owner can define custom roles — named bundles of capabilities — and assign them to principals to delegate a slice of admin power without granting full admin.

  • Capabilities are either system-wide (empty scope) or topic-scoped (a topic name or * pattern, matched with the same wildcard rule as topic ACLs). System capabilities include users.manage, acl.manage, groups.manage, branding.manage, tours.manage, approvals.manage, server.view, topics.acl.view and topics.protect.manage. Topic-scoped ones are topic.acl.manage, topic.protect.manage and topic.acl.view — e.g. authority over team-* only.
  • Assignment targets a user or a whole group (in the @g:<group> form), so a role can be handed to every member of a group at once.
  • Role management is owner-only. Role CRUD and assignment are the anti-self-escalation guard, so only the owner sees the Roles card and can use it (or the ntfy role CLI). There is no delegable "manage roles" capability — it stays with the owner.

See MokoNtfy CLI — groups, roles & protected topics for the exact ntfy role syntax.

How it composes with groups and protected topics

For a user (admin/owner bypass all of this), a request on a topic is resolved by the real authorization engine in this shape:

  • Groups are additive. A group grant applies to every member; a user's effective topic permission is the union of their groups' grants. Group grants are read/write/read-write only — a group deny is not allowed.
  • Per-user grants win. A user's own explicit grant (including a per-user deny) always takes precedence over any group grant — that's how you subtract access that a group would otherwise give.
  • Protected topics require an explicit grant. A topic marked protected is no longer reachable through the fall-through Everyone grant or the server's default access; a matching user or group grant is required. Owners, admins and the topic's reservation owner still retain access.
  • Custom roles don't grant topic publish/subscribe access; they grant management capabilities (e.g. the ability to manage a topic's ACL or protect it). Access to send/receive on a topic still comes from the ACL grants above.

The admin Access preview resolves all of this for you: pick a user (or an anonymous visitor) and a topic and it reports read/write allowed or denied using the same engine.