# Auditoria de leituras da separação

Este runbook descreve a configuração e a operação das partições, do arquivo
morto, da restauração temporária e da migração de leituras legadas. Os 12 meses
mais recentes permanecem consultáveis no PostgreSQL; meses completos mais
antigos são preservados em arquivos no servidor.

## Configuração do servidor

Configure as variáveis abaixo antes de gerar o cache de configuração da
aplicação:

| Variável | Valor aprovado | Finalidade |
| --- | --- | --- |
| `PICKING_READ_LOG_RETENTION_MONTHS` | `12` | Meses mantidos anexados à tabela consultável. |
| `PICKING_READ_LOG_FUTURE_MONTHS` | `2` | Meses futuros criados antecipadamente. |
| `PICKING_READ_LOG_ARCHIVE_PATH` | caminho absoluto | Raiz persistente dos arquivos; obrigatória para arquivar e restaurar. |
| `PICKING_READ_LOG_RESTORE_DAYS` | `7` | Prazo da cópia restaurada no PostgreSQL. |
| `PICKING_READ_LOG_RESTORE_BATCH_SIZE` | `500` | Registros importados por lote na restauração. |
| `PICKING_READ_LOG_LEGACY_DAYS` | `60` | Período padrão analisado pela migração legada. |
| `PICKING_READ_LOG_LEGACY_WINDOW_MINUTES` | `5` | Distância máxima entre leitura legada e movimentação candidata. |
| `PICKING_READ_LOG_LEGACY_BATCH_SIZE` | `500` | Leituras analisadas por lote na migração legada. |

`PICKING_READ_LOG_ARCHIVE_PATH` deve apontar para um volume:

- externo aos diretórios de release e preservado entre deploys;
- local ao processo que executa o scheduler e no mesmo filesystem usado pelos
  arquivos temporários e definitivos;
- gravável pelo usuário da aplicação e não exposto pelo servidor HTTP;
- incluído no backup e no monitoramento de capacidade e inodes.

Uma organização típica é `/var/lib/rex/picking-read-logs`. A aplicação cria um
subdiretório por ano com permissão `0750` e publica, para cada mês, o par:

```text
<raiz>/2025/picking_read_logs_2025_06.jsonl.gz
<raiz>/2025/picking_read_logs_2025_06.manifest.json
```

O processo de backup deve copiar o arquivo e o manifesto como uma unidade e
nunca aplicar retenção que remova um dos dois. Inclua o volume no inventário de
backup, registre seu RPO/RTO junto ao banco e faça uma restauração de teste
periódica em ambiente isolado. Depois de alterar as variáveis, atualize o cache
de configuração conforme o procedimento normal do ambiente.

## Scheduler e monitoramento

Mantenha o scheduler do Laravel ativo a cada minuto, em uma única instância
operacional, por exemplo:

```cron
* * * * * cd /caminho/do/rex-back && php artisan schedule:run >> /dev/null 2>&1
```

Os horários usam `America/Sao_Paulo`:

| Horário | Rotina |
| --- | --- |
| Diariamente, 00:15 | Verifica o mês atual e cria as partições futuras. |
| Dia 1 de cada mês, 01:15 | Arquiva todas as partições completas fora da retenção. |
| Diariamente, 02:15 | Remove do PostgreSQL restaurações cujo prazo terminou. |

Antes da liberação, confirme `php artisan schedule:list` e execute manualmente
`php artisan picking-read-logs:maintain-partitions`. Falha nessa manutenção deve
ser corrigida antes de uma nova separação, pois uma partição mensal ausente faz
a confirmação inteira ser revertida.

Encaminhe falhas do scheduler e do log da aplicação ao plantão responsável por
banco e filesystem. Monitore no mínimo:

- código de saída diferente de zero nos comandos de partição e arquivamento;
- erros de checksum, permissão, criação de arquivo ou falta de partição;
- bytes e inodes livres no volume do arquivo morto;
- crescimento mensal dos arquivos e das partições ainda consultáveis;
- restaurações com `result = failed` ou `cleanup_result = failed`.

