Модель прав для уровней клиентов: планы, лимиты, флаги
Спроектируйте модель прав с понятными схемами для планов, лимитов и флагов, чтобы поддержка и админы могли безопасно менять доступ клиентов без инженеров.

Почему командам нужна модель прав
Если вы продаёте более одного уровня, рано или поздно получите одно и то же тикет: «Клиент X оплатил Pro, но не может получить доступ к Функции Y». Без чёткой системы поддержка не может это исправить напрямую. Простая смена доступа превращается в задачу для инженера.
Более серьёзная проблема — непоследовательность. Правила доступа разбросаны по продукту: галочка в админке, хардкод в API, заметка в таблице и одноразовое обновление базы данных в прошлом квартале. Клиенты видят разное поведение в разных местах, и никто не уверен, какое правило — истинное.
Модель прав даёт единый источник истины о том, кто что может делать, на основе их плана и любых одобренных исключений. Она делает уровни предсказуемыми (чтобы ценообразование оставалось понятным), при этом оставляет место для реальной жизни: временный апгрейд, увеличение квоты или пилотная функция для одного аккаунта.
«Изменять без инженеров» должно быть конкретным. На практике:
- Поддержка меняет доступ в админ‑инструменте, редактируя данные, а не запрашивая деплой.
- Продукт читает те же данные о правах везде (бекенд, веб‑приложение, мобильное приложение).
- Исключения могут быть ограничены по времени и обратимы, а не постоянными костылями.
- Все изменения логируются с указанием кто, когда и зачем их сделал.
Например, клиент на тарифе Business достигает лимита активных пользователей в загруженный сезон. Поддержка должна иметь возможность дать +10 мест на 14 дней, а система должна автоматически отменить это по истечении периода. Инженеры нужны только когда вы добавляете совершенно новую возможность, а не для рутинных корректировок доступа.
Базовые элементы: клиенты, планы и права
Хорошая модель прав начинается с нескольких ясных объектов и четкой ответственности. Если эти базовые понятия расплывчаты, поддержка будет просить инженеров «ещё одно исключение» каждую неделю.
Вот простой набор строительных блоков:
- Customer (аккаунт/тенант): компания или человек, использующий ваш продукт.
- Subscription: коммерческие отношения (триал, активная, отменённая), часто связаны с биллингом.
- Plan: именованный уровень (Free, Pro, Enterprise), задающий дефолтный доступ.
- Entitlement (право): фактическое разрешённое поведение, получаемое из плана плюс любые переопределения.
Оценка прав — не то же самое, что биллинг. Биллинг отвечает «сколько и когда мы взимаем плату», права — «что этот клиент может делать прямо сейчас». Клиент может быть не оплачен, но в грейс‑периоде, или полностью оплачен, но временно заблокирован по соответствию. Держите эти решения раздельно, чтобы финансы могли исправлять счёта, не меняя продуктовый доступ.
Несколько групп полагаются на эту схему:
- Продукт определяет, что означают планы.
- Поддержка нуждается в безопасных контролях для предоставления или снятия доступа.
- Sales ops требует последовательных правил для сделок и продления.
- Финансы хотят надёжного соответствия между тем, что продано, и тем, какой доступ был предоставлен.
Установите границы с самого начала. Делайте содержимое планов и переопределения клиентов конфигурируемыми (чтобы поддержка могла действовать), но держите основное поведение в коде. Примеры «основного поведения»: как вы считаете оставшуюся квоту, как обрабатываете истёкшие триалы и какие действия обязательно аудируются.
Флаги, лимиты и квоты: выберите правильный тип
Большинство проблем с уровнями решаются, когда правильно назвать право. Существуют три распространённых типа, и каждый отвечает на разный вопрос:
- Булевы флаги: функция включена или выключена? Пример: export_enabled = true.
- Числовые лимиты: сколько разрешено одновременно? Пример: max_seats = 10.
- Квоты: сколько может быть использовано за период времени? Пример: api_calls_per_month = 100000.
Флаги подходят для функций, которые не должны работать частично. Если экспорт выключен, спрячьте кнопку и блокируйте эндпоинт. Лимиты хороши для «вместимости», которая не сбрасывается: места, проекты, сохранённые виды.
Квоты требуют дополнительного внимания, потому что время имеет значение. Тикеты поддержки быстро исчезают, когда правило сброса задокументировано и видно в админке.
Область (scope) — ещё одно решение, которое предотвращает путаницу. Флаг вроде «SAML SSO enabled» обычно на уровне аккаунта. «Max projects» может быть на уровне рабочей области. «Can run reports» может быть на уровне пользователя, если вы продаёте дополнения по ролям.
Для квот выберите одно правило сброса и придерживайтесь его:
- Никогда (пожизненные кредиты)
- Ежемесячно (календарный месяц)
- Скользящее окно (последние 30 дней)
- По платёжному периоду (соответствует циклу выставления счёта)
Если правило сброса меняется в зависимости от плана, считайте само правило частью права, а не табуированной информацией.
Практичная схема базы данных для прав
Дружелюбная для поддержки модель прав обычно остаётся «скучной»: несколько таблиц, ясные ключи и записи с временными границами, которые можно аудировать. Цель — позволить администраторам менять доступ, редактируя данные, а не пушить код.
Начните с четырёх основных таблиц: plans, plan_entitlements, customers и customer_overrides.
- Plans описывают уровни (Free, Pro, Enterprise).
- Plan entitlements описывают, что включает каждый план.
- Customers указывают на план.
- Overrides покрывают исключения для одного клиента без изменения плана для всех.
Компактная реляционная форма, которая хорошо работает:
plans:id,name,description,is_activeplan_entitlements:id,plan_id,key,type,value,unit,reset_policy,effective_from,effective_to,created_bycustomers:id,name,plan_id,status,created_atcustomer_overrides:id,customer_id,key,type,value,unit,reset_policy,effective_from,effective_to,created_by
Поля права должны быть согласованными между таблицами. Используйте стабильный key, например seats, api_calls или sso_enabled. type помогает упростить оценку (например: flag, limit, quota). Явно храните unit (например, users, requests, GB). Для квот делайте reset_policy однозначным (monthly, daily, never).
Переопределения должны вести себя как allowlist с датами. Если у клиента активное переопределение sso_enabled=true, оно должно иметь приоритет над значением плана, но только в пределах effective_from и effective_to. Это позволяет «дать 10 дополнительных мест на 14 дней» одной строкой, которая сама истечёт.
Как должна работать оценка прав
Оценка прав — это небольшой фрагмент кода или сервис, отвечающий на один вопрос: «Разрешено ли этому клиенту это делать прямо сейчас?» Если эта часть прогнозируема, всё остальное легче в эксплуатации.
Используйте чёткий порядок приоритета и не отклоняйтесь от него: customer override > plan value > system default. Это позволяет поддержке давать временные исключения без изменения плана и даёт инженерам безопасные дефолты, когда ничего не настроено.
Практичный поток оценки:
- Определите клиента/аккаунт по аутентифицированной сессии (не из тела запроса).
- Загрузите активный план клиента и любые активные переопределения.
- Для заданного ключа возвращайте переопределение, если оно есть; иначе значение плана; иначе системный дефолт.
- Если ключ нигде не найден, для проверок доступа отказывайте (fail closed), а для отображения в UI используйте разумный дефолт.
- Если ключ неизвестен (не в реестре), считайте это ошибкой конфигурации, отказывайте и логируйте для последующей проверки.
Кеширование важно, потому что права проверяются постоянно. Кешируйте разрешённые права по клиенту с коротким TTL и явным номером версии. Инвалидируйте кеш при изменениях: смена плана, изменение определения плана, переопределения клиента или статус клиента (trial, grace, blocked). Простая схема — кешировать по customer_id + entitlements_version, где правки поддержки увеличивают версию, чтобы изменения появились быстро.
Безопасность мультиаренды — бескомпромиссна. Каждый запрос должен фильтроваться по текущему id аккаунта, и каждый кеш должен быть привязан к этому id. Не ищите права по email, домену или имени плана в одиночку.
Пошагово: удобный для поддержки рабочий процесс изменения доступа
Удобный для поддержки рабочий процесс делает модель гибкой, не превращая каждый крайний случай в задачу для инженеров. Цель — делать изменения безопасно, оставлять след и подтверждать опыт клиента.
Безопасный поток для поддержки
Начните с поиска правильной записи клиента и подтверждения того, что он просит и зачем. «Нужно ещё два места на неделю» — это не то же самое, что «мы подписали допсоглашение на более высокий тариф». Хорошая админка показывает в одном месте текущий план, статус клиента и любые активные переопределения.
Перед изменением проверьте реальное использование относительно текущего лимита или квоты. Многие запросы отпадают, когда видно, что аккаунт не дошёл до лимита, или проблема в другом (например, отслеживание использования не обновляется).
Когда нужно скорректировать доступ, предпочтительнее создать явное переопределение, чем редактировать план. Делайте переопределения узкими (один флаг или один лимит), добавляйте владельца и причину, и по умолчанию ставьте дату истечения. Временные исключения обычны и легко забываются.
Простой чеклист в админке обычно достаточен:
- Подтвердить личность клиента, текущий план и причину запроса.
- Просмотреть текущее использование относительно соответствующего лимита.
- Применить ограниченное переопределение и установить срок истечения.
- Добавить заметки и ссылку на тикет/кейc.
- Проверить результат в продукте через имперсонацию или тестовый аккаунт.
Всегда проверяйте изменение так, как это увидит клиент. Если у вас есть имперсонация, делайте очевидным, когда она включена, и логируйте её.
Апгрейды, даунгрейды, триалы и грейс‑периоды
Большинство проблем с правами возникает при изменениях: клиент апгрейдится в середине периода, карта не проходит или триал заканчивается в выходной. Если правила расплывчаты, поддержка начинает гадать, и инженеры вовлекаются.
Для апгрейдов держите всё просто: доступ обычно должен меняться сразу, а финансовые детали остаются в биллинге. Модель прав должна слушать событие биллинга вроде «plan changed» и применять новые права плана сразу. Если биллинг делает проратацию — ок, но не вплетайте расчёт прорытации в модель прав.
Даунгрейды — источник сюрпризов. Выберите понятное поведение и сделайте его видимым для поддержки:
- Grace period: сохранять более высокий доступ до конца оплаченного периода.
- Только чтение: разрешать просматривать/экспортировать данные, но блокировать новые записи.
- Жёсткая остановка: блокировать функцию сразу (лучше для рисковых функций).
- Поведение при превышении лимита: разрешать использование, но блокировать создание при превышении квоты.
- Сохранение данных: хранить данные, но отключать доступ до апгрейда.
Триалы лучше делать отдельным планом, а не булевым флагом на клиенте. Дайте триал‑плану явные флаги и лимиты и правило автоистечения. Когда триал закончится, переведите клиента на дефолтный план (обычно «Free») и примените поведение даунгрейда, которое вы определили.
Грейс‑периоды полезны при сбоях оплаты. Короткое «просрочено» окно (например, 3–7 дней) даёт время исправить платёж, не теряя доступ в середине рабочего дня. Рассматривайте грейс как временное переопределение, а не как отдельное имя плана.
Практический совет: не привязывайте права к маркетинговым названиям типа “Pro” или “Enterprise”. Держите стабильные внутренние ID планов (например, plan_basic_v2), чтобы вы могли переименовывать уровни, не ломая правил.
Аудируемость и контроли безопасности
Если поддержка может менять доступ без инженеров, нужен бумажный след. Хорошая модель прав относится к каждому изменению как к задокументированному решению, а не к тихой правке.
Для каждого переопределения фиксируйте актёра, бизнес‑причину и метки времени. Если в организации требуется, добавьте шаг утверждения для чувствительных изменений.
Что записывать при любом изменении
Держите лог простым, чтобы его реально использовали:
created_byиcreated_atapproved_byиapproved_at(опционально)reason(короткий текст, например “paid add-on” или “incident credit”)previous_valueиnew_valueexpires_at
Контроли безопасности предотвращают аварии до продакшна. Поставьте ограничители в админке и в базе: ограничьте максимальные значения, блокируйте отрицательные числа и требуйте дату истечения для крупных изменений (например, повышение API calls в 10x).
Откат и готовность к аудиту
Поддержка будет ошибаться. Дайте им одну кнопку «вернуть к дефолтам плана», которая очищает переопределения на уровне клиента и возвращает аккаунт к назначенному плану.
Для аудита делайте историю лёгкой для экспорта по клиенту и по диапазону дат. Простой CSV с причиной и утверждением решает большинство вопросов без привлечения инженеров.
Пример: клиент на «Pro» нуждается в 30 дополнительных местах на неделю для мероприятия. Поддержка ставит seats_override=60 с expires_at следующей пятницы, добавляет причину «event» и получает одобрение менеджера. После истечения система автоматически возвращает 30, и весь след доступен для ревизии, если биллинг будет оспаривать факт.
Частые ошибки, которые делают модель прав болезненной
Самый быстрый способ сломать модель прав — позволить ей расти бессистемно. Несколько ранних упрощений могут превратиться в месяцы тикетов поддержки и «почему этот клиент может это делать?».
Одна распространённая ошибка — рассредоточение проверок по разным частям приложения. Если разные места по‑разному принимают решение о доступе, вы получите противоречия. Централизуйте оценку прав за одной функцией или сервисом, и пусть UI и API обращаются к нему.
Ещё одна ловушка — смешивание состояния биллинга и доступа. «Оплачен» не то же самое, что «разрешён». Биллинг имеет ретраи, чардже‑беки, триалы и расчёты, которые могут быть позже. Держите биллинговые события отдельно и переводите их в права по явным правилам (включая грейс‑периоды), чтобы крайние случаи не блокировали пользователей или не давали доступ навсегда.
Избегайте опоры на единый строковый «tier» вроде «basic» или «pro» как на единственный источник истины. Уровни со временем меняются, и бывают исключения. Храните явные флаги и лимиты, чтобы поддержка могла дать одну возможность, не даруя всё, что идёт с меткой уровня.
Переопределения нужны, но бесконтрольные переопределения превращаются в невидимый долг. Требуйте владельца, причину и ссылку на тикет. Поощряйте даты истечения или даты ревью. Делайте переопределения узкими и легко аудитируемыми.
Квоты тоже ломаются, когда правила сброса неясны. Определите, что значит «в месяц» (календарный месяц против скользящих 30 дней), что происходит при апгрейде и переносится ли неиспользованная квота. Применяйте эти правила в бэкенде, а не только в UI, чтобы изменения поддержки не приводили к несогласованному поведению между вебом и мобильным приложением.
Быстрый чеклист перед запуском
Перед выпуском модели прав пройдитесь с теми, кто будет её использовать каждый день: поддержкой, customer success и теми, кто на дежурстве.
Убедитесь, что каждая функция сопоставлена с одним стабильным ключом права и ясным владельцем. Избегайте дубликатов типа reports_enabled vs reporting_enabled. Убедитесь, что каждый план имеет явные дефолты для ключей, которые вы выпускаете. Если ключ отсутствует — безопасно ошибайтесь (обычно deny) и сигнализируйте внутренне, чтобы это исправили.
Для операций подтвердите, что рабочий процесс действительно удобен:
- Поддержка может видеть эффективный доступ (дефолт плана плюс переопределение) без SQL.
- Переопределения логируются с указанием кто, что поменял, почему и когда это истекает.
- Квоты имеют видимое правило сброса и способ показать текущее использование.
Тест реальности: попросите поддержку дать 14‑дневный аддон одному клиенту, затем убрать его. Если они сделают это уверенно за менее чем две минуты, вы близки к цели.
Пример сценария: уровни с временным исключением
Представьте, что у вас три уровня, и каждый задаёт несколько явных прав, которые показываются в продукте и проверяются на бэкенде.
- Free: 1 проект, 3 пользователя, 200 экспортов/месяц, базовый лимит API, 7‑дневные логи аудита.
- Team: 10 проектов, 25 пользователей, 2 000 экспортов/месяц, более высокий лимит API, 30‑дневные логи аудита.
- Business: неограниченно проектов, 200 пользователей, 10 000 экспортов/месяц, максимальный лимит API, 180‑дневные логи аудита, SSO включён.
Теперь клиент Team говорит: «Нам нужно 8 000 экспортов в этом месяце для квартального отчёта. Можете помочь на 30 дней?» Это как раз случай, когда временное переопределение лучше, чем перевод на новый план.
Поддержка открывает карточку клиента, добавляет переопределение export_monthly_limit = 8000 и ставит expires_at через 30 дней. В заметке пишет: «Approved by Alex (Sales), 30‑day exception for Q4 reporting.»
Со стороны клиента должно произойти два эффекта:
- UI отражает новый лимит (например, счётчик использования и надпись «Экспортов осталось» обновляются).
- Экспорты продолжают работать, пока они не достигнут 8 000 за месяц.
Если они превысят лимит, увидят понятное сообщение типа: «Достигнут лимит экспорта (8 000/месяц). Обратитесь в поддержку или апгрейдните тариф, чтобы увеличить лимит.»
После даты истечения переопределение перестаёт действовать автоматически, и клиент возвращается к лимиту плана Team без чьих‑то напоминаний.
Следующие шаги: реализуйте и итеративно улучшайте, не замедляя поддержку
Начните с превращения «фич» в небольшой каталог прав. Дайте каждому элементу ясный ключ, тип (флаг vs лимит vs квота) и дефолтное значение для каждого плана. Этот каталог становится общим языком между продуктом, поддержкой и инженерами, поэтому держите имена точными и стабильными.
Решите, где происходит принудительное соблюдение. Безопасное правило: проверяйте в API всё, что меняет данные или стоит денег; используйте фоновые задания, чтобы останавливать долгие задачи при превышении лимитов; а в UI показывайте подсказки (заблокированные кнопки, понятные подсказки), но не полагайтесь на UI как на единственный барьер.
Держите первую версию узкой. Сфокусируйтесь на правах, которые порождают наибольшее количество вопросов, добавьте проверки для самых рискованных действий и выпустите админ‑вид, показывающий клиента, план, переопределения и историю в одном месте.
Если вам нужно быстро сделать админ‑панель и логику без ручного кодинга, AppMaster (appmaster.io) — практичное решение для такого рода задач: вы можете смоделировать планы и переопределения как данные, реализовать проверки как бизнес‑процессы и выпустить интерфейс поддержки, который остаётся согласованным между бекендом и приложениями.
Вопросы и ответы
Модель прав — это единый и согласованный способ решать, что клиент может делать прямо сейчас на основании его плана и любых одобренных исключений. Это предотвращает ситуации «в UI работает, но в API — нет», потому что все части продукта читают одни и те же правила.
Без чёткой системы поддержки постоянно приходят просьбы к инженерам о мелких изменениях доступа, а клиенты видят непоследовательное поведение в разных экранах и эндпоинтах. Со временем правила разлетаются по коду, галочкам в админке, таблицам и единичным обновлениям в базе, что приводит к инцидентам и спорным ситуациям с биллингом.
Биллинг отвечает на вопрос «что и когда мы должны выставить счётом», а права — на вопрос «что разрешено прямо сейчас». Разделение позволяет финансам исправлять счета и повторные попытки оплаты без случайного изменения доступа к продукту.
Используйте флаг, когда возможность либо полностью включена, либо выключена (например, SSO). Лимит подходит для вместимости, которая не сбрасывается (например, места/проекты). Квота нужна для использования во времени (например, экспорты в месяц), где правило сброса должно быть явно указано.
Выбирайте область (scope), совпадающую с тем, как вы продаёте и контролируете продукт: на уровне аккаунта — для SSO, на уровне рабочей области — для общих ресурсов вроде проектов, на уровне пользователя — для прав или допов, связанных с конкретными людьми. Главное — использовать одну и ту же область везде, где проверяется право.
Обычно применяют порядок приоритета: сначала переопределение клиента, затем значение плана, затем системный дефолт. Если ключ отсутствует или неизвестен, для проверок доступа отказывайте (fail closed) и логируйте ошибку конфигурации, чтобы её исправили.
Храните дефолты планов в одной таблице, а исключения для клиентов — в другой, используя одни и те же стабильные ключи и типы. Делайте исключения с временными границами (начало и конец), чтобы поддержка могла дать временный доступ, который автоматически истечёт.
Кешируйте разрешённые права по клиенту с коротким TTL и номером версии. Когда поддержка меняет план или исключение — увеличивайте версию, чтобы изменения появились быстро, не дожидаясь истечения кеша.
Лучше создать узкое переопределение с датой истечения и причиной, затем проверить результат в продукте от имени клиента. Не редактируйте сам план ради разовой просьбы — это повлияет на всех клиентов тарифа и сложнее для аудита.
Записывайте, кто сделал изменение, когда, зачем, какое было прежнее значение, какое новое и когда это истечёт. Также должна быть кнопка «вернуть к дефолтам плана», чтобы быстро отменить ошибку без ручной чистки.


