User Management¶
Listing users¶
The Users page (/admin/users) lists all users with filters:
- Search by email or display name
- Toggle to show All / Unassigned / Admins only
Each user row shows: name, email, admin badge (if applicable), household membership(s) with role, last seen, and a TTL countdown if they're unassigned and approaching deletion.
Assigning a user to a household¶
Unassigned users appear with a warning indicator. To assign one:
- Click Assign to household on the user row (or from the user detail page).
- Choose a household from the dropdown.
- Choose a role: Member or Owner.
- Confirm (step-up authentication required).
The user is immediately added to the household. They receive an in-app notification and an email (if SMTP is configured). If they're on the waiting page, they're redirected automatically via Server-Sent Events — no page refresh needed.
Promoting and demoting admins¶
To promote a user to App Admin:
- Click Promote on the user row. Requires step-up authentication.
To demote an admin:
- Click Demote on the user row. Requires step-up authentication.
- Blocked if the target is the last admin — you cannot remove the last admin account.
Via CLI:
docker compose exec app uv run python -m app.admin promote-admin --email=user@example.com
docker compose exec app uv run python -m app.admin demote-admin --email=user@example.com
Force logout¶
Force logout revokes all active sessions for a user. They'll be signed out on all devices immediately and will need to log in again. Useful if a device is lost or a session looks suspicious.
This does not delete the account or change any data.
Deleting a user¶
Warning: User deletion is permanent and cannot be undone.
When a user is deleted: - All their active sessions are revoked - Their household memberships are removed - Their "attributed to" tag on split allocations is removed (transactions remain, just lose the user attribution) - Their user account is hard-deleted - An audit log entry is written
The delete button is on the user detail page. It requires step-up authentication and a confirmation dialog that shows: "This will permanently delete [name]'s account. Transaction attribution will be removed. This cannot be undone."
Deletion is blocked if the user is the last App Admin.
Unassigned user cleanup¶
WDIAG runs a daily cleanup job that hard-deletes accounts where:
- No household membership exists
- No pending invitation exists (invited users waiting to accept are exempt)
- The account was created more than UNASSIGNED_ACCOUNT_TTL_DAYS days ago (default 7)
The TTL countdown appears on unassigned user rows in the admin panel. If you want to keep an unassigned account, assign it to a household before the TTL expires.