feat(gateway): 게이트웨이 도메인 개발 #21 - #60
Conversation
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
🚫 Excluded labels (none allowed) (2)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 17
🤖 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/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayRuntimeProperties.kt`:
- Around line 67-72: Validate Cors.maxAgeSeconds during startup by adding
require(cors.maxAgeSeconds >= 0) to the existing common configuration
validation, ensuring negative values are rejected before CORS headers are
emitted.
In
`@systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayErrorResponseWriter.kt`:
- Around line 18-22: GatewayErrorResponseWriter의 응답 본문 생성에서 status, error,
traceId를 문자열 보간으로 JSON에 삽입하지 마세요. 원본 Trace-Id 헤더 대신 TraceId.from() 등 기존 검증 결과를
사용하고, 세 필드를 맵이나 DTO로 구성한 뒤 프로젝트의 검증된 JSON serializer로 직렬화하여 UTF-8 바이트를 생성하세요.
In
`@systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayAccessGlobalFilter.kt`:
- Around line 9-12: GatewayAccessGlobalFilter의 filter가 모든 요청을 무조건 전달하지 않도록
GatewayAccessPolicy를 사용해 JWT 인증 및 권한을 검증하고, 미인증·권한 부족 요청은 거부 응답으로 종료하며 허용된 요청만
chain.filter로 전달하세요. 클래스에 필요한 Spring 빈 등록 선언을 추가하고, 해당 정책에 따라 차단 동작을 검증하는 필터
테스트를 작성하세요.
In
`@systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/RequestSizeGlobalFilter.kt`:
- Around line 25-43: RequestSizeGlobalFilter의 동작을 검증하는 동일 서브시스템 테스트를 추가하세요.
Content-Length가 maxBodyBytes를 초과하는 요청은 413을 반환하고, chunked 본문이 스트리밍 중 누적 한도를 초과하면
413을 반환하며, 본문 크기가 정확히 maxBodyBytes인 요청은 통과하는지 검증하세요.
In
`@systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitBreakerGlobalFilter.kt`:
- Around line 18-83: 핵심 서킷 브레이커 로직에 전용 단위 테스트가 없습니다.
GatewayCircuitBreakerGlobalFilter 테스트를 추가해 503/CIRCUIT_OPEN 응답, half-open 허용·거부,
로컬 breaker와 공유 stateStore 조합을 검증하세요. InMemoryGatewayCircuitStateStore 테스트에서는
open/half-open/close 전환과 동시성을 검증하고, GatewayResilienceConfiguration 테스트에서는
properties.resilience 값이 CircuitBreakerConfig에 올바르게 매핑되는지 확인하세요. 대상 사이트:
systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitBreakerGlobalFilter.kt
18-83, InMemoryGatewayCircuitStateStore.kt 11-77,
GatewayResilienceConfiguration.kt 10-27.
- Around line 27-69: 중복된 로컬 및 공유 회로 차단기 판단을 제거하고 공유 상태 저장소를 단일 게이팅 기준으로 사용하세요.
systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitBreakerGlobalFilter.kt#L27-L69의
GatewayCircuitBreakerGlobalFilter에서 circuitBreaker.tryAcquirePermission() 게이팅을
제거하거나 공유 결정에 위임하도록 재설계하고,
systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayResilienceConfiguration.kt#L12-L26의
GatewayResilienceConfiguration에서는 로컬 CircuitBreakerRegistry를 메트릭 관찰용으로만 유지하거나
half-open 예산 및 실패율 판단을 공유 GatewayCircuitStateStore로 이전하도록 역할을 조정하세요.
- Around line 81-83: Update the DownstreamResponseFailure exception to skip
stack-trace capture by overriding fillInStackTrace() to return the same
exception instance. Preserve its existing route-specific message and
RuntimeException behavior.
In
`@systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/InMemoryGatewayCircuitStateStore.kt`:
- Around line 11-77: Update InMemoryGatewayCircuitStateStore’s State and
tryAcquire flow to track when half-open permits were granted and expire stale
permits after the probe timeout before enforcing the permitted-number limit.
When an expired permit is detected, reclaim it and allow the new probe, while
keeping releaseHalfOpen and record consistent with the updated permit tracking.
In
`@systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/RedisGatewayCircuitStateStore.kt`:
- Around line 26-45: Redis 예외를 fail-open으로 처리하는 각 경로에 동일한 warn 로깅을 추가하세요.
RedisGatewayCircuitStateStore의 tryAcquire와 record에서 각각
onErrorReturn/onErrorResume 직전에 routeId와 예외를 포함해 로그를 남기고,
GatewayCircuitBreakerGlobalFilter의 stateStore.tryAcquire onErrorReturn 경로에도 동일한
로그를 추가하세요.
systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/RedisGatewayCircuitStateStore.kt의
26-45 및 50-86,
systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitBreakerGlobalFilter.kt의
33-34를 모두 반영하되 fail-open 반환 동작은 유지하세요.
In
`@systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/trace/TraceMdcConfiguration.kt`:
- Around line 31-33: Update the onSubscribe method in TraceMdcConfiguration to
invoke delegate.onSubscribe(subscription) through the existing withTraceId
wrapper, matching the other signal handlers so the subscription-time downstream
execution has the trace ID. Add or update a test that verifies the trace context
is present during the delegated onSubscribe signal.
In
`@systems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/DownstreamClientPolicyTest.kt`:
- Around line 21-26: DownstreamClientPolicyTest의
rejectsInvalidRetryBackoffPolicy 주변에 validate()의 각 require 규칙을 검증하는 결정적 경계값 테스트를
추가하세요. connectTimeoutMillis, retries, retryMethods, retryFirstBackoffMillis,
retryMaxBackoffMillis, retryBackoffFactor에 대해 유효하지 않은 값과 필요한 경계값을 각각 확인하고, 단순 예외
발생뿐 아니라 검증 대상 필드와 일치하는 의미 있는 assertion을 사용하세요.
In
`@systems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayServicePropertiesTest.kt`:
- Around line 32-37: Move validatesRuntimeLimitsAtStartup from
GatewayServicePropertiesTest into a dedicated GatewayRuntimePropertiesTest
class, keeping the existing GatewayRuntimeProperties validation assertion
unchanged. Ensure this unit test and the pure validation tests around lines
22–30 do not use `@SpringBootTest` or start a Spring context.
In
`@systems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayGlobalExceptionHandlerTest.kt`:
- Around line 9-32: GatewayGlobalExceptionHandlerTest에 InvalidTraceIdException
처리 경로의 회귀 테스트를 추가하세요. 기존 테스트 패턴을 따라 해당 예외를 handler에 전달하고 응답 상태가 400이며 오류 코드가
INVALID_TRACE_ID로 매핑되는지 검증하세요.
In
`@systems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayCorsGlobalFilterTest.kt`:
- Around line 11-28: Expand GatewayCorsGlobalFilterTest with deterministic
rejection cases for a disallowed origin and for preflight requests containing an
unsupported method or request header. Invoke GatewayCorsGlobalFilter through the
same mock exchange flow and assert meaningful 403 response status and relevant
CORS response behavior for each denial path, while preserving the existing
accepted preflight test.
In
`@systems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/GatewayAdapterInTestRunner.kt`:
- Around line 20-29: Register RedisGatewayCircuitStateStoreIntegrationTest in
GatewayAdapterInTestRunner by adding its import and including
selectClass(RedisGatewayCircuitStateStoreIntegrationTest::class.java) in the
selectors list, so the Redis circuit-state sharing integration test runs in the
Bazel test target.
In
`@systems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayAccessPolicyTest.kt`:
- Around line 7-10: Update leavesAuthenticationAndAuthorizationToIdentity in
GatewayAccessPolicyTest to assert the exact public path, an intended descendant
path, and a protected path; also verify that the near-match
/actuator/healthcheck is not public, preserving clear assertions for each
boundary case.
In
`@systems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayApplicationTestRunner.kt`:
- Around line 11-13: 고정된 테스트 클래스 선택을 제거하고 패키지 단위 discovery로 변경하세요.
systems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayApplicationTestRunner.kt의
GatewayApplicationTestRunner는 application 패키지를 선택하고,
systems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapTestRunner.kt의
GatewayBootstrapTestRunner는 bootstrap 테스트 패키지를 선택하며,
systems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/gateway/domain/GatewayDomainTestRunner.kt의
GatewayDomainTestRunner는 domain 패키지를 선택하도록 각각의 LauncherDiscoveryRequest를 수정하세요.
🪄 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: 63aeabea-1aa7-47aa-a453-787d0f8b4248
⛔ Files ignored due to path filters (1)
kotlin.MODULE.bazelis excluded by none and included by none
📒 Files selected for processing (59)
systems/gateway/.env.examplesystems/gateway/gateway-adapter-in/BUILD.bazelsystems/gateway/gateway-adapter-in/deps.bzlsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/GatewayAdapterInModule.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/DownstreamClientPolicy.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayRuntimeConfiguration.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayRuntimeProperties.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayServiceProperties.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/DownstreamFailureGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayErrorResponseWriter.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayGlobalExceptionHandler.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/InvalidTraceIdException.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayAccessGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayCorsGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayRequestTooLargeException.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/RequestSizeGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitBreakerGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitStateStore.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayResilienceConfiguration.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/InMemoryGatewayCircuitStateStore.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/RedisGatewayCircuitStateStore.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/route/GatewayRouteConfiguration.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/trace/TraceIdGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/trace/TraceMdcConfiguration.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/TestMain.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/GatewayAdapterInTestRunner.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/DownstreamClientPolicyTest.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayServicePropertiesTest.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/error/DownstreamFailureGlobalFilterTest.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayGlobalExceptionHandlerTest.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayCorsGlobalFilterTest.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/integration/GatewayProxyIntegrationTest.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/RedisGatewayCircuitStateStoreIntegrationTest.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/trace/TraceIdGlobalFilterTest.ktsystems/gateway/gateway-adapter-out/BUILD.bazelsystems/gateway/gateway-adapter-out/deps.bzlsystems/gateway/gateway-adapter-out/src/main/kotlin/hs/kr/entrydsm/ExampleApplication.ktsystems/gateway/gateway-adapter-out/src/test/kotlin/hs/kr/entrydsm/TestMain.ktsystems/gateway/gateway-application/BUILD.bazelsystems/gateway/gateway-application/deps.bzlsystems/gateway/gateway-application/src/main/kotlin/hs/kr/entrydsm/gateway/application/DownstreamFailurePolicy.ktsystems/gateway/gateway-application/src/main/kotlin/hs/kr/entrydsm/gateway/application/GatewayAccessPolicy.ktsystems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/TestMain.ktsystems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayAccessPolicyTest.ktsystems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayApplicationTestRunner.ktsystems/gateway/gateway-bootstrap/BUILD.bazelsystems/gateway/gateway-bootstrap/deps.bzlsystems/gateway/gateway-bootstrap/src/main/resources/application.yamlsystems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/TestMain.ktsystems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapApplicationTest.ktsystems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapContextTest.ktsystems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapTestRunner.ktsystems/gateway/gateway-domain/BUILD.bazelsystems/gateway/gateway-domain/deps.bzlsystems/gateway/gateway-domain/src/main/kotlin/hs/kr/entrydsm/gateway/domain/GatewayService.ktsystems/gateway/gateway-domain/src/main/kotlin/hs/kr/entrydsm/gateway/domain/TraceId.ktsystems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/TestMain.ktsystems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/gateway/domain/GatewayDomainRulesTest.ktsystems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/gateway/domain/GatewayDomainTestRunner.kt
💤 Files with no reviewable changes (8)
- systems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
- systems/gateway/gateway-adapter-out/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
- systems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
- systems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
- systems/gateway/gateway-adapter-out/deps.bzl
- systems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
- systems/gateway/gateway-adapter-out/BUILD.bazel
- systems/gateway/gateway-adapter-out/src/main/kotlin/hs/kr/entrydsm/ExampleApplication.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/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapContextTest.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/DownstreamClientPolicyTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/trace/TraceMdcConfiguration.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/DownstreamFailureGlobalFilter.ktsystems/gateway/gateway-application/src/main/kotlin/hs/kr/entrydsm/gateway/application/GatewayAccessPolicy.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayRequestTooLargeException.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayRuntimeConfiguration.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/InvalidTraceIdException.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/GatewayAdapterInModule.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/error/DownstreamFailureGlobalFilterTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/trace/TraceIdGlobalFilter.ktsystems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayAccessPolicyTest.ktsystems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapApplicationTest.ktsystems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/gateway/domain/GatewayDomainRulesTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/DownstreamClientPolicy.ktsystems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapTestRunner.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayErrorResponseWriter.ktsystems/gateway/gateway-domain/src/main/kotlin/hs/kr/entrydsm/gateway/domain/GatewayService.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/GatewayAdapterInTestRunner.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayCorsGlobalFilterTest.ktsystems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/gateway/domain/GatewayDomainTestRunner.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/route/GatewayRouteConfiguration.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/integration/GatewayProxyIntegrationTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayResilienceConfiguration.ktsystems/gateway/gateway-application/src/main/kotlin/hs/kr/entrydsm/gateway/application/DownstreamFailurePolicy.ktsystems/gateway/gateway-domain/src/main/kotlin/hs/kr/entrydsm/gateway/domain/TraceId.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayServicePropertiesTest.ktsystems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayApplicationTestRunner.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayAccessGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitBreakerGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayGlobalExceptionHandlerTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitStateStore.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/trace/TraceIdGlobalFilterTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/RedisGatewayCircuitStateStore.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayCorsGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayServiceProperties.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/RequestSizeGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/RedisGatewayCircuitStateStoreIntegrationTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/InMemoryGatewayCircuitStateStore.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayRuntimeProperties.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayGlobalExceptionHandler.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
#123or a full tracker key like PROJ-123
Files:
systems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapContextTest.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/DownstreamClientPolicyTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/trace/TraceMdcConfiguration.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/DownstreamFailureGlobalFilter.ktsystems/gateway/gateway-application/src/main/kotlin/hs/kr/entrydsm/gateway/application/GatewayAccessPolicy.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayRequestTooLargeException.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayRuntimeConfiguration.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/InvalidTraceIdException.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/GatewayAdapterInModule.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/error/DownstreamFailureGlobalFilterTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/trace/TraceIdGlobalFilter.ktsystems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayAccessPolicyTest.ktsystems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapApplicationTest.ktsystems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/gateway/domain/GatewayDomainRulesTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/DownstreamClientPolicy.ktsystems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapTestRunner.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayErrorResponseWriter.ktsystems/gateway/gateway-domain/src/main/kotlin/hs/kr/entrydsm/gateway/domain/GatewayService.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/GatewayAdapterInTestRunner.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayCorsGlobalFilterTest.ktsystems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/gateway/domain/GatewayDomainTestRunner.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/route/GatewayRouteConfiguration.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/integration/GatewayProxyIntegrationTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayResilienceConfiguration.ktsystems/gateway/gateway-application/src/main/kotlin/hs/kr/entrydsm/gateway/application/DownstreamFailurePolicy.ktsystems/gateway/gateway-domain/src/main/kotlin/hs/kr/entrydsm/gateway/domain/TraceId.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayServicePropertiesTest.ktsystems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayApplicationTestRunner.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayAccessGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitBreakerGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayGlobalExceptionHandlerTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitStateStore.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/trace/TraceIdGlobalFilterTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/RedisGatewayCircuitStateStore.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayCorsGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayServiceProperties.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/RequestSizeGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/RedisGatewayCircuitStateStoreIntegrationTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/InMemoryGatewayCircuitStateStore.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayRuntimeProperties.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayGlobalExceptionHandler.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/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapContextTest.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/DownstreamClientPolicyTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/trace/TraceMdcConfiguration.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/DownstreamFailureGlobalFilter.ktsystems/gateway/gateway-application/src/main/kotlin/hs/kr/entrydsm/gateway/application/GatewayAccessPolicy.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayRequestTooLargeException.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayRuntimeConfiguration.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/InvalidTraceIdException.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/GatewayAdapterInModule.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/error/DownstreamFailureGlobalFilterTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/trace/TraceIdGlobalFilter.ktsystems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayAccessPolicyTest.ktsystems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapApplicationTest.ktsystems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/gateway/domain/GatewayDomainRulesTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/DownstreamClientPolicy.ktsystems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapTestRunner.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayErrorResponseWriter.ktsystems/gateway/gateway-domain/src/main/kotlin/hs/kr/entrydsm/gateway/domain/GatewayService.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/GatewayAdapterInTestRunner.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayCorsGlobalFilterTest.ktsystems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/gateway/domain/GatewayDomainTestRunner.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/route/GatewayRouteConfiguration.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/integration/GatewayProxyIntegrationTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayResilienceConfiguration.ktsystems/gateway/gateway-application/src/main/kotlin/hs/kr/entrydsm/gateway/application/DownstreamFailurePolicy.ktsystems/gateway/gateway-domain/src/main/kotlin/hs/kr/entrydsm/gateway/domain/TraceId.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayServicePropertiesTest.ktsystems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayApplicationTestRunner.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayAccessGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitBreakerGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayGlobalExceptionHandlerTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitStateStore.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/trace/TraceIdGlobalFilterTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/RedisGatewayCircuitStateStore.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayCorsGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayServiceProperties.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/RequestSizeGlobalFilter.ktsystems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/RedisGatewayCircuitStateStoreIntegrationTest.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/InMemoryGatewayCircuitStateStore.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayRuntimeProperties.ktsystems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayGlobalExceptionHandler.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/gateway/gateway-application/src/main/kotlin/hs/kr/entrydsm/gateway/application/GatewayAccessPolicy.ktsystems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayAccessPolicyTest.ktsystems/gateway/gateway-application/src/main/kotlin/hs/kr/entrydsm/gateway/application/DownstreamFailurePolicy.ktsystems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayApplicationTestRunner.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/gateway/gateway-bootstrap/deps.bzlsystems/gateway/gateway-domain/deps.bzlsystems/gateway/gateway-domain/BUILD.bazelsystems/gateway/gateway-adapter-in/BUILD.bazelsystems/gateway/gateway-adapter-in/deps.bzlsystems/gateway/gateway-application/deps.bzlsystems/gateway/gateway-bootstrap/BUILD.bazelsystems/gateway/gateway-application/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
nameargument 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/gateway/gateway-bootstrap/deps.bzlsystems/gateway/gateway-domain/deps.bzlsystems/gateway/gateway-adapter-in/deps.bzlsystems/gateway/gateway-application/deps.bzl
**/*-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/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/gateway/domain/GatewayDomainRulesTest.ktsystems/gateway/gateway-domain/src/main/kotlin/hs/kr/entrydsm/gateway/domain/GatewayService.ktsystems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/gateway/domain/GatewayDomainTestRunner.ktsystems/gateway/gateway-domain/src/main/kotlin/hs/kr/entrydsm/gateway/domain/TraceId.kt
**/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/gateway/gateway-domain/BUILD.bazelsystems/gateway/gateway-adapter-in/BUILD.bazelsystems/gateway/gateway-bootstrap/BUILD.bazelsystems/gateway/gateway-application/BUILD.bazel
🪛 dotenv-linter (4.0.0)
systems/gateway/.env.example
[warning] 3-3: [UnorderedKey] The GATEWAY_APPLICATION_URI key should go before the GATEWAY_IDENTITY_URI key
(UnorderedKey)
[warning] 4-4: [UnorderedKey] The GATEWAY_ADMIN_URI key should go before the GATEWAY_APPLICATION_URI key
(UnorderedKey)
[warning] 7-7: [UnorderedKey] The GATEWAY_CONFIGURATION_URI key should go before the GATEWAY_IDENTITY_URI key
(UnorderedKey)
[warning] 15-15: [UnorderedKey] The GATEWAY_DOWNSTREAM_RETRY_BACKOFF_FACTOR key should go before the GATEWAY_DOWNSTREAM_RETRY_FIRST_BACKOFF_MILLIS key
(UnorderedKey)
[warning] 16-16: [UnorderedKey] The GATEWAY_DOWNSTREAM_RETRY_BACKOFF_BASED_ON_PREVIOUS_VALUE key should go before the GATEWAY_DOWNSTREAM_RETRY_BACKOFF_FACTOR key
(UnorderedKey)
[warning] 17-17: [UnorderedKey] The GATEWAY_DOWNSTREAM_RETRY_JITTER_RANDOM_FACTOR key should go before the GATEWAY_DOWNSTREAM_RETRY_MAX_BACKOFF_MILLIS key
(UnorderedKey)
[warning] 28-28: [UnorderedKey] The GATEWAY_CIRCUIT_FAILURE_RATE_THRESHOLD key should go before the GATEWAY_CIRCUIT_STATE_REDIS_URI key
(UnorderedKey)
[warning] 29-29: [UnorderedKey] The GATEWAY_CIRCUIT_SLIDING_WINDOW_SIZE key should go before the GATEWAY_CIRCUIT_STATE_REDIS_URI key
(UnorderedKey)
[warning] 30-30: [UnorderedKey] The GATEWAY_CIRCUIT_MINIMUM_NUMBER_OF_CALLS key should go before the GATEWAY_CIRCUIT_SLIDING_WINDOW_SIZE key
(UnorderedKey)
[warning] 32-32: [UnorderedKey] The GATEWAY_CIRCUIT_PERMITTED_NUMBER_OF_CALLS_IN_HALF_OPEN_STATE key should go before the GATEWAY_CIRCUIT_SLIDING_WINDOW_SIZE key
(UnorderedKey)
🔇 Additional comments (31)
systems/gateway/gateway-adapter-in/deps.bzl (1)
4-16: LGTM!systems/gateway/gateway-application/deps.bzl (1)
4-5: LGTM!systems/gateway/gateway-bootstrap/deps.bzl (1)
3-3: LGTM!Also applies to: 13-14
systems/gateway/gateway-bootstrap/src/main/resources/application.yaml (1)
4-68: LGTM!systems/gateway/gateway-domain/deps.bzl (1)
4-5: LGTM!systems/gateway/gateway-adapter-in/BUILD.bazel (1)
19-20: 📐 Maintainability & Code Quality
kt_jvm_test의main_class사용은 변경하지 않아도 됩니다.rules_kotlin의
kt_jvm_test는 기본 테스트 러너 대신 커스텀 테스트 런너를 지정할 수 있도록main_class를 지원하므로, 네 타깃 모두 분석 단계에서 해당 속성만으로 실패하지 않습니다.> Likely an incorrect or invalid review comment.systems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayServicePropertiesTest.kt (1)
39-47: LGTM!systems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/error/DownstreamFailureGlobalFilterTest.kt (1)
11-43: LGTM!systems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/integration/GatewayProxyIntegrationTest.kt (1)
1-224: LGTM!systems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/RedisGatewayCircuitStateStoreIntegrationTest.kt (1)
1-72: LGTM! (단, 이 테스트가 실행되려면 FileGatewayAdapterInTestRunner.kt의 러너 등록 이슈가 먼저 해결되어야 합니다.)systems/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/trace/TraceIdGlobalFilterTest.kt (1)
14-71: LGTM!systems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapApplicationTest.kt (1)
6-11: LGTM!systems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapContextTest.kt (1)
13-21: LGTM!systems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/gateway/domain/GatewayDomainRulesTest.kt (1)
7-14: LGTM!systems/gateway/.env.example (1)
1-32: LGTM!systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/GatewayAdapterInModule.kt (1)
1-3: LGTM!systems/gateway/gateway-domain/src/main/kotlin/hs/kr/entrydsm/gateway/domain/GatewayService.kt (1)
1-13: LGTM!systems/gateway/gateway-domain/src/main/kotlin/hs/kr/entrydsm/gateway/domain/TraceId.kt (1)
1-22: LGTM!systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/InvalidTraceIdException.kt (1)
1-3: LGTM!systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayGlobalExceptionHandler.kt (1)
1-80: LGTM!systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/DownstreamFailureGlobalFilter.kt (1)
1-19: LGTM!systems/gateway/gateway-application/src/main/kotlin/hs/kr/entrydsm/gateway/application/DownstreamFailurePolicy.kt (1)
1-24: LGTM!systems/gateway/gateway-application/src/main/kotlin/hs/kr/entrydsm/gateway/application/GatewayAccessPolicy.kt (1)
1-8: LGTM!systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/DownstreamClientPolicy.kt (1)
1-49: LGTM!systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayRuntimeConfiguration.kt (1)
1-9: LGTM!systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitStateStore.kt (1)
1-25: LGTM!systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayServiceProperties.kt (1)
7-48: LGTM!systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/route/GatewayRouteConfiguration.kt (1)
11-29: LGTM!systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/trace/TraceIdGlobalFilter.kt (1)
13-41: LGTM!systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayCorsGlobalFilter.kt (1)
17-64: LGTM!systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayRequestTooLargeException.kt (1)
1-3: LGTM!
| data class Cors( | ||
| var allowedOrigins: List<String> = listOf("http://localhost:3000"), | ||
| var allowedMethods: List<String> = listOf("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"), | ||
| var allowedHeaders: List<String> = listOf("Authorization", "Content-Type", "X-Trace-Id"), | ||
| var maxAgeSeconds: Long = 3600, | ||
| ) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
CORS max-age도 시작 시 검증하세요.
maxAgeSeconds는 음수여도 바인딩되어 Access-Control-Max-Age: -1을 전송할 수 있습니다. 공통 검증에 require(cors.maxAgeSeconds >= 0)를 추가하세요.
🤖 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/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/configuration/GatewayRuntimeProperties.kt`
around lines 67 - 72, Validate Cors.maxAgeSeconds during startup by adding
require(cors.maxAgeSeconds >= 0) to the existing common configuration
validation, ensuring negative values are rejected before CORS headers are
emitted.
| val traceId = exchange.request.headers.getFirst(TraceId.HEADER_NAME) | ||
| ?: exchange.response.headers.getFirst(TraceId.HEADER_NAME) | ||
| traceId?.let { exchange.response.headers.set(TraceId.HEADER_NAME, it) } | ||
| val body = "{\"status\":${status.value()},\"error\":\"$error\",\"traceId\":\"${traceId ?: ""}\"}" | ||
| val buffer = exchange.response.bufferFactory().wrap(body.toByteArray(Charsets.UTF_8)) |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
사용자 제어 Trace ID를 문자열 보간으로 JSON에 넣지 마세요.
여기서는 TraceId.from() 검증 결과가 아니라 원본 요청 헤더를 읽습니다. 예를 들어 X-Trace-Id: a"는 오류 본문을 유효하지 않은 JSON으로 만들며, 조작된 값은 응답 필드 주입에도 악용될 수 있습니다. status, error, traceId를 맵/DTO로 구성한 뒤 검증된 JSON serializer로 바이트를 생성하세요.
🤖 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/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayErrorResponseWriter.kt`
around lines 18 - 22, GatewayErrorResponseWriter의 응답 본문 생성에서 status, error,
traceId를 문자열 보간으로 JSON에 삽입하지 마세요. 원본 Trace-Id 헤더 대신 TraceId.from() 등 기존 검증 결과를
사용하고, 세 필드를 맵이나 DTO로 구성한 뒤 프로젝트의 검증된 JSON serializer로 직렬화하여 UTF-8 바이트를 생성하세요.
| class GatewayAccessGlobalFilter : GlobalFilter, Ordered { | ||
| override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> = chain.filter(exchange) | ||
|
|
||
| override fun getOrder(): Int = Ordered.HIGHEST_PRECEDENCE + 10 |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
접근 제어가 전혀 적용되지 않습니다.
Line 10은 모든 요청을 무조건 전달하므로, 이 필터는 등록되더라도 JWT·권한 검증을 수행하지 않습니다. 또한 클래스 자체에는 빈 등록 선언도 없습니다. GatewayAccessPolicy 기반의 허용/거부 처리를 구현하고, 미인증·권한 부족 요청이 차단되는 필터 테스트를 추가하세요. 이는 PR의 JWT 기반 통합 인증·인가 목표와 맞지 않습니다.
🤖 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/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayAccessGlobalFilter.kt`
around lines 9 - 12, GatewayAccessGlobalFilter의 filter가 모든 요청을 무조건 전달하지 않도록
GatewayAccessPolicy를 사용해 JWT 인증 및 권한을 검증하고, 미인증·권한 부족 요청은 거부 응답으로 종료하며 허용된 요청만
chain.filter로 전달하세요. 클래스에 필요한 Spring 빈 등록 선언을 추가하고, 해당 정책에 따라 차단 동작을 검증하는 필터
테스트를 작성하세요.
| override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> { | ||
| val contentLength = exchange.request.headers.contentLength | ||
| if (contentLength > maxBodyBytes) { | ||
| return GatewayErrorResponseWriter.write(exchange, HttpStatusCode.valueOf(413), "REQUEST_TOO_LARGE") | ||
| } | ||
|
|
||
| val bytesRead = AtomicLong(0) | ||
| val request = object : ServerHttpRequestDecorator(exchange.request) { | ||
| override fun getBody(): Flux<DataBuffer> = super.getBody().handle { buffer, sink -> | ||
| val total = bytesRead.addAndGet(buffer.readableByteCount().toLong()) | ||
| if (total > maxBodyBytes) { | ||
| DataBufferUtils.release(buffer) | ||
| sink.error(GatewayRequestTooLargeException()) | ||
| } else { | ||
| sink.next(buffer) | ||
| } | ||
| } | ||
| } | ||
| return chain.filter(exchange.mutate().request(request).build()) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
본문 크기 제한의 경계·스트리밍 동작을 테스트로 고정하세요.
현재 변경에는 이 필터의 테스트가 없습니다. Content-Length 초과, chunked 본문 누적 초과, 정확히 maxBodyBytes인 요청이 각각 413/통과하는지 검증하세요. 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”.
🤖 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/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/RequestSizeGlobalFilter.kt`
around lines 25 - 43, RequestSizeGlobalFilter의 동작을 검증하는 동일 서브시스템 테스트를 추가하세요.
Content-Length가 maxBodyBytes를 초과하는 요청은 413을 반환하고, chunked 본문이 스트리밍 중 누적 한도를 초과하면
413을 반환하며, 본문 크기가 정확히 maxBodyBytes인 요청은 통과하는지 검증하세요.
Source: Coding guidelines
| @Component | ||
| class GatewayCircuitBreakerGlobalFilter( | ||
| properties: GatewayRuntimeProperties, | ||
| private val circuitBreakerRegistry: CircuitBreakerRegistry, | ||
| private val stateStore: GatewayCircuitStateStore, | ||
| ) : GlobalFilter, Ordered { | ||
| private val policy = properties.resilience | ||
| private val openDurationSeconds = policy.waitDurationSeconds | ||
|
|
||
| override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> { | ||
| val routeId = exchange.getAttribute<Route>(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR)?.id | ||
| ?: return chain.filter(exchange) | ||
| val circuitBreaker = circuitBreakerRegistry.circuitBreaker(routeId) | ||
| val startedAt = System.nanoTime() | ||
|
|
||
| return stateStore.tryAcquire(routeId, policy) | ||
| .onErrorReturn(GatewayCircuitPermit(allowed = true, halfOpen = false)) | ||
| .flatMap { sharedPermit -> | ||
| if (!sharedPermit.allowed) { | ||
| return@flatMap reject(exchange) | ||
| } | ||
| if (!circuitBreaker.tryAcquirePermission()) { | ||
| return@flatMap releaseProbe(sharedPermit, routeId) | ||
| .then(reject(exchange)) | ||
| } | ||
|
|
||
| chain.filter(exchange) | ||
| .then(Mono.defer { | ||
| val failed = exchange.response.statusCode?.is5xxServerError == true | ||
| val duration = System.nanoTime() - startedAt | ||
| if (failed) { | ||
| circuitBreaker.onError( | ||
| duration, | ||
| TimeUnit.NANOSECONDS, | ||
| DownstreamResponseFailure(routeId), | ||
| ) | ||
| } else { | ||
| circuitBreaker.onSuccess(duration, TimeUnit.NANOSECONDS) | ||
| } | ||
| stateStore.record(routeId, failed, sharedPermit.halfOpen, policy) | ||
| }) | ||
| .onErrorResume { error -> | ||
| circuitBreaker.onError( | ||
| System.nanoTime() - startedAt, | ||
| TimeUnit.NANOSECONDS, | ||
| error, | ||
| ) | ||
| stateStore.record(routeId, failed = true, sharedPermit.halfOpen, policy) | ||
| .then(Mono.error(error)) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| override fun getOrder(): Int = Ordered.LOWEST_PRECEDENCE - 100 | ||
|
|
||
| private fun releaseProbe(permit: GatewayCircuitPermit, routeId: String): Mono<Void> = | ||
| if (permit.halfOpen) stateStore.releaseHalfOpen(routeId) else Mono.empty() | ||
|
|
||
| private fun reject(exchange: ServerWebExchange): Mono<Void> { | ||
| exchange.response.headers.add("Retry-After", openDurationSeconds.toString()) | ||
| return GatewayErrorResponseWriter.write(exchange, HttpStatus.SERVICE_UNAVAILABLE, "CIRCUIT_OPEN") | ||
| } | ||
|
|
||
| private class DownstreamResponseFailure(routeId: String) : | ||
| RuntimeException("Downstream service returned a 5xx response for route $routeId") | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift
서킷 브레이커 핵심 로직에 전용 단위 테스트가 없습니다. 세 파일 모두 새로 도입된 프로덕션 로직이지만, 제공된 테스트 파일 목록에는 RedisGatewayCircuitStateStoreIntegrationTest만 있고 이들 세 클래스를 직접 검증하는 테스트가 보이지 않습니다. 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."
systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitBreakerGlobalFilter.kt#L18-L83: 503/CIRCUIT_OPEN 응답, half-open 허용/거부, 로컬 breaker와 공유 store 조합 시나리오를 커버하는 필터 단위 테스트를 추가합니다.systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/InMemoryGatewayCircuitStateStore.kt#L11-L77: open/half-open/close 전환 및 동시성 시나리오에 대한 단위 테스트를 추가합니다.systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayResilienceConfiguration.kt#L10-L27: 최소한properties.resilience값이CircuitBreakerConfig에 올바르게 매핑되는지 검증하는 테스트를 추가합니다.
📍 Affects 3 files
systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitBreakerGlobalFilter.kt#L18-L83(this comment)systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/InMemoryGatewayCircuitStateStore.kt#L11-L77systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayResilienceConfiguration.kt#L10-L27
🤖 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/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitBreakerGlobalFilter.kt`
around lines 18 - 83, 핵심 서킷 브레이커 로직에 전용 단위 테스트가 없습니다.
GatewayCircuitBreakerGlobalFilter 테스트를 추가해 503/CIRCUIT_OPEN 응답, half-open 허용·거부,
로컬 breaker와 공유 stateStore 조합을 검증하세요. InMemoryGatewayCircuitStateStore 테스트에서는
open/half-open/close 전환과 동시성을 검증하고, GatewayResilienceConfiguration 테스트에서는
properties.resilience 값이 CircuitBreakerConfig에 올바르게 매핑되는지 확인하세요. 대상 사이트:
systems/gateway/gateway-adapter-in/src/main/kotlin/hs/kr/entrydsm/gateway/adapterin/resilience/GatewayCircuitBreakerGlobalFilter.kt
18-83, InMemoryGatewayCircuitStateStore.kt 11-77,
GatewayResilienceConfiguration.kt 10-27.
Source: Coding guidelines
| class GatewayGlobalExceptionHandlerTest { | ||
| @Test | ||
| fun mapsUnknownGatewayExceptionTo500WithTraceId() { | ||
| val exchange = MockServerWebExchange.from( | ||
| MockServerHttpRequest.get("/api/identity/users") | ||
| .header("X-Trace-Id", "handler-trace") | ||
| .build(), | ||
| ) | ||
|
|
||
| GatewayGlobalExceptionHandler().handle(exchange, IllegalStateException("gateway failure")).block() | ||
|
|
||
| assertEquals(500, exchange.response.statusCode?.value()) | ||
| assertEquals("handler-trace", exchange.response.headers.getFirst("X-Trace-Id")) | ||
| } | ||
|
|
||
| @Test | ||
| fun mapsOversizedRequestTo413() { | ||
| val exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/api/identity/users").build()) | ||
|
|
||
| GatewayGlobalExceptionHandler().handle(exchange, GatewayRequestTooLargeException()).block() | ||
|
|
||
| assertEquals(413, exchange.response.statusCode?.value()) | ||
| } | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
InvalidTraceIdException → 400 매핑에 대한 테스트 부재
GatewayGlobalExceptionHandler는 InvalidTraceIdException을 400(INVALID_TRACE_ID)으로 매핑하지만, 현재 이 파일이나 TraceIdGlobalFilterTest에서 해당 경로를 검증하는 테스트가 보이지 않습니다. 모든 요청에 영향을 주는 공통 오류 처리 경로이므로 회귀 테스트를 추가해 주세요.
As per path instructions, "Highlight behavior-changing code that lacks corresponding unit/integration tests."
🤖 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/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/error/GatewayGlobalExceptionHandlerTest.kt`
around lines 9 - 32, GatewayGlobalExceptionHandlerTest에 InvalidTraceIdException
처리 경로의 회귀 테스트를 추가하세요. 기존 테스트 패턴을 따라 해당 예외를 handler에 전달하고 응답 상태가 400이며 오류 코드가
INVALID_TRACE_ID로 매핑되는지 검증하세요.
Source: Path instructions
| class GatewayCorsGlobalFilterTest { | ||
| @Test | ||
| fun acceptsCaseInsensitivePreflightHeadersAndExposesTraceId() { | ||
| val exchange = MockServerWebExchange.from( | ||
| MockServerHttpRequest.options("/api/identity/users") | ||
| .header("Origin", "http://localhost:3000") | ||
| .header("Access-Control-Request-Method", "post") | ||
| .header("Access-Control-Request-Headers", "authorization,content-type") | ||
| .build(), | ||
| ) | ||
|
|
||
| GatewayCorsGlobalFilter(GatewayRuntimeProperties()).filter(exchange, GatewayFilterChain { Mono.empty() }).block() | ||
|
|
||
| assertTrue(exchange.response.headers.getFirst("Access-Control-Allow-Origin") == "http://localhost:3000") | ||
| assertTrue(exchange.response.headers.getFirst("Access-Control-Expose-Headers") == "X-Trace-Id") | ||
| assertTrue(exchange.response.headers.getFirst("Vary")?.contains("Origin") == true) | ||
| } | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
CORS 거부 경로(허용되지 않은 origin/method/header) 테스트 누락
현재는 허용된 origin의 성공 케이스만 검증합니다. GatewayCorsGlobalFilter는 미허용 origin에 대한 403 처리, preflight에서 허용되지 않은 method/header 조합에 대한 403 처리 로직도 갖고 있는데 이에 대한 테스트가 없습니다. CORS는 보안 경계이므로 거부 경로도 커버해 주세요.
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/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/filter/GatewayCorsGlobalFilterTest.kt`
around lines 11 - 28, Expand GatewayCorsGlobalFilterTest with deterministic
rejection cases for a disallowed origin and for preflight requests containing an
unsupported method or request header. Invoke GatewayCorsGlobalFilter through the
same mock exchange flow and assert meaningful 403 response status and relevant
CORS response behavior for each denial path, while preserving the existing
accepted preflight test.
Source: Path instructions
| .selectors( | ||
| selectClass(TraceIdGlobalFilterTest::class.java), | ||
| selectClass(GatewayServicePropertiesTest::class.java), | ||
| selectClass(DownstreamClientPolicyTest::class.java), | ||
| selectClass(DownstreamFailureGlobalFilterTest::class.java), | ||
| selectClass(GatewayGlobalExceptionHandlerTest::class.java), | ||
| selectClass(GatewayCorsGlobalFilterTest::class.java), | ||
| selectClass(GatewayProxyIntegrationTest::class.java), | ||
| ) | ||
| .build() |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Redis 서킷 상태 공유 통합 테스트가 러너에 등록되지 않음
RedisGatewayCircuitStateStoreIntegrationTest가 같은 모듈에 새로 추가되었지만 이 런처의 selectors(및 상단 import)에 포함되어 있지 않습니다. 이 러너가 Bazel 테스트 타깃의 실제 실행 진입점이라면, 이 클래스는 CI에서 전혀 실행되지 않습니다. PR 목표에서 강조한 "재시작/scale-out 상태 공유 검증" 테스트가 사실상 죽은 코드가 되어, Redis 기반 공유 상태 저장소의 핵심 회귀를 감지할 수 없습니다.
🐛 제안 수정
import hs.kr.entrydsm.gateway.adapterin.integration.GatewayProxyIntegrationTest
+import hs.kr.entrydsm.gateway.adapterin.resilience.RedisGatewayCircuitStateStoreIntegrationTest
import hs.kr.entrydsm.gateway.adapterin.trace.TraceIdGlobalFilterTest
...
selectClass(GatewayProxyIntegrationTest::class.java),
+ selectClass(RedisGatewayCircuitStateStoreIntegrationTest::class.java),
)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .selectors( | |
| selectClass(TraceIdGlobalFilterTest::class.java), | |
| selectClass(GatewayServicePropertiesTest::class.java), | |
| selectClass(DownstreamClientPolicyTest::class.java), | |
| selectClass(DownstreamFailureGlobalFilterTest::class.java), | |
| selectClass(GatewayGlobalExceptionHandlerTest::class.java), | |
| selectClass(GatewayCorsGlobalFilterTest::class.java), | |
| selectClass(GatewayProxyIntegrationTest::class.java), | |
| ) | |
| .build() | |
| .selectors( | |
| selectClass(TraceIdGlobalFilterTest::class.java), | |
| selectClass(GatewayServicePropertiesTest::class.java), | |
| selectClass(DownstreamClientPolicyTest::class.java), | |
| selectClass(DownstreamFailureGlobalFilterTest::class.java), | |
| selectClass(GatewayGlobalExceptionHandlerTest::class.java), | |
| selectClass(GatewayCorsGlobalFilterTest::class.java), | |
| selectClass(GatewayProxyIntegrationTest::class.java), | |
| selectClass(RedisGatewayCircuitStateStoreIntegrationTest::class.java), | |
| ) | |
| .build() |
🤖 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/gateway/gateway-adapter-in/src/test/kotlin/hs/kr/entrydsm/gateway/adapterin/GatewayAdapterInTestRunner.kt`
around lines 20 - 29, Register RedisGatewayCircuitStateStoreIntegrationTest in
GatewayAdapterInTestRunner by adding its import and including
selectClass(RedisGatewayCircuitStateStoreIntegrationTest::class.java) in the
selectors list, so the Redis circuit-state sharing integration test runs in the
Bazel test target.
| @Test | ||
| fun leavesAuthenticationAndAuthorizationToIdentity() { | ||
| assertTrue(GatewayAccessPolicy().isPublic("/actuator/health")) | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
공개 경로의 경계 조건을 함께 검증해 주세요.
현재 테스트는 /actuator/health의 행복한 경로만 확인하므로, 보호 경로가 실수로 공개되거나 /actuator/healthcheck처럼 잘못된 접두사까지 허용되는 회귀를 잡지 못합니다. 최소한 정확한 경로, 하위 경로, 비공개 경로를 함께 검증하세요.
`@Test`
fun leavesAuthenticationAndAuthorizationToIdentity() {
assertTrue(GatewayAccessPolicy().isPublic("/actuator/health"))
+ assertTrue(GatewayAccessPolicy().isPublic("/actuator/health/details"))
+ assertFalse(GatewayAccessPolicy().isPublic("/actuator/healthcheck"))
+ assertFalse(GatewayAccessPolicy().isPublic("/api/users"))
}As per path instructions, Kotlin 테스트는 행복한 경로만이 아닌 결정적이고 의미 있는 assertion을 포함해야 합니다.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Test | |
| fun leavesAuthenticationAndAuthorizationToIdentity() { | |
| assertTrue(GatewayAccessPolicy().isPublic("/actuator/health")) | |
| } | |
| `@Test` | |
| fun leavesAuthenticationAndAuthorizationToIdentity() { | |
| assertTrue(GatewayAccessPolicy().isPublic("/actuator/health")) | |
| assertTrue(GatewayAccessPolicy().isPublic("/actuator/health/details")) | |
| assertFalse(GatewayAccessPolicy().isPublic("/actuator/healthcheck")) | |
| assertFalse(GatewayAccessPolicy().isPublic("/api/users")) | |
| } |
🤖 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/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayAccessPolicyTest.kt`
around lines 7 - 10, Update leavesAuthenticationAndAuthorizationToIdentity in
GatewayAccessPolicyTest to assert the exact public path, an intended descendant
path, and a protected path; also verify that the near-match
/actuator/healthcheck is not public, preserving clear assertions for each
boundary case.
Source: Path instructions
| val request = LauncherDiscoveryRequestBuilder.request() | ||
| .selectors(selectClass(GatewayAccessPolicyTest::class.java)) | ||
| .build() |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
고정 클래스 선택 대신 패키지 단위 discovery를 사용하세요.
현재 목록에 없는 새 테스트는 소스 glob에 포함되어도 CI에서 실행되지 않습니다.
systems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayApplicationTestRunner.kt#L11-L13: application 패키지를 선택하세요.systems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapTestRunner.kt#L11-L16: bootstrap 테스트 패키지를 선택하세요.systems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/gateway/domain/GatewayDomainTestRunner.kt#L11-L13: domain 패키지를 선택하세요.
수정 예시
-import org.junit.platform.engine.discovery.DiscoverySelectors.selectClass
+import org.junit.platform.engine.discovery.DiscoverySelectors.selectPackage
- .selectors(selectClass(GatewayAccessPolicyTest::class.java))
+ .selectors(selectPackage("hs.kr.entrydsm.gateway.application"))📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| val request = LauncherDiscoveryRequestBuilder.request() | |
| .selectors(selectClass(GatewayAccessPolicyTest::class.java)) | |
| .build() | |
| val request = LauncherDiscoveryRequestBuilder.request() | |
| .selectors(selectPackage("hs.kr.entrydsm.gateway.application")) | |
| .build() |
📍 Affects 3 files
systems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayApplicationTestRunner.kt#L11-L13(this comment)systems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapTestRunner.kt#L11-L16systems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/gateway/domain/GatewayDomainTestRunner.kt#L11-L13
🤖 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/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayApplicationTestRunner.kt`
around lines 11 - 13, 고정된 테스트 클래스 선택을 제거하고 패키지 단위 discovery로 변경하세요.
systems/gateway/gateway-application/src/test/kotlin/hs/kr/entrydsm/gateway/application/GatewayApplicationTestRunner.kt의
GatewayApplicationTestRunner는 application 패키지를 선택하고,
systems/gateway/gateway-bootstrap/src/test/kotlin/hs/kr/entrydsm/gateway/GatewayBootstrapTestRunner.kt의
GatewayBootstrapTestRunner는 bootstrap 테스트 패키지를 선택하며,
systems/gateway/gateway-domain/src/test/kotlin/hs/kr/entrydsm/gateway/domain/GatewayDomainTestRunner.kt의
GatewayDomainTestRunner는 domain 패키지를 선택하도록 각각의 LauncherDiscoveryRequest를 수정하세요.
Summary
Related Issue
Current vs Improved
ConcurrentHashMap상태와 고정된 failure threshold를 사용했습니다.Impact
503 CIRCUIT_OPEN응답이 일관되게 동작합니다.GATEWAY_CIRCUIT_STATE_REDIS_URI와GATEWAY_CIRCUIT_*정책 변수를 지정할 수 있습니다.Testing
bazel test //systems/gateway/... --test_output=errorsgit diff --checkRisk
Checklist