가족·친구가 한 달력을 함께 쓸 수 있게 한다.
- calendar_groups · calendar_group_members (한 사람 한 그룹, 최대 4명), 회원마다 개인 초대 코드(RUP-6자)
- 연동 상태·초대 미리보기·코드로 연동·연동 해제 — 해제하면 내 일정만 남고, 1명 남은 그룹은 지운다
- 일정·반복·완료는 그룹 전체가 보고 고칠 수 있다. 응답에 만든 사람·대상 요약을 담고,
남의 일정을 고칠 때 대상은 그 사람의 아이로 확인한다
- 연동·해제는 advisory lock 으로 줄 세워 인원 초과·중복 그룹을 막는다
- 파일 열람 정책 — 연동된 사람의 프로필·아이 사진
- 초대 코드 생성기·고유 충돌 재시도·대상 요약을 공통으로 옮겨 다이어리와 함께 쓴다
- 에러 코드 SCHED_001~005
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
다이어리를 가족·지인과 함께 쓸 수 있게 한다.
- diary_members 로 함께 쓰는 사람을 두고(주인 포함 최대 4명), 알림 설정을 사람별로 옮긴다
- 초대 코드(RUP-6자) 미리보기·참여, 개인↔공유 전환, 내보내기·나가기 — 내보내거나 나가면 코드를 바꾼다
- 목록·쓰기는 멤버, 수정·삭제는 쓴 사람, 다이어리 정보·삭제는 주인만
- 응답에 멤버·대상 요약·작성자를 담는다
- 파일 열람 정책 — 함께 쓰는 다이어리의 표지·기록 사진·아이 사진·멤버 프로필 사진은 멤버도 받을 수 있다
- 에러 코드 DIARY_003(코드 없음)·004(가득 참)·005(이미 참여)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
다른 회원의 펫 명함을 코드(QR)로 받아 보관함에 두는 기능이다.
- PUT /pet-cards/:id/share-mode: 공유 시트를 열 때 앱이 공유 모양(간략히·상세히)을 알린다.
받는 사람에게는 그 모양의 정보만 간다 — 간략히로 공유했는데 병원·건강 정보가 새지 않게. 기본은 간략히
- GET /shared-pet-cards/:code (+ /images/:kind): 받기 전 미리보기. 사진은 코드를 아는 회원에게 그 명함 사진만
- POST·GET·DELETE /received-cards: 보관함. 받는 순간의 사본을 저장하고 사진도 받는 사람 소유로 복사한다
(보낸 사람이 아이를 지우거나 사진을 바꿔도 받은 명함은 그대로)
- 코드로 찾는 엔드포인트는 분당 30회로 막는다 (코드 추측 방지)
- CARD_002(코드에 맞는 명함 없음)·CARD_003(내 명함) 추가, 프론트·Flutter 사전 재생성
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
앱의 기본 명함 배경(assets/svg/card_bg/*.svg)이 svg 라 검증에 걸렸다.
경로 문자열만 저장하고 서버가 파일을 내려주지 않으므로 svg 를 막을 이유가 없다.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
템플릿을 만든 뒤 새로 나온 권고로 npm audit 이 29건(critical 4)을 보고했다.
- npm audit fix (--force 없이) 로 critical·high 를 모두 정리했다 (piscina·proxy-addr 등)
- @nestjs/swagger@11 이 고정한 js-yaml@5.3.0 은 override 로 5.4.x 로 올렸다
(v12 가 선언하는 버전과 같은 메이저 — multer 와 같은 방식)
- 남은 moderate 20건은 jest 커버리지 도구 체인(개발 전용)이라 유예하고 판단 근거를 security.md 에 남겼다
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
앱의 펫 명함(PetCardRepository)을 서버로 옮긴다.
- /pet-cards: 목록·만들기·꾸미기 바꾸기·삭제, 한 사람 최대 10장 → CARD_001
- /pets/:petId/representative-card: 대표 명함 정하기·풀기 (아이마다 하나 — 부분 유니크 인덱스)
- 명함 코드("0000-000")를 서버가 무작위로 발급한다 — 지금은 앱이 카드 id 로 계산해 기기마다 달라질 수 있었다.
명함 받기에서 이 코드로 찾을 수 있다
- 배경은 색·앱 그림(assets/…)·올린 사진 중 하나만 저장한다. 그림 경로는 경로 탈출을 막는 형식만 받는다
- 아이를 지우면 명함은 FK 로 함께 지워지고 배경 사진은 커밋 뒤 정리한다
- 에러 코드 추가에 따라 프론트·Flutter 사전을 다시 생성했다
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
앱의 다이어리(DiaryBook: 다이어리 + 기록 + 댓글)를 서버로 옮긴다.
- /diaries: 목록·만들기·수정(이름·대상·리본·표지·알림 끄기)·삭제, /diaries/:id/posts 로 기록 남기기
- /diary-posts: 목록·고치기·삭제, /diary-posts/:id/comments 로 댓글 쓰기
- /diary-comments: 목록·고치기·삭제
- 책장은 최대 6권 (추억 보관함의 아이만 담은 다이어리는 세지 않는다) → DIARY_001
- 한 사람이 한 다이어리에 하루 한 번 (유니크 제약) → DIARY_002
- 아이를 지우면 다이어리 대상에서만 떼고 다이어리·기록은 남긴다
- 지금은 주인만 읽고 쓴다 — 기록·댓글에 작성자를 두어 공유 다이어리로 넓힐 수 있게 했다
- 에러 코드 추가에 따라 프론트·Flutter 사전을 다시 생성했다
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
앱의 일정(ScheduleBook: 날짜 일정 + 반복 규칙 + 완료 표시)을 서버로 옮긴다.
어느 날에 무엇이 놓이는지는 지금처럼 앱이 계산하고, 서버는 원본을 보관한다.
- /schedule-events: 목록·여러 건 만들기(기간 설정, 요청당 500건)·내용 바꾸기·삭제·완료 표시
- /repeat-rules: 목록·만들기·주기/내용 바꾸기·삭제, 날짜별 완료 표시(/completions/:date)
- /repeat-rule-completions: 반복 일정 완료 표시 목록
- 대상은 "self" 또는 내 아이만 받는다. 아이를 지우거나 보관하면 그 아이만 떼고 대상이 빈 일정은 지운다
- 날짜 일정과 반복 규칙은 같은 내용 컬럼(ScheduleDetails)을 쓴다
- @nestjs/schedule 의 ScheduleModule 과 이름이 겹쳐 크론 쪽을 별칭으로 부른다
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
앱의 우리 아이 기록(PetRepository)을 서버로 옮긴다.
- GET/POST /pets, PATCH/DELETE /pets/:id, PUT /pets/order, PUT/DELETE /pets/:id/archive
- 목록은 정한 순서(sort_order) 기준 커서 페이지네이션 — 공통 keysetPaginate 로 뽑았다
- 아이를 지우거나 보관할 때 일정·다이어리·명함이 따라 정리할 수 있게 PetLifecycleListener 를 두었다
(반려동물 모듈은 다른 도메인을 모르고, 정리는 같은 트랜잭션에서 한다)
- 사진을 바꾸면 쓰지 않는 파일만 지운다 — 다른 기록이 참조하면 FK 가 막는다
- 목록 응답 Swagger 를 실제 { items, pageInfo } 모양으로 그리는 ApiPaginatedResponse 추가
- e2e 에 목록 pageInfo 계약·미정의 쿼리 거부 검사를 되살렸다
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
앱의 기록을 서버로 옮기려면 회원과 인증이 먼저 있어야 한다.
- 소셜 로그인: 앱이 SDK 로 받은 토큰을 서버가 제공자에게 직접 확인한다
(카카오·네이버는 사용자 정보 API, 구글·Apple 은 id_token JWKS 검증)
- 소셜 앱 키가 생기기 전까지 쓰는 개발용 로그인(기기 키) — 운영에서는 닫힌다
- 액세스 JWT(1시간) + 리프레시 토큰(해시 저장·회전·재사용 탐지)
- 전역 JwtAuthGuard — 기본으로 모든 라우트가 로그인을 요구하고 @Public() 으로만 연다
- 내 정보 조회·수정·탈퇴(모든 기록과 파일 정리), 파일 소유자 기록과 내려받기,
업로드 시 매직 바이트로 내용 형식 검사
- 컬럼은 snake_case 이름 규칙, 테스트 환경은 기동 시 마이그레이션 실행 (CI e2e 는 빈 DB)
- 템플릿 예제 사용자 API(in-memory)를 실제 회원 API 로 교체하고 e2e 계약 테스트를 옮겼다
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>