Skip to content

# TASK_PHASE_ASSETS_PROXY_DEBUG_v2 — MinIO Asset Proxy (логотипи/банери)

## Контекст

- MinIO використовується для зберігання assets (логотипи, банери, зображення).
- Раніше доступ йшов через `https://assets.daarion.space/...` (NGINX → MinIO).
- Було додано proxy в city-service:
- endpoint: `/city/assets/proxy/{path}` (далі — Asset Proxy).
- `normalizeAssetUrl` перетворює `https://assets.daarion.space/daarion-assets/...` у `/api/city/assets/proxy/...`.
- Cursor повідомляв:
- Proxy endpoint працює, локально повертає PNG.
- Компоненти використовують `normalizeAssetUrl`.
- На проді фактично:
- логотипи/банери на `daarion.space` знову не відображаються,
- у браузері видно або «биті» /api-URL, або прямі `assets.daarion.space`, які не відкриваються.

Ціль — зробити так, щоб: - на проді логотипи/банери стабільно відображалися, - всі UI-компоненти використовували один механізм нормалізації URL, - Asset Proxy коректно працював із MinIO в прод-оточенні.

## Завдання

### 1. Перевірити, що саме зараз працює на проді

1. Зайти на продовий `daarion.space` (через SSH-tunel / curl).
2. Для декількох сторінок (мікроDAO, ноди, банери):
3. подивитись `img.src` у HTML/DevTools,
4. зафіксувати: чи це `/api/city/assets/proxy/...` чи `https://assets.daarion.space/...`.
5. Якщо хоч один компонент ще використовує сирий URL:
6. знайти всі місця у фронті, де рендеряться логотипи/банери (microdao, nodes, dashboards, тощо),
7. переконатися, що всюди використовується одна функція `normalizeAssetUrl` (або аналогічний helper),
8. виправити імпорти/використання (ніяких `src={logoUrl}` напряму).

### 2. Перевірити конфіг маршруту Asset Proxy у city-service

1. Знайти в `services/city-service/routes_city.py` (або відповідному файлі) endpoint типу: `python @router.get("/city/assets/proxy/{path:path}")` Важливо: має бути `{path:path}`, щоб підтримувати вкладені шляхи з `/`.

2. Переконатися, що:

3. route справді висить під `/city/assets/proxy/{path}` (не `/assets/proxy` без `/city`),
4. в main-файлі `city-service` router змонтовано як `/api/city` (або відповідно до NGINX/Caddy маршрутизації),

5. результатом на проді стає саме той шлях, який очікує фронт (наприклад `/api/city/assets/proxy/...`).

6. Перехрестити це з проксі-конфігом NGINX/Caddy:

7. `/api/city` → `city-service`,
8. нічого не обрізається/не додається зайве (щоб не вийшло `/api/api/city/...` або `/city/city/...`).

### 3. Перевірити ENV для доступу до MinIO в Asset Proxy

1. Знайти, які ENV використовує proxy для MinIO (наприклад): `python MINIO_PUBLIC_ENDPOINT MINIO_BUCKET MINIO_ASSETS_PREFIX # typ. "daarion-assets"`

2. Переконатися, що:

3. у prod-docker-compose для `city-service` ці ENV присутні й коректні,

4. в коді proxy шлях будується правильно: `python # псевдокод target_url = f"{MINIO_PUBLIC_ENDPOINT}/{MINIO_BUCKET}/{path}"` якщо `normalizeAssetUrl` відрізає `daarion-assets/`, то тут це потрібно додати вручну.

5. Написати невеликий unit/integration-тест або просто `curl` у коді:

6. викликати Asset Proxy з конкретним шляхом, який точно існує в MinIO (`microdao/logo/...`),
7. переконатися, що код отримує 200 і `Content-Type: image/png`.

### 4. Вирівняти контракт normalizeAssetUrl ↔ Asset Proxy

1. В коді `normalizeAssetUrl` явно зафіксувати контракт:
2. Приклад вхідного URL з БД: `text https://assets.daarion.space/daarion-assets/microdao/logo/123.png`

3. Вихідний URL для фронта: `text /api/city/assets/proxy/microdao/logo/123.png`

4. В коді proxy за цим шляхом (`microdao/logo/123.png`) формувати запит до MinIO: `text <MINIO_PUBLIC_ENDPOINT>/daarion-assets/microdao/logo/123.png`

5. Якщо в БД іноді зберігаються шляхи без `daarion-assets/` або без домену:

6. додати обробку в normalizeAssetUrl:

   - якщо шлях починається з `https://assets.daarion.space/` → вирізати домен і префікс бакету,
   - якщо з `/daarion-assets/` → вирізати `/daarion-assets/`,
   - якщо просто `microdao/logo/...` → використовувати як є.

7. Додати короткий коментар у коді normalizeAssetUrl і Asset Proxy, щоб наступні зміни не ламали цей контракт.

### 5. Перевірка на проді

1. Після оновлення `city-service` і `web` (перезбір образів і `docker-compose up -d`):

2. Зайти на основні сторінки з логотипами/банерами:

   - список MicroDAO,
   - сторінка MicroDAO,
   - сторінка нод,
   - dashboard, де є банери.

3. У DevTools:

4. перевірити, що всі картинки ведуть на `/api/city/assets/proxy/...`,
5. статус усіх запитів 200,

6. `Content-Type` відповідає типу зображення.

7. Зафіксувати в короткому звіті:

8. приклади реальних URL (до/після),
9. що саме було змінено в коді / docker-конфігах,
10. інструкцію, як додавати нові компоненти з логотипами, щоб не обійти `normalizeAssetUrl`.

## Acceptance Criteria

- На проді:
- всі логотипи й банери на `daarion.space` завантажуються,
- немає жодних прямих `https://assets.daarion.space/...` у HTML,

- всі запити до зображень йдуть через `/api/city/assets/proxy/...` і повертають 200.

- В репозиторії:

- є один централізований helper (`normalizeAssetUrl`), який використовують усі компоненти для assets,
- Asset Proxy має чіткий контракт з цим helper'ом і коректні ENV для MinIO,

- коротка документація (наприклад, у `docs/ASSETS_DNS_SETUP.md` або новому `docs/ASSETS_PROXY.md`) описує поточну схему.

- Перезапуск сервісів (web + city-service) після змін обов'язково задокументований у звіті Cursor.