Skip to content

feat(configuration): 파일 도메인 모델 및 규칙 정의 #26 - #56

Merged
tlgms merged 8 commits into
developfrom
feat(document)-파일-도메인-모델-#26
Aug 27, 2026

Hidden character warning

The head ref may contain hidden characters: "feat(document)-\ud30c\uc77c-\ub3c4\uba54\uc778-\ubaa8\ub378-#26"
Merged

feat(configuration): 파일 도메인 모델 및 규칙 정의 #26#56
tlgms merged 8 commits into
developfrom
feat(document)-파일-도메인-모델-#26

Conversation

@tlgms

@tlgms tlgms commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

스택 PR 1/4 — base: develop
이후 PR은 이 브랜치를 base로 합니다. 순서대로 머지해 주세요.

Summary

  • Document 파일 처리의 도메인 모델과 형식·용량·파일명 규칙을 정의합니다.
  • Spring / AWS / JPA에 의존하지 않는 순수 Kotlin 모듈입니다 (deps.bzl은 비어 있는 상태 유지).

Related Issue

Scope

  • In scope: configuration-domainhs.kr.entrydsm.configuration.domain.document 패키지
  • Out of scope: 어댑터 구현, REST / gRPC 노출, 트랜잭션 처리

Implementation

API 11종은 허용 확장자·용량 한도·object_key 명명 규칙이 API마다 다릅니다. 이 규칙이 컨트롤러나 어댑터에 흩어지면 원서 슬롯에 이미지가 올라가는 식의 사고를 막을 수 없어 도메인에 모았습니다.

  • FileExtension — 확장자↔MIME 매핑. jpegjpg 별칭으로 처리
  • FileCategory — 용도별 object_key prefix, 허용 확장자 집합, 최대 용량. 전역 화이트리스트 하나로 두면 카테고리별 제한이 불가능해 카테고리가 자기 허용 집합을 갖습니다
  • FileNaming — 명세 응답 예시와 동일한 파일명 생성(application_1001.pdf, photo_5f3c9a2b.jpg 등) + 경로 조작 방어
  • 예외 6종 — 명세 에러 코드와 1:1 (INVALID_FILE_FORMAT, FILE_TOO_LARGE, FILE_NOT_FOUND, STORAGE_UPLOAD_FAILED, PRESIGN_FAILED)
  • 포트port/in 3종, port/out 2종. 참조 구현(EnvironmentVariable)과 동일하게 -application이 아니라 -domain에 둡니다

#7 지원자 목록 excel 다운fileName이 그대로 S3 키에 붙으므로 requireSafeFileName으로 경로 구분자·상위 경로 참조를 거부합니다.

Testing

  • Unit tests — 도메인 규칙 테스트 12개 (확장자 인식, 카테고리별 허용/용량, 명세와 동일한 파일명 생성, 경로 조작 거부)
  • Integration tests
  • Manual verification
bazel test //systems/configuration/...

Deployment Notes

  • Feature flag: 없음
  • Migration required: 없음 (이 PR 범위 한정)
  • Rollout considerations: 도메인 모듈만 추가되며 기존 동작에 영향 없음

Checklist

  • Matches product/tech requirements
  • Backward compatibility considered
  • Docs updated if applicable

리뷰 시 봐주셨으면 하는 것

  1. 용량 한도가 임의값입니다 — 명세에 수치가 없어 문서 10MB / 사진 5MB / 첨부 20MB로 정했습니다. 팀 기준이 있으면 알려주세요.
  2. .hwp MIME — 표준이 없어 application/x-hwp로 고정했습니다.
  3. BUILD.bazel 수정 포함 — 기존 test 타깃이 :main에 의존하지 않아 도메인 클래스를 참조하는 테스트가 컴파일되지 않았습니다. 함께 고쳤습니다. kt_jvm_testtest_class를 하나만 받아 document_test 타깃을 별도로 추가했습니다.
  4. 파일이 21개지만 예외·포트가 4~11줄짜리라 실질 리뷰량은 크지 않습니다.

tlgms and others added 5 commits July 27, 2026 20:36
- FileExtension: 확장자↔MIME 매핑, jpeg 별칭 허용
- FileCategory: 용도별 object_key prefix, 허용 확장자, 최대 용량
- FileDocument: files 테이블 대응 도메인 모델

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
명세의 에러 코드에 1:1 대응하는 예외를 추가한다.
INVALID_FILE_FORMAT, FILE_TOO_LARGE, FILE_NOT_FOUND,
STORAGE_UPLOAD_FAILED, PRESIGN_FAILED 및 키 조작 방어용 예외.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- port/in: UploadFileUseCase, IssueDownloadUrlUseCase, ReadFileUseCase
- port/out: StoragePort(S3), FileDocumentRepository(files)
- DownloadUrl, StoredObject 값 객체와 커맨드 추가

