Skip to content

v1.0.0-alpha-322

@ignis-celestis ignis-celestis tagged this 01 Aug 12:56
FeatureAccessMiddleware could not satisfy either of its declarations. The
allow path omitted `policy`; the deny path passed a `reason` the definition
never declared. MetricDefinitionRegistry matches label sets exactly, so the
middleware threw on the request it had just decided to permit, and would
equally have thrown on every denial — a 500 on every route carrying
#[RequiresFeatureAccess].

Adds `policy` to the allow emission, carrying 'none' when no policy is
registered, since in that case nothing evaluated and nothing decided the
allow. Adds `reason` to feature_access_denied_total, which is worth a label:
it separates a plan that never included the feature from a subscription that
lapsed. resolve() also documented a non-null policy it does not always
return, which PHPStan caught once the null branch became reachable.

Every existing test built the middleware with $telemetry = null, so no test
ever put an emission through a registry — which is how a metric that could
not be emitted shipped. The new cases run the real MetricDefinitionRegistry
over SecurityMetricDefinitions and reproduce the production throw.

Split from a8c198972e4be5d476506a0095a152620a8dddcb
Assets 2
Loading