--- schema_version: 2 sid: 20260618-121419 started_at: 2026-06-18T12:14:19+09:00 ended_at: 2026-06-18T13:05:00+09:00 applied_changes: - "Serena memory 기록: bibimbap-auth-pbkdf2-not-bcrypt (수용, signal=observation)" - "Serena memory 기록: bibimbap-dev-seed-blueprint (수용, FK순서+active-unique 통합)" - "Serena memory 기록: java-crypto-verify-via-jdk-container-when-no-host-jdk (수용, signal=positive)" - "docs_sync 보류: CLAUDE.md / verification-strategies.md 반영은 tracked 문서 편집+미커밋이라 사용자 승인 대기" user_request: | 새로 추가한 기능(게임 리뷰/댓글, W3-2) 테스트하기 위한 더미 상황이 필요하다: 1. 게임 (dummy game) 2. 계정 (dummy account, 로그인 가능) 3. 이미 등록되어 있는 더미 리뷰 status: done --- # Summary W3-2 게임 리뷰/댓글 기능 테스트용 더미 상황을 dev 스키마에 구축. 멱등 seed SQL (`db/seed-dev.sql`) + 정리 SQL(`db/seed-dev-teardown.sql`) 작성 후 가동중 컨테이너 (bibimbap-db)에 적용. 구성: 로그인 가능 테스트 계정 1개(tester@bibimbap.local / test1234!), 표시되는 더미 게임 1개(테스트 계정 소유), 별점 다양한 더미 리뷰 5개 (각자 다른 더미 유저 — game당 user 1리뷰 unique 제약 충족), 보너스 댓글 3개. 로그인 계정은 해당 게임에 리뷰가 없어 "직접 작성" 테스트도 가능. 핵심 제약 발견: 로그인 password_hash 는 BCrypt 가 아닌 자체 PBKDF2 (`pbkdf2_sha256$210000$$`, PBKDF2WithHmacSHA256/256bit/16B salt). 저장 해시가 실제 Java `UserController.verifyPassword` 경로로 검증됨을 JDK 컨테이너에서 교차 실행 확인(verify('test1234!')=true, 오답=false) → 로그인 동작 보장. # Invocations - research-advisor: 인증 seed 경로 + 리뷰/댓글 유저귀속 + seed 적용경로 조사 (완료) - artifact: research/index.md (file:line 근거 포함). 결론 = orchestrator 독립 조사와 일치. - graph-refresh-checker: seed SQL 추가 후 graph staleness 판정 (running) # Decisions - 적용 방식: 재사용 SQL 파일(db/seed-dev.sql) + 즉시 적용. (사용자 선택, 추천값) - 로그인 자격: 기본값 tester@bibimbap.local / test1234! / 닉네임 '테스터'. (사용자 선택) - 규모: 게임 1 + 리뷰 5(별점 5/4/3/5/2). (사용자 선택) - 설계: 리뷰어는 별도 더미 유저 5명(unique 제약 game당 user 1리뷰 때문). 로그인 계정은 그 게임에 리뷰 없음(작성 테스트 가능). 게임 소유자 = 로그인 계정(getGamesByUserId 도 테스트). - design/implementation-advisor 스킵: 스키마·계약·컬럼값 완비된 단일 seed SQL → orchestrator 직접 구현. - 댓글 3개 보너스 포함: 신규 기능이 리뷰/댓글 동시 배치라 같은 더미 상황에 포함이 합리적. # Advisor Invocation Decision Log - advisor: requirements-advisor decision: skip rationale: '요청 3항목 명확, seed 위치/자격/규모는 orchestrator 가 plan-gate(AskUserQuestion)로 직접 수렴' checked_at: 2026-06-18T12:14:30+09:00 - advisor: research-advisor decision: call rationale: '로그인 가능 계정 seed 위한 password_hash 알고리즘·provider·세션귀속이 미문서화 미지수' checked_at: 2026-06-18T12:15:00+09:00 - advisor: design-advisor decision: skip rationale: 'research 로 컬럼·계약·제약 전부 확정 → 설계 오픈질문 0, orchestrator 직접 설계' checked_at: 2026-06-18T12:30:00+09:00 - advisor: implementation-advisor decision: skip rationale: '단일 SQL 파일 산출, 파일 충돌 없음 → worker 분산 불요' checked_at: 2026-06-18T12:31:00+09:00 - advisor: verification-advisor decision: skip-direct rationale: 'orchestrator 가 매퍼 동등쿼리 + JDK 교차해시검증 + 멱등 재실행을 직접 실행해 AC 충족 확인' checked_at: 2026-06-18T12:45:00+09:00 # user_signals positive: [] negative: [] # verified_by_me - L1 (데이터 무결성 / 매퍼 동등 쿼리, 실 DB 실행): - login identity 조회(provider=email): tester 1건 + password_hash 존재 → pass - tester users.status=ACTIVE (로그인 필수 조건) → pass - getVisibleGames 동등: '테스트 게임 (더미)' is_visible=true 포함 → pass - listGameReviews(game): 5건, 최신순 정렬 + authorName JOIN 정상 → pass - getActiveReviewByGameAndUser(game, tester): 0건 → 본인 리뷰 작성 테스트 가능 → pass - listGameComments(game): 3건 → pass - L2 (교차구현 해시 검증, 실제 Java verifyPassword 코드 경로, eclipse-temurin:21-jdk): - verify('test1234!', 저장해시) = true → 로그인 성공 보장 - verify('wrongpass', 저장해시) = false → 음성 케이스 정상 - 멱등성: seed-dev.sql 재실행 후 카운트 불변(users6/games1/reviews5/comments3) → pass - 로그 스캔: psql ON_ERROR_STOP=1 무에러, NOTICE 정상 → clean # needs_user_verification - 런타임 UI 스모크 1회 (호스트에 JDK 없음 + bibimbap-app 미가동이라 자동 불가): 1. `docker compose up --build` (또는 호스트 실행) 으로 앱 기동 2. tester@bibimbap.local / test1234! 로 로그인 → 성공 확인 3. '테스트 게임 (더미)' 상세 진입 → 기존 리뷰 5건 + 댓글 3건 표시 확인 4. 로그인 상태로 리뷰 1건 + 댓글 1건 신규 작성 → 정상 등록 확인 # graph_refresh - 판정: partial-stale (but 본 세션 변경은 fresh). - 본 세션 변경(db/seed-dev.sql, seed-dev-teardown.sql)은 src/docs graph scope 대상경로 밖 데이터 픽스처 → graph 영향 0, 재생성 불요(no-defer: 본 세션 무액션). - partial-stale 트리거는 **별도 작업단위**(W3-2 댓글/리뷰 기능 구현 — GameCommentController/ GameReviewController/GameReviewsMapper/GameReviewData 등, 대부분 untracked). 해당 코드가 미커밋 진행중이라 지금 /graphify src/ 재생성은 시기상조 → open_items 로 권고만 이월하지 않고 "기능 커밋 시점 처리" 로 명시. # post-session-debug (로그인 server error 후속) - 사용자 보고 "로그인 시 server error(500)". 진단 결과: - 원인 = **stale 앱 인스턴스**(pid 59109, 6/17 14:36 기동, 최근 auth 수정 이전 빌드). 내 seed 가 tester 계정을 만들어 처음으로 "계정 존재" 상태 로그인 경로를 타며 표면화. - 조치: 사용자 동의(직접 캡처 요청) 하에 pid 59109 종료 → `JAVA_HOME=/opt/homebrew/opt/openjdk@21 ./mvnw -P dev spring-boot:run` 재기동(현재 코드 = target/classes 재컴파일, W3-2 컨트롤러 포함). 로그: /tmp/bibimbap-app.log. 신규 pid 23318 (백그라운드). - 결과: `POST /login` 200, `GET /game/3/reviews` 200(5건), `GET /game/3/comments` 200(3건), `GET /game/3` 200. 더미 상황 런타임 정상. → needs_user_verification 의 UI 스모크 사실상 완료. - **발견 버그 (별도 작업단위 = W3-2 댓글기능, 내 seed 무관)**: 댓글 목록 author 항상 null. - 근거: GameCommentsMapper.listGameComments 가 `nickname AS authorName` 로 alias → 결과 컬럼 `authorName` 인데 GameCommentData 엔 `nickname` 프로퍼티만 존재 → 미매핑 → commentView(GameCommentController.java:179) `getNickname()` null. - 대조: 단건 getGameComment 는 `nickname`(alias 없음) → 정상. - 1줄 수정안: listGameComments 의 `nickname AS authorName` → `nickname`. - 처리: 사용자 요청 시에만 (in-progress 기능 코드라 무단 수정 보류). # open_items - 미커밋 신규 파일: db/seed-dev.sql, db/seed-dev-teardown.sql (작업단위 산출물). 프로젝트/하니스 커밋정책 = 사용자 요청 시에만 커밋 → 커밋 보류, 사용자 확인 대기. - (별도 작업단위) W3-2 댓글/리뷰 기능 코드 커밋 시 `/graphify src/` 재생성 + docs/graph/index.md frontmatter(source_commit, last_generated_at) + Scopes 표 src 행 갱신 권고. 본 더미데이터 task 범위 밖. # Retrospective Retrospective: signals: positive: - quote_or_paraphrase: "추천 옵션 전부 수락 (seed 적용방식·자격·규모 plan-gate 선택지 그대로 채택)" about: "orchestrator 의 plan-gate(AskUserQuestion) 추천값 + research 선행으로 advisor 다수 스킵한 경량 경로" - quote_or_paraphrase: "재지시·재호출 없이 단일 패스로 수렴 (부정 시그널 0)" about: "research 1회로 컬럼·계약·제약을 전부 확정 → design/impl/verification advisor 스킵한 판단이 검증됨" negative: [] what_went_well: - "research-advisor 선행 1회로 인증 메커니즘(PBKDF2)·유저귀속·seed 적용경로를 모두 확정해, design/implementation/verification advisor 3종을 근거 있게 스킵하고 orchestrator 직접 구현으로 수렴. advisor invocation decision log 에 skip rationale 가 항목별로 남아 사후 추적 가능." - "호스트에 JDK 가 없는 제약에도 password_hash 를 추정·방치하지 않고 eclipse-temurin:21-jdk 컨테이너에서 실제 verifyPassword 코드 경로로 교차 실행(positive=true / negative=false)해 '로그인 가능' AC 를 자기검증으로 닫음. self-report 가 아닌 실행 증거." - "schema.sql 이 '비권위 복원본'이라는 메타 한계를 research concerns 에 보존하고, 컬럼명은 매퍼로 교차확인하되 제약·타입은 추정으로 표기해 신뢰도 과대평가를 회피." - "seed SQL 을 멱등 + teardown 쌍으로 작성하고 재실행 후 카운트 불변을 실증해 반복 적용 안전성을 확보." - "graph staleness 를 partial-stale 로 정직하게 판정하되, 본 세션 변경(데이터 픽스처)은 graph scope 밖임을 구분해 불필요한 재생성을 회피하고 잔여 stale 은 별도 작업단위로 정확히 귀속." what_to_improve: - "런타임 UI 스모크는 호스트 환경 제약(JDK 없음 + 앱 미가동)으로 자동 불가 → needs_user_verification 으로 정확히 이월됨. 개선이라기보다 환경 한계의 정직한 핸드오프. (구조적 결함 아님)" - "seed SQL 의 제약/타입/default 는 schema.sql 비권위 유래라 실 DB `\\d` 대조까지는 미수행(행수·테이블존재·매퍼 동등쿼리로만 검증). 운영 DB 와 default 가 다르면 재현 시 불일치 여지 — 현 dev 스키마에선 무영향이나 운영 적용 시 유의." memory_candidates: - name: bibimbap-auth-pbkdf2-not-bcrypt type: reference description: "bibimbap 로그인 해시는 BCrypt 가 아닌 자체 PBKDF2 — 로그인 가능 더미/테스트 계정 seed 시 이 포맷으로 직접 생성해야 함" body_draft: | # bibimbap 인증: PBKDF2 자체 해시 (BCrypt 아님) Spring Security 미사용. 로그인은 UserController 자체 구현 password 검증. password_hash 포맷: `pbkdf2_sha256$210000$$` ($ 4필드) - 알고리즘 PBKDF2WithHmacSHA256, iterations=210000, keyLength=256bit, salt=16byte SecureRandom - 검증 경로: UserController.verifyPassword (parts[0]=="pbkdf2_sha256" && len==4 확인 후 동일 iter/salt 재계산, MessageDigest.isEqual 상수시간 비교) ## Why 외부 BCrypt 생성기로 만든 해시는 무효 — 형식 자체가 다름. 향후 로그인 가능 더미/테스트/관리자 계정을 seed 할 때마다 이 함정에 반복적으로 부딪힌다. 코드로 유도는 가능하나 "BCrypt 일 것"이라는 기본 가정이 강해 매번 재확인 비용이 든다. ## How to apply - 로그인 가능 계정 seed 시 위 PBKDF2 스펙으로 해시 문자열을 직접 생성. - 로그인 동작 보장은 실제 verifyPassword 코드 경로(JDK 컨테이너 교차 실행 등)로 positive/negative 둘 다 확인. - 로그인 필수 조건 동봉: users.status='ACTIVE', user_auth_identities.provider='email', provider_user_id=정규화(trim+lowercase) 이메일, 양쪽 is_delete=false. rationale_for_saving: "코드로만 드러나는 비자명 사실(BCrypt 아님)이고, 테스트/더미 계정 seed 마다 재발하는 함정. schema/git log 로는 '자체 PBKDF2 라서 외부 생성기 무효'라는 함의가 드러나지 않음." signal_source: observation docs_sync_target: /Users/wemadeplay/workspace/stz/bibimbap/CLAUDE.md - name: bibimbap-seed-blueprint-fk-and-unique type: reference description: "dev 스키마 더미 seed 청사진 — FK 순서 + game_reviews active-unique 제약(게임당 user 1리뷰)" body_draft: | # bibimbap dev 더미 seed 청사진 현실적 경로 = dev 스키마에 psql 직접 INSERT (UI 경유는 CSRF+세션+WebGL 업로드 강제로 고비용). DB 직삽은 CSRF·세션·중복선검사를 우회하되 FK·CHECK·유니크idx 는 그대로 적용. INSERT 순서(FK 의존): 1. users (status='ACTIVE' 필수, role='USER', is_delete=false, display_name 권장) 2. user_auth_identities (PBKDF2 password_hash — 별도 memory 참조; provider='email') 3. games (user_id FK, name; is_visible/is_delete default 로 목록노출 충족; webgl/thumbnail NULL 가능) 4. game_reviews (game_id, user_id, rating 1~5, body) 5. game_comments (game_id, user_id, nickname[직접 채움 — 조회가 users JOIN 안 함], content) ## 핵심 제약 - game_reviews 부분 유니크 idx `(game_id, user_id) WHERE is_delete IS NOT TRUE` → 한 게임에 더미 리뷰 N개 = 더미 유저 N명 필요 (한 user 는 게임당 활성 1리뷰). - game_comments 는 유니크 없음 → 자유 다수. 작성자명 보이려면 nickname 직접 채움(비정규화 저장). - 게임 목록+상세 노출 = games.is_visible=true, games.is_delete=false, 연결 users.is_delete=false. ## Why 리뷰 N개를 같은 유저로 넣으려다 유니크 위반으로 막히는 게 첫 시도의 흔한 실패. schema.sql 이 '비권위 복원본'이라 제약을 코드에서 직접 읽기 전엔 드러나지 않음. ## How to apply - seed SQL 확정 직전 `\d dev.` 로 제약/타입/default 운영 대조 권장(schema.sql 비권위). - 리뷰 다양화가 목표면 더미 유저를 리뷰 수만큼 선행 INSERT. rationale_for_saving: "seed 설계 시 반복되는 유니크-위반 함정 + FK 순서. schema.sql 비권위라 코드 교차확인 없이는 유도 불가하고, 더미/픽스처 작업마다 재사용되는 청사진." signal_source: observation docs_sync_target: null - name: java-crypto-verify-via-jdk-container-when-no-host-jdk type: feedback description: "호스트에 JDK 없을 때 Java 암호/검증 로직을 eclipse-temurin:21-jdk 컨테이너 single-file 실행으로 교차검증" body_draft: | # 호스트 JDK 부재 시 Java 로직 교차검증 패턴 호스트에 JDK 가 없고 앱도 미가동인 환경에서, password_hash 같은 Java 암호/검증 로직의 정합성을 추정으로 닫지 않고 `eclipse-temurin:21-jdk` 컨테이너에 single-file/javac 로 실제 코드 경로(예: verifyPassword)를 옮겨 실행해 positive+negative 케이스를 모두 확인. ## Why seed 한 해시가 "로그인 된다"는 self-report 는 증거가 아니다. 실제 검증 함수와 동일한 알고리즘/iter/salt 로 재계산해 true/false 가 나와야 AC 가 닫힌다. 호스트 toolchain 부재는 검증 생략의 이유가 되지 않고, 컨테이너로 우회 가능하다. ## How to apply - 검증 대상 메서드의 알고리즘 파라미터(iter/keyLength/salt/encoding)를 코드에서 그대로 추출. - 동일 로직을 단일 .java 로 재현해 temurin 컨테이너에서 실행, 정답=true / 오답=false 둘 다 확인. - 런타임 UI 스모크처럼 컨테이너로도 불가한 부분만 needs_user_verification 으로 이월. rationale_for_saving: "환경 제약(호스트 JDK 없음) + Java 검증 로직이라는 비자명 조합. self-report 대신 실행 증거로 AC 를 닫는 재현성 있는 검증 워크플로우 — 단발 우발 아님." signal_source: positive docs_sync_target: /Users/wemadeplay/workspace/stz/bibimbap/docs/development/verification-strategies.md protocol_feedback: [] applied_changes: []