--
--

\restrict LV0qnjUH3SWL0aBPGm6cy1ZkmlSzDJdVUfB9wNeKmjDM3b1Te6x9rqoVJJo161S


SET transaction_timeout = 0;
SELECT pg_catalog.set_config('search_path', '', false);

DROP EVENT TRIGGER IF EXISTS pgrst_drop_watch;
DROP EVENT TRIGGER IF EXISTS pgrst_ddl_watch;
DROP EVENT TRIGGER IF EXISTS issue_pg_net_access;
DROP EVENT TRIGGER IF EXISTS issue_pg_graphql_access;
DROP EVENT TRIGGER IF EXISTS issue_pg_cron_access;
DROP EVENT TRIGGER IF EXISTS issue_graphql_placeholder;
DROP PUBLICATION IF EXISTS supabase_realtime_messages_publication;
DROP PUBLICATION IF EXISTS supabase_realtime;
DROP POLICY IF EXISTS frigate_models_update ON storage.objects;
DROP POLICY IF EXISTS frigate_models_select ON storage.objects;
DROP POLICY IF EXISTS frigate_models_insert ON storage.objects;
DROP POLICY IF EXISTS frigate_models_delete ON storage.objects;
DROP POLICY IF EXISTS "Users can view model files" ON storage.objects;
DROP POLICY IF EXISTS "Users can upload to their folder (form-attachments)" ON storage.objects;
DROP POLICY IF EXISTS "Users can update their own files (form-attachments)" ON storage.objects;
DROP POLICY IF EXISTS "Users can update their form logos" ON storage.objects;
DROP POLICY IF EXISTS "Users can delete their own files (form-attachments)" ON storage.objects;
DROP POLICY IF EXISTS "Users can delete their form logos" ON storage.objects;
DROP POLICY IF EXISTS "Super admin can manage model files" ON storage.objects;
DROP POLICY IF EXISTS "Public can view form attachments" ON storage.objects;
DROP POLICY IF EXISTS "Public can read model-files" ON storage.objects;
DROP POLICY IF EXISTS "Enable upload for authenticated users on test uploads" ON storage.objects;
DROP POLICY IF EXISTS "Enable upload for authenticated users on model files" ON storage.objects;
DROP POLICY IF EXISTS "Enable update for authenticated users on test uploads" ON storage.objects;
DROP POLICY IF EXISTS "Enable update for authenticated users on model files" ON storage.objects;
DROP POLICY IF EXISTS "Enable read for all users on test uploads" ON storage.objects;
DROP POLICY IF EXISTS "Enable read for all users on model files" ON storage.objects;
DROP POLICY IF EXISTS "Enable delete for authenticated users on test uploads" ON storage.objects;
DROP POLICY IF EXISTS "Enable delete for authenticated users on model files" ON storage.objects;
DROP POLICY IF EXISTS "Authenticated users can upload to model-files" ON storage.objects;
DROP POLICY IF EXISTS "Authenticated users can upload form logos" ON storage.objects;
DROP POLICY IF EXISTS "Authenticated users can update model-files" ON storage.objects;
DROP POLICY IF EXISTS "Authenticated users can delete model-files" ON storage.objects;
DROP POLICY IF EXISTS "Anyone can view form logos" ON storage.objects;
DROP POLICY IF EXISTS super_admin_system_settings_policy ON public.system_settings;
DROP POLICY IF EXISTS org_settings_view ON public.organization_settings;
DROP POLICY IF EXISTS org_settings_manage ON public.organization_settings;
DROP POLICY IF EXISTS frigate_triggers_all ON public.frigate_triggers;
DROP POLICY IF EXISTS frigate_sync_logs_all ON public.frigate_sync_logs;
DROP POLICY IF EXISTS frigate_stats_history_all ON public.frigate_stats_history;
DROP POLICY IF EXISTS frigate_model_sync_log_all ON public.frigate_model_sync_log;
DROP POLICY IF EXISTS frigate_model_registry_all ON public.frigate_model_registry;
DROP POLICY IF EXISTS frigate_model_deployments_all ON public.frigate_model_deployments;
DROP POLICY IF EXISTS frigate_deployed_models_all ON public.frigate_deployed_models;
DROP POLICY IF EXISTS autosync_view ON public.auto_sync_settings;
DROP POLICY IF EXISTS autosync_update ON public.auto_sync_settings;
DROP POLICY IF EXISTS aman_view_super_admin ON public.aman_instances;
DROP POLICY IF EXISTS aman_view_rep ON public.aman_instances;
DROP POLICY IF EXISTS aman_view_org_admin ON public.aman_instances;
DROP POLICY IF EXISTS aman_update_super ON public.aman_instances;
DROP POLICY IF EXISTS aman_update_org ON public.aman_instances;
DROP POLICY IF EXISTS aman_insert_super ON public.aman_instances;
DROP POLICY IF EXISTS aman_insert_org ON public.aman_instances;
DROP POLICY IF EXISTS aman_delete_super ON public.aman_instances;
DROP POLICY IF EXISTS aman_delete_org ON public.aman_instances;
DROP POLICY IF EXISTS "Users with admin/manager role can insert cameras" ON public.cameras;
DROP POLICY IF EXISTS "Users can view zones in their organization cameras" ON public.frigate_zones;
DROP POLICY IF EXISTS "Users can view timeline in their organization cameras" ON public.frigate_timeline;
DROP POLICY IF EXISTS "Users can view their own subscriptions" ON public.subscribers;
DROP POLICY IF EXISTS "Users can view their own subscription" ON public.subscribers;
DROP POLICY IF EXISTS "Users can view their own scan results" ON public.network_scan_results;
DROP POLICY IF EXISTS "Users can view their own roles" ON public.user_roles;
DROP POLICY IF EXISTS "Users can view their own branch roles" ON public.branch_roles;
DROP POLICY IF EXISTS "Users can view their own branch access" ON public.user_branch_access;
DROP POLICY IF EXISTS "Users can view their organization" ON public.organizations;
DROP POLICY IF EXISTS "Users can view security zones in their organization" ON public.security_zones;
DROP POLICY IF EXISTS "Users can view notification methods" ON public.notification_methods;
DROP POLICY IF EXISTS "Users can view license plates in their organization cameras" ON public.frigate_license_plates;
DROP POLICY IF EXISTS "Users can view groups in their organization" ON public.user_groups;
DROP POLICY IF EXISTS "Users can view group members in their organization" ON public.user_group_members;
DROP POLICY IF EXISTS "Users can view frigate instances in their organization" ON public.frigate_instances;
DROP POLICY IF EXISTS "Users can view form distribution in their organization" ON public.form_distribution_settings;
DROP POLICY IF EXISTS "Users can view faces in their organization cameras" ON public.frigate_faces;
DROP POLICY IF EXISTS "Users can view events in their organization" ON public.events;
DROP POLICY IF EXISTS "Users can view event types" ON public.event_types;
DROP POLICY IF EXISTS "Users can view detection rules in their organization" ON public.detection_rules;
DROP POLICY IF EXISTS "Users can view cameras in their organization" ON public.cameras;
DROP POLICY IF EXISTS "Users can view camera sources" ON public.camera_sources;
DROP POLICY IF EXISTS "Users can view camera event assignments in their organization" ON public.camera_event_assignments;
DROP POLICY IF EXISTS "Users can view camera alert assignments in their organization" ON public.camera_alert_assignments;
DROP POLICY IF EXISTS "Users can view branches in their organization" ON public.branches;
DROP POLICY IF EXISTS "Users can view all industries" ON public.industries;
DROP POLICY IF EXISTS "Users can view all frigate_reviews" ON public.frigate_reviews;
DROP POLICY IF EXISTS "Users can view all frigate_recordings" ON public.frigate_recordings;
DROP POLICY IF EXISTS "Users can view all frigate_previews" ON public.frigate_previews;
DROP POLICY IF EXISTS "Users can view all frigate_exports" ON public.frigate_exports;
DROP POLICY IF EXISTS "Users can view alert templates for their industry" ON public.alert_templates;
DROP POLICY IF EXISTS "Users can view alert template industries in their organization" ON public.alert_template_industries;
DROP POLICY IF EXISTS "Users can view alert template events" ON public.alert_template_events;
DROP POLICY IF EXISTS "Users can view alert rules in their organization cameras" ON public.frigate_alert_rules;
DROP POLICY IF EXISTS "Users can view active workflow forms" ON public.workflow_forms;
DROP POLICY IF EXISTS "Users can view active notification labels" ON public.notification_labels;
DROP POLICY IF EXISTS "Users can view Aman instances in their organization" ON public.aman_instances;
DROP POLICY IF EXISTS "Users can view AI models in their organization" ON public.ai_models;
DROP POLICY IF EXISTS "Users can view AI analysis logs in their org" ON public.ai_analysis_logs;
DROP POLICY IF EXISTS "Users can update their own subscriptions" ON public.subscribers;
DROP POLICY IF EXISTS "Users can update their own subscription" ON public.subscribers;
DROP POLICY IF EXISTS "Users can update frigate_reviews" ON public.frigate_reviews;
DROP POLICY IF EXISTS "Users can update frigate_recordings" ON public.frigate_recordings;
DROP POLICY IF EXISTS "Users can update frigate_previews" ON public.frigate_previews;
DROP POLICY IF EXISTS "Users can update frigate_exports" ON public.frigate_exports;
DROP POLICY IF EXISTS "Users can update event reviewed" ON public.events;
DROP POLICY IF EXISTS "Users can manage their own preferences" ON public.user_preferences;
DROP POLICY IF EXISTS "Users can insert their own scan results" ON public.network_scan_results;
DROP POLICY IF EXISTS "Users can insert frigate_reviews" ON public.frigate_reviews;
DROP POLICY IF EXISTS "Users can insert frigate_recordings" ON public.frigate_recordings;
DROP POLICY IF EXISTS "Users can insert frigate_previews" ON public.frigate_previews;
DROP POLICY IF EXISTS "Users can insert frigate_exports" ON public.frigate_exports;
DROP POLICY IF EXISTS "Users can delete frigate_reviews" ON public.frigate_reviews;
DROP POLICY IF EXISTS "Users can delete frigate_recordings" ON public.frigate_recordings;
DROP POLICY IF EXISTS "Users can delete frigate_previews" ON public.frigate_previews;
DROP POLICY IF EXISTS "Users can delete frigate_exports" ON public.frigate_exports;
DROP POLICY IF EXISTS "Users can create their own subscriptions" ON public.subscribers;
DROP POLICY IF EXISTS "Users can create security zones in their organization" ON public.security_zones;
DROP POLICY IF EXISTS "System can insert new subscribers" ON public.subscribers;
DROP POLICY IF EXISTS "System can insert frigate_timeline" ON public.frigate_timeline;
DROP POLICY IF EXISTS "System can insert frigate_reviews" ON public.frigate_reviews;
DROP POLICY IF EXISTS "System can insert frigate_recordings" ON public.frigate_recordings;
DROP POLICY IF EXISTS "System can insert frigate_previews" ON public.frigate_previews;
DROP POLICY IF EXISTS "System can insert events during sync" ON public.events;
DROP POLICY IF EXISTS "System can insert cameras during sync" ON public.cameras;
DROP POLICY IF EXISTS "Super admins can manage legal documents" ON public.legal_documents;
DROP POLICY IF EXISTS "Super admin can view and manage all messages" ON public.chat_messages;
DROP POLICY IF EXISTS "Super admin can view all pinned dashboards" ON public.pinned_dashboards;
DROP POLICY IF EXISTS "Super admin can view all form assignments" ON public.form_assignments;
DROP POLICY IF EXISTS "Super admin can view all branches" ON public.branches;
DROP POLICY IF EXISTS "Super admin can manage workflow forms" ON public.workflow_forms;
DROP POLICY IF EXISTS "Super admin can manage storage configs" ON public.storage_configs;
DROP POLICY IF EXISTS "Super admin can manage screen permissions" ON public.screen_permissions;
DROP POLICY IF EXISTS "Super admin can manage notification methods" ON public.notification_methods;
DROP POLICY IF EXISTS "Super admin can manage notification labels" ON public.notification_labels;
DROP POLICY IF EXISTS "Super admin can manage knowledge base" ON public.chatbot_knowledge_base;
DROP POLICY IF EXISTS "Super admin can manage form distribution" ON public.form_distribution_settings;
DROP POLICY IF EXISTS "Super admin can manage camera sources" ON public.camera_sources;
DROP POLICY IF EXISTS "Super admin can manage branch roles" ON public.branch_roles;
DROP POLICY IF EXISTS "Super admin can manage all user roles" ON public.user_roles;
DROP POLICY IF EXISTS "Super admin can manage all subscribers" ON public.subscribers;
DROP POLICY IF EXISTS "Super admin can manage all participants" ON public.chat_thread_participants;
DROP POLICY IF EXISTS "Super admin can manage all organizations" ON public.organizations;
DROP POLICY IF EXISTS "Super admin can manage all industries" ON public.industries;
DROP POLICY IF EXISTS "Super admin can manage all frigate zones" ON public.frigate_zones;
DROP POLICY IF EXISTS "Super admin can manage all frigate timeline" ON public.frigate_timeline;
DROP POLICY IF EXISTS "Super admin can manage all frigate license plates" ON public.frigate_license_plates;
DROP POLICY IF EXISTS "Super admin can manage all frigate instances" ON public.frigate_instances;
DROP POLICY IF EXISTS "Super admin can manage all frigate faces" ON public.frigate_faces;
DROP POLICY IF EXISTS "Super admin can manage all frigate alert rules" ON public.frigate_alert_rules;
DROP POLICY IF EXISTS "Super admin can manage all form submissions" ON public.form_submissions;
DROP POLICY IF EXISTS "Super admin can manage all form distribution settings" ON public.form_distribution_settings;
DROP POLICY IF EXISTS "Super admin can manage all event types" ON public.event_types;
DROP POLICY IF EXISTS "Super admin can manage all chat threads" ON public.chat_threads;
DROP POLICY IF EXISTS "Super admin can manage all camera alert assignments" ON public.camera_alert_assignments;
DROP POLICY IF EXISTS "Super admin can manage all branch access" ON public.user_branch_access;
DROP POLICY IF EXISTS "Super admin can manage all alert templates" ON public.alert_templates;
DROP POLICY IF EXISTS "Super admin can manage all Aman instances" ON public.aman_instances;
DROP POLICY IF EXISTS "Super admin can manage alert template industries" ON public.alert_template_industries;
DROP POLICY IF EXISTS "Super admin can manage alert template events" ON public.alert_template_events;
DROP POLICY IF EXISTS "Super admin can manage AI analysis logs" ON public.ai_analysis_logs;
DROP POLICY IF EXISTS "Representatives can view their assignments" ON public.form_assignments;
DROP POLICY IF EXISTS "Representatives can manage their own submissions" ON public.form_submissions;
DROP POLICY IF EXISTS "Participants can view messages in their threads" ON public.chat_messages;
DROP POLICY IF EXISTS "Participants can send messages to their threads" ON public.chat_messages;
DROP POLICY IF EXISTS "Org members can view participants for org threads" ON public.chat_thread_participants;
DROP POLICY IF EXISTS "Org members can view org threads" ON public.chat_threads;
DROP POLICY IF EXISTS "Org members can view form distribution settings" ON public.form_distribution_settings;
DROP POLICY IF EXISTS "Org members can update org threads" ON public.chat_threads;
DROP POLICY IF EXISTS "Org members can create threads in their org" ON public.chat_threads;
DROP POLICY IF EXISTS "Org members can add participants to their org threads" ON public.chat_thread_participants;
DROP POLICY IF EXISTS "Org admins/managers can view org user roles" ON public.user_roles;
DROP POLICY IF EXISTS "Org admins/managers can update submissions" ON public.form_submissions;
DROP POLICY IF EXISTS "Org admins/managers can manage form distribution settings" ON public.form_distribution_settings;
DROP POLICY IF EXISTS "Org admins can view org subscribers" ON public.subscribers;
DROP POLICY IF EXISTS "Org admins can view all subscribers" ON public.subscribers;
DROP POLICY IF EXISTS "Org admins can update subscribers" ON public.subscribers;
DROP POLICY IF EXISTS "Org admins can manage frigate instances in their organization" ON public.frigate_instances;
DROP POLICY IF EXISTS "Org admins and managers can view org pinned dashboards" ON public.pinned_dashboards;
DROP POLICY IF EXISTS "Labels: users can view their own" ON public.pinned_labels;
DROP POLICY IF EXISTS "Labels: users can update their own" ON public.pinned_labels;
DROP POLICY IF EXISTS "Labels: users can insert their own" ON public.pinned_labels;
DROP POLICY IF EXISTS "Labels: users can delete their own" ON public.pinned_labels;
DROP POLICY IF EXISTS "Company admins can manage branch access in their organization" ON public.user_branch_access;
DROP POLICY IF EXISTS "Branch managers can view branch user roles" ON public.user_roles;
DROP POLICY IF EXISTS "Branch managers can view branch pinned dashboards" ON public.pinned_dashboards;
DROP POLICY IF EXISTS "Branch managers can view branch form submissions" ON public.form_submissions;
DROP POLICY IF EXISTS "Branch managers can update branch form submissions" ON public.form_submissions;
DROP POLICY IF EXISTS "Authenticated users can view active screen permissions" ON public.screen_permissions;
DROP POLICY IF EXISTS "Anyone can view legal documents" ON public.legal_documents;
DROP POLICY IF EXISTS "Anyone can view active knowledge base" ON public.chatbot_knowledge_base;
DROP POLICY IF EXISTS "Admins can manage zones in their organization cameras" ON public.frigate_zones;
DROP POLICY IF EXISTS "Admins can manage faces in their organization" ON public.frigate_faces;
DROP POLICY IF EXISTS "Admins can manage alert rules in their organization cameras" ON public.frigate_alert_rules;
DROP POLICY IF EXISTS "Admins can manage AI models" ON public.ai_models;
DROP POLICY IF EXISTS "Admins and managers can view submissions in their organization" ON public.form_submissions;
DROP POLICY IF EXISTS "Admins and managers can update security zones" ON public.security_zones;
DROP POLICY IF EXISTS "Admins and managers can update cameras" ON public.cameras;
DROP POLICY IF EXISTS "Admins and managers can manage groups" ON public.user_groups;
DROP POLICY IF EXISTS "Admins and managers can manage group members" ON public.user_group_members;
DROP POLICY IF EXISTS "Admins and managers can manage form assignments" ON public.form_assignments;
DROP POLICY IF EXISTS "Admins and managers can manage detection rules" ON public.detection_rules;
DROP POLICY IF EXISTS "Admins and managers can manage camera event assignments" ON public.camera_event_assignments;
DROP POLICY IF EXISTS "Admins and managers can manage Aman instances" ON public.aman_instances;
DROP POLICY IF EXISTS "Admins and managers can delete security zones" ON public.security_zones;
DROP POLICY IF EXISTS "Admins and managers can delete cameras" ON public.cameras;
ALTER TABLE IF EXISTS ONLY storage.vector_indexes DROP CONSTRAINT IF EXISTS vector_indexes_bucket_id_fkey;
ALTER TABLE IF EXISTS ONLY storage.s3_multipart_uploads_parts DROP CONSTRAINT IF EXISTS s3_multipart_uploads_parts_upload_id_fkey;
ALTER TABLE IF EXISTS ONLY storage.s3_multipart_uploads_parts DROP CONSTRAINT IF EXISTS s3_multipart_uploads_parts_bucket_id_fkey;
ALTER TABLE IF EXISTS ONLY storage.s3_multipart_uploads DROP CONSTRAINT IF EXISTS s3_multipart_uploads_bucket_id_fkey;
ALTER TABLE IF EXISTS ONLY storage.objects DROP CONSTRAINT IF EXISTS "objects_bucketId_fkey";
ALTER TABLE IF EXISTS ONLY storage.iceberg_tables DROP CONSTRAINT IF EXISTS iceberg_tables_namespace_id_fkey;
ALTER TABLE IF EXISTS ONLY storage.iceberg_tables DROP CONSTRAINT IF EXISTS iceberg_tables_catalog_id_fkey;
ALTER TABLE IF EXISTS ONLY storage.iceberg_namespaces DROP CONSTRAINT IF EXISTS iceberg_namespaces_catalog_id_fkey;
ALTER TABLE IF EXISTS ONLY public.user_roles DROP CONSTRAINT IF EXISTS user_roles_user_id_fkey;
ALTER TABLE IF EXISTS ONLY public.user_roles DROP CONSTRAINT IF EXISTS user_roles_organization_id_fkey;
ALTER TABLE IF EXISTS ONLY public.user_roles DROP CONSTRAINT IF EXISTS user_roles_granted_by_fkey;
ALTER TABLE IF EXISTS ONLY public.user_preferences DROP CONSTRAINT IF EXISTS user_preferences_user_id_fkey;
ALTER TABLE IF EXISTS ONLY public.user_groups DROP CONSTRAINT IF EXISTS user_groups_organization_id_fkey;
ALTER TABLE IF EXISTS ONLY public.user_group_members DROP CONSTRAINT IF EXISTS user_group_members_user_role_id_fkey;
ALTER TABLE IF EXISTS ONLY public.user_group_members DROP CONSTRAINT IF EXISTS user_group_members_group_id_fkey;
ALTER TABLE IF EXISTS ONLY public.user_branch_access DROP CONSTRAINT IF EXISTS user_branch_access_user_id_fkey;
ALTER TABLE IF EXISTS ONLY public.user_branch_access DROP CONSTRAINT IF EXISTS user_branch_access_granted_by_fkey;
ALTER TABLE IF EXISTS ONLY public.user_branch_access DROP CONSTRAINT IF EXISTS user_branch_access_branch_id_fkey;
ALTER TABLE IF EXISTS ONLY public.system_settings DROP CONSTRAINT IF EXISTS system_settings_updated_by_fkey;
ALTER TABLE IF EXISTS ONLY public.subscribers DROP CONSTRAINT IF EXISTS subscribers_user_id_fkey;
ALTER TABLE IF EXISTS ONLY public.subscribers DROP CONSTRAINT IF EXISTS subscribers_organization_id_fkey;
ALTER TABLE IF EXISTS ONLY public.subscribers DROP CONSTRAINT IF EXISTS subscribers_approved_by_fkey;
ALTER TABLE IF EXISTS ONLY public.students DROP CONSTRAINT IF EXISTS students_organization_id_fkey;
ALTER TABLE IF EXISTS ONLY public.students DROP CONSTRAINT IF EXISTS students_branch_id_fkey;
ALTER TABLE IF EXISTS ONLY public.storage_configs DROP CONSTRAINT IF EXISTS storage_configs_created_by_fkey;
ALTER TABLE IF EXISTS ONLY public.security_zones DROP CONSTRAINT IF EXISTS security_zones_branch_id_fkey;
ALTER TABLE IF EXISTS ONLY public.organizations DROP CONSTRAINT IF EXISTS organizations_industry_id_fkey;
ALTER TABLE IF EXISTS ONLY public.organization_settings DROP CONSTRAINT IF EXISTS organization_settings_organization_id_fkey;
ALTER TABLE IF EXISTS ONLY public.notification_methods DROP CONSTRAINT IF EXISTS notification_methods_created_by_fkey;
ALTER TABLE IF EXISTS ONLY public.network_scan_results DROP CONSTRAINT IF EXISTS network_scan_results_user_id_fkey;
ALTER TABLE IF EXISTS ONLY public.legal_documents DROP CONSTRAINT IF EXISTS legal_documents_updated_by_fkey;
ALTER TABLE IF EXISTS ONLY public.legal_documents DROP CONSTRAINT IF EXISTS legal_documents_created_by_fkey;
ALTER TABLE IF EXISTS ONLY public.health_alerts DROP CONSTRAINT IF EXISTS health_alerts_student_id_fkey;
ALTER TABLE IF EXISTS ONLY public.frigate_zones DROP CONSTRAINT IF EXISTS frigate_zones_camera_id_fkey;
ALTER TABLE IF EXISTS ONLY public.frigate_triggers DROP CONSTRAINT IF EXISTS frigate_triggers_frigate_instance_id_fkey;
ALTER TABLE IF EXISTS ONLY public.frigate_timeline DROP CONSTRAINT IF EXISTS frigate_timeline_camera_id_fkey;
ALTER TABLE IF EXISTS ONLY public.frigate_sync_logs DROP CONSTRAINT IF EXISTS frigate_sync_logs_frigate_instance_id_fkey;
ALTER TABLE IF EXISTS ONLY public.frigate_stats_history DROP CONSTRAINT IF EXISTS frigate_stats_history_frigate_instance_id_fkey;
ALTER TABLE IF EXISTS ONLY public.frigate_model_sync_log DROP CONSTRAINT IF EXISTS frigate_model_sync_log_frigate_instance_id_fkey;
ALTER TABLE IF EXISTS ONLY public.frigate_model_deployments DROP CONSTRAINT IF EXISTS frigate_model_deployments_frigate_instance_id_fkey;
ALTER TABLE IF EXISTS ONLY public.frigate_model_deployments DROP CONSTRAINT IF EXISTS frigate_model_deployments_deployed_by_fkey;
ALTER TABLE IF EXISTS ONLY public.frigate_license_plates DROP CONSTRAINT IF EXISTS frigate_license_plates_frigate_instance_id_fkey;
ALTER TABLE IF EXISTS ONLY public.frigate_license_plates DROP CONSTRAINT IF EXISTS frigate_license_plates_camera_id_fkey;
ALTER TABLE IF EXISTS ONLY public.frigate_instances DROP CONSTRAINT IF EXISTS frigate_instances_branch_id_fkey;
ALTER TABLE IF EXISTS ONLY public.frigate_faces DROP CONSTRAINT IF EXISTS frigate_faces_camera_id_fkey;
ALTER TABLE IF EXISTS ONLY public.frigate_deployed_models DROP CONSTRAINT IF EXISTS frigate_deployed_models_frigate_instance_id_fkey;
ALTER TABLE IF EXISTS ONLY public.frigate_alert_rules DROP CONSTRAINT IF EXISTS frigate_alert_rules_camera_id_fkey;
ALTER TABLE IF EXISTS ONLY public.form_submissions DROP CONSTRAINT IF EXISTS form_submissions_form_assignment_id_fkey;
ALTER TABLE IF EXISTS ONLY public.form_distribution_settings DROP CONSTRAINT IF EXISTS form_distribution_settings_workflow_form_id_fkey;
ALTER TABLE IF EXISTS ONLY public.form_assignments DROP CONSTRAINT IF EXISTS form_assignments_workflow_form_id_fkey;
ALTER TABLE IF EXISTS ONLY public.frigate_timeline DROP CONSTRAINT IF EXISTS fk_frigate_timeline_instance;
ALTER TABLE IF EXISTS ONLY public.frigate_reviews DROP CONSTRAINT IF EXISTS fk_frigate_reviews_instance;
ALTER TABLE IF EXISTS ONLY public.frigate_recordings DROP CONSTRAINT IF EXISTS fk_frigate_recordings_instance;
ALTER TABLE IF EXISTS ONLY public.frigate_previews DROP CONSTRAINT IF EXISTS fk_frigate_previews_instance;
ALTER TABLE IF EXISTS ONLY public.frigate_exports DROP CONSTRAINT IF EXISTS fk_frigate_exports_instance;
ALTER TABLE IF EXISTS ONLY public.events DROP CONSTRAINT IF EXISTS events_camera_id_fkey;
ALTER TABLE IF EXISTS ONLY public.detection_rules DROP CONSTRAINT IF EXISTS detection_rules_organization_id_fkey;
ALTER TABLE IF EXISTS ONLY public.chat_threads DROP CONSTRAINT IF EXISTS chat_threads_organization_id_fkey;
ALTER TABLE IF EXISTS ONLY public.chat_thread_participants DROP CONSTRAINT IF EXISTS chat_thread_participants_thread_id_fkey;
ALTER TABLE IF EXISTS ONLY public.chat_messages DROP CONSTRAINT IF EXISTS chat_messages_thread_id_fkey;
ALTER TABLE IF EXISTS ONLY public.cameras DROP CONSTRAINT IF EXISTS cameras_security_zone_id_fkey;
ALTER TABLE IF EXISTS ONLY public.cameras DROP CONSTRAINT IF EXISTS cameras_frigate_instance_id_fkey;
ALTER TABLE IF EXISTS ONLY public.cameras DROP CONSTRAINT IF EXISTS cameras_branch_id_fkey;
ALTER TABLE IF EXISTS ONLY public.camera_sources DROP CONSTRAINT IF EXISTS camera_sources_created_by_fkey;
ALTER TABLE IF EXISTS ONLY public.camera_alert_assignments DROP CONSTRAINT IF EXISTS camera_alert_assignments_alert_template_id_fkey;
ALTER TABLE IF EXISTS ONLY public.branches DROP CONSTRAINT IF EXISTS branches_organization_id_fkey;
ALTER TABLE IF EXISTS ONLY public.branch_roles DROP CONSTRAINT IF EXISTS branch_roles_user_id_fkey;
ALTER TABLE IF EXISTS ONLY public.branch_roles DROP CONSTRAINT IF EXISTS branch_roles_branch_id_fkey;
ALTER TABLE IF EXISTS ONLY public.alert_templates DROP CONSTRAINT IF EXISTS alert_templates_created_by_fkey;
ALTER TABLE IF EXISTS ONLY public.alert_template_industries DROP CONSTRAINT IF EXISTS alert_template_industries_industry_id_fkey;
ALTER TABLE IF EXISTS ONLY public.alert_template_industries DROP CONSTRAINT IF EXISTS alert_template_industries_alert_template_id_fkey;
ALTER TABLE IF EXISTS ONLY public.alert_template_events DROP CONSTRAINT IF EXISTS alert_template_events_event_type_id_fkey;
ALTER TABLE IF EXISTS ONLY public.alert_template_events DROP CONSTRAINT IF EXISTS alert_template_events_alert_template_id_fkey;
ALTER TABLE IF EXISTS ONLY public.ai_analysis_logs DROP CONSTRAINT IF EXISTS ai_analysis_logs_camera_id_fkey;
ALTER TABLE IF EXISTS ONLY public.ai_analysis_logs DROP CONSTRAINT IF EXISTS ai_analysis_logs_alert_template_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.webauthn_credentials DROP CONSTRAINT IF EXISTS webauthn_credentials_user_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.webauthn_challenges DROP CONSTRAINT IF EXISTS webauthn_challenges_user_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.sso_domains DROP CONSTRAINT IF EXISTS sso_domains_sso_provider_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.sessions DROP CONSTRAINT IF EXISTS sessions_user_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.sessions DROP CONSTRAINT IF EXISTS sessions_oauth_client_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.saml_relay_states DROP CONSTRAINT IF EXISTS saml_relay_states_sso_provider_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.saml_relay_states DROP CONSTRAINT IF EXISTS saml_relay_states_flow_state_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.saml_providers DROP CONSTRAINT IF EXISTS saml_providers_sso_provider_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.refresh_tokens DROP CONSTRAINT IF EXISTS refresh_tokens_session_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.one_time_tokens DROP CONSTRAINT IF EXISTS one_time_tokens_user_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.oauth_consents DROP CONSTRAINT IF EXISTS oauth_consents_user_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.oauth_consents DROP CONSTRAINT IF EXISTS oauth_consents_client_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.oauth_authorizations DROP CONSTRAINT IF EXISTS oauth_authorizations_user_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.oauth_authorizations DROP CONSTRAINT IF EXISTS oauth_authorizations_client_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.mfa_factors DROP CONSTRAINT IF EXISTS mfa_factors_user_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.mfa_challenges DROP CONSTRAINT IF EXISTS mfa_challenges_auth_factor_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.mfa_amr_claims DROP CONSTRAINT IF EXISTS mfa_amr_claims_session_id_fkey;
ALTER TABLE IF EXISTS ONLY auth.identities DROP CONSTRAINT IF EXISTS identities_user_id_fkey;
ALTER TABLE IF EXISTS ONLY _realtime.extensions DROP CONSTRAINT IF EXISTS extensions_tenant_external_id_fkey;
DROP TRIGGER IF EXISTS update_objects_updated_at ON storage.objects;
DROP TRIGGER IF EXISTS protect_objects_delete ON storage.objects;
DROP TRIGGER IF EXISTS protect_buckets_delete ON storage.buckets;
DROP TRIGGER IF EXISTS enforce_bucket_name_length_trigger ON storage.buckets;
DROP TRIGGER IF EXISTS tr_check_filters ON realtime.subscription;
DROP TRIGGER IF EXISTS update_workflow_forms_updated_at ON public.workflow_forms;
DROP TRIGGER IF EXISTS update_user_preferences_updated_at ON public.user_preferences;
DROP TRIGGER IF EXISTS update_user_groups_updated_at ON public.user_groups;
DROP TRIGGER IF EXISTS update_system_settings_updated_at ON public.system_settings;
DROP TRIGGER IF EXISTS update_subscribers_updated_at ON public.subscribers;
DROP TRIGGER IF EXISTS update_storage_configs_updated_at ON public.storage_configs;
DROP TRIGGER IF EXISTS update_security_zones_updated_at ON public.security_zones;
DROP TRIGGER IF EXISTS update_pinned_dashboards_updated_at ON public.pinned_dashboards;
DROP TRIGGER IF EXISTS update_organizations_modtime ON public.organizations;
DROP TRIGGER IF EXISTS update_organization_settings_updated_at ON public.organization_settings;
DROP TRIGGER IF EXISTS update_notification_methods_updated_at ON public.notification_methods;
DROP TRIGGER IF EXISTS update_notification_labels_updated_at ON public.notification_labels;
DROP TRIGGER IF EXISTS update_legal_documents_updated_at ON public.legal_documents;
DROP TRIGGER IF EXISTS update_industries_updated_at ON public.industries;
DROP TRIGGER IF EXISTS update_frigate_reviews_updated_at ON public.frigate_reviews;
DROP TRIGGER IF EXISTS update_frigate_recordings_updated_at ON public.frigate_recordings;
DROP TRIGGER IF EXISTS update_frigate_previews_updated_at ON public.frigate_previews;
DROP TRIGGER IF EXISTS update_frigate_instances_updated_at ON public.frigate_instances;
DROP TRIGGER IF EXISTS update_frigate_exports_updated_at ON public.frigate_exports;
DROP TRIGGER IF EXISTS update_form_distribution_settings_updated_at ON public.form_distribution_settings;
DROP TRIGGER IF EXISTS update_form_assignments_updated_at ON public.form_assignments;
DROP TRIGGER IF EXISTS update_event_types_updated_at ON public.event_types;
DROP TRIGGER IF EXISTS update_chatbot_knowledge_base_updated_at ON public.chatbot_knowledge_base;
DROP TRIGGER IF EXISTS update_cameras_updated_at ON public.cameras;
DROP TRIGGER IF EXISTS update_camera_sources_updated_at ON public.camera_sources;
DROP TRIGGER IF EXISTS update_auto_sync_settings_updated_at ON public.auto_sync_settings;
DROP TRIGGER IF EXISTS update_aman_instances_updated_at ON public.aman_instances;
DROP TRIGGER IF EXISTS update_alert_templates_updated_at ON public.alert_templates;
DROP TRIGGER IF EXISTS trg_veedon_bump_cameras ON public.cameras;
DROP TRIGGER IF EXISTS trg_veedon_bump_assignments ON public.camera_event_assignments;
DROP TRIGGER IF EXISTS trg_touch_thread_after_message_insert ON public.chat_messages;
DROP TRIGGER IF EXISTS trg_restrict_events_update ON public.events;
DROP TRIGGER IF EXISTS trg_registry_updated ON public.frigate_model_registry;
DROP TRIGGER IF EXISTS trg_pinned_labels_updated_at ON public.pinned_labels;
DROP TRIGGER IF EXISTS trg_deployments_updated ON public.frigate_model_deployments;
DROP TRIGGER IF EXISTS trg_chat_threads_updated_at ON public.chat_threads;
DROP TRIGGER IF EXISTS touch_thread_on_message_insert ON public.chat_messages;
DROP TRIGGER IF EXISTS set_updated_at_chat_threads ON public.chat_threads;
DROP TRIGGER IF EXISTS set_updated_at ON public.frigate_zones;
DROP TRIGGER IF EXISTS set_updated_at ON public.frigate_license_plates;
DROP TRIGGER IF EXISTS set_updated_at ON public.frigate_faces;
DROP TRIGGER IF EXISTS set_updated_at ON public.frigate_alert_rules;
DROP TRIGGER IF EXISTS handle_screen_permissions_updated_at ON public.screen_permissions;
DROP TRIGGER IF EXISTS update_subscriber_activity_trigger ON auth.sessions;
DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users;
DROP INDEX IF EXISTS supabase_functions.supabase_functions_hooks_request_id_idx;
DROP INDEX IF EXISTS supabase_functions.supabase_functions_hooks_h_table_id_h_name_idx;
DROP INDEX IF EXISTS storage.vector_indexes_name_bucket_id_idx;
DROP INDEX IF EXISTS storage.name_prefix_search;
DROP INDEX IF EXISTS storage.idx_objects_bucket_id_name_lower;
DROP INDEX IF EXISTS storage.idx_objects_bucket_id_name;
DROP INDEX IF EXISTS storage.idx_multipart_uploads_list;
DROP INDEX IF EXISTS storage.idx_iceberg_tables_namespace_id;
DROP INDEX IF EXISTS storage.idx_iceberg_tables_location;
DROP INDEX IF EXISTS storage.idx_iceberg_namespaces_bucket_id;
DROP INDEX IF EXISTS storage.buckets_analytics_unique_name_idx;
DROP INDEX IF EXISTS storage.bucketid_objname;
DROP INDEX IF EXISTS storage.bname;
DROP INDEX IF EXISTS realtime.subscription_subscription_id_entity_filters_action_filter_selec;
DROP INDEX IF EXISTS realtime.messages_inserted_at_topic_index;
DROP INDEX IF EXISTS realtime.ix_realtime_subscription_entity;
DROP INDEX IF EXISTS public.idx_system_settings_key;
DROP INDEX IF EXISTS public.idx_sync_log_started;
DROP INDEX IF EXISTS public.idx_sync_log_instance;
DROP INDEX IF EXISTS public.idx_security_zones_active;
DROP INDEX IF EXISTS public.idx_pinned_labels_user_id;
DROP INDEX IF EXISTS public.idx_pinned_dashboards_user_id;
DROP INDEX IF EXISTS public.idx_org_settings_org_key;
DROP INDEX IF EXISTS public.idx_model_registry_status;
DROP INDEX IF EXISTS public.idx_model_registry_category;
DROP INDEX IF EXISTS public.idx_model_deployments_status;
DROP INDEX IF EXISTS public.idx_model_deployments_model;
DROP INDEX IF EXISTS public.idx_model_deployments_instance;
DROP INDEX IF EXISTS public.idx_health_alerts_time;
DROP INDEX IF EXISTS public.idx_health_alerts_student;
DROP INDEX IF EXISTS public.idx_frigate_zones_camera_id;
DROP INDEX IF EXISTS public.idx_frigate_triggers_instance;
DROP INDEX IF EXISTS public.idx_frigate_timeline_time;
DROP INDEX IF EXISTS public.idx_frigate_timeline_camera_id;
DROP INDEX IF EXISTS public.idx_frigate_sync_logs_started;
DROP INDEX IF EXISTS public.idx_frigate_sync_logs_instance;
DROP INDEX IF EXISTS public.idx_frigate_stats_history_recorded;
DROP INDEX IF EXISTS public.idx_frigate_stats_history_instance;
DROP INDEX IF EXISTS public.idx_frigate_reviews_severity;
DROP INDEX IF EXISTS public.idx_frigate_reviews_reviewed_new;
DROP INDEX IF EXISTS public.idx_frigate_reviews_reviewed;
DROP INDEX IF EXISTS public.idx_frigate_reviews_instance_camera;
DROP INDEX IF EXISTS public.idx_frigate_recordings_time;
DROP INDEX IF EXISTS public.idx_frigate_recordings_instance_camera;
DROP INDEX IF EXISTS public.idx_frigate_previews_time;
DROP INDEX IF EXISTS public.idx_frigate_previews_instance_camera;
DROP INDEX IF EXISTS public.idx_frigate_license_plates_watch;
DROP INDEX IF EXISTS public.idx_frigate_license_plates_plate_number;
DROP INDEX IF EXISTS public.idx_frigate_license_plates_instance;
DROP INDEX IF EXISTS public.idx_frigate_license_plates_camera_id;
DROP INDEX IF EXISTS public.idx_frigate_faces_label;
DROP INDEX IF EXISTS public.idx_frigate_faces_camera_id;
DROP INDEX IF EXISTS public.idx_frigate_exports_status;
DROP INDEX IF EXISTS public.idx_frigate_exports_instance_camera;
DROP INDEX IF EXISTS public.idx_frigate_deployed_models_status;
DROP INDEX IF EXISTS public.idx_frigate_deployed_models_instance;
DROP INDEX IF EXISTS public.idx_frigate_deployed_models_category;
DROP INDEX IF EXISTS public.idx_events_license_plate;
DROP INDEX IF EXISTS public.idx_events_frigate_id;
DROP INDEX IF EXISTS public.idx_events_face_id;
DROP INDEX IF EXISTS public.idx_events_detected_at;
DROP INDEX IF EXISTS public.idx_events_camera_id;
DROP INDEX IF EXISTS public.idx_event_types_feature_key;
DROP INDEX IF EXISTS public.idx_chatbot_knowledge_language_type;
DROP INDEX IF EXISTS public.idx_chatbot_knowledge_active;
DROP INDEX IF EXISTS public.idx_chat_threads_org;
DROP INDEX IF EXISTS public.idx_chat_participants_user;
DROP INDEX IF EXISTS public.idx_chat_participants_thread;
DROP INDEX IF EXISTS public.idx_chat_messages_thread_created;
DROP INDEX IF EXISTS public.idx_cameras_branch_id;
DROP INDEX IF EXISTS public.idx_aman_instances_org;
DROP INDEX IF EXISTS public.idx_aman_instances_branch;
DROP INDEX IF EXISTS auth.webauthn_credentials_user_id_idx;
DROP INDEX IF EXISTS auth.webauthn_credentials_credential_id_key;
DROP INDEX IF EXISTS auth.webauthn_challenges_user_id_idx;
DROP INDEX IF EXISTS auth.webauthn_challenges_expires_at_idx;
DROP INDEX IF EXISTS auth.users_is_anonymous_idx;
DROP INDEX IF EXISTS auth.users_instance_id_idx;
DROP INDEX IF EXISTS auth.users_instance_id_email_idx;
DROP INDEX IF EXISTS auth.users_email_partial_key;
DROP INDEX IF EXISTS auth.user_id_created_at_idx;
DROP INDEX IF EXISTS auth.unique_phone_factor_per_user;
DROP INDEX IF EXISTS auth.sso_providers_resource_id_pattern_idx;
DROP INDEX IF EXISTS auth.sso_providers_resource_id_idx;
DROP INDEX IF EXISTS auth.sso_domains_sso_provider_id_idx;
DROP INDEX IF EXISTS auth.sso_domains_domain_idx;
DROP INDEX IF EXISTS auth.sessions_user_id_idx;
DROP INDEX IF EXISTS auth.sessions_oauth_client_id_idx;
DROP INDEX IF EXISTS auth.sessions_not_after_idx;
DROP INDEX IF EXISTS auth.saml_relay_states_sso_provider_id_idx;
DROP INDEX IF EXISTS auth.saml_relay_states_for_email_idx;
DROP INDEX IF EXISTS auth.saml_relay_states_created_at_idx;
DROP INDEX IF EXISTS auth.saml_providers_sso_provider_id_idx;
DROP INDEX IF EXISTS auth.refresh_tokens_updated_at_idx;
DROP INDEX IF EXISTS auth.refresh_tokens_session_id_revoked_idx;
DROP INDEX IF EXISTS auth.refresh_tokens_parent_idx;
DROP INDEX IF EXISTS auth.refresh_tokens_instance_id_user_id_idx;
DROP INDEX IF EXISTS auth.refresh_tokens_instance_id_idx;
DROP INDEX IF EXISTS auth.recovery_token_idx;
DROP INDEX IF EXISTS auth.reauthentication_token_idx;
DROP INDEX IF EXISTS auth.one_time_tokens_user_id_token_type_key;
DROP INDEX IF EXISTS auth.one_time_tokens_token_hash_hash_idx;
DROP INDEX IF EXISTS auth.one_time_tokens_relates_to_hash_idx;
DROP INDEX IF EXISTS auth.oauth_consents_user_order_idx;
DROP INDEX IF EXISTS auth.oauth_consents_active_user_client_idx;
DROP INDEX IF EXISTS auth.oauth_consents_active_client_idx;
DROP INDEX IF EXISTS auth.oauth_clients_deleted_at_idx;
DROP INDEX IF EXISTS auth.oauth_auth_pending_exp_idx;
DROP INDEX IF EXISTS auth.mfa_factors_user_id_idx;
DROP INDEX IF EXISTS auth.mfa_factors_user_friendly_name_unique;
DROP INDEX IF EXISTS auth.mfa_challenge_created_at_idx;
DROP INDEX IF EXISTS auth.idx_user_id_auth_method;
DROP INDEX IF EXISTS auth.idx_oauth_client_states_created_at;
DROP INDEX IF EXISTS auth.idx_auth_code;
DROP INDEX IF EXISTS auth.identities_user_id_idx;
DROP INDEX IF EXISTS auth.identities_email_idx;
DROP INDEX IF EXISTS auth.flow_state_created_at_idx;
DROP INDEX IF EXISTS auth.factor_id_created_at_idx;
DROP INDEX IF EXISTS auth.email_change_token_new_idx;
DROP INDEX IF EXISTS auth.email_change_token_current_idx;
DROP INDEX IF EXISTS auth.custom_oauth_providers_provider_type_idx;
DROP INDEX IF EXISTS auth.custom_oauth_providers_identifier_idx;
DROP INDEX IF EXISTS auth.custom_oauth_providers_enabled_idx;
DROP INDEX IF EXISTS auth.custom_oauth_providers_created_at_idx;
DROP INDEX IF EXISTS auth.confirmation_token_idx;
DROP INDEX IF EXISTS auth.audit_logs_instance_id_idx;
DROP INDEX IF EXISTS _realtime.tenants_external_id_index;
DROP INDEX IF EXISTS _realtime.feature_flags_name_index;
DROP INDEX IF EXISTS _realtime.extensions_tenant_external_id_type_index;
DROP INDEX IF EXISTS _realtime.extensions_tenant_external_id_index;
ALTER TABLE IF EXISTS ONLY supabase_migrations.schema_migrations DROP CONSTRAINT IF EXISTS schema_migrations_pkey;
ALTER TABLE IF EXISTS ONLY supabase_functions.migrations DROP CONSTRAINT IF EXISTS migrations_pkey;
ALTER TABLE IF EXISTS ONLY supabase_functions.hooks DROP CONSTRAINT IF EXISTS hooks_pkey;
ALTER TABLE IF EXISTS ONLY storage.vector_indexes DROP CONSTRAINT IF EXISTS vector_indexes_pkey;
ALTER TABLE IF EXISTS ONLY storage.s3_multipart_uploads DROP CONSTRAINT IF EXISTS s3_multipart_uploads_pkey;
ALTER TABLE IF EXISTS ONLY storage.s3_multipart_uploads_parts DROP CONSTRAINT IF EXISTS s3_multipart_uploads_parts_pkey;
ALTER TABLE IF EXISTS ONLY storage.objects DROP CONSTRAINT IF EXISTS objects_pkey;
ALTER TABLE IF EXISTS ONLY storage.migrations DROP CONSTRAINT IF EXISTS migrations_pkey;
ALTER TABLE IF EXISTS ONLY storage.migrations DROP CONSTRAINT IF EXISTS migrations_name_key;
ALTER TABLE IF EXISTS ONLY storage.iceberg_tables DROP CONSTRAINT IF EXISTS iceberg_tables_pkey;
ALTER TABLE IF EXISTS ONLY storage.iceberg_namespaces DROP CONSTRAINT IF EXISTS iceberg_namespaces_pkey;
ALTER TABLE IF EXISTS ONLY storage.buckets_vectors DROP CONSTRAINT IF EXISTS buckets_vectors_pkey;
ALTER TABLE IF EXISTS ONLY storage.buckets DROP CONSTRAINT IF EXISTS buckets_pkey;
ALTER TABLE IF EXISTS ONLY storage.buckets_analytics DROP CONSTRAINT IF EXISTS buckets_analytics_pkey;
ALTER TABLE IF EXISTS ONLY realtime.schema_migrations DROP CONSTRAINT IF EXISTS schema_migrations_pkey;
ALTER TABLE IF EXISTS ONLY realtime.subscription DROP CONSTRAINT IF EXISTS pk_subscription;
ALTER TABLE IF EXISTS realtime.messages DROP CONSTRAINT IF EXISTS messages_payload_exclusive;
ALTER TABLE IF EXISTS ONLY realtime.messages_2026_07_08 DROP CONSTRAINT IF EXISTS messages_2026_07_08_pkey;
ALTER TABLE IF EXISTS ONLY realtime.messages_2026_07_07 DROP CONSTRAINT IF EXISTS messages_2026_07_07_pkey;
ALTER TABLE IF EXISTS ONLY realtime.messages_2026_07_06 DROP CONSTRAINT IF EXISTS messages_2026_07_06_pkey;
ALTER TABLE IF EXISTS ONLY realtime.messages_2026_07_05 DROP CONSTRAINT IF EXISTS messages_2026_07_05_pkey;
ALTER TABLE IF EXISTS ONLY realtime.messages_2026_07_04 DROP CONSTRAINT IF EXISTS messages_2026_07_04_pkey;
ALTER TABLE IF EXISTS ONLY realtime.messages_2026_07_03 DROP CONSTRAINT IF EXISTS messages_2026_07_03_pkey;
ALTER TABLE IF EXISTS ONLY realtime.messages_2026_07_02 DROP CONSTRAINT IF EXISTS messages_2026_07_02_pkey;
ALTER TABLE IF EXISTS ONLY realtime.messages DROP CONSTRAINT IF EXISTS messages_pkey;
ALTER TABLE IF EXISTS ONLY public.workflow_forms DROP CONSTRAINT IF EXISTS workflow_forms_pkey;
ALTER TABLE IF EXISTS ONLY public.user_roles DROP CONSTRAINT IF EXISTS user_roles_user_id_organization_id_key;
ALTER TABLE IF EXISTS ONLY public.user_roles DROP CONSTRAINT IF EXISTS user_roles_pkey;
ALTER TABLE IF EXISTS ONLY public.user_preferences DROP CONSTRAINT IF EXISTS user_preferences_user_id_key;
ALTER TABLE IF EXISTS ONLY public.user_preferences DROP CONSTRAINT IF EXISTS user_preferences_pkey;
ALTER TABLE IF EXISTS ONLY public.user_groups DROP CONSTRAINT IF EXISTS user_groups_pkey;
ALTER TABLE IF EXISTS ONLY public.user_group_members DROP CONSTRAINT IF EXISTS user_group_members_pkey;
ALTER TABLE IF EXISTS ONLY public.user_group_members DROP CONSTRAINT IF EXISTS user_group_members_group_id_user_role_id_key;
ALTER TABLE IF EXISTS ONLY public.user_branch_access DROP CONSTRAINT IF EXISTS user_branch_access_user_id_branch_id_key;
ALTER TABLE IF EXISTS ONLY public.user_branch_access DROP CONSTRAINT IF EXISTS user_branch_access_pkey;
ALTER TABLE IF EXISTS ONLY public.system_settings DROP CONSTRAINT IF EXISTS system_settings_setting_key_key;
ALTER TABLE IF EXISTS ONLY public.system_settings DROP CONSTRAINT IF EXISTS system_settings_pkey;
ALTER TABLE IF EXISTS ONLY public.subscribers DROP CONSTRAINT IF EXISTS subscribers_pkey;
ALTER TABLE IF EXISTS ONLY public.subscribers DROP CONSTRAINT IF EXISTS subscribers_email_key;
ALTER TABLE IF EXISTS ONLY public.students DROP CONSTRAINT IF EXISTS students_wearable_id_key;
ALTER TABLE IF EXISTS ONLY public.students DROP CONSTRAINT IF EXISTS students_pkey;
ALTER TABLE IF EXISTS ONLY public.storage_configs DROP CONSTRAINT IF EXISTS storage_configs_pkey;
ALTER TABLE IF EXISTS ONLY public.security_zones DROP CONSTRAINT IF EXISTS security_zones_pkey;
ALTER TABLE IF EXISTS ONLY public.screen_permissions DROP CONSTRAINT IF EXISTS screen_permissions_screen_key_key;
ALTER TABLE IF EXISTS ONLY public.screen_permissions DROP CONSTRAINT IF EXISTS screen_permissions_pkey;
ALTER TABLE IF EXISTS ONLY public.pinned_labels DROP CONSTRAINT IF EXISTS pinned_labels_pkey;
ALTER TABLE IF EXISTS ONLY public.pinned_dashboards DROP CONSTRAINT IF EXISTS pinned_dashboards_pkey;
ALTER TABLE IF EXISTS ONLY public.organizations DROP CONSTRAINT IF EXISTS organizations_pkey;
ALTER TABLE IF EXISTS ONLY public.organization_settings DROP CONSTRAINT IF EXISTS organization_settings_pkey;
ALTER TABLE IF EXISTS ONLY public.organization_settings DROP CONSTRAINT IF EXISTS organization_settings_organization_id_setting_key_key;
ALTER TABLE IF EXISTS ONLY public.notification_methods DROP CONSTRAINT IF EXISTS notification_methods_pkey;
ALTER TABLE IF EXISTS ONLY public.notification_labels DROP CONSTRAINT IF EXISTS notification_labels_pkey;
ALTER TABLE IF EXISTS ONLY public.network_scan_results DROP CONSTRAINT IF EXISTS network_scan_results_pkey;
ALTER TABLE IF EXISTS ONLY public.legal_documents DROP CONSTRAINT IF EXISTS legal_documents_pkey;
ALTER TABLE IF EXISTS ONLY public.legal_documents DROP CONSTRAINT IF EXISTS legal_documents_document_type_key;
ALTER TABLE IF EXISTS ONLY public.industries DROP CONSTRAINT IF EXISTS industries_pkey;
ALTER TABLE IF EXISTS ONLY public.health_alerts DROP CONSTRAINT IF EXISTS health_alerts_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_zones DROP CONSTRAINT IF EXISTS frigate_zones_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_triggers DROP CONSTRAINT IF EXISTS frigate_triggers_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_triggers DROP CONSTRAINT IF EXISTS frigate_triggers_frigate_instance_id_camera_name_key;
ALTER TABLE IF EXISTS ONLY public.frigate_timeline DROP CONSTRAINT IF EXISTS frigate_timeline_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_sync_logs DROP CONSTRAINT IF EXISTS frigate_sync_logs_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_stats_history DROP CONSTRAINT IF EXISTS frigate_stats_history_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_reviews DROP CONSTRAINT IF EXISTS frigate_reviews_review_id_frigate_instance_id_key;
ALTER TABLE IF EXISTS ONLY public.frigate_reviews DROP CONSTRAINT IF EXISTS frigate_reviews_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_recordings DROP CONSTRAINT IF EXISTS frigate_recordings_recording_id_frigate_instance_id_key;
ALTER TABLE IF EXISTS ONLY public.frigate_recordings DROP CONSTRAINT IF EXISTS frigate_recordings_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_previews DROP CONSTRAINT IF EXISTS frigate_previews_preview_id_frigate_instance_id_key;
ALTER TABLE IF EXISTS ONLY public.frigate_previews DROP CONSTRAINT IF EXISTS frigate_previews_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_model_sync_log DROP CONSTRAINT IF EXISTS frigate_model_sync_log_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_model_registry DROP CONSTRAINT IF EXISTS frigate_model_registry_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_model_registry DROP CONSTRAINT IF EXISTS frigate_model_registry_model_id_key;
ALTER TABLE IF EXISTS ONLY public.frigate_model_deployments DROP CONSTRAINT IF EXISTS frigate_model_deployments_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_model_deployments DROP CONSTRAINT IF EXISTS frigate_model_deployments_model_id_frigate_instance_id_key;
ALTER TABLE IF EXISTS ONLY public.frigate_license_plates DROP CONSTRAINT IF EXISTS frigate_license_plates_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_instances DROP CONSTRAINT IF EXISTS frigate_instances_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_instances DROP CONSTRAINT IF EXISTS frigate_instances_branch_id_name_key;
ALTER TABLE IF EXISTS ONLY public.frigate_faces DROP CONSTRAINT IF EXISTS frigate_faces_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_exports DROP CONSTRAINT IF EXISTS frigate_exports_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_exports DROP CONSTRAINT IF EXISTS frigate_exports_export_id_frigate_instance_id_key;
ALTER TABLE IF EXISTS ONLY public.frigate_deployed_models DROP CONSTRAINT IF EXISTS frigate_deployed_models_pkey;
ALTER TABLE IF EXISTS ONLY public.frigate_deployed_models DROP CONSTRAINT IF EXISTS frigate_deployed_models_frigate_instance_id_model_id_key;
ALTER TABLE IF EXISTS ONLY public.frigate_alert_rules DROP CONSTRAINT IF EXISTS frigate_alert_rules_pkey;
ALTER TABLE IF EXISTS ONLY public.form_submissions DROP CONSTRAINT IF EXISTS form_submissions_pkey;
ALTER TABLE IF EXISTS ONLY public.form_distribution_settings DROP CONSTRAINT IF EXISTS form_distribution_settings_pkey;
ALTER TABLE IF EXISTS ONLY public.form_assignments DROP CONSTRAINT IF EXISTS form_assignments_pkey;
ALTER TABLE IF EXISTS ONLY public.events DROP CONSTRAINT IF EXISTS events_pkey;
ALTER TABLE IF EXISTS ONLY public.event_types DROP CONSTRAINT IF EXISTS event_types_pkey;
ALTER TABLE IF EXISTS ONLY public.detection_rules DROP CONSTRAINT IF EXISTS detection_rules_pkey;
ALTER TABLE IF EXISTS ONLY public.chatbot_knowledge_base DROP CONSTRAINT IF EXISTS chatbot_knowledge_base_pkey;
ALTER TABLE IF EXISTS ONLY public.chatbot_knowledge_base DROP CONSTRAINT IF EXISTS chatbot_knowledge_base_language_content_type_key;
ALTER TABLE IF EXISTS ONLY public.chat_threads DROP CONSTRAINT IF EXISTS chat_threads_pkey;
ALTER TABLE IF EXISTS ONLY public.chat_thread_participants DROP CONSTRAINT IF EXISTS chat_thread_participants_thread_id_user_id_key;
ALTER TABLE IF EXISTS ONLY public.chat_thread_participants DROP CONSTRAINT IF EXISTS chat_thread_participants_pkey;
ALTER TABLE IF EXISTS ONLY public.chat_messages DROP CONSTRAINT IF EXISTS chat_messages_pkey;
ALTER TABLE IF EXISTS ONLY public.cameras DROP CONSTRAINT IF EXISTS cameras_pkey;
ALTER TABLE IF EXISTS ONLY public.camera_sources DROP CONSTRAINT IF EXISTS camera_sources_pkey;
ALTER TABLE IF EXISTS ONLY public.camera_event_assignments DROP CONSTRAINT IF EXISTS camera_event_assignments_pkey;
ALTER TABLE IF EXISTS ONLY public.camera_event_assignments DROP CONSTRAINT IF EXISTS camera_event_assignments_camera_id_event_type_id_key;
ALTER TABLE IF EXISTS ONLY public.camera_alert_assignments DROP CONSTRAINT IF EXISTS camera_alert_assignments_pkey;
ALTER TABLE IF EXISTS ONLY public.camera_alert_assignments DROP CONSTRAINT IF EXISTS camera_alert_assignments_camera_id_alert_template_id_key;
ALTER TABLE IF EXISTS ONLY public.branches DROP CONSTRAINT IF EXISTS branches_pkey;
ALTER TABLE IF EXISTS ONLY public.branches DROP CONSTRAINT IF EXISTS branches_device_token_key;
ALTER TABLE IF EXISTS ONLY public.branch_roles DROP CONSTRAINT IF EXISTS branch_roles_pkey;
ALTER TABLE IF EXISTS ONLY public.auto_sync_settings DROP CONSTRAINT IF EXISTS auto_sync_settings_pkey;
ALTER TABLE IF EXISTS ONLY public.aman_instances DROP CONSTRAINT IF EXISTS aman_instances_pkey;
ALTER TABLE IF EXISTS ONLY public.alert_templates DROP CONSTRAINT IF EXISTS alert_templates_pkey;
ALTER TABLE IF EXISTS ONLY public.alert_template_industries DROP CONSTRAINT IF EXISTS alert_template_industries_pkey;
ALTER TABLE IF EXISTS ONLY public.alert_template_industries DROP CONSTRAINT IF EXISTS alert_template_industries_alert_template_id_industry_id_key;
ALTER TABLE IF EXISTS ONLY public.alert_template_events DROP CONSTRAINT IF EXISTS alert_template_events_pkey;
ALTER TABLE IF EXISTS ONLY public.alert_template_events DROP CONSTRAINT IF EXISTS alert_template_events_alert_template_id_event_type_id_key;
ALTER TABLE IF EXISTS ONLY public.ai_models DROP CONSTRAINT IF EXISTS ai_models_pkey;
ALTER TABLE IF EXISTS ONLY public.ai_analysis_logs DROP CONSTRAINT IF EXISTS ai_analysis_logs_pkey;
ALTER TABLE IF EXISTS ONLY auth.webauthn_credentials DROP CONSTRAINT IF EXISTS webauthn_credentials_pkey;
ALTER TABLE IF EXISTS ONLY auth.webauthn_challenges DROP CONSTRAINT IF EXISTS webauthn_challenges_pkey;
ALTER TABLE IF EXISTS ONLY auth.users DROP CONSTRAINT IF EXISTS users_pkey;
ALTER TABLE IF EXISTS ONLY auth.users DROP CONSTRAINT IF EXISTS users_phone_key;
ALTER TABLE IF EXISTS ONLY auth.sso_providers DROP CONSTRAINT IF EXISTS sso_providers_pkey;
ALTER TABLE IF EXISTS ONLY auth.sso_domains DROP CONSTRAINT IF EXISTS sso_domains_pkey;
ALTER TABLE IF EXISTS ONLY auth.sessions DROP CONSTRAINT IF EXISTS sessions_pkey;
ALTER TABLE IF EXISTS ONLY auth.schema_migrations DROP CONSTRAINT IF EXISTS schema_migrations_pkey;
ALTER TABLE IF EXISTS ONLY auth.saml_relay_states DROP CONSTRAINT IF EXISTS saml_relay_states_pkey;
ALTER TABLE IF EXISTS ONLY auth.saml_providers DROP CONSTRAINT IF EXISTS saml_providers_pkey;
ALTER TABLE IF EXISTS ONLY auth.saml_providers DROP CONSTRAINT IF EXISTS saml_providers_entity_id_key;
ALTER TABLE IF EXISTS ONLY auth.refresh_tokens DROP CONSTRAINT IF EXISTS refresh_tokens_token_unique;
ALTER TABLE IF EXISTS ONLY auth.refresh_tokens DROP CONSTRAINT IF EXISTS refresh_tokens_pkey;
ALTER TABLE IF EXISTS ONLY auth.one_time_tokens DROP CONSTRAINT IF EXISTS one_time_tokens_pkey;
ALTER TABLE IF EXISTS ONLY auth.oauth_consents DROP CONSTRAINT IF EXISTS oauth_consents_user_client_unique;
ALTER TABLE IF EXISTS ONLY auth.oauth_consents DROP CONSTRAINT IF EXISTS oauth_consents_pkey;
ALTER TABLE IF EXISTS ONLY auth.oauth_clients DROP CONSTRAINT IF EXISTS oauth_clients_pkey;
ALTER TABLE IF EXISTS ONLY auth.oauth_client_states DROP CONSTRAINT IF EXISTS oauth_client_states_pkey;
ALTER TABLE IF EXISTS ONLY auth.oauth_authorizations DROP CONSTRAINT IF EXISTS oauth_authorizations_pkey;
ALTER TABLE IF EXISTS ONLY auth.oauth_authorizations DROP CONSTRAINT IF EXISTS oauth_authorizations_authorization_id_key;
ALTER TABLE IF EXISTS ONLY auth.oauth_authorizations DROP CONSTRAINT IF EXISTS oauth_authorizations_authorization_code_key;
ALTER TABLE IF EXISTS ONLY auth.mfa_factors DROP CONSTRAINT IF EXISTS mfa_factors_pkey;
ALTER TABLE IF EXISTS ONLY auth.mfa_factors DROP CONSTRAINT IF EXISTS mfa_factors_last_challenged_at_key;
ALTER TABLE IF EXISTS ONLY auth.mfa_challenges DROP CONSTRAINT IF EXISTS mfa_challenges_pkey;
ALTER TABLE IF EXISTS ONLY auth.mfa_amr_claims DROP CONSTRAINT IF EXISTS mfa_amr_claims_session_id_authentication_method_pkey;
ALTER TABLE IF EXISTS ONLY auth.instances DROP CONSTRAINT IF EXISTS instances_pkey;
ALTER TABLE IF EXISTS ONLY auth.identities DROP CONSTRAINT IF EXISTS identities_provider_id_provider_unique;
ALTER TABLE IF EXISTS ONLY auth.identities DROP CONSTRAINT IF EXISTS identities_pkey;
ALTER TABLE IF EXISTS ONLY auth.flow_state DROP CONSTRAINT IF EXISTS flow_state_pkey;
ALTER TABLE IF EXISTS ONLY auth.custom_oauth_providers DROP CONSTRAINT IF EXISTS custom_oauth_providers_pkey;
ALTER TABLE IF EXISTS ONLY auth.custom_oauth_providers DROP CONSTRAINT IF EXISTS custom_oauth_providers_identifier_key;
ALTER TABLE IF EXISTS ONLY auth.audit_log_entries DROP CONSTRAINT IF EXISTS audit_log_entries_pkey;
ALTER TABLE IF EXISTS ONLY auth.mfa_amr_claims DROP CONSTRAINT IF EXISTS amr_id_pk;
ALTER TABLE IF EXISTS ONLY _realtime.tenants DROP CONSTRAINT IF EXISTS tenants_pkey;
ALTER TABLE IF EXISTS ONLY _realtime.schema_migrations DROP CONSTRAINT IF EXISTS schema_migrations_pkey;
ALTER TABLE IF EXISTS ONLY _realtime.feature_flags DROP CONSTRAINT IF EXISTS feature_flags_pkey;
ALTER TABLE IF EXISTS ONLY _realtime.extensions DROP CONSTRAINT IF EXISTS extensions_pkey;
ALTER TABLE IF EXISTS supabase_functions.hooks ALTER COLUMN id DROP DEFAULT;
ALTER TABLE IF EXISTS auth.refresh_tokens ALTER COLUMN id DROP DEFAULT;
DROP SEQUENCE IF EXISTS supabase_functions.hooks_id_seq;
DROP SEQUENCE IF EXISTS auth.refresh_tokens_id_seq;
DROP FUNCTION IF EXISTS supabase_functions.http_request();
DROP FUNCTION IF EXISTS storage.update_updated_at_column();
DROP FUNCTION IF EXISTS storage.search_v2(prefix text, bucket_name text, limits integer, levels integer, start_after text, sort_order text, sort_column text, sort_column_after text);
DROP FUNCTION IF EXISTS storage.search_by_timestamp(p_prefix text, p_bucket_id text, p_limit integer, p_level integer, p_start_after text, p_sort_order text, p_sort_column text, p_sort_column_after text);
DROP FUNCTION IF EXISTS storage.search(prefix text, bucketname text, limits integer, levels integer, offsets integer, search text, sortcolumn text, sortorder text);
DROP FUNCTION IF EXISTS storage.protect_delete();
DROP FUNCTION IF EXISTS storage.operation();
DROP FUNCTION IF EXISTS storage.list_objects_with_delimiter(_bucket_id text, prefix_param text, delimiter_param text, max_keys integer, start_after text, next_token text, sort_order text);
DROP FUNCTION IF EXISTS storage.list_multipart_uploads_with_delimiter(bucket_id text, prefix_param text, delimiter_param text, max_keys integer, next_key_token text, next_upload_token text);
DROP FUNCTION IF EXISTS storage.get_size_by_bucket();
DROP FUNCTION IF EXISTS storage.get_common_prefix(p_key text, p_prefix text, p_delimiter text);
DROP FUNCTION IF EXISTS storage.foldername(name text);
DROP FUNCTION IF EXISTS storage.filename(name text);
DROP FUNCTION IF EXISTS storage.extension(name text);
DROP FUNCTION IF EXISTS storage.enforce_bucket_name_length();
DROP FUNCTION IF EXISTS storage.can_insert_object(bucketid text, name text, owner uuid, metadata jsonb);
DROP FUNCTION IF EXISTS storage.allow_only_operation(expected_operation text);
DROP FUNCTION IF EXISTS storage.allow_any_operation(expected_operations text[]);
DROP FUNCTION IF EXISTS realtime.wal2json_escape_identifier(name text);
DROP FUNCTION IF EXISTS realtime.topic();
DROP FUNCTION IF EXISTS realtime.to_regrole(role_name text);
DROP FUNCTION IF EXISTS realtime.subscription_check_filters();
DROP FUNCTION IF EXISTS realtime.send_binary(payload bytea, event text, topic text, private boolean);
DROP FUNCTION IF EXISTS realtime.send(payload jsonb, event text, topic text, private boolean);
DROP FUNCTION IF EXISTS realtime.quote_wal2json(entity regclass);
DROP FUNCTION IF EXISTS realtime.list_changes(publication name, slot_name name, max_changes integer, max_record_bytes integer);
DROP FUNCTION IF EXISTS realtime.is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[]);
DROP FUNCTION IF EXISTS realtime.check_equality_op(op realtime.equality_op, type_ regtype, val_1 text, val_2 text);
DROP FUNCTION IF EXISTS realtime."cast"(val text, type_ regtype);
DROP FUNCTION IF EXISTS realtime.build_prepared_statement_sql(prepared_statement_name text, entity regclass, columns realtime.wal_column[]);
DROP FUNCTION IF EXISTS realtime.broadcast_changes(topic_name text, event_name text, operation text, table_name text, table_schema text, new record, old record, level text);
DROP FUNCTION IF EXISTS realtime.apply_rls(wal jsonb, max_record_bytes integer);
DROP FUNCTION IF EXISTS public.veedon_bump_branch_config();
DROP FUNCTION IF EXISTS public.user_is_thread_participant(thread_id uuid);
DROP FUNCTION IF EXISTS public.user_is_org_member_for_thread(thread_id uuid);
DROP FUNCTION IF EXISTS public.update_subscriber_activity();
DROP FUNCTION IF EXISTS public.update_modified_column();
DROP FUNCTION IF EXISTS public.trigger_auto_sync();
DROP FUNCTION IF EXISTS public.trg_touch_updated_at();
DROP FUNCTION IF EXISTS public.touch_chat_thread();
DROP FUNCTION IF EXISTS public.restrict_events_update();
DROP FUNCTION IF EXISTS public.manage_auto_sync_schedule(enabled boolean, interval_minutes integer);
DROP FUNCTION IF EXISTS public.is_super_admin(user_email text);
DROP FUNCTION IF EXISTS public.is_current_user_super_admin();
DROP FUNCTION IF EXISTS public.inc_download_count(mid text);
DROP FUNCTION IF EXISTS public.handle_new_user();
DROP FUNCTION IF EXISTS public.get_user_role(user_id uuid);
DROP FUNCTION IF EXISTS public.current_user_is_org_admin_or_manager(org_id uuid);
DROP FUNCTION IF EXISTS public.current_user_is_branch_manager_for_user(target_user_id uuid);
DROP FUNCTION IF EXISTS public.branch_manager_can_view_submission(_submission_id uuid);
DROP FUNCTION IF EXISTS pgbouncer.get_auth(p_usename text);
DROP FUNCTION IF EXISTS graphql_public.graphql("operationName" text, query text, variables jsonb, extensions jsonb);
DROP FUNCTION IF EXISTS extensions.set_graphql_placeholder();
DROP FUNCTION IF EXISTS extensions.pgrst_drop_watch();
DROP FUNCTION IF EXISTS extensions.pgrst_ddl_watch();
DROP FUNCTION IF EXISTS extensions.grant_pg_net_access();
DROP FUNCTION IF EXISTS extensions.grant_pg_graphql_access();
DROP FUNCTION IF EXISTS extensions.grant_pg_cron_access();
DROP FUNCTION IF EXISTS auth.uid();
DROP FUNCTION IF EXISTS auth.role();
DROP FUNCTION IF EXISTS auth.jwt();
DROP FUNCTION IF EXISTS auth.email();
DROP TYPE IF EXISTS storage.buckettype;
DROP TYPE IF EXISTS realtime.wal_rls;
DROP TYPE IF EXISTS realtime.wal_column;
DROP TYPE IF EXISTS realtime.user_defined_filter;
DROP TYPE IF EXISTS realtime.equality_op;
DROP TYPE IF EXISTS realtime.action;
DROP TYPE IF EXISTS public.user_role;
DROP TYPE IF EXISTS public.subscription_tier;
DROP TYPE IF EXISTS public.detection_method;
DROP TYPE IF EXISTS auth.one_time_token_type;
DROP TYPE IF EXISTS auth.oauth_response_type;
DROP TYPE IF EXISTS auth.oauth_registration_type;
DROP TYPE IF EXISTS auth.oauth_client_type;
DROP TYPE IF EXISTS auth.oauth_authorization_status;
DROP TYPE IF EXISTS auth.factor_type;
DROP TYPE IF EXISTS auth.factor_status;
DROP TYPE IF EXISTS auth.code_challenge_method;
DROP TYPE IF EXISTS auth.aal_level;
DROP EXTENSION IF EXISTS "uuid-ossp";
DROP EXTENSION IF EXISTS supabase_vault;
DROP EXTENSION IF EXISTS pgcrypto;
DROP EXTENSION IF EXISTS pg_stat_statements;
DROP SCHEMA IF EXISTS vault;
DROP SCHEMA IF EXISTS supabase_migrations;
DROP SCHEMA IF EXISTS supabase_functions;
DROP SCHEMA IF EXISTS storage;
DROP SCHEMA IF EXISTS realtime;
DROP SCHEMA IF EXISTS pgbouncer;
DROP EXTENSION IF EXISTS pg_net;
DROP SCHEMA IF EXISTS graphql_public;
DROP SCHEMA IF EXISTS graphql;
DROP SCHEMA IF EXISTS extensions;
DROP SCHEMA IF EXISTS auth;
DROP SCHEMA IF EXISTS _realtime;
--
-- Name: _realtime; Type: SCHEMA; Schema: -; Owner: postgres
--

