Files
halobestie-clone/requirement/phase3.3.md
ramadhan sjamsani 780cade3db Phase 3.3: topic sensitivity + Phase 3.4: auth foundation
Phase 3.3 — Session Topic Sensitivity (complete):
- Backend: topic_sensitivity column + session_sensitivity_log, sensitivity service
  (flip with one-way-latch + audit), PATCH /api/shared/chat/sessions/:id/topic,
  topic carried in pairing + extension WS payloads, CC filter + sensitive stats
  + per-mitra sensitive columns on activity page
- client_app: TopicSelectionBottomSheet before pricing, topic flows through
  pairing request, silent WS handler for session_topic_updated
- mitra_app: SensitivityBadge + SensitivityTheme + sensitivityConfigProvider,
  overlay badge + yellow accent, chat screen app-bar toggle with configurable
  confirmation + latch, extension card shows current flag, history + transcript
  yellow theme
- control_center: Sensitivitas Topik settings section, topic filter + column
  with inline audit log, sensitive stats dashboard card, mitra activity
  sensitive columns with QC flag

Phase 3.4 — Self-Managed Auth (foundation only):
- Migration: auth_sessions + otp_requests tables, social identity columns on
  customers, password_hash + lockout on control_center_users, OTP + CC lockout
  app_config keys
- New services: password (bcrypt + complexity), token (JWT HS256 + refresh
  rotation, session_id claim pre-wires future Valkey revocation),
  social-identity (Google + Apple JWKS), OTP (Fazpass stub — real API TBD)
- Constants: AuthProvider + OtpChannel
- Middleware, auth route rewrites, WS auth update, Firebase → FCM isolation
  still pending (next chunk); Fazpass docs + Apple Developer setup still
  required before E2E testing

Docs:
- requirement/phase3.3.md, phase3.3-plan.md, phase3.3-testing.md
- requirement/phase3.4.md, phase3.4-plan.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 10:15:12 +08:00

9.4 KiB

PRD: Session Topic Sensitivity

Overview

Goal: Let customers flag a chat session as containing sensitive topics (sexuality, pornography, substance use) so mitras can prepare themselves, and give mitras the ability to re-flag the session mid-chat when the topic drifts.

Success looks like: Every new chat request carries an explicit topic flag (regular or sensitive), the mitra sees the flag on the incoming request and during the chat, mitras can decline on the spot based on the flag, and mitras can change the flag mid-session with an audit trail.

Affects: client_app, mitra_app, backend, control_center

Background

  • Current chat flow has no way for customers to warn mitras about sensitive topics (seksualitas, pornografi, penggunaan zat) before the session starts.
  • Mitras cannot prepare themselves or opt out based on topic sensitivity, which can lead to mid-session discomfort or early terminations.
  • Topics may also drift during a session; there is currently no way for the mitra to re-classify the session.

Functional Requirement

1. Customer: Topic Selection Before Pricing

Trigger

  • Customer taps "Mulai Curhat" on the home screen.
  • Before the pricing screen is shown, a bottom sheet appears asking the customer to classify their topic.

Appearance

  • Bottom sheet, rounded top corners, consistent with existing app theme (pink doodle background).
  • Cannot be dismissed by tapping outside or swiping down — selection is required before the pricing screen is shown.
  • Back button (or system back) cancels the entire "Mulai Curhat" flow.

Copy (Indonesian, non-judgmental)

  • Title: Sebelum kita mulai
  • Body: Supaya kami bisa menyiapkan bestie yang tepat untukmu, boleh kami tahu sedikit tentang ceritamu? Tidak ada penilaian di sini — kamu aman bercerita apa pun.
  • Sub-question: Apakah ceritamu menyentuh topik seperti seksualitas, pornografi, atau penggunaan zat?
  • Button A (primary): Topik umum
  • Button B (secondary, equal weight): Topik sensitif
  • Helper line below buttons: Pilihan ini hanya membantu bestie menyiapkan diri. Kamu tetap bisa bercerita apa adanya.

Behavior

  • Tapping either button stores the choice locally and proceeds to the existing pricing screen.
  • Customer cannot change the flag after this selection — it is locked for the duration of the session.
  • Flag is sent to the backend when the chat request is created (part of the pairing request payload).

2. Mitra: Sensitive Flag on Incoming Chat Request

Appearance on Overlay

  • Incoming chat request overlay (from Phase 3.2) shows a label and color accent when the request is flagged sensitive.
  • Label: "Topik sensitif" (small badge, placed near the session metadata).
  • Color accent: warning-sign yellow (see Section 5 for exact color treatment).
  • Regular requests remain as today — no badge, no color change.

Behavior

  • Mitra may accept or decline as today. No new dedicated "decline because sensitive" flow — the existing reject/ignore paths are sufficient.
  • No per-mitra opt-in setting (e.g., "I accept sensitive topics") in this phase.

Push Notification

  • Push notification content (title/body) stays generic for now — the sensitivity label is surfaced only in the overlay.

3. Mitra: Chat Screen Background Color

Sensitive Sessions

  • Chat screen background switches from pink doodle to warning-yellow doodle (same pattern, different base color).
  • A small persistent header or banner shows "Topik sensitif" label so the context is always visible.

Regular Sessions

  • No change — pink doodle as today.

Customer Side

  • Customer's chat screen always shows pink doodle, regardless of flag.
  • Customer is never given a color cue about topic sensitivity, even if the mitra later flips the flag.

