zazzy
Features

Feature flags / entitlements

Plan-based gating and quotas resolved from plans + overrides.

Feature flags are the entitlement layer: what an org can do, resolved from its plan's defaults plus per-org overrides. There is exactly one resolution point — getEntitlements(orgId) — that everything else (tRPC procedures, the public API, UI gates) reads through, so capability checks can never drift from the plan config.

Optional feature

Flags is optional (core: false, requires: ["billing"]). It composes billing's plan resolution and overlays per-org boolean overrides.

What it does

  • ResolutiongetEntitlements(orgId) returns the resolved map: billing's plan defaults (getPlanEntitlements) with per-org FlagOverride booleans overlaid. Order is override › admin planKeyOverride › plan default.
  • Assertions & quotasassertEntitlement and checkQuota guard server-side; UNLIMITED (-1) is the quota contract's unlimited sentinel.
  • Middleware & UI — the entitled(...) tRPC middleware, the <Entitled> component for conditional UI, and a MemberLimitNotice for seat limits.
  • Admin writessetFlagOverride / clearFlagOverride let the admin panel toggle overrides platform-wide (used for rollouts, betas, support exceptions).

Models it adds

ModelPurpose
FlagOverrideA per-org boolean capability override, unique per (org, key). Overlays the plan default; booleans only (numeric quotas come from plans).

Adds the marker-wrapped Organization.flagOverrides relation. createdById is a plain audit column, not a relation — deleting the admin who set an override must not cascade the override away.

Env it needs

None.

Composition

  • requires: ["billing"] — flags reaches billing's getPlanEntitlements through the public surface (never a deep import); billing owns plan resolution, flags owns the single getEntitlements resolution point.
  • Dependentsusage requires: ["flags"] (quota checks via checkQuota) and admin requires: ["flags"] (override writes).

What pruning removes

Leaving flags out drops features/flags, the FlagOverride model, and the Organization.flagOverrides relation. Because usage requires flags, deselecting flags also removes usage; admin requires flags too, so it goes as well.

On this page