Tags

Tags give the ability to mark specific points in history as being important
  • v0.2.29

    Release v0.2.29 — App::cgiMode('fork') warm-fork CGI bridge (~5x faster than proc_open, opt-in)
  • v0.2.28

    Release v0.2.28 — canonical compat/g.php dual-runtime shim + real FPM benchmarks (docs/tooling, no behaviour change)
  • v0.2.27

    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

    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

    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

    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.
  • v0.2.23

    Release v0.2.23
    
    - Added: App::processIsolation(?bool), App::enableCoroutine(?bool),
      App::hookAll(bool|int|null) — fluent setters that decouple the four
      lifecycle decisions previously bundled inside App::superglobals().
      Each defaults to null → resolves to "follow $superglobals" at run()
      time, so existing apps see no behaviour change.
    - Enables the "Mixed-mode / Symfony" lifecycle (superglobals=true +
      processIsolation=false + sessionLifecycle=false): real $_SESSION
      without the ~30-50 ms CGI fork cost on every App::include() call.
    - Added: lifecycle mode matrix in CLAUDE.md documenting the six
      supported combinations and the two unsafe-but-warned combinations.
    - Changed: App::run() resolves lifecycle decisions through the new
      setters; emits [lifecycle] warnings to the debug log for combinations
      that race process-wide $_GET/$_POST/$_SESSION across coroutines.
    - Changed: internal OpenSwoole\Runtime::enableCoroutine() call switched
      to canonical two-arg form (PHPStan level 10 cleanliness).
    
    PHPStan level 10 clean. 321 unit + 146 integration tests pass.
  • v0.2.22

    Release v0.2.22
    
    - Fix: $_SESSION ↔ $g->session bridge in superglobals mode (RequestContext's
      typed property was shadowing the __get/__set proxy, breaking session
      interop with Symfony/Laravel and any framework that writes through
      $_SESSION). Full sweep across zeal_session_start/write_close/status/
      destroy/unset/abort/encode/decode.
    - Fix: zeal_session_status() no longer false-positives PHP_SESSION_ACTIVE
      on fresh worker in superglobals mode (was tripping Symfony's
      NativeSessionStorage "already started by PHP" guard).
    - Added: App::sessionLifecycle(?bool) opt-out for external frameworks that
      own the session lifecycle. Eliminates the duplicate PHPSESSID cookie war.
    
    Enables Symfony-on-ZealPHP via the zealphp-symfony bridge.
  • v0.2.19

    Release v0.2.19 — Tier 1 security/quality CI: composer audit + Dependabot + CodeQL + gitleaks. Plus poser→shields.io badge fix.
  • v0.2.18

    Release v0.2.18 — fix composer.lock out of sync on v0.2.17 (PHPStan 2.1.54 pin)
  • v0.2.17

    Release v0.2.17 — PHPStan 2.x level 10, 0 errors. Vendor cleanup, CI hygiene, PHP 8.5 matrix.
  • v0.2.16

    Release v0.2.16 — PHPStan level 6 → 9 (final climb of three-release series). 0 errors at level 9, 74 documented ignore-sites, 6 real bugs fixed.
  • v0.2.15

    Release v0.2.15 — PHPStan level 5 → 6 (annotation cliff complete; 369 missing-type errors fixed)
  • v0.2.14

    Release v0.2.14 — PHPStan level 1 → 5 (first of three releases climbing to level 9)
  • v0.2.13

    Release v0.2.13
    
    Framework
    - CorsMiddleware: env-var origins (ZEALPHP_CORS_ORIGINS) + one-time
      warning when defaulting to wildcard '*'. Backward-compatible.
    - static_handler_locations default fixed — trailing-slash directory
      entries prevent /js intercepting /json (and similar prefix collisions).
    
    Main repo demo / website
    - app.php cleanup: PSR-12, drop hardcoded TZ + backtick git describe,
      fix /json session leak, remove /exittest (calls exit() = worker kill)
      and 9 other junk demo routes.
    - Demo middleware moved to examples/ with honest names.
    
    Triggered by public app.php line-by-line review. Full trace in CRITIC.md.
  • v0.2.12

    Release v0.2.12 — session-file corruption worker-crash fix
    
    Stability fix (high severity, DoS class):
    Production-breaking TypeError on corrupted / empty / non-array
    session payloads. unserialize() false → typed array assignment →
    worker abnormal exit. Affects all v0.2.6 through v0.2.11.
    
    Fixed at three call sites in src/Session/utils.php:
    - zeal_session_start (request entry)
    - zeal_session_reset (mid-request reset)
    - zeal_session_decode (user-controlled input)
    
    zeal_session_decode now returns bool matching PHP native signature.
    
    11 new regression tests in SessionFileCorruptionTest.php cover
    empty / corrupted / garbage / non-array / missing-file scenarios.
    
    ROADMAP.md restructured around 'v0.2.x = security & migration'
    framing. Connection pool moved out of v0.3 into remaining v0.2.x
    items — it's a production-trust gap, not an observability feature.
    
    204 unit tests, PHPStan green. See CHANGELOG.md and CRITIC.md.
  • v0.2.11

    Release v0.2.11 — open-redirect hardening + docs cleanup
    
    Security:
    - Response::redirect() rejects leading/trailing whitespace and backslash.
      Closes a real open-redirect / stored-XSS bypass of v0.2.5's scheme guard:
      '   javascript:alert(1)' was getting through because the regex anchor
      failed to match URLs with leading whitespace, and browsers strip the
      whitespace before parsing the Location header.
    - All v0.2.5 through v0.2.10 are affected. Upgrade recommended for any
      app that passes user input directly to Response::redirect().
    - 7 new redirect regression tests.
    
    Tests:
    - 17 new RequestContext invariants tests pinning the v0.2.6 architectural
      contracts (class_alias identity, strict __set, response state location,
      ApacheContext lazy alloc, etc.).
    
    Docs:
    - deployment.php env var table rewritten with all 20 ZEALPHP_* vars.
    - migration / sessions / middleware / README updated for v0.2.6+ rename
      and v0.2.10 additions.
    
    193 unit tests, PHPStan green. See CHANGELOG.md and CRITIC.md.
  • v0.2.10

    Release v0.2.10 — discipline-contract sprint
    
    Closes the visibility gap on the per-coroutine isolation contract raised
    in this week's public technical review:
    - RequestContext::once(\$key, \$fn) helper (Laravel 11 once() analog)
    - Worker-recycle access log line
    - Opt-in IniIsolationMiddleware
    - Coroutine safety matrix + Store semantics docs
    - OPcache production tuning notes
    - Handler stack reset in superglobals mode
    
    169 unit tests, PHPStan green. See CHANGELOG.md and CRITIC.md.
  • v0.2.8

    Release v0.2.8 — PHPStan CI green again
    
    After the v0.2.6 G → RequestContext rename, PHPStan flagged 90
    "unknown class" errors because it doesn't follow runtime class_alias.
    This release migrates framework-internal G:: references to the
    canonical RequestContext:: name across src/. The class_alias for
    external user-code backward compat is unchanged.
    
    PHPStan: 0 errors. Unit tests: 155/155.
  • v0.2.7

    Release v0.2.7 — relax setrawcookie filter
    
    v0.2.5 introduced CRLF/NUL injection guards on cookie/header sinks.
    The setrawcookie value filter was too strict — it rejected legal raw
    cookie-octets (space, comma, semicolon) that PHP native accepts. Now
    matches PHP behavior: rejects only \r\n\0 in the value. CRLF guards
    on header(), Response::header(), redirect(), setcookie() are unchanged.
    
    Existing testSetRawCookieDoesNotUrlEncode integration test confirms.