Skip to content

v26.09.1 — response schemas, an error page, a data browser, and five security fixes

Choose a tag to compare

@ancongui ancongui released this 04 Sep 03:45
· 405 commits to main since this release
c29bdc9

A correctness release that also grew two browser surfaces — then had its own 606-file diff reviewed
adversarially and fixed everything that found.

Added

  • firefly/openapi documents what an endpoint RETURNS. Every success response used to be
    {"type": "object"} — a blank panel in a viewer, any in a generated client. DocType compiles a PHPDoc
    type expression into a JSON Schema fragment (array shapes, list<T>, array<K,V> told apart as
    array-vs-object, tuples, literal unions, PHPStan pseudo-types), and ResponseSchemaFactory builds a
    returned class from its wire shape rather than its constructor. Three input collections were fixed with
    it too: array<string, int> was published as an array, which is the wrong JSON type.
  • An HTML error page in the framework's own design, with the exception, its previous chain, the source
    around the throwing line, and a stack trace that separates your frames from your dependencies'. Overridable
    per status; json-paths (default api/*) forces problem+json on your API space whatever the caller asks.
  • Four new dashboard pages — a datasource page (connections, PDO persistence, the compiled
    #[Transactional] contract), a drawn entity map, a feature-switch console, and a data browser with
    filtering, real pagination, full CRUD and relations you can walk in both directions.
  • The skeleton ships what it advertises. firefly/admin and firefly/openapi were required by nothing,
    so create-project produced a project with neither. Its sample REST resource did not persist while its
    docblock claimed it did; it is now an EloquentRepository over two tables, which earns it its first
    #[Transactional].

Security

Five defects, each reproduced before it was fixed and each pinned by a test that fails when the fix is reverted.

CSRF Dashboard routes were mounted with no middleware at all — every @csrf in the views was decorative, and a tokenless curl -X POST changed the log level.
Extraction oracle A filter on a masked column recovered correct horse battery in 21 requests while the page displayed ******.
Production leak problem+json published an unhandled QueryException's SQL and its bindings in production, ungated, while the HTML page beside it withheld everything.
Write primitive The connection wizard, documented as "never writes anything", could create a file anywhere the worker could write via sqlite's database path.
Silent wrong answer contains/starts escaped LIKE wildcards with no ESCAPE clause, so a search for ada_love returned zero rows against a table containing ada_lovelace@example.test.

Laravel's CSRF middleware skips itself under tests, which is how that hole survived being written — so its
regression test asserts the middleware is attached, and the behaviour was verified over real HTTP.

The book

LaraFly by Example — fourteen chapters plus appendices, bilingual — is attached below as PDF and EPUB in
both languages, rebuilt from this tag. Chapter 4A gained "The success body: what an endpoint actually
returns" and Chapter 11 gained the new dashboard surfaces; both editions were edited in parallel.

Gates

2078 passed, 1 skipped · PHPStan max, 0 errors · deptrac 0 violations · Pint clean · book listings
223/223 · CI green on PHP 8.3, 8.4 and 8.5.

Not yet published to Packagist

release.yml splits 28 packages to fireflyframework/firefly-<pkg> mirrors, and those repositories do not
exist and no ACCESS_TOKEN secret is set
— so this tag published nothing to Packagist.

Worth knowing if you are watching the Actions tab: the split run for this tag reported success on all 28
jobs anyway
. symplify/monorepo-split-github-action exits 0 even when its push fails, so the run went
green while no mirror existed and nothing was published. That false green is fixed on main — the workflow
now refuses to start without ACCESS_TOKEN, and reads each tag back from its mirror before passing — but
this tag's run predates the fix.

Creating the mirrors and registering on Packagist need the org owner; see docs/publishing.md steps 6–7.

Full changelog: CHANGELOG.md