Skip to content

[Ops · F4] Contact after fee · guarded self-serve carousel #255

Closed

Description

@owlstonbusiness-svg

Issue F4 — Contact after the fee · Guarded Self-Serve Carousel (phased)

V2 on-platform chat implementation is #476; Phase 0 WA rules unchanged.

Payer-agnostic gate: Contact unlock remains admin fee marked paid (fee_paid / settled) regardless of who the payer is after #444 (tutor-pays lock #464). Do not rebuild the gate around parent-pays-first.

Status / timing lock (CEO + Jarvis · 2026-10-25 HKT)

Do NOT push guarded self-serve chat as the default now.

Stage When What ships
V1 (now) — Phase 0 Immediate urgents Keep this issue’s original rule: human WhatsApp match; phones after fee_paid; no product inbox / no message table. Staff-only contact before fee. Bypass = staff flag (#254), not a WA scanner.
V1.5 gate — Phase A After #459 ledger + #461A lesson log + desk packs #449/#451/#454 in daily use and fee collection is boringly reliable Contact-filter hardening on any text surfaces that will feed chat; unlock-ladder plumbing against fee_paid + verified lessons; still no public carousel chat.
V2 self-serve — Phases B–C After V1.5 gate + #441 Double-Lock is routine Tutor carousel (“Request intro”) + case-scoped intro thread + contact scanner + /phones only after lessons (ladder below).
V2.5 — Phase D After volume Auto-penalties, leak honeypot / weekly CS metrics, soft density hooks from #450.

Unpark trigger: CEO confirms fee leakage risk and lesson logging are stable for ≥2 weeks. Until then this issue stays the V1 contact gate + a parked design for later.

Labels: keep open; not urgent. Later phases are On Hold in spirit even if the issue itself stays the live F4 home.


Phase 0 / V1 — original F4 (SHIP / KEEP)

Summary

No inbox. After the admin fee is paid, each side can see the other’s phone on that case. Before that, only staff can.

Rule (V1 — LOCKED for now)

  • Status before fee_paid: neither side sees a phone, email, or WhatsApp.
  • Status fee_paid or active: the parent or centre contact and the tutor can open the phone on that case.
  • A waive or a refund hides it again.
  • The page says the later lessons are between them. MatchMax does not host the messages.
  • Copying the number out is not blocked. The fee was for the introduction.
  • No message table is created in V1.

Penalty (V1)

  • If the intro happened and the fee is unpaid, staff can invoice it, close the case, and ban new requests.
  • The ban covers the parent, the centre contact, and the tutor on that case.
  • No fine above the unpaid fee. No scanner on WhatsApp. (Bypass = staff flag — #254.)

Acceptance (V1)

  • A case at lesson_2_done before fee_paid shows no phone.
  • A case at fee_paid shows the phone to both parties on that case.
  • No message table is created in V1.

Fee alignment

  • Admin fee = tutor-pays 1.5 lessons (short-case ≤5 → 20% package) — #464 · #443.
  • Double-Lock Lock 2: phones stay locked until Operator marks fee paid — #441.

Phases A–D — Guarded Self-Serve Carousel (PARKED · V1.5 → V2.5)

CEO direction (2026-10-25): browse tutors like a carousel, connect/chat on-platform, detect phone / WA / contact pushes, release raw contact only after they have had lessons, heavy penalty if they try to space / bypass the filter. This extends Phase 0; it does not replace human matching V1.

Why later (not early)

  1. Desk speed ([Ops] Failed-trial pivot + soft tutor inactive #449 / [Ops] Matching speed & reliability pack #451 / [Ops] Matching cockpit + website conversion polish #454) is the bottleneck, not missing DMs.
  2. Chat without a rock-solid fee + lesson gate leaks (IG / WeChat swap → skip admin fee).
  3. Cap.57 + dispute surface gets heavier once MatchMax hosts intro tooling — need counsel-ready copy + report/ban rails.
  4. Hours ledger ([Urgent · V1] Unified account + roles + child sub-profiles + hours ledger #459) + lesson log (#461A) are required for “after lessons” unlock and Trophy/rebate flywheel — build those first.

Does not replace desk V1


1. Carousel UX (Phase B)

Surfaces

  • Homepage “Match tutors” row (swipe cards).
  • Search / filter results (card grid that can swipe on mobile).
  • Later: #472 For you shortlist.
  • Public case board: tutor apply-from-card (tutor-side density; parent still goes through case + fee ladder).

Card chrome (minimum)

Empty / edge

┌─────────────────────────────────────────────┐
│  Match tutors                    See all →  │
│  ┌────────┐ ┌────────┐ ┌────────┐           │
│  │ Photo  │ │ Photo  │ │ Photo  │  → swipe  │
│  │ DSE M2 │ │ IB Econ│ │ IGCSE  │           │
│  │ $350/h │ │ $400/h │ │ $280/h │           │
│  │ 42h ✓  │ │ 18h ✓  │ │ 9h ✓   │           │
│  │[Request│ │[Request│ │[Notify │           │
│  │ intro] │ │ intro] │ │ when▲] │           │
│  └────────┘ └────────┘ └────────┘           │
└─────────────────────────────────────────────┘

2. Case-scoped intro thread (Phase C) — not a social inbox

Lock Rule
Scope One thread per TuitionCase (parent/centre ↔ assigned tutor). No global DM inbox, no tutor↔tutor chat here (#332 stays parked).
Create Only after “Request intro” (or desk assign) creates / binds a case.
Staff Desk can shadow / read for Double-Lock (#441) and dispute; audited views.
Exit After /phones unlock (ladder below), copy still says ongoing lessons are between the parties; MatchMax may archive the intro thread.
Cap.57 MatchMax = intro tooling host only, not employer, not party to the lesson contract. Solicitor review before launch. Cross-link live TOS + #473 protective pack where promos appear; core matching language stays in TOS.

Wireframe (thread)

┌─ Case #1042 · DSE Maths · Intro ─────────────┐
│ 🔒 Contacts unlock after fee + 1 verified L1 │
│                                              │
│ Parent: Hi, looking for 2×/week after school │
│ Tutor:  I can do Tue/Thu 7pm — rate $350/h   │
│ ⚠ System: Phone / WA / IG links are blocked  │
│           until unlock.                      │
│                                              │
│ [ Type a message…          ] [Send]          │
└──────────────────────────────────────────────┘

3. Contact filter stack (Phase A → C)

Reuse #215 (closed) / #220 community contact filter. Extend for intro chat:

Detect Notes
HK phone patterns +852 / spaced / dashed; bare 8-digit only when adjacent to phone/tel/mobile/call (same #220 rule)
WhatsApp wa.me, whatsapp, word-spaced digits
Social Instagram / IG / Telegram / Signal / Line / WeChat / Weixin / t.me / ig.me
Email standard shapes
Handles @name when clearly contact-seeking (tune false positives)
Images OCR if/when scanner configured (#220); QR codes; until OCR live → warn + report path
Evasion zero-width chars, spaced digits (9 1 2 3…), homoglyphs, mixed full-width digits

Progressive enforcement (chat)

  1. Redact matching spans (message may still send with ••• / [contact hidden]).
  2. Warn toast to sender (“Contacts unlock after fee + first verified lesson”).
  3. Strike (see matrix) on repeated / clear intent.
  4. Freeze thread (read-only) pending staff.
  5. Ban matching requests (both sides if both leaked).

Staff override for false positives = audited (#220). Appeal: in-thread “This wasn’t a contact” → staff queue.


4. Unlock ladder — LOCKED (CEO “after lessons”)

Stage What parties see Filter
Before fee_paid In-app intro thread only; no raw phone / email / WA ON
fee_paid (tutor-pays 1.5 / short 20% settled) Still no raw /phones by default Prefer ON until L1 verified
fee_paid AND ≥1 VERIFIED_COMPLETED lesson on that case /phones released to both parties on that case May relax for that case; optional soft warn remains
Waive / refund Hide phones again —

Waive path (staff): Operator may unlock /phones early with audited reason (e.g. centre Cap.57 overflow, proven offline intro, goodwill) — same spirit as fee waive. Default product path = ladder above.

Payment lock: Unlock never before the admin-fee path for that case type is clear (standard 1.5 or short-case 20%). Hybrid short-case still requires the applicable fee settled before counting toward unlock.

Contrast with V1 Phase 0: V1 releases phones at fee_paid with no chat. V2 ladder is stricter on raw contact (needs lesson) because MatchMax now hosts a channel that can leak earlier.


5. Bypass penalty matrix (Phase C → D)

Keep #255 spirit: no fine above the unpaid admin fee. Ban / freeze is the heavy stick.

Strike Trigger (examples) Action
1 First clear filter hit / spaced-digit attempt Warn both sides in-thread; log hit
2 Repeat within same case or across cases 7-day new-request ban for offender; thread freeze optional
3 Persistent bypass / successful off-platform intro with fee unpaid Permanent matching ban (parent and/or tutor as applicable) + invoice unpaid admin if intro happened; close case
Staff escalate Fraud / multi-account / safety #441 REVIEW → BLOCKED; CS-005 playbook

6. Leak honeypot / metrics (Phase D)

  • Log every filter hit: case_id, actor role, rule id, redaction vs block, strike level (no raw PII in analytics exports).
  • Weekly CS digest: near-misses, top evasion patterns, false-positive rate.
  • Optional honeypot: invisible tokens / canary strings that only appear if user copy-pastes system UI — flag as high-intent scrape (staff review, not auto-ban alone).

7. Cap.57 / legal

  • Intro tooling host only; tutors remain independent; MatchMax not employer / not party to lesson contract.
  • Solicitor review before V2 launch (in-app messaging + automated penalties).
  • TOS cross-link; promotional “保留最終決定權” pack is #473 (N/A to matching chat itself).
  • PDPO: chat content used for safety / fee enforcement / dispute only — Privacy Policy update if needed.

8. Phasing checklist

Phase A — V1.5 gate (filter + ladder plumbing)

Phase B — Carousel “Request intro”

  • Homepage + search carousel cards
  • CTA creates/binds case; no thread until case exists
  • Capacity / empty / notify-when-free edges
  • P1 / high-risk cases still route to desk wave ≤3

Phase C — Intro chat + scanner + post-lesson phones

Phase D — Auto-penalties + metrics


9. Acceptance criteria (V2 — when unparked)

  • Parent can browse carousel and tap Request intro without seeing tutor phone.
  • Intro thread exists only for that case; no global inbox.
  • Message containing 9123 4567 / wa.me / spaced digits is redacted or blocked; sender warned.
  • /phones hidden until fee_paid and ≥1 verified completed lesson (unless staff waive).
  • Strike 2 imposes 7-day request ban; Strike 3 bans + invoices unpaid admin when intro happened.
  • No fine amount above unpaid admin fee.
  • Desk can still run human WA matching in parallel; V1 Phase 0 behaviour unchanged when intro_chat_enabled=false.
  • Cap.57 / independence copy visible near chat; solicitor sign-off recorded before prod flag on.
  • Filter false-positive has staff override + appeal path.
  • Tutor at capacity cannot open a new intro thread from carousel.

10. Out of scope


Cross-links

Issue Role
#254 Bypass = staff flag (V1); no WA scanner
#215 / #220 Contact filter reuse
#441 Double-Lock; staff shadow / BLOCKED
#450 §G Website later — this issue is home for guarded self-serve
#459 / #461 Ledger + lesson log (unlock prerequisite)
#449 / #451 / #454 Desk packs before unpark
#464 / #443 Tutor-pays 1.5 / short 20%
#472 For you carousel surface later
#473 Protective clauses (promos); TOS for matching
#332 No squad / global chat

Activity

  1. owlstonbusiness-svg commented on Oct 24, 2026

    @owlstonbusiness-svg
    CollaboratorAuthor

    Cross-link: Double-Lock Lock 2 (phones stay locked until Operator fee paid) lives in #441 + CS-005.

  2. owlstonbusiness-svg commented on Oct 24, 2026

    @owlstonbusiness-svg
    CollaboratorAuthor

    Broker Overflow #442: B2B cases never store end-parent phone; Lesson-2 tutor confirm gates the 1.5-lesson invoice / waive before fee collection.

  3. owlstonbusiness-svg commented on Oct 24, 2026

    @owlstonbusiness-svg
    CollaboratorAuthor

    Cross-link: #442 — Referral lane still uses phones-after-fee; Overflow never stores end-parent.

  4. owlstonbusiness-svg commented on Oct 24, 2026

    @owlstonbusiness-svg
    CollaboratorAuthor

    Cross-link: #443 Short-Case (≤5 → 20%) still respects Paid/Settled before contact-release promises; short invoice after L1 (or booking if 1 session).

  5. owlstonbusiness-svg commented on Oct 25, 2026

    @owlstonbusiness-svg
    CollaboratorAuthor

    Packed under Fee Model Track #464 (2026-10-25).

    CEO locks: tutor pays 1.5-lesson admin · short ≤5 = 20% package · pro-bono 0% · parents/centres do not pay MatchMax matching fees.
    Legacy F1 parent-pays text in #252 closed as superseded. Calendar calculator UI stays parked in #461.

  6. changed the title [-]# Issue F4 — Contact after the fee, not a chat[/-] [+]Issue F4 — Contact after the fee · Guarded Self-Serve Carousel (phased)[/+] on Oct 25, 2026
  7. owlstonbusiness-svg commented on Oct 25, 2026

    @owlstonbusiness-svg
    CollaboratorAuthor

    Expanded 2026-10-25 (CEO + Jarvis) — no new epic.

  8. owlstonbusiness-svg commented on Oct 25, 2026

    @owlstonbusiness-svg
    CollaboratorAuthor

    V1 re-audit note (2026-10-25) — not marking whole issue urgent

  9. owlstonbusiness-svg commented on Oct 25, 2026

    @owlstonbusiness-svg
    CollaboratorAuthor

    V2 chat home locked → #476 (2026-10-26)

    CEO design for AI-Supervised On-Platform Chat (intake bot + 3-way concierge + dual-layer anti-leak + Admin Sentinel) lives in #476.

  10. owlstonbusiness-svg commented on Oct 25, 2026

    @owlstonbusiness-svg
    CollaboratorAuthor

    Follow-up: #476 unlock language now matches this issue’s ladder (fee_paid ∧ ≥1 verified lesson; filter stays on at fee alone). Strike matrix + contact-filter.ts reuse locked in #476 §4.5–4.6 / §10.

  11. owlstonbusiness-svg commented on Oct 27, 2026

    @owlstonbusiness-svg
    CollaboratorAuthor

    CEO 2026-10-27: marked urgent — V1 must-build for the closed loop (lead → fast match → fee → hours). Not a scope expand beyond this issue’s existing V1 slice; parked V2/community/marketplace work stays On Hold.

  12. changed the title [-]Issue F4 — Contact after the fee · Guarded Self-Serve Carousel (phased)[/-] [+][Ops · F4] Contact after fee · guarded self-serve carousel[/+] on Oct 29, 2026
  13. keyframesfound commented on Nov 1, 2026

    @keyframesfound
    Owner

    Closing — the V1 Phase 0 rule this issue locks is shipped and verified; every later phase is explicitly gated on a CEO unpark decision that lives in #476, so there is no agent-buildable scope left here.

    Phase 0 (V1) verified on main @ 1a2a400:

    Later phases (A–D) stay parked by design — the body's own timing lock ("Do NOT push guarded self-serve chat as the default now", unpark = CEO confirms fee leakage + lesson logging stable ≥2 weeks) supersedes the urgent label for those phases; V2 chat implementation tracks #476. Closing per the urgent-queue sweep; reopen if the CEO unpark trigger fires.

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

    enhancementNew feature or requesturgentGood for newcomers

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions