# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [1.0.0-rc.9] - 2026-11-08

### Added
- Extract H1 idle ownership and H2 reservation policy into the independent
  `http_pool` package. Add validated named runtime pool families, stable
  generation references, explicit Fetch selection and sanitized snapshots.
- Add caller-prepared Fetch adapters and the independent `http_test` package:
  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_data` export 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
  `versions` list 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/3` and
  `read_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](docs/tls-migration-plan.md)
and [validation ledger](docs/tls-migration-validation.md) 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](apps/ex_ssl/docs/COMPATIBILITY.md).
- Keep request completion and managed connection retirement tied to public
  `SSL.Lifecycle` evidence, including setup failure, cancellation and ownership
  transfer. Existing HTTP/3 completion remains `unsupported_completion`.

### Removed
- Remove the production OTP SSL transport and unconditional OTP SSL application
  dependencies. Explicit `tls_backend: :ssl` and `"ssl"` return a configuration
  error. The public `SSL` facade, `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.ProtocolClient` for 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: :infinity`
  and 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.HPACK` public 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 `:shutdown` to 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 `PROPFIND` and
  `REPORT`, 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 valid `Trailer` declarations. 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: :structured` and `HTTP.RequestError.pre_send?/1`
  evidence 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/1` and bounded
  `HTTP.RequestCompletion.await/2` / `abort_and_await/2` for 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: true` and 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_address` pins 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/2` for streamed request trailers.
- Provide acknowledged WebSocket writes with finite deadlines and document
  the public WebSocket client boundary for reverse proxies.
- Support `decode_body: false` to 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.md` and
  `docs/http3-implementation-audit.md`. HTTP/3 remains unsupported at this step.

## [0.16.1] - 2026-10-01

### Changed
- Remove the `elixir_quic_http3` sub-app after its migration to
  `gsmlg-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_runtime` as 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.md` for 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.md` for exact
  candidate provenance, outcomes, resource bounds and archived evidence.

## [0.15.0] - 2026-09-30

### Added
- Include `elixir_quic_http3` in 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.md` for 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.2` and `ex_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_core` dependency requirements to `~> 0.13.0`.
- Retain the ex_ssl `~> 0.4.0` integration from 0.12.0 without further runtime
  changes; OTP `:ssl` remains 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 `:ssl` as the default TCP TLS backend while allowing verified TLS
  1.3 or explicitly selected TLS 1.2 through the optional `:ex_ssl` backend.
  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 keeping `response.stream` as a compatibility alias.
- Added HTTP/1.1 streaming request uploads with `HTTP.Stream` bodies and
  `duplex: "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`, and
  `http_web_transport` umbrella apps with browser-like protocol APIs.
- Added e2e coverage for EventSource, WebSocket, and WebTransport workflows.

### Changed
- Extracted shared HTTP primitives into the `http_core` app so protocol apps
  share common code without depending on `http_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 `:httpc` compatibility option buckets from `HTTP.fetch/2`.
  Fetch init options are now flat, and redirects use `redirect: :follow | :manual | :error`.

### Fixed
- Validate response `Transfer-Encoding` framing instead of falling back to
  `Content-Length` for 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 `:httpc` with the internal socket transport while preserving the default
  redirect-following behavior; pass `autoredirect: false` to return redirect responses.
- Legacy `:httpc` options 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`, and `size` fields
- **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/1` instead 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/1` for 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`, and `blob/1`

### Notes
- This release prioritizes Browser Fetch API compatibility over Elixir-specific patterns
- The `body_used` field 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/3` method 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-Agent` header 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-Agent` headers when provided
- Added `HTTP.Headers.user_agent/0` method to access the default User-Agent string
- Added comprehensive `HTTP.Telemetry` module 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

### 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/3` for better extensibility

## [0.4.2] - 2025-08-01

### Added
- Added `HTTP.Response.write_to/2` method to write response bodies to files
  - Supports both streaming and non-streaming responses
  - Automatically creates directories if they don't exist
  - Returns `:ok` or `{: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/1` instead of `length/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-urlencoded` and `multipart/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: :binary` option 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/2` and `HTTP.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.Headers` struct
- **Enhanced type safety** with proper struct types throughout the codebase
- **Updated Response API** - Added `get_header/2` and `content_type/1` helper 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
