[tradein][frontend][ux] Pilot-only юзер: авто-redirect на /trade-in/ после входа (вместо «Доступа нет») #799

Closed
opened 2026-05-30 17:22:46 +00:00 by bot-backend · 3 comments
Collaborator

Frontend/UX. Связано с RBAC (PR #585-587, auth/roles.yaml). Выявлено при UI-аудите 2026-05-30.

Проблема

Pilot-роль (kopylov, user1..10, pilottest) имеет доступ только к /trade-in/**, а / (главная gendesign) для неё запрещена backend-middleware. Сейчас при входе на корень https://gendsgn.ru/ такой юзер видит дед-энд «Доступа нет — учётная запись не привязана к роли» вместо рабочего инструмента.

Это бьёт по демо: kopylov (клиент Практики) — pilot-only. Если он откроет корень (а не точную ссылку /trade-in/), первый экран = «Доступа нет».

Ожидаемое

Если у пользователя единственная доступная зона — trade-in, после входа он автоматически редиректится на /trade-in/ (а не на «Доступа нет»).

Варианты реализации (выбрать)

  1. Caddy — по роли (header X-Authenticated-User → lookup в roles) redir / /trade-in/ 302 для pilot. Минус: Caddy не знает роль из коробки, нужен mapping.
  2. Главный фронт — страница-заглушка «Доступа нет» вместо дед-энда делает /me → если роль pilot и единственный allowed scope = trade-in → window.location = '/trade-in/'. Минимальная правка, не трогает инфру.
  3. Backend — на корневой 403 для pilot отдавать redirect-хинт (allowed_areas), фронт по нему уводит.

Рекомендация: вариант 2 (быстро, в одном фронте, без Caddy-логики). Учесть петлю: не редиректить если уже на trade-in.

DoD

  • pilot-only юзер на / → авто-redirect на /trade-in/, без «Доступа нет».
  • admin/multi-scope — поведение не меняется (остаётся на главной).
  • нет redirect-loop.

Связано

#585, #586, #587 (RBAC), UI-аудит 2026-05-30.

> Frontend/UX. Связано с RBAC (PR #585-587, `auth/roles.yaml`). Выявлено при UI-аудите 2026-05-30. ## Проблема Pilot-роль (kopylov, user1..10, pilottest) имеет доступ **только к `/trade-in/**`**, а `/` (главная gendesign) для неё запрещена backend-middleware. Сейчас при входе на корень `https://gendsgn.ru/` такой юзер видит дед-энд **«Доступа нет — учётная запись не привязана к роли»** вместо рабочего инструмента. **Это бьёт по демо**: kopylov (клиент Практики) — pilot-only. Если он откроет корень (а не точную ссылку `/trade-in/`), первый экран = «Доступа нет». ## Ожидаемое Если у пользователя **единственная доступная зона — trade-in**, после входа он **автоматически редиректится на `/trade-in/`** (а не на «Доступа нет»). ## Варианты реализации (выбрать) 1. **Caddy** — по роли (header `X-Authenticated-User` → lookup в roles) `redir / /trade-in/ 302` для pilot. Минус: Caddy не знает роль из коробки, нужен mapping. 2. **Главный фронт** — страница-заглушка «Доступа нет» вместо дед-энда делает `/me` → если роль pilot и единственный allowed scope = trade-in → `window.location = '/trade-in/'`. Минимальная правка, не трогает инфру. 3. **Backend** — на корневой 403 для pilot отдавать redirect-хинт (`allowed_areas`), фронт по нему уводит. Рекомендация: **вариант 2** (быстро, в одном фронте, без Caddy-логики). Учесть петлю: не редиректить если уже на trade-in. ## DoD - pilot-only юзер на `/` → авто-redirect на `/trade-in/`, без «Доступа нет». - admin/multi-scope — поведение не меняется (остаётся на главной). - нет redirect-loop. ## Связано #585, #586, #587 (RBAC), UI-аудит 2026-05-30.
bot-backend added the
scope/frontend
priority/p2
tradein
labels 2026-05-30 17:22:46 +00:00
lekss361 added the
status/ready
label 2026-05-30 18:00:56 +00:00
bot-frontend self-assigned this 2026-05-30 18:11:12 +00:00
bot-frontend added
status/wip
and removed
status/ready
labels 2026-05-30 18:11:14 +00:00
bot-frontend added
status/review
and removed
status/wip
labels 2026-05-30 18:23:43 +00:00
Collaborator

Working on this in PR #812 (чистый, 1 файл). PR #809 был polluted параллельным окном — закрыт/удалён.

Working on this in PR #812 (чистый, 1 файл). PR #809 был polluted параллельным окном — закрыт/удалён.
bot-frontend added
status/qa
and removed
status/review
labels 2026-05-30 18:26:03 +00:00
Collaborator

RouteGuard pilot-redirect смержен в main (через #809, merge by lekss361 18:23). Дубликат-PR #812 закрыт. → status/qa.

NB: #809 из-за гонки shared-.git index с параллельным auto-analyst окном содержал лишние .claude/* файлы (auto-analyst WIP) поверх RouteGuard — они тоже попали в main этим merge. Сам RouteGuard-фикс корректен и изолирован.

QA smoke: pilot-логин (kopylov/pilottest) на / → авто-redirect /trade-in/; admin на / остаётся; нет redirect-loop.

RouteGuard pilot-redirect смержен в main (через #809, merge by lekss361 18:23). Дубликат-PR #812 закрыт. → status/qa. NB: #809 из-за гонки shared-`.git` index с параллельным auto-analyst окном содержал лишние `.claude/*` файлы (auto-analyst WIP) поверх RouteGuard — они тоже попали в main этим merge. Сам RouteGuard-фикс корректен и изолирован. QA smoke: pilot-логин (kopylov/pilottest) на `/` → авто-redirect `/trade-in/`; admin на `/` остаётся; нет redirect-loop.
Collaborator

QA PASS — RouteGuard pilot-redirect (PR #809, merged 18:23). Live-смоук на gendsgn.ru:

  • pilot-only (user7) на / → авто-redirect https://gendsgn.ru/trade-in, БЕЗ «Доступа нет», лендит на рабочий Trade-In.
  • admin на / → остаётся на https://gendsgn.ru/ (полный главный апп: Аналитика/Site Finder/Trade-In/Концепция/Админ), НЕ редиректит. (ветка не срабатывает: isPathAllowed("/")=true).
  • redirect-loop нет (loop-guard !pathname.startsWith("/trade-in") + replace → back-кнопка не возвращает на дед-энд).

Code (RouteGuard.tsx) корректен и изолирован: redirect-ветка только внутри !isPathAllowed, под window defined + path не под /trade-in + trade-in разрешён роли.

status/done, closing. Демо-релевант (kopylov pilot-only — теперь не упрётся в «Доступа нет» на корне).


⚠️ Side-finding (НЕ блокирует #799, но требует внимания человека) — config-pollution в main через этот merge:

PR #809 кроме RouteGuard.tsx затащил в main 3 protected pipeline-guard файла (race shared-.git index с параллельным auto-analyst окном):

  • .claude/agents/_autonomous_pickup.md (+16)
  • .claude/agents/auto-analyst.md (+27/-1)
  • .claude/commands/work-as-analyst.md (+10)

Эти файлы — в never-auto-merge списке (git-pr.md Auto-merge policy: _autonomous_pickup.md claim/kill-switch/merge-FSM contract + любой work-as-*.md self-extending guard → изменения только через явный human review как СВОЙ change, не бандлом во frontend-PR).

Контент сам по себе валиден и полезен (auto-analyst hardening из реальных инцидентов: token-limit guard на list_repo_issues, parallel-window дедуп, file:line-verify-before-write, ready-only-on-final-body, один loop-механизм). Merge сделан человеком (lekss361, PR был needs-human+status/blocked), т.е. human был в петле — это НЕ bot self-merge guard'а. Но изменения въехали как побочка #799, а не своим reviewed-PR.

Рекомендация человеку: подтвердить, что эти 3 .claude/* правки — финальные/намеренные (не оборванный WIP параллельного окна), либо вынести/перекоммитить отдельным change. Демо-канун — стоит свериться, что guard-контракты не побились.

✅ **QA PASS** — RouteGuard pilot-redirect (PR #809, merged 18:23). Live-смоук на `gendsgn.ru`: - **pilot-only** (`user7`) на `/` → авто-redirect `https://gendsgn.ru/trade-in`, БЕЗ «Доступа нет», лендит на рабочий Trade-In. ✅ - **admin** на `/` → остаётся на `https://gendsgn.ru/` (полный главный апп: Аналитика/Site Finder/Trade-In/Концепция/Админ), НЕ редиректит. ✅ (ветка не срабатывает: `isPathAllowed("/")=true`). - **redirect-loop** нет (loop-guard `!pathname.startsWith("/trade-in")` + `replace` → back-кнопка не возвращает на дед-энд). ✅ Code (RouteGuard.tsx) корректен и изолирован: redirect-ветка только внутри `!isPathAllowed`, под `window` defined + path не под /trade-in + trade-in разрешён роли. → `status/done`, closing. **Демо-релевант** (kopylov pilot-only — теперь не упрётся в «Доступа нет» на корне). --- ⚠️ **Side-finding (НЕ блокирует #799, но требует внимания человека) — config-pollution в main через этот merge:** PR #809 кроме `RouteGuard.tsx` затащил в `main` **3 protected pipeline-guard файла** (race shared-`.git` index с параллельным auto-analyst окном): - `.claude/agents/_autonomous_pickup.md` (+16) - `.claude/agents/auto-analyst.md` (+27/-1) - `.claude/commands/work-as-analyst.md` (+10) Эти файлы — в **never-auto-merge** списке (`git-pr.md` Auto-merge policy: `_autonomous_pickup.md` claim/kill-switch/merge-FSM contract + любой `work-as-*.md` self-extending guard → изменения только через явный human review как СВОЙ change, не бандлом во frontend-PR). **Контент сам по себе валиден и полезен** (auto-analyst hardening из реальных инцидентов: token-limit guard на `list_repo_issues`, parallel-window дедуп, file:line-verify-before-write, ready-only-on-final-body, один loop-механизм). Merge сделан человеком (`lekss361`, PR был `needs-human`+`status/blocked`), т.е. human был в петле — это НЕ bot self-merge guard'а. Но изменения въехали как побочка #799, а не своим reviewed-PR. **Рекомендация человеку:** подтвердить, что эти 3 `.claude/*` правки — финальные/намеренные (не оборванный WIP параллельного окна), либо вынести/перекоммитить отдельным change. Демо-канун — стоит свериться, что guard-контракты не побились.
bot-qa added
status/done
and removed
status/qa
labels 2026-05-30 18:34:22 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
3 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#799
No description provided.