orchestra/support-core
Core support utilities for the Orchestra Platform, providing shared helpers, service providers, and foundational traits that other Orchestra packages build on. Lightweight, framework-agnostic glue for Laravel applications that need a consistent base for extension development.
Architecture fit. orchestra/support-core is a foundation library, not a feature package. Its contents — service-provider base classes, reusable traits, string/array/HTML helpers, and extension contracts — are the commodity plumbing every Laravel service writes for itself. That means it does not slot into a product architecture as a capability; it slots in as a convention layer. The architecture question is therefore not "does this fit our domain" but "do we want one shared convention layer, and is this the one we standardize on." Its natural home is Orchestra Platform extension work and multi-codebase Laravel estates with visible drift (three HTML escapers, four incompatible extension interfaces). For a single service, the overlap with illuminate/support (Str, Arr, Htmlable) makes it a net-negative addition.
Integration feasibility. Technically trivial. v7.0.0 requires Laravel 9+ (transitively PHP 8.0+), installs with a single composer require orchestra/support-core:^7.0, and in most realistic scenarios arrives transitively via orchestra/testbench or another Orchestra component. The day-one value is concrete and low-risk: subclass the Orchestra provider base instead of hand-rolling register()/boot()/mergeConfigFrom() for the Nth time. The high-risk surface is the helpers and traits, because those end up inside application code where replacement becomes a codebase-wide edit. Feasibility is high; the constraint is governance, not engineering.
Technical risk. Four risks dominate, and none are exotic:
"9+" is not an automatic forward-compatibility guarantee.illuminate/* constraints, and may reshape helper signatures. Assume breakage; diff src/ between locked v6 and v7 rather than trusting the note.files can fatal on redeclaration if we define a same-named function, and HTML/string helpers sit directly on rendering paths where an escaping change is security-relevant.Key questions.
illuminate/* and php constraint in the installed composer.json — ^9.0 (dead end at Laravel 10) or a multi-major range?extra.laravel.providers, or does it stay inert until we extend it?files? If so, which function names are now reserved in our global namespace?grep -rn 'Orchestra\\Support' app/ packages/ return today?composer why orchestra/support-core), and can we exclude it if we don't want it?Stack fit. Laravel 9+ / PHP 8.0+ only. Do not attempt this on a Laravel 8 host — you get a resolver failure or an unsupported workaround. It is designed to stay framework-agnostic where possible, but the operative constraint is the Laravel floor, and the package is a first-class fit for Orchestra Platform work and a marginal fit everywhere else. Approve it as scoped foundation for Orchestra-based work; do not let it become the platform-wide standard by accident.
Migration path.
composer why orchestra/support-core (transitive? from what? excludable?) → composer show orchestra/support-core (what actually resolved) → grep the illuminate/php constraints → grep -rn 'Orchestra\\Support' app/ packages/. That grep result is the blast radius; capture it before and after every bump.composer update. If we're on Laravel 8, stay on the last v6 release, plan the framework upgrade first, and treat v6 as having no security-patch commitment.src/ tree between locked v6 and v7 to surface the undisclosed breaking-change surface the one-line changelog omits.php artisan about, php artisan config:cache, and one end-to-end feature test that resolves a real binding.^7.0 explicitly in every composer.json that inherits it, even transitively, so resolver drift is visible in the diff rather than discovered in an incident.Compatibility. Two compatibility obligations: the runtime floor (Laravel 9+/PHP 8.0+) and the behavioural contract of the HTML/string helpers. Treat the latter as API. Use contract-first integration where possible — bind our own implementations to interfaces in our provider rather than extending Orchestra's concrete classes — so Orchestra stays out of our type signatures and a future replacement is a rebind, not a rewrite. Apply trait composition only to classes we own; traits are compile-time coupling, and use-ing them inside models or jobs makes mocking invasive. Guard any helper we add with function_exists() to avoid a fatal redeclare against the package's files autoload.
Sequencing (recommended order).
composer.json (this gates the roadmap answer).support-core v7 bump, pinned, isolated in its own PR.Maintenance. We own the surface, not the vendor. The package gives us no changelog beyond one line, no deprecation policy, and no support tier, so the maintenance burden we're accepting is our own documentation of what we use. Mitigations are cheap and should be non-negotiable: the wrapper adapter, a documented inventory of helpers and traits in use, explicit pins, and a rollback path that is one composer require line rather than a refactor. Add the package to the dependency-review cadence and re-verify framework support by hand at each Laravel major — the "9+" wording buys us nothing automatically.
Support. There is no vendor support tier, effectively no external user base to lean on, and a single-maintainer ecosystem project behind it. Practically, internal escalation goes to whoever on our side adopted it. That is a fine arrangement for package scaffolding and internal tooling; it is not an arrangement to put on a customer-facing request path without a written risk acceptance.
Scaling. Runtime footprint is negligible — it is a thin utility layer, and performance is a non-issue. The scaling concerns are organizational: (a) the more codebases that adopt it, the harder the build-vs-buy answer is to reverse, so the usage policy should scale with adoption rather than lag it; and (b) helper changes bypass config:cache because files autoloads aren't cached, meaning a helper change requires composer dump-autoload and won't be caught by the usual config-clear reflex. Standardize once at the platform level rather than letting each team decide, or you get the drift you adopted the package to eliminate.
Failure modes (ranked by likelihood × impact).
{{ }} with a raw helper call on user input.files autoload plus a same-named function equals a hard fatal. Mitigation: function_exists() guards on everything we add.composer.lock or an unknown transitive constraint. The most common day-to-day cause of "clearly exists but won't resolve." Mitigation: the debugging checklist — composer why → composer show → grep the constraint → php artisan about → config:cache → one feature test through the binding.boot() may not exist, producing BindingResolutionException on a class that plainly exists. Mitigation: check deferral before restructuring anything.vendor:publish --force overwrites edits. Mitigation: review the diff before forcing in production-adjacent environments.Ramp-up. Low, and that's part of the appeal. The API surface is small and conventional — a provider base class, a handful of traits, helpers, and contracts — so a Laravel-competent engineer is productive in under a day. The ramp-up that actually matters is the policy ramp, not the API: engineers must learn the two rules that keep the exit reversible — don't call helpers directly, call the adapter; don't apply traits to vendor classes. If those two rules are in the contributing guide and enforced in review, onboarding cost stays near zero and the build-vs-buy decision remains reversible. If they aren't, the coupling cost compounds silently and we discover it at the next framework major.
How can I help you explore Laravel packages today?