profileSync stored avatar/banner paths with /api/uploads/ prefix on remote
instances, causing resolveAssetUrl to produce double-path URLs like
https://remote/api/uploads//api/uploads/file.jpg that 404'd. Store bare
filenames instead, strip prefix defensively in resolveAssetUrl and server-side
for existing data self-healing.
Avatars/banners now resize to max 512px/1920px and convert to WebP before
upload (zero server cost). Chat image uploads generate an 800px-wide WebP
thumbnail via Sharp; the feed shows the thumbnail, click opens the full-res
original. Adds lazy loading to avatars. Federation-compatible: remote
instances without this feature fall back gracefully.
Add banner image, accent color, and bio fields to user profiles with
full-stack support: schema migration, API validation (hex color format,
190-char bio limit), sanitizeUser propagation, and new GET /users/:id/mutuals
endpoint. Rewrite AccountPanel with live preview card, avatar/banner upload
via ImageCropModal, 16-preset accent color picker, and bio editor. Enhance
UserProfilePopout with banner display, accent-colored names, bio rendering,
and mutual counts. Add new UserProfileModal with About/Mutual Friends/Mutual
Spaces tabs and friend action buttons.
Batch 1 — Bug fixes:
- Fix stale voice state on remote reconnect (clearVoiceUsersForOrigin)
- Fix logout not cleaning remote servers from store
- Fix reply-to asset normalization for remote messages
- Fix HTTPS hardcoded in autoConnectAll (store full origin, legacy fallback)
Batch 2 — Password enforcement + replication flow:
- Add connectToRemote() with home password verification before remote auth
- Auto-cascade: verify home password → register on remote → login fallback
- Replace Register/Login tabs with single password field in ConnectedInstances
- Add DifferentPasswordError for typed fallback-login UI transition
- Fallback login form shown only when remote has different password
Phase 5 of multi-instance federation. Adds a two-layer fix:
Layer 1 — Data ingestion normalization: Remote instance user avatars,
server icons, and attachment filenames are rewritten to absolute URLs
when entering the app (via WebSocket events or API responses), so all
downstream components render them correctly without changes.
Layer 2 — Outbound action routing: wsSend calls (voice join/leave/status,
typing) and file uploads in UI components now route through the correct
instance based on the active channel's origin.