from tortoise import BaseDBAsyncClient RUN_IN_TRANSACTION = True async def upgrade(db: BaseDBAsyncClient) -> str: return """ CREATE TABLE IF NOT EXISTS "api_token" ( "id" UUID NOT NULL PRIMARY KEY, "user_sub" VARCHAR(255) NOT NULL, "name" VARCHAR(100) NOT NULL, "token_prefix" VARCHAR(16) NOT NULL, "token_hash" VARCHAR(64) NOT NULL UNIQUE, "created_at" TIMESTAMPTZ NOT NULL, "last_used_at" TIMESTAMPTZ, "expires_at" DATE ); CREATE INDEX IF NOT EXISTS "idx_api_token_user_su_7c5de7" ON "api_token" ("user_sub"); COMMENT ON TABLE "api_token" IS 'Personal access token for programmatic API access.'; CREATE TABLE IF NOT EXISTS "app_user" ( "id" UUID NOT NULL PRIMARY KEY, "sub" VARCHAR(255) NOT NULL UNIQUE, "display_name" VARCHAR(200) NOT NULL, "name" VARCHAR(255), "family_name" VARCHAR(255), "given_name" VARCHAR(255), "middle_name" VARCHAR(255), "nickname" VARCHAR(255), "preferred_username" VARCHAR(255), "profile" VARCHAR(2048), "picture" VARCHAR(2048), "website" VARCHAR(2048), "gender" VARCHAR(100), "birthdate" VARCHAR(32), "zoneinfo" VARCHAR(100), "locale" VARCHAR(100), "updated_at" BIGINT, "created_at" TIMESTAMPTZ NOT NULL, "last_seen_at" TIMESTAMPTZ NOT NULL ); COMMENT ON TABLE "app_user" IS 'One OIDC identity that has logged in at least once.'; CREATE TABLE IF NOT EXISTS "vault" ( "id" UUID NOT NULL PRIMARY KEY, "owner_sub" VARCHAR(255) NOT NULL, "name" VARCHAR(200) NOT NULL, "description" TEXT NOT NULL, "settings" JSONB NOT NULL, "version" INT NOT NULL, "created_at" TIMESTAMPTZ NOT NULL, "updated_at" TIMESTAMPTZ NOT NULL ); CREATE INDEX IF NOT EXISTS "idx_vault_owner_s_cdc1f8" ON "vault" ("owner_sub"); COMMENT ON TABLE "vault" IS 'One private XCA database owned by an OIDC user.'; CREATE TABLE IF NOT EXISTS "key" ( "id" UUID NOT NULL PRIMARY KEY, "name" VARCHAR(200) NOT NULL, "comment" TEXT NOT NULL, "source" VARCHAR(20) NOT NULL, "key_type" VARCHAR(20) NOT NULL, "key_size" INT, "curve" VARCHAR(100), "public_der" BYTEA NOT NULL, "public_key_sha256" VARCHAR(64) NOT NULL, "private_der" BYTEA, "private_nonce" BYTEA, "has_private" BOOL NOT NULL, "version" INT NOT NULL, "search_text" TEXT NOT NULL, "created_at" TIMESTAMPTZ NOT NULL, "updated_at" TIMESTAMPTZ NOT NULL, "vault_id" UUID NOT NULL REFERENCES "vault" ("id") ON DELETE CASCADE, CONSTRAINT "uid_key_vault_i_e0ffb5" UNIQUE ("vault_id", "public_key_sha256") ); CREATE INDEX IF NOT EXISTS "idx_key_public__eba47e" ON "key" ("public_key_sha256"); CREATE INDEX IF NOT EXISTS "idx_key_vault_i_a6f27f" ON "key" ("vault_id", "name"); CREATE INDEX IF NOT EXISTS "idx_key_vault_i_c2e997" ON "key" ("vault_id", "key_type"); COMMENT ON TABLE "key" IS 'A public or private key item.'; CREATE TABLE IF NOT EXISTS "request" ( "id" UUID NOT NULL PRIMARY KEY, "name" VARCHAR(200) NOT NULL, "comment" TEXT NOT NULL, "source" VARCHAR(20) NOT NULL, "subject_der" BYTEA NOT NULL, "req_der" BYTEA NOT NULL, "public_key_der" BYTEA NOT NULL, "request_sha256" VARCHAR(64) NOT NULL, "signed" BOOL NOT NULL, "signed_at" TIMESTAMPTZ, "attributes" JSONB NOT NULL, "version" INT NOT NULL, "search_text" TEXT NOT NULL, "created_at" TIMESTAMPTZ NOT NULL, "updated_at" TIMESTAMPTZ NOT NULL, "key_id" UUID REFERENCES "key" ("id") ON DELETE SET NULL, "vault_id" UUID NOT NULL REFERENCES "vault" ("id") ON DELETE CASCADE, CONSTRAINT "uid_request_vault_i_b661f4" UNIQUE ("vault_id", "request_sha256") ); CREATE INDEX IF NOT EXISTS "idx_request_request_fad061" ON "request" ("request_sha256"); CREATE INDEX IF NOT EXISTS "idx_request_vault_i_346e22" ON "request" ("vault_id", "name"); CREATE INDEX IF NOT EXISTS "idx_request_vault_i_2cd9ef" ON "request" ("vault_id", "signed"); COMMENT ON TABLE "request" IS 'A PKCS#10 certificate signing request item.'; CREATE TABLE IF NOT EXISTS "certificate" ( "id" UUID NOT NULL PRIMARY KEY, "name" VARCHAR(200) NOT NULL, "comment" TEXT NOT NULL, "source" VARCHAR(20) NOT NULL, "serial_hex" VARCHAR(128) NOT NULL, "subject_der" BYTEA NOT NULL, "issuer_der" BYTEA NOT NULL, "subject_hash" VARCHAR(64) NOT NULL, "issuer_hash" VARCHAR(64) NOT NULL, "not_before" TIMESTAMPTZ NOT NULL, "not_after" TIMESTAMPTZ NOT NULL, "is_ca" BOOL NOT NULL, "path_length" INT, "cert_der" BYTEA NOT NULL, "public_key_der" BYTEA NOT NULL, "signature_algorithm" VARCHAR(100) NOT NULL, "fingerprint_md5" VARCHAR(32) NOT NULL, "fingerprint_sha1" VARCHAR(40) NOT NULL, "fingerprint_sha256" VARCHAR(64) NOT NULL, "version" INT NOT NULL, "search_text" TEXT NOT NULL, "created_at" TIMESTAMPTZ NOT NULL, "updated_at" TIMESTAMPTZ NOT NULL, "issuer_id" UUID REFERENCES "certificate" ("id") ON DELETE SET NULL, "key_id" UUID REFERENCES "key" ("id") ON DELETE SET NULL, "request_id" UUID REFERENCES "request" ("id") ON DELETE SET NULL, "vault_id" UUID NOT NULL REFERENCES "vault" ("id") ON DELETE CASCADE, CONSTRAINT "uid_certificate_vault_i_842384" UNIQUE ("vault_id", "fingerprint_sha256") ); CREATE INDEX IF NOT EXISTS "idx_certificate_serial__787fd1" ON "certificate" ("serial_hex"); CREATE INDEX IF NOT EXISTS "idx_certificate_subject_ed411b" ON "certificate" ("subject_hash"); CREATE INDEX IF NOT EXISTS "idx_certificate_issuer__b8daa0" ON "certificate" ("issuer_hash"); CREATE INDEX IF NOT EXISTS "idx_certificate_is_ca_906cf3" ON "certificate" ("is_ca"); CREATE INDEX IF NOT EXISTS "idx_certificate_fingerp_12be2c" ON "certificate" ("fingerprint_sha256"); CREATE INDEX IF NOT EXISTS "idx_certificate_vault_i_18b9a0" ON "certificate" ("vault_id", "name"); CREATE INDEX IF NOT EXISTS "idx_certificate_vault_i_dfb18f" ON "certificate" ("vault_id", "issuer_id"); CREATE INDEX IF NOT EXISTS "idx_certificate_vault_i_eded8f" ON "certificate" ("vault_id", "not_after"); COMMENT ON TABLE "certificate" IS 'An X.509 certificate item.'; CREATE TABLE IF NOT EXISTS "certificate_revocation" ( "id" UUID NOT NULL PRIMARY KEY, "serial_hex" VARCHAR(128) NOT NULL, "revoked_at" TIMESTAMPTZ NOT NULL, "invalidity_date" TIMESTAMPTZ, "reason" VARCHAR(50) NOT NULL, "crl_number" INT NOT NULL, "created_at" TIMESTAMPTZ NOT NULL, "ca_id" UUID NOT NULL REFERENCES "certificate" ("id") ON DELETE CASCADE, CONSTRAINT "uid_certificate_ca_id_1c9aa5" UNIQUE ("ca_id", "serial_hex") ); CREATE INDEX IF NOT EXISTS "idx_certificate_serial__8fa20f" ON "certificate_revocation" ("serial_hex"); COMMENT ON TABLE "certificate_revocation" IS 'A serial revoked by a CA (XCA stores revocations on the CA).'; CREATE TABLE IF NOT EXISTS "crl" ( "id" UUID NOT NULL PRIMARY KEY, "name" VARCHAR(200) NOT NULL, "comment" TEXT NOT NULL, "source" VARCHAR(20) NOT NULL, "crl_der" BYTEA NOT NULL, "crl_hash" VARCHAR(64) NOT NULL, "crl_number" INT, "last_update" TIMESTAMPTZ NOT NULL, "next_update" TIMESTAMPTZ, "revoked_count" INT NOT NULL, "signature_algorithm" VARCHAR(100) NOT NULL, "search_text" TEXT NOT NULL, "created_at" TIMESTAMPTZ NOT NULL, "updated_at" TIMESTAMPTZ NOT NULL, "issuer_id" UUID REFERENCES "certificate" ("id") ON DELETE SET NULL, "vault_id" UUID NOT NULL REFERENCES "vault" ("id") ON DELETE CASCADE, CONSTRAINT "uid_crl_vault_i_e5461a" UNIQUE ("vault_id", "crl_hash") ); CREATE INDEX IF NOT EXISTS "idx_crl_crl_has_c44d61" ON "crl" ("crl_hash"); CREATE INDEX IF NOT EXISTS "idx_crl_vault_i_6af15c" ON "crl" ("vault_id", "name"); CREATE INDEX IF NOT EXISTS "idx_crl_vault_i_576344" ON "crl" ("vault_id", "issuer_id"); COMMENT ON TABLE "crl" IS 'A certificate revocation list item.'; CREATE TABLE IF NOT EXISTS "template" ( "id" UUID NOT NULL PRIMARY KEY, "name" VARCHAR(200) NOT NULL, "comment" TEXT NOT NULL, "source" VARCHAR(20) NOT NULL, "subject" JSONB NOT NULL, "settings" JSONB NOT NULL, "version" INT NOT NULL, "search_text" TEXT NOT NULL, "created_at" TIMESTAMPTZ NOT NULL, "updated_at" TIMESTAMPTZ NOT NULL, "vault_id" UUID NOT NULL REFERENCES "vault" ("id") ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS "idx_template_vault_i_18d8f5" ON "template" ("vault_id", "name"); COMMENT ON TABLE "template" IS 'An XCA-style template: subject + extension/validity defaults.'; CREATE TABLE IF NOT EXISTS "authority" ( "id" UUID NOT NULL PRIMARY KEY, "crl_expire" TIMESTAMPTZ, "crl_number" INT NOT NULL, "crl_days" INT NOT NULL, "tls_auth_key" BYTEA, "tls_auth_key_nonce" BYTEA, "created_at" TIMESTAMPTZ NOT NULL, "updated_at" TIMESTAMPTZ NOT NULL, "template_id" UUID REFERENCES "template" ("id") ON DELETE SET NULL, "certificate_id" UUID NOT NULL UNIQUE REFERENCES "certificate" ("id") ON DELETE CASCADE ); COMMENT ON TABLE "authority" IS 'CA-specific properties, one row per CA certificate.'; CREATE TABLE IF NOT EXISTS "aerich" ( "id" SERIAL NOT NULL PRIMARY KEY, "version" VARCHAR(255) NOT NULL, "app" VARCHAR(100) NOT NULL, "content" JSONB NOT NULL );""" async def downgrade(db: BaseDBAsyncClient) -> str: return """ """ MODELS_STATE = ( "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" )