Sub-scope 06 (httpclient) service + dynamic + observation + migration — manifest and probes
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-30T05:36:11+00:00

=== OWNED FILES ===
2af09e541e44e5fe5a7cf24b15136642768a4087 main/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/CallScopedDnsPin.java 78
27618ac790d4e0046ae8dc9ccfe822a9ad04adc8 main/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/CanonicalTarget.java 41
22074cb132f9d4d512170e12714c4ade7d4b0a20 main/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/DefaultDynamicTargetGateway.java 228
b7fcfaa0a7cdc49c6b08dedc00e57d60f45caa69 main/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/DynamicCredentialBinding.java 79
ac3fc51793c5fb8b94ae7f9622ef2efa28202343 main/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/DynamicTargetGateway.java 21
f321f921eb9a532d0646a693bd708c27900948c5 main/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/DynamicTargetPolicy.java 86
f2437231ac5e58c5c4330e42c27d60d785b9245d main/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/DynamicTargetPolicyName.java 16
71577ef97db1dcdd53278b6a290917a12332ff2e main/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/IpAddressClassifier.java 215
960c7a4f75ed4bb91fa15aca5eba0620fff90ee4 main/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/PinnedTarget.java 24
50d4d3bf482d7c01534c9291acdecf395d552858 main/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/TargetCanonicalizer.java 112
29a3df649ea8a3a92008e518f495a792d75c51b8 main/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/ValidatedDnsResolver.java 89
e43820f9778a041ec21f43f3131b22535b351592 main/java/dev/caskeleton/adapter/outbound/httpclient/migration/MigrationFinding.java 37
bb3563961e27ea83ec9d98066378ffe645d5f7a9 main/java/dev/caskeleton/adapter/outbound/httpclient/migration/RestTemplateInventory.java 37
6975590b25ec9c54b609b38417c3b9ebc4a5ff10 main/java/dev/caskeleton/adapter/outbound/httpclient/migration/RestTemplateInventoryScanner.java 59
c732b6ab9d542765795d0e5762f929010f809e8d main/java/dev/caskeleton/adapter/outbound/httpclient/migration/RestTemplateToRestClientAdapter.java 31
1dbb0bc7d98e76add4e87c26855ea8bd0e8bea8b main/java/dev/caskeleton/adapter/outbound/httpclient/observation/AttemptObservation.java 91
07b76d79376e25d75d9a234128ad41f393b7447d main/java/dev/caskeleton/adapter/outbound/httpclient/observation/HttpClientObservationNames.java 38
3b3fa7a105542ea7a4fa37b704d6c7b801d59337 main/java/dev/caskeleton/adapter/outbound/httpclient/observation/HttpClientTagPolicy.java 48
4577e52c32022a0e22db855e2c1f3ce996e6b236 main/java/dev/caskeleton/adapter/outbound/httpclient/observation/LogicalCallObservation.java 86
8666481f62760563c8879a9aa50925a6c9e149e8 main/java/dev/caskeleton/adapter/outbound/httpclient/observation/SafeHttpLogEvent.java 65
a5e69de9d6450b425396ac9563d2d6bb72dc531f main/java/dev/caskeleton/adapter/outbound/httpclient/observation/SensitiveValueRedactor.java 53
52bb01e25a00172aa0fcde9d27abb494ce115aba main/java/dev/caskeleton/adapter/outbound/httpclient/service/BlockingServiceInvocationHandler.java 52
a6a4b2c442a54d0db9c67f25b67a4d9969fff801 main/java/dev/caskeleton/adapter/outbound/httpclient/service/DefaultHttpServiceRegistry.java 115
c36bc593bf52dc041194e6ee20b2a8a9a939f189 main/java/dev/caskeleton/adapter/outbound/httpclient/service/DefaultReactiveHttpServiceRegistry.java 108
6a755427420edbcef4159b66a5ad65d81ff73176 main/java/dev/caskeleton/adapter/outbound/httpclient/service/HttpClientProfile.java 21
b2f36166a930c990b0389ed1be9923cce7e19dc5 main/java/dev/caskeleton/adapter/outbound/httpclient/service/HttpOperationPolicy.java 33
3b49db43679a3fd95703ce5e599c212820499009 main/java/dev/caskeleton/adapter/outbound/httpclient/service/HttpServiceRegistry.java 17
59929fedf0b1ab68e78c60271dea5a4127a12235 main/java/dev/caskeleton/adapter/outbound/httpclient/service/KernelHttpExchangeAdapter.java 211
7930325d46b5da36e0c87ea60fc917c5bc429044 main/java/dev/caskeleton/adapter/outbound/httpclient/service/OperationContextHolder.java 38
bcad49a3265db6dd3157220f85ce8ad7cdb29d55 main/java/dev/caskeleton/adapter/outbound/httpclient/service/ReactiveHttpServiceRegistry.java 11
935bf7584884f90f86c315d861466dcaf88bcff6 main/java/dev/caskeleton/adapter/outbound/httpclient/service/ReactiveKernelHttpExchangeAdapter.java 272
968873f1b16a0d6fe5dad9068651fce1b020bee4 main/java/dev/caskeleton/adapter/outbound/httpclient/service/ReactiveOperationContext.java 21
20522e681dcae77d02b1a2ec30602ac2ea7c2113 main/java/dev/caskeleton/adapter/outbound/httpclient/service/ReactiveServiceInvocationHandler.java 79
bce1f13e9c22a53e49fc019b930acf4a812a9a3a main/java/dev/caskeleton/adapter/outbound/httpclient/service/ServiceOperationDescriptor.java 32
b7ecaf988db71e1a4f90eb9f5ff3aa654eed3de0 main/java/dev/caskeleton/adapter/outbound/httpclient/service/ServiceOperationDescriptorScanner.java 154
d276cc605f4f92df779c48b847cbaa946788d3ff test/java/dev/caskeleton/adapter/outbound/httpclient/architecture/HttpClientModuleBoundaryTest.java 115
76e10b273255a7e8faf974420802a897fdcf2271 test/java/dev/caskeleton/adapter/outbound/httpclient/architecture/PlatformClasses.java 40
2aa907b1b3f9df7a5beb1094b2a057db7d318efe test/java/dev/caskeleton/adapter/outbound/httpclient/architecture/PublicApiArchitectureTest.java 152
eb356ac8a3a3092902a7caa9cbc09d593167f8b5 test/java/dev/caskeleton/adapter/outbound/httpclient/contract/AllStableTransportsContractTest.java 217
bd864272cb9ba0fe3d330f5bd19b2ef76e6b296d test/java/dev/caskeleton/adapter/outbound/httpclient/contract/FailureInjectionContractTest.java 86
bf64d702c186503c074297bd9a2e13c27a2072b1 test/java/dev/caskeleton/adapter/outbound/httpclient/contract/NegotiatedProtocolContractTest.java 175
8bddf0864197c9b35d50f20fe55b7d761fb68bef test/java/dev/caskeleton/adapter/outbound/httpclient/contract/ResourceLifecycleContractTest.java 42
b14b51f5ffe6151719542b0be41d1abfc77a8858 test/java/dev/caskeleton/adapter/outbound/httpclient/contract/RetrySafetyContractTest.java 15
4aa7e00c81f2f679cfe7a38bb51ec8eba8c55316 test/java/dev/caskeleton/adapter/outbound/httpclient/contract/SecurityContractTest.java 84
12732b6ced283b139cff9db6d0bf3ad7a1e39ff8 test/java/dev/caskeleton/adapter/outbound/httpclient/contract/StatefulUpstreamRetryContractTest.java 170
e795be1532576002788b322c9e7020ffbdd1fe02 test/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/DynamicTargetSecurityTest.java 253
efc598351139295ac9485b5fc5ce5fe473a94697 test/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/TargetCanonicalizerTest.java 76
ac0708d2aefb5465a388847f60583f5d98f8fc50 test/java/dev/caskeleton/adapter/outbound/httpclient/migration/RestTemplateBoundaryTest.java 45
002cfe85746b58db8f5b1835be984426b9702d89 test/java/dev/caskeleton/adapter/outbound/httpclient/migration/RestTemplateToRestClientAdapterTest.java 64
8663d7ee8c483d6a6bd77c2a3d018ac44e92bfe5 test/java/dev/caskeleton/adapter/outbound/httpclient/observation/DeclaredMetricsAreEmittedTest.java 131
470f72a9496f91468355c26b563d36a6e9ff1a19 test/java/dev/caskeleton/adapter/outbound/httpclient/observation/HttpClientTagPolicyTest.java 85
2b4770cd22b6faf5c0a0c1bdaaeb6855f5d9d390 test/java/dev/caskeleton/adapter/outbound/httpclient/service/BlockingHttpServiceRegistryTest.java 76
a9522043a7c32ca58b7c486aa1e1d651f1801c22 test/java/dev/caskeleton/adapter/outbound/httpclient/service/BlockingReactiveSignatureSeparationTest.java 43
7cd7f5e356477c0d95ec5091e83862aa6e673949 test/java/dev/caskeleton/adapter/outbound/httpclient/service/ReactiveHttpServiceRegistryTest.java 89
99cbf7319f1fbfbd56cd687ef18211de2911b3db test/java/dev/caskeleton/adapter/outbound/httpclient/service/ServiceSignatureValidationTest.java 67
ff643ff91f7840c09b3699789d506f995992aa01 test/java/dev/caskeleton/adapter/outbound/httpclient/service/TypedClientPlatformPolicyTest.java 136

