Product Decisions This Supports
- Architecture strategy: DDD vs. framework-default CRUD. A "shared kernel" is the DDD pattern for a small, deliberately co-owned set of domain primitives (identifiers, value objects, money, collections, pagination, domain-event abstractions) shared between bounded contexts. Evaluating this package forces the real decision: are we adopting tactical DDD patterns in our Laravel codebase, or staying with Eloquent models and service classes? That choice drives hiring profile, code review standards, and sprint velocity for the next 12–18 months.
- Build vs. buy vs. borrow for internal infrastructure. The honest read is still borrow. The v0.9.8 release is a pulse, not a heartbeat: a single visibility change to Tactician event-subscriber definitions to fix a Symfony 4 conflict. Symfony 4 reached end-of-life in November 2019. A maintainer patching for a dead framework version is a signal that the library is frozen in its original 2017–2018 context, not that it is being modernized. Recommendation is unchanged: mine the patterns, own the code.
- Dependency-graph due diligence. The release note is the most informative artifact published in six years, and what it reveals is coupling: the package is wired into League Tactician's command bus and the Symfony event dispatcher, not into Laravel's own event system. Adding it to a Laravel app means inheriting a second eventing model, a command-bus abstraction, and transitive maintenance obligations on libraries with their own thin release cadence. That is a strong argument for a ~300-line in-house kernel over a dependency.
- Roadmap sequencing for modularization. Extracting a shared kernel is a late-stage refactor. It only pays off after you have at least two bounded contexts duplicating the same concepts. If we are pre-product-market-fit or single-domain, this package is not on the critical path; file it under "Q3+ if we split the monolith."
- Standards and vocabulary alignment. Even if we never install it, the package is a cheap artifact for aligning engineering on naming: what a
Uuid, AggregateId, or DomainEvent looks like in our codebase. The v0.9.8 diff is a useful second lesson — it shows how framework-version pinning leaks into a domain layer, which is exactly what we want our internal kernel to avoid. Useful input to an internal RFC.
- Dependency governance policy. A concrete test case for our rule on unmaintained packages: permissively licensed (MIT), stale major-version assumptions, and a fresh patch release that does not change the risk profile. Answer used here: fork-and-vendor only if we need it; otherwise pattern-mine it and move on.
When to Consider This Package
Consider (as reference material) when:
- We are actively designing a modular monolith or service split and need a concrete, small example of shared-kernel boundaries in PHP.
- The team is new to DDD in Laravel and wants a real-world (if modest) artifact to critique in a design review — reading code is cheaper than a workshop.
- We want a sanity check on our own value-object conventions before freezing them in an internal package.
- We want a cautionary example of domain code coupled to a specific Symfony major version, to justify keeping our kernel framework-agnostic.
Look elsewhere / do not adopt as a dependency when:
- Runtime risk matters. v0.9.8 is the first release since 2018-09-28, and it is a one-line compatibility fix for Symfony 4 — a framework that has been EOL for years. There is no evidence of a PHP 8.2+/8.3 pass, no Laravel 10/11 support statement, no security process, and no issue triage. A single visibility patch does not constitute a maintenance commitment; anything on our production request path should not sit on this.
- We want framework-native eventing. The release confirms the package is built around League Tactician and the Symfony event dispatcher. In a Laravel codebase this duplicates
Event/Listener and queued jobs. Prefer Laravel-native events, or mature DDD tooling (Broadway, Prooph, EventEngine) if we genuinely need CQRS or event sourcing. For value objects, moneyphp/money, ramsey/uuid, and brick/math cover the 80% case with active maintenance.
- We are a single bounded context. A shared kernel with one consumer is just a folder. Put the classes under
app/Domain/Support and skip the ceremony.
- Licensing hygiene is the only question. MIT is permissive — forking and vendoring is legally uncomplicated. That mitigates abandonment risk, but it converts "dependency management" into "we now maintain a fork," which is a real, recurring cost. The Tactician/Symfony coupling raises the surface area of that fork.
If we do proceed: fork it, pin it, treat it as vendored source (not a Composer dependency), strip the Tactician/Symfony event wiring on day one and re-express events on Laravel's dispatcher, add it to the upgrade checklist for each PHP/Laravel major, and assign an owner by name.
How to Pitch It (Stakeholders)
For executives (one paragraph):
This is a small, MIT-licensed PHP library from a Spanish digital agency that packages up the "shared vocabulary" classes used across their projects. It is functionally interesting but commercially dormant — one GitHub star, no downstream users, and a six-year gap between releases. The one release that just appeared is a one-line fix for a Symfony version that itself went out of support in 2019, so it does not change our risk read. We are not recommending it as a production dependency. We are recommending we spend a few hours reading it as a reference while we set our own conventions, and that we capture the outcome as an internal, owned package. Net cost: roughly one engineer-day. Net benefit: we avoid paying for a dependency we would end up maintaining anyway, and we avoid the slower path of discovering these patterns mid-refactor.
For engineering leads:
It is a pattern source, not a dependency. Adopt the ideas — explicit IDs, immutable value objects, a thin domain-event contract — and write our own ~200–400 lines behind our namespace with our tests and our PHP version support. The new v0.9.8 tag is not a revival: it makes Tactician event-subscriber definitions public to dodge a Symfony 4 conflict, which tells us the domain layer is entangled with a command bus and an EOL event dispatcher. That is precisely the coupling we should refuse to inherit. If we pull any file from it directly, MIT permits it; keep the attribution header and log the provenance in our third-party notice file — and remove the Symfony-specific wiring before it lands.
For the design review:
Use it as the discussion prompt for three questions: (1) which concepts genuinely belong in our shared kernel versus which are context-local; (2) what is our deprecation path when a shared kernel class changes — the failure mode the upstream project never had to solve with only one consumer; and (3) how do we keep the kernel free of any single framework's event or bus abstractions, given that the upstream library's most recent change exists solely because it did not.