Ir ao conteúdo
SEED engenhariaDesign System

Componentes

66. Credenciais — senha e código de uso único

estávelseed-componentes.md v1.43 · §66seção 72 de 9866-credenciais-senha-e-codigo-de-uso-unico-estavel.md · MD5 e3789c03

Título completo no canon: Credenciais — senha e código de uso único — estável (F7.5, 2026-08-16 · promovido em 2026-08-17 pelo gate visual do Rafael — verbatim: "aprovado") · CD1–CD16 · fecha C13 e C14 · bancada banco-credencial.html v0.2 · suite-credencial.mjs 30 · 0 · 0

Por que os dois campos moram na MESMA seção — e o que foi descartado. C13 (senha com revelar) e C14 (campo de código/OTP) chegaram na fila como duas lacunas. Viraram uma seção porque são governados pela mesma norma e falham pelo mesmo mecanismo: o SC 3.3.8 Accessible Authentication (Minimum) da WCAG 2.2 proíbe teste de função cognitiva em qualquer etapa da autenticação — memorizar, transcrever, soletrar, calcular. Bloquear o colar, atrapalhar o gerenciador de senha e exigir transcrição são o mesmo defeito nos dois campos, e o conserto é o mesmo. Descartado: duas seções (§66 e §67). Separá-las duplicaria os contratos idênticos — colar, autocomplete, mensagem de erro — e cópia de contrato é a classe de problema que o tokens_bloco.py existe para impedir. Se um dia um dos dois ganhar contrato que o outro não pode ter, a separação nasce por supersede formal, não por conveniência.

66.0 Rodada zero — NÃO VISITADO, com o motivo dito#

O quê Veredito Motivo
Tela de autenticação do produto de referência (arquétipo A19) NÃO VISITADO Toda a leitura do estudo-clickup-completo.md foi feita dentro de uma sessão logada. Ver a tela de login exigiria sair da sessão da conta corporativa — risco operacional real, e a autorização de navegação é de leitura, não de mexer em estado de conta
Fluxo de recuperação com código NÃO VISITADO — e bloqueado Ele só existe depois de disparar um e-mail de verdade. Disparar é escrita, e escrita não está autorizada (mesma barreira nomeada da PS-P2)

E aqui a ausência de leitura visual custa pouco, e é preciso dizer por quê para não parecer conveniência: campo de credencial é o arquétipo do sistema em que a norma é mais densa e mais específica — o SC 3.3.8 chega ao ponto de dizer que colar tem de funcionar. Onde a norma decide, copiar o desenho do vizinho não acrescenta; mede-se contra a norma. É o oposto do §57 (quadro), em que a norma diz pouco e a leitura visual decidiu quase tudo.

66.1 RITO — três rodadas encadeadas#

Rodada Fonte O que trouxe
R1 — canon W3C, Understanding SC 3.3.8 Accessible Authentication (Minimum) Define teste de função cognitiva como "memorização, transcrição, uso de ortografia correta, cálculos ou resolução de puzzles". Verbatim que decide o C14: "um serviço que requer transcrição manual de código de verificação não é compatível. Como com usuários e senhas, deve ser possível ao usuário pelo menos COLAR o código." E: bloquear paste ou exigir "o 1º, 3º e 5º caractere" falha o critério. Gerenciador de senha e copiar-colar são listados como mecanismos conformantes
R2 — mercado/stack GOV.UK Design System — Password input · Cloud Four — Simple One-Time Passcode Inputs GOV.UK: o revelar é button com aria-label “Show password”/“Hide password”, anúncio “Your password is visible/hidden”, type volta a password no envio (senão o navegador guarda o valor como texto e o oferece em autofill de campo comum), spellcheck="false" contra spell-jacking, sem maxlength, e o achado de pesquisa: “ter um segundo campo não ajuda os usuários” — o campo “confirme a senha” sai. Cloud Four: OTP é um <input> com inputmode="numeric", autocomplete="one-time-code", pattern e maxlength; a aparência de caixinhas se faz com tipografia (mono + letter-spacing), não com seis elementos
R3 — normas WCAG 2.2: SC 1.3.5 Identify Input Purpose · SC 1.4.11 Non-text Contrast · SC 2.2.1 Timing Adjustable · SC 4.1.3 Status Messages autocomplete correto é o que permite o preenchimento automático (1.3.5) e o que torna o gerenciador um mecanismo (3.3.8). A borda do campo é elemento não-textual e cobra 3:1 (1.4.11) — foi por aí que apareceu o achado do 66.4. O prazo do código cai na exceção Essential do 2.2.1: estender invalidaria a atividade; o contrato então não é estender, é declarar o prazo e oferecer reenvio

