Symptom
POST /account/recover-identity appears in the generated document. That endpoint does not exist. The handler it documents is registered at POST /user/account/recover, which is absent from the document.
Evidence
The annotation names the right handler in its @see and the wrong path in the attribute:
// src/User/src/OpenAPI.php:1049-1052
/**
* @see PostUserAccountRecoverHandler::handle()
*/
#[OA\Post(
path: '/account/recover-identity',
The route:
// src/User/src/RoutesDelegator.php:86
$routeCollector->post('/user/account/recover', PostUserAccountRecoverHandler::class, 'user::recover-account');
The route name user::recover-account is in the guest permission list (config/autoload/authorization.global.php:212), so the real endpoint is reachable unauthenticated, as intended — it is only the documentation that points elsewhere.
Root cause
A path rename that updated the delegator and not the annotation, or the reverse. The @see docblock stayed correct throughout, which is why the drift is invisible to a reader skimming the annotations. Nothing in the toolchain cross-checks an OA\Post(path:) against the router, so this cannot fail a build.
Proposed fix
Correct the annotation to the registered path:
#[OA\Post(
path: '/user/account/recover',
RecoverIdentity remains a reasonable tag name for it. If /account/recover-identity is the intended public path, the delegator is what should change instead — but the two must agree, and the route is what actually serves traffic.
Recommended follow-up
This class of drift is worth a guard rather than a one-off fix. A cheap one: enumerate RouteCollectorInterface::getRoutes() and compare verb + path against the generated paths, failing on any mismatch in either direction. In the fork this runs as a script and found this issue plus five path-parameter name mismatches in fork-owned modules (/accounts/{account_id} documented against a route registered as /accounts/{id}, and similar) — all invisible to swagger-php, all breaking generated clients that bind parameters by name.
Symptom
POST /account/recover-identityappears in the generated document. That endpoint does not exist. The handler it documents is registered atPOST /user/account/recover, which is absent from the document.Evidence
The annotation names the right handler in its
@seeand the wrong path in the attribute:The route:
The route name
user::recover-accountis in theguestpermission list (config/autoload/authorization.global.php:212), so the real endpoint is reachable unauthenticated, as intended — it is only the documentation that points elsewhere.Root cause
A path rename that updated the delegator and not the annotation, or the reverse. The
@seedocblock stayed correct throughout, which is why the drift is invisible to a reader skimming the annotations. Nothing in the toolchain cross-checks anOA\Post(path:)against the router, so this cannot fail a build.Proposed fix
Correct the annotation to the registered path:
RecoverIdentityremains a reasonable tag name for it. If/account/recover-identityis the intended public path, the delegator is what should change instead — but the two must agree, and the route is what actually serves traffic.Recommended follow-up
This class of drift is worth a guard rather than a one-off fix. A cheap one: enumerate
RouteCollectorInterface::getRoutes()and compare verb + path against the generatedpaths, failing on any mismatch in either direction. In the fork this runs as a script and found this issue plus five path-parameter name mismatches in fork-owned modules (/accounts/{account_id}documented against a route registered as/accounts/{id}, and similar) — all invisible to swagger-php, all breaking generated clients that bind parameters by name.