4. Mitra: Flip Flag Mid-Session

Control

  • Toggle icon in the mitra's chat screen app bar.
  • Tapping it flips the session flag (regular ↔ sensitive).

Confirmation Dialog

  • By default, flipping shows a confirmation dialog:
    • regular → sensitive: "Tandai sesi ini sebagai sensitif?" — [Batal] [Tandai]
    • sensitive → regular: "Tandai sesi ini sebagai topik umum?" — [Batal] [Tandai]
  • The confirmation can be disabled via app_config key sensitive_flip_confirmation_enabled (default true). When disabled, the flip happens instantly and a toast appears ("Sesi ditandai sensitif" / "Sesi ditandai topik umum").

One-Way Latch (Configurable)

  • By default, mitra can flip back and forth (regular ↔ sensitive).
  • A app_config key sensitive_flag_one_way_latch (default false) toggles to one-way mode: once sensitive, cannot revert to regular.
  • When latch is active and the session is already sensitive, the toggle icon is disabled (with a tooltip explaining why).

Persistence

  • The flip updates sessions.topic_sensitivity immediately (backend-authoritative).
  • Every flip is recorded in session_sensitivity_log (see Section 7).

WebSocket Event

  • Mitra's flip triggers a WS event to the customer (for future-proofing / analytics), but the customer's client silently ignores it — no UI change.
  • Multi-device mitra sync is not required in this phase (mitra app doesn't yet support concurrent multi-device sessions).

5. Visual Treatment

Color Palette

  • Pink (existing): current doodle theme, used for regular sessions on both sides and for customer side always.
  • Yellow: warning-sign yellow, using the same doodle pattern as pink. Exact hex TBD during implementation — should read clearly as "attention / caution" without feeling alarming.

Badge / Label

  • "Topik sensitif" pill-style badge, pink-text-on-yellow or dark-text-on-yellow for contrast.
  • Used on:
    • Incoming chat request overlay (mitra)
    • Chat screen header (mitra)
    • Extension request card (mitra)
    • Mitra chat history list row
    • Mitra transcript / history detail

Customer Side

  • No yellow, no badge, no label — ever.

6. Extension Flow

Mitra's Extension Request Card

  • When a customer requests extension, the mitra's extension UI shows the current session flag (i.e., whatever the flag is at the time the extension request arrives, including any mid-session mitra flip).
  • Treatment: same as incoming chat request — yellow color accent + "Topik sensitif" badge when applicable.

On Extension Acceptance

  • The flag carries over to the extended session unchanged.
  • Customer is not re-asked about topic sensitivity on extension.

7. Audit Trail

Table: session_sensitivity_log

  • id — PK
  • session_id — FK → sessions
  • changed_by_mitra_id — FK → mitras
  • from_valueregular | sensitive
  • to_valueregular | sensitive
  • created_at — timestamp

When Logged

  • Every mitra flip (both directions).
  • Customer's initial selection is NOT logged here — it is the initial value of sessions.topic_sensitivity.

8. Mitra Chat History

List Rows

  • Each past session row shows a small "Topik sensitif" badge if the session was flagged sensitive at any point.
  • Regular sessions have no badge.

Transcript Detail

  • Sensitive sessions show the yellow doodle background in the transcript view.
  • Regular sessions show pink.

Customer Side

  • Customer's history and transcript views are unchanged — no badge, no color change, ever.

9. Control Center

Dashboard: Sensitive vs Regular Stats

  • New panel on the existing dashboard or session-management page: count and percentage of sensitive sessions over a date range.
  • Optionally: per-mitra breakdown (future nice-to-have — not blocking for this phase).

Session Management Filter

  • Add a filter / sort on the session management page by topic_sensitivity (all / regular / sensitive).

Config

  • Expose two new app_config keys on the existing config page:
    • sensitive_flip_confirmation_enabled (bool, default true) — whether mitra sees a confirmation dialog when flipping the flag.
    • sensitive_flag_one_way_latch (bool, default false) — whether mitra can only flip regular → sensitive (no flip back).

10. Out of Scope for Phase 3.3

  • Pricing differentiation based on topic sensitivity. For now, the flag does not affect pricing. Schema should leave room for this in the future.
  • Per-mitra opt-in setting ("I accept sensitive topics"). Mitras decline on the spot via existing reject/ignore paths.
  • Auto-moderation or keyword detection — flag is self-reported by customer / mitra only.
  • FCM push notification content reflecting sensitivity — generic push only; label is in-app overlay only.
  • Multi-device mitra sync of flag flips.
  • Customer-side visual cues about topic sensitivity.

Data Model Summary

New columns

  • sessions.topic_sensitivity — enum regular | sensitive, NOT NULL, default regular.
  • chat_requests.topic_sensitivity — enum regular | sensitive, NOT NULL, default regular (mirrored for pre-acceptance visibility).

New table

  • session_sensitivity_log (see Section 7).

New app_config keys

  • sensitive_flip_confirmation_enabled (bool, default true)
  • sensitive_flag_one_way_latch (bool, default false)

Tech Stack

  • Flutter for client_app / mitra_app (existing Riverpod state management)
  • Fastify backend (existing WebSocket plugin + pairing/extension services)
  • PostgreSQL migration for new columns + table
  • Control center: React + Vite (existing pages extended)