feat(tradein/auth): восстановить доступ praktika + безлимит через данные вместо хардкода #2544

Merged
lekss361 merged 2 commits from feat/tradein-praktika-unlimited into main 2026-07-26 23:29:54 +00:00
Owner

Запрос

Артём просит включить аккаунту praktika безлимитный доступ.

Важная деталь: у praktika сейчас роль expired — пробный доступ закончился 27 июня. Это объясняет, почему последняя оценка у него 26 июня: аккаунт не перестал пользоваться, ему закрыли доступ. Поэтому задача не сводится к снятию лимита, нужно ещё вернуть доступ.

Что сделано

1. Роль восстановлена. auth/roles.yaml: praktika: expiredpilot. Пилотный скоуп не менялся — только раздел Trade-In, без аналитики и админки. Сделано по образцу восстановления user2 («Брусника», 13 июля).

2. Безлимит стал управляться данными, а не хардкодом. Раньше is_unlimited содержал if username == "kopylov": return True — конкретный клиент прописан в коде сервиса квот. Добавлять туда второе имя было бы удвоением проблемы.

Теперь в account_quota_overrides есть явная колонка unlimited boolean. Явная колонка, а не числовой сентинел: 0 неоднозначен — это «ноль оценок» или «без лимита»?

kopylov перенесён в данные той же миграцией, а не оставлен параллельно в коде — иначе источников правды было бы два. Поведение не меняется.

Порядок деплоя проверен отдельно, потому что от него зависит, не потеряет ли реальный клиент безлимит на время выката: в deploy-tradein.yml миграции применяются на строке 372 с явным комментарием «ДО app», а контейнеры пересоздаются на строке 532. То есть строка kopylov окажется в таблице раньше, чем стартует новый код. Окна без безлимита нет.

3. praktika получил безлимит той же миграцией, с осмысленной пометкой.

Побочная находка

test_rbac.py использовал praktika как единственную живую фикстуру роли expired — после восстановления доступа в конфиге не осталось ни одного истёкшего пользователя, и два теста потеряли бы смысл. Добавлен expiredtest: expired по образцу существующих тестовых аккаунтов, тесты переключены на него.

Test plan

  • uv run pytest -q2699 passed, 8 skipped
  • ruff check с проектным конфигом — чисто
  • Тесты: praktika не упирается в лимит и не получает 429; обычный пилот упирается; kopylov сохранил безлимит уже через данные; /quota не отдаёт «0 из 0» для безлимитного; идемпотентность миграции
  • Тесты квот переписаны с позиционных моков на маршрутизацию по тексту SQL — иначе они стали бы хрупкими, потому что is_unlimited теперь то ходит в базу, то нет
  • Миграция к живой базе не применялась — идемпотентность подтверждена только структурно
  • Не проверялось сквозным путём, что praktika реально логинится и видит интерфейс — только серверная логика
## Запрос Артём просит включить аккаунту `praktika` безлимитный доступ. **Важная деталь:** у `praktika` сейчас роль `expired` — пробный доступ закончился 27 июня. Это объясняет, почему последняя оценка у него 26 июня: аккаунт не перестал пользоваться, ему закрыли доступ. Поэтому задача не сводится к снятию лимита, нужно ещё вернуть доступ. ## Что сделано **1. Роль восстановлена.** `auth/roles.yaml`: `praktika: expired` → `pilot`. Пилотный скоуп не менялся — только раздел Trade-In, без аналитики и админки. Сделано по образцу восстановления `user2` («Брусника», 13 июля). **2. Безлимит стал управляться данными, а не хардкодом.** Раньше `is_unlimited` содержал `if username == "kopylov": return True` — конкретный клиент прописан в коде сервиса квот. Добавлять туда второе имя было бы удвоением проблемы. Теперь в `account_quota_overrides` есть явная колонка `unlimited boolean`. Явная колонка, а не числовой сентинел: `0` неоднозначен — это «ноль оценок» или «без лимита»? `kopylov` **перенесён в данные той же миграцией**, а не оставлен параллельно в коде — иначе источников правды было бы два. Поведение не меняется. **Порядок деплоя проверен отдельно, потому что от него зависит, не потеряет ли реальный клиент безлимит на время выката:** в `deploy-tradein.yml` миграции применяются на строке 372 с явным комментарием «ДО app», а контейнеры пересоздаются на строке 532. То есть строка `kopylov` окажется в таблице раньше, чем стартует новый код. Окна без безлимита нет. **3. `praktika` получил безлимит** той же миграцией, с осмысленной пометкой. ## Побочная находка `test_rbac.py` использовал `praktika` как **единственную живую фикстуру** роли `expired` — после восстановления доступа в конфиге не осталось ни одного истёкшего пользователя, и два теста потеряли бы смысл. Добавлен `expiredtest: expired` по образцу существующих тестовых аккаунтов, тесты переключены на него. ## Test plan - [x] `uv run pytest -q` — **2699 passed**, 8 skipped - [x] `ruff check` с проектным конфигом — чисто - [x] Тесты: `praktika` не упирается в лимит и не получает 429; обычный пилот упирается; `kopylov` сохранил безлимит уже через данные; `/quota` не отдаёт «0 из 0» для безлимитного; идемпотентность миграции - [x] Тесты квот переписаны с позиционных моков на маршрутизацию по тексту SQL — иначе они стали бы хрупкими, потому что `is_unlimited` теперь то ходит в базу, то нет - [ ] Миграция к живой базе не применялась — идемпотентность подтверждена только структурно - [ ] Не проверялось сквозным путём, что `praktika` реально логинится и видит интерфейс — только серверная логика
lekss361 added 1 commit 2026-07-26 22:51:12 +00:00
fix(tradein/auth): restore praktika access + data-driven unlimited quota grants
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 10s
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 56s
3e4c93c91e
praktika (ГК «Практика») role expired -> pilot: доступ восстановлен по решению
владельца продукта. Добавлен expiredtest QA-аккаунт, чтобы test_rbac.py сохранил
regression-покрытие role=expired (praktika больше не годится как fixture).

account_quota.is_unlimited() больше не хардкодит username == 'kopylov': грант
безлимитных оценок теперь читается из account_quota_overrides.unlimited (migration
191) — единый источник правды для всех non-admin unlimited-аккаунтов. kopylov
перенесён в данные той же миграцией (поведение не меняется, деплой применяет SQL
раньше кода); praktika получил такой же грант.

unlimited выбран как явная boolean-колонка, а не sentinel monthly_limit (-1/0),
т.к. 0 неоднозначен ("ноль оценок" vs "без лимита").
bot-backend added 1 commit 2026-07-26 23:28:09 +00:00
Merge remote-tracking branch 'forgejo/main' into feat/tradein-praktika-unlimited
All checks were successful
CI / changes (pull_request) Successful in 11s
CI Trade-In / changes (pull_request) Successful in 11s
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 1m5s
466928b0b5
lekss361 merged commit 5f3579b8c2 into main 2026-07-26 23:29:54 +00:00
lekss361 deleted branch feat/tradein-praktika-unlimited 2026-07-26 23:29:54 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
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#2544
No description provided.