Background
Nexent can currently create users only through invitation-code self-registration (services/user_management_service.signup_user_with_invitation). There is no way for a tenant administrator to provision an account directly through the northbound API.
In integration / operations scenarios the tenant admin needs to open an account for a user (email + initial password) without going through the invitation flow.
Requirement
Add a northbound HTTP endpoint that lets a tenant administrator create a user belonging to their own tenant.
Proposed contract
POST /nb/v1/users, authenticated with the existing northbound Bearer API key (_get_northbound_context -> ctx.user_id / ctx.tenant_id).
- Permission gate (core): the caller must have
user_role == "ADMIN" in ctx.tenant_id (database.user_tenant_db.get_user_role_by_tenant). Anyone else gets 403 Forbidden.
- Request body:
{ email, initial_password, name?, role? }
role defaults to "USER", allow-list USER / DEV / ADMIN. SU (platform super admin) is intentionally rejected.
initial_password must pass the existing validate_password_strength (>= 8 chars, upper + lower + digit).
- New user created via the Supabase admin client (
auth.admin.create_user with email_confirm: True) and linked to the caller's tenant with insert_user_tenant(...).
- Response
201: { user_id, user_email, user_role, tenant_id }
- Errors:
401 invalid API key, 403 not a tenant admin, 400 weak password / invalid role / tenant quota exceeded, 409 email already registered, 422 request validation, 500 internal error.
Design decisions
- Email uniqueness is global, not per-tenant. Supabase Auth treats one email as one user globally, so an email already registered in another tenant is rejected with
409 rather than silently being attached to a second tenant. Stricter than per-tenant uniqueness and keeps the permission boundary unambiguous.
- No side effects beyond account creation. No tool/skill list initialisation, no notification email -- those are tenant-level or need infrastructure the repo does not have today.
Out of scope
- No change to the existing invitation-code self-registration flow.
- No batch / Excel import (single-user creation only).
- No cross-tenant provisioning (created users always land in the caller's tenant).
- No activation or notification email.
Acceptance criteria
Background
Nexent can currently create users only through invitation-code self-registration (
services/user_management_service.signup_user_with_invitation). There is no way for a tenant administrator to provision an account directly through the northbound API.In integration / operations scenarios the tenant admin needs to open an account for a user (email + initial password) without going through the invitation flow.
Requirement
Add a northbound HTTP endpoint that lets a tenant administrator create a user belonging to their own tenant.
Proposed contract
POST /nb/v1/users, authenticated with the existing northbound Bearer API key (_get_northbound_context->ctx.user_id/ctx.tenant_id).user_role == "ADMIN"inctx.tenant_id(database.user_tenant_db.get_user_role_by_tenant). Anyone else gets403 Forbidden.{ email, initial_password, name?, role? }roledefaults to"USER", allow-listUSER/DEV/ADMIN.SU(platform super admin) is intentionally rejected.initial_passwordmust pass the existingvalidate_password_strength(>= 8 chars, upper + lower + digit).auth.admin.create_userwithemail_confirm: True) and linked to the caller's tenant withinsert_user_tenant(...).201:{ user_id, user_email, user_role, tenant_id }401invalid API key,403not a tenant admin,400weak password / invalid role / tenant quota exceeded,409email already registered,422request validation,500internal error.Design decisions
409rather than silently being attached to a second tenant. Stricter than per-tenant uniqueness and keeps the permission boundary unambiguous.Out of scope
Acceptance criteria
POST /nb/v1/usersreachable and protected by northbound API-key auth.user_role != ADMIN) ->403.409.