# 🔍 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_<table>_<cols>` | 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.