66.2 Os contratos CD1–CD16#

# Contrato Por quê Descartado
CD1 Colar nunca é bloqueado — senha e código SC 3.3.8 literal. E é o contrato que a suíte prova usando a área de transferência de verdade (Ctrl+V), não lendo atributo “Bloquear paste por segurança”: empurra a pessoa para senha memorizável, que é menos segura
CD2 autocomplete correto e obrigatório: username · current-password · new-password · one-time-code É o que faz o gerenciador de senha funcionar — e gerenciador é mecanismo conformante do 3.3.8, além do SC 1.3.5 autocomplete="off" em campo de senha (prática comum, hostil, e ignorada pelos navegadores modernos)
CD3 Senha com spellcheck="false" e autocapitalize="none" Spell-jacking: o corretor pode enviar o conteúdo do campo a um serviço remoto. E capitalizar a primeira letra corrompe a senha em teclado móvel Deixar o padrão do navegador (o padrão não conhece o contexto)
CD4 Senha sem maxlength; o limite vira mensagem de erro Truncar em silêncio faz a pessoa guardar uma senha que ela não digitou — e descobrir no próximo login maxlength “para proteger o banco” (o hash tem tamanho fixo; o limite é do formulário, não do dado)
CD5 Sem campo “confirme a senha” Achado de pesquisa do GOV.UK: “um segundo campo não ajuda”. Com revelar disponível, ele é digitação dobrada sem ganho Confirmação obrigatória (convenção herdada de quando não existia revelar)
CD6 O revelar é button type="button", com aria-controls e nome que diz o efeito Dentro de um <form>, botão sem type é SUBMIT — um “mostrar senha” que envia o formulário é defeito que só aparece no primeiro uso real. E “olho” mudo não é nome checkbox “mostrar senha” (o estado do controle não é o estado do campo); ícone sem nome acessível
CD7 A visibilidade é anunciada, não só refletida no botão Quem não vê a tela precisa saber que a senha está exposta em texto — é informação de segurança física (alguém atrás), não de UI Só trocar o rótulo do botão (não é anúncio; a AT não relê o botão sozinha)
CD8 Ao enviar, o campo volta a type="password" GOV.UK, verbatim: senão o navegador memoriza o valor como texto digitado e passa a oferecê-lo em autofill de campos não-senha Deixar revelado (vazamento silencioso, e a pessoa não fez nada errado)
CD9 A senha começa oculta; revelar é ação deliberada Padrão seguro. O estado inicial não pode depender de quem não escolheu nada Começar revelada “porque é mais fácil”
CD10 O código é UM campo — nunca N caixinhas Com maxlength="1", colar o código deixa um dígito. Isso é transcrição manual obrigatória: falha do 3.3.8. Some-se seis paradas de tabulação para um dado só e o autofill do sistema sem alvo Seis caixinhas — o desenho mais comum do mercado. Está impresso na bancada, operante e na sua MELHOR forma, e a suíte mede os dois (ver 66.4-b)
CD11 No código, inputmode="numeric", pattern e maxlength são legítimos Aqui o comprimento é do sistema (o código tem 6 dígitos por definição), não da pessoa. É o oposto do CD4, e o porquê está dito — a mesma propriedade é certa num campo e errada no outro Tratar os dois campos com a mesma regra “sem maxlength” (regra sem motivo vira dogma)
CD12 O prazo do código é declarado em texto, e existe reenvio SC 2.2.1, exceção Essential: estender o prazo invalidaria a atividade. O que se pode fazer é não esconder e dar caminho de saída Contador regressivo animado (pressão, e vira ruído em leitor de tela); prazo só no e-mail
CD13 Erro de credencial não diz qual metade errou; erro de formato diz “Essa senha está errada” confirma que o usuário existe — enumeração de contas. Mas “o código tem 6 dígitos” não revela nada e evita uma tentativa perdida. A fronteira é: formato ajuda, existência não Mensagem específica sempre (vaza); mensagem genérica sempre (esconde erro de digitação do próprio usuário)
CD14 Força da senha com texto e forma, e ela não bloqueia o envio Barra colorida sozinha é o mesmo defeito das quatro bandeiras em quatro cores do §63 (C131): em cinza viram a mesma barra. Aqui a quantidade de blocos preenchidos é a forma Bloquear envio por “senha fraca” (regra de política do produto, não do DS — e empurra para senha decorável)
CD15 Caps Lock ligado é aviso anunciado, não erro Com a senha oculta a pessoa vê pontinhos idênticos e não tem como saber por que falhou Detectar só depois do erro (tarde); nada (o padrão, e é o motivo de metade dos “esqueci a senha”)
CD16 Nenhuma transcrição parcial (“digite o 1º, 3º e 5º caractere”) Falha citada nominalmente no Understanding do SC 3.3.8, e incompatível com gerenciador de senha O padrão bancário brasileiro de “letras da senha” (é exatamente o caso que a norma proíbe)

