All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[1.0.0-rc.9] - 2026-11-08
Added
- Extract H1 idle ownership and H2 reservation policy into the independent
http_poolpackage. Add validated named runtime pool families, stable generation references, explicit Fetch selection and sanitized snapshots. - Add caller-prepared Fetch adapters and the independent
http_testpackage: owner-isolated expectations, Task/allowance propagation, retained exit verification, acknowledged streams, cancellation and an optional bounded Plug bridge. Unmatched fixtures fail without network fallback. - Include both packages in unified versions, dependency-ordered publication, CI impact selection and standalone candidate consumers with and without Plug.
[1.0.0-rc.8] - 2026-11-07
Fixed
- Complete authenticated TLS 1.2 full handshakes with legacy OTP servers that omit EMS, using the RFC 5246 master-secret derivation while preserving server trust, hostname, ECDHE signature, Finished, AEAD and downgrade checks (#157).
- Keep TLS 1.2 session retention, caching and
session_dataexport restricted to EMS connections. Reject an accepted EMS resumption without EMS; a declined session may take one fresh full handshake. Renegotiation and application key exporters remain unsupported.
[1.0.0-rc.7] - 2026-11-07
Fixed
- Normalize default ExSSL mixed-version offers to TLS 1.3 first for either public
versionslist order, matching OTP client behavior and avoiding unnecessary downgrade rejection against dual-version OTP servers. Preserve explicit WireProfile ordering, certificate verification and downgrade checks (#157). - Add OTP control coverage for ordinary TLS and in-memory RSA mTLS. TLS 1.2 still requires EMS; OTP servers that omit EMS remain unsupported, so #157's TLS 1.2-only acceptance remains blocked.
[1.0.0-rc.6] - 2026-11-07
Added
- Accept authenticated client NAT rebinding and IP migration on established Quic and Abyss server connections, preserving streams and operation handles. Bound path validation, amplification reservations, congestion/RTT controllers, and local/peer CID issuance and retirement. Report the server-only capability and public path/resource observations; local migration and 0-RTT remain deferred.
- Require pinned independent UDP port/IP migration, exact STREAM bytes/FIN, DATAGRAM continuity, wire CID separation, concurrent listener isolation and cleanup in source, candidate-package and published-package gates.
Fixed
- Let a bounded PTO probe retransmit retained reliable data when its path's congestion window is full. Keep original and probe bytes in flight, preserve the congestion window, and prevent queued application data or unreliable DATAGRAM payloads from spending the one-shot probe allowance.
[1.0.0-rc.5] - 2026-11-07
Added
- Expose opt-in QUIC DATAGRAM through
Abyss.QUIC.send_datagram/3andread_datagrams/3, with validated per-connection receive limits and handler readability events. Preserve engine negotiation, operation references, unreliable delivery and congestion/resource accounting. - Require independent aioquic DATAGRAM and reliable-stream traffic through Abyss in both candidate and published Hex server consumer gates.
[1.0.0-rc.4] - 2026-11-07
Fixed
- Scope CI Credo checks to their selected application and resolve imported server lint/type findings. Observe QUIC handshake expiry and Hell read timeout directly, and preserve legacy rebar3 installations in cold consumers.
Changed
- Require Elixir 1.18 and Erlang/OTP 27 or later for Abyss and abyss_raw; retire their unsupported imported minimum and validate both at the new floor.
- Coordinate Abyss, Hell and abyss_raw with the HTTP family at one RC/stable version. Publish eleven portable packages through the unified release and publish abyss_raw asynchronously after verified Abyss publication, with separate native acceptance and status.
- Keep the original nine-client/engine no-OTP-SSL verification scoped explicitly; Hell retains its OTP TLS transport and server ExSSL remains a future feature.
[1.0.0-rc.3] - 2026-11-06
Fixed
- Add request-local WebSocket connection addresses without changing Host or TLS identity, bounded handshake metadata on Open/Error, and independent frame and read-buffer receive limits across HTTP/1 and HTTP/2 (#152).
- Return the documented timeout tuple when a finite Promise wait expires, preserving the active request, its eventual result and explicit cleanup handle (#153).
[1.0.0-rc.2] - 2026-11-05
Fixed
- Preserve opaque TLS socket types across construction and nested-carrier operations, and reject malformed private carrier handles without stranding pending writes or their lifecycle permits.
- Resolve the configured Credo and Dialyzer findings while preserving TLS/QUIC validation, HTTP/2 delivery acknowledgments and primary connection errors.
[1.0.0-rc.1] - 2026-11-05
Fixed
- Reclaim managed request slots released during completion checks, preventing false request-capacity errors after confirmed cleanup (#151).
- Run current TLS benchmarks through ExSSL and keep OTP comparisons in an explicit historical runtime with separate source and build identities.
Documentation
- Align TLS guides with the ExSSL-only runtime and identify historical results, required performance coverage and remaining validation limits explicitly.
[1.0.0-rc.0] - 2026-11-02
The initial coordinated TLS migration release candidate is 1.0.0-rc.0.
Candidate production releases pass the supported traffic matrix with OTP SSL
unavailable. The release workflow also requires cold published consumers to
repeat the critical checks. See the
migration checklist
and validation ledger for executed gates.
Changed
- Use ExSSL by default for Fetch, EventSource, WebSocket and managed HTTP/1 and HTTP/2. HTTPS supports TLS 1.3 and the documented TLS 1.2 profile through one negotiation, with certificate verification enabled by default.
- Use ExSSL for HTTPS origins inside HTTPS proxy CONNECT tunnels, retaining separate origin/proxy verification and cleanup evidence for both TLS layers.
- Preserve ordinary verification callbacks, partial-chain trust, CRL/OCSP, encrypted private keys and multiple client identities within the documented TLS compatibility bounds.
- Keep request completion and managed connection retirement tied to public
SSL.Lifecycleevidence, including setup failure, cancellation and ownership transfer. Existing HTTP/3 completion remainsunsupported_completion.
Removed
- Remove the production OTP SSL transport and unconditional OTP SSL application
dependencies. Explicit
tls_backend: :ssland"ssl"return a configuration error. The publicSSLfacade,ssl:options and compatibility message names remain supported.
[0.21.19] - 2026-10-29
Fixed
- Retain HTTP/1 WebSocket transport references while draining buffered control frames after EOF, preventing nil-transport Close writes. Preserve delivery ACK backpressure without repeated reads, and finish failed protocol Close writes abnormally with their original error instead of leaving cleanup pending (#150).
[0.21.18] - 2026-10-27
Added
- Request-local HTTP/1 response head, field, count, informational-response and CONNECT budgets with structured, content-free limit errors (#145).
- Lazy fixed-length multipart envelopes with bounded regular-file reads and upload cancellation/source-finalization coverage (#146).
- Opt-in IPv6 preference with connection-only IPv4 fallback under one deadline, strict address/family pins and no retry after TLS or HTTP begins (#147).
- Public
HTTP.ProtocolClientfor retained cleartext HTTP/1 and HTTP/2 sessions, stream reset, explicit receive credit and live SETTINGS on one connection (#148). - Independently verified HTTPS origin TLS inside authenticated HTTPS proxy
CONNECT, including HTTP/1 and HTTP/2, isolated credentials and completion
accounting for both TLS layers. Nested routes require OTP
:ssl; ExSSL fails before dialing. Missing TLS setup handles retain unconfirmed cleanup (#149).
Fixed
- Serialize policy HTTP socket close with TLS retirement, preserving exact auxiliary cleanup evidence through cancellation and setup deadline races.
- Preserve HTTP/1 cancellation when a socket closes during active-once rearming after a fragmented response head, retaining actual cleanup confirmation.
- Normalize HTTP/3 owner deadline expiry to the public request timeout only after the total request deadline, preserving earlier operation failures.
- Preserve OTP OCSP and certificate callback error normalization when runtime values exceed upstream typespecs.
- Preserve opaque TLS/QUIC cleanup capabilities across module boundaries and declare accurate completion/transport contracts for strict Dialyzer checks.
- Make integration fixtures observe the matching transport, provider lifetime and pool notification, and bound TLS receive batches for blocked-write tests.
[0.21.17] - 2026-10-24
Added
- Support disabling QUIC local idle expiry with
idle_timeout: :infinityand bounded public PING admission for caller-managed keepalive. Preserve peer idle constraints and independent handshake, operation and closing bounds (#143).
[0.21.16] - 2026-10-22
Added
- Document the role-neutral
HTTP.HTTP2.HPACKpublic codec API, including stateful contexts, encoding policies, complete-block decoding limits and SETTINGS table-size coordination for client and server consumers (#141).
[0.21.15] - 2026-10-22
Fixed
- Preserve opaque request-completion types across the public Fetch and Promise APIs so consumer Fetch/await composition passes Dialyzer without suppressing opacity checks (#139).
[0.21.14] - 2026-10-19
Added
- Confirmed pre-HTTP TLS setup failure evidence for ordinary direct HTTP/1 structured requests after ServerHello, with tracked receiver/sender cleanup. Earlier or ambiguous TLS failures remain unconfirmed; caller-managed failover still requires successful completion and deadline/cancellation checks (#135).
Fixed
- Redact private WebSocket connection state, messages and errors from OTP
status and termination diagnostics. Normalize abnormal process exits and
cleanup failures to
:shutdownto suppress independent private crash reports while preserving normal transport processing (#136). - Report cleanup as unconfirmed when OTP TLS setup fails without returning a trackable TLS socket, including proxy and HTTP/2 setup. TCP closure or dial helper termination cannot certify the missing TLS receiver/sender cleanup (#135).
[0.21.13] - 2026-10-16
Added
- Per-request ordinary HTTP/1 response consumer delivery/acknowledgement deadlines,
including
:infinity, across both Stream and socket producer waits. Existing finite defaults, network idle policies, cancellation and total limits stay independent (#131).
Fixed
- Confirm fixed-length HTTP/1 upload source completion before exposing an immediate peer response, preserving enumerable resource finalization. Source failures and bounded completion expiry fail the request; genuinely early responses and cancellation retain bounded teardown (#132).
[0.21.12] - 2026-10-16
Added
- Per-request HTTP/1 response stream idle policy, including
:infinity, without changing global configuration or consumer acknowledgement safety. Response readers follow the policy; socket idle deadlines, cancellation and owned cleanup remain independent (#129).
[0.21.11] - 2026-10-15
Added
- Independent HTTP/1 read and write idle deadlines for TCP, OTP TLS and ExSSL, with positive millisecond options, direction-specific progress, typed timeout reasons and owned cleanup. Preserve total request/connect limits, cancellation and streaming backpressure; reject unsupported protocols and managed scopes explicitly (#126).
[0.21.10] - 2026-10-15
Fixed
- Preserve HTTP/1 cancellation when cleanup closes the socket during post-send activation or final send result delivery, retaining independent transport and protocol failures and the existing logical cleanup barrier (#122).
- Reject non-HTTP/1 textual response versions before accepting headers or bodies on OTP TLS and ex_ssl, preserving compatible HTTP/1 minor versions and closing rejected connections without replay or reuse (#121).
[0.21.9] - 2026-10-15
Fixed
- Support unlimited HTTP/1 request and connection timeouts without deadline arithmetic crashes. Preserve independent finite connection/request limits, streamed upload/download cancellation and owner cleanup.
[0.21.8] - 2026-10-14
Fixed
- Reject malformed HTTP/1 status lines and chunk syntax, conflicting response Transfer-Encoding/Content-Length, and oversized completed chunk lines while preserving valid extension grammar and connection cleanup without replay.
- Accept valid ASCII HTTP extension methods, including DAV
PROPFINDandREPORT, preserving binary method case, bodies and authorization without creating atoms from caller-supplied method strings. - Validate a certificate path ending at a supplied trust anchor when the peer includes trailing cross-signed alternatives. Preserve PKIX signatures, hostname, validity, depth and certificate-signature policy checks.
[0.21.7] - 2026-10-14
Fixed
- Observe connection worker exits and promptly return a sanitized connection failure instead of waiting for the connect timeout. Preserve socket cleanup, cancellation, subscriber death and finite deadlines during connection setup.
[0.21.6] - 2026-10-14
Added
- Accept the optional fixed
alpn_advertised_protocols: ["http/1.1"]policy for managed HTTP/1 OTP TLS scopes. Preserve the default without ALPN and reject conflicting protocol overrides.
Fixed
- Bound QUIC receive ACK history by retiring old ranges instead of closing active connections when historical packet-number gaps fill the range limit. Ignore duplicate and retired packets before applying stream or control effects, while preserving valid reordering and retransmissions with fresh packet numbers.
[0.21.5] - 2026-10-13
Fixed
- Make HTTP/3 Session uploads progress when peer stream or connection credit cannot admit a complete transport fragment. Split definitely blocked sends while preserving byte order, the terminal FIN and the original deadline; reconcile uncertain sends without replaying accepted data.
[0.21.4] - 2026-10-13
Fixed
- Send ordered, repeated HTTP/3 request trailers through
HTTP.Stream.finish/2, including zero-DATA uploads and validTrailerdeclarations. Trailing HEADERS finish the request exactly once; asynchronous failures, cancellation, finite deadlines and unknown-operation reconciliation retain their existing behavior. - Use a stable managed HTTP/1 response writer session with consumer-driven chunk acknowledgements instead of creating a stream monitor for every chunk. Retain uncertain chunk ownership after timeout, abort and deadline.
- Coalesce HTTP/1 pool expiration into a reference-matched maintenance timer while enforcing pending handoff and idle checkout deadlines independently. Validate handoff deadlines before tracker monitors are released; ignore stale scope reconciliation timers and wait for tracker termination on completion.
Documentation
- Record the pinned OTP managed-H1 control-accounting audit, workload/build manifest, proof gaps and empirical TLS stress evidence. These hardening changes do not certify native/deferred memory reclamation or a numerical activation budget. Issue #97 remains open; Gaoxy numerical managed production stays disabled.
[0.21.3] - 2026-10-11
Fixed
- Preserve the original streamed response failure during internal request cleanup, including HTTP/1 chunk-line and trailer parser errors. Late first readers can observe the terminal error; unread responses retain their request lease and keep completion pending until consumed or explicitly cancelled.
- Preserve abort and deadline errors for late readers of response streams from requests without a completion tracker, including default redirect-follow requests.
[0.21.2] - 2026-10-11
Fixed
- Track OTP 27 and OTP 28 TLS receiver and sender processes independently through connection setup, HTTP/1 reuse and HTTP/2 pool handoff. Retain managed connection capacity and retirement barriers until both processes terminate.
- Retire managed generations with unconfirmed cleanup when TLS setup returns no resource inventory or an unsupported socket representation. Preserve durable retirement receipts after the coordinator has terminated.
[0.21.1] - 2026-10-11
Fixed
- Bound HTTP/2 informational response notifications per request and coalesce pool capacity updates, preserving sibling streams and shared HPACK state. Compact retained header fragments, raw HPACK literals and frame remainders.
- Normalize managed request inputs into owned binaries, bound buffered iodata traversal, and charge generated HTTP/1 and HTTP/2 fields before admission.
- Own compact frozen TLS/socket policy binaries while preserving credential verification, policy identity and redacted status. Document retained payload, representation and preparation transient limits separately.
- Return the documented managed connection-capacity error while HTTP/2 connections drain, preserving completion, retirement and explicit replacement.
[0.21.0] - 2026-10-11
Added
- Add caller-owned managed HTTP/1 and HTTP/2 transport scopes with private pools, finite admission, frozen destination and TLS policy, bounded status, and durable graceful/abort retirement receipts. Keep request cleanup completion separate from whole-scope retirement. Managed scopes support direct TCP/OTP TLS, explicit protocols, and raw streamed responses with manual/error redirects; reject unsupported policies before dialing.
- Extend request completion to supported explicit HTTP/HTTPS proxy routes, including pending CONNECT/TLS, uploads, response streams, cancellation and safe pooled return. Preserve proxy identity and authentication isolation.
Fixed
- Limit each inbound HTTP/2 header block to 256 frames, including empty HEADERS/CONTINUATION and the final frame, and omit empty fragment storage. Reject excess fragmentation at connection scope while preserving separate connections and existing compressed-byte, HPACK and decoded-header limits.
[0.20.0] - 2026-10-10
Added
- Extend request cleanup completion to pooled HTTP/1 and explicit HTTP/2/h2c requests. Confirm safe HTTP/1 pool handoff or closure, and HTTP/2 stream, helper, delivery and reservation release without closing healthy siblings.
- Support bounded HTTP/2 upload trailers through
HTTP.Stream.finish/2, with ordered fields, shared HPACK encoding, atomic HEADERS/CONTINUATION writes, peer header-list limits and request-local validation failures. - Add opt-in
error_mode: :structuredandHTTP.RequestError.pre_send?/1evidence for confirmed failures before direct TCP establishment. Preserve raw errors by default and leave validated-address failover to the caller. - Support explicit HTTPS proxies for HTTP origins with verified proxy TLS, absolute-form HTTP/1 forwarding and isolated pooled connections. Reject HTTPS origins through HTTPS proxies before dialing; never fall back directly.
Fixed
- Stop caller upload streams and wake blocked producers on terminal request failures, including proxy and pooled-route failures before connection setup. Preserve successful header-first responses and early-response cleanup.
[0.19.1] - 2026-10-10
Fixed
- Preserve the
?delimiter for a present empty query in HTTP request targets, including streaming proxy-mode requests and HTTP proxy absolute-form targets.
[0.19.0] - 2026-10-10
Added
- Expose
HTTP.Promise.completion/1and boundedHTTP.RequestCompletion.await/2/abort_and_await/2for request-scoped cleanup confirmation on explicit HTTP/1 requests without connection reuse, using manual/error redirects and direct TCP or OTP TLS transport. - Distinguish confirmed cleanup, cleanup still pending at the caller's deadline, and cleanup whose completion cannot be confirmed. Preserve asynchronous AbortController cancellation and streaming Promise response behavior.
Fixed
- Abort the WebSocket transport when its owner exits during a blocked TLS write, and settle pending writes before stopping the connection.
[0.18.1] - 2026-10-10
Fixed
- Preserve the original IPv4/IPv6 certificate identity with ExSSL when upgrading HTTP proxy CONNECT tunnels or dialing a different pinned address.
- Allow an explicit ExSSL certificate reference identity independently of SNI while retaining mandatory peer verification and socket upgrade checks.
- Isolate TLS session tickets by both certificate reference identity and SNI.
- Retain SNI-derived certificate verification for ordinary ExSSL calls unless an explicit independent reference identity is supplied.
- Process already-delivered HTTP/1 WebSocket frames before finalizing TCP or TLS read termination; retain abnormal closure when no valid peer Close exists.
[0.18.0] - 2026-10-10
Added
- Return header-first Fetch responses with
stream_response: trueand retain acknowledged streaming backpressure and cancellation. - Preserve GET, HEAD and DELETE request bodies with
request_mode: :proxy; ordinary Fetch behavior remains the default. - Expose bounded HTTP/1 WebSocket proxy frames, acknowledged frame writes, configurable automatic pong and validated wire close codes.
- Support explicit HTTP proxies with absolute-form forwarding and HTTPS CONNECT tunnels, isolated proxy authorization and origin TLS verification.
- Add opt-in bounded HTTP/1 keep-alive reuse with route, TLS and caller isolation.
- Accept validated IPv4/IPv6
connect_addresspins while preserving original HTTP authority, TLS identity and trust. Require explicit redirect handling; reject unsupported proxy, Unix and HTTP/3 combinations before network I/O. ExSSL cannot yet verify a distinct original literal IP against a pinned address; this case rejects explicitly pending upstream issue #49.
Fixed
- Return consistent closed readiness errors when a QUIC connection exits normally during a call; retain timeouts and unexpected exit reasons.
Changed
- Update Dialyxir, Earmark Parser, Erlex, ExDoc, Jason, Makeup, Makeup Erlang and Telemetry to current compatible releases. Retain Credo 1.7.13 because newer releases report unrelated existing nesting violations.
- Verify candidate-package Telemetry archives against the version and checksum in the lockfile instead of a fixed historical version.
[0.17.2] - 2026-10-09
Added
- Expose bounded HTTP/1 request and response trailers, including
HTTP.Stream.finish/2for streamed request trailers. - Provide acknowledged WebSocket writes with finite deadlines and document the public WebSocket client boundary for reverse proxies.
- Support
decode_body: falseto preserve original response bytes across HTTP/1, HTTP/2 and HTTP/3, for both buffered and streamed responses.
Fixed
- Read HTTP/1 responses while streaming uploads are backpressured; stop unfinished uploads on early final responses and bound cancellation for plain TCP, OTP TLS and ExSSL without replaying uncertain writes.
- Remove credentials and nested request secrets from Fetch telemetry by default and honor per-request and global telemetry opt-outs.
- Validate WebSocket handshakes and clean up blocked writes on cancellation, deadlines and owner loss, including verified secure connections.
[0.17.1] - 2026-10-09
Fixed
- Preserve declared Content-Length for streaming HTTP/1 and HTTP/2 uploads, reject length mismatches, and retain producer backpressure and cancellation.
- Transparently decode gzip and zlib-wrapped deflate response Content-Encoding for buffered and streamed Fetch consumers across HTTP/1, HTTP/2, and HTTP/3; preserve archive bytes when Content-Encoding is absent.
- Strip URL credentials from every WebSocket telemetry event and support omitting or explicitly replacing telemetry URLs without changing handshakes.
- Correct migration provenance to describe the available synchronized Hex graph.
[0.17.0] - 2026-10-06
Added
- Preserve bounded, ordered HTTP/2 informational responses and separate buffered and streamed trailers through the existing response and stream APIs.
- Gate shared transport and tooling changes against affected Fetch, EventSource and WebSocket consumers, with independent peer traffic and package evidence.
- Document the scoped HTTP/2 beta support contract and rollout/rollback runbook.
Fixed
- Bound reusable automatic HTTPS negotiation before dialing, settle HTTP/1.1 fallback claims, and clean up admission on cancellation, deadlines and exit.
- Honor peer stream capacity after the single initial automatic H2 reservation, including zero capacity and saturated admission queues.
Validation
- Frozen HTTP/2 candidate passed all 78 acceptance gates, both genuine
30-minute soaks, automatic CI and full CI/Test/E2E. Retain measured resources,
package checksums, rejected attempts and limits in
docs/http2-beta-validation.md.
[0.16.7] - 2026-10-06
Added
- Report HTTP/3 beta and static/literal QPACK capabilities in the companion; keep raw QUIC HTTP/3 and deferred application features unsupported.
- Require digest-pinned Caddy and aioquic public acceptance, isolated candidate and published Hex traffic, negative TLS checks, and retained peer diagnostics in coordinated releases.
- Add the scoped 24-hour canary with explicit cleanup, memory, mailbox, process, endpoint and error thresholds, as separate asynchronous validation against the release tag and published packages; interrupted pre-release evidence is retained without claiming a completed 24-hour pass.
Fixed
- Transfer owner-proven unopened requests at concurrent lifetime rotation using their original deadlines and untouched bodies; sent or unknown admissions retain their original reconciliation path.
[0.16.6] - 2026-10-05
Added
- Enable strict, verified HTTP/3 Fetch with binary and streamed uploads, process-backed downloads, abort and total-deadline handling.
- Expose actual network protocol in Response and request-stop telemetry; retain bounded informational fields and expose buffered/streamed trailers.
- Add explicit HTTP/3 EventSource with acknowledged deliveries, cursor-aware reconnect, secure readiness, redirects and native error classification.
Fixed
- Remove known-unsent queued requests promptly on abort or subscriber death; preserve reconciliation for already-pending native operations.
- Reject streamed-body redirect replay and cross-origin client-identity reuse.
Validation
- Native public API regressions and pinned independent aioquic/Caddy public integrity, TLS negatives, multiplexing, SSE and connection-rotation evidence. Final required CI/artifact/canary acceptance is recorded separately in WP5.
[0.16.5] - 2026-10-05
Added
- Supervised HTTP/3 owners, bounded leases and request relays, demand-driven body bridges, safe connection identity, GOAWAY draining and lifetime rotation.
- Bounded receive credit for 32 concurrent streams, with explicit validation of owned and borrowed endpoints and isolation for paused consumers.
Fixed
- Accept valid QUIC NEW_TOKEN frames and authenticated RFC 9001 peer key updates, preserving reordered previous-phase packets and rejecting invalid transitions.
- Install production dependencies before each staged Hex publication and verify the prepared package still rebuilds to the audited archive bytes.
- Move the HTTP/3 facade into runtime and declare its companion dependency in source, CI closures, portable packages and isolated consumers.
Validation
- Native and pinned aioquic runtime integrity, concurrency, backpressure and cleanup gates; authenticated stock Caddy binary POST interoperability. Public Fetch HTTP/3 remains unsupported until WP4.
[0.16.4] - 2026-10-05
Fixed
- Frame binary and demand-driven uploads as HTTP/3 DATA, retain blocked work without freezing sibling reads, and retire completed requests exactly once.
- Decode responses incrementally with separate header and retained-byte limits, informational/final/trailer validation, critical streams, and GOAWAY admission.
- Correct all 99 QPACK static indexes and preserve indexed/literal field order.
- Use uv to install the release peer dependencies in its Python environment.
Validation
- Native adapter regressions and a pinned independent aioquic binary echo gate. Public Fetch HTTP/3 remains unsupported pending runtime integration.
[0.16.3] - 2026-10-05
Fixed
- Compose HTTP/3 sessions with native QUIC generations, authenticated H3 readiness, consistent stream handles, retained operation references, and explicit endpoint ownership and terminal teardown.
- Preserve cancellation isolation and reconcile ambiguous admission without replaying request bytes or destructive reads.
- Repair the baseline ServerHello Dialyzer warning without changing GREASE handling, and make release tests independent of the prepared patch version.
Validation
- WP1 native-contract seams and local UDP session tests; public Fetch HTTP/3 remains unsupported until the runtime and independent acceptance gates.
[0.16.2] - 2026-10-05
Fixed
- Restore Fetch's test dependency in isolated WebSocket and EventSource CI jobs.
- Inspect candidate Hex archives in memory using Hex's supported unpack mode.
Validation
- WP0 baseline restoration; see
docs/http3-wp0-baseline.mdanddocs/http3-implementation-audit.md. HTTP/3 remains unsupported at this step.
[0.16.1] - 2026-10-01
Changed
- Remove the
elixir_quic_http3sub-app after its migration togsmlg-dev/ex_quic, including unused dependencies from Fetch and WebTransport. - Update six-package CI, release, and consumer tooling and current documentation to reflect the new ownership boundary. HTTP/3 and WebTransport selectors remain explicitly unsupported pending integration and interoperability work.
Fixed
- Keep isolated package consumers on explicit shared local dependency overrides after removing the migrated package.
[0.16.0] - 2026-10-01
Added
- Extract
http_runtimeas the shared, independently installable HTTP/2 owner, pool and stream application used by Fetch, EventSource and WebSocket. - Add explicitly selected HTTP/2/h2c EventSource and RFC 8441 WebSocket support, acknowledged delivery, finite parsing/send/delivery bounds and actual-version accessors. Preserve HTTP/1 defaults and explicit TLS backend selection.
- Add independent SSE/WebSocket/mixed peers, standalone package traffic gates and a reproducible final acceptance entrypoint with original Fetch42 workloads.
Fixed
- Preserve ordinary Fetch early-response upload cleanup while accepted CONNECT tunnels remain duplex; gate admission on peer capability without blocking ordinary siblings or consuming stream capacity while waiting.
- Settle logical stream resources on close, owner death, reset and runtime restart, retain accepted bytes before terminal errors, and stop parsing after an internal WebSocket terminal failure.
- Mask WebSocket payloads using binary words to avoid per-byte list heap growth.
Validation
- See
docs/http2-stream-clients-validation.mdfor exact phase/final-candidate results, source and artifact checksums, backend/peer matrices and resource observations. Short runner checks are explicitly distinct from 30-minute soaks.
[0.15.1] - 2026-09-30
Fixed
- Stop abandoned HTTP/2 uploads atomically after final response headers, retain incomplete response bodies and trailers, and close unfinished request halves before releasing peer capacity without replaying upload DATA.
- Promote queued, never-sent requests when connection capacity becomes available, including owner shutdown, draining, cross-origin capacity release, and a saturated surviving sibling, while preserving deadlines and connection limits.
- Preserve sibling upload scheduling when an already-stopped stream is removed again during cleanup.
Validation
- Add deterministic wire-level early-response, queued-admission, lifecycle and package-consumer regressions with explicit event barriers.
- Complete all 42 local HTTP/2 acceptance gates, including both independent peers,
supported transports, 10-MiB transfers, 10,000-request reuse workloads and a
full 30-minute mixed soak. See
docs/http2-production-validation.mdfor exact candidate provenance, outcomes, resource bounds and archived evidence.
[0.15.0] - 2026-09-30
Added
- Include
elixir_quic_http3in the coordinated six-package release, with versioned HTTP/3 dependencies for Fetch and WebTransport and standalone package-consumer validation.
Changed
- Route explicit HTTP/2 and h2c requests through supervised, profile-aware pooled owners, including requests without an explicit wire profile.
- Reclaim completed protocol streams; slice binary and streaming uploads by available peer credit; bound download admission and return stream credit on consumption.
- Validate frame boundaries, response phases and lengths, HPACK table updates, and peer settings; preserve typed reset/GOAWAY outcomes and original deadlines.
- Advertise no server push in wire-profile revision 2, with cold/warm header ordering applied once. Keep synthetic profiles explicitly synthetic.
- Add redacted connection/pool telemetry and independent peer/package/soak gates.
Known limitations
- HTTP/2 production acceptance remains in progress; see
docs/http2-production-validation.mdfor failing or unrun blocking gates.
[0.14.0] - 2026-09-29
Added
- Add an internal authenticated QUIC client adapter with bounded stream I/O, cancellation, operation outcome tracking, and lifecycle validation.
- Add published TLS consumer provenance and independent resumption coverage for HTTP/1.1, HTTP/2, WebSocket, and EventSource.
- Add validated versioned HTTP/2 wire profiles, ordered serialization controls, pure connection/stream state models, and bounded redacted fingerprint observations.
- Add flat HTTP/2 profile, reuse, scope, and priority option validation.
- Add bounded PRIORITY_UPDATE handling, upload credit recovery after WINDOW_UPDATE, peer MAX_FRAME_SIZE DATA fragmentation, and capture provenance manifest validation.
Changed
- Use Hex
elixir_quic ~> 0.2.2andex_ssl ~> 0.7.2, with no runtime Git pins. - Preserve OTP TLS defaults and existing production HTTP/3/WebTransport paths.
Known limitations
- The new adapter does not implement HTTP/3 sessions or QPACK. The Abyss joint raw-stream test awaits its published-engine namespace migration (abyss #5).
- Full drain-deadline policy, broader independent mature-implementation interoperability, and captured browser-profile verification remain pending. Profiled h2c and HTTPS h2 pooling support overlapping socket streams while preserving TLS/profile identity isolation.
[0.13.0] - 2026-09-22
Changed
- Publish all five packages at the shared 0.13.0 version and update their
internal
http_coredependency requirements to~> 0.13.0. - Retain the ex_ssl
~> 0.4.0integration from 0.12.0 without further runtime changes; OTP:sslremains the default TLS backend.
[0.12.0] - 2026-09-22
Added
- Add verified ex_ssl 0.4.0 TLS 1.2 support across Fetch, HTTP/2, WebSocket, and EventSource, and opt-in TLS 1.3 ticket resumption over fresh HTTP/1.1 connections. The default remains verified TLS 1.3 with tickets disabled.
- Forward validated ex_ssl client identities, TCP socket options, and ordered TLS 1.3 algorithm preferences. Pin client identities to the redirect origin.
Changed
- Keep OTP
:sslas the default TCP TLS backend while allowing verified TLS 1.3 or explicitly selected TLS 1.2 through the optional:ex_sslbackend. HTTP/3 and WebTransport continue to use QUIC's independent TLS implementation. - Run individual app tests and E2E suites from the umbrella root after explicit test-environment preparation, so transitive runtime applications are compiled and on the code path even on cold checkouts.
- Validate all five built packages in an isolated external consumer, including transitive dependencies and verified local TLS requests.
Fixed
- Deliver complete HTTP/2 responses when the peer closes immediately after an
END_STREAM DATA frame and a non-essential WINDOW_UPDATE or acknowledgement
returns
:closed. Incomplete responses and required request writes before response completion still fail normally. - Preserve unread ex_ssl TLS records when an HTTP/2 control write fails after normal peer closure. Drain them through the existing active-once receiver and require a complete HTTP/2 response, without extending deadlines or accepting truncated responses, error resets, or protocol errors.
- Preserve valid HTTP/2 early final responses while cancelling remaining upload DATA, including queued DATA released by WINDOW_UPDATE. Accept NO_ERROR resets only after response completion; require END_STREAM and a complete field block even for responses with no body.
- Enforce HTTP/2 response Content-Length and bounded frame/header parsing while preserving valid cross-record and streaming completion after peer closure.
[0.11.0] - 2026-07-04
Added
- Added Fetch-style streaming response bodies by exposing the stream PID in
response.body, while keepingresponse.streamas a compatibility alias. - Added HTTP/1.1 streaming request uploads with
HTTP.Streambodies andduplex: "half"chunked request framing.
Changed
- Updated response helpers, docs, and e2e coverage for the new streamed body shape.
- Return explicit unsupported errors for streaming request bodies on HTTP/2 and HTTP/3 instead of buffering or misframing them.
[0.10.0] - 2026-07-01
Added
- Added independent
http_web_socket,http_event_source, andhttp_web_transportumbrella apps with browser-like protocol APIs. - Added e2e coverage for EventSource, WebSocket, and WebTransport workflows.
Changed
- Extracted shared HTTP primitives into the
http_coreapp so protocol apps share common code without depending onhttp_fetch. - Updated CI, test, e2e, and release workflows to cover every umbrella app and publish all packages with one shared version.
[0.9.1] - 2026-06-23
Changed
- Removed legacy
:httpccompatibility option buckets fromHTTP.fetch/2. Fetch init options are now flat, and redirects useredirect: :follow | :manual | :error.
Fixed
- Validate response
Transfer-Encodingframing instead of falling back toContent-Lengthfor unsupported transfer codings. - Keep completed empty streams readable for late consumers.
- Make the Unix socket e2e coverage independent of a host Docker daemon.
- Align release metadata, README examples, and project guidance with the socket transport.
[0.9.0] - 2026-06-17
Changed
- Replaced
:httpcwith the internal socket transport while preserving the default redirect-following behavior; passautoredirect: falseto return redirect responses. - Legacy
:httpcoptions that are not implemented by the socket transport are documented as compatibility-only options.
[0.7.0] - 2025-01-XX
Added - Browser Fetch API Compatibility (~85% API Parity)
- HTTP.StatusText module - Maps HTTP status codes to standard status text messages (60+ codes)
- Response.status_text - Status message property (e.g., "OK", "Not Found")
- Response.ok - Boolean property indicating success (true for 200-299 status codes)
- Response.body_used - Tracks body consumption (field exists for API compatibility)
- Response.redirected - Indicates if response was redirected
- Response.type - Response type (
:basic,:cors,:error,:opaque) - Response.new/1 - Constructor helper that auto-populates Browser API fields
- Response.clone/1 - Clone response for multiple reads (buffers streaming responses)
- Response.arrayBuffer/1 - Read body as binary (ArrayBuffer equivalent)
- Response.array_buffer/1 - Snake_case alias for arrayBuffer
- HTTP.Blob module - Blob struct with
data,type, andsizefields - Response.blob/1 - Read body as Blob with metadata (extracts MIME type from headers)
- Comprehensive Browser API compatibility documentation in README
- 41 new tests covering all Browser Fetch API features
Changed - Breaking Changes for Browser API Compatibility
- Response struct fields added:
status_text,ok,body_used,redirected,type- Migration: Update pattern matches to ignore new fields or use variable binding
- Example:
%Response{status: 200} = response(ignores new fields)
- Response construction: All internal Response creation now uses
Response.new/1- Ensures consistent Browser API field population
- Migration: Use
Response.new/1instead of direct%Response{}for consistency
- body_used field: Present for Browser API compatibility but doesn't enforce in Elixir
- Due to Elixir's immutability, multiple reads of the same response value work
- Use
clone/1for clarity when reading multiple times
Documentation
- Added "Browser Fetch API Compatibility" section to README with examples
- Documented Elixir-specific differences (immutability, synchronous returns, streams)
- Updated all Response documentation to reflect new Browser API properties
- Added comprehensive examples for
clone/1,arrayBuffer/1, andblob/1
Notes
- This release prioritizes Browser Fetch API compatibility over Elixir-specific patterns
- The
body_usedfield exists for API compatibility but cannot prevent multiple reads due to immutability - All critical Browser Fetch API Response properties and methods are now supported
[0.5.0] - 2025-08-01
Added
- HTTP.Telemetry module - Complete telemetry integration for HTTP request monitoring
- Request lifecycle events with rich metadata
- Response body reading events for tracking download progress
- Streaming events for real-time data transfer monitoring
- Zero configuration integration with Elixir's :telemetry library
Changed
- Updated default User-Agent string format to include library version 0.5.0
- Enhanced telemetry event metadata with improved error reporting
[0.4.3] - 2025-08-01
Added
- Added
HTTP.Headers.set_default/3method to set headers only if they don't already exist- Uses case-insensitive header name matching
- Preserves existing headers when they already contain the specified name
- Added automatic default
User-Agentheader to all HTTP requests- Format:
Mozilla/5.0 (macOS; aarch64-apple-darwin24.3.0) OTP/27 BEAM/15.2.3 Elixir/1.18.3 http_fetch/0.4.3 - Includes OS information, system architecture, OTP version, BEAM version, Elixir version, and library version
- Uses dynamic version detection via
Application.spec(:http_fetch, :vsn) - Preserves custom
User-Agentheaders when provided
- Format:
- Added
HTTP.Headers.user_agent/0method to access the default User-Agent string - Added comprehensive
HTTP.Telemetrymodule for HTTP request metrics and monitoring- Request lifecycle events:
[:http_fetch, :request, :start],[:http_fetch, :request, :stop],[:http_fetch, :request, :exception] - Response body reading events:
[:http_fetch, :response, :body_read_start],[:http_fetch, :response, :body_read_stop] - Streaming events:
[:http_fetch, :streaming, :start],[:http_fetch, :streaming, :chunk],[:http_fetch, :streaming, :stop] - Rich metadata: Includes URLs, HTTP status codes, response sizes, durations, and error reasons
- Automatic integration: All HTTP.fetch operations automatically emit telemetry events
- Zero configuration: Works out of the box with Elixir's :telemetry library
- Request lifecycle events:
Changed
- Enhanced User-Agent string to include system architecture information
- Refactored User-Agent generation for consistency across the codebase
- Updated default headers handling to use
set_default/3for better extensibility
[0.4.2] - 2025-08-01
Added
- Added
HTTP.Response.write_to/2method to write response bodies to files- Supports both streaming and non-streaming responses
- Automatically creates directories if they don't exist
- Returns
:okor{:error, reason}for proper error handling
Fixed
- Fixed streaming implementation message format for complete responses
- Increased streaming threshold from 100KB to 5MB to prevent issues with large files
- Fixed test assertion for content-length comparison using
byte_size/1instead oflength/1
Changed
- Updated streaming threshold to prevent streaming for files under 5MB
- Improved streaming process error handling
[0.4.1] - 2025-07-31
Added
- URI struct support - HTTP.fetch/2 now accepts both string URLs and %URI{} structs
- Enhanced URL handling - Automatic conversion from string to %URI{} for internal processing
- Type safety improvements - HTTP.Request and HTTP.Response now use %URI{} internally
- Improved Request field naming - More intuitive field names for :httpc.request mapping
Changed
- Refactored URL handling - All internal representations now use %URI{} instead of string
Updated type specifications - HTTP.Request.url type changed from String.t() | charlist() to URI.t()
- Updated Response.url type - Changed from String.t() to URI.t()
- Updated function signatures - handle_httpc_response and related functions now accept URI.t()
- HTTP.Request field renaming for better clarity:
options→http_options(3rd argument to :httpc.request)opts→options(4th argument to :httpc.request)
Technical Details
- Backward compatibility - String URLs are automatically parsed to URI structs
- Consistent URI handling - All internal operations use parsed URI structs
- Eliminated redundant parsing - Removed duplicate URI.parse calls in streaming functions
- Enhanced type safety - Stronger typing throughout the codebase
- Updated test suite - Request tests updated to use URI.parse/1 for consistency
- Improved field documentation - Clear mapping to :httpc.request arguments
[0.4.0] - 2025-07-30
Added
- HTTP.FetchOptions module - New dedicated module for processing fetch options with full httpc support
- Enhanced option handling - Support for all :httpc.request options including timeout, SSL, streaming, etc.
- Multiple input formats - Accept keyword lists, maps, or HTTP.FetchOptions struct
- Complete httpc integration - Proper separation of HttpOptions and Options for :httpc.request
- Type-safe configuration - Structured approach to HTTP request configuration
- Comprehensive option coverage - All documented :httpc.request options supported
- HTTP.FormData module - New dedicated module for handling form data and multipart/form-data encoding
- File upload support - Support for file uploads with streaming via
File.Stream.t() - Automatic content type detection - Automatically chooses between
application/x-www-form-urlencodedandmultipart/form-data - Streaming file uploads - Efficient large file uploads using Elixir streams
- Form data builder API - Fluent interface with
new/0,append_field/3,append_file/4-5 - Multipart boundary generation - Automatic random boundary generation for multipart requests
- Comprehensive test coverage - Full test suite for form data and fetch options functionality
Changed
- HTTP.fetch refactored - Now uses HTTP.FetchOptions for consistent option processing
- HTTP.Request body parameter - Now accepts
HTTP.FormData.t()for form submissions - Enhanced content type handling - Automatic content-type detection and header setting
- Improved multipart encoding - Proper multipart/form-data format with boundaries
- Unified configuration API - All configuration goes through HTTP.FetchOptions
Technical Details
- HTTP.FetchOptions struct with comprehensive field support for all httpc options
- FormData struct with parts array for form fields and file uploads
- Streaming support via
File.Stream.t()for memory-efficient file uploads - URL encoding fallback for simple form data without file uploads
- Backward compatibility maintained for existing string/charlist body usage
[0.3.0] - 2025-07-30
Fixed
- HTTP option placement - Fixed
body_format: :binaryoption being passed to wrong :httpc argument - Eliminated warning messages - Removed "Invalid option {body_format,binary} ignored" notices during tests
- Improved error handling - Enhanced response handling for malformed URLs and network errors
Technical Details
- Corrected httpc arguments - Proper separation of request options vs client options
- Cleaned up streaming setup - Removed redundant option configurations
- Enhanced test reliability - Reduced external dependency flakiness
[0.2.0] - 2025-07-30
Added
- HTTP.Headers module - New dedicated module for HTTP header processing
- Structured headers - HTTP.Request and HTTP.Response now use
HTTP.Headers.t()struct - Header manipulation utilities -
new/1,get/2,set/3,merge/2,delete/2, etc. - Header parsing - Content-Type parsing with media type and parameters extraction
- Case-insensitive header access via
HTTP.Headers.get/2andHTTP.Response.get_header/2 - Backward compatibility - HTTP.fetch still accepts list/map formats with auto-conversion
Changed
- Refactored header storage from plain lists to
HTTP.Headersstruct - Enhanced type safety with proper struct types throughout the codebase
- Updated Response API - Added
get_header/2andcontent_type/1helper methods
Technical Details
- New HTTP.Headers struct with comprehensive header manipulation capabilities
- Immutable operations - All header operations return new struct instances
- Automatic conversion - Input formats (list/map) auto-converted to struct
- Enhanced documentation with examples for new header functionality
- Maintained backward compatibility - Existing code continues to work
[0.1.0] - 2025-07-30
Added
- Initial project setup with Mix
- Basic project structure and configuration
- Core HTTP fetch functionality
- Response and Request struct definitions
- Promise implementation for async operations
- AbortController for request cancellation
- Comprehensive test coverage
- Documentation and README