Права доступа (entitlements) — это элегантное решение для сложной задачи монетизации софта. Они позволяют отделить модель ценообразования от логики приложения, делая изменения тарифных планов безболезненными.
Три слоя контроля доступа
В приложении часто смешивают три разных механизма контроля доступа. Это приводит к хрупкому коду, который сложно поддерживать. Разделим их:
| Слой | Назначение | Кто управляет | Срок жизни |
|---|---|---|---|
| Feature Flags | Инженерные практики: релизы, A/B-тесты, канарейки | Разработчики | Временный (дни-недели) |
| Entitlements | Бизнес-доступ: какие фичи доступны на тарифе | Продукт, бизнес | Постоянный |
| Authorization | Права пользователя: роли, permissions | Админы, пользователи | Постоянный |
Подробнее о фиче-флагах: Фиче-тогглы: полное руководство
Псевдокод, демонстрирующий разделение:
// Слой 1: Feature Flag (инженерный)
// Временный, для раскатки новой фичи
if (featureFlag.isEnabled("new-analytics-dashboard")) {
// Слой 2: Entitlement (бизнес)
// Постоянный, зависит от тарифного плана
if (customer.hasEntitlement("analytics")) {
// Слой 3: Authorization (пользователь)
// Постоянный, зависит от роли
if (user.hasPermission("view-analytics")) {
showAnalyticsDashboard();
}
}
}
Что такое права доступа
Права доступа (entitlements) — это набор разрешений, определяющих, что клиент может делать с приложением в рамках своего тарифного плана.
Примеры entitlements
{
"customer_id": "12345",
"entitlements": {
"audit_logs": true, // Булевая фича
"user_limit": 5, // Числовой лимит
"storage_gb": 10, // Квота
"api_requests_per_day": 1000
},
"usage": {
"current_users": 4,
"storage_used_gb": 3.2,
"api_requests_today": 847
}
}
Чем entitlements НЕ являются
- Не настройки клиента. Клиент может уменьшить свой лимит (например, 256 МБ логов вместо 1 ГБ), но entitlement всё равно даёт доступ к полному объёму.
- Не тарифные планы. План "Pro" может включать entitlements: audit_logs, 10 users, 50 GB storage. Но сам entitlement — это конкретная функция, а не уровень продукта.
Права доступа vs биллинг
Биллинговая система (Stripe, Paddle) отвечает за финансовые транзакции. Но до и после оплаты происходит многое:
- Пользователь начинает с бесплатного плана или trial
- Апгрейд/даунгрейд между планами
- Grandfathering — сохранение старых условий для существующих клиентов
- Кастомные enterprise-сделки
Почему разделять entitlements и биллинг
| Причина | Объяснение |
|---|---|
| Защитный слой | Ошибки интеграции с биллингом не блокируют доступ к фичам |
| Grandfathering | Биллинг не умеет сохранять старые условия для существующих клиентов |
| Низкая задержка | Проверки entitlements должны быть быстрыми (мс), биллинг не оптимизирован для этого |
| Разные среды | Dev/staging/prod — биллинг часто не поддерживает несколько сред |
| Гибкость | Доступ к фичам может не зависеть от статуса оплаты (trial, промо) |
Альтернативные подходы и их проблемы
Проверка по ID плана
// Плохо: логика привязана к названию плана
if (currentUser.plan === "pro") {
enableAdvancedFeatures();
}
Проблемы:
- Любое изменение плана требует изменения кода
- Миграция клиентов на новый план — поиск всех упоминаний старого плана
- Enterprise-клиенты с кастомными условиями множат количество планов
Авторизация (roles/permissions)
// Ограниченно: не учитывает бизнес-модель
if (currentUser.hasRole("admin")) {
enableAdminPanel();
}
Проблемы:
- Не учитывает коммерческие аспекты подписок
- Нет поддержки лимитов использования (5 users, 10 GB)
- Сложности в микросервисной архитектуре
Feature flags для монетизации
// Неправильное использование
if (Feature.enabled("premium-analytics")) {
showPremiumAnalytics();
}
Проблемы:
- Feature flags — для релизов, не для монетизации
- Нет поддержки лимитов и учёта использования
- Сложно для не-технических команд (sales, support)
Правильный подход: комбинация
// Feature flag — для раскатки (временный)
if (featureFlag.enabled("new-premium-analytics")) {
// Entitlement — для монетизации (постоянный)
if (customer.entitled("premium-analytics")) {
// Authorization — для ролей (постоянный)
if (user.can("view-analytics")) {
showPremiumAnalytics();
}
}
}
Лучшие практики
1. Избегайте вложенных проверок entitlements
// Плохо
if (entitled("feature_a")) {
if (entitled("feature_b")) {
doSomething();
}
}
// Хорошо: создайте новый entitlement или абстракцию
if (entitled("combined_feature")) {
doSomething();
}
// Или wrapper
function canAccessCombinedFeature() {
return entitled("feature_a") && entitled("feature_b");
}
2. Не предполагайте наличие новых entitlements
Новые entitlements могут отсутствовать у старых клиентов. Всегда предусматривайте fallback:
if (entitled("new_feature")) {
enableNewFeature();
} else {
fallbackBehavior(); // Важно!
}
3. Fail open при сбоях
При сбое сервиса entitlements — предоставляйте доступ по умолчанию, чтобы не блокировать пользователей:
async function checkEntitlement(feature) {
try {
return await entitlementService.check(feature);
} catch (error) {
logger.warn("Entitlement service unavailable, failing open");
return true; // Разрешаем доступ при сбое
}
}
4. Централизуйте проверки
class EntitlementChecker {
canInviteMembers(newMembers) {
const current = this.usage.members;
const limit = this.entitlements.memberLimit;
return current + newMembers <= limit;
}
canUploadFile(sizeBytes) {
const usedGb = this.usage.storageGb;
const limitGb = this.entitlements.storageGb;
return usedGb + (sizeBytes / 1e9) <= limitGb;
}
}
5. Удаляйте устаревшие entitlements
Сначала удалите проверки из кода, затем сам entitlement. Не накапливайте "мусор".
Резюме
| Механизм | Вопрос | Пример |
|---|---|---|
| Feature Flag | Готова ли фича к релизу? | Раскатка нового UI на 10% пользователей |
| Entitlement | Оплатил ли клиент эту фичу? | Доступ к аналитике на плане Pro |
| Authorization | Имеет ли пользователь право на это действие? | Только админ может удалять пользователей |
Ключевые принципы:
- Логика приложения не должна зависеть от названия плана — планы меняются
- Feature flags — для инженеров, entitlements — для бизнеса
- Разделяйте entitlements и биллинг — это разные задачи
- Централизуйте проверки entitlements
- Предусматривайте fallback и fail open
- Фиче-тогглы: полное руководство — инженерные практики для релизов