Introduces the SDD root: a v1.0.0 constitution and machine-readable AGENTS.md grounded in the project's real conventions; six EARS-aware persona spec-review checklists that cross-reference .claude/personas/; feature-spec/ADR/threat-model/ api-contract templates; a fully worked _example feature; a living RTM; and an adrs/ pointer that reuses the existing docs/adr/ archive. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.1 KiB
3.1 KiB
Tasks — Profile picture upload
Red/Green TDD order: each implementation task is preceded by the failing test that requires it. Task IDs are referenced from
spec.md→ Traceability and from.specify/rtm.md. Check off as work lands; reference the issue in each commit (Refs #<n>).
Backend
- T-1 Add
ErrorCode.AVATAR_TOO_LARGEin all four sites at once:ErrorCode.java,frontend/src/lib/shared/errors.ts,getErrorMessage(),messages/{de,en,es}.json. (No new behavior yet — enables REQ-008's error.) → covers REQ-008 (error plumbing) - T-2
@WebMvcTestUserAvatarControllerTest: write failing slice tests —unauthenticatedReturns401,rejectsNonImage(400 UNSUPPORTED_FILE_TYPE),rejectsOversize(400 AVATAR_TOO_LARGE). Then implementUserAvatarController+@RequirePermissionto green. → REQ-006, REQ-007, REQ-008 - T-3 Unit
UserServiceAvatarTest: failing testsstoresUnderUserKey,replaceLeavesNoOrphan, validation maps toDomainException. Then implementUserService.setAvatar/removeAvatar(mockFileService) to green. → REQ-001, REQ-002, REQ-003 - T-4 Flyway
V78__add_app_user_avatar_object_key.sql(verify next free number on disk) adding nullableavatar_object_key VARCHAR(512); add the column +@SchematoAppUser/UserProfileView(avatarUrlderived). Test: repository round-trip. → REQ-002 - T-5
deleteMyAvatarcontroller test + impl (clears key, deletes object, returnsavatarUrl: null). → REQ-003 - T-6 Admin path: failing tests
adminDeletesOthersAvatar(200),nonAdminForbiddenOnOthers(403). Implement ownership/ADMIN_USERcheck to green. → REQ-005, REQ-009 - T-7 Authenticated proxy
getUserAvatarstreaming endpoint +Content-Type+X-Content-Type-Options: nosniff; test 200 bytes / 404 when no avatar. → REQ-004 (view side) - T-A Run
npm run generate:apiafter T-4/T-7 soavatarUrllands inapi.ts.
Frontend
- T-8 i18n keys for the new strings in
messages/{de,en,es}.json(button labels, validation errors mapped viagetErrorMessage). → REQ-007, REQ-008 (UX) - T-9 Component test
avatar-placeholder.svelte.spec.ts: failing test asserting initials render whenavatarUrlis null; implement the placeholder. → REQ-004 - T-10
/profileupload control: file picker, client-side type/size pre-check, instant preview, confirm/remove. States: idle/preview/uploading/error/done. → REQ-002, REQ-003 - T-11 Render avatar where names appear (comments, activity feed,
/users/[id]), falling back to the placeholder. → REQ-004 - T-12 E2E
avatar.spec.ts: upload → preview → confirm → avatar visible; remove → initials return. → REQ-002, REQ-003, REQ-004
Cross-cutting
- T-13 Set
spring.servlet.multipart.max-file-sizeto a 2 MB-matching ceiling so an oversized body is rejected at the container edge (defense in depth for REQ-008). - T-14 Update
.specify/rtm.mdStatus column toDoneper REQ as each test goes green.