Decision 2026-05-26: pilot аккаунты пилот-программы получают доступ ТОЛЬКО к разделу Trade-In (оценка вторички). Landing, Analytics, Site Finder, Concept — admin-only. Изменения: - `auth/roles.yaml` — `pilot.paths` сужен с 7 путей до 2: `/trade-in/**` + `/trade-in/api/v1/**`. Deny список оставлен как есть для defense-in-depth. - `backend/tests/test_rbac.py` + tradein mirror — переписан `test_is_path_allowed_pilot_excludes_admin` → `_pilot_only_tradein`: pilot allowed только /trade-in, denied на /, /analytics, /site-finder, /concept, /api/v1/parcels. Тест `test_get_user_scope_pilot` ассертит что /trade-in/** в allowed, / и /analytics/** нет. - `frontend/src/lib/__tests__/isPathAllowed.test.ts` — те же parity обновления (pilot allowed list сужен, denied list расширен landing + non-tradein путями). - `caddy/users.caddy.snippet` — синхронизирован с VPS-актуальной версией: regen'd user1..user10 hashes + admintest/pilottest entries (locally added на VPS 2026-05-26 для QA RBAC). Без этого `deploy.yml` делал бы `git reset --hard` и стирал бы локальные правки. - `auth/roles.yaml` users: блок — также добавлены `admintest: admin` и `pilottest: pilot` (mirror VPS local edit). Эффект для UX: - pilot открывает `/` → frontend RouteGuard → fullscreen «Доступа нет» (т.к. `/` не в allowed_paths). - pilot TopNav на main frontend — только пункт «Trade-In» виден (остальные `/analytics`, `/site-finder`, `/concept`, `/admin` отфильтрованы `isPathAllowed`). - pilot открывает `/trade-in` → работает как раньше. - admin (admintest, kopylov-если бы был admin) — без изменений. Backend middleware path-enforcement не делает — security guarantee по-прежнему на admin-only endpoints (`/api/v1/admin/*` блочится для пилота). Path-filter на UI-уровне через `allowed_paths` / `deny_paths` в /me response. Pilot login flow: после basic_auth → main frontend → useMe → /me → scope (allowed=/trade-in/**). RouteGuard на `/` → NoAccessScreen. Pilot должен bookmark'ить `https://gendsgn.ru/trade-in/` напрямую. Follow-up: можно добавить auto-redirect в RouteGuard — если pilot landing-path → redirect на первый allowed (`/trade-in`). Отдельный PR. Tests: 20/20 pass на обоих backend стэках, ruff clean.
57 lines
2.1 KiB
YAML
57 lines
2.1 KiB
YAML
# RBAC roles + user → role mapping.
|
|
#
|
|
# Single source of truth for both main backend (backend/app/core/auth.py) and
|
|
# tradein backend (tradein-mvp/backend/app/core/auth.py). Mounted into both
|
|
# containers at /app/auth/roles.yaml via docker-compose bind-mount.
|
|
#
|
|
# Glob semantics (fnmatch-based, see app.core.auth.is_path_allowed):
|
|
# - "/**" → matches any path (admin scope).
|
|
# - "/foo/**" → matches /foo, /foo/, /foo/bar, /foo/bar/baz/...
|
|
# - "/foo" → matches exactly /foo.
|
|
#
|
|
# A path is allowed iff (1) it matches one of `paths` AND (2) it does NOT match
|
|
# any pattern in `deny`. `deny` overrides `paths` (deny-by-default within
|
|
# match scope).
|
|
#
|
|
# Username list MUST match exactly the 12 entries in caddy/users.caddy.snippet
|
|
# — Caddy basic_auth sets X-Authenticated-User from {http.auth.user.id}, and
|
|
# unknown users hit /me with 403 ("user not in roles config").
|
|
#
|
|
# Last updated: 2026-05-26 (pilot scope narrowed to /trade-in/** only — decision
|
|
# 2026-05-26: pilot аккаунты пилот-программы видят ТОЛЬКО раздел Trade-In;
|
|
# Analytics / Site Finder / Concept / landing — admin-only).
|
|
|
|
roles:
|
|
admin:
|
|
paths:
|
|
- "/**"
|
|
deny: []
|
|
pilot:
|
|
# Pilot имеет доступ ТОЛЬКО к разделу Trade-In (оценка вторички).
|
|
# Landing (/), analytics, site-finder, concept, остальной /api/v1/* — закрыты.
|
|
# Backend middleware всё равно пропускает known users на все non-admin paths
|
|
# (path-level enforcement делает frontend RouteGuard через `allowed_paths`),
|
|
# но для UX/security принципов keep deny список explicit.
|
|
paths:
|
|
- "/trade-in/**"
|
|
- "/trade-in/api/v1/**"
|
|
deny:
|
|
- "/admin/**"
|
|
- "/api/v1/admin/**"
|
|
- "/trade-in/api/v1/admin/**"
|
|
|
|
users:
|
|
admin: admin
|
|
kopylov: pilot
|
|
user1: pilot
|
|
user2: pilot
|
|
user3: pilot
|
|
user4: pilot
|
|
user5: pilot
|
|
user6: pilot
|
|
user7: pilot
|
|
user8: pilot
|
|
user9: pilot
|
|
user10: pilot
|
|
admintest: admin # temp QA 2026-05-26
|
|
pilottest: pilot # temp QA 2026-05-26
|