bibimbap/.atp/work-session/20260618-121419/report.md

16 KiB

schema_version sid started_at ended_at applied_changes user_request status
2 20260618-121419 2026-06-18T12:14:19+09:00 2026-06-18T13:05:00+09:00
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 문서 편집+미커밋이라 사용자 승인 대기
새로 추가한 기능(게임 리뷰/댓글, W3-2) 테스트하기 위한 더미 상황이 필요하다: 1. 게임 (dummy game) 2. 계정 (dummy account, 로그인 가능) 3. 이미 등록되어 있는 더미 리뷰 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 authorNamenickname.
    • 처리: 사용자 요청 시에만 (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: []