winter/storm
Winter Storm is the Laravel-based core library behind Winter CMS, providing the module and plugin system, backend scaffolding, and shared helpers that power the platform. Use it to build or extend Winter CMS applications on a familiar, well-documented foundation.
Architecture fit. Storm is the substrate Winter CMS sits on — a Laravel-extension layer providing Halcyon (file-backed models), Argon (asset compilation/caching), an extendable behavior system, an event bus, and a genuinely useful Filesystem/PathResolver/Support set. It is a framework on top of a framework, not a drop-in utility. Fit is strong if the roadmap is a Winter CMS surface or a Winter plugin ecosystem; it is wrong-shaped for a standard Laravel SaaS, where adopting it means inheriting CMS domain abstractions (themes, plugins, behaviors) you don't need and coupling your release cadence to a CMS's. As a TPM the decision to force is scope: either a Winter-shaped platform is the product, or the only thing worth taking is the security-hardened path/filesystem core (PathResolver::resolve/within/join/standardize, Filesystem::isAbsolutePath/symbolizePath/normalizePath). Treat "adopt Storm" and "vendor the path helpers" as two different roadmap items with very different costs.
Integration feasibility. Composer-installable, MIT-licensed, moderate dependency graph (Laravel plus a spread of Symfony components: console, finder, process, yaml, string, http, mailer, mime). The unsolved question is bootstrapping: Storm assumes a Winter/October-style container, provider registration, facades, and possibly global helper function files in autoload. Registering it inside a plain Laravel app is not a documented path. The pure static helpers likely work once autoloaded; Halcyon/Argon/Database model extensions are where the container assumptions live. Feasibility is therefore "prove it in a spike," not "assume it works."
Technical risk.
Dependents: 0 is almost certainly a Packagist artefact (Winter's own manifest should depend on it), so treat it as unreliable rather than reassuring — the real point stands that standalone consumer base is effectively nil, and stars (51) leave no external bug-finder pool, semver promise you can put in a contract, or security advisory stream beyond Winter's own maintainers filing one.PathResolver::within() (GHSA-58fp, separator-boundary/prefix-collision). Both edges: the project fixes it at the correct layer and publishes advisories (positive signal, one of the strongest reasons to prefer the canonical implementation over a homegrown one); an outdated pin makes it a live path-traversal risk (strongest reason to pin and monitor).Key questions before committing.
PathResolver/Filesystem only, or Halcyon/Argon/Database extensions? This decides whether the roadmap item is one engineer-day or a multi-week framework marriage.composer.json autoload global helper function files? A name collision is a fatal boot error in every environment.Dependents: 0 real, and is any non-Winter project actually running this standalone in production?Stack fit. Laravel 10/11 and PHP 8.1+ (verify against the actual composer.json constraints before any commitment). Good fit if we are Laravel; no fit if our surface is Symfony-only or non-PHP. This is a library, so there is no user-facing rollout to plan — the sequencing risk is engineering-side only.
Migration path — phased and independently abandonable.
composer require winter/storm, resolve constraints, boot the provider, smoke-test PathResolver::resolve/within/join and Filesystem::isAbsolutePath. Exit criteria: no autoload or alias collisions, existing suite green, lockfile committed. This is the go/no-go gate.../../etc/passwd), prefix collision (/var/www/secret vs /var/www/secret_other), symlink escape, open_basedir behaviour, and Windows separators, so every future upgrade is gated on behaviour we already asserted. This is the deliverable a TPM can sign off on.Compatibility. Pin an exact version, commit the lockfile, and add Storm to the "check before upgrading Laravel" checklist. Confirm no clashes across facades, aliases, and globally-loaded helper functions during Phase 0. Decide in advance whether we will accept security backports only on Storm's current line or whether we will carry a patch if upstream moves on.
Sequencing. Budget roughly one engineer-week for Phase 0–1 including review. Put the alternative on the table explicitly: MIT permits vendoring. If the need is essentially one class, copy PathResolver (with MIT attribution) plus the same contract tests and skip the dependency — trading an external release cadence for a few hundred lines we own and can reason about. Counter-argument to record in the decision: the package's own guidance is that hand-rolled path logic is where traversal bugs appear, so vendoring must be a verbatim copy of the canonical code with tests, never a reimplementation. The AGENTS.md/README-per-module documentation is good enough to make a faithful copy realistic.
Maintenance. Low if we consume a sliver: we upgrade on our schedule, contract tests catch regressions, and the per-module READMEs plus the bundled AGENTS.md ("search Storm, then Laravel, then Symfony — never hand-roll") give new engineers a written doctrine rather than tribal knowledge. High if we ever need a patch: we would be maintaining a fork of a CMS substrate, with no upstream obligation to our use case. The AGENTS.md substitution table (Str/Arr/Collection, Symfony Finder/Process/Filesystem, data_get, collect) is adoptable on its own as an internal policy regardless of whether we install the code — that is a cheap, high-leverage artifact to carry into our own repos.
Support. GitHub issues triaged against Winter CMS priorities, plus the Winter community. No commercial support contract. Our non-CMS usage is an edge case upstream has no incentive to prioritise; escalation is maintainer goodwill only, on a codebase with a bus factor near one. Any decision to depend on it should ship with a pin-and-monitor plan and a named owner — not a hope that someone notices.
Scaling. Static helpers are request-scoped and scale trivially. The moment Halcyon (file-backed models) or Argon (asset compilation/caching) is in play, assumptions become filesystem-bound and single-node: no transactional semantics across distributed writers, and cache invalidation becomes our problem. Halcyon must not sit behind a horizontally-scaled write path without a design review — the operational conversation changes from "is this a library?" to "do we have a sharded-file-system problem?"
Failure modes to plan for.
Symfony\Component\Filesystem\Filesystem::dumpFile semantics) and backup coverage.open_basedir, and symlink behaviour diverging from Linux CI; mitigate with cross-platform tests if we ship to Windows hosts.Ramp-up. Two to five days for a Laravel-fluent engineer to be productive on the utility modules; the per-module READMEs are decent and the AGENTS.md search order enforces a useful discipline. Ramp-up is materially steeper for Halcyon/Argon — unfamiliar mental model, thin public corpus, and essentially no third-party tutorials or Stack Overflow coverage, so onboarding cost is real engineering time, not an afternoon of Googling. As TPM, plan for the utility path (cheap onboarding) and treat the substrate path (expensive onboarding) as requiring a named champion and an explicit resourcing decision.
Stakeholder framing. The pitch is not "we should use Winter CMS." It is "we should not be hand-rolling path sanitizers or helper utilities in 2025 — here is a hardened, audited reference and a policy for where logic belongs." The code is a citation; the policy and the contract tests are the deliverable. Position the dependency as bounded, surgical, and reversible, with a written exit path (vendor the classes if Storm's cadence ever hurts us) so the decision is safe to make now.
How can I help you explore Laravel packages today?