Tags give the ability to mark specific points in history as being important
-
v0.2.43
1ab5d453 · ·Release v0.2.43 - fix(session): persist sessions in CGI isolation mode (#108) — pool worker now flushes $_SESSION between dispatches; SessionManager skips its lifecycle when superglobals(true) + processIsolation(true) (subprocess owns sessions); App::mintCgiSession() emits Set-Cookie on first-visit since PHP's session module can't reach userspace setcookie() under uopz.
-
v0.2.42
b80197a8 · ·Release v0.2.42 - Fix #103: variadic-defensive App::dispatchTaskCallback() for OpenSwoole 22.x's two task-handler signatures (2-arg coroutine + 4-arg legacy). Prod workers no longer crash with ArgumentCountError under default task_enable_coroutine => true. Pinned by 10 unit tests. - Acknowledge #104: sibling-package zealphp-mongodb v0.2.8-v0.2.11 (BSONDocument drop-in, MongoDB\Driver\* polyfills, pass-by-ref fixes). No framework change; documented upgrade path in CHANGELOG. Also carries the intended v0.2.41 release content (FCGI worker pool default, WP-on-proc regression fix, ZealAPI helpers) — v0.2.41 was mis-tagged on Packagist at orphan commit 0372c3a. Skip v0.2.41; composer require sibidharan/zealphp:^0.2.42 if already installed.
-
v0.2.41
590cc8e3 · ·Release v0.2.41 - ZealPHP-native FCGI-style worker pool — cgiMode('pool') is now the framework default. CGI bridge per-request cost drops ~30–50 ms (proc) to ~1–3 ms (pool). cgiMode('fork') removed entirely. - FPM-style $GLOBALS snapshot/restore in pool_worker.php. - WordPress on cgiMode('proc') regression fix (issue #18): autoload gated behind opt-in App::cgiSubprocessAutoload(true), default off restores v0.2.0 zero-overhead subprocess start. - ZealAPI helpers upstreamed from labs-dashboard-web (PR #100): resolveClubParam(), failAs(Throwable), json() made public. -
v0.2.40
cbc0e471 · ·Release v0.2.40 Production hardening + Memcached + federated WebSocket rooms. Highlights - Production hardening pass on the Redis backend surface — closed 3 critical (FD-reuse race in WSRouter, HMAC-signed L1 invalidations, rediss:// TLS) + 10 medium gaps. Default behaviour preserved across all 13 fixes. - Memcached backend for Store + Counter (Store::BACKEND_MEMCACHED, Counter::BACKEND_MEMCACHED) with ZEALPHP_MEMCACHED_SERVERS env var + array config; phpredis + predis driver validated for SUBSCRIBE under HOOK_ALL. - Federated WebSocket Rooms (P1.1 of v0.3.0 roadmap, landed early) — WSRouter::room(name): Room with first-class join/leave/push/onMessage/ onPresence + cluster-wide membership via shared Store table + one PSUBSCRIBE pattern subscriber per worker. - Three-backend Store facade — Store::BACKEND_TABLE / BACKEND_REDIS / BACKEND_TIERED, plus Cache::getOrCompute read-through with null sentinel. - v0.3.0 early helpers — App::parallel / parallelLimit, App::onSignal, App::stats, HTTP::get/post/put/delete, App::addProcess for sidecars. - Real end-to-end async integration tests for pub/sub + streams delivery (RedisPubSubFederationTest) + redis-pubsub coverage pass. - Fixed route/demo_rooms.php deferring WSRouter::init to onWorkerStart (would crash production deploys with ZEALPHP_STORE_BACKEND=redis). CI: every required check green, codecov/patch passed at 79.03%.
-
v0.2.39
d854b99c · ·Release v0.2.39 — pluggable Store/Counter backends Phase 1 of the pluggable-backend program. `Store` and `Counter` now delegate to backend instances behind their existing static/instance APIs. `OpenSwoole\\Table` / `OpenSwoole\\Atomic` remain the default (nanosecond hot path); flip to Redis/Valkey for cross-node shared state with one line in app.php (`Store::defaultBackend(Store::BACKEND_REDIS)`) or the `ZEALPHP_STORE_BACKEND=redis` env var. Every existing handler call site keeps working unchanged. Pub/sub + Streams primitives (`Store::publish` / `App::onPubSub` / `Store::publishReliable` / `App::onReliableMessage`) ship in this release backed by RedisPubSub + RedisStreams lifecycle classes. Phase 3 pub/sub design empirically de-risked via three committed spikes (in-process, cross-process, cross-host @ 0.53 ms median via wireguard). Tagged retroactively at d854b99 (the 'complete v0.2.39 version-ref bumps' commit) — the v0.2.39 content was authored but never tagged when work moved on to v0.2.40. Master branch is behind d854b99; the v0.2.40 release on top of v0.2.39 brings everything to master via PR #87. Full notes: CHANGELOG.md [0.2.39] section (kept verbatim within the v0.2.40 collapsed entry).
-
v0.2.38
6c2bac3f · ·Release v0.2.38 — Apache + nginx parity wave Security: - referer DNS-label wildcard (closes example.evil.com over-match) - symlink escape via static serving (realpath docroot containment) - mod_expires no longer caches 4xx/5xx - double-encoded traversal (%252e%252e -> 400) - multi-range DoS cap (CVE-2011-3192 class) - explicit plaintext-htpasswd rejection + DES salt alphabet fix - error responses no longer leak prior handler headers Added: - ConditionalRequest evaluator (RFC 9110 If-Match/Unmod/None-Match/Mod-Since precedence + 412) - MimeResolver (multi-suffix Content-Type/Encoding/Language a la mod_mime) - ContentEncoding/ContentLanguage middleware - per-key ConcurrencyLimit (Store-backed, proxy-aware) + dry-run + configurable status - RateLimit burst/nodelay/dry-run/configurable-status, App::clientIp() keying - HostRouter trailing-wildcard + regex server_name + Host-400, IPv6 host parse - HeaderMiddleware nginx-style status-conditional add_header + always opt-out - Range If-Range HTTP-date; sendFile multi-range (206 multipart) - ExpiresMiddleware dual-header + M-base + error-suppress + clamp - Two source-diff audit docs: docs/apache-parity-audit.md, docs/nginx-parity-audit.md Changed: - HeaderMiddleware default = status-conditional (mild BC; per-rule always to restore) - Compression Vary merges instead of overwriting, q=0 refused, weak-ETag on compress - Redirect QSA merges query with & when target has one - BodySizeLimit chunked enforcement + 0 = unlimited - App::$limit_request_fields enforced (400 on excess); STANDARDS.md adds OpenSwoole-governed surfaces Tests: 1962 unit, Infection covered-MSI 92% (gate 92), plain-MSI 90% (gate 88). PR #38.
-
v0.2.37
4339076a · ·Release v0.2.37 - BasicAuth APR1 (apr_md5) digest fix: byte-reversed encoding could never verify a real htpasswd -m hash; now pinned against Apache htpasswd/openssl oracles - Infection covered-MSI 65% -> 95% (1680/1763 killed; 83 survivors all provably-equivalent, catalogued in STANDARDS.md); gate ratcheted to 88/92 - Apache httpd core-logic diff + non-support register (ProxyPass/TLS/WebDAV/CGI/mod_rewrite/.htaccess/...) - Runnable HTTP fuzz harnesses: radamsa (500 muts, 0 hangs/0 leaks), gabbi (7/7), slowhttptest; wired into CI (fuzz.yml)
-
v0.2.36
d6ff17d6 · ·Release v0.2.36 - 405 Method Not Allowed + Allow header (RFC 9110 §15.5.6); implicit document-root routes scoped to GET/POST (Apache static-handler parity) - Mutation Score Indicator badge in README, auto-refreshed from CI on master - Conformance: symlink-escape refusal + chunked-framing edge cases (extension/trailer/leading-zeros) - STANDARDS.md advanced-testing roadmap (Infection / http-garden / Radamsa / slowhttptest / Gabbi)
-
v0.2.35
97cbd3de · ·Release v0.2.35 HTTP/1.1 + static-serving conformance: - RFC 9112 §3.2 Host enforcement: HTTP/1.1 without Host -> 400 (1.0 exempt). - StaticServingConformanceTest: traversal corpus confined to docroot, dotfiles never served, autoindex off, MIME + conditional 304. - Host-rule + response-splitting (header() CR/LF/NUL) conformance. - STANDARDS.md request-line/Host/static matrix + OpenSwoole deviation register.
-
v0.2.34
a4b8e01c · ·Release v0.2.34 Standards conformance + Apache/nginx parity: - Conformance suites: IANA status (exhaustive), RFC 6265 cookies, RFC 9110 IMF-date, HTTP/1.1 framing & request smuggling (RFC 9112 §6-§7), live traversal proof. - CI gates: 80% coverage floor (codecov), Infection mutation testing (minMsi 55 / covered 60), perf-regression smoke. STANDARDS.md catalogue. - Middleware: ScopedMiddleware, RequestHeaderMiddleware, MergeSlashesMiddleware, BodySizeLimitMiddleware, RefererMiddleware, ReturnMiddleware. - Fixes: #23 session pipe-format cross-server parity, #25 .php URLs 404 not 403.
-
v0.2.33
5619dce7 · ·Release v0.2.33 Fixed: - #16 RedisSessionHandler is now coroutine-safe (one \Redis connection per coroutine instead of a shared socket) — resolves session corruption under concurrent/rapid sequential requests with a shared handler.
-
v0.2.32
a140f42a · ·Release v0.2.32 Apache/mod_php parity wave 2: - Built-in overrides: php_sapi_name, filter_input/filter_input_array, header_register_callback, error_log - $_SERVER completeness: GATEWAY_INTERFACE, REQUEST_SCHEME, HTTPS - Directive middleware: RedirectMiddleware (mod_alias), SetEnvIfMiddleware (mod_setenvif) - Config: ServerTokens (X-Powered-By), FileETag, default_mimetype Fixes: - #20 void return discarded buffered output - #21 unset($g->session[k]) not persisted through custom handler
-
v0.2.31
fe943776 · ·Release v0.2.31 - phpinfo() now renders styled HTML (Apache/mod_php parity) via ZealPHP\Diagnostics\PhpInfo + uopz override - App::onWorkerStop() per-worker shutdown hook - Fix #18: API routes keep DOCUMENT_ROOT at the web root (not /api); SCRIPT_NAME/PHP_SELF/SCRIPT_FILENAME parity - Fix #19: session_regenerate_id() is custom-handler-aware — migrates data + emits new-ID cookie (Redis/Valkey OAuth flows) - Test coverage ~29% -> ~80% combined; real WebSocket integration tests
-
v0.2.30
6e15fc34 · ·Release v0.2.30 — full superglobal aliasing ($g->get IS $_GET in superglobals mode) + issue #17 CLI/CGI fixes
-
v0.2.29
116b071c · ·Release v0.2.29 — App::cgiMode('fork') warm-fork CGI bridge (~5x faster than proc_open, opt-in) -
v0.2.28
de2d83af · ·Release v0.2.28 — canonical compat/g.php dual-runtime shim + real FPM benchmarks (docs/tooling, no behaviour change)
-
v0.2.27
3e4f9982 · ·Release v0.2.27 — superglobals(true) parity + drop-in LAMP Mixed-mode - $_GET/$_SESSION et al. populated per request in superglobals(true) mode - $g->session aliased to $_SESSION (same array) - Unsafe lifecycle combos throw at boot - examples/lamp-scaffold + SuperglobalsParityTest - Known issue: Symfony coroutine-mode session concurrency (use enableCoroutine(false))
-
v0.2.26
766f776d · ·Release v0.2.26 Closes issue #15: narrow whitelist for session unserialize. v0.2.25 set allowed_classes => false in all session decode paths, converting stdClass (the most common session object shape — json_decode output, OAuth tokens, API profiles) to __PHP_Incomplete_Class and breaking real apps. v0.2.26 narrows the whitelist to ['stdClass'] specifically — zero magic methods means no gadget chain — while keeping every other class refused. PHPStan level 10 clean. 385 unit + 147 integration tests pass.
-
v0.2.25
a5fa1e30 · ·Release v0.2.25 Closes issue #13 with two complementary fixes: - Added: App::authChecker(?callable), adminChecker(?callable), usernameProvider(?callable) — apps wire ZealAPI's auth methods to their own session/auth state. Was hardcoded `return false;` in PR #10. - Fixed: session write/destroy now delegates to \SessionHandlerInterface when one is registered (PR #14). Redis-backed sessions actually persist now. Plus read-then-merge for the handler-write path to mitigate concurrent-request races on top-level session keys. Backwards-compatible — both fixes only change behaviour when the opt-in (authChecker registration / handler registration) is used. PHPStan level 10 clean. 383 unit + 147 integration tests pass.
-
v0.2.24
5ec4d242 · ·Release v0.2.24 - feat(fragment): App::fragment(name, fn) — htmx-essay template fragments. Mark named regions inside a template; the same App::render('page', args) call serves the full page (no selector) or just one region (selector passed via $args['fragment']). 5th member of the file-execution family alongside render / renderToString / renderStream / include. Honours the universal return contract (int=status / array=JSON / string=HTML / Generator=stream). Missing fragment → HTTP 404, no silent fallback. - fix(session): session_start() auto-emits Set-Cookie on first-time visitors (PR #12). Restores correct OAuth/redirect behaviour where a 302 used to go out with no PHPSESSID and the next request started a fresh session. - fix(executeFile): HaltException catch no longer drops the buffered output when no explicit result was captured. echo "x"; throw new HaltException now correctly returns "x" as the body. Lessons: - /learn/htmx extended with "Template fragments — one file, two responses" - /learn/sessions extended with "First-visit cookie" section (PR #12) Live demo: /demo/fragments/contacts PHPStan level 10 clean. 362 unit + 147 integration tests pass.