바이너리는 커맨드가 아니라 InputStream 파라미터로 분리해 커맨드의 값 의미를 유지한다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
명세 응답 예시(application_1001.pdf, photo_5f3c9a2b.jpg 등)에 맞는
파일명 생성 규칙을 도메인에 둔다.

경로 구분자, 상위 경로 참조, 허용 외 문자를 걸러 object_key 조작을 막는다.
지원자 목록 excel 다운로드는 fileName이 그대로 키에 붙으므로
requireSafeFileName으로 거부한다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
확장자 인식, 카테고리별 허용 형식/용량, 명세 예시와 동일한 파일명 생성,
경로 조작 거부를 검증한다.

기존 test 타깃이 :main에 의존하지 않아 도메인 클래스를 참조하는 테스트가
컴파일되지 않던 문제를 함께 수정한다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 27, 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: a943f502-5849-4d1c-9b8d-2d740fe02010

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:

  • 🔍 Trigger review
📝 Walkthrough

사용자는 파일 업로드와 다운로드 기능에 필요한 순수 Kotlin 도메인 모델과 규칙을 사용할 수 있습니다. Spring, AWS, JPA 의존성은 추가하지 않았습니다.

아키텍처 변경

  • FileExtension에 확장자와 MIME 타입 매핑을 추가했습니다.
  • jpgjpeg 별칭을 지원합니다.
  • FileCategory에 객체 키 prefix, 허용 확장자, 최대 파일 크기를 정의했습니다.
  • FileDocument, DownloadUrl, StoredObject 도메인 모델을 추가했습니다.
  • FileNaming에 파일명 생성, 원본 파일명 정제, 식별자 검증 기능을 추가했습니다.
  • 경로 탐색과 안전하지 않은 파일명을 차단합니다.
  • 파일 형식, 파일 크기, 파일명, 저장소 업로드, 다운로드 URL 발급, 문서 조회 관련 예외 6개를 추가했습니다.
  • 파일 업로드, 파일 조회, 다운로드 URL 발급을 위한 입력 포트를 추가했습니다.
  • 파일 문서 저장소와 객체 저장소를 위한 출력 포트를 추가했습니다.
  • 업로드 및 다운로드 URL 발급 명령 객체를 추가했습니다.
  • Bazel 테스트 타깃과 테스트 의존성을 갱신했습니다.

위험 영역

  • FileNaming의 파일명 검증과 정제 규칙은 객체 키 안전성에 직접 영향을 줍니다.
  • FileCategory의 허용 확장자와 최대 크기 설정은 업로드 가능 범위를 결정합니다.
  • StoragePortFileDocumentRepository 구현체가 없으므로 저장소 연동 동작은 포함하지 않습니다.
  • UUID 기반 파일명 token은 테스트에서 형식과 길이만 검증할 수 있습니다.

마이그레이션 및 호환성

  • 신규 configuration-domain 문서 패키지를 사용하는 어댑터와 애플리케이션 계층이 필요합니다.
  • 기존 API, 트랜잭션 처리, 저장소 구현은 변경하지 않습니다.
  • 구현체는 새 입력 포트와 출력 포트를 연결해야 합니다.
  • FileExtension, FileCategory, 명령 객체의 패키지 경로와 메서드 시그니처를 기준으로 통합해야 합니다.

검증 체크리스트

  • 확장자 인식과 대소문자 처리를 검증했습니다.
  • jpg/jpeg 별칭 처리를 검증했습니다.
  • 카테고리별 확장자 제한을 검증했습니다.
  • 파일 크기 제한을 검증했습니다.
  • 객체 키와 파일명 생성을 검증했습니다.
  • 원본 파일명 정제와 경로 탐색 차단을 검증했습니다.
  • 식별자 및 다운로드 파일명의 안전성 검증을 추가했습니다.
  • Bazel document_test 타깃을 추가했습니다.

롤아웃 노트

  • 먼저 configuration-domain 테스트 타깃을 실행합니다.
  • 이후 저장소와 API 어댑터를 새 포트에 연결합니다.
  • 운영 배포 전 파일 카테고리별 허용 확장자와 최대 크기를 확인합니다.