CREATE SCHEMA _realtime;


ALTER SCHEMA _realtime OWNER TO postgres;

--
-- Name: auth; Type: SCHEMA; Schema: -; Owner: supabase_admin
--

CREATE SCHEMA auth;


ALTER SCHEMA auth OWNER TO supabase_admin;

--
-- Name: extensions; Type: SCHEMA; Schema: -; Owner: postgres
--

CREATE SCHEMA extensions;


ALTER SCHEMA extensions OWNER TO postgres;

--
-- Name: graphql; Type: SCHEMA; Schema: -; Owner: supabase_admin
--

CREATE SCHEMA graphql;


ALTER SCHEMA graphql OWNER TO supabase_admin;

--
-- Name: graphql_public; Type: SCHEMA; Schema: -; Owner: supabase_admin
--

CREATE SCHEMA graphql_public;


ALTER SCHEMA graphql_public OWNER TO supabase_admin;

--
-- Name: pg_net; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS pg_net WITH SCHEMA extensions;


--
-- Name: EXTENSION pg_net; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION pg_net IS 'Async HTTP';


--
-- Name: pgbouncer; Type: SCHEMA; Schema: -; Owner: pgbouncer
--

CREATE SCHEMA pgbouncer;


ALTER SCHEMA pgbouncer OWNER TO pgbouncer;

