Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
ab42397
Modernize PHP support and verify real error handling failures
coisa Sep 15, 2026
dfb0433
fix: preserve shutdown delivery and bound renderer cleanup
coisa Sep 15, 2026
8646c73
feat: integrate FastForward providers and add agent guidance
coisa Sep 16, 2026
75137ca
docs: identify the Error Handler skill by its package
coisa Sep 16, 2026
ecede64
refactor: adopt FastForward autowiring and complete PHPDoc
coisa Oct 15, 2026
fb4652b
test: verify required service failures across FastForward versions
coisa Oct 15, 2026
c4cd54d
refactor: consolidate Interop wiring and isolate buffer cleanup
coisa Oct 15, 2026
2253e34
fix: harden reporting and document release workflow
coisa Oct 15, 2026
48b10c5
ci: correct setup-node commit reference
coisa Oct 15, 2026
82f8d3d
ci: report coverage in a SHA-aware sticky PR note
coisa Oct 15, 2026
611ea93
refactor: separate HTTP reporting from public rendering
coisa Oct 15, 2026
ea30a94
docs: record validated HTTP redesign evidence
coisa Oct 15, 2026
9cc4c32
docs: align major release note with final HTTP contract
coisa Oct 15, 2026
4a5508a
docs: simplify provider examples and improve reading flow
coisa Oct 15, 2026
166e5b6
Reconcile major contracts with delivered 2.x maintenance
coisa Oct 16, 2026
afa38fd
Reconcile delivered adapters and major PHPUnit verification
coisa Oct 16, 2026
f2d789d
Keep major Changeset rehearsal free of trailing whitespace
coisa Oct 16, 2026
4ea93db
test: cover buffer replacement during native handler destruction
coisa Oct 16, 2026
770680f
Merge current 2.x maintenance into the major draft
coisa Oct 16, 2026
0f0002f
Merge released 2.x cookbook and coverage policy into major
coisa Oct 16, 2026
abb5e35
chore: reconcile reviewed 2.4.2 maintenance deliveries
coisa Oct 16, 2026
1172ded
merge: reconcile master consumer skill with major APIs
coisa Oct 17, 2026
650a662
chore: reconcile next major with published 2.5.0
coisa Oct 17, 2026
e9fe523
chore(release): avoid whitespace in generated major notes
coisa Oct 17, 2026
1f33d4d
feat: accept callable ErrorHandler constructor inputs
coisa Oct 17, 2026
cc98da3
chore(deps): refresh stable Composer ranges for the major
coisa Oct 17, 2026
98eba68
fix: retain PSR-14 reporters without an optional callable
coisa Oct 17, 2026
5d6f242
docs: reconcile master and document the current API
coisa Oct 17, 2026
0fcf15a
docs: align consumer guidance and release maintenance
coisa Oct 17, 2026
6625512
chore: reconcile the 2.5.1 release metadata
coisa Oct 17, 2026
e20b351
fix: keep caller buffers out of captured responses
coisa Oct 17, 2026
7ebd1f4
chore: reconcile released 2.5.2 maintenance
coisa Oct 17, 2026
e267b5d
chore: reconcile master 2.5.4 into the major upgrade
coisa Oct 20, 2026
2661dd4
chore: reconcile merged Whoops repair into major
coisa Oct 20, 2026
c178301
fix(changelog): retain inherited Whoops fragment
coisa Oct 20, 2026
8ecd83c
feat!: negotiate request-aware error responses with Symfony renderers
coisa Oct 21, 2026
9197aa1
Merge remote-tracking branch 'origin/master' into codex/pr3-response-…
coisa Oct 21, 2026
02e2d66
fix: enforce verified Symfony runtime compatibility floors
coisa Oct 21, 2026
d5aa900
test: preserve the resolved PHP extension platform in example children
coisa Oct 21, 2026
5744e12
fix: negotiate the actual UTF-8 HTML representation
coisa Oct 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changelog/fix-optional-callable-event-composition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: fixed
type: patch
---

Skip structural autowiring failure for an unconfigured optional callable reporter so the default major aggregate still delivers PSR-14 events. Preserve configured reporter order and explicit factory failures, and document the container's remaining concrete fallback boundary.
59 changes: 59 additions & 0 deletions .changelog/modernize-error-handler.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
category: changed
type: major
---

