stack/apps/dashboard
Bilal Godil 59ef500f7e Treat canceled-at-period-end subscriptions as still in effect
Canceling a subscription without a Stripe backing (test mode, free plans)
writes status=canceled with endedAt set to the end of the current period,
so the customer keeps their entitlements until then. But every read path
classified subscriptions with isActiveSubscription (active/trialing only),
so during the paid-through window the owned product fell through to the
one-time-purchase branch: the account settings payments tab showed
"One-time purchase" with no end date and no way to tell the plan was
winding down, and plan usage reported the free plan while the paid plan's
quotas were still in effect.

Introduce isSubscriptionInEffect (status-agnostic, endedAt-based — the
same semantics Bulldozer's grant timefold and ensure-free-plan already
use) and use it at the read sites: product list classification, plan
usage resolution, and the switch route's sub-vs-OTP occupancy check.
Write sites keep isActiveSubscription so wound-down subs can't be
re-canceled or switched from. The product list now also computes
is_cancelable instead of hardcoding it, double-canceling returns a
dedicated error instead of claiming the product is an OTP, and the
Stripe cancel path uses cancel_at_period_end instead of canceling
immediately, matching the promise made by the confirmation dialog.
The account settings panels render "Ends on <date>" for winding-down
subscriptions.
2026-07-16 13:19:07 -07:00
..
public Add 6/12/26 changelog entry (#1589) 2026-06-16 16:44:03 -07:00
scripts Enable dev tool Dashboard tab via development-environment probe instead of env var (#1749) 2026-07-09 20:23:07 -07:00
src Treat canceled-at-period-end subscriptions as still in effect 2026-07-16 13:19:07 -07:00
.env Gate usage limit banners behind HEXCLAVE_DISABLE_PLAN_LIMITS (#1728) 2026-07-05 21:17:21 -07:00
.env.development Gate usage limit banners behind HEXCLAVE_DISABLE_PLAN_LIMITS (#1728) 2026-07-05 21:17:21 -07:00
.eslintrc.cjs Config sources (#1083) 2026-01-21 18:08:35 -08:00
.gitignore Support local dashboard in remote SSH and GH Codespaces (#1538) 2026-06-04 16:36:17 -07:00
.npmrc Split backend and dashboard (#83) 2024-06-18 15:49:31 +02:00
components.json Split backend and dashboard (#83) 2024-06-18 15:49:31 +02:00
DESIGN-GUIDE.md fix: remove email-outbox dashboard page (#1662) 2026-06-24 11:10:24 -07:00
instrumentation-client.ts feat(hexclave): PR 3 — native @hexclave/* source rename + delete dual-publish wiring (#1482) 2026-05-29 15:21:59 -07:00
LICENSE Split backend and dashboard (#83) 2024-06-18 15:49:31 +02:00
next.config.mjs Enable dev tool Dashboard tab via development-environment probe instead of env var (#1749) 2026-07-09 20:23:07 -07:00
package.json Enable dev tool Dashboard tab via development-environment probe instead of env var (#1749) 2026-07-09 20:23:07 -07:00
postcss.config.js Split backend and dashboard (#83) 2024-06-18 15:49:31 +02:00
tailwind.config.ts feat(hexclave): PR 3 — native @hexclave/* source rename + delete dual-publish wiring (#1482) 2026-05-29 15:21:59 -07:00
tsconfig.json Support local dashboard in remote SSH and GH Codespaces (#1538) 2026-06-04 16:36:17 -07:00
vitest.config.ts In-source unit tests (#429) 2025-02-14 11:47:52 -08:00