You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Three HTTP-client capabilities are intentionally absent from the toolkit, but nothing in docs/product-spec.md records that they are deliberate. A reader surveying the surface can reasonably read each absence as an oversight rather than a decision:
RFC 9111 response cache. There is no response cache anywhere in core. sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/common/ETag.kt and sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/common/RequestConditions.kt are pure RFC 7232 header helpers — ETag models the ETag/If-Match/If-None-Match value forms, and RequestConditions.applyTo writes the conditional headers onto a Headers.Builder. Neither carries any storage, freshness, or revalidation logic.
Cookie jar / session cookies. There is no CookieJar, CookieStore, or CookieHandler type in the SDK. The OkHttp builder's build() (sdk-transport-okhttp/.../OkHttpTransport.kt:496) never installs a cookieJar, so the SDK-managed client keeps OkHttp's CookieJar.NO_COOKIES default; the JDK transport builder never installs a CookieHandler and names it a BYO-only knob (sdk-transport-jdkhttp/.../JdkHttpTransport.kt:371).
Connection-pool / keep-alive sizing. Both transport builders expose timeouts, proxy, and redirect handling, but neither exposes pool sizing. The OkHttp builder KDoc already directs pool sizing to a BYO client (sdk-transport-okhttp/.../OkHttpTransport.kt:391-395, "connection pool sizing"), and java.net.http.HttpClient.Builder has no pool-sizing knob at all.
This is a documentation-only task. The proposal is to state all three as explicit non-goals with their bring-your-own escape hatches; it does not propose building any of them.
Rationale
The SDK is a platform — a core HTTP-client toolkit consumed by generated service clients, downstream SDKs, and application code — so the boundary of what the toolkit does and does not own is itself part of the contract. When that boundary is left implicit, an external consumer cannot distinguish "we decided not to own this, here is where it lives instead" from "this was forgotten." Writing these down as non-goals turns each gap into a documented seam the consumer can plan around.
Each of the three belongs above core, or in a BYO client, for a platform-specific reason:
Response cache. A conformant RFC 9111 cache needs transport-specific persistent storage and revalidation state. Pulling that into core would break the near-zero-dependency guarantee that SEAM-1 / NFR-1 encode: core MUST NOT carry a runtime dependency on any concrete transport, serialization library, I/O implementation, or async framework, and a persistent cache store is exactly such a dependency. If a cache is wanted, it belongs in the transport: a BYO OkHttpClient configured with an okhttp3.Cache works today, because OkHttpTransport.close() is ownership-aware and closes the response cache only for SDK-created clients (OkHttpTransport.kt:352, client.cache?.close(), reached only after the !owned early return) while leaving a caller-supplied client untouched (TRANSPORT-15, XCUT-22).
Cookie jar. Stateful session management is application/session policy, not wire plumbing — it belongs one layer up (the generated client or the application), where the session lifecycle actually lives. The redirect step passes the origin-scoped Cookie header through on a same-origin hop (REDIR-10) and strips it only on a cross-origin redirect (sdk-core/.../http/pipeline/steps/DefaultRedirectStep.kt:283, REDIR-9 / XCUT-17) for credential hygiene — that is hygiene, not cookie storage.
Pool sizing. This is genuinely native-client-specific. OkHttp exposes a ConnectionPool; java.net.http.HttpClient.Builder exposes nothing equivalent. A cross-transport pool-sizing surface in core would be a leaky lowest-common-denominator abstraction that could not be honored uniformly, so it stays BYO on the native client.
Documenting these keeps the platform honest about its edges without weakening SEAM-1 / NFR-1.
Proposed change
Add a capability non-goals subsection to docs/product-spec.md. §1 already carries a Non-goals of this specification paragraph (line 13) that scopes what the document prescribes (language, framework, codegen, and so on); this new subsection is distinct — it records capabilities the toolkit deliberately does not build — so place it adjacent to that paragraph under §1 Product Overview (line 15), or under §17 Transport Adapter Conformance Contract (line 795), whichever the maintainer prefers for discoverability. Anchor the response-cache entry to §4.6 Conditional-request helpers (line 154), where ETag/RequestConditions are already specified. For each capability, state (a) that it is a deliberate non-goal, (b) the platform reason it is out of core, and (c) the BYO escape hatch:
Response caching (RFC 9111): not provided; ETag/RequestConditions are RFC 7232 header helpers only. Escape hatch: a BYO OkHttpClient with an okhttp3.Cache, whose lifecycle stays with the caller (TRANSPORT-15, XCUT-22).
Cookie jar / session cookies: no CookieJar/CookieStore/CookieHandler; OkHttp keeps NO_COOKIES, the JDK transport installs no CookieHandler. Stateful cookies belong to the generated client / application; the redirect step's cross-origin Cookie stripping is hygiene, not storage.
Connection-pool / keep-alive sizing: not exposed by either transport builder; keep it BYO on the native client because it is native-specific (OkHttp ConnectionPool; the JDK builder has no pool config).
Add a one-line BYO note about cookies to the OkHttp transport, alongside the existing BYO guidance in the Builder KDoc (OkHttpTransport.kt:391-395), so the cookie non-goal is discoverable from the code, matching how connection-pool sizing is already handled there.
Acceptance criteria
docs/product-spec.md gains a capability non-goals subsection that names all three capabilities as deliberate non-goals, each with its rationale and BYO escape hatch as above, and that is clearly distinct from the existing document-scope Non-goals of this specification paragraph.
The response-cache entry references the RFC 7232 nature of ETag/RequestConditions and the okhttp3.Cache + ownership-aware-close escape hatch, and cites SEAM-1/NFR-1 for why a cache stays out of core.
The cookie entry notes the OkHttp NO_COOKIES default and the absent JDK CookieHandler, points session management one layer up, and references the redirect step's cross-origin Cookie stripping (REDIR-9/XCUT-17) as hygiene rather than storage.
The pool-sizing entry explains the leaky lowest-common-denominator problem (OkHttp has a pool, the JDK builder does not) and keeps it BYO.
The OkHttp Builder KDoc mentions cookies among the BYO-only concerns.
No production/runtime code implements caching, a cookie jar, or a pool-sizing surface as part of this change.
References
sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/common/ETag.kt — RFC 7232 ETag/If-Match/If-None-Match helper; no storage/revalidation.
sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/common/RequestConditions.kt — RFC 7232 conditional-request headers (applyTo writes them onto a Headers.Builder); no cache logic.
sdk-transport-okhttp/src/main/kotlin/org/dexpace/sdk/transport/okhttp/OkHttpTransport.kt:496 — build() never installs a cookieJar (keeps OkHttp NO_COOKIES).
sdk-transport-okhttp/src/main/kotlin/org/dexpace/sdk/transport/okhttp/OkHttpTransport.kt:391-395 — Builder KDoc directs connection-pool sizing (and other unmapped knobs) to a BYO OkHttpClient.
sdk-transport-okhttp/src/main/kotlin/org/dexpace/sdk/transport/okhttp/OkHttpTransport.kt:352 — ownership-aware close() calls client.cache?.close() only for SDK-owned clients (guarded by the !owned early return).
sdk-transport-jdkhttp/src/main/kotlin/org/dexpace/sdk/transport/jdkhttp/JdkHttpTransport.kt:371 — Builder KDoc names the cookie handler a BYO-only concern; no CookieHandler is installed.
sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/pipeline/steps/DefaultRedirectStep.kt:283 — strips the Cookie header on a cross-origin redirect.
docs/product-spec.md — SEAM-1 (MUST, near-zero-dep core), NFR-1 (MUST, no concrete runtime deps in core), NFR-2 (SHOULD, adapter = core + at most one third-party lib), TRANSPORT-15 / XCUT-22 (MUST, ownership-aware close; BYO resources never closed), REDIR-9 / XCUT-17 (MUST, cross-origin Cookie/Proxy-Authorization stripping), REDIR-10 (SHOULD, same-origin Cookie retained). §1 Product Overview (line 15), §4.6 Conditional-request helpers (line 154), §17 Transport Adapter Conformance Contract (line 795).
Summary
Three HTTP-client capabilities are intentionally absent from the toolkit, but nothing in
docs/product-spec.mdrecords that they are deliberate. A reader surveying the surface can reasonably read each absence as an oversight rather than a decision:sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/common/ETag.ktandsdk-core/src/main/kotlin/org/dexpace/sdk/core/http/common/RequestConditions.ktare pure RFC 7232 header helpers —ETagmodels theETag/If-Match/If-None-Matchvalue forms, andRequestConditions.applyTowrites the conditional headers onto aHeaders.Builder. Neither carries any storage, freshness, or revalidation logic.CookieJar,CookieStore, orCookieHandlertype in the SDK. The OkHttp builder'sbuild()(sdk-transport-okhttp/.../OkHttpTransport.kt:496) never installs acookieJar, so the SDK-managed client keeps OkHttp'sCookieJar.NO_COOKIESdefault; the JDK transport builder never installs aCookieHandlerand names it a BYO-only knob (sdk-transport-jdkhttp/.../JdkHttpTransport.kt:371).sdk-transport-okhttp/.../OkHttpTransport.kt:391-395, "connection pool sizing"), andjava.net.http.HttpClient.Builderhas no pool-sizing knob at all.This is a documentation-only task. The proposal is to state all three as explicit non-goals with their bring-your-own escape hatches; it does not propose building any of them.
Rationale
The SDK is a platform — a core HTTP-client toolkit consumed by generated service clients, downstream SDKs, and application code — so the boundary of what the toolkit does and does not own is itself part of the contract. When that boundary is left implicit, an external consumer cannot distinguish "we decided not to own this, here is where it lives instead" from "this was forgotten." Writing these down as non-goals turns each gap into a documented seam the consumer can plan around.
Each of the three belongs above core, or in a BYO client, for a platform-specific reason:
OkHttpClientconfigured with anokhttp3.Cacheworks today, becauseOkHttpTransport.close()is ownership-aware and closes the response cache only for SDK-created clients (OkHttpTransport.kt:352,client.cache?.close(), reached only after the!ownedearly return) while leaving a caller-supplied client untouched (TRANSPORT-15, XCUT-22).Cookieheader through on a same-origin hop (REDIR-10) and strips it only on a cross-origin redirect (sdk-core/.../http/pipeline/steps/DefaultRedirectStep.kt:283, REDIR-9 / XCUT-17) for credential hygiene — that is hygiene, not cookie storage.ConnectionPool;java.net.http.HttpClient.Builderexposes nothing equivalent. A cross-transport pool-sizing surface in core would be a leaky lowest-common-denominator abstraction that could not be honored uniformly, so it stays BYO on the native client.Documenting these keeps the platform honest about its edges without weakening SEAM-1 / NFR-1.
Proposed change
docs/product-spec.md. §1 already carries a Non-goals of this specification paragraph (line 13) that scopes what the document prescribes (language, framework, codegen, and so on); this new subsection is distinct — it records capabilities the toolkit deliberately does not build — so place it adjacent to that paragraph under §1 Product Overview (line 15), or under §17 Transport Adapter Conformance Contract (line 795), whichever the maintainer prefers for discoverability. Anchor the response-cache entry to §4.6 Conditional-request helpers (line 154), whereETag/RequestConditionsare already specified. For each capability, state (a) that it is a deliberate non-goal, (b) the platform reason it is out of core, and (c) the BYO escape hatch:ETag/RequestConditionsare RFC 7232 header helpers only. Escape hatch: a BYOOkHttpClientwith anokhttp3.Cache, whose lifecycle stays with the caller (TRANSPORT-15, XCUT-22).CookieJar/CookieStore/CookieHandler; OkHttp keepsNO_COOKIES, the JDK transport installs noCookieHandler. Stateful cookies belong to the generated client / application; the redirect step's cross-originCookiestripping is hygiene, not storage.ConnectionPool; the JDK builder has no pool config).BuilderKDoc (OkHttpTransport.kt:391-395), so the cookie non-goal is discoverable from the code, matching how connection-pool sizing is already handled there.Acceptance criteria
docs/product-spec.mdgains a capability non-goals subsection that names all three capabilities as deliberate non-goals, each with its rationale and BYO escape hatch as above, and that is clearly distinct from the existing document-scope Non-goals of this specification paragraph.ETag/RequestConditionsand theokhttp3.Cache+ ownership-aware-close escape hatch, and cites SEAM-1/NFR-1 for why a cache stays out of core.NO_COOKIESdefault and the absent JDKCookieHandler, points session management one layer up, and references the redirect step's cross-originCookiestripping (REDIR-9/XCUT-17) as hygiene rather than storage.BuilderKDoc mentions cookies among the BYO-only concerns.References
sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/common/ETag.kt— RFC 7232ETag/If-Match/If-None-Matchhelper; no storage/revalidation.sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/common/RequestConditions.kt— RFC 7232 conditional-request headers (applyTowrites them onto aHeaders.Builder); no cache logic.sdk-transport-okhttp/src/main/kotlin/org/dexpace/sdk/transport/okhttp/OkHttpTransport.kt:496—build()never installs acookieJar(keeps OkHttpNO_COOKIES).sdk-transport-okhttp/src/main/kotlin/org/dexpace/sdk/transport/okhttp/OkHttpTransport.kt:391-395—BuilderKDoc directs connection-pool sizing (and other unmapped knobs) to a BYOOkHttpClient.sdk-transport-okhttp/src/main/kotlin/org/dexpace/sdk/transport/okhttp/OkHttpTransport.kt:352— ownership-awareclose()callsclient.cache?.close()only for SDK-owned clients (guarded by the!ownedearly return).sdk-transport-jdkhttp/src/main/kotlin/org/dexpace/sdk/transport/jdkhttp/JdkHttpTransport.kt:371—BuilderKDoc names the cookie handler a BYO-only concern; noCookieHandleris installed.sdk-core/src/main/kotlin/org/dexpace/sdk/core/http/pipeline/steps/DefaultRedirectStep.kt:283— strips theCookieheader on a cross-origin redirect.docs/product-spec.md— SEAM-1 (MUST, near-zero-dep core), NFR-1 (MUST, no concrete runtime deps in core), NFR-2 (SHOULD, adapter = core + at most one third-party lib), TRANSPORT-15 / XCUT-22 (MUST, ownership-aware close; BYO resources never closed), REDIR-9 / XCUT-17 (MUST, cross-originCookie/Proxy-Authorizationstripping), REDIR-10 (SHOULD, same-originCookieretained). §1 Product Overview (line 15), §4.6 Conditional-request helpers (line 154), §17 Transport Adapter Conformance Contract (line 795).