Skip to content

feat(identity): 계정 Account API와 JPA 저장소 구성 #48 - #54

Open
kusuri12-09 wants to merge 1 commit into
developfrom
feat/48-identity-account-api
Open

feat(identity): 계정 Account API와 JPA 저장소 구성 #48#54
kusuri12-09 wants to merge 1 commit into
developfrom
feat/48-identity-account-api

Conversation

@kusuri12-09

Copy link
Copy Markdown
Member

Summary

  • 내 계정 정보 조회 및 계정 삭제 API를 추가했습니다.
  • Account input port·command·service를 구성했습니다.
  • Account와 StudentProfile의 JPA entity, repository, adapter를 추가했습니다.
  • JPA auditing과 계정 domain 테스트를 구성했습니다.
  • develop 대비 변경 파일 18개로 분리했습니다.

Related Issue

Scope

  • In scope:
    • GET /api/identity/v11/accounts/me
    • DELETE /api/identity/v11/accounts/me
    • Account service 및 input port
    • Account·StudentProfile JPA entity와 repository adapter
    • JPA auditing 설정 및 관련 테스트
  • Out of scope:
    • 실제 외부 인증·Pass·Redis 연동
    • 지원서 application 저장소
    • account 탈퇴 후 개인정보 정책 및 배치 처리

Implementation

  • AccountControllerAccountPort를 통해 내 정보 조회와 계정 삭제를 처리합니다.
  • AccountService는 인증 정보를 account repository로 resolve하고, application data에서 지원 상태를 조합해 응답합니다.
  • AccountJpaEntityStudentProfileJpaEntity를 분리하고 Spring Data repository 및 adapter로 저장소 경계를 구성했습니다.
  • 생성·수정 시각은 JPA auditing으로 관리합니다.

Testing

  • Unit tests
  • Integration tests
  • Manual verification
  • 검증 범위:
    • AccountControllerTest 추가
    • StudentProfileTest 추가
    • 인증 없는 계정 API: 401 AUTH_UNAUTHORIZED
    • 전체 Bazel 테스트는 로컬 Bazel 환경 문제로 완료하지 못함

Deployment Notes

  • Feature flag: 없음
  • Migration required: accounts, student_profiles 테이블 스키마 적용 필요
  • Rollout considerations:
    • DB 접속 정보와 운영 스키마 migration 상태를 배포 전에 확인해야 합니다.
    • Hibernate에서 final getter에 대한 lazy proxy 경고가 확인되어 all-open 또는 entity property open 처리가 필요합니다.
    • 실제 auth/application adapter와 함께 선행 PR 순서대로 병합해야 합니다.

Checklist

  • Matches product/tech requirements
  • Backward compatibility considered
  • Docs updated if applicable
  • 운영 DB migration 확인
  • Hibernate final getter 경고 해결

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (1)
  • ready-for-review
