Sub-scope 04 (inbound-web) ratelimit + admission + budget + throttle
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-30T07:23:43+00:00

=== OWNED FILES ===
91364220d354fa936a10b942e6b2dcde630498b3 main/java/dev/caskeleton/adapter/inbound/web/admission/AdmissionDecision.java 59
178b4490eb12e5eed46a3f852a8a264b85c86e0d main/java/dev/caskeleton/adapter/inbound/web/admission/AdmissionPermit.java 21
16681817bdd516264d4909bcb4786f732855920b main/java/dev/caskeleton/adapter/inbound/web/admission/AdmissionProfile.java 80
d00ff8067c01ba747e4f94c96572f43173e44405 main/java/dev/caskeleton/adapter/inbound/web/admission/SemaphoreAdmissionController.java 118
b14a7024c1c8b003ef79df07368278a0444358d1 main/java/dev/caskeleton/adapter/inbound/web/admission/WebAdmissionController.java 21
064bc2a25fb24a24318f4e4836e28ef3a7142aca main/java/dev/caskeleton/adapter/inbound/web/advanced/ratelimit/RateLimitDraftHeaderWriter.java 73
25ef35f4c36501e9848d1c28dfc130cc3c8ce8fd main/java/dev/caskeleton/adapter/inbound/web/advanced/ratelimit/RateLimitDraftProfile.java 36
527173887c38bb4299fcea99e11fbb36a4deb81e main/java/dev/caskeleton/adapter/inbound/web/advanced/ratelimit/RateLimitDraftVersion.java 41
7300a77496caf76d63d42aba79efed3b5ec0e874 main/java/dev/caskeleton/adapter/inbound/web/budget/WebBudgetCatalog.java 77
7c429e0e8257d90e9fd8bcd594eef9368358fc2d main/java/dev/caskeleton/adapter/inbound/web/budget/WebBudgetExceededException.java 56
219b33822d4b542333a2dab1449cc23ba26ffc16 main/java/dev/caskeleton/adapter/inbound/web/budget/WebBudgetMeter.java 89
df6334d8bc0fc3eccc1aee269ccde151f1549028 main/java/dev/caskeleton/adapter/inbound/web/budget/WebBudgetOutcome.java 40
65a4d2c3f3b6ff18458e587550de70f3579d7c17 main/java/dev/caskeleton/adapter/inbound/web/budget/WebBudgetProfileName.java 35
5ccabea10ffcdb5066a8da97146da3d0a58e200b main/java/dev/caskeleton/adapter/inbound/web/budget/WebBudgetViolation.java 39
476086f93ce7d1358dc5e03b509edbcffc361f91 main/java/dev/caskeleton/adapter/inbound/web/budget/WebRequestBudget.java 141
37c6eaaa23dc44f2aa7e696a1fb0b4c094c14252 main/java/dev/caskeleton/adapter/inbound/web/mvc/budget/BoundedHttpServletRequest.java 115
8ba1739ac67c6743deae81c3ad732cc631b974ba main/java/dev/caskeleton/adapter/inbound/web/mvc/budget/BoundedHttpServletResponse.java 151
ea75c7ef7569a86c5c5c6156f56e505954644324 main/java/dev/caskeleton/adapter/inbound/web/mvc/budget/WebMvcBudgetExceptionHandler.java 84
d35a927c92567e81c69f64f512de827c0b53ed65 main/java/dev/caskeleton/adapter/inbound/web/mvc/budget/WebMvcBudgetFilter.java 122
132e294ed05e2e576f04ac7bbdf45343c20c279e main/java/dev/caskeleton/adapter/inbound/web/mvc/throttle/WebMvcThrottleFilter.java 136
d6d622affd05580e675083c8f5bfc2361129a52b main/java/dev/caskeleton/adapter/inbound/web/ratelimit/ClientIpResolver.java 8
3998c4a6d452d2b07efb3527446ebc578529fe13 main/java/dev/caskeleton/adapter/inbound/web/ratelimit/ClientIpResolverFactory.java 13
00303de4d8813ad2f634d41845fe90372c9bd6e6 main/java/dev/caskeleton/adapter/inbound/web/ratelimit/EdgeRateLimitTransportBridge.java 86
980c68b886f3dd3141245504ae8df8cca73bf739 main/java/dev/caskeleton/adapter/inbound/web/ratelimit/EdgeRateLimitTransportSettings.java 40
48a302c4834994d13c7ab59cbdb99b87a7d87cb5 main/java/dev/caskeleton/adapter/inbound/web/ratelimit/ForwardedHeaderClientIpResolver.java 18
3a946d89ad14457d8c044e40a6680bee5eed10e2 main/java/dev/caskeleton/adapter/inbound/web/ratelimit/RateLimitClientIpMode.java 13
30294e192050277f092a8224231d1750a44d5342 main/java/dev/caskeleton/adapter/inbound/web/ratelimit/RateLimitDecision.java 65
0726c4d35d1a0a1d063626e2fa6aaadc07904f53 main/java/dev/caskeleton/adapter/inbound/web/ratelimit/RateLimitEvaluationIdGenerator.java 8
5e05dc2cb9c3e33d1ac42c7e61b50565bf8874e2 main/java/dev/caskeleton/adapter/inbound/web/ratelimit/RateLimitFailurePolicy.java 30
19e7cf3969ec583c50bd01d631a79536a2e8ed7f main/java/dev/caskeleton/adapter/inbound/web/ratelimit/RateLimitInterceptor.java 112
a475a46a747e8ac49c694b479fda5972e9e60f40 main/java/dev/caskeleton/adapter/inbound/web/ratelimit/RateLimitKeyResolver.java 66
34928384705f1b47268ecfef9d71daba9a4b4e02 main/java/dev/caskeleton/adapter/inbound/web/ratelimit/RateLimitProfileName.java 32
651e860d43ed50f1d2e00496fc4dbc4f3f8f5768 main/java/dev/caskeleton/adapter/inbound/web/ratelimit/RateLimitTransportError.java 38
b460c3cb37399a5c581320b9c34eb005544499bb main/java/dev/caskeleton/adapter/inbound/web/ratelimit/RateLimitWebConfig.java 67
d20cc46d411c98e414855fd107480e7dd6368461 main/java/dev/caskeleton/adapter/inbound/web/ratelimit/RemoteAddrClientIpResolver.java 11
b0a9a5ce791f990544a182a059f2340b0fc9f728 main/java/dev/caskeleton/adapter/inbound/web/ratelimit/SecureRandomRateLimitEvaluationIdGenerator.java 38
7afd8c25c817d7ae49017a651f94fd39a773d5bc main/java/dev/caskeleton/adapter/inbound/web/ratelimit/VersionedEdgeSubjectPseudonymizer.java 45
2d51bee694b2bd6847addf938d7cb54abecf26db main/java/dev/caskeleton/adapter/inbound/web/ratelimit/WebRateLimiter.java 25
817578500dc87cc5d4affbaaafc15243f36ce64f main/java/dev/caskeleton/adapter/inbound/web/webflux/budget/BoundedServerWebExchange.java 79
172eca7694b781fc0a14206f328c92f0ad008d80 main/java/dev/caskeleton/adapter/inbound/web/webflux/budget/WebFluxBudgetFilter.java 122
58b921077cdb445708a87b5083d4b47992925658 main/java/dev/caskeleton/adapter/inbound/web/webflux/throttle/WebFluxThrottleFilter.java 142
ded314b65a8deaa1efffbeb7145f9eea1f26174b test/java/dev/caskeleton/adapter/inbound/web/advanced/ratelimit/RateLimitDraftHeaderWriterTest.java 108
25f51374ee7763c347632ca7cd5904212f220c62 test/java/dev/caskeleton/adapter/inbound/web/budget/WebRequestBudgetTest.java 110
e43e7f9b760ddd43f3a589f0388e816bc0dcb2e6 test/java/dev/caskeleton/adapter/inbound/web/ratelimit/EdgeRateLimitTransportBridgeTest.java 100
6dffb8edee33161a156cd3431ae32b43c55a36e1 test/java/dev/caskeleton/adapter/inbound/web/ratelimit/EdgeRateLimitTransportSettingsTest.java 44
67ec066c7261ab339e0e0d4556420b76508a663b test/java/dev/caskeleton/adapter/inbound/web/ratelimit/RateLimitInterceptorTest.java 178
5b22af742cf30c3729d2e31b8772c7a4a1778d39 test/java/dev/caskeleton/adapter/inbound/web/ratelimit/RateLimitKeyResolverTest.java 99
15168b5a9a2eb38933a71146649141656837d1ae test/java/dev/caskeleton/adapter/inbound/web/ratelimit/RateLimitWebConfigTest.java 35
e01a2ce6cb177dddb3ae3855b1debe3ca04decf1 test/java/dev/caskeleton/adapter/inbound/web/ratelimit/SecureRandomRateLimitEvaluationIdGeneratorTest.java 24
6ec469f04b3dbb6c0da4b5859cc97e777c600ccd test/java/dev/caskeleton/adapter/inbound/web/ratelimit/VersionedEdgeSubjectPseudonymizerTest.java 32
file_count=50

