Backup e restauração
O COBRES é SaaS: o PostgreSQL atende todas as organizações. Uma restauração integral afeta todos os clientes. A operação técnica da plataforma executa este procedimento; o cliente valida os objetivos e a conferência dos seus dados. Não restaure produção para desfazer somente o erro de uma organização sem avaliar o impacto nas demais.
Escopo e objetivos
A infraestrutura declarada em application/.railway/railway.ts usa Railway, com PostgreSQL, Redis, API, worker e bucket files. O README descreve as permissões dos papéis e os comandos de migração e saúde. A IaC não declara política de backup, retenção ou recuperação para um instante específico (PITR).
Preencher e aprovar antes de entrar em produção:
| Decisão | Valor acordado |
|---|---|
| RPO: perda máxima aceitável de dados | A preencher pelo cliente e pela plataforma |
| RTO: tempo máximo para restabelecer a operação | A preencher pelo cliente e pela plataforma |
| Frequência e retenção das cópias | A preencher |
| Responsável pela execução e substituto | A preencher |
| Local protegido das cópias e controle de acesso | A preencher |
| Frequência do ensaio e data do último aprovado | A preencher |
O conjunto recuperável inclui:
- Banco PostgreSQL completo: todos os schemas, dados, funções, permissões, políticas RLS e livro financeiro. Não limitar o dump ao schema
cobresou a uma organização. - Bucket de arquivos: objetos de uploads, exportações, anexos e PDFs, preservando chaves e metadados. O dump contém referências aos objetos, não seu conteúdo.
- Inventário de segredos sem valores: nomes, serviço consumidor, referência no cofre, responsável, versão e dependências de recuperação/rotação. As chaves de criptografia e suas versões anteriores precisam continuar disponíveis pelo mecanismo seguro da plataforma para ler os dados restaurados. O inventário sozinho não as recupera.
- Revisão do Alembic, commit e imagem da aplicação, configuração sem segredos e procedimento de bootstrap dos papéis. O dump do banco não cria os papéis globais do PostgreSQL.
Redis participa da prontidão e de sessões/limites transitórios; documentar o efeito de recriá-lo e a necessidade de nova autenticação. Ele não substitui o banco nem o bucket como cópia dos dados persistentes.
Backup lógico e verificação
Executar em estação operacional controlada, com ferramentas PostgreSQL compatíveis com a versão do servidor. Os exemplos pressupõem serviços libpq cobres-backup e cobres-restore-drill previamente configurados por canal seguro, sem senhas na linha de comando ou nos registros. O primeiro aponta para a origem com leitura de todos os dados e autorização para contornar RLS, como superuser ou papel com BYPASSRLS; o segundo aponta exclusivamente para uma base descartável com privilégios administrativos para restaurar owners e ACLs. Guardar os artefatos cifrados, fora do repositório, com acesso restrito.
- Registrar ambiente, horário UTC, versão do PostgreSQL, commit/imagem e revisão atual. Em
application/api, com a configuração operacional da origem, executaralembic currente guardar somente a revisão no registro do backup. - Obter uma janela consistente entre banco e arquivos: interromper integrações externas, uploads, entrada de webhooks e demais escritas da API e do worker; drenar trabalhos em andamento. Registrar o início e o fim da janela e as contagens/totais financeiros de controle usados no ensaio. O snapshot consistente do
pg_dumpnão inclui uma cópia atômica do bucket. - Criar o dump completo e conferir o índice e a integridade do arquivo:
umask 077
pg_dump --dbname='service=cobres-backup' --format=custom --file=cobres.dump
pg_restore --list cobres.dump > cobres.dump.list
sha256sum cobres.dump > cobres.dump.sha256
sha256sum --check cobres.dump.sha256
No macOS, usar shasum -a 256 e shasum -a 256 -c em lugar de sha256sum. Exigir código de saída zero em cada etapa. O índice e o checksum não comprovam restauração: executar o ensaio abaixo.
- Copiar o bucket por ferramenta compatível com S3, usando configuração segura existente. Preservar chaves, conteúdo, tipo de conteúdo e demais metadados necessários. Registrar manifesto de objetos, tamanhos e checksums quando disponíveis; não presumir que ETag seja MD5. Verificar contagens, bytes e amostras de download, incluindo um anexo e um PDF. Verificar no provedor a ferramenta e as garantias de cópia/versionamento disponíveis.
- Relacionar dump, cópia do bucket, revisão e manifesto pelo mesmo identificador de backup. Retomar as escritas após finalizar a cópia consistente; na entrada em produção, manter o congelamento até a decisão operacional. Registrar duração, tamanho, localização e resultado, sem dados pessoais ou valores de segredos nos logs. Conferir que uma segunda cópia pode ser acessada independentemente do ambiente de origem. O formato custom e o processo de verificação seguem a documentação do pg_dump.
Estratégia de ponto no tempo
Backup lógico periódico recupera o estado do snapshot do dump; ele sozinho não oferece PITR. A recuperação pontual precisa de backup físico/base e uma sequência contínua de WAL arquivado, conforme a documentação do PostgreSQL. Para atender ao RPO acordado, verificar no provedor Railway, no plano e no serviço efetivamente contratados: existência dessa cobertura, retenção, granularidade, região, cifragem, custo e procedimento para restaurar em outro destino. Confirmar também se o recurso anunciado como snapshot oferece PITR ou somente pontos discretos.
Se PITR estiver disponível, configurar retenção e frequência compatíveis com o RPO, monitorar falhas e ensaiar a restauração até um horário UTC conhecido anterior a uma alteração de teste. Medir o atraso real do último ponto recuperável. Se não estiver disponível, registrar a lacuna e combinar backups lógicos mais frequentes ou outra solução de hospedagem/backup antes de aceitar um RPO menor que o intervalo entre dumps.
Verificar no provedor a retenção e a recuperação de objetos removidos ou sobrescritos no bucket. PITR do PostgreSQL não recupera arquivos: manter versões/cópias que permitam reconstruir as referências no instante escolhido. Conservar backup lógico como cópia independente e testável mesmo quando houver snapshots.
Ensaio de restauração
- Reservar PostgreSQL e bucket descartáveis, isolados da produção. Confirmar o destino por duas pessoas, sua versão e capacidade. Bloquear saída para bancos, e-mail e webhooks reais: o outbox restaurado pode conter trabalhos pendentes. Não iniciar worker contra integrações reais.
- Criar os papéis e aplicar o bootstrap de permissões documentado no README em um cluster isolado. Disponibilizar as dependências necessárias, inclusive extensões. Restaurar como administrador preservando ownership e ACLs: funções
SECURITY DEFINERprecisam continuar com os donos corretos. Não usar--no-ownerou--no-aclpara contornar erros de permissão. - Em uma base vazia e descartável, executar:
sha256sum --check cobres.dump.sha256
pg_restore --exit-on-error --single-transaction --dbname='service=cobres-restore-drill' cobres.dump
psql 'service=cobres-restore-drill' -X -v ON_ERROR_STOP=1 -c 'SELECT version_num FROM app.alembic_version;'
psql 'service=cobres-restore-drill' -X -v ON_ERROR_STOP=1 -c 'SELECT count(*) AS debts FROM cobres.debts; SELECT count(*) AS charges FROM cobres.finance_charges;'
Não usar --create: o banco restaurado deve ser o destino descartável escolhido, sem reutilizar o nome da origem. Exigir código de saída zero e resolver qualquer erro antes de prosseguir. As opções estão descritas na documentação do pg_restore.
- Restaurar os objetos no bucket de ensaio. Comparar o manifesto e abrir amostras de anexos/PDFs referenciados pelo banco. Conferir contagens e totais financeiros agregados com o registro feito na janela do backup; sucesso do comando não basta.
- Usar a imagem/commit correspondente ao backup. Configurar todos os pools da API, o migrator e o worker para a cópia, Redis isolado e bucket de ensaio. Recuperar as referências de configuração pelo canal seguro da plataforma. Em
application/api, executaralembic currentcontra a cópia e comparar com a revisão registrada. Não rodar o predeploy que aplica migrações antes dessa conferência. - Subir a API e um worker isolado com transporte de teste e conectores externos bloqueados/substituídos por simuladores. Consultar os dois endpoints:
curl --fail --silent --show-error http://127.0.0.1:8000/health/live
curl --fail --silent --show-error http://127.0.0.1:8000/health/ready
O primeiro deve retornar status: ok; o segundo deve confirmar os pools PostgreSQL, Redis, bucket e heartbeat do worker. Em produção, ausência de heartbeat ou bucket indisponível causa 503; em desenvolvimento, absent não significa que o ensaio está aprovado. Confirmar explicitamente essas dependências e que todos os pools apontam para a cópia.
- Fazer uma leitura autenticada de teste, conferir isolamento entre organizações e os totais acordados com o cliente. Registrar ponto recuperado, tempo total até operação validada, erros e comparação com RPO/RTO. Aprovar o ensaio somente após as conferências. Encerrar os serviços e descartar as cópias conforme a retenção combinada.
Checklist antes de entrar em produção
- Cliente e plataforma preencheram RPO/RTO, responsáveis, retenção e critérios de conferência.
- Capacidades e limitações de snapshot/PITR e recuperação do bucket foram verificadas no provedor.
- Backup completo do banco e cópia consistente dos objetos concluídos, protegidos e identificados.
- Inventário sem valores, referências de recuperação e revisão Alembic conferidos.
- Restauração em base descartável aprovada, com smoke query, health endpoints, amostras de arquivos e totais conferidos.
- RPO/RTO medidos atendem ao acordo; evidências e localização das cópias estão acessíveis aos responsáveis.
- Janela de congelamento e responsáveis pela decisão de reversão definidos, considerando todas as organizações.
- Integrações e outbox serão isolados durante recuperação; retomada exige reconciliar boletos e mensagens já enviados depois do ponto restaurado para evitar duplicidade.
- Backup final anterior à entrada em produção e conferência posterior previstos no roteiro.