🚫 Excluded labels (none allowed) (2)
  • wip
  • do-not-review

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ed987cfc-ebdf-42c1-a6bb-d6e3e5e1be41

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/48-identity-account-api
  • 🛠️ cleanup stale imports
  • 🛠️ harden error messages
  • 🛠️ test clarity pass

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@systems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountControllerTest.kt`:
- Around line 17-27: Extend AccountControllerTest beyond
getMePassesAuthorizationAndReturnsBasicInfo to cover deleteMe authorization
propagation through the account port, and add a deterministic unauthenticated
web-layer test asserting the documented 401 status and AUTH_UNAUTHORIZED
response code. Use the existing fake port and controller symbols, with
meaningful assertions for both the forwarded Authorization value and the
missing-Authorization behavior.

In
`@systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/StudentProfileJpaEntity.kt`:
- Around line 42-43: Update StudentProfileJpaEntity.birthdate from String to
LocalDate and map it to a non-nullable DATE column, keeping the existing
required-field behavior. Adjust JpaAccountRepositoryAdapter and any related
persistence mapping so the domain-facing string conversion remains correct
without calling LocalDate.parse on an already typed value.

In
`@systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt`:
- Around line 27-90:
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt:27-90에
JPA 통합 테스트를 추가해 신규 계정·프로필 저장 및 재조회, 기존 프로필 갱신과 도메인 변환을 검증하세요.
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.kt:11-24의
createdAt·updatedAt 감사 시간 매핑도 검증하고,
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.kt:6-8
및
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.kt:6-8의
로그인 ID·계정 ID 조회 쿼리 결과를 각각 확인하세요.

In
`@systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt`:
- Around line 11-14: AccountService에서 Spring의 `@Service` 의존성을 제거해 애플리케이션 서비스를
프레임워크 비의존 클래스로 유지하고, bootstrap 구성에서 AccountService를 빈으로 명시 등록하세요. 실제 삭제·조회 동작을
검증하는 AccountService 테스트를 추가해 Kotlin production logic 변경을 커버하세요.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 614bc68a-5ec2-4085-b025-4a0cf410f371

📥 Commits

Reviewing files that changed from the base of the PR and between 7ff684b and 0630fac.

📒 Files selected for processing (18)
  • systems/identity/identity-adapter-in/src/main/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountController.kt
  • systems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
  • systems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountControllerTest.kt
  • systems/identity/identity-adapter-out/BUILD.bazel
  • systems/identity/identity-adapter-out/deps.bzl
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/config/JpaAuditingConfig.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/AccountJpaEntity.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/StudentProfileJpaEntity.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/AccountPort.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/DeleteAccountCommand.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/ReadAccountCommand.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt
  • systems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
  • systems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/identity/domain/StudentProfileTest.kt
📜 Review details
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{kt,go}

📄 CodeRabbit inference engine (Custom checks)

If production logic is changed in Kotlin or Go files, require corresponding test updates in the same subsystem unless the PR description explicitly justifies why tests are unnecessary

Files:

  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/ReadAccountCommand.kt
  • systems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountControllerTest.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/config/JpaAuditingConfig.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/DeleteAccountCommand.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/AccountPort.kt
  • systems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/identity/domain/StudentProfileTest.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/AccountJpaEntity.kt
  • systems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt
  • systems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
  • systems/identity/identity-adapter-in/src/main/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountController.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/StudentProfileJpaEntity.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt
**/*.{java,kt,scala,groovy,go,js,ts,tsx,jsx,py,rb,rs,cpp,c,h,hpp,cs}

📄 CodeRabbit inference engine (Custom checks)

Flag TODO/FIXME comments introduced by this PR that do not include an issue reference in the form #123 or a full tracker key like PROJ-123

Files:

  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/ReadAccountCommand.kt
  • systems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountControllerTest.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/config/JpaAuditingConfig.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/DeleteAccountCommand.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/AccountPort.kt
  • systems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/identity/domain/StudentProfileTest.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/AccountJpaEntity.kt
  • systems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt
  • systems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
  • systems/identity/identity-adapter-in/src/main/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountController.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/StudentProfileJpaEntity.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt
**/*.kt

⚙️ CodeRabbit configuration file

**/*.kt: Apply Kotlin Official Coding Conventions.

Formatting and structure:

  • Use 4 spaces for indentation; no tabs.
  • Keep files focused and readable; avoid horizontal alignment for spacing.
  • Place related declarations together and keep overloads adjacent.
  • Keep implementation member order stable and logical for readability.

Naming:

  • Package names are lowercase and do not use underscores.
  • Class/object names use UpperCamelCase.
  • Functions/properties/local variables use lowerCamelCase.
  • Constants use UPPER_SNAKE_CASE only for true constants.

API and null-safety:

  • Avoid platform type leakage in public APIs.
  • Use explicit types in public APIs when inference obscures meaning.
  • Prefer immutable values (val) over mutable values (var) unless mutation is required.
  • Flag nullable flows that can be replaced with safer modeling.

Imports and idioms:

  • Avoid wildcard imports unless justified by language/tooling conventions.
  • Prefer expression bodies for short, clear functions.
  • Prefer standard library idioms over custom utility wrappers when equivalent.

Architecture and tests:

  • Respect module boundaries (domain/application/adapter/bootstrap layering).
  • Highlight behavior-changing code that lacks corresponding unit/integration tests.
  • Ask for deterministic tests and meaningful assertions, not only happy-path checks.

Files:

  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/ReadAccountCommand.kt
  • systems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountControllerTest.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/config/JpaAuditingConfig.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/DeleteAccountCommand.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/AccountPort.kt
  • systems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/identity/domain/StudentProfileTest.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/AccountJpaEntity.kt
  • systems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt
  • systems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
  • systems/identity/identity-adapter-in/src/main/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountController.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/StudentProfileJpaEntity.kt
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt
**/*-application/**/*.{java,kt,scala,groovy}

📄 CodeRabbit inference engine (Custom checks)

For files under *-application modules, flag direct dependency on infrastructure-specific framework classes unless justified

Files:

  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/ReadAccountCommand.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/DeleteAccountCommand.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/AccountPort.kt
  • systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt
**/*-domain/**/*.{java,kt,scala,groovy}

📄 CodeRabbit inference engine (Custom checks)

For files under *-domain modules, fail if imports reference adapter or bootstrap packages

Files:

  • systems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/identity/domain/StudentProfileTest.kt
  • systems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
**/{BUILD.bazel,*.bzl}

📄 CodeRabbit inference engine (Custom checks)

In BUILD.bazel and .bzl files, require buildifier-compatible formatting and stable target naming

Files:

  • systems/identity/identity-adapter-out/deps.bzl
  • systems/identity/identity-adapter-out/BUILD.bazel
**/*.bzl

⚙️ CodeRabbit configuration file

**/*.bzl: Apply Bazel Starlark (.bzl) style guidance.

Readability and docs:

  • Keep file/module docstrings and docstrings for public functions/macros.
  • Use descriptive parameter names and document attribute intent.

API design:

  • Macros should take a name argument and derive generated target names from it.
  • Prefer keyword arguments when calling macros for clarity and stability.
  • Keep macro side effects predictable and visible.

Encapsulation:

  • Use private visibility for helper targets created by macros unless explicitly public.
  • Avoid exposing internal implementation targets unintentionally.

Tooling:

  • Enforce buildifier formatting and lint compliance.

Files:

  • systems/identity/identity-adapter-out/deps.bzl
**/BUILD.bazel

⚙️ CodeRabbit configuration file

**/BUILD.bazel: Apply Bazel BUILD style guidance.

Core rules:

  • BUILD formatting must match buildifier output.
  • Prefer DAMP BUILD files over over-abstracted DRY patterns.
  • Keep top-level layout clear: load() first, then package/default visibility, then targets.

Target definitions:

  • Keep deps explicit and close to each target's real direct dependencies.
  • Avoid recursive globs unless there is a clear, documented reason.
  • Avoid top-level list comprehensions for generating many targets.
  • Prefer literal labels and stable naming for readability and tooling compatibility.
  • Use boolean values (True/False), not numeric stand-ins.

Maintenance:

  • Flag duplicated target logic that should be moved into a macro.
  • Flag macro usage that hides important dependency or visibility decisions.

Files:

  • systems/identity/identity-adapter-out/BUILD.bazel
🔇 Additional comments (13)
systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/AccountPort.kt (1)

1-11: LGTM!

systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/DeleteAccountCommand.kt (1)

1-5: LGTM!

systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/ReadAccountCommand.kt (1)

1-5: LGTM!

systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt (1)

19-39: 📐 Maintainability & Code Quality

AccountService에 대응하는 애플리케이션 계층 테스트를 추가하거나 확인해 주세요.

삭제 시각 주입, 인증 실패 처리, BasicInfoResult 전체 필드 매핑을 검증하는 결정적 서비스 테스트가 필요합니다. 제공된 PR 테스트 목록에는 controller/domain 테스트만 확인되므로, application 서브시스템 테스트가 이미 존재하는지 확인하고 없다면 추가해 주세요.

As per coding guidelines: Kotlin production logic 변경에는 같은 서브시스템의 대응 테스트가 필요하며, 불필요한 경우 PR 설명에 명시적인 정당화가 있어야 합니다.

Source: Coding guidelines

systems/identity/identity-adapter-out/BUILD.bazel (1)

11-11: LGTM!

systems/identity/identity-adapter-out/deps.bzl (1)

1-6: LGTM!

systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/config/JpaAuditingConfig.kt (1)

1-8: LGTM!

systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/AccountJpaEntity.kt (1)

1-34: LGTM!

systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/StudentProfileJpaEntity.kt (1)

1-41: LGTM!

Also applies to: 45-58

systems/identity/identity-adapter-in/src/main/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountController.kt (1)

21-35: LGTM!

systems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/TestMain.kt (1)

3-17: LGTM!

systems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/identity/domain/StudentProfileTest.kt (1)

11-29: LGTM!

systems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/TestMain.kt (1)

6-10: 🎯 Functional Correctness

수정이 필요 없습니다.

TestMain.kths.kr.entrydsm.identity.domain 패키지 안에 있고, AccountTest, StudentProfileTest도 같은 패키지이므로 import 생략이 컴팩과 무관합니다.

Comment on lines +17 to +27
fun getMePassesAuthorizationAndReturnsBasicInfo() {
val accountPort = FakeAccountPort()
val controller = AccountController(accountPort)

val response = controller.getMe("Bearer access-token")

val command = requireNotNull(accountPort.readAccountCommand)
assertEquals("Bearer access-token", command.authorization)
assertEquals("user_123", response.data?.userId)
assertEquals(ApplicantStatus.SUBMITTED, response.data?.applicantStatus)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

DELETE /me와 미인증 계약도 검증하세요.

현재 테스트는 getMe만 호출합니다. deleteMe의 Authorization 전달과, Authorization 누락 시 명세대로 401 AUTH_UNAUTHORIZED가 되는 웹 계층 경로를 추가로 검증하세요.

As per coding guidelines, “If production logic is changed in Kotlin or Go files, require corresponding test updates in the same subsystem unless the PR description explicitly justifies why tests are unnecessary.”
As per path instructions, “Ask for deterministic tests and meaningful assertions, not only happy-path checks.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@systems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountControllerTest.kt`
around lines 17 - 27, Extend AccountControllerTest beyond
getMePassesAuthorizationAndReturnsBasicInfo to cover deleteMe authorization
propagation through the account port, and add a deterministic unauthenticated
web-layer test asserting the documented 401 status and AUTH_UNAUTHORIZED
response code. Use the existing fake port and controller symbols, with
meaningful assertions for both the forwarded Authorization value and the
missing-Authorization behavior.