Walkthrough

문서 도메인에 파일 모델, 확장자·크기·파일명 검증 규칙, 업로드·조회·다운로드 URL 발급 포트가 추가되었습니다. 관련 예외와 도메인 테스트 및 Bazel 테스트 타깃도 추가되었습니다.

Changes

문서 도메인 기능

Layer / File(s) Summary
파일 모델과 검증 규칙
systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/*
systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/*
DownloadUrl, StoredObject, FileDocument 모델을 추가했습니다. FileExtensionFileCategory로 형식, MIME 타입, 허용 확장자, 최대 크기, 객체 키를 정의합니다. FileNaming으로 표준 파일명 생성과 안전하지 않은 입력 검증을 제공합니다. 관련 예외를 추가했습니다.
문서 명령과 포트 계약
systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/command/*
systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/*
업로드와 다운로드 URL 발급 명령을 추가했습니다. 파일 업로드·조회·존재 확인·다운로드 URL 발급 유스케이스를 정의했습니다. 파일 문서 저장소와 객체 저장소 포트를 정의했습니다.
도메인 테스트와 Bazel 구성
systems/configuration/configuration-domain/src/test/kotlin/hs/kr/entrydsm/configuration/domain/document/DocumentDomainTest.kt
systems/configuration/configuration-domain/BUILD.bazel
확장자 판별, 별칭과 대소문자 처리, 카테고리별 크기 제한, 객체 키와 파일명 생성, 원본 파일명 정제, 경로 탐색 입력 거부를 검증합니다. document_test 타깃과 :main 의존성을 추가했습니다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested labels: feature, kotlin, bazel, test

Suggested reviewers: kusuri12-09, wlyoon921

🚥 Pre-merge checks | ✅ 9 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 85.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (9 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 Conventional Commit 형식인 feat(configuration): subject를 따르며 파일 도메인 모델과 규칙 추가 내용을 설명합니다.
Description check ✅ Passed 설명이 파일 도메인 모델, 규칙, 포트, 테스트 및 범위를 변경 내용과 일치하게 설명합니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Kotlin Layer Boundary ✅ Passed develop 대비 변경 파일은 configuration-domain과 테스트뿐입니다. 모든 domain 모듈의 package/import에서 adapter 또는 bootstrap 참조를 찾지 못했고 변경된 application 파일도 없습니다.
Go Error Context ✅ Passed PR 커밋의 변경 파일은 BUILD.bazel과 Kotlin 테스트뿐이며 변경된 Go 코드나 외부 호출 오류 처리가 없습니다.
Bazel Formatting ✅ Passed BUILD.bazel은 load/package/타깃 순서, 4칸 들여쓰기, 후행 쉼표와 줄바꿈을 유지하며 구문이 유효합니다. document_test도 기존 main/test 규칙과 충돌하지 않습니다.
Behavior Change Needs Tests ✅ Passed 문서 도메인에 Kotlin 생산 코드가 추가되었고, 같은 서브시스템에 DocumentDomainTest 12개와 별도 document_test 타깃이 추가되었습니다. PR 설명도 단위 테스트를 명시합니다.
Todo Must Reference Issue ✅ Passed develop 대비 PR 전체 추가 라인과 변경 파일에서 TODO/FIXME 주석이 발견되지 않았습니다. 따라서 이슈 참조 누락 항목이 없습니다.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat(document)-파일-도메인-모델-#26
  • 🛠️ 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.

@tlgms
tlgms requested review from kusuri12-09 and wlyoon921 July 27, 2026 13:59

@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: 3

🤖 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/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileCategory.kt`:
- Line 24: Update FileCategory.objectKeyOf to validate fileName through
FileNaming.requireSafeFileName before constructing the prefixed object key,
preserving the existing key format for valid names. Add a DocumentDomainTest
case asserting that objectKeyOf("../../etc/passwd") throws the expected
validation exception.

In
`@systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileExtension.kt`:
- Around line 18-22: Rename the non-const properties in FileExtension.kt at
lines 18-22 from DOCUMENT_FORMATS, IMAGE_FORMATS, and ATTACHMENT_FORMATS to
documentFormats, imageFormats, and attachmentFormats, updating all references.
Apply the same lowerCamelCase convention in FileNaming.kt lines 8-10 by renaming
the properties to safeIdentifier, unsafeCharacters, and applicantListDate and
updating their references.

In
`@systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileNaming.kt`:
- Line 11: Update TOKEN_LENGTH and the corresponding token-generation logic in
FileNaming to use a full UUID or another identifier with at least 128 bits,
rather than an 8-character hexadecimal token. Adjust related tests expecting
[0-9a-f]{8} to validate the new identifier length and format.
🪄 Autofix

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: 03ae35d1-1383-4683-97a6-fb305604d6ae

📥 Commits

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

📒 Files selected for processing (21)
  • systems/configuration/configuration-domain/BUILD.bazel
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/DownloadUrl.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileCategory.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileDocument.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileExtension.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileNaming.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/StoredObject.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/command/IssueDownloadUrlCommand.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/command/UploadFileCommand.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/FileDocumentNotFoundException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/FileTooLargeException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/InvalidFileFormatException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/InvalidFileNameException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/PresignFailedException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/StorageUploadFailedException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/IssueDownloadUrlUseCase.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/ReadFileUseCase.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/UploadFileUseCase.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/out/FileDocumentRepository.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/out/StoragePort.kt
  • systems/configuration/configuration-domain/src/test/kotlin/hs/kr/entrydsm/configuration/domain/document/DocumentDomainTest.kt
📜 Review details
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{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/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/FileDocumentNotFoundException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/PresignFailedException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/IssueDownloadUrlUseCase.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/DownloadUrl.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/FileTooLargeException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/InvalidFileFormatException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/ReadFileUseCase.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/InvalidFileNameException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/out/StoragePort.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/UploadFileUseCase.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/command/UploadFileCommand.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileDocument.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/StorageUploadFailedException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileCategory.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/out/FileDocumentRepository.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/StoredObject.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileNaming.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileExtension.kt
  • systems/configuration/configuration-domain/src/test/kotlin/hs/kr/entrydsm/configuration/domain/document/DocumentDomainTest.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/command/IssueDownloadUrlCommand.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/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/FileDocumentNotFoundException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/PresignFailedException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/IssueDownloadUrlUseCase.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/DownloadUrl.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/FileTooLargeException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/InvalidFileFormatException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/ReadFileUseCase.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/InvalidFileNameException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/out/StoragePort.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/UploadFileUseCase.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/command/UploadFileCommand.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileDocument.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/StorageUploadFailedException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileCategory.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/out/FileDocumentRepository.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/StoredObject.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileNaming.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileExtension.kt
  • systems/configuration/configuration-domain/src/test/kotlin/hs/kr/entrydsm/configuration/domain/document/DocumentDomainTest.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/command/IssueDownloadUrlCommand.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/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/FileDocumentNotFoundException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/PresignFailedException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/IssueDownloadUrlUseCase.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/DownloadUrl.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/FileTooLargeException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/InvalidFileFormatException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/ReadFileUseCase.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/InvalidFileNameException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/out/StoragePort.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/UploadFileUseCase.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/command/UploadFileCommand.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileDocument.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/StorageUploadFailedException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileCategory.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/out/FileDocumentRepository.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/StoredObject.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileNaming.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileExtension.kt
  • systems/configuration/configuration-domain/src/test/kotlin/hs/kr/entrydsm/configuration/domain/document/DocumentDomainTest.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/command/IssueDownloadUrlCommand.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/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/FileDocumentNotFoundException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/PresignFailedException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/IssueDownloadUrlUseCase.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/DownloadUrl.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/FileTooLargeException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/InvalidFileFormatException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/ReadFileUseCase.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/InvalidFileNameException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/out/StoragePort.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/UploadFileUseCase.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/command/UploadFileCommand.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileDocument.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/StorageUploadFailedException.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileCategory.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/out/FileDocumentRepository.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/StoredObject.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileNaming.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileExtension.kt
  • systems/configuration/configuration-domain/src/test/kotlin/hs/kr/entrydsm/configuration/domain/document/DocumentDomainTest.kt
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/command/IssueDownloadUrlCommand.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/configuration/configuration-domain/BUILD.bazel
**/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/configuration/configuration-domain/BUILD.bazel
🔇 Additional comments (12)
systems/configuration/configuration-domain/BUILD.bazel (1)

