A plataforma não possui um endpoint /health/ padronizado para uso com load balancers e monitoramento externo. Um health check bem estruturado verifica o estado de cada dependência crítica e retorna resposta estruturada.
O que precisa ser feito:
- Criar `GET /health/` retornando JSON com status de cada componente: banco de dados, Redis, Celery, Storage
- HTTP 200 quando tudo OK, HTTP 503 quando qualquer componente crítico falha
- Criar `GET /ready/` mais leve (apenas banco de dados) para liveness probe
- Endpoint sem autenticação mas com rate limiting básico
- Tempo de resposta < 200ms
Stack: Python / Django 5.0
Requisitos técnicos:
- Checks: DB (SELECT 1), Redis (ping), Celery (inspect), Storage (head)
- Registrar URLs sem autenticação
- Testes unitários com mock das dependências
Critérios de aceite:
- GET /health/ retorna JSON com status de cada componente em < 200ms
- HTTP 503 quando qualquer componente crítico falha
- GET /ready/ responde apenas com status do banco
- Testes unitários cobrindo cenário de falha de cada componente
A plataforma tem Web Push mas não possui notificações in-app (sininho no header). Usuários sem permissão de push perdem atualizações de propostas aceitas, mensagens e contratos.
O que precisa ser feito:
- Criar model de Notificação genérico: usuário, tipo, mensagem, url, lida, criado_em
- Signals nos eventos chave: proposta aceita, mensagem recebida, projeto iniciado
- Endpoint HTMX polling a cada 30s para atualizar badge do sininho
- Dropdown com últimas 10 notificações e link para a ação
- Marcar todas como lidas via HTMX
Stack: Python / Django 5.0 + HTMX (backend + frontend)
Requisitos técnicos:
- Model de notificação na app de usuários
- Polling com hx-trigger no header
- Badge com contagem de não lidas
- Sem duplicação de notificação para o mesmo evento
Critérios de aceite:
- Notificação criada ao: proposta aceita, mensagem recebida, projeto iniciado
- Badge atualiza a cada 30s sem reload de página
- Dropdown lista últimas 10 com link para ação
- Marcar como lida funciona via HTMX
Os endpoints de busca de projetos e freelancers são públicos e não possuem rate limiting. Isso permite scraping massivo da base de dados e ataques de enumeração de usuários cadastrados.
O que precisa ser feito:
- Implementar rate limiting via decorator ou middleware
- Limites: 60 req/min para autenticados, 20 req/min para anônimos
- Retornar HTTP 429 com header `Retry-After` ao exceder limite
- Contador baseado em IP para anônimos, user_id para autenticados
Stack: Python / Django 5.0
Requisitos técnicos:
- Não bloquear usuários legítimos em uso normal
- Configurável via settings (não hardcoded)
- Logging dos bloqueios para monitoramento
Critérios de aceite:
- Exceder limite retorna HTTP 429 com Retry-After header
- Limites diferentes para autenticados vs anônimos
- Não impacta usuários legítimos navegando normalmente
- Teste automatizado verificando o comportamento de 429
Views que retornam listas de propostas e freelancers não possuem paginação adequada via HTMX, forçando full page reload para navegar. Isso é um problema de performance e UX.
O que precisa ser feito:
- Criar endpoint de partial HTML para lista de propostas de um projeto (10/página)
- Implementar scroll infinito na lista de freelancers via hx-trigger revealed
- URL deve atualizar com `?page=N` via hx-push-url
- Adicionar loading indicator entre páginas
Stack: Python / Django 5.0 + HTMX (frontend + backend)
Requisitos técnicos:
- Django Paginator nativo
- Retornar apenas HTML da lista + paginação (não página completa)
- hx-swap correto para append (scroll infinito) ou replace (paginação clássica)
Critérios de aceite:
- Lista de propostas pagina sem reload
- Lista de freelancers carrega próxima página ao scroll
- URL atualiza com ?page=N
- Loading indicator visível entre páginas
Listagens públicas de projetos e freelancers são acessadas por todos os visitantes mas não utilizam o Redis cache configurado no projeto. Cada pageview executa queries desnecessárias no banco, aumentando latência e carga.
O que precisa ser feito:
- Implementar cache com chaves baseadas nos parâmetros de query (filtros, página, categoria)
- TTL de 5 minutos para listagens
- Invalidar cache ao criar/editar projeto via signal Django
- Cache não deve servir dados personalizados de usuários autenticados para visitantes anônimos
Stack: Python / Django 5.0 / Redis (django-redis já instalado no projeto)
Requisitos técnicos:
- Apenas Redis (não cache em memória)
- Filtros diferentes geram chaves de cache diferentes
- Invalidação via signal ao salvar projeto
Critérios de aceite:
- Segunda requisição idêntica não executa queries ao banco
- Cache invalida em ≤ 1s após criação de projeto
- Cache não vaza dados de usuário autenticado para anônimos
Pelo menos um endpoint do Kanban usa @csrf_exempt, removendo a proteção CSRF. Isso expõe o endpoint a ataques onde um site malicioso pode fazer requisições em nome do usuário autenticado sem seu consentimento.
O que precisa ser feito:
- Remover todos os decoradores `@csrf_exempt` das views de kanban
- Garantir que o frontend envie `X-CSRFToken` header nas requisições JavaScript fetch
- Para HTMX, configurar o token CSRF via meta tag no template base
- Escrever teste verificando que requisição sem CSRF token retorna 403
Stack: Python / Django 5.0 + JavaScript vanilla
Requisitos técnicos:
- Sem @csrf_exempt em nenhuma view do módulo de kanban
- Funcionalidade de kanban sem nenhuma regressão
- CSRF token obtido da cookie via JavaScript
Critérios de aceite:
- Zero @csrf_exempt nas views de kanban
- Requisições AJAX incluem X-CSRFToken header
- Requisição sem CSRF token retorna 403
- Teste automatizado cobrindo o cenário
Campos de valor monetário usam FloatField em vez de DecimalField. Operações com ponto flutuante geram erros de arredondamento (0.1 + 0.2 = 0.30000000000000004), o que é inaceitável para cálculos financeiros.
O que precisa ser feito:
- Migrar todos os campos monetários para `DecimalField(max_digits=12, decimal_places=2)` nos models de projetos e propostas
- Verificar e migrar campos financeiros em outros módulos se necessário
- Criar migration limpa e reversível
- Atualizar forms e views que dependem desses campos
Stack: Python / Django 5.0 / PostgreSQL
Requisitos técnicos:
- Migration deve ser reversível
- Sem perda de dados existentes
- Verificar se forms de criação de projeto precisam de ajuste de validação
Critérios de aceite:
- Zero FloatField em campos monetários em toda a codebase
- Cálculo de taxa (price * 0.15) retorna valor exato sem floating-point drift
- Migration executa sem erros
- Sem regressão em forms e templates que exibem valores
O endpoint de atualização de card do Kanban não verifica se o usuário tem permissão para editar o board antes de processar a requisição. Qualquer usuário logado pode modificar cards de outros usuários — falha IDOR (Insecure Direct Object Reference).
O que precisa ser feito:
- Adicionar verificação de permissão em TODAS as views mutáveis do kanban: atualizar card, deletar card, adicionar coluna, deletar coluna
- Verificação: owner do board OU participante autorizado
- Criar Mixin ou decorator reutilizável para verificação de permissão de board
- Retornar HTTP 403 (não 404) para acesso não autorizado
- Escrever teste unitário cobrindo o cenário de acesso não autorizado
Stack: Python / Django 5.0
Requisitos técnicos:
- Mixin reutilizável em todas as views do kanban
- Sem mudança de models ou migrations
Critérios de aceite:
- Requisição com card de outro usuário retorna HTTP 403
- Teste automatizado cobre cenário de acesso não autorizado
- Permissão verificada em todas as views mutáveis do kanban
A listagem de projetos e a view de detalhe com propostas apresentam N+1 queries: para cada projeto renderizado, queries separadas são feitas para o dono e skills requeridas. Com 20 projetos por página, isso resulta em 40+ queries onde deveriam ser 2-3.
O que precisa ser feito:
- Adicionar `select_related` para campos FK nas views de listagem e detalhe de projetos
- Adicionar `prefetch_related` para propostas com dados do freelancer
- Corrigir queryset de participantes do kanban que não usa prefetch
- Verificar com Django Debug Toolbar: listagem ≤ 5 queries, detalhe ≤ 8 queries
Stack: Python / Django 5.0 / PostgreSQL
Requisitos técnicos:
- Apenas otimizações de queryset — sem mudança de models, migrations ou frontend
- Nenhum prefetch redundante
Critérios de aceite:
- Listagem executa ≤ 5 queries
- Detalhe com propostas executa ≤ 8 queries
- Sem regressão funcional
O Service Worker de notificações push existe mas não possui tratamento de erros. Falhas silenciosas causam usuários sem notificações sem saberem. Não há feedback visual ao usuário nem retry logic.
O que precisa ser feito:
- Adicionar try-catch em todos os event handlers do Service Worker
- Feedback visual quando usuário nega permissão de notificações
- Retry automático em falha de subscription por erro de rede
- Log de erros para o console
- Não criar novo sistema — apenas hardening do existente
Requisitos técnicos:
- JavaScript vanilla (Service Worker API)
- Sem quebrar funcionalidade de push existente
- UX de negação deve ser discreta (não modal bloqueante)
Critérios de aceite:
- Nenhuma exceção silenciosa no Service Worker
- Usuário vê mensagem clara ao negar permissão
- Falha de subscription loga no console
- Retry automático após falha transitória de rede
Os templates de projetos possuem texto hardcoded em português sem uso das tags de internacionalização do Django. Isso impede futura expansão internacional e viola a convenção de i18n do projeto.
O que precisa ser feito:
- Auditar todos os templates na seção de projetos
- Adicionar `{% load i18n %}` em todos os templates alterados
- Envolver textos visíveis ao usuário com `{% trans "..." %}`
- Executar `python manage.py makemessages -l pt_BR`
- Atualizar e compilar o arquivo de tradução pt-BR
Requisitos técnicos:
- Django i18n nativo (sem libs externas)
- `compilemessages` deve executar sem erros
- Funcionalidade idêntica após a mudança
Critérios de aceite:
- Zero texto visible-to-user hardcoded nos templates de projetos
- Arquivo .po atualizado e compilado
- Nenhuma regressão visual ou funcional
O módulo de status monitora saúde dos serviços, mas a página de status pública precisa de um design que transmita confiança e seja clara para usuários não técnicos. Referência visual: statuspage.io, instatus.com.
O que precisa ser feito:
- Badge de status global destacado (OPERACIONAL / DEGRADADO / FORA DO AR)
- Grid de serviços agrupados por categoria com ícones
- Mini gráfico de barras de uptime dos últimos 90 dias usando CSS puro (width proporcional)
- Seção de incidentes ativos com destaque visual
- Histórico de incidentes resolvidos
Requisitos técnicos:
- CSS puro / Tailwind para o gráfico de uptime (sem Chart.js)
- ARIA roles para status operacional/degradado
- Responsivo e dark mode
- Zero Bootstrap
Critérios de aceite:
- Status geral comunicado em menos de 2 segundos de leitura
- Gráfico de 90 dias legível em mobile
- Incidentes ativos têm destaque visual claro
O módulo de gamificação existe no backend mas a interface pode carecer de elementos visuais que maximizam engajamento: countdown para fim do desafio, ranking com avatares, badges com animação de unlock, progress bars.
O que precisa ser feito:
- Countdown timer JS (vanilla) para desafios com prazo
- Ranking visual com medalhas: ouro/prata/bronze para top-3
- Animação CSS de 'unlock' para badges recém conquistados (keyframes)
- Progress bar animada refletindo score do participante
- Não alterar nada no backend
Requisitos técnicos:
- JavaScript vanilla para o countdown
- Animações via CSS keyframes (sem libs externas)
- 100% Tailwind
- Responsivo e dark mode
Critérios de aceite:
- Countdown exibe horas:minutos:segundos e some quando encerra
- Top-3 com ícones de ouro/prata/bronze
- Badge com animação de unlock ao conquistar
- Progress bar reflete score / 100 visualmente
A página de perfil público do freelancer é um ponto crítico de conversão (clientes decidem contratar a partir dela), mas carece de hierarquia visual clara, não é mobile-first, e não destaca adequadamente os elementos mais importantes.
O que precisa ser feito:
- Redesenhar o layout com grid Tailwind responsivo
- Hero com foto/capa de perfil e dados principais
- Stats destacados: projetos concluídos, rating médio, taxa de aceite, badges
- Seção de skills com pills navegáveis
- Portfólio em grid responsivo
- Reviews paginados com HTMX
Requisitos técnicos:
- 100% Tailwind CSS (zero Bootstrap)
- Mobile-first: funciona perfeitamente em 320px, 768px e 1280px
- Sem alterações em models ou views (apenas templates)
Critérios de aceite:
- Stats de social proof visíveis acima do fold em mobile
- Portfólio abre preview sem sair da página
- Zero Bootstrap em código novo
- Dark mode completo
A plataforma não possui um sistema de toast/notificação global reutilizável. Feedback de ações importantes (salvar projeto, enviar proposta, erro de rede) é feito de forma inconsistente — alguns templates usam alerts, outros não dão feedback.
O que precisa ser feito:
- Criar arquivo JS com API simples: `Toast.show({message, type, duration})`
- Container de toasts injetado no DOM uma vez, toasts empilhados verticalmente
- Integrar com HTMX via evento `htmx:afterRequest` e headers de resposta
- Integrar em pelo menos 3 ações existentes (salvar projeto, enviar proposta, atualizar kanban)
Requisitos técnicos:
- JavaScript vanilla, zero dependências
- Tipos: success, error, warning, info
- Auto-dismiss após 4s com opção de fechar manualmente
- Múltiplos toasts empilhados sem sobreposição
Critérios de aceite:
- Toast aparece no canto inferior direito com animação
- Full-width na base em mobile
- Dark mode compatível
- Integrado em mínimo 3 ações reais da plataforma
A paginação da listagem de projetos não possui aria-label, não marca a página atual como aria-current e os links não são descritivos para leitores de tela. Usuários com tecnologias assistivas têm experiência degradada.
O que precisa ser feito:
- Adicionar `<nav aria-label="Paginação">` na paginação
- Marcar página atual com `aria-current="page"`
- Adicionar `aria-label` ou `<span class="sr-only">` nos botões anterior/próximo
- Adicionar skiplink 'Ir para o conteúdo' na navegação principal
- Verificar contraste de cores nos estados hover/focus
Requisitos técnicos:
- Padrão WCAG 2.1 AA
- Navegação por teclado (Tab, Enter, Space)
- Sem alterações visuais para usuários sem tecnologia assistiva
Critérios de aceite:
- Navegação por teclado funciona completamente na paginação
- Skiplink presente e funcional
- Roles ARIA corretos em toda a navegação principal
Existem dois padrões diferentes de empty state na plataforma: o componente oficial e implementações ad-hoc inline em alguns templates. Isso cria inconsistência visual e dificulta manutenção.
O que precisa ser feito:
- Auditar todos os templates com listagens (projetos, freelancers, chat, gamificação)
- Substituir empty states ad-hoc pelo componente padrão
- Se o componente não suportar ícone customizado, adicionar essa propriedade
- Garantir que todas as listagens tenham empty state (nenhuma retorna vazia sem mensagem)
Requisitos técnicos:
- Usar `{% include %}` com o componente padrão de empty state
- Ícone e mensagem contextualizado por seção
- Dark mode compatível
Critérios de aceite:
- Componente padrão é o único usado em produção
- Mínimo 5 listagens auditadas e corrigidas
- Consistência visual garantida
A página de configuração de aparência do usuário usa classes Bootstrap (form-label, btn, btn-outline-secondary) e atributos style inline — violando as regras do projeto que exigem Tailwind exclusivo e proíbem style inline e Bootstrap em código novo.
O que precisa ser feito:
- Reescrever o template de aparência em Tailwind puro
- Remover todos os atributos `style=` inline
- Remover todas as classes Bootstrap
- Migrar qualquer script inline para arquivo .js separado
- Os toggles de tema (light/dark/system) devem usar radio buttons estilizados com Tailwind
Requisitos técnicos:
- Zero Bootstrap no template
- Zero style inline
- Zero scripts inline
- Visual consistente com restante das páginas de perfil
Critérios de aceite:
- Toggle de tema funciona identicamente ao comportamento atual
- Aparência consistente em dark/light mode
O Kanban possui drag-and-drop funcional mas sem feedback visual durante a operação. Não há loading spinner após soltar o card (enquanto o PATCH é enviado), nem rollback em caso de falha de rede.
O que precisa ser feito:
- Exibir overlay de loading na coluna destino durante o fetch de atualização
- Implementar atualização otimista com rollback automático em caso de erro
- Criar sistema de toast de sucesso/erro
- Tratamento de erro de rede (card retorna à posição original com animação)
Requisitos técnicos:
- JavaScript vanilla
- Toast reutilizável (criar `setup/static/js/utils/toast.js`)
- Animação de retorno em CSS
Critérios de aceite:
- Card exibe overlay translúcido durante o PATCH
- Em erro de rede, card retorna à posição original
- Toast de erro com mensagem clara ao usuário
- Sem regressão no drag-and-drop existente
O filtro de projetos não possui debounce na busca textual, gerando múltiplas requisições por keystroke. O script de filtro contém código inline (onchange, onkeyup) que viola as regras do projeto.
O que precisa ser feito:
- Remover todos os scripts inline do template de filtro
- Usar `hx-trigger="keyup changed delay:300ms"` nativo do HTMX para debounce
- Criar endpoint Django para retornar partial HTML da lista de projetos
- Adicionar `hx-indicator` com loading durante a busca
- URL deve atualizar com query params via `hx-push-url`
Requisitos técnicos:
- Zero inline JS nos templates
- Filtros combinados devem funcionar (categoria + nível + busca textual)
- Backend: view que retorna partial da lista de projetos
Critérios de aceite:
- Requisição só dispara após 300ms de inatividade
- URL reflete filtros aplicados (compartilhável)
- Indicador de loading durante busca