tradein/auth 7: Seed-миграция существующих юзеров в tradein_users #2557

Closed
opened 2026-07-30 06:21:57 +00:00 by lekss361 · 1 comment
Owner

Часть эпика #2549 (шаг 7/8). Блокирован: после #2551 (schema); семантика manager_id — из #2554. Worker: database-expert.

Org-карта (утверждена владельцем 2026-07-30)

username role manager_id is_active примечание
admin admin NULL true владелец
kopylov manager NULL true отдельный клиент
praktika manager NULL true ГК «Практика», unlimited-квота уже в account_quota_overrides
user1, user3–user10 employee NULL true свободные слоты БЕЗ org — раскидка по организациям вручную через UI при выдаче клиенту
user2 employee NULL false «Брусника», закрыт 2026-07-30 (#2548)
admintest/pilottest/analysttest/expiredtest НЕ мигрировать: legacy QA-фикстуры остаются в roles.yaml (dual-mode fallback)

Scope

  • tradein-mvp/backend/data/sql/19X_tradein_users_seed.sql (номер перепроверить на дубль): INSERT ... ON CONFLICT (username) DO UPDATE (idempotent), password_hash = NULL — пароли admin проставит вручную через team-UI (#2556) после деплоя; NULL-hash = логин через сессию невозможен, работает только легаси Caddy fallback (dual-mode).

DoD

Ре-запуск не дублирует; SELECT username, role, manager_id, is_active соответствует карте; ни один активный юзер не потерял доступ (dual-mode: Caddy-путь работает до установки пароля).

Часть эпика #2549 (шаг 7/8). **Блокирован**: после #2551 (schema); семантика manager_id — из #2554. Worker: database-expert. ## Org-карта (утверждена владельцем 2026-07-30) | username | role | manager_id | is_active | примечание | |---|---|---|---|---| | admin | admin | NULL | true | владелец | | kopylov | manager | NULL | true | отдельный клиент | | praktika | manager | NULL | true | ГК «Практика», unlimited-квота уже в account_quota_overrides | | user1, user3–user10 | employee | NULL | true | свободные слоты БЕЗ org — раскидка по организациям вручную через UI при выдаче клиенту | | user2 | employee | NULL | **false** | «Брусника», закрыт 2026-07-30 (#2548) | | admintest/pilottest/analysttest/expiredtest | — | — | — | НЕ мигрировать: legacy QA-фикстуры остаются в roles.yaml (dual-mode fallback) | ## Scope - `tradein-mvp/backend/data/sql/19X_tradein_users_seed.sql` (номер перепроверить на дубль): `INSERT ... ON CONFLICT (username) DO UPDATE` (idempotent), `password_hash = NULL` — пароли admin проставит вручную через team-UI (#2556) после деплоя; NULL-hash = логин через сессию невозможен, работает только легаси Caddy fallback (dual-mode). ## DoD Ре-запуск не дублирует; `SELECT username, role, manager_id, is_active` соответствует карте; ни один активный юзер не потерял доступ (dual-mode: Caddy-путь работает до установки пароля).
lekss361 added the
auth
scope/db
tradein
labels 2026-07-30 06:23:38 +00:00
Author
Owner

⚠️ Требование из deep-review PR #2561 (auth-core) — обязательно учесть в этом seed-PR.

rbac._propagate_authenticated_user кодирует session-username через encode("latin-1", "replace"). Это убрало 500-ки на не-ASCII логинах, но породило тихую коллизию: кириллические username одинаковой длины схлопываются в одну строку ('иванов' и 'петров''??????'). Два таких юзера получат один downstream-identity → общий created_by, общая квота, взаимный IDOR, общий support-тред.

Сегодня недостижимо (tradein_users пустая), но именно этот seed заводит первых юзеров. Поэтому в рамках #2557:

  • либо CHECK (username ~ '^[A-Za-z0-9._-]+$') на tradein_users.username (предпочтительно — fail-closed на уровне схемы),
  • либо fail-closed ветка в rbac на не-кодируемом username (401 вместо тихой подмены).

Все seed-логины из org-карты выше ASCII, так что CHECK ничего не ломает.

⚠️ Требование из deep-review PR #2561 (auth-core) — **обязательно учесть в этом seed-PR**. `rbac._propagate_authenticated_user` кодирует session-username через `encode("latin-1", "replace")`. Это убрало 500-ки на не-ASCII логинах, но породило тихую коллизию: кириллические username **одинаковой длины схлопываются в одну строку** (`'иванов'` и `'петров'` → `'??????'`). Два таких юзера получат один downstream-identity → общий `created_by`, общая квота, взаимный IDOR, общий support-тред. Сегодня недостижимо (`tradein_users` пустая), но именно этот seed заводит первых юзеров. Поэтому в рамках #2557: - либо `CHECK (username ~ '^[A-Za-z0-9._-]+$')` на `tradein_users.username` (предпочтительно — fail-closed на уровне схемы), - либо fail-closed ветка в rbac на не-кодируемом username (401 вместо тихой подмены). Все seed-логины из org-карты выше ASCII, так что CHECK ничего не ломает.
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#2557
No description provided.