Skip to content

# TASK_PHASE_DATABASE_HARDENING_AND_ASSETS_MIGRATION_v1

Статус: TODO
Пріоритет: CRITICAL
Мета: Захистити базу даних від втрати та перенести assets на S3-compatible storage

## 0. Проблема

1. База даних зникла - PostgreSQL був пересозданий, всі дані втрачені
2. Логотипи/банери зникли - файли на диску є, але посилання в БД пропали
3. Немає автоматичних бекапів - немає механізму відновлення
4. Assets залежать від локального сервера - при втраті БД втрачаються посилання

## 1. Цілі

1. ✅ PostgreSQL → persistent Docker volume (не зникає при перезапуску)
2. ✅ Автоматичні бекапи БД кожні 12 годин
3. ✅ Assets (лого/банери/аватарки) → MinIO (S3-compatible)
4. ✅ Спрощений `normalizeAssetUrl` для S3 URLs
5. ✅ Seed-скрипт для аварійного відновлення міста

## 2. Кроки виконання

### 2.1. Міграція PostgreSQL → persistent storage

Файл: `docker-compose.yml` або `docker-compose.db.yml`

- [ ] Додати volume `pgdata:/var/lib/postgresql/data` до DB service
- [ ] Створити volume `pgdata` в секції volumes
- [ ] Перевірити що дані зберігаються після перезапуску

### 2.2. Backup система БД

Файл: `docker-compose.yml`

- [ ] Додати service `db-backup` з `prodrigestivill/postgres-backup-local`
- [ ] Налаштувати `SCHEDULE: "@every 12h"`
- [ ] Налаштувати retention (7 днів, 4 тижні, 6 місяців)
- [ ] Створити директорію `db_backups/` для зберігання

### 2.3. MinIO для assets storage

Файл: `docker-compose.yml`

- [ ] Додати service `minio` з `minio/minio:latest`
- [ ] Налаштувати volumes `minio_data:/data`
- [ ] Налаштувати environment variables (MINIO_ROOT_USER, MINIO_ROOT_PASSWORD)
- [ ] Відкрити порти 9000 (API) та 9001 (console)

### 2.4. Бекенд: інтеграція з MinIO

Файли: - `services/city-service/config.py` - додати налаштування MinIO - `services/city-service/lib/assets_client.py` - створити клієнт для MinIO - `services/city-service/routes_city.py` - оновити upload endpoints

- [ ] Додати залежність `minio` в `requirements.txt`
- [ ] Створити `assets_client.py` з функцією `upload_asset()`
- [ ] Оновити upload handlers для MicroDAO logo/banner
- [ ] Оновити upload handlers для Agent avatar
- [ ] Перевірити що URL зберігаються як повні HTTPS URLs

### 2.5. Міграція БД для asset полів

Файл: `migrations/043_asset_urls_to_text.sql`

- [ ] Змінити тип `logo_url`, `banner_url`, `avatar_url` на `text`
- [ ] Додати коментарі про формат URL (HTTPS до MinIO)

### 2.6. Frontend: спрощений normalizeAssetUrl

Файл: `apps/web/src/lib/utils/assetUrl.ts`

- [ ] Спростити функцію - тільки passthrough для HTTPS URLs
- [ ] Залишити fallback для старих `/api/static/` URLs
- [ ] Прибрати всю складну логіку нормалізації

### 2.7. Seed-скрипт для аварійного відновлення

Файл: `scripts/seed_full_city_reset.py`

- [ ] Створити базові MicroDAO (DAARION, Energy Union, GreenFood, Soul)
- [ ] Додати райони міста
- [ ] Додати базові city rooms
- [ ] Додати core агентів NODE1
- [ ] Використовувати S3 URLs для логотипів/банерів

### 2.8. Документація

Файли: - `docs/DB_RESTORE.md` - інструкція по відновленню БД - `docs/SEED_RECOVERY.md` - інструкція по аварійному відновленню - `docs/INFRA_ASSETS_MINIO.md` - документація по MinIO setup

- [ ] Створити DB_RESTORE.md з командами відновлення
- [ ] Створити SEED_RECOVERY.md з інструкціями
- [ ] Створити INFRA_ASSETS_MINIO.md з конфігурацією

## 3. Перевірка після виконання

- [ ] PostgreSQL дані зберігаються після `docker compose restart db`
- [ ] Бекапи створюються в `db_backups/` кожні 12 годин
- [ ] MinIO доступний на `http://localhost:9000` (API) та `http://localhost:9001` (console)
- [ ] Upload логотипу MicroDAO зберігається в MinIO та повертає HTTPS URL
- [ ] Frontend відображає логотипи з MinIO URLs
- [ ] Seed-скрипт відновлює базові дані міста

## 4. ENV змінні

Додати в `.env`:

    # PostgreSQL
    POSTGRES_PASSWORD=super-secret

    # MinIO
    MINIO_ROOT_USER=assets-admin
    MINIO_ROOT_PASSWORD=very-strong-password
    ASSETS_BUCKET=daarion-assets
    ASSETS_PUBLIC_BASE_URL=https://assets.daarion.space/daarion-assets
    MINIO_ENDPOINT=http://minio:9000

## 5. DNS налаштування

- [ ] `assets.daarion.space` → IP NODE1 (для публічного доступу до assets)
- [ ] `minio.daarion.space` → IP NODE1 (опційно, для консолі)

## 6. Caddy/NGINX конфігурація

Див. `docs/INFRA_ASSETS_MINIO.md` для деталей налаштування reverse proxy.