CREATE TABLE "chat_channel_members" ( "workspace_id" uuid NOT NULL, "channel_id" uuid NOT NULL, "user_id" uuid NOT NULL, "joined_at" timestamp with time zone DEFAULT now() NOT NULL, CONSTRAINT "chat_channel_members_workspace_id_channel_id_user_id_pk" PRIMARY KEY("workspace_id","channel_id","user_id") ); --> statement-breakpoint CREATE TABLE "chat_channels" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "workspace_id" uuid NOT NULL, "kind" varchar(16) NOT NULL, "name" varchar(200), "owner_user_id" uuid NOT NULL, "direct_key" text, "next_sequence" bigint DEFAULT 1 NOT NULL, "archived_at" timestamp with time zone, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL, CONSTRAINT "chat_channels_workspace_id_id_unique" UNIQUE("workspace_id","id"), CONSTRAINT "chat_channels_kind_check" CHECK ("chat_channels"."kind" in ('public', 'private', 'direct')), CONSTRAINT "chat_channels_direct_key_check" CHECK (("chat_channels"."kind" = 'direct' and "chat_channels"."direct_key" is not null and "chat_channels"."name" is null) or ("chat_channels"."kind" <> 'direct' and "chat_channels"."direct_key" is null)), CONSTRAINT "chat_channels_next_sequence_check" CHECK ("chat_channels"."next_sequence" > 0) ); --> statement-breakpoint CREATE TABLE "chat_message_mentions" ( "workspace_id" uuid NOT NULL, "message_id" uuid NOT NULL, "user_id" uuid NOT NULL, CONSTRAINT "chat_message_mentions_workspace_id_message_id_user_id_pk" PRIMARY KEY("workspace_id","message_id","user_id") ); --> statement-breakpoint CREATE TABLE "chat_messages" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "workspace_id" uuid NOT NULL, "channel_id" uuid NOT NULL, "sequence" bigint NOT NULL, "parent_message_id" uuid, "author_type" varchar(16) NOT NULL, "author_user_id" uuid, "author_agent_id" uuid, "body" text NOT NULL, "status" varchar(16) DEFAULT 'sent' NOT NULL, "client_idempotency_key" varchar(200) NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "edited_at" timestamp with time zone, "deleted_at" timestamp with time zone, CONSTRAINT "chat_messages_workspace_id_id_unique" UNIQUE("workspace_id","id"), CONSTRAINT "chat_messages_workspace_channel_id_unique" UNIQUE("workspace_id","channel_id","id"), CONSTRAINT "chat_messages_workspace_channel_sequence_unique" UNIQUE("workspace_id","channel_id","sequence"), CONSTRAINT "chat_messages_workspace_channel_client_key_unique" UNIQUE("workspace_id","channel_id","client_idempotency_key"), CONSTRAINT "chat_messages_author_check" CHECK (("chat_messages"."author_type" = 'human' and "chat_messages"."author_user_id" is not null and "chat_messages"."author_agent_id" is null) or ("chat_messages"."author_type" = 'agent' and "chat_messages"."author_user_id" is null and "chat_messages"."author_agent_id" is not null) or ("chat_messages"."author_type" = 'system' and "chat_messages"."author_user_id" is null and "chat_messages"."author_agent_id" is null)), CONSTRAINT "chat_messages_status_check" CHECK ("chat_messages"."status" in ('sent', 'edited', 'deleted')), CONSTRAINT "chat_messages_sequence_check" CHECK ("chat_messages"."sequence" >= 0) ); --> statement-breakpoint CREATE TABLE "chat_outbox" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL, "workspace_id" uuid NOT NULL, "message_id" uuid NOT NULL, "event_version" integer DEFAULT 1 NOT NULL, "event_type" varchar(100) NOT NULL, "dedupe_key" varchar(250) NOT NULL, "payload" jsonb NOT NULL, "created_at" timestamp with time zone DEFAULT now() NOT NULL, "published_at" timestamp with time zone, "attempts" integer DEFAULT 0 NOT NULL, "last_error" text, CONSTRAINT "chat_outbox_workspace_id_dedupe_key_unique" UNIQUE("workspace_id","dedupe_key"), CONSTRAINT "chat_outbox_event_version_check" CHECK ("chat_outbox"."event_version" > 0), CONSTRAINT "chat_outbox_attempts_check" CHECK ("chat_outbox"."attempts" >= 0) ); --> statement-breakpoint CREATE TABLE "chat_read_cursors" ( "workspace_id" uuid NOT NULL, "channel_id" uuid NOT NULL, "user_id" uuid NOT NULL, "sequence" bigint DEFAULT 0 NOT NULL, "updated_at" timestamp with time zone DEFAULT now() NOT NULL, CONSTRAINT "chat_read_cursors_workspace_id_channel_id_user_id_pk" PRIMARY KEY("workspace_id","channel_id","user_id"), CONSTRAINT "chat_read_cursors_sequence_check" CHECK ("chat_read_cursors"."sequence" >= 0) ); --> statement-breakpoint ALTER TABLE "chat_channel_members" ADD CONSTRAINT "chat_channel_members_workspace_id_workspaces_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_channel_members" ADD CONSTRAINT "chat_channel_members_channel_fk" FOREIGN KEY ("workspace_id","channel_id") REFERENCES "public"."chat_channels"("workspace_id","id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_channel_members" ADD CONSTRAINT "chat_channel_members_workspace_member_fk" FOREIGN KEY ("workspace_id","user_id") REFERENCES "public"."workspace_members"("workspace_id","user_id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_channels" ADD CONSTRAINT "chat_channels_workspace_id_workspaces_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_channels" ADD CONSTRAINT "chat_channels_owner_member_fk" FOREIGN KEY ("workspace_id","owner_user_id") REFERENCES "public"."workspace_members"("workspace_id","user_id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_message_mentions" ADD CONSTRAINT "chat_message_mentions_workspace_id_workspaces_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_message_mentions" ADD CONSTRAINT "chat_message_mentions_message_fk" FOREIGN KEY ("workspace_id","message_id") REFERENCES "public"."chat_messages"("workspace_id","id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_message_mentions" ADD CONSTRAINT "chat_message_mentions_workspace_member_fk" FOREIGN KEY ("workspace_id","user_id") REFERENCES "public"."workspace_members"("workspace_id","user_id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_messages" ADD CONSTRAINT "chat_messages_workspace_id_workspaces_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_messages" ADD CONSTRAINT "chat_messages_channel_fk" FOREIGN KEY ("workspace_id","channel_id") REFERENCES "public"."chat_channels"("workspace_id","id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_messages" ADD CONSTRAINT "chat_messages_parent_fk" FOREIGN KEY ("workspace_id","channel_id","parent_message_id") REFERENCES "public"."chat_messages"("workspace_id","channel_id","id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_messages" ADD CONSTRAINT "chat_messages_human_author_member_fk" FOREIGN KEY ("workspace_id","author_user_id") REFERENCES "public"."workspace_members"("workspace_id","user_id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_outbox" ADD CONSTRAINT "chat_outbox_workspace_id_workspaces_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_outbox" ADD CONSTRAINT "chat_outbox_message_fk" FOREIGN KEY ("workspace_id","message_id") REFERENCES "public"."chat_messages"("workspace_id","id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_read_cursors" ADD CONSTRAINT "chat_read_cursors_workspace_id_workspaces_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspaces"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_read_cursors" ADD CONSTRAINT "chat_read_cursors_channel_fk" FOREIGN KEY ("workspace_id","channel_id") REFERENCES "public"."chat_channels"("workspace_id","id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint ALTER TABLE "chat_read_cursors" ADD CONSTRAINT "chat_read_cursors_workspace_member_fk" FOREIGN KEY ("workspace_id","user_id") REFERENCES "public"."workspace_members"("workspace_id","user_id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint CREATE INDEX "chat_channel_members_workspace_id_idx" ON "chat_channel_members" USING btree ("workspace_id");--> statement-breakpoint CREATE INDEX "chat_channel_members_workspace_id_user_id_idx" ON "chat_channel_members" USING btree ("workspace_id","user_id");--> statement-breakpoint CREATE INDEX "chat_channels_workspace_id_idx" ON "chat_channels" USING btree ("workspace_id");--> statement-breakpoint CREATE UNIQUE INDEX "chat_channels_workspace_id_direct_key_unique" ON "chat_channels" USING btree ("workspace_id","direct_key") WHERE "chat_channels"."direct_key" is not null;--> statement-breakpoint CREATE INDEX "chat_message_mentions_workspace_id_idx" ON "chat_message_mentions" USING btree ("workspace_id");--> statement-breakpoint CREATE INDEX "chat_messages_workspace_id_idx" ON "chat_messages" USING btree ("workspace_id");--> statement-breakpoint CREATE INDEX "chat_outbox_workspace_id_idx" ON "chat_outbox" USING btree ("workspace_id");--> statement-breakpoint CREATE INDEX "chat_outbox_unpublished_idx" ON "chat_outbox" USING btree ("created_at") WHERE "chat_outbox"."published_at" is null;--> statement-breakpoint CREATE INDEX "chat_read_cursors_workspace_id_idx" ON "chat_read_cursors" USING btree ("workspace_id");