Como ponto de partida, alerte com menos de 20% de espaço livre e trate menos de
10% como crítico; ajuste os limites após observar o volume real. O comando de
limpeza registra falhas individuais no log e na auditoria, portanto elas também
devem ser monitoradas mesmo quando o comando termina.

## Manutenção e arquivamento

Verifique ou crie as partições futuras:

```bash
php artisan picking-read-logs:maintain-partitions
```

Arquive automaticamente todos os meses elegíveis ou repita um mês específico:

```bash
php artisan picking-read-logs:archive
php artisan picking-read-logs:archive --month=2025-06
```

O arquivamento usa streaming, valida período, quantidade e SHA-256, publica por
rename atômico e só então remove a partição. Reexecutar um mês já publicado
valida novamente os dois artefatos. Uma restauração protege o mês contra novo
arquivamento até que a limpeza dedicada remova sua cópia do PostgreSQL, mesmo
que o prazo de consulta já tenha terminado.

Se o comando falhar:

1. Preserve a partição, o `.jsonl.gz` e o manifesto existentes.
2. Consulte o log da aplicação e corrija espaço, permissão ou configuração.
3. Se houver erro de checksum, recupere do backup o par correspondente; não
   edite o arquivo nem o manifesto manualmente.
4. Repita o comando com `--month`. Uma falha não remove a partição de origem.

Não execute manualmente o arquivamento de um mês que ainda esteja dentro dos 12
meses consultáveis; o comando rejeita esse uso.

## Restauração para o suporte

Antes de restaurar, obtenha o mês solicitado, um motivo rastreável e o ID de um
usuário operador existente. Execute:

```bash
php artisan picking-read-logs:restore \
  --month=2025-06 \
  --reason="Chamado SUP-1234" \
  --operator=42
```

O comando valida o manifesto e o checksum antes da importação, registra a
tentativa permanentemente e informa a expiração. Em caso de sucesso, o mês fica
consultável pelo histórico da tarefa durante sete dias. O arquivo e o manifesto
originais nunca são consumidos ou removidos.

Se a restauração falhar, corrija a causa indicada no log e repita o comando com
o mesmo contexto. A tentativa anterior permanece registrada como `failed` e a
transação não deixa uma importação parcial. Não apague ou sobrescreva uma
partição existente para forçar a restauração.

A limpeza normal é agendada, mas pode ser executada após corrigir uma falha:

```bash
php artisan picking-read-logs:cleanup-restorations
```

Ela remove somente a cópia restaurada no PostgreSQL. Confirme no atendimento
que a consulta deixou de ser necessária antes de antecipar qualquer ação fora
do prazo automático.

## Migração das leituras legadas

A migração é administrativa e não faz parte do deploy. Primeiro simule e
registre as contagens:

```bash
php artisan picking-read-logs:migrate-legacy \
  --dry-run \
  --days=60 \
  --batch=500 \
  --window=5
```

Revise `Analisados`, `Aptos`, `Já migrados` e os descartes por motivo. Somente
depois dessa conferência execute sem `--dry-run`:

```bash
php artisan picking-read-logs:migrate-legacy \
  --days=60 \
  --batch=500 \
  --window=5
```

O comando migra apenas associações determinísticas, mantém `reading_logs`
intacta e reconhece fontes já processadas. Ele usa lock administrativo e recusa
uma segunda execução simultânea. Se falhar, corrija a causa e reexecute; os
lotes concluídos são reconhecidos por `source_reading_log_id` e não são
duplicados. `--days` e `--window` aceitam de 1 a 60, e `--batch`, de 1 a 5000.

## Verificação e rollback

Use `php artisan <comando> --help` para conferir as opções disponíveis. Após o
deploy, valide nesta ordem:

1. cache de configuração atualizado e volume persistente gravável;
2. `picking-read-logs:maintain-partitions` concluído;
3. scheduler listado e ativo;
4. dry-run da migração revisado antes da execução real;
5. logs, partições e capacidade do volume acompanhados nas primeiras viradas.

Um rollback da aplicação não deve remover `picking_read_logs`, suas partições,
a auditoria de restaurações ou os arquivos publicados. Os registros já
capturados precisam permanecer preservados mesmo que a versão anterior volte a
usar a tabela genérica para novas leituras.
