CREATE TYPE "public"."grant_status" AS ENUM('active', 'revoked', 'expired');--> statement-breakpoint CREATE TYPE "public"."peer_state" AS ENUM('pending', 'active', 'suspended', 'revoked');--> statement-breakpoint CREATE TABLE "admin_tokens" ( "id" text PRIMARY KEY NOT NULL, "user_id" text NOT NULL, "token_hash" text NOT NULL, "label" text NOT NULL, "scope" text DEFAULT 'admin' NOT NULL, "expires_at" timestamp with time zone, "last_used_at" timestamp with time zone, "created_at" timestamp with time zone DEFAULT now() NOT NULL ); --> statement-breakpoint CREATE TABLE "federation_audit_log" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "request_id" text NOT NULL, "peer_id" uuid, "subject_user_id" text, "grant_id" uuid, "verb" text NOT NULL, "resource" text NOT NULL, "status_code" integer NOT NULL, "result_count" integer, "denied_reason" text, "latency_ms" integer, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "query_hash" text, "outcome" text, "bytes_out" integer ); --> statement-breakpoint CREATE TABLE "federation_grants" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "subject_user_id" text NOT NULL, "peer_id" uuid NOT NULL, "scope" jsonb NOT NULL, "status" "grant_status" DEFAULT 'active' NOT NULL, "expires_at" timestamp with time zone, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "revoked_at" timestamp with time zone, "revoked_reason" text ); --> statement-breakpoint CREATE TABLE "federation_peers" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "common_name" text NOT NULL, "display_name" text NOT NULL, "cert_pem" text NOT NULL, "cert_serial" text NOT NULL, "cert_not_after" timestamp with time zone NOT NULL, "client_key_pem" text, "state" "peer_state" DEFAULT 'pending' NOT NULL, "endpoint_url" text, "last_seen_at" timestamp with time zone, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "revoked_at" timestamp with time zone, CONSTRAINT "federation_peers_common_name_unique" UNIQUE("common_name"), CONSTRAINT "federation_peers_cert_serial_unique" UNIQUE("cert_serial") ); --> statement-breakpoint ALTER TABLE "admin_tokens" ADD CONSTRAINT "admin_tokens_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "federation_audit_log" ADD CONSTRAINT "federation_audit_log_peer_id_federation_peers_id_fk" FOREIGN KEY ("peer_id") REFERENCES "public"."federation_peers"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint ALTER TABLE "federation_audit_log" ADD CONSTRAINT "federation_audit_log_subject_user_id_users_id_fk" FOREIGN KEY ("subject_user_id") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint ALTER TABLE "federation_audit_log" ADD CONSTRAINT "federation_audit_log_grant_id_federation_grants_id_fk" FOREIGN KEY ("grant_id") REFERENCES "public"."federation_grants"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint ALTER TABLE "federation_grants" ADD CONSTRAINT "federation_grants_subject_user_id_users_id_fk" FOREIGN KEY ("subject_user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "federation_grants" ADD CONSTRAINT "federation_grants_peer_id_federation_peers_id_fk" FOREIGN KEY ("peer_id") REFERENCES "public"."federation_peers"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint CREATE INDEX "admin_tokens_user_id_idx" ON "admin_tokens" USING btree ("user_id");--> statement-breakpoint CREATE UNIQUE INDEX "admin_tokens_hash_idx" ON "admin_tokens" USING btree ("token_hash");--> statement-breakpoint CREATE INDEX "federation_audit_log_peer_created_at_idx" ON "federation_audit_log" USING btree ("peer_id","created_at" DESC NULLS LAST);--> statement-breakpoint CREATE INDEX "federation_audit_log_subject_created_at_idx" ON "federation_audit_log" USING btree ("subject_user_id","created_at" DESC NULLS LAST);--> statement-breakpoint CREATE INDEX "federation_audit_log_created_at_idx" ON "federation_audit_log" USING btree ("created_at" DESC NULLS LAST);--> statement-breakpoint CREATE INDEX "federation_grants_subject_status_idx" ON "federation_grants" USING btree ("subject_user_id","status");--> statement-breakpoint CREATE INDEX "federation_grants_peer_status_idx" ON "federation_grants" USING btree ("peer_id","status");--> statement-breakpoint CREATE INDEX "federation_peers_cert_serial_idx" ON "federation_peers" USING btree ("cert_serial");--> statement-breakpoint CREATE INDEX "federation_peers_state_idx" ON "federation_peers" USING btree ("state");