feature/quota-and-member-limits #2
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feature/quota-and-member-limits"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Feature A — Storage quota (1 GiB per family): - src/lib/quota.ts: enforcement library with pure functions (fully unit-tested) and DB-bound helpers; isPaidFamily() is the single payment abstraction gate - src/lib/format-bytes.ts: extracted formatBytes() — safe for client imports - POST /api/upload: quota check before presigned URL issuance (HTTP 402 + reason code) - POST /api/memories/[id]/confirm: HeadObject reconciles actual R2 size; deletes over-quota objects and marks row failed rather than silently exceeding limit - GET /api/storage-usage: storage info endpoint for UI meter - src/components/StorageMeter.tsx: meter bar + StorageQuotaBanner + MemberLimitBanner - memories/page.tsx: quota banner, FAB disabled (⊘) when exceeded, compact meter in header - settings/page.tsx: always-visible StorageMeter + MemberLimitBanner in invite section Feature B — Member limit (2 per family, free tier): - invites/route.ts: replaced ad-hoc inline check with checkMemberLimit() from quota lib Structured 403 response: { reason, currentCount, limit } - Freeze rule: paid→free downgrade leaves all members intact; only new invites blocked Migration: - drizzle/0007_subscription_status.sql: ADD COLUMN subscription_status varchar(20) - debug-migration/route.ts: step added for hot-apply without full redeploy - src/db/schema/family.ts: subscriptionStatus field added to Drizzle schema Tests: 44 unit tests in src/__tests__/quota.test.ts, all passing - Pure function tests (no DB): isPaidFamily, wouldExceedQuota, isAtMemberLimit, formatBytes - DB-bound tests (mocked @/db): getFamilyStorageUsage, checkStorageQuota, checkMemberLimit, getStorageInfo, tenant isolation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>