Files
microdao-daarion/site/tasks/ASSETS_PROXY_MANUAL_TEST_PLAN/index.html
Apple ef3473db21 snapshot: NODE1 production state 2026-02-09
Complete snapshot of /opt/microdao-daarion/ from NODE1 (144.76.224.179).
This represents the actual running production code that has diverged
significantly from the previous main branch.

Key changes from old main:
- Gateway (http_api.py): expanded from ~40KB to 164KB with full agent support
- Router: new /v1/agents/{id}/infer endpoint with vision + DeepSeek routing
- Behavior Policy: SOWA v2.2 (3-level: FULL/ACK/SILENT)
- Agent Registry: config/agent_registry.yml as single source of truth
- 13 agents configured (was 3)
- Memory service integration
- CrewAI teams and roles

Excluded from snapshot: venv/, .env, data/, backups, .tgz archives

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 08:46:46 -08:00

1137 lines
37 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="canonical" href="https://IvanTytar.github.io/microdao-daarion/tasks/ASSETS_PROXY_MANUAL_TEST_PLAN/">
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.5.3, mkdocs-material-9.5.18">
<title>Manual Test Plan — Assets Proxy Debugging - DAARION Documentation</title>
<link rel="stylesheet" href="../../assets/stylesheets/main.66ac8b77.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#manual-test-plan-assets-proxy-debugging" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="../.." title="DAARION Documentation" class="md-header__button md-logo" aria-label="DAARION Documentation" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
DAARION Documentation
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Manual Test Plan — Assets Proxy Debugging
</span>
</div>
</div>
</div>
<script>var media,input,key,value,palette=__md_get("__palette");if(palette&&palette.color){"(prefers-color-scheme)"===palette.color.media&&(media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']"),palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent"));for([key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="../.." title="DAARION Documentation" class="md-nav__button md-logo" aria-label="DAARION Documentation" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
</a>
DAARION Documentation
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../public/" class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../public/getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Getting Started
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../public/architecture-overview/" class="md-nav__link">
<span class="md-ellipsis">
Architecture
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../public/daiS_daos_overview/" class="md-nav__link">
<span class="md-ellipsis">
DAIS & DAOS
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="">
<span class="md-ellipsis">
Internal
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Internal
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5_1" >
<label class="md-nav__link" for="__nav_5_1" id="__nav_5_1_label" tabindex="0">
<span class="md-ellipsis">
Infra
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_5_1_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5_1">
<span class="md-nav__icon md-icon"></span>
Infra
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../internal/infra/INFRA_AUTOMATION_PACK_V1/" class="md-nav__link">
<span class="md-ellipsis">
Infra Automation Pack v1
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../internal/infra/monitoring_overview/" class="md-nav__link">
<span class="md-ellipsis">
Monitoring Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../internal/infra/nodes_registry_v0/" class="md-nav__link">
<span class="md-ellipsis">
Nodes Registry v0
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5_2" >
<label class="md-nav__link" for="__nav_5_2" id="__nav_5_2_label" tabindex="0">
<span class="md-ellipsis">
Specs
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_5_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5_2">
<span class="md-nav__icon md-icon"></span>
Specs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../internal/specs/matrix_presence_aggregator/" class="md-nav__link">
<span class="md-ellipsis">
Matrix Presence Aggregator
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../internal/specs/city_map_spec/" class="md-nav__link">
<span class="md-ellipsis">
City Map Spec
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../internal/specs/node_join_protocol_draft/" class="md-nav__link">
<span class="md-ellipsis">
Node Join Protocol (Draft)
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#_1" class="md-nav__link">
<span class="md-ellipsis">
Контекст
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#1" class="md-nav__link">
<span class="md-ellipsis">
Крок 1: Перевірка реальних запитів в браузері
</span>
</a>
<nav class="md-nav" aria-label="Крок 1: Перевірка реальних запитів в браузері">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#11-devtools" class="md-nav__link">
<span class="md-ellipsis">
1.1 Відкрити DevTools
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#12" class="md-nav__link">
<span class="md-ellipsis">
1.2 Знайти "биті" зображення
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#13-url" class="md-nav__link">
<span class="md-ellipsis">
1.3 Аналіз URL
</span>
</a>
<nav class="md-nav" aria-label="1.3 Аналіз URL">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#url-_nextimageurl" class="md-nav__link">
<span class="md-ellipsis">
Якщо URL виглядає як /_next/image?url=...
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#url-apicityassetsproxy" class="md-nav__link">
<span class="md-ellipsis">
Якщо URL виглядає як /api/city/assets/proxy/...
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#2-web-" class="md-nav__link">
<span class="md-ellipsis">
Крок 2: Перевірка оновлення web-сервісу
</span>
</a>
<nav class="md-nav" aria-label="Крок 2: Перевірка оновлення web-сервісу">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#21-web-" class="md-nav__link">
<span class="md-ellipsis">
2.1 Перебудувати web-сервіс
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#22-hard-refresh" class="md-nav__link">
<span class="md-ellipsis">
2.2 Hard refresh в браузері
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#3-proxy" class="md-nav__link">
<span class="md-ellipsis">
Крок 3: Перевірка шляху в proxy
</span>
</a>
<nav class="md-nav" aria-label="Крок 3: Перевірка шляху в proxy">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#31-path" class="md-nav__link">
<span class="md-ellipsis">
3.1 Скопіювати точний path
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#32-city-service" class="md-nav__link">
<span class="md-ellipsis">
3.2 Перевірка через city-service
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#33-minio" class="md-nav__link">
<span class="md-ellipsis">
3.3 Перевірка напряму у MinIO
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#34" class="md-nav__link">
<span class="md-ellipsis">
3.4 Аналіз результатів
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#4" class="md-nav__link">
<span class="md-ellipsis">
Крок 4: Перевірка логів
</span>
</a>
<nav class="md-nav" aria-label="Крок 4: Перевірка логів">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#41-city-service" class="md-nav__link">
<span class="md-ellipsis">
4.1 Логи city-service
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#42-web-" class="md-nav__link">
<span class="md-ellipsis">
4.2 Логи web-сервісу
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#5-normalizeasseturl" class="md-nav__link">
<span class="md-ellipsis">
Крок 5: Перевірка normalizeAssetUrl
</span>
</a>
<nav class="md-nav" aria-label="Крок 5: Перевірка normalizeAssetUrl">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#51" class="md-nav__link">
<span class="md-ellipsis">
5.1 Перевірка вхідних даних з БД
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#52" class="md-nav__link">
<span class="md-ellipsis">
5.2 Перевірка нормалізації
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#_2" class="md-nav__link">
<span class="md-ellipsis">
Очікувані результати
</span>
</a>
<nav class="md-nav" aria-label="Очікувані результати">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#_3" class="md-nav__link">
<span class="md-ellipsis">
✅ Успішний сценарій
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_4" class="md-nav__link">
<span class="md-ellipsis">
❌ Проблемні сценарії
</span>
</a>
<nav class="md-nav" aria-label="❌ Проблемні сценарії">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#1-404-not-found" class="md-nav__link">
<span class="md-ellipsis">
Сценарій 1: 404 Not Found
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#2-405-method-not-allowed" class="md-nav__link">
<span class="md-ellipsis">
Сценарій 2: 405 Method Not Allowed
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#3-500-internal-server-error" class="md-nav__link">
<span class="md-ellipsis">
Сценарій 3: 500 Internal Server Error
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#4-200" class="md-nav__link">
<span class="md-ellipsis">
Сценарій 4: Зображення не відображається, але статус 200
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#-" class="md-nav__link">
<span class="md-ellipsis">
Чек-лист для швидкої перевірки
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#_5" class="md-nav__link">
<span class="md-ellipsis">
Наступні кроки після тестування
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="manual-test-plan-assets-proxy-debugging">Manual Test Plan — Assets Proxy Debugging<a class="headerlink" href="#manual-test-plan-assets-proxy-debugging" title="Permanent link">&para;</a></h1>
<h2 id="_1">Контекст<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h2>
<p>Після виправлення HEAD методу в city-service, логотипи та банери все ще не відображаються на фронті. Потрібно перевірити:</p>
<ol>
<li>Які URL генерує фронт</li>
<li>Що реально повертає Next.js route</li>
<li>Чи web-сервіс оновлений до останнього коду</li>
</ol>
<h2 id="1">Крок 1: Перевірка реальних запитів в браузері<a class="headerlink" href="#1" title="Permanent link">&para;</a></h2>
<h3 id="11-devtools">1.1 Відкрити DevTools<a class="headerlink" href="#11-devtools" title="Permanent link">&para;</a></h3>
<ol>
<li>Відкрити <code>https://daarion.space/microdao</code> у браузері</li>
<li>Відкрити DevTools (F12 або Cmd+Option+I)</li>
<li>Перейти на вкладку <strong>Network</strong></li>
<li>Фільтр: <strong>Img</strong> (або All + фільтр за назвою банера/логотипа)</li>
</ol>
<h3 id="12">1.2 Знайти "биті" зображення<a class="headerlink" href="#12" title="Permanent link">&para;</a></h3>
<ol>
<li>Знайти запити до зображень, які не завантажились (червоний статус або placeholder)</li>
<li>Клікнути по одному з них</li>
<li>Перевірити:</li>
<li><strong>Request URL</strong> (повний шлях)</li>
<li><strong>Status</strong> (200/404/500/...)</li>
<li><strong>Response headers</strong><code>Content-Type</code>, <code>Content-Length</code></li>
</ol>
<h3 id="13-url">1.3 Аналіз URL<a class="headerlink" href="#13-url" title="Permanent link">&para;</a></h3>
<h4 id="url-_nextimageurl">Якщо URL виглядає як <code>/_next/image?url=...</code><a class="headerlink" href="#url-_nextimageurl" title="Permanent link">&para;</a></h4>
<p>→ Використовується Next <code>&lt;Image&gt;</code> з оптимізацією</p>
<p><strong>Рішення:</strong>
- Або виставити <code>unoptimized</code> на компоненті
- Або налаштувати <code>next.config.ts</code> (domains) та переконатися, що <code>url</code> вказує на <code>/api/city/assets/proxy/...</code></p>
<h4 id="url-apicityassetsproxy">Якщо URL виглядає як <code>/api/city/assets/proxy/...</code><a class="headerlink" href="#url-apicityassetsproxy" title="Permanent link">&para;</a></h4>
<p>→ Це правильний шлях через proxy</p>
<p><strong>Далі:</strong>
1. Відкрити цей URL у новій вкладці браузера
2. Перевірити:
- Якщо картинка <strong>відкривається</strong> → проблема в Next <code>&lt;Image&gt;</code> / верстці
- Якщо не відкривається (404/500 або HTML-сторінка) → проблема в шляху або в проміжному Next route</p>
<h2 id="2-web-">Крок 2: Перевірка оновлення web-сервісу<a class="headerlink" href="#2-web-" title="Permanent link">&para;</a></h2>
<h3 id="21-web-">2.1 Перебудувати web-сервіс<a class="headerlink" href="#21-web-" title="Permanent link">&para;</a></h3>
<p>На сервері (там де docker-compose):</p>
<div class="codehilite"><pre><span></span><code><span class="nb">cd</span><span class="w"> </span>/opt/microdao-daarion
git<span class="w"> </span>pull
docker<span class="w"> </span>compose<span class="w"> </span>-f<span class="w"> </span>docker-compose.web.yml<span class="w"> </span>build<span class="w"> </span>web
docker<span class="w"> </span>compose<span class="w"> </span>-f<span class="w"> </span>docker-compose.web.yml<span class="w"> </span>up<span class="w"> </span>-d<span class="w"> </span>--no-deps<span class="w"> </span>web
</code></pre></div>
<h3 id="22-hard-refresh">2.2 Hard refresh в браузері<a class="headerlink" href="#22-hard-refresh" title="Permanent link">&para;</a></h3>
<p>Після перебудови:</p>
<ol>
<li>Відкрити <code>https://daarion.space/microdao</code></li>
<li>Зробити hard refresh:</li>
<li><strong>Windows/Linux:</strong> <code>Ctrl+Shift+R</code></li>
<li><strong>Mac:</strong> <code>Cmd+Shift+R</code></li>
</ol>
<h2 id="3-proxy">Крок 3: Перевірка шляху в proxy<a class="headerlink" href="#3-proxy" title="Permanent link">&para;</a></h2>
<h3 id="31-path">3.1 Скопіювати точний path<a class="headerlink" href="#31-path" title="Permanent link">&para;</a></h3>
<p>З Network tab в DevTools:</p>
<ol>
<li>Знайти запит до <code>/api/city/assets/proxy/...</code></li>
<li>Скопіювати точний path після <code>/api/city/assets/proxy/</code></li>
</ol>
<p>Наприклад: <code>microdao/banner/xyz.png</code></p>
<h3 id="32-city-service">3.2 Перевірка через city-service<a class="headerlink" href="#32-city-service" title="Permanent link">&para;</a></h3>
<p>На сервері (там де <code>city-service</code>):</p>
<div class="codehilite"><pre><span></span><code><span class="c1"># Перевірка через city-service (внутрішній Docker network)</span>
docker<span class="w"> </span><span class="nb">exec</span><span class="w"> </span>daarion-city-service<span class="w"> </span>curl<span class="w"> </span>-i<span class="w"> </span><span class="s2">&quot;http://localhost:7001/city/assets/proxy/microdao/banner/xyz.png&quot;</span>
</code></pre></div>
<h3 id="33-minio">3.3 Перевірка напряму у MinIO<a class="headerlink" href="#33-minio" title="Permanent link">&para;</a></h3>
<div class="codehilite"><pre><span></span><code><span class="c1"># Перевірка напряму у MinIO (якщо є NGINX/MinIO url)</span>
curl<span class="w"> </span>-I<span class="w"> </span><span class="s2">&quot;https://assets.daarion.space/daarion-assets/microdao/banner/xyz.png&quot;</span>
</code></pre></div>
<h3 id="34">3.4 Аналіз результатів<a class="headerlink" href="#34" title="Permanent link">&para;</a></h3>
<ul>
<li>Якщо другий запит (на MinIO) <strong>200</strong>, а перший ні → проблема в:</li>
<li><code>normalizeAssetUrl</code> неправильно обрізає/додає <code>daarion-assets/</code></li>
<li>Next route/NGINX "з'їдає" частину шляху</li>
</ul>
<p><strong>Примітка:</strong> Банери часто лежать в іншому префіксі, ніж логотипи, тому:
- Для логотипів <code>normalizeAssetUrl</code> може працювати (структура шляху співпала)
- Для банерів — ні (інший префікс, додатковий каталог, інший формат збереження в БД)</p>
<h2 id="4">Крок 4: Перевірка логів<a class="headerlink" href="#4" title="Permanent link">&para;</a></h2>
<h3 id="41-city-service">4.1 Логи city-service<a class="headerlink" href="#41-city-service" title="Permanent link">&para;</a></h3>
<div class="codehilite"><pre><span></span><code>docker<span class="w"> </span>logs<span class="w"> </span>daarion-city-service<span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span><span class="s2">&quot;assets/proxy&quot;</span>
</code></pre></div>
<p>Перевірити:
- Чи є запити на <code>/city/assets/proxy/...</code>
- Який статус (200/404/500)
- Чи є помилки</p>
<h3 id="42-web-">4.2 Логи web-сервісу<a class="headerlink" href="#42-web-" title="Permanent link">&para;</a></h3>
<div class="codehilite"><pre><span></span><code>docker<span class="w"> </span>logs<span class="w"> </span>daarion-web<span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span>-E<span class="w"> </span><span class="s2">&quot;assets|proxy|image&quot;</span>
</code></pre></div>
<p>Перевірити:
- Чи є запити на <code>/api/city/assets/proxy/...</code>
- Чи є помилки в Next.js route</p>
<h2 id="5-normalizeasseturl">Крок 5: Перевірка normalizeAssetUrl<a class="headerlink" href="#5-normalizeasseturl" title="Permanent link">&para;</a></h2>
<h3 id="51">5.1 Перевірка вхідних даних з БД<a class="headerlink" href="#51" title="Permanent link">&para;</a></h3>
<div class="codehilite"><pre><span></span><code><span class="c1"># Отримати URL з БД для конкретного MicroDAO</span>
curl<span class="w"> </span>-s<span class="w"> </span><span class="s2">&quot;https://daarion.space/api/city/microdao/daarion&quot;</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>jq<span class="w"> </span><span class="s1">&#39;{logo_url, banner_url}&#39;</span>
</code></pre></div>
<h3 id="52">5.2 Перевірка нормалізації<a class="headerlink" href="#52" title="Permanent link">&para;</a></h3>
<p>В браузері (Console в DevTools):</p>
<div class="codehilite"><pre><span></span><code><span class="c1">// Тест normalizeAssetUrl</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">testUrl</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;https://assets.daarion.space/daarion-assets/microdao/logo/2025/12/02/abc123.png&quot;</span><span class="p">;</span>
<span class="c1">// Очікуваний результат: &quot;/api/city/assets/proxy/microdao/logo/2025/12/02/abc123.png&quot;</span>
</code></pre></div>
<h2 id="_2">Очікувані результати<a class="headerlink" href="#_2" title="Permanent link">&para;</a></h2>
<h3 id="_3">✅ Успішний сценарій<a class="headerlink" href="#_3" title="Permanent link">&para;</a></h3>
<ol>
<li><strong>Network tab:</strong></li>
<li>URL: <code>/api/city/assets/proxy/microdao/logo/2025/12/02/abc123.png</code></li>
<li>Status: <code>200 OK</code></li>
<li>Content-Type: <code>image/png</code></li>
<li>
<p>Зображення відображається</p>
</li>
<li>
<p><strong>Логи city-service:</strong>
<code>INFO: "GET /city/assets/proxy/microdao/logo/2025/12/02/abc123.png HTTP/1.1" 200 OK</code></p>
</li>
<li>
<p><strong>Прямий доступ до URL:</strong></p>
</li>
<li>Відкривається зображення в новій вкладці</li>
</ol>
<h3 id="_4">❌ Проблемні сценарії<a class="headerlink" href="#_4" title="Permanent link">&para;</a></h3>
<h4 id="1-404-not-found">Сценарій 1: 404 Not Found<a class="headerlink" href="#1-404-not-found" title="Permanent link">&para;</a></h4>
<p><strong>Симптоми:</strong>
- Status: <code>404</code>
- Response: <code>Asset not found</code></p>
<p><strong>Можливі причини:</strong>
- Файл не існує в MinIO
- Неправильний path (зайвий/відсутній префікс <code>daarion-assets/</code>)
- Неправильна нормалізація URL</p>
<p><strong>Рішення:</strong>
- Перевірити чи файл існує в MinIO
- Перевірити <code>normalizeAssetUrl</code> контракт
- Перевірити шлях в БД</p>
<h4 id="2-405-method-not-allowed">Сценарій 2: 405 Method Not Allowed<a class="headerlink" href="#2-405-method-not-allowed" title="Permanent link">&para;</a></h4>
<p><strong>Симптоми:</strong>
- Status: <code>405</code>
- Response: <code>Method Not Allowed</code></p>
<p><strong>Можливі причини:</strong>
- HEAD метод не підтримується (має бути виправлено)
- Next.js route не має HEAD handler</p>
<p><strong>Рішення:</strong>
- Перевірити чи city-service має оновлений код
- Перевірити чи Next.js route має HEAD handler</p>
<h4 id="3-500-internal-server-error">Сценарій 3: 500 Internal Server Error<a class="headerlink" href="#3-500-internal-server-error" title="Permanent link">&para;</a></h4>
<p><strong>Симптоми:</strong>
- Status: <code>500</code>
- Response: <code>Internal Server Error</code></p>
<p><strong>Можливі причини:</strong>
- Помилка в city-service при доступі до MinIO
- Неправильні ENV змінні (MINIO_ENDPOINT, MINIO_ACCESS_KEY, тощо)</p>
<p><strong>Рішення:</strong>
- Перевірити логи city-service
- Перевірити ENV змінні в docker-compose</p>
<h4 id="4-200">Сценарій 4: Зображення не відображається, але статус 200<a class="headerlink" href="#4-200" title="Permanent link">&para;</a></h4>
<p><strong>Симптоми:</strong>
- Status: <code>200 OK</code>
- Content-Type правильний
- Але зображення не відображається</p>
<p><strong>Можливі причини:</strong>
- Next <code>&lt;Image&gt;</code> з оптимізацією блокує
- CSS/верстка приховує зображення
- CORS проблема</p>
<p><strong>Рішення:</strong>
- Перевірити чи використовується <code>&lt;img&gt;</code> або <code>&lt;Image&gt;</code>
- Перевірити CSS стилі
- Перевірити CORS headers</p>
<h2 id="-">Чек-лист для швидкої перевірки<a class="headerlink" href="#-" title="Permanent link">&para;</a></h2>
<ul>
<li>[ ] Web-сервіс перебудовано з останнім кодом</li>
<li>[ ] Hard refresh в браузері виконано</li>
<li>[ ] Network tab показує запити на <code>/api/city/assets/proxy/...</code></li>
<li>[ ] Статус запитів: <code>200 OK</code></li>
<li>[ ] Content-Type: <code>image/png</code> або <code>image/jpeg</code></li>
<li>[ ] Прямий доступ до URL відкриває зображення</li>
<li>[ ] Логи city-service показують успішні запити</li>
<li>[ ] <code>normalizeAssetUrl</code> правильно конвертує URL з БД</li>
</ul>
<h2 id="_5">Наступні кроки після тестування<a class="headerlink" href="#_5" title="Permanent link">&para;</a></h2>
<ol>
<li>Зафіксувати результати тестування</li>
<li>Якщо є проблеми — зібрати:</li>
<li>Точні URL з Network tab</li>
<li>Логи city-service та web-сервісу</li>
<li>Приклади URL з БД</li>
<li>Передати інформацію для подальшого виправлення</li>
</ol>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "../..", "features": ["navigation.sections", "navigation.instant", "content.code.copy"], "search": "../../assets/javascripts/workers/search.b8dbb3d2.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="../../assets/javascripts/bundle.3220b9d7.min.js"></script>
</body>
</html>