Appearance
Users & roles
There are three control-plane roles, in a simple ladder. The role lives on the user (cp_users.role), not on memberships — so a user has one role across the whole portal, plus zero or more federation/spoke memberships.
The roles
| Role | Can do | Cannot do |
|---|---|---|
| operator | Everything: see all federations, all spokes, all users; mint tokens; impersonate (from the support tools) | — |
| hub_admin | Everything within their federations: provision/destroy spokes, manage users on those spokes, change federation mode, view billing | See other federations; touch operator-only settings |
| spoke_admin | Read their assigned spokes; see audit activity for those spokes; receive notifications | Provision spokes; change federation mode; touch billing |
The Moodle-side role of admin / teacher / student / etc is separate — that's per-spoke and lives inside Moodle. A user can be a spoke_admin in Nucleus and a teacher in the Moodle, or any other combination.
Inviting users
/users → Invite user:
- Email — required. The invite goes here.
- Role — pick from the ladder. Hub admins can invite up to spoke_admin within their federations; only operators can mint other operators.
- Federation / spoke scope — for hub_admin and spoke_admin, pick which federation(s) or spoke(s) they get access to.
The invitee gets an email with a 7-day setup link. They click through, set a password, and land in the portal.
Delegating spoke admin (per-spoke, atomic)
Sometimes you want to give someone access to one spoke without making them a federation-wide hub_admin. Use /spokes/<id> → Delegate:
- Email + display name.
- Pre-existing user → add the spoke to their existing memberships, no email.
- New user → create + invite + grant in one step.
This is the most common path for "I want my customer's IT person to be able to admin their own spoke and nothing else".
Removing access
/users/<id> → Revoke. The user's account stays (so audit trails keep working) but their memberships are stripped. They can still log in but they'll see "no assignment" — a placeholder telling them they have no scope.
To delete the user entirely: contact support. We don't expose hard-delete in the portal because it complicates audit.
Where roles get checked
Every API endpoint declares its role floor. The portal hides UI for things you can't do, but the API is the actual enforcement layer — direct API calls go through the same authorization guard as the portal.
See the API reference — every endpoint shows the required role + scope.
What about hub-side users?
Identity-projected users (mode B / both) are managed in Moodle, not here. They sign in to a spoke, the projection pushes them to the hub. You can see them in /identity but you can't promote them to a portal role from there — that's a separate invite from the portal.