Sub-scope 05 (inbound-web) idempotency + operation + operationasync + evidence
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-30T07:26:46+00:00

=== OWNED FILES ===
09b8372242c82d595ee2f9c3666ca578b676fe27 main/java/dev/caskeleton/adapter/inbound/web/evidence/WebApplicationEvidence.java 44
2b2d95ea7c6b1c08efa9daa27ea35dd2ce7f8bfe main/java/dev/caskeleton/adapter/inbound/web/evidence/WebEvidenceAxis.java 15
9d50db0ade99d79433193c095679d079fdb34770 main/java/dev/caskeleton/adapter/inbound/web/evidence/WebExecutionEvidence.java 57
3a6dc3e2292e7ea77f973bd77a68c3461fbe6a48 main/java/dev/caskeleton/adapter/inbound/web/evidence/WebExecutionEvidenceTracker.java 125
ea8eed7e43c59f73c57c29219e59977680a52dcc main/java/dev/caskeleton/adapter/inbound/web/evidence/WebRequestPhase.java 44
269ab58d05e149e802c6d1f1ba8965960b8804f7 main/java/dev/caskeleton/adapter/inbound/web/evidence/WebResponseEvidence.java 46
401ffe547bfb75201bdcb493ec2ad1b31bbde4fe main/java/dev/caskeleton/adapter/inbound/web/idempotency/DeterministicCommandEncoder.java 74
e97ca5b43539cc0cbab27197a30f15cdfb41b6be main/java/dev/caskeleton/adapter/inbound/web/idempotency/FingerprintHeaderPolicy.java 102
6bc27398702703e6296473ce7d5fdbf7a382bc25 main/java/dev/caskeleton/adapter/inbound/web/idempotency/IdempotencyAdmission.java 85
02e93a8b2b9bf830369021194517d05c8f90383e main/java/dev/caskeleton/adapter/inbound/web/idempotency/IdempotencyKey.java 33
0dc1a346d1d8d51249f39a1069ecea0d1f669864 main/java/dev/caskeleton/adapter/inbound/web/idempotency/IdempotencyKeySupport.java 66
3daf9dbddd62b03584f1e3d675eae8253b6a3b03 main/java/dev/caskeleton/adapter/inbound/web/idempotency/IdempotencyResponsePlan.java 97
e6563e02b7814ec4374cb66a67d2ea756672fa5c main/java/dev/caskeleton/adapter/inbound/web/idempotency/JsonIdempotentResponseCodec.java 44
bcdecedf0ae006aceb630d4377fc020ac3bf7598 main/java/dev/caskeleton/adapter/inbound/web/idempotency/SemanticRequestFingerprintFactory.java 94
d4c5c53c1ef4609e56b1c2057ae673920512c83c main/java/dev/caskeleton/adapter/inbound/web/idempotency/WebIdempotencyGate.java 180
7a0ba511685fb7086e06f62eb8aa79ca139ccd0a main/java/dev/caskeleton/adapter/inbound/web/mvc/idempotency/IdempotentResponseWriter.java 84
aceb3928ef9d8321e1c130a8ee0a4536bbe7d43e main/java/dev/caskeleton/adapter/inbound/web/mvc/idempotency/WebMvcIdempotentInvoker.java 108
0f5c4dfde6c99cf4e5f762f1cd962a07465e26fd main/java/dev/caskeleton/adapter/inbound/web/mvc/operation/OperationHttpController.java 105
f333b4eae4f8169f71a6b1e46088f199c416ceef main/java/dev/caskeleton/adapter/inbound/web/operation/AdmissionProfileName.java 35
6a9b1ebfadd3b7fad907d6b4d3849af2229e83cb main/java/dev/caskeleton/adapter/inbound/web/operation/AuthorizationProfileName.java 35
d9715d2f988d62a1630000dad36f7f9e52a989c1 main/java/dev/caskeleton/adapter/inbound/web/operation/CachePolicyName.java 35
1d36292c292382371d5ebed1b32b0b1fe619592c main/java/dev/caskeleton/adapter/inbound/web/operation/HttpMethodSemantic.java 54
3a0f6f5784d856454b7b5ff8778f07db12fcaf8f main/java/dev/caskeleton/adapter/inbound/web/operation/IdempotencyPolicy.java 20
dc03e5d24fa694498053cc7ce988182507d761cc main/java/dev/caskeleton/adapter/inbound/web/operation/InMemoryWebOperationCatalog.java 61
826c260984a2d3de253cb01aaf3ed82cd64528c2 main/java/dev/caskeleton/adapter/inbound/web/operation/MutationKind.java 38
916ad6adb9ae107737789fb43efd472ba56852da main/java/dev/caskeleton/adapter/inbound/web/operation/PreconditionPolicy.java 21
1c17d83ecbe49279203ac45eb1e16489c879bf47 main/java/dev/caskeleton/adapter/inbound/web/operation/ResponseProfileName.java 35
53572651a5b29d37b9a6994ab206496b3a2f4ce9 main/java/dev/caskeleton/adapter/inbound/web/operation/WebOperationCatalog.java 28
225984be514179238b0740670f724ee6ce662a9a main/java/dev/caskeleton/adapter/inbound/web/operation/WebOperationProfile.java 119
1bc8022b2b9b08660c06c66b29c7c3f28c2791ba main/java/dev/caskeleton/adapter/inbound/web/operationasync/OperationAccessPolicy.java 42
ee641d0b4f594fb8cc82b4f7886d834153c76b37 main/java/dev/caskeleton/adapter/inbound/web/operationasync/OperationId.java 29
1c2a0d2dc8569e4af92ccd7a1fe9de8368ab54d8 main/java/dev/caskeleton/adapter/inbound/web/operationasync/OperationProgress.java 50
ba9351e26f8dbf3f3f8d1d8cd81fcc49bf48aece main/java/dev/caskeleton/adapter/inbound/web/operationasync/OperationQueryService.java 74
37a69e38dd86724c908e5e347bf29856b453f45c main/java/dev/caskeleton/adapter/inbound/web/operationasync/OperationResource.java 159
441aaca5389c99c568f16eefe7eeda13066695d8 main/java/dev/caskeleton/adapter/inbound/web/operationasync/OperationResourceFactory.java 112
c3c340fe86f9f816711d42988ddb8b8cba101484 main/java/dev/caskeleton/adapter/inbound/web/operationasync/OperationResponse.java 56
00453ac2722e568d28d4e33d50db2fdb99dfc1e4 main/java/dev/caskeleton/adapter/inbound/web/operationasync/OperationResponseMapper.java 43
fd905407b7c0ca864c80eccc3f7d6e988e081b18 main/java/dev/caskeleton/adapter/inbound/web/operationasync/OperationStatus.java 40
8129f0895798453076bd9af97440617c9f412e20 main/java/dev/caskeleton/adapter/inbound/web/webflux/idempotency/WebFluxIdempotentInvoker.java 168
23ad8ee4b0a4113872e15374b44ad2efdda0ef42 main/java/dev/caskeleton/adapter/inbound/web/webflux/operation/ReactiveOperationHttpController.java 106
9dc9f2412a5d6287533e0b85cb49073131a92c57 test/java/dev/caskeleton/adapter/inbound/web/evidence/WebExecutionEvidenceTrackerTest.java 156
b531bd2a9f21c6c92c66f3e903a462cbdfaa8bf3 test/java/dev/caskeleton/adapter/inbound/web/idempotency/IdempotencyKeySupportTest.java 80
6b41124404aa453a69157860a914a4a2bdb89398 test/java/dev/caskeleton/adapter/inbound/web/idempotency/InMemoryIdempotencyStore.java 70
03ddbb79c4c27e9923a5fa30916443b42e4a73a7 test/java/dev/caskeleton/adapter/inbound/web/idempotency/SemanticRequestFingerprintFactoryTest.java 140
bd2825015460b787bdba7bdc463d38c1e4f33778 test/java/dev/caskeleton/adapter/inbound/web/idempotency/WebIdempotencyGateTest.java 343
2636c7fb45114d566c58c720fe82a3879b9aa433 test/java/dev/caskeleton/adapter/inbound/web/mvc/idempotency/WebMvcIdempotentInvokerTest.java 288
93b8a0dcf5ac710ffaa337c7dafe7efdf0c0c06a test/java/dev/caskeleton/adapter/inbound/web/operation/WebOperationCatalogTest.java 141
787e4a5fbd4b4bc4863e92a590e035ca9668300a test/java/dev/caskeleton/adapter/inbound/web/operationasync/OperationAccessPolicyTest.java 122
5ea653c8698c2aab6095b1ac45b41a3a3abdcc04 test/java/dev/caskeleton/adapter/inbound/web/operationasync/OperationResourceTest.java 230
aa70c62a7d7441f545e241e4c48954658731af97 test/java/dev/caskeleton/adapter/inbound/web/webflux/idempotency/WebFluxIdempotentInvokerTest.java 268
file_count=50

