Skip to content

feat(E15): entrar sem entrar, do número da OAB à tela de retomada - #111

Merged
danielgorgonha merged 5 commits into
mainfrom
feat/oab-kept
Sep 21, 2026
Merged

danielgorgonha merged 5 commits into
mainfrom
feat/oab-kept

Conversation

@danielgorgonha

@danielgorgonha danielgorgonha commented Sep 21, 2026 •

Copy link
Copy Markdown
Member

Fecha a E15 em 11 de 12. A única tarefa que sobra é a T10, que é Plus: o botão do Google no painel do
advogado. Cinco commits, um por tarefa.

E15-T09 — o número da OAB

O campo existia no formulário, viajava no pedido e era descartado na chegada. Pior do que não perguntar:
promete uma conferência que nada consegue fazer.

cadastro() grava o número só em conta de advogado; public_user() devolve a chave sempre, nula para
quem não tem; a rota pública da cidadã devolve advogado: {nome, oab}, que é onde o número serve, porque
ela recebeu um link de alguém que diz ser advogado. A frase c0.sentYou prometia {oab} desde a primeira
tela e não tinha de onde ler; agora lê, com variante sem número. Mock em paridade.

Eu tinha marcado a T09 como pronta com só a coluna criada. O texto da prova no épico foi corrigido.

E15-T07 — destinatária é uma conta, não um endereço

ensure_recipient() comparava visitor.email com inv.email, então conta sem e-mail nunca passava, e a
conta que a confirmação de nome cria é exatamente essa. Pôr o endereço no convite desligava o caminho sem
digitação: a pessoa via o botão e recebia 403 ao tocar.

Coluna nova Invite.usuario_id e invites.claim(). Enquanto ninguém reivindicou, vale a regra antiga por
endereço. confirm-name passou a usar ensure_valid, porque confirmar o nome é virar a destinatária.
DELETE /api/tarefas/{id}/cidadao devolve o convite ao estado sem dona: sem isso o documento ficaria
trancado para todo mundo, e foi um teste que já existia que pegou.

E15-T06 — "esse nome não é o meu"

O botão só marcava uma variável local. POST /api/t/{hash}/deny-name registra e não faz mais nada: não
cria conta, não vincula e não tranca a confirmação depois, porque tocar no botão errado não pode deixar
ninguém de fora do próprio documento. A leitura e as dúvidas seguem. O painel mostra o aviso enquanto
ninguém se vinculou, que é a única coisa que quem enviou pode consertar sozinho.

E15-T08 — como voltar depois

A conta nasce sem e-mail e sem senha, então não existe "esqueci minha senha" e não há endereço para onde
mandar link novo. /t/{hash}/resume dá a mensagem pronta para ela mandar para si mesma, por WhatsApp ou
copiando. A mensagem leva só o endereço: resumeMessage() aceita o título do documento e o ignora de
propósito, porque título de documento jurídico costuma ser o pior pedaço dele para aparecer na conversa de
alguém. O link do WhatsApp vai sem número de destino.

E15-T11 — os quatro casos do critério de aceite

Três já valiam. O quarto não: confirmar o nome duas vezes devolvia 409, ou seja, um toque duplo num celular
lento dizia à dona do documento que ela é outra pessoa. O 409 é para a segunda pessoa, não para a segunda
batida da mesma pessoa, e a sessão devolvida é a mesma.

No web, o teste chama a rota confirm-name de verdade e confere que o corpo não tem token e que o cookie
sai HttpOnly. Conferido por mutação: devolvendo o token no corpo, o teste fica vermelho.

Como verificar

python -m pytest tests_v3.py -q (149 passando), pnpm test (103 passando), pnpm lint e pnpm build.

O grep do critério de aceite volta vazio:
grep -rn 'type="password"\|inputMode="numeric"\|one-time-code' apps/web/components/Journey.tsx apps/web/app/t

Fora do repositório, no workspace: ADR-0012 escrito (a T12 pedia
0010, mas 0010 é a âncora OpenTimestamps e 0011 é a base legal de dado sensível), com a linha do ADR-0006
no índice dizendo que a parte de login da cidadã foi revista. A afirmação sobre o credenciamento do gov.br
ficou marcada [NÃO VERIFICADO]: nenhuma fonte da pesquisa a sustenta.

