CREATE TYPE "UserAccountKind" AS ENUM ('LEGACY_DEFAULT', 'GUEST', 'REGISTERED'); CREATE TYPE "UserAccountStatus" AS ENUM ('ACTIVE', 'LOCKED', 'DELETED'); ALTER TABLE "users" ADD COLUMN "account_kind" "UserAccountKind", ADD COLUMN "account_status" "UserAccountStatus", ADD COLUMN "library_namespace" UUID; UPDATE "users" SET "account_kind" = 'LEGACY_DEFAULT'::"UserAccountKind", "account_status" = 'ACTIVE'::"UserAccountStatus", "library_namespace" = COALESCE("library_namespace", gen_random_uuid()) WHERE "account_kind" IS NULL OR "account_status" IS NULL OR "library_namespace" IS NULL; UPDATE "users" SET "account_kind" = 'LEGACY_DEFAULT'::"UserAccountKind", "account_status" = 'ACTIVE'::"UserAccountStatus" WHERE "slug" = 'default-owner'; ALTER TABLE "users" ALTER COLUMN "account_kind" SET NOT NULL, ALTER COLUMN "account_kind" SET DEFAULT 'LEGACY_DEFAULT'::"UserAccountKind", ALTER COLUMN "account_status" SET NOT NULL, ALTER COLUMN "account_status" SET DEFAULT 'ACTIVE'::"UserAccountStatus", ALTER COLUMN "library_namespace" SET NOT NULL; CREATE UNIQUE INDEX "users_library_namespace_key" ON "users"("library_namespace"); CREATE TABLE "user_password_credentials" ( "id" UUID NOT NULL, "user_id" UUID NOT NULL, "password_hash" TEXT NOT NULL, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, CONSTRAINT "user_password_credentials_pkey" PRIMARY KEY ("id") ); CREATE UNIQUE INDEX "user_password_credentials_user_id_key" ON "user_password_credentials"("user_id"); CREATE TABLE "user_oauth_identities" ( "id" UUID NOT NULL, "user_id" UUID NOT NULL, "provider" TEXT NOT NULL, "provider_subject" TEXT NOT NULL, "email" TEXT, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, CONSTRAINT "user_oauth_identities_pkey" PRIMARY KEY ("id") ); CREATE UNIQUE INDEX "user_oauth_identities_provider_provider_subject_key" ON "user_oauth_identities"("provider", "provider_subject"); CREATE INDEX "user_oauth_identities_user_id_idx" ON "user_oauth_identities"("user_id"); CREATE TABLE "email_verification_tokens" ( "id" UUID NOT NULL, "user_id" UUID NOT NULL, "email" TEXT NOT NULL, "token_hash" TEXT NOT NULL, "expires_at" TIMESTAMP(3) NOT NULL, "consumed_at" TIMESTAMP(3), "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "email_verification_tokens_pkey" PRIMARY KEY ("id") ); CREATE UNIQUE INDEX "email_verification_tokens_token_hash_key" ON "email_verification_tokens"("token_hash"); CREATE INDEX "email_verification_tokens_user_id_idx" ON "email_verification_tokens"("user_id"); CREATE TABLE "password_reset_tokens" ( "id" UUID NOT NULL, "user_id" UUID NOT NULL, "token_hash" TEXT NOT NULL, "expires_at" TIMESTAMP(3) NOT NULL, "consumed_at" TIMESTAMP(3), "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "password_reset_tokens_pkey" PRIMARY KEY ("id") ); CREATE UNIQUE INDEX "password_reset_tokens_token_hash_key" ON "password_reset_tokens"("token_hash"); CREATE INDEX "password_reset_tokens_user_id_idx" ON "password_reset_tokens"("user_id"); CREATE TABLE "device_link_history" ( "id" UUID NOT NULL, "user_id" UUID NOT NULL, "device_id" UUID, "linked_by_device_id" UUID, "link_method" TEXT NOT NULL, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "device_link_history_pkey" PRIMARY KEY ("id") ); CREATE INDEX "device_link_history_user_id_idx" ON "device_link_history"("user_id"); CREATE INDEX "device_link_history_device_id_idx" ON "device_link_history"("device_id"); CREATE TABLE "ownership_transfers" ( "id" UUID NOT NULL, "from_user_id" UUID NOT NULL, "to_user_id" UUID, "requested_by_device_id" UUID, "status" TEXT NOT NULL, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "updated_at" TIMESTAMP(3) NOT NULL, "completed_at" TIMESTAMP(3), CONSTRAINT "ownership_transfers_pkey" PRIMARY KEY ("id") ); CREATE INDEX "ownership_transfers_from_user_id_idx" ON "ownership_transfers"("from_user_id"); CREATE INDEX "ownership_transfers_to_user_id_idx" ON "ownership_transfers"("to_user_id"); ALTER TABLE "user_password_credentials" ADD CONSTRAINT "user_password_credentials_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE "user_oauth_identities" ADD CONSTRAINT "user_oauth_identities_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE "email_verification_tokens" ADD CONSTRAINT "email_verification_tokens_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE "password_reset_tokens" ADD CONSTRAINT "password_reset_tokens_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE "device_link_history" ADD CONSTRAINT "device_link_history_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE "device_link_history" ADD CONSTRAINT "device_link_history_device_id_fkey" FOREIGN KEY ("device_id") REFERENCES "devices"("id") ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE "device_link_history" ADD CONSTRAINT "device_link_history_linked_by_device_id_fkey" FOREIGN KEY ("linked_by_device_id") REFERENCES "devices"("id") ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE "ownership_transfers" ADD CONSTRAINT "ownership_transfers_from_user_id_fkey" FOREIGN KEY ("from_user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; ALTER TABLE "ownership_transfers" ADD CONSTRAINT "ownership_transfers_to_user_id_fkey" FOREIGN KEY ("to_user_id") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE; ALTER TABLE "ownership_transfers" ADD CONSTRAINT "ownership_transfers_requested_by_device_id_fkey" FOREIGN KEY ("requested_by_device_id") REFERENCES "devices"("id") ON DELETE SET NULL ON UPDATE CASCADE;