=== 8.1 도달성: 멱등성 실행 계층과 durable-operation 표면 ===
WebIdempotencyGate                       5 test       2 testkit 
WebMvcIdempotentInvoker                  1 test       1 testkit 
WebFluxIdempotentInvoker                 1 test       1 testkit 
IdempotentResponseWriter                 1 test       1 testkit 
SemanticRequestFingerprintFactory        6 test       2 testkit 
OperationQueryService                    1 testkit 
OperationResourceFactory                 1 testkit 
WebExecutionEvidenceTracker              1 main 
$ grep -rn 'inbound.web.idempotency\|WebIdempotencyGate\|IdempotencyKeySupport' --include=*.java app-bootstrap/src/main | wc -l
0
exit=0

$ grep -rn 'IdempotencyKeySupport' --include=*.java adapter/inbound/web/src/main sample-portfolio/src/main | grep -v IdempotencyKeySupport.java | wc -l
0
exit=0

=== 8.2 durable-operation 컨트롤러의 게이트와 의존 ===
$ grep -n 'ConditionalOnProperty' -A 4 adapter/inbound/web/src/main/java/dev/caskeleton/adapter/inbound/web/mvc/operation/OperationHttpController.java | tail -5
35:@ConditionalOnProperty(
36-    prefix = "app.web-platform.durable-operations",
37-    name = "enabled",
38-    havingValue = "true")
39-@RequestMapping(OperationHttpController.BASE_PATH)
exit=0

