[EPIC] tradein: DB-backed auth + ролевка manager→employee (login-форма, сессии, team-management) #2549

Open
opened 2026-07-30 06:16:55 +00:00 by lekss361 · 0 comments
Owner

Решение владельца продукта 2026-07-30. Уход от статичной auth (Caddy basic_auth + auth/roles.yaml, изменение = деплой) к DB-backed auth с ролевой моделью.

Требования

  • Users в Postgres (БД tradein), login-форма, server-side сессии (httponly cookie) — управление юзерами мгновенно, без деплоя.
  • Роли: admin (владелец, видит всё) / manager (мастер-аккаунт организации) / employee (сотрудник).
  • Manager: создаёт/блокирует аккаунты сотрудников СВОЕЙ организации, выставляет per-сотрудник месячную квоту оценок, видит счётчики использования и историю оценок своих сотрудников. Per-org изоляция (manager видит только своё поддерево manager_id).
  • Лимиты: переиспользуем account_quota.py + account_quota_overrides (migration 191).
  • Статистика: переиспользуем user_events + паттерны admin-дашбордов (LIVE 2026-07-13).
  • Cutover: dual-mode (AUTH_MODE=dual|db_only) — Caddy basic_auth остаётся на переходный период, снятие отдельным follow-up после bake.

Утверждённые решения

  • Server-side сессии (opaque token, таблица tradein_sessions), НЕ JWT — мгновенный revoke.
  • Пароли: bcrypt (новая dep bcrypt>=4.2.0), cost≥12, валидация длины ≤72 байт на API.
  • Org-модель: self-referential tradein_users.manager_id → tradein_users.id (без отдельной таблицы organizations).
  • Team-management: новый префикс /api/v1/team/* (НЕ /api/v1/admin/* — rbac_guard режет admin-пути для не-admin).
  • Миграция существующих: admin→admin; kopylov, praktika→manager (отдельные org); user1, user3–user10→employee БЕЗ org (свободные слоты под admin, раскидка по org вручную через UI при выдаче клиенту); user2 (Брусника) закрыт 2026-07-30 (#2548) → is_active=false; analyst/test-аккаунты — legacy, вне новой модели.
  • TTL сессии: 30 дней sliding. Первичный пароль сотрудника manager задаёт вручную в форме (без email-flow).
  • Rate-limit на login (username+IP), события login_success/login_faileduser_events.

Sub-issues (порядок/зависимости)

  1. Foundation: bcrypt + password.py + session-config — parallel-safe
  2. Schema: tradein_users + tradein_sessions (SQL 192_*) — parallel-safe
  3. Auth-core: login/logout + session middleware + dual-mode rbac_guard — после 1+2, deep-code-reviewer обязателен
  4. Team-API: CRUD сотрудников + квоты + статистика (org-scoped) — после 3
  5. Frontend: login-форма + session-aware RouteGuard — после 3
  6. Frontend: team-дашборд менеджера — после 4
  7. Seed-миграция существующих юзеров — после 2+4
  8. DevOps: SESSION_SECRET в .env.runtime + AUTH_MODE=dual ДО деплоя шага 3; финальный cutover (снятие Caddy-гейта) — отдельный follow-up после bake

Security-инварианты (проверяются в review каждого шага)

  • Org-изоляция: manager A не видит сотрудников manager B — обязательный негативный тест.
  • Cookie: httponly + secure + samesite=lax; Origin/Referer-check на POST/PATCH /team/*.
  • Не логировать raw-пароль (проверить логи/Sentry breadcrumbs на body login).
  • RateLimitMiddleware/RequestAuditMiddleware ключуются по x-authenticated-user — session-запросы должны прокидывать резолвленное имя (иначе не лимитируются/не аудируются).

План: tech-analyst 2026-07-30.

Решение владельца продукта 2026-07-30. Уход от статичной auth (Caddy basic_auth + `auth/roles.yaml`, изменение = деплой) к DB-backed auth с ролевой моделью. ## Требования - Users в Postgres (БД tradein), login-форма, server-side сессии (httponly cookie) — управление юзерами мгновенно, без деплоя. - Роли: `admin` (владелец, видит всё) / `manager` (мастер-аккаунт организации) / `employee` (сотрудник). - Manager: создаёт/блокирует аккаунты сотрудников СВОЕЙ организации, выставляет per-сотрудник месячную квоту оценок, видит счётчики использования и историю оценок своих сотрудников. Per-org изоляция (manager видит только своё поддерево `manager_id`). - Лимиты: переиспользуем `account_quota.py` + `account_quota_overrides` (migration 191). - Статистика: переиспользуем `user_events` + паттерны admin-дашбордов (LIVE 2026-07-13). - Cutover: dual-mode (`AUTH_MODE=dual|db_only`) — Caddy basic_auth остаётся на переходный период, снятие отдельным follow-up после bake. ## Утверждённые решения - Server-side сессии (opaque token, таблица `tradein_sessions`), НЕ JWT — мгновенный revoke. - Пароли: bcrypt (новая dep `bcrypt>=4.2.0`), cost≥12, валидация длины ≤72 байт на API. - Org-модель: self-referential `tradein_users.manager_id → tradein_users.id` (без отдельной таблицы organizations). - Team-management: новый префикс `/api/v1/team/*` (НЕ `/api/v1/admin/*` — rbac_guard режет admin-пути для не-admin). - Миграция существующих: `admin→admin`; `kopylov`, `praktika`→manager (отдельные org); `user1`, `user3–user10`→employee БЕЗ org (свободные слоты под admin, раскидка по org вручную через UI при выдаче клиенту); `user2` (Брусника) закрыт 2026-07-30 (#2548) → `is_active=false`; `analyst`/test-аккаунты — legacy, вне новой модели. - TTL сессии: 30 дней sliding. Первичный пароль сотрудника manager задаёт вручную в форме (без email-flow). - Rate-limit на login (username+IP), события `login_success`/`login_failed` → `user_events`. ## Sub-issues (порядок/зависимости) 1. Foundation: bcrypt + password.py + session-config — parallel-safe 2. Schema: `tradein_users` + `tradein_sessions` (SQL 192_*) — parallel-safe 3. Auth-core: login/logout + session middleware + dual-mode rbac_guard — после 1+2, **deep-code-reviewer обязателен** 4. Team-API: CRUD сотрудников + квоты + статистика (org-scoped) — после 3 5. Frontend: login-форма + session-aware RouteGuard — после 3 6. Frontend: team-дашборд менеджера — после 4 7. Seed-миграция существующих юзеров — после 2+4 8. DevOps: SESSION_SECRET в .env.runtime + AUTH_MODE=dual ДО деплоя шага 3; финальный cutover (снятие Caddy-гейта) — отдельный follow-up после bake ## Security-инварианты (проверяются в review каждого шага) - Org-изоляция: manager A не видит сотрудников manager B — обязательный негативный тест. - Cookie: httponly + secure + samesite=lax; Origin/Referer-check на POST/PATCH `/team/*`. - Не логировать raw-пароль (проверить логи/Sentry breadcrumbs на body login). - `RateLimitMiddleware`/`RequestAuditMiddleware` ключуются по `x-authenticated-user` — session-запросы должны прокидывать резолвленное имя (иначе не лимитируются/не аудируются). План: tech-analyst 2026-07-30.
lekss361 added the
auth
enhancement
tradein
labels 2026-07-30 06:23:36 +00:00
Sign in to join this conversation.
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#2549
No description provided.