# Changelog

## Score

- CAI 74 → 67 (-6.5)
- Rubric changed (rubric-2026.10.1 → rubric-2026.10.5) — scores are not directly comparable.

## Lenses

- Code Health 95 → 71 (-24.1)
- Architecture 97 → 97 (+0.0)
- Maturity 59 → 54 (-4.7)
- Readiness 90 → 90 (+0.0)
- Security 81 → 81 (+0.0)

## Resolved (5)

- Duplicate high-level convenience methods across multiple types. `Geocoder`, `GeocoderTrait`, `ProviderAggregator`, and `StatefulGeocoder` all expose `geocode(string)` and `reverse(float, float)` methods. While `Geocoder` is the static facade and `ProviderAggregator`/`StatefulGeocoder` are implementations, the existence of `GeocoderTrait` which duplicates these exact signatures alongside the `*Query` variants creates confusion about which entry point to use. Specifically, `GeocoderTrait` is a trait, meaning it injects these methods into any class using it (like `ProviderAggregator` or `StatefulGeocoder`), but `ProviderAggregator` also explicitly lists them in its public surface, suggesting redundancy or a leak of trait implementation details into the public API contract.
- Inconsistent factory method naming and return types. `GeocodeQuery` uses `create` and returns `self`, while `ReverseQuery` has both `create` (returning unspecified type, likely `self` but inconsistent with GeocodeQuery's explicit `self`) and `fromCoordinates` (returning `self`). The presence of two factory methods for `ReverseQuery` (`create` and `fromCoordinates`) when `GeocodeQuery` only has `create` is inconsistent. Furthermore, `GeocodeQuery` lacks a `fromText` or similar explicit factory, relying on `create`, whereas `ReverseQuery` offers a more descriptive `fromCoordinates`.
- Off-boarding risk: anonymized user #1
- PR-triggered workflow without a permissions block
- Workflow holding a long-lived secret is unscoped

## New (49)

- Duplicate high-level API surface with different underlying semantics. The `Geocoder` interface (and its trait/aggregator/stateful implementations) exposes simple `geocode(string)` and `reverse(float, float)` methods. However, the core `Provider` interface and `PluginProvider` only expose `geocodeQuery(GeocodeQuery)` and `reverseQuery(ReverseQuery)`. This forces the high-level classes to maintain a thin wrapper layer that converts simple arguments into Query objects, creating two parallel entry points for the same operation. Users must decide whether to use the simple convenience methods or the more flexible Query-based methods, which can lead to confusion about which one to use for advanced features (like setting limits or locales).
- Off-boarding risk: anonymized user #1
- Orphaned file (src/Common/Model/Address.php)
- Orphaned file (src/Common/Model/AddressBuilder.php)
- Orphaned file (src/Common/Model/AdminLevelCollection.php)
- Orphaned file (src/Common/ProviderAggregator.php)
- Orphaned file (src/Common/Query/GeocodeQuery.php)
- Orphaned file (src/Common/Query/ReverseQuery.php)
- Orphaned file (src/Common/StatefulGeocoder.php)
- Orphaned file (src/Http/Provider/AbstractHttpProvider.php)
- Orphaned file (src/Plugin/PluginProvider.php)
- Orphaned file (src/Provider/AlgoliaPlaces/AlgoliaPlaces.php)
- Orphaned file (src/Provider/ArcGISOnline/ArcGISOnline.php)
- Orphaned file (src/Provider/AzureMaps/AzureMaps.php)
- Orphaned file (src/Provider/BingMaps/BingMaps.php)
- Orphaned file (src/Provider/Cache/ProviderCache.php)
- Orphaned file (src/Provider/Chain/Chain.php)
- Orphaned file (src/Provider/FreeGeoIp/FreeGeoIp.php)
- Orphaned file (src/Provider/GeoIP2/GeoIP2.php)
- Orphaned file (src/Provider/GeoIP2/GeoIP2Adapter.php)
- …and 29 more