$ grep -rn 'app.web-platform.durable-operations' --include=*.yml --include=*.yaml --include=*.java . | sed 's|adapter/inbound/web/src/||'
./main/java/dev/caskeleton/adapter/inbound/web/mvc/operation/OperationHttpController.java:36:    prefix = "app.web-platform.durable-operations",
./main/java/dev/caskeleton/adapter/inbound/web/webflux/operation/ReactiveOperationHttpController.java:37:    prefix = "app.web-platform.durable-operations",
exit=0

$ grep -rn 'OperationQueryService' --include=*.java adapter/inbound/web/src/main app-bootstrap/src/main | grep -v 'OperationQueryService.java' | sed 's|.*/web/||'
mvc/operation/OperationHttpController.java:6:import dev.caskeleton.adapter.inbound.web.operationasync.OperationQueryService;
mvc/operation/OperationHttpController.java:45:  private final OperationQueryService operations;
mvc/operation/OperationHttpController.java:52:  public OperationHttpController(OperationQueryService operations) {
webflux/operation/ReactiveOperationHttpController.java:6:import dev.caskeleton.adapter.inbound.web.operationasync.OperationQueryService;
webflux/operation/ReactiveOperationHttpController.java:28: * {@link OperationQueryService}, which both call. What differs is only what has to: the store is
webflux/operation/ReactiveOperationHttpController.java:46:  private final OperationQueryService operations;
webflux/operation/ReactiveOperationHttpController.java:56:      OperationQueryService operations, Scheduler blockingScheduler) {
exit=0

=== 8.3 WebOperationCatalog 를 읽는 쪽 ===
$ grep -rn 'WebOperationCatalog' --include=*.java adapter/inbound/web/src/main app-bootstrap/src/main | grep -v 'operation/WebOperationCatalog.java\|InMemoryWebOperationCatalog.java' | sed 's|.*/web/||'
mvc/autoconfigure/WebMvcPlatformAutoConfiguration.java:17:import dev.caskeleton.adapter.inbound.web.operation.InMemoryWebOperationCatalog;
mvc/autoconfigure/WebMvcPlatformAutoConfiguration.java:18:import dev.caskeleton.adapter.inbound.web.operation.WebOperationCatalog;
mvc/autoconfigure/WebMvcPlatformAutoConfiguration.java:58:  @ConditionalOnMissingBean(WebOperationCatalog.class)
mvc/autoconfigure/WebMvcPlatformAutoConfiguration.java:59:  public InMemoryWebOperationCatalog webOperationCatalog() {
mvc/autoconfigure/WebMvcPlatformAutoConfiguration.java:60:    return new InMemoryWebOperationCatalog();
webflux/autoconfigure/WebFluxPlatformAutoConfiguration.java:13:import dev.caskeleton.adapter.inbound.web.operation.InMemoryWebOperationCatalog;
webflux/autoconfigure/WebFluxPlatformAutoConfiguration.java:14:import dev.caskeleton.adapter.inbound.web.operation.WebOperationCatalog;
webflux/autoconfigure/WebFluxPlatformAutoConfiguration.java:76:  @ConditionalOnMissingBean(WebOperationCatalog.class)
webflux/autoconfigure/WebFluxPlatformAutoConfiguration.java:77:  public InMemoryWebOperationCatalog webOperationCatalog() {
webflux/autoconfigure/WebFluxPlatformAutoConfiguration.java:78:    return new InMemoryWebOperationCatalog();
admin/route/WebRouteInventory.java:4:import dev.caskeleton.adapter.inbound.web.operation.WebOperationCatalog;
admin/route/WebRouteInventory.java:50:  public void requireRegisteredOperations(WebOperationCatalog catalog) {
advanced/functional/FunctionalRoutePolicyValidator.java:3:import dev.caskeleton.adapter.inbound.web.operation.WebOperationCatalog;
advanced/functional/FunctionalRoutePolicyValidator.java:22:  private final WebOperationCatalog catalog;
advanced/functional/FunctionalRoutePolicyValidator.java:24:  public FunctionalRoutePolicyValidator(WebOperationCatalog catalog) {
advanced/functional/FunctionalRouteRegistry.java:3:import dev.caskeleton.adapter.inbound.web.operation.WebOperationCatalog;
advanced/functional/FunctionalRouteRegistry.java:25:  public FunctionalRouteRegistry(WebOperationCatalog catalog) {
exit=0

=== 8.4 fingerprint 정규화 형식 ===
$ grep -n 'SEPARATOR\|canonical.append' adapter/inbound/web/src/main/java/dev/caskeleton/adapter/inbound/web/idempotency/SemanticRequestFingerprintFactory.java
36:  private static final char SEPARATOR = '\u001f';
68:    canonical.append(operation.value());
71:            (name, value) -> canonical.append(SEPARATOR).append(name).append('=').append(value));
72:    canonical.append(SEPARATOR).append(encoder.canonicalize(command));
76:            (name, value) -> canonical.append(SEPARATOR).append(name).append(':').append(value));
exit=0

$ grep -rn 'ByteBuffer.allocate(Integer.BYTES)\|putInt(encoded.length)' --include=*.java adapter | wc -l
17
exit=0

