Auto-allocate default_credit on user create / update
Credit behavior on POST /api/v1/auth/users and
PUT /api/v1/auth/users/{user_id}.
User create/update still succeeds when auth checks pass. Credit allocation is soft-fail: missing or insufficient budget does not fail the user API.
Helpers live in app/features/rate_limit/service.py:
delete_user_credit_config— removesUserLlmCreditConfig(no used guard)try_allocate_default_user_credit— allocates orgdefault_creditwhen possible; notifies the requester on budget / usage shortfall
Available budget:
remaining = org.limit_credits - SUM(user_llm_credit_configs.limit_credits)
Allocate only when all of:
- target user is not
system_admin(quota bypass) - org has
OrgLlmCreditConfiganddefault_credit > 0 - user has no existing
UserLlmCreditConfig remaining >= default_credit- current-period
used <= default_credit
Notify type: llm_credit_org_budget_insufficient (requester only).
Create user (POST /auth/users)​
| # | Condition | Credit behavior | Notify requester? |
|---|---|---|---|
| C1 | New user, has org_id, default_credit > 0, remaining OK, used OK | Create UserLlmCreditConfig with limit = default_credit | No |
| C2 | Has org_id, default_credit > 0, remaining < default_credit | No config | Yes |
| C3 | Has org_id, default_credit > 0, used > default_credit | No config | Yes |
| C4 | default_credit = 0 or no OrgLlmCreditConfig | No config | No |
| C5 | org_id is None | Skip allocate | No |
| C6 | Target is system_admin | Skip (quota bypass) | No |
Reactivate user (same POST, soft-deleted email)​
When create finds an existing user with deleted=True, it reactivates that
row (same user_id) instead of inserting a new user.
| # | Condition | Credit behavior | Notify? |
|---|---|---|---|
| R1 | Org changed + old config exists | Delete old config → try allocate for new org (C1–C6) | Only if allocate fails (budget / used) |
| R2 | Same org + config already exists | No delete; allocate no-op | No |
| R3 | Same org + no config yet | Try allocate like create | Same as C1–C3 |
Update user (PUT /auth/users/{id}, admin path)​
Self-edit by a non–system_admin returns early and does not touch credit (U7).
| # | Condition | Credit behavior | Notify? |
|---|---|---|---|
| U1 | Org changed + old config exists | Delete old config → allocate for new org | Only if allocate fails |
| U2 | Org changed + no config | Allocate for new org | Same as above |
| U3 | Org changed → org_id = null (sysadmin) | Delete old config; no allocate | No |
| U4 | Same org + no config + default_credit > 0 + budget OK | Backfill: create config | No |
| U5 | Same org + no config + insufficient budget / used | No config | Yes |
| U6 | Same org + config already exists | Allocate no-op (keep old limit) | No |
| U7 | Self-edit (non–sysadmin edits self) | Early return — no credit logic | No |
Quick summary​
| Action | When config is created | When config is deleted | When requester is notified |
|---|---|---|---|
| Create | Budget + default OK | — | Allocate attempted but remaining/used blocks it |
| Reactivate org change | After delete, if new org OK | Always if old config exists | Same as create shortfall |
| Update org change | After delete, if new org OK | Always if old config exists | Same |
| Update same org, no quota | Backfill if OK | — | Shortfall only |
| Update same org, has quota | — | — | — |