19 lines
5.4 KiB
JSON
19 lines
5.4 KiB
JSON
{"task_id":"QA-3.fix.C1","origin":"QA-3","severity":"critical","title":"fix: email normalization in register/login","dod":"auth.service.register/login 모두 input.email을 trim().toLowerCase() 후 처리. User 생성 시 동일 값 저장. 기존 사용자와의 호환을 위해 마이그레이션 스크립트 필요 여부 검토","depends":[],"files":["backend/src/auth/auth.service.ts"]}
|
|
{"task_id":"QA-3.fix.C2","origin":"QA-3","severity":"critical","title":"fix: JwtStrategy.validate() DB 재조회","dod":"JwtStrategy가 async validate(payload)로 바뀌고 prisma.user.findUnique({ where: { id: payload.sub }, select: { id: true, email: true }})를 호출. 없으면 UnauthorizedException","depends":[],"files":["backend/src/auth/jwt.strategy.ts","backend/src/auth/auth.module.ts"]}
|
|
{"task_id":"QA-3.fix.M1","origin":"QA-3","severity":"major","title":"fix: JWT_SECRET required at boot","dod":"auth.module.ts / jwt.strategy.ts에서 fallback 문자열 제거. ConfigService에서 JWT_SECRET 없으면 throw","depends":[],"files":["backend/src/auth/auth.module.ts","backend/src/auth/jwt.strategy.ts"]}
|
|
{"task_id":"QA-3.fix.M2","origin":"QA-3","severity":"major","title":"fix: ValidationPipe forbidNonWhitelisted=true","dod":"main.ts ValidationPipe 옵션에 forbidNonWhitelisted: true 추가. 누락 필드 오류 메시지 확인","depends":[],"files":["backend/src/main.ts"]}
|
|
{"task_id":"QA-4.fix.C1","origin":"QA-4","severity":"critical","title":"fix: review page per-item submit lock","dod":"review/page.tsx의 submit/skip이 Set<number> 기반 per-review lock을 사용. 동일 아이템 중복 클릭 차단","depends":[],"files":["frontend/src/app/review/page.tsx"]}
|
|
{"task_id":"QA-4.fix.C2","origin":"QA-4","severity":"critical","title":"fix: subjects/[id] NaN route handling","dod":"subjectId 를 Number.isFinite 로 검사 후 null 이면 NotFound UI 렌더. 유효하지 않은 URL 로 API 호출 안 함","depends":[],"files":["frontend/src/app/subjects/[id]/page.tsx"]}
|
|
{"task_id":"QA-4.fix.M1","origin":"QA-4","severity":"major","title":"fix: history 페이지 에러 상태","dod":"review/history, study/history, stats 페이지 fetch 에 catch 추가. error state UI + retry 버튼","depends":[],"files":["frontend/src/app/review/history/page.tsx","frontend/src/app/study/history/page.tsx","frontend/src/app/stats/page.tsx"]}
|
|
{"task_id":"QA-4.fix.M2","origin":"QA-4","severity":"major","title":"fix: 네이티브 confirm/alert 제거","dod":"subjects 페이지의 삭제 흐름을 custom Modal/Toast 로 교체. 성공/실패 피드백 명확","depends":[],"files":["frontend/src/app/subjects/page.tsx","frontend/src/app/subjects/[id]/page.tsx","frontend/src/components/ui/primitives.tsx"]}
|
|
{"task_id":"QA-5.fix.C1","origin":"QA-5","severity":"critical","title":"fix: reviews.submit() 전체를 tx 안으로","dod":"reviews.service.submit() 의 snapshot upsert 와 review 업데이트 + next schedule 생성이 단일 $transaction(async tx=> ...) 안에서 실행. update where { id, status: 'pending' } 로 atomic guard","depends":[],"files":["backend/src/reviews/reviews.service.ts"]}
|
|
{"task_id":"QA-5.fix.C2","origin":"QA-5","severity":"critical","title":"fix: Tag 삭제 cascade 데이터 보호","dod":"schema.prisma 의 SkillSnapshot.tag onDelete 를 SetNull 로 변경하고 tagId 를 Int? 로. 또는 Tag.archivedAt 을 추가해 soft delete. 선택 후 마이그레이션 생성","depends":[],"files":["backend/prisma/schema.prisma","backend/src/tags/tags.service.ts"]}
|
|
{"task_id":"QA-5.fix.M1","origin":"QA-5","severity":"major","title":"fix: iteration 증가를 tx 안에서","dod":"reviews.service.submit() 의 tx 안에서 직전 done 리뷰의 iteration 을 재조회 후 +1","depends":["QA-5.fix.C1"],"files":["backend/src/reviews/reviews.service.ts"]}
|
|
{"task_id":"QA-5.fix.M2","origin":"QA-5","severity":"major","title":"fix: StudyLog.tag onDelete 정의","dod":"schema.prisma StudyLog.tag 관계에 onDelete: SetNull 추가 + 마이그레이션","depends":["QA-5.fix.C2"],"files":["backend/prisma/schema.prisma"]}
|
|
{"task_id":"QA-6.fix.C1","origin":"QA-6","severity":"critical","title":"fix: Prisma migrations 생성","dod":"로컬에서 prisma migrate dev --name init 실행 후 migrations/ 디렉토리 커밋","depends":["QA-5.fix.C2","QA-5.fix.M2"],"files":["backend/prisma/migrations/**"]}
|
|
{"task_id":"QA-6.fix.C2","origin":"QA-6","severity":"critical","title":"fix: backend postinstall prisma generate","dod":"backend/package.json scripts 에 \"postinstall\": \"prisma generate\" 추가","depends":[],"files":["backend/package.json"]}
|
|
{"task_id":"QA-6.fix.C3","origin":"QA-6","severity":"critical","title":"fix: pnpm lockfile 생성","dod":"repo 루트 또는 각 workspace 에서 pnpm install 실행 후 pnpm-lock.yaml 커밋","depends":["QA-6.fix.C2"],"files":["**/pnpm-lock.yaml"]}
|
|
{"task_id":"QA-6.fix.C4","origin":"QA-6","severity":"critical","title":"fix: PM2 ecosystem.config.js","dod":"root 에 ecosystem.config.js 생성. reloop-api / reloop-web 프로세스 정의, cwd/env/script 명시","depends":[],"files":["ecosystem.config.js"]}
|
|
{"task_id":"QA-6.fix.M1","origin":"QA-6","severity":"major","title":"fix: next.config.js output standalone","dod":"frontend/next.config.js 에 output: 'standalone' 추가","depends":[],"files":["frontend/next.config.js"]}
|
|
{"task_id":"QA-6.fix.M2","origin":"QA-6","severity":"major","title":"fix: frontend .env.example + root README","dod":"frontend/.env.example 생성. root README.md 에 env 목록과 배포 순서 정리","depends":[],"files":["frontend/.env.example","README.md"]}
|