Pular para o conteúdo

Backlog de melhorias

Melhorias levantadas no uso do painel administrativo e na auditoria de segurança e qualidade do código, em outubro de 2026. Cada item tem um identificador estável (MF-xx) para ser citado em tarefas, PRs e conversas com o cliente.

ID Melhoria Tipo Prioridade Esforço
MF-01 Corrigir alteração de senha no painel Bug Alta Pequeno
MF-02 Busca e filtros nas tabelas do admin UX Alta Médio
MF-03 Modal de detalhes para dados extensos UX Alta Médio
MF-04 Remover a coluna ID e editar pela coluna Ação UX Média Pequeno
MF-05 Fixar a coluna Ação UX Média Pequeno
MF-06 Itens por página na paginação UX Média Pequeno
MF-07 Placeholder para dados ainda não gerados UX Média Pequeno
MF-08 Contraste e estética das tabelas Visual Média Médio
MF-09 Máscaras de entrada e exibição de dados UX Média Médio
MF-10 Ícones por categoria na seção Diversos Visual Baixa Pequeno
MF-11 Atalho para a documentação nas áreas sobre a Moldapé Produto Baixa Pequeno
MF-12 Reescrever o DataTable sobre o TanStack Table Arquitetura Alta Médio
MF-13 Restringir CORS e rever o SameSite do cookie Segurança Crítica Pequeno
MF-14 Verificar a posse do recurso (IDOR) Segurança Crítica Médio
MF-15 Calcular o valor do pagamento no servidor Segurança Crítica Pequeno
MF-16 Validar o webhook e restringir o token de serviço Segurança Crítica Médio
MF-17 Atualizar dependências vulneráveis (restante) Segurança Alta Médio
MF-18 Migrar para Fastify 5 Segurança Média Médio
MF-19 Respostas de erro sem detalhes internos Segurança Alta Pequeno
MF-20 Endurecer o Better Auth (restante) Segurança Alta Pequeno
MF-21 Headers de segurança (API e CSP) Segurança Média Pequeno
MF-22 Logs sem dados sensíveis e estruturados Segurança Alta Médio
MF-23 Consertar o CI e torná-lo obrigatório Qualidade Alta Médio
MF-24 Cobertura de testes nos fluxos críticos Qualidade Média Grande
MF-26 Reduzir any e ligar o modo estrito Qualidade Média Grande
MF-27 Migrations automáticas no deploy Qualidade Alta Pequeno
MF-01

Corrigir a alteração de senha de usuários e administradores

  • Prioridade alta
  • Tipo Bug
  • Esforço Pequeno
  • Área Admin · Acessos
  • Status Proposta

No painel Acessos, editar um usuário ou administrador e preencher uma nova senha não altera a senha. O formulário é salvo sem erro, o que dá a impressão de sucesso.

O modal UserFormModal envia a senha junto dos demais campos para authClient.admin.updateUser({ userId, data }). No Better Auth, esse método atualiza a tabela user; a senha fica na tabela account, com hash, e é alterada por um método próprio do plugin de admin (setUserPassword).

  • Separar a troca de senha: quando o campo vier preenchido, chamar authClient.admin.setUserPassword({ userId, newPassword }).
  • Mostrar erro claro se a operação falhar e um toast de sucesso só depois da confirmação.
  • Revogar as sessões ativas do usuário após a troca (revokeUserSessions).
  • Remover a senha aleatória de reserva (Math.random()) na criação de usuários: senha passa a ser obrigatória ou o usuário recebe um link de definição de senha.
  • Depois de alterar, o login com a senha antiga falha e com a nova funciona.
  • Vale para usuários e administradores.
  • Sessões abertas do usuário são encerradas.
MF-02

Barra de busca e filtros nas seções do admin

  • Prioridade alta
  • Tipo UX
  • Esforço Médio
  • Área Admin · todas as tabelas
  • Status Proposta

As tabelas crescem com o uso (usuários, pedidos, rascunhos) e não há como encontrar um registro sem rolar a página.

  • Campo de busca acima de cada tabela, com debounce de 300 ms, buscando nos campos de texto relevantes (nome, e-mail, código do pedido, nome do produto).
  • Filtros por coluna onde fizer sentido: status e período em Pedidos; ativo/inativo em Produtos, Peças e Coberturas; perfil em Acessos.
  • Estado da busca refletido na URL (?q=&status=) para poder compartilhar o link filtrado.
  • Para volumes maiores, busca no servidor (parâmetros na API) em vez de filtrar só a página carregada.
  • Digitar parte de um e-mail ou código de pedido filtra a tabela em até 1 s.
  • “Limpar filtros” volta ao estado inicial.
  • A busca funciona junto com a paginação (MF-06).
