Acesso Pro nunca expirava

Bug: terapeutas mantinham o acesso Pro do TRG Club depois que a filiação CITRG expirava — 2026-07-07

O que aconteceu

A verificação de elegibilidade já rodava em todo sign-in de terapeuta (AutoSubscribeJob → CreateFlow → ValidateEligibility lê valid_until_timestamp do CITRG), mas o resultado era descartado para usuários que já tinham uma assinatura Pro: ValidateExistingSubscription falhava o fluxo com “Você já possui um plano PRO ativo” antes que qualquer coisa pudesse reagir a pro_eligible == false. Combinado com assinaturas Pro sendo criadas com expires_at = nil (o scope non_expired trata nil como nunca expira), o acesso Pro era efetivamente permanente.

Causas raiz para lembrar

  1. Validação computada mas não usada. Um fluxo que busca estado externo (valid_until do CITRG) precisa ter um passo que reconcilia o estado local com ele — não só um guard no caminho de criação. Procurar por valores context.<flag> que nenhum passo posterior consome.
  2. expires_at = nil significa “nunca expira” em Subscription#non_expired. Qualquer assinatura criada sem expiração é permanente a menos que algum passo a expire explicitamente.
  3. A ordem do fluxo escconde bugs. fail! num fluxo Ucasy interrompe os passos restantes; uma validação que falha antecipadamente (“já tem um plano”) pode silenciosamente pular passos de reconciliação colocados depois dela. Passos de reconciliação precisam vir antes de validações de saída antecipada.
  4. O citrg-api nunca empurra a expiração. A expiração de filiação lá é computada na leitura (valid_until < today) — sem status flip, sem webhook, sem job que notifica o TRG Club. Qualquer garantia de atualidade precisa vir de polling do TRG Club (fluxo no momento do login, ou um job recorrente).

Follow-ups (não cobertos por esta correção)

  • Job recorrente para rebaixar usuários Pro que nunca mais logam (tokens do DeviseTokenAuth se auto-renovam, então usuários sempre online pulam as verificações no login).
  • Janela de acesso de 12 meses do Anjo/Tutelado na plataforma de aulas (Apolo) — nenhum sistema guarda essa data hoje; a fonte da verdade precisa ser definida antes de poder ser aplicada.
  • apolo_access_permitted? do citrg-api libera usuários com carteirinha emitida mesmo que a documentação atual não esteja aprovada (membership.rb) — causa candidata para “documentação não aprovada mas ainda tem acesso”.