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:
2026-04-09 00:17:25 +08:00
parent b4efcf14c2
commit b0502ac92b
58 changed files with 2148 additions and 709 deletions

View File

@@ -1,9 +1,83 @@
{
"permissions": {
"allow": [
"Bash(npm init:*)",
"Bash(cmd.exe /c \"npm --version\")",
"Bash(flutter --version)"
"Bash(git clone:*)",
"Bash(shopt -s dotglob)",
"Bash(cp -rn /tmp/halobestie-clone-temp/* /home/rama/workspaces/workspace-claude/halobestie-clone/)",
"Bash(rm -rf /tmp/halobestie-clone-temp)",
"Bash(git -C /home/rama/workspaces/workspace-claude/halobestie-clone log --oneline -5)",
"Read(//home/rama/workspaces/workspace-claude/backend/src/routes/internal/**)",
"Bash(git add:*)",
"Bash(git commit -m ':*)",
"Bash(git push:*)",
"Bash(flutter --version)",
"Bash(flutter devices:*)",
"Bash(flutter emulators:*)",
"Bash(flutter pub:*)",
"Bash(flutter run:*)",
"Bash(flutter create:*)",
"Bash(adb emu:*)",
"Bash(firebase --version)",
"Bash(flutterfire --version)",
"Bash(firebase projects:list)",
"Bash(npm install:*)",
"Bash(dart pub:*)",
"Bash(pkill -f \"flutter run\")",
"Bash(pkill -f \"gradle\")",
"Bash(kill 12672 12712 12809 14069 14567)",
"Bash(adb -s emulator-5554 emu kill)",
"Bash(timeout 5 bash -c 'echo > /dev/tcp/omv.sjamsani.id/5432 && echo \"PostgreSQL: reachable\" || echo \"PostgreSQL: unreachable\"')",
"Bash(timeout 5 bash -c 'echo > /dev/tcp/omv.sjamsani.id/6379 && echo \"Valkey: reachable\" || echo \"Valkey: unreachable\"')",
"Bash(PGPASSWORD=halobestie_clone psql -h omv.sjamsani.id -U halobestie_clone -d halobestie_clone -c \"SELECT 1 AS connected;\")",
"Bash(dpkg -l)",
"Bash(npm ls:*)",
"Bash(node -e ':*)",
"Bash(npm run:*)",
"Bash(timeout 5 bash -c 'echo > /dev/tcp/192.168.88.247/3000 && echo \"Backend reachable via static IP\" || echo \"Not reachable\"')",
"Bash(pkill -f \"flutter_tools.snapshot run\")",
"Bash(curl -s http://192.168.88.247:3000/)",
"Bash(lscpu)",
"Bash(pkill -f \"flutter_tools.snapshot run.*chrome\")",
"Bash(curl -s -X OPTIONS -H \"Origin: http://localhost\" -H \"Access-Control-Request-Method: POST\" -H \"Access-Control-Request-Headers: authorization,content-type\" -I http://192.168.88.247:3000/api/mitra/auth/verify)",
"Bash(node -e \"import\\('@fastify/cors'\\).then\\(m => console.log\\('cors loaded ok'\\)\\)\")",
"Bash(curl -sv -X OPTIONS -H \"Origin: http://localhost\" -H \"Access-Control-Request-Method: POST\" http://192.168.88.247:3000/api/mitra/auth/verify)",
"Bash(pkill -f \"node.*server.js\")",
"Bash(curl -sv -X OPTIONS -H \"Origin: http://localhost\" -H \"Access-Control-Request-Method: POST\" -H \"Access-Control-Request-Headers: authorization,content-type\" http://192.168.88.247:3000/api/mitra/auth/verify)",
"Bash(pkill -f \"flutter_tools.snapshot run.*emulator\")",
"Bash(curl -s http://192.168.88.247:3000/api/shared/config/anonymity)",
"Bash(flutter build:*)",
"Bash(keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android)",
"Read(//home/rama/.android/avd/**)",
"Bash(node -e \"const pkg = require\\('./node_modules/@fastify/websocket/package.json'\\); console.log\\('@fastify/websocket:', pkg.version\\); const fp = require\\('./node_modules/fastify/package.json'\\); console.log\\('fastify:', fp.version\\)\")",
"Bash(node -e \"const p=require\\('fs'\\).readFileSync\\('/dev/stdin','utf8'\\); const j=JSON.parse\\(p\\); console.log\\(JSON.stringify\\(j.dependencies, null, 2\\)\\)\")",
"Bash(node -e \"const p=require\\('fs'\\).readFileSync\\('/dev/stdin','utf8'\\); const j=JSON.parse\\(p\\); console.log\\(JSON.stringify\\(j.scripts, null, 2\\)\\)\")",
"WebSearch",
"WebFetch(domain:fastify.dev)",
"Bash(grep -E \"\\\\.js$\")",
"Bash(node -e \"const f=require\\('fastify/package.json'\\); const w=require\\('@fastify/websocket/package.json'\\); const c=require\\('@fastify/cors/package.json'\\); const s=require\\('@fastify/sensible/package.json'\\); console.log\\('fastify:', f.version, '| websocket:', w.version, '| cors:', c.version, '| sensible:', s.version\\)\")",
"Bash(pkill -f \"flutter run.*emulator-5556\")",
"Bash(pkill -f \"qemu-system\")",
"Bash(kill -9 7413 17891)",
"Bash(kill -9 5752 5841)",
"Bash(sed -i 's/hw.cpu.ncore=12/hw.cpu.ncore=4/' ~/.android/avd/Medium_Phone.avd/config.ini)",
"Bash(sed -i 's/hw.cpu.ncore = 6/hw.cpu.ncore = 4/' ~/.android/avd/Medium_Phone.avd/hardware-qemu.ini)",
"Bash(xargs kill:*)",
"Bash(pkill -f \"Mitra_Phone\")",
"Bash(kill -9 22483 21705)",
"Bash(kill -9 46545)",
"Bash(node -e \"import admin from 'firebase-admin'; import {initFirebase} from './src/plugins/firebase.js'; initFirebase\\(\\); const t = await admin.auth\\(\\).createCustomToken\\('fUVSXRF3k1S97aqSCPH5S6ZYXZT2'\\); console.log\\(t\\)\")",
"Bash(curl -s http://192.168.88.247:3000/api/client/chat/pricing -H \"Authorization: Bearer $\\(node -e \"import admin from 'firebase-admin'; import {initFirebase} from './src/plugins/firebase.js'; initFirebase\\(\\); const t = await admin.auth\\(\\).createCustomToken\\('fUVSXRF3k1S97aqSCPH5S6ZYXZT2'\\); console.log\\(t\\)\" 2>/dev/null\\)\")",
"Bash(dart analyze:*)",
"Read(//home/rama/workspaces/workspace-claude/**)",
"Bash(pkill -f \"flutter run.*52002\")",
"Bash(pkill -f \"flutter run.*emulator-5554\")",
"Bash(fuser -k 3000/tcp)",
"Bash(fuser -k 3001/tcp)",
"Bash(fuser 3000/tcp)",
"Bash(kill -9 923894)"
],
"additionalDirectories": [
"/home/rama/workspaces/workspace-claude/halobestie-clone/backend/src"
]
}
}