diff --git a/BACKLOG.md b/BACKLOG.md index 5207e56..358473b 100644 --- a/BACKLOG.md +++ b/BACKLOG.md @@ -307,8 +307,8 @@ Sami explicitly stated he wants email auth as an OPTION alongside TOTP, not a re - **result:** 19/19 platform-paths tests pass (8 new for assertSafe + 3 new for isMountedCheck). 5/5 start.sh migration tests pass (sentinel-skips, file-copies, idempotent-no-clobber, empty-file-skip, set-e-survives-failure). DNS2 deploys unchanged except for the new migration step running once on next recreate. Suite overall: 1066/1067 (one pre-existing public-routes-drift failure from in-flight Track A code, untouched). ### DC-052: License-tier enforcement — Free caps user count at 3, gates share features on Pro -- **status:** todo -- **owner:** unclaimed +- **status:** in-progress +- **owner:** hermes - **details:** Per `/root/dashcaddy/PRODUCT-SPEC-DECISIONS.md` (locked 2026-07-20): Free = up to 3 users, Pro = unlimited. The DC-048 user-store needs a `countUsers()` helper. The `/api/v1/auth/admin/invites` POST handler must check `if (users.count() >= 3 && !licenseManager.isPro()) throw new ValidationError('upgrade required', 'tier')`. Same check on `POST /admin/users` (pre-authorize). Share-link creation routes (DC-053) gate on `licenseManager.isPro()`. **Free has NO trial path** — there is no automatic Pro trial, no time-limited upsell. The user picks Free or Pro deliberately. **LIFETIME keys are creator-only**: the API rejects any LIFETIME code at `verifyCode` time in production. The `license-keygen.js --lifetime` path stays on Sami's dev machine only; it's never wired to Stripe Checkout. - **impact:** First pricing enforcement. Without this, Pro is just a label. With this, every upgrade path has a clear moment to upsell. - **prerequisite:** DC-048 (shipped).