Corrige defeitos de UX/UI do shell operacional - #4
Conversation
|
Warning Review limit reached
Next review available in: 16 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (11)
WalkthroughA PR atualiza autenticação, navegação, páginas do dashboard, acessibilidade e estilos visuais. Também adiciona estados de carregamento e erro, o endpoint de sign-out, documentação de UX/UI e suporte do Chromium no CI. ChangesAutenticação e roteamento
Shell e dashboard
Fundação visual e verificação
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f2b13b799d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| const supabase = await createClient() | ||
| const { data } = await supabase.auth.getUser() |
There was a problem hiding this comment.
Read the account identity from verified claims
On every authenticated initial dashboard render, this server layout calls auth.getUser() even though the proxy has already verified the JWT. This adds another Auth service request and makes the entire dashboard render fail or stall when that request is unavailable merely to obtain a display label; read the e-mail from auth.getClaims() as required by the repository's server-auth invariant instead.
AGENTS.md reference: AGENTS.md:L15-L15
Useful? React with 👍 / 👎.
| * bounce the user to another host after a successful sign-in. | ||
| */ | ||
| function resolveDestination(next: string | null) { | ||
| if (!next || !next.startsWith("/") || next.startsWith("//")) { |
There was a problem hiding this comment.
Validate the parsed origin of post-login destinations
When an attacker supplies a destination such as ?next=%2F%5Cevil.example, the decoded value begins with / and not //, so it passes this check, but WHATWG URL parsing normalizes the backslash and treats it as https://evil.example/. After a successful sign-in, router.replace can therefore perform an external navigation; reuse the callback route's parsed-URL origin comparison rather than validating only the string prefix.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/ux-ui-auditoria.md`:
- Around line 126-132: Atualize os dois blocos de outline no documento para usar
cercas Markdown com a linguagem text, preservando integralmente o conteúdo
textual e removendo os avisos MD040.
In `@README.md`:
- Line 103: Atualize a seção “Ainda não existe” do README para não indicar mais
que o logout está indisponível; remova essa menção ou documente a rota existente
POST /auth/sign-out.
In `@src/app/auth/sign-out/route.ts`:
- Around line 9-15: Atualize o fluxo de logout em torno de
`supabase.auth.signOut()` para capturar falhas da promessa e redirecionar para
`/login` com uma resposta de erro, sem usar o status 303 de sucesso quando o
logout falhar. Preserve o redirecionamento 303 apenas para execuções
bem-sucedidas.
In `@src/app/globals.css`:
- Line 12: Remove the raw hexadecimal value from the --primary-strong
declaration in globals.css and reference the existing --brand-800 design token
instead, preserving the light-only theme and a single source of truth.
In `@src/components/auth/login-form.tsx`:
- Around line 43-47: Atualize o tratamento de erro no fluxo de login para não
comparar signInError.message; use o código estruturado retornado pelo
Supabase/Auth, tratando invalid_login_credentials como credenciais incorretas e
mantendo a mensagem genérica para os demais erros.
- Around line 17-22: Atualize resolveDestination para validar o destino
normalizado com URL antes de retorná-lo, rejeitando valores como
"/%5Cexample.com" que possam ser interpretados como navegação para outra origem;
preserve FALLBACK_DESTINATION para qualquer destino inválido e mantenha o fluxo
existente de router.replace para destinos comprovadamente internos.
In `@src/components/dashboard/metric-card.tsx`:
- Around line 31-42: Atualize o estado `isLoading` no componente do cartão de
métrica para marcar o contêiner como `aria-busy` e incluir um texto `sr-only`
com “Carregando {label}”, mantendo o `Skeleton` visual existente. Garanta que o
anúncio seja acessível sem alterar os estados de valor ou ausência de dados.
In `@src/components/layout/app-shell.tsx`:
- Around line 175-185: Atualize o item de menu de encerramento na composição
DropdownMenuItem para que a ativação por Enter ou Espaço acione o botão de
envio, mantendo o form como contêiner. Faça o button type="submit" preencher
toda a área do item e receber corretamente a interação por teclado, sem alterar
a ação de sign-out.
In `@src/components/ui/sheet.tsx`:
- Around line 75-77: Update the XIcon element in the sheet close-control markup
to include aria-hidden="true", keeping the existing “Fechar” screen-reader text
unchanged so the icon is treated as decorative and not announced redundantly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 58a7a4f0-398d-4579-a2e2-6961ad608112
⛔ Files ignored due to path filters (6)
public/file.svgis excluded by!**/*.svgpublic/globe.svgis excluded by!**/*.svgpublic/next.svgis excluded by!**/*.svgpublic/vercel.svgis excluded by!**/*.svgpublic/window.svgis excluded by!**/*.svgsrc/app/icon.svgis excluded by!**/*.svg
📒 Files selected for processing (22)
ARCHITECTURE.mdCLAUDE.mdREADME.mddocs/ux-ui-auditoria.mdsrc/app/(auth)/login/page.tsxsrc/app/(dashboard)/[module]/page.tsxsrc/app/(dashboard)/dashboard/page.tsxsrc/app/(dashboard)/error.tsxsrc/app/(dashboard)/layout.tsxsrc/app/(dashboard)/loading.tsxsrc/app/(dashboard)/not-found.tsxsrc/app/auth/sign-out/route.tssrc/app/globals.csssrc/app/layout.tsxsrc/app/not-found.tsxsrc/components/auth/login-form.tsxsrc/components/dashboard/metric-card.tsxsrc/components/layout/app-shell.tsxsrc/components/ui/button.tsxsrc/components/ui/card.tsxsrc/components/ui/sheet.tsxsrc/proxy.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (6)
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.{ts,tsx}: Use strict TypeScript; do not useanyor@ts-ignore.
Never expose or read Supabaseservice_roleor secret keys in browser code, the repository, or examples.
Group imports as external imports followed by@/…imports, separated by a blank line.
Use Portuguese-Brazilian text for interface content; use English for comments and identifiers except defined domain terms.
Files:
src/components/ui/button.tsxsrc/app/auth/sign-out/route.tssrc/app/(dashboard)/error.tsxsrc/proxy.tssrc/app/not-found.tsxsrc/app/(auth)/login/page.tsxsrc/app/(dashboard)/layout.tsxsrc/components/ui/sheet.tsxsrc/app/(dashboard)/not-found.tsxsrc/components/ui/card.tsxsrc/app/layout.tsxsrc/app/(dashboard)/dashboard/page.tsxsrc/components/dashboard/metric-card.tsxsrc/app/(dashboard)/[module]/page.tsxsrc/components/auth/login-form.tsxsrc/app/(dashboard)/loading.tsxsrc/components/layout/app-shell.tsx
src/components/**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Provide
aria-labelfor icon-only controls,aria-hiddenfor decorative icons,sr-onlytitles for sheets, androle="alert"for errors.
Files:
src/components/ui/button.tsxsrc/components/ui/sheet.tsxsrc/components/ui/card.tsxsrc/components/dashboard/metric-card.tsxsrc/components/auth/login-form.tsxsrc/components/layout/app-shell.tsx
src/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Use Base UI via shadcn components, not Radix UI; use
lucide-reactfor icons.
Files:
src/components/ui/button.tsxsrc/components/ui/sheet.tsxsrc/components/ui/card.tsxsrc/components/dashboard/metric-card.tsxsrc/components/auth/login-form.tsxsrc/components/layout/app-shell.tsx
src/components/ui/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Do not edit generated shadcn UI primitives without a specific reason, and review added components to ensure they use project tokens.
Files:
src/components/ui/button.tsxsrc/components/ui/sheet.tsxsrc/components/ui/card.tsx
src/app/**/*.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
src/app/**/*.tsx: Use Server Components by default; add"use client"only when state, events, or hooks require it.
Use TanStack Query only for genuinely interactive remote state; prefer Server Components for simple reads.
Before completing UI work, verify mobile and desktop viewports, visible focus, contrast, loading/error/empty states, and keyboard navigation.
Files:
src/app/(dashboard)/error.tsxsrc/app/not-found.tsxsrc/app/(auth)/login/page.tsxsrc/app/(dashboard)/layout.tsxsrc/app/(dashboard)/not-found.tsxsrc/app/layout.tsxsrc/app/(dashboard)/dashboard/page.tsxsrc/app/(dashboard)/[module]/page.tsxsrc/app/(dashboard)/loading.tsx
src/app/globals.css
📄 CodeRabbit inference engine (CLAUDE.md)
Keep the interface light-only and use the project design tokens; do not reintroduce dark mode or raw hex colors.
Files:
src/app/globals.css
🪛 LanguageTool
ARCHITECTURE.md
[locale-violation] ~138-~138: “server” é um estrangeirismo. É preferível dizer “servidor”.
Context: ...proxy.ts, src/lib/supabase/proxy.ts, src/lib/supabase/server.ts, src/app/auth/callback/route.ts`...
(PT_BARBARISMS_REPLACE_SERVER)
docs/ux-ui-auditoria.md
[style] ~4-~4: Para conferir mais clareza ao seu texto, busque usar uma linguagem mais concisa.
Context: ..., visão geral e páginas de módulo), com o que foi corrigido nesta rodada e o que continua em aberto...
(O_QUE_ESTAR_SER_PARTICIPIOPASSADO)
[grammar] ~6-~6: Possível erro de concordância.
Context: ... DESIGN.md e inspeção do build de produção em Chromium (1440×1000 e 39...
(GENERAL_GENDER_AGREEMENT_ERRORS)
[grammar] ~16-~16: Possível erro de concordância.
Context: ... — crítico Encontrado ao verificar o build: middleware-manifest.json vinha com `...
(ERRO_DE_CONCORDNCIA_DO_GÉNERO_MASCULINO_O)
[grammar] ~28-~28: Possível erro de concordância.
Context: ... Correção: proxy.ts → src/proxy.ts. O build passou a listar ƒ Proxy (Middleware) ...
(ERRO_DE_CONCORDNCIA_DO_GÉNERO_MASCULINO_O)
[uncategorized] ~41-~41: Pontuação duplicada
Context: ... — crítico globals.css declarava --font-sans: "Plus Jakarta Sans" e `body ...
(DOUBLE_PUNCTUATION_XML)
[style] ~41-~41: Possível fragmento. Utilize apenas uma conjunção deste tipo.
Context: ...rava --font-sans: "Plus Jakarta Sans" e body { font-family: "Plus Jakarta Sans" }, mas nada no projeto baixava a fonte: sem `n...
(REDUNDANT_CONJUNCTIONS)
[misspelling] ~49-~49: Você quis dizer “Google”?
Context: ...ema. Correção: Plus_Jakarta_Sans via next/font/google (variável, 200–800, display: "swap",...
(GOOGLE)
[grammar] ~51-~51: Possível erro de concordância.
Context: ...ns. A fonte passa a ser auto-hospedada no build. > next/font/google` baixa a fonte em...
(GENERAL_GENDER_AGREEMENT_ERRORS)
[grammar] ~53-~53: Possível erro de concordância.
Context: ...oglebaixa a fonte em tempo de build — o build passa a exigir acesso a >fonts.google...
(ERRO_DE_CONCORDNCIA_DO_GÉNERO_MASCULINO_O)
[grammar] ~64-~64: Possível erro de concordância.
Context: ...mada do Tailwind. Consequências medidas no build antigo: | Utilitário | Deveria pintar ...
(GENERAL_GENDER_AGREEMENT_ERRORS)
[uncategorized] ~76-~76: Empregue a forma composta, plural + singular, nesta expressão académica/científica.
Context: ...nza de 1px sobre o verde. Correção: as regras base foram movidas para @layer base. Depoi...
(SUBSTANTIVO_PLURAL_E_CHAVE_BASE)
[style] ~95-~95: “dentro de uma” é uma expressão prolixa. É preferível dizer “numa” ou “em uma”.
Context: ...esktop tinha Operação ⌄ Campus Ledger dentro de uma div inerte: um chevron que prometia u...
(PT_WORDINESS_REPLACE_DENTRO_DE_UMA)
[uncategorized] ~106-~106: Sinal de pontuação isolado.
Context: ...rrar sessão" era um item morto Perfil, Preferências e Encerrar sessão eram...
(UNLIKELY_OPENING_PUNCTUATION)
[grammar] ~109-~109: Segundo o Acordo Ortográfico de 45, os meses e as estações do ano devem ser capitalizados.
Context: ... funcionar e não fazia nada. Correção: POST /auth/sign-out (route handler que chama `auth.signOut...
(AO45_MONTHS_CASING)
[uncategorized] ~130-~130: Se é uma abreviatura, falta um ponto. Se for uma expressão, coloque entre aspas.
Context: ...s e pedidos … ``` CardTitle ganhou a prop opcional `as` e os títulos de card pass...
(ABREVIATIONS_PUNCTUATION)
[uncategorized] ~168-~168: Pontuação duplicada
Context: ...com o texto branco). Adicionado o token --primary-strong: #0a4d32`` e o hover passo...
(DOUBLE_PUNCTUATION_XML)
[locale-violation] ~225-~225: “template” é um estrangeirismo. É preferível dizer “modelo”.
Context: ...rca. - public/ só continha os SVGs do template do Next (next.svg, vercel.svg, `fil...
(PT_BARBARISMS_REPLACE_TEMPLATE)
[uncategorized] ~238-~238: Pontuação duplicada
Context: ...ndo a regra de usar tokens. Adicionados --radius-tile, --radius-card, `--radius...
(DOUBLE_PUNCTUATION_XML)
[locale-violation] ~251-~251: “Server” é um estrangeirismo. É preferível dizer “servidor”.
Context: ...value/isLoading`; falta a leitura via Server Component. 2. **Seletor de organizaç...
(PT_BARBARISMS_REPLACE_SERVER)
[uncategorized] ~266-~266: Esta locução deve ser separada por vírgulas, e só deve ser utilizada no início duma frase para efeitos de estilo.
Context: ...ound/10em vez da hairline--outline.** Além disso todo card passava border-border` se...
(VERB_COMMA_CONJUNCTION)
[style] ~270-~270: Para conferir mais clareza ao seu texto, evite pleonasmos.
Context: ...d é clicável ainda; vale implementar junto com o primeiro card navegável. 8. **`databa...
(REDUNDANCY_JUNTO_COM)
[grammar] ~288-~288: Possível erro de concordância.
Context: ...sobre a verificação As medições vieram do build de produção em Chromium headless. Um de...
(GENERAL_GENDER_AGREEMENT_ERRORS)
CLAUDE.md
[uncategorized] ~107-~107: Encontrada possível ausência de vírgula.
Context: ...o Next 16 chama proxy() para todas as rotas exceto assets estáticos. O arquivo p...
(AI_PT_HYDRA_LEO_MISSING_COMMA)
[grammar] ~253-~253: Segundo o Acordo Ortográfico de 45, os meses e as estações do ano devem ser capitalizados.
Context: ...o estão implementados. Logout existe em POST /auth/sign-out; Perfil e Preferências no menu da ...
(AO45_MONTHS_CASING)
🪛 markdownlint-cli2 (0.23.1)
docs/ux-ui-auditoria.md
[warning] 126-126: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 132-132: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 262-262: Ordered list item prefix
Expected: 1; Actual: 5; Style: 1/2/3
(MD029, ol-prefix)
[warning] 266-266: Ordered list item prefix
Expected: 2; Actual: 6; Style: 1/2/3
(MD029, ol-prefix)
[warning] 268-268: Ordered list item prefix
Expected: 3; Actual: 7; Style: 1/2/3
(MD029, ol-prefix)
[warning] 271-271: Ordered list item prefix
Expected: 4; Actual: 8; Style: 1/2/3
(MD029, ol-prefix)
[warning] 273-273: Ordered list item prefix
Expected: 5; Actual: 9; Style: 1/2/3
(MD029, ol-prefix)
[warning] 277-277: Ordered list item prefix
Expected: 1; Actual: 10; Style: 1/2/3
(MD029, ol-prefix)
[warning] 278-278: Ordered list item prefix
Expected: 2; Actual: 11; Style: 1/2/3
(MD029, ol-prefix)
[warning] 279-279: Ordered list item prefix
Expected: 3; Actual: 12; Style: 1/2/3
(MD029, ol-prefix)
🔇 Additional comments (21)
src/app/(dashboard)/[module]/page.tsx (4)
1-13: LGTM!
43-62: LGTM!
64-70: LGTM!
72-105: 📐 Maintainability & Code QualityConfirme a validação visual antes do merge.
Valide esta rota em viewport móvel e desktop. Confirme foco visível no breadcrumb, contraste do
Badge, navegação por teclado e os estados de carregamento, erro e não encontrado. Registre a validação no build de produção em Chromium.Source: Coding guidelines
src/proxy.ts (1)
1-13: LGTM!src/app/(dashboard)/layout.tsx (1)
2-24: LGTM!ARCHITECTURE.md (1)
138-138: LGTM!CLAUDE.md (1)
69-69: LGTM!Also applies to: 107-108, 251-258
src/components/auth/login-form.tsx (1)
60-109: LGTM!src/app/(auth)/login/page.tsx (1)
1-41: LGTM!src/components/layout/app-shell.tsx (1)
3-3: LGTM!Also applies to: 12-12, 51-138, 191-273
src/app/(dashboard)/error.tsx (1)
1-30: LGTM!src/app/(dashboard)/loading.tsx (1)
1-23: LGTM!src/app/(dashboard)/not-found.tsx (1)
1-33: LGTM!src/app/not-found.tsx (1)
1-33: LGTM!src/components/dashboard/metric-card.tsx (1)
4-28: LGTM!src/app/(dashboard)/dashboard/page.tsx (1)
14-18: LGTM!Also applies to: 19-66, 68-80, 104-128
src/components/ui/card.tsx (1)
36-47: LGTM!src/app/globals.css (1)
57-57: LGTM!Also applies to: 69-81, 107-147
src/app/layout.tsx (1)
1-12: LGTM!Also applies to: 22-33
src/components/ui/button.tsx (1)
11-12: LGTM!
Dois defeitos reais, ambos confirmados por teste antes da correção: - "Encerrar sessão" só funcionava com o mouse. Com o <form> renderizado como o DropdownMenuItem, o foco de teclado caía no form e Enter não disparava click nenhum — só keydown/keyup. Além de inverter o aninhamento (o form envolve o item, o item é o button type=submit), era preciso passar nativeButton: o Base UI assume elemento não-nativo por padrão e intercepta Enter/Espaço. Verificado nos três caminhos: Enter, Espaço e mouse levam a /login. - Redirecionamento aberto no ?next=. A validação por prefixo deixava passar ?next=%2F%5Cevil.example, que decodifica para /\evil.example — começa com / e não com //, mas o parser de URL normaliza a barra invertida e resolve para https://evil.example/. Agora compara a origem parseada, como a rota de callback sempre fez. Verificado: /eventos passa; /\evil.example, //evil.example e https://evil.example caem no fallback. Ajustes menores da mesma revisão: - layout do dashboard lê o e-mail com getClaims() em vez de getUser(), evitando uma requisição ao serviço de Auth em cada render inicial para obter só um rótulo. O e-mail vem de JwtPayload.email. - POST /auth/sign-out deixa de redirecionar como sucesso quando signOut() falha: leva a /login?erro=logout e a tela avisa que a sessão anterior pode não ter sido encerrada. - Erro de login filtrado por signInError.code em vez do texto da mensagem. O código correto no @supabase/auth-js instalado é invalid_credentials. - --primary-strong referencia var(--brand-800) em vez de repetir #0a4d32. - MetricCard anuncia o carregamento com aria-busy e sr-only, com o Skeleton marcado como decorativo. - XIcon do sheet marcado com aria-hidden. - README deixa de listar logout como inexistente. - Blocos de código do documento com linguagem e listas renumeradas. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GPazBanQrY9LixdsSoNKpR
|
Revisão aplicada em Logout inalcançável por teclado ( Redirecionamento aberto no
Demais itens, todos aplicados: Uma correção ao sugerido: o código de erro do Supabase para credencial inválida é Sobre o check de Docstring Coverage (16.67%): não tratei. Subir para 80% exigiria docstring em cada componente React deste diff, e O commit
Generated by Claude Code |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/components/ui/button.tsx (1)
7-20: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winRemova as variantes
dark:do componente.As classes
dark:permitem mudanças visuais no modo escuro. Isto contradiz a exigência de interface light-only. Remova também as variantesdark:deoutline,ghostedestructive.As per coding guidelines: “Manter a interface light-only ... não reintroduzir dark mode.”
Correção proposta
- ... dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 ... + ... aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 ... - dark:border-input dark:bg-input/30 dark:hover:bg-input/50 - dark:hover:bg-muted/50 - dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/ui/button.tsx` around lines 7 - 20, Remova todas as classes utilitárias com prefixo dark: do componente de variantes de botão, incluindo as definições outline, ghost e destructive, além de qualquer ocorrência na classe base. Preserve as demais classes e comportamentos visuais light-only inalterados.Source: Coding guidelines
src/components/layout/app-shell.tsx (1)
52-81: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy liftVincule a organização ativa à autorização do servidor.
A lista
organizationsé criada no cliente. O layout fornece apenasaccountEmailaoAppShell. Além disso,activeOrganizationsempre usaorganizations[0].Ao selecionar outra opção, o seletor pode mostrar outra organização, mas o cabeçalho e o conteúdo continuam na primeira organização. Passe as organizações autorizadas e a organização ativa a partir do Server Component. Se a troca ainda não existe, substitua o
Selectpor uma indicação não interativa da organização autorizada.As per path instructions: “Não aceite identidades, organizações, papéis ou permissões fabricados no cliente.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/layout/app-shell.tsx` around lines 52 - 81, Atualize o fluxo entre o Server Component e AppShell para fornecer as organizações autorizadas e a organização ativa obtidas do servidor, removendo a lista fixa organizations e o activeOrganization baseado em organizations[0]. Não permita que o cliente fabrique identidades, organizações, papéis ou permissões; enquanto a troca não for implementada, substitua o Select por uma indicação não interativa da organização autorizada.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@README.md`:
- Around line 28-29: Atualize a lista de lacunas no README para remover “testes
do app” e “CI”, mantendo documentados apenas testes E2E, fluxos de negócio e
monitoramento de produção.
In `@src/app/auth/sign-out/route.ts`:
- Around line 15-26: Atualize o fluxo da rota de sign-out em torno de
getSupabaseConfig para definir destination.searchParams com erro=logout também
quando a configuração estiver ausente. Preserve o tratamento existente para
erros de signOut e exceções, mantendo a autenticação fail-closed no servidor.
In `@src/components/ui/input.tsx`:
- Around line 12-15: Remova os modificadores dark: das primitivas compartilhadas
para preservar a interface light-only: em src/components/ui/input.tsx nas linhas
12-15, remova-os do fundo e dos estados desabilitado e inválido; em
src/components/ui/select.tsx nas linhas 44-46, remova-os do fundo, hover e
estado inválido; em src/components/ui/dropdown-menu.tsx nas linhas 91-92, remova
o modificador do foco destrutivo. Mantenha os tokens e demais variantes
existentes.
---
Outside diff comments:
In `@src/components/layout/app-shell.tsx`:
- Around line 52-81: Atualize o fluxo entre o Server Component e AppShell para
fornecer as organizações autorizadas e a organização ativa obtidas do servidor,
removendo a lista fixa organizations e o activeOrganization baseado em
organizations[0]. Não permita que o cliente fabrique identidades, organizações,
papéis ou permissões; enquanto a troca não for implementada, substitua o Select
por uma indicação não interativa da organização autorizada.
In `@src/components/ui/button.tsx`:
- Around line 7-20: Remova todas as classes utilitárias com prefixo dark: do
componente de variantes de botão, incluindo as definições outline, ghost e
destructive, além de qualquer ocorrência na classe base. Preserve as demais
classes e comportamentos visuais light-only inalterados.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 43d66077-edca-45bb-a585-3385bf8aabf5
📒 Files selected for processing (20)
AGENTS.mdCLAUDE.mdREADME.mddocs/ux-ui-auditoria.mdsrc/app/(auth)/login/page.tsxsrc/app/(dashboard)/dashboard/page.tsxsrc/app/(dashboard)/error.tsxsrc/app/(dashboard)/layout.tsxsrc/app/(dashboard)/not-found.tsxsrc/app/auth/sign-out/route.tssrc/app/globals.csssrc/app/not-found.tsxsrc/components/auth/login-form.tsxsrc/components/dashboard/metric-card.tsxsrc/components/layout/app-shell.tsxsrc/components/ui/button.tsxsrc/components/ui/dropdown-menu.tsxsrc/components/ui/input.tsxsrc/components/ui/select.tsxsrc/components/ui/sheet.tsx
Auditoria completa da interface (login, AppShell, visão geral, módulos)
comparada com DESIGN.md e verificada no build de produção em Chromium.
Registro em docs/ux-ui-auditoria.md.
Correções críticas:
- src/proxy.ts: o proxy estava na raiz do repositório e o Next 16 o
ignorava em silêncio (middleware-manifest vazio). Nenhuma rota estava
protegida: GET /dashboard respondia 200 sem sessão. Com o arquivo ao
lado de app/, /dashboard e /eventos passam a redirecionar 307 para
/login?next=<path>.
- Plus Jakarta Sans nunca era carregada: os tokens declaravam a família
mas nada baixava a fonte, e o app renderizava na sans-serif do
sistema. Carregada via next/font/google como fonte variável.
- Um `* { border-color }` fora de @layer vencia todas as camadas do
Tailwind e matava focus-visible:border-ring,
aria-invalid:border-destructive e border-transparent. Movido para
@layer base; os três estados voltam a pintar.
Navegação e acessibilidade:
- Configurações não tinha entrada no menu mobile, tornando /configuracoes
inalcançável em viewport pequena.
- Link "pular para o conteúdo", id em <main>, aria-current nos links
ativos e anel de foco com token.
- CardTitle aceita `as` para render heading real; os títulos de card
saíram de <div> e o outline deixa de ter h3 sem h2 acima.
- Alvos de toque de 32/28px para 44px nos controles mobile.
- Logout real em POST /auth/sign-out; Perfil e Preferências
desabilitados em vez de itens mortos.
- Seletor de organização mostrava o slug "campus-ledger"; passa a usar
`items` do Base UI para exibir o rótulo.
- Header: removido o chevron de um menu inexistente; nome da organização
agora também aparece no mobile.
Estados, layout e fidelidade ao design:
- loading/error/not-found do grupo (dashboard) e not-found raiz, em
português; o Skeleton que existia sem uso entrou no loading.
- generateMetadata nas páginas de módulo: cada rota tem título próprio.
- Largura de conteúdo unificada entre visão geral e módulos; métricas em
duas colunas desde o menor viewport; header de seção deixa de colidir
no mobile; card lateral não estica mais.
- Hover do botão primário escurece (--primary-strong) em vez de clarear.
- Tokens --radius-card/--shadow-card/--shadow-panel no lugar dos valores
crus repetidos; chip de ícone circular conforme rounded.full.
- prefers-reduced-motion respeitado.
- CTA desabilitado explica o motivo via aria-describedby; métrica vazia
anuncia "sem dados" para leitor de tela.
- Login: BrandMark, ?next= honrado (só caminhos same-origin), erro de
credencial distinto de indisponibilidade, aria-describedby/aria-busy.
- icon.svg da marca e remoção dos SVGs do template do Next.
- E-mail da conta lido no Server Component do layout, sem round-trip no
cliente nem flash de placeholder.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GPazBanQrY9LixdsSoNKpR
As variantes do shadcn nasciam com h-8 (32px) em botão, input e select trigger — abaixo dos 44px de alvo de toque e longe dos 44/48/56px do design. Cada tela corrigia por conta própria, então a escala vivia espalhada em className em vez das variantes. Escala nas variantes (medida no build de produção): - Button default: 44px, px-5, 600 — button-compact do DESIGN.md - Button lg: 56px, px-6, 1rem/700 — button-primary - Button sm/xs: 40px/32px, opt-in para tabelas e barras densas - Button icon: 44px; icon-sm 40px; icon-xs 32px; icon-lg 56px - Input: 48px, px-4, 1rem, fundo branco — input - SelectTrigger: 48px, acompanhando o campo de texto como manda o spec - Itens de dropdown e de select: 44px Input e SelectTrigger saíram de bg-transparent para bg-card: o spec descreve o campo como "white fill, hairline border", e sobre o canvas Com as variantes corretas, os ajustes locais saíram — h-12, h-11, min-h-11, px-5, font-bold e rounded-lg foram removidos de login, visão geral, error, not-found e AppShell. O CTA da visão geral e o botão de entrar passaram a size="lg". Corrige também um defeito anterior a esta auditoria, encontrado ao medir as alturas dos itens de menu: o menu da conta lançava "MenuGroupContext is missing" e abria vazio, porque DropdownMenuLabel mapeia para Menu.GroupLabel e estava solto fora de um DropdownMenuGroup. Verificado depois da correção: os três itens renderizam sem erro de página e POST /auth/sign-out leva a /login. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GPazBanQrY9LixdsSoNKpR
Dois defeitos reais, ambos confirmados por teste antes da correção: - "Encerrar sessão" só funcionava com o mouse. Com o <form> renderizado como o DropdownMenuItem, o foco de teclado caía no form e Enter não disparava click nenhum — só keydown/keyup. Além de inverter o aninhamento (o form envolve o item, o item é o button type=submit), era preciso passar nativeButton: o Base UI assume elemento não-nativo por padrão e intercepta Enter/Espaço. Verificado nos três caminhos: Enter, Espaço e mouse levam a /login. - Redirecionamento aberto no ?next=. A validação por prefixo deixava passar ?next=%2F%5Cevil.example, que decodifica para /\evil.example — começa com / e não com //, mas o parser de URL normaliza a barra invertida e resolve para https://evil.example/. Agora compara a origem parseada, como a rota de callback sempre fez. Verificado: /eventos passa; /\evil.example, //evil.example e https://evil.example caem no fallback. Ajustes menores da mesma revisão: - layout do dashboard lê o e-mail com getClaims() em vez de getUser(), evitando uma requisição ao serviço de Auth em cada render inicial para obter só um rótulo. O e-mail vem de JwtPayload.email. - POST /auth/sign-out deixa de redirecionar como sucesso quando signOut() falha: leva a /login?erro=logout e a tela avisa que a sessão anterior pode não ter sido encerrada. - Erro de login filtrado por signInError.code em vez do texto da mensagem. O código correto no @supabase/auth-js instalado é invalid_credentials. - --primary-strong referencia var(--brand-800) em vez de repetir #0a4d32. - MetricCard anuncia o carregamento com aria-busy e sr-only, com o Skeleton marcado como decorativo. - XIcon do sheet marcado com aria-hidden. - README deixa de listar logout como inexistente. - Blocos de código do documento com linguagem e listas renumeradas. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GPazBanQrY9LixdsSoNKpR
Cada item foi um defeito real neste repositório e nenhum deles falha `pnpm check` — por isso ficam nas instruções carregadas a cada sessão, e não só no relatório da auditoria. CLAUDE.md ganha "Armadilhas conhecidas", agrupadas por como falham: - Configuração que falha em silêncio: proxy na raiz sendo ignorado (nenhuma rota protegida), CSS fora de @layer vencendo o Tailwind, fonte declarada mas nunca baixada. - Base UI, onde a API difere do Radix: Select precisa de `items` para mostrar rótulo, Menu.GroupLabel exige Menu.Group, e `render` com elemento nativo precisa de `nativeButton` ou o Enter é engolido. - Auth: getClaims() em vez de getUser() no servidor, validação de ?next= por origem parseada, error.code em vez de error.message, e logout que falha não pode redirecionar como sucesso. - Interface: a escala de DESIGN.md já vive nas variantes; não corrigir altura com className. - Verificação: abrir o que é interativo (dois bugs sobreviveram a uma rodada porque o dropdown nunca foi aberto), ler estilo computado depois da transição, rota temporária sob /auth/* para auditar tela autenticada, e rebuildar antes de culpar o código por erro de tsc. AGENTS.md passa a dizer, na seção de qualidade, que `pnpm check` não pega essa classe de defeito, e aponta para a lista. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GPazBanQrY9LixdsSoNKpR
4cffdfa to
da1a43b
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/ux-ui-auditoria.md`:
- Around line 166-169: Atualize o trecho da auditoria que documenta
--primary-strong para refletir a implementação final usando var(--brand-800),
removendo a referência ao valor hexadecimal `#0a4d32`. Preserve a descrição do
comportamento de hover escurecido e mantenha apenas a forma atualmente
implementada do token.
In `@src/app/`(dashboard)/dashboard/page.tsx:
- Around line 104-128: Atualize o cartão próximo ao título “Operação segura por
padrão” para não apresentar controles ainda não implementados como garantias
atuais. Altere os itens de RLS, check-in e financeiro para linguagem
prospectiva, como “Planejado: ...”, mantendo o restante do cartão inalterado.
In `@src/app/`(dashboard)/error.tsx:
- Around line 20-23: Atualize o componente DashboardError e remova a afirmação
de que a operação continua registrada, pois não há confirmação do servidor nesse
fluxo. Mantenha apenas as orientações para tentar novamente e avisar a equipe
responsável.
In `@src/app/`(dashboard)/not-found.tsx:
- Line 27: Substitua o uso de Button com renderização de Link nos fallbacks
not-found por um Link estilizado diretamente com buttonVariants, preservando o
texto e o destino /dashboard; aplique a correção em
src/app/(dashboard)/not-found.tsx (linhas 27-27) e src/app/not-found.tsx (linhas
26-26).
In `@src/app/globals.css`:
- Around line 138-147: Move the prefers-reduced-motion rule containing the
universal selectors into an `@layer` base block, preserving its existing
declarations and media-query behavior while ensuring the global CSS is no longer
outside a Tailwind layer.
In `@src/app/layout.tsx`:
- Around line 20-23: Substitua o hexadecimal direto em viewport.themeColor pelo
token de design ou constante canônica compartilhada que representa a cor da
marca, mantendo o valor efetivo e a configuração colorScheme inalterados.
In `@src/components/auth/login-form.tsx`:
- Around line 104-108: Update the submit Button in the login form to use the
design-system size="lg" prop, remove h-12 and font-bold from className, and
retain only w-full for layout.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: d9feb155-3fdf-45d7-9a8a-9c6a81bf5aba
⛔ Files ignored due to path filters (6)
public/file.svgis excluded by!**/*.svgpublic/globe.svgis excluded by!**/*.svgpublic/next.svgis excluded by!**/*.svgpublic/vercel.svgis excluded by!**/*.svgpublic/window.svgis excluded by!**/*.svgsrc/app/icon.svgis excluded by!**/*.svg
📒 Files selected for processing (28)
.github/workflows/ci.ymlAGENTS.mdARCHITECTURE.mdCLAUDE.mdREADME.mddocs/ux-ui-auditoria.mdsrc/app/(auth)/login/page.tsxsrc/app/(dashboard)/[module]/page.tsxsrc/app/(dashboard)/dashboard/page.tsxsrc/app/(dashboard)/error.tsxsrc/app/(dashboard)/loading.tsxsrc/app/(dashboard)/not-found.tsxsrc/app/auth/sign-out/route.tssrc/app/globals.csssrc/app/layout.tsxsrc/app/not-found.tsxsrc/components/auth/login-form.tsxsrc/components/dashboard/metric-card.tsxsrc/components/layout/account-menu.tsxsrc/components/layout/app-shell.tsxsrc/components/layout/navigation-links.tsxsrc/components/layout/workspace-selector.tsxsrc/components/ui/button.tsxsrc/components/ui/card.tsxsrc/components/ui/dropdown-menu.tsxsrc/components/ui/input.tsxsrc/components/ui/select.tsxsrc/components/ui/sheet.tsx
Auditoria completa da interface (login, AppShell, visão geral, módulos)
comparada com DESIGN.md e verificada no build de produção em Chromium.
Registro em docs/ux-ui-auditoria.md.
Correções críticas:
ignorava em silêncio (middleware-manifest vazio). Nenhuma rota estava
protegida: GET /dashboard respondia 200 sem sessão. Com o arquivo ao
lado de app/, /dashboard e /eventos passam a redirecionar 307 para
/login?next=.
mas nada baixava a fonte, e o app renderizava na sans-serif do
sistema. Carregada via next/font/google como fonte variável.
* { border-color }fora de @layer vencia todas as camadas doTailwind e matava focus-visible:border-ring,
aria-invalid:border-destructive e border-transparent. Movido para
@layer base; os três estados voltam a pintar.
Navegação e acessibilidade:
inalcançável em viewport pequena.
ativos e anel de foco com token.
aspara render heading real; os títulos de cardsaíram de
desabilitados em vez de itens mortos.
itemsdo Base UI para exibir o rótulo.agora também aparece no mobile.
Estados, layout e fidelidade ao design:
português; o Skeleton que existia sem uso entrou no loading.
duas colunas desde o menor viewport; header de seção deixa de colidir
no mobile; card lateral não estica mais.
crus repetidos; chip de ícone circular conforme rounded.full.
anuncia "sem dados" para leitor de tela.
credencial distinto de indisponibilidade, aria-describedby/aria-busy.
cliente nem flash de placeholder.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01GPazBanQrY9LixdsSoNKpR
Summary by CodeRabbit
Novas funcionalidades
Melhorias de acessibilidade e interface
Documentação