Editions and entitlements
Deployment edition
Section titled “Deployment edition”Every SupaCloud instance runs as one of two editions: Community or Enterprise. The edition is a property of the deployment, not of any individual Organization or Workspace. It is resolved once at boot, cached for the process lifetime, and is fail-closed: anything other than a valid, unexpired Enterprise license resolves to Community.
Community
Section titled “Community”The default. Feature availability is determined per Organization by its Stripe subscription and plan. An Organization without an active subscription falls back to the free plan when billing is enforced, or to the historical grant-all legacy fallback on a self-hosted instance that has never configured Stripe.
Enterprise
Section titled “Enterprise”Unlocked by a valid HS256 JWT in SUPACLOUD_EDITION_LICENSE, verified against SUPACLOUD_EDITION_SECRET (minimum 32 bytes), whose edition claim is enterprise and whose exp has not passed. Both secrets are loaded via the supacloud/app OpenBao path when SECRET_BACKEND=openbao (see Secret provisioning).
When the edition resolves to Enterprise, workspace_entitlements short-circuits to the full legacy_features grant — every boolean feature enabled and every quota set to "unlimited" (with the exception of support_tier, which is set to the string "legacy") — for every Workspace on the instance, independent of any Stripe subscription. The resulting EntitlementSummary reports plan_id: "enterprise" and status: "edition". Per-workspace and per-user overrides still apply on top (see below).
Development bypass
Section titled “Development bypass”MODE=dev combined with SUPACLOUD_EDITION=enterprise activates Enterprise without a license token. This path is never honoured when MODE is prod or production.
Entitlement precedence
Section titled “Entitlement precedence”On a Community deployment (or where overrides need to be applied on top of the Enterprise grant), feature values are resolved through a five-layer chain. The first layer that defines a value for a given feature key wins; lower-priority layers are not merged or averaged.
user override ?? seat type ?? workspace override ?? org plan (subscription → plan.features) ?? default (free plan or legacy grant-all)The base map (default / org plan, layers 1-2) is established in workspace_entitlements; the three override layers (workspace override, seat type, user override — layers 3-5) are then applied, lowest to highest priority, inside apply_active_overrides (services/billing/features.rs):
| Priority | Source | Where stored |
|---|---|---|
| 5 — highest | User override | feature_overrides row with user_id set |
| 4 | Seat type | seat_types.entitlements via organization_members.seat_type_id |
| 3 | Workspace override | feature_overrides row with workspace_id set, user_id NULL |
| 2 | Organization plan | subscriptions → plans.features (via workspaces.organization_id) |
| 1 — lowest | Default | free plan seed, or legacy grant-all on unsubscribed self-hosted |
What each layer controls
Section titled “What each layer controls”Organization plan. The base entitlement set comes from the plans.features JSONB column of the active subscription. On the free tier, quota keys such as users.max carry a small numeric cap; mid-tier paid plans (pro/team) carry larger numeric caps; only the enterprise (and the private legacy) plan carries "unlimited".
Workspace override. A feature_overrides row scoped to a Workspace (no user_id) lets an operator extend or restrict a specific feature key for everyone in that Workspace, regardless of the plan. Expires when expires_at passes or when the row is revoked.
Seat type. Each member of an Organization may be assigned a seat_type via organization_members.seat_type_id. A seat type carries a subset of the same feature-key vocabulary as plans.features. Keys present in the seat type override the workspace/plan value for that user; keys absent fall through to the next lower layer. This enables per-user tier sharpening (for example, granting sso_oidc_byo to operators while keeping members on a restricted seat).
User override. A feature_overrides row scoped to a specific user is the highest-priority source and overrides every other layer. Reserved for exceptional cases such as support agreements or temporary grants.
Feature value semantics
Section titled “Feature value semantics”A feature value is either:
true— the feature is enabled with no numeric limit.false/null/ absent — the feature is disabled;require_featurereturns403 Forbidden."unlimited"— applies to quota keys (e.g.runs.per_month); no upper bound is enforced.- a number — a hard cap;
require_below_limitchecks the current count before allowing the operation.
Related
Section titled “Related”- Secret provisioning — how
SUPACLOUD_EDITION_LICENSEandSUPACLOUD_EDITION_SECRETare loaded from OpenBao. - ADR 0035 (Organization tenancy) and the
#305edition short-circuit —docs/decisions/0035-organization-tenancy-seats-invites-secret-scoping.md. - Source:
server/src/app/edition.rs,server/src/services/billing/features.rs.