Files
cloudlense/frontend/supabase/migrations/20250813102225_remote_schema.sql
Dennis 50e25e3ee8 refactor: flatten monorepo structure to backend/ frontend/ devops/
Rename subdirectories for a cleaner single-repo layout:
- website-monitoring-backend/  → backend/
- website-monitoring-frontend/ → frontend/
- website-monitoring-devops/   → devops/

Update all references in package.json scripts, CI workflows,
docker-compose, pre-commit hooks, and documentation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-07 00:25:29 +01:00

2454 lines
66 KiB
PL/PgSQL

SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SELECT pg_catalog.set_config('search_path', '', false);
SET check_function_bodies = false;
SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
CREATE EXTENSION IF NOT EXISTS "pgsodium";
COMMENT ON SCHEMA "public" IS 'standard public schema';
CREATE EXTENSION IF NOT EXISTS "pg_graphql" WITH SCHEMA "graphql";
CREATE EXTENSION IF NOT EXISTS "pg_stat_statements" WITH SCHEMA "extensions";
CREATE EXTENSION IF NOT EXISTS "pg_trgm" WITH SCHEMA "extensions";
CREATE EXTENSION IF NOT EXISTS "pgcrypto" WITH SCHEMA "extensions";
CREATE EXTENSION IF NOT EXISTS "pgjwt" WITH SCHEMA "extensions";
CREATE EXTENSION IF NOT EXISTS "supabase_vault" WITH SCHEMA "vault";
CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA "extensions";
CREATE TYPE "public"."comparison_operator" AS ENUM (
'less_than',
'less_than_equal',
'greater_than',
'greater_than_equal',
'equal_to',
'not_equal_to'
);
ALTER TYPE "public"."comparison_operator" OWNER TO "postgres";
CREATE TYPE "public"."metric_category" AS ENUM (
'performance',
'seo',
'accessibility',
'best_practices',
'security',
'pwa'
);
ALTER TYPE "public"."metric_category" OWNER TO "postgres";
CREATE TYPE "public"."notification_channel" AS ENUM (
'email',
'slack',
'webhook',
'in_app'
);
ALTER TYPE "public"."notification_channel" OWNER TO "postgres";
CREATE TYPE "public"."resource_type" AS ENUM (
'script',
'stylesheet',
'image',
'font',
'document',
'media',
'other'
);
ALTER TYPE "public"."resource_type" OWNER TO "postgres";
CREATE TYPE "public"."scan_status" AS ENUM (
'pending',
'queued',
'running',
'completed',
'failed',
'cancelled'
);
ALTER TYPE "public"."scan_status" OWNER TO "postgres";
CREATE TYPE "public"."severity_level" AS ENUM (
'critical',
'high',
'medium',
'low',
'info'
);
ALTER TYPE "public"."severity_level" OWNER TO "postgres";
CREATE TYPE "public"."subscription_tier" AS ENUM (
'free',
'starter',
'professional',
'enterprise'
);
ALTER TYPE "public"."subscription_tier" OWNER TO "postgres";
CREATE TYPE "public"."user_role" AS ENUM (
'owner',
'admin',
'editor',
'viewer'
);
ALTER TYPE "public"."user_role" OWNER TO "postgres";
CREATE OR REPLACE FUNCTION "public"."apply_data_retention"() RETURNS "void"
LANGUAGE "plpgsql" SECURITY DEFINER
SET "search_path" TO 'public', 'pg_temp'
AS $$
BEGIN
-- Delete old scan results (older than 90 days)
DELETE FROM public.scan_results
WHERE created_at < NOW() - INTERVAL '90 days';
-- Delete old metric values (older than 90 days)
DELETE FROM public.metric_values
WHERE created_at < NOW() - INTERVAL '90 days';
-- Delete old alert history (older than 365 days)
DELETE FROM public.alert_history
WHERE created_at < NOW() - INTERVAL '365 days';
-- Delete old audit logs (older than 365 days)
DELETE FROM public.audit_logs
WHERE created_at < NOW() - INTERVAL '365 days';
END;
$$;
ALTER FUNCTION "public"."apply_data_retention"() OWNER TO "postgres";
CREATE OR REPLACE FUNCTION "public"."calculate_competitor_comparison"("website_id" "uuid") RETURNS TABLE("metric_key" character varying, "your_score" numeric, "competitor_avg" numeric, "competitor_best" numeric, "percentile" numeric)
LANGUAGE "plpgsql"
SET "search_path" TO 'public', 'pg_temp'
AS $$
BEGIN
RETURN QUERY
WITH your_metrics AS (
SELECT
m.key,
mv.value
FROM scans s
JOIN metric_values mv ON mv.scan_id = s.id
JOIN metric_definitions m ON m.id = mv.metric_id
WHERE s.website_id = calculate_competitor_comparison.website_id
AND s.created_at = (
SELECT MAX(created_at)
FROM scans
WHERE website_id = calculate_competitor_comparison.website_id
)
),
competitor_metrics AS (
SELECT
m.key,
mv.value,
PERCENT_RANK() OVER (PARTITION BY m.key ORDER BY mv.value) as percentile
FROM scans s
JOIN metric_values mv ON mv.scan_id = s.id
JOIN metric_definitions m ON m.id = mv.metric_id
WHERE s.website_id IN (
SELECT competitor_url_id
FROM competitor_websites
WHERE website_id = calculate_competitor_comparison.website_id
)
AND s.created_at >= NOW() - INTERVAL '30 days'
)
SELECT
ym.key,
ym.value as your_score,
AVG(cm.value) as competitor_avg,
MAX(cm.value) as competitor_best,
MAX(cm.percentile) * 100 as percentile
FROM your_metrics ym
LEFT JOIN competitor_metrics cm ON cm.key = ym.key
GROUP BY ym.key, ym.value;
END;
$$;
ALTER FUNCTION "public"."calculate_competitor_comparison"("website_id" "uuid") OWNER TO "postgres";
CREATE OR REPLACE FUNCTION "public"."calculate_competitor_comparison"("website_id_param" "uuid", "competitor_id_param" "uuid") RETURNS "jsonb"
LANGUAGE "plpgsql" SECURITY DEFINER
SET "search_path" TO 'public', 'pg_temp'
AS $$
DECLARE
result jsonb;
BEGIN
-- Calculate comparison metrics between website and competitor
SELECT jsonb_build_object(
'performance_score_diff',
COALESCE(w.performance_score - c.performance_score, 0),
'seo_score_diff',
COALESCE(w.seo_score - c.seo_score, 0),
'accessibility_score_diff',
COALESCE(w.accessibility_score - c.accessibility_score, 0)
) INTO result
FROM public.websites w
CROSS JOIN public.competitor_websites c
WHERE w.id = website_id_param
AND c.id = competitor_id_param;
RETURN COALESCE(result, '{}'::jsonb);
END;
$$;
ALTER FUNCTION "public"."calculate_competitor_comparison"("website_id_param" "uuid", "competitor_id_param" "uuid") OWNER TO "postgres";
CREATE OR REPLACE FUNCTION "public"."calculate_health_score"("website_id_param" "uuid") RETURNS numeric
LANGUAGE "plpgsql" SECURITY DEFINER
SET "search_path" TO 'public', 'pg_temp'
AS $$
DECLARE
health_score numeric;
BEGIN
-- Calculate weighted health score based on latest metrics
SELECT
COALESCE(
(performance_score * 0.4 +
seo_score * 0.3 +
accessibility_score * 0.2 +
best_practices_score * 0.1),
0
)
INTO health_score
FROM public.websites
WHERE id = website_id_param;
RETURN COALESCE(health_score, 0);
END;
$$;
ALTER FUNCTION "public"."calculate_health_score"("website_id_param" "uuid") OWNER TO "postgres";
CREATE OR REPLACE FUNCTION "public"."email_exists"("email_to_check" "text") RETURNS boolean
LANGUAGE "sql" SECURITY DEFINER
AS $$
select exists(
select 1 from users where lower(email) = lower(email_to_check)
);
$$;
ALTER FUNCTION "public"."email_exists"("email_to_check" "text") OWNER TO "postgres";
CREATE OR REPLACE FUNCTION "public"."generate_performance_report"("website_id" "uuid", "days" integer) RETURNS "jsonb"
LANGUAGE "plpgsql"
SET "search_path" TO 'public', 'pg_temp'
AS $$
DECLARE
report JSONB;
BEGIN
SELECT jsonb_build_object(
'website_info', (
SELECT jsonb_build_object(
'name', name,
'url', base_url,
'report_period', jsonb_build_object(
'start', NOW() - (days || ' days')::interval,
'end', NOW()
)
)
FROM websites
WHERE id = website_id
),
'performance_summary', (
SELECT jsonb_build_object(
'average_performance_score', AVG(mv.value),
'best_performance_score', MAX(mv.value),
'worst_performance_score', MIN(mv.value),
'trend', jsonb_agg(
jsonb_build_object(
'date', DATE(s.created_at),
'score', mv.value
) ORDER BY s.created_at
)
)
FROM scans s
JOIN metric_values mv ON mv.scan_id = s.id
JOIN metric_definitions md ON md.id = mv.metric_id
WHERE s.website_id = generate_performance_report.website_id
AND md.key = 'performance'
AND s.created_at >= NOW() - (days || ' days')::interval
),
'core_metrics', (
SELECT jsonb_object_agg(
md.key,
jsonb_build_object(
'average', AVG(mv.value),
'best', MAX(mv.value),
'worst', MIN(mv.value)
)
)
FROM scans s
JOIN metric_values mv ON mv.scan_id = s.id
JOIN metric_definitions md ON md.id = mv.metric_id
WHERE s.website_id = generate_performance_report.website_id
AND md.is_core_metric = true
AND s.created_at >= NOW() - (days || ' days')::interval
),
'resource_summary', (
SELECT jsonb_object_agg(
resource_type,
jsonb_build_object(
'count', COUNT(*),
'total_size', SUM(size_bytes),
'average_duration', AVG(duration_ms)
)
)
FROM scans s
JOIN resource_analysis ra ON ra.scan_id = s.id
WHERE s.website_id = generate_performance_report.website_id
AND s.created_at >= NOW() - (days || ' days')::interval
),
'alerts', (
SELECT jsonb_agg(
jsonb_build_object(
'severity', severity,
'message', message,
'created_at', created_at
)
)
FROM alerts
WHERE website_id = generate_performance_report.website_id
AND created_at >= NOW() - (days || ' days')::interval
)
) INTO report;
RETURN report;
END;
$$;
ALTER FUNCTION "public"."generate_performance_report"("website_id" "uuid", "days" integer) OWNER TO "postgres";
CREATE OR REPLACE FUNCTION "public"."generate_performance_report"("website_id_param" "uuid", "start_date" timestamp with time zone DEFAULT ("now"() - '30 days'::interval), "end_date" timestamp with time zone DEFAULT "now"()) RETURNS "jsonb"
LANGUAGE "plpgsql" SECURITY DEFINER
SET "search_path" TO 'public', 'pg_temp'
AS $$
DECLARE
report jsonb;
BEGIN
-- Generate comprehensive performance report
SELECT jsonb_build_object(
'website_id', website_id_param,
'period', jsonb_build_object(
'start_date', start_date,
'end_date', end_date
),
'summary', jsonb_build_object(
'total_scans', COUNT(s.id),
'avg_performance_score', AVG(w.performance_score),
'avg_seo_score', AVG(w.seo_score),
'avg_accessibility_score', AVG(w.accessibility_score)
),
'trends', jsonb_agg(
jsonb_build_object(
'date', DATE(s.created_at),
'performance_score', w.performance_score,
'seo_score', w.seo_score
)
)
) INTO report
FROM public.scans s
JOIN public.websites w ON w.id = s.website_id
WHERE s.website_id = website_id_param
AND s.created_at BETWEEN start_date AND end_date
GROUP BY website_id_param;
RETURN COALESCE(report, '{}'::jsonb);
END;
$$;
ALTER FUNCTION "public"."generate_performance_report"("website_id_param" "uuid", "start_date" timestamp with time zone, "end_date" timestamp with time zone) OWNER TO "postgres";
CREATE OR REPLACE FUNCTION "public"."handle_new_user"() RETURNS "trigger"
LANGUAGE "plpgsql" SECURITY DEFINER
SET "search_path" TO 'public', 'pg_temp'
AS $$
BEGIN
-- Log the new row to Postgres logs for debugging
RAISE LOG 'New user created: %', ROW(NEW.*);
-- Insert into public.users table
INSERT INTO public.users (id, email, organization_id, role, created_at, updated_at)
VALUES (
NEW.id,
NEW.email,
NEW.raw_user_meta_data->>'organization_id',
COALESCE(NEW.raw_user_meta_data->>'role', 'member'),
NOW(),
NOW()
);
RETURN NEW;
END;
$$;
ALTER FUNCTION "public"."handle_new_user"() OWNER TO "postgres";
CREATE OR REPLACE FUNCTION "public"."perform_maintenance"() RETURNS "void"
LANGUAGE "plpgsql"
SET "search_path" TO 'public', 'pg_temp'
AS $$
BEGIN
-- Clean up old rate limit records
DELETE FROM rate_limits
WHERE window_start < NOW() - INTERVAL '1 day';
-- Archive old notifications
UPDATE notification_deliveries
SET status = 'archived'
WHERE created_at < NOW() - INTERVAL '30 days';
-- Clean up expired API keys
UPDATE api_keys
SET is_active = false
WHERE expires_at < NOW();
-- Update statistics
ANALYZE websites;
ANALYZE scans;
ANALYZE metric_values;
ANALYZE resource_analysis;
-- Vacuum analyze for better query planning
VACUUM ANALYZE websites;
VACUUM ANALYZE scans;
VACUUM ANALYZE metric_values;
VACUUM ANALYZE resource_analysis;
END;
$$;
ALTER FUNCTION "public"."perform_maintenance"() OWNER TO "postgres";
CREATE OR REPLACE FUNCTION "public"."process_alert_notifications"() RETURNS "trigger"
LANGUAGE "plpgsql"
SET "search_path" TO 'public', 'pg_temp'
AS $$
DECLARE
website_record RECORD;
user_record RECORD;
BEGIN
-- Get website details
SELECT * INTO website_record
FROM websites
WHERE id = NEW.website_id;
-- Insert notification for each user in the organization
FOR user_record IN
SELECT u.*
FROM users u
WHERE u.organization_id = website_record.organization_id
AND (u.settings->>'email_notifications')::boolean = true
LOOP
INSERT INTO notification_deliveries (
alert_id,
channel,
recipient,
content
) VALUES (
NEW.id,
'email',
user_record.email,
format(
'Alert for %s: %s. Severity: %s',
website_record.name,
NEW.message,
NEW.severity
)
);
END LOOP;
RETURN NEW;
END;
$$;
ALTER FUNCTION "public"."process_alert_notifications"() OWNER TO "postgres";
CREATE OR REPLACE FUNCTION "public"."update_scan_status"() RETURNS "trigger"
LANGUAGE "plpgsql"
SET "search_path" TO 'public', 'pg_temp'
AS $$
BEGIN
IF NEW.status = 'completed' THEN
-- Update website's last scan timestamp
UPDATE websites
SET last_scan_at = NOW()
WHERE id = NEW.website_id;
-- Check for alerts
INSERT INTO alerts (website_id, page_id, severity, title, message)
SELECT
NEW.website_id,
NEW.page_id,
ac.severity,
'Metric threshold exceeded',
format('%s is %s threshold of %s', m.name, ac.comparison, ac.threshold)
FROM metric_values mv
JOIN metric_definitions m ON m.id = mv.metric_id
JOIN alert_configurations ac ON ac.metric_id = m.id
WHERE mv.scan_id = NEW.id
AND ac.website_id = NEW.website_id
AND (
CASE ac.comparison
WHEN 'less_than' THEN mv.value < ac.threshold
WHEN 'greater_than' THEN mv.value > ac.threshold
WHEN 'equal_to' THEN mv.value = ac.threshold
END
);
END IF;
RETURN NEW;
END;
$$;
ALTER FUNCTION "public"."update_scan_status"() OWNER TO "postgres";
SET default_tablespace = '';
SET default_table_access_method = "heap";
CREATE TABLE IF NOT EXISTS "public"."alert_configurations" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"website_id" "uuid" NOT NULL,
"name" character varying NOT NULL,
"description" "text",
"metric_id" "uuid" NOT NULL,
"threshold" numeric NOT NULL,
"comparison" "public"."comparison_operator" DEFAULT 'less_than'::"public"."comparison_operator",
"severity" "public"."severity_level" DEFAULT 'medium'::"public"."severity_level",
"consecutive_count" integer DEFAULT 1,
"cooldown_minutes" integer DEFAULT 60,
"notification_channels" "public"."notification_channel"[] DEFAULT ARRAY['email'::"public"."notification_channel"],
"notification_template" "text",
"is_active" boolean DEFAULT true,
"last_triggered_at" timestamp with time zone,
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."alert_configurations" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."alert_history" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"alert_id" "uuid" NOT NULL,
"event_type" character varying NOT NULL,
"event_data" "jsonb" NOT NULL,
"created_by" "uuid",
"created_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."alert_history" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."alerts" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"website_id" "uuid" NOT NULL,
"page_id" "uuid",
"config_id" "uuid",
"metric_id" "uuid",
"severity" "public"."severity_level" DEFAULT 'medium'::"public"."severity_level",
"title" character varying NOT NULL,
"message" "text" NOT NULL,
"details" "jsonb" DEFAULT '{}'::"jsonb",
"status" character varying DEFAULT 'open'::character varying,
"acknowledged_by" "uuid",
"acknowledged_at" timestamp with time zone,
"resolved_at" timestamp with time zone,
"resolution_note" "text",
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."alerts" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."api_keys" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"organization_id" "uuid" NOT NULL,
"name" character varying NOT NULL,
"key_hash" character varying NOT NULL,
"scopes" character varying[] DEFAULT ARRAY['read'::"text"],
"rate_limit_per_minute" integer DEFAULT 60,
"is_active" boolean DEFAULT true,
"last_used_at" timestamp with time zone,
"expires_at" timestamp with time zone,
"created_by" "uuid",
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."api_keys" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."audit_logs" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"organization_id" "uuid",
"user_id" "uuid",
"action" character varying NOT NULL,
"entity_type" character varying NOT NULL,
"entity_id" "uuid",
"changes" "jsonb",
"ip_address" character varying,
"user_agent" character varying,
"created_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."audit_logs" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."budget_violations" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"budget_id" "uuid" NOT NULL,
"scan_id" "uuid" NOT NULL,
"actual_value" numeric NOT NULL,
"threshold_value" numeric NOT NULL,
"percentage_over" numeric,
"created_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."budget_violations" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."competitor_websites" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"website_id" "uuid" NOT NULL,
"competitor_url" character varying NOT NULL,
"name" character varying NOT NULL,
"is_active" boolean DEFAULT true,
"scan_frequency" character varying DEFAULT 'daily'::character varying,
"metrics_to_track" character varying[] DEFAULT ARRAY['performance'::"text", 'seo'::"text", 'accessibility'::"text", 'best_practices'::"text"],
"last_scan_at" timestamp with time zone,
"metadata" "jsonb" DEFAULT '{}'::"jsonb",
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."competitor_websites" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."crawl_queue" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"website_id" "uuid" NOT NULL,
"url" character varying NOT NULL,
"priority" integer DEFAULT 1,
"status" character varying DEFAULT 'pending'::character varying,
"parent_url" character varying,
"discovery_depth" integer DEFAULT 0,
"attempts" integer DEFAULT 0,
"last_attempt_at" timestamp with time zone,
"next_attempt_at" timestamp with time zone,
"error_message" "text",
"metadata" "jsonb" DEFAULT '{}'::"jsonb",
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."crawl_queue" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."crawl_sessions" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"website_id" "uuid" NOT NULL,
"status" character varying DEFAULT 'running'::character varying,
"pages_discovered" integer DEFAULT 0,
"pages_processed" integer DEFAULT 0,
"start_url" character varying NOT NULL,
"max_depth" integer,
"started_at" timestamp with time zone DEFAULT "now"(),
"completed_at" timestamp with time zone,
"error_message" "text",
"metadata" "jsonb" DEFAULT '{}'::"jsonb",
"created_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."crawl_sessions" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."dashboard_widgets" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"dashboard_id" "uuid" NOT NULL,
"widget_type" character varying NOT NULL,
"name" character varying NOT NULL,
"config" "jsonb" NOT NULL,
"position" "jsonb" NOT NULL,
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."dashboard_widgets" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."dashboards" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"organization_id" "uuid" NOT NULL,
"name" character varying NOT NULL,
"description" "text",
"layout" "jsonb" DEFAULT '[]'::"jsonb",
"is_default" boolean DEFAULT false,
"created_by" "uuid",
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."dashboards" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."generated_reports" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"template_id" "uuid" NOT NULL,
"website_id" "uuid",
"generated_by" "uuid",
"report_data" "jsonb" NOT NULL,
"format" character varying DEFAULT 'pdf'::character varying,
"file_url" character varying,
"created_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."generated_reports" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."metric_definitions" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"key" character varying NOT NULL,
"name" character varying NOT NULL,
"description" "text" NOT NULL,
"category" "public"."metric_category" NOT NULL,
"unit" character varying,
"is_core_metric" boolean DEFAULT false,
"default_threshold" numeric,
"warning_threshold" numeric,
"critical_threshold" numeric,
"direction" character varying DEFAULT 'higher_is_better'::character varying NOT NULL,
"weight" numeric DEFAULT 1.0,
"documentation_url" "text",
"created_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."metric_definitions" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."metric_values" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"scan_id" "uuid" NOT NULL,
"metric_id" "uuid" NOT NULL,
"value" numeric NOT NULL,
"raw_value" character varying,
"unit" character varying,
"is_passing" boolean,
"created_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."metric_values" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."notification_deliveries" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"alert_id" "uuid" NOT NULL,
"channel" "public"."notification_channel" NOT NULL,
"recipient" character varying NOT NULL,
"content" "text" NOT NULL,
"status" character varying DEFAULT 'pending'::character varying,
"sent_at" timestamp with time zone,
"error_message" "text",
"retry_count" integer DEFAULT 0,
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."notification_deliveries" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."organizations" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"name" character varying NOT NULL,
"subscription_tier" character varying DEFAULT 'free'::character varying,
"subscription_status" character varying DEFAULT 'active'::character varying,
"settings" "jsonb" DEFAULT '{"retention_days": 90, "alert_email_digest": "daily", "default_scan_depth": 3, "enable_competitor_analysis": false}'::"jsonb",
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."organizations" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."pages" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"website_id" "uuid" NOT NULL,
"url" character varying NOT NULL,
"path" character varying NOT NULL,
"title" character varying,
"description" "text",
"content_hash" character varying,
"content_type" character varying,
"status_code" integer,
"is_active" boolean DEFAULT true,
"priority" integer DEFAULT 1,
"depth" integer DEFAULT 0,
"parent_page_id" "uuid",
"discovery_method" character varying DEFAULT 'crawl'::character varying,
"last_seen_at" timestamp with time zone,
"metadata" "jsonb" DEFAULT '{"word_count": 0, "is_indexable": true, "has_canonical": false, "inbound_links": 0, "outbound_links": 0}'::"jsonb",
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."pages" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."performance_budgets" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"website_id" "uuid" NOT NULL,
"name" character varying NOT NULL,
"description" "text",
"metric_id" "uuid",
"budget_type" character varying NOT NULL,
"threshold" numeric NOT NULL,
"applies_to" "jsonb" DEFAULT '{"paths": ["/*"], "resource_types": ["all"]}'::"jsonb",
"is_active" boolean DEFAULT true,
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."performance_budgets" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."scans" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"website_id" "uuid" NOT NULL,
"page_id" "uuid" NOT NULL,
"triggered_by" "uuid",
"scan_type" character varying DEFAULT 'full'::character varying NOT NULL,
"status" "public"."scan_status" DEFAULT 'pending'::"public"."scan_status",
"priority" integer DEFAULT 1,
"categories" "public"."metric_category"[] DEFAULT ARRAY['performance'::"public"."metric_category", 'seo'::"public"."metric_category", 'accessibility'::"public"."metric_category", 'best_practices'::"public"."metric_category"],
"device_type" character varying DEFAULT 'desktop'::character varying,
"user_agent" character varying,
"lighthouse_version" character varying,
"chrome_version" character varying,
"environment" "jsonb" DEFAULT '{}'::"jsonb",
"started_at" timestamp with time zone DEFAULT "now"(),
"completed_at" timestamp with time zone,
"duration_ms" integer,
"error_message" "text",
"retry_count" integer DEFAULT 0,
"metadata" "jsonb" DEFAULT '{}'::"jsonb",
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"(),
"scheduled_at" timestamp with time zone
);
ALTER TABLE "public"."scans" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."websites" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"organization_id" "uuid" NOT NULL,
"base_url" character varying NOT NULL,
"name" character varying NOT NULL,
"is_active" boolean DEFAULT true,
"crawl_settings" "jsonb" DEFAULT '{"max_depth": 3, "max_pages": 100, "crawl_timing": "off_peak", "crawl_frequency": "daily", "exclude_patterns": ["/admin/*", "/api/*", "*.pdf", "*.jpg", "*.png"], "include_patterns": ["/*"], "respect_robots_txt": true}'::"jsonb",
"scan_schedule" "jsonb" DEFAULT '{"days": ["monday", "tuesday", "wednesday", "thursday", "friday"], "frequency": "hourly", "time_windows": ["0-6", "20-23"]}'::"jsonb",
"performance_budgets" "jsonb" DEFAULT '{"max_requests": 100, "page_weight_kb": 1000, "time_to_interactive_ms": 3000, "first_contentful_paint_ms": 1000}'::"jsonb",
"notifications" "jsonb" DEFAULT '{"channels": ["email"], "thresholds": {"seo": 90, "performance": 90, "accessibility": 90, "best_practices": 90}}'::"jsonb",
"last_crawl_at" timestamp with time zone,
"last_scan_at" timestamp with time zone,
"metadata" "jsonb" DEFAULT '{}'::"jsonb",
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."websites" OWNER TO "postgres";
CREATE OR REPLACE VIEW "public"."performance_trends" WITH ("security_invoker"='on') AS
SELECT "w"."id" AS "website_id",
"w"."name" AS "website_name",
"p"."url" AS "page_url",
"m"."key" AS "metric_key",
"mv"."value" AS "metric_value",
"s"."created_at" AS "scan_date",
"avg"("mv"."value") OVER (PARTITION BY "w"."id", "p"."id", "m"."id" ORDER BY "s"."created_at" ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS "rolling_average"
FROM (((("public"."websites" "w"
JOIN "public"."pages" "p" ON (("p"."website_id" = "w"."id")))
JOIN "public"."scans" "s" ON (("s"."page_id" = "p"."id")))
JOIN "public"."metric_values" "mv" ON (("mv"."scan_id" = "s"."id")))
JOIN "public"."metric_definitions" "m" ON (("m"."id" = "mv"."metric_id")))
WHERE ("s"."created_at" >= ("now"() - '30 days'::interval));
ALTER TABLE "public"."performance_trends" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."rate_limits" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"key_type" character varying NOT NULL,
"key_value" character varying NOT NULL,
"window_start" timestamp with time zone NOT NULL,
"request_count" integer DEFAULT 1,
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."rate_limits" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."report_templates" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"organization_id" "uuid" NOT NULL,
"name" character varying NOT NULL,
"description" "text",
"template_type" character varying NOT NULL,
"content" "jsonb" NOT NULL,
"schedule" "jsonb",
"is_active" boolean DEFAULT true,
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."report_templates" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."resource_analysis" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"scan_id" "uuid" NOT NULL,
"resource_type" "public"."resource_type" NOT NULL,
"url" character varying NOT NULL,
"size_bytes" integer NOT NULL,
"transfer_size_bytes" integer,
"duration_ms" integer,
"is_third_party" boolean DEFAULT false,
"is_cached" boolean,
"compression_ratio" numeric,
"mime_type" character varying,
"protocol" character varying,
"priority" character varying,
"status_code" integer,
"metadata" "jsonb" DEFAULT '{}'::"jsonb",
"created_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."resource_analysis" OWNER TO "postgres";
CREATE OR REPLACE VIEW "public"."resource_usage_summary" WITH ("security_invoker"='on') AS
SELECT "w"."id" AS "website_id",
"w"."name" AS "website_name",
"ra"."resource_type",
"count"(*) AS "resource_count",
"avg"("ra"."size_bytes") AS "avg_size",
"sum"("ra"."size_bytes") AS "total_size",
"avg"("ra"."duration_ms") AS "avg_duration"
FROM (("public"."websites" "w"
JOIN "public"."scans" "s" ON (("s"."website_id" = "w"."id")))
JOIN "public"."resource_analysis" "ra" ON (("ra"."scan_id" = "s"."id")))
WHERE ("s"."created_at" >= ("now"() - '24:00:00'::interval))
GROUP BY "w"."id", "w"."name", "ra"."resource_type";
ALTER TABLE "public"."resource_usage_summary" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."scan_results" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"scan_id" "uuid" NOT NULL,
"category" "public"."metric_category" NOT NULL,
"score" numeric,
"raw_data" "jsonb",
"created_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."scan_results" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."url_patterns" (
"id" "uuid" DEFAULT "extensions"."uuid_generate_v4"() NOT NULL,
"website_id" "uuid" NOT NULL,
"pattern" character varying NOT NULL,
"pattern_type" character varying NOT NULL,
"description" "text",
"is_regex" boolean DEFAULT false,
"is_active" boolean DEFAULT true,
"priority" integer DEFAULT 1,
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."url_patterns" OWNER TO "postgres";
CREATE TABLE IF NOT EXISTS "public"."users" (
"id" "uuid" NOT NULL,
"email" character varying NOT NULL,
"name" character varying,
"organization_id" "uuid",
"role" character varying DEFAULT 'viewer'::character varying,
"is_active" boolean DEFAULT true,
"settings" "jsonb" DEFAULT '{"dashboard_layout": "default", "email_notifications": true, "notification_frequency": "instant"}'::"jsonb",
"created_at" timestamp with time zone DEFAULT "now"(),
"updated_at" timestamp with time zone DEFAULT "now"()
);
ALTER TABLE "public"."users" OWNER TO "postgres";
ALTER TABLE ONLY "public"."alert_configurations"
ADD CONSTRAINT "alert_configurations_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."alert_history"
ADD CONSTRAINT "alert_history_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."alerts"
ADD CONSTRAINT "alerts_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."api_keys"
ADD CONSTRAINT "api_keys_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."audit_logs"
ADD CONSTRAINT "audit_logs_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."budget_violations"
ADD CONSTRAINT "budget_violations_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."competitor_websites"
ADD CONSTRAINT "competitor_websites_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."competitor_websites"
ADD CONSTRAINT "competitor_websites_website_id_competitor_url_key" UNIQUE ("website_id", "competitor_url");
ALTER TABLE ONLY "public"."crawl_queue"
ADD CONSTRAINT "crawl_queue_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."crawl_sessions"
ADD CONSTRAINT "crawl_sessions_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."dashboard_widgets"
ADD CONSTRAINT "dashboard_widgets_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."dashboards"
ADD CONSTRAINT "dashboards_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."generated_reports"
ADD CONSTRAINT "generated_reports_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."metric_definitions"
ADD CONSTRAINT "metric_definitions_key_key" UNIQUE ("key");
ALTER TABLE ONLY "public"."metric_definitions"
ADD CONSTRAINT "metric_definitions_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."metric_values"
ADD CONSTRAINT "metric_values_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."notification_deliveries"
ADD CONSTRAINT "notification_deliveries_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."organizations"
ADD CONSTRAINT "organizations_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."pages"
ADD CONSTRAINT "pages_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."pages"
ADD CONSTRAINT "pages_website_id_url_key" UNIQUE ("website_id", "url");
ALTER TABLE ONLY "public"."performance_budgets"
ADD CONSTRAINT "performance_budgets_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."rate_limits"
ADD CONSTRAINT "rate_limits_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."report_templates"
ADD CONSTRAINT "report_templates_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."resource_analysis"
ADD CONSTRAINT "resource_analysis_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."scan_results"
ADD CONSTRAINT "scan_results_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."scans"
ADD CONSTRAINT "scans_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."url_patterns"
ADD CONSTRAINT "url_patterns_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."users"
ADD CONSTRAINT "users_email_key" UNIQUE ("email");
ALTER TABLE ONLY "public"."users"
ADD CONSTRAINT "users_pkey" PRIMARY KEY ("id");
ALTER TABLE ONLY "public"."websites"
ADD CONSTRAINT "websites_organization_id_base_url_key" UNIQUE ("organization_id", "base_url");
ALTER TABLE ONLY "public"."websites"
ADD CONSTRAINT "websites_pkey" PRIMARY KEY ("id");
CREATE INDEX "idx_alert_configurations_metric_id" ON "public"."alert_configurations" USING "btree" ("metric_id");
CREATE INDEX "idx_alert_configurations_website_id" ON "public"."alert_configurations" USING "btree" ("website_id");
CREATE INDEX "idx_alert_history_alert_id" ON "public"."alert_history" USING "btree" ("alert_id");
CREATE INDEX "idx_alerts_config_id" ON "public"."alerts" USING "btree" ("config_id");
CREATE INDEX "idx_alerts_metric_id" ON "public"."alerts" USING "btree" ("metric_id");
CREATE INDEX "idx_alerts_page_id" ON "public"."alerts" USING "btree" ("page_id");
CREATE INDEX "idx_alerts_website_id" ON "public"."alerts" USING "btree" ("website_id");
CREATE INDEX "idx_budget_violations_budget_id" ON "public"."budget_violations" USING "btree" ("budget_id");
CREATE INDEX "idx_budget_violations_scan_id" ON "public"."budget_violations" USING "btree" ("scan_id");
CREATE INDEX "idx_crawl_queue_website_id" ON "public"."crawl_queue" USING "btree" ("website_id");
CREATE INDEX "idx_crawl_sessions_website_id" ON "public"."crawl_sessions" USING "btree" ("website_id");
CREATE INDEX "idx_dashboard_widgets_dashboard_id" ON "public"."dashboard_widgets" USING "btree" ("dashboard_id");
CREATE INDEX "idx_generated_reports_template_id" ON "public"."generated_reports" USING "btree" ("template_id");
CREATE INDEX "idx_generated_reports_website_id" ON "public"."generated_reports" USING "btree" ("website_id");
CREATE INDEX "idx_metric_values_metric_id" ON "public"."metric_values" USING "btree" ("metric_id");
CREATE INDEX "idx_metric_values_scan_id" ON "public"."metric_values" USING "btree" ("scan_id");
CREATE INDEX "idx_notification_deliveries_alert_id" ON "public"."notification_deliveries" USING "btree" ("alert_id");
CREATE INDEX "idx_pages_parent_page_id" ON "public"."pages" USING "btree" ("parent_page_id");
CREATE INDEX "idx_performance_budgets_metric_id" ON "public"."performance_budgets" USING "btree" ("metric_id");
CREATE INDEX "idx_performance_budgets_website_id" ON "public"."performance_budgets" USING "btree" ("website_id");
CREATE INDEX "idx_resource_analysis_scan_id" ON "public"."resource_analysis" USING "btree" ("scan_id");
CREATE INDEX "idx_scan_results_scan_id" ON "public"."scan_results" USING "btree" ("scan_id");
CREATE INDEX "idx_scans_page_id" ON "public"."scans" USING "btree" ("page_id");
CREATE INDEX "idx_scans_website_id" ON "public"."scans" USING "btree" ("website_id");
CREATE INDEX "idx_url_patterns_website_id" ON "public"."url_patterns" USING "btree" ("website_id");
CREATE INDEX "idx_users_organization_id" ON "public"."users" USING "btree" ("organization_id");
CREATE OR REPLACE TRIGGER "alert_notification_trigger" AFTER INSERT ON "public"."alerts" FOR EACH ROW EXECUTE FUNCTION "public"."process_alert_notifications"();
CREATE OR REPLACE TRIGGER "scan_status_update" AFTER UPDATE OF "status" ON "public"."scans" FOR EACH ROW WHEN (("old"."status" IS DISTINCT FROM "new"."status")) EXECUTE FUNCTION "public"."update_scan_status"();
ALTER TABLE ONLY "public"."alert_configurations"
ADD CONSTRAINT "alert_configurations_metric_id_fkey" FOREIGN KEY ("metric_id") REFERENCES "public"."metric_definitions"("id");
ALTER TABLE ONLY "public"."alert_configurations"
ADD CONSTRAINT "alert_configurations_website_id_fkey" FOREIGN KEY ("website_id") REFERENCES "public"."websites"("id");
ALTER TABLE ONLY "public"."alert_history"
ADD CONSTRAINT "alert_history_alert_id_fkey" FOREIGN KEY ("alert_id") REFERENCES "public"."alerts"("id");
ALTER TABLE ONLY "public"."alerts"
ADD CONSTRAINT "alerts_config_id_fkey" FOREIGN KEY ("config_id") REFERENCES "public"."alert_configurations"("id");
ALTER TABLE ONLY "public"."alerts"
ADD CONSTRAINT "alerts_metric_id_fkey" FOREIGN KEY ("metric_id") REFERENCES "public"."metric_definitions"("id");
ALTER TABLE ONLY "public"."alerts"
ADD CONSTRAINT "alerts_page_id_fkey" FOREIGN KEY ("page_id") REFERENCES "public"."pages"("id");
ALTER TABLE ONLY "public"."alerts"
ADD CONSTRAINT "alerts_website_id_fkey" FOREIGN KEY ("website_id") REFERENCES "public"."websites"("id");
ALTER TABLE ONLY "public"."budget_violations"
ADD CONSTRAINT "budget_violations_budget_id_fkey" FOREIGN KEY ("budget_id") REFERENCES "public"."performance_budgets"("id");
ALTER TABLE ONLY "public"."budget_violations"
ADD CONSTRAINT "budget_violations_scan_id_fkey" FOREIGN KEY ("scan_id") REFERENCES "public"."scans"("id");
ALTER TABLE ONLY "public"."competitor_websites"
ADD CONSTRAINT "competitor_websites_website_id_fkey" FOREIGN KEY ("website_id") REFERENCES "public"."websites"("id");
ALTER TABLE ONLY "public"."crawl_queue"
ADD CONSTRAINT "crawl_queue_website_id_fkey" FOREIGN KEY ("website_id") REFERENCES "public"."websites"("id") ON DELETE CASCADE;
ALTER TABLE ONLY "public"."crawl_sessions"
ADD CONSTRAINT "crawl_sessions_website_id_fkey" FOREIGN KEY ("website_id") REFERENCES "public"."websites"("id") ON DELETE CASCADE;
ALTER TABLE ONLY "public"."dashboard_widgets"
ADD CONSTRAINT "dashboard_widgets_dashboard_id_fkey" FOREIGN KEY ("dashboard_id") REFERENCES "public"."dashboards"("id");
ALTER TABLE ONLY "public"."users"
ADD CONSTRAINT "fk_organization" FOREIGN KEY ("organization_id") REFERENCES "public"."organizations"("id") ON DELETE CASCADE;
ALTER TABLE ONLY "public"."generated_reports"
ADD CONSTRAINT "generated_reports_template_id_fkey" FOREIGN KEY ("template_id") REFERENCES "public"."report_templates"("id");
ALTER TABLE ONLY "public"."generated_reports"
ADD CONSTRAINT "generated_reports_website_id_fkey" FOREIGN KEY ("website_id") REFERENCES "public"."websites"("id");
ALTER TABLE ONLY "public"."metric_values"
ADD CONSTRAINT "metric_values_metric_id_fkey" FOREIGN KEY ("metric_id") REFERENCES "public"."metric_definitions"("id");
ALTER TABLE ONLY "public"."metric_values"
ADD CONSTRAINT "metric_values_scan_id_fkey" FOREIGN KEY ("scan_id") REFERENCES "public"."scans"("id");
ALTER TABLE ONLY "public"."notification_deliveries"
ADD CONSTRAINT "notification_deliveries_alert_id_fkey" FOREIGN KEY ("alert_id") REFERENCES "public"."alerts"("id");
ALTER TABLE ONLY "public"."pages"
ADD CONSTRAINT "pages_parent_page_id_fkey" FOREIGN KEY ("parent_page_id") REFERENCES "public"."pages"("id");
ALTER TABLE ONLY "public"."pages"
ADD CONSTRAINT "pages_website_id_fkey" FOREIGN KEY ("website_id") REFERENCES "public"."websites"("id") ON DELETE CASCADE;
ALTER TABLE ONLY "public"."performance_budgets"
ADD CONSTRAINT "performance_budgets_metric_id_fkey" FOREIGN KEY ("metric_id") REFERENCES "public"."metric_definitions"("id");
ALTER TABLE ONLY "public"."performance_budgets"
ADD CONSTRAINT "performance_budgets_website_id_fkey" FOREIGN KEY ("website_id") REFERENCES "public"."websites"("id");
ALTER TABLE ONLY "public"."resource_analysis"
ADD CONSTRAINT "resource_analysis_scan_id_fkey" FOREIGN KEY ("scan_id") REFERENCES "public"."scans"("id");
ALTER TABLE ONLY "public"."scan_results"
ADD CONSTRAINT "scan_results_scan_id_fkey" FOREIGN KEY ("scan_id") REFERENCES "public"."scans"("id");
ALTER TABLE ONLY "public"."scans"
ADD CONSTRAINT "scans_page_id_fkey" FOREIGN KEY ("page_id") REFERENCES "public"."pages"("id");
ALTER TABLE ONLY "public"."scans"
ADD CONSTRAINT "scans_website_id_fkey" FOREIGN KEY ("website_id") REFERENCES "public"."websites"("id") ON DELETE CASCADE;
ALTER TABLE ONLY "public"."url_patterns"
ADD CONSTRAINT "url_patterns_website_id_fkey" FOREIGN KEY ("website_id") REFERENCES "public"."websites"("id");
ALTER TABLE ONLY "public"."users"
ADD CONSTRAINT "users_id_fkey" FOREIGN KEY ("id") REFERENCES "auth"."users"("id");
ALTER TABLE ONLY "public"."users"
ADD CONSTRAINT "users_organization_id_fkey" FOREIGN KEY ("organization_id") REFERENCES "public"."organizations"("id");
CREATE POLICY "Allow organization insert for authenticated" ON "public"."organizations" FOR INSERT TO "authenticated" WITH CHECK (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."alert_configurations" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."alert_history" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."audit_logs" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."budget_violations" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."competitor_websites" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."crawl_queue" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."crawl_sessions" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."dashboard_widgets" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."generated_reports" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."metric_definitions" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."notification_deliveries" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."performance_budgets" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."rate_limits" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."report_templates" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."resource_analysis" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."scan_results" FOR SELECT USING (true);
CREATE POLICY "Allow read for authenticated users" ON "public"."url_patterns" FOR SELECT USING (true);
CREATE POLICY "Allow user insert for anon" ON "public"."users" FOR INSERT TO "anon" WITH CHECK (true);
CREATE POLICY "Allow user insert for authenticated" ON "public"."users" FOR INSERT TO "authenticated" WITH CHECK (true);
CREATE POLICY "Allow user insert for authenticator" ON "public"."users" FOR INSERT TO "authenticator" WITH CHECK (true);
CREATE POLICY "Allow user insert for dashboard_user" ON "public"."users" FOR INSERT TO "dashboard_user" WITH CHECK (true);
CREATE POLICY "Allow user update for anon" ON "public"."users" FOR UPDATE TO "anon" USING (("id" = ( SELECT "auth"."uid"() AS "uid")));
CREATE POLICY "Allow user update for authenticated" ON "public"."users" FOR UPDATE TO "authenticated" USING (("id" = ( SELECT "auth"."uid"() AS "uid")));
CREATE POLICY "Allow user update for authenticator" ON "public"."users" FOR UPDATE TO "authenticator" USING (("id" = ( SELECT "auth"."uid"() AS "uid")));
CREATE POLICY "Allow user update for dashboard_user" ON "public"."users" FOR UPDATE TO "dashboard_user" USING (("id" = ( SELECT "auth"."uid"() AS "uid")));
CREATE POLICY "Users can delete pages of their organization" ON "public"."pages" FOR DELETE USING (("website_id" IN ( SELECT "websites"."id"
FROM "public"."websites"
WHERE ("websites"."organization_id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))))));
CREATE POLICY "Users can delete scans of their organization" ON "public"."scans" FOR DELETE USING (("website_id" IN ( SELECT "w"."id"
FROM "public"."websites" "w"
WHERE ("w"."organization_id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))))));
CREATE POLICY "Users can delete websites of their organization" ON "public"."websites" FOR DELETE USING (("organization_id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))));
CREATE POLICY "Users can insert pages for their organization" ON "public"."pages" FOR INSERT WITH CHECK (("website_id" IN ( SELECT "websites"."id"
FROM "public"."websites"
WHERE ("websites"."organization_id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))))));
CREATE POLICY "Users can insert scans for their organization" ON "public"."scans" FOR INSERT WITH CHECK (("website_id" IN ( SELECT "w"."id"
FROM "public"."websites" "w"
WHERE ("w"."organization_id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))))));
CREATE POLICY "Users can insert websites for their organization" ON "public"."websites" FOR INSERT WITH CHECK (("organization_id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))));
CREATE POLICY "Users can select their own data" ON "public"."users" FOR SELECT USING (("auth"."uid"() = "id"));
CREATE POLICY "Users can update pages of their organization" ON "public"."pages" FOR UPDATE USING (("website_id" IN ( SELECT "websites"."id"
FROM "public"."websites"
WHERE ("websites"."organization_id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))))));
CREATE POLICY "Users can update scans of their organization" ON "public"."scans" FOR UPDATE USING (("website_id" IN ( SELECT "w"."id"
FROM "public"."websites" "w"
WHERE ("w"."organization_id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))))));
CREATE POLICY "Users can update websites of their organization" ON "public"."websites" FOR UPDATE USING (("organization_id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))));
CREATE POLICY "Users can view alerts they are allowed to" ON "public"."alerts" FOR SELECT USING (("website_id" IN ( SELECT "w"."id"
FROM "public"."websites" "w"
WHERE ("w"."organization_id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))))));
CREATE POLICY "Users can view dashboards of their organization" ON "public"."dashboards" FOR SELECT USING (("organization_id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))));
CREATE POLICY "Users can view metric_values of their organization" ON "public"."metric_values" FOR SELECT USING (("scan_id" IN ( SELECT "s"."id"
FROM ("public"."scans" "s"
JOIN "public"."websites" "w" ON (("w"."id" = "s"."website_id")))
WHERE ("w"."organization_id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))))));
CREATE POLICY "Users can view pages they are allowed to" ON "public"."pages" FOR SELECT USING (("website_id" IN ( SELECT "w"."id"
FROM "public"."websites" "w"
WHERE ("w"."organization_id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))))));
CREATE POLICY "Users can view scans they are allowed to" ON "public"."scans" FOR SELECT USING (("website_id" IN ( SELECT "w"."id"
FROM "public"."websites" "w"
WHERE ("w"."organization_id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))))));
CREATE POLICY "Users can view their org's API keys" ON "public"."api_keys" FOR SELECT USING (("organization_id" IN ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))));
CREATE POLICY "Users can view their org's websites" ON "public"."websites" FOR SELECT USING (("organization_id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))));
CREATE POLICY "Users can view their organization" ON "public"."organizations" FOR SELECT USING (("id" = ( SELECT "users"."organization_id"
FROM "public"."users"
WHERE ("users"."id" = ( SELECT "auth"."uid"() AS "uid")))));
CREATE POLICY "Users can view their own profile" ON "public"."users" FOR SELECT USING (("id" = ( SELECT "auth"."uid"() AS "uid")));
ALTER TABLE "public"."alert_configurations" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."alert_history" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."alerts" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."api_keys" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."audit_logs" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."budget_violations" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."competitor_websites" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."crawl_queue" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."crawl_sessions" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."dashboard_widgets" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."dashboards" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."generated_reports" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."metric_definitions" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."metric_values" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."notification_deliveries" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."organizations" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."pages" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."performance_budgets" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."rate_limits" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."report_templates" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."resource_analysis" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."scan_results" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."scans" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."url_patterns" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."users" ENABLE ROW LEVEL SECURITY;
ALTER TABLE "public"."websites" ENABLE ROW LEVEL SECURITY;
ALTER PUBLICATION "supabase_realtime" OWNER TO "postgres";
GRANT USAGE ON SCHEMA "public" TO "postgres";
GRANT USAGE ON SCHEMA "public" TO "anon";
GRANT USAGE ON SCHEMA "public" TO "authenticated";
GRANT USAGE ON SCHEMA "public" TO "service_role";
GRANT ALL ON FUNCTION "public"."apply_data_retention"() TO "anon";
GRANT ALL ON FUNCTION "public"."apply_data_retention"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."apply_data_retention"() TO "service_role";
GRANT ALL ON FUNCTION "public"."calculate_competitor_comparison"("website_id" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."calculate_competitor_comparison"("website_id" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."calculate_competitor_comparison"("website_id" "uuid") TO "service_role";
GRANT ALL ON FUNCTION "public"."calculate_competitor_comparison"("website_id_param" "uuid", "competitor_id_param" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."calculate_competitor_comparison"("website_id_param" "uuid", "competitor_id_param" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."calculate_competitor_comparison"("website_id_param" "uuid", "competitor_id_param" "uuid") TO "service_role";
GRANT ALL ON FUNCTION "public"."calculate_health_score"("website_id_param" "uuid") TO "anon";
GRANT ALL ON FUNCTION "public"."calculate_health_score"("website_id_param" "uuid") TO "authenticated";
GRANT ALL ON FUNCTION "public"."calculate_health_score"("website_id_param" "uuid") TO "service_role";
GRANT ALL ON FUNCTION "public"."email_exists"("email_to_check" "text") TO "anon";
GRANT ALL ON FUNCTION "public"."email_exists"("email_to_check" "text") TO "authenticated";
GRANT ALL ON FUNCTION "public"."email_exists"("email_to_check" "text") TO "service_role";
GRANT ALL ON FUNCTION "public"."generate_performance_report"("website_id" "uuid", "days" integer) TO "anon";
GRANT ALL ON FUNCTION "public"."generate_performance_report"("website_id" "uuid", "days" integer) TO "authenticated";
GRANT ALL ON FUNCTION "public"."generate_performance_report"("website_id" "uuid", "days" integer) TO "service_role";
GRANT ALL ON FUNCTION "public"."generate_performance_report"("website_id_param" "uuid", "start_date" timestamp with time zone, "end_date" timestamp with time zone) TO "anon";
GRANT ALL ON FUNCTION "public"."generate_performance_report"("website_id_param" "uuid", "start_date" timestamp with time zone, "end_date" timestamp with time zone) TO "authenticated";
GRANT ALL ON FUNCTION "public"."generate_performance_report"("website_id_param" "uuid", "start_date" timestamp with time zone, "end_date" timestamp with time zone) TO "service_role";
GRANT ALL ON FUNCTION "public"."handle_new_user"() TO "anon";
GRANT ALL ON FUNCTION "public"."handle_new_user"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."handle_new_user"() TO "service_role";
GRANT ALL ON FUNCTION "public"."perform_maintenance"() TO "anon";
GRANT ALL ON FUNCTION "public"."perform_maintenance"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."perform_maintenance"() TO "service_role";
GRANT ALL ON FUNCTION "public"."process_alert_notifications"() TO "anon";
GRANT ALL ON FUNCTION "public"."process_alert_notifications"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."process_alert_notifications"() TO "service_role";
GRANT ALL ON FUNCTION "public"."update_scan_status"() TO "anon";
GRANT ALL ON FUNCTION "public"."update_scan_status"() TO "authenticated";
GRANT ALL ON FUNCTION "public"."update_scan_status"() TO "service_role";
GRANT ALL ON TABLE "public"."alert_configurations" TO "anon";
GRANT ALL ON TABLE "public"."alert_configurations" TO "authenticated";
GRANT ALL ON TABLE "public"."alert_configurations" TO "service_role";
GRANT ALL ON TABLE "public"."alert_history" TO "anon";
GRANT ALL ON TABLE "public"."alert_history" TO "authenticated";
GRANT ALL ON TABLE "public"."alert_history" TO "service_role";
GRANT ALL ON TABLE "public"."alerts" TO "anon";
GRANT ALL ON TABLE "public"."alerts" TO "authenticated";
GRANT ALL ON TABLE "public"."alerts" TO "service_role";
GRANT ALL ON TABLE "public"."api_keys" TO "anon";
GRANT ALL ON TABLE "public"."api_keys" TO "authenticated";
GRANT ALL ON TABLE "public"."api_keys" TO "service_role";
GRANT ALL ON TABLE "public"."audit_logs" TO "anon";
GRANT ALL ON TABLE "public"."audit_logs" TO "authenticated";
GRANT ALL ON TABLE "public"."audit_logs" TO "service_role";
GRANT ALL ON TABLE "public"."budget_violations" TO "anon";
GRANT ALL ON TABLE "public"."budget_violations" TO "authenticated";
GRANT ALL ON TABLE "public"."budget_violations" TO "service_role";
GRANT ALL ON TABLE "public"."competitor_websites" TO "anon";
GRANT ALL ON TABLE "public"."competitor_websites" TO "authenticated";
GRANT ALL ON TABLE "public"."competitor_websites" TO "service_role";
GRANT ALL ON TABLE "public"."crawl_queue" TO "anon";
GRANT ALL ON TABLE "public"."crawl_queue" TO "authenticated";
GRANT ALL ON TABLE "public"."crawl_queue" TO "service_role";
GRANT ALL ON TABLE "public"."crawl_sessions" TO "anon";
GRANT ALL ON TABLE "public"."crawl_sessions" TO "authenticated";
GRANT ALL ON TABLE "public"."crawl_sessions" TO "service_role";
GRANT ALL ON TABLE "public"."dashboard_widgets" TO "anon";
GRANT ALL ON TABLE "public"."dashboard_widgets" TO "authenticated";
GRANT ALL ON TABLE "public"."dashboard_widgets" TO "service_role";
GRANT ALL ON TABLE "public"."dashboards" TO "anon";
GRANT ALL ON TABLE "public"."dashboards" TO "authenticated";
GRANT ALL ON TABLE "public"."dashboards" TO "service_role";
GRANT ALL ON TABLE "public"."generated_reports" TO "anon";
GRANT ALL ON TABLE "public"."generated_reports" TO "authenticated";
GRANT ALL ON TABLE "public"."generated_reports" TO "service_role";
GRANT ALL ON TABLE "public"."metric_definitions" TO "anon";
GRANT ALL ON TABLE "public"."metric_definitions" TO "authenticated";
GRANT ALL ON TABLE "public"."metric_definitions" TO "service_role";
GRANT ALL ON TABLE "public"."metric_values" TO "anon";
GRANT ALL ON TABLE "public"."metric_values" TO "authenticated";
GRANT ALL ON TABLE "public"."metric_values" TO "service_role";
GRANT ALL ON TABLE "public"."notification_deliveries" TO "anon";
GRANT ALL ON TABLE "public"."notification_deliveries" TO "authenticated";
GRANT ALL ON TABLE "public"."notification_deliveries" TO "service_role";
GRANT ALL ON TABLE "public"."organizations" TO "anon";
GRANT ALL ON TABLE "public"."organizations" TO "authenticated";
GRANT ALL ON TABLE "public"."organizations" TO "service_role";
GRANT ALL ON TABLE "public"."pages" TO "anon";
GRANT ALL ON TABLE "public"."pages" TO "authenticated";
GRANT ALL ON TABLE "public"."pages" TO "service_role";
GRANT ALL ON TABLE "public"."performance_budgets" TO "anon";
GRANT ALL ON TABLE "public"."performance_budgets" TO "authenticated";
GRANT ALL ON TABLE "public"."performance_budgets" TO "service_role";
GRANT ALL ON TABLE "public"."scans" TO "anon";
GRANT ALL ON TABLE "public"."scans" TO "authenticated";
GRANT ALL ON TABLE "public"."scans" TO "service_role";
GRANT ALL ON TABLE "public"."websites" TO "anon";
GRANT ALL ON TABLE "public"."websites" TO "authenticated";
GRANT ALL ON TABLE "public"."websites" TO "service_role";
GRANT ALL ON TABLE "public"."performance_trends" TO "anon";
GRANT ALL ON TABLE "public"."performance_trends" TO "authenticated";
GRANT ALL ON TABLE "public"."performance_trends" TO "service_role";
GRANT ALL ON TABLE "public"."rate_limits" TO "anon";
GRANT ALL ON TABLE "public"."rate_limits" TO "authenticated";
GRANT ALL ON TABLE "public"."rate_limits" TO "service_role";
GRANT ALL ON TABLE "public"."report_templates" TO "anon";
GRANT ALL ON TABLE "public"."report_templates" TO "authenticated";
GRANT ALL ON TABLE "public"."report_templates" TO "service_role";
GRANT ALL ON TABLE "public"."resource_analysis" TO "anon";
GRANT ALL ON TABLE "public"."resource_analysis" TO "authenticated";
GRANT ALL ON TABLE "public"."resource_analysis" TO "service_role";
GRANT ALL ON TABLE "public"."resource_usage_summary" TO "anon";
GRANT ALL ON TABLE "public"."resource_usage_summary" TO "authenticated";
GRANT ALL ON TABLE "public"."resource_usage_summary" TO "service_role";
GRANT ALL ON TABLE "public"."scan_results" TO "anon";
GRANT ALL ON TABLE "public"."scan_results" TO "authenticated";
GRANT ALL ON TABLE "public"."scan_results" TO "service_role";
GRANT ALL ON TABLE "public"."url_patterns" TO "anon";
GRANT ALL ON TABLE "public"."url_patterns" TO "authenticated";
GRANT ALL ON TABLE "public"."url_patterns" TO "service_role";
GRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLE "public"."users" TO "anon";
GRANT ALL ON TABLE "public"."users" TO "authenticated";
GRANT ALL ON TABLE "public"."users" TO "service_role";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "postgres";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "anon";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "authenticated";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "service_role";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "postgres";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "anon";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "authenticated";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "service_role";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "postgres";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "anon";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "authenticated";
ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "service_role";
RESET ALL;