The field existed on the form, travelled in the request and was dropped on arrival, which is worse than
not asking: it promises a check that nothing can perform. The number is now stored on lawyer accounts
only, returned by every account payload as a key that is null for whoever has no number, and carried to
the citizen beside the name of whoever sent the document, which is where it is worth anything: she got a
link from a stranger who says he is a lawyer, and the number is what she can look up at the Ordem.

The phrase `c0.sentYou` had promised `{oab}` since the first screen and had nowhere to read it from. It
now reads it, with a variant that names only the lawyer when there is no number, so the screen never
invents one.
@vercel

vercel Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
leia Ready Ready Preview Sep 21, 2026 8:24pm UTC

Request Review

`ensure_recipient()` compared `visitor.email` with `inv.email`, so an account with no e-mail never passed,
and the account the name confirmation creates is exactly that one. Putting the address on the invite
switched off the very path this epic exists to open: the person saw the button and got a 403 on touch.

The invite now remembers which account claimed it. While nobody has claimed it the old rule by address
still holds, which is what remains for invites issued before this column. Claiming is a different act and
does not go through the addressee rule: confirming the name IS becoming the addressee, and demanding that
she already was would shut the door on whoever holds the link and the name.

Undoing a link clears the claim as well. Without that, the account that was undone would keep the invite
and the document would stay locked for everyone, including the right person.
@danielgorgonha danielgorgonha changed the title feat(auth): keep the OAB number the signup was already asking for (E15) feat(E15): keep the OAB, and make the addressee an account instead of an address Sep 21, 2026
…x it (E15)

The button set a local flag and nothing else. The document then sat in the panel with no hint of why it
never moved, and the one person who can fix a document sent to the wrong name had no way to learn of it.

`POST /api/t/{hash}/deny-name` only records. It creates no account, links nothing, and does not lock the
confirmation afterwards: touching the wrong button cannot shut someone out of their own document. Reading
and doubts keep working by design, because the barrier for someone on a borrowed phone is the account, not
the reading; what she loses is the receipt, which claims a name understood the document.

The client swallows a failed record: the warning serves whoever sent the document, and the person who
touched the button cannot get a red bar over a problem that is neither hers nor in her way.
… it (E15)

Her account was born with no e-mail and no password, which is the whole point of getting in without
typing. The bill for that comes due here: there is no "forgot my password", because there is no password,
and no address to send a new link to. The link she already has is the only way back, and keeping it is
something she has to do now, while the phone is in her hand.

Where this person keeps things is her own WhatsApp conversation with herself, not browser bookmarks she
may not know exist and that vanish with the phone. So the screen offers two things: copy and send.

The message carries the address and nothing else. `resumeMessage()` accepts the document title and ignores
it on purpose: the title of a legal document tends to be the worst part of it to surface in someone's chat
thread, and the address alone already does the entire job. The WhatsApp link carries no destination
number, so she is the one who picks who it goes to.
…that was missing

Three of them already held. The fourth did not: confirming the name twice returned 409, so a double tap on
a slow phone told the owner of the document that she is somebody else. The 409 is for the second person,
not for the second tap of the same person, and the session handed back is the same one, so repeating the
request never drops the first.

On the web side the test calls the real `confirm-name` route and checks that the body carries the person
and never the token, and that the cookie comes back HttpOnly. That account is the one that needs the rule
most: it was born with no e-mail and no password, so the token IS the whole account, and there is no
password to change afterwards. The test was checked by mutation, returning the token in the body to watch
it go red.
@danielgorgonha danielgorgonha changed the title feat(E15): keep the OAB, and make the addressee an account instead of an address feat(E15): entrar sem entrar, do número da OAB à tela de retomada Sep 21, 2026
@danielgorgonha
danielgorgonha merged commit 338edce into main Sep 21, 2026
4 checks passed
@danielgorgonha
danielgorgonha deleted the feat/oab-kept branch September 21, 2026 20:25

This branch was successfully deployed

1 active deployment
Preview — 02159ba3 Deployed Sep 21, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant