From 6378349af0288a2400a06afe788ffe78865012b0 Mon Sep 17 00:00:00 2001 From: Krrish Dholakia Date: Sat, 21 Feb 2026 18:36:16 -0800 Subject: [PATCH] Revert "fix: add migration.sql for prisma" This reverts commit 2a0085b260fa7a1eca66a80f1bd5c73cb8360e9f. --- .../migration.sql | 21 ------ .../litellm_proxy_extras/schema.prisma | 65 ++++++++++++++----- litellm/proxy/schema.prisma | 50 ++++++++++++++ .../types/proxy/policy_engine/policy_types.py | 47 +++++++++++++- schema.prisma | 18 +---- 5 files changed, 147 insertions(+), 54 deletions(-) delete mode 100644 litellm-proxy-extras/litellm_proxy_extras/migrations/20260221182522_add_policy_versioning/migration.sql diff --git a/litellm-proxy-extras/litellm_proxy_extras/migrations/20260221182522_add_policy_versioning/migration.sql b/litellm-proxy-extras/litellm_proxy_extras/migrations/20260221182522_add_policy_versioning/migration.sql deleted file mode 100644 index 5fd158f2560..00000000000 --- a/litellm-proxy-extras/litellm_proxy_extras/migrations/20260221182522_add_policy_versioning/migration.sql +++ /dev/null @@ -1,21 +0,0 @@ --- DropIndex -DROP INDEX "LiteLLM_PolicyTable_policy_name_key"; - - --- AlterTable -ALTER TABLE "LiteLLM_PolicyTable" ADD COLUMN "is_latest" BOOLEAN NOT NULL DEFAULT true, -ADD COLUMN "parent_version_id" TEXT, -ADD COLUMN "production_at" TIMESTAMP(3), -ADD COLUMN "published_at" TIMESTAMP(3), -ADD COLUMN "version_number" INTEGER NOT NULL DEFAULT 1, -ADD COLUMN "version_status" TEXT NOT NULL DEFAULT 'production'; - --- CreateIndex -CREATE INDEX "LiteLLM_PolicyTable_policy_name_version_status_idx" ON "LiteLLM_PolicyTable"("policy_name", "version_status"); - --- CreateIndex -CREATE INDEX "LiteLLM_PolicyTable_version_status_idx" ON "LiteLLM_PolicyTable"("version_status"); - --- CreateIndex -CREATE UNIQUE INDEX "LiteLLM_PolicyTable_policy_name_version_number_key" ON "LiteLLM_PolicyTable"("policy_name", "version_number"); - diff --git a/litellm-proxy-extras/litellm_proxy_extras/schema.prisma b/litellm-proxy-extras/litellm_proxy_extras/schema.prisma index 7018b2709e2..45cd90f3413 100644 --- a/litellm-proxy-extras/litellm_proxy_extras/schema.prisma +++ b/litellm-proxy-extras/litellm_proxy_extras/schema.prisma @@ -213,6 +213,53 @@ model LiteLLM_DeletedTeamTable { @@index([created_at]) } +// Audit table for deleted teams - preserves spend and team information for historical tracking +model LiteLLM_DeletedTeamTable { + id String @id @default(uuid()) + team_id String // Original team_id + team_alias String? + organization_id String? + object_permission_id String? + admins String[] + members String[] + members_with_roles Json @default("{}") + metadata Json @default("{}") + max_budget Float? + soft_budget Float? + spend Float @default(0.0) + models String[] + max_parallel_requests Int? + tpm_limit BigInt? + rpm_limit BigInt? + budget_duration String? + budget_reset_at DateTime? + blocked Boolean @default(false) + model_spend Json @default("{}") + model_max_budget Json @default("{}") + router_settings Json? @default("{}") + team_member_permissions String[] @default([]) + access_group_ids String[] @default([]) + policies String[] @default([]) + model_id Int? // id for LiteLLM_ModelTable -> stores team-level model aliases + allow_team_guardrail_config Boolean @default(false) + + // Original timestamps from team creation/updates + created_at DateTime? @map("created_at") + updated_at DateTime? @map("updated_at") + + // Deletion metadata + deleted_at DateTime @default(now()) @map("deleted_at") + deleted_by String? @map("deleted_by") // User who deleted the team + deleted_by_api_key String? @map("deleted_by_api_key") // API key hash that performed the deletion + litellm_changed_by String? @map("litellm_changed_by") // From litellm-changed-by header if provided + + @@index([team_id]) + @@index([deleted_at]) + @@index([organization_id]) + @@index([team_alias]) + @@index([created_at]) +} + // Track spend, rate limit, budget Users model LiteLLM_UserTable { user_id String @id @@ -273,7 +320,6 @@ model LiteLLM_MCPServerTable { alias String? description String? url String? - spec_path String? transport String @default("sse") auth_type String? credentials Json? @default("{}") @@ -963,33 +1009,20 @@ model LiteLLM_SkillsTable { updated_by String? } -// Policy table for storing guardrail policies with versioning support +// Policy table for storing guardrail policies model LiteLLM_PolicyTable { policy_id String @id @default(uuid()) - policy_name String // Policy name (multiple versions can share same name) + policy_name String @unique inherit String? // Name of parent policy to inherit from description String? guardrails_add String[] @default([]) guardrails_remove String[] @default([]) condition Json? @default("{}") // Policy conditions (e.g., model matching) pipeline Json? // Optional guardrail pipeline (mode + steps[]) - - // Versioning fields - version_number Int @default(1) - version_status String @default("production") // "draft", "published", or "production" - parent_version_id String? // Reference to the policy version this was created from - is_latest Boolean @default(true) - published_at DateTime? // When this version was published - production_at DateTime? // When this version was promoted to production - created_at DateTime @default(now()) created_by String? updated_at DateTime @default(now()) @updatedAt updated_by String? - - @@unique([policy_name, version_number]) - @@index([policy_name, version_status]) - @@index([version_status]) } // Policy attachment table for defining where policies apply diff --git a/litellm/proxy/schema.prisma b/litellm/proxy/schema.prisma index 7018b2709e2..57f02afe4ae 100644 --- a/litellm/proxy/schema.prisma +++ b/litellm/proxy/schema.prisma @@ -987,6 +987,9 @@ model LiteLLM_PolicyTable { updated_at DateTime @default(now()) @updatedAt updated_by String? + // Relations + mirroring_configs LiteLLM_PolicyMirroringTable[] + @@unique([policy_name, version_number]) @@index([policy_name, version_status]) @@index([version_status]) @@ -1007,6 +1010,53 @@ model LiteLLM_PolicyAttachmentTable { updated_by String? } +// Policy mirroring configuration for silent/shadow testing +model LiteLLM_PolicyMirroringTable { + mirroring_id String @id @default(uuid()) + policy_id String // References LiteLLM_PolicyTable.policy_id + traffic_percentage Float @default(0.0) // 0.0-100.0 + max_requests Int? // Optional limit on total mirrored requests + current_requests Int @default(0) + enabled Boolean @default(true) + fail_silently Boolean @default(true) // Don't block requests if mirroring fails + log_results Boolean @default(true) // Store results in mirror logs + started_at DateTime @default(now()) + expires_at DateTime? // Optional expiration time for mirroring + created_at DateTime @default(now()) + created_by String? + updated_at DateTime @default(now()) @updatedAt + updated_by String? + + // Relations + policy LiteLLM_PolicyTable @relation(fields: [policy_id], references: [policy_id]) + mirror_logs LiteLLM_PolicyMirrorLogs[] + + @@index([policy_id, enabled]) + @@index([expires_at]) +} + +// Policy mirroring execution logs +model LiteLLM_PolicyMirrorLogs { + log_id String @id @default(uuid()) + mirroring_id String // References LiteLLM_PolicyMirroringTable.mirroring_id + request_id String? // Original request ID if available + executed_at DateTime @default(now()) + execution_time_ms Float? // How long the mirrored policy execution took + result String // "pass", "fail", "error" + terminal_action String? // Final action taken by policy (allow/block/modify) + step_results Json? // Detailed step-by-step results + error_message String? // Error details if result = "error" + metadata Json? @default("{}") + created_at DateTime @default(now()) + + // Relations + mirroring_config LiteLLM_PolicyMirroringTable @relation(fields: [mirroring_id], references: [mirroring_id]) + + @@index([mirroring_id, executed_at]) + @@index([result]) + @@index([executed_at]) +} + //Unified Access Groups table for storing unified access groups model LiteLLM_AccessGroupTable { access_group_id String @id @default(uuid()) diff --git a/litellm/types/proxy/policy_engine/policy_types.py b/litellm/types/proxy/policy_engine/policy_types.py index fb73106ea70..542fc1dad38 100644 --- a/litellm/types/proxy/policy_engine/policy_types.py +++ b/litellm/types/proxy/policy_engine/policy_types.py @@ -48,7 +48,7 @@ class PolicyVersionStatus(str, Enum): Status of a policy version in the version workflow. - DRAFT: Policy is being edited, not yet published - - PUBLISHED: Policy is ready for testing + - PUBLISHED: Policy is ready for testing/mirroring - PRODUCTION: Policy is active and applied to matching requests """ @@ -57,6 +57,46 @@ class PolicyVersionStatus(str, Enum): PRODUCTION = "production" +class SilentMirroringConfig(BaseModel): + """ + Configuration for silent/shadow testing of policy versions. + + Silent mirroring executes a policy version on a percentage of traffic + without blocking requests, allowing safe testing before promotion. + + Example usage: + - Test new policy on 10% of traffic + - Limit to 1000 test executions + - Log all results for analysis + - Automatically expire after testing period + """ + + traffic_percentage: float = Field( + default=0.0, + ge=0.0, + le=100.0, + description="Percentage of traffic to mirror (0.0-100.0)", + ) + max_requests: Optional[int] = Field( + default=None, + description="Maximum number of requests to mirror (optional limit)", + ) + fail_silently: bool = Field( + default=True, + description="Continue request processing if mirroring fails", + ) + log_results: bool = Field( + default=True, + description="Store execution results in mirror logs", + ) + expires_at: Optional[datetime] = Field( + default=None, + description="Optional expiration time for mirroring", + ) + + model_config = ConfigDict(extra="forbid") + + # ───────────────────────────────────────────────────────────────────────────── # Policy Condition # ───────────────────────────────────────────────────────────────────────────── @@ -208,6 +248,7 @@ class Policy(BaseModel): - Policies support version workflow: draft → published → production - Multiple versions of the same policy can coexist - Only production versions are applied to requests by default + - Published versions can be tested via silent mirroring Example configuration: ```yaml @@ -290,6 +331,10 @@ class Policy(BaseModel): default=None, description="When this version was promoted to production", ) + silent_mirroring: Optional[SilentMirroringConfig] = Field( + default=None, + description="Silent mirroring configuration (for testing)", + ) model_config = ConfigDict(extra="forbid") diff --git a/schema.prisma b/schema.prisma index 7018b2709e2..d483e92e528 100644 --- a/schema.prisma +++ b/schema.prisma @@ -273,7 +273,6 @@ model LiteLLM_MCPServerTable { alias String? description String? url String? - spec_path String? transport String @default("sse") auth_type String? credentials Json? @default("{}") @@ -963,33 +962,20 @@ model LiteLLM_SkillsTable { updated_by String? } -// Policy table for storing guardrail policies with versioning support +// Policy table for storing guardrail policies model LiteLLM_PolicyTable { policy_id String @id @default(uuid()) - policy_name String // Policy name (multiple versions can share same name) + policy_name String @unique inherit String? // Name of parent policy to inherit from description String? guardrails_add String[] @default([]) guardrails_remove String[] @default([]) condition Json? @default("{}") // Policy conditions (e.g., model matching) pipeline Json? // Optional guardrail pipeline (mode + steps[]) - - // Versioning fields - version_number Int @default(1) - version_status String @default("production") // "draft", "published", or "production" - parent_version_id String? // Reference to the policy version this was created from - is_latest Boolean @default(true) - published_at DateTime? // When this version was published - production_at DateTime? // When this version was promoted to production - created_at DateTime @default(now()) created_by String? updated_at DateTime @default(now()) @updatedAt updated_by String? - - @@unique([policy_name, version_number]) - @@index([policy_name, version_status]) - @@index([version_status]) } // Policy attachment table for defining where policies apply