"""initial schema Revision ID: 563ae5ac1d0d Revises: Create Date: 2026-07-18 14:41:47.620604 """ from typing import Sequence, Union import pgvector.sqlalchemy import sqlalchemy as sa from sqlalchemy.dialects import postgresql from alembic import op # revision identifiers, used by Alembic. revision: str = "563ae5ac1d0d" down_revision: Union[str, Sequence[str], None] = None branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: """Upgrade schema.""" op.execute("CREATE EXTENSION IF NOT EXISTS vector") # ### commands auto generated by Alembic - please adjust! ### op.create_table( "departments", sa.Column("name", sa.String(length=200), nullable=False), sa.Column("id", sa.Uuid(), nullable=False), sa.Column( "created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.Column( "updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint("name"), ) op.create_table( "jobs", sa.Column("type", sa.String(length=100), nullable=False), sa.Column("payload", postgresql.JSONB(astext_type=sa.Text()), nullable=False), sa.Column( "status", sa.Enum( "pending", "running", "done", "failed", name="jobstatus", native_enum=False, length=32, ), nullable=False, ), sa.Column( "run_after", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.Column("attempts", sa.Integer(), nullable=False), sa.Column("last_error", sa.Text(), nullable=True), sa.Column("id", sa.Uuid(), nullable=False), sa.Column( "created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.Column( "updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.PrimaryKeyConstraint("id"), ) op.create_index( "ix_jobs_status_run_after", "jobs", ["status", "run_after"], unique=False ) op.create_table( "templates", sa.Column("name", sa.String(length=200), nullable=False), sa.Column("version", sa.String(length=20), nullable=False), sa.Column("config", postgresql.JSONB(astext_type=sa.Text()), nullable=False), sa.Column("is_builtin", sa.Boolean(), nullable=False), sa.Column("id", sa.Uuid(), nullable=False), sa.Column( "created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.Column( "updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.PrimaryKeyConstraint("id"), ) op.create_table( "users", sa.Column("email", sa.String(length=320), nullable=False), sa.Column("name", sa.String(length=200), nullable=False), sa.Column( "role", sa.Enum("member", "admin", name="userrole", native_enum=False, length=32), nullable=False, ), sa.Column("password_hash", sa.String(length=255), nullable=False), sa.Column("department_id", sa.Uuid(), nullable=True), sa.Column("id", sa.Uuid(), nullable=False), sa.Column( "created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.Column( "updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.ForeignKeyConstraint( ["department_id"], ["departments.id"], ondelete="SET NULL" ), sa.PrimaryKeyConstraint("id"), ) op.create_index(op.f("ix_users_email"), "users", ["email"], unique=True) op.create_table( "auth_sessions", sa.Column("user_id", sa.Uuid(), nullable=False), sa.Column("expires_at", sa.DateTime(timezone=True), nullable=False), sa.Column("id", sa.Uuid(), nullable=False), sa.Column( "created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.Column( "updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.ForeignKeyConstraint(["user_id"], ["users.id"], ondelete="CASCADE"), sa.PrimaryKeyConstraint("id"), ) op.create_index( op.f("ix_auth_sessions_user_id"), "auth_sessions", ["user_id"], unique=False ) op.create_table( "documents", sa.Column("title", sa.String(length=500), nullable=False), sa.Column( "status", sa.Enum( "draft", "published", "archived", name="documentstatus", native_enum=False, length=32, ), nullable=False, ), sa.Column( "visibility", sa.Enum( "public", "department", "restricted", name="documentvisibility", native_enum=False, length=32, ), nullable=False, ), sa.Column("content_md", sa.Text(), nullable=False), sa.Column("meta", postgresql.JSONB(astext_type=sa.Text()), nullable=False), sa.Column("author_id", sa.Uuid(), nullable=True), sa.Column("department_id", sa.Uuid(), nullable=True), sa.Column("id", sa.Uuid(), nullable=False), sa.Column( "created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.Column( "updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.ForeignKeyConstraint(["author_id"], ["users.id"], ondelete="SET NULL"), sa.ForeignKeyConstraint( ["department_id"], ["departments.id"], ondelete="SET NULL" ), sa.PrimaryKeyConstraint("id"), ) op.create_table( "chunks", sa.Column("document_id", sa.Uuid(), nullable=False), sa.Column("chunk_index", sa.Integer(), nullable=False), sa.Column("content", sa.Text(), nullable=False), sa.Column( "embedding", pgvector.sqlalchemy.vector.VECTOR(dim=1024), nullable=False ), sa.Column( "tsv", postgresql.TSVECTOR(), sa.Computed( "to_tsvector('german'::regconfig, " "content || ' ' || coalesce(meta->>'heading_path', ''))", persisted=True, ), nullable=True, ), sa.Column("meta", postgresql.JSONB(astext_type=sa.Text()), nullable=False), sa.Column("id", sa.Uuid(), nullable=False), sa.Column( "created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.Column( "updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.ForeignKeyConstraint(["document_id"], ["documents.id"], ondelete="CASCADE"), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint("document_id", "chunk_index"), ) op.create_index( op.f("ix_chunks_document_id"), "chunks", ["document_id"], unique=False ) op.create_index( "ix_chunks_embedding_hnsw", "chunks", ["embedding"], unique=False, postgresql_using="hnsw", postgresql_ops={"embedding": "vector_cosine_ops"}, ) op.create_index( "ix_chunks_tsv", "chunks", ["tsv"], unique=False, postgresql_using="gin" ) op.create_table( "conversations", sa.Column( "mode", sa.Enum( "query", "insight", name="conversationmode", native_enum=False, length=32, ), nullable=False, ), sa.Column( "status", sa.Enum( "active", "completed", "abandoned", name="conversationstatus", native_enum=False, length=32, ), nullable=False, ), sa.Column("user_id", sa.Uuid(), nullable=False), sa.Column("id", sa.Uuid(), nullable=False), sa.Column( "created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.Column( "updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.ForeignKeyConstraint(["user_id"], ["users.id"], ondelete="CASCADE"), sa.PrimaryKeyConstraint("id"), ) op.create_index( op.f("ix_conversations_user_id"), "conversations", ["user_id"], unique=False ) op.create_table( "doc_permissions", sa.Column("document_id", sa.Uuid(), nullable=False), sa.Column("department_id", sa.Uuid(), nullable=False), sa.Column( "level", sa.Enum("read", name="permissionlevel", native_enum=False, length=32), nullable=False, ), sa.Column( "created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.Column( "updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.ForeignKeyConstraint( ["department_id"], ["departments.id"], ondelete="CASCADE" ), sa.ForeignKeyConstraint(["document_id"], ["documents.id"], ondelete="CASCADE"), sa.PrimaryKeyConstraint("document_id", "department_id"), ) op.create_table( "messages", sa.Column("conversation_id", sa.Uuid(), nullable=False), sa.Column( "role", sa.Enum( "user", "assistant", "system", name="messagerole", native_enum=False, length=32, ), nullable=False, ), sa.Column("content", sa.Text(), nullable=False), sa.Column("id", sa.Uuid(), nullable=False), sa.Column( "created_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.Column( "updated_at", sa.DateTime(timezone=True), server_default=sa.text("now()"), nullable=False, ), sa.ForeignKeyConstraint( ["conversation_id"], ["conversations.id"], ondelete="CASCADE" ), sa.PrimaryKeyConstraint("id"), ) op.create_index( op.f("ix_messages_conversation_id"), "messages", ["conversation_id"], unique=False, ) # ### end Alembic commands ### def downgrade() -> None: """Downgrade schema.""" # ### commands auto generated by Alembic - please adjust! ### op.drop_index(op.f("ix_messages_conversation_id"), table_name="messages") op.drop_table("messages") op.drop_table("doc_permissions") op.drop_index(op.f("ix_conversations_user_id"), table_name="conversations") op.drop_table("conversations") op.drop_index("ix_chunks_tsv", table_name="chunks", postgresql_using="gin") op.drop_index( "ix_chunks_embedding_hnsw", table_name="chunks", postgresql_using="hnsw", postgresql_ops={"embedding": "vector_cosine_ops"}, ) op.drop_index(op.f("ix_chunks_document_id"), table_name="chunks") op.drop_table("chunks") op.drop_table("documents") op.drop_index(op.f("ix_auth_sessions_user_id"), table_name="auth_sessions") op.drop_table("auth_sessions") op.drop_index(op.f("ix_users_email"), table_name="users") op.drop_table("users") op.drop_table("templates") op.drop_index("ix_jobs_status_run_after", table_name="jobs") op.drop_table("jobs") op.drop_table("departments") # ### end Alembic commands ###