v2.11.1
One fix, for a defect introduced by v2.11.0's user-agent caching.
If your logs show the UserAgent plugin working normally but the site feels slow, this release is why you could not see the cause. An unwritable cache directory made every request re-parse the full detection corpus — roughly 645 ms instead of ~20 ms — while the only log line reported the cache as successfully initialised.
No configuration changes. No behaviour changes to detection, rules, or anything else.
PHP 8.1–8.5 supported.
Fixes
-
The user-agent cache is now verified before it is trusted.
Constructing a cache pool proves nothing. Symfony's
FilesystemAdapteris created quite happily against a directory it cannot write to, and only fails later, on each individual write. v2.11.0 took successful construction as success, logged[DEBUG] User Agent regex cache initializedand then re-parsed the 1.7 MB detection corpus on every single request, indefinitely, with nothing above
debugto say so.The plugin now writes and reads back a probe value before trusting a pool. When that value does not come back:
[WARNING] User Agent regex cache is not writable - every request will re-parse the detection corpusThe context carries the impact and the three ways out. Falling back to running uncached is still the right behaviour — an optimisation must not be able to take a site down — but it has to be visible. A 30× slowdown that reports itself as healthy is worse than one that reports nothing at all.
A round trip rather than an
is_writable()check, deliberately: the pool may be a filesystem directory, Redis, APCu, or an instance injected through configuration overrides, and the only property that matters is whether a value written now can be read back. It costs a fraction of a millisecond and runs once per plugin instance, not once per evaluation.
Who is affected
Anyone on v2.11.0 whose cache location is not writable by the PHP user. That is not an exotic situation — a read-only container filesystem, a KANOPI_FIREWALL_CACHE_DIR owned by the deploying user rather than the web user, or an open_basedir that excludes the system temp directory all produce it.
If the cache is writable, v2.11.0 was already behaving correctly and this release changes nothing for you.
To check without upgrading, look for User Agent regex cache initialized at debug and confirm the directory it names actually contains files after a request.
Upgrade notes
-
composer update kanopi/firewall, and nothing else. No config to change, no new dependencies, no rule behaviour altered. -
After upgrading, check your logs once at
warninglevel. If the new message appears, the cache has never been working and the fix has simply made that visible. Pointmetadata.cache.dirat a writable directory, defineKANOPI_FIREWALL_CACHE_DIR, or setmetadata.cache: falseto accept the cost deliberately and silence it. -
Nothing needs clearing.
device-detectorkeys its cache entries by its own version, so upgrades invalidate them without help.
Internal
-
Three regression tests: the unwritable case, that the probe does not reject a cache which works, and that the probe leaves nothing behind that could be mistaken for corpus data.
-
Suite: 1,015 unit tests and 49 integration tests pass. PHPCS, PHPStan at level max and Rector are clean, and
bin/firewall-checkis clean at level max despite sitting outside thesrc/-scoped gates. The 2 reported deprecations are a pre-existingReflectionProperty::setValue()call inLoggingFactoryTest, unrelated to this release. -
ConfigTest::testFileGetContentsSuccessSameProcessreacheshttps://example.comand is flaky on a cold network. It failed once during this work and passes in isolation; it is unrelated to the fix, but worth knowing if CI trips on it.