Phase 3 testing fixes: Fastify 5, SSE→WebSocket+FCM, enums, security, session lifecycle
- Upgrade Fastify 4→5 with all plugins (@fastify/websocket 11, cors 11, sensible 6) - Migrate all SSE endpoints to WebSocket + FCM push (mitra chat requests, customer pairing status) - Add flutter_local_notifications for foreground push notifications with sound - Add splash screen to both apps (hide auth loading flash) - Introduce constants/enums across entire codebase (no raw string literals) - Move price tiers from hardcoded array to app_config DB (data-driven, includes 1-min test tier) - Add session ownership validation on all shared chat routes - Add ownership checks on endSession, respondToExtension, requestExtension - Fix session timer: auto-complete expired/stale sessions on server restart - Add 5-min grace period for abandoned closing sessions - Fix extension flow: proper session_resumed handling, clearExtensionRequest, closure grace timer cleanup - Fix chat screens: ConnectChat in initState, session status check on connect - Fix customer expired view: 5-min countdown, closure state priority over expired state - Fix mitra extension UI: loading spinner, disable buttons, handle EXTENSION_RESOLVED error - Fix GoRouter navigation consistency (no more Navigator.pushNamed) - Fix goodbye view keyboard overflow (SingleChildScrollView) - Add active session card on customer home screen with refresh on navigate back - Fix PricingBottomSheet extension mode (RequestExtension instead of new pairing) - Send session_resumed to both parties on extension accept Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
101
backend/src/constants.js
Normal file
101
backend/src/constants.js
Normal file
@@ -0,0 +1,101 @@
|
||||
// User types
|
||||
export const UserType = Object.freeze({
|
||||
CUSTOMER: 'customer',
|
||||
MITRA: 'mitra',
|
||||
})
|
||||
|
||||
// Chat session statuses
|
||||
export const SessionStatus = Object.freeze({
|
||||
SEARCHING: 'searching',
|
||||
PENDING_ACCEPTANCE: 'pending_acceptance',
|
||||
PENDING_PAYMENT: 'pending_payment',
|
||||
ACTIVE: 'active',
|
||||
EXTENDING: 'extending',
|
||||
CLOSING: 'closing',
|
||||
COMPLETED: 'completed',
|
||||
CANCELLED: 'cancelled',
|
||||
EXPIRED: 'expired',
|
||||
})
|
||||
|
||||
// Chat message statuses
|
||||
export const MessageStatus = Object.freeze({
|
||||
SENT: 'sent',
|
||||
DELIVERED: 'delivered',
|
||||
READ: 'read',
|
||||
})
|
||||
|
||||
// Chat message types
|
||||
export const MessageType = Object.freeze({
|
||||
TEXT: 'text',
|
||||
})
|
||||
|
||||
// Chat request notification responses
|
||||
export const NotificationResponse = Object.freeze({
|
||||
ACCEPTED: 'accepted',
|
||||
DECLINED: 'declined',
|
||||
IGNORED: 'ignored',
|
||||
})
|
||||
|
||||
// Session extension statuses
|
||||
export const ExtensionStatus = Object.freeze({
|
||||
PENDING: 'pending',
|
||||
ACCEPTED: 'accepted',
|
||||
REJECTED: 'rejected',
|
||||
TIMEOUT: 'timeout',
|
||||
})
|
||||
|
||||
// Customer transaction types
|
||||
export const TransactionType = Object.freeze({
|
||||
FREE_TRIAL: 'free_trial',
|
||||
PAID: 'paid',
|
||||
EXTENSION: 'extension',
|
||||
})
|
||||
|
||||
// Who ended a session
|
||||
export const EndedBy = Object.freeze({
|
||||
SYSTEM: 'system',
|
||||
CUSTOMER: 'customer',
|
||||
MITRA: 'mitra',
|
||||
})
|
||||
|
||||
// WebSocket message types
|
||||
export const WsMessage = Object.freeze({
|
||||
// Auth
|
||||
AUTH: 'auth',
|
||||
AUTH_OK: 'auth_ok',
|
||||
ERROR: 'error',
|
||||
|
||||
// Chat
|
||||
MESSAGE: 'message',
|
||||
MESSAGE_ACK: 'message_ack',
|
||||
MESSAGE_STATUS: 'message_status',
|
||||
TYPING: 'typing',
|
||||
|
||||
// Pairing
|
||||
CHAT_REQUEST: 'chat_request',
|
||||
CHAT_REQUEST_CLOSED: 'chat_request_closed',
|
||||
PAIRED: 'paired',
|
||||
|
||||
// Session lifecycle
|
||||
SESSION_TIMER: 'session_timer',
|
||||
SESSION_EXPIRED: 'session_expired',
|
||||
SESSION_CLOSING: 'session_closing',
|
||||
SESSION_COMPLETED: 'session_completed',
|
||||
SESSION_ENDED: 'session_ended',
|
||||
SESSION_PAUSED: 'session_paused',
|
||||
SESSION_RESUMED: 'session_resumed',
|
||||
SESSION_ASSIGNED: 'session_assigned',
|
||||
SESSION_REROUTED: 'session_rerouted',
|
||||
REROUTED: 'rerouted',
|
||||
|
||||
// Extension
|
||||
EXTENSION_REQUEST: 'extension_request',
|
||||
EXTENSION_RESPONSE: 'extension_response',
|
||||
|
||||
// Early end
|
||||
EARLY_END: 'early_end',
|
||||
|
||||
// Delivery
|
||||
DELIVERED: 'delivered',
|
||||
READ: 'read',
|
||||
})
|
||||
Reference in New Issue
Block a user