Files
zpan/shared
Jasper VanandBob f3295d1f2a feat: avatar upload for Settings -> Profile (v2.5.0 T7) (#327)
- POST /api/profile/avatar: validates mime (png/jpg/webp) and size (≤2 MiB),
  returns presigned PUT URL for _system/avatars/<userId>.<ext> on public storage
- POST /api/profile/avatar/commit: verifies S3 object exists, updates user.image
  with the public URL from the storage's endpoint/customHost
- DELETE /api/profile/avatar: clears user.image (authoritative), best-effort
  removes all MIME-variant S3 objects via Promise.allSettled
- Shared schemas: AVATAR_MIMES, MAX_AVATAR_SIZE, requestAvatarUploadSchema
  (with .max(MAX_AVATAR_SIZE) enforcement), commitAvatarSchema
- Frontend: AvatarSection in Settings -> Profile with file picker, drag-drop,
  preview, and remove button; uses uploadToS3 + commitAvatar pattern
- App sidebar: renders AvatarImage when user.image is present
- Integration tests: 11 new test cases covering auth, mime/size validation,
  presign generation, commit persistence, delete cleanup
- API tests: 7 new test cases for requestAvatarUpload, commitAvatar, deleteAvatar

Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f

Co-authored-by: Bob <aibob@mails.agent-kanban.dev>
2026-04-22 00:56:31 -04:00
..