Báo cáo ổn định môi trường & API — WELIFE Local (REVISED)
| Trường |
Giá trị |
| Ngày baseline |
2026-08-06 ~09:49 ICT |
| Ngày gap-closure |
2026-08-06 ~10:00 ICT |
| WP |
LOCAL-STABILITY-GAP-CLOSURE-01 |
| Phạm vi |
API + môi trường + Metro + static web — NO DEVICE |
| Domain |
TOOLING + D-AUTH + PLACES |
Final verdict
| Lớp |
Kết quả |
| LOCAL ENVIRONMENT |
STABLE |
| CORE API |
STABLE |
| STATIC/WEB SURFACES |
PASS (tsc/build) |
| FULL MOBILE E2E |
NOT TESTED (cấm device) |
| GOOGLE REAL LOGIN |
OWNER_REQUIRED |
| APPLICATION REGRESSION |
NO |
URL contract (WP-LOCAL-API-ROOT-FIX-01)
| URL |
Mục đích |
GET /api/v1 |
API index JSON |
GET /api/v1/health |
Health chính thức |
GET /docs |
Swagger |
GET /chat |
HTTP probe only — không phải WS handshake, không phải UI chat |
| Socket.IO path |
/socket.io |
| Socket.IO namespace |
/chat |
Realtime chat authenticated E2E: PASS · WP-CHAT-AUTH-E2E-01
Git status before (tóm tắt)
Working tree có nhiều thay đổi từ WP trước (design/mockups move, auth Google prep, P8 FE, …).
Không reset/checkout. Không commit trong WP này.
Audit findings → hành động
radiusMeters → 400 — ValidationPipe.forbidNonWhitelisted từ chối field chưa khai báo trên DualNearbyQueryDto / nearby DTOs.
Fixed: thêm alias radiusMeters + resolveNearbyRadius + controller normalize.
- Google placeholder được coi là audience —
PASTE_….apps.googleusercontent.com pass format cũ → verify 401.
Fixed: reject placeholder; API trả 400 “chưa cấu hình”.
- Hai Metro 8081+8083 — conflict.
Fixed: kill PID 23368 (8081, start sớm hơn); giữ 8083 + API 3000.
- Partner/Driver/Dashboard chưa xác nhận static.
Done: tsc 0 cả ba; dashboard
vite build PASS.
- Google E2E / Pay / SMS — OWNER_REQUIRED (không bịa secret).
Bugs fixed
1. Places radiusMeters 400
- Root cause: forbidNonWhitelisted + thiếu field trên DTO.
- Files:
api/src/modules/places/dto/place.dto.ts, nearby-places.dto.ts, places.controller.ts, hub-places.service.ts, common/dto/nearby-geo-query.dto.ts, các *.service.ts nearby (atm/parking/fuel/charging/transit/homeservices).
- Fix: alias +
resolveNearbyRadius.
- Evidence: HTTP 200 cho
?lat&lng&radiusMeters=2000 và catalog latitude&longitude&radiusMeters; unit nearby-query.dto.spec.ts PASS.
2. Google placeholder treated as configured
- Root cause: format check chỉ cần suffix
.apps.googleusercontent.com.
- Files:
api/src/modules/auth/google-auth.util.ts, auth.service.ts (issuer check), mobile/.../googleClientIds.ts, scripts/env-check.mjs.
- Fix: placeholder regex + độ dài prefix; issuer allowlist; env:check WARN.
- Evidence:
POST /auth/google → 400 chưa cấu hình; util specs 5 tests PASS; env:check WARN PLACEHOLDER.
3. Metro duplicate
- Root cause: hai
expo start --offline -c.
- Fix:
Stop-Process -Id 23368 only.
- Evidence: 8081 down · 8083 HTTP 200 · API health ok.
Environment (evidence)
| Check |
Result |
| Docker PG/Redis/MinIO/Mailpit |
PASS (healthy) |
npm run env:check |
PASS (WARN Google PLACEHOLDER) |
| Postgres :5434 |
PASS |
| Redis :6380 |
PASS |
| MinIO :9000/:9001 |
PASS |
| Mailpit |
PASS |
API smoke (evidence)
| Check |
Result |
| GET /health |
PASS 200 |
| GET /health/deps |
PASS 200 |
| GET /docs |
PASS 200 |
| Email OTP send |
PASS 200 · redis · email · mailSent |
| Places lat+lng |
PASS 200 |
| Places + radius |
PASS 200 |
| Places + radiusMeters |
PASS 200 |
| Places catalog + radiusMeters |
PASS 200 |
| Google invalid / placeholder env |
PASS 400 not configured |
| Deprecated social GOOGLE |
PASS 400 |
Code quality
| Check |
Result |
| Unit google-auth.util |
5/5 PASS |
| Unit nearby-query.dto |
5/5 PASS |
| Unit assert-secure-boot |
3/3 PASS |
| Total targeted unit |
13/13 PASS |
api nest build |
PASS |
| mobile tsc |
PASS exit 0 |
| partner tsc |
PASS exit 0 |
| driver tsc |
PASS exit 0 |
| dashboard tsc |
PASS exit 0 |
| dashboard vite build |
PASS |
| Lint full-repo |
NOT RUN (no root lint script; deferred PRE_EXISTING) |
Metro
| Port |
Status |
| 8081 |
down (cleaned) |
| 8083 |
HTTP 200 · expo start --offline -c |
| Duplicate cleaned |
YES |
| API :3000 |
ok (not killed with Metro) |
Surfaces
| Surface |
Static |
Build |
Runtime HTTP |
Device |
| Partner |
tsc PASS |
N/A (Expo) |
NOT TESTED |
NOT TESTED |
| Driver |
tsc PASS |
N/A (Expo) |
NOT TESTED |
NOT TESTED |
| Dashboard |
tsc PASS |
vite build PASS |
NOT TESTED (dev server) |
N/A |
| Mobile |
tsc PASS |
Metro process only |
Metro 8083 |
NOT TESTED |
Google OAuth
| Item |
Status |
| Implementation |
PREPARED |
| Placeholder guard |
PASS |
| Issuer check |
PASS (unit) |
| Security tests (invalid/deprecated/placeholder) |
PASS |
| Real Client ID |
OWNER_REQUIRED |
| Real Google E2E |
NOT TESTED / BLOCKED |
Device / emulator
Android Emulator NOT OPENED
iOS Simulator NOT OPENED
Expo Go NOT OPENED
Physical device NOT USED
Secrets
No secret invented: YES
No secret logged: YES
No secret committed: YES
Remaining blockers
- OWNER: Web OAuth Client ID thật →
EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID + GOOGLE_CLIENT_ID · WP-AUTH-GOOGLE-LIVE-01
- Device UI / Expo Go smoke — ngoài phạm vi
- Authenticated Chat Socket.IO E2E — NOT CONFIRMED · WP-CHAT-AUTH-E2E-01
- Routing OSRM/Mapbox thật vs Haversine — PARTIAL · WP-ROUTING-PROVIDER-01
- Smoke driver/partner register idempotency — WP-SMOKE-IDEMPOTENCY-01
- Pay / SMS live — OWNER_REQUIRED riêng
Follow-up functional audit (2026-08-06)
smoke:chain + extra domain probes đã chạy lại → 103 PASS / 0 FAIL quan sát được.
Phân loại đã chỉnh (Google = config guard only; Chat realtime NOT CONFIRMED; Routing external PARTIAL):
→ FUNCTIONAL-AUDIT-2026-08-06.md · WP-FUNCTIONAL-AUDIT-01 · COMPLETE_WITH_EXTERNAL_BLOCKERS
Documentation updated
docs/reports/LOCAL-STABILITY-REPORT-2026-08-06.md (pointer → revised)
docs/reports/LOCAL-STABILITY-REPORT-2026-08-06-REVISED.md (this file)
docs/reports/FUNCTIONAL-AUDIT-2026-08-06.md
docs/reports/FUNCTIONAL-EXTRA-AUDIT.json
docs/SMOKE-CHAIN-RESULT.json
docs/WP-AUTH-GOOGLE-PREP.md
docs/LOCAL-TEST.md
docs/00-DOC-MAP.md
Footer
Domain: TOOLING + D-AUTH + PLACES
WP: LOCAL-STABILITY-GAP-CLOSURE-01
Scope: Environment · API · Auth · Places · Metro · Web/static · NO DEVICE
Local environment: STABLE
Core API: STABLE
Google real login: OWNER_REQUIRED
Device: NOT OPENED