Modernize the library for PHP 8.3+ while retaining the package
`coisa/error-handler` and namespace `CoiSA\ErrorHandler`.
- Require PHP `^8.3`, with a tested CI matrix of PHP 8.3–8.5.
- Require FastForward Container `^1.10` and expose the Interop service provider as the
container entrypoint. Remove the standalone Container/ConfigProvider APIs,
their package-specific exceptions and constructor-only factories. Keep explicit
lifecycle/composition factories under `ServiceProvider\Factory`.
- Keep construction and discovery inert. Preserve cached services and provide
explicit fresh handler/middleware factories. Require reverse-order unregistration,
retain one shutdown callback per handler and notify only the active owner.
- Exit 1 after successful registered uncaught-exception reporting. Preserve direct
calls without termination; propagate reporter failures without retry during a
failed registration while allowing independent direct deliveries.
- Separate HTTP reporting from rendering. Middleware requires both contracts,
reports once and then invokes a pure response factory. Use a generic stream by
default, standard reason phrases and integer HTTP error statuses through 599.
- Keep explicit public output capture as an opt-in renderer adapter. Preserve `0`,
use a generic fallback for empty output, clean reachable buffers after success and failure,
and retain renderer-failure precedence over cleanup failures. If no capture
remains above the caller's entry depth, use the generic fallback without reading caller output.
- Retain delivered 2.x handlers and native release tooling. Add distribution checks
and organized PHPUnit Unit/Functional/Process coverage. Cover partial callback
ownership, fail-fast reporter identity and native fatal diagnostic metadata.
Preserve the configurable 80% overall coverage floor and real comparisons;
retire the prototype Fire/HTTP/Python parents and custom release publisher.
- Check all complete cookbook recipes against executable source, retaining
the exact inventory and omitting only each leading license header.
- Ship the canonical `resources/skills/coisa-error-handler` package with
configuration-first examples for the Interop provider and pure
renderer contracts. Preserve its license and optional installer metadata, and
require the complete consumer payload in distribution checks.
- Add a direct native regression for output-handler destruction that replaces its
removed buffer, proving bounded cleanup, primary-failure and caller ownership.
- Preserve the JSON, optional Whoops and explicit reporting adapters published in
2.5.0. Compose pure renderers after the middleware report; retain trusted debug
configuration, lazy page overrides and fresh middleware scopes without a second
diagnostic delivery. Consolidate response profiles into the request-aware
provider described in the companion negotiation entry.
- Accept matching callables in all three ErrorHandler constructor inputs using
existing adapters. Preserve interface identity and precedence, required reporter,
optional null defaults, inert construction and the existing reporting policies.
Keep explicit provider factories for cached services and fresh scopes.
- Refresh Composer development-tool ranges to the current stable lines, retaining
PHP 8.3 support through PHPUnit 12.5 and Symfony Process 7.4 alternatives.
Require Nyholm 1.8.2 in development for its PHP 8.5 fixes; retain the compatible
PSR ranges and optional Whoops 2.18.7 minimum with its upstream native STDIN source-read fix.
The Whoops compatibility fix preserves its renderer contract; the lifecycle and
HTTP-default changes above apply to this major.
- Describe the accompanying API without temporary PR or publication status,
and clarify that diagnostic reporter output remains outside the PSR-7 body.
- Correct callable-filtering guidance, clarify generic stream and fatal-reporting
contracts, and distinguish checkout recipes from bundled application examples.
Keep installed documentation links usable and release instructions current.
- Keep available representations and diagnostic authorization under application control.
8 changes: 8 additions & 0 deletions .changelog/negotiate-the-html-response-charset.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
category: fixed
type: patch
---

Negotiate the built-in HTML renderer using its actual UTF-8 media type. Honor
charset-specific Accept preferences and exclusions instead of choosing HTML when
its charset is explicitly forbidden or falling back when UTF-8 HTML is accepted.
26 changes: 26 additions & 0 deletions .changelog/request-aware-response-negotiation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
category: changed
type: major
---

Negotiate error responses from the current request through a single
`ErrorHandlerServiceProvider`. Replace the JSON and Whoops profile providers with
lazy Problem Details JSON, plain-text and Symfony HTML representations. Accept a required
`ServerRequestInterface` alongside the original throwable in every response
factory and forward it unchanged after one middleware report.

Keep diagnostic output disabled by default. Explicit debug configuration enables
JSON diagnostics and Symfony's detailed HTML, while production HTML remains a
generic status page. Keep Whoops available only through explicit application
composition, without changing the default based on installed optional packages.
Respect Accept quality and exclusions, preserve existing Vary fields and keep
selection independent across requests that reuse the same cached service.

