fix(mera/b2c): публичный лэндинг всё же дёргает /api/v1/me — инвариант «на публичной странице запроса к /me не происходит» нарушен #2631

Closed
opened 2026-08-02 13:08:23 +00:00 by lekss361 · 1 comment
Owner

Найдено post-deploy smoke'ом после мержа #2545 (периметр открыт, лэндинг живой на https://meraocenka.ru/).

Наблюдение

При анонимной загрузке https://meraocenka.ru/ в сетевой панели фиксируется:

GET /trade-in/api/v1/me → 404

Плюс GET /favicon.ico → 404 (косметика, отдельно).

Почему это важно

Это прямо противоречит инварианту, ради которого делался рефакторинг RouteGuard (вынос GuardedRoute в next/dynamic). В шапке tradein-mvp/frontend/src/app/mera-public/layout.tsx:23 записано:

useMe() — на публичной странице запроса к /api/v1/me не происходит вовсе

По факту происходит. Значит на публичной странице монтируется какой-то клиентский код из закрытого контура, которого там быть не должно.

Утечки нет — периметр meraocenka.ru отрабатывает штатно и отдаёт 404 (allowlist-by-default, /trade-in/api/* наружу не проксируется, подтверждено scripts/smoke-mera-perimeter.sh). То есть сегодня это шум в консоли посетителя, а не дыра.

Но: тот же лэндинг доступен и по пути gendsgn.ru/trade-in/mera-public, где /trade-in/api/v1/me проксируется и вернёт 401. И главное — сам факт означает, что «пустой по зависимостям» публичный бандл таким не является, а это была заявленная цель этапа 1.

Что проверить

  1. Кто именно инициирует вызов. Кандидаты: провайдер чата поддержки, TanStack Query с фоновой инвалидацией, что-то в корневом app/layout.tsx, что рендерится до/мимо RouteGuard.
  2. Не приезжает ли вместе с ним в публичный чанк ещё что-то из закрытого контура (lib/api, lib/sessionId, isPathAllowed, RBAC-поля) — ровно то, от чего уходили выносом GuardedRoute в отдельный чанк.
  3. Проверить размер и содержимое публичного бандла: next build + анализ чанка страницы /mera-public.

Definition of Done

  • На анонимной загрузке https://meraocenka.ru/ в сети нет ни одного запроса к /trade-in/api/*
  • Тест, фиксирующий это как инвариант (иначе отрегрессит при следующей правке layout)
  • /favicon.ico отдаётся (или явно объявлен ненужным)

Как воспроизвести

Открыть https://meraocenka.ru/ в чистом инкогнито, посмотреть Network. Запрос к /trade-in/api/v1/me виден сразу на загрузке.

Refs #2545

Найдено post-deploy smoke'ом после мержа #2545 (периметр открыт, лэндинг живой на https://meraocenka.ru/). ## Наблюдение При анонимной загрузке `https://meraocenka.ru/` в сетевой панели фиксируется: ``` GET /trade-in/api/v1/me → 404 ``` Плюс `GET /favicon.ico → 404` (косметика, отдельно). ## Почему это важно Это прямо противоречит инварианту, ради которого делался рефакторинг `RouteGuard` (вынос `GuardedRoute` в `next/dynamic`). В шапке `tradein-mvp/frontend/src/app/mera-public/layout.tsx:23` записано: > `useMe()` — на публичной странице запроса к `/api/v1/me` не происходит вовсе По факту происходит. Значит на публичной странице монтируется какой-то клиентский код из закрытого контура, которого там быть не должно. **Утечки нет** — периметр `meraocenka.ru` отрабатывает штатно и отдаёт 404 (allowlist-by-default, `/trade-in/api/*` наружу не проксируется, подтверждено `scripts/smoke-mera-perimeter.sh`). То есть сегодня это шум в консоли посетителя, а не дыра. **Но:** тот же лэндинг доступен и по пути `gendsgn.ru/trade-in/mera-public`, где `/trade-in/api/v1/me` проксируется и вернёт **401**. И главное — сам факт означает, что «пустой по зависимостям» публичный бандл таким не является, а это была заявленная цель этапа 1. ## Что проверить 1. Кто именно инициирует вызов. Кандидаты: провайдер чата поддержки, TanStack Query с фоновой инвалидацией, что-то в корневом `app/layout.tsx`, что рендерится до/мимо `RouteGuard`. 2. Не приезжает ли вместе с ним в публичный чанк ещё что-то из закрытого контура (`lib/api`, `lib/sessionId`, `isPathAllowed`, RBAC-поля) — ровно то, от чего уходили выносом `GuardedRoute` в отдельный чанк. 3. Проверить размер и содержимое публичного бандла: `next build` + анализ чанка страницы `/mera-public`. ## Definition of Done - [ ] На анонимной загрузке `https://meraocenka.ru/` в сети нет ни одного запроса к `/trade-in/api/*` - [ ] Тест, фиксирующий это как инвариант (иначе отрегрессит при следующей правке layout) - [ ] `/favicon.ico` отдаётся (или явно объявлен ненужным) ## Как воспроизвести Открыть `https://meraocenka.ru/` в чистом инкогнито, посмотреть Network. Запрос к `/trade-in/api/v1/me` виден сразу на загрузке. Refs #2545
Collaborator

Закрыто через PR #2644 (merged + прод-верифицировано). Итог по DoD:

  1. «Нет запросов к /trade-in/api/ на анонимной загрузке»* — в текущем коде утечка не воспроизводится: next build + standalone + разбор app-build-manifest показали чистый chunk-split #2545; live-проверка meraocenka.ru — во всех 12 чанках лэндинга строки /api/v1/me нет. Репорт issue почти наверняка ловил stale-образ (rapid-merge trap).
  2. Тест-инвариантscripts/check-mera-public-isolation.mjs (BFS по статическим импортам от корневого layout + mera-public; фейл с цепочкой при достижении useMe/lib/api/sessionId/isPathAllowed/GuardedRoute вне dynamic; проверен инъекцией нарушения) + blocking-шаг в CI frontend-checks.
  3. favicon — добавлен (мульти-размер, брендовые токены) + handle /favicon.ico в Caddy-периметре; live: GET https://meraocenka.ru/favicon.ico → 200.
Закрыто через PR #2644 (merged + прод-верифицировано). Итог по DoD: 1. **«Нет запросов к /trade-in/api/* на анонимной загрузке»** — в текущем коде утечка не воспроизводится: `next build` + standalone + разбор `app-build-manifest` показали чистый chunk-split #2545; live-проверка meraocenka.ru — во всех 12 чанках лэндинга строки `/api/v1/me` нет. Репорт issue почти наверняка ловил stale-образ (rapid-merge trap). 2. **Тест-инвариант** — `scripts/check-mera-public-isolation.mjs` (BFS по статическим импортам от корневого layout + mera-public; фейл с цепочкой при достижении useMe/lib/api/sessionId/isPathAllowed/GuardedRoute вне dynamic; проверен инъекцией нарушения) + blocking-шаг в CI `frontend-checks`. 3. **favicon** — добавлен (мульти-размер, брендовые токены) + `handle /favicon.ico` в Caddy-периметре; live: `GET https://meraocenka.ru/favicon.ico → 200`.
Sign in to join this conversation.
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#2631
No description provided.