# HTTP Client Canonical Zero-Binding Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use > `superpowers:subagent-driven-development` or `superpowers: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` - [x] Write RED tests for the canonical YAML shape under `ca-skeleton.capabilities.http-client` and `ca-skeleton.providers.http-client`. - [x] Reject unknown fields, malformed IDs, unknown expected state, and any legacy input entering canonical composition, including the DISABLED state. - [x] Preserve `OutboundHttpSettings` constructors as migration API, but remove its global `@ConfigurationPropertiesScan` participation. - [x] 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` - [x] Prove `DISABLED + bindings 0 + provider definitions 0` resolves to `DISABLED_VERIFIED`, selected binding/card count 0. - [x] Reject `DISABLED` with bindings or provider resources. - [x] Reject `ACTIVE` with zero bindings. - [x] For every binding, require an exact provider, provider destination, and registered operation catalog for the same destination. - [x] Derive the `httpclient-static-buffered` card from each current buffered classic profile. - [x] 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` - [x] Detach legacy HTTP infrastructure from component/configuration-properties scanning while preserving direct constructors/factory methods used by forks and existing unit tests. - [x] Register only canonical configuration, immutable registries, resolver, and inert descriptor in the composition root. - [x] 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. - [x] Assert zero `OutboundHttpClient`, `RestClient`, `OutboundCallExecutor`, `OutboundHttpShutdownGuard`, `OutboundHttpResilience`, `RetryRegistry`, and `CircuitBreakerRegistry` beans/resources in the default context. - [x] Assert contradictory/ACTIVE configurations fail startup before resource construction. - [x] Load the real `application.yml` in composition tests and prove ACTIVE reaches the `NOT_IMPLEMENTED` readiness 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` - [x] Mark canonical zero-binding as implemented without marking HTTP R2 complete. - [x] Keep HC5/provider resources/security/real-network qualification explicitly unimplemented. - [x] Run focused tests: ```bash 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.