Sources: Coding guidelines, Path instructions

Comment on lines +42 to +43
@Column(name = "birthdate", nullable = false, length = 255)
val birthdate: String = "",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== candidate files =="
fd -a 'StudentProfileJpaEntity\.kt|JpaAccountRepositoryAdapter\.kt' . || true

echo "== git diff stat =="
git diff --stat HEAD || true

echo "== grep birthdate usages =="
rg -n "birthdate|birth" -S . || true

echo "== inspect StudentProfileJpaEntity =="
file=$(fd 'StudentProfileJpaEntity\.kt' . | head -n1 || true)
if [ -n "${file:-}" ]; then
  wc -l "$file"
  cat -n "$file"
fi

echo "== inspect adapter outline/content around toDomain =="
adapter=$(fd 'JpaAccountRepositoryAdapter\.kt' . | head -n1 || true)
if [ -n "${adapter:-}" ]; then
  wc -l "$adapter"
  ast-grep outline "$adapter" || true
  rg -n "toDomain|birthdate|StudentProfileJpaEntity|LocalDate" -C 8 "$adapter" || true
fi

Repository: EntryDSM/entrydsm-platform

Length of output: 8873


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== student profile domain/model =="
profileDomain=$(fd 'StudentProfile\.kt' systems/identity/identity-domain systems/identity 2>/dev/null | head -n5)
for f in $profileDomain; do
  echo "--- $f"
  wc -l "$f"
  sed -n '1,220p' "$f"