66.3 Os números medidos#

Medida Claro Escuro
Erro de credencial (texto sobre fundo de perigo) 6,58 9,47
Erro de formato 6,58 9,47
Aviso de Caps Lock 9,05 9,27
Confirmação do código 5,89 9,35
Dica do campo · rótulo da força 7,75 8,11
Borda do campo (não-textual, piso 3,00) 3,38 4,50

A prova do CD10, medida em casa e não citada: colado o mesmo 482913 nos dois desenhos, com clipboard real e Ctrl+V

Desenho O que ficou
Campo único (canônico) 4829136 de 6 dígitos
Seis caixinhas (contraexemplo) 4 · vazio · vazio · vazio · vazio · vazio — 1 de 6

66.4 O achado da BORDA — e a decisão, tomada depois de ler o gêmeo inteiro#

A guarda de contraste reprovou a borda do campo: --seed-border-default (#C8D6DF) sobre --seed-surface-raised (#FFFFFF) mede 1,49 no claro e 2,32 no escuro. Quando o fundo do campo é igual ao da superfície em volta — que é o caso —, a borda é o único indicador de onde se pode clicar, e o SC 1.4.11 cobra 3:1.

Medidos os quatro candidatos do gêmeo, nos dois temas, contra a superfície elevada:

Token Claro Escuro
--seed-border-default 1,49 ✗ 2,32 ✗
--seed-border-strong 2,53 ✗ 4,50 ✓
--seed-border-focus 3,22 ✓ 8,31 ✓
--seed-border-interactive 3,38 ✓ 4,50 ✓

E aí a leitura do gêmeo mudou a decisão que eu ia tomar. A primeira conclusão desta rodada foi "o §13 declara --seed-field-border (cinza-600, 4,74:1) e esse token não existe no seed-tokens.css; logo, promova-o ao gêmeo". Errado — e o próprio gêmeo diz por quê. O comentário da v1.12 do seed-tokens.css, escrito ao criar o --seed-border-interactive:

"fronteira de COMPONENTE INTERATIVO (SC 1.4.11, piso 3:1) — nenhum outro semântico de borda passava no claro (default 1.49, strong 2.53) … medido contra as seis superfícies 3.38/3.38/3.11/4.50/5.51/5.05, todos ≥3."

O sistema já tinha resolvido esta pergunta, com os mesmos números que eu remedi. Promover o --seed-field-border ao gêmeo criaria um segundo semântico para a mesma coisa — exatamente o drift que o tokens_bloco.py existe para impedir.

Decisão, com supersede formal: o --seed-border-interactive é o semântico canônico de fronteira de controle em todo o sistema. O --seed-field-border do §13 — declarado localmente dentro da banco-formfield.html, nunca no gêmeo — fica SUPERSEDIDO por ele.

E a decisão não é só de consistência: é melhor NOS DOIS TEMAS somados.

Claro Escuro
--seed-field-border (local, cinza-600) 4,74 3,21
--seed-border-interactive (gêmeo, cinza-500) 3,38 4,50

O token local é melhor no claro e pior no escuro; o do gêmeo é equilibrado e passa nos dois. Um par que se degrada na inversão é o defeito BT3 do §64 — e o token local se degrada.

Nada muda no gêmeo seed-tokens.css nesta rodada. §65, §66, §67 e §68 já consomem o --seed-border-interactive. O que sobra é migrar a banco-formfield.html do token local para o semântico do gêmeo — artefato estável, então entra por auditoria e não por edição solta (CD-P2).

66.4-b O contraexemplo estava fraco — o gate consertou, e o argumento ficou mais forte#

Apontamento do Rafael, verbatim: "eu tentei colar e não consegui, quando digito o cursor pula pro próximo campo, mas quando clico no backspace não consigo apagar cada campo, era pra ir voltando e apagando."

Ele está certo, e o erro era meu: a primeira versão das seis caixinhas só avançava o foco. Qualquer implementação séria de OTP em caixinhas escreve pelo menos três remendos — avançar ao digitar, voltar apagando no Backspace e navegar por setas. Comparar o campo único com uma versão capenga das caixinhas é espantalho, e argumento apoiado em espantalho cai na primeira vez que alguém implementa direito.

Corrigido: o contraexemplo agora tem os três remendos. E é aqui que o conserto fortalece a tese em vez de enfraquecê-la — porque o argumento verdadeiro nunca foi "caixinhas não funcionam", e sim quanto custa fazê-las funcionar:

Campo único Seis caixinhas
Avançar ao digitar — (não se aplica) remendo 1
Voltar apagando nativo remendo 2
Navegar por setas nativo remendo 3
Colar o código nativo — 6 de 6 dígitos remendo 4, que ninguém escreveu — 1 de 6
Paradas de tabulação 1 6
Alvo do autocomplete="one-time-code" 1 campo nenhum

Regra de método que sai daqui: contraexemplo tem de estar na MELHOR forma que o desenho concorrente consegue ter. Contraexemplo enfraquecido mede a nossa implementação dele, não a decisão que ele representa — e o placar verde vira autoengano.

A guarda CD10-c passa a medir isso: ela exercita os três remendos no contraexemplo e reprova se algum faltar. E foi provada capaz de reprovar antes de ser aceita: removidos os remendos, o placar vai a 26 · 1.

66.5 Dois defeitos de instrumento na mesma rodada#

Décimo sexto — o parser de cor não entendia HEXADECIMAL (nasceu no §65 e vale para toda guarda do projeto; o registro completo está em 65.4). Resumo: getComputedStyle devolve rgb(), mas o valor de um token lido por getPropertyValue volta como está escrito no gêmeo (#242E34). O regex de dígitos casava só o final e a razão saiu 232,67fisicamente impossível — com a guarda emitindo PASS. Regra nova: número fora da faixa [1,00 … 21,00] é MEDIDOR QUEBRADO, não veredito.

Décimo sétimo — a guarda leu a DOCUMENTAÇÃO do contrato como se fosse o contrato violado. A primeira forma do CD16 varria o innerText do <body> inteiro procurando “1º, 3º e 5º caractere”. Ela achou — dentro da própria tabela de contratos da bancada, onde o CD16 cita a frase proibida entre aspas para explicar o que proíbe. O artefato foi reprovado por explicar a si mesmo.

Regra nova: guarda mede o CONTROLE, nunca o texto que descreve o controle. O escopo passou a ser rótulos, legendas, dicas e placeholder dos campos. Mesma família dos defeitos de recorte (8º e 14º): escopo errado inventa achado ou esconde achado — aqui, inventou.

E a guarda foi provada capaz de reprovar antes de ser aceita: injetada a frase proibida num rótulo real, o placar vai a 25 · 1. Guarda que nunca falha não é guarda.

66.6 A bancada e a suíte#

banco-credencial.html v0.1, gerada por validacao/gen-banco-credencial.py sobre validacao/banco-credencial-template.html. Barra fixa e seletor de largura desde a v0.1 (BT1/BT2). Nada nesta bancada envia nada a lugar nenhum, e o selo diz isso.

suite-credencial.mjs — 27 PASS · 0 FAIL · 1 medida. É a primeira suíte do projeto que usa a área de transferência: o contexto do navegador é aberto com permissão de clipboard, o código é escrito nele e colado com Ctrl+V. Colar não se prova lendo atributo.

Guarda O que ela faz de fato
CD1-senha / CD1-codigo escreve no clipboard e cola nos dois campos
CD10-b cola o mesmo código nos dois desenhos e compara: 6/6 contra 1/6
CD7 clica no revelar e confere tipo, nome do botão e anúncio
CD8 envia o formulário e confere que o tipo voltou a password
CD15 dispara keyup com modifierCapsLock — e a guarda declara que o modificador é sintético, em vez de fingir que ligou a tecla
CD12-OP clica em reenviar e confere que o campo limpou e o prazo foi anunciado
CD13-OP digita código incompleto, clica em confirmar e confere erro, aria-invalid e foco

66.7 Pendências#

# Pendência Por que fica aberta
CD-P1 FECHADA — gate visual APROVADO em 2026-08-17. O olho achou que o contraexemplo das seis caixinhas era espantalho (não voltava apagando no Backspace); corrigido para a melhor forma de mercado, com guarda CD10-c. A seção é promovida a estável
CD-P2 Migrar a banco-formfield.html do --seed-field-border local para o --seed-border-interactive do gêmeo Decidido em 2026-08-16 (66.4), com supersede formal: o gêmeo já tem o semântico canônico de fronteira de controle desde a v1.12, criado com os mesmos números. O token local é melhor no claro (4,74 × 3,38) e pior no escuro (3,21 × 4,50). A migração é de artefato estável: entra por auditoria, junto com a CD-P3
CD-P3 Auditoria de todos os campos do sistema contra o piso 3,00 de borda Esta rodada mediu banco-formfield (passa, 4,74/3,60) e os dois artefatos novos. As telas (tela-detalhe, tela-lista, tela-painel) não foram medidas nesta régua
CD-P4 FECHADA em 2026-08-16, no gate. Dado real num artefato estável A banco-formfield.html trazia dois endereços de e-mail reais — linha 333 (estado success, campo s4) e linha 756 (campo g3). Os dois viraram operador@exemplo.com.br. Achado colateral do gate: a varredura foi feita porque o Rafael perguntou onde verificar — e a resposta honesta exigiu procurar, o que revelou a segunda ocorrência que o registro original não mencionava
CD-P5 O fluxo completo de autenticação (arquétipo A19) segue AUSENTE O §66 entrega os campos; a tela de entrar/recuperar/criar conta não existe como tela-*.html. O mapa de cobertura registra A19 como arquétipo, e ele continua sem gabarito
BancadaSEED Design System v2 · banco-credencial (§66 · senha e código de uso único) — preview v0.2abrir em página própria ↗

Também cita o §66: tela-autenticacao.

Esc