--
-- Name: realtime; Type: SCHEMA; Schema: -; Owner: supabase_admin
--

CREATE SCHEMA realtime;


ALTER SCHEMA realtime OWNER TO supabase_admin;

--
-- Name: storage; Type: SCHEMA; Schema: -; Owner: supabase_admin
--

CREATE SCHEMA storage;


ALTER SCHEMA storage OWNER TO supabase_admin;

--
-- Name: supabase_functions; Type: SCHEMA; Schema: -; Owner: supabase_admin
--

CREATE SCHEMA supabase_functions;


ALTER SCHEMA supabase_functions OWNER TO supabase_admin;

--
-- Name: supabase_migrations; Type: SCHEMA; Schema: -; Owner: postgres
--

CREATE SCHEMA supabase_migrations;


ALTER SCHEMA supabase_migrations OWNER TO postgres;

--
-- Name: vault; Type: SCHEMA; Schema: -; Owner: supabase_admin
--

CREATE SCHEMA vault;


ALTER SCHEMA vault OWNER TO supabase_admin;

--
-- Name: pg_stat_statements; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS pg_stat_statements WITH SCHEMA extensions;


--
-- Name: EXTENSION pg_stat_statements; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION pg_stat_statements IS 'track planning and execution statistics of all SQL statements executed';


--
-- Name: pgcrypto; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA extensions;


--
-- Name: EXTENSION pgcrypto; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION pgcrypto IS 'cryptographic functions';


--
-- Name: supabase_vault; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS supabase_vault WITH SCHEMA vault;


--
-- Name: EXTENSION supabase_vault; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION supabase_vault IS 'Supabase Vault Extension';


--
-- Name: uuid-ossp; Type: EXTENSION; Schema: -; Owner: -
--

CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA extensions;


--
-- Name: EXTENSION "uuid-ossp"; Type: COMMENT; Schema: -; Owner: 
--

COMMENT ON EXTENSION "uuid-ossp" IS 'generate universally unique identifiers (UUIDs)';


--
-- Name: aal_level; Type: TYPE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TYPE auth.aal_level AS ENUM (
    'aal1',
    'aal2',
    'aal3'
);


ALTER TYPE auth.aal_level OWNER TO supabase_auth_admin;

--
-- Name: code_challenge_method; Type: TYPE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TYPE auth.code_challenge_method AS ENUM (
    's256',
    'plain'
);


ALTER TYPE auth.code_challenge_method OWNER TO supabase_auth_admin;

--
-- Name: factor_status; Type: TYPE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TYPE auth.factor_status AS ENUM (
    'unverified',
    'verified'
);


ALTER TYPE auth.factor_status OWNER TO supabase_auth_admin;

--
-- Name: factor_type; Type: TYPE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TYPE auth.factor_type AS ENUM (
    'totp',
    'webauthn',
    'phone'
);


ALTER TYPE auth.factor_type OWNER TO supabase_auth_admin;

--
-- Name: oauth_authorization_status; Type: TYPE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TYPE auth.oauth_authorization_status AS ENUM (
    'pending',
    'approved',
    'denied',
    'expired'
);


ALTER TYPE auth.oauth_authorization_status OWNER TO supabase_auth_admin;

--
-- Name: oauth_client_type; Type: TYPE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TYPE auth.oauth_client_type AS ENUM (
    'public',
    'confidential'
);


ALTER TYPE auth.oauth_client_type OWNER TO supabase_auth_admin;

--
-- Name: oauth_registration_type; Type: TYPE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TYPE auth.oauth_registration_type AS ENUM (
    'dynamic',
    'manual'
);


ALTER TYPE auth.oauth_registration_type OWNER TO supabase_auth_admin;

--
-- Name: oauth_response_type; Type: TYPE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TYPE auth.oauth_response_type AS ENUM (
    'code'
);


ALTER TYPE auth.oauth_response_type OWNER TO supabase_auth_admin;

--
-- Name: one_time_token_type; Type: TYPE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TYPE auth.one_time_token_type AS ENUM (
    'confirmation_token',
    'reauthentication_token',
    'recovery_token',
    'email_change_token_new',
    'email_change_token_current',
    'phone_change_token'
);


ALTER TYPE auth.one_time_token_type OWNER TO supabase_auth_admin;

--
-- Name: detection_method; Type: TYPE; Schema: public; Owner: postgres
--

CREATE TYPE public.detection_method AS ENUM (
    'file',
    'api'
);


ALTER TYPE public.detection_method OWNER TO postgres;

--
-- Name: subscription_tier; Type: TYPE; Schema: public; Owner: postgres
--

CREATE TYPE public.subscription_tier AS ENUM (
    'basic',
    'professional',
    'enterprise',
    'ai-premium'
);


ALTER TYPE public.subscription_tier OWNER TO postgres;

--
-- Name: user_role; Type: TYPE; Schema: public; Owner: postgres
--

CREATE TYPE public.user_role AS ENUM (
    'admin',
    'manager',
    'viewer',
    'super_admin',
    'company_admin',
    'branch_manager',
    'representative'
);


ALTER TYPE public.user_role OWNER TO postgres;

--
-- Name: action; Type: TYPE; Schema: realtime; Owner: supabase_admin
--

CREATE TYPE realtime.action AS ENUM (
    'INSERT',
    'UPDATE',
    'DELETE',
    'TRUNCATE',
    'ERROR'
);


ALTER TYPE realtime.action OWNER TO supabase_admin;

--
-- Name: equality_op; Type: TYPE; Schema: realtime; Owner: supabase_admin
--

CREATE TYPE realtime.equality_op AS ENUM (
    'eq',
    'neq',
    'lt',
    'lte',
    'gt',
    'gte',
    'in'
);


ALTER TYPE realtime.equality_op OWNER TO supabase_admin;

--
-- Name: user_defined_filter; Type: TYPE; Schema: realtime; Owner: supabase_admin
--

CREATE TYPE realtime.user_defined_filter AS (
	column_name text,
	op realtime.equality_op,
	value text
);


ALTER TYPE realtime.user_defined_filter OWNER TO supabase_admin;

--
-- Name: wal_column; Type: TYPE; Schema: realtime; Owner: supabase_admin
--

CREATE TYPE realtime.wal_column AS (
	name text,
	type_name text,
	type_oid oid,
	value jsonb,
	is_pkey boolean,
	is_selectable boolean
);


ALTER TYPE realtime.wal_column OWNER TO supabase_admin;

--
-- Name: wal_rls; Type: TYPE; Schema: realtime; Owner: supabase_admin
--

CREATE TYPE realtime.wal_rls AS (
	wal jsonb,
	is_rls_enabled boolean,
	subscription_ids uuid[],
	errors text[]
);


ALTER TYPE realtime.wal_rls OWNER TO supabase_admin;

--
-- Name: buckettype; Type: TYPE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TYPE storage.buckettype AS ENUM (
    'STANDARD',
    'ANALYTICS',
    'VECTOR'
);


ALTER TYPE storage.buckettype OWNER TO supabase_storage_admin;

--
-- Name: email(); Type: FUNCTION; Schema: auth; Owner: supabase_auth_admin
--

CREATE FUNCTION auth.email() RETURNS text
    LANGUAGE sql STABLE
    AS $$
  select 
  coalesce(
    nullif(current_setting('request.jwt.claim.email', true), ''),
    (nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'email')
  )::text
$$;


ALTER FUNCTION auth.email() OWNER TO supabase_auth_admin;

--
-- Name: FUNCTION email(); Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON FUNCTION auth.email() IS 'Deprecated. Use auth.jwt() -> ''email'' instead.';


--
-- Name: jwt(); Type: FUNCTION; Schema: auth; Owner: supabase_auth_admin
--

CREATE FUNCTION auth.jwt() RETURNS jsonb
    LANGUAGE sql STABLE
    AS $$
  select 
    coalesce(
        nullif(current_setting('request.jwt.claim', true), ''),
        nullif(current_setting('request.jwt.claims', true), '')
    )::jsonb
$$;


ALTER FUNCTION auth.jwt() OWNER TO supabase_auth_admin;

--
-- Name: role(); Type: FUNCTION; Schema: auth; Owner: supabase_auth_admin
--

CREATE FUNCTION auth.role() RETURNS text
    LANGUAGE sql STABLE
    AS $$
  select 
  coalesce(
    nullif(current_setting('request.jwt.claim.role', true), ''),
    (nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'role')
  )::text
$$;


ALTER FUNCTION auth.role() OWNER TO supabase_auth_admin;

--
-- Name: FUNCTION role(); Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON FUNCTION auth.role() IS 'Deprecated. Use auth.jwt() -> ''role'' instead.';


--
-- Name: uid(); Type: FUNCTION; Schema: auth; Owner: supabase_auth_admin
--

CREATE FUNCTION auth.uid() RETURNS uuid
    LANGUAGE sql STABLE
    AS $$
  select 
  coalesce(
    nullif(current_setting('request.jwt.claim.sub', true), ''),
    (nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'sub')
  )::uuid
$$;


ALTER FUNCTION auth.uid() OWNER TO supabase_auth_admin;

--
-- Name: FUNCTION uid(); Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON FUNCTION auth.uid() IS 'Deprecated. Use auth.jwt() -> ''sub'' instead.';


--
-- Name: grant_pg_cron_access(); Type: FUNCTION; Schema: extensions; Owner: supabase_admin
--

CREATE FUNCTION extensions.grant_pg_cron_access() RETURNS event_trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
  IF EXISTS (
    SELECT
    FROM pg_event_trigger_ddl_commands() AS ev
    JOIN pg_extension AS ext
    ON ev.objid = ext.oid
    WHERE ext.extname = 'pg_cron'
  )
  THEN
    grant usage on schema cron to postgres with grant option;

    alter default privileges in schema cron grant all on tables to postgres with grant option;
    alter default privileges in schema cron grant all on functions to postgres with grant option;
    alter default privileges in schema cron grant all on sequences to postgres with grant option;

    alter default privileges for user supabase_admin in schema cron grant all
        on sequences to postgres with grant option;
    alter default privileges for user supabase_admin in schema cron grant all
        on tables to postgres with grant option;
    alter default privileges for user supabase_admin in schema cron grant all
        on functions to postgres with grant option;

    grant all privileges on all tables in schema cron to postgres with grant option;
    revoke all on table cron.job from postgres;
    grant select on table cron.job to postgres with grant option;
  END IF;
END;
$$;


ALTER FUNCTION extensions.grant_pg_cron_access() OWNER TO supabase_admin;

--
-- Name: FUNCTION grant_pg_cron_access(); Type: COMMENT; Schema: extensions; Owner: supabase_admin
--

COMMENT ON FUNCTION extensions.grant_pg_cron_access() IS 'Grants access to pg_cron';


--
-- Name: grant_pg_graphql_access(); Type: FUNCTION; Schema: extensions; Owner: supabase_admin
--

CREATE FUNCTION extensions.grant_pg_graphql_access() RETURNS event_trigger
    LANGUAGE plpgsql
    AS $_$
begin
    if not exists (
        select 1
        from pg_event_trigger_ddl_commands() ev
        join pg_catalog.pg_extension e on ev.objid = e.oid
        where e.extname = 'pg_graphql'
    ) then
        return;
    end if;

    drop function if exists graphql_public.graphql;
    create or replace function graphql_public.graphql(
        "operationName" text default null,
        query text default null,
        variables jsonb default null,
        extensions jsonb default null
    )
        returns jsonb
        language sql
    as $$
        select graphql.resolve(
            query := query,
            variables := coalesce(variables, '{}'),
            "operationName" := "operationName",
            extensions := extensions
        );
    $$;

    -- Attach the wrapper to the extension so DROP EXTENSION cascades to it,
    -- which in turn triggers set_graphql_placeholder to reinstall the "not enabled" stub.
    alter extension pg_graphql add function graphql_public.graphql(text, text, jsonb, jsonb);

    grant usage on schema graphql to postgres, anon, authenticated, service_role;
    grant execute on function graphql.resolve to postgres, anon, authenticated, service_role;
    grant usage on schema graphql to postgres with grant option;
    grant usage on schema graphql_public to postgres with grant option;
end;
$_$;


ALTER FUNCTION extensions.grant_pg_graphql_access() OWNER TO supabase_admin;

--
-- Name: FUNCTION grant_pg_graphql_access(); Type: COMMENT; Schema: extensions; Owner: supabase_admin
--

COMMENT ON FUNCTION extensions.grant_pg_graphql_access() IS 'Grants access to pg_graphql';


--
-- Name: grant_pg_net_access(); Type: FUNCTION; Schema: extensions; Owner: supabase_admin
--

