# Paridade de rotas × Swagger/OpenAPI

Auditoria concluída em 2026-09-14 para o gate de release-readiness `Swagger/OpenAPI reflects all current external/internal contracts`.

## Objetivo

Garantir que a documentação gerada pelo L5 Swagger represente a superfície HTTP efetivamente registrada pelo Laravel, incluindo aliases de compatibilidade e o mecanismo de autenticação/autorização de transporte aplicável a cada rota.

## Fontes de verdade

A verificação usa duas fontes em runtime:

1. `Route::getRoutes()` para obter URI, método HTTP e middleware efetivamente registrados;
2. `php artisan l5-swagger:generate` para produzir o documento OpenAPI a partir das anotações/attributes atuais.

O teste `SwaggerRouteParityTest` compara essas duas superfícies operação por operação para `GET`, `POST`, `PUT`, `PATCH` e `DELETE`.

## Divergências encontradas

### Aliases reais documentados apenas em texto

Algumas rotas apontam para o mesmo método de controller, mas possuem URIs distintas. O antigo comando auxiliar `swagger:generate-annotations` mantém somente a primeira rota encontrada por método de controller, portanto não é suficiente como prova de cobertura de contratos.

A auditoria encontrou aliases ativos que apareciam apenas em descrições como “Também disponível em...”, especialmente:

- portal do cliente: `/api/client/ticket-departments`, anexos e endpoints `/api/client/tickets/*` que reutilizam os contratos `/api/site/tickets/*`;
- Helpdesk: aliases `/api/helpdesk/*` que reutilizam contratos administrativos `/api/admin/tickets/*`.

Esses aliases passam a existir como `PathItem` OpenAPI explícitos referenciando o contrato canônico. O `POST /api/helpdesk/tickets`, cujo controller ativo não possuía annotation própria, recebe operação explícita de compatibilidade.

### URLs temporárias assinadas

Rotas com middleware `signed` estavam descritas como “assinadas”, porém o documento não possuía um security scheme que representasse a assinatura HMAC da query string.

Foi adicionado `signedUrl` (`apiKey` no parâmetro `signature`) e os contratos de download passam a declarar a segurança real:

- anexos de Chat: `signedUrl`;
- evidências de Ordem de Serviço: `signedUrl`;
- `/api/helpdesk/attachments/{attachment}/download`: `signedUrl`;
- `/api/admin/tickets/attachments/{attachment}/download`: alternativas `bearerAuth` **ou** `signedUrl`, pois existem duas rotas Laravel para o mesmo método/path.

Os parâmetros temporários `expires` e, quando aplicável, `tenant` também são documentados.

## Regressão automatizada

`SwaggerRouteParityTest`:

- regenera o OpenAPI antes da comparação;
- percorre todas as rotas cujo URI começa com `api/`;
- ignora somente os endpoints internos da própria UI/OAuth do L5 Swagger;
- exige que cada método/path real exista no documento;
- resolve `PathItem.$ref` interno para aliases de compatibilidade;
- deriva o perfil de segurança do middleware real (`auth:api`, `auth:client`, `signed`);
- exige que as alternativas de security do OpenAPI sejam equivalentes às variantes de rota registradas;
- exige os schemes `bearerAuth`, `clientBearerAuth` e `signedUrl`.

Com isso, adicionar uma rota nova sem documentação ou alterar sua autenticação sem atualizar o OpenAPI passa a gerar regressão automática.

## Arquivo gerado

`storage/api-docs/api-docs.json` é um artefato gerado por `php artisan l5-swagger:generate`. A garantia desta entrega está no source das annotations e no teste que regenera o documento antes de validar a paridade; não se usa a idade do JSON versionado como substituto para essa verificação.

## Resultado

A superfície HTTP passa a possuir um gate reproduzível de rota × método × security. Após o merge desta entrega, o gate `Swagger/OpenAPI reflects all current external/internal contracts` pode ser considerado concluído.


## Gate específico do Fluxo PDV

A release corporativa do PDV adiciona uma segunda camada de verificação em
`PdvSwaggerContractTest`.

O teste deriva em runtime todas as rotas associadas aos controllers de:

- `App\\Http\\Controllers\\Pos\\*`;
- `App\\Http\\Controllers\\Tabs\\*`;
- `App\\Http\\Controllers\\Devices\\*`;
- `StockMapController`;
- `StockMovementController`.

Para cada operação real, o OpenAPI gerado deve conter:

- método e path;
- `summary`;
- tag de domínio;
- pelo menos uma resposta documentada;
- parâmetros de path obrigatórios;
- `bearerAuth` quando a rota usa `auth:api`;
- `deviceBridgeAuth` quando a rota usa autenticação do Device Bridge.

Além da descoberta dinâmica, contratos críticos como catálogo incremental,
offline sync, health, dashboard, peso manual, devices, balanças, comandas,
Stock Map e histórico de movimentações são exigidos explicitamente.

O gate é executado por `composer verify:pdv-release` e pelo workflow
`PDV Release Gate`. Assim, uma nova rota do domínio PDV sem contrato L5
Swagger passa a bloquear a release funcional mesmo que o `API Quality`
esteja interrompido por outro gate independente.
