Pular para o conteúdo principal

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ãoValor acordado
RPO: perda máxima aceitável de dadosA preencher pelo cliente e pela plataforma
RTO: tempo máximo para restabelecer a operaçãoA preencher pelo cliente e pela plataforma
Frequência e retenção das cópiasA preencher
Responsável pela execução e substitutoA preencher
Local protegido das cópias e controle de acessoA preencher
Frequência do ensaio e data do último aprovadoA 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 cobres ou 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.

  1. 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, executar alembic current e guardar somente a revisão no registro do backup.
  2. 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_dump não inclui uma cópia atômica do bucket.
  3. 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.

  1. 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.
  2. 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​

  1. 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.
  2. 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 DEFINER precisam continuar com os donos corretos. Não usar --no-owner ou --no-acl para contornar erros de permissão.
  3. 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.

  1. 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.
  2. 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, executar alembic current contra a cópia e comparar com a revisão registrada. Não rodar o predeploy que aplica migrações antes dessa conferência.
  3. 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.

  1. 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.