b49efdcb11
CI & Build / Python lint (push) Successful in 3s
CI & Build / TypeScript typecheck (push) Successful in 11s
CI & Build / integration (push) Successful in 30s
CI & Build / Python tests (push) Failing after 31s
CI & Build / Build & push image (push) Has been skipped
Narrow Scribe to a Claude-Code work system-of-record (milestone #194, decision note #1759). Wholesale removal per rule #22 — backend + schema half. Calendar/events + CalDAV: delete models/event, services/{events,caldav, caldav_sync}, routes/events, mcp/tools/events; strip event branches from backup (bump v3->v4), dashboard (upcoming_events), trash, recent, and the mcp server read-only allowlist + instructions. Typed entities (person/place/list): delete mcp/tools/entities; drop the notes.metadata (entity_meta) column from model/service/routes and the knowledge browse service. note_type STAYS — it also marks 'process' notes. Scheduler: event_scheduler -> recurrence_scheduler, keeping only the recurring-task spawn job (drops event reminders + CalDAV sync). Schema: migration 0069 drops the events table + notes.metadata column + orphan caldav settings rows (faithful downgrade recreates them). KEEP: recurrence.py (task recurrence), notifications task reminders, graph view, and every work surface. Frontend + plugin/docs true-up follow next. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BPtbSzA4JLMAKgFZ8VTg7Q
83 lines
3.6 KiB
Python
83 lines
3.6 KiB
Python
"""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))
|