[BE-03] partner persistence infra (Repository 구현·ApiKeyGenerator 구현)

작업 내용 (설계 의도)

변경 사항

근거 TDD: ../TDD.md “인터페이스 시그니처”. BE-01 domain interface의 infrastructure 구현.

  • infrastructure/partner/PartnerJpaRepository.kt·PartnerRepositoryImpl.kt — Partner 저장·findById·findByLinkedUserId.
  • infrastructure/partner/PartnerApiKeyJpaRepository.kt·PartnerApiKeyRepositoryImpl.kt — 저장·findById·findActiveByPartnerId(partner_id + status=ACTIVE).
  • infrastructure/partner/ApiKeyGeneratorImpl.ktSecureRandom 256-bit URL-safe + PasswordEncoder 위임(hash/matches). mcp McpTokenDomainService의 randomPart 생성 방식 참조.
  • JPA Entity와 Domain Entity 분리 시 매핑(reconstitute) 준수. @Query 금지 — 파생 쿼리 또는 QueryDSL.

롤백: 코드 롤백만(테이블은 BE 티켓 범위 아님, DBA 마이그레이션).

의존

  • BE-01

다이어그램

클래스 의존

flowchart LR
    Impl["PartnerRepositoryImpl"]
    Jpa["PartnerJpaRepository"]
    KeyImpl["PartnerApiKeyRepositoryImpl"]
    Gen["ApiKeyGeneratorImpl"]
    RepoIf["PartnerRepository (domain)"]
    Impl -.implements.-> RepoIf
    Impl --> Jpa
    KeyImpl --> Jpa

테스트 케이스

  • save 후 findById로 동일 Partner를 복원한다 (TestContainers MySQL).
  • findActiveByPartnerId는 REVOKED 키를 제외하고 ACTIVE 키만 반환한다.
  • findActiveByPartnerId는 ACTIVE 키가 없으면 null을 반환한다.
  • ApiKeyGeneratorImpl.matches는 hash한 평문과 일치하면 true, 다른 값이면 false를 반환한다.
  • generateRandomPart는 호출마다 다른 값을 생성한다.