Serialize Problem Details with Symfony Serializer, preserving public HTTP status
codes and keeping trace arguments and objects out of debug responses. Support
compatible Symfony component majors without requiring a matching VarDumper major.
Exclude older component patches that emit native PHP 8.4+ deprecations, including
incompatible transitive VarDumper versions, without adding a direct dependency.
Offer an explicit Symfony CLI reporter through the same provider, writing to
STDERR or the application's Console error output without installing native hooks.
Demonstrate PSR-14 reporting with FastForward Event Dispatcher and its provider.
2 changes: 1 addition & 1 deletion .github/workflows/changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
issues: read
statuses: write

# Official v0 compatibility branch; reviewed against v0.2.0.
# Official v0 compatibility branch; reviewed against v0.3.0.
uses: php-fast-forward/changelog/.github/workflows/changelog.yml@v0

with:
Expand Down
64 changes: 62 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,76 @@ jobs:
- name: Run formatting, PHPCS, PHPUnit and maximum src-plus-tests analysis
run: composer --no-plugins check

symfony-compatibility:
name: Symfony ${{ matrix.error-handler }} / PHP ${{ matrix.php }}
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
include:
- php: '8.3'
error-handler: '~5.4.0'
serializer: '~5.4.0'
http-foundation: '~6.4.0'
- php: '8.3'
error-handler: '~6.4.0'
serializer: '~6.4.0'
http-foundation: '~6.4.0'
- php: '8.4'
error-handler: '~7.0.0'
serializer: '~7.0.0'
http-foundation: '~7.4.0'
- php: '8.5'
error-handler: '~8.0.0'
serializer: '~8.0.0'
http-foundation: '~8.1.0'

steps:
- uses: actions/checkout@v7
with:
persist-credentials: false

- name: Isolate Composer state
run: |
echo "COMPOSER_HOME=$RUNNER_TEMP/composer-home" >> "$GITHUB_ENV"
echo "COMPOSER_CACHE_DIR=$RUNNER_TEMP/composer-cache" >> "$GITHUB_ENV"

- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, mbstring, xml, xmlwriter
ini-values: error_reporting=E_ALL
coverage: none
tools: composer:v2

- name: Resolve the supported Symfony combination
env:
ERROR_HANDLER: ${{ matrix.error-handler }}
SERIALIZER: ${{ matrix.serializer }}
HTTP_FOUNDATION: ${{ matrix.http-foundation }}
run: |
composer update --no-plugins --no-scripts --no-interaction --prefer-dist --no-progress \
--with "symfony/error-handler:$ERROR_HANDLER" \
--with "symfony/serializer:$SERIALIZER" \
--with "symfony/http-foundation:$HTTP_FOUNDATION"
composer check-platform-reqs
composer show --locked

- name: Verify the adapters and application composition
run: composer --no-plugins check

production:
name: Production / PHP ${{ matrix.php }} / ${{ matrix.dependencies }}
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
php: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5']
php: ['8.3', '8.4', '8.5']
dependencies: [highest]
include:
- php: '7.4'
- php: '8.3'
dependencies: lowest
- php: '8.5'
dependencies: lowest
Expand Down Expand Up @@ -246,3 +305,4 @@ jobs:
with:
header: phpunit-coverage
path: ${{ steps.coverage-diff.outputs.file }}

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/composer.lock
.idea/
vendor/
/tmp/
tests/html/
tests/clover.xml
tests/cobertura.xml
Expand Down
10 changes: 7 additions & 3 deletions .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@
$header = HeaderExtractor::extractFromFile(__FILE__);

return PhpCsFixer::create($paths, $header, [
'trailing_comma_in_multiline' => [
'after_heredoc' => true,
'elements' => ['arguments', 'array_destructuring', 'arrays'],
// PER3 sections 4/4.4 recommend concise empty bodies (SHOULD); keep multiline bodies
// to converge with complete PSR12 checking, including braced namespaces.
// https://github.com/php-fig/per-coding-style/blob/3.0.0/spec.md#44-methods-and-functions
'single_line_empty_body' => false,
'braces_position' => [
'allow_single_line_anonymous_functions' => false,
'allow_single_line_empty_anonymous_classes' => false,
],
]);
Loading
Loading