ADR-0016: Public RequestFactory as the URI boundary
- Status
-
Accepted
- Date
-
2026-10-10
- Relation
-
Supplements ADR-0003; its middleware and transport boundaries remain.
Context
A PSR-7 URI object may already have lost information from the original
string. Middleware cannot recover that information to distinguish forbidden
raw syntax. The registered TYPO3 path therefore needs validation before
Core processes the raw URI. The public
TYPO3CMSCore is the entry point for this
boundary; the internal Guzzle is not replaced.
Core 13 and Core 14 differ in readonly inheritance. A version
number alone does not establish a compatible parent class. A conflicting
object mapping or different factory instances would also change the
qualified entry point.
Decision
ext_localconf.php registers Guarded or
Guarded according to the actual supported Core
shape, when no existing mapping is present. Registration is validated on
every request, including Disabled mode. Conflicts are neither overwritten
nor silently accepted. The Core factory and the PSR factory alias must
resolve to the same expected instance.
Request validates the supported version,
inheritance, visibility, return type, parameter names, types and defaults,
and constructor before loading the replacement class. The parent's
readonly shape must match its Core branch. The public request
signature remains intact.
Raw validates the raw URI before PSR-7
processing in Enforce mode. Observe reports a denial and continues to
delegate; Disabled skips raw policy validation. The replacement then
delegates to the exact original Core factory, preserving method, options
and context. Middleware ordering, Core context restrictions and the
controlled terminal transport from ADR-0003: Two middleware boundaries and a controlled terminal transport remain additional
boundaries.
Alternatives considered
- PSR-7 middleware alone: cannot validate raw information already lost.
- Replace the internal GuzzleClientFactory: couples the extension to an internal Core API and replaces more than the required URI boundary.
- One replacement class for both Core branches: ignores incompatible
readonlyinheritance rules. - Accept only a version number or any existing mapping: establishes neither the actual ABI nor the active factory identity.
Consequences
The registered Core factory gains an earlier validation boundary without a second HTTP stack. Incompatible APIs or conflicting registration produce a controlled failure. Projects with their own factory replacement need an explicit integration. Early bootstrap calls, independent clients and direct sockets remain outside this boundary. For an already constructed PSR-18 request, raw URI validation remains the caller's responsibility; see Raw URLs and PSR-7 and Coverage and trust boundary.
Sources and evidence
The implementation is in Classes/,
Classes/,
Classes/ and the two replacement
classes. Wiring is in Configuration/Services.yaml and
ext_localconf.php.
Tests/,
Tests/,
Tests/ and
Tests/ maintain compatibility,
mode and configuration controls. The genuine Core bootstrap probe in
Tests/ checks factory identity
and raw syntax rejection with separate contact counters. Previously
executed results are recorded under Verification report.
Authoring this ADR inspected the current sources; it did not execute these
tests again or produce a new Native mutation measurement.
Reconsideration trigger
Changes to the public Core signature, inheritance, object registration or PSR alias wiring require renewed ABI and bootstrap qualification. An expanded coverage promise needs evidence for each additional entry path.