Phase 4 Stage 10 Maestro: 09_chat_tab.yaml + seed-pending-payment endpoint
Closes the Stage 10 acceptance criterion §10.11 #13 (Maestro coverage). - New dev-only `POST /internal/_test/seed-pending-payment` — inserts a payment_sessions row in `pending` status with expires_at 20m out, so the Pembayaran sub-tab has a deterministic row to render. Body accepts { phone, isExtension?, amount?, durationMinutes?, mode? }. Gated on NODE_ENV != 'production' like the other test routes. - New Maestro helper script `seed_pending_payment.js` mirrors the existing seed_history_session pattern. - New flow `09_chat_tab.yaml`: cold-start onboarding → home (returning view) → seed completed session + seed pending payment → tap "💬 chat" bottom-nav → lands on /chat/aktif via redirect → assert "aktif" / "pembayaran" / "selesai" pills + empty-state copy → tap pembayaran → assert "menunggu pembayaran sesi" + "bayar Rp..." → tap selesai → assert "X menit" duration row → tap row → assert "Transkrip Chat" appbar → back → still on /chat/selesai. Maestro parsed the YAML cleanly and started executing against the device; full run requires backend + online mitra in dev DB (same pre-reqs as flows 03/05/06/08). - TECH_DEBT entry: Stage 10 retired the standalone bestie-history list screen, which means (a) the "curhat lagi" targeted-payment entry point has no UI affordance anywhere in the app — its plumbing in payment_notifier / payment_screen is now orphaned, and (b) the Stage 8 flow `08_returning_targeted.yaml` will fail at `assertVisible: "Riwayat Chat"` because it expects the deleted screen. Three fix paths listed in the entry for product to pick. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
105
TECH_DEBT.md
Normal file
105
TECH_DEBT.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# Tech Debt
|
||||
|
||||
Running list of known shortcuts, deferred hardening, and "good enough for now"
|
||||
decisions that need follow-up before they bite us in production.
|
||||
|
||||
Format: `[date]` short title, then enough context for someone (or future-you)
|
||||
to act on it without re-deriving the discussion.
|
||||
|
||||
---
|
||||
|
||||
## Backend
|
||||
|
||||
### `[2026-05-11]` Public `GET /api/public/bestie/available` needs rate limiting before prod
|
||||
|
||||
**File:** `backend/src/routes/public/public.bestie-availability.routes.js`
|
||||
|
||||
**Decision:** The endpoint was made unauthenticated by business requirement —
|
||||
SHome1st renders before any JWT exists, and the CTA must reflect global mitra
|
||||
availability so users see whether bestie is online before committing to
|
||||
onboarding. Response is intentionally a single boolean (no count, no IDs).
|
||||
|
||||
**Why it's debt:** No auth + no rate limit. The 10s in-memory cache bounds DB
|
||||
load, but a single attacker can still hammer the endpoint to:
|
||||
- run sustained traffic against the public listener (DoS surface)
|
||||
- scrape `available` over time to infer mitra online/offline patterns (weak
|
||||
information leak — only "is anyone online", but still a signal)
|
||||
|
||||
**Mitigation before prod:**
|
||||
- Per-IP rate limit (suggested: ~30 req/min/IP, headroom over the legitimate
|
||||
5s client poll cadence = 12 req/min/IP).
|
||||
- Implement via `@fastify/rate-limit` plugin so other public endpoints can
|
||||
share the policy as we add them under `/api/public/*`.
|
||||
- Verify Cloud Run / NLB preserves real client IP and that
|
||||
`request.ip` reflects it (Fastify already has `trustProxy: true`).
|
||||
|
||||
**Not required:** auth, captcha, or removing the count from
|
||||
`/api/client/mitra-availability` (that route stays authed for CC/debug).
|
||||
|
||||
---
|
||||
|
||||
## Client app
|
||||
|
||||
### `[2026-05-11]` Social-login (Google / Apple) has no entry point after S3a rewrite
|
||||
|
||||
**Files:** `client_app/lib/features/auth/screens/register_screen.dart` (no longer renders them); `client_app/lib/core/auth/auth_providers_provider.dart` (still wired).
|
||||
|
||||
**Decision:** `RegisterScreen` was rewritten to match Figma `S3Phone` 1:1
|
||||
(step-dots + name greeting + privacy card + tanpa-verif ghost link). Figma
|
||||
S3a shows no Google/Apple buttons, so they were removed from this screen.
|
||||
|
||||
**Why it's debt:** Google/Apple buttons used to render here when the
|
||||
`authProvidersProvider` flags were enabled. Today both flags are `false`
|
||||
(creds pending — see `Phase 3.4 Status` memory), so nothing visible is
|
||||
missing. But the moment `/api/shared/auth-providers` flips either flag,
|
||||
the buttons have nowhere to live.
|
||||
|
||||
**Fix-when-creds-arrive:**
|
||||
- Decide where Google/Apple buttons belong (likely a dedicated login screen
|
||||
reachable from the SHome1st "masuk →" banner), or whether to bring them
|
||||
back to S3a as Figma-friendly tiles above the phone input.
|
||||
- `loginGoogle` / `loginApple` on `authProvider` are still intact, so the
|
||||
wiring is one button widget away.
|
||||
|
||||
### `[2026-05-12]` Stage 10 — "curhat lagi" entry point lost; Stage 8 Maestro flow broken
|
||||
|
||||
**Files:** `client_app/lib/features/home/widgets/bestie_choice_sheet.dart` (line ~54, now routes to `/chat`); `client_app/.maestro/flows/08_returning_targeted.yaml` (asserts "Riwayat Chat" + "curhat lagi" which no longer render).
|
||||
|
||||
**Decision:** Stage 10 retired `chat_history_screen.dart` and re-pointed the BestieChoiceSheet "bestie yang udah kenal" CTA at `/chat` (which redirects to `/chat/aktif`). The Selesai sub-tab matches Figma `SChatList` — transcript-only, no per-row "curhat lagi" button.
|
||||
|
||||
**Why it's debt:** The "curhat lagi" targeted-payment entry point lived only on the deleted history screen (line 213 `label: 'curhat lagi'` → `context.push('/payment', extra: { 'targetedMitraId': ... })`). After Stage 10 there is **no** UI affordance to start a targeted payment against a known mitra from the customer app — only the general "Mulai Curhat → blast" path. The targeted-payment plumbing in `payment_notifier.dart` / `payment_screen.dart` is now orphaned (still wired, no caller).
|
||||
|
||||
Side-effect: `08_returning_targeted.yaml` (Stage 8) expects to navigate from BestieChoiceSheet → bestie-history list → "curhat lagi" tap → targeted payment. The middle screen is gone; the flow will fail at `assertVisible: "Riwayat Chat"`.
|
||||
|
||||
**Fix options (pick one with product):**
|
||||
- **A.** Add a "curhat lagi" secondary CTA on Selesai rows (deviates from Figma SChatList but restores the feature). Update `08_returning_targeted.yaml` to navigate `/chat/selesai → tap row's curhat-lagi → targeted payment`.
|
||||
- **B.** Keep Selesai as transcript-only per Figma; reintroduce a "pick a past bestie" picker reachable from BestieChoiceSheet (essentially restore `chat_history_screen.dart` under a new name + route, kept separate from the Chat tab).
|
||||
- **C.** Drop the "curhat lagi" feature entirely. Update mermaid + BestieChoiceSheet copy to remove the "bestie yang udah kenal" branch. Delete orphaned targeted-payment plumbing.
|
||||
|
||||
Until decided, `08_returning_targeted.yaml` should be marked `.skip` or the Stage 8 flow rewritten against the new home → SHomeReturning history list (which DOES still render bestie rows via `bestieHistoryProvider`, but those rows tap-through to transcripts only — same "no curhat lagi" gap).
|
||||
|
||||
### `[2026-05-12]` S5 ESP screen retired from spec — code still ships it
|
||||
|
||||
**Files:** `client_app/lib/features/onboarding/` (S5ESP screen + nav wiring);
|
||||
`screens/onboarding.jsx::S5ESP` (Figma reference still in handoff); any
|
||||
`espSelectionProvider` / `espSkippedProvider` Riverpod state.
|
||||
|
||||
**Decision:** Business removed the ESP multi-select step from the customer
|
||||
flow on 2026-05-12. Both verified and anonymous branches now go from
|
||||
`VerifChoiceSheet` straight to the `usp_seen?` gate. See
|
||||
`requirement/flow_customer.mermaid.md` §2.
|
||||
|
||||
**Why it's debt:** Stage 2 (commit `2645bcd`) shipped the ESP screen and its
|
||||
state providers. The screen is still reachable in the current build. The
|
||||
mermaid spec is the source of truth — the code has drifted behind by one
|
||||
business decision.
|
||||
|
||||
**Fix:**
|
||||
- Delete the ESP screen widget and its route registration.
|
||||
- Remove `espSelectionProvider` / `espSkippedProvider` and any nav step that
|
||||
routes through ESP.
|
||||
- Wire `VerifChoiceSheet → USPGate → (USP screen | skip → next)` directly.
|
||||
- Drop the "ESP is decorative only" memory (it's now superseded by removal).
|
||||
- Keep `screens/onboarding.jsx::S5ESP` in the Figma handoff folder — it's
|
||||
history, not active design.
|
||||
|
||||
Reference in New Issue
Block a user