6.7 KiB
HTTP Client Canonical Zero-Binding Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use
superpowers:subagent-driven-developmentorsuperpowers:executing-plans. Repository policy overrides the skill's commit steps: do not stage, commit, amend, or push.
Goal: Make HTTP client activation an explicit canonical composition decision and prove that the default zero-binding state creates no client, executor, shutdown guard, retry/circuit-breaker registry, or transport resource.
Architecture: adapter:outbound:httpclient owns strict canonical configuration, immutable
binding/provider/catalog/readiness registries, and a pure activation resolver. app-bootstrap owns
the composition root that binds canonical properties and publishes an inert capability descriptor.
The existing JDK OutboundHttpClient remains an explicitly constructed R1 migration facade; its
legacy settings and infrastructure configuration must no longer be discovered automatically.
Scope boundary: This increment does not add Apache HC5, a provider factory, a real semantic
upstream binding, hard wire cancellation, TLS/DNS/proxy/auth, or an R2 readiness claim. Every current
ACTIVE selection must fail closed because the only derived readiness card remains
NOT_IMPLEMENTED.
Task 1: Add strict canonical selection and provider binding models
Files:
-
Create:
src/adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/activation/HttpClientExpectedState.java -
Create:
src/adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/activation/HttpClientCanonicalConfiguration.java -
Create:
src/adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/activation/HttpClientCanonicalConfigurationBinder.java -
Test:
src/adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/activation/HttpClientCanonicalConfigurationBinderTest.java -
Write RED tests for the canonical YAML shape under
ca-skeleton.capabilities.http-clientandca-skeleton.providers.http-client. -
Reject unknown fields, malformed IDs, unknown expected state, and any legacy input entering canonical composition, including the DISABLED state.
-
Preserve
OutboundHttpSettingsconstructors as migration API, but remove its global@ConfigurationPropertiesScanparticipation. -
Keep provider definitions inert data; configuration alone must not create a transport.
Task 2: Add catalog/readiness registries and pure fail-closed activation resolution
Files:
-
Create:
src/adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/activation/HttpOperationCatalogRegistry.java -
Create:
src/adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/activation/HttpClientReadinessCardRegistry.java -
Create:
src/adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/activation/ResolvedHttpClientCapability.java -
Create:
src/adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/activation/HttpClientActivationResolver.java -
Test:
src/adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/activation/HttpClientActivationResolverTest.java -
Prove
DISABLED + bindings 0 + provider definitions 0resolves toDISABLED_VERIFIED, selected binding/card count 0. -
Reject
DISABLEDwith bindings or provider resources. -
Reject
ACTIVEwith zero bindings. -
For every binding, require an exact provider, provider destination, and registered operation catalog for the same destination.
-
Derive the
httpclient-static-bufferedcard from each current buffered classic profile. -
Mark that card
NOT_IMPLEMENTED; reject ACTIVE before any provider resource/factory exists.
Task 3: Move HTTP Spring activation to the composition root
Files:
-
Modify:
src/adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/OutboundHttpClientConfig.java -
Modify:
src/adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/OutboundHttpSettings.java -
Modify:
src/adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/OutboundHttpResilienceConfig.java -
Create:
src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap/httpclient/HttpClientCompositionConfig.java -
Modify:
src/app-bootstrap/src/main/resources/application.yml -
Modify:
src/app-bootstrap/src/test/java/dev/caskeleton/adapter/outbound/OptionalAdapterBeanGatingTest.java -
Test:
src/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/httpclient/HttpClientCompositionConfigTest.java -
Detach legacy HTTP infrastructure from component/configuration-properties scanning while preserving direct constructors/factory methods used by forks and existing unit tests.
-
Register only canonical configuration, immutable registries, resolver, and inert descriptor in the composition root.
-
Default application YAML to canonical
expected-state: DISABLED, empty bindings, and empty provider definitions; keep legacy migration keys out of both main and test application YAML. -
Assert zero
OutboundHttpClient,RestClient,OutboundCallExecutor,OutboundHttpShutdownGuard,OutboundHttpResilience,RetryRegistry, andCircuitBreakerRegistrybeans/resources in the default context. -
Assert contradictory/ACTIVE configurations fail startup before resource construction.
-
Load the real
application.ymlin composition tests and prove ACTIVE reaches theNOT_IMPLEMENTEDreadiness card rather than a legacy conflict.
Task 4: Document exact readiness and verify
Files:
-
Modify:
src/adapter/outbound/httpclient/README.md -
Modify:
src/adapter/outbound/httpclient/CLAUDE.md -
Modify:
docs/superpowers/specs/2026-07-27-httpclient-production-capability-design.md -
Modify:
docs/superpowers/plans/2026-07-28-httpclient-production-capability-foundation.md -
Mark canonical zero-binding as implemented without marking HTTP R2 complete.
-
Keep HC5/provider resources/security/real-network qualification explicitly unimplemented.
-
Run focused tests:
cd src
./gradlew :adapter:outbound:httpclient:check --rerun-tasks --console=plain
./gradlew :app-bootstrap:check --rerun-tasks --console=plain
./gradlew :sample-portfolio:test --rerun-tasks --console=plain
./gradlew verifyCleanArchitectureDependencies verifyConfigurationPropertiesProcessor \
verifyEnvKeys verifyPublicPathSnapshot --console=plain
Do not edit unrelated notification, messaging, object-storage, JPA, MongoDB, GraphQL, gRPC, web, or WebSocket files.