- Add Ko-fi webhook (/api/webhooks/kofi) with upsert by (provider, external_user_id)
• Computes renews_at = timestamp + 1 calendar month + 1 day
• Preserves first started_at; stores raw payload; canonicalizes by email when available
- Add Ko-fi claim flow
• POST /api/support/kofi/claim/start — sends verification email via SMTP
• GET /api/support/kofi/claim/verify — finalizes link (sets app_user), redirects to /portal/account
• POST /api/support/kofi/unlink — clears app_user on Ko-fi rows
- Add derive-on-read membership logic
• /lib/memberships.ts — single source of truth for badges & “active” state
• /api/support/badges — thin wrapper that returns per-provider badges
- Account UI
• components/account/SupporterBadges.tsx — renders provider badges (Ko-fi now; extensible)
• components/account/ConnectKofi.tsx — “Link Ko-fi” form (email → verify link)
• components/account/LinkStatus.tsx — success/error banner on return
• app/portal/account/AccountPanel.tsx — integrates badges, link panel, and banner
- Config/env
• Requires: DIRECTUS_URL, DIRECTUS_TOKEN_ADMIN_SUPPORTER, KOFI_VERIFY_TOKEN
• SMTP: SMTP_HOST, SMTP_PORT, SMTP_SECURE, SMTP_USER, SMTP_PASS, EMAIL_FROM
• APP_ORIGIN used to build absolute verify URLs
- Misc
• Fixed import to use @/lib/memberships
• No cron required; UI derives active state via status === active && renews_at >= now
Refs: beta readiness for Ko-fi supporters