Build Log · August 28, 2026

MedinaCHF — Onboarding Simplification, a Self-Hosted Invite Email, and a Live Production Outage Fixed

Courtney's live-member-test brief asked for less friction between invitation and Member Home. Building it surfaced that Clerk's invitation email needs a paid plan to customize, which led to a bigger decision (create Clerk accounts directly, send our own email) that a real account-deletion bug and a Crucible council review both caught and fixed before it shipped. A live production 500 (a missing table from an unrelated prior session) was found and fixed mid-session using the same evidence discipline. Two smaller features (RSVP manual correction, membership-progress event list) and two small bug fixes closed out the session.

  • MedinaCHF
  • Onboarding
  • Clerk
  • Crucible
  • Production Incident
real bugs found and fixed in the new account-creation logic before deploy (one could have deleted a real member's Clerk account)
2

real bugs found and fixed in the new account-creation logic before deploy (one could have deleted a real member's Clerk account)

live production outage found via real Vercel logs and fixed (missing admin_intents table, unrelated to this session's own changes)
1

live production outage found via real Vercel logs and fixed (missing admin_intents table, unrelated to this session's own changes)

separate feature/fix threads shipped and deployed: onboarding simplification, self-hosted invite email, RSVP manual correction, and two small UI bug fixes
4

separate feature/fix threads shipped and deployed: onboarding simplification, self-hosted invite email, RSVP manual correction, and two small UI bug fixes

Timeline

  1. Start

    Charge received from Courtney via Zeb: simplify onboarding after a live member test

    Remove the /welcome install-choice screen and the first-login Getting Started card; route straight to Member Home

  2. Build

    Removed /welcome and GettingStartedCard, relocated Add-to-Phone into Help

    Verified via real tsc + production build + live curl checks against the deployed routes

  3. Scope growth

    Zeb asked whether the invitation email could be customized — Clerk's template requires a paid plan

    Investigated, then Zeb chose to create Clerk accounts directly and send ForgeKit's own email instead of upgrading Clerk

  4. Bug found

    A real Clerk account created with the notification email held back has no adults.clerkUserId until the member signs in

    An earlier version of the shared helper treated that null as 'no account exists' and would have called the orphan-cleanup function, deleting the real account on a later retry

  5. Crucible

    Ran crucible:council (architect + qe) on the account-creation design before deploying

    Council flagged the same fail-open pattern recurring in a second function (updateMemberOnboardingStatus) and called for one shared, fail-closed Clerk-lookup helper

  6. Fix + deploy

    Centralized the Clerk-existence check into resolveClerkAccountForEmail, fails closed on API uncertainty

    tsc + production build re-verified clean, deployed to medinachf.forgekits.build

  7. Live incident

    Zeb reported /coordinator/settings throwing a live error mid-session

    Pulled real Vercel production logs first — found relation "admin_intents" does not exist, a table defined in schema.ts by a prior session but never pushed to production

  8. Fixed + verified

    Pushed the missing table to production, independently confirmed via information_schema, confirmed the live page recovers

    Root cause predates this session entirely — surfaced only because Courtney/Zeb happened to load that page

  9. Feature

    Added coordinator RSVP manual add/remove, mirroring the existing attendance-correction pattern

    Mainly for correcting completed-event records — coordinator-only, org+event scoped

  10. Close

    Two small bug fixes along the way (a mislabeled button, the Add Member panel's width/required-field visibility)

    All four feature threads verified and deployed to production before this retro was written

What shipped

  • products/medinaCHF/app/member/layout.tsx, app/member/page.tsx — removed the /welcome redirect and the Getting Started card; a newly onboarded member lands directly on normal Member Home

  • products/medinaCHF/app/welcome/page.tsx, components/GettingStartedCard.tsx — deleted entirely

  • products/medinaCHF/app/member/help/page.tsx — relocated AddToPhoneButton here as an optional resource

  • products/medinaCHF/lib/emails/member-account-ready.ts — new self-hosted HTML/text invitation email matching Courtney's copy

  • products/medinaCHF/lib/email.ts — added sendHtmlEmail

  • products/medinaCHF/lib/actions/member-management.ts — createMemberAccountDirect, createClerkAccountForAdult, resolveClerkAccountForEmail, updateMemberOnboardingStatus; createMemberManually now always creates the Clerk account inline with an optional sendAccountEmail flag

  • products/medinaCHF/components/coordinator/AddMemberButton.tsx — 'Send account email now' checkbox, wider panel, visible required-field markers

  • products/medinaCHF/components/coordinator/MemberDetailPanel.tsx — 'Send Account Email (ForgeKit)' button, manual onboarding-status override control

  • products/medinaCHF/tests/e2e/armory/coordinator-member-management.spec.ts — updated for the new Add Member button label/checkbox, added a held-back-email regression test

  • products/medinaCHF/lib/db/schema.ts — admin_intents table pushed to production (fix for a live outage; schema itself predates this session)

  • products/medinaCHF/lib/actions/rsvp.ts — recordRsvpForFamily, removeRsvpRecord

  • products/medinaCHF/components/coordinator/RsvpEditor.tsx — new coordinator RSVP add/remove UI

  • products/medinaCHF/app/coordinator/events/[id]/page.tsx — wired in RSVP add/remove, removed dead RSVP_LABEL constant

  • products/medinaCHF/lib/queries/attendance.ts — listCountedAttendanceEventsForFamily

  • products/medinaCHF/components/CountedEventsSection.tsx — 'Events That Counted This Year' on Plan Something

  • products/medinaCHF/app/member/planning-board/page.tsx, app/member/page.tsx — wired in the counted-events list and its Home deep-link; fixed 'View My Membership' button label to 'View My Profile'

“what the fuck. just delete it already. you have my permission.”
— Zeb, mid-session, after a self-inflicted concurrency-tooling deadlock (s1) that turned out to require no file deletion at all — resolved by dropping a shell habit (`cd ... &&`), not by touching the file in question