MF-03

Modal com o detalhamento de dados extensos

  • Prioridade alta
  • Tipo UX
  • Esforço Médio
  • Área Admin · Produtos, Peças, Coberturas, Pedidos
  • Status Proposta

Colunas como Preços, Reforços de maciez, Configurações de logo e Vetorização exibem listas inteiras dentro da célula. Uma única cobertura ocupa uma tela inteira de altura, e a vetorização de produtos mostra dezenas de URLs. A tabela perde a função de visão geral.

  • Na tabela, mostrar só um resumo: contagem e faixa (ex.: “6 preços · R$ 0,00 – R$ 82,30”, “10 arquivos”).
  • Um botão Ver detalhes abre um modal (ou painel lateral) com os dados completos organizados em seções, com miniaturas no lugar de URLs.
  • Linhas com altura fixa, sem quebra de texto longa.
  • Nenhuma linha da tabela passa de cerca de 64 px de altura.
  • Todos os dados continuam acessíveis em no máximo um clique.
  • O modal fecha com Esc e devolve o foco à linha de origem.
MF-04

Remover a coluna ID e levar a edição para a coluna Ação

  • Prioridade média
  • Tipo UX
  • Esforço Pequeno
  • Área Admin · todas as tabelas
  • Status Proposta

A primeira coluna mostra o ID interno (cuid), que não tem significado para quem opera o painel e ocupa espaço. Hoje é também o link para editar o registro, o que não é descobrível.

  • Remover a coluna ID das tabelas (o ID pode aparecer no modal de detalhes, com botão de copiar, para suporte técnico).
  • Adicionar o botão Editar (ícone de lápis + rótulo acessível) na coluna Ação, ao lado de Desativar e Excluir.
  • Onde existir um código legível (ex.: ORD-… em Pedidos), ele substitui o ID.
  • Nenhuma tabela do admin exibe cuid como coluna.
  • Toda linha editável tem o botão Editar na coluna Ação.
MF-05

Fixar a coluna Ação

  • Prioridade média
  • Tipo UX
  • Esforço Pequeno
  • Área Admin · todas as tabelas
  • Status Proposta

Em tabelas largas (Coberturas, Produtos), a coluna Ação fica fora da área visível e o próprio cabeçalho aparece cortado. Para excluir ou editar é preciso rolar horizontalmente.

Coluna Ação com position: sticky; right: 0, fundo sólido e sombra sutil à esquerda quando houver conteúdo rolado por baixo. O cabeçalho da tabela também fica fixo ao rolar verticalmente.

  • Em 1280 px de largura, as ações de qualquer linha ficam visíveis sem rolagem horizontal.
MF-06

Seleção de itens por página na paginação

  • Prioridade média
  • Tipo UX
  • Esforço Pequeno
  • Área Admin · todas as tabelas
  • Status Proposta
  • Seletor com 10, 25, 50 e 100 itens por página, padrão 25.
  • Texto “Exibindo 26–50 de 312”.
  • Preferência lembrada por tabela no navegador e refletida na URL (?pagina=2&porPagina=50).
  • Mudar a quantidade volta para a página 1 e mantém busca e filtros.
MF-07

Placeholder nas colunas com dados ainda não gerados

  • Prioridade média
  • Tipo UX
  • Esforço Pequeno
  • Área Admin · Rascunhos, Pedidos
  • Status Proposta

Em Rascunhos, as colunas Pedido e Imagens criação aparecem em branco quando o rascunho ainda não virou pedido ou não teve imagens geradas. Célula vazia é ambígua: pode ser “ainda não existe”, “falhou” ou “está carregando”.

Um texto padrão discreto por situação, nunca célula vazia:

Situação Exibição
Ainda não gerado “Aguardando” em cinza, com ícone de relógio
Não se aplica “—” com aria-label="Não se aplica"
Falha ao gerar “Erro” em vermelho, com dica explicando
Carregando skeleton animado

Já existe um bom precedente na coluna Logo da cobertura, que mostra “Sem logo”.

  • Nenhuma célula do admin fica visualmente vazia.
