Commit Graph
3 Commits
Author SHA1 Message Date
hermes 375dea22ca PRODUCT-SPEC-DECISIONS + DC-052–056 build pipeline
Captures the 14 product-spec decisions locked today with Sami:
- Time-based pricing: 30/90/180/365 day tiers at $20/$50/$70/$99
- Free = up to 3 users, Pro = unlimited
- Free = local-only; Pro adds Tailscale-mediated share + public share links
- Stripe Checkout, USD-only, optional dashcaddy.net account
- LIFETIME keys are creator-only (no public exposure)
- Use existing license-keygen, no new auth system
- Invitees MUST use email magic link (email = identity for non-host users)

BACKLOG gets 5 new build tickets:
- DC-052: License-tier enforcement (cap Free at 3 users, gate share on Pro)
- DC-053: Public + Tailscale-mediated share routes (the killer Pro feature)
- DC-054: Stripe webhook bridge for auto-issuing license keys
- DC-055: dashcaddy.net/pricing page + Stripe Checkout
- DC-056: ToS + Privacy Policy pages (GDPR-aware)

No code changes — pure planning artifacts. Code work begins next.
2026-07-20 21:00:54 -07:00
hermes 0b85caa80a DC-041: integration test for dashcaddy-update.sh auto-update pipeline 2026-07-20 20:01:42 -07:00
hermes 321334cd33 DC-048: multi-user bootstrap + admin invites (opt-in)
CI / Security audit (push) Has been cancelled
CI / Test & Lint (push) Has been cancelled
Implements the user-store + invite-store + admin routes. The whole
system is opt-in via siteConfig.authProviders.email.enabled = true;
single-user TOTP-only installs see zero behavior change.

Backend:
- src/security/user-store.js: users + allowlist + bootstrap sentinel,
  atomic writes, last-admin protection, defensive dataDir resolver.
- src/security/invite-store.js: single-use tokens (SHA-256 hashed on
  disk), TTL, auto-prune, defensive dataDir resolver.
- routes/auth/admin.js: /me, /admin/users (CRUD), /admin/allowlist,
  /admin/invites (CRUD), public /invites/:token (peek + accept).
- routes/auth/index.js: wires userStore, gates admin router on
  email auth being enabled.
- src/auth/providers/email.js: verify() enforces allowlist, creates
  user record, tags req.user; default-enabled flipped to opt-in.
- src/auth/providers/totp.js: bootstraps system@totp.local admin on
  first verify so current DNS2 operator shows in /admin/users.
- src/security/audit-logger.js: middleware adds userId/userEmail/
  userRole/viaProvider to log details when req.user is tagged.
- PUBLIC_ROUTES + CSRF allowlists updated for invite redemption.

Frontend:
- status/js/admin.js: modal overlay with users list (role-edit,
  delete), invite form (email/role/TTL), copy-link button,
  outstanding-invites list with revoke. Exports window.AdminPanel.
- status/js/core/init.js: calls AdminPanel.attachTrigger so the
  Admin button only appears when /me returns isAdmin=true.

Tests: 35 new tests across 3 files (user-store, invite-store, auth
multistore integration). Full suite: 1298/1298 passing.

Docs: BACKLOG.md marks DC-048 done. CHANGELOG.md [Unreleased]
section gets the DC-048 entry.
2026-07-20 17:44:11 -07:00