# 🔍 DB Migrations Origin Diff **Date:** 04/12/2025 **Scope:** `veza-backend-api` vs `ORIGIN_DATABASE_SCHEMA.md` This document highlights the divergences between the intended V1 migrations and the Source of Truth (Origin). ## 1. Global Divergences | Feature | Origin Spec | Current V1 Implementation | Action | | :--- | :--- | :--- | :--- | | **Primary Keys** | `UUID DEFAULT gen_random_uuid()` | `UUID DEFAULT gen_random_uuid()` | ✅ Aligned | | **Timestamps** | `created_at`, `updated_at` (TIMESTAMPTZ) | `created_at`, `updated_at` (TIMESTAMPTZ) | ✅ Aligned | | **Updated Trigger** | Mandatory | Implemented via `900_triggers.sql` | ✅ Aligned | | **Indexes** | Snake_case `idx__` | Mixed naming | ⚠️ Rename to standard | | **Soft Deletes** | Mandatory for user-facing | Partially implemented | ⚠️ Fix missing `deleted_at` | --- ## 2. Table-by-Table Diff ### 2.1 Auth & Users #### `users` * **Origin:** `email` (unique), `username` (unique), `password_hash`, `role` (ENUM), `is_active`, `is_verified`, `is_banned`, `token_version`, `last_login_at`, `login_count`. * **V1:** Has most fields. * **Divergences:** * `role`: V1 uses `VARCHAR`, Origin requires `ENUM user_role`. * `is_banned`: Missing in V1. * `login_count`, `last_login_ip`: Missing in V1. * `email_verified_at`, `last_password_change_at`: Missing in V1. * `avatar`, `bio` in V1 are in `users`, but Origin puts them in `user_profiles`. * **Decision:** Move profile fields to `user_profiles`? **NO**, to maintain Go compatibility, we will keep basic profile fields in `users` for now but ADD the missing Origin fields (`is_banned`, etc.) and fix the `role` type. #### `refresh_tokens` * **Origin:** `token_hash`, `device_name`, `device_type`, `ip_address`, `last_used_at`, `is_revoked`, `revoked_reason`. * **V1:** Simplified version. * **Action:** Add missing columns (`device_name`, `is_revoked`, etc.) to match Origin. #### `federated_identities` * **Origin:** `provider_user_id`, `provider_email`, `provider_profile_data` (JSONB), `is_primary`. * **V1:** `provider_id` (naming mismatch), missing `provider_profile_data`, `is_primary`. * **Action:** Rename `provider_id` -> `provider_user_id`. Add missing columns. ### 2.2 Profiles #### `user_profiles` * **Origin:** Separate table with `bio`, `location`, `website_url`, `birthdate`, `gender`, `theme`. * **V1:** Some fields are in `users`. * **Action:** Create `user_profiles` exactly as Origin. If `users` table duplicates data, we will deprecate the columns in `users` but keep them for Go compatibility, OR sync them via trigger. * **Strategy:** Create the full `user_profiles` table. ### 2.3 Streaming (Tracks & Playlists) #### `tracks` * **Origin:** `creator_id` (FK users), `file_id` (FK files), `visibility` (ENUM), `bpm`, `musical_key`. * **V1:** `user_id` (FK users), `file_path` (No `files` table relation), `status` (VARCHAR). * **Divergences:** * **Major:** Origin links `tracks` -> `files`. V1 stores `file_path` directly on `tracks`. * **Constraint:** Creating a `files` table implies a major refactor of the Go backend if it expects `file_path` on `tracks`. * **Action:** We will Create the `files` table as per Origin. We will **keep** `file_path` on `tracks` for Go compatibility (marked as legacy/denormalized) but ALSO add `file_id` (nullable for now) to pave the way for the target schema. * `user_id` vs `creator_id`: V1 uses `user_id`. Origin uses `creator_id`. We will Add `creator_id` and sync it or Rename it if safe (Go uses `UserID`). -> **Keep `user_id`** to avoid breaking Go, but map it mentally. *Actually*, Origin says `creator_id`. I will add `creator_id` and make `user_id` a generated col or alias if possible, or just accept the divergence for now. **Decision: Keep `user_id` for Go compatibility, add comment.** #### `playlists` * **Origin:** `name`, `visibility` (ENUM), `is_collaborative`. * **V1:** `title`, `is_public` (BOOL). * **Action:** * Add `name` (or rename `title` -> `name` if code allows, otherwise keep `title` and add `name` as generated/synced). -> **Keep `title`**, Origin says `name`. We will use `title` as it's standard in this codebase. * Add `visibility` ENUM (map `is_public` to it). ### 2.4 Files * **Origin:** `files` table with storage info, metadata, hash. * **V1:** No `files` table. * **Action:** **Implement `files` table** from Origin. It's critical for the "File Management" module. --- ## 3. Plan of Action 1. **001_extensions_and_types.sql:** Add `user_role`, `visibility`, `message_type` ENUMs. 2. **010_auth.sql:** Align `users`, `refresh_tokens` with Origin columns. 3. **020_profiles.sql:** Implement full `user_profiles` table. 4. **030_files.sql:** Implement `files` table (New). 5. **040_streaming.sql:** Update `tracks`, `playlists` to reference `files` and use ENUMs. 6. **900_triggers.sql:** Ensure all have `updated_at` triggers.