Changelog
All notable changes to JustAPI will be documented in this file.
The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.
[2.0.8] - 2026-08-06
Added (2026-08-07)
- Native async DB awaits β
app.db.query_async(sql, params)/app.db.execute_async(...): awaitable DB ops on the DB's own tokio runtime, GIL released, loop never blocked. 53Γ faster than the blocking path on slow queries (320 vs 6 RPS, ADR-093) - Multi-worker prefork verified β
justapi serve --workers N --scale: 4 workers = 1.88Γ throughput (99.7k RPS), auto-scale respawns (benchmarked 2026-08-07) - Type-checked DX β
py.typedmarker + mypy-clean.pyistubs (routes,app.db,native_async,sse_nativeall typed) - Scaffold demos differentiators β
justapi creategenerates a CRUD app exercisingquery_async,@native_async, and Rust-native SSE - Rust-native SSE streaming β
app.sse_native(path, count, interval_ms): events generated entirely in Rust, zero Python per event (ADR-088) @native_asyncdecorator β marks async handlers for the fastest dispatch; true parallel dispatch on free-threaded CPython (ADR-089)- Callback-driven async resolution β
_DoneNotifierfires on coroutine completion; no blocking wait, no thread hop (ADR-086)
Security Fixes
- CRITICAL: Fixed global panic hook race condition in
panic.rs(P0-1) - CRITICAL: Fixed RwLock poisoning panics in
PerRouteCircuitBreakerMiddleware(P0-2) - CRITICAL: Fixed division by zero in rate limiter (P0-3)
- HIGH: Added SQL identifier validation for CRUD table/column names (H-1)
- HIGH: Fixed WebSocket unwrap on hot path (H-2)
- HIGH: GraphiQL now gated on
JUSTAPI_ENABLE_GRAPHIQLenv var (H-3) - HIGH: Added 5-second per-check timeout in health checks (H-5)
- MEDIUM: Added Mutex poison recovery to Python bindings (7 files) (M-5)
- MEDIUM: Fixed ChaosMiddleware potential panic on misconfigured latency (M-6)
- MEDIUM: Added
nosniffheader to large file streaming path (M-7)
Added
- HTTP/3 (QUIC) transport β
app.enable_http3(cert_path, key_path)serves the app over HTTP/3 on the same port as TCP (featurehttp3; h3 + h3-quinn + quinn). Python handlers, DI, schema validation, and the GIL pool all work over QUIC (ADR-079, ADR-082) Securitydependency marker βSecurity(dep, scopes=...)isDependswith OAuth2-scope metadata (FastAPI parity); top-level re-exports ofJwtAuth,OAuth2PasswordBearer,OAuth2PasswordRequestForm,OAuth2PasswordRequestFormStrictfromjustapi.authJustAPPalias βJustAPP()is the same class asJustAPIApp()(alsoJustAPI)- QUERY method (RFC 10008) testability β
TestClient::query/query_with,JustAPITestClient.query/query_with,AsyncTestClient.query(RFC requires Content-Type; enforced with 400) __version__βjustapi.__version__now exposed (2.0.8)scripts/sanitize.shβ fast memory-safety gate: ASan on the full core suite + targeted Miri on the onlyunsafemodule (memory.rs); replaces the 20+ min full-suite Miri run- 4 portable wheels β manylinux + musllinux Γ x86_64 + aarch64 via
maturin --zig;scripts/publish.shbuilds/verifies/upload all
Fixed
- CRITICAL: Python-handler write-path collapse β concurrent writes dropped to ~3 RPS at c=11 (was 150 at c=10): the request-scoped auto-transaction double-acquired pool connections (
2NforNwrites). Removed; SQLite BUSY/LOCK now maps to 503 Retry-After. Writes now flat ~150 RPS c=1..50 (ADR-080) - CRITICAL: GIL pool not fork-safe β a forked child inherited the parent's initialized pool whose worker threads don't exist β every Python request hung (504s). Pool now tracks its PID and rebuilds after
fork(2); fixes prefork deployments and the long-standingtest_circuit_breakerflake (ADR-081) - DI awaitedness bug β
Depends/Securityon async callable instances (e.g.OAuth2PasswordBearer) were invoked without awaiting (unawaited coroutines leaked);_is_async_callablenow checks__call__ - Default-feature test gate β
db_bridge/edge_casesintegration tests now carry proper#![cfg(feature = ...)]guards;cargo test --workspacepasses on default features - Added GraphQL query depth/complexity limits (depth=10, complexity=200)
- Added 4 MiB gRPC message size limit
- Added 1024-route capacity for circuit breakers with FIFO eviction
- Added symlink resolution in static file serving via
canonicalize() - Added
x-content-type-options: nosniffheader to all static file responses - Fixed poisoned mutex cascading panics in request coalescer
- Redis dependency now feature-gated behind
redis-rate-limit
Performance
- Router FIFO cache eviction now O(1) with
VecDeque - Accept-Encoding now respects RFC 7231 quality values
- Health checks now run in parallel
- Metrics no longer misclassify 1xx status codes
- Environment variables cached with
LazyLock - CRUD query params now URL-decoded
Changed
- PLAN.md honesty pass β phase table distinguishes β verified vs π‘ implemented/unverified (all AI/inference phases marked unverified: MockModel-only, no GPU/real weights); Phase 52 stays frozen
- Docs fabrication sweep β removed false APIs from docs (
justapi.middleware,PyScheduler,enable_rate_limiter,enable_compression,fastapi.securityimports); rewrote security tutorials, scheduler API, performance-tuning with the real API; added HTTP/3 deployment guide - README comparison table β now states the honest breakdown (700k native fast path / 120k Python / 180k DB SELECT) instead of a single number
- Release infra β version bumped to 2.0.8 everywhere; publish consolidated to
wheels.yml(7-platform matrix, sole PyPI publisher); duplicate publish jobs disabled; classifier set to "4 - Beta" - Server code partially split:
ws.rs,sse_ws.rs,handler_exec.rsextracted - Added
#[non_exhaustive]to public enums for forward compatibility - ANSI injection prevention in diagnostics
- Implemented
GatewayState::get_route()(was a stub returningNone)
CI/CD
- Memory-safety gate now
scripts/sanitize.sh(ASan + targeted Miri) instead of the 20-min full-suite Miri run - Added
--testsflag to clippy in CI - Added
--all-featuresto cargo test in CI - Added
fuzz_pipeline,fuzz_websocket,fuzz_grpctargets to fuzz workflow - Fuzzing duration increased from 60s to 5 minutes per target
- Added benchmark regression gate to CI (95% threshold)
- Added integration test job (server startup, health checks, endpoints)
- Added PyPI publish workflow with OIDC trusted publishers
Documentation
- Created troubleshooting guide (10 common issues)
- Created performance tuning guide (10 optimization areas)
- Created migration guide from Robyn/Granian
- Created API stability guarantees document
- All docs integrated into docs_site
Testing
- 6 new edge case tests for SQL validation, health timeouts, chaos config
- 2 new fuzz targets (WebSocket, gRPC)
- New regression tests: write-path collapse, fork-safety, async-callable DI,
JustAPPalias, HTTP/3 e2e - 521+ total tests passing (170 Python, workspace suites green)
[Unreleased]
Added
PerRouteRateLimitermiddleware with prefix matching, method filtering, and optional fallback (middleware.rs)Server::add_per_route_rate_limit()builder methodCoreErrortyped error enum with 12 variants,thiserror-derived (error.rs)CoreError::to_problem_json()for RFC 9457 Problem Details renderingCoreError::into_response()for direct HTTP response buildingCoreError::status_code()for variant-to-HTTP-status mappingServer::with_shutdown_timeout(Duration)builder method (configurable drain timeout, default 30s)- 15 new crash-prevention and feature tests
Changed
- BREAKING: All error responses now follow RFC 9457 Problem Details format (
application/problem+json) instead of{"detail":"..."}or{"error":"..."}. Clients matching ondetailfield will still work; clients matching onerrorfield must update. error_response()returns{type, title, status, detail}instead of{detail}service_unavailable_response()returns{type, title, status, detail}withapplication/problem+jsoncontent typejson_error()in middleware returns{type, title, status, detail}instead of{error}Handler::Staticdispatch useserror_response()for non-2xx status codes- 40+
unwrap()calls on request hot paths replaced with safe error handling - Mutex locks in
metrics.rsandtracing_setup.rsnow recover from poisoning - Email format validator handles missing
@without panicking openai.rsstatus code conversion usessafe_status()fallback
Fixed
- User-triggerable server crash via email validation without
@character (validate.rs:33,app.rs:244) - Potential panic from
Bound::new()failure on every request (handlers.rs:176) - Potential panic from
CString::new()andpy.eval()infast_dumps(handlers.rs:335-336) - Mutex poisoning causing panic on
/metricsendpoint (metrics.rs:153,278) - Clock skew panic in Redis rate limiter (
rate_limit.rs:78) - Clock skew panic in mail verification tokens (
mail/otp.rs,mail/verify.rs)
[2.0.7] - 2026-07-25
Added
- Generator dependencies (FastAPI-style
yieldinDepends) - ORJSON as optional Rust-level serializer (
orjsonfeature) - Production panic hotspot audit β fixed 6 categories of
unwrap()panics - Scalar API Reference documentation page (156 pages total)
Changed
- Demo shop stress test β all D1βD4 defects fixed, 29/29 assertions pass
[2.0.0] - 2026-07-03
Added
- Initial release of JustAPI 2.0 "Singularity"
- Rust core (
justapi-core): HTTP/1.1+HTTP/2, routing, middleware, compression, WebSocket, SSE, TLS, database ORM, OpenAPI, GraphQL, gRPC, WASM middleware - Python bindings (
justapi-py): FastAPI-compatible decorator API, DI, controllers, TestClient - CLI (
justapi-cli): serve, db migrate/rollback, routes, doctor, gen, new, create, profile - Inference engine (
justapi-inference): KV cache, RadixAttention, continuous batching, speculative decoding, OpenAI-compatible API - 493+ tests, 8 fuzz targets, CI with Miri