Pausar e parar
Pausa feita pela família e parada feita pela própria pessoa - quem pode, o que para, o que é apagado, como volta e quais eventos e notificações saem.
Há duas formas de a proteção deixar de funcionar numa vaga, e as duas passam pelo mesmo ponto de entrada: stopMonitoring (backend/src/domains/subscriptions/use-cases/monitoring.ts). Assim, o ingest, a análise e as telas concordam sobre o que é "proteção desligada".
| Pausa | Parada pela pessoa | |
|---|---|---|
| Quem faz | Owner ou corresponsável | A própria pessoa, em "Minha proteção" (D7) |
| Rota | POST /seats/{uid}/pause | POST /consent-requests/{token}/stop |
| Duração | days (1, 3, 7 ou 30), until (até 30 dias à frente) ou sem fim | Sem fim |
| Como volta | DELETE /seats/{uid}/pause, ou sozinha no fim do prazo | Só com um novo consentimento da pessoa |
| Status da vaga | paused, pause.cause = "guardian" | paused, pause.cause = "dependent" |
| Chave da vaga | Mantida | Destruída |
| Pareamento | Continua vivo | Sessão do WhatsApp desconectada, pareamento revoked |
| Importação de histórico | Segura onde está e continua depois | Marcada como failed |
| Consentimento | Não muda | Vira revoked (revokedBy: "dependent"), e o resend fica travado |
| Evento | seat.paused / seat.resumed | seat.stopped { cause: "dependent" } |
| Notificação | seat.paused / seat.resumed (info), pros outros responsáveis | consent.stopped (crítica: fura o horário de silêncio), pra todos |
Pausa
O que a pausa garante (AD-019, decisão da pausa):
- A partir dela, nada da pessoa é guardado (descartado antes da cifra) nem analisado, e nenhum alerta sai.
- Nada enviado durante a pausa é lido depois, nem se chegar atrasado ou numa importação.
- Janelas de análise já fechadas antes da pausa ficam guardadas e rodam depois da retomada, porque têm mensagens de quando a proteção estava ligada.
- A retomada abre uma janela nova a partir daquele momento. Nunca cobre o buraco.
Detalhes da API:
- Corpo:
{ days },{ until }ou{}(sem fim), mais umreasonopcional (até 200 caracteres). Oreasoné uma nota do responsável: nunca aparece pra pessoa nem vai nos eventos. Mandardayseuntiljuntos dá400. - Pausar uma vaga já pausada move o fim da mesma pausa e reenvia
seat.pausedcomchanged: true, sem notificar de novo. - A resposta (
200) é a vaga inteira, compause: { cause, since, until, byName }.byNamepode sernull(convidado sem nome): use "Alguém da família". DELETE …/pauseé idempotente: uma vaga que não está pausada volta como está.- O worker
pause-resumerencerra as pausas vencidas a cada 30 s. Aíseat.resumedsai comcause: "schedule". - A pessoa vê só "pausada" (e até quando) na página pública. Nunca vê quem pausou nem por quê.
Erros: 409 STOPPED_BY_DEPENDENT (a pessoa parou, e o responsável não desfaz), 422 SEAT_NOT_ACTIVE (vaga pendente ou arquivada), 422 PAUSE_UNTIL_PAST, 422 PAUSE_TOO_LONG (details.maxDays = 30).
Parada pela pessoa
POST /consent-requests/{token}/stop com { confirm: true } (aceita o link de consentimento ou o de proteção). Repetir devolve a mesma hora e não notifica de novo. Na ordem:
- Uma pausa sem fim com
cause: "dependent"é aberta. Uma pausa de responsável em curso vira essa parada. - Janelas abertas fecham, e as análises pendentes da vaga viram
skipped. - A chave da vaga é destruída (crypto-shred). Mensagens guardadas e trechos de alertas ficam ilegíveis na hora, e o que ainda chegar é descartado.
- Importações em curso viram
failed. A sessão do WhatsApp é desconectada e o pareamento virarevokedcom motivostopped_by_dependent(saipairing.ended). - Sai
seat.stopped { cause: "dependent", stoppedAt }, o único evento da parada. - O consentimento vira
revokedpela pessoa, o resend fica travado porCONSENT_RESEND_COOLDOWN_HOURS(24 h) e todos os responsáveis recebemconsent.stoppedcom o fato e a hora, nunca um motivo.
A selfie e a voz são apagadas EVIDENCE_RETENTION_DAYS (180) dias depois da parada (veja Consentimento). Se a pessoa disser sim de novo a um link reenviado, resumeMonitoring(seat, { kind: "consent" }) encerra a parada com uma chave nova e emite seat.resumed com cause: "consent". Um consentimento novo nunca tira uma pausa de responsável.
curl -s -X POST "$API/seats/$SEAT/pause" \
-H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
-d '{"days":7}'
# → data.status = "paused", data.pause = { cause: "guardian", since, until, byName }
curl -s -X DELETE "$API/seats/$SEAT/pause" -H "authorization: Bearer $TOKEN"
# → data.status = "active", data.pause = nullNo app, escute seat.paused, seat.resumed e seat.stopped e busque a vaga de novo. Com pause.cause === "dependent", mostre o estado "parou a proteção" sem botão de retomar.
Em aberto
- A cobrança não muda com a parada. Pela decisão de produto, a vaga deixa de cobrar no fim do período, mas isso depende do G-33/G-35.
- As métricas do backoffice (MRR, vagas ativas) contam só
status = 'active', então uma vaga pausada some do MRR, embora a cobrança continue. - Uma importação segurada pela pausa continua ocupando a vaga de admissão da conta na fila.
- Não existe pausa feita pelo backoffice, e o escopo por vaga dos corresponsáveis (G-27) ainda não limita quem pode pausar.
Fontes
backend/src/http/routes/seats/pause.route.ts,backend/src/http/routes/consents/protection.route.tsbackend/src/domains/subscriptions/use-cases/monitoring.ts,schemas/pause.schema.tsbackend/src/domains/consents/use-cases/protection.ts,backend/src/domains/ingest/use-cases/seat-crypto.tsbackend/apps/workers/pause-resumer.tsbackend/src/domains/notifications/catalog.ts- Notas das frentes k-lifecycle e k-consent (
k-lifecycle-api.md,k-consent-api.md) - AD-019 (D7 e a decisão da pausa)
Pareamento
Como o app do responsável conecta o WhatsApp da pessoa protegida - pré-requisitos, código no celular da pessoa ou QR na tela, estados, eventos e erros.
Alertas
Do achado da análise ao alerta e à notificação - o que já existe na main, as regras de agrupamento e privacidade, e o que ainda falta.