CREATE FUNCTION extensions.grant_pg_net_access() RETURNS event_trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
  IF EXISTS (
    SELECT 1
    FROM pg_event_trigger_ddl_commands() AS ev
    JOIN pg_extension AS ext
    ON ev.objid = ext.oid
    WHERE ext.extname = 'pg_net'
  )
  THEN
    GRANT USAGE ON SCHEMA net TO supabase_functions_admin, postgres, anon, authenticated, service_role;

    ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;
    ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SECURITY DEFINER;

    ALTER function net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;
    ALTER function net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) SET search_path = net;

    REVOKE ALL ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;
    REVOKE ALL ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) FROM PUBLIC;

    GRANT EXECUTE ON FUNCTION net.http_get(url text, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role;
    GRANT EXECUTE ON FUNCTION net.http_post(url text, body jsonb, params jsonb, headers jsonb, timeout_milliseconds integer) TO supabase_functions_admin, postgres, anon, authenticated, service_role;
  END IF;
END;
$$;


ALTER FUNCTION extensions.grant_pg_net_access() OWNER TO supabase_admin;

--
-- Name: FUNCTION grant_pg_net_access(); Type: COMMENT; Schema: extensions; Owner: supabase_admin
--

COMMENT ON FUNCTION extensions.grant_pg_net_access() IS 'Grants access to pg_net';


--
-- Name: pgrst_ddl_watch(); Type: FUNCTION; Schema: extensions; Owner: supabase_admin
--

CREATE FUNCTION extensions.pgrst_ddl_watch() RETURNS event_trigger
    LANGUAGE plpgsql
    AS $$
DECLARE
  cmd record;
BEGIN
  FOR cmd IN SELECT * FROM pg_event_trigger_ddl_commands()
  LOOP
    IF cmd.command_tag IN (
      'CREATE SCHEMA', 'ALTER SCHEMA'
    , 'CREATE TABLE', 'CREATE TABLE AS', 'SELECT INTO', 'ALTER TABLE'
    , 'CREATE FOREIGN TABLE', 'ALTER FOREIGN TABLE'
    , 'CREATE VIEW', 'ALTER VIEW'
    , 'CREATE MATERIALIZED VIEW', 'ALTER MATERIALIZED VIEW'
    , 'CREATE FUNCTION', 'ALTER FUNCTION'
    , 'CREATE TRIGGER'
    , 'CREATE TYPE', 'ALTER TYPE'
    , 'CREATE RULE'
    , 'COMMENT'
    )
    -- don't notify in case of CREATE TEMP table or other objects created on pg_temp
    AND cmd.schema_name is distinct from 'pg_temp'
    THEN
      NOTIFY pgrst, 'reload schema';
    END IF;
  END LOOP;
END; $$;


ALTER FUNCTION extensions.pgrst_ddl_watch() OWNER TO supabase_admin;

--
-- Name: pgrst_drop_watch(); Type: FUNCTION; Schema: extensions; Owner: supabase_admin
--

CREATE FUNCTION extensions.pgrst_drop_watch() RETURNS event_trigger
    LANGUAGE plpgsql
    AS $$
DECLARE
  obj record;
BEGIN
  FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects()
  LOOP
    IF obj.object_type IN (
      'schema'
    , 'table'
    , 'foreign table'
    , 'view'
    , 'materialized view'
    , 'function'
    , 'trigger'
    , 'type'
    , 'rule'
    )
    AND obj.is_temporary IS false -- no pg_temp objects
    THEN
      NOTIFY pgrst, 'reload schema';
    END IF;
  END LOOP;
END; $$;


ALTER FUNCTION extensions.pgrst_drop_watch() OWNER TO supabase_admin;

--
-- Name: set_graphql_placeholder(); Type: FUNCTION; Schema: extensions; Owner: supabase_admin
--

CREATE FUNCTION extensions.set_graphql_placeholder() RETURNS event_trigger
    LANGUAGE plpgsql
    AS $_$
    DECLARE
    graphql_is_dropped bool;
    BEGIN
    graphql_is_dropped = (
        SELECT ev.schema_name = 'graphql_public'
        FROM pg_event_trigger_dropped_objects() AS ev
        WHERE ev.schema_name = 'graphql_public'
    );

    IF graphql_is_dropped
    THEN
        create or replace function graphql_public.graphql(
            "operationName" text default null,
            query text default null,
            variables jsonb default null,
            extensions jsonb default null
        )
            returns jsonb
            language plpgsql
        as $$
            DECLARE
                server_version float;
            BEGIN
                server_version = (SELECT (SPLIT_PART((select version()), ' ', 2))::float);

                IF server_version >= 14 THEN
                    RETURN jsonb_build_object(
                        'errors', jsonb_build_array(
                            jsonb_build_object(
                                'message', 'pg_graphql extension is not enabled.'
                            )
                        )
                    );
                ELSE
                    RETURN jsonb_build_object(
                        'errors', jsonb_build_array(
                            jsonb_build_object(
                                'message', 'pg_graphql is only available on projects running Postgres 14 onwards.'
                            )
                        )
                    );
                END IF;
            END;
        $$;
    END IF;

    END;
$_$;


ALTER FUNCTION extensions.set_graphql_placeholder() OWNER TO supabase_admin;

--
-- Name: FUNCTION set_graphql_placeholder(); Type: COMMENT; Schema: extensions; Owner: supabase_admin
--

COMMENT ON FUNCTION extensions.set_graphql_placeholder() IS 'Reintroduces placeholder function for graphql_public.graphql';


--
-- Name: graphql(text, text, jsonb, jsonb); Type: FUNCTION; Schema: graphql_public; Owner: supabase_admin
--

CREATE FUNCTION graphql_public.graphql("operationName" text DEFAULT NULL::text, query text DEFAULT NULL::text, variables jsonb DEFAULT NULL::jsonb, extensions jsonb DEFAULT NULL::jsonb) RETURNS jsonb
    LANGUAGE plpgsql
    AS $$
            DECLARE
                server_version float;
            BEGIN
                server_version = (SELECT (SPLIT_PART((select version()), ' ', 2))::float);

                IF server_version >= 14 THEN
                    RETURN jsonb_build_object(
                        'errors', jsonb_build_array(
                            jsonb_build_object(
                                'message', 'pg_graphql extension is not enabled.'
                            )
                        )
                    );
                ELSE
                    RETURN jsonb_build_object(
                        'errors', jsonb_build_array(
                            jsonb_build_object(
                                'message', 'pg_graphql is only available on projects running Postgres 14 onwards.'
                            )
                        )
                    );
                END IF;
            END;
        $$;


ALTER FUNCTION graphql_public.graphql("operationName" text, query text, variables jsonb, extensions jsonb) OWNER TO supabase_admin;

--
-- Name: get_auth(text); Type: FUNCTION; Schema: pgbouncer; Owner: supabase_admin
--

CREATE FUNCTION pgbouncer.get_auth(p_usename text) RETURNS TABLE(username text, password text)
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO ''
    AS $_$
begin
    raise debug 'PgBouncer auth request: %', p_usename;

    return query
    select 
        rolname::text, 
        case when rolvaliduntil < now() 
            then null 
            else rolpassword::text 
        end 
    from pg_authid 
    where rolname=$1 and rolcanlogin;
end;
$_$;


ALTER FUNCTION pgbouncer.get_auth(p_usename text) OWNER TO supabase_admin;

--
-- Name: branch_manager_can_view_submission(uuid); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.branch_manager_can_view_submission(_submission_id uuid) RETURNS boolean
    LANGUAGE sql STABLE SECURITY DEFINER
    SET search_path TO ''
    AS $$
  WITH fa AS (
    SELECT fa.representative_id
    FROM public.form_assignments fa
    JOIN public.form_submissions fs ON fs.form_assignment_id = fa.id
    WHERE fs.id = _submission_id
  ),
  manager_branches AS (
    SELECT br.branch_id
    FROM public.branch_roles br
    WHERE br.user_id = auth.uid() AND br.role = 'branch_manager'
  ),
  rep_branches AS (
    SELECT br.branch_id
    FROM public.user_roles ur
    JOIN public.branch_roles br ON br.user_id = ur.user_id
    WHERE ur.id = (SELECT representative_id FROM fa)
  )
  SELECT EXISTS (
    SELECT 1 FROM manager_branches mb
    JOIN rep_branches rb ON rb.branch_id = mb.branch_id
  );
$$;


ALTER FUNCTION public.branch_manager_can_view_submission(_submission_id uuid) OWNER TO postgres;

--
-- Name: current_user_is_branch_manager_for_user(uuid); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.current_user_is_branch_manager_for_user(target_user_id uuid) RETURNS boolean
    LANGUAGE sql STABLE SECURITY DEFINER
    SET search_path TO ''
    AS $$
  SELECT EXISTS (
    SELECT 1
    FROM public.branch_roles br_mgr
    JOIN public.branch_roles br_user ON br_user.branch_id = br_mgr.branch_id
    WHERE br_mgr.user_id = auth.uid()
      AND br_mgr.role = 'branch_manager'
      AND br_user.user_id = target_user_id
  );
$$;


ALTER FUNCTION public.current_user_is_branch_manager_for_user(target_user_id uuid) OWNER TO postgres;

--
-- Name: current_user_is_org_admin_or_manager(uuid); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.current_user_is_org_admin_or_manager(org_id uuid) RETURNS boolean
    LANGUAGE sql STABLE SECURITY DEFINER
    SET search_path TO ''
    AS $$
  SELECT EXISTS (
    SELECT 1 FROM public.user_roles ur
    WHERE ur.user_id = auth.uid()
      AND ur.organization_id = org_id
      AND ur.role IN ('admin','manager')
  );
$$;


ALTER FUNCTION public.current_user_is_org_admin_or_manager(org_id uuid) OWNER TO postgres;

--
-- Name: get_user_role(uuid); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.get_user_role(user_id uuid) RETURNS public.user_role
    LANGUAGE sql SECURITY DEFINER
    SET search_path TO ''
    AS $_$
  SELECT role FROM public.user_roles WHERE user_id = $1 LIMIT 1
$_$;


ALTER FUNCTION public.get_user_role(user_id uuid) OWNER TO postgres;




ALTER FUNCTION public.handle_new_user() OWNER TO postgres;

--
-- Name: inc_download_count(text); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.inc_download_count(mid text) RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
BEGIN
  UPDATE frigate_model_registry
     SET download_count = COALESCE(download_count, 0) + 1
   WHERE model_id = mid;
END;
$$;


ALTER FUNCTION public.inc_download_count(mid text) OWNER TO postgres;

--
-- Name: is_current_user_super_admin(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.is_current_user_super_admin() RETURNS boolean
    LANGUAGE sql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
  SELECT public.is_super_admin((SELECT email FROM auth.users WHERE id = auth.uid()))
$$;


ALTER FUNCTION public.is_current_user_super_admin() OWNER TO postgres;

--
-- Name: is_super_admin(text); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.is_super_admin(user_email text) RETURNS boolean
    LANGUAGE sql SECURITY DEFINER
    SET search_path TO ''
    AS $$
  SELECT LOWER(user_email) IN ('ashraffarid@gmail.com', 'demo@beyondsenses.ai')
$$;


ALTER FUNCTION public.is_super_admin(user_email text) OWNER TO postgres;

--
-- Name: manage_auto_sync_schedule(boolean, integer); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.manage_auto_sync_schedule(enabled boolean, interval_minutes integer DEFAULT 30) RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
BEGIN
  -- No-op: pg_cron not available in local dev
  NULL;
END;
$$;


ALTER FUNCTION public.manage_auto_sync_schedule(enabled boolean, interval_minutes integer) OWNER TO postgres;

--
-- Name: restrict_events_update(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.restrict_events_update() RETURNS trigger
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
BEGIN
  IF OLD.metadata->>'source' = 'veedon-edge' THEN
    RETURN NEW;
  END IF;
  IF NEW.reviewed IS DISTINCT FROM TRUE THEN
    RAISE EXCEPTION 'Only allowed to set reviewed=true';
  END IF;
  IF OLD.reviewed = TRUE THEN
    RAISE EXCEPTION 'Event already reviewed';
  END IF;
  IF NEW.id <> OLD.id OR
     NEW.camera_id IS DISTINCT FROM OLD.camera_id OR
     NEW.metadata IS DISTINCT FROM OLD.metadata OR
     NEW.detected_at IS DISTINCT FROM OLD.detected_at OR
     NEW.severity IS DISTINCT FROM OLD.severity OR
     NEW.snapshot_url IS DISTINCT FROM OLD.snapshot_url OR
     NEW.event_type IS DISTINCT FROM OLD.event_type THEN
     RAISE EXCEPTION 'Only the reviewed field may be updated';
  END IF;
  RETURN NEW;
END;
$$;


ALTER FUNCTION public.restrict_events_update() OWNER TO postgres;

--
-- Name: touch_chat_thread(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.touch_chat_thread() RETURNS trigger
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
BEGIN
  UPDATE public.chat_threads SET updated_at = now() WHERE id = NEW.thread_id;
  RETURN NEW;
END;
$$;


ALTER FUNCTION public.touch_chat_thread() OWNER TO postgres;

--
-- Name: trg_touch_updated_at(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.trg_touch_updated_at() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN NEW.updated_at = now(); RETURN NEW; END;
$$;


ALTER FUNCTION public.trg_touch_updated_at() OWNER TO postgres;

--
-- Name: trigger_auto_sync(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.trigger_auto_sync() RETURNS void
    LANGUAGE plpgsql SECURITY DEFINER
    AS $$
BEGIN
  -- Skipped: requires pg_net extension not enabled in local dev
  -- In production, this function calls auto-sync-data edge function via pg_net
  NULL;
END;
$$;


ALTER FUNCTION public.trigger_auto_sync() OWNER TO postgres;

--
-- Name: update_modified_column(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.update_modified_column() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
    NEW.updated_at = now();
    RETURN NEW;
END;
$$;


ALTER FUNCTION public.update_modified_column() OWNER TO postgres;

--
-- Name: update_subscriber_activity(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.update_subscriber_activity() RETURNS trigger
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
BEGIN
    UPDATE public.subscribers 
    SET last_activity = now() 
    WHERE user_id = NEW.user_id OR user_id = OLD.user_id;
    RETURN COALESCE(NEW, OLD);
END;
$$;


ALTER FUNCTION public.update_subscriber_activity() OWNER TO postgres;

--
-- Name: user_is_org_member_for_thread(uuid); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.user_is_org_member_for_thread(thread_id uuid) RETURNS boolean
    LANGUAGE sql SECURITY DEFINER
    SET search_path TO ''
    AS $$
  SELECT EXISTS (
    SELECT 1
    FROM public.chat_threads t
    JOIN public.user_roles ur ON ur.organization_id = t.organization_id
    WHERE t.id = user_is_org_member_for_thread.thread_id
      AND ur.user_id = auth.uid()
  );
$$;


ALTER FUNCTION public.user_is_org_member_for_thread(thread_id uuid) OWNER TO postgres;

--
-- Name: user_is_thread_participant(uuid); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.user_is_thread_participant(thread_id uuid) RETURNS boolean
    LANGUAGE sql SECURITY DEFINER
    SET search_path TO 'public'
    AS $$
  SELECT EXISTS (
    SELECT 1 FROM public.chat_thread_participants p
    WHERE p.thread_id = user_is_thread_participant.thread_id
      AND p.user_id = auth.uid()
  );
$$;


ALTER FUNCTION public.user_is_thread_participant(thread_id uuid) OWNER TO postgres;

--
-- Name: veedon_bump_branch_config(); Type: FUNCTION; Schema: public; Owner: postgres
--

CREATE FUNCTION public.veedon_bump_branch_config() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
DECLARE
  target_branch uuid;
BEGIN
  IF TG_TABLE_NAME = 'cameras' THEN
    target_branch := COALESCE(NEW.branch_id, OLD.branch_id);
  ELSIF TG_TABLE_NAME = 'camera_event_assignments' THEN
    SELECT branch_id INTO target_branch FROM cameras
      WHERE id = COALESCE(NEW.camera_id, OLD.camera_id);
  END IF;
  IF target_branch IS NOT NULL THEN
    UPDATE branches SET config_version = config_version + 1 WHERE id = target_branch;
  END IF;
  RETURN COALESCE(NEW, OLD);
END;
$$;


ALTER FUNCTION public.veedon_bump_branch_config() OWNER TO postgres;

--
-- Name: apply_rls(jsonb, integer); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.apply_rls(wal jsonb, max_record_bytes integer DEFAULT (1024 * 1024)) RETURNS SETOF realtime.wal_rls
    LANGUAGE plpgsql
    AS $$
declare
    -- Regclass of the table e.g. public.notes
    entity_ regclass = (quote_ident(wal ->> 'schema') || '.' || quote_ident(wal ->> 'table'))::regclass;

    -- I, U, D, T: insert, update ...
    action realtime.action = (
        case wal ->> 'action'
            when 'I' then 'INSERT'
            when 'U' then 'UPDATE'
            when 'D' then 'DELETE'
            else 'ERROR'
        end
    );

    -- Is row level security enabled for the table
    is_rls_enabled bool = relrowsecurity from pg_class where oid = entity_;

    subscriptions realtime.subscription[] = array_agg(subs)
        from
            realtime.subscription subs
        where
            subs.entity = entity_
            -- Filter by action early - only get subscriptions interested in this action
            -- action_filter column can be: '*' (all), 'INSERT', 'UPDATE', or 'DELETE'
            and (subs.action_filter = '*' or subs.action_filter = action::text);

    -- Subscription vars
    working_role regrole;
    working_selected_columns text[];
    claimed_role regrole;
    claims jsonb;

    subscription_id uuid;
    subscription_has_access bool;
    visible_to_subscription_ids uuid[] = '{}';

    -- structured info for wal's columns
    columns realtime.wal_column[];
    -- previous identity values for update/delete
    old_columns realtime.wal_column[];

    error_record_exceeds_max_size boolean = octet_length(wal::text) > max_record_bytes;

    -- Primary jsonb output for record
    output jsonb;

    -- Loop record for iterating unique roles (outer loop)
    role_record record;
    -- Loop record for iterating unique selected_columns within a role (inner loop)
    cols_record record;
    -- Subscription ids visible at the role level (before fanning out by selected_columns)
    visible_role_sub_ids uuid[] = '{}';

begin
    perform set_config('role', null, true);

    columns =
        array_agg(
            (
                x->>'name',
                x->>'type',
                x->>'typeoid',
                realtime.cast(
                    (x->'value') #>> '{}',
                    coalesce(
                        (x->>'typeoid')::regtype, -- null when wal2json version <= 2.4
                        (x->>'type')::regtype
                    )
                ),
                (pks ->> 'name') is not null,
                true
            )::realtime.wal_column
        )
        from
            jsonb_array_elements(wal -> 'columns') x
            left join jsonb_array_elements(wal -> 'pk') pks
                on (x ->> 'name') = (pks ->> 'name');

    old_columns =
        array_agg(
            (
                x->>'name',
                x->>'type',
                x->>'typeoid',
                realtime.cast(
                    (x->'value') #>> '{}',
                    coalesce(
                        (x->>'typeoid')::regtype, -- null when wal2json version <= 2.4
                        (x->>'type')::regtype
                    )
                ),
                (pks ->> 'name') is not null,
                true
            )::realtime.wal_column
        )
        from
            jsonb_array_elements(wal -> 'identity') x
            left join jsonb_array_elements(wal -> 'pk') pks
                on (x ->> 'name') = (pks ->> 'name');

    for role_record in
        select claims_role
        from (select distinct claims_role from unnest(subscriptions)) t
        order by claims_role::text
    loop
        working_role := role_record.claims_role;

        -- Update `is_selectable` for columns and old_columns (once per role)
        columns =
            array_agg(
                (
                    c.name,
                    c.type_name,
                    c.type_oid,
                    c.value,
                    c.is_pkey,
                    pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')
                )::realtime.wal_column
            )
            from
                unnest(columns) c;

        old_columns =
                array_agg(
                    (
                        c.name,
                        c.type_name,
                        c.type_oid,
                        c.value,
                        c.is_pkey,
                        pg_catalog.has_column_privilege(working_role, entity_, c.name, 'SELECT')
                    )::realtime.wal_column
                )
                from
                    unnest(old_columns) c;

        if action <> 'DELETE' and count(1) = 0 from unnest(columns) c where c.is_pkey then
            -- Fan out 400 error per distinct selected_columns for this role
            for cols_record in
                select selected_columns
                from (select distinct selected_columns from unnest(subscriptions) s where s.claims_role = working_role) t
                order by coalesce(array_to_string(selected_columns, ','), '')
            loop
                working_selected_columns := cols_record.selected_columns;
                return next (
                    jsonb_build_object(
                        'schema', wal ->> 'schema',
                        'table', wal ->> 'table',
                        'type', action
                    ),
                    is_rls_enabled,
                    (select array_agg(s.subscription_id) from unnest(subscriptions) as s where s.claims_role = working_role and (s.selected_columns is not distinct from working_selected_columns)),
                    array['Error 400: Bad Request, no primary key']
                )::realtime.wal_rls;
            end loop;

        -- The claims role does not have SELECT permission to the primary key of entity
        elsif action <> 'DELETE' and sum(c.is_selectable::int) <> count(1) from unnest(columns) c where c.is_pkey then
            -- Fan out 401 error per distinct selected_columns for this role
            for cols_record in
                select selected_columns
                from (select distinct selected_columns from unnest(subscriptions) s where s.claims_role = working_role) t
                order by coalesce(array_to_string(selected_columns, ','), '')
            loop
                working_selected_columns := cols_record.selected_columns;
                return next (
                    jsonb_build_object(
                        'schema', wal ->> 'schema',
                        'table', wal ->> 'table',
                        'type', action
                    ),
                    is_rls_enabled,
                    (select array_agg(s.subscription_id) from unnest(subscriptions) as s where s.claims_role = working_role and (s.selected_columns is not distinct from working_selected_columns)),
                    array['Error 401: Unauthorized']
                )::realtime.wal_rls;
            end loop;

        else
            -- Create the prepared statement (once per role)
            if is_rls_enabled and action <> 'DELETE' then
                if (select 1 from pg_prepared_statements where name = 'walrus_rls_stmt' limit 1) > 0 then
                    deallocate walrus_rls_stmt;
                end if;
                execute realtime.build_prepared_statement_sql('walrus_rls_stmt', entity_, columns);
            end if;

            -- Collect all visible subscription IDs for this role (filter check + RLS check)
            visible_role_sub_ids = '{}';

            for subscription_id, claims in (
                    select
                        subs.subscription_id,
                        subs.claims
                    from
                        unnest(subscriptions) subs
                    where
                        subs.entity = entity_
                        and subs.claims_role = working_role
                        and (
                            realtime.is_visible_through_filters(columns, subs.filters)
                            or (
                              action = 'DELETE'
                              and realtime.is_visible_through_filters(old_columns, subs.filters)
                            )
                        )
            ) loop

                if not is_rls_enabled or action = 'DELETE' then
                    visible_role_sub_ids = visible_role_sub_ids || subscription_id;
                else
                    -- Check if RLS allows the role to see the record
                    perform
                        -- Trim leading and trailing quotes from working_role because set_config
                        -- doesn't recognize the role as valid if they are included
                        set_config('role', trim(both '"' from working_role::text), true),
                        set_config('request.jwt.claims', claims::text, true);

                    execute 'execute walrus_rls_stmt' into subscription_has_access;

                    if subscription_has_access then
                        visible_role_sub_ids = visible_role_sub_ids || subscription_id;
                    end if;
                end if;
            end loop;

            perform set_config('role', null, true);

            -- Inner loop: per distinct selected_columns for this role
            for cols_record in
                select selected_columns
                from (select distinct selected_columns from unnest(subscriptions) s where s.claims_role = working_role) t
                order by coalesce(array_to_string(selected_columns, ','), '')
            loop
                working_selected_columns := cols_record.selected_columns;

                output = jsonb_build_object(
                    'schema', wal ->> 'schema',
                    'table', wal ->> 'table',
                    'type', action,
                    'commit_timestamp', to_char(
                        ((wal ->> 'timestamp')::timestamptz at time zone 'utc'),
                        'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'
                    ),
                    'columns', (
                        select
                            jsonb_agg(
                                jsonb_build_object(
                                    'name', pa.attname,
                                    'type', pt.typname
                                )
                                order by pa.attnum asc
                            )
                        from
                            pg_attribute pa
                            join pg_type pt
                                on pa.atttypid = pt.oid
                            left join (
                                select unnest(conkey) as pkey_attnum
                                from pg_constraint
                                where conrelid = entity_ and contype = 'p'
                            ) pk on pk.pkey_attnum = pa.attnum
                        where
                            attrelid = entity_
                            and attnum > 0
                            and pg_catalog.has_column_privilege(working_role, entity_, pa.attname, 'SELECT')
                            and (working_selected_columns is null or pa.attname = any(working_selected_columns) or pk.pkey_attnum is not null)
                    )
                )
                -- Add "record" key for insert and update
                || case
                    when action in ('INSERT', 'UPDATE') then
                        jsonb_build_object(
                            'record',
                            (
                                select
                                    jsonb_object_agg(
                                        -- if unchanged toast, get column name and value from old record
                                        coalesce((c).name, (oc).name),
                                        case
                                            when (c).name is null then (oc).value
                                            else (c).value
                                        end
                                    )
                                from
                                    unnest(columns) c
                                    full outer join unnest(old_columns) oc
                                        on (c).name = (oc).name
                                where
                                    coalesce((c).is_selectable, (oc).is_selectable)
                                    and (working_selected_columns is null or coalesce((c).name, (oc).name) = any(working_selected_columns) or coalesce((c).is_pkey, (oc).is_pkey))
                                    and ( not error_record_exceeds_max_size or (octet_length((c).value::text) <= 64))
                            )
                        )
                    else '{}'::jsonb
                end
                -- Add "old_record" key for update and delete
                || case
                    when action = 'UPDATE' then
                        jsonb_build_object(
                                'old_record',
                                (
                                    select jsonb_object_agg((c).name, (c).value)
                                    from unnest(old_columns) c
                                    where
                                        (c).is_selectable
                                        and (working_selected_columns is null or (c).name = any(working_selected_columns) or (c).is_pkey)
                                        and ( not error_record_exceeds_max_size or (octet_length((c).value::text) <= 64))
                                )
                            )
                    when action = 'DELETE' then
                        jsonb_build_object(
                            'old_record',
                            (
                                select jsonb_object_agg((c).name, (c).value)
                                from unnest(old_columns) c
                                where
                                    (c).is_selectable
                                    and (working_selected_columns is null or (c).name = any(working_selected_columns) or (c).is_pkey)
                                    and ( not error_record_exceeds_max_size or (octet_length((c).value::text) <= 64))
                                    and ( not is_rls_enabled or (c).is_pkey ) -- if RLS enabled, we can't secure deletes so filter to pkey
                            )
                        )
                    else '{}'::jsonb
                end;

                -- Filter visible_role_sub_ids to those matching the current selected_columns group
                visible_to_subscription_ids = coalesce(
                    (
                        select array_agg(s.subscription_id)
                        from unnest(subscriptions) s
                        where s.claims_role = working_role
                          and (s.selected_columns is not distinct from working_selected_columns)
                          and s.subscription_id = any(visible_role_sub_ids)
                    ),
                    '{}'::uuid[]
                );

                return next (
                    output,
                    is_rls_enabled,
                    visible_to_subscription_ids,
                    case
                        when error_record_exceeds_max_size then array['Error 413: Payload Too Large']
                        else '{}'
                    end
                )::realtime.wal_rls;
            end loop;

        end if;
    end loop;

    perform set_config('role', null, true);
end;
$$;


ALTER FUNCTION realtime.apply_rls(wal jsonb, max_record_bytes integer) OWNER TO supabase_admin;

--
-- Name: broadcast_changes(text, text, text, text, text, record, record, text); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.broadcast_changes(topic_name text, event_name text, operation text, table_name text, table_schema text, new record, old record, level text DEFAULT 'ROW'::text) RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
    -- Declare a variable to hold the JSONB representation of the row
    row_data jsonb := '{}'::jsonb;
BEGIN
    IF level = 'STATEMENT' THEN
        RAISE EXCEPTION 'function can only be triggered for each row, not for each statement';
    END IF;
    -- Check the operation type and handle accordingly
    IF operation = 'INSERT' OR operation = 'UPDATE' OR operation = 'DELETE' THEN
        row_data := jsonb_build_object('old_record', OLD, 'record', NEW, 'operation', operation, 'table', table_name, 'schema', table_schema);
        PERFORM realtime.send (row_data, event_name, topic_name);
    ELSE
        RAISE EXCEPTION 'Unexpected operation type: %', operation;
    END IF;
EXCEPTION
    WHEN OTHERS THEN
        RAISE EXCEPTION 'Failed to process the row: %', SQLERRM;
END;

$$;


ALTER FUNCTION realtime.broadcast_changes(topic_name text, event_name text, operation text, table_name text, table_schema text, new record, old record, level text) OWNER TO supabase_admin;

--
-- Name: build_prepared_statement_sql(text, regclass, realtime.wal_column[]); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.build_prepared_statement_sql(prepared_statement_name text, entity regclass, columns realtime.wal_column[]) RETURNS text
    LANGUAGE sql
    AS $$
      /*
      Builds a sql string that, if executed, creates a prepared statement to
      tests retrive a row from *entity* by its primary key columns.
      Example
          select realtime.build_prepared_statement_sql('public.notes', '{"id"}'::text[], '{"bigint"}'::text[])
      */
          select
      'prepare ' || prepared_statement_name || ' as
          select
              exists(
                  select
                      1
                  from
                      ' || entity || '
                  where
                      ' || string_agg(quote_ident(pkc.name) || '=' || quote_nullable(pkc.value #>> '{}') , ' and ') || '
              )'
          from
              unnest(columns) pkc
          where
              pkc.is_pkey
          group by
              entity
      $$;


ALTER FUNCTION realtime.build_prepared_statement_sql(prepared_statement_name text, entity regclass, columns realtime.wal_column[]) OWNER TO supabase_admin;

--
-- Name: cast(text, regtype); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime."cast"(val text, type_ regtype) RETURNS jsonb
    LANGUAGE plpgsql IMMUTABLE
    AS $$
declare
  res jsonb;
begin
  if type_::text = 'bytea' then
    return to_jsonb(val);
  end if;
  execute format('select to_jsonb(%L::'|| type_::text || ')', val) into res;
  return res;
end
$$;


ALTER FUNCTION realtime."cast"(val text, type_ regtype) OWNER TO supabase_admin;

--
-- Name: check_equality_op(realtime.equality_op, regtype, text, text); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.check_equality_op(op realtime.equality_op, type_ regtype, val_1 text, val_2 text) RETURNS boolean
    LANGUAGE plpgsql IMMUTABLE
    AS $$
      /*
      Casts *val_1* and *val_2* as type *type_* and check the *op* condition for truthiness
      */
      declare
          op_symbol text = (
              case
                  when op = 'eq' then '='
                  when op = 'neq' then '!='
                  when op = 'lt' then '<'
                  when op = 'lte' then '<='
                  when op = 'gt' then '>'
                  when op = 'gte' then '>='
                  when op = 'in' then '= any'
                  else 'UNKNOWN OP'
              end
          );
          res boolean;
      begin
          execute format(
              'select %L::'|| type_::text || ' ' || op_symbol
              || ' ( %L::'
              || (
                  case
                      when op = 'in' then type_::text || '[]'
                      else type_::text end
              )
              || ')', val_1, val_2) into res;
          return res;
      end;
      $$;


ALTER FUNCTION realtime.check_equality_op(op realtime.equality_op, type_ regtype, val_1 text, val_2 text) OWNER TO supabase_admin;

--
-- Name: is_visible_through_filters(realtime.wal_column[], realtime.user_defined_filter[]); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[]) RETURNS boolean
    LANGUAGE sql IMMUTABLE
    AS $_$
    /*
    Should the record be visible (true) or filtered out (false) after *filters* are applied
    */
        select
            -- Default to allowed when no filters present
            $2 is null -- no filters. this should not happen because subscriptions has a default
            or array_length($2, 1) is null -- array length of an empty array is null
            or bool_and(
                coalesce(
                    realtime.check_equality_op(
                        op:=f.op,
                        type_:=coalesce(
                            col.type_oid::regtype, -- null when wal2json version <= 2.4
                            col.type_name::regtype
                        ),
                        -- cast jsonb to text
                        val_1:=col.value #>> '{}',
                        val_2:=f.value
                    ),
                    false -- if null, filter does not match
                )
            )
        from
            unnest(filters) f
            join unnest(columns) col
                on f.column_name = col.name;
    $_$;


ALTER FUNCTION realtime.is_visible_through_filters(columns realtime.wal_column[], filters realtime.user_defined_filter[]) OWNER TO supabase_admin;

--
-- Name: list_changes(name, name, integer, integer); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.list_changes(publication name, slot_name name, max_changes integer, max_record_bytes integer) RETURNS TABLE(wal jsonb, is_rls_enabled boolean, subscription_ids uuid[], errors text[], slot_changes_count bigint)
    LANGUAGE sql
    SET log_min_messages TO 'fatal'
    AS $$
  WITH pub AS (
    SELECT
      concat_ws(
        ',',
        CASE WHEN bool_or(pubinsert) THEN 'insert' ELSE NULL END,
        CASE WHEN bool_or(pubupdate) THEN 'update' ELSE NULL END,
        CASE WHEN bool_or(pubdelete) THEN 'delete' ELSE NULL END
      ) AS w2j_actions,
      coalesce(
        string_agg(
          realtime.quote_wal2json(format('%I.%I', schemaname, tablename)::regclass),
          ','
        ) filter (WHERE ppt.tablename IS NOT NULL),
        ''
      ) AS w2j_add_tables
    FROM pg_publication pp
    LEFT JOIN pg_publication_tables ppt ON pp.pubname = ppt.pubname
    WHERE pp.pubname = publication
    GROUP BY pp.pubname
    LIMIT 1
  ),
  -- MATERIALIZED ensures pg_logical_slot_get_changes is called exactly once
  w2j AS MATERIALIZED (
    SELECT x.*, pub.w2j_add_tables
    FROM pub,
         pg_logical_slot_get_changes(
           slot_name, null, max_changes,
           'include-pk', 'true',
           'include-transaction', 'false',
           'include-timestamp', 'true',
           'include-type-oids', 'true',
           'format-version', '2',
           'actions', pub.w2j_actions,
           'add-tables', pub.w2j_add_tables
         ) x
  ),
  slot_count AS (
    SELECT count(*)::bigint AS cnt
    FROM w2j
    WHERE w2j.w2j_add_tables <> ''
  ),
  rls_filtered AS (
    SELECT xyz.wal, xyz.is_rls_enabled, xyz.subscription_ids, xyz.errors
    FROM w2j,
         realtime.apply_rls(
           wal := w2j.data::jsonb,
           max_record_bytes := max_record_bytes
         ) xyz(wal, is_rls_enabled, subscription_ids, errors)
    WHERE w2j.w2j_add_tables <> ''
      AND xyz.subscription_ids[1] IS NOT NULL
  )
  SELECT rf.wal, rf.is_rls_enabled, rf.subscription_ids, rf.errors, sc.cnt
  FROM rls_filtered rf, slot_count sc

  UNION ALL

  SELECT null, null, null, null, sc.cnt
  FROM slot_count sc
  WHERE NOT EXISTS (SELECT 1 FROM rls_filtered)
$$;


ALTER FUNCTION realtime.list_changes(publication name, slot_name name, max_changes integer, max_record_bytes integer) OWNER TO supabase_admin;

--
-- Name: quote_wal2json(regclass); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.quote_wal2json(entity regclass) RETURNS text
    LANGUAGE sql IMMUTABLE STRICT
    AS $$
  SELECT
    realtime.wal2json_escape_identifier(nsp.nspname::text)
    || '.'
    || realtime.wal2json_escape_identifier(pc.relname::text)
  FROM pg_class pc
  JOIN pg_namespace nsp ON pc.relnamespace = nsp.oid
  WHERE pc.oid = entity
$$;


ALTER FUNCTION realtime.quote_wal2json(entity regclass) OWNER TO supabase_admin;

--
-- Name: send(jsonb, text, text, boolean); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.send(payload jsonb, event text, topic text, private boolean DEFAULT true) RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
  generated_id uuid;
  final_payload jsonb;
BEGIN
  BEGIN
    -- Generate a new UUID for the id
    generated_id := gen_random_uuid();

    -- Check if payload has an 'id' key, if not, add the generated UUID
    IF payload ? 'id' THEN
      final_payload := payload;
    ELSE
      final_payload := jsonb_set(payload, '{id}', to_jsonb(generated_id));
    END IF;

    -- Set the topic configuration
    EXECUTE format('SET LOCAL realtime.topic TO %L', topic);

    -- Attempt to insert the message
    INSERT INTO realtime.messages (id, payload, event, topic, private, extension)
    VALUES (generated_id, final_payload, event, topic, private, 'broadcast');
  EXCEPTION
    WHEN OTHERS THEN
      -- Capture and notify the error
      RAISE WARNING 'ErrorSendingBroadcastMessage: %', SQLERRM;
  END;
END;
$$;


ALTER FUNCTION realtime.send(payload jsonb, event text, topic text, private boolean) OWNER TO supabase_admin;

--
-- Name: send_binary(bytea, text, text, boolean); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.send_binary(payload bytea, event text, topic text, private boolean DEFAULT true) RETURNS void
    LANGUAGE plpgsql
    AS $$
DECLARE
  generated_id uuid;
BEGIN
  BEGIN
    generated_id := gen_random_uuid();

    EXECUTE format('SET LOCAL realtime.topic TO %L', topic);

    INSERT INTO realtime.messages (id, binary_payload, event, topic, private, extension)
    VALUES (generated_id, payload, event, topic, private, 'broadcast');
  EXCEPTION
    WHEN OTHERS THEN
      RAISE WARNING 'ErrorSendingBroadcastMessage: %', SQLERRM;
  END;
END;
$$;


ALTER FUNCTION realtime.send_binary(payload bytea, event text, topic text, private boolean) OWNER TO supabase_admin;

--
-- Name: subscription_check_filters(); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.subscription_check_filters() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
declare
    col_names text[] = coalesce(
            array_agg(c.column_name order by c.ordinal_position),
            '{}'::text[]
        )
        from
            information_schema.columns c
        where
            format('%I.%I', c.table_schema, c.table_name)::regclass = new.entity
            and pg_catalog.has_column_privilege(
                (new.claims ->> 'role'),
                format('%I.%I', c.table_schema, c.table_name)::regclass,
                c.column_name,
                'SELECT'
            );
    table_col_names text[] = coalesce(
            array_agg(pa.attname),
            '{}'::text[]
        )
        from
            pg_attribute pa
        where
            pa.attrelid = new.entity
            and pa.attnum > 0;
    filter realtime.user_defined_filter;
    col_type regtype;
    in_val jsonb;
    selected_col text;
begin
    for filter in select * from unnest(new.filters) loop
        -- Filtered column is valid
        if not filter.column_name = any(col_names) then
            raise exception 'invalid column for filter %', filter.column_name;
        end if;

        -- Type is sanitized and safe for string interpolation
        col_type = (
            select atttypid::regtype
            from pg_catalog.pg_attribute
            where attrelid = new.entity
                  and attname = filter.column_name
        );
        if col_type is null then
            raise exception 'failed to lookup type for column %', filter.column_name;
        end if;
        if filter.op = 'in'::realtime.equality_op then
            in_val = realtime.cast(filter.value, (col_type::text || '[]')::regtype);
            if coalesce(jsonb_array_length(in_val), 0) > 100 then
                raise exception 'too many values for `in` filter. Maximum 100';
            end if;
        else
            -- raises an exception if value is not coercable to type
            perform realtime.cast(filter.value, col_type);
        end if;
    end loop;

    -- Validate that selected_columns reference columns the role can SELECT
    if new.selected_columns is not null then
        for selected_col in select * from unnest(new.selected_columns) loop
            if not selected_col = any(col_names) then
                raise exception 'invalid column for select %', selected_col;
            end if;
        end loop;
    end if;

    -- Apply consistent order to filters so the unique constraint on
    -- (subscription_id, entity, filters) can't be tricked by a different filter order
    new.filters = coalesce(
        array_agg(f order by f.column_name, f.op, f.value),
        '{}'
    ) from unnest(new.filters) f;

    -- Normalize selected_columns order so ARRAY['a','b'] and ARRAY['b','a'] are
    -- treated as the same subscription group in apply_rls
    new.selected_columns = (
        select array_agg(c order by c)
        from unnest(new.selected_columns) c
    );

    return new;
end;
$$;


ALTER FUNCTION realtime.subscription_check_filters() OWNER TO supabase_admin;

--
-- Name: to_regrole(text); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.to_regrole(role_name text) RETURNS regrole
    LANGUAGE sql IMMUTABLE
    AS $$ select role_name::regrole $$;


ALTER FUNCTION realtime.to_regrole(role_name text) OWNER TO supabase_admin;

--
-- Name: topic(); Type: FUNCTION; Schema: realtime; Owner: supabase_realtime_admin
--

CREATE FUNCTION realtime.topic() RETURNS text
    LANGUAGE sql STABLE
    AS $$
select nullif(current_setting('realtime.topic', true), '')::text;
$$;


ALTER FUNCTION realtime.topic() OWNER TO supabase_realtime_admin;

--
-- Name: wal2json_escape_identifier(text); Type: FUNCTION; Schema: realtime; Owner: supabase_admin
--

CREATE FUNCTION realtime.wal2json_escape_identifier(name text) RETURNS text
    LANGUAGE sql IMMUTABLE STRICT
    AS $$
  -- Prefix `\`, `,`, `.`, and any whitespace with `\`
  SELECT regexp_replace(name, '([\\,.[:space:]])', '\\\1', 'g')
$$;


ALTER FUNCTION realtime.wal2json_escape_identifier(name text) OWNER TO supabase_admin;

--
-- Name: allow_any_operation(text[]); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.allow_any_operation(expected_operations text[]) RETURNS boolean
    LANGUAGE sql STABLE
    AS $$
  WITH current_operation AS (
    SELECT storage.operation() AS raw_operation
  ),
  normalized AS (
    SELECT CASE
      WHEN raw_operation LIKE 'storage.%' THEN substr(raw_operation, 9)
      ELSE raw_operation
    END AS current_operation
    FROM current_operation
  )
  SELECT EXISTS (
    SELECT 1
    FROM normalized n
    CROSS JOIN LATERAL unnest(expected_operations) AS expected_operation
    WHERE expected_operation IS NOT NULL
      AND expected_operation <> ''
      AND n.current_operation = CASE
        WHEN expected_operation LIKE 'storage.%' THEN substr(expected_operation, 9)
        ELSE expected_operation
      END
  );
$$;


ALTER FUNCTION storage.allow_any_operation(expected_operations text[]) OWNER TO supabase_storage_admin;

--
-- Name: allow_only_operation(text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.allow_only_operation(expected_operation text) RETURNS boolean
    LANGUAGE sql STABLE
    AS $$
  WITH current_operation AS (
    SELECT storage.operation() AS raw_operation
  ),
  normalized AS (
    SELECT
      CASE
        WHEN raw_operation LIKE 'storage.%' THEN substr(raw_operation, 9)
        ELSE raw_operation
      END AS current_operation,
      CASE
        WHEN expected_operation LIKE 'storage.%' THEN substr(expected_operation, 9)
        ELSE expected_operation
      END AS requested_operation
    FROM current_operation
  )
  SELECT CASE
    WHEN requested_operation IS NULL OR requested_operation = '' THEN FALSE
    ELSE COALESCE(current_operation = requested_operation, FALSE)
  END
  FROM normalized;
$$;


ALTER FUNCTION storage.allow_only_operation(expected_operation text) OWNER TO supabase_storage_admin;

--
-- Name: can_insert_object(text, text, uuid, jsonb); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.can_insert_object(bucketid text, name text, owner uuid, metadata jsonb) RETURNS void
    LANGUAGE plpgsql
    AS $$
BEGIN
  INSERT INTO "storage"."objects" ("bucket_id", "name", "owner", "metadata") VALUES (bucketid, name, owner, metadata);
  -- hack to rollback the successful insert
  RAISE sqlstate 'PT200' using
  message = 'ROLLBACK',
  detail = 'rollback successful insert';
END
$$;


ALTER FUNCTION storage.can_insert_object(bucketid text, name text, owner uuid, metadata jsonb) OWNER TO supabase_storage_admin;

--
-- Name: enforce_bucket_name_length(); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.enforce_bucket_name_length() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
begin
    if length(new.name) > 100 then
        raise exception 'bucket name "%" is too long (% characters). Max is 100.', new.name, length(new.name);
    end if;
    return new;
end;
$$;


ALTER FUNCTION storage.enforce_bucket_name_length() OWNER TO supabase_storage_admin;

--
-- Name: extension(text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.extension(name text) RETURNS text
    LANGUAGE plpgsql IMMUTABLE
    AS $$
DECLARE
    _parts text[];
    _filename text;
BEGIN
    -- Split on "/" to get path segments
    SELECT string_to_array(name, '/') INTO _parts;
    -- Get the last path segment (the actual filename)
    SELECT _parts[array_length(_parts, 1)] INTO _filename;
    -- Extract extension: reverse, split on '.', then reverse again
    RETURN reverse(split_part(reverse(_filename), '.', 1));
END
$$;


ALTER FUNCTION storage.extension(name text) OWNER TO supabase_storage_admin;

--
-- Name: filename(text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.filename(name text) RETURNS text
    LANGUAGE plpgsql
    AS $$
DECLARE
_parts text[];
BEGIN
	select string_to_array(name, '/') into _parts;
	return _parts[array_length(_parts,1)];
END
$$;


ALTER FUNCTION storage.filename(name text) OWNER TO supabase_storage_admin;

--
-- Name: foldername(text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.foldername(name text) RETURNS text[]
    LANGUAGE plpgsql IMMUTABLE
    AS $$
DECLARE
    _parts text[];
BEGIN
    -- Split on "/" to get path segments
    SELECT string_to_array(name, '/') INTO _parts;
    -- Return everything except the last segment
    RETURN _parts[1 : array_length(_parts,1) - 1];
END
$$;


ALTER FUNCTION storage.foldername(name text) OWNER TO supabase_storage_admin;

--
-- Name: get_common_prefix(text, text, text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.get_common_prefix(p_key text, p_prefix text, p_delimiter text) RETURNS text
    LANGUAGE sql IMMUTABLE
    AS $$
SELECT CASE
    WHEN position(p_delimiter IN substring(p_key FROM length(p_prefix) + 1)) > 0
    THEN left(p_key, length(p_prefix) + position(p_delimiter IN substring(p_key FROM length(p_prefix) + 1)))
    ELSE NULL
END;
$$;


ALTER FUNCTION storage.get_common_prefix(p_key text, p_prefix text, p_delimiter text) OWNER TO supabase_storage_admin;

--
-- Name: get_size_by_bucket(); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.get_size_by_bucket() RETURNS TABLE(size bigint, bucket_id text)
    LANGUAGE plpgsql STABLE
    AS $$
BEGIN
    return query
        select sum((metadata->>'size')::bigint)::bigint as size, obj.bucket_id
        from "storage".objects as obj
        group by obj.bucket_id;
END
$$;


ALTER FUNCTION storage.get_size_by_bucket() OWNER TO supabase_storage_admin;

--
-- Name: list_multipart_uploads_with_delimiter(text, text, text, integer, text, text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.list_multipart_uploads_with_delimiter(bucket_id text, prefix_param text, delimiter_param text, max_keys integer DEFAULT 100, next_key_token text DEFAULT ''::text, next_upload_token text DEFAULT ''::text) RETURNS TABLE(key text, id text, created_at timestamp with time zone)
    LANGUAGE plpgsql
    AS $_$
BEGIN
    RETURN QUERY EXECUTE
        'SELECT DISTINCT ON(key COLLATE "C") * from (
            SELECT
                CASE
                    WHEN position($2 IN substring(key from length($1) + 1)) > 0 THEN
                        substring(key from 1 for length($1) + position($2 IN substring(key from length($1) + 1)))
                    ELSE
                        key
                END AS key, id, created_at
            FROM
                storage.s3_multipart_uploads
            WHERE
                bucket_id = $5 AND
                key ILIKE $1 || ''%'' AND
                CASE
                    WHEN $4 != '''' AND $6 = '''' THEN
                        CASE
                            WHEN position($2 IN substring(key from length($1) + 1)) > 0 THEN
                                substring(key from 1 for length($1) + position($2 IN substring(key from length($1) + 1))) COLLATE "C" > $4
                            ELSE
                                key COLLATE "C" > $4
                            END
                    ELSE
                        true
                END AND
                CASE
                    WHEN $6 != '''' THEN
                        id COLLATE "C" > $6
                    ELSE
                        true
                    END
            ORDER BY
                key COLLATE "C" ASC, created_at ASC) as e order by key COLLATE "C" LIMIT $3'
        USING prefix_param, delimiter_param, max_keys, next_key_token, bucket_id, next_upload_token;
END;
$_$;


ALTER FUNCTION storage.list_multipart_uploads_with_delimiter(bucket_id text, prefix_param text, delimiter_param text, max_keys integer, next_key_token text, next_upload_token text) OWNER TO supabase_storage_admin;

--
-- Name: list_objects_with_delimiter(text, text, text, integer, text, text, text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.list_objects_with_delimiter(_bucket_id text, prefix_param text, delimiter_param text, max_keys integer DEFAULT 100, start_after text DEFAULT ''::text, next_token text DEFAULT ''::text, sort_order text DEFAULT 'asc'::text) RETURNS TABLE(name text, id uuid, metadata jsonb, updated_at timestamp with time zone, created_at timestamp with time zone, last_accessed_at timestamp with time zone)
    LANGUAGE plpgsql STABLE
    AS $_$
DECLARE
    v_peek_name TEXT;
    v_current RECORD;
    v_common_prefix TEXT;

    -- Configuration
    v_is_asc BOOLEAN;
    v_prefix TEXT;
    v_start TEXT;
    v_upper_bound TEXT;
    v_file_batch_size INT;

    -- Seek state
    v_next_seek TEXT;
    v_count INT := 0;

    -- Dynamic SQL for batch query only
    v_batch_query TEXT;

BEGIN
    -- ========================================================================
    -- INITIALIZATION
    -- ========================================================================
    v_is_asc := lower(coalesce(sort_order, 'asc')) = 'asc';
    v_prefix := coalesce(prefix_param, '');
    v_start := CASE WHEN coalesce(next_token, '') <> '' THEN next_token ELSE coalesce(start_after, '') END;
    v_file_batch_size := LEAST(GREATEST(max_keys * 2, 100), 1000);

    -- Calculate upper bound for prefix filtering (bytewise, using COLLATE "C")
    IF v_prefix = '' THEN
        v_upper_bound := NULL;
    ELSIF right(v_prefix, 1) = delimiter_param THEN
        v_upper_bound := left(v_prefix, -1) || chr(ascii(delimiter_param) + 1);
    ELSE
        v_upper_bound := left(v_prefix, -1) || chr(ascii(right(v_prefix, 1)) + 1);
    END IF;

    -- Build batch query (dynamic SQL - called infrequently, amortized over many rows)
    IF v_is_asc THEN
        IF v_upper_bound IS NOT NULL THEN
            v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
                'FROM storage.objects o WHERE o.bucket_id = $1 AND o.name COLLATE "C" >= $2 ' ||
                'AND o.name COLLATE "C" < $3 ORDER BY o.name COLLATE "C" ASC LIMIT $4';
        ELSE
            v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
                'FROM storage.objects o WHERE o.bucket_id = $1 AND o.name COLLATE "C" >= $2 ' ||
                'ORDER BY o.name COLLATE "C" ASC LIMIT $4';
        END IF;
    ELSE
        IF v_upper_bound IS NOT NULL THEN
            v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
                'FROM storage.objects o WHERE o.bucket_id = $1 AND o.name COLLATE "C" < $2 ' ||
                'AND o.name COLLATE "C" >= $3 ORDER BY o.name COLLATE "C" DESC LIMIT $4';
        ELSE
            v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
                'FROM storage.objects o WHERE o.bucket_id = $1 AND o.name COLLATE "C" < $2 ' ||
                'ORDER BY o.name COLLATE "C" DESC LIMIT $4';
        END IF;
    END IF;

    -- ========================================================================
    -- SEEK INITIALIZATION: Determine starting position
    -- ========================================================================
    IF v_start = '' THEN
        IF v_is_asc THEN
            v_next_seek := v_prefix;
        ELSE
            -- DESC without cursor: find the last item in range
            IF v_upper_bound IS NOT NULL THEN
                SELECT o.name INTO v_next_seek FROM storage.objects o
                WHERE o.bucket_id = _bucket_id AND o.name COLLATE "C" >= v_prefix AND o.name COLLATE "C" < v_upper_bound
                ORDER BY o.name COLLATE "C" DESC LIMIT 1;
            ELSIF v_prefix <> '' THEN
                SELECT o.name INTO v_next_seek FROM storage.objects o
                WHERE o.bucket_id = _bucket_id AND o.name COLLATE "C" >= v_prefix
                ORDER BY o.name COLLATE "C" DESC LIMIT 1;
            ELSE
                SELECT o.name INTO v_next_seek FROM storage.objects o
                WHERE o.bucket_id = _bucket_id
                ORDER BY o.name COLLATE "C" DESC LIMIT 1;
            END IF;

            IF v_next_seek IS NOT NULL THEN
                v_next_seek := v_next_seek || delimiter_param;
            ELSE
                RETURN;
            END IF;
        END IF;
    ELSE
        -- Cursor provided: determine if it refers to a folder or leaf
        IF EXISTS (
            SELECT 1 FROM storage.objects o
            WHERE o.bucket_id = _bucket_id
              AND o.name COLLATE "C" LIKE v_start || delimiter_param || '%'
            LIMIT 1
        ) THEN
            -- Cursor refers to a folder
            IF v_is_asc THEN
                v_next_seek := v_start || chr(ascii(delimiter_param) + 1);
            ELSE
                v_next_seek := v_start || delimiter_param;
            END IF;
        ELSE
            -- Cursor refers to a leaf object
            IF v_is_asc THEN
                v_next_seek := v_start || delimiter_param;
            ELSE
                v_next_seek := v_start;
            END IF;
        END IF;
    END IF;

    -- ========================================================================
    -- MAIN LOOP: Hybrid peek-then-batch algorithm
    -- Uses STATIC SQL for peek (hot path) and DYNAMIC SQL for batch
    -- ========================================================================
    LOOP
        EXIT WHEN v_count >= max_keys;

        -- STEP 1: PEEK using STATIC SQL (plan cached, very fast)
        IF v_is_asc THEN
            IF v_upper_bound IS NOT NULL THEN
                SELECT o.name INTO v_peek_name FROM storage.objects o
                WHERE o.bucket_id = _bucket_id AND o.name COLLATE "C" >= v_next_seek AND o.name COLLATE "C" < v_upper_bound
                ORDER BY o.name COLLATE "C" ASC LIMIT 1;
            ELSE
                SELECT o.name INTO v_peek_name FROM storage.objects o
                WHERE o.bucket_id = _bucket_id AND o.name COLLATE "C" >= v_next_seek
                ORDER BY o.name COLLATE "C" ASC LIMIT 1;
            END IF;
        ELSE
            IF v_upper_bound IS NOT NULL THEN
                SELECT o.name INTO v_peek_name FROM storage.objects o
                WHERE o.bucket_id = _bucket_id AND o.name COLLATE "C" < v_next_seek AND o.name COLLATE "C" >= v_prefix
                ORDER BY o.name COLLATE "C" DESC LIMIT 1;
            ELSIF v_prefix <> '' THEN
                SELECT o.name INTO v_peek_name FROM storage.objects o
                WHERE o.bucket_id = _bucket_id AND o.name COLLATE "C" < v_next_seek AND o.name COLLATE "C" >= v_prefix
                ORDER BY o.name COLLATE "C" DESC LIMIT 1;
            ELSE
                SELECT o.name INTO v_peek_name FROM storage.objects o
                WHERE o.bucket_id = _bucket_id AND o.name COLLATE "C" < v_next_seek
                ORDER BY o.name COLLATE "C" DESC LIMIT 1;
            END IF;
        END IF;

        EXIT WHEN v_peek_name IS NULL;

        -- STEP 2: Check if this is a FOLDER or FILE
        v_common_prefix := storage.get_common_prefix(v_peek_name, v_prefix, delimiter_param);

        IF v_common_prefix IS NOT NULL THEN
            -- FOLDER: Emit and skip to next folder (no heap access needed)
            name := rtrim(v_common_prefix, delimiter_param);
            id := NULL;
            updated_at := NULL;
            created_at := NULL;
            last_accessed_at := NULL;
            metadata := NULL;
            RETURN NEXT;
            v_count := v_count + 1;

            -- Advance seek past the folder range
            IF v_is_asc THEN
                v_next_seek := left(v_common_prefix, -1) || chr(ascii(delimiter_param) + 1);
            ELSE
                v_next_seek := v_common_prefix;
            END IF;
        ELSE
            -- FILE: Batch fetch using DYNAMIC SQL (overhead amortized over many rows)
            -- For ASC: upper_bound is the exclusive upper limit (< condition)
            -- For DESC: prefix is the inclusive lower limit (>= condition)
            FOR v_current IN EXECUTE v_batch_query USING _bucket_id, v_next_seek,
                CASE WHEN v_is_asc THEN COALESCE(v_upper_bound, v_prefix) ELSE v_prefix END, v_file_batch_size
            LOOP
                v_common_prefix := storage.get_common_prefix(v_current.name, v_prefix, delimiter_param);

                IF v_common_prefix IS NOT NULL THEN
                    -- Hit a folder: exit batch, let peek handle it
                    v_next_seek := v_current.name;
                    EXIT;
                END IF;

                -- Emit file
                name := v_current.name;
                id := v_current.id;
                updated_at := v_current.updated_at;
                created_at := v_current.created_at;
                last_accessed_at := v_current.last_accessed_at;
                metadata := v_current.metadata;
                RETURN NEXT;
                v_count := v_count + 1;

                -- Advance seek past this file
                IF v_is_asc THEN
                    v_next_seek := v_current.name || delimiter_param;
                ELSE
                    v_next_seek := v_current.name;
                END IF;

                EXIT WHEN v_count >= max_keys;
            END LOOP;
        END IF;
    END LOOP;
END;
$_$;


ALTER FUNCTION storage.list_objects_with_delimiter(_bucket_id text, prefix_param text, delimiter_param text, max_keys integer, start_after text, next_token text, sort_order text) OWNER TO supabase_storage_admin;

--
-- Name: operation(); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.operation() RETURNS text
    LANGUAGE plpgsql STABLE
    AS $$
BEGIN
    RETURN current_setting('storage.operation', true);
END;
$$;


ALTER FUNCTION storage.operation() OWNER TO supabase_storage_admin;

--
-- Name: protect_delete(); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.protect_delete() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
    -- Check if storage.allow_delete_query is set to 'true'
    IF COALESCE(current_setting('storage.allow_delete_query', true), 'false') != 'true' THEN
        RAISE EXCEPTION 'Direct deletion from storage tables is not allowed. Use the Storage API instead.'
            USING HINT = 'This prevents accidental data loss from orphaned objects.',
                  ERRCODE = '42501';
    END IF;
    RETURN NULL;
END;
$$;


ALTER FUNCTION storage.protect_delete() OWNER TO supabase_storage_admin;

--
-- Name: search(text, text, integer, integer, integer, text, text, text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.search(prefix text, bucketname text, limits integer DEFAULT 100, levels integer DEFAULT 1, offsets integer DEFAULT 0, search text DEFAULT ''::text, sortcolumn text DEFAULT 'name'::text, sortorder text DEFAULT 'asc'::text) RETURNS TABLE(name text, id uuid, updated_at timestamp with time zone, created_at timestamp with time zone, last_accessed_at timestamp with time zone, metadata jsonb)
    LANGUAGE plpgsql STABLE
    AS $_$
DECLARE
    v_peek_name TEXT;
    v_current RECORD;
    v_common_prefix TEXT;
    v_delimiter CONSTANT TEXT := '/';

    -- Configuration
    v_limit INT;
    v_prefix TEXT;
    v_prefix_lower TEXT;
    v_is_asc BOOLEAN;
    v_order_by TEXT;
    v_sort_order TEXT;
    v_upper_bound TEXT;
    v_file_batch_size INT;

    -- Dynamic SQL for batch query only
    v_batch_query TEXT;

    -- Seek state
    v_next_seek TEXT;
    v_count INT := 0;
    v_skipped INT := 0;
BEGIN
    -- ========================================================================
    -- INITIALIZATION
    -- ========================================================================
    v_limit := LEAST(coalesce(limits, 100), 1500);
    v_prefix := coalesce(prefix, '') || coalesce(search, '');
    v_prefix_lower := lower(v_prefix);
    v_is_asc := lower(coalesce(sortorder, 'asc')) = 'asc';
    v_file_batch_size := LEAST(GREATEST(v_limit * 2, 100), 1000);

    -- Validate sort column
    CASE lower(coalesce(sortcolumn, 'name'))
        WHEN 'name' THEN v_order_by := 'name';
        WHEN 'updated_at' THEN v_order_by := 'updated_at';
        WHEN 'created_at' THEN v_order_by := 'created_at';
        WHEN 'last_accessed_at' THEN v_order_by := 'last_accessed_at';
        ELSE v_order_by := 'name';
    END CASE;

    v_sort_order := CASE WHEN v_is_asc THEN 'asc' ELSE 'desc' END;

    -- ========================================================================
    -- NON-NAME SORTING: Use path_tokens approach (unchanged)
    -- ========================================================================
    IF v_order_by != 'name' THEN
        RETURN QUERY EXECUTE format(
            $sql$
            WITH folders AS (
                SELECT path_tokens[$1] AS folder
                FROM storage.objects
                WHERE objects.name ILIKE $2 || '%%'
                  AND bucket_id = $3
                  AND array_length(objects.path_tokens, 1) <> $1
                GROUP BY folder
                ORDER BY folder %s
            )
            (SELECT folder AS "name",
                   NULL::uuid AS id,
                   NULL::timestamptz AS updated_at,
                   NULL::timestamptz AS created_at,
                   NULL::timestamptz AS last_accessed_at,
                   NULL::jsonb AS metadata FROM folders)
            UNION ALL
            (SELECT path_tokens[$1] AS "name",
                   id, updated_at, created_at, last_accessed_at, metadata
             FROM storage.objects
             WHERE objects.name ILIKE $2 || '%%'
               AND bucket_id = $3
               AND array_length(objects.path_tokens, 1) = $1
             ORDER BY %I %s)
            LIMIT $4 OFFSET $5
            $sql$, v_sort_order, v_order_by, v_sort_order
        ) USING levels, v_prefix, bucketname, v_limit, offsets;
        RETURN;
    END IF;

    -- ========================================================================
    -- NAME SORTING: Hybrid skip-scan with batch optimization
    -- ========================================================================

    -- Calculate upper bound for prefix filtering
    IF v_prefix_lower = '' THEN
        v_upper_bound := NULL;
    ELSIF right(v_prefix_lower, 1) = v_delimiter THEN
        v_upper_bound := left(v_prefix_lower, -1) || chr(ascii(v_delimiter) + 1);
    ELSE
        v_upper_bound := left(v_prefix_lower, -1) || chr(ascii(right(v_prefix_lower, 1)) + 1);
    END IF;

    -- Build batch query (dynamic SQL - called infrequently, amortized over many rows)
    IF v_is_asc THEN
        IF v_upper_bound IS NOT NULL THEN
            v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
                'FROM storage.objects o WHERE o.bucket_id = $1 AND lower(o.name) COLLATE "C" >= $2 ' ||
                'AND lower(o.name) COLLATE "C" < $3 ORDER BY lower(o.name) COLLATE "C" ASC LIMIT $4';
        ELSE
            v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
                'FROM storage.objects o WHERE o.bucket_id = $1 AND lower(o.name) COLLATE "C" >= $2 ' ||
                'ORDER BY lower(o.name) COLLATE "C" ASC LIMIT $4';
        END IF;
    ELSE
        IF v_upper_bound IS NOT NULL THEN
            v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
                'FROM storage.objects o WHERE o.bucket_id = $1 AND lower(o.name) COLLATE "C" < $2 ' ||
                'AND lower(o.name) COLLATE "C" >= $3 ORDER BY lower(o.name) COLLATE "C" DESC LIMIT $4';
        ELSE
            v_batch_query := 'SELECT o.name, o.id, o.updated_at, o.created_at, o.last_accessed_at, o.metadata ' ||
                'FROM storage.objects o WHERE o.bucket_id = $1 AND lower(o.name) COLLATE "C" < $2 ' ||
                'ORDER BY lower(o.name) COLLATE "C" DESC LIMIT $4';
        END IF;
    END IF;

    -- Initialize seek position
    IF v_is_asc THEN
        v_next_seek := v_prefix_lower;
    ELSE
        -- DESC: find the last item in range first (static SQL)
        IF v_upper_bound IS NOT NULL THEN
            SELECT o.name INTO v_peek_name FROM storage.objects o
            WHERE o.bucket_id = bucketname AND lower(o.name) COLLATE "C" >= v_prefix_lower AND lower(o.name) COLLATE "C" < v_upper_bound
            ORDER BY lower(o.name) COLLATE "C" DESC LIMIT 1;
        ELSIF v_prefix_lower <> '' THEN
            SELECT o.name INTO v_peek_name FROM storage.objects o
            WHERE o.bucket_id = bucketname AND lower(o.name) COLLATE "C" >= v_prefix_lower
            ORDER BY lower(o.name) COLLATE "C" DESC LIMIT 1;
        ELSE
            SELECT o.name INTO v_peek_name FROM storage.objects o
            WHERE o.bucket_id = bucketname
            ORDER BY lower(o.name) COLLATE "C" DESC LIMIT 1;
        END IF;

        IF v_peek_name IS NOT NULL THEN
            v_next_seek := lower(v_peek_name) || v_delimiter;
        ELSE
            RETURN;
        END IF;
    END IF;

    -- ========================================================================
    -- MAIN LOOP: Hybrid peek-then-batch algorithm
    -- Uses STATIC SQL for peek (hot path) and DYNAMIC SQL for batch
    -- ========================================================================
    LOOP
        EXIT WHEN v_count >= v_limit;

        -- STEP 1: PEEK using STATIC SQL (plan cached, very fast)
        IF v_is_asc THEN
            IF v_upper_bound IS NOT NULL THEN
                SELECT o.name INTO v_peek_name FROM storage.objects o
                WHERE o.bucket_id = bucketname AND lower(o.name) COLLATE "C" >= v_next_seek AND lower(o.name) COLLATE "C" < v_upper_bound
                ORDER BY lower(o.name) COLLATE "C" ASC LIMIT 1;
            ELSE
                SELECT o.name INTO v_peek_name FROM storage.objects o
                WHERE o.bucket_id = bucketname AND lower(o.name) COLLATE "C" >= v_next_seek
                ORDER BY lower(o.name) COLLATE "C" ASC LIMIT 1;
            END IF;
        ELSE
            IF v_upper_bound IS NOT NULL THEN
                SELECT o.name INTO v_peek_name FROM storage.objects o
                WHERE o.bucket_id = bucketname AND lower(o.name) COLLATE "C" < v_next_seek AND lower(o.name) COLLATE "C" >= v_prefix_lower
                ORDER BY lower(o.name) COLLATE "C" DESC LIMIT 1;
            ELSIF v_prefix_lower <> '' THEN
                SELECT o.name INTO v_peek_name FROM storage.objects o
                WHERE o.bucket_id = bucketname AND lower(o.name) COLLATE "C" < v_next_seek AND lower(o.name) COLLATE "C" >= v_prefix_lower
                ORDER BY lower(o.name) COLLATE "C" DESC LIMIT 1;
            ELSE
                SELECT o.name INTO v_peek_name FROM storage.objects o
                WHERE o.bucket_id = bucketname AND lower(o.name) COLLATE "C" < v_next_seek
                ORDER BY lower(o.name) COLLATE "C" DESC LIMIT 1;
            END IF;
        END IF;

        EXIT WHEN v_peek_name IS NULL;

        -- STEP 2: Check if this is a FOLDER or FILE
        v_common_prefix := storage.get_common_prefix(lower(v_peek_name), v_prefix_lower, v_delimiter);

        IF v_common_prefix IS NOT NULL THEN
            -- FOLDER: Handle offset, emit if needed, skip to next folder
            IF v_skipped < offsets THEN
                v_skipped := v_skipped + 1;
            ELSE
                name := split_part(rtrim(storage.get_common_prefix(v_peek_name, v_prefix, v_delimiter), v_delimiter), v_delimiter, levels);
                id := NULL;
                updated_at := NULL;
                created_at := NULL;
                last_accessed_at := NULL;
                metadata := NULL;
                RETURN NEXT;
                v_count := v_count + 1;
            END IF;

            -- Advance seek past the folder range
            IF v_is_asc THEN
                v_next_seek := lower(left(v_common_prefix, -1)) || chr(ascii(v_delimiter) + 1);
            ELSE
                v_next_seek := lower(v_common_prefix);
            END IF;
        ELSE
            -- FILE: Batch fetch using DYNAMIC SQL (overhead amortized over many rows)
            -- For ASC: upper_bound is the exclusive upper limit (< condition)
            -- For DESC: prefix_lower is the inclusive lower limit (>= condition)
            FOR v_current IN EXECUTE v_batch_query
                USING bucketname, v_next_seek,
                    CASE WHEN v_is_asc THEN COALESCE(v_upper_bound, v_prefix_lower) ELSE v_prefix_lower END, v_file_batch_size
            LOOP
                v_common_prefix := storage.get_common_prefix(lower(v_current.name), v_prefix_lower, v_delimiter);

                IF v_common_prefix IS NOT NULL THEN
                    -- Hit a folder: exit batch, let peek handle it
                    v_next_seek := lower(v_current.name);
                    EXIT;
                END IF;

                -- Handle offset skipping
                IF v_skipped < offsets THEN
                    v_skipped := v_skipped + 1;
                ELSE
                    -- Emit file
                    name := split_part(v_current.name, v_delimiter, levels);
                    id := v_current.id;
                    updated_at := v_current.updated_at;
                    created_at := v_current.created_at;
                    last_accessed_at := v_current.last_accessed_at;
                    metadata := v_current.metadata;
                    RETURN NEXT;
                    v_count := v_count + 1;
                END IF;

                -- Advance seek past this file
                IF v_is_asc THEN
                    v_next_seek := lower(v_current.name) || v_delimiter;
                ELSE
                    v_next_seek := lower(v_current.name);
                END IF;

                EXIT WHEN v_count >= v_limit;
            END LOOP;
        END IF;
    END LOOP;
END;
$_$;


ALTER FUNCTION storage.search(prefix text, bucketname text, limits integer, levels integer, offsets integer, search text, sortcolumn text, sortorder text) OWNER TO supabase_storage_admin;

--
-- Name: search_by_timestamp(text, text, integer, integer, text, text, text, text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.search_by_timestamp(p_prefix text, p_bucket_id text, p_limit integer, p_level integer, p_start_after text, p_sort_order text, p_sort_column text, p_sort_column_after text) RETURNS TABLE(key text, name text, id uuid, updated_at timestamp with time zone, created_at timestamp with time zone, last_accessed_at timestamp with time zone, metadata jsonb)
    LANGUAGE plpgsql STABLE
    AS $_$
DECLARE
    v_cursor_op text;
    v_query text;
    v_prefix text;
BEGIN
    v_prefix := coalesce(p_prefix, '');

    IF p_sort_order = 'asc' THEN
        v_cursor_op := '>';
    ELSE
        v_cursor_op := '<';
    END IF;

    v_query := format($sql$
        WITH raw_objects AS (
            SELECT
                o.name AS obj_name,
                o.id AS obj_id,
                o.updated_at AS obj_updated_at,
                o.created_at AS obj_created_at,
                o.last_accessed_at AS obj_last_accessed_at,
                o.metadata AS obj_metadata,
                storage.get_common_prefix(o.name, $1, '/') AS common_prefix
            FROM storage.objects o
            WHERE o.bucket_id = $2
              AND o.name COLLATE "C" LIKE $1 || '%%'
        ),
        -- Aggregate common prefixes (folders)
        -- Both created_at and updated_at use MIN(obj_created_at) to match the old prefixes table behavior
        aggregated_prefixes AS (
            SELECT
                rtrim(common_prefix, '/') AS name,
                NULL::uuid AS id,
                MIN(obj_created_at) AS updated_at,
                MIN(obj_created_at) AS created_at,
                NULL::timestamptz AS last_accessed_at,
                NULL::jsonb AS metadata,
                TRUE AS is_prefix
            FROM raw_objects
            WHERE common_prefix IS NOT NULL
            GROUP BY common_prefix
        ),
        leaf_objects AS (
            SELECT
                obj_name AS name,
                obj_id AS id,
                obj_updated_at AS updated_at,
                obj_created_at AS created_at,
                obj_last_accessed_at AS last_accessed_at,
                obj_metadata AS metadata,
                FALSE AS is_prefix
            FROM raw_objects
            WHERE common_prefix IS NULL
        ),
        combined AS (
            SELECT * FROM aggregated_prefixes
            UNION ALL
            SELECT * FROM leaf_objects
        ),
        filtered AS (
            SELECT *
            FROM combined
            WHERE (
                $5 = ''
                OR ROW(
                    date_trunc('milliseconds', %I),
                    name COLLATE "C"
                ) %s ROW(
                    COALESCE(NULLIF($6, '')::timestamptz, 'epoch'::timestamptz),
                    $5
                )
            )
        )
        SELECT
            split_part(name, '/', $3) AS key,
            name,
            id,
            updated_at,
            created_at,
            last_accessed_at,
            metadata
        FROM filtered
        ORDER BY
            COALESCE(date_trunc('milliseconds', %I), 'epoch'::timestamptz) %s,
            name COLLATE "C" %s
        LIMIT $4
    $sql$,
        p_sort_column,
        v_cursor_op,
        p_sort_column,
        p_sort_order,
        p_sort_order
    );

    RETURN QUERY EXECUTE v_query
    USING v_prefix, p_bucket_id, p_level, p_limit, p_start_after, p_sort_column_after;
END;
$_$;


ALTER FUNCTION storage.search_by_timestamp(p_prefix text, p_bucket_id text, p_limit integer, p_level integer, p_start_after text, p_sort_order text, p_sort_column text, p_sort_column_after text) OWNER TO supabase_storage_admin;

--
-- Name: search_v2(text, text, integer, integer, text, text, text, text); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.search_v2(prefix text, bucket_name text, limits integer DEFAULT 100, levels integer DEFAULT 1, start_after text DEFAULT ''::text, sort_order text DEFAULT 'asc'::text, sort_column text DEFAULT 'name'::text, sort_column_after text DEFAULT ''::text) RETURNS TABLE(key text, name text, id uuid, updated_at timestamp with time zone, created_at timestamp with time zone, last_accessed_at timestamp with time zone, metadata jsonb)
    LANGUAGE plpgsql STABLE
    AS $$
DECLARE
    v_sort_col text;
    v_sort_ord text;
    v_limit int;
BEGIN
    -- Cap limit to maximum of 1500 records
    v_limit := LEAST(coalesce(limits, 100), 1500);

    -- Validate and normalize sort_order
    v_sort_ord := lower(coalesce(sort_order, 'asc'));
    IF v_sort_ord NOT IN ('asc', 'desc') THEN
        v_sort_ord := 'asc';
    END IF;

    -- Validate and normalize sort_column
    v_sort_col := lower(coalesce(sort_column, 'name'));
    IF v_sort_col NOT IN ('name', 'updated_at', 'created_at') THEN
        v_sort_col := 'name';
    END IF;

    -- Route to appropriate implementation
    IF v_sort_col = 'name' THEN
        -- Use list_objects_with_delimiter for name sorting (most efficient: O(k * log n))
        RETURN QUERY
        SELECT
            split_part(l.name, '/', levels) AS key,
            l.name AS name,
            l.id,
            l.updated_at,
            l.created_at,
            l.last_accessed_at,
            l.metadata
        FROM storage.list_objects_with_delimiter(
            bucket_name,
            coalesce(prefix, ''),
            '/',
            v_limit,
            start_after,
            '',
            v_sort_ord
        ) l;
    ELSE
        -- Use aggregation approach for timestamp sorting
        -- Not efficient for large datasets but supports correct pagination
        RETURN QUERY SELECT * FROM storage.search_by_timestamp(
            prefix, bucket_name, v_limit, levels, start_after,
            v_sort_ord, v_sort_col, sort_column_after
        );
    END IF;
END;
$$;


ALTER FUNCTION storage.search_v2(prefix text, bucket_name text, limits integer, levels integer, start_after text, sort_order text, sort_column text, sort_column_after text) OWNER TO supabase_storage_admin;

--
-- Name: update_updated_at_column(); Type: FUNCTION; Schema: storage; Owner: supabase_storage_admin
--

CREATE FUNCTION storage.update_updated_at_column() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
    NEW.updated_at = now();
    RETURN NEW; 
END;
$$;


ALTER FUNCTION storage.update_updated_at_column() OWNER TO supabase_storage_admin;

--
-- Name: http_request(); Type: FUNCTION; Schema: supabase_functions; Owner: supabase_functions_admin
--

CREATE FUNCTION supabase_functions.http_request() RETURNS trigger
    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO 'supabase_functions'
    AS $$
  DECLARE
    request_id bigint;
    payload jsonb;
    url text := TG_ARGV[0]::text;
    method text := TG_ARGV[1]::text;
    headers jsonb DEFAULT '{}'::jsonb;
    params jsonb DEFAULT '{}'::jsonb;
    timeout_ms integer DEFAULT 1000;
  BEGIN
    IF url IS NULL OR url = 'null' THEN
      RAISE EXCEPTION 'url argument is missing';
    END IF;

    IF method IS NULL OR method = 'null' THEN
      RAISE EXCEPTION 'method argument is missing';
    END IF;

    IF TG_ARGV[2] IS NULL OR TG_ARGV[2] = 'null' THEN
      headers = '{"Content-Type": "application/json"}'::jsonb;
    ELSE
      headers = TG_ARGV[2]::jsonb;
    END IF;

    IF TG_ARGV[3] IS NULL OR TG_ARGV[3] = 'null' THEN
      params = '{}'::jsonb;
    ELSE
      params = TG_ARGV[3]::jsonb;
    END IF;

    IF TG_ARGV[4] IS NULL OR TG_ARGV[4] = 'null' THEN
      timeout_ms = 1000;
    ELSE
      timeout_ms = TG_ARGV[4]::integer;
    END IF;

    CASE
      WHEN method = 'GET' THEN
        SELECT http_get INTO request_id FROM net.http_get(
          url,
          params,
          headers,
          timeout_ms
        );
      WHEN method = 'POST' THEN
        payload = jsonb_build_object(
          'old_record', OLD,
          'record', NEW,
          'type', TG_OP,
          'table', TG_TABLE_NAME,
          'schema', TG_TABLE_SCHEMA
        );

        SELECT http_post INTO request_id FROM net.http_post(
          url,
          payload,
          params,
          headers,
          timeout_ms
        );
      ELSE
        RAISE EXCEPTION 'method argument % is invalid', method;
    END CASE;

    INSERT INTO supabase_functions.hooks
      (hook_table_id, hook_name, request_id)
    VALUES
      (TG_RELID, TG_NAME, request_id);

    RETURN NEW;
  END
$$;


ALTER FUNCTION supabase_functions.http_request() OWNER TO supabase_functions_admin;



--
-- Name: extensions; Type: TABLE; Schema: _realtime; Owner: supabase_admin
--

CREATE TABLE _realtime.extensions (
    id uuid NOT NULL,
    type text,
    settings jsonb,
    tenant_external_id text,
    inserted_at timestamp(0) without time zone NOT NULL,
    updated_at timestamp(0) without time zone NOT NULL
);


ALTER TABLE _realtime.extensions OWNER TO supabase_admin;

--
-- Name: feature_flags; Type: TABLE; Schema: _realtime; Owner: supabase_admin
--

CREATE TABLE _realtime.feature_flags (
    id uuid NOT NULL,
    name character varying(255) NOT NULL,
    enabled boolean DEFAULT false NOT NULL,
    inserted_at timestamp(0) without time zone NOT NULL,
    updated_at timestamp(0) without time zone NOT NULL
);


ALTER TABLE _realtime.feature_flags OWNER TO supabase_admin;

--
-- Name: schema_migrations; Type: TABLE; Schema: _realtime; Owner: supabase_admin
--

CREATE TABLE _realtime.schema_migrations (
    version bigint NOT NULL,
    inserted_at timestamp(0) without time zone
);


ALTER TABLE _realtime.schema_migrations OWNER TO supabase_admin;

--
-- Name: tenants; Type: TABLE; Schema: _realtime; Owner: supabase_admin
--

CREATE TABLE _realtime.tenants (
    id uuid NOT NULL,
    name text,
    external_id text,
    jwt_secret text,
    max_concurrent_users integer DEFAULT 200 NOT NULL,
    inserted_at timestamp(0) without time zone NOT NULL,
    updated_at timestamp(0) without time zone NOT NULL,
    max_events_per_second integer DEFAULT 100 NOT NULL,
    postgres_cdc_default text DEFAULT 'postgres_cdc_rls'::text,
    max_bytes_per_second integer DEFAULT 100000 NOT NULL,
    max_channels_per_client integer DEFAULT 100 NOT NULL,
    max_joins_per_second integer DEFAULT 500 NOT NULL,
    suspend boolean DEFAULT false,
    jwt_jwks jsonb,
    notify_private_alpha boolean DEFAULT false,
    private_only boolean DEFAULT false NOT NULL,
    migrations_ran integer DEFAULT 0,
    broadcast_adapter character varying(255) DEFAULT 'gen_rpc'::character varying,
    max_presence_events_per_second integer DEFAULT 1000,
    max_payload_size_in_kb integer DEFAULT 3000,
    max_client_presence_events_per_window integer,
    client_presence_window_ms integer,
    presence_enabled boolean DEFAULT false NOT NULL,
    feature_flags jsonb DEFAULT '{}'::jsonb NOT NULL,
    CONSTRAINT jwt_secret_or_jwt_jwks_required CHECK (((jwt_secret IS NOT NULL) OR (jwt_jwks IS NOT NULL)))
);


ALTER TABLE _realtime.tenants OWNER TO supabase_admin;

--
-- Name: audit_log_entries; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.audit_log_entries (
    instance_id uuid,
    id uuid NOT NULL,
    payload json,
    created_at timestamp with time zone,
    ip_address character varying(64) DEFAULT ''::character varying NOT NULL
);


ALTER TABLE auth.audit_log_entries OWNER TO supabase_auth_admin;

--
-- Name: TABLE audit_log_entries; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.audit_log_entries IS 'Auth: Audit trail for user actions.';


--
-- Name: custom_oauth_providers; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.custom_oauth_providers (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    provider_type text NOT NULL,
    identifier text NOT NULL,
    name text NOT NULL,
    client_id text NOT NULL,
    client_secret text NOT NULL,
    acceptable_client_ids text[] DEFAULT '{}'::text[] NOT NULL,
    scopes text[] DEFAULT '{}'::text[] NOT NULL,
    pkce_enabled boolean DEFAULT true NOT NULL,
    attribute_mapping jsonb DEFAULT '{}'::jsonb NOT NULL,
    authorization_params jsonb DEFAULT '{}'::jsonb NOT NULL,
    enabled boolean DEFAULT true NOT NULL,
    email_optional boolean DEFAULT false NOT NULL,
    issuer text,
    discovery_url text,
    skip_nonce_check boolean DEFAULT false NOT NULL,
    cached_discovery jsonb,
    discovery_cached_at timestamp with time zone,
    authorization_url text,
    token_url text,
    userinfo_url text,
    jwks_uri text,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    CONSTRAINT custom_oauth_providers_authorization_url_https CHECK (((authorization_url IS NULL) OR (authorization_url ~~ 'https://%'::text))),
    CONSTRAINT custom_oauth_providers_authorization_url_length CHECK (((authorization_url IS NULL) OR (char_length(authorization_url) <= 2048))),
    CONSTRAINT custom_oauth_providers_client_id_length CHECK (((char_length(client_id) >= 1) AND (char_length(client_id) <= 512))),
    CONSTRAINT custom_oauth_providers_discovery_url_length CHECK (((discovery_url IS NULL) OR (char_length(discovery_url) <= 2048))),
    CONSTRAINT custom_oauth_providers_identifier_format CHECK ((identifier ~ '^[a-z0-9][a-z0-9:-]{0,48}[a-z0-9]$'::text)),
    CONSTRAINT custom_oauth_providers_issuer_length CHECK (((issuer IS NULL) OR ((char_length(issuer) >= 1) AND (char_length(issuer) <= 2048)))),
    CONSTRAINT custom_oauth_providers_jwks_uri_https CHECK (((jwks_uri IS NULL) OR (jwks_uri ~~ 'https://%'::text))),
    CONSTRAINT custom_oauth_providers_jwks_uri_length CHECK (((jwks_uri IS NULL) OR (char_length(jwks_uri) <= 2048))),
    CONSTRAINT custom_oauth_providers_name_length CHECK (((char_length(name) >= 1) AND (char_length(name) <= 100))),
    CONSTRAINT custom_oauth_providers_oauth2_requires_endpoints CHECK (((provider_type <> 'oauth2'::text) OR ((authorization_url IS NOT NULL) AND (token_url IS NOT NULL) AND (userinfo_url IS NOT NULL)))),
    CONSTRAINT custom_oauth_providers_oidc_discovery_url_https CHECK (((provider_type <> 'oidc'::text) OR (discovery_url IS NULL) OR (discovery_url ~~ 'https://%'::text))),
    CONSTRAINT custom_oauth_providers_oidc_issuer_https CHECK (((provider_type <> 'oidc'::text) OR (issuer IS NULL) OR (issuer ~~ 'https://%'::text))),
    CONSTRAINT custom_oauth_providers_oidc_requires_issuer CHECK (((provider_type <> 'oidc'::text) OR (issuer IS NOT NULL))),
    CONSTRAINT custom_oauth_providers_provider_type_check CHECK ((provider_type = ANY (ARRAY['oauth2'::text, 'oidc'::text]))),
    CONSTRAINT custom_oauth_providers_token_url_https CHECK (((token_url IS NULL) OR (token_url ~~ 'https://%'::text))),
    CONSTRAINT custom_oauth_providers_token_url_length CHECK (((token_url IS NULL) OR (char_length(token_url) <= 2048))),
    CONSTRAINT custom_oauth_providers_userinfo_url_https CHECK (((userinfo_url IS NULL) OR (userinfo_url ~~ 'https://%'::text))),
    CONSTRAINT custom_oauth_providers_userinfo_url_length CHECK (((userinfo_url IS NULL) OR (char_length(userinfo_url) <= 2048)))
);


ALTER TABLE auth.custom_oauth_providers OWNER TO supabase_auth_admin;

--
-- Name: flow_state; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.flow_state (
    id uuid NOT NULL,
    user_id uuid,
    auth_code text,
    code_challenge_method auth.code_challenge_method,
    code_challenge text,
    provider_type text NOT NULL,
    provider_access_token text,
    provider_refresh_token text,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    authentication_method text NOT NULL,
    auth_code_issued_at timestamp with time zone,
    invite_token text,
    referrer text,
    oauth_client_state_id uuid,
    linking_target_id uuid,
    email_optional boolean DEFAULT false NOT NULL
);


ALTER TABLE auth.flow_state OWNER TO supabase_auth_admin;

--
-- Name: TABLE flow_state; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.flow_state IS 'Stores metadata for all OAuth/SSO login flows';


--
-- Name: identities; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.identities (
    provider_id text NOT NULL,
    user_id uuid NOT NULL,
    identity_data jsonb NOT NULL,
    provider text NOT NULL,
    last_sign_in_at timestamp with time zone,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    email text GENERATED ALWAYS AS (lower((identity_data ->> 'email'::text))) STORED,
    id uuid DEFAULT gen_random_uuid() NOT NULL
);


ALTER TABLE auth.identities OWNER TO supabase_auth_admin;

--
-- Name: TABLE identities; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.identities IS 'Auth: Stores identities associated to a user.';


--
-- Name: COLUMN identities.email; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON COLUMN auth.identities.email IS 'Auth: Email is a generated column that references the optional email property in the identity_data';


--
-- Name: instances; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.instances (
    id uuid NOT NULL,
    uuid uuid,
    raw_base_config text,
    created_at timestamp with time zone,
    updated_at timestamp with time zone
);


ALTER TABLE auth.instances OWNER TO supabase_auth_admin;

--
-- Name: TABLE instances; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.instances IS 'Auth: Manages users across multiple sites.';


--
-- Name: mfa_amr_claims; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.mfa_amr_claims (
    session_id uuid NOT NULL,
    created_at timestamp with time zone NOT NULL,
    updated_at timestamp with time zone NOT NULL,
    authentication_method text NOT NULL,
    id uuid NOT NULL
);


ALTER TABLE auth.mfa_amr_claims OWNER TO supabase_auth_admin;

--
-- Name: TABLE mfa_amr_claims; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.mfa_amr_claims IS 'auth: stores authenticator method reference claims for multi factor authentication';


--
-- Name: mfa_challenges; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.mfa_challenges (
    id uuid NOT NULL,
    factor_id uuid NOT NULL,
    created_at timestamp with time zone NOT NULL,
    verified_at timestamp with time zone,
    ip_address inet NOT NULL,
    otp_code text,
    web_authn_session_data jsonb
);


ALTER TABLE auth.mfa_challenges OWNER TO supabase_auth_admin;

--
-- Name: TABLE mfa_challenges; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.mfa_challenges IS 'auth: stores metadata about challenge requests made';


--
-- Name: mfa_factors; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.mfa_factors (
    id uuid NOT NULL,
    user_id uuid NOT NULL,
    friendly_name text,
    factor_type auth.factor_type NOT NULL,
    status auth.factor_status NOT NULL,
    created_at timestamp with time zone NOT NULL,
    updated_at timestamp with time zone NOT NULL,
    secret text,
    phone text,
    last_challenged_at timestamp with time zone,
    web_authn_credential jsonb,
    web_authn_aaguid uuid,
    last_webauthn_challenge_data jsonb
);


ALTER TABLE auth.mfa_factors OWNER TO supabase_auth_admin;

--
-- Name: TABLE mfa_factors; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.mfa_factors IS 'auth: stores metadata about factors';


--
-- Name: COLUMN mfa_factors.last_webauthn_challenge_data; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON COLUMN auth.mfa_factors.last_webauthn_challenge_data IS 'Stores the latest WebAuthn challenge data including attestation/assertion for customer verification';


--
-- Name: oauth_authorizations; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.oauth_authorizations (
    id uuid NOT NULL,
    authorization_id text NOT NULL,
    client_id uuid NOT NULL,
    user_id uuid,
    redirect_uri text NOT NULL,
    scope text NOT NULL,
    state text,
    resource text,
    code_challenge text,
    code_challenge_method auth.code_challenge_method,
    response_type auth.oauth_response_type DEFAULT 'code'::auth.oauth_response_type NOT NULL,
    status auth.oauth_authorization_status DEFAULT 'pending'::auth.oauth_authorization_status NOT NULL,
    authorization_code text,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    expires_at timestamp with time zone DEFAULT (now() + '00:03:00'::interval) NOT NULL,
    approved_at timestamp with time zone,
    nonce text,
    CONSTRAINT oauth_authorizations_authorization_code_length CHECK ((char_length(authorization_code) <= 255)),
    CONSTRAINT oauth_authorizations_code_challenge_length CHECK ((char_length(code_challenge) <= 128)),
    CONSTRAINT oauth_authorizations_expires_at_future CHECK ((expires_at > created_at)),
    CONSTRAINT oauth_authorizations_nonce_length CHECK ((char_length(nonce) <= 255)),
    CONSTRAINT oauth_authorizations_redirect_uri_length CHECK ((char_length(redirect_uri) <= 2048)),
    CONSTRAINT oauth_authorizations_resource_length CHECK ((char_length(resource) <= 2048)),
    CONSTRAINT oauth_authorizations_scope_length CHECK ((char_length(scope) <= 4096)),
    CONSTRAINT oauth_authorizations_state_length CHECK ((char_length(state) <= 4096))
);


ALTER TABLE auth.oauth_authorizations OWNER TO supabase_auth_admin;

--
-- Name: oauth_client_states; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.oauth_client_states (
    id uuid NOT NULL,
    provider_type text NOT NULL,
    code_verifier text,
    created_at timestamp with time zone NOT NULL
);


ALTER TABLE auth.oauth_client_states OWNER TO supabase_auth_admin;

--
-- Name: TABLE oauth_client_states; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.oauth_client_states IS 'Stores OAuth states for third-party provider authentication flows where Supabase acts as the OAuth client.';


--
-- Name: oauth_clients; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.oauth_clients (
    id uuid NOT NULL,
    client_secret_hash text,
    registration_type auth.oauth_registration_type NOT NULL,
    redirect_uris text NOT NULL,
    grant_types text NOT NULL,
    client_name text,
    client_uri text,
    logo_uri text,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    deleted_at timestamp with time zone,
    client_type auth.oauth_client_type DEFAULT 'confidential'::auth.oauth_client_type NOT NULL,
    token_endpoint_auth_method text NOT NULL,
    CONSTRAINT oauth_clients_client_name_length CHECK ((char_length(client_name) <= 1024)),
    CONSTRAINT oauth_clients_client_uri_length CHECK ((char_length(client_uri) <= 2048)),
    CONSTRAINT oauth_clients_logo_uri_length CHECK ((char_length(logo_uri) <= 2048)),
    CONSTRAINT oauth_clients_token_endpoint_auth_method_check CHECK ((token_endpoint_auth_method = ANY (ARRAY['client_secret_basic'::text, 'client_secret_post'::text, 'none'::text])))
);


ALTER TABLE auth.oauth_clients OWNER TO supabase_auth_admin;

--
-- Name: oauth_consents; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.oauth_consents (
    id uuid NOT NULL,
    user_id uuid NOT NULL,
    client_id uuid NOT NULL,
    scopes text NOT NULL,
    granted_at timestamp with time zone DEFAULT now() NOT NULL,
    revoked_at timestamp with time zone,
    CONSTRAINT oauth_consents_revoked_after_granted CHECK (((revoked_at IS NULL) OR (revoked_at >= granted_at))),
    CONSTRAINT oauth_consents_scopes_length CHECK ((char_length(scopes) <= 2048)),
    CONSTRAINT oauth_consents_scopes_not_empty CHECK ((char_length(TRIM(BOTH FROM scopes)) > 0))
);


ALTER TABLE auth.oauth_consents OWNER TO supabase_auth_admin;

--
-- Name: one_time_tokens; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.one_time_tokens (
    id uuid NOT NULL,
    user_id uuid NOT NULL,
    token_type auth.one_time_token_type NOT NULL,
    token_hash text NOT NULL,
    relates_to text NOT NULL,
    created_at timestamp without time zone DEFAULT now() NOT NULL,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    CONSTRAINT one_time_tokens_token_hash_check CHECK ((char_length(token_hash) > 0))
);


ALTER TABLE auth.one_time_tokens OWNER TO supabase_auth_admin;

--
-- Name: refresh_tokens; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.refresh_tokens (
    instance_id uuid,
    id bigint NOT NULL,
    token character varying(255),
    user_id character varying(255),
    revoked boolean,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    parent character varying(255),
    session_id uuid
);


ALTER TABLE auth.refresh_tokens OWNER TO supabase_auth_admin;

--
-- Name: TABLE refresh_tokens; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.refresh_tokens IS 'Auth: Store of tokens used to refresh JWT tokens once they expire.';


--
-- Name: refresh_tokens_id_seq; Type: SEQUENCE; Schema: auth; Owner: supabase_auth_admin
--

CREATE SEQUENCE auth.refresh_tokens_id_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER SEQUENCE auth.refresh_tokens_id_seq OWNER TO supabase_auth_admin;

--
-- Name: refresh_tokens_id_seq; Type: SEQUENCE OWNED BY; Schema: auth; Owner: supabase_auth_admin
--

ALTER SEQUENCE auth.refresh_tokens_id_seq OWNED BY auth.refresh_tokens.id;


--
-- Name: saml_providers; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.saml_providers (
    id uuid NOT NULL,
    sso_provider_id uuid NOT NULL,
    entity_id text NOT NULL,
    metadata_xml text NOT NULL,
    metadata_url text,
    attribute_mapping jsonb,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    name_id_format text,
    CONSTRAINT "entity_id not empty" CHECK ((char_length(entity_id) > 0)),
    CONSTRAINT "metadata_url not empty" CHECK (((metadata_url = NULL::text) OR (char_length(metadata_url) > 0))),
    CONSTRAINT "metadata_xml not empty" CHECK ((char_length(metadata_xml) > 0))
);


ALTER TABLE auth.saml_providers OWNER TO supabase_auth_admin;

--
-- Name: TABLE saml_providers; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.saml_providers IS 'Auth: Manages SAML Identity Provider connections.';


--
-- Name: saml_relay_states; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.saml_relay_states (
    id uuid NOT NULL,
    sso_provider_id uuid NOT NULL,
    request_id text NOT NULL,
    for_email text,
    redirect_to text,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    flow_state_id uuid,
    CONSTRAINT "request_id not empty" CHECK ((char_length(request_id) > 0))
);


ALTER TABLE auth.saml_relay_states OWNER TO supabase_auth_admin;

--
-- Name: TABLE saml_relay_states; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.saml_relay_states IS 'Auth: Contains SAML Relay State information for each Service Provider initiated login.';


--
-- Name: schema_migrations; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.schema_migrations (
    version character varying(255) NOT NULL
);


ALTER TABLE auth.schema_migrations OWNER TO supabase_auth_admin;

--
-- Name: TABLE schema_migrations; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.schema_migrations IS 'Auth: Manages updates to the auth system.';


--
-- Name: sessions; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.sessions (
    id uuid NOT NULL,
    user_id uuid NOT NULL,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    factor_id uuid,
    aal auth.aal_level,
    not_after timestamp with time zone,
    refreshed_at timestamp without time zone,
    user_agent text,
    ip inet,
    tag text,
    oauth_client_id uuid,
    refresh_token_hmac_key text,
    refresh_token_counter bigint,
    scopes text,
    CONSTRAINT sessions_scopes_length CHECK ((char_length(scopes) <= 4096))
);


ALTER TABLE auth.sessions OWNER TO supabase_auth_admin;

--
-- Name: TABLE sessions; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.sessions IS 'Auth: Stores session data associated to a user.';


--
-- Name: COLUMN sessions.not_after; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON COLUMN auth.sessions.not_after IS 'Auth: Not after is a nullable column that contains a timestamp after which the session should be regarded as expired.';


--
-- Name: COLUMN sessions.refresh_token_hmac_key; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON COLUMN auth.sessions.refresh_token_hmac_key IS 'Holds a HMAC-SHA256 key used to sign refresh tokens for this session.';


--
-- Name: COLUMN sessions.refresh_token_counter; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON COLUMN auth.sessions.refresh_token_counter IS 'Holds the ID (counter) of the last issued refresh token.';


--
-- Name: sso_domains; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.sso_domains (
    id uuid NOT NULL,
    sso_provider_id uuid NOT NULL,
    domain text NOT NULL,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    CONSTRAINT "domain not empty" CHECK ((char_length(domain) > 0))
);


ALTER TABLE auth.sso_domains OWNER TO supabase_auth_admin;

--
-- Name: TABLE sso_domains; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.sso_domains IS 'Auth: Manages SSO email address domain mapping to an SSO Identity Provider.';


--
-- Name: sso_providers; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.sso_providers (
    id uuid NOT NULL,
    resource_id text,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    disabled boolean,
    CONSTRAINT "resource_id not empty" CHECK (((resource_id = NULL::text) OR (char_length(resource_id) > 0)))
);


ALTER TABLE auth.sso_providers OWNER TO supabase_auth_admin;

--
-- Name: TABLE sso_providers; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.sso_providers IS 'Auth: Manages SSO identity provider information; see saml_providers for SAML.';


--
-- Name: COLUMN sso_providers.resource_id; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON COLUMN auth.sso_providers.resource_id IS 'Auth: Uniquely identifies a SSO provider according to a user-chosen resource ID (case insensitive), useful in infrastructure as code.';


--
-- Name: users; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.users (
    instance_id uuid,
    id uuid NOT NULL,
    aud character varying(255),
    role character varying(255),
    email character varying(255),
    encrypted_password character varying(255),
    email_confirmed_at timestamp with time zone,
    invited_at timestamp with time zone,
    confirmation_token character varying(255),
    confirmation_sent_at timestamp with time zone,
    recovery_token character varying(255),
    recovery_sent_at timestamp with time zone,
    email_change_token_new character varying(255),
    email_change character varying(255),
    email_change_sent_at timestamp with time zone,
    last_sign_in_at timestamp with time zone,
    raw_app_meta_data jsonb,
    raw_user_meta_data jsonb,
    is_super_admin boolean,
    created_at timestamp with time zone,
    updated_at timestamp with time zone,
    phone text DEFAULT NULL::character varying,
    phone_confirmed_at timestamp with time zone,
    phone_change text DEFAULT ''::character varying,
    phone_change_token character varying(255) DEFAULT ''::character varying,
    phone_change_sent_at timestamp with time zone,
    confirmed_at timestamp with time zone GENERATED ALWAYS AS (LEAST(email_confirmed_at, phone_confirmed_at)) STORED,
    email_change_token_current character varying(255) DEFAULT ''::character varying,
    email_change_confirm_status smallint DEFAULT 0,
    banned_until timestamp with time zone,
    reauthentication_token character varying(255) DEFAULT ''::character varying,
    reauthentication_sent_at timestamp with time zone,
    is_sso_user boolean DEFAULT false NOT NULL,
    deleted_at timestamp with time zone,
    is_anonymous boolean DEFAULT false NOT NULL,
    CONSTRAINT users_email_change_confirm_status_check CHECK (((email_change_confirm_status >= 0) AND (email_change_confirm_status <= 2)))
);


ALTER TABLE auth.users OWNER TO supabase_auth_admin;

--
-- Name: TABLE users; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON TABLE auth.users IS 'Auth: Stores user login data within a secure schema.';


--
-- Name: COLUMN users.is_sso_user; Type: COMMENT; Schema: auth; Owner: supabase_auth_admin
--

COMMENT ON COLUMN auth.users.is_sso_user IS 'Auth: Set this column to true when the account comes from SSO. These accounts can have duplicate emails.';


--
-- Name: webauthn_challenges; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.webauthn_challenges (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    user_id uuid,
    challenge_type text NOT NULL,
    session_data jsonb NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    expires_at timestamp with time zone NOT NULL,
    CONSTRAINT webauthn_challenges_challenge_type_check CHECK ((challenge_type = ANY (ARRAY['signup'::text, 'registration'::text, 'authentication'::text])))
);


ALTER TABLE auth.webauthn_challenges OWNER TO supabase_auth_admin;

--
-- Name: webauthn_credentials; Type: TABLE; Schema: auth; Owner: supabase_auth_admin
--

CREATE TABLE auth.webauthn_credentials (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    user_id uuid NOT NULL,
    credential_id bytea NOT NULL,
    public_key bytea NOT NULL,
    attestation_type text DEFAULT ''::text NOT NULL,
    aaguid uuid,
    sign_count bigint DEFAULT 0 NOT NULL,
    transports jsonb DEFAULT '[]'::jsonb NOT NULL,
    backup_eligible boolean DEFAULT false NOT NULL,
    backed_up boolean DEFAULT false NOT NULL,
    friendly_name text DEFAULT ''::text NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    last_used_at timestamp with time zone
);


ALTER TABLE auth.webauthn_credentials OWNER TO supabase_auth_admin;

--
-- Name: ai_analysis_logs; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.ai_analysis_logs (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    camera_id uuid NOT NULL,
    alert_template_id uuid,
    prompt text NOT NULL,
    response_text text,
    model text,
    image_url text,
    metadata jsonb DEFAULT '{}'::jsonb,
    created_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.ai_analysis_logs OWNER TO postgres;

--
-- Name: ai_models; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.ai_models (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    name text NOT NULL,
    description text,
    category text NOT NULL,
    version text NOT NULL,
    enabled boolean DEFAULT true NOT NULL,
    configuration jsonb,
    created_at timestamp with time zone DEFAULT now()
);


ALTER TABLE public.ai_models OWNER TO postgres;

--
-- Name: alert_template_events; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.alert_template_events (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    alert_template_id uuid NOT NULL,
    event_type_id uuid NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.alert_template_events OWNER TO postgres;

--
-- Name: alert_template_industries; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.alert_template_industries (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    alert_template_id uuid NOT NULL,
    industry_id uuid NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.alert_template_industries OWNER TO postgres;

--
-- Name: alert_templates; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.alert_templates (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    name text NOT NULL,
    name_ar text NOT NULL,
    description text,
    description_ar text,
    detection_method public.detection_method NOT NULL,
    model_file_url text,
    model_type text,
    huggingface_api_key text,
    model_api_endpoint text,
    enabled boolean DEFAULT true NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    created_by uuid,
    api_provider text
);


ALTER TABLE public.alert_templates OWNER TO postgres;

--
-- Name: aman_instances; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.aman_instances (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    organization_id uuid NOT NULL,
    branch_id uuid,
    name text NOT NULL,
    base_url text NOT NULL,
    access_token text NOT NULL,
    active boolean DEFAULT true NOT NULL,
    created_by uuid,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    username text,
    password text,
    dashboard_path text DEFAULT '/lovelace/default_view?kiosk'::text,
    aman_api_url text
);

ALTER TABLE ONLY public.aman_instances REPLICA IDENTITY FULL;


ALTER TABLE public.aman_instances OWNER TO postgres;

--
-- Name: auto_sync_settings; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.auto_sync_settings (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    enabled boolean DEFAULT true NOT NULL,
    interval_minutes integer DEFAULT 30 NOT NULL,
    last_sync timestamp with time zone,
    next_sync timestamp with time zone,
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now()
);


ALTER TABLE public.auto_sync_settings OWNER TO postgres;

--
-- Name: branch_roles; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.branch_roles (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    user_id uuid NOT NULL,
    branch_id uuid NOT NULL,
    role text NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    CONSTRAINT branch_roles_role_check CHECK ((role = 'branch_manager'::text))
);


ALTER TABLE public.branch_roles OWNER TO postgres;

--
-- Name: branches; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.branches (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    organization_id uuid,
    name text NOT NULL,
    address text,
    latitude numeric(10,8),
    longitude numeric(11,8),
    active boolean DEFAULT true NOT NULL,
    created_at timestamp with time zone DEFAULT now(),
    device_token text DEFAULT (md5((gen_random_uuid())::text) || md5((gen_random_uuid())::text)),
    config_version integer DEFAULT 1 NOT NULL,
    last_seen timestamp with time zone,
    agent_info jsonb DEFAULT '{}'::jsonb,
    alert_numbers text DEFAULT ''::text,
    engine_image text,
    device_status text DEFAULT 'pending'::text NOT NULL,
    device_fingerprint text,
    hardware_info jsonb DEFAULT '{}'::jsonb,
    is_vm boolean DEFAULT false,
    allow_vm boolean DEFAULT false,
    device_first_seen timestamp with time zone
);


ALTER TABLE public.branches OWNER TO postgres;

--
-- Name: camera_alert_assignments; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.camera_alert_assignments (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    camera_id uuid NOT NULL,
    alert_template_id uuid NOT NULL,
    enabled boolean DEFAULT true NOT NULL,
    confidence_threshold numeric DEFAULT 0.7,
    created_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.camera_alert_assignments OWNER TO postgres;

--
-- Name: camera_event_assignments; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.camera_event_assignments (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    camera_id uuid NOT NULL,
    event_type_id uuid NOT NULL,
    enabled boolean DEFAULT true NOT NULL,
    confidence_threshold numeric DEFAULT 0.7,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    config jsonb DEFAULT '{}'::jsonb
);


ALTER TABLE public.camera_event_assignments OWNER TO postgres;

--
-- Name: camera_sources; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.camera_sources (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    name text NOT NULL,
    name_ar text NOT NULL,
    protocol text NOT NULL,
    requires_auth boolean DEFAULT false NOT NULL,
    default_port integer,
    url_pattern text,
    description text,
    description_ar text,
    icon text DEFAULT 'camera'::text,
    active boolean DEFAULT true NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    created_by uuid
);


ALTER TABLE public.camera_sources OWNER TO postgres;

--
-- Name: cameras; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.cameras (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    branch_id uuid,
    name text NOT NULL,
    rtsp_url text,
    frigate_identifier text,
    status text DEFAULT 'offline'::text,
    last_connection timestamp with time zone,
    config jsonb,
    created_at timestamp with time zone DEFAULT now(),
    model text DEFAULT 'AI-CAM-4K'::text,
    features jsonb DEFAULT '{"ai_analysis": true, "night_vision": true, "audio_recording": false, "motion_detection": true}'::jsonb,
    max_resolution text DEFAULT '4K'::text,
    security_zone_id uuid,
    description text,
    detection_rules jsonb DEFAULT '[]'::jsonb,
    updated_at timestamp with time zone DEFAULT now(),
    enabled boolean DEFAULT true NOT NULL,
    frigate_instance_id uuid
);


ALTER TABLE public.cameras OWNER TO postgres;

--
-- Name: COLUMN cameras.status; Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON COLUMN public.cameras.status IS 'Camera connection status based on actual data/stream (متصلة/غير متصلة)';


--
-- Name: COLUMN cameras.enabled; Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON COLUMN public.cameras.enabled IS 'Camera activation status (مفعل/غير مفعل)';


--
-- Name: chat_messages; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.chat_messages (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    thread_id uuid NOT NULL,
    organization_id uuid NOT NULL,
    sender_id uuid NOT NULL,
    content text NOT NULL,
    metadata jsonb DEFAULT '{}'::jsonb NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.chat_messages OWNER TO postgres;

--
-- Name: chat_thread_participants; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.chat_thread_participants (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    thread_id uuid NOT NULL,
    user_id uuid NOT NULL,
    added_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.chat_thread_participants OWNER TO postgres;

--
-- Name: chat_threads; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.chat_threads (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    organization_id uuid NOT NULL,
    created_by uuid,
    name text,
    is_private boolean DEFAULT false NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.chat_threads OWNER TO postgres;

--
-- Name: chatbot_knowledge_base; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.chatbot_knowledge_base (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    language text NOT NULL,
    content_type text NOT NULL,
    title text,
    data jsonb DEFAULT '{}'::jsonb NOT NULL,
    is_active boolean DEFAULT true NOT NULL,
    display_order integer DEFAULT 0,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    created_by uuid,
    updated_by uuid,
    CONSTRAINT chatbot_knowledge_base_content_type_check CHECK ((content_type = ANY (ARRAY['company'::text, 'services'::text, 'sectors'::text, 'integrations'::text, 'features'::text, 'stats'::text, 'contact'::text]))),
    CONSTRAINT chatbot_knowledge_base_language_check CHECK ((language = ANY (ARRAY['ar'::text, 'en'::text])))
);


ALTER TABLE public.chatbot_knowledge_base OWNER TO postgres;

--
-- Name: detection_rules; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.detection_rules (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    organization_id uuid,
    name text NOT NULL,
    description text,
    object_types text[],
    min_confidence numeric(5,2) DEFAULT 0.6 NOT NULL,
    cooldown_seconds integer DEFAULT 60,
    notification_channels text[],
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now()
);


ALTER TABLE public.detection_rules OWNER TO postgres;

--
-- Name: event_types; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.event_types (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    name_en text NOT NULL,
    name_ar text NOT NULL,
    description_en text,
    description_ar text,
    icon text DEFAULT 'alert-circle'::text,
    color text DEFAULT '#3b82f6'::text,
    enabled boolean DEFAULT true NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    created_by uuid,
    feature_key text,
    kind text DEFAULT 'rule'::text,
    default_config jsonb DEFAULT '{}'::jsonb,
    available boolean DEFAULT true,
    sector text DEFAULT 'general'::text
);


ALTER TABLE public.event_types OWNER TO postgres;

--
-- Name: events; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.events (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    camera_id uuid,
    event_type text NOT NULL,
    severity text DEFAULT 'info'::text NOT NULL,
    metadata jsonb,
    snapshot_url text,
    detected_at timestamp with time zone DEFAULT now(),
    reviewed boolean DEFAULT false NOT NULL,
    attributes jsonb DEFAULT '{}'::jsonb,
    face_id text,
    license_plate text,
    zones text[],
    sub_label text,
    top_score double precision,
    start_time timestamp with time zone,
    end_time timestamp with time zone,
    has_clip boolean DEFAULT false,
    has_snapshot boolean DEFAULT false,
    frigate_id text
);


ALTER TABLE public.events OWNER TO postgres;

--
-- Name: form_assignments; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.form_assignments (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    workflow_form_id uuid NOT NULL,
    organization_id uuid NOT NULL,
    representative_id uuid NOT NULL,
    assigned_by uuid,
    due_date timestamp with time zone,
    reminder_frequency text DEFAULT 'daily'::text,
    is_active boolean DEFAULT true NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.form_assignments OWNER TO postgres;

--
-- Name: form_distribution_settings; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.form_distribution_settings (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    workflow_form_id uuid,
    distribution_type text NOT NULL,
    target_groups jsonb DEFAULT '[]'::jsonb,
    target_users jsonb DEFAULT '[]'::jsonb,
    schedule_type text DEFAULT 'immediate'::text,
    schedule_data jsonb DEFAULT '{}'::jsonb,
    notification_settings jsonb DEFAULT '{"push": true, "email": true}'::jsonb,
    created_by uuid,
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now()
);


ALTER TABLE public.form_distribution_settings OWNER TO postgres;

--
-- Name: form_submissions; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.form_submissions (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    form_assignment_id uuid NOT NULL,
    submitted_data jsonb DEFAULT '{}'::jsonb NOT NULL,
    submitted_at timestamp with time zone DEFAULT now() NOT NULL,
    submitted_by uuid,
    status text DEFAULT 'in_progress'::text NOT NULL
);


ALTER TABLE public.form_submissions OWNER TO postgres;

--
-- Name: frigate_alert_rules; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_alert_rules (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    camera_id uuid,
    rule_name text NOT NULL,
    object_types text[] DEFAULT '{}'::text[],
    zones text[] DEFAULT '{}'::text[],
    min_confidence double precision DEFAULT 0.7,
    cooldown_seconds integer DEFAULT 60,
    notification_methods jsonb DEFAULT '{"push": true, "email": false}'::jsonb,
    enabled boolean DEFAULT true NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.frigate_alert_rules OWNER TO postgres;

--
-- Name: frigate_deployed_models; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_deployed_models (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    frigate_instance_id uuid NOT NULL,
    model_id text NOT NULL,
    model_name text NOT NULL,
    category text NOT NULL,
    labels jsonb DEFAULT '[]'::jsonb NOT NULL,
    onnx_path text,
    pt_path text,
    config_snippet text,
    runtime text DEFAULT 'cpu'::text,
    status text DEFAULT 'pending'::text,
    download_url text,
    license text,
    accuracy jsonb,
    error_message text,
    deployed_at timestamp with time zone,
    applied_to_cameras text[] DEFAULT ARRAY[]::text[],
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now()
);


ALTER TABLE public.frigate_deployed_models OWNER TO postgres;

--
-- Name: frigate_exports; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_exports (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    export_id text NOT NULL,
    frigate_instance_id uuid NOT NULL,
    camera text NOT NULL,
    start_time timestamp with time zone NOT NULL,
    end_time timestamp with time zone NOT NULL,
    path text,
    status text,
    url text,
    metadata jsonb,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.frigate_exports OWNER TO postgres;

--
-- Name: frigate_faces; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_faces (
    id text NOT NULL,
    camera_id uuid,
    embedding jsonb,
    label text,
    confidence double precision DEFAULT 0.0 NOT NULL,
    thumbnail_url text,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.frigate_faces OWNER TO postgres;

--
-- Name: frigate_instances; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_instances (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    branch_id uuid NOT NULL,
    name text NOT NULL,
    description text,
    host_url text NOT NULL,
    api_key text,
    config_yaml text,
    enabled boolean DEFAULT true NOT NULL,
    last_sync_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,
    sync_interval_seconds integer DEFAULT 300
);


ALTER TABLE public.frigate_instances OWNER TO postgres;

--
-- Name: COLUMN frigate_instances.sync_interval_seconds; Type: COMMENT; Schema: public; Owner: postgres
--

COMMENT ON COLUMN public.frigate_instances.sync_interval_seconds IS 'Synchronization interval in seconds for Frigate data sync';


--
-- Name: frigate_license_plates; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_license_plates (
    id text NOT NULL,
    plate_number text NOT NULL,
    camera_id uuid,
    confidence double precision DEFAULT 0.0 NOT NULL,
    region text,
    vehicle_make text,
    vehicle_model text,
    vehicle_color text,
    thumbnail_url text,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    frigate_instance_id uuid,
    is_watchlisted boolean DEFAULT false,
    watchlist_notes text,
    recognized_count integer DEFAULT 0,
    last_seen_at timestamp with time zone
);


ALTER TABLE public.frigate_license_plates OWNER TO postgres;

--
-- Name: frigate_model_deployments; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_model_deployments (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    model_id text NOT NULL,
    frigate_instance_id uuid NOT NULL,
    deployment_status text DEFAULT 'pending'::text,
    applied_to_cameras text[] DEFAULT ARRAY[]::text[],
    applied_zones jsonb DEFAULT '[]'::jsonb,
    runtime text DEFAULT 'cpu'::text,
    threshold real DEFAULT 0.5,
    remote_path text,
    config_snippet text,
    last_sync_at timestamp with time zone,
    last_verified_at timestamp with time zone,
    last_event_count integer DEFAULT 0,
    error_message text,
    deployed_by uuid,
    deployed_at timestamp with time zone,
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now()
);


ALTER TABLE public.frigate_model_deployments OWNER TO postgres;

--
-- Name: frigate_model_registry; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_model_registry (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    model_id text NOT NULL,
    name_ar text NOT NULL,
    name_en text NOT NULL,
    category text NOT NULL,
    sector_ar text,
    description_ar text,
    publisher text NOT NULL,
    source_url text NOT NULL,
    framework text NOT NULL,
    labels jsonb DEFAULT '[]'::jsonb NOT NULL,
    label_to_frigate jsonb DEFAULT '{}'::jsonb NOT NULL,
    license text NOT NULL,
    commercial_ok boolean DEFAULT true,
    preferred_runtime text[] DEFAULT ARRAY['cpu'::text],
    accuracy jsonb,
    last_updated date,
    stars integer,
    recommendation text DEFAULT 'alternate'::text,
    compliance_note_ar text,
    storage_path text,
    storage_size_bytes bigint,
    storage_etag text,
    storage_updated_at timestamp with time zone,
    formats jsonb DEFAULT '[]'::jsonb,
    frigate_config_yaml text,
    status text DEFAULT 'available'::text,
    download_count integer DEFAULT 0,
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now()
);


ALTER TABLE public.frigate_model_registry OWNER TO postgres;

--
-- Name: frigate_model_sync_log; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_model_sync_log (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    sync_type text NOT NULL,
    model_id text,
    frigate_instance_id uuid,
    status text NOT NULL,
    bytes_transferred bigint,
    duration_ms integer,
    error_message text,
    metadata jsonb DEFAULT '{}'::jsonb,
    started_at timestamp with time zone DEFAULT now(),
    completed_at timestamp with time zone
);


ALTER TABLE public.frigate_model_sync_log OWNER TO postgres;

--
-- Name: frigate_previews; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_previews (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    preview_id text NOT NULL,
    frigate_instance_id uuid NOT NULL,
    camera text NOT NULL,
    start_time timestamp with time zone NOT NULL,
    end_time timestamp with time zone NOT NULL,
    path text,
    url text,
    metadata jsonb,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.frigate_previews OWNER TO postgres;

--
-- Name: frigate_recordings; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_recordings (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    recording_id text NOT NULL,
    frigate_instance_id uuid NOT NULL,
    camera text NOT NULL,
    start_time timestamp with time zone NOT NULL,
    end_time timestamp with time zone NOT NULL,
    duration integer,
    size bigint,
    path text,
    url text,
    metadata jsonb,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.frigate_recordings OWNER TO postgres;

--
-- Name: frigate_reviews; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_reviews (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    review_id text NOT NULL,
    frigate_instance_id uuid NOT NULL,
    camera text NOT NULL,
    start_time timestamp with time zone NOT NULL,
    end_time timestamp with time zone NOT NULL,
    severity text,
    has_been_reviewed boolean DEFAULT false,
    data jsonb,
    metadata jsonb,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    frigate_review_id text,
    reviewed boolean DEFAULT false,
    reviewed_by uuid,
    reviewed_at timestamp with time zone,
    thumb_path text
);


ALTER TABLE public.frigate_reviews OWNER TO postgres;

--
-- Name: frigate_stats_history; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_stats_history (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    frigate_instance_id uuid,
    recorded_at timestamp with time zone DEFAULT now(),
    cpu_usages jsonb,
    gpu_usages jsonb,
    memory_usage jsonb,
    detector_speeds jsonb,
    camera_fps jsonb,
    service_info jsonb
);


ALTER TABLE public.frigate_stats_history OWNER TO postgres;

--
-- Name: frigate_sync_logs; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_sync_logs (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    frigate_instance_id uuid,
    sync_type text NOT NULL,
    status text DEFAULT 'started'::text NOT NULL,
    events_processed integer DEFAULT 0,
    events_inserted integer DEFAULT 0,
    events_skipped integer DEFAULT 0,
    duration_ms integer,
    error_message text,
    started_at timestamp with time zone DEFAULT now(),
    completed_at timestamp with time zone
);


ALTER TABLE public.frigate_sync_logs OWNER TO postgres;

--
-- Name: frigate_timeline; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_timeline (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    camera_id uuid,
    start_time timestamp with time zone NOT NULL,
    end_time timestamp with time zone NOT NULL,
    segment_type text DEFAULT 'recording'::text NOT NULL,
    file_path text,
    duration_seconds integer,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    frigate_instance_id uuid,
    class_type text,
    data jsonb,
    metadata jsonb,
    entry_id text
);


ALTER TABLE public.frigate_timeline OWNER TO postgres;

--
-- Name: frigate_triggers; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_triggers (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    frigate_instance_id uuid,
    camera text NOT NULL,
    name text NOT NULL,
    description text,
    trigger_type text DEFAULT 'text'::text,
    similarity_threshold real DEFAULT 0.7,
    enabled boolean DEFAULT true,
    last_triggered_at timestamp with time zone,
    actions jsonb DEFAULT '[]'::jsonb,
    created_at timestamp with time zone DEFAULT now()
);


ALTER TABLE public.frigate_triggers OWNER TO postgres;

--
-- Name: frigate_zones; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.frigate_zones (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    camera_id uuid,
    name text NOT NULL,
    coordinates jsonb NOT NULL,
    zone_type text DEFAULT 'detection'::text NOT NULL,
    enabled boolean DEFAULT true NOT NULL,
    color text DEFAULT '#3b82f6'::text,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.frigate_zones OWNER TO postgres;

--
-- Name: health_alerts; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.health_alerts (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    student_id uuid,
    alert_type text NOT NULL,
    value numeric,
    severity text DEFAULT 'high'::text,
    note text DEFAULT ''::text,
    detected_at timestamp with time zone DEFAULT now(),
    notified boolean DEFAULT false,
    resolved boolean DEFAULT false
);


ALTER TABLE public.health_alerts OWNER TO postgres;

--
-- Name: industries; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.industries (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    name text NOT NULL,
    name_ar text NOT NULL,
    description text,
    description_ar text,
    icon text DEFAULT 'building'::text,
    active boolean DEFAULT true NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.industries OWNER TO postgres;

--
-- Name: legal_documents; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.legal_documents (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    document_type text NOT NULL,
    title text NOT NULL,
    content text NOT NULL,
    version integer DEFAULT 1 NOT NULL,
    effective_date timestamp with time zone DEFAULT now() NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    created_by uuid,
    updated_by uuid,
    CONSTRAINT legal_documents_document_type_check CHECK ((document_type = ANY (ARRAY['terms_of_service'::text, 'privacy_policy'::text])))
);


ALTER TABLE public.legal_documents OWNER TO postgres;

--
-- Name: network_scan_results; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.network_scan_results (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    ip_address inet NOT NULL,
    port integer NOT NULL,
    manufacturer text,
    model text,
    device_type text,
    protocol text,
    mac_address text,
    hostname text,
    discovered_at timestamp with time zone DEFAULT now() NOT NULL,
    scan_session_id uuid NOT NULL,
    user_id uuid
);


ALTER TABLE public.network_scan_results OWNER TO postgres;

--
-- Name: notification_labels; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.notification_labels (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    type text NOT NULL,
    name_ar text NOT NULL,
    name_en text,
    is_active boolean DEFAULT true NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    created_by uuid
);


ALTER TABLE public.notification_labels OWNER TO postgres;

--
-- Name: notification_methods; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.notification_methods (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    name_ar text NOT NULL,
    name_en text NOT NULL,
    type text NOT NULL,
    icon text DEFAULT 'bell'::text,
    enabled boolean DEFAULT true NOT NULL,
    settings jsonb DEFAULT '{}'::jsonb,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    created_by uuid,
    CONSTRAINT notification_methods_type_check CHECK ((type = ANY (ARRAY['whatsapp'::text, 'email'::text, 'phone'::text, 'sms'::text])))
);


ALTER TABLE public.notification_methods OWNER TO postgres;

--
-- Name: organization_settings; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.organization_settings (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    organization_id uuid NOT NULL,
    setting_key text NOT NULL,
    setting_value jsonb NOT NULL,
    description text,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.organization_settings OWNER TO postgres;

--
-- Name: organizations; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.organizations (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    name text NOT NULL,
    subscription_tier public.subscription_tier DEFAULT 'basic'::public.subscription_tier NOT NULL,
    max_cameras integer DEFAULT 5 NOT NULL,
    active boolean DEFAULT true NOT NULL,
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now(),
    subscription_limits jsonb DEFAULT '{"users": 3, "cameras": 5, "branches": 1, "storage_gb": 10, "ai_detections_per_month": 1000}'::jsonb,
    max_branches integer DEFAULT 1,
    features jsonb DEFAULT '{"analytics": false, "recording": false, "ai_detection": true, "live_streaming": true}'::jsonb,
    subscription_status text DEFAULT 'pending'::text,
    industry_id uuid
);


ALTER TABLE public.organizations OWNER TO postgres;

--
-- Name: pinned_dashboards; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.pinned_dashboards (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    user_id uuid NOT NULL,
    instance_id uuid NOT NULL,
    name text,
    path text DEFAULT '/lovelace/default_view?kiosk'::text NOT NULL,
    x integer DEFAULT 0 NOT NULL,
    y integer DEFAULT 0 NOT NULL,
    width integer DEFAULT 600 NOT NULL,
    height integer DEFAULT 400 NOT NULL,
    order_index integer DEFAULT 0 NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    zoom numeric DEFAULT 1.0 NOT NULL
);


ALTER TABLE public.pinned_dashboards OWNER TO postgres;

--
-- Name: pinned_labels; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.pinned_labels (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    user_id uuid NOT NULL,
    text text DEFAULT 'Label'::text NOT NULL,
    color text DEFAULT '#111827'::text NOT NULL,
    font_size integer DEFAULT 16 NOT NULL,
    x integer DEFAULT 40 NOT NULL,
    y integer DEFAULT 40 NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.pinned_labels OWNER TO postgres;

--
-- Name: screen_permissions; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.screen_permissions (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    screen_key text NOT NULL,
    path text NOT NULL,
    title_en text,
    title_ar text,
    description_en text,
    description_ar text,
    allowed_roles text[] DEFAULT '{}'::text[] NOT NULL,
    allow_super_admin boolean DEFAULT true NOT NULL,
    is_active boolean DEFAULT true NOT NULL,
    created_by uuid,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE public.screen_permissions OWNER TO postgres;

--
-- Name: security_zones; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.security_zones (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    branch_id uuid,
    name text NOT NULL,
    description text,
    coordinates jsonb,
    sensitivity_level integer DEFAULT 5,
    active_hours jsonb,
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now(),
    active boolean DEFAULT true NOT NULL
);


ALTER TABLE public.security_zones OWNER TO postgres;

--
-- Name: storage_configs; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.storage_configs (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    name text NOT NULL,
    type text NOT NULL,
    config jsonb DEFAULT '{}'::jsonb NOT NULL,
    is_active boolean DEFAULT false NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    created_by uuid,
    CONSTRAINT storage_configs_type_check CHECK ((type = ANY (ARRAY['google_drive'::text, 'ftp'::text, 'aws_s3'::text, 'local'::text])))
);


ALTER TABLE public.storage_configs OWNER TO postgres;

--
-- Name: students; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.students (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    organization_id uuid,
    branch_id uuid,
    name text NOT NULL,
    condition text,
    guardian_phone text,
    clinic_phone text,
    wearable_id text,
    created_at timestamp with time zone DEFAULT now()
);


ALTER TABLE public.students OWNER TO postgres;

--
-- Name: subscribers; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.subscribers (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    user_id uuid,
    email text NOT NULL,
    stripe_customer_id text,
    subscribed boolean DEFAULT false NOT NULL,
    subscription_tier public.subscription_tier DEFAULT 'basic'::public.subscription_tier,
    subscription_end timestamp with time zone,
    usage_analytics jsonb DEFAULT '{}'::jsonb,
    billing_cycle text DEFAULT 'monthly'::text,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    subscription_status text DEFAULT 'pending'::text,
    approved_by uuid,
    approved_at timestamp with time zone,
    last_activity timestamp with time zone DEFAULT now(),
    notes text,
    organization_id uuid
);


ALTER TABLE public.subscribers OWNER TO postgres;

--
-- Name: system_settings; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.system_settings (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    setting_key text NOT NULL,
    setting_value jsonb DEFAULT '{}'::jsonb NOT NULL,
    description text,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_by uuid
);


ALTER TABLE public.system_settings OWNER TO postgres;

--
-- Name: user_branch_access; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.user_branch_access (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    user_id uuid,
    branch_id uuid,
    granted_by uuid,
    granted_at timestamp with time zone DEFAULT now()
);


ALTER TABLE public.user_branch_access OWNER TO postgres;

--
-- Name: user_group_members; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.user_group_members (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    group_id uuid,
    user_role_id uuid,
    added_by uuid,
    added_at timestamp with time zone DEFAULT now()
);


ALTER TABLE public.user_group_members OWNER TO postgres;

--
-- Name: user_groups; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.user_groups (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    name text NOT NULL,
    description text,
    organization_id uuid,
    group_type text DEFAULT 'custom'::text NOT NULL,
    metadata jsonb DEFAULT '{}'::jsonb,
    created_by uuid,
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now()
);


ALTER TABLE public.user_groups OWNER TO postgres;

--
-- Name: user_preferences; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.user_preferences (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    user_id uuid,
    language text DEFAULT 'en'::text,
    timezone text DEFAULT 'UTC'::text,
    theme text DEFAULT 'system'::text,
    notifications jsonb DEFAULT '{"sms": false, "push": true, "email": true}'::jsonb,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    ui_language text,
    tts_language text,
    CONSTRAINT user_preferences_language_check CHECK ((language = ANY (ARRAY['en'::text, 'ar'::text, 'uk'::text, 'vi'::text])))
);


ALTER TABLE public.user_preferences OWNER TO postgres;

--
-- Name: user_roles; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.user_roles (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    user_id uuid,
    organization_id uuid,
    role public.user_role NOT NULL,
    created_at timestamp with time zone DEFAULT now(),
    permissions jsonb DEFAULT '{"manage_users": false, "view_cameras": true, "view_analytics": true, "manage_settings": false}'::jsonb,
    granted_by uuid,
    granted_at timestamp with time zone DEFAULT now(),
    notification_type text,
    notification_value text,
    name text,
    CONSTRAINT user_roles_notification_type_check CHECK ((notification_type = ANY (ARRAY['whatsapp'::text, 'email'::text, 'phone'::text, 'sms'::text])))
);


ALTER TABLE public.user_roles OWNER TO postgres;

--
-- Name: workflow_forms; Type: TABLE; Schema: public; Owner: postgres
--

CREATE TABLE public.workflow_forms (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    name text NOT NULL,
    name_ar text NOT NULL,
    description text,
    description_ar text,
    activity_type text NOT NULL,
    form_fields jsonb DEFAULT '[]'::jsonb NOT NULL,
    is_active boolean DEFAULT true NOT NULL,
    created_by uuid,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    logo_url text
);


ALTER TABLE public.workflow_forms OWNER TO postgres;

--
-- Name: messages; Type: TABLE; Schema: realtime; Owner: supabase_realtime_admin
--

CREATE TABLE realtime.messages (
    topic text NOT NULL,
    extension text NOT NULL,
    payload jsonb,
    event text,
    private boolean DEFAULT false,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    binary_payload bytea
)
PARTITION BY RANGE (inserted_at);


ALTER TABLE realtime.messages OWNER TO supabase_realtime_admin;

--
-- Name: messages_2026_07_02; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.messages_2026_07_02 (
    topic text NOT NULL,
    extension text NOT NULL,
    payload jsonb,
    event text,
    private boolean DEFAULT false,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    binary_payload bytea,
    CONSTRAINT messages_payload_exclusive CHECK (((payload IS NULL) OR (binary_payload IS NULL)))
);


ALTER TABLE realtime.messages_2026_07_02 OWNER TO supabase_admin;

--
-- Name: messages_2026_07_03; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.messages_2026_07_03 (
    topic text NOT NULL,
    extension text NOT NULL,
    payload jsonb,
    event text,
    private boolean DEFAULT false,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    binary_payload bytea,
    CONSTRAINT messages_payload_exclusive CHECK (((payload IS NULL) OR (binary_payload IS NULL)))
);


ALTER TABLE realtime.messages_2026_07_03 OWNER TO supabase_admin;

--
-- Name: messages_2026_07_04; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.messages_2026_07_04 (
    topic text NOT NULL,
    extension text NOT NULL,
    payload jsonb,
    event text,
    private boolean DEFAULT false,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    binary_payload bytea,
    CONSTRAINT messages_payload_exclusive CHECK (((payload IS NULL) OR (binary_payload IS NULL)))
);


ALTER TABLE realtime.messages_2026_07_04 OWNER TO supabase_admin;

--
-- Name: messages_2026_07_05; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.messages_2026_07_05 (
    topic text NOT NULL,
    extension text NOT NULL,
    payload jsonb,
    event text,
    private boolean DEFAULT false,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    binary_payload bytea,
    CONSTRAINT messages_payload_exclusive CHECK (((payload IS NULL) OR (binary_payload IS NULL)))
);


ALTER TABLE realtime.messages_2026_07_05 OWNER TO supabase_admin;

--
-- Name: messages_2026_07_06; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.messages_2026_07_06 (
    topic text NOT NULL,
    extension text NOT NULL,
    payload jsonb,
    event text,
    private boolean DEFAULT false,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    binary_payload bytea,
    CONSTRAINT messages_payload_exclusive CHECK (((payload IS NULL) OR (binary_payload IS NULL)))
);


ALTER TABLE realtime.messages_2026_07_06 OWNER TO supabase_admin;

--
-- Name: messages_2026_07_07; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.messages_2026_07_07 (
    topic text NOT NULL,
    extension text NOT NULL,
    payload jsonb,
    event text,
    private boolean DEFAULT false,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    binary_payload bytea,
    CONSTRAINT messages_payload_exclusive CHECK (((payload IS NULL) OR (binary_payload IS NULL)))
);


ALTER TABLE realtime.messages_2026_07_07 OWNER TO supabase_admin;

--
-- Name: messages_2026_07_08; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.messages_2026_07_08 (
    topic text NOT NULL,
    extension text NOT NULL,
    payload jsonb,
    event text,
    private boolean DEFAULT false,
    updated_at timestamp without time zone DEFAULT now() NOT NULL,
    inserted_at timestamp without time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    binary_payload bytea,
    CONSTRAINT messages_payload_exclusive CHECK (((payload IS NULL) OR (binary_payload IS NULL)))
);


ALTER TABLE realtime.messages_2026_07_08 OWNER TO supabase_admin;

--
-- Name: schema_migrations; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.schema_migrations (
    version bigint NOT NULL,
    inserted_at timestamp(0) without time zone
);


ALTER TABLE realtime.schema_migrations OWNER TO supabase_admin;

--
-- Name: subscription; Type: TABLE; Schema: realtime; Owner: supabase_admin
--

CREATE TABLE realtime.subscription (
    id bigint NOT NULL,
    subscription_id uuid NOT NULL,
    entity regclass NOT NULL,
    filters realtime.user_defined_filter[] DEFAULT '{}'::realtime.user_defined_filter[] NOT NULL,
    claims jsonb NOT NULL,
    claims_role regrole GENERATED ALWAYS AS (realtime.to_regrole((claims ->> 'role'::text))) STORED NOT NULL,
    created_at timestamp without time zone DEFAULT timezone('utc'::text, now()) NOT NULL,
    action_filter text DEFAULT '*'::text,
    selected_columns text[],
    CONSTRAINT subscription_action_filter_check CHECK ((action_filter = ANY (ARRAY['*'::text, 'INSERT'::text, 'UPDATE'::text, 'DELETE'::text])))
);


ALTER TABLE realtime.subscription OWNER TO supabase_admin;

--
-- Name: subscription_id_seq; Type: SEQUENCE; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE realtime.subscription ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (
    SEQUENCE NAME realtime.subscription_id_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1
);


--
-- Name: buckets; Type: TABLE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TABLE storage.buckets (
    id text NOT NULL,
    name text NOT NULL,
    owner uuid,
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now(),
    public boolean DEFAULT false,
    avif_autodetection boolean DEFAULT false,
    file_size_limit bigint,
    allowed_mime_types text[],
    owner_id text,
    type storage.buckettype DEFAULT 'STANDARD'::storage.buckettype NOT NULL
);


ALTER TABLE storage.buckets OWNER TO supabase_storage_admin;

--
-- Name: COLUMN buckets.owner; Type: COMMENT; Schema: storage; Owner: supabase_storage_admin
--

COMMENT ON COLUMN storage.buckets.owner IS 'Field is deprecated, use owner_id instead';


--
-- Name: buckets_analytics; Type: TABLE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TABLE storage.buckets_analytics (
    name text NOT NULL,
    type storage.buckettype DEFAULT 'ANALYTICS'::storage.buckettype NOT NULL,
    format text DEFAULT 'ICEBERG'::text NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    deleted_at timestamp with time zone
);


ALTER TABLE storage.buckets_analytics OWNER TO supabase_storage_admin;

--
-- Name: buckets_vectors; Type: TABLE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TABLE storage.buckets_vectors (
    id text NOT NULL,
    type storage.buckettype DEFAULT 'VECTOR'::storage.buckettype NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE storage.buckets_vectors OWNER TO supabase_storage_admin;

--
-- Name: iceberg_namespaces; Type: TABLE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TABLE storage.iceberg_namespaces (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    bucket_name text NOT NULL,
    name text NOT NULL COLLATE pg_catalog."C",
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    metadata jsonb DEFAULT '{}'::jsonb NOT NULL,
    catalog_id uuid NOT NULL
);


ALTER TABLE storage.iceberg_namespaces OWNER TO supabase_storage_admin;

--
-- Name: iceberg_tables; Type: TABLE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TABLE storage.iceberg_tables (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    namespace_id uuid NOT NULL,
    bucket_name text NOT NULL,
    name text NOT NULL COLLATE pg_catalog."C",
    location text NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL,
    remote_table_id text,
    shard_key text,
    shard_id text,
    catalog_id uuid NOT NULL
);


ALTER TABLE storage.iceberg_tables OWNER TO supabase_storage_admin;

--
-- Name: migrations; Type: TABLE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TABLE storage.migrations (
    id integer NOT NULL,
    name character varying(100) NOT NULL,
    hash character varying(40) NOT NULL,
    executed_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP
);


ALTER TABLE storage.migrations OWNER TO supabase_storage_admin;

--
-- Name: objects; Type: TABLE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TABLE storage.objects (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    bucket_id text,
    name text,
    owner uuid,
    created_at timestamp with time zone DEFAULT now(),
    updated_at timestamp with time zone DEFAULT now(),
    last_accessed_at timestamp with time zone DEFAULT now(),
    metadata jsonb,
    path_tokens text[] GENERATED ALWAYS AS (string_to_array(name, '/'::text)) STORED,
    version text,
    owner_id text,
    user_metadata jsonb
);


ALTER TABLE storage.objects OWNER TO supabase_storage_admin;

--
-- Name: COLUMN objects.owner; Type: COMMENT; Schema: storage; Owner: supabase_storage_admin
--

COMMENT ON COLUMN storage.objects.owner IS 'Field is deprecated, use owner_id instead';


--
-- Name: s3_multipart_uploads; Type: TABLE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TABLE storage.s3_multipart_uploads (
    id text NOT NULL,
    in_progress_size bigint DEFAULT 0 NOT NULL,
    upload_signature text NOT NULL,
    bucket_id text NOT NULL,
    key text NOT NULL COLLATE pg_catalog."C",
    version text NOT NULL,
    owner_id text,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    user_metadata jsonb,
    metadata jsonb
);


ALTER TABLE storage.s3_multipart_uploads OWNER TO supabase_storage_admin;

--
-- Name: s3_multipart_uploads_parts; Type: TABLE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TABLE storage.s3_multipart_uploads_parts (
    id uuid DEFAULT gen_random_uuid() NOT NULL,
    upload_id text NOT NULL,
    size bigint DEFAULT 0 NOT NULL,
    part_number integer NOT NULL,
    bucket_id text NOT NULL,
    key text NOT NULL COLLATE pg_catalog."C",
    etag text NOT NULL,
    owner_id text,
    version text NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE storage.s3_multipart_uploads_parts OWNER TO supabase_storage_admin;

--
-- Name: vector_indexes; Type: TABLE; Schema: storage; Owner: supabase_storage_admin
--

CREATE TABLE storage.vector_indexes (
    id text DEFAULT gen_random_uuid() NOT NULL,
    name text NOT NULL COLLATE pg_catalog."C",
    bucket_id text NOT NULL,
    data_type text NOT NULL,
    dimension integer NOT NULL,
    distance_metric text NOT NULL,
    metadata_configuration jsonb,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    updated_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE storage.vector_indexes OWNER TO supabase_storage_admin;

--
-- Name: hooks; Type: TABLE; Schema: supabase_functions; Owner: supabase_functions_admin
--

CREATE TABLE supabase_functions.hooks (
    id bigint NOT NULL,
    hook_table_id integer NOT NULL,
    hook_name text NOT NULL,
    created_at timestamp with time zone DEFAULT now() NOT NULL,
    request_id bigint
);


ALTER TABLE supabase_functions.hooks OWNER TO supabase_functions_admin;

--
-- Name: TABLE hooks; Type: COMMENT; Schema: supabase_functions; Owner: supabase_functions_admin
--

COMMENT ON TABLE supabase_functions.hooks IS 'Supabase Functions Hooks: Audit trail for triggered hooks.';


--
-- Name: hooks_id_seq; Type: SEQUENCE; Schema: supabase_functions; Owner: supabase_functions_admin
--

CREATE SEQUENCE supabase_functions.hooks_id_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER SEQUENCE supabase_functions.hooks_id_seq OWNER TO supabase_functions_admin;

--
-- Name: hooks_id_seq; Type: SEQUENCE OWNED BY; Schema: supabase_functions; Owner: supabase_functions_admin
--

ALTER SEQUENCE supabase_functions.hooks_id_seq OWNED BY supabase_functions.hooks.id;


--
-- Name: migrations; Type: TABLE; Schema: supabase_functions; Owner: supabase_functions_admin
--

CREATE TABLE supabase_functions.migrations (
    version text NOT NULL,
    inserted_at timestamp with time zone DEFAULT now() NOT NULL
);


ALTER TABLE supabase_functions.migrations OWNER TO supabase_functions_admin;

--
-- Name: schema_migrations; Type: TABLE; Schema: supabase_migrations; Owner: postgres
--

CREATE TABLE supabase_migrations.schema_migrations (
    version text NOT NULL,
    statements text[],
    name text
);


ALTER TABLE supabase_migrations.schema_migrations OWNER TO postgres;

--
-- Name: messages_2026_07_02; Type: TABLE ATTACH; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2026_07_02 FOR VALUES FROM ('2026-07-02 00:00:00') TO ('2026-07-03 00:00:00');


--
-- Name: messages_2026_07_03; Type: TABLE ATTACH; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2026_07_03 FOR VALUES FROM ('2026-07-03 00:00:00') TO ('2026-07-04 00:00:00');


--
-- Name: messages_2026_07_04; Type: TABLE ATTACH; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2026_07_04 FOR VALUES FROM ('2026-07-04 00:00:00') TO ('2026-07-05 00:00:00');


--
-- Name: messages_2026_07_05; Type: TABLE ATTACH; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2026_07_05 FOR VALUES FROM ('2026-07-05 00:00:00') TO ('2026-07-06 00:00:00');


--
-- Name: messages_2026_07_06; Type: TABLE ATTACH; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2026_07_06 FOR VALUES FROM ('2026-07-06 00:00:00') TO ('2026-07-07 00:00:00');


--
-- Name: messages_2026_07_07; Type: TABLE ATTACH; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2026_07_07 FOR VALUES FROM ('2026-07-07 00:00:00') TO ('2026-07-08 00:00:00');


--
-- Name: messages_2026_07_08; Type: TABLE ATTACH; Schema: realtime; Owner: supabase_admin
--

ALTER TABLE ONLY realtime.messages ATTACH PARTITION realtime.messages_2026_07_08 FOR VALUES FROM ('2026-07-08 00:00:00') TO ('2026-07-09 00:00:00');


--
-- Name: refresh_tokens id; Type: DEFAULT; Schema: auth; Owner: supabase_auth_admin
--

ALTER TABLE ONLY auth.refresh_tokens ALTER COLUMN id SET DEFAULT nextval('auth.refresh_tokens_id_seq'::regclass);


--
-- Name: hooks id; Type: DEFAULT; Schema: supabase_functions; Owner: supabase_functions_admin
--

ALTER TABLE ONLY supabase_functions.hooks ALTER COLUMN id SET DEFAULT nextval('supabase_functions.hooks_id_seq'::regclass);




--
-- Data for Name: feature_flags; Type: TABLE DATA; Schema: _realtime; Owner: supabase_admin
--

COPY _realtime.feature_flags (id, name, enabled, inserted_at, updated_at) FROM stdin;
\.


--
-- Data for Name: schema_migrations; Type: TABLE DATA; Schema: _realtime; Owner: supabase_admin
--

COPY _realtime.schema_migrations (version, inserted_at) FROM stdin;
20210706140551	2026-06-12 00:19:48
20220329161857	2026-06-12 00:19:48
20220410212326	2026-06-12 00:19:48
20220506102948	2026-06-12 00:19:48
20220527210857	2026-06-12 00:19:48
20220815211129	2026-06-12 00:19:48
20220815215024	2026-06-12 00:19:48
20220818141501	2026-06-12 00:19:48
20221018173709	2026-06-12 00:19:48
20221102172703	2026-06-12 00:19:48
20221223010058	2026-06-12 00:19:49
20230110180046	2026-06-12 00:19:49
20230810220907	2026-06-12 00:19:49
20230810220924	2026-06-12 00:19:49
20231024094642	2026-06-12 00:19:49
20240306114423	2026-06-12 00:19:49
20240418082835	2026-06-12 00:19:49
20240625211759	2026-06-12 00:19:49
20240704172020	2026-06-12 00:19:49
20240902173232	2026-06-12 00:19:49
20241106103258	2026-06-12 00:19:49
20250424203323	2026-06-12 00:19:49
20250613072131	2026-06-12 00:19:49
20250711044927	2026-06-12 00:19:49
20250811121559	2026-06-12 00:19:49
20250926223044	2026-06-12 00:19:49
20251204170944	2026-06-12 00:19:49
20251218000543	2026-06-12 00:19:49
20260209232800	2026-06-12 00:19:49
20260304000000	2026-06-12 00:19:49
20260422000000	2026-06-12 00:19:49
\.


--
-- Data for Name: tenants; Type: TABLE DATA; Schema: _realtime; Owner: supabase_admin
--

COPY _realtime.tenants (id, name, external_id, jwt_secret, max_concurrent_users, inserted_at, updated_at, max_events_per_second, postgres_cdc_default, max_bytes_per_second, max_channels_per_client, max_joins_per_second, suspend, jwt_jwks, notify_private_alpha, private_only, migrations_ran, broadcast_adapter, max_presence_events_per_second, max_payload_size_in_kb, max_client_presence_events_per_window, client_presence_window_ms, presence_enabled, feature_flags) FROM stdin;
48547377-27b9-4666-a449-d11d29a7238f	realtime-dev	realtime-dev	iNjicxc4+llvc9wovDvqymwfnj9teWMlyOIbJ8Fh6j2WNU8CIJ2ZgjR6MUIKqSmeDmvpsKLsZ9jgXJmQPpwL8w==	200	2026-07-03 02:52:35	2026-07-03 02:52:35	100	postgres_cdc_rls	100000	100	100	f	{"keys": [{"x": "M5Sjqn5zwC9Kl1zVfUUGvv9boQjCGd45G8sdopBExB4", "y": "P6IXMvA2WYXSHSOMTBH2jsw_9rrzGy89FjPf6oOsIxQ", "alg": "ES256", "crv": "P-256", "ext": true, "kid": "b81269f1-21d8-4f2e-b719-c2240a840d90", "kty": "EC", "use": "sig", "key_ops": ["verify"]}, {"k": "c3VwZXItc2VjcmV0LWp3dC10b2tlbi13aXRoLWF0LWxlYXN0LTMyLWNoYXJhY3RlcnMtbG9uZw", "kty": "oct"}]}	f	f	73	gen_rpc	1000	3000	\N	\N	f	{}
\.


--
-- Data for Name: audit_log_entries; Type: TABLE DATA; Schema: auth; Owner: supabase_auth_admin
--

COPY auth.audit_log_entries (instance_id, id, payload, created_at, ip_address) FROM stdin;
00000000-0000-0000-0000-000000000000	f5e1a42e-535d-42ad-bcd1-4b67bcdfc41a	{"action":"user_signedup","actor_id":"00000000-0000-0000-0000-000000000000","actor_username":"service_role","actor_via_sso":false,"log_type":"team","traits":{"provider":"email","user_email":"ashraffarid@gmail.com","user_id":"f69c2370-64a4-467b-9be5-0262b271986a","user_phone":""}}	2026-06-12 00:22:09.687585+00	
00000000-0000-0000-0000-000000000000	b7ab855d-e6a3-4a2e-9e2a-ba0f247d30cf	{"action":"login","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-06-12 00:23:50.310115+00	
00000000-0000-0000-0000-000000000000	975efd8f-fae1-4da9-853f-708e69068e9d	{"action":"user_signedup","actor_id":"00000000-0000-0000-0000-000000000000","actor_username":"service_role","actor_via_sso":false,"log_type":"team","traits":{"provider":"email","user_email":"admin@admin.com","user_id":"8526382f-7ebb-4245-b8be-84c1f7a14e40","user_phone":""}}	2026-06-12 00:24:01.260914+00	
00000000-0000-0000-0000-000000000000	4d7bd547-f0e3-410d-98d2-855d14eb9413	{"action":"login","actor_id":"8526382f-7ebb-4245-b8be-84c1f7a14e40","actor_username":"admin@admin.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-06-12 00:24:13.097843+00	
00000000-0000-0000-0000-000000000000	99fca6ea-01cc-4b80-9dd9-699f2c0bf8c2	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 01:22:26.972543+00	
00000000-0000-0000-0000-000000000000	5827e7aa-69ab-4481-adc4-1bfe30c97a0c	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 01:22:26.973762+00	
00000000-0000-0000-0000-000000000000	4cdd32d0-95dc-4df3-b3a2-bebd6aa5a8aa	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 02:20:31.188079+00	
00000000-0000-0000-0000-000000000000	ff19960b-ded5-4583-8b0e-94647af83157	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 02:20:31.189584+00	
00000000-0000-0000-0000-000000000000	c5721887-42cb-4879-9ba9-f72097d8e180	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 07:40:00.217294+00	
00000000-0000-0000-0000-000000000000	7b2e9625-0a98-45fc-a0f3-8b2c0a9d5ca1	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 07:40:00.220807+00	
00000000-0000-0000-0000-000000000000	be172e0a-6120-4b47-ba4d-530a8b4c8461	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 08:38:31.118893+00	
00000000-0000-0000-0000-000000000000	8f186932-f06b-4c4f-a6b3-e6048bb7aa4b	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 08:38:31.120296+00	
00000000-0000-0000-0000-000000000000	85493b82-3299-42f8-8923-e3361aa35bf1	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 09:36:31.113163+00	
00000000-0000-0000-0000-000000000000	4aee5924-e37b-457c-8d02-3da5787c2e3f	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 09:36:31.113979+00	
00000000-0000-0000-0000-000000000000	f51f6a51-1f47-4c86-bf59-70b856390cc6	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 10:34:31.137325+00	
00000000-0000-0000-0000-000000000000	476988c4-27ed-4301-9493-7764a0774a2a	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 10:34:31.138871+00	
00000000-0000-0000-0000-000000000000	777a4580-f611-4772-9291-13a20caa4501	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 13:06:40.931565+00	
00000000-0000-0000-0000-000000000000	aeaf188e-e02e-4414-9735-687d739c2d68	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 13:06:40.935416+00	
00000000-0000-0000-0000-000000000000	c8decebe-776e-42b7-a55f-5a3dbb760652	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 14:05:31.140659+00	
00000000-0000-0000-0000-000000000000	3885b45f-863d-48e8-a496-c425d5c1a282	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 14:05:31.141919+00	
00000000-0000-0000-0000-000000000000	be77cbc7-6f60-4a55-8605-f4b0fc1547b2	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 15:04:14.62976+00	
00000000-0000-0000-0000-000000000000	40539b17-7e5f-48c7-bb3a-36c82b1f2205	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 15:04:14.63116+00	
00000000-0000-0000-0000-000000000000	92d8e64b-cd00-464f-b378-028d2dd9ef93	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 16:02:27.067685+00	
00000000-0000-0000-0000-000000000000	869f7277-77d3-4692-a604-981abb9cf036	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 16:02:27.068934+00	
00000000-0000-0000-0000-000000000000	05002b3e-fd35-4d09-9ad8-cfd8e8456516	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 17:00:31.848327+00	
00000000-0000-0000-0000-000000000000	c0a13cde-a6c3-4ec6-a0ee-4f221f19cde0	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 17:00:31.84944+00	
00000000-0000-0000-0000-000000000000	563e7b94-25eb-438e-a962-cd5299feb76b	{"action":"login","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-06-12 19:44:05.336282+00	
00000000-0000-0000-0000-000000000000	d804bf6c-3dc7-45db-ae19-1beb901f7ed2	{"action":"login","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-06-12 20:06:15.459909+00	
00000000-0000-0000-0000-000000000000	95d8a750-8b72-4a78-b367-231d59bdc3c7	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 21:35:33.069457+00	
00000000-0000-0000-0000-000000000000	b94ea55f-866e-42a7-ac9e-17225095aeb5	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-12 21:35:33.070521+00	
00000000-0000-0000-0000-000000000000	78709773-219f-4e78-8b9a-d972bfbd9e23	{"action":"login","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-06-12 22:24:41.618754+00	
00000000-0000-0000-0000-000000000000	03a012e4-ce5e-4e9b-9531-3f5e8879aaa9	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-20 00:38:21.639988+00	
00000000-0000-0000-0000-000000000000	41291e9a-4ffa-41dc-b8fd-d48d0e0b0685	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-06-20 00:38:21.642363+00	
00000000-0000-0000-0000-000000000000	0df241ff-9d15-47ad-848e-46ab87c2d528	{"action":"login","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-06-20 00:38:36.343956+00	
00000000-0000-0000-0000-000000000000	4728b510-b881-4940-b3e7-c747b6090a76	{"action":"login","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-06-20 00:39:00.92554+00	
00000000-0000-0000-0000-000000000000	f519e006-f584-440e-945f-abd53a69d303	{"action":"user_modified","actor_id":"00000000-0000-0000-0000-000000000000","actor_username":"service_role","actor_via_sso":false,"log_type":"user","traits":{"user_email":"ashraffarid@gmail.com","user_id":"f69c2370-64a4-467b-9be5-0262b271986a","user_phone":""}}	2026-07-04 12:21:13.270407+00	
00000000-0000-0000-0000-000000000000	60d5edee-750c-44c4-914e-0ccb727a13ca	{"action":"login","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-07-04 12:21:22.929556+00	
00000000-0000-0000-0000-000000000000	21f4758b-d81b-427c-bc33-c939fc4f9d6a	{"action":"login","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-07-04 12:21:42.207885+00	
00000000-0000-0000-0000-000000000000	64db59c4-2ef7-429f-a1c6-36ae855ac8cd	{"action":"login","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-07-04 12:21:52.473326+00	
00000000-0000-0000-0000-000000000000	dfc0c831-7917-4b37-8967-ed82d12cf4f7	{"action":"login","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-07-04 12:23:50.993945+00	
00000000-0000-0000-0000-000000000000	0d72966c-e0ae-41c2-8b3e-f51afc9df6b5	{"action":"user_signedup","actor_id":"00000000-0000-0000-0000-000000000000","actor_username":"service_role","actor_via_sso":false,"log_type":"team","traits":{"provider":"email","user_email":"veedon.test@local.dev","user_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","user_phone":""}}	2026-07-04 13:10:17.918076+00	
00000000-0000-0000-0000-000000000000	07cbb809-79da-4a85-a5c7-673780f76064	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 13:20:18.568754+00	
00000000-0000-0000-0000-000000000000	c8cce902-6b1f-4eec-90c9-d10da6704214	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 13:20:18.572071+00	
00000000-0000-0000-0000-000000000000	c239a058-4135-4342-b722-0ada7c73ce0a	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 14:18:18.554482+00	
00000000-0000-0000-0000-000000000000	120776d4-590e-40e9-a1a2-88e282f3c6cc	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 14:18:18.55532+00	
00000000-0000-0000-0000-000000000000	9ec66434-8747-41a4-bad7-b704251d4bcb	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 15:16:18.553291+00	
00000000-0000-0000-0000-000000000000	1ef001c4-401f-4fad-8384-3fbff9f4355e	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 15:16:18.553918+00	
00000000-0000-0000-0000-000000000000	482d85e3-01ad-46ed-acb6-5f02415df707	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 16:14:18.559053+00	
00000000-0000-0000-0000-000000000000	c22b37c2-075c-4131-be27-ea21e5c392be	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 16:14:18.559817+00	
00000000-0000-0000-0000-000000000000	9b0080b5-cba8-4ee8-b80e-dc9a6cbce0da	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 17:12:18.566843+00	
00000000-0000-0000-0000-000000000000	aa9b99ae-ffeb-4035-96d1-3c4292c45a88	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 17:12:18.56809+00	
00000000-0000-0000-0000-000000000000	ed74fda4-8125-433a-8f40-fe8688cdbcb7	{"action":"login","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-07-04 17:33:59.462776+00	
00000000-0000-0000-0000-000000000000	892250d2-03c4-4ebf-bc4f-daadc6771906	{"action":"logout","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"account"}	2026-07-04 17:33:59.583088+00	
00000000-0000-0000-0000-000000000000	fc496b3d-c8ab-4992-bb01-318c53607fc3	{"action":"login","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-07-04 17:34:26.161698+00	
00000000-0000-0000-0000-000000000000	f1255434-b732-48b2-8a2a-4440a20a0b07	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 18:10:20.358597+00	
00000000-0000-0000-0000-000000000000	0d82727d-4b03-46b8-8b98-def715c3dfee	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 18:10:20.359468+00	
00000000-0000-0000-0000-000000000000	869d16e0-c228-4333-8950-a334458c6acc	{"action":"token_refreshed","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-04 18:32:50.927095+00	
00000000-0000-0000-0000-000000000000	90717f37-c90d-4335-8b9b-6816c5decd64	{"action":"token_revoked","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-04 18:32:50.927664+00	
00000000-0000-0000-0000-000000000000	813bf38d-bcbe-42e9-826b-0ce0d9b970bd	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 19:08:20.343223+00	
00000000-0000-0000-0000-000000000000	9b17047a-7206-4346-9653-7dbd78a00760	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 19:08:20.343999+00	
00000000-0000-0000-0000-000000000000	8c7c75ed-248f-452d-9c81-8cd00ad913a6	{"action":"token_refreshed","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-04 19:30:50.91724+00	
00000000-0000-0000-0000-000000000000	f67e35f2-e8d3-4110-b54b-3581f639c7ae	{"action":"token_revoked","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-04 19:30:50.91777+00	
00000000-0000-0000-0000-000000000000	70573a75-26e7-43fd-a0c7-449ca64ab191	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 20:06:20.350409+00	
00000000-0000-0000-0000-000000000000	1c92d1c2-853f-4545-9a6e-0df8626eb0e6	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 20:06:20.351027+00	
00000000-0000-0000-0000-000000000000	96e0f36f-fa5a-4af1-9bcf-04d78a1bef8e	{"action":"token_refreshed","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-04 20:29:20.313188+00	
00000000-0000-0000-0000-000000000000	85414ea2-7b9f-4e13-8c4f-2167444fbdca	{"action":"token_revoked","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-04 20:29:20.313728+00	
00000000-0000-0000-0000-000000000000	34f3f6a3-896c-4c18-83dd-ed17bc3bc876	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 21:04:20.33772+00	
00000000-0000-0000-0000-000000000000	9b702acd-8da7-452b-9b2a-4f37df5a1f16	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 21:04:20.338503+00	
00000000-0000-0000-0000-000000000000	5eb00c7c-bb5a-48b6-9fac-d50f1e9abd08	{"action":"token_refreshed","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-04 21:43:10.512108+00	
00000000-0000-0000-0000-000000000000	28b3cd19-dd78-48a4-8084-cf9f1af15ebc	{"action":"token_revoked","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-04 21:43:10.512741+00	
00000000-0000-0000-0000-000000000000	96e4a63e-e77b-4806-968b-b3afaf7450c4	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 22:02:20.352469+00	
00000000-0000-0000-0000-000000000000	40dcc7cf-7b59-47de-8605-a03bcdd8fe7a	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 22:02:20.353191+00	
00000000-0000-0000-0000-000000000000	d33bf4a6-9b69-4eee-a08e-aaf16fac373a	{"action":"login","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-07-04 22:39:23.052077+00	
00000000-0000-0000-0000-000000000000	92268808-5a53-4410-9a26-ea70034e6620	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 23:00:20.336642+00	
00000000-0000-0000-0000-000000000000	0ff955c6-8fa3-4365-903e-f5933af42a1c	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 23:00:20.33734+00	
00000000-0000-0000-0000-000000000000	ecee8d13-d278-4155-bf03-d3dce616727e	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 23:59:20.339247+00	
00000000-0000-0000-0000-000000000000	5babb661-3024-402d-9109-64a4ccda8a53	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-04 23:59:20.341267+00	
00000000-0000-0000-0000-000000000000	8ef8e5f8-d643-4ba8-aa1f-60e823f57d7d	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-05 01:18:52.110532+00	
00000000-0000-0000-0000-000000000000	10f45a36-2947-4a59-9ade-c3cc1656e74a	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-05 01:18:52.113932+00	
00000000-0000-0000-0000-000000000000	0ad7079c-ab6e-4864-acbb-c4ccbf0e9562	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-05 02:17:20.303194+00	
00000000-0000-0000-0000-000000000000	a457d6d0-428a-4f64-85ca-1443667dcd61	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-05 02:17:20.304721+00	
00000000-0000-0000-0000-000000000000	852ebf01-83e4-4f79-8f35-8f67d4b20b94	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-05 03:15:20.303414+00	
00000000-0000-0000-0000-000000000000	48fb851d-acbb-43d8-a6eb-d15ac468d19d	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-05 03:15:20.3051+00	
00000000-0000-0000-0000-000000000000	5191a4c2-0952-4703-81eb-f94df65e8731	{"action":"token_refreshed","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-05 03:42:30.614011+00	
00000000-0000-0000-0000-000000000000	9b6798b0-cf78-4716-b3a4-b8b50a728036	{"action":"token_revoked","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-05 03:42:30.614705+00	
00000000-0000-0000-0000-000000000000	5e3b3947-5474-4b6a-aedf-9f577558db33	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-05 04:14:20.297575+00	
00000000-0000-0000-0000-000000000000	4660217a-ece1-4d57-8ad4-eac3bf9a023d	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-05 04:14:20.29826+00	
00000000-0000-0000-0000-000000000000	0b747f95-fb1e-42a7-a489-afbe1840c96a	{"action":"token_refreshed","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-05 04:40:50.745025+00	
00000000-0000-0000-0000-000000000000	0cabf0d4-1474-43c9-8b14-b40e0ee6aaa4	{"action":"token_revoked","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-05 04:40:50.745701+00	
00000000-0000-0000-0000-000000000000	dfd2de2e-8985-4213-8bc6-d7d14daf086d	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-05 05:13:20.29312+00	
00000000-0000-0000-0000-000000000000	c1ea02c5-f300-40f1-b79f-7d82e7f70202	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-05 05:13:20.294169+00	
00000000-0000-0000-0000-000000000000	54ba45f9-22bf-45b1-9fe6-60ad00d21ef3	{"action":"token_refreshed","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-05 05:39:22.703133+00	
00000000-0000-0000-0000-000000000000	291ed1df-fed6-4f3c-919e-21aa98fa3f7b	{"action":"token_revoked","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-05 05:39:22.726898+00	
00000000-0000-0000-0000-000000000000	5f66022a-dde1-4f42-939a-130087f4f237	{"action":"user_modified","actor_id":"00000000-0000-0000-0000-000000000000","actor_username":"service_role","actor_via_sso":false,"log_type":"user","traits":{"user_email":"ashraffarid@gmail.com","user_id":"f69c2370-64a4-467b-9be5-0262b271986a","user_phone":""}}	2026-07-05 06:00:38.301517+00	
00000000-0000-0000-0000-000000000000	39a089e2-cdc6-437d-bf4e-79b405e7f4f1	{"action":"user_modified","actor_id":"00000000-0000-0000-0000-000000000000","actor_username":"service_role","actor_via_sso":false,"log_type":"user","traits":{"user_email":"ashraffarid@gmail.com","user_id":"f69c2370-64a4-467b-9be5-0262b271986a","user_phone":""}}	2026-07-05 06:00:51.62088+00	
00000000-0000-0000-0000-000000000000	fa5863dd-d486-407b-9647-06b8ecfb322d	{"action":"login","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-07-05 06:01:05.94478+00	
00000000-0000-0000-0000-000000000000	c259b72d-397e-4103-b912-8d1c5451104d	{"action":"login","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-07-05 06:01:24.962898+00	
00000000-0000-0000-0000-000000000000	4290bcef-7982-4130-834d-00d391b5df07	{"action":"login","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-07-05 06:01:57.244894+00	
00000000-0000-0000-0000-000000000000	687b980d-44f8-4cce-be0a-f29fa111dec9	{"action":"login","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-07-05 06:10:45.721802+00	
00000000-0000-0000-0000-000000000000	b3aae1f0-9217-40cc-aa37-8e605def0c32	{"action":"token_refreshed","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-05 06:37:53.264427+00	
00000000-0000-0000-0000-000000000000	f0b2e542-7986-4dbe-9a58-b5b113e6299e	{"action":"token_revoked","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"token"}	2026-07-05 06:37:53.264934+00	
00000000-0000-0000-0000-000000000000	5e724357-3a71-4e39-af32-cfb87cc1d31a	{"action":"login","actor_id":"a7b186ca-e6c3-4ece-9349-26a0dbf0defa","actor_username":"veedon.test@local.dev","actor_via_sso":false,"log_type":"account","traits":{"provider":"email"}}	2026-07-05 06:40:06.8369+00	
00000000-0000-0000-0000-000000000000	c3dee3c5-c9fd-49f4-b39d-580779f3d0e7	{"action":"token_refreshed","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-05 07:09:16.27619+00	
00000000-0000-0000-0000-000000000000	7c7bea3b-b476-4e2e-88c4-5ead9abb522c	{"action":"token_revoked","actor_id":"f69c2370-64a4-467b-9be5-0262b271986a","actor_username":"ashraffarid@gmail.com","actor_via_sso":false,"log_type":"token"}	2026-07-05 07:09:16.276769+00	
\.


--
