# Fluxo PDV — deploy seguro API → App e rollback

## Objetivo

Definir a sequência obrigatória de release coordenada entre:

- API: `paulodias-dev/fluxo-pdv-api`;
- App: `paulodias-dev/fluxo-pdv-app`.

O princípio central é **API primeiro, App depois**. O App nunca deve ser
publicado consumindo um contrato que ainda não está disponível no backend.

## 1. Release manifest

Antes do deploy, registre no change/release record:

- SHA exato da API;
- SHA exato do App;
- versão/tag de release;
- operador responsável;
- janela de mudança;
- backup associado;
- migrations incluídas;
- contratos OpenAPI alterados;
- plano de rollback;
- evidência dos gates.

Nunca use apenas `main` como identificador de rollback. Rollback deve apontar
para SHAs imutáveis conhecidos.

## 2. Gates obrigatórios antes de staging/produção

Na API:

```bash
composer install --no-dev --classmap-authoritative
composer validate --no-check-publish
php artisan l5-swagger:generate
```

No CI de release, devem estar disponíveis:

- `API Quality`;
- `PDV Release Gate`;
- `PDV Performance` como evidência de performance, respeitando os SLOs
  documentados.

O gate funcional canônico do PDV é:

```bash
composer verify:pdv-release
```

Esse comando é destinado a CI/staging com banco descartável. **Não execute a
suíte destrutiva de testes na base de produção.**

## 3. Pré-deploy da API

1. Fixe o SHA aprovado da API.
2. Gere backup consistente do banco segundo o procedimento operacional.
3. Confirme espaço, conectividade MySQL e workers/filas.
4. Valide variáveis/segredos do runtime.
5. Revise migrations do release.
6. Para migrations aditivas, valide previamente:

```bash
php artisan migrate --pretend --force
```

7. Confirme que não há migration destrutiva inesperada.
8. Confirme compatibilidade backward com o App atualmente em produção.

### Regra de compatibilidade

Durante a janela em que a API nova está ativa com o App antigo, endpoints,
campos e autenticação usados pelo App antigo devem continuar válidos.

Mudança incompatível exige estratégia expand/contract em releases distintas:

1. **expand:** API aceita contrato antigo e novo;
2. publicar App novo;
3. observar/estabilizar;
4. **contract:** remover contrato antigo somente em release posterior.

## 4. Deploy da API

Sequência recomendada:

```bash
git checkout <API_SHA_APROVADO>
composer install --no-dev --classmap-authoritative --no-interaction
php artisan optimize:clear
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan queue:restart
```

Depois:

1. aguarde workers retornarem;
2. valide conexão MySQL;
3. valide Queue Health;
4. valide filas fiscais;
5. valide geração/acesso do OpenAPI;
6. execute smoke tests não destrutivos;
7. valide login e resolução de tenant;
8. valide uma leitura de catálogo/health do PDV;
9. confirme ausência de aumento anormal de 5xx, deadlocks e backlog.

**Não publique o App ainda** se qualquer smoke da API falhar.

## 5. Deploy do App

Somente após a API nova estar saudável:

1. fixe o SHA aprovado do `fluxo-pdv-app`;
2. instale dependências exatamente pelo lockfile;
3. execute lint/typecheck/test/build definidos pelo App;
4. gere o bundle usando a URL da API homologada;
5. publique o App;
6. invalide cache/CDN somente quando necessário;
7. valide login, troca de tenant e fluxo principal do PDV.

A ordem é portanto:

`backup → API → migrations → workers → smoke API → App → smoke integrado`.

## 6. Smoke integrado mínimo

Após API + App:

- autenticação e tenant correto;
- catálogo incremental;
- abertura do PDV;
- leitura/pesquisa de produto;
- finalização de venda controlada;
- atualização do estoque;
- transactional outbox fiscal;
- fila fiscal saudável;
- comanda e realtime;
- sync offline/idempotência;
- device/terminal revogado continua bloqueado.

Use tenant/dados próprios de homologação ou procedimento controlado de produção.
Não crie transações fiscais reais apenas para smoke quando o ambiente/regra
fiscal não permitir.

## 7. Critérios de abort

Interrompa o rollout antes do App se ocorrer qualquer um:

- migration falha;
- API não sobe saudável;
- tenant isolation falha;
- autenticação passa a resolver tenant incorreto;
- fila fiscal sem workers;
- backlog cresce sem drenagem;
- venda cria efeitos parciais;
- estoque negativo indevido;
- taxa de 5xx/deadlocks excede baseline operacional.

## 8. Rollback do App

Se a API está saudável e o problema está no frontend:

1. reverta primeiro o App para o SHA anterior;
2. mantenha a API nova se ela for backward-compatible;
3. invalide caches do bundle;
4. repita smoke integrado com App anterior.

Esse é o rollback preferido, pois evita reverter migrations desnecessariamente.

## 9. Rollback da API

Se a falha estiver na API:

1. interrompa o rollout do App ou reverta o App primeiro;
2. pause tráfego/mutações afetadas se necessário;
3. preserve evidências/logs/correlation IDs;
4. volte o código da API para o SHA anterior aprovado;
5. execute `composer install` correspondente ao lockfile desse SHA;
6. limpe/recrie caches;
7. reinicie workers;
8. execute smoke da API anterior.

### Regra para migrations

**Não execute `migrate:rollback` automaticamente em produção.**

Migrations aditivas podem normalmente permanecer após rollback de código,
desde que o código anterior as ignore.

Rollback de schema só pode ocorrer quando:

- a migration específica foi revisada como reversível;
- não há dados novos que seriam perdidos;
- existe backup validado;
- o responsável da mudança aprovou explicitamente.

Se houver risco de perda/corrupção, prefira restaurar a aplicação e manter o
schema expandido, ou executar o procedimento de restore aprovado.

## 10. Fiscal e filas durante rollback

Antes de rollback de API:

- registre backlog por fila;
- não apague `fiscal_outbox`;
- não apague `fiscal_emission_attempts`;
- não reemita documento apenas porque a resposta se perdeu;
- preserve correlation IDs;
- após retorno dos workers, use reconciliação/retry auditável.

Outbox e tentativas fiscais são registros operacionais duráveis e não devem ser
tratados como cache descartável.

## 11. Offline e devices

Durante rollback, preserve:

- IDs/chaves de idempotência já aceitos;
- credenciais e versão de Device Bridge;
- revogações de terminal/device;
- cursores de catálogo;
- operações offline pendentes.

O App pode reenviar operações após perda de resposta. A API anterior escolhida
para rollback precisa continuar compatível com essas identidades.

## 12. Encerramento da mudança

A release só é encerrada depois de registrar:

- SHAs efetivamente publicados;
- migrations efetivamente aplicadas;
- horário de deploy;
- resultado dos smokes;
- estado das filas;
- incidentes/desvios;
- decisão de manter ou reverter;
- evidência de backup/restore quando aplicável.

Sem esses registros, a mudança não deve ser tratada como release corporativa
auditável.
