CREATE TABLE IF NOT EXISTS "approvals" ( "id" serial PRIMARY KEY NOT NULL, "content_id" integer NOT NULL, "outlet" text NOT NULL, "approved_by" text NOT NULL, "approved_at" timestamp with time zone DEFAULT now() NOT NULL, "notes" text ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "audit" ( "id" serial PRIMARY KEY NOT NULL, "ts" timestamp with time zone DEFAULT now() NOT NULL, "actor" text NOT NULL, "action" text NOT NULL, "subject_type" text NOT NULL, "subject_id" text NOT NULL, "correlation_id" text NOT NULL, "payload_jsonb" jsonb ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "content" ( "id" serial PRIMARY KEY NOT NULL, "vault_path" text NOT NULL, "slug" text NOT NULL, "title" text NOT NULL, "body_sanitized" text NOT NULL, "frontmatter_jsonb" jsonb NOT NULL, "content_hash" text NOT NULL, "version" integer DEFAULT 1 NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL, CONSTRAINT "content_vault_path_unique" UNIQUE("vault_path") ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "linkedin_tokens" ( "id" serial PRIMARY KEY NOT NULL, "subject_type" text NOT NULL, "subject_urn" text NOT NULL, "access_token_ct" text NOT NULL, "refresh_token_ct" text, "access_expires_at" timestamp with time zone NOT NULL, "refresh_expires_at" timestamp with time zone, "scopes" text NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "metrics" ( "id" serial PRIMARY KEY NOT NULL, "publication_id" integer NOT NULL, "collected_at" timestamp with time zone DEFAULT now() NOT NULL, "impressions" integer DEFAULT 0 NOT NULL, "reactions" integer DEFAULT 0 NOT NULL, "comments" integer DEFAULT 0 NOT NULL, "shares" integer DEFAULT 0 NOT NULL, "clicks" integer DEFAULT 0 NOT NULL, "raw_jsonb" jsonb ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "outlet_feature_flags" ( "outlet" text PRIMARY KEY NOT NULL, "enabled" boolean DEFAULT true NOT NULL, "reason" text, "updated_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_by" text NOT NULL ); --> statement-breakpoint CREATE TABLE IF NOT EXISTS "publications" ( "id" serial PRIMARY KEY NOT NULL, "content_id" integer NOT NULL, "outlet" text NOT NULL, "status" text NOT NULL, "scheduled_at" timestamp with time zone, "published_at" timestamp with time zone, "external_id" text, "external_url" text, "idempotency_key" text NOT NULL, "error" text, "metadata_jsonb" jsonb ); --> statement-breakpoint DO $$ BEGIN ALTER TABLE "approvals" ADD CONSTRAINT "approvals_content_id_content_id_fk" FOREIGN KEY ("content_id") REFERENCES "public"."content"("id") ON DELETE no action ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "metrics" ADD CONSTRAINT "metrics_publication_id_publications_id_fk" FOREIGN KEY ("publication_id") REFERENCES "public"."publications"("id") ON DELETE no action ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint DO $$ BEGIN ALTER TABLE "publications" ADD CONSTRAINT "publications_content_id_content_id_fk" FOREIGN KEY ("content_id") REFERENCES "public"."content"("id") ON DELETE no action ON UPDATE no action; EXCEPTION WHEN duplicate_object THEN null; END $$; --> statement-breakpoint CREATE INDEX IF NOT EXISTS "audit_ts_idx" ON "audit" USING btree ("ts");--> statement-breakpoint CREATE INDEX IF NOT EXISTS "audit_correlation_idx" ON "audit" USING btree ("correlation_id");--> statement-breakpoint CREATE INDEX IF NOT EXISTS "content_slug_idx" ON "content" USING btree ("slug");--> statement-breakpoint CREATE UNIQUE INDEX IF NOT EXISTS "linkedin_tokens_subject_idx" ON "linkedin_tokens" USING btree ("subject_urn");--> statement-breakpoint CREATE UNIQUE INDEX IF NOT EXISTS "publications_idempotency_key_idx" ON "publications" USING btree ("idempotency_key");--> statement-breakpoint CREATE INDEX IF NOT EXISTS "publications_content_outlet_idx" ON "publications" USING btree ("content_id","outlet");