---
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.
