--- status: ANSWERED — ready for PRD (phase3.7.md) captured: 2026-05-02 answered: 2026-05-03 --- # Phase 3.7 — Clarifying Questions (Answered) Raw asks from user (2026-05-02 chat): 1. CTA Curhat on customer home is gated by mitra availability — pulled every 5 seconds. 2. New session flow: **CTA → payment screen → payment confirmed → blast → mitra accept (idempotent) → chat starts**. (Today: blast happens immediately on CTA, no payment in path.) 3. Customer can start a new session with the **same** mitra via a CTA on chat history. 4. Returning-chat (same-mitra) requests need mitra approval. **20-second** window, **auto-reject** on timeout. Timeout configurable via control center. 5. Session extension still requires approval, but **10-second** window with **auto-approve** on timeout (flip from today's auto-reject). Configurable via control center. --- ## Phase numbering — DECIDED - Called **Phase 3.7** (next free after 3.6). Originally drafted as "Phase 4" but user prefers to keep 3.x numbering for this scope. --- ## Section 1 — CTA gated by mitra availability (5s poll) | # | Q | Answer | |---|---|---| | 1.1 | Signal definition | **(b)** at least 1 mitra online **AND below max-customer capacity** | | 1.2 | Endpoint shape | New lightweight `GET /api/client/mitra-availability` → `{ available: bool, count?: number }`. **Backend reads from Valkey only — must not hit Postgres on every poll.** Count optional in payload (CC debugging), client only reads `available` | | 1.3 | Polling lifecycle | Foreground only. Pause on background, resume on foreground | | 1.4 | Disabled-state UX | **(a)** Greyed CTA with subtitle "Belum ada bestie tersedia" | | 1.5 | Visible count | Binary only — no number shown to user | | 1.6 | Stale data on poll fail | **(b)** Default to disabled | --- ## Section 2 — New flow: CTA → Payment → Blast → Accept → Chat ### 2a. Payment screen | # | Q | Answer | |---|---|---| | 2a.1 | Integration depth | **Mocked** — no real Xendit in 3.7. Real Xendit deferred to a later phase | | 2a.2 | Pricing source | Keep existing Phase 3 mock pricing. Real pricing/tiers later (saved to memory) | | 2a.3 | Free trial UX | **(b)** "Gratis" Rp 0 confirmation step on the same payment screen — does not skip to blast | | 2a.4 | Abandonment | **(b)** Persist a "pending payment" / "abandoned" row; auto-expire after configurable timeout | | 2a.5 | Payment timeout | **20 minutes default**, **CC-configurable** (`payment_session_timeout_minutes`) | ### 2b. Blast → Accept | # | Q | Answer | |---|---|---| | 2b.1 | Customer screen during blast | Reuse existing "Searching for bestie..." screen. Real design later via Claude design | | 2b.2 | Blast timeout | Same as Phase 2; verify it is CC-configurable, otherwise add `pairing_blast_timeout_seconds` | | 2b.3 | No mitra accepts within window | **Persist payment + log failed-pairing event with a tag** (e.g. `no_mitra_available`, `all_mitras_rejected`, `targeted_mitra_offline`, `targeted_mitra_rejected`, `targeted_mitra_timeout`, `payment_session_expired`, `customer_cancelled`). Surface to **Control Center for manual review/refund decision**. Customer-facing: hard-fail message for now (CTA copy will be revised later) | | 2b.4 | All mitras explicitly reject | Same as 2b.3 — different tag value | | 2b.5 | Idempotency on accept | Confirmed — keep Phase 2's DB-level uniqueness on session acceptance | ### 2c. Migration | # | Q | Answer | |---|---|---| | 2c.1 | Replacement strategy | **Replace entirely** — delete the old instant-blast path. No feature flag | | 2c.2 | Existing screens | Reuse where possible; replace only when reuse is impractical | --- ## Section 3 — "Curhat lagi" with the same mitra (from chat history) | # | Q | Answer | |---|---|---| | 3.1 | Per row or per partner | **(a)** CTA on every chat history row (simpler) | | 3.2 | Payment first | Yes — same payment screen as regular curhat | | 3.3 | Mitra offline at tap | **(a) but with popup** — show "Bestie sedang tidak online" popup. Offer "Chat dengan bestie lain" if any other mitra is available; otherwise just show the offline message | | 3.4 | Mitra at capacity | Same as 3.3 | | 3.5 | On rejection / 20s auto-reject | Same as 3.3. **Important:** payment is already taken by this point — **the same payment carries over to the general blast fallback (no double-charge)**. If fallback also fails, treat as 2b.3 (logged + CC review with appropriate tag) | | 3.6 | Bypass general gating | **Independent** — depends only on the targeted mitra's status, not the section 1 availability poll | | 3.7 | Anonymity | Unchanged (mitra always sees customer call_name) | --- ## Section 4 — Returning-chat approval window (20s, auto-reject) | # | Q | Answer | |---|---|---| | 4.1 | Mitra UX | Reuse existing incoming-request notification component (FCM + foreground card), add visible 20s countdown | | 4.2 | Customer UX during 20s | **(a)** Overlay "Menunggu konfirmasi bestie..." with cancel button | | 4.3 | Auto-reject downstream | Same as 3.5 (popup → offer general blast fallback or fail; payment carries over) | | 4.4 | Mitra offline at request time | **(a)** Auto-reject immediately, do not wait 20s | | 4.5 | Control center config | New config row: `returning_chat_confirmation_timeout_seconds` (default 20). **Use a clear label and explanation in the CC UI** | | 4.6 | Concurrency (mitra mid-session with someone else) | **(c)** Send the card and let mitra decide | --- ## Section 5 — Extension approval flip (10s, **auto-approve**) | # | Q | Answer | |---|---|---| | 5.1 | Behavioral flip — confirm | **Confirmed intentional** — flip from auto-reject → auto-approve | | 5.2 | Default value & config | **(c)** Keep existing extension-timeout row; add new `extension_default_action_on_timeout` enum (`auto_reject` \| `auto_approve`), default `auto_approve` | | 5.3 | Customer overlay during 10s | Same overlay as today, just shorter timer | | 5.4 | Charge timing for extension | **(b)** Charge at approval moment (auto-approve fires charge; explicit reject within 10s = no charge). **Important:** extension is NOT auto-charged — customer chooses time + price first (same UX as initial chat request, **without trial**) | | 5.5 | Mitra UX | Same extension card; copy adjusted to reflect auto-approve | | 5.6 | Mitra disconnected/offline during 10s | **(b)** Treat as auto-reject (safer for customer). **Domain rule (saved to memory): mitra can flip to offline mid-session — never use "in-session" as proxy for "online"** | --- ## Cross-cutting | # | Q | Answer | |---|---|---| | X.1 | Refund / failed-pairing model | Single consistent model across 2b.3 / 3.5 / 4.3: payment row persists, event logged with **tag** (cause) for filtering/audit, surfaced to CC for manual review | | X.2 | Old instant-blast code | **Delete entirely**, no kill-switch, no feature flag | | X.3 | Free trial | Same payment screen UI, Rp 0 / "Gratis", with duration/tier picker shown | | X.4 | Anonymity | Unchanged | | X.5 | New CC configs | `pairing_blast_timeout_seconds` (only if not already), `payment_session_timeout_minutes` (default 20), `returning_chat_confirmation_timeout_seconds` (default 20), `extension_default_action_on_timeout` enum (default `auto_approve`) — no others | | X.6 | Phase numbering | **Phase 3.7** | --- ## Next step PRD `phase3.7.md`, then `phase3.7-plan.md`, then code.