Skip to content

[Feature · #459] DOB / age on Google sign-up #522

Closed

Description

@owlstonbusiness-svg

[Feature · under #459] Collect DOB / age on Google sign-up — UX card flow, HK contractual capacity & PDPO, spotlight tour handoff & #514 CRM birthday automation

Parent: #459 (Unified Account & Child Sub-Profiles)
Linked: #514 (Client relationship memory) under #511 (WA desk / Ops CRM) · fee framing #508 / Drop-Protection #520


1. Why

MatchMax connects students, parents, and Independent Tutors. Collecting Date of Birth (DOB) at the right moment solves three problems:

  1. Role & flow routing ([Urgent · V1] Unified account + roles + child sub-profiles + hours ledger #459): Student vs Parent vs Independent Tutor, plus child sub-profiles.
  2. Legal self-protection (HK + PDPO): Age of majority for binding commercial contracts is 18 (Cap. 410). Primary/secondary students must be welcomed (not hard-banned like an 18+ app), but financial obligations — including the 1.5-lesson Platform Administrative Fee (100% L1 + 50% L2) — and Independent Tutor terms need age-tiered guardrails so fees cannot be voided for lack of capacity.
  3. High-touch memory ([Ops · CRM · #511] Client relationship memory #514): Birthday WhatsApp + CRM notes without making Day-0 onboarding feel like an interrogation. Also: if someone only exists on WA (no website account yet), Ops can capture age/DOB/Form level into #514 notes; website DOB is source of truth once they sign up.

2. UX: when, where, card, spotlight

2.1 Timing

Google OAuth (openid email profile) does not reliably return birthday unless we request sensitive user.birthday.read (scary consent screen → kills conversion). Collect natively right after OAuth:

  1. Google OAuth callback
  2. Post-OAuth onboarding card /onboarding/welcome (before full home, or over dimmed backdrop) — target 5–8 seconds
  3. On Continue → Spotlight tour handoff (role-aware profile/sub-profiles → matching/notes → Account & Privacy)

2.2 Card wireframe (copy lock)

Welcome to MatchMax 👋  Step 1/1
Let's personalise your experience in 5 seconds.

1. I am joining primarily as a...
   [ 🎓 Student ]  [ 👨‍👩‍👧 Parent ]  [ Independent Tutor ]
   (You can switch or add roles anytime in your profile)

2. Your Date of Birth
   [ Day (DD) v ]  [ Month (MMM) v ]  [ Year (YYYY) v ]
   🔒 Year is strictly private. Used for age-appropriate features and optional birthday wishes.

[If age < 18]
   [x] My parent/guardian is aware I am using MatchMax, and will approve any paid tutor bookings or fees.

[If age < 13]
   Parent / Guardian WhatsApp or Email (for account link):
   [ +852 … or parent@email.com ]

[ ] Show my birthday (Month & Day only, e.g. 🎂 15 Mar) on my public profile. (Optional — off by default)

By continuing, you agree to our updated [Terms of Service] and [Privacy Policy (PICS)], including WhatsApp service updates.

[ Continue to My Profile → ]

Dropdowns DD/MMM/YYYY (not native <input type="date">) — faster to reach 2008–2012 birth years.

Parent mis-entry: If role = Parent AND calculated age < 18 → inline helper:
"Looks like you entered a student's birthday! Please enter your own birth year here — you can add your child's age on their sub-profile in the next step."

Brand: primary #1d9bf0, ink #0f1419, sky #8ecdf8, white card #ffffff.


3. Age tiers (CEO/legal: confirm Form 1 ~11–12 → Tier 4)

Age tier Cohort Browse / platform Booking & 1.5 fee Independent Tutor
≥18 Parents, adult students, uni tutors Full; can create child sub-profiles Full capacity Full (notes sell / payouts OK; score verify optional)
16–17 Senior secondary F5–6 / IB Full student Parental awareness checkbox; parent/guardian contact as financial guarantor on paid cases Co-sign parent on tutor terms + payout bank verify
13–15 Junior secondary ~F1–4 Full student browse / requests Parent co-pilot at checkout for 1.5 fee confirm Blocked from tutor role
<13 (incl. primary & early Form 1 ~11–12) Young students No hard ban — convert to #459 student sub-profile linked to parent email/WA Parent-managed fees + WA Blocked from tutor role

Legacy users: no login lockout; non-blocking banner on next booking or profile edit until DOB collected.


4. Public birthday (Facebook-style, opt-in)

  • Default show_birthday_public = false
  • If on: show 🎂 15 Mar (month + day only) to logged-in users only
  • Never public year or exact age
  • Not in unauthenticated HTML/API (anti-scrape)

5. #514 CRM + birthday WhatsApp

Progressive profiling (keep Day-0 card thin)

When Collect Why
Onboarding (Day 0) Role + DOB only Gates + birthday
First case / tutor setup Curriculum, exam year, subject/goal Milestone check-ins
WA chat tags (#514) Language, hobbies, learning style, age/Form/DOB if no website account Holistic memory

6. ToS + Privacy Policy / PICS (must ship with feature)

Privacy / PICS (Cap. 486)

  1. DPP1: DOB collected for age eligibility & safeguards; contractual capacity for paid matches / Platform Administrative Fee; personalisation (optional public month/day badge; birthday WA/email subject to marketing consent).
  2. DPP3: Birth year confidential; month/day public only if user toggles show-birthday.
  3. Part 6A direct marketing: clear Account Settings opt-out for birthday wishes & perks via WhatsApp.
  4. DPP2/4: restricted Ops/CS access ([Ops · CRM · #511] Client relationship memory #514); user can see own DOB.

ToS

  1. Minors & parental guarantee: under-18 browse/connect with parent/guardian involvement; parent assumes financial responsibility for the 1.5-lesson Platform Administrative Fee and related settlements.
  2. Independent Tutor: independent operators (never employment / agency-employee language); warrant ≥18 or verified parental co-consent to tutor.

7. Risks

Risk Mitigation
Fake DOB No default date; flag Form vs age mismatches in #514
Edit abuse 1 self-serve edit; further changes via CS + user_audit_logs
Child safety Never public year/age; <13 via parent contact
Leap day Feb 29 → Feb 28 non-leap

8. Data sketch

-- users
date_of_birth DATE NULL,
dob_collected_at TIMESTAMPTZ NULL,
dob_edit_count INT NOT NULL DEFAULT 0,
parental_gate_status VARCHAR(32) NOT NULL DEFAULT 'none',
-- none | awareness_checked | parent_linked | verified_adult | blocked
parent_contact_reference VARCHAR(255) NULL,
show_birthday_public BOOLEAN NOT NULL DEFAULT FALSE,
allow_birthday_whatsapp BOOLEAN NOT NULL DEFAULT TRUE,
onboarding_tour_completed BOOLEAN NOT NULL DEFAULT FALSE;

-- child_sub_profiles (#459)
date_of_birth DATE NULL,
graduation_year INT NULL,
personal_notes JSONB DEFAULT '{}';

-- birthday cron index on month/day where DOB set and allow_birthday_whatsapp

Public serializer: strip DOB; if opted in + authenticated requester → birthday_display: "15 Mar" only.
Middleware: if dob_collected_at null on new account → onboarding card; on complete → persist + startSpotlightTour.


9. Acceptance criteria

  • Post-OAuth card: role + DD/MMM/YYYY; brand palette; <8s path
  • Age gates per table (≥18 / 16–17 / 13–15 / <13 → sub-profile, no hard ban)
  • Parent role + age <18 → mis-entry helper (child DOB blocked on parent primary)
  • Spotlight tour after Continue
  • Public birthday opt-in month/day only; never year; logged-in only
  • One self-serve DOB edit; further via CS + audit
  • 09:30 HKT birthday cards into [Epic · Ops/WA] Business WhatsApp AI desk #511/[Ops · CRM · #511] Client relationship memory #514 queue; Feb 29 handled; marketing opt-out
  • Ops can store age/DOB/Form on [Ops · CRM · #511] Client relationship memory #514 for WA-only clients
  • ToS + PICS updated (Cap. 410 parental guarantee for 1.5 fee; Independent Tutor; PDPO + marketing opt-out)
  • Copy: Platform Administrative Fee / Independent Tutor only

Open for CEO / counsel

  1. Confirm cut-offs (esp. Form 1 ~11–12 = Tier 4).
  2. Tutor minimum: block <16 hard vs co-sign at 16–17 only (draft = co-sign 16–17, block <16).
  3. Birthday WA: Business line only vs also personal CS2.

Out of scope

Community birthday feed; selling age data; replacing #459 role model; Google user.birthday.read scope.

Activity

  1. changed the title [-][Feature · #459] Collect DOB / age on Google sign-up — UX card, HK capacity & PDPO, spotlight + #514 birthday CRM[/-] [+][Feature · #459] DOB / age on Google sign-up[/+] on Oct 29, 2026
  2. added a commit that references this issue on Nov 1, 2026
  3. keyframesfound commented on Nov 1, 2026

    @keyframesfound
    Owner

    Closing — website-side scope shipped on main (c0e8ce4, 20261101060000 migration prod-applied):

    • Post-OAuth DOB card in the first-run onboarding dialog (OnboardingGate.tsx): Day/Month/Year selects, 🔒 year-private copy, optional — the 5-second target. Same save records role intent + handle (unchanged [Urgent · V1] Unified account + roles + child sub-profiles + hours ledger #459 flow).
    • Age tiers (HK Cap.410 / PDPO): <18 requires the parental-awareness checkbox (parental_awareness_confirmed_at stamped server-side); <13 collects parent/guardian contact; under-16 cannot activate Teaching — enforced in the extended complete_onboarding RPC (AGE_RESTRICTED) AND in submitTutorApplication (defence in depth). 16–17 full student with co-sign checkbox; ≥18 full. Missing DOB never blocks (legacy).
    • Public birthday: show_birthday_public default off; when on, the Channel Profile shows 🎂 MM-DD only to logged-in users — year/age never leave the server (verified in getChannelProfile).
    • Legacy users: non-blocking banner on /account → Settings → Birthday (date_of_birth editable there).
    • Schema: profiles.date_of_birth/show_birthday_public/parent_guardian_contact/parental_awareness_confirmed_at + age_tier(user_id) helper; migration live on prod.
    • ⏭️ Birthday WhatsApp CRM ([Ops · CRM · #511] Client relationship memory #514/[Epic · Ops/WA] Business WhatsApp AI desk #511 daily 09:30 card) — explicitly excluded per the owner's standing WA-exclusion instruction; the spotlight-tour handoff remains the existing tour contract (gate reports pending → tours start on accept, shipped 2026-10-24).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ClaudeRoute to Claude Code: complex or UI-heavy workenhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions