# 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).

## [0.5.0] - 2026-05-26

### Added

- **Websocket-attached TUI for headless mode** ([#67](https://github.com/mjc/nntp-proxy/pull/67))
  - Added a headless dashboard publisher via `--tui-listen IP:PORT` and a read-only attached TUI client via `--tui-attach IP:PORT`.
  - Attached dashboards reconnect automatically, keep the last good snapshot on disconnect, and show proxy CPU/memory alongside local TUI CPU/memory.
  - Dashboard publish/attach mode is intended for localhost-only use and should not be exposed directly to a network. It uses a redacted dashboard payload instead of exposing full backend configuration.

- **RFC 8054 backend wire compression** ([#53](https://github.com/mjc/nntp-proxy/pull/53))
  - Added `COMPRESS DEFLATE` negotiation for proxy-to-backend links with configurable compression mode and level.
  - Backend responses can now be transparently compressed without changing client-side NNTP behavior.

- **TCP command pipelining** ([#55](https://github.com/mjc/nntp-proxy/pull/55))
  - Added backend pipeline workers and batched `ARTICLE`/`BODY`/`STAT`/`HEAD` execution to reduce round trips for sequential article fetches.
  - Added queued pipeline routing and leftover-response handling for pipelined backend connections.

- **Persistent proxy/TUI metrics** ([#57](https://github.com/mjc/nntp-proxy/pull/57))
  - Added versioned JSON metrics persistence and restore via `[proxy].stats_file` so cumulative dashboard stats survive restarts.

- **Typed request pipeline and availability-only cache index** ([#60](https://github.com/mjc/nntp-proxy/pull/60))
  - Added `RequestContext`-based request handling so validated request metadata can flow through routing, batching, cache lookup, and metrics without rebuilding ad-hoc command buffers.
  - Added a compact persisted availability-only index so exact 430 knowledge can be retained without storing article bodies.

- **NixOS flake module and package derivation**
  - Added `nixosModules.default` / `nixosModules.nntp-proxy` for declarative `services.nntp-proxy` deployments.
  - The module can render config from `services.nntp-proxy.settings`, use an existing `configFile`, open the listener firewall port, manage writable stats/cache paths, and pass a runtime `credentialsFile` overlay for secrets.
  - Added a shared Nix package derivation and TUI attach wrapper so flake packages and the NixOS module use the same packaged runtime.

### Changed

- **Breaking: article-body caching now defaults off**
  - `[cache].store_article_bodies` now defaults to `false`; backend availability is still tracked in the availability index.
  - Existing deployments with a `[cache]` section that omitted `store_article_bodies` will switch from full article-body caching to availability-only tracking after upgrade.
  - Operators who rely on memory or disk article-body cache hits should set `store_article_bodies = true` explicitly. `[cache.disk]` only stores article bodies when body caching is enabled.

- **Near-complete internal rewrite since 0.4.0**
  - Rebuilt the proxy internals around typed request contexts, request-scoped response metadata, explicit cache metadata, backend pipeline queues, framer-owned multiline response handling, pooled-buffer forwarding, persisted metrics, persisted availability state, and config migration helpers.
  - The public goal is still the same NNTP proxy, but the routing, caching, response forwarding, connection lifecycle, persistence, dashboard/runtime, and operator-facing configuration paths are substantially new compared to 0.4.0.

- **Configuration and CLI naming refresh**
  - Reorganized config around `[routing]`, `[memory]`, `[cache]`, and `[health_check]` with clearer canonical names such as `article_cache_capacity`, `article_cache_ttl_secs`, and `store_article_bodies`.
  - Config loading now migrates older layouts in place and CLI parsing keeps legacy flag aliases for compatibility.

- **Runtime binary presentation**
  - Current docs and release packaging describe a single `nntp-proxy` executable with selectable dashboard/headless UI behavior.
  - Historical entries below still mention older separate binaries where that reflected the release at the time.

- **Disk cache compression configuration** ([#56](https://github.com/mjc/nntp-proxy/pull/56))
  - Disk cache compression is now a selectable codec (`lz4`, `zstd`, or `none`) instead of a boolean toggle.

- **Typed cache and routing internals** ([#60](https://github.com/mjc/nntp-proxy/pull/60))
  - Reworked cache lookup, cache upsert, pipeline completion, backend response accounting, and metrics recording around typed request and cache metadata.
  - Reworked cache response generation and ingestion to use borrowed bytes and typed cache parts, reducing copying on cache hits.

- **Response forwarding and framing ownership** ([#69](https://github.com/mjc/nntp-proxy/pull/69), [#71](https://github.com/mjc/nntp-proxy/pull/71))
  - Reworked ARTICLE/BODY/HEAD forwarding around range-backed response views, framer-owned multiline response emission, and borrowed direct response writes.
  - Centralized multiline response boundary handling in `MultilineFramer` so callers no longer need to reason about terminator offsets or suffix bytes.
  - Reworked pooled response buffers and scratch buffers so large pass-through responses can stay on the borrowed-buffer path instead of being flattened into owned response objects.

### Fixed

- **Oversized article cache-retention handling**
  - Full article/body/head cache retention now stops owning payload data once a response exceeds the cache section size limit, streams the response through to the client, and skips cache insertion for that response.
  - Disk-cache section encoding now rejects sections above the same limit during writes as well as reads.

- **Article retry fallback behavior** ([#67](https://github.com/mjc/nntp-proxy/pull/67))
  - `ARTICLE`/`BODY` requests that are already known missing across eligible backends now return `430` instead of disconnecting the client.
  - This also fixes the pipelined batch path so cached-missing article requests fail with protocol responses instead of dropping the session.

- **Dashboard startup and connection handling** ([#67](https://github.com/mjc/nntp-proxy/pull/67))
  - Dashboard listener bind failures now fail startup clearly instead of leaving the proxy running without the requested dashboard endpoint.
  - Remote dashboard publishing and attach handling were hardened around shutdown, reconnects, and listener/test race conditions.

- **Backend connection state and multiline response framing** ([#58](https://github.com/mjc/nntp-proxy/pull/58), [#59](https://github.com/mjc/nntp-proxy/pull/59))
  - Fixed pooled-connection read-ahead handling so bytes past `\r\n.\r\n` are preserved for the next response instead of desynchronizing reused backend connections.
  - Direct per-command multiline responses are now fully buffered and terminator-validated before being forwarded, preventing partial-response corruption.

- **RFC 3977 / RFC 4643 protocol compliance**
  - Fixed greeting and authentication behavior to return RFC-correct `201`, `482`, `502`, and `501` responses where appropriate.
  - Added `MODE READER` negotiation support and return `503` for unsupported commands that must be rejected explicitly.

- **Retry and recovery behavior** ([#52](https://github.com/mjc/nntp-proxy/pull/52), [#57](https://github.com/mjc/nntp-proxy/pull/57))
  - Added jittered retry backoff for stale pooled connections to avoid synchronized retry storms after backend disruption.
  - Improved connection draining, health checks, and graceful-shutdown timeouts so broken or half-read connections are less likely to be reused.

- **Typed request/cache correctness** ([#60](https://github.com/mjc/nntp-proxy/pull/60))
  - Fixed availability-only 430 retention so missing-article knowledge can be reused without a cached payload.
  - Tightened message-ID routing to require a single exact validated token and restored multiline fallback for unknown extension commands.
  - Routed full-buffer multiline terminator detection through `MultilineFramer` and guarded availability bit generation with `BackendId::availability_bit()`.

- **Large-transfer forwarding, retry cleanup, and remote TUI history** ([#68](https://github.com/mjc/nntp-proxy/pull/68), [#71](https://github.com/mjc/nntp-proxy/pull/71))
  - Restored shared large-transfer pipelining and stabilized pipelined response forwarding.
  - Fixed ordered retry cleanup accounting and tightened connection retirement/state tracking around backend lifecycle transitions.
  - Fixed remote TUI startup and graph history so attached clients accumulate their own history instead of depending on server-side graph state.

### Performance

- **End-to-end proxy-in-the-middle matrix baseline**
  - Ran current 100GiB cache-miss e2e spot checks with `nntpbench` client -> `nntp-proxy` -> `nntpbench` server.
  - On a Ryzen 9 5950X, direct upstream measured 11307.07 MiB/s. Proxy `1/1/1` measured 4712.73 MiB/s mean over 10 runs, and proxy `4/8/8` measured 10019.26 MiB/s mean over 10 runs.
  - On an Apple M1 with 16 GiB RAM, direct upstream measured 7557.08 MiB/s. Proxy `1/1/1` measured 3208.73 MiB/s mean over 10 runs, and proxy `4/8/8` measured 3856.64 MiB/s mean over 10 runs.
  - Ran current 10GiB default matrices across 112 points (`threads=1 2 4 8`, `backend_connections=1 2 4 8 16 32 64`, `clients=1 4 8 16`, client threads fixed at 4, pipeline depth fixed at 32). On a Ryzen 9 5950X, the best point was 11004.94 MiB/s at `8/8/4`; the best one-proxy-thread row was 6235.59 MiB/s at `1/2/16`. On an Apple M1 with 16 GiB RAM and OS-default Darwin socket buffers, the best point was 6004.22 MiB/s at `2/2/4`; the best one-proxy-thread row was 5404.49 MiB/s at `1/2/16`.
  - Made the release cache-miss benchmark harness pick Darwin-safe socket-buffer defaults and allow client, upstream, and proxy socket buffer sizes to be overridden independently.

- **Major large-article throughput and CPU-efficiency improvement since 0.4.0**
  - The proxy hot path was rebuilt around byte-oriented typed requests, request-scoped response metadata, pooled buffers, and cache responses that can be written without flattening payloads into temporary `Vec`s.
  - Current cached-response writer benches generate ARTICLE hits in 94.23 ns mean, with HEAD/BODY/STAT derived hits all under 80 ns mean.
  - Current single-connection local socket benches measured 366.6 MB/s mean for 788 KiB memory-cache hits and 349.9 MB/s mean for metadata-only cache misses.
  - The most important path is large article cache-miss handling, where the proxy still has to route the request, read the backend multiline response, validate framing, update cache/availability metadata, and stream the response back to the client.
  - Single-connection local socket roundtrip benches measured backend roundtrip at 350.2 MB/s for 788 KiB articles and 596.5 MB/s for 1536 KiB articles; memory-cache hits measured 366.6 MB/s and 694.0 MB/s for those same sizes.
  - Large sequential article fetches benefit most from backend command pipelining, response batching, fewer request re-parses, fewer atomics per request, and reduced connection churn.

- **Cache-hit and cache-miss hot paths rewritten** ([#60](https://github.com/mjc/nntp-proxy/pull/60), [#61](https://github.com/mjc/nntp-proxy/pull/61))
  - Cache entries now carry typed status, payload-shape, response-length, backend, tier, and availability metadata so routing, cache lookup, metrics, and response generation do not rediscover the same facts repeatedly.
  - Cache-hit serving now uses borrowed payload sections, vectored writes, boxed/shared slices, typed wire lengths, and request-kind-aware response rendering to avoid avoidable allocations and copies.
  - Cache-miss and ingestion paths now parse chunked backend responses directly from bytes, hand off owned multiline chunks where useful, avoid scratch-buffer zero-fill, and avoid redundant availability and TTL bookkeeping.

- **Pipeline, routing, and backend I/O reductions** ([#55](https://github.com/mjc/nntp-proxy/pull/55), [#58](https://github.com/mjc/nntp-proxy/pull/58), [#60](https://github.com/mjc/nntp-proxy/pull/60))
  - Added backend pipeline workers and FIFO completion queues so sequential `ARTICLE`/`BODY`/`HEAD`/`STAT` requests can be batched while preserving client response order.
  - Coalesced typed request writes, reused response buffers, pooled capture/scratch buffers, reduced repeated message-ID wrapping, and skipped unnecessary timing reads on untimed backend paths.
  - Cache-hit profiling drove vectored response writes: the 64 KiB native cache-hit sample improved from about 34.1 us / 1.92 GiB/s to about 28.3 us / 2.32 GiB/s after coalescing cached response writes, before later cache-hit refinements.
  - Reworked terminator scanning around the multiline framing path, `memmem`, and dot-first scans so multiline response validation is both safer and cheaper.

- **Borrowed forwarding and buffer-pool reductions** ([#69](https://github.com/mjc/nntp-proxy/pull/69), [#71](https://github.com/mjc/nntp-proxy/pull/71))
  - Added range-backed forwarding so response slices can reference pooled read buffers without materializing a full owned response.
  - Reduced direct-response and ordered-response allocations, tuned pooled buffer handling, read pooled buffers without a `Take` adapter, and made buffer pools lazy.
  - Added fast `perf.data` parser tooling and refreshed benchmark documentation for the large cache-miss path.

- **Disk-cache and availability-index performance**
  - Tuned foyer disk-cache behavior with higher parallelism, better block sizing, direct cache-entry construction on precheck paths, configurable compression codecs, and cold invalidation of old disk formats.
  - Added a compact availability-only negative index so known missing articles can be retained without storing article bodies or repeatedly querying every backend.
  - Added adaptive availability sharding and guarded sync paths so availability persistence work is skipped when there is nothing meaningful to write.

- **Benchmark coverage and measurement cleanup** ([#60](https://github.com/mjc/nntp-proxy/pull/60), [#61](https://github.com/mjc/nntp-proxy/pull/61))
  - Added or refreshed benchmark suites for request parsing/serialization, cache ingest, cache lookup, cache response generation, router selection, end-to-end proxy behavior, streaming round-trips, and multiline-framing boundary handling.
  - Added realistic article-size cases, drained end-to-end response reads, cache-miss metadata-only cases, and in-memory streaming round-trip benchmarks.
  - Corrected the cache-miss callgrind harness so instruction-count comparisons reflect normal benchmark setup.

### Testing

- Expanded regression coverage for pipelining, leftover-response handling, terminator detection, config migration, typed request parsing, availability-only caching, and RFC 3977 / RFC 4643 compliance.

### Docs

- Rewrote `README.md` and refreshed example configs to match the current routing, cache, memory, and health-check layout, including canonical config names and availability-only cache behavior.
- Added updated performance notes documenting the cache hot path and current benchmark methodology.

## [0.4.0] - 2026-01-27

### Added

- **Backend Server Tiering** ([#48](https://github.com/mjc/nntp-proxy/pull/48))
  - Servers can be assigned tier levels (0=primary, higher=backup/archive)
  - Tier-aware selection ensures lower-tier backends are prioritized for article requests
  - Configuration via file-based `tier = N` or environment `NNTP_SERVER_N_TIER=N`
  - Backwards compatible: servers without tier assignment default to tier 0

- **Tier-Aware Cache TTL** ([#48](https://github.com/mjc/nntp-proxy/pull/48))
  - Exponential TTL scaling: `effective_ttl = base_ttl * 2^tier`
  - Higher-tier backends (backups/archives) get exponentially longer cache retention
  - Dramatically reduces expensive queries to slow backup servers
  - Examples with 1-hour base TTL:
    - Tier 0 (primary): 1 hour
    - Tier 5 (backup): 32 hours (~1.3 days)
    - Tier 10 (archive): 1024 hours (~42.7 days)
    - Tier 15: ~1365 days (~3.7 years)

- **Hybrid Disk Cache** ([#47](https://github.com/mjc/nntp-proxy/pull/47))
  - New two-tier cache: memory + disk backing using foyer
  - Memory tier for hot articles, disk tier for larger capacity
  - Automatic LRU promotion for frequently accessed disk entries
  - LZ4 compression reduces disk usage by ~60%
  - Configuration via `[cache.disk]` section with path and capacity

- **Adaptive Precheck for STAT/HEAD** ([#46](https://github.com/mjc/nntp-proxy/pull/46))
  - Concurrent backend queries for STAT/HEAD commands
  - Returns first successful response immediately
  - Background task updates full backend availability
  - Reduces latency for article metadata lookups

### Changed

- **⚠️ Breaking: Default Backend Selection Strategy** ([#47](https://github.com/mjc/nntp-proxy/pull/47))
  - Default changed from `WeightedRoundRobin` to `LeastLoaded`
  - Existing deployments relying on previous default should explicitly set `backend_selection = "WeightedRoundRobin"` in config

- **Metrics Always Enabled** ([#47](https://github.com/mjc/nntp-proxy/pull/47)) - Metrics collection is no longer optional for better observability

- **⚠️ Breaking: Disk Cache Format** ([#48](https://github.com/mjc/nntp-proxy/pull/48)) - Existing disk cache will be discarded on upgrade due to format changes for tier-aware TTL

- **Release Binary Optimization** - Enabled aggressive binary size optimizations (strip, LTO, single codegen-unit) reducing release artifacts by ~90% (4.5-4.9M vs 41-43M). Release builds now take ~10x longer due to full LTO, but significantly faster downloads and lower disk usage for deployments.

### Fixed

- **Windows Cross-Compilation with TUI** - Fixed build failures when cross-compiling for Windows from non-Windows hosts. The TUI binary's dependencies (ratatui, crossterm, sysinfo) pull windows-sys 0.61+ which requires Windows library stubs during cross-compilation. Now properly links against mingw-w64 libraries from nixpkgs in the flake-based build environment.
- **Stale Connection Handling** ([#46](https://github.com/mjc/nntp-proxy/pull/46)) - Fixed "overnight 430" bug where pooled connections become stale after idle periods, causing false article-not-found errors
- **Critical Pending Count Leak** - Fixed pending request count not being properly decremented in precheck path
- **Precheck Performance** - Fixed precheck stalling at 53k cache entries by using atomic moka APIs
- **Disk Cache Errors** - Improved error messages and handling for disk full scenarios

## [0.3.0] - 2025-11-21

### Added

- **Terminal User Interface (TUI)** ([#38](https://github.com/mjc/nntp-proxy/pull/38), [#40](https://github.com/mjc/nntp-proxy/pull/40))
  - New `nntp-proxy-tui` binary with real-time monitoring dashboard
  - Live metrics: connections, throughput, backend health, user activity
  - System resource monitoring: CPU usage, memory usage, peak tracking
  - Interactive log viewer with fullscreen mode ('L' hotkey)
  - Per-user statistics tracking with article counts
  - Per-backend statistics with load balancing visualization
  - Connection statistics and pool utilization graphs
  - Built with ratatui for responsive terminal UI

- **Comprehensive Metrics System**
  - Lock-free metrics collection using DashMap for zero-allocation recording
  - Modular metrics architecture: `MetricsCollector`, `MetricsSnapshot`
  - Backend statistics: bytes transferred, command counts, error tracking
  - User statistics: active users, commands per user, article tracking
  - Connection statistics: pool utilization, connection lifecycle tracking
  - Directional byte tracking: separate client-to-backend and backend-to-client metrics
  - Snapshot-based metrics export for TUI consumption (zero-copy)

- **Property-Based Testing** ([#40](https://github.com/mjc/nntp-proxy/pull/40))
  - Comprehensive proptest integration for all newtype wrappers
  - Reusable test macros: `test_nonzero_newtype_full!`, `test_validated_string!`
  - 10,000+ generated test cases covering edge cases (0, MAX, overflow)
  - Code reduction: 26% fewer test lines (571 lines) with 100x more coverage
  - Integration property tests for routing modes and session handling

- **Massive Test Coverage Improvements**
  - Overall coverage: 74% → 85%+ across codebase
  - 500+ new tests added across 30+ modules
  - Module-specific improvements:
    - `pool/buffer.rs`: 0% → 100% (+21 tests)
    - `session/mod.rs`: 62.5% → 100% (+15 tests)
    - `cache/article.rs`: 69% → 98.7% (+12 tests)
    - `config/types.rs`: 31% → 99.8% (+35 tests)
    - `types/protocol.rs`: 52% → 91% (+18 tests)
    - `pool/deadpool_connection.rs`: 54.5% → 78.7% (+24 tests)
  - New test suites: routing modes, session handling, metrics, cache helpers

- **API Improvements**
  - Shared CLI args module (`args.rs`) with `CommonArgs` and `CacheArgs`
  - `PooledBuffer::as_mut_slice()` for better API discoverability
  - `BufferPool::acquire()` replacing `get_buffer()` for clearer semantics
  - Type-safe directional byte tracking (`BytesSentToBackend`, `BytesReceivedFromBackend`)
  - Anonymous user constant centralization (`ANONYMOUS_USER`)

### Changed

- **Routing Mode Rename** - `RoutingMode::Standard` → `RoutingMode::Stateful` for clarity
- **API Renames for Clarity**
  - `CommandHandler::handle_command()` → `classify()`
  - `NntpCommand::classify()` → `parse()`
  - `ResponseCode` → `Response` (matches RFC 3977 terminology)
  - `DeadpoolConnectionProviderBuilder` → `Builder`
  - Removed `get_` prefixes, `_sync` suffixes from method names
  - Removed redundant `Config` suffix from config types

- **Code Quality & Refactoring**
  - Integrated caching directly into `ClientSession` - eliminated `CachingSession` duplication
  - Consolidated per-command routing handlers and shutdown signal handling
  - Extracted testable pure functions from session handlers
  - Functional style refactoring in cache logic
  - AuthResult changed from struct to enum for better type safety
  - Removed conditionals from match guards - pure pattern matching
  - Eliminated duplicate command parsing in cache path
  - Removed verbose debug logging to reduce code bloat (~200 lines)

- **Configuration Enhancements**
  - Added proxy config section with threading model configuration
  - Environment variable support for all configuration options
  - Extended timeout configuration options
  - Enhanced validation with better error messages

### Fixed

- **Test Infrastructure**
  - Fixed flaky tests and dead code warnings
  - Added missing `#[tokio::test]` attribute to async tests
  - Improved test isolation with random port allocation

### Performance

- **Lock-Free Metrics** - Zero-allocation metrics recording using atomic operations and DashMap
- **TUI Optimizations** - Eliminated snapshot cloning, optimized data conversions
- **Buffer Tuning** - Optimized for real-world article sizes (724KB average)

### Technical Details

- **Test Infrastructure**: Reusable test macros, property-based testing, MockNntpServer builder
- **Metrics Architecture**: Modular design with snapshot isolation, lock-free recording
- **TUI Stack**: ratatui + crossterm, system stats via sysinfo crate
- **Code Reduction**: 571 lines of test code eliminated while increasing coverage 100x
- **New Files**: 25+ new modules (metrics, TUI, test infrastructure)
- **Total Changes**: 24,591 insertions, 3,038 deletions across 112 files

## [0.2.3] - 2025-11-12

### Added

- **Domain Types Refactoring** ([#35](https://github.com/mjc/nntp-proxy/pull/35))
  - Comprehensive newtype pattern implementation across codebase
  - Type-safe newtypes for all domain values:
    - `Username`, `Password` - Validated authentication credentials
    - `StatusCode` - NNTP response status codes
    - `TransferMetrics` - Replaces (u64, u64) tuples
    - `AuthResult`, `QuitStatus` - Return value newtypes
    - `Timeout` newtypes for type-safe duration handling
    - Connection pool metrics: `AvailableConnections`, `CreatedConnections`, `InUseConnections`
  - Comprehensive config validation tests (25 new tests)
  - `MockNntpServer` builder pattern to eliminate test duplication
  - Test factory functions reducing boilerplate by ~800 lines
  - GitHub Actions CI workflow with cargo-nextest (7x faster)
  - **Fixes**: [#31](https://github.com/mjc/nntp-proxy/issues/31) - Config field naming inconsistencies
  - **Fixes**: [#33](https://github.com/mjc/nntp-proxy/issues/33) - Client auth appearing to be required

- **Docker Support** ([#36](https://github.com/mjc/nntp-proxy/pull/36))
  - Multi-stage Docker build with Rust nightly (for let-chains feature)
  - Environment variable configuration for containerized deployments
  - Backend server configuration via indexed env vars: `NNTP_SERVER_N_*`
  - Full TLS configuration support via environment variables
  - Health check configuration: max per cycle, pool timeout
  - Connection keepalive duration configuration
  - Docker Compose examples with .env.example pattern
  - Secure credential management (no hardcoded defaults)
  - **Fixes**: [#32](https://github.com/mjc/nntp-proxy/pull/32) - Docker build issues

### Fixed

- **Critical: Greeting Flush Bug** ([#37](https://github.com/mjc/nntp-proxy/pull/37))
  - Fixed connection resets for NNTP clients that send commands immediately after connecting
  - Root cause: greetings buffered in TCP send buffer without flush
  - Added `flush()` immediately after all greeting writes
  - Affects per-command and hybrid routing modes
  
- **223 Response Code Handling**
  - Backends commonly return 223 for missing articles (even on message-ID requests)
  - Changed log level from WARN to DEBUG for 223 responses
  - Added integration test demonstrating real-world backend behavior

- **Docker Build Issues**
  - Fixed empty NNTP_PROXY_THREADS env var causing parse errors
  - Fixed Duration type conversions from u64 environment variables
  - Fixed health check variable expansion in docker-compose
  - Improved error messages with specific variable names

- **Security Improvements**
  - Removed insecure credential defaults from docker-compose
  - Fail-fast behavior when required credentials missing

### Changed

- **Domain Types Code Quality** ([#35](https://github.com/mjc/nntp-proxy/pull/35))
  - Comprehensive newtype pattern across codebase for type safety
  - Consolidated config/pool/protocol types with macros
  - Code reduction: ~1,840 lines while improving type safety
  - Refactored integration tests: -800 lines of boilerplate
  - Improved Rust idioms: const fn, #[must_use], #[inline]
  - Extracted common auth and QUIT handling

- **Documentation**
  - Clarified greeting flow in code comments
  - Updated function documentation for greeting handling

### Technical Details

- **Greeting Flow**: Backend greetings consumed when connections created in pool; proxy sends own greeting with immediate flush to client
- **Type Safety**: All domain values now use validated newtypes (Username, Password, StatusCode, TransferMetrics, etc.)
- **Testing**: Added MockNntpServer builder, cargo-nextest CI, 25 config validation tests, random ports for parallel execution

## [0.2.2] - 2025-11-07

### Added

- **Client Authentication System** ([#29](https://github.com/mjc/nntp-proxy/pull/29))
  - Config-file based client authentication support
  - Credential validation against configured users
  - Authentication caching for improved performance
  - RFC-compliant NNTP response codes (480, 481, 482)
  - Comprehensive authentication security tests (bypass prevention, integration, security)
  - **Closes**: [#28](https://github.com/mjc/nntp-proxy/issues/28) - Basic user auth/permissions
  
### Changed

- **Performance Optimizations**
  - Introduced `PooledBuffer` type to eliminate repeated 64KB Vec allocations
  - Optimized authentication hot path to restore 80MB/s throughput
  - Eliminated Vec allocations in streaming functions
  - Reduced buffer allocation overhead with smarter initialization tracking
  
- **Code Quality**
  - Made `AuthHandler` more idiomatic Rust
  - Extracted `route_command_with_error_handling` helper to reduce duplication
  - Simplified `PooledBuffer` API to prevent undefined behavior
  - Removed unused macro parameters from `validated_string!`

### Fixed

- **Response Parsing**
  - Fixed bug in `has_spanning_terminator` with comprehensive test coverage
  - Proper tracking of initialized bytes in `PooledBuffer` to prevent reading uninitialized memory

### Improved

- **Test Coverage**
  - Added comprehensive authentication tests (bypass prevention, integration, security scenarios)
  - Added tests for RFC-compliant response codes
  - Added tests proving authentication design correctness
  - Overall test suite expanded significantly for authentication features

## [0.2.1] - 2025-10-27

### Fixed

- **Error handling and logging improvements** ([#24](https://github.com/mjc/nntp-proxy/pull/24))
  - Fixed spurious "broken pipe" error logs that masked real issues like authentication failures
  - Client disconnects after successful data transfer now correctly log at DEBUG level instead of ERROR/WARN
  - Authentication failures now prominently visible in logs with full context (backend name, host, port, username, server response)

### Changed

- **Code quality and maintainability**
  - Refactored per-command routing handler to eliminate nested helper functions
  - Reduced `per_command.rs` from 620 to 550 lines (-11%)
  - Flattened main command loop from 4-5 nesting levels to 2 maximum
  - Simplified error handling with inline logic instead of jumping between functions
  - Added `ErrorClassifier` utility for consistent error classification across codebase
  - Enhanced `ConnectionError` with classification methods (`is_client_disconnect()`, `is_authentication_error()`, `is_network_error()`)

- **Streaming improvements**
  - Refactored `handle_client_write_error()` to distinguish complete vs incomplete chunk disconnects
  - Complete chunk disconnects now log at DEBUG (normal behavior)
  - Incomplete chunk disconnects log at WARN (unusual but handled)

### Added

- **Test coverage**
  - Added 8 tests for ConnectionError classification
  - Added 7 tests for ErrorClassifier functionality
  - Added 3 tests for streaming error scenarios
  - Added 10 tests for message ID extraction
  - All 378 tests passing with 74.08% overall coverage

## [0.2.0] - 2025-10-09

### Added

- **SSL/TLS Support**
  - Full SSL/TLS implementation for secure connections
  - Configurable certificate validation
  - Stream abstraction layer to support both plain and TLS connections
  
- **Enhanced TCP Tuning**
  - Cross-platform TCP optimization with platform-specific features
  - Configurable socket buffer sizes
  - TCP_NODELAY support for reduced latency
  - Platform-specific optimizations (TCP_QUICKACK on Linux, TCP_NOPUSH on BSD/macOS)
  
- **Caching Proxy**
  - Article caching support to reduce backend bandwidth
  - Configurable cache capacity
  - LRU eviction policy
  - Bandwidth optimization for frequently accessed articles
  
- **Health Checking System**
  - Fast TCP-level health checks instead of expensive DATE commands
  - Configurable health check intervals and failure thresholds
  - Automatic backend recovery tracking
  - Health metrics for monitoring

- **Builder Patterns**
  - `ServerConfigBuilder` for cleaner test code
  - `ClientSessionBuilder` for flexible session creation
  - `DeadpoolConnectionProviderBuilder` for connection provider setup

### Changed

- **Architecture improvements**
  - Split session handlers into routing mode modules (standard, per-command, hybrid)
  - Reorganized types/config into focused submodules
  - Modularized codebase for better maintainability
  - Consolidated constants into dedicated module

- **Performance optimizations**
  - Line buffer reuse in streaming to avoid allocations
  - Optimized cache session memory operations
  - Capacity hints for allocations
  - Inline hints for frequently-called functions
  - Iterator combinators instead of manual loops

- **Configuration**
  - Added environment variable support for CLI and backend servers
  - Comprehensive configuration validation with error messages
  - Removed duplicate buffer constants

### Fixed

- **Per-command routing fixes**
  - Fixed multiline response detection
  - Removed unnecessary flush calls
  - Fixed duplicate greeting in per-command routing mode
  - Fixed QUIT command broken pipe errors

- **Connection management**
  - Fixed connection pool exhaustion by using correct pooled connection method
  - Fixed TCP stream corruption in connection recycling
  - Proper handling of fresh vs pooled connections

### Improved

- **Code quality**
  - Applied clippy suggestions for idiomatic Rust
  - Added comprehensive documentation with `#[must_use]` attributes
  - Improved error types with detailed context
  - Thread-safe environment variable tests
  - Reduced cloning overhead with `from_server_config` constructor

## [0.1.0] - 2025-09-05

### Added

- **Core NNTP Proxy Functionality**
  - High-performance NNTP proxy server
  - Connection pooling with deadpool
  - Multiple routing modes (standard, per-command, hybrid)
  - Round-robin load balancing across backend servers
  - Stateful and stateless connection modes

- **Authentication**
  - Client authentication interception
  - Backend authentication handling
  - Credential management
  
- **Connection Management**
  - Deadpool-based connection pooling
  - Connection prewarming
  - Graceful shutdown support
  - Signal handling (SIGTERM, SIGINT)
  
- **Performance Features**
  - High-throughput TCP optimizations
  - Efficient buffer management with buffer pools
  - Zero-copy operations where possible
  - Per-request connection provider trait
  
- **Configuration**
  - TOML-based configuration
  - Configurable buffer sizes
  - Pool size and timeout settings
  - Backend server configuration
  
- **Testing**
  - Comprehensive test coverage
  - Mock server infrastructure
  - Integration tests
  - Test helpers and utilities
  
- **Development Tools**
  - Git hooks for code quality
  - Nix flake for reproducible builds
  - Docker support
  - Development documentation

[0.5.0]: https://github.com/mjc/nntp-proxy/compare/v0.4.0...v0.5.0
[0.4.0]: https://github.com/mjc/nntp-proxy/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/mjc/nntp-proxy/compare/v0.2.3...v0.3.0
[0.2.3]: https://github.com/mjc/nntp-proxy/compare/v0.2.2...v0.2.3
[0.2.2]: https://github.com/mjc/nntp-proxy/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/mjc/nntp-proxy/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/mjc/nntp-proxy/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/mjc/nntp-proxy/releases/tag/v0.1.0
