channor/opaque-route-key
Laravel package that swaps numeric route model binding keys for opaque, non-guessable identifiers, so URLs stop exposing sequential IDs. Simple setup, works with existing route model binding, and helps keep internal IDs and resource counts private.
What the package is. channor/opaque-route-key generates opaque route keys for Laravel route-model binding, so externally visible URLs don't expose sequential primary keys. Integration surface is deliberately narrow: a service provider, a config file, a salt, a model trait, and route binding resolution. No external service, no datastore, no runtime infrastructure.
What v2.0.0 actually is. This is a cleanup major, not a feature release. It deletes the accumulated v1 compatibility scaffolding:
Channor\HashedRouteKey compatibility layer (class/API removed outright).hashed-route-key config file.HASHED_ROUTE_KEY_SALT environment fallback.replace metadata.Crucially, the release notes state that codec defaults and attempt-0 behavior are preserved, and auto_reserve_model_names remains defaulted to false. That is the right signal for a major: the URL format is intended to be byte-identical to v1, and the break is at the configuration/namespace level only. This makes it a low-code-change, high-verification upgrade.
Architecture fit. High. It is framework-idiomatic Laravel (provider + config + trait), which means it inherits Laravel's config caching, env loading, and package discovery semantics. That cuts both ways: the same mechanisms that make it trivial to install also make misconfiguration silent rather than loud.
Integration feasibility. Mechanically easy — bump the Composer constraint, publish the new config, grep for legacy symbols. The difficulty is not effort, it is evidence: we must prove key output is unchanged for existing data before we ship.
Technical risk: medium. Four discrete risks, in descending severity:
HASHED_ROUTE_KEY_SALT fallback means any environment that supplied the salt only via env now resolves a salt from somewhere else. If that happens, every previously issued URL 404s — including URLs already persisted outside our control (transactional emails, notifications, sitemaps, webhooks, partner integrations, QR codes). This failure is silent at write time and only surfaces as traffic loss.use Channor\HashedRouteKey;, typehint, container binding, or model override still pointing at the v1 class becomes a fatal error at runtime, not install time.replace removal. Apps or internal packages that satisfied a requirement on the legacy package name via replace will now hit resolution conflicts or attempt a duplicate install (two packages fighting over the same trait/config).config/hashed-route-key.php plus a cached config store will be inert rather than erroring — the app runs, ignores the file, and behaves unexpectedly.Key questions before approval:
APP_KEY?replace require coordinated releases of any internal packages that depended on the old name?docs/upgrade-v2.md and that it documents the salt migration, not just the class removal.Stack fit. Drop-in for a standard Laravel app using Composer, package auto-discovery, and route-model binding. No queue, cache, or storage implications. Nothing about this package touches request lifecycle beyond route resolution.
Compatibility. v2 is explicitly not backward compatible at the symbol and configuration level. The supported coexistence pattern is documented and blunt: stay on channor/opaque-route-key:^1.1 if you still need the Channor\HashedRouteKey API. That means this is an all-in cutover per application — no partial migration, no side-by-side v1/v2 within one app. If we run multiple services, each service cuts over independently, which is acceptable only because the key format is stable; if it weren't, cross-service URL handoff would break.
Migration path.
Channor\HashedRouteKey, hashed-route-key, HASHED_ROUTE_KEY_SALT, and the legacy publish tag — including deploy scripts, Dockerfiles, Helm charts, and CI configs, which are the usual blind spots.^2.0 on a branch, resolve, run the full suite plus the golden-vector test..env.example in the same pull request so no environment drifts between the two.Sequencing. Config and code must ship together. For rolling or blue/green deploys, old and new instances will briefly coexist; this is safe only because the codec defaults are preserved and both read the same salt. Deploy order: config/secret updated first, then application code, with config:clear && config:cache as an explicit deploy step (a cached-config deploy that skips this will run v2 against v1's cached config). Keep the v1 pin available as a rollback target — rollback is safe precisely because key output is unchanged.
Maintenance. Net positive. Deleting the compat layer, legacy config, and replace metadata permanently shrinks the maintenance surface — fewer moving parts to reason about at the next major. The cost is concentrated entirely in this one upgrade window.
Support. Mixed. Positives: a dedicated docs/upgrade-v2.md and an explicit, unambiguous fallback recommendation (^1.1). Negatives: the release notes describe removals but not replacements — they never state the new config filename, the new env var, or the new default salt source. That is the single piece of information an operator needs, and it lives behind a link. Support load will spike if the upgrade guide omits a "if you see 404s after upgrading, check X" section. Recommend we contribute that troubleshooting note upstream.
Scaling. No impact. Key generation is a pure per-request computation with no I/O, no cache dependency, and no shared state. Attempt-0 behavior being preserved means no change in generation cost or collision characteristics. Database indexes on route-key columns are untouched. This package will never be a scaling bottleneck.
Failure modes, in order of what will actually page someone:
Class not found. Loud and immediate — the preferable failure. Caught by the grep in step 1 and by a staging smoke test.^1.1 is non-destructive — no data written under v2 becomes unreadable. This materially lowers the risk of the whole change and should be stated explicitly in the change record.Ramp-up. Low, roughly half a day for an engineer familiar with Laravel config and env semantics, plus review time. The conceptual model ("we removed the shims, the keys are the same, here's where the salt lives now") is easy to convey. The ramp-up risk is not skill, it is discipline: the upgrade punishes teams who skip the environment audit, because nothing about v2 will tell them they missed an environment until a link breaks.
Recommendation. Approve the upgrade, gated on two conditions: (1) the golden-vector parity test passes against production-derived keys, and (2) the salt is confirmed present in every environment through the new config path before code ships. If either cannot be demonstrated, stay on ^1.1 — it remains explicitly supported and there is no security or functional driver forcing v2.
How can I help you explore Laravel packages today?