Skip to content

Feature Gates

ContractorHub uses feature flags and subscription tiers to control which capabilities are available to each tenant. This allows gradual rollouts and tier-based access.

Feature flags are stored in the tenant’s config_json column and can be toggled via the Settings API or directly in the tenant config file.

FlagDefaultDescription
quotes_enabledtrueEnables the estimate/quote builder, catalog, and sharing features
enable_contractor_systemfalseEnables contractor assignments, My Assignments portal, and audit logging
enable_force_password_changefalseRequires users to change their password on next login when flagged by an admin

The SUBSCRIPTION_TIER environment variable controls which tier the tenant operates under. Higher tiers unlock additional features.

TierFeatures
baseLeads, customers, projects, estimates, dashboard, search, notes, todos
proEverything in base, plus: contractor system, advanced scheduling, SMS templates, automation workflows

The tier is checked at the middleware level. Attempting to access a pro-only feature on a base tier returns a 403 error with the code TIER_REQUIRED.

Feature flags are set in config/.tenant.dev.env for development and applied to the tenant’s config_json during seeding:

FEATURE_QUOTES_ENABLED=true
FEATURE_CONTRACTOR_SYSTEM=true
FEATURE_FORCE_PASSWORD_CHANGE=false
SUBSCRIPTION_TIER=pro

Admins can update feature flags via the tenant settings endpoint:

PATCH /api/v1/tenant
{
"config_json": {
"quotes_enabled": true,
"enable_contractor_system": true
}
}

The dev-info endpoint (non-production only) reports current feature flag status:

GET /api/v1/public/dev-info

Response includes:

{
"features": {
"quotes_enabled": true,
"contractor_system": false,
"force_password_change": false
}
}

When adding a new feature flag:

  1. Add the flag to config/.tenant.dev.env and config/.tenant.env.example.
  2. Update the seed script to read and apply the flag to config_json.
  3. Create or reuse a middleware guard (see requireFeatureFlag() in the API).
  4. Apply the guard to the relevant route registrations in src/index.ts.
  5. Document the flag in this page.