The auth module serves sign-in and token refresh, users, roles, permissions, ABAC policies, approval chains and steps, approval requests, notification rules, and the per-user interface state. All 56 endpoints sit under /api/v1/auth. For business meaning see the Auth module page.
Group facts¶
| Item | Value | Source |
|---|---|---|
| Base path | /api/v1/auth |
src/cluster_erp/core/module_base.py:37-38, src/cluster_erp/modules/auth/module.py:58 |
| Routers | 10 router objects in 9 files; listed in the section Endpoint summary | src/cluster_erp/modules/auth/module.py:32 |
| Endpoints | 56, counted from the route decorators and add_api_route calls of the routers that register_routes mounts |
src/cluster_erp/modules/auth/approval_chains/routes.py, src/cluster_erp/modules/auth/approvals/routes.py, src/cluster_erp/modules/auth/login/routes.py ... |
| Authentication | Bearer header or session cookie, resolved by get_current_user; see Authentication and headers |
src/cluster_erp/modules/auth/guards.py:85-167 |
| Permission guard | 44 of 56 routes declare require_permission; the other routes show their guard in the tables |
src/cluster_erp/modules/auth/guards.py:205-240 |
| Error format | JSON body {"error": {...}}; see Errors |
src/cluster_erp/server/error_handler.py:33-46 |
Endpoint summary¶
One row per sub-module folder. The router prefix is added to the base path.
| Sub-module | Routers | Endpoints | Router source |
|---|---|---|---|
login |
router |
4 | src/cluster_erp/modules/auth/login/routes.py:51 |
users |
router (/users) |
8 | src/cluster_erp/modules/auth/users/routes.py:23 |
roles |
router (/roles) |
8 | src/cluster_erp/modules/auth/roles/routes.py:20 |
permissions |
router (/permissions) |
1 | src/cluster_erp/modules/auth/permissions/routes.py:11 |
policies |
router (/policies) |
6 | src/cluster_erp/modules/auth/policies/routes.py:15 |
approval_chains |
router (/approval-chains), steps_router (/approval-steps) |
12 | src/cluster_erp/modules/auth/approval_chains/routes.py:21, src/cluster_erp/modules/auth/approval_chains/routes.py:25 |
approvals |
router (/approvals) |
9 | src/cluster_erp/modules/auth/approvals/routes.py:22 |
notification_rules |
router (/notification-rules) |
6 | src/cluster_erp/modules/auth/notification_rules/routes.py:21 |
ui_state |
router |
2 | src/cluster_erp/modules/auth/ui_state/routes.py:13 |
Sign-in and session endpoints¶
Sign-in, token refresh, sign-out, and the current-user read. The mechanism is described in Authentication and headers.
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
POST |
/api/v1/auth/login |
login |
none (sign-in) | LoginRequest |
none | LoginResponse |
200 (default) | src/cluster_erp/modules/auth/login/routes.py:123 |
POST |
/api/v1/auth/refresh |
refresh |
refresh token | RefreshRequest \| None |
none | RefreshResponse |
200 (default) | src/cluster_erp/modules/auth/login/routes.py:260 |
POST |
/api/v1/auth/logout |
logout |
authenticated user (get_current_user) |
none | none | Response |
204 |
src/cluster_erp/modules/auth/login/routes.py:373 |
GET |
/api/v1/auth/me |
me |
authenticated user (get_current_user) |
none | none | MeResponse |
200 (default) | src/cluster_erp/modules/auth/login/routes.py:434 |
Users endpoints¶
User list, create, read, update, deactivate, bulk deactivate, own password change, and an administrator password reset.
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
GET |
/api/v1/auth/users/ |
list_users |
user.read |
none | search, active_only, limit, offset |
dict |
200 (default) | src/cluster_erp/modules/auth/users/routes.py:59 |
POST |
/api/v1/auth/users/ |
create_user |
user.create |
UserCreate |
none | UserRead |
201 |
src/cluster_erp/modules/auth/users/routes.py:111 |
GET |
/api/v1/auth/users/{user_id} |
get_user |
user.read |
none | none | UserRead |
200 (default) | src/cluster_erp/modules/auth/users/routes.py:111 |
PUT |
/api/v1/auth/users/{user_id} |
update_user |
user.update |
UserUpdate |
none | UserRead |
200 (default) | src/cluster_erp/modules/auth/users/routes.py:124 |
DELETE |
/api/v1/auth/users/{user_id} |
delete_user |
user.delete |
none | none | none | 204 |
src/cluster_erp/modules/auth/users/routes.py:140 |
POST |
/api/v1/auth/users/bulk-delete |
bulk_delete_users |
user.delete |
BulkDeleteRequest |
none | BulkDeleteResponse |
200 (default) | src/cluster_erp/modules/auth/users/routes.py:151 |
POST |
/api/v1/auth/users/me/change-password |
change_own_password |
authenticated user (get_current_user) |
ChangePasswordRequest |
none | none | 204 |
src/cluster_erp/modules/auth/users/routes.py:162 |
POST |
/api/v1/auth/users/{user_id}/reset-password |
reset_password |
user.reset_password |
ResetPasswordRequest |
none | none | 204 |
src/cluster_erp/modules/auth/users/routes.py:177 |
Roles endpoints¶
Role records and the permission set assigned to a role.
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
GET |
/api/v1/auth/roles/ |
list_roles |
role.read |
none | active_only, search |
list[RoleRead] |
200 (default) | src/cluster_erp/modules/auth/roles/routes.py:42 |
POST |
/api/v1/auth/roles/ |
create_role |
role.create |
RoleCreate |
none | RoleRead |
201 |
src/cluster_erp/modules/auth/roles/routes.py:54 |
GET |
/api/v1/auth/roles/{role_id} |
get_role |
role.read |
none | none | RoleRead |
200 (default) | src/cluster_erp/modules/auth/roles/routes.py:68 |
PUT |
/api/v1/auth/roles/{role_id} |
update_role |
role.update |
RoleUpdate |
none | RoleRead |
200 (default) | src/cluster_erp/modules/auth/roles/routes.py:81 |
DELETE |
/api/v1/auth/roles/{role_id} |
delete_role |
role.delete |
none | none | none | 204 |
src/cluster_erp/modules/auth/roles/routes.py:95 |
POST |
/api/v1/auth/roles/bulk-delete |
bulk_delete_roles |
role.delete |
BulkDeleteRequest |
none | BulkDeleteResponse |
200 (default) | src/cluster_erp/modules/auth/roles/routes.py:111 |
GET |
/api/v1/auth/roles/{role_id}/permissions |
get_role_permissions |
permission.read |
none | none | list[uuid.UUID] |
200 (default) | src/cluster_erp/modules/auth/roles/routes.py:122 |
PUT |
/api/v1/auth/roles/{role_id}/permissions |
assign_role_permissions |
permission.assign |
RolePermissionAssign |
none | RoleRead |
200 (default) | src/cluster_erp/modules/auth/roles/routes.py:135 |
Permissions endpoints¶
A read-only list of permission codes.
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
GET |
/api/v1/auth/permissions/ |
list_permissions |
permission.read |
none | module, resource |
list[PermissionRead] |
200 (default) | src/cluster_erp/modules/auth/permissions/routes.py:14 |
ABAC policies endpoints¶
Attribute-based access policies attached to permission codes.
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
GET |
/api/v1/auth/policies/ |
list_policies |
abac_policy.read |
none | active_only, search |
list[PolicyRead] |
200 (default) | src/cluster_erp/modules/auth/policies/routes.py:18 |
POST |
/api/v1/auth/policies/ |
create_policy |
abac_policy.create |
PolicyCreate |
none | PolicyRead |
201 |
src/cluster_erp/modules/auth/policies/routes.py:30 |
GET |
/api/v1/auth/policies/{policy_id} |
get_policy |
abac_policy.read |
none | none | PolicyRead |
200 (default) | src/cluster_erp/modules/auth/policies/routes.py:41 |
PUT |
/api/v1/auth/policies/{policy_id} |
update_policy |
abac_policy.update |
PolicyUpdate |
none | PolicyRead |
200 (default) | src/cluster_erp/modules/auth/policies/routes.py:54 |
DELETE |
/api/v1/auth/policies/{policy_id} |
delete_policy |
abac_policy.delete |
none | none | none | 204 |
src/cluster_erp/modules/auth/policies/routes.py:68 |
POST |
/api/v1/auth/policies/bulk-delete |
bulk_delete_policies |
abac_policy.delete |
BulkDeleteRequest |
none | BulkDeleteResponse |
200 (default) | src/cluster_erp/modules/auth/policies/routes.py:79 |
Approval chains endpoints¶
Two routers: router for approval chains and their steps under a chain, steps_router for single steps.
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
GET |
/api/v1/auth/approval-chains/ |
list_chains |
approval_chain.read |
none | active_only, search |
list[ChainRead] |
200 (default) | src/cluster_erp/modules/auth/approval_chains/routes.py:32 |
POST |
/api/v1/auth/approval-chains/ |
create_chain |
approval_chain.create |
ChainCreate |
none | ChainRead |
201 |
src/cluster_erp/modules/auth/approval_chains/routes.py:44 |
GET |
/api/v1/auth/approval-chains/{chain_id} |
get_chain |
approval_chain.read |
none | none | ChainRead |
200 (default) | src/cluster_erp/modules/auth/approval_chains/routes.py:55 |
PUT |
/api/v1/auth/approval-chains/{chain_id} |
update_chain |
approval_chain.update |
ChainUpdate |
none | ChainRead |
200 (default) | src/cluster_erp/modules/auth/approval_chains/routes.py:68 |
DELETE |
/api/v1/auth/approval-chains/{chain_id} |
delete_chain |
approval_chain.delete |
none | none | none | 204 |
src/cluster_erp/modules/auth/approval_chains/routes.py:82 |
POST |
/api/v1/auth/approval-chains/bulk-delete |
bulk_delete_chains |
approval_chain.delete |
BulkDeleteRequest |
none | BulkDeleteResponse |
200 (default) | src/cluster_erp/modules/auth/approval_chains/routes.py:93 |
GET |
/api/v1/auth/approval-chains/{chain_id}/steps |
list_chain_steps |
approval_chain.read |
none | none | list[ApprovalStepRead] |
200 (default) | src/cluster_erp/modules/auth/approval_chains/routes.py:110 |
POST |
/api/v1/auth/approval-chains/{chain_id}/steps |
add_chain_step |
approval_chain.update |
ApprovalStepCreate |
none | ApprovalStepRead |
201 |
src/cluster_erp/modules/auth/approval_chains/routes.py:121 |
GET |
/api/v1/auth/approval-steps/{step_id} |
get_step |
approval_chain.read |
none | none | ApprovalStepRead |
200 (default) | src/cluster_erp/modules/auth/approval_chains/routes.py:135 |
PUT |
/api/v1/auth/approval-steps/{step_id} |
update_step |
approval_chain.update |
ApprovalStepCreate |
none | ApprovalStepRead |
200 (default) | src/cluster_erp/modules/auth/approval_chains/routes.py:148 |
DELETE |
/api/v1/auth/approval-steps/{step_id} |
delete_step |
approval_chain.update |
none | none | none | 204 |
src/cluster_erp/modules/auth/approval_chains/routes.py:162 |
POST |
/api/v1/auth/approval-steps/bulk-delete |
bulk_delete_steps |
approval_chain.update |
BulkDeleteRequest |
none | BulkDeleteResponse |
200 (default) | src/cluster_erp/modules/auth/approval_chains/routes.py:173 |
Approval requests endpoints¶
Approval requests: pending list, the caller's inbox, create, read, decide, defer and lift a deferral, cancel, and the approvals of one entity.
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
GET |
/api/v1/auth/approvals/pending |
list_pending |
permission.read |
none | none | list[ApprovalRequestRead] |
200 (default) | src/cluster_erp/modules/auth/approvals/routes.py:25 |
GET |
/api/v1/auth/approvals/inbox |
approval_inbox |
authenticated user (get_current_user) |
none | none | list[dict[str, Any]] |
200 (default) | src/cluster_erp/modules/auth/approvals/routes.py:35 |
POST |
/api/v1/auth/approvals/ |
create_approval_request |
permission.assign |
ApprovalRequestCreate |
none | ApprovalRequestRead |
201 |
src/cluster_erp/modules/auth/approvals/routes.py:56 |
GET |
/api/v1/auth/approvals/{request_id} |
get_approval_request |
permission.read |
none | none | ApprovalRequestRead |
200 (default) | src/cluster_erp/modules/auth/approvals/routes.py:77 |
POST |
/api/v1/auth/approvals/{request_id}/decide |
decide_approval |
authenticated user (get_current_user) |
ApprovalDecisionCreate |
none | ApprovalRequestRead |
200 (default) | src/cluster_erp/modules/auth/approvals/routes.py:90 |
POST |
/api/v1/auth/approvals/{request_id}/defer |
defer_approval |
authenticated user (get_current_user) |
ApprovalDeferCreate |
none | ApprovalDeferRead |
200 (default) | src/cluster_erp/modules/auth/approvals/routes.py:134 |
DELETE |
/api/v1/auth/approvals/{request_id}/defer |
lift_approval_defer |
authenticated user (get_current_user) |
none | none | none | 204 |
src/cluster_erp/modules/auth/approvals/routes.py:157 |
POST |
/api/v1/auth/approvals/{request_id}/cancel |
cancel_approval |
authenticated user (get_current_user) |
none | none | none | 204 |
src/cluster_erp/modules/auth/approvals/routes.py:171 |
GET |
/api/v1/auth/approvals/entity/{entity_type}/{entity_id} |
get_entity_approvals |
permission.read |
none | none | list[ApprovalRequestRead] |
200 (default) | src/cluster_erp/modules/auth/approvals/routes.py:189 |
Notification rules endpoints¶
Notification rule records.
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
GET |
/api/v1/auth/notification-rules/ |
list_notification_rules |
notification_rule.read |
none | active_only, search |
list[NotificationRuleRead] |
200 (default) | src/cluster_erp/modules/auth/notification_rules/routes.py:24 |
POST |
/api/v1/auth/notification-rules/ |
create_notification_rule |
notification_rule.create |
NotificationRuleCreate |
none | NotificationRuleRead |
201 |
src/cluster_erp/modules/auth/notification_rules/routes.py:36 |
GET |
/api/v1/auth/notification-rules/{rule_id} |
get_notification_rule |
notification_rule.read |
none | none | NotificationRuleRead |
200 (default) | src/cluster_erp/modules/auth/notification_rules/routes.py:47 |
PUT |
/api/v1/auth/notification-rules/{rule_id} |
update_notification_rule |
notification_rule.update |
NotificationRuleUpdate |
none | NotificationRuleRead |
200 (default) | src/cluster_erp/modules/auth/notification_rules/routes.py:60 |
DELETE |
/api/v1/auth/notification-rules/{rule_id} |
delete_notification_rule |
notification_rule.delete |
none | none | none | 204 |
src/cluster_erp/modules/auth/notification_rules/routes.py:74 |
POST |
/api/v1/auth/notification-rules/bulk-delete |
bulk_delete_notification_rules |
notification_rule.delete |
BulkDeleteRequest |
none | BulkDeleteResponse |
200 (default) | src/cluster_erp/modules/auth/notification_rules/routes.py:85 |
Interface state endpoints¶
The signed-in user's own layout state, read as a whole and written per key. The handler takes the user id from the credential (src/cluster_erp/modules/auth/ui_state/routes.py:15-18).
| Method | Path | Handler | Permission | Request | Query | Response | Status | Source |
|---|---|---|---|---|---|---|---|---|
GET |
/api/v1/auth/ui-state |
get_my_ui_state |
authenticated user (get_current_user) |
none | none | dict |
200 (default) | src/cluster_erp/modules/auth/ui_state/routes.py:21 |
PUT |
/api/v1/auth/ui-state/{key} |
put_my_ui_state |
authenticated user (get_current_user) |
UiStateWrite |
none | none | 204 |
src/cluster_erp/modules/auth/ui_state/routes.py:30 |
Error codes¶
The table lists the error codes that code under src/cluster_erp/modules/auth/ raises, found by a syntax-tree scan for AppError(...), the factories in src/cluster_erp/core/errors.py (not_found, conflict, protected, permission_denied, privilege_escalation, check_version), and HTTPException(...). A status of 400 is the AppError default (src/cluster_erp/core/errors.py:23). Guard errors (401, 403), the entitlement codes, and validation errors (422) apply to every route and are listed on Errors.
| Code | HTTP status | Raised in | First site |
|---|---|---|---|
ABAC_RESOURCE_RULES_UNSUPPORTED |
422 |
policies |
src/cluster_erp/modules/auth/policies/services.py:81 |
APPROVAL_INVALID_STATE |
400, 409, 422 |
approval_chains, approvals |
src/cluster_erp/modules/auth/approval_chains/services.py:132 |
AUTH_CSRF_HEADER_MISSING |
403 |
login, session_cookies |
src/cluster_erp/modules/auth/login/routes.py:271 |
AUTH_INVALID_CREDENTIALS |
401 |
login, users |
src/cluster_erp/modules/auth/login/routes.py:143 |
AUTH_MISSING_HEADER |
401 |
guards |
src/cluster_erp/modules/auth/guards.py:103 |
AUTH_PERMISSION_DENIED |
403 |
approvals, guards |
src/cluster_erp/modules/auth/approvals/services.py:364 |
AUTH_PRIVILEGE_ESCALATION |
403 |
roles, users |
src/cluster_erp/modules/auth/roles/services.py:163 |
AUTH_REFRESH_FAILED |
401 |
login |
src/cluster_erp/modules/auth/login/routes.py:269 |
AUTH_SELF_APPROVAL_FORBIDDEN |
403 |
approvals |
src/cluster_erp/modules/auth/approvals/services.py:314 |
AUTH_TOKEN_BLACKLISTED |
401 |
guards |
src/cluster_erp/modules/auth/guards.py:131 |
AUTH_TOKEN_EXPIRED |
401 |
guards |
src/cluster_erp/modules/auth/guards.py:113 |
AUTH_TOKEN_INVALID |
401 |
guards |
src/cluster_erp/modules/auth/guards.py:115 |
AUTH_TOKEN_PAYLOAD_INVALID |
401 |
guards |
src/cluster_erp/modules/auth/guards.py:120 |
AUTH_TOO_MANY_ATTEMPTS |
429 |
login |
src/cluster_erp/modules/auth/login/routes.py:93 |
AUTH_USER_INACTIVE |
401 |
guards, login |
src/cluster_erp/modules/auth/guards.py:151 |
RESOURCE_CONFLICT |
409 |
roles, users |
src/cluster_erp/modules/auth/roles/routes.py:63 |
RESOURCE_NOT_FOUND |
404 |
approval_chains, approvals, notification_rules, policies, roles, users |
src/cluster_erp/modules/auth/approval_chains/routes.py:64 |
RESOURCE_PROTECTED |
400 |
roles |
src/cluster_erp/modules/auth/roles/routes.py:106 |
VALIDATION_ERROR |
422 |
users |
src/cluster_erp/modules/auth/users/routes.py:87 |
Events emitted¶
The table lists the contract classes that code under src/cluster_erp/modules/auth/ passes directly to EventBus.emit, found by a syntax-tree scan. Events built in a variable first are not counted. The contracts are described in Contracts reference.
| Contract | Sites | First site |
|---|---|---|
ApprovalCompleted |
1 | src/cluster_erp/modules/auth/approvals/routes.py:119 |
Related pages¶
Verified against commit 92f8051 on 2026-11-13.