gendesign/tradein-mvp/backend/data/sql/191_account_quota_unlimited_flag.sql
lekss361 5f3579b8c2
All checks were successful
Deploy Trade-In / changes (push) Successful in 13s
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 1m2s
Deploy Trade-In / build-backend (push) Successful in 5m35s
Deploy Trade-In / deploy (push) Successful in 1m14s
feat(tradein/auth): восстановить доступ praktika + безлимит через данные вместо хардкода (#2544)
2026-07-26 23:29:53 +00:00

68 lines
4.7 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- Migration 191: account_quota_overrides.unlimited — безлимит как данные, не хардкод
--
-- WHY:
-- app.services.account_quota.is_unlimited() до этой миграции проверял ровно два
-- условия: роль admin ИЛИ literal `username == 'kopylov'` — захардкоженное сравнение
-- строки прямо в коде. Восстановление пилота praktika (ГК «Практика», доступ вернул
-- владелец продукта 2026-07-27 — см. auth/roles.yaml) с безлимитным грантом сделало
-- бы это хардкодом ВТОРОГО имени: не масштабируется (каждый следующий безлимитный
-- клиент требовал бы code-change + review + deploy вместо data-change) и плохо само
-- по себе как паттерн (магическая строка вместо конфигурируемых данных).
--
-- unlimited — отдельная boolean-колонка, а не sentinel-значение monthly_limit
-- (-1 / 0): `0` неоднозначен («ноль оценок в месяц» vs «без лимита»), explicit
-- boolean честнее и не требует специального парсинга в user_limit()/is_unlimited().
--
-- kopylov ПЕРЕНЕСЁН в данные этой же миграцией (хардкод в коде убран, не оставлен
-- параллельно) — единый источник правды для non-admin unlimited-аккаунтов вместо
-- двух параллельных механизмов (код-константа + таблица). Порядок деплоя
-- (SQL-миграция применяется РАНЬШЕ, чем стартует новый код — см.
-- .claude/rules/sql.md "Migration order") гарантирует, что строка kopylov уже в
-- таблице к моменту, когда новый is_unlimited() (без хардкода) начинает работать —
-- поведение kopylov не меняется ни на секунду простоя.
--
-- WHAT:
-- 1. account_quota_overrides.unlimited boolean NOT NULL DEFAULT false.
-- 2. Seed: kopylov (перенос хардкода) + praktika (новый грант, пилот восстановлен
-- 2026-07-27) — оба unlimited=true. monthly_limit=999999 — placeholder: get_status()
-- безусловно читает monthly_limit через user_limit() даже для unlimited-аккаунтов
-- (чтобы вернуть какое-то "limit" поле в /quota), а само enforcement для unlimited
-- обходит этот лимит (is_unlimited() гейтит раньше в check_and_raise()/increment()).
-- Значение просто не должно выглядеть абсурдным, если когда-либо surfaced напрямую.
--
-- IDEMPOTENCY:
-- ALTER TABLE ... ADD COLUMN IF NOT EXISTS (новая колонка) + INSERT ... ON CONFLICT
-- DO UPDATE (повторный прогон сходится к тому же состоянию, не дублирует строки).
--
-- Dependencies: 185_account_quota_overrides.sql (создаёт account_quota_overrides).
BEGIN;
ALTER TABLE account_quota_overrides
ADD COLUMN IF NOT EXISTS unlimited boolean NOT NULL DEFAULT false;
COMMENT ON COLUMN account_quota_overrides.unlimited IS
'Безлимитный грант (нет месячного лимита оценок) — читается '
'app.services.account_quota.is_unlimited(). Заменяет прежний хардкод username в коде.';
INSERT INTO account_quota_overrides (username, monthly_limit, unlimited, note)
VALUES ('kopylov', 999999, true,
'Личный аккаунт — безлимит перенесён из хардкода is_unlimited() в данные '
'(migration 191, 2026-07-27), поведение не изменилось')
ON CONFLICT (username) DO UPDATE SET
monthly_limit = EXCLUDED.monthly_limit,
unlimited = EXCLUDED.unlimited,
note = EXCLUDED.note,
updated_at = now();
INSERT INTO account_quota_overrides (username, monthly_limit, unlimited, note)
VALUES ('praktika', 999999, true,
'ГК «Практика» — пилот восстановлен 2026-07-27 (решение владельца продукта), '
'безлимитный грант')
ON CONFLICT (username) DO UPDATE SET
monthly_limit = EXCLUDED.monthly_limit,
unlimited = EXCLUDED.unlimited,
note = EXCLUDED.note,
updated_at = now();
COMMIT;