121 lines
6.7 KiB
Markdown
121 lines
6.7 KiB
Markdown
# 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.
|