diff --git a/alembic/versions/0061_partial_unique_topic_rule_titles.py b/alembic/versions/0061_partial_unique_topic_rule_titles.py new file mode 100644 index 0000000..fa8810c --- /dev/null +++ b/alembic/versions/0061_partial_unique_topic_rule_titles.py @@ -0,0 +1,49 @@ +"""partial-unique topic/rule titles (ignore soft-deleted rows) + +Revision ID: 0061 +Revises: 0060 +Create Date: 2026-06-02 + +Topics and rules are soft-deleted (SoftDeleteMixin), but uq_topic_per_rulebook +and uq_rule_per_topic were plain UNIQUE constraints. Trashing a topic/rule +named "X" then creating a new "X" β€” or restoring into a reused title slot β€” +collided with the dead row and raised an unhandled 500. Replace the full +UNIQUE constraints with partial unique indexes that only consider live +(deleted_at IS NULL) rows. +""" +from alembic import op +import sqlalchemy as sa + + +revision = "0061" +down_revision = "0060" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + op.drop_constraint("uq_topic_per_rulebook", "rulebook_topics", type_="unique") + op.create_index( + "uq_topic_per_rulebook", + "rulebook_topics", + ["rulebook_id", "title"], + unique=True, + postgresql_where=sa.text("deleted_at IS NULL"), + ) + op.drop_constraint("uq_rule_per_topic", "rules", type_="unique") + op.create_index( + "uq_rule_per_topic", + "rules", + ["topic_id", "title"], + unique=True, + postgresql_where=sa.text("deleted_at IS NULL"), + ) + + +def downgrade() -> None: + op.drop_index("uq_rule_per_topic", table_name="rules") + op.create_unique_constraint("uq_rule_per_topic", "rules", ["topic_id", "title"]) + op.drop_index("uq_topic_per_rulebook", table_name="rulebook_topics") + op.create_unique_constraint( + "uq_topic_per_rulebook", "rulebook_topics", ["rulebook_id", "title"] + ) diff --git a/alembic/versions/0062_drop_userprofile_curator_columns.py b/alembic/versions/0062_drop_userprofile_curator_columns.py new file mode 100644 index 0000000..00e5633 --- /dev/null +++ b/alembic/versions/0062_drop_userprofile_curator_columns.py @@ -0,0 +1,41 @@ +"""drop dead UserProfile curator columns + +Revision ID: 0062 +Revises: 0061 +Create Date: 2026-06-02 + +learned_summary, observations_raw, and observations_updated_at were written by +the curator/LLM-profile machinery removed in the Phase-8 MCP pivot. Nothing has +populated them since; the profile API returned permanently-empty fields. Drop +the columns. +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + + +revision = "0062" +down_revision = "0061" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + op.drop_column("user_profiles", "learned_summary") + op.drop_column("user_profiles", "observations_raw") + op.drop_column("user_profiles", "observations_updated_at") + + +def downgrade() -> None: + op.add_column( + "user_profiles", + sa.Column("observations_updated_at", sa.DateTime(timezone=True), nullable=True), + ) + op.add_column( + "user_profiles", + sa.Column("observations_raw", postgresql.JSONB(), nullable=True), + ) + op.add_column( + "user_profiles", + sa.Column("learned_summary", sa.Text(), nullable=True), + ) diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index 6150a66..5a89b8e 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -1,6 +1,6 @@ services: app: - image: git.fabledsword.com/bvandeusen/fabledassistant:latest + image: git.fabledsword.com/bvandeusen/fabledscribe:latest environment: DATABASE_URL: "postgresql+asyncpg://fabled:${DB_PASSWORD}@db:5432/fabledassistant" SECRET_KEY: "${SECRET_KEY}" diff --git a/frontend/src/components/AppHeader.vue b/frontend/src/components/AppHeader.vue index 5de4c6a..34c4ff1 100644 --- a/frontend/src/components/AppHeader.vue +++ b/frontend/src/components/AppHeader.vue @@ -45,7 +45,8 @@ router.afterEach(() => { + + +