Multi-App Entitlement System for HeroSuite
Overview
Implement an entitlement system that allows subscription-based access to HeroSuite applications (Books, Sales) with tiered pricing based on user counts and contact limits.
Business Requirements
Subscription Tiers
| Tier | Users | Contact Limit | Apps | Price |
|------|-------|---------------|------|-------|
| Free | 1 | 10 | Books OR Sales | £0 |
| Explore | 2-5 | Unlimited | Books, Sales, or Both | TBD |
| Essential | 5-15 | Unlimited | Books, Sales, or Both | TBD |
| Elite | Unlimited | Unlimited | Books + Sales | TBD |
Upgrade Triggers
- Free user adds 2nd user → Prompt for Explore tier
- Explore exceeds 5 users → Prompt for Essential
- Essential exceeds 15 users → Prompt for Elite
- Any tier wants 2nd app → Prompt for bundle
---
Completed Work ✅
Phase 1: Foundation (Done)
Database:
- [x]
planstable with name, user_limit, contact_limit, features (JSONB), stripe_price_id - [x] Added
plan_idandapps_enabled(array) totenantstable - [x] Seeder for Explore, Essential, Elite plans
Models:
- [x]
Planmodel with feature checks (allows_app?,allows_books?,unlimited_users?) - [x]
Tenantmodel methods: free_tier?/current_plan_namehas_access_to?(app)/has_books_access?/has_sales_access?user_limit/at_user_limit?/users_remainingcontact_limit/at_contact_limit?/contacts_remaining
Tests:
- [x] 13 specs for Plan model
- [x] 28 specs for Tenant entitlement methods
- [x] Factories for plans and tenant traits
Files created/modified:
db/migrate/20260103150001_create_plans.rbdb/migrate/20260103150002_add_plan_to_tenants.rbapp/models/plan.rbapp/models/tenant.rb(extended)db/seeds/plans.rbspec/models/plan_spec.rbspec/models/tenant_spec.rbspec/factories/plans.rbspec/factories/tenants.rb
---
Remaining Work
Phase 2: Controller Enforcement
- [ ] Create
EntitlementEnforcementconcern
``ruby``
module EntitlementEnforcement
def requires_entitlement(feature, **options)
before_action(**options) do
unless current_tenant.has_access_to?(feature)
redirect_to upgrade_path, alert: "Please upgrade to access this feature"
end
end
end
end
- [ ] Apply to Books controllers (all current controllers)
- [ ] Add user limit check when creating/inviting users
- [ ] Add contact limit check when creating customers/vendors (free tier only)
- [ ] Create upgrade prompt partial
Phase 3: Stripe Integration
- [ ] Uncomment and configure
paygem in Gemfile - [ ] Create
config/initializers/pay.rb - [ ] Set up Stripe products and prices for each tier
- [ ] Implement webhook handler for subscription changes
- [ ] Create
Stripe::SyncSubscriptionServiceto sync plan changes - [ ] Add billing portal link for subscription management
Phase 4: UI Components
- [ ] Upgrade prompt modal (shown when hitting limits)
- [ ] Plan comparison page (
/pricingor/plans) - [ ] Current plan indicator in navigation/settings
- [ ] User limit warning in user management
- [ ] Contact limit warning for free tier users
Phase 5: Sales App Foundation (Future)
- [ ] Create
apps/salesRails engine structure - [ ] Implement shared
Contactmodel (replaces separate Customer in Books) - [ ] Add CRM-specific
ContactProfileextension - [ ] Apply entitlement enforcement to Sales controllers
---
Technical Notes
Data Model
# Free tier is implicit (plan_id = nil)
# Contact limit only applies to free tier
# apps_enabled defaults to ['books'] for all existing tenants
class Tenant
FREE_TIER_USER_LIMIT = 1
FREE_TIER_CONTACT_LIMIT = 10
end
Shared Contact Strategy (for Phase 5)
When Sales is built, the Customer and Vendor models will be unified into a Contact model with app-specific profile extensions:
Contact (shared)
├── Core: name, email, phone, address
├── has_one :crm_profile (Sales-specific)
└── has_one :accounting_profile (Books-specific)
---
Labels
enhancementarchitecturesubscription
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