Plans & tiers
A license is issued at one of three tiers. The tier decides which
@withpotter/* packages a box may install — and therefore what it
can do.
export type Tier = 'basic' | 'growth' | 'enterprise'Cumulative model
Tiers are strictly nested:
BASIC ⊆ GROWTH ⊆ ENTERPRISE
Every package in a lower tier is included in every higher tier. This invariant is
asserted at module load in the control plane (assertManifestInvariants()) and
fails CI if monotonicity ever breaks — so an upgrade can never remove a
capability.
What each tier unlocks
| Tier | Adds | Examples |
|---|---|---|
| Foundation | Always present | tenant-core, auth-core, commerce, page, media |
| Basic | Core commerce | product, order, cart, payments, invoice, booking, analytics, review |
| Growth | Retention & marketing | subscriptions, loyalty, blog, content, campaign, automation, segments |
| Enterprise | Everything | team, platform-analytics, device-session |
See the package catalog for the full per-tier list.
How the entitled set is resolved
The tier manifest stores leaf packages — the intent-level capabilities of each tier. The actual entitled set is computed from those leaves:
function resolveTierPackages(leaves: readonly string[]): string[] {
const engines = resolveClosure(leaves) // dependency-closed engine set
const console = resolveConsolePackages(engines) // matching frontend packages
return [...new Set([...engines, ...console])].sort()
}- Closure. Expand each leaf to include every engine package it depends on.
- Console. Add the matching console (dashboard) packages.
- Dedupe & sort. Produce the final list stored in
TIER_PACKAGES[tier].
This closed set is exactly what lands in the activation token’s pkgs claim, so
the gated registry can
authorize downloads with a simple membership check.
Querying entitlements
The manifest exposes:
| Function | Returns |
|---|---|
packagesForTier(tier) | ReadonlySet<string> — O(1) membership |
isPackageAllowed(tier, pkg) | boolean |
A license gates which packages a box installs, not which versions. Pinning a
box to a specific platform version is a separate, proposed capability (the
VERSION_FREEZE_LTS_PLAN RFC).
Next
- Capability gating — how entitlements are enforced in the engine and console.