# 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, ноди, банери): - подивитись `img.src` у HTML/DevTools, - зафіксувати: чи це `/api/city/assets/proxy/...` чи `https://assets.daarion.space/...`. 3. Якщо хоч один компонент ще використовує сирий URL: - знайти всі місця у фронті, де рендеряться логотипи/банери (microdao, nodes, dashboards, тощо), - переконатися, що всюди використовується **одна** функція `normalizeAssetUrl` (або аналогічний helper), - виправити імпорти/використання (ніяких `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. Переконатися, що: * route справді висить під `/city/assets/proxy/{path}` (не `/assets/proxy` без `/city`), * в main-файлі `city-service` router змонтовано як `/api/city` (або відповідно до NGINX/Caddy маршрутизації), * результатом на проді стає **саме той шлях**, який очікує фронт (наприклад `/api/city/assets/proxy/...`). 3. Перехрестити це з проксі-конфігом NGINX/Caddy: * `/api/city` → `city-service`, * нічого не обрізається/не додається зайве (щоб не вийшло `/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. Переконатися, що: * у prod-docker-compose для `city-service` ці ENV присутні й коректні, * в коді proxy шлях будується правильно: ```python # псевдокод target_url = f"{MINIO_PUBLIC_ENDPOINT}/{MINIO_BUCKET}/{path}" ``` якщо `normalizeAssetUrl` відрізає `daarion-assets/`, то тут це потрібно додати вручну. 3. Написати невеликий unit/integration-тест або просто `curl` у коді: * викликати Asset Proxy з конкретним шляхом, який точно існує в MinIO (`microdao/logo/...`), * переконатися, що код отримує 200 і `Content-Type: image/png`. ### 4. Вирівняти контракт normalizeAssetUrl ↔ Asset Proxy 1. В коді `normalizeAssetUrl` явно зафіксувати контракт: * Приклад вхідного URL з БД: ```text https://assets.daarion.space/daarion-assets/microdao/logo/123.png ``` * Вихідний URL для фронта: ```text /api/city/assets/proxy/microdao/logo/123.png ``` 2. В коді proxy за цим шляхом (`microdao/logo/123.png`) формувати запит до MinIO: ```text /daarion-assets/microdao/logo/123.png ``` 3. Якщо в БД іноді зберігаються шляхи без `daarion-assets/` або без домену: * додати обробку в normalizeAssetUrl: * якщо шлях починається з `https://assets.daarion.space/` → вирізати домен і префікс бакету, * якщо з `/daarion-assets/` → вирізати `/daarion-assets/`, * якщо просто `microdao/logo/...` → використовувати як є. 4. Додати короткий коментар у коді normalizeAssetUrl і Asset Proxy, щоб наступні зміни не ламали цей контракт. ### 5. Перевірка на проді 1. Після оновлення `city-service` і `web` (перезбір образів і `docker-compose up -d`): * Зайти на основні сторінки з логотипами/банерами: * список MicroDAO, * сторінка MicroDAO, * сторінка нод, * dashboard, де є банери. 2. У DevTools: * перевірити, що всі картинки ведуть на `/api/city/assets/proxy/...`, * статус усіх запитів 200, * `Content-Type` відповідає типу зображення. 3. Зафіксувати в короткому звіті: * приклади реальних URL (до/після), * що саме було змінено в коді / docker-конфігах, * інструкцію, як додавати нові компоненти з логотипами, щоб не обійти `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.