25-25: 📐 Maintainability & Code Quality | ⚡ Quick win

document_test에는 명시적인 테스트 소스를 사용하십시오.

새 타깃은 모든 테스트 소스를 재귀 glob으로 다시 포함합니다. document_testDocumentDomainTest만 실행하므로 해당 파일만 srcs에 지정하십시오. 이 변경은 타깃 입력과 컴파일 범위를 안정화합니다.

[ suggest_recommended_refactor]

As per path instructions, "Avoid recursive globs unless there is a clear, documented reason."

Source: Path instructions

systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/FileTooLargeException.kt (1)

1-4: LGTM!

systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/InvalidFileNameException.kt (1)

1-4: LGTM!

systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/command/IssueDownloadUrlCommand.kt (1)

5-8: 🔒 Security & Privacy

두 명령의 파일명 입력이 동일한 object key 안전성 경계를 공유합니다.

FileNaming.requireSafeFileName을 통과한 값만 FileCategory.objectKeyOf에 전달되도록 두 유스케이스의 호출 순서를 확인하세요.

  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/command/IssueDownloadUrlCommand.kt#L5-L8: fileName을 검증한 후 object key 조회와 URL 발급을 수행하세요.
  • systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/command/UploadFileCommand.kt#L5-L10: nullable fileName이 생성 규칙을 우회하지 않도록 안전한 값 객체를 사용하거나 검증 후 object key를 생성하세요.
systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/command/UploadFileCommand.kt (2)

7-9: 🔒 Security & Privacy

선택적 fileName으로 파일명 생성 규칙을 우회하지 못하게 하세요.

호출자가 fileName을 직접 지정할 수 있습니다. 이 값이 FileCategory.objectKeyOf에 전달되기 전에 FileNaming.requireSafeFileName을 통과하지 않으면 경로 구분자와 ..가 포함된 object key가 생성될 수 있습니다. 안전한 값 객체를 사용하거나, 업로드 유스케이스에서 항상 검증 후 object key를 생성하는지 확인하세요.


8-8: 🗄️ Data Integrity & Integration

음수 sizeBytes 입력을 명시적으로 거부하세요.

systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/FileCategory.kt Line 7-25의 exceedsMaxSizesizeBytes > maxSizeBytes만 확인합니다. 별도 하한 검사가 없으면 음수 크기가 StoragePort.uploadFileDocument.sizeBytes로 전달될 수 있습니다. sizeBytes >= 0 검증과 -1, 0, 최대값, 최대값 초과 경계값 테스트를 확인하세요.

systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/IssueDownloadUrlUseCase.kt (1)

6-9: LGTM!

systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/ReadFileUseCase.kt (1)

6-10: LGTM!

systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/in/UploadFileUseCase.kt (1)

7-9: LGTM!

systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/out/FileDocumentRepository.kt (1)

5-11: LGTM!

systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/port/out/StoragePort.kt (1)

6-19: LGTM!

systems/configuration/configuration-domain/src/main/kotlin/hs/kr/entrydsm/configuration/domain/document/exception/FileDocumentNotFoundException.kt (1)

3-4: 🎯 Functional Correctness

ID 기반 조회의 예외 메시지를 구분하세요.

FileDocumentNotFoundException의 생성자로 전달된 값은 현재 실제 객체 키로만 쓰입니다. 나중에 findById(id: Long)가 이 예외를 던지면 메시지에도 ID가 표시되어 조회 기준을 오해할 수 있으므로, ID 조회와 object key 조회는 서로 다른 예외로 구분하세요. 현재는 해당 throw site가 없습니다.

@tlgms tlgms closed this Aug 11, 2026
@tlgms tlgms reopened this Aug 11, 2026
kusuri12-09
kusuri12-09 previously approved these changes Aug 14, 2026
@tlgms
tlgms removed the request for review from wlyoon921 August 19, 2026 01:27
tlgms and others added 2 commits August 19, 2026 22:53
FileCategory.objectKeyOf 가 파일명을 검증 없이 prefix 에 이어붙여
경로 구분자나 상위 경로 참조를 그대로 키에 넣을 수 있었다.
FileNaming.requireSafeFileName 을 통과한 값만 사용하도록 바꾸고,
128비트로 확장된 랜덤 토큰 길이에 맞춰 깨져 있던 테스트 기대값도 수정했다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
const 가 아닌 프로퍼티에 UPPER_SNAKE_CASE 를 쓰고 있어 코딩 컨벤션과 어긋났다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tlgms
tlgms merged commit 870612b into develop Aug 27, 2026
2 checks passed
@tlgms
tlgms deleted the feat(document)-파일-도메인-모델-#26 branch August 27, 2026 06:42
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.

2 participants