fix(agenda): o botão "Reativar" tipo de agendamento passa a funcionar - #716
fix(agenda): o botão "Reativar" tipo de agendamento passa a funcionar#716paulolimajr77 wants to merge 1 commit into
Conversation
Ele nunca funcionou, desde que a tela nasceu. Mandava
`PATCH /api/v1/agenda/tipos` com `{ id, is_active: true }`, e o
`alterarSchema` daquela rota e `criarSchema.partial()` — `is_active` nao
esta entre os doze campos de `camposDoTipo`. Zod descarta chave
desconhecida em SILENCIO: o corpo chegava vazio ao `update` e a rota
respondia 422 "Nenhum campo para alterar." para quem nao pediu para
alterar campo nenhum.
Quem desativou um tipo por engano ficava sem saida pela tela — o nome
seguia ocupado pelo tipo desligado, porque o slug e unico.
O compilador teria acusado. Nao acusou porque a chamada terminava em
`as never`, o unico cast do arquivo da tela, exatamente em cima da
travessia.
O conserto espelha o Desativar em vez de tornar `is_active` editavel:
aceita-lo no PATCH deixaria o mesmo pedido que muda a duracao poder
DESLIGAR um tipo, e a trilha registraria a religada como
`agenda.tipo_alterado { campos: ["is_active"] }` — indistinguivel de uma
alteracao de campo qualquer. Sub-rota de acao e a forma que a casa ja usa
(`agenda/google/desconectar`, `contacts/merge`, `lgpd/anonymize`).
O que vigia:
- `tests/unit/agenda-reativar-tipo.test.ts` — comportamento da rota nova
(grava, filtra o tenant pela sessao, audita com verbo proprio, recusa o
que nao existe) e a TRAVESSIA tela->rota: toda chave que a tela manda
tem de ser aceita pelo schema. Sabotado de volta ao estado antigo, o
caso reprova nomeando `is_active`.
- O caso e2e ja existia e conferia o botao so com `toBeVisible` — foi
assim que ele sobreviveu morto. Ver que o controle esta DESENHADO nao e
ver que ele ABRE. Agora clica e cobra o efeito nos dois lugares.
⚠️ Custo medido no proprio teste: a primeira versao da travessia passou
verde com a tela sabotada. O corpo era `{…} as never`, um `AsExpression`
e nao um `ObjectLiteralExpression`, entao a varredura atravessava sem ver
chave nenhuma. O cast escondia o campo do compilador E do guarda escrito
para vigiar o compilador. O leitor agora desembrulha `as`/`satisfies`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
@paulolimajr77 is attempting to deploy a commit to the rafael-maudibrasil's projects Team on Vercel. A member of the Team first needs to authorize it. |
ECC Tools / Security EvidenceCommit: Security evidence gate passed (success) No security-sensitive scanner-evidence gap detected. Mode: enforce Scanned 7 changed file(s). No missing scanner-evidence signal was detected. Check publication was denied or unavailable. An app owner must enable Checks: read and write, and the installation owner must approve the updated permission. |
ECC Tools / PR Risk TaxonomyCommit: PR taxonomy review recommended (neutral) Detected 1 PR taxonomy bucket(s): CI/CD Recommendation. Scanned 7 changed file(s). Roadmap taxonomy buckets: CI/CD RecommendationCI, dependency, coverage, and contract signals should be routed into follow-up checks or verification work. Signals:
Paths:
Check publication was denied or unavailable. An app owner must enable Checks: read and write, and the installation owner must approve the updated permission. |
ECC Tools / Reference Set ReadinessCommit: Reference set readiness gaps detected (neutral) Reference evidence present for 1/7 areas (14%) across 7 changed file(s). This check is based on files changed in this PR. Repository-level readiness is still reported by
Check publication was denied or unavailable. An app owner must enable Checks: read and write, and the installation owner must approve the updated permission. |
ECC Tools / Hosted Promotion ReadinessCommit: Hosted promotion readiness passed (success) No hosted promotion evidence gaps detected across 7 changed file(s); 0 corpus scenarios had matching evidence. This check compares PR file changes against the evaluator/RAG promotion corpus in No evaluator corpus scenarios matched this PR. Check publication was denied or unavailable. An app owner must enable Checks: read and write, and the installation owner must approve the updated permission. |
|
Recebido, @paulolimajr77 — obrigado por isto. Duas coisas que vão parecer erro seu e não são:
Um mantenedor vai revisar de verdade — rodando os gates e reproduzindo o comportamento, não só Esta mensagem é automática e não diz nada sobre o seu PR: ela é sobre o processo. O que vem |
|
Recebido — obrigado. Duas coisas que vão parecer erro seu e não são:
Um aviso útil: a Vou revisar de verdade — rodando os gates e reproduzindo o comportamento, não só lendo o diff — e volto com o resultado. Se eu achar algo, venho com a medição junto, nunca com um "acho que". |
O botão "Reativar" de Configurações › Tipos de agendamento existe desde que a tela existe e nunca funcionou uma vez. Clicar devolve sempre
422 "Nenhum campo para alterar."— para quem não pediu para alterar campo nenhum.Quem desativa um tipo por engano fica sem saída pela tela: o nome segue ocupado pelo tipo desligado, porque o slug é único.
A causa
app/app/settings/tenant/agenda/_client.tsxmandaPATCH /api/v1/agenda/tiposcom{ id, is_active: true }. OalterarSchemadaquela rota écriarSchema.partial().extend({ id }), eis_activenão está entre os doze campos decamposDoTipo. Zod descarta chave desconhecida em silêncio: o corpo chega vazio aoupdatee a rota cai na recusa de "nenhum campo".O compilador teria acusado. Não acusou porque a chamada terminava em
as never— o único cast do arquivo, exatamente em cima da travessia.O conserto
Espelha o
DELETEem vez de tornaris_activeeditável. Aceitá-lo no PATCH deixaria o mesmo pedido que muda duração poder desligar um tipo, e a trilha registraria a religada comoagenda.tipo_alterado { campos: ["is_active"] }— indistinguível de uma alteração de campo qualquer. Sub-rota de ação é a forma que a casa já usa (agenda/google/desconectar,contacts/merge,lgpd/anonymize).POST /api/v1/agenda/tipos/reativar— mesma guarda do desativar (manager+requireSupportWrite), filtro explícito deorganization_id, 404 quando não há linhaagenda.tipo_reativadoemAUDIT_ACTIONSas neversai da telaO que medi
tests/unit/agenda-reativar-tipo.test.ts(12 casos), em duas camadas:is_active: true, filtra o tenant pela sessão, audita com verbo próprio, recusa o que não existe, e os dois caminhos de recusa não escrevemis_active{…} as never— umAsExpression, não umObjectLiteralExpression—, então a varredura atravessava sem ver chave nenhuma. O cast escondia o campo do compilador e do guarda escrito para vigiar o compilador. O leitor agora desembrulhaas/satisfiesantes de ler o corpo.O caso e2e já existia e conferia o botão só com
toBeVisible— foi assim que ele sobreviveu morto. Ver que o controle está desenhado não é ver que ele abre. Reescrito: agora clica e cobra o efeito nos dois lugares (o rótulo "desativado" sai da lista, e o tipo volta a ser oferecido em/app/agenda).Gates na prévia do merge:
typecheck0, testes da área 26/26.Provado em tela, numa VPS real rodando a mudança: desativar → reativar → o aviso "Tipo reativado." e a linha volta ao normal.
O que NÃO medi
pnpm test:unitinteiro nesta branch (rodei na branch de origem da mudança: 5 arquivos vermelhos, os 4 conhecidos de Windows + 1 meu, já corrigido)pnpm test:e2e— precisa de Supabase local e app buildado; a spec alterada roda no CI🤖 Generated with Claude Code