- Signup now creates unverified users and sends a verification email
(Resend); dev falls back to [VERIFY-LINK] console log
- /api/auth/verify-email: single-use token handler, mints tia_session
on success, redirects to /onboarding
- /api/auth/resend-verification: rate-limited (3/hr), enumeration-safe
- Sign-in gated on email_verified — unverified accounts get 403 with
needsVerification flag so the UI can show the resend button
- Google OAuth via arctic v3: PKCE + state anti-CSRF, find-or-create
user, writes accounts row, mints tia_session
- Login page: Google button, check-email screen, resend link on 403
- drizzle/0005_email_verification.sql: creates email_verifications
table + backfills all existing users as verified (runs automatically
on container start before app boots)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Admin invites by entering email instead of copying a link
- If email matches existing Tia user → creates pending invite visible
on their Circles page with Accept/Decline buttons
- If email is not registered → sends Resend email with signup link
that lands them directly in the circle after account creation
- DB migration adds invited_email + invited_family_id to circle_invites
- New GET /api/circles/invites endpoint for pending invite banners
- Remove clipboard-copy approach entirely
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The SQL file existed but was missing from _journal.json so the
migrator skipped it on deploy. Adding the journal entry ensures
the circles tables are created on next container boot.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
drizzle-kit generate against the now-prod-aligned schema produces a
single baseline migration covering all 35 tables.
VERIFIED: 0000_baseline_prod_2026_05_19.sql was compared column-for-column
and type-for-type against the drizzle-kit pull introspection of tia_prod.
Table sets identical, all columns and types match. The baseline is a
faithful representation of production.
This baseline will be marked as already-applied in prod's
__drizzle_migrations table (done out-of-band, not in git), so the migrator
runs nothing on the next deploy. It exists purely as the reference point
for future schema diffs.
Adds drizzle/README.md documenting the baseline reset and the migration
workflow going forward.