From 6713edfe09d828f6f8f4f3e060ffa9bfcf9f6138 Mon Sep 17 00:00:00 2001 From: Yassin Kortam Date: Mon, 8 Jun 2026 15:37:53 -0700 Subject: [PATCH] style(identity): trim narrative module docstrings --- litellm/identity/adapter.py | 4 --- litellm/identity/cache.py | 13 +++------ litellm/identity/context.py | 12 +++------ litellm/identity/extractors/__init__.py | 8 +----- litellm/identity/extractors/client.py | 6 ++--- litellm/identity/extractors/end_user.py | 13 +++------ litellm/identity/extractors/header.py | 7 +---- litellm/identity/invalidation.py | 35 ++++++------------------- litellm/identity/jwt.py | 20 +++----------- litellm/identity/oauth2.py | 10 +++---- litellm/identity/principal.py | 11 +++----- litellm/identity/resolver.py | 14 +++------- litellm/identity/store.py | 14 +++------- 13 files changed, 39 insertions(+), 128 deletions(-) diff --git a/litellm/identity/adapter.py b/litellm/identity/adapter.py index 15fa6583dc2..acb2d2f0797 100644 --- a/litellm/identity/adapter.py +++ b/litellm/identity/adapter.py @@ -1,9 +1,5 @@ """Bidirectional bridge between ``IdentityContext`` and ``UserAPIKeyAuth``. -The legacy Pydantic model stays the universal carrier. These two pure -functions let new code work in terms of ``IdentityContext`` without -forcing call sites to migrate today. - Invariants: - ``identity_context_to_user_api_key_auth(uak.to_identity_context())`` preserves every identity-relevant field on ``uak``. diff --git a/litellm/identity/cache.py b/litellm/identity/cache.py index bf3a0383abf..83882bbe6c0 100644 --- a/litellm/identity/cache.py +++ b/litellm/identity/cache.py @@ -1,14 +1,7 @@ -"""Three-layer identity cache. +"""Three-layer identity cache (process memory -> Redis -> Prisma). -Layer 1 (per-process, ~5s TTL): bounded ``InMemoryCache`` inside the -``DualCache`` we wrap. Bounds revocation staleness without round-tripping -to Redis on every request. - -Layer 2 (Redis, cross-replica): the ``redis_cache`` on the same -``DualCache``. Writes go to both layers; reads fall through. - -Layer 3 (Prisma): not owned here. ``store.load_identity`` calls the DB -when both cache layers miss. +Layers 1 and 2 are the in-memory and Redis halves of the wrapped +``DualCache``; layer 3 is the DB, owned by ``store.load_identity`` on miss. Cross-table fan-out is handled via *generation counters*: when a team or user changes, the counter for that team/user is bumped. Cached diff --git a/litellm/identity/context.py b/litellm/identity/context.py index f3637f9a9cb..cb3d7db1dd4 100644 --- a/litellm/identity/context.py +++ b/litellm/identity/context.py @@ -1,13 +1,7 @@ -"""The per-request identity bundle. +"""The per-request identity bundle consumed downstream of auth. -``IdentityContext`` is what downstream consumers (auth, spend, guardrails, -logging, audit) should read identity from. Today it travels alongside the -legacy ``UserAPIKeyAuth`` via the adapter functions in -``litellm.identity.adapter``. - -The bundle is mutable on purpose: identity fields like ``end_user_id`` are -sometimes resolved or overridden after initial extraction, and the -existing ``UserAPIKeyAuth`` mutation patterns must keep working. +Mutable on purpose: fields like ``end_user_id`` are resolved or overridden +after initial extraction. """ from dataclasses import dataclass, field diff --git a/litellm/identity/extractors/__init__.py b/litellm/identity/extractors/__init__.py index 116b27a9190..875560d1a12 100644 --- a/litellm/identity/extractors/__init__.py +++ b/litellm/identity/extractors/__init__.py @@ -1,7 +1 @@ -"""Identity extractors. - -Each extractor wraps an existing helper in ``litellm/proxy/auth/`` and -returns a piece of an ``IdentityContext``. Extractors must not introduce -new behavior. If you need to change *how* a field is resolved, change the -underlying helper and update the extractor's tests. -""" +"""Identity extractors: each returns a piece of an ``IdentityContext``.""" diff --git a/litellm/identity/extractors/client.py b/litellm/identity/extractors/client.py index 72aadb8191b..87fae888a3c 100644 --- a/litellm/identity/extractors/client.py +++ b/litellm/identity/extractors/client.py @@ -1,9 +1,7 @@ """Client/network identity extraction. -Builds a ``ClientInfo`` from a FastAPI request. ``X-Forwarded-For`` is -only honored when the direct peer is in a configured trusted-proxy CIDR. -The trust logic is delegated to ``IPAddressUtils.is_request_from_trusted_proxy`` -so we stay in sync with the rest of the proxy. +``X-Forwarded-For`` is honored only when the direct peer is a configured +trusted proxy (delegated to ``IPAddressUtils.is_request_from_trusted_proxy``). """ from typing import Any, Dict, List, Mapping, Optional diff --git a/litellm/identity/extractors/end_user.py b/litellm/identity/extractors/end_user.py index 22acd98527c..db7b1c52d91 100644 --- a/litellm/identity/extractors/end_user.py +++ b/litellm/identity/extractors/end_user.py @@ -1,10 +1,7 @@ -"""End-user extraction. +"""End-user id extraction. -Thin wrapper over the existing six-check chain in -``litellm.proxy.auth.auth_utils.get_end_user_id_from_request_body``. -Validation against the DB stays in ``resolve_and_validate_end_user_id`` -and runs from the legacy auth path; this extractor returns the raw -identifier only. +Wraps ``auth_utils.get_end_user_id_from_request_body``; returns the raw +identifier only. DB validation stays in ``resolve_and_validate_end_user_id``. """ from typing import Optional @@ -19,6 +16,4 @@ def extract_end_user_id( from litellm.proxy.auth.auth_utils import get_end_user_id_from_request_body - return get_end_user_id_from_request_body( - request_body=body, request_headers=headers - ) + return get_end_user_id_from_request_body(request_body=body, request_headers=headers) diff --git a/litellm/identity/extractors/header.py b/litellm/identity/extractors/header.py index f47cfd943c5..98e7b7c08e8 100644 --- a/litellm/identity/extractors/header.py +++ b/litellm/identity/extractors/header.py @@ -1,12 +1,7 @@ -"""Header-driven identity extractors. - -These pull non-credential identity fields out of request headers. They -do not perform authorization decisions; that stays in the auth chain. -""" +"""Header-driven extraction of non-credential identity fields.""" from typing import Optional - AUDIT_CHANGED_BY_HEADER = "litellm-changed-by" diff --git a/litellm/identity/invalidation.py b/litellm/identity/invalidation.py index ba2dac79f93..b3256d76cb4 100644 --- a/litellm/identity/invalidation.py +++ b/litellm/identity/invalidation.py @@ -1,20 +1,9 @@ """Identity-cache invalidation hooks. -Two flavors: - -- Per-token: a key was rotated, blocked, or deleted. We know the exact - token hash, so we drop the entry from both memory and Redis. - -- Per-scope (team / user / org): a row that fans out to many keys - changed. Rather than enumerating every key that references the team, - we bump a generation counter for that scope. Cached identities carry - the scope generations they were minted under; reads compare and treat - a mismatch as a miss. - -The legacy ``_delete_cache_key_object`` and the per-table cache deletes -in ``auth_checks.py`` stay in place. These hooks run side-by-side so we -don't strand a partially-deployed fleet that's still reading from the -legacy cache keys. +Per-token deletes drop a known token hash from both cache layers. Per-scope +(team / user / org) changes bump a generation counter instead of +enumerating every key that references the row; reads compare the stored +generation and treat a mismatch as a miss. """ from __future__ import annotations @@ -47,24 +36,16 @@ async def invalidate_identity_for_team( *, team_id: str, dual_cache: "DualCache" ) -> None: """Mark every identity that references this team as stale.""" - await _identity_cache_for(dual_cache).bump_generation( - team_generation_key(team_id) - ) + await _identity_cache_for(dual_cache).bump_generation(team_generation_key(team_id)) async def invalidate_identity_for_user( *, user_id: str, dual_cache: "DualCache" ) -> None: """Mark every identity that references this user as stale.""" - await _identity_cache_for(dual_cache).bump_generation( - user_generation_key(user_id) - ) + await _identity_cache_for(dual_cache).bump_generation(user_generation_key(user_id)) -async def invalidate_identity_for_org( - *, org_id: str, dual_cache: "DualCache" -) -> None: +async def invalidate_identity_for_org(*, org_id: str, dual_cache: "DualCache") -> None: """Mark every identity that references this organization as stale.""" - await _identity_cache_for(dual_cache).bump_generation( - org_generation_key(org_id) - ) + await _identity_cache_for(dual_cache).bump_generation(org_generation_key(org_id)) diff --git a/litellm/identity/jwt.py b/litellm/identity/jwt.py index 32d0935722c..d0b9bdf07ff 100644 --- a/litellm/identity/jwt.py +++ b/litellm/identity/jwt.py @@ -1,20 +1,8 @@ -"""JWT identity construction. +"""JWT identity construction: ``auth_builder`` result -> ``UserAPIKeyAuth``. -Owns the translation from a ``JWTAuthManager.auth_builder`` result (or -any equivalent JWT-validated payload) into the proxy's carrier model -``UserAPIKeyAuth``. The JWT branch of ``_user_api_key_auth_builder`` -used to inline this construction; centralizing it here means: - -- Every JWT-derived ``UserAPIKeyAuth`` carries the same team / user / - membership fields, so downstream auth checks see one shape. -- The mapping from ``jwt_claims`` to a ``JWTPrincipal`` happens at the - same boundary, so callers that want the typed principal can read it - off ``UserAPIKeyAuth.to_identity_context()``. - -This module does NOT perform JWT validation or policy checks. Signature -verification, RBAC, scope, email-domain enforcement, and -``custom_validate`` are all done by ``JWTAuthManager.auth_builder`` -upstream. Here we just build the carrier. +Validation (signature, RBAC, scope, email-domain, ``custom_validate``) is +done upstream by ``JWTAuthManager.auth_builder``; this module only builds +the carrier. """ from __future__ import annotations diff --git a/litellm/identity/oauth2.py b/litellm/identity/oauth2.py index 4d6dd16f363..e73882a337d 100644 --- a/litellm/identity/oauth2.py +++ b/litellm/identity/oauth2.py @@ -1,11 +1,7 @@ -"""OAuth2 identity construction. +"""OAuth2 identity construction: introspection response -> ``UserAPIKeyAuth``. -Owns the translation from an OAuth2 introspection / userinfo response -into the proxy's carrier model ``UserAPIKeyAuth``. The HTTP plumbing — -introspection endpoint detection, request signing, error handling — -stays in ``litellm.proxy.auth.oauth2_check.Oauth2Handler``; this module -just maps a validated response payload into the carrier so the JWT and -OAuth2 paths converge on the same construction surface. +The HTTP plumbing stays in ``oauth2_check.Oauth2Handler``; this module maps +an already-validated response payload into the carrier. """ from __future__ import annotations diff --git a/litellm/identity/principal.py b/litellm/identity/principal.py index eba2ff70309..e97935dc25e 100644 --- a/litellm/identity/principal.py +++ b/litellm/identity/principal.py @@ -1,12 +1,7 @@ -"""Caller-identity primitives. +"""Caller-identity primitives: a frozen ``Principal`` per credential kind. -A ``Principal`` answers "who is making this request" using only the fields -that uniquely identify the caller. Per-row enrichment (budgets, team rows, -object permissions) is intentionally not modeled here; that data continues -to ride on ``UserAPIKeyAuth``. - -Each subtype is a frozen dataclass with a ``kind`` discriminator suitable -for ``match``-style dispatch. +Per-row enrichment (budgets, team rows, object permissions) is not modeled +here; that data rides on ``UserAPIKeyAuth``. """ from dataclasses import dataclass, field diff --git a/litellm/identity/resolver.py b/litellm/identity/resolver.py index 43da2038e16..801d102be8a 100644 --- a/litellm/identity/resolver.py +++ b/litellm/identity/resolver.py @@ -1,15 +1,7 @@ -"""Compose extractors + DB load into a single ``IdentityContext`` per request. +"""Compose extractors into an ``IdentityContext`` for a request. -Two call shapes: - -- ``resolve_identity_for_principal`` — given pre-extracted credentials, decide - the principal kind and resolve it. Used by the proxy auth chain after it - already pulled the api-key out of the request. - -- ``resolve_identity`` — request-scoped composition for new entrypoints. Not - yet wired into ``user_api_key_auth.py``; lives here so callers without a - hashed-token-in-hand (CLI, MCP, background jobs) can still build a - ``IdentityContext``. +``resolve_identity`` builds the context from request-side signals (no DB); +the hydrated-row variant is ``store.load_identity``. """ from __future__ import annotations diff --git a/litellm/identity/store.py b/litellm/identity/store.py index 6847277f0ad..d16d1e56d20 100644 --- a/litellm/identity/store.py +++ b/litellm/identity/store.py @@ -1,14 +1,8 @@ -"""Cold-path identity loader. +"""Cold-path identity loader: cache-or-one-DB-query for a hashed token. -One async function, one I/O round trip on cache miss. The actual SQL -JOIN lives in ``litellm.proxy.utils.PrismaClient.get_data`` (the -``combined_view`` query) and is reused as-is so we don't duplicate the -schema-coupled SQL. Object-permission rows that are referenced but not -joined are lazily filled exactly as the legacy ``get_key_object`` did. - -The cached payload is ``UserAPIKeyAuth`` — the proxy's existing carrier. -Callers that want an ``IdentityContext`` view should call -``uak.to_identity_context()`` at the consumption site. +The combined-view SQL is reused from ``PrismaClient.get_data`` rather than +duplicated. The cached payload is ``UserAPIKeyAuth``, the proxy's existing +carrier. """ from __future__ import annotations