# Execução — `CC-4` Gerar e compartilhar o link de convite

**Plano:** `CC-4-plano.md` · **Data:** 06/08/2026
**Ambiente:** backend local (Postgres `bolao`, fonte fake), Flutter em teste de
widget. Backend: `test/convite.e2e-spec.ts`. Mobile:
`test/token_de_convite_test.dart`, `test/home_page_test.dart`,
`test/convite_dialog_test.dart`, `test/bolao_page_test.dart`.

**Resultado: 14/14 ✅** — 1 defeito encontrado e corrigido (CC-4-12/13).

| ID | Resultado | Onde |
| -- | --------- | ---- |
| CC-4-01 | ✅ | e2e "admin gera convite com validade de 1 dia" |
| CC-4-02 | ✅ | e2e "convidado entra pelo link e cai no bolão certo" |
| CC-4-03 | ✅ | e2e "o token não é guardado em texto no banco" |
| CC-4-04 | ✅ **novo** | e2e "CC-4-04 cada bolão tem token próprio…" |
| CC-4-05 | ✅ | e2e "participante comum não gera nem invalida convite" |
| CC-4-06 | ✅ | e2e "gerar novo convite invalida o anterior na hora" |
| CC-4-07 | ✅ | e2e 404 inválido / 410 expirado / 404 inexistente |
| CC-4-08 | ✅ | e2e "bolão já começado recusa gerar convite" |
| CC-4-09 | ✅ | e2e "bolão encerrado recusa entrada e recusa gerar convite" |
| CC-4-10 | ✅ **novo** | e2e "CC-4-10 invalidar sem convite ativo é idempotente" |
| CC-4-11 | ✅ | e2e "reabrir o link não duplica participação" |
| CC-4-12 | ✅ **corrigido** | widget "CC-4-12 colar o link inteiro entra no bolão" |
| CC-4-13 | ✅ **corrigido** | widget "CC-4-13 colar a mensagem inteira também entra" |
| CC-4-14 | ✅ | widget "participante comum não vê a ação de convidar" |

## Defeito encontrado — colar o link dizia "convite inválido"

O app compartilha um **link** (`bolao://bolao.app/convite/<token>`) e o diálogo
de entrada pede "o código". Quem recebe o convite no WhatsApp copia o que tem: o
link. Colado no campo, o servidor procurava o hash do texto inteiro, não achava,
e respondia **"convite inválido ou já substituído"** — um diagnóstico errado
sobre um convite perfeitamente válido, no ponto exato onde o convidado desiste e
volta para o grupo.

Nenhum caso anterior cobria isso porque todos os testes colavam o token limpo —
que é o que **o teste** tem em mão, não o que a pessoa tem.

Correção: `lib/features/boloes/data/token_de_convite.dart` normaliza o que foi
colado (link, link no meio de frase, espaço, query anexada, percent-encoding),
usado por `_entrarCom` na home. Percentual solto não vira exceção: vai para o
servidor e recebe a recusa dele.

## Observações

- `POST /pools/join` responde **200**, não 201 — a entrada é idempotente
  (reabrir o link não cria nada). Meu caso esperava 201 por hábito; corrigi o
  caso, não o endpoint.
- `DELETE /pools/:id/invite` responde 204. Idempotente por construção
  (`updateMany`), o que atende CC-4-10 sem código novo.
