# Changelog All notable changes to `angeo/module-aeo-audit` will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [3.2.0] — 2026-07-15 > Security and tooling release. Hardens the Core Web Vitals checker's handling > of the CrUX API key and adds continuous integration. The CrUX checker gains a > constructor dependency (`Magento\\Framework\\Encryption\\EncryptorInterface`), > which Magento's object manager injects automatically — no configuration > changes are required. Upgrading from 3.1.x is drop-in (`composer update`, > then `bin/magento setup:upgrade && bin/magento setup:di:compile`). ### Security - **CrUX API key is now decrypted before use.** The key is stored encrypted (`Magento\\Config\\Model\\Config\\Backend\\Encrypted`); the checker now decrypts it via `EncryptorInterface` instead of reading the raw stored value. A value that fails to decrypt (rotated crypt key, corrupted data) is treated exactly like an unconfigured key — a garbage credential is never transmitted. - **CrUX API key moved out of the request URL.** The key was previously sent as a `?key=` query parameter, where it leaks into web-server access logs, proxy logs and browser history. It now travels in the `X-Goog-Api-Key` request header. - **TLS verification re-enabled for the CrUX call.** The external request was made with peer/host verification disabled, exposing it to man-in-the-middle interception of the API key and response. The call now goes through `HttpCache`, which keeps TLS verification on and restricts protocols, matching the module-wide HTTP security posture. ### Added -- **Continuous integration.** GitHub Actions pipeline running PHPCS, PHPStan and PHPUnit against PHP 8.2–8.4 on every push and pull request. - **Build-status badge** in the README, backed by the CI workflow. - **Official distribution channels** section clarifying that installation needs no custom Composer repository — only Packagist and GitHub are supported. ### Changed - **PHP 8.5 and Magento 2.4.9 declared.** `composer.json` now allows PHP 8.2–8.5; compatibility table and badges updated accordingly. - **PHPUnit accepts ^10.5 || ^11.0 || ^12.0** to match the 2.4.7–2.4.9 toolchains, with a version-agnostic `phpunit.xml` and a dedicated `Test/bootstrap.php`. ### Notes - Static analysis (PHPStan) is run locally against a real Magento install and is intentionally not part of CI, since it requires the full framework. ## [3.1.0] — 2026-06-10 > Minor release. Adds per-signal enable/disable configuration, configurable > sitemap placeholder-slug handling, and fixes two false-signal bugs in the > sitemap checker. Fully backward compatible — no interface or DB changes. ### Added - **Per-signal configuration.** Every one of the 15 signals can now be enabled or disabled individually under **Stores → Configuration → Angeo AEO → AEO Audit → Signals (Checks)**. All signals are **enabled by default**, so a fresh install behaves exactly as before. Disabled signals are skipped during the audit and excluded from the score entirely — they neither raise nor lower it (removed from both numerator and denominator). Settings are store-scoped. - **Configurable sitemap placeholder-slug handling.** New group **Angeo AEO → AEO Audit → Sitemap Checker**: - `Placeholder slug handling` — *Affect score* (default) or *Ignore* (report-only, never changes status/score). - `Placeholder slug threshold` — how many placeholder slugs are tolerated before the score is affected (default 1). - New `Angeo\AeoAudit\Model\Config` — a single typed reader for all module settings, so checkers no longer touch `ScopeConfig` directly. - New `Angeo\AeoAudit\Model\Config\Source\SlugMode` option source. - Unit tests: disabled-checker skipping in `AuditRunner`; sitemap foreign-element FAIL; placeholder-slug score/ignore modes; disproportion-false-positive regression. ### Fixed - **Sitemap: false "disproportion" warning.** The v3 check compared sitemap URL count against active **products only**, but a sitemap also lists the homepage, CMS pages and categories — so healthy stores were frequently warned. URL count is now compared against the full indexable surface (products + categories + CMS pages) and reported as **informational context only** (`coverage_ratio`); it never changes the result status. - **Sitemap: false "stale" warning.** Staleness was computed from the **first** `` in the file, so a single old entry (often the homepage or a CMS page) flagged the whole sitemap as stale. A legitimately unchanged product *should* keep an old `` — that is honest metadata, not a defect. The check now inspects the **newest** `` across the file and only warns if nothing at all has changed in 180 days (a sign of a broken generation cron). Individual old entries are informational only. ### Added — sitemap structural integrity - **Sitemap: foreign-element detection.** Non-sitemap elements injected directly into `` (e.g. a stray `