feat(tradein): dev/CI preview route for a11y+lighthouse (#801) #803

Merged
bot-reviewer merged 1 commit from feat/801-preview-route into main 2026-05-30 17:37:40 +00:00
Collaborator

Что

Dev/CI-only preview-маршрут «денежного экрана» на статичной фикстуре — разблокирует автоматический UI-аудит (axe/lighthouse). Решает #801.

Проблема: axe/lighthouse требуют отрендеренную страницу; live trade-in за auth-gate, локальный фронт без бэкенда = белый экран (RouteGuard висит на pending /me).

Как

  • src/app/ui-preview/estimate/{page,fixture}.tsx — рендерит реальные компоненты результата (HeroSummary + CianValuationCard + Distribution + Deals + StreetDeals + Exposure + PriceTrend) на фикстуре AggregatedEstimate, полностью оффлайн: собственный QueryClient с засеянным фейковым /meuseMe/useBrand резолвятся без сети.
  • RouteGuard — bypass /ui-preview/* под флагом (RBAC к preview не применяется).
  • Гейт NEXT_PUBLIC_ENABLE_PREVIEW=1 (иначе notFound) — в проде по умолчанию OFF. Папка ui-preview (не _-prefix — Next трактует _* как private/non-routable, отсюда первый 404).

Проверено (локально, флаг включён)

  • Страница рендерится оффлайн (скриншот: весь money-screen).
  • axe (wcag2a/aa) baseline — 2 serious:
    • color-contrast: teal #14b8a6 на #f6f7f9, 14px → 2.32 (надо ≥4.5) — подпись в card-meta.
    • svg-img-alt: recharts scatter-точки (role="img") без aria-label/title (3 ноды).
    • 23 passes.
  • tsc --noEmit clean, pre-commit passed.

Использование

echo NEXT_PUBLIC_ENABLE_PREVIEW=1 > tradein-mvp/frontend/.env.local
cd tradein-mvp/frontend && npm run dev
# → http://localhost:3000/ui-preview/estimate

CI: собрать с NEXT_PUBLIC_ENABLE_PREVIEW=1, next start, навести axe/lighthouse на /ui-preview/estimate.

Followup

Найденные axe-дефекты (контраст teal, svg-alt recharts) — отдельными issue после merge.

Refs #801.

## Что Dev/CI-only preview-маршрут «денежного экрана» на статичной фикстуре — разблокирует автоматический UI-аудит (axe/lighthouse). Решает #801. **Проблема**: axe/lighthouse требуют отрендеренную страницу; live trade-in за auth-gate, локальный фронт без бэкенда = белый экран (RouteGuard висит на pending `/me`). ## Как - `src/app/ui-preview/estimate/{page,fixture}.tsx` — рендерит реальные компоненты результата (HeroSummary + CianValuationCard + Distribution + Deals + StreetDeals + Exposure + PriceTrend) на фикстуре `AggregatedEstimate`, **полностью оффлайн**: собственный `QueryClient` с засеянным фейковым `/me` → `useMe`/`useBrand` резолвятся без сети. - `RouteGuard` — bypass `/ui-preview/*` под флагом (RBAC к preview не применяется). - Гейт **`NEXT_PUBLIC_ENABLE_PREVIEW=1`** (иначе `notFound`) — в проде по умолчанию OFF. Папка `ui-preview` (не `_`-prefix — Next трактует `_*` как private/non-routable, отсюда первый 404). ## Проверено (локально, флаг включён) - Страница рендерится оффлайн (скриншот: весь money-screen). - **axe (wcag2a/aa) baseline — 2 serious**: - `color-contrast`: teal `#14b8a6` на `#f6f7f9`, 14px → **2.32** (надо ≥4.5) — подпись в card-meta. - `svg-img-alt`: recharts scatter-точки (`role="img"`) без `aria-label`/title (3 ноды). - 23 passes. - `tsc --noEmit` clean, pre-commit passed. ## Использование ``` echo NEXT_PUBLIC_ENABLE_PREVIEW=1 > tradein-mvp/frontend/.env.local cd tradein-mvp/frontend && npm run dev # → http://localhost:3000/ui-preview/estimate ``` CI: собрать с `NEXT_PUBLIC_ENABLE_PREVIEW=1`, `next start`, навести axe/lighthouse на `/ui-preview/estimate`. ## Followup Найденные axe-дефекты (контраст teal, svg-alt recharts) — отдельными issue после merge. Refs #801.
bot-backend added 1 commit 2026-05-30 17:35:47 +00:00
UI-аудит инструментами (axe/lighthouse) требует отрендеренную контентную
страницу. Live trade-in за auth-gate, локальный фронт без бэкенда = белый экран
(RouteGuard висит на pending /me). Добавлен оффлайн preview «денежного экрана».

- src/app/ui-preview/estimate/{page,fixture}.tsx — рендерит реальные компоненты
  результата (HeroSummary + Cian + Distribution + Deals + StreetDeals + Exposure
  + PriceTrend) на статичной фикстуре AggregatedEstimate, без сети: свой
  QueryClient с засеянным фейковым /me (useMe/useBrand резолвятся оффлайн).
- RouteGuard: bypass /ui-preview/* под флагом (RBAC к preview не применяется).
- Гейт: NEXT_PUBLIC_ENABLE_PREVIEW=1 (иначе notFound) — в проде по умолчанию off.
  Папка ui-preview (НЕ _-prefix: Next трактует _* как private/non-routable).

Проверено локально (NEXT_PUBLIC_ENABLE_PREVIEW=1): страница рендерится оффлайн,
axe (wcag2a/aa) дал baseline — 2 serious: color-contrast (teal #14b8a6 на светлом
2.32<4.5) + svg-img-alt (recharts scatter без accessible text). tsc clean.

Refs #801. Followup: фиксы найденных axe-дефектов отдельными issue.
bot-backend added the
scope/frontend
status/review
tradein
labels 2026-05-30 17:35:47 +00:00
bot-reviewer approved these changes 2026-05-30 17:37:27 +00:00
bot-reviewer left a comment
Collaborator

APPROVE

Dev/CI preview-маршрут (#801). RBAC-bypass проверил тщательно (ключевой риск).

Security (RBAC bypass) — корректно gated

  • ENABLED = NEXT_PUBLIC_ENABLE_PREVIEW === "1"; page if (!ENABLED) notFound() → 404 в проде. RouteGuard-bypass if (ENABLE_PREVIEW && rawPath.startsWith("/ui-preview"))тоже flag-gated. Double-gated: в проде (флаг unset, build-time) и bypass-условие false, И страница notFound → маршрут мёртв, RBAC не затронут.
  • Фейковый PREVIEW_USER (admin) засеян только в QueryClient самой preview-страницы (render-scoped) чтобы useMe/useBrand резолвились оффлайн — не privilege escalation (нет реального /me, нет токена, scope = preview-поддерево).
  • Fixture = только фейк-данные (preview-UUID, "preview"-URL) — secrets в бандле нет.

Correctness — рендерит реальные result-компоненты на фикстуре полностью оффлайн — ровно что нужно axe/lighthouse. ui-preview-папка (не _-prefix, который Next трактует non-routable). tsc clean, pre-commit passed. axe baseline (2 serious: teal-контраст 2.32, recharts svg-alt) задокументированы как post-merge follow-up — их обнаружение валидирует работу маршрута.

Scope — RouteGuard.tsx = app auth-код (не bot-pipeline/self-extending файл); RBAC-правка — легитимный предмет #801, gated, без расширения bot-merge-прав. Нет backend, нет secrets.

Verdict: APPROVE (#801). Advisory: прод-build/deploy НЕ должен выставлять NEXT_PUBLIC_ENABLE_PREVIEW=1 (deploy-config дисциплина) — ops/QA подтвердить; 2 axe-находки → follow-up issues.

<!-- gendesign-review-bot: sha=9649135 verdict=approve --> ✅ APPROVE Dev/CI preview-маршрут (#801). RBAC-bypass проверил тщательно (ключевой риск). **Security (RBAC bypass) — корректно gated** - `ENABLED = NEXT_PUBLIC_ENABLE_PREVIEW === "1"`; page `if (!ENABLED) notFound()` → 404 в проде. RouteGuard-bypass `if (ENABLE_PREVIEW && rawPath.startsWith("/ui-preview"))` — **тоже** flag-gated. **Double-gated**: в проде (флаг unset, build-time) и bypass-условие false, И страница notFound → маршрут мёртв, RBAC не затронут. - Фейковый `PREVIEW_USER` (admin) засеян **только в QueryClient самой preview-страницы** (render-scoped) чтобы `useMe`/`useBrand` резолвились оффлайн — **не** privilege escalation (нет реального `/me`, нет токена, scope = preview-поддерево). - Fixture = только фейк-данные (preview-UUID, "preview"-URL) — secrets в бандле нет. **Correctness** — рендерит реальные result-компоненты на фикстуре полностью оффлайн — ровно что нужно axe/lighthouse. `ui-preview`-папка (не `_`-prefix, который Next трактует non-routable). tsc clean, pre-commit passed. axe baseline (2 serious: teal-контраст 2.32, recharts svg-alt) задокументированы как post-merge follow-up — их обнаружение валидирует работу маршрута. **Scope** — RouteGuard.tsx = app auth-код (не bot-pipeline/self-extending файл); RBAC-правка — легитимный предмет #801, gated, без расширения bot-merge-прав. Нет backend, нет secrets. **Verdict: ✅ APPROVE** (#801). Advisory: прод-build/deploy НЕ должен выставлять `NEXT_PUBLIC_ENABLE_PREVIEW=1` (deploy-config дисциплина) — ops/QA подтвердить; 2 axe-находки → follow-up issues.
bot-reviewer merged commit 046febcae8 into main 2026-05-30 17:37:40 +00:00
bot-reviewer deleted branch feat/801-preview-route 2026-05-30 17:37:41 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#803
No description provided.