rapira/contract
Shared contracts and interfaces for the Rapira Laravel ecosystem. rapira/contract provides stable abstractions that keep packages decoupled and make it easier to build extensible, maintainable applications. Depend on contracts instead of concrete implementations for cleaner, more portable code.
Architecture fit. Release 0.9.1 materially changes the earlier read. The note — “let the stub functions answer through a runtime double” — confirms the package ships executable stub functions, not just interfaces and DTOs. That makes it a client-side stub layer for the Rapira contract, with a swappable runtime for testing. Architecturally that is legitimate, but it belongs in the adapter/infrastructure layer, never in domain or application code. The positive signal is that the maintainer has built an explicit testing seam; a package with a runtime double is easier to verify than one with only opaque stubs. The negative signal is that the package now carries runtime behavior, resolution logic, and likely a binding mechanism, all of which can leak into production if the double is selectable by configuration rather than by test-only construction.
Integration feasibility. Composer installation remains trivial. Integration now includes answering a new class of question: how are stub functions resolved, and how is the runtime double selected? If the double is activated through a container binding or a static runtime registry, test isolation and production safety both depend on that mechanism being explicit and fail-closed. If it is activated through a config flag, the integration must include a deployment assertion that the flag is off outside tests. The package is still pre-1.0 at 0.9.1, so feature releases in the 0.9.x line can carry breaking API changes.
Technical risk. The dominant risks have shifted:
Key questions to resolve before adoption.
php and illuminate/* constraints, and is there a test suite covering the double?Stack fit. The package now fits as an adapter-layer dependency with a testing facility. It should be required in production only if the stubs are used by the adapter; the runtime double should be treated as test infrastructure even if it ships in the same package. Verify PSR-4 namespace, auto-discovery, and whether the double is namespaced under a Testing or Double sub-namespace that can be excluded or guarded.
Migration path. The earlier isolation advice is now mandatory rather than advisory:
Rapira\Contract\* or any stub function directly.Compatibility. Check composer why-not against our PHP and Laravel versions. If the package declares no illuminate/* constraints, that is good for compatibility but weak evidence of Laravel testing. Confirm the generated stubs do not require a PHP extension or a specific runtime version beyond our platform. Confirm the runtime double does not introduce a dev-only dependency into the production autoload graph.
Sequencing. Two sprints remains appropriate, with sharper acceptance criteria:
Maintenance. The package now has a generation surface. Budget recurring effort to regenerate or verify stubs whenever the Rust contract changes, and to re-run the contract test suite on each Laravel upgrade. The adapter layer keeps that cost bounded, but the generation step is a new operational task that did not exist under the contracts-only assumption.
Support. Support remains direct-to-maintainer. Establish a human contact in the Rapira org and confirm whether issues and PRs are triaged. With a runtime double now in the package, support questions are likely to include test-double behavior, which makes upstream responsiveness more valuable than before.
Scaling. Stub functions imply serialization and transport boundaries. Test-double performance is irrelevant at scale, but production stub overhead is not. Benchmark the PHP-side serialization path against expected payload volumes, especially if the Rust side is highly optimized. Organizationally, the risk is that multiple teams adopt the stubs independently and diverge in how they configure the runtime; central ownership of the adapter and the double guard is the mitigation.
Failure modes.
| Failure | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Runtime double active in production | Medium | Fabricated responses, silent data corruption | Fail-closed activation; deployment assertion; adapter guard |
| Stub drift from Rust contract | Medium–High | Runtime deserialization or method-not-found errors | Generated-stub verification in CI; live contract tests |
| Static or global runtime state | Medium | Test bleed, order-dependent failures | Prefer constructor injection; audit resolution mechanism |
| Breaking change under 0.9.x | Medium | Fatal errors | Exact version pin; adapter isolation |
| Unexpected service provider or facade | Medium | Container pollution, boot-order issues | Source review before adoption |
| Upstream abandonment | Medium | No patches for new Laravel majors | Internal fork; pinned version |
| Future-dated release artifact | Low–Medium | Unstable API surface | Verify git tags, not Packagist metadata |
Ramp-up. The package itself remains sub-hour onboarding for a Laravel team. The new learning curve is the stub and double mechanism: how stubs are generated, how the double is selected, and how to keep the two separated across environments. Estimate one engineer-week to independent contribution, most of it spent on the Rapira contract semantics and the generation workflow rather than on Laravel integration. Document the double guard and the generation command in the repository; those two documents are the onboarding artifacts that matter.
Recommendation. Conditionally viable, with a higher bar than before. Release 0.9.1 resolves the “is it contracts-only?” question in the negative: it is a stub layer with a runtime double. That is workable if the double can be made fail-closed and the stubs are generated from the Rust source of truth. If either condition cannot be demonstrated in the Sprint 1 spike, define the boundary types internally and use this package as reference material rather than a dependency. The testing seam is a genuine positive; the production-safety question is now the deciding factor.
How can I help you explore Laravel packages today?