main: 35  test: 21
=== 8.1 approved 맵의 수명 ===
$ grep -n 'approved' adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/ValidatedDnsResolver.java
27: * approved five minutes ago is not evidence about the host now, which is the entire premise of
37:  private final Map<String, List<InetAddress>> approved = new ConcurrentHashMap<>();
58:        approved.remove(host);
65:    approved.put(host, immutable);
74:  public List<InetAddress> approvedAddresses(String host) {
75:    return approved.getOrDefault(host, List.of());
79:    approved.remove(host);
exit=0

$ grep -n 'resolver.forget' -B 3 adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/DefaultDynamicTargetGateway.java
118-        } finally {
119-          // Discarded at the end of the hop. Retaining it would grow without bound and, worse,
120-          // would let a later call reuse an approval that was only ever made for this one.
121:          resolver.forget(pinned.target().host());
exit=0

$ git grep -n 'approvedAddresses(' -- 'adapter/outbound/httpclient/src/main' 'app-bootstrap/src/main' | grep -v CallScopedDnsPin | grep -v PinnedTarget
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/dynamic/ValidatedDnsResolver.java:74:  public List<InetAddress> approvedAddresses(String host) {
exit=0

=== 8.2 전송이 핀을 통해 해석하는가 ===
$ grep -n 'CallScopedDnsPin::addressesFor\|ValidatedAddressResolverGroup' -r app-bootstrap/src/main adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient
app-bootstrap/src/main/java/dev/caskeleton/bootstrap/autoconfigure/httpclient/HttpClientTransportAutoConfiguration.java:81:    return Optional.of(CallScopedDnsPin::addressesFor);
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/reactor/ReactorHttpClientFactory.java:66:      AddressResolverGroup<?> resolver = new ValidatedAddressResolverGroup(approvedAddresses.get());
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/reactor/ValidatedAddressResolverGroup.java:24:public final class ValidatedAddressResolverGroup extends AddressResolverGroup<InetSocketAddress> {
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/reactor/ValidatedAddressResolverGroup.java:28:  public ValidatedAddressResolverGroup(Function<String, List<InetAddress>> approvedAddresses) {
exit=0

=== 8.3 관측 태그 폐쇄성 ===
$ grep -n 'Set.of\|reject\|ALLOWED' adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/observation/HttpClientTagPolicy.java | head -20
9: * <p>The policy rejects an unknown tag name instead of accepting it: a metric backend cannot undo a
15:  private static final Set<String> ALLOWED =
16:      Set.of(
39:    return ALLOWED;
43:    if (!ALLOWED.contains(name)) {
exit=0

$ grep -n 'query\|drop\|redact' adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/observation/SensitiveValueRedactor.java | head -12
11: * <p>Query values are dropped entirely rather than masked per key: an allowlist of "safe" query
44:  /** Returns the URI without userinfo, query, or fragment. */
exit=0

=== 8.4 아키텍처 test와 계약 lane ===
$ git ls-files 'adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/architecture' 'adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/contract' | xargs -n1 basename
HttpClientModuleBoundaryTest.java
PlatformClasses.java
PublicApiArchitectureTest.java
AllStableTransportsContractTest.java
FailureInjectionContractTest.java
NegotiatedProtocolContractTest.java
ResourceLifecycleContractTest.java
RetrySafetyContractTest.java
SecurityContractTest.java
StatefulUpstreamRetryContractTest.java
exit=0

$ git grep -h '  void [a-z]\|@Tag(' -- 'adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/architecture' 'adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/contract' | sed 's/^ *//' | sort -u | head -40
@Tag("httpclient-contract")
@Tag("httpclient-fault")
@Tag("httpclient-security")
@Tag("httpclient-spring62-surface")
void aResetPeerProducesStableEvidenceRatherThanAGenericFailure() throws Exception {
void absoluteUriIsRejectedOnEveryTransport(String transport) throws Exception {
void anApacheProfileCannotClaimHttp2() {
void connectionsSurviveErrorStatusDecodeFailureAndUnreadStreams() throws Exception {
void coreApiDependsOnNothingInsideThePlatform() {
void crossOriginRedirectDoesNotForwardCredentials() throws Exception {
void doesNotRetryANonIdempotentWriteAgainstTheSameStatefulUpstream() throws Exception {
void dynamicTargetsRejectEveryForbiddenAddressClass() {
void errorStatusMapsToTheSameStableException(String transport) throws Exception {
void everyDocumentedRetryCaseHoldsItsDecision() {
void everySelectedBlockingTransportRanEveryContract() {
void everySelectedReactiveTransportRanEveryContract() {
void everySelectedTransportIsClaimedByExactlyOneContainer() {
void honoursRetryAfterAndSucceedsOnTheSecondAttempt() throws Exception {
void methodAndTemplateEncodingIsIdentical(String transport) throws Exception {
void noProductionPackageDependsOnTheTestkit() {
void noPublicMethodHandsOutASpringHttpClient() {
void noPublicMethodReturnsANativeEngineClient() {
void notSentConnectFailureHasSameStableMetadata(String transport) {
void observationVocabularyRejectsHighCardinalityAndSecrets() {
void oversizedStreamingResponseIsRejected() throws Exception {
void profileDependsOnlyOnTheCoreApi() {
void publicApiDoesNotExposeNativeEnginesOrUnsafeBuilders() {
void recordedMetersCarryNoUrlOrCredential() throws Exception {
void replaysOnceAfterA401AndReResolvesTheCredential() throws Exception {
void resilienceOwnsRetryDecisionsWithoutDependingOnTransports() {
void springHttpClientsAreConfinedToTheirExecutionPackages() {
void stopsAtTheConfiguredAttemptCeilingAgainstAPermanentlyFailingUpstream() throws Exception {
void theApacheClassicClientCannotSpeakPriorKnowledgeH2c() throws Exception {
void theCoreApiCarriesNoMutableBuilderSurface() {
void theExperimentalHttp3PackageIsNotReferencedByStableCode() {
void theJdkTransportNegotiatesHttp2WhenTheProfileAsksForIt() throws Exception {
void theJdkTransportStaysOnHttp11WhenTheProfileSaysSo() throws Exception {
void theReactorTransportNegotiatesHttp2() throws Exception {
void theSelectedTransportSetIsExplicit() {
void theSpring7ServiceGroupApiIsUsedOnlyInItsOwnPackage() {
exit=0

