Skip to content

10. Revision Candidates (Not A Contract)

Common contract table of contents

The items in this chapter aren't a contract. They aren't an implementation basis, and once promotion is decided, they move to that chapter's contract body and the 5 languages are updated together (the README change procedure).

ID Title Motivation To Decide
R1 Expose the error body on typed failure submit<T>() discards the response body at status ≥ 400, requiring a submitRaw() workaround to read the API error payload — a practical pitfall The form that carries status+headers+raw body in the failure value (an exception field vs. a failure envelope), the 5-language expression
R3′ The total retry deadline option (R3's backoff+jitter was promoted and completed on 2026-07-12 — Chapter 6 §6.2) A total deadline spanning the whole retry is still not in the contract (only cpp enforces a total budget on both paths — a language deviation) Whether to introduce a total deadline option (e.g. totalTimeout), the direction for unifying with the cpp deviation
R4 multipart binary file multipartFile's content is a string, so binary upload isn't possible Adding a byte-argument overload vs. a file-path argument, the 5-language signature
R5 Deeper kotlin coroutine work Cancellation doesn't propagate to the underlying request, streaming is only a callback sink (no Flow), java's blocking fetch and kotlin's suspend fetch share a name The suspendCancellableCoroutine propagation scope, whether to add a Flow<ByteArray> download, cleaning up the fetch naming
R7 Reconsidering the one-shot verb path one-shot builds/tears down the transport stack per request (dotnet recreates the handler → socket exhaustion risk). This path is also why the 7 client/builder verbs are duplicated Keep + document a warning vs. reuse an internal shared transport vs. remove
R8 Switching cpp to true async I/O The current approach offloads sync Beast to a thread pool (sync-over-threadpool) — a worker is occupied for the whole request duration and the default scheduler is serial Scope/schedule of a Beast async-exchange switch (large), relationship with a short-term mitigation (splitting thread count/scheduler)
R9 Unifying the request cancellation surface Only dotnet takes a CancellationToken; cpp/java/node have no means to cancel an in-flight request (timeout is the only boundary). Same root as kotlin's non-propagated cancellation (R5) Scope of exposing a language-idiomatic cancellation means (node AbortSignal, java future cancel, cpp cancellation token), the error kind on cancel
R10 An observability hook (interceptor) With no request/response interceptor, there's no place to hook token refresh, common logging, zlink flow-tracing header propagation, or metrics. The biggest unification gap with the framework core (message-flow tracing) Hook point (before request/after response/on failure), signature, the flow-correlation header standard
R11 Multi-value response header Since the response header is map<string,string>, a repeated same name (Set-Cookie, etc.) collapses. The cookie jar handles it internally, but a raw consumer loses information Extending the headers type (adding a multi-value accessor vs. changing the map type — compatibility), the 5-language expression
R12 Making the streaming surface language-idiomatic The download sink/upload provider is a sync callback — no backpressure, inconsistent with language idiom (node async iterator, dotnet IAsyncEnumerable, kotlin Flow). A generalization of R5 Whether to keep the callback in parallel, the per-language idiomatic type mapping, the cpp counterpart
R13 A hosting/DI integration helper With no ASP.NET Core DI, NestJS module, or Spring bean registration helper, there's no touchpoint with the framework hosting guide flow. It's natural for the DI container to manage the client lifetime rule (§2.4) A separate package vs. inclusion in the core, per-language scope (dotnet/node first), the configuration binding form
R14 A conditional-polling terminal (poll) There's demand for "repeat at interval X, up to N times/period T until the response satisfies a condition," such as waiting for job completion or checking status. Unconditional repetition (loop) is a scheduling concern and defaults to being outside the transport contract, but can be subsumed as a special form of poll The terminal signature (condition predicate/interval/bound), the return form (final response vs. history), the boundary with retry (Chapter 6), whether cancellation (R9) must precede it, whether to include unconditional repetition

Don't grow the columns of this table to record a registration/ promotion history — leave it in the plan (in progress) or commit message. Removed numbers: R2 (timeout DeadlineExceeded), R3 (backoff+jitter), and R6 (header casing) were promoted to the contract body (Chapter 6 §6.2 / Chapter 4 §4.3) and removed. R3's remaining issue is split out as R3′.