Skip to content

1.0.5

Choose a tag to compare

@goldnead goldnead released this 05 Aug 06:04
· 51 commits to main since this release

Changed — the route parameter guard checks the rule, not a snapshot of the siblings

No defect in this addon, no route changed, and nothing in src/ was touched. What changed is that 1.0.4's guard test was asserting something false.

That test carried a hand-written map of the names other installed packages bind application-wide, and it named webhook, endpoint, rule and template as claimed by goldnead/statamic-webhook-manager and automation as claimed by goldnead/statamic-automations. Webhook-manager renamed its four in its 1.7.0 and automations renamed its one in its 1.6.0. All five names are free. The entries were harmless — an entry for a name nobody binds matches nothing, which is why the suite stayed green — but a check that describes the world incorrectly is a check nobody can rely on, and correcting the five names would only have reset the clock on the same problem.

A snapshot of the siblings can only ever describe them as they are today. It says nothing about the addon that starts binding {handle} next month, which is exactly the case that hurts, and it has to be maintained by five repositories at once. What replaces it is the rule webhook-manager arrived at in its 1.7.0:

A Route::bind() is registered on the router, not on the package that calls it. Bind only names that unambiguously belong to your addon — specific enough that no sibling would reach for one by accident. Names you do not bind may stay as generic as they like: nothing resolves them, so nothing can be taken from anyone.

That is a property of this package, so this package's own suite can enforce it without knowing anything about its neighbours.

it binds only parameter names that belong to this addon reads the Route::bind() calls out of this package's own src/ — comments stripped, string literals only, and a call whose name is not a literal fails the test rather than escaping it — and requires every name found to match activity + a capital. This addon binds nothing at all today, so the rule costs it nothing, which is precisely why it is worth pinning now: the binding that hurts is never the one somebody weighed, it is the one added later because binding by the entity's obvious name looked like the obvious thing to do.

it does not swallow a sibling addon's generic route parameter is the behavioural half. tests/TestCase.php now mounts stand-in routes for a sibling package — {automation}, {rule}, {template}, {webhook}, {endpoint}, {handle}, {id}, {slug}, {record}, each doing nothing but echoing its own value — and the test asserts every one answers with what it was given. They live in the bed rather than in the test body deliberately: a route added from inside a test body is shadowed by Statamic's {segments?} frontend catch-all and answers 404 whatever the bindings do, which would have made the check pass for the wrong reason.

Demonstrated rather than asserted: with a Route::bind('handle', …) added to a service provider in this family, the old three-test file stayed green on all three, while the new file fails three of its five and names {handle} in both directions — once as bound-but-not-ours, once as a sibling route answering 404 instead of its own value.

1.0.4's first test is kept as it was: it pins that the CP bed mounts SubstituteBindings, without which no Route::bind() has any effect in tests and the whole file would pass for nothing. So is the check against statamic/cms, reduced to the ten CMS entity names it actually binds — that list is third-party, short and stable, and stays hand-kept for the same reason the sibling list could not.

What deliberately did not change: {id}, this addon's only route parameter. It is as generic as a name gets and it is staying. Renaming it would move text without removing any exposure, because it is not bound — nothing resolves it, so nothing can collide. The rule above is what protects it.