Repository navigation
feat: limpeza remota do aparelho do ACS e rotação da chave do cache (#81) - #93
Merged
Merged
Conversation
…enovação recusam aparelho marcado (#81)
…esma transação (#81)
…er (#81, CRIPTO-APP-CACHE)
…lta da rede e na renovação (#81)
…uadro em segundo plano (#81)
) remote_wipe_e2e.dart roda o SinalAcsApp com o id da instalação, a chave do SQLCipher, os tokens de envio e o diário de produção; deixa uma visita pendente (envio fora do ar pelo decorator, sem "Sair") com o painel aberto; o coordenador da fixture pede a limpeza pela rede real e a volta do segundo plano a aplica. Confere no aparelho banco vazio com chave nova, nenhum token de envio e id novo, e entra de novo pela tela. acs_remote_wipe_e2e.sh confere no banco o pedido entregue e confirmado, os tokens do id antigo revogados, a trilha dos três eventos, a visita ausente de visits e a cadeia de auditoria; acs_remote_wipe_e2e_test.sh guarda a estrutura sem Docker nem aparelho. O decorator de envio vai para support/envio_fora_do_ar.dart, compartilhado com full_journey_e2e.dart. A fila por dono do full_journey passa a reabrir o banco depois do "Limpar este aparelho": desde a D6 ele fecha e apaga o arquivo e troca a chave, e a conexão antiga do teste ficava fechada.
… limpo (#81) O apagador da limpeza remota sela o cache da microárea e o pull de cada escopo antes de destruir o banco: a resposta que volta da rede depois não lê, não grava e não reabre o arquivo, então nenhuma chave nova é criada e nenhum nome ou condição crônica fica no aparelho que o servidor registra como limpo. O selo do cache abre no próximo login.
…o da partida tem teto (#81) Com o diário em erasing, a limpeza conta como feita quando o pedido já foi apagado nesta execução ou quando o id da instalação já é outro (o apagador o troca no último passo): a retomada depois de "Entrar de novo" só reenvia a confirmação e não leva as visitas do login novo. Na partida, só a confirmação ganha o teto de startupWipeCheckTimeout; a limpeza segue sem teto, antes de qualquer uso do banco.
…es D5 e de taxa (#81)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #81
Resumo
A coordenação (o coordenador, só para ACS da própria UBS) ou o administrador pode pedir pelo backoffice a limpeza remota de um aparelho do ACS. O aparelho perde o acesso na hora. No próximo contato com o servidor, ele apaga tudo o que o SinalACS guarda nele, inclusive visitas não enviadas, troca a chave do SQLCipher e o próprio id de instalação, e confirma ao servidor. Pedido, entrega e confirmação ficam na trilha de auditoria. A chave do cache passa a ser trocada por evento (CRIPTO-APP-CACHE): no wipe remoto e no "Limpar este aparelho".
O certificado de cliente MQTT por aparelho (STRIDE-S) não está aqui. Ele depende de uma biblioteca X.509 fora de
spec/stack.mde de uma PKI de produção, e foi para a #94. Por isso este PR não fecha a #81, e o R3 continua parcial na auditoria do PRD.Plano:
docs/superpowers/plans/2026-10-17-issue-81-wipe-remoto-e-rotacao-de-chave.md(D1–D8).Backend
device_wipe_orders, uma linha pordeviceId(índice único). Migração20261017171640323.admin.acsDevices/admin.orderDeviceWipe:deniedgravada antes.alreadyOrdered.devices.pendingWipe/devices.confirmWipe:orderIdou nada.DeviceWipeRequiredExceptionemauth.loginInstitutional,auth.refreshSessionevisits.syncDeferred. A checagem roda antes da senha ou da renovação, e um id que já foi marcado fica marcado para sempre.App do ACS
VisitDatabase.destroy(): fecha o banco e apaga o arquivo, os sidecars, a cópia.recuperadoe a chave. É exclusivo contraopen()concorrente.RemoteWipeCoordinator:erasing/erased), e só apaga o diário depois que o servidor confirma.erasingnão apaga de novo quando a limpeza daquele pedido já terminou.device_wiped("Aparelho limpo pela coordenação"), fora do bloqueio por inatividade.WipeBlocked) e agora também troca a chave.Admin
Provas
dart test: 1438 passando.flutter test: 685 passando;flutter analyzelimpo.flutter test: 473 passando.scripts/qa/ci_invariants.sh: ok.scripts/qa/acs_remote_wipe_e2e.shnoemulator-5554(API 36), contra o banco de teste. O teste deixa uma visita pendente com o painel aberto; o coordenador pede a limpeza; o app, ao voltar do segundo plano, mostra a tela de aparelho limpo. No aparelho: o arquivo do banco sumiu, a chave foi trocada, os tokens de envio foram apagados e o id é novo. O ACS entra de novo com o id novo. No banco, as 11 checagens passaram (o pedido foi entregue e confirmado, nenhum token vivo ficou com o id antigo, as três linhas de trilha existem, a visita não chegou ao servidor) eaudit_chain_checksaiu íntegro. Log emdocs/superpowers/plans/2026-10-17-issue-81-e2e.log.acs_full_e2e.sh(6/6) eadmin_acs_gestao_e2e.sh(3/3). Ofull_journey_e2e.dartfoi ajustado à rotação da chave: agora confere que a conexão foi fechada e que a chave mudou, e conta as tabelas num banco reaberto.Limites conhecidos (detalhe no
PROGRESS.md, seção #81)deviceIdconsegue confirmar sem limpar nada. O acesso continua bloqueado.user_version7, mas o schema é 8) e a linha do RNF04 nocobertura_prd.py --final.