=== 8.1 도달성: 네 필터와 admission controller 의 등록 지점 ===
-- WebMvcBudgetFilter
./testkit/java/dev/caskeleton/webtestkit/BudgetFixtureApplication.java:43:  FilterRegistrationBean<WebMvcBudgetFilter> budgetFilter() {
./testkit/java/dev/caskeleton/webtestkit/BudgetFixtureApplication.java:44:    FilterRegistrationBean<WebMvcBudgetFilter> registration =
./testkit/java/dev/caskeleton/webtestkit/BudgetFixtureApplication.java:46:            new WebMvcBudgetFilter(
-- WebFluxBudgetFilter
./webfluxContractTest/java/dev/caskeleton/adapter/inbound/web/testkit/budget/ReactiveBudgetFixtureApplication.java:39:    return new WebFluxBudgetFilter(
-- WebMvcThrottleFilter
./testkit/java/dev/caskeleton/webtestkit/ThrottleFixtureApplication.java:47:  FilterRegistrationBean<WebMvcThrottleFilter> throttleFilter(CountingRateLimiter limiter) {
./testkit/java/dev/caskeleton/webtestkit/ThrottleFixtureApplication.java:48:    FilterRegistrationBean<WebMvcThrottleFilter> registration =
./testkit/java/dev/caskeleton/webtestkit/ThrottleFixtureApplication.java:50:            new WebMvcThrottleFilter(
-- WebFluxThrottleFilter
./webfluxContractTest/java/dev/caskeleton/adapter/inbound/web/testkit/throttle/ReactiveThrottleFixtureApplication.java:44:        new WebFluxThrottleFilter(
-- SemaphoreAdmissionController
./testkit/java/dev/caskeleton/adapter/inbound/web/testkit/throttle/ThrottleFixtureSupport.java:39:    return new SemaphoreAdmissionController(AdmissionProfile.standard(), writeProfile());
-- WebRateLimiter
-- WebBudgetMeter
./main/java/dev/caskeleton/adapter/inbound/web/mvc/budget/WebMvcBudgetFilter.java:56:            new WebBudgetMeter(WebBudgetViolation.RESPONSE_TOO_LARGE, budget.maxResponseBytes()));
./main/java/dev/caskeleton/adapter/inbound/web/mvc/budget/WebMvcBudgetFilter.java:62:              new WebBudgetMeter(WebBudgetViolation.BODY_TOO_LARGE, budget.maxBodyBytes())),
./main/java/dev/caskeleton/adapter/inbound/web/webflux/budget/WebFluxBudgetFilter.java:103:    new WebBudgetMeter(WebBudgetViolation.BODY_TOO_LARGE, budget.maxBodyBytes())
./main/java/dev/caskeleton/adapter/inbound/web/webflux/budget/BoundedServerWebExchange.java:41:        new WebBudgetMeter(WebBudgetViolation.BODY_TOO_LARGE, budget.maxBodyBytes());
./main/java/dev/caskeleton/adapter/inbound/web/webflux/budget/BoundedServerWebExchange.java:43:        new WebBudgetMeter(WebBudgetViolation.RESPONSE_TOO_LARGE, budget.maxResponseBytes());

=== 8.2 조건 형제 비교: 두 개의 rate limiting 메커니즘 ===
$ grep -n 'addInterceptors' -A 3 adapter/inbound/web/src/main/java/dev/caskeleton/adapter/inbound/web/ratelimit/RateLimitWebConfig.java
55:  public void addInterceptors(InterceptorRegistry registry) {
56-    registry.addInterceptor(rateLimitInterceptor);
57-  }
58-
exit=0

$ grep -rn 'WebRateLimiter' --include=*.java adapter/inbound/web/src/main | sed 's|.*/web/||'
ratelimit/WebRateLimiter.java:16:public interface WebRateLimiter {
mvc/throttle/WebMvcThrottleFilter.java:13:import dev.caskeleton.adapter.inbound.web.ratelimit.WebRateLimiter;
mvc/throttle/WebMvcThrottleFilter.java:41:  private final WebRateLimiter limiter;
mvc/throttle/WebMvcThrottleFilter.java:61:      WebRateLimiter limiter,
webflux/throttle/WebFluxThrottleFilter.java:13:import dev.caskeleton.adapter.inbound.web.ratelimit.WebRateLimiter;
webflux/throttle/WebFluxThrottleFilter.java:44:  private final WebRateLimiter limiter;
webflux/throttle/WebFluxThrottleFilter.java:66:      WebRateLimiter limiter,
exit=0

=== 8.3 WebBudgetCatalog 소비자 ===
$ grep -rn 'WebBudgetCatalog' --include=*.java adapter/inbound/web/src/main app-bootstrap/src/main | grep -v 'WebBudgetCatalog.java' | sed 's|.*/web/||;s|.*/bootstrap/|BOOT:|'
mvc/autoconfigure/WebMvcPlatformAutoConfiguration.java:3:import dev.caskeleton.adapter.inbound.web.budget.WebBudgetCatalog;
mvc/autoconfigure/WebMvcPlatformAutoConfiguration.java:66:  public WebBudgetCatalog webBudgetCatalog() {
mvc/autoconfigure/WebMvcPlatformAutoConfiguration.java:67:    WebBudgetCatalog catalog = new WebBudgetCatalog();
webflux/autoconfigure/WebFluxPlatformAutoConfiguration.java:3:import dev.caskeleton.adapter.inbound.web.budget.WebBudgetCatalog;
webflux/autoconfigure/WebFluxPlatformAutoConfiguration.java:84:  public WebBudgetCatalog webBudgetCatalog() {
webflux/autoconfigure/WebFluxPlatformAutoConfiguration.java:85:    WebBudgetCatalog catalog = new WebBudgetCatalog();
exit=0

=== 8.4 budgets 게이트 프로퍼티가 존재하는가 ===
$ grep -rn 'backend.web.budgets' --include=*.yml --include=*.yaml --include=*.properties --include=*.java . | sed 's|adapter/inbound/web/src/||'
./webfluxContractTest/java/dev/caskeleton/adapter/inbound/web/testkit/budget/ReactiveWebBudgetIT.java:19:    properties = "backend.web.budgets.enabled=true")
./test/java/dev/caskeleton/adapter/inbound/web/testkit/budget/TomcatWebBudgetIT.java:20:    properties = "backend.web.budgets.enabled=true")
./main/java/dev/caskeleton/adapter/inbound/web/mvc/budget/WebMvcBudgetExceptionHandler.java:40:@ConditionalOnProperty(prefix = "backend.web.budgets", name = "enabled", havingValue = "true")
./jettyCompatTest/java/dev/caskeleton/adapter/inbound/web/testkit/budget/JettyWebBudgetIT.java:20:    properties = "backend.web.budgets.enabled=true")
exit=0

$ grep -rn 'BudgetProblemMapper' --include=*.java adapter/inbound/web/src/main app-bootstrap/src/main | grep -v 'BudgetProblemMapper.java' | sed 's|.*/web/||'
mvc/budget/WebMvcBudgetFilter.java:7:import dev.caskeleton.adapter.inbound.web.error.BudgetProblemMapper;
mvc/budget/WebMvcBudgetFilter.java:32:  private final BudgetProblemMapper problems;
mvc/budget/WebMvcBudgetFilter.java:43:      WebRequestBudget budget, BudgetProblemMapper problems, JsonMapper mapper) {
mvc/budget/WebMvcBudgetExceptionHandler.java:4:import dev.caskeleton.adapter.inbound.web.error.BudgetProblemMapper;
mvc/budget/WebMvcBudgetExceptionHandler.java:28: * <p>Both paths produce the document through the same {@link BudgetProblemMapper}, so which one
mvc/budget/WebMvcBudgetExceptionHandler.java:37:// Gated on a property rather than on the BudgetProblemMapper bean, for the same reason: on a
mvc/budget/WebMvcBudgetExceptionHandler.java:44:  private final BudgetProblemMapper problems;
mvc/budget/WebMvcBudgetExceptionHandler.java:51:  public WebMvcBudgetExceptionHandler(BudgetProblemMapper problems) {
webflux/budget/WebFluxBudgetFilter.java:7:import dev.caskeleton.adapter.inbound.web.error.BudgetProblemMapper;
webflux/budget/WebFluxBudgetFilter.java:39:  private final BudgetProblemMapper problems;
webflux/budget/WebFluxBudgetFilter.java:50:      WebRequestBudget budget, BudgetProblemMapper problems, JsonMapper mapper) {
exit=0

