feat(rbac): analyst role + §19 audit-log middleware (#962) #1163

Merged
bot-backend merged 1 commit from feat/analyst-role-audit-962 into main 2026-06-08 07:16:52 +00:00
Collaborator

Что

#962 (EPIC18, ТЗ §19): роль analyst + §19 audit-log.

По решению Anton: analyst = доступ ко ВСЕМУ кроме admin/управления (скрейперы/sync/админ-эндпоинты). Данные (сделки, инсайды, экспорт) — видит. → data-ACL не нужен → нет зависимости от #948 (циклическую разорвал).

Содержимое

  • auth/roles.yaml: роль analyst (paths: /**, deny: /admin/** + /api/v1/admin/** + /trade-in/api/v1/admin/**) + QA-юзер analysttest.
  • core/auth.py (+ tradein-зеркало): Role Literal += analyst.
  • Backend-hard: существующий rbac_guard уже 403'ит любой non-admin на /api/v1/admin/* → добавление роли авто-блокирует analyst (verified тестом: analyst→403 admin-api, 200 parcels-api). Новый enforcement не нужен.
  • §19 audit-log: data/sql/144_audit_log.sql (идемпотентная) + core/audit_middleware.py — best-effort middleware логирует чувствительные действия (analyze/forecast/export) в audit_log ПОСЛЕ ответа. Сбой аудита НЕ ломает запрос (2-слойный try/except + finally close). Зарегистрирован INNER к rbac_guard → аудитятся только авторизованные (403 короткозамыкается до аудита). classify_path матчит export до forecast (anchored).

Качество

  • code-reviewer: APPROVE — оба гейта: audit truly best-effort (exploding-write тест → 200; no leak; audited-paths-only, без latency на всё API) + middleware order верный (rbac outer). Параметризованный INSERT (no injection, no ::), миграция 144 идемпотентна (CHECK guarded, NN корректный), no-regression (rbac_guard байт-в-байт), без новых deps. 610 тестов (4 analyst-rbac + 11 audit). parcels.py не тронут (NON-colliding с ИРД-треком).

Follow-up

  • devops: реальные analyst-логины добавить в caddy/users.caddy.snippet (Caddy basic_auth) — иначе Caddy не отдаст X-Authenticated-User. (analysttest уже рядом с admintest/pilottest.)
  • ACL на инсайды — когда #948 построит сущность insight (поле зарезервировано).

Refs #962.

## Что #962 (EPIC18, ТЗ §19): роль **`analyst`** + **§19 audit-log**. По решению Anton: **analyst = доступ ко ВСЕМУ кроме admin/управления** (скрейперы/sync/админ-эндпоинты). Данные (сделки, инсайды, экспорт) — видит. → **data-ACL не нужен → нет зависимости от #948** (циклическую разорвал). ## Содержимое - `auth/roles.yaml`: роль `analyst` (`paths: /**`, `deny: /admin/** + /api/v1/admin/** + /trade-in/api/v1/admin/**`) + QA-юзер `analysttest`. - `core/auth.py` (+ tradein-зеркало): `Role` Literal += `analyst`. - **Backend-hard:** существующий `rbac_guard` уже 403'ит любой non-admin на `/api/v1/admin/*` → добавление роли авто-блокирует analyst (verified тестом: analyst→403 admin-api, 200 parcels-api). Новый enforcement не нужен. - **§19 audit-log:** `data/sql/144_audit_log.sql` (идемпотентная) + `core/audit_middleware.py` — best-effort middleware логирует чувствительные действия (analyze/forecast/export) в `audit_log` ПОСЛЕ ответа. Сбой аудита НЕ ломает запрос (2-слойный try/except + finally close). Зарегистрирован INNER к rbac_guard → аудитятся только авторизованные (403 короткозамыкается до аудита). `classify_path` матчит export до forecast (anchored). ## Качество - `code-reviewer`: ✅ APPROVE — оба гейта: audit truly best-effort (exploding-write тест → 200; no leak; audited-paths-only, без latency на всё API) + middleware order верный (rbac outer). Параметризованный INSERT (no injection, no `::`), миграция 144 идемпотентна (CHECK guarded, NN корректный), no-regression (rbac_guard байт-в-байт), без новых deps. **610 тестов** (4 analyst-rbac + 11 audit). `parcels.py` не тронут (NON-colliding с ИРД-треком). ## Follow-up - **devops:** реальные analyst-логины добавить в `caddy/users.caddy.snippet` (Caddy basic_auth) — иначе Caddy не отдаст `X-Authenticated-User`. (`analysttest` уже рядом с admintest/pilottest.) - ACL на инсайды — когда #948 построит сущность insight (поле зарезервировано). Refs #962.
bot-backend added the
scope/backend
GG-форсайт
site-finder
labels 2026-06-08 07:16:50 +00:00
bot-backend added 1 commit 2026-06-08 07:16:51 +00:00
feat(rbac): add analyst role + §19 audit-log middleware (#962)
Some checks failed
CI / changes (push) Successful in 6s
CI / frontend-tests (push) Has been skipped
CI / changes (pull_request) Successful in 6s
Deploy Trade-In / changes (push) Successful in 7s
Deploy / changes (push) Successful in 6s
CI / frontend-tests (pull_request) Has been skipped
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 36s
Deploy / build-backend (push) Successful in 1m39s
Deploy / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 48s
Deploy / build-worker (push) Successful in 2m41s
Deploy / deploy (push) Failing after 4s
Deploy Trade-In / deploy (push) Successful in 47s
CI / backend-tests (push) Successful in 6m38s
CI / backend-tests (pull_request) Successful in 6m30s
86828d0388
EPIC18/§19. analyst sees everything (deals, insights, exports, site-finder,
analytics, concept) EXCEPT admin/data-management. Enforcement is backend-hard
(the existing rbac_guard already 403s any non-admin role on /api/v1/admin/*, so
adding the role auto-blocks it) + frontend (deny_paths via /me) + audit.

§19 audit: new best-effort HTTP middleware logs the sensitive actions
(analyze / forecast / forecast-export) to a new audit_log table after the
response. Audit failures never break or delay-fail the request (2-layer
try/except + finally close). Registered INNER to rbac_guard so only authorized
requests are audited (a 403 short-circuits before audit). classify_path matches
export before forecast (anchored).

- auth/roles.yaml: analyst role (paths /**, deny admin-mgmt) + analysttest QA user
- core/auth.py (+ tradein mirror): Role Literal += analyst
- core/audit_middleware.py (new) + main.py registration
- data/sql/144_audit_log.sql (idempotent; auto-applies)
- tests: analyst rbac (403 admin / 200 parcels) + 11 audit cases

No data-level ACL (analyst sees data per policy) -> no #948 dependency. No new
deps. parcels.py untouched. Real analyst logins still need adding to
caddy/users.caddy.snippet (devops).

Refs #962.
bot-backend merged commit 86828d0388 into main 2026-06-08 07:16:52 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
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#1163
No description provided.