SuperdindaDocs

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

PausaParada pela pessoa
Quem fazOwner ou corresponsávelA própria pessoa, em "Minha proteção" (D7)
RotaPOST /seats/{uid}/pausePOST /consent-requests/{token}/stop
Duraçãodays (1, 3, 7 ou 30), until (até 30 dias à frente) ou sem fimSem fim
Como voltaDELETE /seats/{uid}/pause, ou sozinha no fim do prazoSó com um novo consentimento da pessoa
Status da vagapaused, pause.cause = "guardian"paused, pause.cause = "dependent"
Chave da vagaMantidaDestruída
PareamentoContinua vivoSessão do WhatsApp desconectada, pareamento revoked
Importação de históricoSegura onde está e continua depoisMarcada como failed
ConsentimentoNão mudaVira revoked (revokedBy: "dependent"), e o resend fica travado
Eventoseat.paused / seat.resumedseat.stopped { cause: "dependent" }
Notificaçãoseat.paused / seat.resumed (info), pros outros responsáveisconsent.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 um reason opcional (até 200 caracteres). O reason é uma nota do responsável: nunca aparece pra pessoa nem vai nos eventos. Mandar days e until juntos dá 400.
  • Pausar uma vaga já pausada move o fim da mesma pausa e reenvia seat.paused com changed: true, sem notificar de novo.
  • A resposta (200) é a vaga inteira, com pause: { cause, since, until, byName }. byName pode ser null (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-resumer encerra as pausas vencidas a cada 30 s. Aí seat.resumed sai com cause: "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:

  1. Uma pausa sem fim com cause: "dependent" é aberta. Uma pausa de responsável em curso vira essa parada.
  2. Janelas abertas fecham, e as análises pendentes da vaga viram skipped.
  3. 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.
  4. Importações em curso viram failed. A sessão do WhatsApp é desconectada e o pareamento vira revoked com motivo stopped_by_dependent (sai pairing.ended).
  5. Sai seat.stopped { cause: "dependent", stoppedAt }, o único evento da parada.
  6. O consentimento vira revoked pela pessoa, o resend fica travado por CONSENT_RESEND_COOLDOWN_HOURS (24 h) e todos os responsáveis recebem consent.stopped com 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.

Pausar por 7 dias e retomar
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 = null

No 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.ts
  • backend/src/domains/subscriptions/use-cases/monitoring.ts, schemas/pause.schema.ts
  • backend/src/domains/consents/use-cases/protection.ts, backend/src/domains/ingest/use-cases/seat-crypto.ts
  • backend/apps/workers/pause-resumer.ts
  • backend/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)

On this page