Skip to content

v26.09.4 — the native gaps, closed in the framework

Choose a tag to compare

@ancongui ancongui released this 23 Sep 19:05
· 108 commits to main since this release

Everything here began as a place where an application running on 26.09.3 had to write framework-shaped code of its own — a metric wrapper around a method, a retry loop, a publisher per broker, a security rule that silently matched nothing. Each one is now an attribute the compiled manifest carries and a firefly.* key that configures it.

Highlights

Micrometer's method attributes. #[Timed], #[Counted] and #[Observed] ride the same interceptor chain #[Transactional] does. The scanner refuses the shapes that would compile into nothing rather than dropping them in silence — a metric on a class no post-processor reaches, on a final class or method, and the two shapes PHP does not inherit: a class-level attribute on a base whose stereotyped child returns [] for it, and a method an unannotated override hides. The drop decision is per method and an intersection over subclasses, so one child that merely inherits an annotated method cannot vouch for a sibling that overrides it.

The six resilience patterns as attributes, on that same chain, instead of wrappers — with an idle TTL for breaker and limiter records.

The EDA brokers reach the tracing seam. RabbitMqEventPublisher, KafkaEventPublisher and PostgresEventPublisher route publish() through EdaTracing::tracePublish(), so a broker record carries a traceparent of the framework's own making — gated by firefly.eda.tracing.brokers.enabled. The tracing figure and its Known-latent caveat moved with the code.

Spring Data continues. A #[Projection] and a trailing Pageable combine, paging in the database. initialDelay is applied rather than carried.

Breaking

Each of these is migratable without guessing; CHANGELOG.md carries the full migration note for every one.

  • when-authorized health details are real, instead of quietly degrading to never. An application already running that value with security on starts disclosing what it used to withhold. Decide, do not inherit: set never, list roles in firefly.management.endpoint.health.roles, or bind your own HealthDetailsAuthorizer. HealthEndpoint gained a required fourth constructor parameter.
  • problem+json's traceId is the W3C trace id, and correlationId is its own member beside it; both travel as response headers. With tracing off, every byte is what it was.
  • A URL rule written /api/* stops being a dead rule, so every /-prefixed rule now matches what its author meant.
  • The OpenAPI document publishes the security the server actually has, and what the dispatcher enforces rather than only what the URL rules say.

Documentation

The provenance guard that shipped in 26.09.3 audits every Markdown file this repository ships, and wave N branched before it existed. Eighteen listings quoting code the wave had changed were re-quoted verbatim from the files they name, five new listings gained a marker, and four claims that live outside any fenced block — where no guard reads them — were corrected, including the figure's alt text.

Verification

All 21 findings wave N's review loop left unconfirmed were verified against the tree before this tag: 21 already fixed, 0 still broken, each proven with git merge-base --is-ancestor.

Gate at 72db787: Pint, PHPStan max, 3779 tests (15,144 assertions), Deptrac 0 violations, 75 browser tests, and CI green on PHP 8.3, 8.4 and 8.5.

Installing

This release is not published to Packagist — the org's mirror repositories and release credentials are not configured, by design. Install from the monorepo or a git VCS repository entry; docs/publishing.md documents what a future Packagist release would need.

Full changelog: v26.09.3...v26.09.4