rename: "Team" billing tier to "Family"

All literal "team" tier-value references renamed to "family" across
API routes, admin UI, OpenAPI schemas, and lib/tiers.ts. The DB enum
value itself is renamed in place via ALTER TYPE ... RENAME VALUE
(migration 0044) rather than drizzle-kit's auto-generated
drop-and-recreate-the-enum migration, which would have failed against
any existing row still holding 'team' — RENAME VALUE preserves
existing data with no cast/backfill needed.

Also adds STRIPE_PLAN.md — a full Stripe billing integration plan
(Checkout+Portal, tier→Price mapping, admin billing dashboard, and a
multi-user Family-group design since Family is meant to cover several
accounts under one subscription, not one payer). Planning only, no
Stripe code yet.

v0.47.0
This commit is contained in:
Arnaud
2026-07-18 00:25:51 +02:00
parent 21a3622e6c
commit c8f4b50ef3
47 changed files with 5469 additions and 60 deletions
@@ -24,7 +24,7 @@ type Invite = {
token: string;
email: string | null;
role: "user" | "moderator" | "admin";
tier: "free" | "pro" | "team";
tier: "free" | "pro" | "family";
createdAt: string;
expiresAt: string | null;
};
@@ -33,7 +33,7 @@ export function InvitesManager({ invites, appUrl }: { invites: Invite[]; appUrl:
const router = useRouter();
const [email, setEmail] = useState("");
const [role, setRole] = useState<"user" | "moderator" | "admin">("user");
const [tier, setTier] = useState<"free" | "pro" | "team">("free");
const [tier, setTier] = useState<"free" | "pro" | "family">("free");
const [creating, setCreating] = useState(false);
const [revokeId, setRevokeId] = useState<string | null>(null);
@@ -106,7 +106,7 @@ export function InvitesManager({ invites, appUrl }: { invites: Invite[]; appUrl:
<SelectContent>
<SelectItem value="free">Free</SelectItem>
<SelectItem value="pro">Pro</SelectItem>
<SelectItem value="team">Team</SelectItem>
<SelectItem value="family">Family</SelectItem>
</SelectContent>
</Select>
</div>