- loadProfile() now returns Promise (was missing return)
- Avatar upload via COS instead of storing WeChat temp path
- Add POST /user/avatar endpoint with multer + COS SDK
- Incomplete registration detection: redirect to register if phone is empty
- bcrypt password hashing with auto-migration from SHA-256
- BLE command retry (3 attempts, 500ms delay, skip on disconnect)
- BLE auto-reconnect with service re-discovery on disconnect
- Treatment page disconnect/reconnect event handling
- Token refresh endpoint with 3-day grace period
- Client-side token auto-refresh when <24h remaining
- Single treatment record detail API with ownership check