Tier Deliverability Checklist (v1)
Pricing readiness tier (where we are)β
Use this as the internal launch bar for βcan we sell Starter / Growth truthfully?β It is separate from Stripe checkout polishβthis is product + API truth.
| Readiness | Name | Criteria (all must hold to claim the level) | Status (2026-04-30) |
|---|---|---|---|
| P0 | Copy only | Marketing claims exist; no reliable enforcement. | Past (superseded) |
| P1 | Enforceable core | TIER_DEFAULTS + TIER_LIMITS in code; requireFeature on tiered modules; seat/report cap paths exist (default monitor). | Met |
| P2 | Discoverable + honest | Tenants can see planTier + tierLimits via GET /config β billingEntitlements; landing bullets match flags/caps; VIP path via grandfatherFullAccess. | Met |
| P3 | Hardened revenue | Hard cap mode piloted per-tenant or via env; aggregate logging/metrics for at-cap and FEATURE_DISABLED; billing status doesnβt leak wrong tier. | In progress β Shipped: enforcement toggles + tier_gate logs; invalidateCustomerConfigCache after Stripe webhooks (fresh GET /config / entitlements after subscription changes); service app toast on 402 TIER_LIMIT. Still open: pilot cohorts, log dashboards/alerts, ongoing Stripe price-ID / QA hygiene |
| P4 | Scale | Grandfather + new-customer policies automated; self-serve upgrade/downgrade stories tested end-to-end. | Future |
One-line summary: P2 is met for honest Starter/Growth packaging. P3 adds hard/monitor controls, tier_gate logs, Stripe β config invalidation, and 402 UX in the web app; finishing P3 is mostly operational (pilot hard enforce, log pipelines, billing ops)βnot missing enforcement code.
Purposeβ
Ensure public pricing (Starter, Growth, AI waitlist) is backed by enforceable behavior: each promise maps to a gate (feature flag) or cap (tier limit), with known API + UI enforcement points.
Source of truthβ
- Pricing copy:
attunelogic-landing/src/pages/Home/Pricing.jsx - Packaging proposal:
docs/proposals/billing/monetization-and-tiers-v1.md - Feature gates:
attunelogic-api/src/services/config/default-configs/feature-flags.js(FEATURE_REGISTRY,TIER_DEFAULTS) - Numeric caps: same file (
TIER_LIMITS) enforced byattunelogic-api/src/middlewares/requireSeatCap.js - Entitlements:
attunelogic-api/src/services/billing/index.js(getEntitlementsForCustomer,buildBillingEntitlements)
Client discovery (no extra billing round-trip)β
Tenant apps load GET /api/v1/config. The API includes:
config.configs.billingEntitlementsβ same shape as billing summaryentitlements(planTier,tierLimits,monitorOnly,seatCapEnforcementMode, β¦)
Use this for upgrade prompts, showing caps in Settings, and matching UI to monitor vs hard seat-cap enforcement.
Stripe β config freshness (P3): When Stripe webhooks update a tenant (planTier, billing.status, etc.), the API calls invalidateCustomerConfigCache so the next GET /config is rebuilt with the new Customer document β entitlements do not stay stale after subscription changes.
Web app β hard cap blocks: The service appβs RTK baseQuery shows a toast on HTTP 402 with code: TIER_LIMIT (seat/report limit) so users get an immediate message to upgrade, not a silent failure.
Starter ($99/mo)β
Capsβ
- Office seats = 3 β
tierLimits.officeSeats - Driver seats = 25 β
tierLimits.driverSeats - Saved reports = 3 β
tierLimits.savedReports
Feature gates (tier1 defaults)β
- Live updates OFF β
jobs.liveUpdates.enabled - Route mapping OFF β
routing.enabled(maps/routes API guarded) - Advanced settings OFF β
settings.advanced.enabled(incl. raw customer-config edit API)
Growth ($249/mo)β
Capsβ
- Office = 10, drivers = unlimited, saved reports = unlimited
Feature gates (tier2 defaults)β
- Live updates ON, routing ON, advanced settings OFF
Rolloutβ
- Seat caps default to monitor. Hard blocks: set
SEAT_CAP_HARD_ENFORCE=trueon the API (global), or per tenantCustomer.billing.enforcementMode: "hard"(Super Admin β Customer β Seat / report cap enforcement). Env wins for emergency rollback (falseforces monitor). - Logs:
console.infolines with_evt: "tier_gate"β eventsseat_cap_monitor,seat_cap_blocked,feature_disabled(attunelogic-api/src/utils/tierGateLog.js). Parse in Datadog / CloudWatch / etc.
Grandfather / VIP (single-customer full access)β
Some tenants must stay untied from tier packaging (founding customers, VIP pilots): all GA product surface area stays on, numeric caps treated as unlimited.
Mechanism (Product DB): Customer.grandfatherFullAccess (boolean, default false).
- Feature flags: Resolver applies synthetic tier defaults = all GA keys ON from
FEATURE_REGISTRY(tenant overrides still win; dev/beta lifecycle rules unchanged β beta still requires latest + allowlist in prod). - Seat/report caps:
requireSeatCap, programmatic driver cap check, and billing entitlements treat caps as unlimited (same numeric behavior astier4). - Super Admin: Web β Super Admin β Customer β Settings β Grandfather: full product access; Seat / report cap enforcement (monitor vs hard vs default).
- API:
PUT /admin/customers/:idmay setgrandfatherFullAccess,planTier, and mergedbilling(e.g.enforcementMode) β superAdmin-only; billing is merged, not replaced wholesale.