# Phase 1: Database Schema & Migration **Status:** ⬜ Not Started **Parent plan:** [PLAN.md](./PLAN.md) **Domain:** backend ## Objective Add new database models (CommandConfig, CommandTracker, CommandTrackerListener), rename existing models (Tracker → NotificationTracker, TrackerTarget → NotificationTrackerTarget), add chat_action to NotificationTarget, and write idempotent migration logic. ## Tasks - [ ] Task 1: Rename `Tracker` model to `NotificationTracker` — update class name, `__tablename__` to `"notification_tracker"`, and all field references. Keep all existing fields (provider_id, collection_ids, scan_interval, batch_duration, enabled, etc.) - [ ] Task 2: Rename `TrackerTarget` model to `NotificationTrackerTarget` — update class name, `__tablename__` to `"notification_tracker_target"`, rename `tracker_id` FK to `notification_tracker_id` - [ ] Task 3: Rename `TrackerState` model to `NotificationTrackerState` — update class name, `__tablename__` to `"notification_tracker_state"`, rename `tracker_id` FK to `notification_tracker_id` - [ ] Task 4: Add `chat_action` optional string field to `NotificationTarget` model (for telegram targets, e.g. "typing", "upload_photo") - [ ] Task 5: Create `CommandConfig` model — fields: id, user_id (FK→User), provider_type (str), name, icon, enabled_commands (JSON list), locale (str, default "en"), response_mode (str, default "media"), default_count (int, default 5), rate_limits (JSON dict), created_at - [ ] Task 6: Create `CommandTracker` model — fields: id, user_id (FK→User), provider_id (FK→ServiceProvider), command_config_id (FK→CommandConfig), name, icon, enabled (bool), created_at - [ ] Task 7: Create `CommandTrackerListener` model — fields: id, command_tracker_id (FK→CommandTracker), listener_type (str, e.g. "telegram_bot"), listener_id (int), created_at. Add unique constraint on (command_tracker_id, listener_type, listener_id) - [ ] Task 8: Remove `commands_config` field from `TelegramBot` model (will be migrated to CommandConfig) - [ ] Task 9: Remove `commands_config` field from `TrackerTarget`/`NotificationTrackerTarget` model - [ ] Task 10: Write idempotent migration in `migrations.py`: - Rename table `tracker` → `notification_tracker` - Rename table `tracker_target` → `notification_tracker_target` and rename column `tracker_id` → `notification_tracker_id` - Rename table `tracker_state` → `notification_tracker_state` and rename column `tracker_id` → `notification_tracker_id` - Add `chat_action` column to `notification_target` - Create `command_config` table - Create `command_tracker` table - Create `command_tracker_listener` table - Migrate existing `TelegramBot.commands_config` JSON → `CommandConfig` rows (one per bot that has non-default config) - Drop `commands_config` column from old telegram_bot table - Drop `commands_config` column from notification_tracker_target table - [ ] Task 11: Update all model imports in `models.py` `__init__` / re-exports — ensure other modules can still import the models - [ ] Task 12: Update `EventLog` model — rename `tracker_id` field to `notification_tracker_id` (nullable FK), add migration for column rename ## Files to Modify/Create - `packages/server/src/notify_bridge_server/database/models.py` — rename models, add new models, remove fields - `packages/server/src/notify_bridge_server/database/migrations.py` — add migration functions ## Acceptance Criteria - All new tables are created on startup via migration - Existing data is preserved and migrated (table renames, column renames, commands_config → CommandConfig) - Server starts without errors with existing test-data database - All existing imports still resolve (may need temporary aliases) ## Notes - SQLite does not support `ALTER TABLE RENAME COLUMN` in older versions. Use the existing pattern of adding new columns + copying data if needed. - The migration must be idempotent — safe to run multiple times. - Other modules (API routes, services) will still reference old model names after this phase. That's OK — Phase 2 will update the API layer. For now, add Python-level aliases (e.g., `Tracker = NotificationTracker`) so existing code continues to work. - TrackerTarget.commands_config was unused in practice — safe to drop without data loss. ## Review Checklist - [ ] All tasks completed - [ ] Code follows project conventions - [ ] No unintended side effects - [ ] Build passes - [ ] Tests pass (new + existing) ## Handoff to Next Phase