An Action was constructed with only the Request, so anything a Domain
needed beyond that — a connection, a mailer, a clock — had no way in. The
only route was a global such as env(), which is a service locator with a
two-word vocabulary, and each application would have grown its own the
first time it opened a database. Nothing in the framework said otherwise.
The answer is not a container. The application declares one class of its
own — what it is made of, one public property per thing — builds it in
public/index.php beside everything else, and the Kernel constructs every
Action as `new $action($request, $services)`. The Action hands its Domain
the pieces the Domain asks for by constructor, never the whole object, so
a Domain's signature is still the complete list of what it depends on and
a unit test builds one with a fake.
The Kernel now takes that object instead of an Env and a Log of its own:
`Kernel(Router $router, ServicesInterface $services, array $middleware)`.
The first iteration kept both and added the services as a fifth argument,
which handed the same Env over twice. ServicesInterface declares the two
properties the Kernel runs on, `env` and `log` — an interface may declare
properties as of PHP 8.4 — and nothing else, because past those two the
framework must not know or name what an application is made of.
- the Action stub takes `Services $services` beside the Request, so the
place a dependency comes from is in every generated file
- `inspect` recognises the role and lists what the class provides;
`context` carries a `services` entry. Both find the class by reflecting
the routed Actions' constructors, never by name, and never construct it
- the fixture application gains a Services class and an Action that uses
it; KernelTest asserts the object the Kernel is given is the one the
Action receives, and that an Action taking only the Request still routes
Not covered: routes/middleware.php still takes (Env, Log), because the
console builds that list to report it and cannot build the application's
services. A middleware that needs a connection has no explicit route yet.
BREAKING: Kernel::__construct() takes (Router, ServicesInterface, array)
in place of (Router, Env, Log, array). Every application must declare a
class implementing ServicesInterface with public Env $env and Log $log,
build it in public/index.php, and pass it to the Kernel.