|
All checks were successful
CI / changes (pull_request) Successful in 8s
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 52s
rbac_guard гейтил только /api/v1/admin/* → revoked (role=expired, roles.yaml paths:[] deny:/**) и узко-скоупленные аккаунты сохраняли полный non-admin API-доступ (напр. POST /api/v1/search — экспорт листингов + estimate-quota). is_path_allowed (roles.yaml paths/deny) существовал, но НЕ вызывался (0 callers). Fix: после admin-гейта вызываем is_path_allowed(role, external_path) для всех non-bootstrap путей. roles.yaml globs — внешние (Caddy срезал /trade-in), поэтому восстанавливаем внешний путь (_EXTERNAL_PREFIX + path). Bootstrap-пути /me и /brand/* исключены — expired ДОЛЖЕН получить role=expired через /me (trial-экран) и брендинг; без исключения trial-UX сломался бы (expired paths:[] → 403 на /me). На сбой парса — fail-open + громкий лог (не лочим платящего pilot из-за конфиг-бага). roles.yaml НЕ меняю — только энфорсю уже задекларированную политику. pilot/admin/ analyst доступ сохранён (verified), expired теперь 403 на non-admin API. Тесты: +5 scope-кейсов (expired denied search/trade-in, allowed me/brand; pilot/ admin/analyst preserved) — 31 passed. Тест-harness middleware — mirror, обновлён. |
||
|---|---|---|
| .. | ||
| api | ||
| core | ||
| observability | ||
| schemas | ||
| services | ||
| tasks | ||
| __init__.py | ||
| main.py | ||
| scheduler_main.py | ||