ForgeKitFORGEKIT

Build Log

Member Management Round 2 — Shared Family Data Foundation

August 14, 2026

Extended Round 1's manual-add flow with spouse, birthday, and children so Leadership can create one real test family and invite it into an already-populated My Family.

MedinaCHFFeatureMember Management
17
files changed in the feature commit
3
production deploys
1
real production bug found and fixed same-session

Timeline

Start
Received Court's consolidated brief
Skipped the Crucible checkpoint — brief was already tightly pre-shaped with explicit in/out scope
Orient
Read Round 1's code before assuming anything
Found the shared-record architecture, mobile nav fix, and manual Add Member already built — scoped the session to the real gap only
Anvil
Spouse-as-adults-row vs. spouse-as-plain-fields
Zeb corrected two rounds of my proposed schema before landing on plain fields on families — no login, no forced placeholder email
Build
Schema + admin/member actions + directory + email-change workflow
Verified schema live via information_schema, full data lifecycle round-tripped against real Neon DB
Deploy 1
Feature shipped to production
tsc clean, local build passed, live site verified responding
Real bug found
Zeb hit a false 'another member already uses this email' error
Editing his own family's spouse fields failed because an unordered adults-by-familyId query could return either of 2 real adult rows
Deploy 2
Fixed getPrimaryAdult() at all 3 call sites, verified against the real Jungeberg family data, redeployed
Deploy 3
Added missing desktop Connect (directory) link
Mobile bottom-tab had promoted Connect to primary since 2026-08-07; desktop member nav was never updated to match

What shipped

products/medinaCHF/lib/db/schema.ts — families.spouseFirstName/spouseLastName, adults.birthMonth/birthDay (month/day only, no year), new emailChangeRequests table

products/medinaCHF/lib/actions/member-management.ts — extended createMemberManually/updateMemberBasicInfo with spouse/birthday/children; added adminUpsertChild/adminDeleteChild; added resolveEmailChangeRequest/dismissEmailChangeRequest using a Clerk-safe email-replace composed from createEmailAddress+updateUser+deleteEmailAddress (installed @clerk/backend SDK predates Clerk's single-call ReplaceUserEmailAddress endpoint)

products/medinaCHF/lib/actions/family-profile.ts — added updateMyPhone (member self-service) and requestEmailChange (creates an emailChangeRequests row)

products/medinaCHF/lib/queries/attention-needed.ts — new email_change category, same fingerprint/dismissal pattern as existing categories but status-driven since a request is terminal, not a recurring condition

products/medinaCHF/lib/queries/family-profile.ts — FamilyCard now carries primaryAdultPhone/primaryAdultEmail/spouseName; birthMonth/birthDay deliberately never added to this type at all

products/medinaCHF/components/coordinator/AddMemberButton.tsx, MemberDetailPanel.tsx — spouse fields, month/day birthday picker, repeatable children editor (+ Add Another Child, no fixed slot count)

products/medinaCHF/components/MyAdultProfileForm.tsx, RequestEmailChangeModal.tsx — member phone editing, read-only login email with Request Email Change modal

products/medinaCHF/components/coordinator/ResolveEmailChangeButton.tsx — inline Attention Needed resolution for email-change requests

products/medinaCHF/components/FamilyCardPreview.tsx — directory now shows phone/email/spouse name on the full (non-compact) profile view only

BUGFIX: products/medinaCHF/lib/actions/member-management.ts — getPrimaryAdult() helper, fixing an unordered adults-by-familyId query at 3 call sites that could non-deterministically pick either adult row in a 2+-adult family

BUGFIX: products/medinaCHF/app/member/layout.tsx — added missing Connect/directory link to the desktop member nav

no, store the spouse on families and if they have an adults row, then email is required. why does this not work?

Zeb, correcting two rounds of over-engineered spouse-schema proposals down to the actually-correct simple one