MF-08

Melhorar o contraste e a estética das tabelas

  • Prioridade média
  • Tipo Visual
  • Esforço Médio
  • Área Admin · todas as tabelas
  • Status Proposta

Tabelas brancas sobre fundo branco, com divisórias muito claras: o olho não separa a tabela do resto da página nem uma linha da outra.

  • Fundo da página em cinza muito claro (#F7F6F8) e tabela em cartão branco com borda e sombra leve.
  • Cabeçalho com fundo diferenciado e texto em caixa alta com espaçamento.
  • Linhas zebradas sutis e destaque de linha ao passar o mouse.
  • Números e valores alinhados à direita; datas e códigos em fonte tabular.
  • Cores a partir dos tokens semânticos, respeitando contraste mínimo de 4,5:1.
  • Contraste entre texto e fundo ≥ 4,5:1 em todas as células.
  • Mesma aparência em todas as tabelas (vem do DataTable).
MF-12

Reescrever o DataTable sobre o TanStack Table

  • Prioridade alta
  • Tipo Arquitetura
  • Esforço Médio
  • Área @moldape/ui · DataTable
  • Status Proposta

O DataTable de packages/ui/src/data-table.tsx é uma implementação própria (254 linhas): recebe columns (key, header, render) e data, e decide as ações por uma lista de callbacks fixos (onEdit, onDelete, onSuspendAccess, onRestoreAccess, onActivateItem, onDeactivateItem, onChangeStatus, customActions). Ele não sabe ordenar, filtrar, paginar, fixar colunas nem expandir linhas. Cada uma das 7 telas do admin que o usam resolve isso (ou não resolve) por conta própria.

Manter o DataTable como componente de apresentação do @moldape/ui e trocar o motor por @tanstack/react-table (headless, sem estilo próprio, encaixa no shadcn + Tailwind atual). É o mesmo caminho do Data Table do shadcn/ui.

Recurso do TanStack Table Melhoria que resolve
getFilteredRowModel + globalFilter / columnFilters MF-02 busca e filtros
getExpandedRowModel ou linha clicável → modal MF-03 detalhes
columnVisibility (ID oculto por padrão) + coluna actions MF-04
columnPinning: { right: ['actions'] } MF-05 coluna Ação fixa
getPaginationRowModel + setPageSize MF-06 itens por página
cell com estados vazios padronizados MF-07 placeholder
getSortedRowModel ordenação por coluna (novo)
manualPagination / manualFiltering paginação no servidor quando a tabela crescer

Plano de migração:

  1. Adicionar @tanstack/react-table ao packages/ui e criar DataTable<TData> tipado com ColumnDef<TData>[] (acaba com o any de DataTableRow).
  2. Trocar os 8 callbacks de ação por uma definição de coluna actions (rowActions: (row) => Action[]), que permite ações condicionais (suspender ou restaurar) sem novas props.
  3. Criar subcomponentes reutilizáveis: DataTableToolbar (busca + filtros), DataTablePagination (com seletor de itens por página) e DataTableColumnHeader (ordenação).
  4. Migrar as telas uma a uma (access, products, pieces, coverages, orders, drafts, miscellaneous), mantendo a API antiga como adapter até a última migração e depois removê-la.
  5. Persistir filtro, ordenação e página na URL (?q=&sort=&page=&size=), para que o admin possa compartilhar e voltar a uma visão.
  • As 7 telas do admin usam o novo DataTable e a API antiga foi removida.
  • Busca, ordenação, itens por página (10/20/50/100) e coluna Ação fixa funcionam em todas elas.
  • Colunas tipadas: nenhum any em data-table.tsx.
  • Teste de componente cobrindo filtro, ordenação, paginação e ação por linha.
  • Acessível: cabeçalho ordenável com aria-sort, ações com aria-label.
MF-09

Máscaras de entrada e de exibição de dados

  • Prioridade média
  • Tipo UX
  • Esforço Médio
  • Área Cadastro, perfil, admin
  • Status Proposta

Telefones aparecem como 71987148979, e CPF/CNPJ e CEP são digitados sem formatação. Isso dificulta a leitura e aumenta o erro de digitação.

Um módulo único de formatação (por exemplo, @moldape/ui/format), usado tanto nos campos quanto nas tabelas:

Dado Máscara
Telefone (71) 98714-8979 / (71) 3565-4389
CPF / CNPJ 000.000.000-00 / 00.000.000/0000-00, com validação de dígitos
CEP 00000-000, com preenchimento de endereço
Moeda R$ 1.234,56 via Intl.NumberFormat('pt-BR') (resolve também UX-04)
Data 20/10/2026 e 20/10/2026 14:32

O valor salvo no banco continua sem máscara; a máscara é só de entrada e exibição.

  • Mesmos formatos no cadastro, no perfil e nas tabelas do admin.
  • Colar um valor já formatado ou sem formatação funciona nos dois casos.
  • Campos com inputMode adequado (tel, numeric) para o teclado do celular.
MF-10

Ícones por categoria na seção Diversos

  • Prioridade baixa
  • Tipo Visual
  • Esforço Pequeno
  • Área Admin · Diversos
  • Status Proposta

Taxa, Itens de suporte, Documentos, Slide show e Cupons usam o mesmo ícone de engrenagem. O ícone deixa de ajudar a localizar a seção.

Proposta (ícones lucide-react, já usado no projeto)

Seção intitulada “Proposta (ícones lucide-react, já usado no projeto)”
Seção Ícone
Taxa Receipt ou Percent
Itens de suporte LifeBuoy
Documentos FileText
Slide show GalleryHorizontal
Cupons de desconto TicketPercent
Diversos hoje: todas as seções com o mesmo ícone
Diversos hoje: todas as seções com o mesmo ícone
MF-11

Atalho para a documentação nas áreas sobre a Moldapé

  • Prioridade baixa
  • Tipo Produto
  • Esforço Pequeno
  • Área Conta · A Moldapé, Admin
  • Status Proposta
  • Em Conta → A Moldapé, um link “Conheça a plataforma” para a documentação e outro para baixar o PDF.
  • No menu do painel administrativo, um item “Documentação”.
  • Abrir em nova aba e usar a variável NEXT_PUBLIC_DOCS_URL (não fixar a URL no código).

Segurança e qualidade de software (MF-13 a MF-27)

Os itens MF-13 a MF-27 tratam de correções de segurança e de qualidade do código. Por conterem detalhes técnicos que não devem circular fora da equipe enquanto não forem corrigidos, o detalhamento está apenas na versão online da documentação, de acesso restrito. A tabela acima resume prioridade e esforço.

Itens levantados na auditoria de código de outubro de 2026 (leitura do código do monorepo e pnpm audit do lockfile). Onde o problema já está descrito em Riscos e dívida técnica, o item aponta para o risco R-xx em vez de repetir o diagnóstico.

MF-13

Restringir o CORS da API e rever o SameSite do cookie de sessão

  • Prioridade crítica
  • Tipo Segurança
  • Esforço Pequeno
  • Área order-lifecycle · server.ts, web · auth.ts
  • Status Proposta
  • apps/order-lifecycle/src/server.ts registra o CORS com origin: true e credentials: true (comentário: “Temporary: allow all origins to debug the issue”). Isso devolve Access-Control-Allow-Origin igual à origem de qualquer site, com credenciais.
  • O Better Auth em produção grava o cookie de sessão com sameSite: 'none' (apps/web/src/lib/auth/auth.ts), e auth-cookies.ts usa None como padrão.
  • Juntos, permitem que uma página maliciosa aberta pela usuária leia e altere rascunhos, carrinho e pedidos dela (CSRF com leitura de resposta).
  • Existe CORS_ORIGIN em config.ts, mas a variável não é usada.
  • origin a partir de CORS_ORIGIN (lista: https://moldape.com, https://www.moldape.com e, em homologação, o domínio de staging).
  • Cookie de sessão com SameSite=Lax. Como moldape.com e api.moldape.com são o mesmo site (mesmo domínio registrável), Lax funciona; None só é necessário entre domínios diferentes.
  • Remover o comentário “temporary” e cobrir com teste.
  • Requisição com Origin: https://exemplo-malicioso.com não recebe Access-Control-Allow-Origin.
  • Cookie de sessão sai com Secure; HttpOnly; SameSite=Lax em produção.
  • Login, checkout e estúdio continuam funcionando em produção e homologação.
MF-14

Verificar a posse do recurso em rascunhos, carrinho, pedidos e uploads (IDOR)

  • Prioridade crítica
  • Tipo Segurança
  • Esforço Médio
  • Área order-lifecycle · controllers
  • Status Proposta

Detalha o risco R-11. Vários handlers recebem um ID na URL ou no corpo e operam sobre ele sem comparar com request.user.id:

Controller Operações sem checagem de posse
draft-controller ler, excluir, adicionar/remover produto, peça, cobertura e observação, trocar lado da peça
cart-controller criar carrinho com userId vindo do corpo, buscar por usuário, adicionar/alterar/remover item, limpar, aplicar/remover cupom e taxa, converter em pedido
order-controller ler pedido
upload-controller excluir plantigrafia (a checagem de path traversal existe, a de dono não)

Quem souber (ou adivinhar) o ID de um rascunho, carrinho ou pedido de outra pessoa consegue lê-lo ou alterá-lo.

  • O userId vem sempre da sessão (request.user.id), nunca do corpo ou da query.
  • Um guard por agregado na camada de aplicação: assertOwnership(resource, user) nos casos de uso, com exceção explícita para admin.
  • Responder 404 (e não 403) quando o recurso não é do usuário, para não revelar que o ID existe.
  • Ativar a regra route-guard do revisor de PRs para impedir rotas novas sem guarda.
  • Teste automatizado com dois usuários (A e B) para cada rota da tabela: B não lê nem altera nada de A.
  • Nenhum handler lê userId de body ou query.
MF-15

Calcular o valor do pagamento no servidor

  • Prioridade crítica
  • Tipo Segurança
  • Esforço Pequeno
  • Área order-lifecycle · payment-controller
  • Status Proposta

payment-controller.createPaymentLink repassa o req.body direto para o PaymentService e daí para a InfinitePay. Valor, itens e descrição são os que o navegador mandar: dá para gerar um link de R$ 1,00 para um pedido de R$ 300,00.

  • A rota recebe só o orderId (ou cartId).
  • O servidor carrega o pedido do usuário logado (ver MF-14), soma itens, cupom e taxa a partir do banco e monta o payload.
  • Guardar o valor esperado no pedido e conferir no webhook (MF-16).
  • Validar a entrada com schema (Zod ou JSON Schema do Fastify).
  • Alterar o valor no corpo da requisição não muda o valor cobrado.
  • Webhook com valor pago diferente do esperado não marca o pedido como pago.
MF-16

Validar o webhook da InfinitePay e restringir o token de serviço

  • Prioridade crítica
  • Tipo Segurança
  • Esforço Médio
  • Área order-lifecycle · pagamentos
  • Status Proposta

Ver R-01: o webhook marca pedidos como pagos sem verificar a origem, e o PAYMENT_BYPASS_TOKEN é aceito em qualquer rota.

  • Ao receber o webhook, consultar o pagamento na API da InfinitePay pelo ID da transação e só então atualizar o pedido (conferindo valor e orderId).
  • Processamento idempotente (mesmo evento duas vezes não duplica efeitos).
  • Token de serviço restrito às rotas internas que precisam dele, com rotação.
  • Um POST forjado no webhook não muda o status de nenhum pedido.
  • O token de serviço é recusado fora da lista de rotas internas.
MF-17

Atualizar dependências com vulnerabilidades críticas e altas

  • Prioridade alta
  • Tipo Segurança
  • Esforço Médio
  • Área Monorepo · dependências
  • Status Proposta
  • next 14.2.33 → 16.4.2 e React 19; axios removido (fetch nativo); vitest 1.6 → 5.0.5; Jest e ts-jest (que traziam o handlebars crítico), TanStack Router (seroval), Uploadcare e Material Tailwind fora do lockfile; zod unificado em uma versão.
Pacote Onde Situação Versão mínima corrigida
better-auth 1.3.30 web, @moldape/auth avisos críticos incluídos 1.4.9 (e 1.6.11 para o mais recente)
jspdf 3.0.3 web, order-lifecycle avisos críticos incluídos 4.2.1
nodemailer 6.10 packages/email 15 avisos altos 7.0.11 (ideal: a mais recente)
fastify 4.29 order-lifecycle vários corrigidos só na linha 5 ver MF-18
  1. jspdf@^4.2.1 e nodemailer atuais.
  2. better-auth para a linha atual no catálogo do pnpm (vale para web e editor 3D de uma vez), lendo o changelog (a API do plugin admin mudou entre 1.3 e 1.4).
  3. Adicionar pnpm audit --audit-level=high --prod no CI (MF-23) e Renovate/Dependabot com agrupamento semanal.
  • pnpm audit --prod sem avisos críticos; altos com justificativa registrada.
  • CI falha quando surge um aviso crítico novo.
MF-18

Migrar o order-lifecycle para Fastify 5

  • Prioridade média
  • Tipo Segurança
  • Esforço Médio
  • Área order-lifecycle, packages/swagger
  • Status Proposta

O Fastify 4 saiu do suporte (LTS) em 30/06/2025 e não recebe mais correções: os avisos recentes sobre bypass de validação e de autenticação por URL malformada só foram corrigidos na linha 5 (>=5.12.2).

Seguir o guia oficial de migração v4 → v5: atualizar fastify, @fastify/* (cors, multipart, static, swagger, swagger-ui) e packages/swagger juntos; revisar os pontos que mudaram (schemas completos em querystring/params, reply.redirect, tipos de request).

  • fastify@5 com todos os plugins compatíveis e testes de rota passando.
  • Health check e Swagger funcionando em homologação antes de produção.
MF-19

Não expor detalhes internos nas respostas de erro

  • Prioridade alta
  • Tipo Segurança
  • Esforço Pequeno
  • Área order-lifecycle · setErrorHandler
  • Status Proposta

O error handler global devolve ao cliente error.message e um objeto user com id e e-mail do usuário, em qualquer status, inclusive 500. Mensagens de erro do Prisma e de bibliotecas acabam revelando nomes de tabela, colunas e caminhos.

  • Para 5xx: mensagem genérica e um requestId; os detalhes ficam só no log.
  • Para 4xx: mensagem de domínio controlada (erros da aplicação com code).
  • Nunca devolver dados do usuário no corpo do erro.
  • Um erro 500 provocado responde { success:false, code, message, requestId } sem stack, sem mensagem do Prisma e sem user.
MF-20

Endurecer a configuração do Better Auth

  • Prioridade alta
  • Tipo Segurança
  • Esforço Pequeno
  • Área web · lib/auth/auth.ts
  • Status Proposta

A configuração foi para @moldape/auth (createMoldapeAuth): log warn em produção (BETTER_AUTH_LOG_LEVEL para mudar), debugLogs só em debug, openAPI() só fora de produção e trustedOrigins sem duplicatas, vindo de BETTER_AUTH_TRUSTED_ORIGINS.

  • requireEmailVerification: false: qualquer e-mail é aceito sem confirmação.
  • Sem rate limit nas rotas de login e redefinição.
  • Ativar a verificação de e-mail (o SMTP já existe em packages/email).
  • Rate limit do próprio Better Auth nas rotas de login e redefinição.
  • Conta nova só acessa o estúdio depois de confirmar o e-mail.
  • /api/auth/reference responde 404 em produção.
  • Nenhum log de nível debug do Better Auth em produção.
MF-21

Headers de segurança na API e no site

  • Prioridade média
  • Tipo Segurança
  • Esforço Pequeno
  • Área order-lifecycle, web · next.config
  • Status Proposta

O site já envia X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy e HSTS (next.config.ts). Faltam a Content-Security-Policy no site e qualquer header de segurança na API (sem @fastify/helmet).

  • @fastify/helmet na API (CSP desligada, já que ela só serve JSON, exceto o Swagger).
  • headers() no next.config com CSP em modo report-only primeiro, depois aplicada.
  • HSTS na Cloudflare.
MF-22

Tirar dados sensíveis dos logs e adotar log estruturado

  • Prioridade alta
  • Tipo Segurança
  • Esforço Médio
  • Área web, order-lifecycle
  • Status Proposta

Complementa R-05 e R-13. Há 294 chamadas a console.log/ console.debug em apps/web/src e apps/order-lifecycle/src (eram 366), incluindo cookies de sessão no middleware de autenticação da API e o payload de pagamento (nome, endereço, valor) no checkout. No web, o build de produção já descarta console.log (compiler.removeConsole); na API, não.

  • No order-lifecycle, usar só o logger do Fastify (pino) com redact para cookie, authorization, password, email, phone, address.
  • No web, um logger pequeno que não imprime nada no navegador em produção.
  • Regra de lint no-console como erro (com exceção para scripts) e a regra secret-in-log do revisor de PRs ativa.
  • Zero console.* em apps/*/src fora de scripts.
  • Teste do redact: um log com cookie sai com [Redacted].
MF-23

Consertar o CI e fazer dele o portão da main

  • Prioridade alta
  • Tipo Qualidade
  • Esforço Médio
  • Área bitbucket-pipelines.yml
  • Status Proposta

Ver R-06 e Implantação: o passo de health check chama um script que não existe, o build procura um Dockerfile na raiz e a imagem usa Node 18 (produção usa Node 20). O pre-commit está com os testes comentados. Na prática nada impede código quebrado de chegar à main.

Um pipeline com turbo run lint typecheck test build --filter=...[origin/main], Node 20, cache do pnpm, pnpm audit (MF-17), knip para dependências e exports sem uso e o revisor de PRs. Proteger a main exigindo o pipeline verde.

  • Pipeline verde na main e obrigatório para merge.
  • Um PR com erro de tipo, teste falhando ou aviso crítico de dependência é bloqueado.
MF-24

Medir a cobertura de testes e cobrir o que é crítico

  • Prioridade média
  • Tipo Qualidade
  • Esforço Grande
  • Área order-lifecycle, web
  • Status Proposta

Há 31 arquivos de teste no monorepo, a cobertura nunca foi medida e não roda no CI. Os fluxos que mais doem quando quebram (posse de recurso, cálculo do carrinho, webhook de pagamento, geração do PDF) não têm teste de ponta a ponta.

  • vitest --coverage no CI com relatório no PR.
  • Meta inicial de 60% em application/ e domain/ do order-lifecycle, subindo 10 pontos por trimestre; sem meta para UI no começo.
  • Testes de integração para as rotas de MF-14, MF-15 e MF-16.
  • Um smoke test com Playwright para login → upload → rascunho → checkout (sem concluir pagamento). A base já existe desde a 2.1.0 (apps/web/e2e, @moldape/playwright-config): specs públicas, proteção de rotas e telas autenticadas de cliente e admin. Falta o fluxo de compra e rodar no CI com usuários de teste.
  • Recriar no Vitest a cobertura de login, cadastro e recuperação de senha (as suítes herdadas do Jest, obsoletas, foram apagadas na 2.1.0).
  • Cobertura publicada a cada PR; a cobertura não pode cair.
MF-26

Reduzir o uso de any e ligar o modo estrito

  • Prioridade média
  • Tipo Qualidade
  • Esforço Grande
  • Área Monorepo · TypeScript
  • Status Proposta

São 589 ocorrências de any, inclusive nos pontos de entrada da API (req: any, res: any nos controllers) e no DataTable. Os tipos não protegem justamente onde entra dado externo.

  • Tipar request/reply dos controllers com os tipos do Fastify e schemas (MF-15).
  • @typescript-eslint/no-explicit-any como aviso agora e erro em arquivos novos (o revisor de PRs aplica só ao diff).
  • Meta: cortar pela metade em dois ciclos, começando por presentation/ e packages/ui.
  • Nenhum any novo entra em PR; contagem total acompanhada no CI.
MF-27

Rodar as migrations automaticamente no deploy

  • Prioridade alta
  • Tipo Qualidade
  • Esforço Pequeno
  • Área order-lifecycle · Coolify, Prisma
  • Status Proposta

O build do web não roda mais prisma migrate dev e, desde a 2.2.0, existe pnpm prisma:migrate:deploy (prisma migrate deploy).

Ver R-07: ninguém executa o migrate deploy automaticamente; as migrations de produção dependem de rodar o comando na mão.

pnpm prisma:migrate:deploy como pre-deploy command do Coolify no order-lifecycle (dono do schema), com backup antes.

  • Deploy do order-lifecycle com migration pendente aplica a migration antes de subir a nova versão.
  • Nenhum migrate dev em nixpacks.toml, Dockerfiles ou scripts de deploy.
  1. Dê o próximo ID livre (MF-29, MF-30…). IDs não são reaproveitados.
  2. Descreva o problema observado, não só a solução.
  3. Classifique o tipo, a prioridade (Alta: quebra um fluxo ou causa erro; Média: atrapalha o uso diário; Baixa: refinamento; Crítica: falha de segurança explorável ou perda de dinheiro/dados) e o esforço (P: até 1 dia; M: até 1 semana; G: mais que isso).
  4. Escreva critérios de aceite verificáveis.
  5. Quando for implementada, troque o status para Concluída e cite o PR.
Desenvolvido e documentado por
Nós Tecnologia · Desenvolvimento Criativo