diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b5c815..b98f191 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to BlazeServe 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.4.0] - 2026-09-11 + +### Added +- **Machine-Readable CLI Outputs**: Added opt-in `--json` mode to `blaze doctor` (reporting structured path, port, and optimization checks) and single-run `blaze benchmark` (reporting normalized base URL, byte counts, elapsed seconds, and throughput in MiB/s) while preserving default Rich terminal formatting. +- **Local Contributor Smoke Flow**: Added `scripts/contributor_smoke.py` as an activation-free local smoke command verifying authenticated static GET, byte-range slicing, file upload and readback, and liveness/readiness probes with clean lifecycle teardown. +- **Live IPv6 Loopback Coverage**: Added capability-aware live IPv6 integration testing on `[::1]:0` and socket-family preservation across dual-stack resolution. +- **Offline Deployment Configuration Validation**: Added a dedicated, read-only CI job and contributor reproduction workflow verifying Docker Compose, Kubernetes manifests, reverse-proxy configs, Linux kernel tuning syntax, Prometheus alerting rules, and systemd service unit integrity. +- **Compatibility and Deprecation Policy**: Published a normative compatibility policy (`COMPATIBILITY.md`) defining public surfaces, support evidence matrix, deprecation stages, and exception standards. +- **Extended Protocol Integration Tests**: Added deterministic tests covering Cross-Origin Resource Sharing (CORS) header sets and representation-aware `Vary` dimensions across uncompressed, gzip precompressed, and range requests. + +### Security +- **Path Traversal Barrier Enforcement**: Strengthened path canonicalization and barrier guards across upload and ZIP endpoints, ensuring resolved targets strictly remain within the configured root. +- **HTTP Response Splitting Sanitization**: Sanitized dynamic attachment filenames in the `Content-Disposition` header to prevent CRLF injection and response splitting. + ## [0.3.1] - 2026-09-05 ### Added diff --git a/blazeserve/__init__.py b/blazeserve/__init__.py index 61cbb67..ee9e94b 100644 --- a/blazeserve/__init__.py +++ b/blazeserve/__init__.py @@ -1,2 +1,2 @@ __all__ = ["__version__"] -__version__ = "0.3.1" +__version__ = "0.4.0" diff --git a/blazeserve/ui.py b/blazeserve/ui.py index a3567b8..5ece6a0 100644 --- a/blazeserve/ui.py +++ b/blazeserve/ui.py @@ -117,7 +117,7 @@ def render_directory_index(

⚡ {title}

- BlazeServe 0.3.1 + BlazeServe 0.4.0
{upload_ui} diff --git a/deploy/k8s/deployment.yaml b/deploy/k8s/deployment.yaml index aba9e9b..0469b82 100644 --- a/deploy/k8s/deployment.yaml +++ b/deploy/k8s/deployment.yaml @@ -26,7 +26,7 @@ spec: type: RuntimeDefault containers: - name: blazeserve - image: ghcr.io/whoisjayd/blazeserve:v0.3.1 + image: ghcr.io/whoisjayd/blazeserve:v0.4.0 imagePullPolicy: IfNotPresent args: ["serve", "/data", "--host", "0.0.0.0", "--port", "8000", "--log-json"] ports: diff --git a/pyproject.toml b/pyproject.toml index 4b3ef32..650a522 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "blazeserve" -version = "0.3.1" +version = "0.4.0" description = "⚡ Ultra-fast HTTP file server with advanced performance optimizations, real-time metrics, and production-ready architecture — supports byte-range/multi-range downloads, TLS, Basic Auth, throttling, uploads, streaming ZIP, CORS, and a polished CLI." readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.10" diff --git a/tests/integration/test_operational_endpoints.py b/tests/integration/test_operational_endpoints.py index 6996e4d..dba3ed8 100644 --- a/tests/integration/test_operational_endpoints.py +++ b/tests/integration/test_operational_endpoints.py @@ -44,7 +44,7 @@ def test_version_endpoint(server: tuple[str, int]): assert resp.status == 200 data = json.loads(resp.read()) assert data["name"] == "blazeserve" - assert data["version"] == "0.3.1" + assert data["version"] == "0.4.0" assert "python" in data assert "platform" in data finally: diff --git a/tests/unit/test_version.py b/tests/unit/test_version.py index 6919368..da1f4eb 100644 --- a/tests/unit/test_version.py +++ b/tests/unit/test_version.py @@ -8,5 +8,5 @@ @pytest.mark.unit def test_version_string(): - assert __version__ == "0.3.1" - assert blazeserve.__version__ == "0.3.1" + assert __version__ == "0.4.0" + assert blazeserve.__version__ == "0.4.0" diff --git a/uv.lock b/uv.lock index 88c62d8..6b7fa7c 100644 --- a/uv.lock +++ b/uv.lock @@ -81,7 +81,7 @@ wheels = [ [[package]] name = "blazeserve" -version = "0.3.1" +version = "0.4.0" source = { editable = "." } dependencies = [ { name = "click" },