---
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$<saltB64>$<hashB64>`, 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$<base64(salt)>$<base64(hash)>` ($ 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.<table>` 로 제약/타입/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: []
