"""drop events table + notes.metadata column (retire calendar + entity surfaces) Revision ID: 0069 Revises: 0068 Create Date: 2026-07-19 The personal-assistant surfaces (calendar/events + CalDAV, and the typed person/place/list entities that stored structured fields in notes.metadata) were removed when Scribe narrowed to a Claude-Code work system-of-record. This migration drops their storage: - the `events` table (all calendar/CalDAV data) - the `notes.metadata` (entity_meta) JSONB column — it only ever held person/place/list structured fields. The `note_type` column STAYS: it also distinguishes 'process' notes. - orphan CalDAV settings rows (nothing reads them after the removal) Downgrade recreates the table + column structure at its pre-removal shape. The dropped data itself is not recoverable. """ from alembic import op import sqlalchemy as sa from sqlalchemy.dialects.postgresql import JSONB revision = "0069" down_revision = "0068" branch_labels = None depends_on = None def upgrade() -> None: # Entity metadata column (person/place/list structured fields). The # note_type column is intentionally kept — it also marks 'process' notes. op.drop_column("notes", "metadata") # Calendar / CalDAV storage. Dropping the table drops its indexes + the # duration CHECK constraint with it. op.drop_table("events") # Orphan CalDAV integration settings — no code reads them post-removal. op.execute("DELETE FROM settings WHERE key LIKE 'caldav%'") def downgrade() -> None: # Recreate the events table at its pre-removal schema (empty — the data is # gone). Mirrors the model as of 0037 (reminders) + 0043 (duration_minutes) # + 0057 (soft-delete columns/index). op.create_table( "events", sa.Column("id", sa.Integer(), primary_key=True), sa.Column("user_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False), sa.Column("project_id", sa.Integer(), sa.ForeignKey("projects.id", ondelete="SET NULL"), nullable=True), sa.Column("uid", sa.Text(), nullable=False), sa.Column("title", sa.Text(), nullable=False, server_default=""), sa.Column("start_dt", sa.DateTime(timezone=True), nullable=False), sa.Column("duration_minutes", sa.Integer(), nullable=True), sa.Column("all_day", sa.Boolean(), nullable=False, server_default=sa.false()), sa.Column("description", sa.Text(), nullable=False, server_default=""), sa.Column("location", sa.Text(), nullable=False, server_default=""), sa.Column("caldav_uid", sa.Text(), nullable=False, server_default=""), sa.Column("color", sa.Text(), nullable=False, server_default=""), sa.Column("recurrence", sa.Text(), nullable=True), sa.Column("reminder_minutes", sa.Integer(), nullable=True), sa.Column("reminder_sent_at", sa.DateTime(timezone=True), nullable=True), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()), sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()), sa.Column("deleted_at", sa.DateTime(timezone=True), nullable=True), sa.Column("deleted_batch_id", sa.Text(), nullable=True), sa.CheckConstraint( "duration_minutes IS NULL OR duration_minutes >= 0", name="events_duration_minutes_non_negative", ), ) op.create_index("ix_events_deleted_at", "events", ["deleted_at"]) # Re-add the entity metadata column. op.add_column("notes", sa.Column("metadata", JSONB(), nullable=True))