codexLB-up 1.25.0b10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- app/__init__.py +10 -0
- app/admin_cli.py +494 -0
- app/cli.py +339 -0
- app/codex_sessions_retag.py +487 -0
- app/core/__init__.py +0 -0
- app/core/audit/__init__.py +0 -0
- app/core/audit/service.py +216 -0
- app/core/audit/types.py +94 -0
- app/core/auth/__init__.py +236 -0
- app/core/auth/api_key_cache.py +65 -0
- app/core/auth/dashboard_access.py +429 -0
- app/core/auth/dashboard_mode.py +171 -0
- app/core/auth/dashboard_session_ttl.py +74 -0
- app/core/auth/dashboard_users_cache.py +120 -0
- app/core/auth/dependencies.py +710 -0
- app/core/auth/external_identity.py +78 -0
- app/core/auth/guardian.py +374 -0
- app/core/auth/models.py +49 -0
- app/core/auth/providers/__init__.py +129 -0
- app/core/auth/providers/oidc.py +838 -0
- app/core/auth/providers/registry.py +118 -0
- app/core/auth/refresh.py +394 -0
- app/core/auth/step_up.py +117 -0
- app/core/auth/totp.py +81 -0
- app/core/balancer/__init__.py +71 -0
- app/core/balancer/logic.py +1612 -0
- app/core/balancer/rendezvous_hash.py +21 -0
- app/core/balancer/types.py +21 -0
- app/core/bootstrap.py +172 -0
- app/core/cache/invalidation.py +426 -0
- app/core/clients/__init__.py +0 -0
- app/core/clients/codex.py +996 -0
- app/core/clients/codex_version.py +187 -0
- app/core/clients/codex_version_snapshot.py +2 -0
- app/core/clients/files.py +534 -0
- app/core/clients/headers.py +29 -0
- app/core/clients/http.py +511 -0
- app/core/clients/model_fetcher.py +276 -0
- app/core/clients/native_egress.py +1304 -0
- app/core/clients/oauth.py +477 -0
- app/core/clients/proxy.py +6089 -0
- app/core/clients/proxy_websocket.py +1411 -0
- app/core/clients/rate_limit_reset_credits.py +412 -0
- app/core/clients/stream_errors.py +12 -0
- app/core/clients/thread_cache_identity.py +347 -0
- app/core/clients/usage.py +467 -0
- app/core/clock.py +170 -0
- app/core/config/__init__.py +0 -0
- app/core/config/background_jobs.py +73 -0
- app/core/config/context_window_overrides.py +166 -0
- app/core/config/dashboard_overrides.py +145 -0
- app/core/config/inheritable.py +47 -0
- app/core/config/key_fingerprint.py +115 -0
- app/core/config/settings.py +872 -0
- app/core/config/settings_cache.py +100 -0
- app/core/config/spool_retention.py +217 -0
- app/core/config/tiers.py +174 -0
- app/core/conversation_archive.py +568 -0
- app/core/crypto.py +37 -0
- app/core/draining.py +11 -0
- app/core/errors.py +365 -0
- app/core/exceptions.py +155 -0
- app/core/handlers/__init__.py +3 -0
- app/core/handlers/exceptions.py +478 -0
- app/core/http_protocol.py +176 -0
- app/core/http_protocol_httptools.py +204 -0
- app/core/ingress_limits.py +17 -0
- app/core/metadata_store.py +18 -0
- app/core/metrics/__init__.py +0 -0
- app/core/metrics/middleware.py +74 -0
- app/core/metrics/prometheus.py +604 -0
- app/core/middleware/__init__.py +25 -0
- app/core/middleware/api_firewall.py +111 -0
- app/core/middleware/app_version.py +37 -0
- app/core/middleware/dashboard_auth_proxy.py +55 -0
- app/core/middleware/dashboard_csrf.py +177 -0
- app/core/middleware/dashboard_gzip.py +41 -0
- app/core/middleware/dashboard_overrides.py +59 -0
- app/core/middleware/firewall_cache.py +91 -0
- app/core/middleware/inflight.py +126 -0
- app/core/middleware/multipart_content_encoding.py +129 -0
- app/core/middleware/path_rewrite.py +148 -0
- app/core/middleware/request_body_limit.py +196 -0
- app/core/middleware/request_decompression.py +209 -0
- app/core/middleware/request_id.py +72 -0
- app/core/middleware/required_capability_http.py +116 -0
- app/core/middleware/trusted_proxy_headers.py +36 -0
- app/core/multipart.py +237 -0
- app/core/multipart_fields.py +91 -0
- app/core/openai/__init__.py +0 -0
- app/core/openai/chat_requests.py +493 -0
- app/core/openai/chat_responses.py +931 -0
- app/core/openai/contracts.py +46 -0
- app/core/openai/exceptions.py +24 -0
- app/core/openai/host_models.py +14 -0
- app/core/openai/images.py +413 -0
- app/core/openai/message_coercion.py +376 -0
- app/core/openai/model_refresh_scheduler.py +423 -0
- app/core/openai/model_registry.py +997 -0
- app/core/openai/model_registry_store.py +548 -0
- app/core/openai/models.py +172 -0
- app/core/openai/parsing.py +97 -0
- app/core/openai/requests.py +1980 -0
- app/core/openai/strict_schema.py +199 -0
- app/core/openai/tool_call_safety.py +99 -0
- app/core/openai/v1_requests.py +187 -0
- app/core/plan_types.py +90 -0
- app/core/prestop.py +202 -0
- app/core/rate_limiter/__init__.py +0 -0
- app/core/rate_limiter/db_rate_limiter.py +215 -0
- app/core/request_locality.py +473 -0
- app/core/resilience/__init__.py +0 -0
- app/core/resilience/backpressure.py +57 -0
- app/core/resilience/bulkhead.py +202 -0
- app/core/resilience/circuit_breaker.py +150 -0
- app/core/resilience/degradation.py +55 -0
- app/core/resilience/loop_lag_monitor.py +60 -0
- app/core/resilience/memory_monitor.py +137 -0
- app/core/resilience/network_recovery.py +256 -0
- app/core/resilience/overload.py +98 -0
- app/core/resilience/toggles.py +114 -0
- app/core/retention/__init__.py +0 -0
- app/core/retention/job.py +240 -0
- app/core/retention/scheduler.py +69 -0
- app/core/runtime_logging.py +601 -0
- app/core/scheduling/__init__.py +0 -0
- app/core/scheduling/leader_election.py +993 -0
- app/core/scheduling/leader_election_handle.py +25 -0
- app/core/server.py +140 -0
- app/core/shutdown.py +326 -0
- app/core/socket_peer.py +22 -0
- app/core/startup.py +41 -0
- app/core/timeout_invariants.py +347 -0
- app/core/tracing/__init__.py +0 -0
- app/core/tracing/otel.py +207 -0
- app/core/types.py +6 -0
- app/core/upstream_proxy/__init__.py +13 -0
- app/core/upstream_proxy/cache.py +130 -0
- app/core/upstream_proxy/resolver.py +189 -0
- app/core/upstream_proxy/types.py +104 -0
- app/core/usage/__init__.py +407 -0
- app/core/usage/depletion.py +109 -0
- app/core/usage/live_hub.py +41 -0
- app/core/usage/live_snapshots.py +174 -0
- app/core/usage/logs.py +212 -0
- app/core/usage/metadata_scheduler.py +118 -0
- app/core/usage/models.py +54 -0
- app/core/usage/pricing.py +576 -0
- app/core/usage/pricing_catalog.py +241 -0
- app/core/usage/pricing_snapshot.json +821 -0
- app/core/usage/quota.py +133 -0
- app/core/usage/refresh_policy.py +21 -0
- app/core/usage/refresh_scheduler.py +713 -0
- app/core/usage/reset_credits_refresh_scheduler.py +435 -0
- app/core/usage/types.py +168 -0
- app/core/utils/__init__.py +0 -0
- app/core/utils/json_guards.py +18 -0
- app/core/utils/locks.py +33 -0
- app/core/utils/masking.py +20 -0
- app/core/utils/proxy_env.py +104 -0
- app/core/utils/request_id.py +65 -0
- app/core/utils/retry.py +77 -0
- app/core/utils/shared_future.py +172 -0
- app/core/utils/sse.py +286 -0
- app/core/utils/time.py +24 -0
- app/db/__init__.py +0 -0
- app/db/account_identity_lock.py +56 -0
- app/db/alembic/__init__.py +1 -0
- app/db/alembic/env.py +70 -0
- app/db/alembic/revision_ids.py +43 -0
- app/db/alembic/versions/20260213_000000_base_schema.py +248 -0
- app/db/alembic/versions/20260213_000100_normalize_account_plan_types.py +45 -0
- app/db/alembic/versions/20260213_000200_add_request_logs_reasoning_effort.py +45 -0
- app/db/alembic/versions/20260213_000300_add_accounts_reset_at.py +45 -0
- app/db/alembic/versions/20260213_000400_add_accounts_chatgpt_account_id.py +45 -0
- app/db/alembic/versions/20260213_000500_add_dashboard_settings.py +70 -0
- app/db/alembic/versions/20260213_000600_add_dashboard_settings_totp.py +64 -0
- app/db/alembic/versions/20260213_000700_add_dashboard_settings_password.py +59 -0
- app/db/alembic/versions/20260213_000800_add_api_keys.py +87 -0
- app/db/alembic/versions/20260214_000000_add_api_key_limits.py +143 -0
- app/db/alembic/versions/20260215_000000_add_idx_logs_requested_at.py +38 -0
- app/db/alembic/versions/20260218_000000_add_api_key_usage_reservations.py +117 -0
- app/db/alembic/versions/20260218_000100_add_import_without_overwrite_and_drop_accounts_email_unique.py +198 -0
- app/db/alembic/versions/20260225_000000_add_dashboard_settings_routing_strategy.py +53 -0
- app/db/alembic/versions/20260228_020000_align_api_key_limit_enum_types.py +104 -0
- app/db/alembic/versions/20260228_030000_add_api_firewall_allowlist.py +42 -0
- app/db/alembic/versions/20260306_000000_add_request_logs_service_tier.py +45 -0
- app/db/alembic/versions/20260307_000000_add_api_key_enforcement_fields.py +56 -0
- app/db/alembic/versions/20260308_000000_add_sqlite_performance_indexes.py +41 -0
- app/db/alembic/versions/20260309_000000_add_additional_usage_history.py +71 -0
- app/db/alembic/versions/20260309_000000_request_logs_nullable_account_id.py +28 -0
- app/db/alembic/versions/20260310_000000_add_request_logs_transport.py +45 -0
- app/db/alembic/versions/20260310_000000_fix_postgresql_enum_value_casing.py +79 -0
- app/db/alembic/versions/20260310_120000_add_sticky_session_kinds_and_affinity_ttl.py +110 -0
- app/db/alembic/versions/20260312_000000_add_additional_usage_quota_key.py +193 -0
- app/db/alembic/versions/20260312_000000_split_sticky_sessions_primary_key_by_kind.py +96 -0
- app/db/alembic/versions/20260312_010000_merge_additional_usage_and_sticky_session_heads.py +25 -0
- app/db/alembic/versions/20260312_020000_merge_request_logs_transport_and_feature_heads.py +25 -0
- app/db/alembic/versions/20260312_020000_merge_request_logs_transport_and_sticky_heads.py +25 -0
- app/db/alembic/versions/20260312_120000_add_dashboard_upstream_stream_transport.py +62 -0
- app/db/alembic/versions/20260313_024500_merge_request_log_transport_heads.py +27 -0
- app/db/alembic/versions/20260319_100937_increase_prompt_cache_ttl_to_1800s.py +73 -0
- app/db/alembic/versions/20260319_111500_merge_prompt_cache_ttl_and_upstream_transport_heads.py +25 -0
- app/db/alembic/versions/20260319_183000_normalize_sqlite_account_status_casing.py +48 -0
- app/db/alembic/versions/20260320_000000_add_request_log_requested_actual_tiers.py +51 -0
- app/db/alembic/versions/20260321_190000_tighten_dashboard_db_indexes.py +64 -0
- app/db/alembic/versions/20260321_210000_merge_request_log_tiers_and_dashboard_index_heads.py +25 -0
- app/db/alembic/versions/20260325_000000_add_request_log_cost.py +193 -0
- app/db/alembic/versions/20260328_000000_add_rate_limit_attempts.py +48 -0
- app/db/alembic/versions/20260328_120000_add_request_log_ttft.py +37 -0
- app/db/alembic/versions/20260328_130000_add_audit_logs_table.py +45 -0
- app/db/alembic/versions/20260328_140000_add_scheduler_leader_table.py +39 -0
- app/db/alembic/versions/20260330_000000_add_cache_locality_settings.py +69 -0
- app/db/alembic/versions/20260330_010000_merge_scheduler_leader_and_cache_locality_heads.py +25 -0
- app/db/alembic/versions/20260330_020000_add_bridge_ring_members.py +46 -0
- app/db/alembic/versions/20260401_000000_add_api_key_enforced_service_tier.py +52 -0
- app/db/alembic/versions/20260401_000000_add_cache_invalidation.py +41 -0
- app/db/alembic/versions/20260401_020000_merge_cache_invalidation_and_api_key_service_tier_heads.py +22 -0
- app/db/alembic/versions/20260402_000000_switch_dashboard_routing_default_to_capacity_weighted.py +66 -0
- app/db/alembic/versions/20260403_000000_add_credit_api_key_limit_values.py +44 -0
- app/db/alembic/versions/20260406_000000_add_api_key_account_assignments.py +57 -0
- app/db/alembic/versions/20260406_010000_add_api_key_assignment_scope_flag.py +75 -0
- app/db/alembic/versions/20260407_000000_add_bridge_gateway_safe_mode.py +51 -0
- app/db/alembic/versions/20260407_010000_merge_api_key_assignment_and_bridge_gateway_heads.py +25 -0
- app/db/alembic/versions/20260408_000000_switch_import_without_overwrite_default_to_true.py +73 -0
- app/db/alembic/versions/20260408_010000_merge_import_without_overwrite_and_assignment_heads.py +25 -0
- app/db/alembic/versions/20260409_000000_add_http_bridge_sessions.py +130 -0
- app/db/alembic/versions/20260409_000000_switch_sticky_threads_and_prefer_earlier_reset_defaults_to_true.py +89 -0
- app/db/alembic/versions/20260409_010000_add_dashboard_settings_bootstrap_token.py +57 -0
- app/db/alembic/versions/20260409_010000_merge_http_bridge_and_import_without_overwrite_heads.py +25 -0
- app/db/alembic/versions/20260409_020000_fix_http_bridge_last_seen_index.py +46 -0
- app/db/alembic/versions/20260410_000000_backfill_pristine_dashboard_settings_defaults.py +77 -0
- app/db/alembic/versions/20260410_030000_restore_import_without_overwrite_default_true.py +73 -0
- app/db/alembic/versions/20260410_040000_merge_dashboard_defaults_and_import_default_heads.py +25 -0
- app/db/alembic/versions/20260413_000000_add_accounts_blocked_at.py +44 -0
- app/db/alembic/versions/20260415_160000_add_automations_tables.py +189 -0
- app/db/alembic/versions/20260415_160000_add_request_logs_response_lookup_index.py +67 -0
- app/db/alembic/versions/20260417_000000_add_request_log_plan_type.py +44 -0
- app/db/alembic/versions/20260418_190000_add_automation_runs_cycle_key.py +87 -0
- app/db/alembic/versions/20260419_000000_add_automation_run_cycle_metadata.py +56 -0
- app/db/alembic/versions/20260419_020000_add_automation_run_cycles_snapshot_tables.py +342 -0
- app/db/alembic/versions/20260421_000000_add_dashboard_session_ttl_setting.py +51 -0
- app/db/alembic/versions/20260421_120000_merge_request_log_lookup_and_plan_type_heads.py +25 -0
- app/db/alembic/versions/20260421_130000_merge_automation_and_request_log_heads.py +25 -0
- app/db/alembic/versions/20260422_103000_normalize_legacy_automation_run_cycle_keys.py +648 -0
- app/db/alembic/versions/20260423_120000_add_api_key_limit_reset_at_index.py +43 -0
- app/db/alembic/versions/20260424_000000_merge_dashboard_session_ttl_and_request_log_heads.py +25 -0
- app/db/alembic/versions/20260426_000000_add_dashboard_relative_availability_settings.py +68 -0
- app/db/alembic/versions/20260427_130000_add_warmup_model_and_request_kind.py +75 -0
- app/db/alembic/versions/20260506_000000_add_account_routing_policy.py +37 -0
- app/db/alembic/versions/20260509_000000_add_api_key_traffic_class.py +37 -0
- app/db/alembic/versions/20260509_010000_add_additional_quota_routing_policies.py +37 -0
- app/db/alembic/versions/20260513_000000_add_accounts_alias.py +44 -0
- app/db/alembic/versions/20260513_000000_add_api_key_apply_to_codex_model.py +59 -0
- app/db/alembic/versions/20260514_000000_add_request_logs_api_key_time_index.py +43 -0
- app/db/alembic/versions/20260515_000000_add_prefer_earlier_reset_window.py +47 -0
- app/db/alembic/versions/20260515_000000_soft_delete_request_logs_on_account_delete.py +83 -0
- app/db/alembic/versions/20260515_020000_add_split_sticky_budget_thresholds.py +62 -0
- app/db/alembic/versions/20260516_000000_add_sqlite_hot_path_indexes.py +75 -0
- app/db/alembic/versions/20260517_000000_merge_sqlite_hot_path_and_request_log_delete_heads.py +24 -0
- app/db/alembic/versions/20260518_000000_add_http_bridge_durable_input_prefix.py +44 -0
- app/db/alembic/versions/20260518_010000_merge_http_bridge_and_sqlite_recovery_heads.py +25 -0
- app/db/alembic/versions/20260518_120000_add_dashboard_guest_access.py +57 -0
- app/db/alembic/versions/20260520_000000_merge_api_key_and_http_bridge_heads.py +26 -0
- app/db/alembic/versions/20260520_010000_add_request_logs_api_key_account_index.py +45 -0
- app/db/alembic/versions/20260520_010000_merge_automation_and_api_key_heads.py +26 -0
- app/db/alembic/versions/20260520_030000_add_quota_planner.py +194 -0
- app/db/alembic/versions/20260520_040000_merge_quota_planner_and_request_log_index_heads.py +24 -0
- app/db/alembic/versions/20260521_000000_add_account_security_work_authorized.py +46 -0
- app/db/alembic/versions/20260521_000000_merge_dashboard_guest_and_api_key_heads.py +26 -0
- app/db/alembic/versions/20260521_000000_merge_prefer_reset_window_head.py +26 -0
- app/db/alembic/versions/20260521_000000_merge_warmup_and_request_log_index_heads.py +25 -0
- app/db/alembic/versions/20260522_000000_add_limit_warmup_trigger.py +195 -0
- app/db/alembic/versions/20260524_000000_merge_accounts_alias_and_reset_window_heads.py +24 -0
- app/db/alembic/versions/20260525_000000_add_usage_raw_window_latest_index.py +31 -0
- app/db/alembic/versions/20260526_000000_add_request_log_failure_metadata.py +100 -0
- app/db/alembic/versions/20260531_000000_add_account_workspace_identity.py +39 -0
- app/db/alembic/versions/20260531_000000_add_single_account_routing.py +42 -0
- app/db/alembic/versions/20260601_000000_merge_relative_availability_and_usage_raw_heads.py +24 -0
- app/db/alembic/versions/20260601_010000_add_api_key_usage_sections.py +58 -0
- app/db/alembic/versions/20260601_010000_add_routing_policy_persistence.py +67 -0
- app/db/alembic/versions/20260601_010000_merge_security_work_and_relative_availability_heads.py +25 -0
- app/db/alembic/versions/20260601_010000_merge_split_sticky_and_relative_usage_heads.py +25 -0
- app/db/alembic/versions/20260601_010000_merge_warmup_and_relative_availability_heads.py +25 -0
- app/db/alembic/versions/20260601_020000_merge_additional_quota_routing_and_relative_availability_heads.py +25 -0
- app/db/alembic/versions/20260601_020000_merge_quota_planner_and_relative_availability_heads.py +25 -0
- app/db/alembic/versions/20260601_020000_merge_reset_window_and_relative_availability_heads.py +25 -0
- app/db/alembic/versions/20260601_020000_merge_routing_policy_and_split_threshold_heads.py +24 -0
- app/db/alembic/versions/20260601_020000_merge_warmup_and_request_log_failure_heads.py +25 -0
- app/db/alembic/versions/20260601_030000_merge_single_account_and_routing_quota_heads.py +29 -0
- app/db/alembic/versions/20260601_040000_merge_security_work_and_routing_consolidation_heads.py +25 -0
- app/db/alembic/versions/20260601_050000_merge_quota_planner_and_routing_consolidation_heads.py +25 -0
- app/db/alembic/versions/20260602_050000_add_upstream_proxy_routing.py +164 -0
- app/db/alembic/versions/20260602_060000_merge_account_workspace_and_failure_heads.py +25 -0
- app/db/alembic/versions/20260602_070000_add_request_log_useragent_fields.py +86 -0
- app/db/alembic/versions/20260602_070000_merge_quota_planner_and_account_workspace_heads.py +25 -0
- app/db/alembic/versions/20260602_080000_merge_upstream_proxy_and_quota_planner_heads.py +25 -0
- app/db/alembic/versions/20260602_080000_merge_useragent_and_upstream_proxy_heads.py +24 -0
- app/db/alembic/versions/20260603_000000_add_weekly_pace_working_days.py +52 -0
- app/db/alembic/versions/20260603_000000_free_account_monthly_window.py +60 -0
- app/db/alembic/versions/20260604_000000_add_reauth_required_account_status.py +159 -0
- app/db/alembic/versions/20260604_010000_merge_automations_and_reauth_status_heads.py +25 -0
- app/db/alembic/versions/20260604_010000_merge_dashboard_guest_and_reauth_status_heads.py +25 -0
- app/db/alembic/versions/20260604_010000_merge_useragent_and_reauth_heads.py +24 -0
- app/db/alembic/versions/20260607_000000_merge_weekly_monthly_useragent_heads.py +28 -0
- app/db/alembic/versions/20260608_000000_add_hide_upstream_quota_from_api_keys.py +50 -0
- app/db/alembic/versions/20260611_000000_add_request_log_archive_request_id.py +47 -0
- app/db/alembic/versions/20260611_000000_merge_automations_and_weekly_monthly_useragent_heads.py +26 -0
- app/db/alembic/versions/20260611_000000_merge_dashboard_guest_and_weekly_useragent_heads.py +26 -0
- app/db/alembic/versions/20260611_010000_add_request_log_client_ip.py +57 -0
- app/db/alembic/versions/20260611_020000_merge_request_log_archive_and_client_ip_heads.py +26 -0
- app/db/alembic/versions/20260611_030000_merge_dashboard_guest_and_request_log_client_ip_heads.py +26 -0
- app/db/alembic/versions/20260613_000000_add_accounts_codex_installation_id.py +57 -0
- app/db/alembic/versions/20260613_010000_merge_installation_id_and_dashboard_weekly_heads.py +26 -0
- app/db/alembic/versions/20260615_000000_merge_automations_and_dashboard_guest_heads.py +26 -0
- app/db/alembic/versions/20260623_000000_add_limit_warmup_exhausted_threshold.py +51 -0
- app/db/alembic/versions/20260626_000000_add_http_downstream_transport_policy.py +46 -0
- app/db/alembic/versions/20260626_010000_add_request_logs_upstream_transport.py +31 -0
- app/db/alembic/versions/20260629_000000_add_dashboard_query_hot_path_indexes.py +53 -0
- app/db/alembic/versions/20260630_000000_add_limit_warmup_staggered_idle.py +47 -0
- app/db/alembic/versions/20260630_000000_merge_request_log_client_ip_and_dashboard_hot_path_heads.py +26 -0
- app/db/alembic/versions/20260630_010000_merge_warmup_and_request_log_dashboard_heads.py +26 -0
- app/db/alembic/versions/20260630_020000_merge_automations_and_main_heads.py +26 -0
- app/db/alembic/versions/20260630_020000_merge_warmup_threshold_and_main_heads.py +26 -0
- app/db/alembic/versions/20260630_030000_add_automation_run_model_snapshot.py +59 -0
- app/db/alembic/versions/20260630_040000_merge_automation_snapshot_and_warmup_threshold_heads.py +26 -0
- app/db/alembic/versions/20260630_050000_add_automation_run_prompt_snapshot.py +52 -0
- app/db/alembic/versions/20260701_000000_add_weekly_pace_smoothing_minutes.py +51 -0
- app/db/alembic/versions/20260702_000000_add_model_sources.py +176 -0
- app/db/alembic/versions/20260705_000000_add_model_source_audio_transcriptions.py +50 -0
- app/db/alembic/versions/20260705_000000_harden_dashboard_session_ttl.py +62 -0
- app/db/alembic/versions/20260706_000000_add_model_source_audio_per_minute.py +43 -0
- app/db/alembic/versions/20260707_000000_merge_model_sources_and_session_ttl.py +24 -0
- app/db/alembic/versions/20260707_010000_merge_automations_and_model_sources_heads.py +24 -0
- app/db/alembic/versions/20260707_020000_add_automation_job_account_scope.py +125 -0
- app/db/alembic/versions/20260709_000000_add_ttft_phase_observability.py +66 -0
- app/db/alembic/versions/20260711_000000_add_dashboard_prohibit_fast_mode.py +42 -0
- app/db/alembic/versions/20260711_010000_add_account_chatgpt_user_id.py +40 -0
- app/db/alembic/versions/20260711_020000_add_dashboard_account_concurrency_caps.py +71 -0
- app/db/alembic/versions/20260711_030000_add_limit_warmup_idle_threshold.py +51 -0
- app/db/alembic/versions/20260712_010000_add_account_usage_rollups.py +56 -0
- app/db/alembic/versions/20260712_020000_add_api_key_usage_rollups.py +53 -0
- app/db/alembic/versions/20260713_020000_add_model_registry_snapshot.py +42 -0
- app/db/alembic/versions/20260713_040000_add_account_refresh_claims.py +42 -0
- app/db/alembic/versions/20260713_040000_add_replica_guardrails.py +64 -0
- app/db/alembic/versions/20260713_070000_add_reset_credit_redeem_tables.py +58 -0
- app/db/alembic/versions/20260714_000000_add_oauth_flow_states.py +63 -0
- app/db/alembic/versions/20260715_000000_add_request_log_queue_latency.py +44 -0
- app/db/alembic/versions/20260716_000000_add_oauth_device_flow_slots.py +41 -0
- app/db/alembic/versions/20260716_010000_add_dashboard_retention_settings.py +48 -0
- app/db/alembic/versions/20260716_010000_add_reset_credit_display_settings.py +73 -0
- app/db/alembic/versions/20260717_000000_add_http_bridge_retry_circuits.py +47 -0
- app/db/alembic/versions/20260717_000000_merge_retention_and_reset_credit_display_heads.py +26 -0
- app/db/alembic/versions/20260717_000000_optimize_dashboard_hot_path_indexes.py +162 -0
- app/db/alembic/versions/20260717_000001_merge_retry_circuits_and_dashboard_indexes.py +22 -0
- app/db/alembic/versions/20260720_000000_add_request_log_conversation_id.py +57 -0
- app/db/alembic/versions/20260722_000000_backfill_request_log_useragent_families.py +40 -0
- app/db/alembic/versions/20260724_000000_add_request_usage_time_rollups.py +176 -0
- app/db/alembic/versions/20260724_000000_merge_request_log_schema_heads.py +33 -0
- app/db/alembic/versions/20260725_000000_add_http_bridge_pending_tool_calls.py +43 -0
- app/db/alembic/versions/20260726_000000_add_account_plan_downgrade_observations.py +44 -0
- app/db/alembic/versions/20260726_000000_repair_request_usage_rollups_after_merge.py +37 -0
- app/db/alembic/versions/20260727_000000_add_sticky_session_continuity_abandoned_at.py +45 -0
- app/db/alembic/versions/20260728_000000_merge_pending_tool_calls_and_rollup_repair_heads.py +31 -0
- app/db/alembic/versions/20260730_000000_add_api_key_fair_share_threshold.py +44 -0
- app/db/alembic/versions/20260730_000000_add_http_bridge_recovery_attempts.py +60 -0
- app/db/alembic/versions/20260731_000000_add_capability_lineage_markers.py +38 -0
- app/db/alembic/versions/20260803_000000_merge_http_bridge_recovery_and_capability_lineage_heads.py +30 -0
- app/db/alembic/versions/20260804_000000_add_http_bridge_operations.py +63 -0
- app/db/alembic/versions/20260804_000001_add_global_http_bridge_operation_fingerprint.py +53 -0
- app/db/alembic/versions/20260804_230000_add_request_log_connection_request_kind.py +43 -0
- app/db/alembic/versions/20260805_000000_add_http_bridge_operation_spool.py +75 -0
- app/db/alembic/versions/20260805_000001_finalize_http_bridge_operation_spool.py +65 -0
- app/db/alembic/versions/20260806_000000_add_additional_usage_alias_probe_indexes.py +84 -0
- app/db/alembic/versions/20260806_000000_add_anonymous_telemetry.py +49 -0
- app/db/alembic/versions/20260806_010000_add_conversation_presence_rollup.py +72 -0
- app/db/alembic/versions/20260806_020000_add_usage_history_bulk_covering_indexes.py +99 -0
- app/db/alembic/versions/20260806_030000_add_api_key_allowed_reasoning_efforts.py +65 -0
- app/db/alembic/versions/20260806_120000_add_http_bridge_owner_process_epoch.py +57 -0
- app/db/alembic/versions/20260807_000000_merge_http_bridge_operation_spool_and_latest_main.py +24 -0
- app/db/alembic/versions/20260808_000000_tune_usage_history_autovacuum.py +54 -0
- app/db/alembic/versions/20260810_000000_add_http_bridge_recovery_dispatch_count.py +44 -0
- app/db/alembic/versions/20260811_000000_add_hourly_rollup_cancelled_count.py +92 -0
- app/db/alembic/versions/20260812_000000_merge_recovery_dispatch_and_hourly_cancelled_heads.py +25 -0
- app/db/alembic/versions/20260812_120000_add_sticky_abandonment_scope.py +43 -0
- app/db/alembic/versions/20260813_000000_add_file_account_pins.py +40 -0
- app/db/alembic/versions/20260816_000000_add_account_pending_deletion.py +81 -0
- app/db/alembic/versions/20260816_000000_add_model_source_embeddings.py +50 -0
- app/db/alembic/versions/20260821_000000_add_retry_circuit_admission_generation.py +49 -0
- app/db/alembic/versions/20260826_000000_add_http_bridge_event_chunks.py +107 -0
- app/db/alembic/versions/20260828_000000_add_accounts_chatgpt_identity_index.py +55 -0
- app/db/alembic/versions/20260830_000000_add_quota_warmup_claim_expiry.py +83 -0
- app/db/alembic/versions/20260908_000000_add_guest_session_generation.py +37 -0
- app/db/alembic/versions/20260908_000000_add_subscription_overflow.py +140 -0
- app/db/alembic/versions/20260908_000000_replace_upstream_stream_transport_default_sentinel.py +50 -0
- app/db/alembic/versions/20260908_020000_merge_overflow_transport_heads.py +27 -0
- app/db/alembic/versions/20260909_000000_add_dashboard_roles.py +72 -0
- app/db/alembic/versions/20260909_010000_add_dashboard_users.py +183 -0
- app/db/alembic/versions/20260909_020000_reproject_compat_admin_credentials.py +105 -0
- app/db/alembic/versions/20260909_030000_add_audit_actor_columns.py +103 -0
- app/db/alembic/versions/20260909_030000_dashboard_resilience_toggle_settings.py +63 -0
- app/db/alembic/versions/20260909_040000_add_dashboard_user_invites.py +54 -0
- app/db/alembic/versions/20260909_040000_dashboard_timeout_settings.py +68 -0
- app/db/alembic/versions/20260909_050000_dashboard_routing_overload_settings.py +65 -0
- app/db/alembic/versions/20260909_060000_add_report_rollup.py +74 -0
- app/db/alembic/versions/20260909_070000_automation_run_claim_budget.py +50 -0
- app/db/alembic/versions/20260909_080000_dashboard_stream_bridge_budgets.py +62 -0
- app/db/alembic/versions/20260909_090000_dashboard_background_job_toggles.py +63 -0
- app/db/alembic/versions/20260909_100000_dashboard_codex_prewarm.py +49 -0
- app/db/alembic/versions/20260909_110000_model_context_window_overrides.py +45 -0
- app/db/alembic/versions/20260909_120000_dashboard_conversation_archive.py +48 -0
- app/db/alembic/versions/20260909_130000_add_request_logs_live_facet_indexes.py +96 -0
- app/db/alembic/versions/20260910_000000_add_totp_required_for_admin_role.py +44 -0
- app/db/alembic/versions/20260910_000000_request_logs_missing_cost_index.py +52 -0
- app/db/alembic/versions/20260910_010000_add_dashboard_auth_providers.py +134 -0
- app/db/alembic/versions/20260910_010000_dashboard_spool_retention.py +52 -0
- app/db/alembic/versions/20260910_020000_add_dashboard_role_mappings.py +74 -0
- app/db/alembic/versions/20260910_143000_request_log_affinity.py +28 -0
- app/db/alembic/versions/20260910_180000_merge_affinity_guest_heads.py +17 -0
- app/db/alembic/versions/20260910_200000_merge_affinity_identity_heads.py +17 -0
- app/db/alembic/versions/20260910_220000_merge_affinity_invite_heads.py +17 -0
- app/db/alembic/versions/20260911_000000_model_source_pins_kind_expires_index.py +43 -0
- app/db/alembic/versions/20260911_010000_merge_pin_index_and_affinity_heads.py +17 -0
- app/db/alembic/versions/20260911_020000_add_http_bridge_terminal_append_phase.py +54 -0
- app/db/alembic/versions/20260911_030000_add_local_login_policy.py +48 -0
- app/db/alembic/versions/20260911_040000_add_thread_cache_identity_mode.py +48 -0
- app/db/alembic/versions/20260911_060000_add_bridge_session_continuity_abandonment.py +40 -0
- app/db/alembic/versions/20260912_000000_merge_thread_cache_and_bridge_retirement_heads.py +22 -0
- app/db/alembic/versions/20260912_010000_drop_legacy_dashboard_credentials.py +140 -0
- app/db/alembic/versions/20260913_000000_add_oidc_provider_flow.py +134 -0
- app/db/alembic/versions/20260914_000000_add_scim_tokens.py +78 -0
- app/db/alembic/versions/20260914_000000_drop_subscription_overflow_schema.py +132 -0
- app/db/alembic/versions/20260918_000000_merge_scim_and_overflow_heads.py +17 -0
- app/db/alembic/versions/__init__.py +1 -0
- app/db/backup.py +64 -0
- app/db/migrate.py +1249 -0
- app/db/migration_lock.py +160 -0
- app/db/migration_url.py +18 -0
- app/db/models.py +3100 -0
- app/db/recover.py +244 -0
- app/db/session.py +1295 -0
- app/db/snapshot.py +46 -0
- app/db/sqlite_lock_retry.py +190 -0
- app/db/sqlite_utils.py +549 -0
- app/dependencies.py +462 -0
- app/main.py +1240 -0
- app/modules/__init__.py +0 -0
- app/modules/accounts/__init__.py +0 -0
- app/modules/accounts/api.py +426 -0
- app/modules/accounts/auth_manager.py +1439 -0
- app/modules/accounts/background_repository.py +160 -0
- app/modules/accounts/deletion.py +540 -0
- app/modules/accounts/mappers.py +654 -0
- app/modules/accounts/refresh_claims.py +352 -0
- app/modules/accounts/repository.py +1679 -0
- app/modules/accounts/schemas.py +308 -0
- app/modules/accounts/service.py +809 -0
- app/modules/accounts/usage_rollup.py +486 -0
- app/modules/accounts/usage_rollup_scheduler.py +75 -0
- app/modules/accounts/usage_time_rollup.py +1037 -0
- app/modules/accounts/usage_time_rollup_read.py +522 -0
- app/modules/api_keys/__init__.py +1 -0
- app/modules/api_keys/api.py +344 -0
- app/modules/api_keys/last_used_coalescer.py +216 -0
- app/modules/api_keys/limit_windows.py +41 -0
- app/modules/api_keys/repository.py +1200 -0
- app/modules/api_keys/reset_scheduler.py +85 -0
- app/modules/api_keys/schemas.py +135 -0
- app/modules/api_keys/service.py +2123 -0
- app/modules/audit/__init__.py +0 -0
- app/modules/audit/api.py +88 -0
- app/modules/audit/repository.py +74 -0
- app/modules/audit/schemas.py +33 -0
- app/modules/audit/service.py +71 -0
- app/modules/auth_providers/__init__.py +0 -0
- app/modules/auth_providers/api.py +127 -0
- app/modules/auth_providers/config.py +343 -0
- app/modules/auth_providers/repository.py +101 -0
- app/modules/auth_providers/schemas.py +88 -0
- app/modules/auth_providers/seed.py +105 -0
- app/modules/auth_providers/service.py +289 -0
- app/modules/automations/__init__.py +1 -0
- app/modules/automations/api.py +369 -0
- app/modules/automations/repository.py +1896 -0
- app/modules/automations/scheduler.py +107 -0
- app/modules/automations/schemas.py +158 -0
- app/modules/automations/service.py +2548 -0
- app/modules/cache_isolation_probe/__init__.py +0 -0
- app/modules/cache_isolation_probe/api.py +188 -0
- app/modules/cache_isolation_probe/prefix.py +144 -0
- app/modules/cache_isolation_probe/schemas.py +94 -0
- app/modules/cache_isolation_probe/sender.py +229 -0
- app/modules/cache_isolation_probe/service.py +525 -0
- app/modules/conversation_archive/__init__.py +1 -0
- app/modules/conversation_archive/api.py +101 -0
- app/modules/conversation_archive/schemas.py +28 -0
- app/modules/conversation_archive/service.py +165 -0
- app/modules/dashboard/__init__.py +1 -0
- app/modules/dashboard/api.py +106 -0
- app/modules/dashboard/builders.py +107 -0
- app/modules/dashboard/repository.py +304 -0
- app/modules/dashboard/schemas.py +148 -0
- app/modules/dashboard/service.py +534 -0
- app/modules/dashboard/timeframes.py +19 -0
- app/modules/dashboard/weekly_pace.py +617 -0
- app/modules/dashboard_auth/__init__.py +1 -0
- app/modules/dashboard_auth/api.py +1344 -0
- app/modules/dashboard_auth/oidc_api.py +753 -0
- app/modules/dashboard_auth/oidc_flows.py +330 -0
- app/modules/dashboard_auth/repository.py +452 -0
- app/modules/dashboard_auth/schemas.py +232 -0
- app/modules/dashboard_auth/service.py +1384 -0
- app/modules/dashboard_roles/__init__.py +0 -0
- app/modules/dashboard_roles/api.py +64 -0
- app/modules/dashboard_roles/repository.py +54 -0
- app/modules/dashboard_roles/schemas.py +29 -0
- app/modules/dashboard_roles/seed.py +80 -0
- app/modules/dashboard_roles/service.py +142 -0
- app/modules/dashboard_users/__init__.py +0 -0
- app/modules/dashboard_users/api.py +278 -0
- app/modules/dashboard_users/break_glass.py +169 -0
- app/modules/dashboard_users/credentials.py +18 -0
- app/modules/dashboard_users/identity_resolver.py +665 -0
- app/modules/dashboard_users/repository.py +725 -0
- app/modules/dashboard_users/schemas.py +117 -0
- app/modules/dashboard_users/service.py +1054 -0
- app/modules/firewall/__init__.py +1 -0
- app/modules/firewall/api.py +78 -0
- app/modules/firewall/repository.py +51 -0
- app/modules/firewall/schemas.py +28 -0
- app/modules/firewall/service.py +93 -0
- app/modules/fleet/__init__.py +1 -0
- app/modules/fleet/api.py +177 -0
- app/modules/fleet/mappers.py +56 -0
- app/modules/fleet/observability.py +372 -0
- app/modules/fleet/schemas.py +119 -0
- app/modules/health/__init__.py +0 -0
- app/modules/health/api.py +246 -0
- app/modules/health/schemas.py +27 -0
- app/modules/limit_warmup/__init__.py +1 -0
- app/modules/limit_warmup/repository.py +159 -0
- app/modules/limit_warmup/service.py +1001 -0
- app/modules/model_sources/__init__.py +1 -0
- app/modules/model_sources/api.py +99 -0
- app/modules/model_sources/catalog.py +307 -0
- app/modules/model_sources/forwarding.py +1435 -0
- app/modules/model_sources/projection.py +55 -0
- app/modules/model_sources/repository.py +201 -0
- app/modules/model_sources/schemas.py +79 -0
- app/modules/model_sources/selection.py +166 -0
- app/modules/model_sources/service.py +236 -0
- app/modules/oauth/__init__.py +0 -0
- app/modules/oauth/api.py +101 -0
- app/modules/oauth/repository.py +238 -0
- app/modules/oauth/schemas.py +49 -0
- app/modules/oauth/service.py +1196 -0
- app/modules/oauth/templates/oauth_success.html +122 -0
- app/modules/proxy/__init__.py +0 -0
- app/modules/proxy/_load_balancer/__init__.py +1 -0
- app/modules/proxy/_load_balancer/error_rate.py +116 -0
- app/modules/proxy/_load_balancer/latency_cohort.py +154 -0
- app/modules/proxy/_load_balancer/model_eligibility.py +250 -0
- app/modules/proxy/_load_balancer/opportunistic_admission.py +350 -0
- app/modules/proxy/_load_balancer/overload_backoff.py +394 -0
- app/modules/proxy/_load_balancer/sticky_selection.py +2417 -0
- app/modules/proxy/_load_balancer/throughput_cohort.py +233 -0
- app/modules/proxy/_load_balancer/ttft_cohort.py +214 -0
- app/modules/proxy/_load_balancer/tunables.py +97 -0
- app/modules/proxy/_load_balancer/types.py +96 -0
- app/modules/proxy/_load_balancer/unbound_selection.py +534 -0
- app/modules/proxy/_service/__init__.py +6 -0
- app/modules/proxy/_service/api_key_usage.py +745 -0
- app/modules/proxy/_service/clock_budget.py +38 -0
- app/modules/proxy/_service/codex_control.py +611 -0
- app/modules/proxy/_service/compact.py +2211 -0
- app/modules/proxy/_service/file_ops.py +749 -0
- app/modules/proxy/_service/http_bridge/__init__.py +3 -0
- app/modules/proxy/_service/http_bridge/accepted_replay.py +331 -0
- app/modules/proxy/_service/http_bridge/account_sessions.py +57 -0
- app/modules/proxy/_service/http_bridge/activity.py +178 -0
- app/modules/proxy/_service/http_bridge/helpers.py +3959 -0
- app/modules/proxy/_service/http_bridge/mixin.py +2435 -0
- app/modules/proxy/_service/http_bridge/owner_forwarding.py +609 -0
- app/modules/proxy/_service/http_bridge/protocol.py +167 -0
- app/modules/proxy/_service/http_bridge/proxy_failover.py +58 -0
- app/modules/proxy/_service/http_bridge/quarantine.py +443 -0
- app/modules/proxy/_service/http_bridge/request_submit.py +4582 -0
- app/modules/proxy/_service/http_bridge/retry_circuit.py +2442 -0
- app/modules/proxy/_service/http_bridge/service_stubs.py +492 -0
- app/modules/proxy/_service/http_bridge/session_registry.py +778 -0
- app/modules/proxy/_service/http_bridge/streaming.py +5328 -0
- app/modules/proxy/_service/http_bridge/upstream_events.py +4538 -0
- app/modules/proxy/_service/observability.py +410 -0
- app/modules/proxy/_service/rate_limit.py +361 -0
- app/modules/proxy/_service/realtime_live.py +655 -0
- app/modules/proxy/_service/refresh.py +154 -0
- app/modules/proxy/_service/request_log.py +585 -0
- app/modules/proxy/_service/response_create.py +930 -0
- app/modules/proxy/_service/streaming/__init__.py +3 -0
- app/modules/proxy/_service/streaming/helpers.py +1317 -0
- app/modules/proxy/_service/streaming/mixin.py +1100 -0
- app/modules/proxy/_service/streaming/protocol.py +32 -0
- app/modules/proxy/_service/streaming/retry.py +3762 -0
- app/modules/proxy/_service/support.py +2122 -0
- app/modules/proxy/_service/transcribe.py +434 -0
- app/modules/proxy/_service/warmup.py +483 -0
- app/modules/proxy/_service/websocket/__init__.py +3 -0
- app/modules/proxy/_service/websocket/helpers.py +2360 -0
- app/modules/proxy/_service/websocket/mixin.py +7285 -0
- app/modules/proxy/_service/websocket/protocol.py +74 -0
- app/modules/proxy/account_cache.py +229 -0
- app/modules/proxy/account_eligibility.py +87 -0
- app/modules/proxy/additional_model_limits.py +40 -0
- app/modules/proxy/affinity.py +830 -0
- app/modules/proxy/affinity_observation.py +101 -0
- app/modules/proxy/api.py +10254 -0
- app/modules/proxy/api_key_usage.py +113 -0
- app/modules/proxy/cap_partitioning.py +280 -0
- app/modules/proxy/capability_lineage.py +65 -0
- app/modules/proxy/capability_lineage_repository.py +82 -0
- app/modules/proxy/capability_routing.py +253 -0
- app/modules/proxy/continuity.py +112 -0
- app/modules/proxy/downstream_delivery.py +277 -0
- app/modules/proxy/durable_bridge_coordinator.py +1217 -0
- app/modules/proxy/durable_bridge_repository.py +4516 -0
- app/modules/proxy/durable_bridge_runtime.py +9 -0
- app/modules/proxy/durable_bridge_transcript_codec.py +122 -0
- app/modules/proxy/fair_share.py +131 -0
- app/modules/proxy/file_pin_repository.py +210 -0
- app/modules/proxy/helpers.py +439 -0
- app/modules/proxy/http_bridge_event_batcher.py +613 -0
- app/modules/proxy/http_bridge_forwarding.py +797 -0
- app/modules/proxy/http_continuation.py +76 -0
- app/modules/proxy/images_observability.py +62 -0
- app/modules/proxy/images_service.py +1054 -0
- app/modules/proxy/load_balancer.py +3016 -0
- app/modules/proxy/rate_limit_cache.py +46 -0
- app/modules/proxy/replay_safety.py +1063 -0
- app/modules/proxy/repo_bundle.py +31 -0
- app/modules/proxy/request_policy.py +1054 -0
- app/modules/proxy/ring_membership.py +251 -0
- app/modules/proxy/schemas.py +345 -0
- app/modules/proxy/selection_errors.py +41 -0
- app/modules/proxy/service.py +2600 -0
- app/modules/proxy/source_admission.py +125 -0
- app/modules/proxy/source_dispatch.py +999 -0
- app/modules/proxy/sticky_repository.py +831 -0
- app/modules/proxy/thread_anchors.py +491 -0
- app/modules/proxy/tool_call_dedupe.py +802 -0
- app/modules/proxy/types.py +54 -0
- app/modules/proxy/work_admission.py +121 -0
- app/modules/quota_planner/__init__.py +1 -0
- app/modules/quota_planner/api.py +276 -0
- app/modules/quota_planner/logic.py +743 -0
- app/modules/quota_planner/repository.py +722 -0
- app/modules/quota_planner/scheduler.py +212 -0
- app/modules/quota_planner/schemas.py +102 -0
- app/modules/quota_planner/warmup.py +693 -0
- app/modules/rate_limit_reset_credits/__init__.py +0 -0
- app/modules/rate_limit_reset_credits/api.py +601 -0
- app/modules/rate_limit_reset_credits/redeem_coordination.py +274 -0
- app/modules/rate_limit_reset_credits/store.py +114 -0
- app/modules/reports/__init__.py +1 -0
- app/modules/reports/api.py +134 -0
- app/modules/reports/cache.py +74 -0
- app/modules/reports/filters.py +27 -0
- app/modules/reports/repository.py +525 -0
- app/modules/reports/rollup.py +150 -0
- app/modules/reports/rollup_read.py +148 -0
- app/modules/reports/schemas.py +123 -0
- app/modules/reports/service.py +287 -0
- app/modules/reports/thread_identity.py +256 -0
- app/modules/request_logs/__init__.py +0 -0
- app/modules/request_logs/api.py +224 -0
- app/modules/request_logs/cost_backfill.py +154 -0
- app/modules/request_logs/mappers.py +97 -0
- app/modules/request_logs/repository.py +1765 -0
- app/modules/request_logs/schemas.py +145 -0
- app/modules/request_logs/service.py +348 -0
- app/modules/role_mappings/__init__.py +0 -0
- app/modules/role_mappings/api.py +206 -0
- app/modules/role_mappings/matching.py +55 -0
- app/modules/role_mappings/repository.py +106 -0
- app/modules/role_mappings/schemas.py +67 -0
- app/modules/role_mappings/service.py +334 -0
- app/modules/runtime/__init__.py +1 -0
- app/modules/runtime/api.py +18 -0
- app/modules/runtime/schemas.py +14 -0
- app/modules/runtime/service.py +218 -0
- app/modules/scim/__init__.py +1 -0
- app/modules/scim/api.py +194 -0
- app/modules/scim/dependencies.py +112 -0
- app/modules/scim/errors.py +77 -0
- app/modules/scim/management_api.py +156 -0
- app/modules/scim/repository.py +212 -0
- app/modules/scim/schemas.py +145 -0
- app/modules/scim/service.py +786 -0
- app/modules/scim/tokens.py +43 -0
- app/modules/settings/__init__.py +1 -0
- app/modules/settings/api.py +1677 -0
- app/modules/settings/repository.py +606 -0
- app/modules/settings/schemas.py +496 -0
- app/modules/settings/service.py +769 -0
- app/modules/shared/__init__.py +0 -0
- app/modules/shared/schemas.py +22 -0
- app/modules/sticky_sessions/__init__.py +1 -0
- app/modules/sticky_sessions/api.py +118 -0
- app/modules/sticky_sessions/cleanup_scheduler.py +487 -0
- app/modules/sticky_sessions/schemas.py +78 -0
- app/modules/sticky_sessions/service.py +196 -0
- app/modules/telemetry/__init__.py +5 -0
- app/modules/telemetry/api.py +115 -0
- app/modules/telemetry/clients.py +62 -0
- app/modules/telemetry/consent.py +115 -0
- app/modules/telemetry/scheduler.py +85 -0
- app/modules/telemetry/schemas.py +163 -0
- app/modules/telemetry/sender.py +221 -0
- app/modules/telemetry/snapshot.py +490 -0
- app/modules/usage/__init__.py +0 -0
- app/modules/usage/additional_quota_keys.py +379 -0
- app/modules/usage/api.py +45 -0
- app/modules/usage/background_repository.py +147 -0
- app/modules/usage/builders.py +559 -0
- app/modules/usage/depletion_service.py +277 -0
- app/modules/usage/live_ingest.py +356 -0
- app/modules/usage/mappers.py +29 -0
- app/modules/usage/plan_downgrade_observations.py +488 -0
- app/modules/usage/repository.py +1890 -0
- app/modules/usage/schemas.py +68 -0
- app/modules/usage/service.py +102 -0
- app/modules/usage/updater.py +1488 -0
- app/static/assets/Trans-Cj-J9mVA.js +1 -0
- app/static/assets/access-page-DHzZiXZi.js +1 -0
- app/static/assets/account-cost-donut-DGhfA4U8.js +1 -0
- app/static/assets/account-identifiers-CxbdLshZ.js +1 -0
- app/static/assets/account-status-DIsU5sUS.js +1 -0
- app/static/assets/account-trend-chart-BptlfwwQ.js +1 -0
- app/static/assets/accounts-page-Bbai8ift.js +3 -0
- app/static/assets/api-Dwa7XxPe.js +1 -0
- app/static/assets/api-client-dugX1Pti.js +55 -0
- app/static/assets/api-key-create-dialog-DnRm0oYN.js +1 -0
- app/static/assets/api-key-created-dialog-B6jkDG9f.js +1 -0
- app/static/assets/api-key-edit-dialog-Ck3Bnc3V.js +1 -0
- app/static/assets/api-trend-chart-BchCw7Hj.js +1 -0
- app/static/assets/apis-page-BvXz9c6i.js +2 -0
- app/static/assets/arrow-up-Dqh_KzJo.js +1 -0
- app/static/assets/arrow-up-down-LBRgVDGY.js +1 -0
- app/static/assets/automations-page-DQgNAJOR.js +3 -0
- app/static/assets/badge-DqMb9es0.js +1 -0
- app/static/assets/blur-email-HEvKagG2.js +1 -0
- app/static/assets/button-BjVmmiGW.js +1 -0
- app/static/assets/checkbox-apsl9vzk.js +1 -0
- app/static/assets/chevron-left-1d_pHVa5.js +1 -0
- app/static/assets/circle-alert-BS0xd_o1.js +1 -0
- app/static/assets/clsx-DB0hHKMi.js +1 -0
- app/static/assets/colors-BBy8GEtr.js +1 -0
- app/static/assets/copy-button-D7nAvOKR.js +1 -0
- app/static/assets/cost-per-day-chart-YdqlkZVM.js +1 -0
- app/static/assets/createLucideIcon-DBLzLNh2.js +1 -0
- app/static/assets/dashboard-page-CSdhBy0f.js +2 -0
- app/static/assets/distribution-metric-format-yZTy1ZEu.js +1 -0
- app/static/assets/donut-chart-Bxc69cra.js +1 -0
- app/static/assets/download-kQteIcsB.js +1 -0
- app/static/assets/ellipsis-B_5OgIre.js +1 -0
- app/static/assets/empty-state-JcA7tc8m.js +1 -0
- app/static/assets/es2015-bMH8YKZT.js +41 -0
- app/static/assets/es6-B264ni6W.js +69 -0
- app/static/assets/external-link-UVAOgMQ0.js +1 -0
- app/static/assets/i18n-BWqZ9Ua2.js +1 -0
- app/static/assets/inbox-B_RM2s1J.js +1 -0
- app/static/assets/index-DIpd264Z.js +23 -0
- app/static/assets/index-DMeLKRJx.css +2 -0
- app/static/assets/inherit-badge-QhTYVaU6.js +1 -0
- app/static/assets/invite-dialog-0CYh0GiQ.js +1 -0
- app/static/assets/iso-Bpe5Ihbb.js +1 -0
- app/static/assets/label-CGaLmLNf.js +1 -0
- app/static/assets/lazy-recharts-Pv8p9ArM.js +2 -0
- app/static/assets/loading-overlay-CzKQfHLI.js +1 -0
- app/static/assets/mini-quota-bar-cGT_t8Ae.js +1 -0
- app/static/assets/model-distribution-donut-BKjAfT48.js +1 -0
- app/static/assets/model-source-multi-select-D2d06Vc7.js +1 -0
- app/static/assets/multi-select-filter-KIA5qU6Z.js +1 -0
- app/static/assets/oauth-dialog-XeaGGDjS.js +1 -0
- app/static/assets/pagination-controls-D1Ypd0RU.js +1 -0
- app/static/assets/payload-CIYnGZz9.js +1 -0
- app/static/assets/queue-wait-chart-VoV7Yg9L.js +1 -0
- app/static/assets/report-chart-card-BXDliwcc.js +1 -0
- app/static/assets/reports-page-CGCJeMHG.js +3 -0
- app/static/assets/reset-credit-confirm-dialog-QOifTnVB.js +1 -0
- app/static/assets/rolldown-runtime-hePW80VL.js +1 -0
- app/static/assets/search-HfhqwERt.js +1 -0
- app/static/assets/select-Cl33bz-g.js +1 -0
- app/static/assets/settings-page-mZj01HYl.js +2 -0
- app/static/assets/shim-CZwyM4Q7.js +1 -0
- app/static/assets/skeleton-C_EUc4Rp.js +1 -0
- app/static/assets/sparkline-chart-DdNNsddM.js +1 -0
- app/static/assets/status-badge-CHHA5X6c.js +1 -0
- app/static/assets/switch-CzxgokcM.js +1 -0
- app/static/assets/table-DXaNSQ0G.js +1 -0
- app/static/assets/time-to-first-token-chart--68L0u_v.js +1 -0
- app/static/assets/tokens-per-day-chart-Cs82BFuE.js +1 -0
- app/static/assets/tokens-per-second-chart-AD2dfOn6.js +1 -0
- app/static/assets/totp-settings-CRHtxQ7j.js +1 -0
- app/static/assets/trash-D3KyWr1h.js +1 -0
- app/static/assets/use-account-quota-display-BPmrTBTC.js +1 -0
- app/static/assets/use-accounts-PWlVGw3z.js +1 -0
- app/static/assets/use-auth-CuDlW3iC.js +1 -0
- app/static/assets/use-chart-colors-DIu6tClI.js +1 -0
- app/static/assets/use-model-sources-Bul24JBu.js +1 -0
- app/static/assets/use-models-DUCPUuZg.js +1 -0
- app/static/assets/use-reduced-motion-hAm5r6_d.js +1 -0
- app/static/assets/useTranslation--56nHhlH.js +1 -0
- app/static/assets/useragent-distribution-donut-Dup6sf_n.js +1 -0
- app/static/assets/users-uIC3TIlE.js +1 -0
- app/static/assets/vendor-query-_bHZuxEx.js +1 -0
- app/static/assets/vendor-react-BVL0YZPW.js +9 -0
- app/static/favicon.svg +10 -0
- app/static/fonts/GeistSans-Variable.woff2 +0 -0
- app/static/fonts/jetbrains-mono-latin-ext.woff2 +0 -0
- app/static/fonts/jetbrains-mono-latin.woff2 +0 -0
- app/static/index.html +29 -0
- codexlb_up-1.25.0b10.dist-info/METADATA +124 -0
- codexlb_up-1.25.0b10.dist-info/RECORD +827 -0
- codexlb_up-1.25.0b10.dist-info/WHEEL +4 -0
- codexlb_up-1.25.0b10.dist-info/entry_points.txt +3 -0
- codexlb_up-1.25.0b10.dist-info/licenses/LICENSE +21 -0
- config/additional_quota_registry.json +11 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Add alias probe indexes for additional-usage latest-per-account reads.
|
|
2
|
+
|
|
3
|
+
The PostgreSQL latest-per-account read is being reshaped from a
|
|
4
|
+
``DISTINCT ON`` scan over every row under a quota key into correlated
|
|
5
|
+
per-account top-1 probes. Canonical probes ride the existing
|
|
6
|
+
``ix_additional_usage_quota_window_latest``; the registry's ``limit_name``
|
|
7
|
+
and ``metered_feature`` aliases match through ``lower(...)`` and therefore
|
|
8
|
+
need expression twins so each alias probe is a single btree descent too.
|
|
9
|
+
|
|
10
|
+
Revision ID: 20260806_000000_add_additional_usage_alias_probe_indexes
|
|
11
|
+
Revises: 20260804_230000_add_request_log_connection_request_kind
|
|
12
|
+
Create Date: 2026-08-06 00:00:00.000000
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import sqlalchemy as sa
|
|
18
|
+
from alembic import op
|
|
19
|
+
|
|
20
|
+
revision = "20260806_000000_add_additional_usage_alias_probe_indexes"
|
|
21
|
+
down_revision = "20260804_230000_add_request_log_connection_request_kind"
|
|
22
|
+
branch_labels = None
|
|
23
|
+
depends_on = None
|
|
24
|
+
|
|
25
|
+
_ALIAS_INDEXES = (
|
|
26
|
+
("ix_additional_usage_alias_limit_latest", "lower(limit_name)"),
|
|
27
|
+
("ix_additional_usage_alias_feature_latest", "lower(metered_feature)"),
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _drop_invalid_postgres_index(index_name: str) -> None:
|
|
32
|
+
"""Drop a leftover invalid index from an interrupted CREATE INDEX CONCURRENTLY.
|
|
33
|
+
|
|
34
|
+
``IF NOT EXISTS`` would silently accept the invalid index by name,
|
|
35
|
+
leaving the alias probes without a usable index.
|
|
36
|
+
"""
|
|
37
|
+
bind = op.get_bind()
|
|
38
|
+
invalid = bind.execute(
|
|
39
|
+
sa.text(
|
|
40
|
+
"SELECT 1 FROM pg_index i JOIN pg_class c ON c.oid = i.indexrelid "
|
|
41
|
+
"WHERE c.relname = :name AND NOT i.indisvalid"
|
|
42
|
+
),
|
|
43
|
+
{"name": index_name},
|
|
44
|
+
).scalar()
|
|
45
|
+
if invalid:
|
|
46
|
+
op.execute(sa.text(f"DROP INDEX CONCURRENTLY IF EXISTS {index_name}"))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def upgrade() -> None:
|
|
50
|
+
bind = op.get_bind()
|
|
51
|
+
|
|
52
|
+
if bind.dialect.name == "postgresql":
|
|
53
|
+
with op.get_context().autocommit_block():
|
|
54
|
+
for index_name, expression in _ALIAS_INDEXES:
|
|
55
|
+
_drop_invalid_postgres_index(index_name)
|
|
56
|
+
op.execute(
|
|
57
|
+
sa.text(
|
|
58
|
+
f"""
|
|
59
|
+
CREATE INDEX CONCURRENTLY IF NOT EXISTS {index_name}
|
|
60
|
+
ON additional_usage_history (
|
|
61
|
+
{expression}, "window", account_id,
|
|
62
|
+
recorded_at DESC, used_percent DESC, id DESC
|
|
63
|
+
)
|
|
64
|
+
"""
|
|
65
|
+
)
|
|
66
|
+
)
|
|
67
|
+
else:
|
|
68
|
+
for index_name, expression in _ALIAS_INDEXES:
|
|
69
|
+
op.execute(
|
|
70
|
+
sa.text(
|
|
71
|
+
f"""
|
|
72
|
+
CREATE INDEX IF NOT EXISTS {index_name}
|
|
73
|
+
ON additional_usage_history (
|
|
74
|
+
{expression}, "window", account_id,
|
|
75
|
+
recorded_at DESC, used_percent DESC, id DESC
|
|
76
|
+
)
|
|
77
|
+
"""
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def downgrade() -> None:
|
|
83
|
+
for index_name, _expression in _ALIAS_INDEXES:
|
|
84
|
+
op.drop_index(index_name, table_name="additional_usage_history", if_exists=True)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""add anonymous telemetry identity and consent
|
|
2
|
+
|
|
3
|
+
Revision ID: 20260806_000000_add_anonymous_telemetry
|
|
4
|
+
Revises: 20260812_000000_merge_recovery_dispatch_and_hourly_cancelled_heads
|
|
5
|
+
Create Date: 2026-08-06
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import sqlalchemy as sa
|
|
11
|
+
from alembic import op
|
|
12
|
+
|
|
13
|
+
revision = "20260806_000000_add_anonymous_telemetry"
|
|
14
|
+
down_revision = "20260812_000000_merge_recovery_dispatch_and_hourly_cancelled_heads"
|
|
15
|
+
branch_labels = None
|
|
16
|
+
depends_on = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _columns() -> set[str]:
|
|
20
|
+
return {column["name"] for column in sa.inspect(op.get_bind()).get_columns("dashboard_settings")}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def upgrade() -> None:
|
|
24
|
+
columns = _columns()
|
|
25
|
+
with op.batch_alter_table("dashboard_settings") as batch_op:
|
|
26
|
+
if "telemetry_consent" not in columns:
|
|
27
|
+
batch_op.add_column(
|
|
28
|
+
sa.Column(
|
|
29
|
+
"telemetry_consent",
|
|
30
|
+
sa.String(length=16),
|
|
31
|
+
server_default=sa.text("'undecided'"),
|
|
32
|
+
nullable=False,
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
if "telemetry_instance_id" not in columns:
|
|
36
|
+
batch_op.add_column(sa.Column("telemetry_instance_id", sa.String(length=36), nullable=True))
|
|
37
|
+
if "telemetry_private_key_encrypted" not in columns:
|
|
38
|
+
batch_op.add_column(sa.Column("telemetry_private_key_encrypted", sa.LargeBinary(), nullable=True))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def downgrade() -> None:
|
|
42
|
+
columns = _columns()
|
|
43
|
+
with op.batch_alter_table("dashboard_settings") as batch_op:
|
|
44
|
+
if "telemetry_private_key_encrypted" in columns:
|
|
45
|
+
batch_op.drop_column("telemetry_private_key_encrypted")
|
|
46
|
+
if "telemetry_instance_id" in columns:
|
|
47
|
+
batch_op.drop_column("telemetry_instance_id")
|
|
48
|
+
if "telemetry_consent" in columns:
|
|
49
|
+
batch_op.drop_column("telemetry_consent")
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""add conversation presence rollup table and fold watermark
|
|
2
|
+
|
|
3
|
+
DDL only — the satellite is created empty and backfill is owned entirely by
|
|
4
|
+
the runtime conversation fold pass, so this revision never blocks startup.
|
|
5
|
+
The watermark column backfills existing state rows to the epoch, so the new
|
|
6
|
+
satellite starts its own paced backfill from zero without touching the
|
|
7
|
+
lifetime or hourly watermarks.
|
|
8
|
+
|
|
9
|
+
Revision ID: 20260806_010000_add_conversation_presence_rollup
|
|
10
|
+
Revises: 20260806_000000_add_additional_usage_alias_probe_indexes
|
|
11
|
+
Create Date: 2026-08-06
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import sqlalchemy as sa
|
|
17
|
+
from alembic import op
|
|
18
|
+
from sqlalchemy.engine import Connection
|
|
19
|
+
|
|
20
|
+
revision = "20260806_010000_add_conversation_presence_rollup"
|
|
21
|
+
down_revision = "20260806_000000_add_additional_usage_alias_probe_indexes"
|
|
22
|
+
branch_labels = None
|
|
23
|
+
depends_on = None
|
|
24
|
+
|
|
25
|
+
_TABLE = "request_conversation_hourly_rollups"
|
|
26
|
+
_STATE_TABLE = "account_usage_rollup_state"
|
|
27
|
+
_WATERMARK_COLUMN = "conversation_folded_through"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _columns(connection: Connection, table_name: str) -> set[str]:
|
|
31
|
+
inspector = sa.inspect(connection)
|
|
32
|
+
if not inspector.has_table(table_name):
|
|
33
|
+
return set()
|
|
34
|
+
return {str(column["name"]) for column in inspector.get_columns(table_name) if column.get("name") is not None}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def upgrade() -> None:
|
|
38
|
+
bind = op.get_bind()
|
|
39
|
+
|
|
40
|
+
if not sa.inspect(bind).has_table(_TABLE):
|
|
41
|
+
op.create_table(
|
|
42
|
+
_TABLE,
|
|
43
|
+
sa.Column("bucket_epoch", sa.BigInteger(), nullable=False),
|
|
44
|
+
sa.Column("conversation_id", sa.String(), nullable=False),
|
|
45
|
+
sa.Column("account_id", sa.String(), nullable=False),
|
|
46
|
+
sa.Column("is_deleted", sa.Boolean(), server_default=sa.false(), nullable=False),
|
|
47
|
+
sa.Column("request_count", sa.BigInteger(), server_default=sa.text("0"), nullable=False),
|
|
48
|
+
sa.PrimaryKeyConstraint("bucket_epoch", "conversation_id", "account_id", "is_deleted"),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
state_columns = _columns(bind, _STATE_TABLE)
|
|
52
|
+
if state_columns and _WATERMARK_COLUMN not in state_columns:
|
|
53
|
+
with op.batch_alter_table(_STATE_TABLE) as batch_op:
|
|
54
|
+
batch_op.add_column(
|
|
55
|
+
sa.Column(
|
|
56
|
+
_WATERMARK_COLUMN,
|
|
57
|
+
sa.DateTime(),
|
|
58
|
+
server_default=sa.text("'1970-01-01 00:00:00'"),
|
|
59
|
+
nullable=False,
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def downgrade() -> None:
|
|
65
|
+
bind = op.get_bind()
|
|
66
|
+
|
|
67
|
+
if _WATERMARK_COLUMN in _columns(bind, _STATE_TABLE):
|
|
68
|
+
with op.batch_alter_table(_STATE_TABLE) as batch_op:
|
|
69
|
+
batch_op.drop_column(_WATERMARK_COLUMN)
|
|
70
|
+
|
|
71
|
+
if sa.inspect(bind).has_table(_TABLE):
|
|
72
|
+
op.drop_table(_TABLE)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Add covering indexes for the projections bulk usage-history fetch.
|
|
2
|
+
|
|
3
|
+
The dashboard projections bulk read selects six narrow columns from
|
|
4
|
+
``usage_history`` but every index matching its predicate shapes is a pure
|
|
5
|
+
key index, so PostgreSQL fetches the heap for every matched row (avg 2.0 s
|
|
6
|
+
on the reference deployment). These covering twins carry the selected
|
|
7
|
+
columns in an ``INCLUDE`` payload so the read can be served index-only:
|
|
8
|
+
one for the coalesced-primary window shape and one for the explicit
|
|
9
|
+
raw-window shape (``secondary`` is a live dashboard path).
|
|
10
|
+
|
|
11
|
+
Non-PostgreSQL backends create the same-named indexes with key columns
|
|
12
|
+
only (``INCLUDE`` unsupported), mirroring ``20260717_000000``: SQLite
|
|
13
|
+
serves this read from its snapshot cache and never runs the SQL shape, so
|
|
14
|
+
the twins exist for schema/drift parity with the ``models.py``
|
|
15
|
+
declarations.
|
|
16
|
+
|
|
17
|
+
Revision ID: 20260806_020000_add_usage_history_bulk_covering_indexes
|
|
18
|
+
Revises: 20260730_000000_add_api_key_fair_share_threshold
|
|
19
|
+
Create Date: 2026-08-06 02:00:00.000000
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import sqlalchemy as sa
|
|
25
|
+
from alembic import op
|
|
26
|
+
|
|
27
|
+
revision = "20260806_020000_add_usage_history_bulk_covering_indexes"
|
|
28
|
+
down_revision = "20260730_000000_add_api_key_fair_share_threshold"
|
|
29
|
+
branch_labels = None
|
|
30
|
+
depends_on = None
|
|
31
|
+
|
|
32
|
+
# The coalesced index carries the raw "window" column in its payload: the
|
|
33
|
+
# planner only considers an index-only scan when every column referenced by
|
|
34
|
+
# the query is returnable from the index, and expression key columns cannot
|
|
35
|
+
# return their underlying raw column, so without it the coalesce(...) qual
|
|
36
|
+
# disqualifies the index-only path (verified on PostgreSQL 18).
|
|
37
|
+
_COVERING_INDEXES = (
|
|
38
|
+
(
|
|
39
|
+
"idx_usage_window_account_time_covering",
|
|
40
|
+
"coalesce(\"window\", 'primary')",
|
|
41
|
+
'used_percent, reset_at, window_minutes, id, "window"',
|
|
42
|
+
),
|
|
43
|
+
(
|
|
44
|
+
"idx_usage_window_raw_account_time_covering",
|
|
45
|
+
'"window"',
|
|
46
|
+
"used_percent, reset_at, window_minutes, id",
|
|
47
|
+
),
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _drop_invalid_postgres_index(index_name: str) -> None:
|
|
52
|
+
"""Drop a leftover invalid index from an interrupted CREATE INDEX CONCURRENTLY.
|
|
53
|
+
|
|
54
|
+
``IF NOT EXISTS`` would silently accept the invalid index by name,
|
|
55
|
+
leaving the bulk fetch without a usable covering index.
|
|
56
|
+
"""
|
|
57
|
+
bind = op.get_bind()
|
|
58
|
+
invalid = bind.execute(
|
|
59
|
+
sa.text(
|
|
60
|
+
"SELECT 1 FROM pg_index i JOIN pg_class c ON c.oid = i.indexrelid "
|
|
61
|
+
"WHERE c.relname = :name AND NOT i.indisvalid"
|
|
62
|
+
),
|
|
63
|
+
{"name": index_name},
|
|
64
|
+
).scalar()
|
|
65
|
+
if invalid:
|
|
66
|
+
op.execute(sa.text(f"DROP INDEX CONCURRENTLY IF EXISTS {index_name}"))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def upgrade() -> None:
|
|
70
|
+
bind = op.get_bind()
|
|
71
|
+
|
|
72
|
+
if bind.dialect.name == "postgresql":
|
|
73
|
+
with op.get_context().autocommit_block():
|
|
74
|
+
for index_name, window_expression, include_columns in _COVERING_INDEXES:
|
|
75
|
+
_drop_invalid_postgres_index(index_name)
|
|
76
|
+
op.execute(
|
|
77
|
+
sa.text(
|
|
78
|
+
f"""
|
|
79
|
+
CREATE INDEX CONCURRENTLY IF NOT EXISTS {index_name}
|
|
80
|
+
ON usage_history ({window_expression}, account_id, recorded_at)
|
|
81
|
+
INCLUDE ({include_columns})
|
|
82
|
+
"""
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
else:
|
|
86
|
+
for index_name, window_expression, _include_columns in _COVERING_INDEXES:
|
|
87
|
+
op.execute(
|
|
88
|
+
sa.text(
|
|
89
|
+
f"""
|
|
90
|
+
CREATE INDEX IF NOT EXISTS {index_name}
|
|
91
|
+
ON usage_history ({window_expression}, account_id, recorded_at)
|
|
92
|
+
"""
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def downgrade() -> None:
|
|
98
|
+
for index_name, _window_expression, _include_columns in _COVERING_INDEXES:
|
|
99
|
+
op.drop_index(index_name, table_name="usage_history", if_exists=True)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""add API-key reasoning effort allowlists
|
|
2
|
+
|
|
3
|
+
The nullable column preserves the existing unrestricted policy for every
|
|
4
|
+
existing API key. New writes serialize a non-empty canonical JSON list.
|
|
5
|
+
|
|
6
|
+
Revision ID: 20260806_030000_add_api_key_allowed_reasoning_efforts
|
|
7
|
+
Revises: 20260816_000000_add_account_pending_deletion
|
|
8
|
+
Create Date: 2026-08-06 03:00:00.000000
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import sqlalchemy as sa
|
|
14
|
+
from alembic import op
|
|
15
|
+
from sqlalchemy.engine import Connection
|
|
16
|
+
|
|
17
|
+
revision = "20260806_030000_add_api_key_allowed_reasoning_efforts"
|
|
18
|
+
down_revision = "20260816_000000_add_account_pending_deletion"
|
|
19
|
+
branch_labels = None
|
|
20
|
+
depends_on = None
|
|
21
|
+
|
|
22
|
+
_TABLE = "api_keys"
|
|
23
|
+
_COLUMN = "allowed_reasoning_efforts"
|
|
24
|
+
_POLICY_CHECK = "ck_api_keys_reasoning_policy_exclusive"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _columns(connection: Connection) -> set[str]:
|
|
28
|
+
inspector = sa.inspect(connection)
|
|
29
|
+
if not inspector.has_table(_TABLE):
|
|
30
|
+
return set()
|
|
31
|
+
return {str(column["name"]) for column in inspector.get_columns(_TABLE) if column.get("name") is not None}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _check_constraints(connection: Connection) -> set[str]:
|
|
35
|
+
inspector = sa.inspect(connection)
|
|
36
|
+
if not inspector.has_table(_TABLE):
|
|
37
|
+
return set()
|
|
38
|
+
return {str(constraint["name"]) for constraint in inspector.get_check_constraints(_TABLE) if constraint.get("name")}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def upgrade() -> None:
|
|
42
|
+
connection = op.get_bind()
|
|
43
|
+
columns = _columns(connection)
|
|
44
|
+
if _COLUMN not in columns:
|
|
45
|
+
with op.batch_alter_table(_TABLE) as batch_op:
|
|
46
|
+
batch_op.add_column(sa.Column(_COLUMN, sa.Text(), nullable=True))
|
|
47
|
+
|
|
48
|
+
constraints = _check_constraints(connection)
|
|
49
|
+
if _POLICY_CHECK not in constraints:
|
|
50
|
+
with op.batch_alter_table(_TABLE) as batch_op:
|
|
51
|
+
batch_op.create_check_constraint(
|
|
52
|
+
_POLICY_CHECK,
|
|
53
|
+
f"{_COLUMN} IS NULL OR enforced_reasoning_effort IS NULL",
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def downgrade() -> None:
|
|
58
|
+
connection = op.get_bind()
|
|
59
|
+
columns = _columns(connection)
|
|
60
|
+
if _COLUMN not in columns:
|
|
61
|
+
return
|
|
62
|
+
with op.batch_alter_table(_TABLE) as batch_op:
|
|
63
|
+
if _POLICY_CHECK in _check_constraints(connection):
|
|
64
|
+
batch_op.drop_constraint(_POLICY_CHECK, type_="check")
|
|
65
|
+
batch_op.drop_column(_COLUMN)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""add owner process epoch to durable HTTP bridge sessions
|
|
2
|
+
|
|
3
|
+
Revision ID: 20260806_120000_add_http_bridge_owner_process_epoch
|
|
4
|
+
Revises: 20260808_000000_tune_usage_history_autovacuum
|
|
5
|
+
Create Date: 2026-08-06 12:00:00.000000
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import sqlalchemy as sa
|
|
11
|
+
from alembic import op
|
|
12
|
+
from sqlalchemy.engine import Connection
|
|
13
|
+
|
|
14
|
+
revision = "20260806_120000_add_http_bridge_owner_process_epoch"
|
|
15
|
+
down_revision = "20260808_000000_tune_usage_history_autovacuum"
|
|
16
|
+
branch_labels = None
|
|
17
|
+
depends_on = None
|
|
18
|
+
|
|
19
|
+
_TABLE = "http_bridge_sessions"
|
|
20
|
+
_COLUMN = "owner_process_epoch"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _columns(connection: Connection) -> set[str]:
|
|
24
|
+
inspector = sa.inspect(connection)
|
|
25
|
+
if not inspector.has_table(_TABLE):
|
|
26
|
+
return set()
|
|
27
|
+
return {str(column["name"]) for column in inspector.get_columns(_TABLE) if column.get("name") is not None}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def upgrade() -> None:
|
|
31
|
+
bind = op.get_bind()
|
|
32
|
+
if _COLUMN in _columns(bind):
|
|
33
|
+
return
|
|
34
|
+
with op.batch_alter_table(_TABLE) as batch_op:
|
|
35
|
+
batch_op.add_column(sa.Column(_COLUMN, sa.String(length=64), nullable=True))
|
|
36
|
+
op.drop_index("idx_http_bridge_sessions_owner_state", table_name=_TABLE, if_exists=True)
|
|
37
|
+
op.create_index(
|
|
38
|
+
"idx_http_bridge_sessions_owner_state",
|
|
39
|
+
_TABLE,
|
|
40
|
+
["owner_instance_id", _COLUMN, "state"],
|
|
41
|
+
if_not_exists=True,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def downgrade() -> None:
|
|
46
|
+
bind = op.get_bind()
|
|
47
|
+
if _COLUMN not in _columns(bind):
|
|
48
|
+
return
|
|
49
|
+
op.drop_index("idx_http_bridge_sessions_owner_state", table_name=_TABLE, if_exists=True)
|
|
50
|
+
op.create_index(
|
|
51
|
+
"idx_http_bridge_sessions_owner_state",
|
|
52
|
+
_TABLE,
|
|
53
|
+
["owner_instance_id", "state"],
|
|
54
|
+
if_not_exists=True,
|
|
55
|
+
)
|
|
56
|
+
with op.batch_alter_table(_TABLE) as batch_op:
|
|
57
|
+
batch_op.drop_column(_COLUMN)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""merge the durable HTTP bridge ledger with the current release head.
|
|
2
|
+
|
|
3
|
+
The operation-ledger revisions were authored on the recovery branch while
|
|
4
|
+
main continued to receive additive schema revisions. This no-op merge keeps
|
|
5
|
+
Alembic at one head without rewriting either already-applied lineage.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
revision = "20260807_000000_merge_http_bridge_operation_spool_and_latest_main"
|
|
11
|
+
down_revision = (
|
|
12
|
+
"20260806_120000_add_http_bridge_owner_process_epoch",
|
|
13
|
+
"20260805_000001_finalize_http_bridge_operation_spool",
|
|
14
|
+
)
|
|
15
|
+
branch_labels = None
|
|
16
|
+
depends_on = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def upgrade() -> None:
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def downgrade() -> None:
|
|
24
|
+
pass
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Tune usage_history autovacuum so the covering read path stays index-only.
|
|
2
|
+
|
|
3
|
+
The covering indexes from ``20260806_020000`` only pay off while the
|
|
4
|
+
visibility map is fresh: ``usage_history`` is append-heavy (high-frequency
|
|
5
|
+
usage snapshots, no updates or deletes), and PostgreSQL's default
|
|
6
|
+
insert-driven autovacuum trigger (20% of the table) lets the freshly
|
|
7
|
+
appended pages sit without an all-visible bit for a long time, turning the
|
|
8
|
+
"index-only" scan into one heap fetch per row — exactly the regression the
|
|
9
|
+
covering indexes were built to remove. This was observed on the reference
|
|
10
|
+
deployment and resolved by manually applying the settings below plus a
|
|
11
|
+
one-off ``VACUUM ANALYZE``; this revision codifies the settings.
|
|
12
|
+
|
|
13
|
+
Mirrors ``20260717_000000_optimize_dashboard_hot_path_indexes``, which set
|
|
14
|
+
the same parameters on the other two insert-heavy tables
|
|
15
|
+
(``request_logs``, ``additional_usage_history``). ``ALTER TABLE ... SET``
|
|
16
|
+
is idempotent, so re-applying on a deployment that already carries the
|
|
17
|
+
manual settings is harmless. Non-PostgreSQL backends are a no-op (SQLite
|
|
18
|
+
has no visibility map and serves this read from its snapshot cache).
|
|
19
|
+
|
|
20
|
+
Revision ID: 20260808_000000_tune_usage_history_autovacuum
|
|
21
|
+
Revises: 20260806_020000_add_usage_history_bulk_covering_indexes
|
|
22
|
+
Create Date: 2026-08-08 00:00:00.000000
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
import sqlalchemy as sa
|
|
28
|
+
from alembic import op
|
|
29
|
+
|
|
30
|
+
revision = "20260808_000000_tune_usage_history_autovacuum"
|
|
31
|
+
down_revision = "20260806_020000_add_usage_history_bulk_covering_indexes"
|
|
32
|
+
branch_labels = None
|
|
33
|
+
depends_on = None
|
|
34
|
+
|
|
35
|
+
_POSTGRES_AUTOVACUUM_SETTINGS = (
|
|
36
|
+
"autovacuum_vacuum_insert_scale_factor = 0.02, "
|
|
37
|
+
"autovacuum_vacuum_insert_threshold = 50000, "
|
|
38
|
+
"autovacuum_analyze_scale_factor = 0.02"
|
|
39
|
+
)
|
|
40
|
+
_POSTGRES_AUTOVACUUM_RESET = (
|
|
41
|
+
"autovacuum_vacuum_insert_scale_factor, autovacuum_vacuum_insert_threshold, autovacuum_analyze_scale_factor"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def upgrade() -> None:
|
|
46
|
+
bind = op.get_bind()
|
|
47
|
+
if bind.dialect.name == "postgresql":
|
|
48
|
+
op.execute(sa.text(f"ALTER TABLE usage_history SET ({_POSTGRES_AUTOVACUUM_SETTINGS})"))
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def downgrade() -> None:
|
|
52
|
+
bind = op.get_bind()
|
|
53
|
+
if bind.dialect.name == "postgresql":
|
|
54
|
+
op.execute(sa.text(f"ALTER TABLE usage_history RESET ({_POSTGRES_AUTOVACUUM_RESET})"))
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""persist the HTTP bridge ambiguous recovery dispatch budget
|
|
2
|
+
|
|
3
|
+
Revision ID: 20260810_000000_add_http_bridge_recovery_dispatch_count
|
|
4
|
+
Revises: 20260807_000000_merge_http_bridge_operation_spool_and_latest_main
|
|
5
|
+
Create Date: 2026-08-10
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import sqlalchemy as sa
|
|
11
|
+
from alembic import op
|
|
12
|
+
from sqlalchemy.engine import Connection
|
|
13
|
+
|
|
14
|
+
revision = "20260810_000000_add_http_bridge_recovery_dispatch_count"
|
|
15
|
+
down_revision = "20260807_000000_merge_http_bridge_operation_spool_and_latest_main"
|
|
16
|
+
branch_labels = None
|
|
17
|
+
depends_on = None
|
|
18
|
+
|
|
19
|
+
_TABLE = "http_bridge_operations"
|
|
20
|
+
_COLUMN = "recovery_dispatch_count"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _has_table(connection: Connection) -> bool:
|
|
24
|
+
return sa.inspect(connection).has_table(_TABLE)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _has_column(connection: Connection) -> bool:
|
|
28
|
+
return any(item["name"] == _COLUMN for item in sa.inspect(connection).get_columns(_TABLE))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def upgrade() -> None:
|
|
32
|
+
bind = op.get_bind()
|
|
33
|
+
if not _has_table(bind) or _has_column(bind):
|
|
34
|
+
return
|
|
35
|
+
op.add_column(
|
|
36
|
+
_TABLE,
|
|
37
|
+
sa.Column(_COLUMN, sa.Integer(), nullable=False, server_default=sa.text("0")),
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def downgrade() -> None:
|
|
42
|
+
bind = op.get_bind()
|
|
43
|
+
if _has_table(bind) and _has_column(bind):
|
|
44
|
+
op.drop_column(_TABLE, _COLUMN)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""add cancelled_count measure to hourly usage rollups
|
|
2
|
+
|
|
3
|
+
Additive DDL plus one marker stamp: the new measure is populated by the
|
|
4
|
+
hourly fold pass going forward (sum(status = 'cancelled')), and error_count
|
|
5
|
+
narrows to sum(status NOT IN ('success', 'cancelled')) at the same deploy.
|
|
6
|
+
Rows folded before this revision keep the legacy sum(status != 'success')
|
|
7
|
+
error fold and read cancelled_count = 0 via the server default — they are
|
|
8
|
+
deliberately NOT backfilled (raw rows below the watermark may already be
|
|
9
|
+
retention-pruned, so the old fold cannot be re-split), which shows as a
|
|
10
|
+
disclosed step change on error-rate trends (#1552).
|
|
11
|
+
|
|
12
|
+
Rolling-upgrade fence: this migration runs before old replicas drain, so a
|
|
13
|
+
legacy leader can keep folding (and advancing the shared watermark) with the
|
|
14
|
+
old error fold afterwards. ``account_usage_rollup_state.upgrade_repair_from``
|
|
15
|
+
records where that legacy-suspect range starts: existing state rows are
|
|
16
|
+
stamped with their current ``hourly_folded_through``; the epoch server
|
|
17
|
+
default covers a state row bootstrapped by an OLD replica after this
|
|
18
|
+
migration (its whole backfill is legacy-folded). New code refolds
|
|
19
|
+
``[upgrade_repair_from, hourly_folded_through)`` from raw on its first fold
|
|
20
|
+
pass and then sets the marker to NULL — a value only new code ever writes.
|
|
21
|
+
|
|
22
|
+
Revision ID: 20260811_000000_add_hourly_rollup_cancelled_count
|
|
23
|
+
Revises: 20260806_120000_add_http_bridge_owner_process_epoch
|
|
24
|
+
Create Date: 2026-08-11
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from __future__ import annotations
|
|
28
|
+
|
|
29
|
+
import sqlalchemy as sa
|
|
30
|
+
from alembic import op
|
|
31
|
+
from sqlalchemy.engine import Connection
|
|
32
|
+
|
|
33
|
+
revision = "20260811_000000_add_hourly_rollup_cancelled_count"
|
|
34
|
+
down_revision = "20260806_120000_add_http_bridge_owner_process_epoch"
|
|
35
|
+
branch_labels = None
|
|
36
|
+
depends_on = None
|
|
37
|
+
|
|
38
|
+
_TABLE = "request_usage_hourly_rollups"
|
|
39
|
+
_COLUMN = "cancelled_count"
|
|
40
|
+
_STATE_TABLE = "account_usage_rollup_state"
|
|
41
|
+
_MARKER_COLUMN = "upgrade_repair_from"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _columns(connection: Connection, table_name: str) -> set[str]:
|
|
45
|
+
inspector = sa.inspect(connection)
|
|
46
|
+
if not inspector.has_table(table_name):
|
|
47
|
+
return set()
|
|
48
|
+
return {str(column["name"]) for column in inspector.get_columns(table_name) if column.get("name") is not None}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def upgrade() -> None:
|
|
52
|
+
bind = op.get_bind()
|
|
53
|
+
|
|
54
|
+
if _COLUMN not in _columns(bind, _TABLE):
|
|
55
|
+
with op.batch_alter_table(_TABLE) as batch_op:
|
|
56
|
+
batch_op.add_column(
|
|
57
|
+
sa.Column(
|
|
58
|
+
_COLUMN,
|
|
59
|
+
sa.BigInteger(),
|
|
60
|
+
server_default=sa.text("0"),
|
|
61
|
+
nullable=False,
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
state_columns = _columns(bind, _STATE_TABLE)
|
|
66
|
+
if state_columns and _MARKER_COLUMN not in state_columns:
|
|
67
|
+
with op.batch_alter_table(_STATE_TABLE) as batch_op:
|
|
68
|
+
batch_op.add_column(
|
|
69
|
+
sa.Column(
|
|
70
|
+
_MARKER_COLUMN,
|
|
71
|
+
sa.DateTime(),
|
|
72
|
+
server_default=sa.text("'1970-01-01 00:00:00'"),
|
|
73
|
+
nullable=True,
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
# Existing rows: the legacy-suspect range starts at the watermark as
|
|
77
|
+
# of this migration — everything a legacy leader folds afterwards
|
|
78
|
+
# lies above it. Rows inserted later by old code keep the epoch
|
|
79
|
+
# server default (their entire backfill is legacy-suspect).
|
|
80
|
+
op.execute(sa.text(f"UPDATE {_STATE_TABLE} SET {_MARKER_COLUMN} = hourly_folded_through"))
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def downgrade() -> None:
|
|
84
|
+
bind = op.get_bind()
|
|
85
|
+
|
|
86
|
+
if _MARKER_COLUMN in _columns(bind, _STATE_TABLE):
|
|
87
|
+
with op.batch_alter_table(_STATE_TABLE) as batch_op:
|
|
88
|
+
batch_op.drop_column(_MARKER_COLUMN)
|
|
89
|
+
|
|
90
|
+
if _COLUMN in _columns(bind, _TABLE):
|
|
91
|
+
with op.batch_alter_table(_TABLE) as batch_op:
|
|
92
|
+
batch_op.drop_column(_COLUMN)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""merge the recovery-dispatch and hourly-rollup migration heads.
|
|
2
|
+
|
|
3
|
+
The durable HTTP bridge recovery branch and upstream's cancelled-count rollup
|
|
4
|
+
landed as independent additive revisions. This no-op merge keeps startup and
|
|
5
|
+
CI migration checks at one canonical Alembic head without rewriting either
|
|
6
|
+
already-applied lineage.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
revision = "20260812_000000_merge_recovery_dispatch_and_hourly_cancelled_heads"
|
|
12
|
+
down_revision = (
|
|
13
|
+
"20260810_000000_add_http_bridge_recovery_dispatch_count",
|
|
14
|
+
"20260811_000000_add_hourly_rollup_cancelled_count",
|
|
15
|
+
)
|
|
16
|
+
branch_labels = None
|
|
17
|
+
depends_on = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def upgrade() -> None:
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def downgrade() -> None:
|
|
25
|
+
pass
|