done

echo "== input/profile creation sources =="
rg -n "StudentProfile\(.*birthdate|profile\.birthdate|birthdate\s*=" -S systems/identity/identity-application systems/identity/identity-adapter-in systems/identity/identity-domain -C 4 || true

echo "== focused test files =="
testFiles=$(fd 'StudentProfileTest\.kt|AccountControllerTest\.kt|.*Test\.kt' systems/identity -e kt 2>/dev/null | head -n 20)
for f in $testFiles; do
  if rg -q "birthdate|StudentProfile" "$f"; then
    echo "--- $f"
    wc -l "$f"
    sed -n '1,220p' "$f"
  fi
done

Repository: EntryDSM/entrydsm-platform

Length of output: 7970


생년월일은 문자열에서 LocalDate로 매핑해 주세요.

StudentProfileJpaEntitybirthdate: String + VARCHAR(255)로 저장하지만, JpaAccountRepositoryAdapter.kt:83에서 LocalDate.parse(birthdate)로 변환합니다. DB가 날짜 형식을 검증하지 않아 잘못된 값이 저장되면 계정 조회가 예외가 됩니다. birthdateLocalDate/DATE로 맞춰주고, 문자열 매핑을 유지해야 한다면 엄격한 converter 및 입력 검증으로 2009-03-15 형식을 강제해 주세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/StudentProfileJpaEntity.kt`
around lines 42 - 43, Update StudentProfileJpaEntity.birthdate from String to
LocalDate and map it to a non-nullable DATE column, keeping the existing
required-field behavior. Adjust JpaAccountRepositoryAdapter and any related
persistence mapping so the domain-facing string conversion remains correct
without calling LocalDate.parse on an already typed value.

Comment on lines +27 to +90
override fun save(account: Account): Account {
val existing = accountJpaRepository.findById(account.userId).orElse(null)
?.takeIf { it.loginIdHash == account.loginId }
val entity = if (existing == null) {
AccountJpaEntity(
loginIdHash = account.loginId,
passwordHash = account.passwordForPersistence(),
role = account.role,
status = account.status,
)
} else {
existing.apply {
passwordHash = account.passwordForPersistence()
status = account.status
}
}
val savedAccount = accountJpaRepository.saveAndFlush(entity)
val savedUserId = requireNotNull(savedAccount.id)
val profile = studentProfileJpaRepository.findByAccount_Id(savedUserId)
?: StudentProfileJpaEntity(
account = savedAccount,
signupType = account.profile.signupType,
nameEncrypted = account.profile.name,
phoneEncrypted = account.profile.phone,
birthdate = account.profile.birthdate.toString(),
)
profile.applicantStatus = account.profile.applicantStatus
profile.passStatus = account.profile.passStatus
profile.submittedAt = account.profile.submittedAt
profile.announcedAt = account.profile.announcedAt
val savedProfile = studentProfileJpaRepository.saveAndFlush(profile)
return savedAccount.toDomain(savedProfile)
}

private fun AccountJpaEntity.toDomain(profile: StudentProfileJpaEntity? = null): Account {
val resolvedProfile = profile ?: requireNotNull(id) { "Account ID must be present" }
.let { studentProfileJpaRepository.findByAccount_Id(it) }
?: error("Student profile not found for account $id")
val createdAt = createdAtValue() ?: Instant.EPOCH
val updatedAt = updatedAtValue() ?: createdAt
return Account.create(
userId = requireNotNull(id),
loginId = loginIdHash,
password = passwordHash,
role = role,
status = status,
profile = resolvedProfile.toDomain(updatedAt),
createdAt = createdAt,
updatedAt = updatedAt,
)
}

private fun StudentProfileJpaEntity.toDomain(accountUpdatedAt: Instant): StudentProfile =
StudentProfile(
name = nameEncrypted,
phone = phoneEncrypted,
birthdate = LocalDate.parse(birthdate),
signupType = signupType,
applicantStatus = applicantStatus,
passStatus = passStatus,
submittedAt = submittedAt,
announcedAt = announcedAt,
updatedAt = updatedAtValue() ?: accountUpdatedAt,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

새 JPA 영속성 경로에 adapter-out 테스트를 추가하세요.

계정/프로필 저장·재조회, 기존 프로필 갱신, 두 조회 쿼리, 감사 시간 매핑을 검증하는 동일 서브시스템의 JPA 통합 테스트가 없습니다.

  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt#L27-L90: 신규 저장과 기존 엔티티 갱신 후 도메인 변환 결과를 검증하세요.
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.kt#L11-L24: 저장 시 createdAt·updatedAt 감사 값이 채워지는지 검증하세요.
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.kt#L6-L8: 로그인 ID 조회 결과를 검증하세요.
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.kt#L6-L8: 계정 ID 기반 프로필 조회 결과를 검증하세요.

As per coding guidelines, “If production logic is changed in Kotlin or Go files, require corresponding test updates in the same subsystem unless the PR description explicitly justifies why tests are unnecessary.”
As per path instructions, “Highlight behavior-changing code that lacks corresponding unit/integration tests.”

📍 Affects 4 files
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt#L27-L90 (this comment)
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.kt#L11-L24
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.kt#L6-L8
  • systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.kt#L6-L8
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt`
around lines 27 - 90,
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt:27-90에
JPA 통합 테스트를 추가해 신규 계정·프로필 저장 및 재조회, 기존 프로필 갱신과 도메인 변환을 검증하세요.
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.kt:11-24의
createdAt·updatedAt 감사 시간 매핑도 검증하고,
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.kt:6-8
및
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.kt:6-8의
로그인 ID·계정 ID 조회 쿼리 결과를 각각 확인하세요.

