An org admin listing their own teams on GET /team/list and GET /v2/team/list
only saw teams in the orgs they administer. Teams they belong to in other
orgs were dropped because the org scope and the membership scope were ANDed.
A self query now unions the two, while a query for another user keeps the
org boundary intersection.
Resolves LIT-3723
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- actually drop the ruff-strict-budget.json changes: the earlier
checkout restored the edited HEAD version instead of main, so the
twelve limit changes were still in the branch; budget ratcheting
stays with the scheduled automation
- annotate validator_call as Final per repo convention
- drop the standalone comment duplicating the inline noqa reason
- restore the short-circuit in custom_team_metadata_validate: only
touch __call__ when the plain coroutine-function check fails, so a
raising descriptor on an async function is not newly triggered
- inline the noqa reasons per the suppression policy
- drop the ruff-strict-budget.json edit: budget ratcheting is reserved
for the scheduled automation on the default branch
Zeroes the remaining violations for 12 rules so they can hard-fail
in the main ruff config instead of being budget-ratcheted, and drops
their strict-gate budgets to 0:
- B021: drop useless f-prefix on the Javelin docstring
- C404 / C419: dict()/any() around unnecessary list comprehension
- PLR0124: replace the 'value == value' NaN idiom (and the separate
+/-inf exclusion) with math.isfinite in _validate_response_time
- SIM201: 'not X == "function"' -> 'X != "function"'
- SIM211: 'False if x is False else True' -> 'x is not False'
- SIM222: drop literal 'None or' before "success"
- UP036: remove the dead sys.version_info < (3, 8) branch (and the
now-unused sys import) in the weights_biases TYPE_CHECKING block
- B018 x2: keep the deliberate property side-effect access but assign
it ('_ = self.prompt_manager') as the rule requires
- PLR0206: the unusable '@property def api_version(self, api_version)'
(a property getter cannot take extra args) becomes a @staticmethod
matching its siblings get_api_base/get_api_key; it had no callers
- PLR1704: rename the loop variable (and the nested helper parameter)
that shadowed abatch_completion_fastest_response's 'model' argument
- B004 x2: scoped noqa with rationale — both sites retrieve __call__
to unwrap functors for iscoroutinefunction, which is a value use,
not the callability test B004 assumes; the callable() autofix would
break them
N999 intentionally stays on the ratchet (limit 1): it flags the
'litellm/proxy/lambda.py' filename, which needs a module rename.
Verified: full-tree 'ruff check litellm' green with the graduated
rules enforced; ruff-strict counts for all 12 rules are 0; budget
JSON regenerated in the gate script's json.dumps style.
Lock affected teams in sorted order inside a single 60s transaction so a
failure on any team rolls back every rewrite and every user row delete.
PrismaClient.tx() gains an optional timeout for the larger batch.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
/user/bulk_delete now deletes the users' keys, invitation links, org and team
memberships and user rows in one transaction and reports a rolled-back batch
per row instead of leaving partial deletes behind. Both bulk endpoints evict
the deleted keys (and deleted user objects) from the auth cache, so a deleted
key stops authenticating immediately rather than at TTL expiry.
/team/bulk_member_delete rejects member rows that carry both user_id and
user_email, reports repeated rows as duplicates, and only cleans up keys and
memberships of members it actually matched.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Batch user deletion that also removes each user from every team they belong to, and batch removal of many members from one team. Each touched team is rewritten once under the team advisory lock from a roster re-read under that lock
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Rows opting into auto_create_key lost blocked, permissions, aliases, config,
agent_id, budget_fallbacks and budget_limits before reaching the key helper.
When create_many commits but the response is lost, re-read which ids landed
and retry only the rest so committed rows report success and get their teams.
Regenerate schema.d.ts and allowlist the endpoint in the Terraform audit.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Creates up to 500 internal users in one request with set-based validation,
a single create_many for user rows, and one locked write per referenced team.
Rows fail independently, keys are opt-in per row via auto_create_key, and
send_invite_email is rejected for the batch.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Adds a nullable tpd_limit column and field to keys, teams, budgets and end users. The batch submission limiter swaps the per-minute RPM/TPM descriptor of any scope that has a tpd_limit for a token-only 24h descriptor, so batch traffic is budgeted per day while online traffic keeps the existing per-minute limits. The Admin UI exposes the field on key, team and budget create/edit forms
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The org cache entries written by prefetch_auth_objects carry the 5s
DEFAULT_IN_MEMORY_TTL. The first @log_db_metrics getter lazily imports
litellm.proxy.proxy_server, which on a cold CI runner can take longer
than 5s, so the org entry expired before get_org_object read it and the
getter fell through to the MagicMock database. Inject a frozen clock
into InMemoryCache so the test asserts the join, not import latency.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Move the BaseLLMException import into _map_error_event_exception so the
module no longer imports it at load time, clearing the module-level cyclic
import CodeQL flagged. The class is used only on the cold error path.
Replace the mutable list-append test collector with aiter/anext so the
regression tests read the stream immutably.
RouterRateLimitError now carries the model group's deployment ids so it
can tell when every deployment is cooled down, and exposes that as
type=all_deployments_in_cooldown with an explicit message. A partial
cooldown keeps type=rate_limit_error. Either way the proxy no longer
reports type=internal_server_error next to code 429
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>