arch-02 reproduction
Public source retained with the related article. Generated results, dependency directories, runtime storage, secrets, and oversized binary artifacts are intentionally excluded.
README
# ARCH-02 composition-root experiment
This fixture supports the planned article *A Composition Root Makes Choices
Visible*. It compares two Laravel quote use cases with the same request and
response:
- `QuoteProduct` declares `ProductPrices` in its constructor, and a registered
service provider selects the HTTP adapter; and
- `LocatedQuoteProduct` has no constructor dependency and resolves a configured
adapter from Laravel's container inside `execute()`.
The experiment asks when Laravel can detect an incomplete object graph and
where a reviewer can discover the adapter choice. It does not treat container
resolution time or file count as design evidence.
## Run it
Docker is the only host dependency.
```sh
./run.sh
```
The runner builds a digest-pinned image and retains commands, exits, durations,
responses, failures, source diffs, and generated composition reports under
`results/`.
## Behavior and resolution matrix
| Case | Expected result |
| --- | --- |
| explicit v1 with provider v1 | request passes |
| explicit v1 with provider v2 | mapping fails at the v1 field |
| explicit v2 with provider v2 | request passes |
| located v2 with provider v2 | request passes |
| explicit binding present | `QuoteProduct` resolves without invoking it |
| explicit binding missing | resolution raises the expected binding error before invocation |
| located entry invalid | `LocatedQuoteProduct` resolves, then invocation raises the expected entry error |
The missing-selection cases are PHPUnit integration contracts. Their commands
exit successfully only when the expected Laravel exception occurs at the
declared boundary. Retained output records whether the application method was
invoked.
## Source controls
`analyze.php` reads the committed PHP and configuration files. It verifies the
registered provider, `ProductPrices` binding, constructor dependency, both
adapter choices, framework-free explicit application, and deliberate located
lookup. Three owned controls must be rejected independently:
- application code calling the container;
- a provider absent from `bootstrap/providers.php`; and
- a registered provider without a `ProductPrices` binding.
## Boundary of the conclusion
Laravel feature requests are in-process integration evidence, not real inbound
network requests. The catalogue adapter does cross a real local HTTP process
boundary. The fixture proves the owned container graph, failure timing,
provider-body mapping, and source inventory. It does not prove DNS, TLS,
credentials, deployment behavior, debugging speed, or a universal provider
layout.
Retained files
- .dockerignore
- analyze.php
- app/Application/ProductPrices.php
- app/Application/Quote.php
- app/Application/QuoteProduct.php
- app/Http/ExplicitQuoteController.php
- app/Http/LocatedQuoteController.php
- app/Infrastructure/V1HttpProductPrices.php
- app/Infrastructure/V2HttpProductPrices.php
- app/Located/LocatedQuoteProduct.php
- app/Providers/ArchitectureServiceProvider.php
- bin/test-with-provider.sh
- bootstrap/app.php
- bootstrap/providers.php
- compare.php
- composer.json
- composer.lock
- config/logging.php
- config/services.php
- Dockerfile
- phpunit-resolution.xml
- phpunit.xml
- provider/router.php
- README.md
- routes/web.php
- run.sh
- tests/Feature/QuoteRequestTest.php
- tests/fixtures/LocatorDefect.php
- tests/fixtures/ProviderMissingBinding.php
- tests/fixtures/providers-missing.php
- tests/Integration/CompositionResolutionTest.php
- tests/TestCase.php