refactor(workspace): enforce layered crate boundaries

This commit is contained in:
elky
2026-07-15 23:47:19 +08:00
parent a728c090a9
commit 8616fe6ee2
969 changed files with 40187 additions and 27240 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,16 @@
-- Name: ldap_configs id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.ldap_configs ALTER COLUMN id SET DEFAULT nextval('public.ldap_configs_id_seq'::regclass);
--
-- Name: proxy_node_events id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.proxy_node_events ALTER COLUMN id SET DEFAULT nextval('public.proxy_node_events_id_seq'::regclass);
--
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,993 @@
-- Name: announcement_reads announcement_reads_announcement_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.announcement_reads
ADD CONSTRAINT announcement_reads_announcement_id_fkey FOREIGN KEY (announcement_id) REFERENCES public.announcements(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: announcement_reads announcement_reads_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.announcement_reads
ADD CONSTRAINT announcement_reads_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: announcements announcements_author_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.announcements
ADD CONSTRAINT announcements_author_id_fkey FOREIGN KEY (author_id) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: api_key_provider_mappings api_key_provider_mappings_api_key_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.api_key_provider_mappings
ADD CONSTRAINT api_key_provider_mappings_api_key_id_fkey FOREIGN KEY (api_key_id) REFERENCES public.api_keys(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: api_key_provider_mappings api_key_provider_mappings_provider_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.api_key_provider_mappings
ADD CONSTRAINT api_key_provider_mappings_provider_id_fkey FOREIGN KEY (provider_id) REFERENCES public.providers(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: api_keys api_keys_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.api_keys
ADD CONSTRAINT api_keys_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: audit_logs audit_logs_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.audit_logs
ADD CONSTRAINT audit_logs_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: billing_rules billing_rules_global_model_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.billing_rules
ADD CONSTRAINT billing_rules_global_model_id_fkey FOREIGN KEY (global_model_id) REFERENCES public.global_models(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: billing_rules billing_rules_model_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.billing_rules
ADD CONSTRAINT billing_rules_model_id_fkey FOREIGN KEY (model_id) REFERENCES public.models(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: provider_api_keys fk_provider_api_keys_provider; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.provider_api_keys
ADD CONSTRAINT fk_provider_api_keys_provider FOREIGN KEY (provider_id) REFERENCES public.providers(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: gemini_file_mappings gemini_file_mappings_key_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.gemini_file_mappings
ADD CONSTRAINT gemini_file_mappings_key_id_fkey FOREIGN KEY (key_id) REFERENCES public.provider_api_keys(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: gemini_file_mappings gemini_file_mappings_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.gemini_file_mappings
ADD CONSTRAINT gemini_file_mappings_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: management_tokens management_tokens_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.management_tokens
ADD CONSTRAINT management_tokens_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: models models_global_model_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.models
ADD CONSTRAINT models_global_model_id_fkey FOREIGN KEY (global_model_id) REFERENCES public.global_models(id);
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: models models_provider_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.models
ADD CONSTRAINT models_provider_id_fkey FOREIGN KEY (provider_id) REFERENCES public.providers(id);
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: payment_callbacks payment_callbacks_payment_order_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.payment_callbacks
ADD CONSTRAINT payment_callbacks_payment_order_id_fkey FOREIGN KEY (payment_order_id) REFERENCES public.payment_orders(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: payment_orders payment_orders_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.payment_orders
ADD CONSTRAINT payment_orders_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: payment_orders payment_orders_wallet_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.payment_orders
ADD CONSTRAINT payment_orders_wallet_id_fkey FOREIGN KEY (wallet_id) REFERENCES public.wallets(id) ON DELETE RESTRICT;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_plan_entitlements user_plan_entitlements_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_plan_entitlements
ADD CONSTRAINT user_plan_entitlements_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_plan_entitlements user_plan_entitlements_plan_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_plan_entitlements
ADD CONSTRAINT user_plan_entitlements_plan_id_fkey FOREIGN KEY (plan_id) REFERENCES public.billing_plans(id) ON DELETE RESTRICT;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_plan_entitlements user_plan_entitlements_payment_order_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_plan_entitlements
ADD CONSTRAINT user_plan_entitlements_payment_order_id_fkey FOREIGN KEY (payment_order_id) REFERENCES public.payment_orders(id) ON DELETE RESTRICT;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: entitlement_usage_ledgers entitlement_usage_ledgers_user_entitlement_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.entitlement_usage_ledgers
ADD CONSTRAINT entitlement_usage_ledgers_user_entitlement_id_fkey FOREIGN KEY (user_entitlement_id) REFERENCES public.user_plan_entitlements(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: entitlement_usage_ledgers entitlement_usage_ledgers_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.entitlement_usage_ledgers
ADD CONSTRAINT entitlement_usage_ledgers_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: provider_endpoints provider_endpoints_provider_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.provider_endpoints
ADD CONSTRAINT provider_endpoints_provider_id_fkey FOREIGN KEY (provider_id) REFERENCES public.providers(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: provider_usage_tracking provider_usage_tracking_provider_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.provider_usage_tracking
ADD CONSTRAINT provider_usage_tracking_provider_id_fkey FOREIGN KEY (provider_id) REFERENCES public.providers(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: proxy_node_events proxy_node_events_node_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.proxy_node_events
ADD CONSTRAINT proxy_node_events_node_id_fkey FOREIGN KEY (node_id) REFERENCES public.proxy_nodes(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: proxy_nodes proxy_nodes_registered_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.proxy_nodes
ADD CONSTRAINT proxy_nodes_registered_by_fkey FOREIGN KEY (registered_by) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: refund_requests refund_requests_approved_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.refund_requests
ADD CONSTRAINT refund_requests_approved_by_fkey FOREIGN KEY (approved_by) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: refund_requests refund_requests_payment_order_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.refund_requests
ADD CONSTRAINT refund_requests_payment_order_id_fkey FOREIGN KEY (payment_order_id) REFERENCES public.payment_orders(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: refund_requests refund_requests_processed_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.refund_requests
ADD CONSTRAINT refund_requests_processed_by_fkey FOREIGN KEY (processed_by) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: refund_requests refund_requests_requested_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.refund_requests
ADD CONSTRAINT refund_requests_requested_by_fkey FOREIGN KEY (requested_by) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: refund_requests refund_requests_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.refund_requests
ADD CONSTRAINT refund_requests_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: refund_requests refund_requests_wallet_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.refund_requests
ADD CONSTRAINT refund_requests_wallet_id_fkey FOREIGN KEY (wallet_id) REFERENCES public.wallets(id) ON DELETE RESTRICT;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: request_candidates request_candidates_api_key_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.request_candidates
ADD CONSTRAINT request_candidates_api_key_id_fkey FOREIGN KEY (api_key_id) REFERENCES public.api_keys(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: request_candidates request_candidates_endpoint_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.request_candidates
ADD CONSTRAINT request_candidates_endpoint_id_fkey FOREIGN KEY (endpoint_id) REFERENCES public.provider_endpoints(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: request_candidates request_candidates_provider_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.request_candidates
ADD CONSTRAINT request_candidates_provider_id_fkey FOREIGN KEY (provider_id) REFERENCES public.providers(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: request_candidates request_candidates_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.request_candidates
ADD CONSTRAINT request_candidates_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: stats_daily_api_key stats_daily_api_key_api_key_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.stats_daily_api_key
ADD CONSTRAINT stats_daily_api_key_api_key_id_fkey FOREIGN KEY (api_key_id) REFERENCES public.api_keys(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: stats_user_daily stats_user_daily_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.stats_user_daily
ADD CONSTRAINT stats_user_daily_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Usage is a historical fact table. Snapshot identity columns such as
-- user_id/api_key_id/provider_endpoint_id/provider_api_key_id/wallet_id
-- intentionally do not carry foreign keys because terminal usage events may
-- arrive after those mutable dimension rows have been disabled or deleted.
--
--
-- Name: user_model_usage_counts user_model_usage_counts_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_model_usage_counts
ADD CONSTRAINT user_model_usage_counts_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_group_members user_group_members_group_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_group_members
ADD CONSTRAINT user_group_members_group_id_fk FOREIGN KEY (group_id) REFERENCES public.user_groups(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_group_members user_group_members_user_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_group_members
ADD CONSTRAINT user_group_members_user_id_fk FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_oauth_links user_oauth_links_provider_type_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_oauth_links
ADD CONSTRAINT user_oauth_links_provider_type_fkey FOREIGN KEY (provider_type) REFERENCES public.oauth_providers(provider_type) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_oauth_links user_oauth_links_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_oauth_links
ADD CONSTRAINT user_oauth_links_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_preferences user_preferences_default_provider_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_preferences
ADD CONSTRAINT user_preferences_default_provider_id_fkey FOREIGN KEY (default_provider_id) REFERENCES public.providers(id);
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_preferences user_preferences_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_preferences
ADD CONSTRAINT user_preferences_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_sessions user_sessions_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_sessions
ADD CONSTRAINT user_sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_invite_codes user_invite_codes_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_invite_codes
ADD CONSTRAINT user_invite_codes_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_referrals user_referrals_inviter_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_referrals
ADD CONSTRAINT user_referrals_inviter_user_id_fkey FOREIGN KEY (inviter_user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_referrals user_referrals_invitee_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_referrals
ADD CONSTRAINT user_referrals_invitee_user_id_fkey FOREIGN KEY (invitee_user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: user_referrals user_referrals_first_paid_order_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.user_referrals
ADD CONSTRAINT user_referrals_first_paid_order_id_fkey FOREIGN KEY (first_paid_order_id) REFERENCES public.payment_orders(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: referral_rewards referral_rewards_referral_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.referral_rewards
ADD CONSTRAINT referral_rewards_referral_id_fkey FOREIGN KEY (referral_id) REFERENCES public.user_referrals(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: referral_rewards referral_rewards_inviter_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.referral_rewards
ADD CONSTRAINT referral_rewards_inviter_user_id_fkey FOREIGN KEY (inviter_user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: referral_rewards referral_rewards_invitee_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.referral_rewards
ADD CONSTRAINT referral_rewards_invitee_user_id_fkey FOREIGN KEY (invitee_user_id) REFERENCES public.users(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: referral_rewards referral_rewards_source_order_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.referral_rewards
ADD CONSTRAINT referral_rewards_source_order_id_fkey FOREIGN KEY (source_order_id) REFERENCES public.payment_orders(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: video_tasks video_tasks_api_key_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.video_tasks
ADD CONSTRAINT video_tasks_api_key_id_fkey FOREIGN KEY (api_key_id) REFERENCES public.api_keys(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: video_tasks video_tasks_endpoint_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.video_tasks
ADD CONSTRAINT video_tasks_endpoint_id_fkey FOREIGN KEY (endpoint_id) REFERENCES public.provider_endpoints(id);
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: video_tasks video_tasks_key_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.video_tasks
ADD CONSTRAINT video_tasks_key_id_fkey FOREIGN KEY (key_id) REFERENCES public.provider_api_keys(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: video_tasks video_tasks_provider_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.video_tasks
ADD CONSTRAINT video_tasks_provider_id_fkey FOREIGN KEY (provider_id) REFERENCES public.providers(id);
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: video_tasks video_tasks_remixed_from_task_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.video_tasks
ADD CONSTRAINT video_tasks_remixed_from_task_id_fkey FOREIGN KEY (remixed_from_task_id) REFERENCES public.video_tasks(id);
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: video_tasks video_tasks_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.video_tasks
ADD CONSTRAINT video_tasks_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: wallet_daily_usage_ledgers wallet_daily_usage_ledgers_wallet_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.wallet_daily_usage_ledgers
ADD CONSTRAINT wallet_daily_usage_ledgers_wallet_id_fkey FOREIGN KEY (wallet_id) REFERENCES public.wallets(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: wallet_transactions wallet_transactions_operator_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.wallet_transactions
ADD CONSTRAINT wallet_transactions_operator_id_fkey FOREIGN KEY (operator_id) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: wallet_transactions wallet_transactions_wallet_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.wallet_transactions
ADD CONSTRAINT wallet_transactions_wallet_id_fkey FOREIGN KEY (wallet_id) REFERENCES public.wallets(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: wallets wallets_api_key_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.wallets
ADD CONSTRAINT wallets_api_key_id_fkey FOREIGN KEY (api_key_id) REFERENCES public.api_keys(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
--
-- Name: wallets wallets_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
DO $mig$ BEGIN
ALTER TABLE ONLY public.wallets
ADD CONSTRAINT wallets_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
@@ -0,0 +1,49 @@
-- Restore a normal lookup path before sqlx records this migration in the
-- same transaction. sqlx inserts into `_sqlx_migrations` unqualified.
INSERT INTO public.user_groups (
id,
name,
normalized_name,
description,
priority,
allowed_providers_mode,
allowed_api_formats_mode,
allowed_models_mode,
rate_limit_mode
)
VALUES (
'00000000-0000-0000-0000-000000000001',
'Default',
'default',
'Default group for all users',
0,
'unrestricted',
'unrestricted',
'unrestricted',
'system'
)
ON CONFLICT (id) DO NOTHING;
INSERT INTO public.system_configs (id, key, value, description)
VALUES (
'00000000-0000-0000-0000-000000000002',
'default_user_group_id',
'"00000000-0000-0000-0000-000000000001"'::json,
'Default user group'
)
ON CONFLICT (key) DO NOTHING;
INSERT INTO public.user_group_members (group_id, user_id)
SELECT '00000000-0000-0000-0000-000000000001', id
FROM public.users
WHERE is_deleted IS FALSE
AND LOWER(role::text) <> 'admin'
ON CONFLICT (group_id, user_id) DO NOTHING;
SELECT pg_catalog.set_config('search_path', 'public', true);
--
-- PostgreSQL database dump complete
--
@@ -0,0 +1,474 @@
-- Baseline v2 extension: usage body blobs
CREATE TABLE IF NOT EXISTS public.usage_body_blobs (
body_ref character varying(160) NOT NULL,
request_id character varying(100) NOT NULL,
body_field character varying(50) NOT NULL,
payload_gzip bytea NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT usage_body_blobs_pkey PRIMARY KEY (body_ref),
CONSTRAINT usage_body_blobs_request_id_field_key UNIQUE (request_id, body_field),
CONSTRAINT usage_body_blobs_request_id_fkey
FOREIGN KEY (request_id)
REFERENCES public.usage(request_id)
ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS ix_usage_body_blobs_request_id
ON public.usage_body_blobs USING btree (request_id);
-- Baseline v2 extension: usage http audits
CREATE TABLE IF NOT EXISTS public.usage_http_audits (
request_id character varying(100) NOT NULL,
request_headers json,
provider_request_headers json,
response_headers json,
client_response_headers json,
request_body_ref character varying(160),
provider_request_body_ref character varying(160),
response_body_ref character varying(160),
client_response_body_ref character varying(160),
request_body_state character varying(32),
provider_request_body_state character varying(32),
response_body_state character varying(32),
client_response_body_state character varying(32),
body_capture_mode character varying(32) DEFAULT 'none' NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT usage_http_audits_pkey PRIMARY KEY (request_id),
CONSTRAINT usage_http_audits_request_id_fkey
FOREIGN KEY (request_id)
REFERENCES public.usage(request_id)
ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS ix_usage_http_audits_updated_at
ON public.usage_http_audits USING btree (updated_at);
-- Baseline v2 extension: usage routing snapshots
CREATE TABLE IF NOT EXISTS public.usage_routing_snapshots (
request_id character varying(100) NOT NULL,
candidate_id character varying(160),
candidate_index integer,
key_name character varying(255),
planner_kind character varying(120),
route_family character varying(80),
route_kind character varying(80),
execution_path character varying(80),
local_execution_runtime_miss_reason character varying(120),
selected_provider_id character varying(100),
selected_endpoint_id character varying(100),
selected_provider_api_key_id character varying(100),
has_format_conversion boolean,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT usage_routing_snapshots_pkey PRIMARY KEY (request_id),
CONSTRAINT usage_routing_snapshots_request_id_fkey
FOREIGN KEY (request_id)
REFERENCES public.usage(request_id)
ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS ix_usage_routing_snapshots_route_family_kind
ON public.usage_routing_snapshots USING btree (route_family, route_kind);
CREATE INDEX IF NOT EXISTS ix_usage_routing_snapshots_candidate_id
ON public.usage_routing_snapshots USING btree (candidate_id);
CREATE TABLE IF NOT EXISTS public.usage_settlement_snapshots (
request_id character varying(100) NOT NULL,
billing_status character varying(20) NOT NULL,
wallet_id character varying(36),
wallet_balance_before numeric(20,8),
wallet_balance_after numeric(20,8),
wallet_recharge_balance_before numeric(20,8),
wallet_recharge_balance_after numeric(20,8),
wallet_gift_balance_before numeric(20,8),
wallet_gift_balance_after numeric(20,8),
provider_monthly_used_usd numeric(20,8),
finalized_at timestamp with time zone,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT usage_settlement_snapshots_pkey PRIMARY KEY (request_id),
CONSTRAINT usage_settlement_snapshots_request_id_fkey
FOREIGN KEY (request_id)
REFERENCES public.usage(request_id)
ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS ix_usage_settlement_snapshots_wallet_id
ON public.usage_settlement_snapshots USING btree (wallet_id);
CREATE INDEX IF NOT EXISTS ix_usage_settlement_snapshots_billing_status
ON public.usage_settlement_snapshots USING btree (billing_status);
ALTER TABLE IF EXISTS public.usage_settlement_snapshots
ADD COLUMN IF NOT EXISTS billing_snapshot_schema_version character varying(20),
ADD COLUMN IF NOT EXISTS billing_snapshot_status character varying(20),
ADD COLUMN IF NOT EXISTS rate_multiplier numeric(10,6),
ADD COLUMN IF NOT EXISTS is_free_tier boolean,
ADD COLUMN IF NOT EXISTS input_price_per_1m numeric(20,8),
ADD COLUMN IF NOT EXISTS output_price_per_1m numeric(20,8),
ADD COLUMN IF NOT EXISTS cache_creation_price_per_1m numeric(20,8),
ADD COLUMN IF NOT EXISTS cache_read_price_per_1m numeric(20,8),
ADD COLUMN IF NOT EXISTS price_per_request numeric(20,8),
ADD COLUMN IF NOT EXISTS settlement_snapshot_schema_version character varying(20),
ADD COLUMN IF NOT EXISTS settlement_snapshot jsonb,
ADD COLUMN IF NOT EXISTS billing_dimensions jsonb,
ADD COLUMN IF NOT EXISTS billing_input_tokens bigint,
ADD COLUMN IF NOT EXISTS billing_effective_input_tokens bigint,
ADD COLUMN IF NOT EXISTS billing_output_tokens bigint,
ADD COLUMN IF NOT EXISTS billing_cache_creation_tokens bigint,
ADD COLUMN IF NOT EXISTS billing_cache_creation_5m_tokens bigint,
ADD COLUMN IF NOT EXISTS billing_cache_creation_1h_tokens bigint,
ADD COLUMN IF NOT EXISTS billing_cache_read_tokens bigint,
ADD COLUMN IF NOT EXISTS billing_total_input_context bigint,
ADD COLUMN IF NOT EXISTS billing_cache_creation_cost_usd numeric(20,8),
ADD COLUMN IF NOT EXISTS billing_cache_read_cost_usd numeric(20,8),
ADD COLUMN IF NOT EXISTS billing_total_cost_usd numeric(20,8),
ADD COLUMN IF NOT EXISTS billing_actual_total_cost_usd numeric(20,8),
ADD COLUMN IF NOT EXISTS billing_pricing_source character varying(50),
ADD COLUMN IF NOT EXISTS billing_rule_id character varying(100),
ADD COLUMN IF NOT EXISTS billing_rule_version character varying(50);
CREATE INDEX IF NOT EXISTS ix_usage_settlement_snapshots_schema_version
ON public.usage_settlement_snapshots USING btree (settlement_snapshot_schema_version);
CREATE INDEX IF NOT EXISTS ix_usage_settlement_snapshots_pricing_source
ON public.usage_settlement_snapshots USING btree (billing_pricing_source);
CREATE INDEX IF NOT EXISTS idx_usage_settlement_dashboard_cover
ON public.usage_settlement_snapshots USING btree (request_id)
INCLUDE (
billing_input_tokens,
billing_effective_input_tokens,
billing_output_tokens,
billing_cache_creation_tokens,
billing_cache_creation_5m_tokens,
billing_cache_creation_1h_tokens,
billing_cache_read_tokens,
billing_total_input_context,
billing_cache_creation_cost_usd,
billing_cache_read_cost_usd,
billing_total_cost_usd,
billing_actual_total_cost_usd,
input_price_per_1m
);
ALTER TABLE public.usage SET (
autovacuum_analyze_scale_factor = 0.02,
autovacuum_analyze_threshold = 10000
);
ALTER TABLE public.usage_settlement_snapshots SET (
autovacuum_analyze_scale_factor = 0.02,
autovacuum_analyze_threshold = 10000
);
CREATE OR REPLACE VIEW public.usage_billing_facts AS
SELECT
usage_rows.id,
usage_rows.request_id,
usage_rows.user_id,
usage_rows.api_key_id,
usage_rows.username,
usage_rows.api_key_name,
usage_rows.provider_name,
usage_rows.model,
usage_rows.target_model,
usage_rows.provider_id,
usage_rows.provider_endpoint_id,
usage_rows.provider_api_key_id,
usage_rows.request_type,
usage_rows.api_format,
usage_rows.api_family,
usage_rows.endpoint_kind,
usage_rows.endpoint_api_format,
usage_rows.provider_api_family,
usage_rows.provider_endpoint_kind,
COALESCE(usage_rows.has_format_conversion, FALSE) AS has_format_conversion,
COALESCE(usage_rows.is_stream, FALSE) AS is_stream,
usage_rows.status_code,
usage_rows.error_message,
usage_rows.error_category,
usage_rows.response_time_ms,
usage_rows.first_byte_time_ms,
usage_rows.status,
COALESCE(settlement.billing_status, usage_rows.billing_status) AS billing_status,
usage_rows.created_at,
COALESCE(settlement.finalized_at, usage_rows.finalized_at) AS finalized_at,
GREATEST(COALESCE(settlement.billing_input_tokens, usage_rows.input_tokens, 0), 0)::bigint
AS input_tokens,
GREATEST(
COALESCE(
settlement.billing_effective_input_tokens,
CASE
WHEN GREATEST(COALESCE(usage_rows.input_tokens, 0), 0) <= 0 THEN 0
WHEN GREATEST(COALESCE(usage_rows.cache_read_input_tokens, 0), 0) <= 0
THEN GREATEST(COALESCE(usage_rows.input_tokens, 0), 0)
WHEN split_part(lower(COALESCE(COALESCE(usage_rows.endpoint_api_format, usage_rows.api_format), '')), ':', 1)
IN ('openai', 'gemini', 'google')
THEN GREATEST(
GREATEST(COALESCE(usage_rows.input_tokens, 0), 0)
- GREATEST(COALESCE(usage_rows.cache_read_input_tokens, 0), 0),
0
)
ELSE GREATEST(COALESCE(usage_rows.input_tokens, 0), 0)
END
),
0
)::bigint AS effective_input_tokens,
GREATEST(COALESCE(settlement.billing_output_tokens, usage_rows.output_tokens, 0), 0)::bigint
AS output_tokens,
GREATEST(
COALESCE(
settlement.billing_cache_creation_tokens,
CASE
WHEN COALESCE(usage_rows.cache_creation_input_tokens, 0) = 0
AND (
COALESCE(usage_rows.cache_creation_input_tokens_5m, 0)
+ COALESCE(usage_rows.cache_creation_input_tokens_1h, 0)
) > 0
THEN COALESCE(usage_rows.cache_creation_input_tokens_5m, 0)
+ COALESCE(usage_rows.cache_creation_input_tokens_1h, 0)
ELSE COALESCE(usage_rows.cache_creation_input_tokens, 0)
END,
0
),
0
)::bigint AS cache_creation_input_tokens,
GREATEST(
COALESCE(
settlement.billing_cache_creation_5m_tokens,
usage_rows.cache_creation_input_tokens_5m,
0
),
0
)::bigint AS cache_creation_input_tokens_5m,
GREATEST(
COALESCE(
settlement.billing_cache_creation_1h_tokens,
usage_rows.cache_creation_input_tokens_1h,
0
),
0
)::bigint AS cache_creation_input_tokens_1h,
GREATEST(COALESCE(settlement.billing_cache_read_tokens, usage_rows.cache_read_input_tokens, 0), 0)::bigint
AS cache_read_input_tokens,
GREATEST(
COALESCE(
CASE
WHEN settlement.billing_input_tokens IS NOT NULL
OR settlement.billing_output_tokens IS NOT NULL
OR settlement.billing_cache_creation_tokens IS NOT NULL
OR settlement.billing_cache_creation_5m_tokens IS NOT NULL
OR settlement.billing_cache_creation_1h_tokens IS NOT NULL
OR settlement.billing_cache_read_tokens IS NOT NULL
THEN COALESCE(settlement.billing_input_tokens, 0)
+ COALESCE(settlement.billing_output_tokens, 0)
+ COALESCE(
settlement.billing_cache_creation_tokens,
COALESCE(settlement.billing_cache_creation_5m_tokens, 0)
+ COALESCE(settlement.billing_cache_creation_1h_tokens, 0),
0
)
+ COALESCE(settlement.billing_cache_read_tokens, 0)
END,
usage_rows.total_tokens,
0
),
0
)::bigint AS total_tokens,
GREATEST(
COALESCE(
settlement.billing_total_input_context,
CASE
WHEN split_part(lower(COALESCE(COALESCE(usage_rows.endpoint_api_format, usage_rows.api_format), '')), ':', 1)
IN ('claude', 'anthropic')
THEN GREATEST(COALESCE(usage_rows.input_tokens, 0), 0)
+ CASE
WHEN COALESCE(usage_rows.cache_creation_input_tokens, 0) = 0
AND (
COALESCE(usage_rows.cache_creation_input_tokens_5m, 0)
+ COALESCE(usage_rows.cache_creation_input_tokens_1h, 0)
) > 0
THEN COALESCE(usage_rows.cache_creation_input_tokens_5m, 0)
+ COALESCE(usage_rows.cache_creation_input_tokens_1h, 0)
ELSE COALESCE(usage_rows.cache_creation_input_tokens, 0)
END
+ GREATEST(COALESCE(usage_rows.cache_read_input_tokens, 0), 0)
WHEN split_part(lower(COALESCE(COALESCE(usage_rows.endpoint_api_format, usage_rows.api_format), '')), ':', 1)
IN ('openai', 'gemini', 'google')
THEN CASE
WHEN GREATEST(COALESCE(usage_rows.input_tokens, 0), 0) <= 0 THEN 0
WHEN GREATEST(COALESCE(usage_rows.cache_read_input_tokens, 0), 0) <= 0
THEN GREATEST(COALESCE(usage_rows.input_tokens, 0), 0)
ELSE GREATEST(
GREATEST(COALESCE(usage_rows.input_tokens, 0), 0)
- GREATEST(COALESCE(usage_rows.cache_read_input_tokens, 0), 0),
0
)
END
+ GREATEST(COALESCE(usage_rows.cache_read_input_tokens, 0), 0)
ELSE GREATEST(COALESCE(usage_rows.input_tokens, 0), 0)
+ CASE
WHEN COALESCE(usage_rows.cache_creation_input_tokens, 0) = 0
AND (
COALESCE(usage_rows.cache_creation_input_tokens_5m, 0)
+ COALESCE(usage_rows.cache_creation_input_tokens_1h, 0)
) > 0
THEN COALESCE(usage_rows.cache_creation_input_tokens_5m, 0)
+ COALESCE(usage_rows.cache_creation_input_tokens_1h, 0)
ELSE COALESCE(usage_rows.cache_creation_input_tokens, 0)
END
+ GREATEST(COALESCE(usage_rows.cache_read_input_tokens, 0), 0)
END,
0
),
0
)::bigint AS total_input_context,
COALESCE(CAST(usage_rows.input_cost_usd AS DOUBLE PRECISION), 0) AS input_cost_usd,
COALESCE(CAST(usage_rows.output_cost_usd AS DOUBLE PRECISION), 0) AS output_cost_usd,
COALESCE(
CAST(settlement.billing_cache_creation_cost_usd AS DOUBLE PRECISION),
CAST(usage_rows.cache_creation_cost_usd AS DOUBLE PRECISION),
0
) AS cache_creation_cost_usd,
COALESCE(
CAST(settlement.billing_cache_read_cost_usd AS DOUBLE PRECISION),
CAST(usage_rows.cache_read_cost_usd AS DOUBLE PRECISION),
0
) AS cache_read_cost_usd,
COALESCE(
CAST(settlement.billing_total_cost_usd AS DOUBLE PRECISION),
CAST(usage_rows.total_cost_usd AS DOUBLE PRECISION),
0
) AS total_cost_usd,
COALESCE(
CAST(settlement.billing_actual_total_cost_usd AS DOUBLE PRECISION),
CAST(usage_rows.actual_total_cost_usd AS DOUBLE PRECISION),
0
) AS actual_total_cost_usd,
COALESCE(
CAST(settlement.output_price_per_1m AS DOUBLE PRECISION),
CAST(usage_rows.output_price_per_1m AS DOUBLE PRECISION)
) AS output_price_per_1m,
COALESCE(
CAST(settlement.input_price_per_1m AS DOUBLE PRECISION),
CAST(usage_rows.input_price_per_1m AS DOUBLE PRECISION)
) AS input_price_per_1m,
COALESCE(
CAST(settlement.cache_creation_price_per_1m AS DOUBLE PRECISION),
CAST(usage_rows.cache_creation_price_per_1m AS DOUBLE PRECISION)
) AS cache_creation_price_per_1m,
COALESCE(
CAST(settlement.cache_read_price_per_1m AS DOUBLE PRECISION),
CAST(usage_rows.cache_read_price_per_1m AS DOUBLE PRECISION)
) AS cache_read_price_per_1m,
COALESCE(
CAST(settlement.price_per_request AS DOUBLE PRECISION),
CAST(usage_rows.price_per_request AS DOUBLE PRECISION)
) AS price_per_request,
settlement.billing_pricing_source,
settlement.billing_rule_id,
settlement.billing_rule_version,
COALESCE(usage_rows.upstream_is_stream, COALESCE(usage_rows.is_stream, FALSE)) AS upstream_is_stream
FROM public."usage" AS usage_rows
LEFT JOIN public.usage_settlement_snapshots AS settlement
ON settlement.request_id = usage_rows.request_id;
COMMENT ON VIEW public.usage_billing_facts IS
'Canonical billing read model. Token/cost fields prefer usage_settlement_snapshots.billing_* and fall back to deprecated usage mirrors for legacy rows.';
COMMENT ON COLUMN public.usage_billing_facts.upstream_is_stream IS
'Resolved upstream stream mode from public.usage.upstream_is_stream, falling back to usage.is_stream for legacy rows.';
COMMENT ON COLUMN public.usage.input_tokens IS
'DEPRECATED: billing dimension mirror. Use public.usage_settlement_snapshots.billing_input_tokens or public.usage_billing_facts.input_tokens.';
COMMENT ON COLUMN public.usage.output_tokens IS
'DEPRECATED: billing dimension mirror. Use public.usage_settlement_snapshots.billing_output_tokens or public.usage_billing_facts.output_tokens.';
COMMENT ON COLUMN public.usage.total_tokens IS
'DEPRECATED: billing dimension mirror. Use public.usage_billing_facts.total_tokens.';
COMMENT ON COLUMN public.usage.cache_creation_input_tokens IS
'DEPRECATED: billing dimension mirror. Use public.usage_settlement_snapshots.billing_cache_creation_tokens or public.usage_billing_facts.cache_creation_input_tokens.';
COMMENT ON COLUMN public.usage.cache_creation_input_tokens_5m IS
'DEPRECATED: billing dimension mirror. Use public.usage_settlement_snapshots.billing_cache_creation_5m_tokens or public.usage_billing_facts.cache_creation_input_tokens_5m.';
COMMENT ON COLUMN public.usage.cache_creation_input_tokens_1h IS
'DEPRECATED: billing dimension mirror. Use public.usage_settlement_snapshots.billing_cache_creation_1h_tokens or public.usage_billing_facts.cache_creation_input_tokens_1h.';
COMMENT ON COLUMN public.usage.cache_read_input_tokens IS
'DEPRECATED: billing dimension mirror. Use public.usage_settlement_snapshots.billing_cache_read_tokens or public.usage_billing_facts.cache_read_input_tokens.';
COMMENT ON COLUMN public.usage.cache_creation_cost_usd IS
'DEPRECATED: billing cost mirror. Use public.usage_settlement_snapshots.billing_cache_creation_cost_usd or public.usage_billing_facts.cache_creation_cost_usd.';
COMMENT ON COLUMN public.usage.cache_read_cost_usd IS
'DEPRECATED: billing cost mirror. Use public.usage_settlement_snapshots.billing_cache_read_cost_usd or public.usage_billing_facts.cache_read_cost_usd.';
COMMENT ON COLUMN public.usage.total_cost_usd IS
'DEPRECATED: billing cost mirror. Use public.usage_settlement_snapshots.billing_total_cost_usd or public.usage_billing_facts.total_cost_usd.';
COMMENT ON COLUMN public.usage.actual_total_cost_usd IS
'DEPRECATED: billing cost mirror. Use public.usage_settlement_snapshots.billing_actual_total_cost_usd or public.usage_billing_facts.actual_total_cost_usd.';
COMMENT ON COLUMN public.usage.wallet_id IS
'DEPRECATED: settlement owner moved to public.usage_settlement_snapshots.wallet_id. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.wallet_balance_before IS
'DEPRECATED: settlement owner moved to public.usage_settlement_snapshots.wallet_balance_before. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.wallet_balance_after IS
'DEPRECATED: settlement owner moved to public.usage_settlement_snapshots.wallet_balance_after. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.wallet_recharge_balance_before IS
'DEPRECATED: settlement owner moved to public.usage_settlement_snapshots.wallet_recharge_balance_before. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.wallet_recharge_balance_after IS
'DEPRECATED: settlement owner moved to public.usage_settlement_snapshots.wallet_recharge_balance_after. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.wallet_gift_balance_before IS
'DEPRECATED: settlement owner moved to public.usage_settlement_snapshots.wallet_gift_balance_before. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.wallet_gift_balance_after IS
'DEPRECATED: settlement owner moved to public.usage_settlement_snapshots.wallet_gift_balance_after. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.rate_multiplier IS
'DEPRECATED: settlement pricing owner moved to public.usage_settlement_snapshots.rate_multiplier. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.input_price_per_1m IS
'DEPRECATED: settlement pricing owner moved to public.usage_settlement_snapshots.input_price_per_1m. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.output_price_per_1m IS
'DEPRECATED: settlement pricing owner moved to public.usage_settlement_snapshots.output_price_per_1m. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.cache_creation_price_per_1m IS
'DEPRECATED: settlement pricing owner moved to public.usage_settlement_snapshots.cache_creation_price_per_1m. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.cache_read_price_per_1m IS
'DEPRECATED: settlement pricing owner moved to public.usage_settlement_snapshots.cache_read_price_per_1m. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.price_per_request IS
'DEPRECATED: settlement pricing owner moved to public.usage_settlement_snapshots.price_per_request. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.username IS
'DEPRECATED: display cache only. Prefer join-time lookup from user/auth records. Legacy compatibility only.';
COMMENT ON COLUMN public.usage.api_key_name IS
'DEPRECATED: display cache only. Prefer join-time lookup from API key records. Legacy compatibility only.';
COMMENT ON COLUMN public.usage.billing_status IS
'DEPRECATED: authoritative owner moved to public.usage_settlement_snapshots.billing_status. Compatibility/index mirror only; do not write new values.';
COMMENT ON COLUMN public.usage.finalized_at IS
'DEPRECATED: authoritative owner moved to public.usage_settlement_snapshots.finalized_at. Compatibility/index mirror only; do not write new values.';
COMMENT ON COLUMN public.usage.request_headers IS
'DEPRECATED: HTTP audit owner moved to public.usage_http_audits.request_headers. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.provider_request_headers IS
'DEPRECATED: HTTP audit owner moved to public.usage_http_audits.provider_request_headers. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.response_headers IS
'DEPRECATED: HTTP audit owner moved to public.usage_http_audits.response_headers. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.client_response_headers IS
'DEPRECATED: HTTP audit owner moved to public.usage_http_audits.client_response_headers. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.request_body IS
'DEPRECATED: HTTP body owner moved to public.usage_body_blobs plus public.usage_http_audits.request_body_ref. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.request_body_compressed IS
'DEPRECATED: HTTP body owner moved to public.usage_body_blobs plus public.usage_http_audits.request_body_ref. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.provider_request_body IS
'DEPRECATED: HTTP body owner moved to public.usage_body_blobs plus public.usage_http_audits.provider_request_body_ref. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.provider_request_body_compressed IS
'DEPRECATED: HTTP body owner moved to public.usage_body_blobs plus public.usage_http_audits.provider_request_body_ref. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.response_body IS
'DEPRECATED: HTTP body owner moved to public.usage_body_blobs plus public.usage_http_audits.response_body_ref. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.response_body_compressed IS
'DEPRECATED: HTTP body owner moved to public.usage_body_blobs plus public.usage_http_audits.response_body_ref. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.client_response_body IS
'DEPRECATED: HTTP body owner moved to public.usage_body_blobs plus public.usage_http_audits.client_response_body_ref. Legacy compatibility only; do not write new values.';
COMMENT ON COLUMN public.usage.client_response_body_compressed IS
'DEPRECATED: HTTP body owner moved to public.usage_body_blobs plus public.usage_http_audits.client_response_body_ref. Legacy compatibility only; do not write new values.';
@@ -0,0 +1,132 @@
CREATE TABLE IF NOT EXISTS public.redeem_code_batches (
id character varying(36) NOT NULL,
name character varying(120) NOT NULL,
amount_usd numeric(20,8) NOT NULL,
currency character varying(3) DEFAULT 'USD'::character varying NOT NULL,
balance_bucket character varying(20) DEFAULT 'gift'::character varying NOT NULL,
total_count integer NOT NULL,
status character varying(20) DEFAULT 'active'::character varying NOT NULL,
description text,
created_by character varying(36),
expires_at timestamp with time zone,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
CONSTRAINT ck_redeem_code_batches_amount_positive CHECK ((amount_usd > (0)::numeric)),
CONSTRAINT ck_redeem_code_batches_total_count_positive CHECK ((total_count > 0))
);
CREATE TABLE IF NOT EXISTS public.redeem_codes (
id character varying(36) NOT NULL,
batch_id character varying(36) NOT NULL,
code_hash character varying(64) NOT NULL,
code_prefix character varying(8) NOT NULL,
code_suffix character varying(8) NOT NULL,
status character varying(20) DEFAULT 'active'::character varying NOT NULL,
redeemed_by_user_id character varying(36),
redeemed_wallet_id character varying(36),
redeemed_payment_order_id character varying(36),
redeemed_at timestamp with time zone,
disabled_by character varying(36),
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL
);
DO $mig$ BEGIN
ALTER TABLE ONLY public.redeem_code_batches
ADD CONSTRAINT redeem_code_batches_pkey PRIMARY KEY (id);
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
DO $mig$ BEGIN
ALTER TABLE ONLY public.redeem_codes
ADD CONSTRAINT redeem_codes_pkey PRIMARY KEY (id);
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
DO $mig$ BEGIN
ALTER TABLE ONLY public.redeem_codes
ADD CONSTRAINT uq_redeem_codes_code_hash UNIQUE (code_hash);
EXCEPTION
WHEN duplicate_object THEN NULL;
WHEN duplicate_table THEN NULL;
WHEN invalid_table_definition THEN NULL;
END $mig$;
CREATE INDEX IF NOT EXISTS idx_redeem_code_batches_status
ON public.redeem_code_batches USING btree (status, created_at);
CREATE INDEX IF NOT EXISTS idx_redeem_codes_batch_created
ON public.redeem_codes USING btree (batch_id, created_at);
CREATE INDEX IF NOT EXISTS idx_redeem_codes_status
ON public.redeem_codes USING btree (status, updated_at);
CREATE INDEX IF NOT EXISTS idx_redeem_codes_redeemed_user
ON public.redeem_codes USING btree (redeemed_by_user_id, redeemed_at);
CREATE INDEX IF NOT EXISTS idx_redeem_codes_redeemed_order
ON public.redeem_codes USING btree (redeemed_payment_order_id);
DO $mig$ BEGIN
ALTER TABLE ONLY public.redeem_code_batches
ADD CONSTRAINT redeem_code_batches_created_by_fkey FOREIGN KEY (created_by) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
END $mig$;
DO $mig$ BEGIN
ALTER TABLE ONLY public.redeem_codes
ADD CONSTRAINT redeem_codes_batch_id_fkey FOREIGN KEY (batch_id) REFERENCES public.redeem_code_batches(id) ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN NULL;
END $mig$;
DO $mig$ BEGIN
ALTER TABLE ONLY public.redeem_codes
ADD CONSTRAINT redeem_codes_redeemed_by_user_id_fkey FOREIGN KEY (redeemed_by_user_id) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
END $mig$;
DO $mig$ BEGIN
ALTER TABLE ONLY public.redeem_codes
ADD CONSTRAINT redeem_codes_redeemed_wallet_id_fkey FOREIGN KEY (redeemed_wallet_id) REFERENCES public.wallets(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
END $mig$;
DO $mig$ BEGIN
ALTER TABLE ONLY public.redeem_codes
ADD CONSTRAINT redeem_codes_redeemed_payment_order_id_fkey FOREIGN KEY (redeemed_payment_order_id) REFERENCES public.payment_orders(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
END $mig$;
DO $mig$ BEGIN
ALTER TABLE ONLY public.redeem_codes
ADD CONSTRAINT redeem_codes_disabled_by_fkey FOREIGN KEY (disabled_by) REFERENCES public.users(id) ON DELETE SET NULL;
EXCEPTION
WHEN duplicate_object THEN NULL;
END $mig$;
ALTER TABLE public.stats_user_daily
ADD COLUMN IF NOT EXISTS actual_total_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS response_time_sum_ms double precision DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS response_time_samples bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS effective_input_tokens bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS total_input_context bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS cache_creation_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS cache_read_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL;
ALTER TABLE public.stats_hourly_user
ADD COLUMN IF NOT EXISTS cache_creation_tokens bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS cache_read_tokens bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS actual_total_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS response_time_sum_ms double precision DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS response_time_samples bigint DEFAULT 0 NOT NULL;
@@ -0,0 +1,324 @@
CREATE TABLE IF NOT EXISTS public.stats_user_summary (
id character varying(36) NOT NULL,
user_id character varying(36) NOT NULL,
username character varying(100),
cutoff_date timestamp with time zone NOT NULL,
all_time_requests integer DEFAULT 0 NOT NULL,
all_time_success_requests integer DEFAULT 0 NOT NULL,
all_time_error_requests integer DEFAULT 0 NOT NULL,
all_time_input_tokens bigint DEFAULT '0'::bigint NOT NULL,
all_time_output_tokens bigint DEFAULT '0'::bigint NOT NULL,
all_time_cache_creation_tokens bigint DEFAULT '0'::bigint NOT NULL,
all_time_cache_read_tokens bigint DEFAULT '0'::bigint NOT NULL,
all_time_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
all_time_actual_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
active_days integer DEFAULT 0 NOT NULL,
first_active_date timestamp with time zone,
last_active_date timestamp with time zone,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT stats_user_summary_pkey PRIMARY KEY (id),
CONSTRAINT uq_stats_user_summary_user_id UNIQUE (user_id),
CONSTRAINT stats_user_summary_user_id_fkey
FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_stats_user_summary_cutoff_date
ON public.stats_user_summary USING btree (cutoff_date);
ALTER TABLE public.stats_daily
ADD COLUMN IF NOT EXISTS effective_input_tokens bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS total_input_context bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS response_time_sum_ms double precision DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS response_time_samples bigint DEFAULT 0 NOT NULL;
ALTER TABLE public.stats_daily_model
ADD COLUMN IF NOT EXISTS response_time_sum_ms double precision DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS response_time_samples bigint DEFAULT 0 NOT NULL;
CREATE TABLE IF NOT EXISTS public.stats_user_daily_model (
id character varying(36) NOT NULL,
user_id character varying(36) NOT NULL,
username character varying(100),
date timestamp with time zone NOT NULL,
model character varying(100) NOT NULL,
total_requests integer DEFAULT 0 NOT NULL,
input_tokens bigint DEFAULT '0'::bigint NOT NULL,
output_tokens bigint DEFAULT '0'::bigint NOT NULL,
total_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
response_time_sum_ms double precision DEFAULT '0'::double precision NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT stats_user_daily_model_pkey PRIMARY KEY (id),
CONSTRAINT uq_stats_user_daily_model_user_date_model UNIQUE (user_id, date, model),
CONSTRAINT stats_user_daily_model_user_id_fkey
FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_date
ON public.stats_user_daily_model USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_user_id
ON public.stats_user_daily_model USING btree (user_id);
ALTER TABLE public.stats_hourly
ADD COLUMN IF NOT EXISTS response_time_sum_ms double precision DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS response_time_samples bigint DEFAULT 0 NOT NULL;
ALTER TABLE public.stats_hourly_model
ADD COLUMN IF NOT EXISTS response_time_sum_ms double precision DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS response_time_samples bigint DEFAULT 0 NOT NULL;
CREATE TABLE IF NOT EXISTS public.stats_hourly_user_model (
id character varying(36) NOT NULL,
hour_utc timestamp with time zone NOT NULL,
user_id character varying(36) NOT NULL,
model character varying(100) NOT NULL,
total_requests integer DEFAULT 0 NOT NULL,
input_tokens bigint DEFAULT '0'::bigint NOT NULL,
output_tokens bigint DEFAULT '0'::bigint NOT NULL,
total_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
response_time_sum_ms double precision DEFAULT '0'::double precision NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT stats_hourly_user_model_pkey PRIMARY KEY (id),
CONSTRAINT uq_stats_hourly_user_model UNIQUE (hour_utc, user_id, model),
CONSTRAINT stats_hourly_user_model_user_id_fkey
FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_stats_hourly_user_model_hour
ON public.stats_hourly_user_model USING btree (hour_utc);
CREATE INDEX IF NOT EXISTS idx_stats_hourly_user_model_user_hour
ON public.stats_hourly_user_model USING btree (user_id, hour_utc);
CREATE TABLE IF NOT EXISTS public.schema_backfills (
version bigint NOT NULL,
description text NOT NULL,
success boolean NOT NULL DEFAULT TRUE,
checksum bytea NOT NULL,
execution_time bigint NOT NULL DEFAULT 0,
applied_at timestamp with time zone NOT NULL DEFAULT now(),
CONSTRAINT schema_backfills_pkey PRIMARY KEY (version)
);
CREATE INDEX IF NOT EXISTS idx_schema_backfills_applied_at
ON public.schema_backfills USING btree (applied_at DESC);
ALTER TABLE public.stats_user_daily_model
ADD COLUMN IF NOT EXISTS success_requests integer DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS effective_input_tokens bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS total_tokens bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS total_input_context bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS cache_creation_tokens bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS cache_creation_ephemeral_5m_tokens bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS cache_creation_ephemeral_1h_tokens bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS cache_read_tokens bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS actual_total_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS successful_response_time_sum_ms double precision DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS successful_response_time_samples bigint DEFAULT 0 NOT NULL;
CREATE TABLE IF NOT EXISTS public.stats_user_daily_provider (
id character varying(36) NOT NULL,
user_id character varying(36) NOT NULL,
username character varying(100),
date timestamp with time zone NOT NULL,
provider_name character varying(100) NOT NULL,
total_requests integer DEFAULT 0 NOT NULL,
success_requests integer DEFAULT 0 NOT NULL,
input_tokens bigint DEFAULT '0'::bigint NOT NULL,
effective_input_tokens bigint DEFAULT '0'::bigint NOT NULL,
output_tokens bigint DEFAULT '0'::bigint NOT NULL,
total_tokens bigint DEFAULT '0'::bigint NOT NULL,
total_input_context bigint DEFAULT '0'::bigint NOT NULL,
cache_creation_tokens bigint DEFAULT '0'::bigint NOT NULL,
cache_creation_ephemeral_5m_tokens bigint DEFAULT '0'::bigint NOT NULL,
cache_creation_ephemeral_1h_tokens bigint DEFAULT '0'::bigint NOT NULL,
cache_read_tokens bigint DEFAULT '0'::bigint NOT NULL,
total_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
actual_total_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
response_time_sum_ms double precision DEFAULT '0'::double precision NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL,
successful_response_time_sum_ms double precision DEFAULT '0'::double precision NOT NULL,
successful_response_time_samples bigint DEFAULT 0 NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT stats_user_daily_provider_pkey PRIMARY KEY (id),
CONSTRAINT uq_stats_user_daily_provider_user_date_provider UNIQUE (user_id, date, provider_name),
CONSTRAINT stats_user_daily_provider_user_id_fkey
FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_provider_date
ON public.stats_user_daily_provider USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_provider_user_id
ON public.stats_user_daily_provider USING btree (user_id);
CREATE TABLE IF NOT EXISTS public.stats_user_daily_api_format (
id character varying(36) NOT NULL,
user_id character varying(36) NOT NULL,
username character varying(100),
date timestamp with time zone NOT NULL,
api_format character varying(50) NOT NULL,
total_requests integer DEFAULT 0 NOT NULL,
success_requests integer DEFAULT 0 NOT NULL,
input_tokens bigint DEFAULT '0'::bigint NOT NULL,
effective_input_tokens bigint DEFAULT '0'::bigint NOT NULL,
output_tokens bigint DEFAULT '0'::bigint NOT NULL,
total_tokens bigint DEFAULT '0'::bigint NOT NULL,
total_input_context bigint DEFAULT '0'::bigint NOT NULL,
cache_creation_tokens bigint DEFAULT '0'::bigint NOT NULL,
cache_creation_ephemeral_5m_tokens bigint DEFAULT '0'::bigint NOT NULL,
cache_creation_ephemeral_1h_tokens bigint DEFAULT '0'::bigint NOT NULL,
cache_read_tokens bigint DEFAULT '0'::bigint NOT NULL,
total_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
actual_total_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
response_time_sum_ms double precision DEFAULT '0'::double precision NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL,
successful_response_time_sum_ms double precision DEFAULT '0'::double precision NOT NULL,
successful_response_time_samples bigint DEFAULT 0 NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT stats_user_daily_api_format_pkey PRIMARY KEY (id),
CONSTRAINT uq_stats_user_daily_api_format_user_date_api_format UNIQUE (user_id, date, api_format),
CONSTRAINT stats_user_daily_api_format_user_id_fkey
FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_api_format_date
ON public.stats_user_daily_api_format USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_api_format_user_id
ON public.stats_user_daily_api_format USING btree (user_id);
CREATE TABLE IF NOT EXISTS public.stats_daily_model_provider (
id character varying(36) NOT NULL,
date timestamp with time zone NOT NULL,
model character varying(100) NOT NULL,
provider_name character varying(100) NOT NULL,
total_requests integer DEFAULT 0 NOT NULL,
total_tokens bigint DEFAULT '0'::bigint NOT NULL,
total_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
response_time_sum_ms double precision DEFAULT '0'::double precision NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT stats_daily_model_provider_pkey PRIMARY KEY (id),
CONSTRAINT uq_stats_daily_model_provider UNIQUE (date, model, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_daily_model_provider_date
ON public.stats_daily_model_provider USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_model_provider_date_model_provider
ON public.stats_daily_model_provider USING btree (date, model, provider_name);
CREATE TABLE IF NOT EXISTS public.stats_user_daily_model_provider (
id character varying(36) NOT NULL,
user_id character varying(36) NOT NULL,
username character varying(100),
date timestamp with time zone NOT NULL,
model character varying(100) NOT NULL,
provider_name character varying(100) NOT NULL,
total_requests integer DEFAULT 0 NOT NULL,
total_tokens bigint DEFAULT '0'::bigint NOT NULL,
total_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
response_time_sum_ms double precision DEFAULT '0'::double precision NOT NULL,
response_time_samples bigint DEFAULT 0 NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT stats_user_daily_model_provider_pkey PRIMARY KEY (id),
CONSTRAINT uq_stats_user_daily_model_provider UNIQUE (user_id, date, model, provider_name),
CONSTRAINT stats_user_daily_model_provider_user_id_fkey
FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_provider_date
ON public.stats_user_daily_model_provider USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_model_provider_user_date
ON public.stats_user_daily_model_provider USING btree (user_id, date);
ALTER TABLE public.stats_daily
ADD COLUMN IF NOT EXISTS cache_creation_ephemeral_5m_tokens bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS cache_creation_ephemeral_1h_tokens bigint DEFAULT '0'::bigint NOT NULL;
ALTER TABLE public.stats_user_daily
ADD COLUMN IF NOT EXISTS cache_creation_ephemeral_5m_tokens bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS cache_creation_ephemeral_1h_tokens bigint DEFAULT '0'::bigint NOT NULL;
ALTER TABLE public.stats_daily_model
ADD COLUMN IF NOT EXISTS cache_creation_ephemeral_5m_tokens bigint DEFAULT '0'::bigint NOT NULL,
ADD COLUMN IF NOT EXISTS cache_creation_ephemeral_1h_tokens bigint DEFAULT '0'::bigint NOT NULL;
ALTER TABLE public.stats_daily
ADD COLUMN IF NOT EXISTS cache_hit_total_requests bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS cache_hit_requests bigint DEFAULT 0 NOT NULL;
ALTER TABLE public.stats_hourly
ADD COLUMN IF NOT EXISTS cache_hit_total_requests bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS cache_hit_requests bigint DEFAULT 0 NOT NULL;
ALTER TABLE public.stats_daily
ADD COLUMN IF NOT EXISTS completed_total_requests bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS completed_cache_hit_requests bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS completed_input_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS completed_cache_creation_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS completed_cache_read_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS completed_total_input_context bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS completed_cache_creation_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS completed_cache_read_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL;
ALTER TABLE public.stats_hourly
ADD COLUMN IF NOT EXISTS completed_total_requests bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS completed_cache_hit_requests bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS completed_input_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS completed_cache_creation_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS completed_cache_read_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS completed_total_input_context bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS completed_cache_creation_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS completed_cache_read_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL;
ALTER TABLE public.stats_daily
ADD COLUMN IF NOT EXISTS settled_total_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS settled_total_requests bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_input_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_output_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_cache_creation_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_cache_read_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_first_finalized_at_unix_secs bigint,
ADD COLUMN IF NOT EXISTS settled_last_finalized_at_unix_secs bigint;
ALTER TABLE public.stats_hourly
ADD COLUMN IF NOT EXISTS settled_total_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS settled_total_requests bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_input_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_output_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_cache_creation_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_cache_read_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_first_finalized_at_unix_secs bigint,
ADD COLUMN IF NOT EXISTS settled_last_finalized_at_unix_secs bigint;
ALTER TABLE public.stats_user_daily
ADD COLUMN IF NOT EXISTS settled_total_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS settled_total_requests bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_input_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_output_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_cache_creation_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_cache_read_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_first_finalized_at_unix_secs bigint,
ADD COLUMN IF NOT EXISTS settled_last_finalized_at_unix_secs bigint;
ALTER TABLE public.stats_hourly_user
ADD COLUMN IF NOT EXISTS settled_total_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
ADD COLUMN IF NOT EXISTS settled_total_requests bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_input_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_output_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_cache_creation_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_cache_read_tokens bigint DEFAULT 0 NOT NULL,
ADD COLUMN IF NOT EXISTS settled_first_finalized_at_unix_secs bigint,
ADD COLUMN IF NOT EXISTS settled_last_finalized_at_unix_secs bigint;
@@ -0,0 +1,173 @@
CREATE TABLE IF NOT EXISTS public.stats_daily_cost_savings (
id character varying(36) NOT NULL,
date timestamp with time zone NOT NULL,
cache_read_tokens bigint DEFAULT '0'::bigint NOT NULL,
cache_read_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
cache_creation_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
estimated_full_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT stats_daily_cost_savings_pkey PRIMARY KEY (id),
CONSTRAINT uq_stats_daily_cost_savings_date UNIQUE (date)
);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_date
ON public.stats_daily_cost_savings USING btree (date);
CREATE TABLE IF NOT EXISTS public.stats_daily_cost_savings_provider (
id character varying(36) NOT NULL,
date timestamp with time zone NOT NULL,
provider_name character varying(100) NOT NULL,
cache_read_tokens bigint DEFAULT '0'::bigint NOT NULL,
cache_read_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
cache_creation_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
estimated_full_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT stats_daily_cost_savings_provider_pkey PRIMARY KEY (id),
CONSTRAINT uq_stats_daily_cost_savings_provider UNIQUE (date, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_provider_date
ON public.stats_daily_cost_savings_provider USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_provider_date_provider
ON public.stats_daily_cost_savings_provider USING btree (date, provider_name);
CREATE TABLE IF NOT EXISTS public.stats_daily_cost_savings_model (
id character varying(36) NOT NULL,
date timestamp with time zone NOT NULL,
model character varying(100) NOT NULL,
cache_read_tokens bigint DEFAULT '0'::bigint NOT NULL,
cache_read_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
cache_creation_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
estimated_full_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT stats_daily_cost_savings_model_pkey PRIMARY KEY (id),
CONSTRAINT uq_stats_daily_cost_savings_model UNIQUE (date, model)
);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_date
ON public.stats_daily_cost_savings_model USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_date_model
ON public.stats_daily_cost_savings_model USING btree (date, model);
CREATE TABLE IF NOT EXISTS public.stats_daily_cost_savings_model_provider (
id character varying(36) NOT NULL,
date timestamp with time zone NOT NULL,
model character varying(100) NOT NULL,
provider_name character varying(100) NOT NULL,
cache_read_tokens bigint DEFAULT '0'::bigint NOT NULL,
cache_read_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
cache_creation_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
estimated_full_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT stats_daily_cost_savings_model_provider_pkey PRIMARY KEY (id),
CONSTRAINT uq_stats_daily_cost_savings_model_provider UNIQUE (date, model, provider_name)
);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_provider_date
ON public.stats_daily_cost_savings_model_provider USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_daily_cost_savings_model_provider_date_dims
ON public.stats_daily_cost_savings_model_provider USING btree (date, model, provider_name);
CREATE TABLE IF NOT EXISTS public.stats_user_daily_cost_savings (
id character varying(36) NOT NULL,
user_id character varying(36) NOT NULL,
username character varying(100),
date timestamp with time zone NOT NULL,
cache_read_tokens bigint DEFAULT '0'::bigint NOT NULL,
cache_read_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
cache_creation_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
estimated_full_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT stats_user_daily_cost_savings_pkey PRIMARY KEY (id),
CONSTRAINT uq_stats_user_daily_cost_savings UNIQUE (user_id, date),
CONSTRAINT stats_user_daily_cost_savings_user_id_fkey
FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_date
ON public.stats_user_daily_cost_savings USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_user_date
ON public.stats_user_daily_cost_savings USING btree (user_id, date);
CREATE TABLE IF NOT EXISTS public.stats_user_daily_cost_savings_provider (
id character varying(36) NOT NULL,
user_id character varying(36) NOT NULL,
username character varying(100),
date timestamp with time zone NOT NULL,
provider_name character varying(100) NOT NULL,
cache_read_tokens bigint DEFAULT '0'::bigint NOT NULL,
cache_read_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
cache_creation_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
estimated_full_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT stats_user_daily_cost_savings_provider_pkey PRIMARY KEY (id),
CONSTRAINT uq_stats_user_daily_cost_savings_provider UNIQUE (user_id, date, provider_name),
CONSTRAINT stats_user_daily_cost_savings_provider_user_id_fkey
FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_provider_date
ON public.stats_user_daily_cost_savings_provider USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_provider_user_date
ON public.stats_user_daily_cost_savings_provider USING btree (user_id, date);
CREATE TABLE IF NOT EXISTS public.stats_user_daily_cost_savings_model (
id character varying(36) NOT NULL,
user_id character varying(36) NOT NULL,
username character varying(100),
date timestamp with time zone NOT NULL,
model character varying(100) NOT NULL,
cache_read_tokens bigint DEFAULT '0'::bigint NOT NULL,
cache_read_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
cache_creation_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
estimated_full_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT stats_user_daily_cost_savings_model_pkey PRIMARY KEY (id),
CONSTRAINT uq_stats_user_daily_cost_savings_model UNIQUE (user_id, date, model),
CONSTRAINT stats_user_daily_cost_savings_model_user_id_fkey
FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_date
ON public.stats_user_daily_cost_savings_model USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_user_date
ON public.stats_user_daily_cost_savings_model USING btree (user_id, date);
CREATE TABLE IF NOT EXISTS public.stats_user_daily_cost_savings_model_provider (
id character varying(36) NOT NULL,
user_id character varying(36) NOT NULL,
username character varying(100),
date timestamp with time zone NOT NULL,
model character varying(100) NOT NULL,
provider_name character varying(100) NOT NULL,
cache_read_tokens bigint DEFAULT '0'::bigint NOT NULL,
cache_read_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
cache_creation_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
estimated_full_cost numeric(20,8) DEFAULT '0'::double precision NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT stats_user_daily_cost_savings_model_provider_pkey PRIMARY KEY (id),
CONSTRAINT uq_stats_user_daily_cost_savings_model_provider
UNIQUE (user_id, date, model, provider_name),
CONSTRAINT stats_user_daily_cost_savings_model_provider_user_id_fkey
FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_provider_date
ON public.stats_user_daily_cost_savings_model_provider USING btree (date);
CREATE INDEX IF NOT EXISTS idx_stats_user_daily_cost_savings_model_provider_user_date
ON public.stats_user_daily_cost_savings_model_provider USING btree (user_id, date);
@@ -0,0 +1,50 @@
ALTER TABLE public.proxy_node_events
ADD COLUMN IF NOT EXISTS event_metadata json;
CREATE TABLE IF NOT EXISTS public.proxy_node_metrics_1m (
node_id character varying(36) NOT NULL,
bucket_start_unix_secs bigint NOT NULL,
samples bigint DEFAULT 0 NOT NULL,
uptime_samples bigint DEFAULT 0 NOT NULL,
active_connections_sum bigint DEFAULT 0 NOT NULL,
active_connections_max bigint DEFAULT 0 NOT NULL,
heartbeat_rtt_ms_sum bigint DEFAULT 0 NOT NULL,
heartbeat_rtt_ms_max bigint DEFAULT 0 NOT NULL,
connect_errors_delta bigint DEFAULT 0 NOT NULL,
disconnects_delta bigint DEFAULT 0 NOT NULL,
error_events_delta bigint DEFAULT 0 NOT NULL,
ws_in_bytes_delta bigint DEFAULT 0 NOT NULL,
ws_out_bytes_delta bigint DEFAULT 0 NOT NULL,
ws_in_frames_delta bigint DEFAULT 0 NOT NULL,
ws_out_frames_delta bigint DEFAULT 0 NOT NULL,
PRIMARY KEY (node_id, bucket_start_unix_secs),
CONSTRAINT proxy_node_metrics_1m_node_id_fkey
FOREIGN KEY (node_id) REFERENCES public.proxy_nodes(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS public.proxy_node_metrics_1h (
node_id character varying(36) NOT NULL,
bucket_start_unix_secs bigint NOT NULL,
samples bigint DEFAULT 0 NOT NULL,
uptime_samples bigint DEFAULT 0 NOT NULL,
active_connections_sum bigint DEFAULT 0 NOT NULL,
active_connections_max bigint DEFAULT 0 NOT NULL,
heartbeat_rtt_ms_sum bigint DEFAULT 0 NOT NULL,
heartbeat_rtt_ms_max bigint DEFAULT 0 NOT NULL,
connect_errors_delta bigint DEFAULT 0 NOT NULL,
disconnects_delta bigint DEFAULT 0 NOT NULL,
error_events_delta bigint DEFAULT 0 NOT NULL,
ws_in_bytes_delta bigint DEFAULT 0 NOT NULL,
ws_out_bytes_delta bigint DEFAULT 0 NOT NULL,
ws_in_frames_delta bigint DEFAULT 0 NOT NULL,
ws_out_frames_delta bigint DEFAULT 0 NOT NULL,
PRIMARY KEY (node_id, bucket_start_unix_secs),
CONSTRAINT proxy_node_metrics_1h_node_id_fkey
FOREIGN KEY (node_id) REFERENCES public.proxy_nodes(id) ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS idx_proxy_node_metrics_1m_bucket_start
ON public.proxy_node_metrics_1m (bucket_start_unix_secs);
CREATE INDEX IF NOT EXISTS idx_proxy_node_metrics_1h_bucket_start
ON public.proxy_node_metrics_1h (bucket_start_unix_secs);
@@ -0,0 +1,46 @@
CREATE TABLE IF NOT EXISTS public.background_task_runs (
id character varying(64) PRIMARY KEY,
task_key character varying(200) NOT NULL,
kind character varying(32) NOT NULL,
"trigger" character varying(64) NOT NULL,
status character varying(32) NOT NULL,
attempt integer NOT NULL DEFAULT 0,
max_attempts integer NOT NULL DEFAULT 0,
owner_instance character varying(200),
progress_percent integer NOT NULL DEFAULT 0,
progress_message text,
payload_json jsonb,
result_json jsonb,
error_message text,
cancel_requested boolean NOT NULL DEFAULT false,
created_by character varying(200),
created_at_unix_secs bigint NOT NULL,
started_at_unix_secs bigint,
finished_at_unix_secs bigint,
updated_at_unix_secs bigint NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_background_task_runs_task_key
ON public.background_task_runs (task_key);
CREATE INDEX IF NOT EXISTS idx_background_task_runs_status
ON public.background_task_runs (status);
CREATE INDEX IF NOT EXISTS idx_background_task_runs_kind
ON public.background_task_runs (kind);
CREATE INDEX IF NOT EXISTS idx_background_task_runs_created_at
ON public.background_task_runs (created_at_unix_secs DESC);
CREATE INDEX IF NOT EXISTS idx_background_task_runs_status_created
ON public.background_task_runs (status, created_at_unix_secs DESC, updated_at_unix_secs DESC);
CREATE INDEX IF NOT EXISTS idx_background_task_runs_kind_created
ON public.background_task_runs (kind, created_at_unix_secs DESC, updated_at_unix_secs DESC);
CREATE TABLE IF NOT EXISTS public.background_task_events (
id character varying(64) PRIMARY KEY,
run_id character varying(64) NOT NULL REFERENCES public.background_task_runs(id) ON DELETE CASCADE,
event_type character varying(64) NOT NULL,
message text NOT NULL,
payload_json jsonb,
created_at_unix_secs bigint NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_background_task_events_run_id
ON public.background_task_events (run_id, created_at_unix_secs ASC);
@@ -0,0 +1,82 @@
CREATE TABLE IF NOT EXISTS public.routing_groups (
id character varying(64) NOT NULL,
name character varying(255) NOT NULL,
description text,
enabled boolean DEFAULT true NOT NULL,
is_system_default boolean DEFAULT false NOT NULL,
config_json jsonb NOT NULL,
version bigint DEFAULT 1 NOT NULL,
created_at bigint NOT NULL,
updated_at bigint NOT NULL,
published_at bigint
);
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_constraint WHERE conname = 'routing_groups_pkey'
) THEN
ALTER TABLE ONLY public.routing_groups
ADD CONSTRAINT routing_groups_pkey PRIMARY KEY (id);
END IF;
IF NOT EXISTS (
SELECT 1 FROM pg_constraint WHERE conname = 'routing_groups_name_key'
) THEN
ALTER TABLE ONLY public.routing_groups
ADD CONSTRAINT routing_groups_name_key UNIQUE (name);
END IF;
END $$;
CREATE INDEX IF NOT EXISTS routing_groups_system_default_idx
ON public.routing_groups USING btree (is_system_default, enabled);
CREATE TABLE IF NOT EXISTS public.routing_group_bindings (
id character varying(64) NOT NULL,
group_id character varying(64) NOT NULL,
subject_type character varying(32) NOT NULL,
subject_id character varying(64) NOT NULL,
is_default boolean DEFAULT false NOT NULL,
allow_explicit_select boolean DEFAULT true NOT NULL,
created_at bigint NOT NULL,
updated_at bigint NOT NULL
);
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_constraint WHERE conname = 'routing_group_bindings_pkey'
) THEN
ALTER TABLE ONLY public.routing_group_bindings
ADD CONSTRAINT routing_group_bindings_pkey PRIMARY KEY (id);
END IF;
END $$;
CREATE INDEX IF NOT EXISTS routing_group_bindings_group_id_idx
ON public.routing_group_bindings USING btree (group_id);
CREATE INDEX IF NOT EXISTS routing_group_bindings_subject_idx
ON public.routing_group_bindings USING btree (subject_type, subject_id);
CREATE TABLE IF NOT EXISTS public.routing_group_versions (
id character varying(64) NOT NULL,
group_id character varying(64) NOT NULL,
version bigint NOT NULL,
config_json jsonb NOT NULL,
created_at bigint NOT NULL,
created_by character varying(64)
);
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_constraint WHERE conname = 'routing_group_versions_pkey'
) THEN
ALTER TABLE ONLY public.routing_group_versions
ADD CONSTRAINT routing_group_versions_pkey PRIMARY KEY (id);
END IF;
IF NOT EXISTS (
SELECT 1 FROM pg_constraint WHERE conname = 'routing_group_versions_group_version_key'
) THEN
ALTER TABLE ONLY public.routing_group_versions
ADD CONSTRAINT routing_group_versions_group_version_key UNIQUE (group_id, version);
END IF;
END $$;
CREATE INDEX IF NOT EXISTS routing_group_versions_group_id_idx
ON public.routing_group_versions USING btree (group_id);
@@ -0,0 +1,11 @@
-- Empty databases do not need a concurrent build: the snapshot runs before
-- traffic starts and executes inside a transaction.
CREATE INDEX IF NOT EXISTS idx_usage_legacy_body_ref_cleanup_created_at
ON public.usage (created_at, id)
WHERE request_metadata IS NOT NULL
AND (
request_metadata::jsonb ? 'request_body_ref'
OR request_metadata::jsonb ? 'provider_request_body_ref'
OR request_metadata::jsonb ? 'response_body_ref'
OR request_metadata::jsonb ? 'client_response_body_ref'
);
@@ -0,0 +1,14 @@
001_types_and_tables.sql
002_defaults.sql
003_constraints.sql
004_indexes.sql
005_foreign_keys.sql
006_footer.sql
100_usage_capture.sql
110_redeem_codes.sql
120_stats_rollups.sql
130_stats_cost_savings.sql
140_proxy_node_metrics.sql
150_background_tasks.sql
160_routing_profiles.sql
170_usage_legacy_body_ref_cleanup_index.sql