Sources: Coding guidelines, Path instructions

Comment on lines +11 to +14
import org.springframework.stereotype.Service

@Service
class AccountService(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg 'systems/identity|build\.kts|gradle|settings|identity-application' | head -200

echo "== AccountService =="
fd -a 'AccountService\.kt$' . | while read -r f; do
  echo "--- $f"
  wc -l "$f"
  sed -n '1,220p' "$f"
done

echo "== Spring stereotype usages in identity-application =="
rg -n "import org\.springframework\.stereotype|`@Service`|`@Component`|`@ConfigurationProperties`|SpringBootApplication" systems/identity/identity-application || true

echo "== module build files =="
fd -a 'build\.kt*|gradle\.kts|settings\.kt*|settings\.gradle' systems/identity or fd . systems/identity | rg 'build\.kts|gradle\.kts|settings' | head -50
for f in $(fd 'build\.kts|gradle\.kts' systems/identity); do
  echo "--- $f"
  sed -n '1,220p' "$f"
done

Repository: EntryDSM/entrydsm-platform

Length of output: 5883


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== application module Bazel files =="
for f in systems/identity/identity-application/BUILD.bazel systems/identity/identity-dependencies.bzl systems/identity/identity-application/deps.bzl; do
  if [ -f "$f" ]; then
    echo "--- $f"
    sed -n '1,220p' "$f"
  fi
done

echo "== identity service registration/usages =="
rg -n "AccountService|ApplicationDataPort|AccountRepository|AccountPort|compose|register|bootstrap|component|koin|Dagger" systems/identity -g '*.kt' || true

echo "== test files under identity-application =="
fd . systems/identity/identity-application/src/test || true
rg -n "AccountService|deleteAccount|BasicInfoResult|ApplicationDataPort|AccountRepository" systems/identity/identity-application/src/test -g '*.kt' || true

Repository: EntryDSM/entrydsm-platform

Length of output: 4217


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== identity application test =="
sed -n '1,220p' systems/identity/identity-application/src/test/kotlin/hs/kr/entrydsm/TestMain.kt

echo "== account service logic details =="
sed -n '1,80p' systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt

echo "== ports =="
for f in systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/AccountPort.kt systems/identity/identity-bootstrap/src/main/kotlin/hs/kr/entrydsm/ExampleApplication.kt systems/identity/bootstrap/src/main/kotlin/hs/kr/entrydsm/ExampleApplication.kt systems/identity/identity-bootstrap/BUILD.bazel systems/identity/identity-bootstrap/deps.bzl; do
  [ -f "$f" ] && { echo "--- $f"; sed -n '1,260p' "$f"; }
done

Repository: EntryDSM/entrydsm-platform

Length of output: 4796


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== all Spring stereotype usages in systems ==
rg -n "import org\.springframework\.stereotype|`@Service`|`@Component`|`@Configuration`|`@ConfigurationProperties`|`@SpringBootApplication`" systems || true

Repository: EntryDSM/entrydsm-platform

Length of output: 224


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Spring stereotype usages in systems =="
rg -n 'import org\.springframework\.stereotype|`@Service`|`@Component`|`@Configuration`|`@ConfigurationProperties`|`@SpringBootApplication`' systems || true

Repository: EntryDSM/entrydsm-platform

Length of output: 3017


Application service를 Spring stereotype에서 분리하고 이 변경에 대한 test를 추가해 주세요.

identity-applicationidentity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt:11-18에서 @Service를 직접 사용하며, 실제 삭제/조회 로직이 추가되었지만 AccountService 테스트는 아직 없습니다. 서비스는 프레임워크 비의존 클래스로 두고 bootstrap에서 빈으로 등록해 모듈 경계를 지키고, Kotlin production logic 변경에 대한 동급 subsystem test도 동반해 주세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt`
around lines 11 - 14, AccountService에서 Spring의 `@Service` 의존성을 제거해 애플리케이션 서비스를
프레임워크 비의존 클래스로 유지하고, bootstrap 구성에서 AccountService를 빈으로 명시 등록하세요. 실제 삭제·조회 동작을
검증하는 AccountService 테스트를 추가해 Kotlin production logic 변경을 커버하세요.

Source: Coding guidelines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant