Hub 360 Bug Tracker
Plataforma completa de gestao e documentacao de bugs. Formulario publico de report, dashboard autenticado com filtros, notas internas e audit log.
Stack Tecnologica
Next.js 16 (App Router)
Framework React com server components, API routes e renderizacao hibrida.
Supabase
Backend-as-a-Service com PostgreSQL, Auth, Storage e Row Level Security.
Tailwind CSS 4
Framework CSS utility-first para estilizacao rapida e responsiva.
TypeScript
Tipagem estatica em todo o projeto para seguranca e produtividade.
Playwright
Framework de testes E2E com 64 testes cobrindo UI, API e seguranca.
Vercel
Deploy automatico com CI/CD integrado ao GitHub.
Estrutura de Arquivos
hub360-bugs/
-- Paginas
src/app/page.tsx # Redirect -> /login
src/app/login/page.tsx # Tela de login
src/app/dashboard/page.tsx # Dashboard principal
src/app/report/[slug]/page.tsx # Form publico de report
-- API Routes
src/app/api/auth/route.ts # Autenticacao
src/app/api/bugs/route.ts # Listar / criar bugs
src/app/api/bugs/[id]/route.ts # Detalhe / atualizar bug
src/app/api/bugs/[id]/notes/route.ts # Notas internas
src/app/api/upload/route.ts # Upload de arquivos
-- Componentes
src/components/BugDrawer.tsx # Drawer de detalhes
src/components/StatusBadge.tsx # Badge de status
src/components/SeverityBadge.tsx # Badge de severidade
-- Libs
src/lib/auth.ts # Helpers de auth (client)
src/lib/supabase-browser.ts # Client Supabase (browser)
src/lib/supabase-server.ts # Client Supabase (server)
src/lib/utils.ts # Utilitarios
src/types/index.ts # Tipos TypeScript
-- Database
setup-db.sql # Schema SQL completo
seed.mjs # Dados de seed
supabase/config.toml # Config Supabase CLI
-- Testes
tests/app.spec.ts # 64 testes Playwright
playwright.config.ts # Config Playwright
Login
Tela de autenticacao para membros da equipe. Valida credenciais via Supabase Auth e armazena sessao no localStorage.
Credenciais de Teste
| Nome | Senha | Papel | |
|---|---|---|---|
| Ricardo Mendes | admin@hub360.com.br | Hub360@2025 | Admin |
| Ana Souza | dev@hub360.com.br | Hub360@2025 | Dev |
| Carlos Lima | pm@hub360.com.br | Hub360@2025 | PM |
Fluxo
Dashboard
Painel principal autenticado para visualizacao e gestao de bugs. Requer login.
Funcionalidades
Filtros Multiplos
Projeto, status, severidade, responsavel e busca por titulo com debounce de 300ms.
Ordenacao
Colunas clicaveis: titulo, status, severidade, data de criacao. Toggle asc/desc.
Cards de Status
Contadores clicaveis por status. Mostram total de bugs em cada estado.
Bug Drawer
Painel lateral com detalhes, anexos, notas internas e audit log completo.
Paginacao
30 bugs por pagina com navegacao entre paginas.
Gestao de Bugs
Alterar status, atribuir responsavel e adicionar notas internas diretamente do drawer.
Status Disponiveis
Severidades
Formulario de Report
Formulario publico acessivel via /report/[slug]. Qualquer usuario pode reportar bugs sem precisar de login.
Campos do Formulario
| Campo | Obrigatorio | Validacao |
|---|---|---|
| Nome do reporter | Nao | - |
| Email do reporter | Nao | - |
| Titulo | Sim | 5-200 caracteres |
| Onde encontrou | Sim | 3-300 caracteres |
| O que fez (passos) | Sim | 5-1000 caracteres |
| O que esperava | Sim | 5-1000 caracteres |
| O que aconteceu | Sim | 5-1000 caracteres |
| Severidade | Sim | Critica, Alta, Media, Baixa |
| Dispositivo | Nao | Auto-detectado |
| Anexos | Sim (min 1) | Max 3 arquivos, 100MB cada. JPG, PNG, WebP, MP4, MOV, WebM |
Recursos
- Auto-save no
localStoragea cada 500ms - Deteccao automatica de dispositivo (Android, iOS, Desktop)
- Protecao contra duplicatas (idempotency key com janela de 5min)
- Rate limiting: 10 envios por hora por IP
- Tela de sucesso com numero do bug
Projetos de Teste
| Projeto | Slug | URL de Report |
|---|---|---|
| AZ-IB | az-ib | /report/az-ib |
| Liscan | liscan | /report/liscan |
| NEX Solar | nex-solar | /report/nex-solar |
API Reference
Todas as rotas de API estao em /api/*. Rotas autenticadas requerem header Authorization: Bearer <token>.
POST /api/auth e retornado no campo session.access_token.
Autenticacao de membros da equipe. Retorna sessao e dados do usuario.
REQUEST BODY{
"email": "admin@hub360.com.br",
"password": "Hub360@2025"
}
RESPONSE 200
{
"success": true,
"session": {
"access_token": "eyJhbGci...",
"refresh_token": "...",
"expires_at": 1234567890
},
"user": {
"id": "uuid",
"email": "admin@hub360.com.br",
"team_member": { /* TeamMember object */ }
}
}
ERROS
| Status | Motivo |
|---|---|
400 | Email ou senha ausentes |
401 | Credenciais invalidas |
Lista bugs com filtros, busca e paginacao. Requer autenticacao.
QUERY PARAMS| Param | Tipo | Default | Descricao |
|---|---|---|---|
page | number | 1 | Pagina atual |
page_size | number | 30 | Itens por pagina |
project_id | UUID | - | Filtrar por projeto |
status | string | - | Filtrar por status (comma-separated) |
severity | string | - | Filtrar por severidade |
assigned_to | UUID | - | Filtrar por responsavel |
search | string | - | Busca por titulo (full-text) |
sort_by | string | created_at | Campo de ordenacao |
sort_dir | asc|desc | desc | Direcao da ordenacao |
{
"bugs": [
{
"id": "uuid",
"number": 1,
"title": "Botao nao responde",
"status": "new",
"severity": "critical",
"created_at": "2025-03-18T...",
"project": { "name": "AZ-IB" },
"assignee": { "name": "Ana Souza" }
}
],
"total": 50,
"page": 1,
"page_size": 30,
"total_pages": 2
}
Cria um novo bug report. Rota publica (sem autenticacao).
REQUEST BODY{
"project_slug": "az-ib",
"title": "Botao de login nao funciona",
"where_found": "Tela de login > Botao Entrar",
"steps_taken": "Abri o app, digitei email...",
"expected_behavior": "Login bem-sucedido",
"actual_behavior": "Nada acontece",
"severity": "high",
"device_info": "Samsung Galaxy A34 / Android 14",
"reporter_name": "Joao",
"reporter_email": "joao@email.com",
"attachment_paths": [
{ "path": "az-ib/123-foto.png", "name": "foto.png", "type": "image/png", "size": 102400 }
]
}
RESPONSE 200
{
"success": true,
"bug": { "id": "uuid", "number": 42 },
"duplicate": false
}
ERROS
| Status | Motivo |
|---|---|
400 | Campos obrigatorios ausentes ou invalidos |
404 | Projeto nao encontrado |
403 | Projeto inativo |
429 | Rate limit excedido (max 10/hora/IP) |
Retorna detalhes completos de um bug, incluindo anexos, notas e audit log. Requer autenticacao.
RESPONSE 200{
"id": "uuid",
"number": 1,
"title": "Botao nao responde",
"status": "new",
"severity": "critical",
"version": 2,
"where_found": "...",
"steps_taken": "...",
"expected_behavior": "...",
"actual_behavior": "...",
"project": { "name": "AZ-IB" },
"assignee": { "name": "Ana Souza" },
"attachments": [{ "file_name": "foto.png", "url": "https://signed..." }],
"notes": [{ "content": "Investigando...", "author": {} }],
"audit_log": [{ "action": "status_changed", "old_value": "new", "new_value": "analyzing" }]
}
Atualiza status, responsavel ou duplicata de um bug. Requer autenticacao. Usa optimistic locking.
REQUEST BODY{
"status": "analyzing",
"assigned_to": "uuid-do-membro",
"version": 2 // para optimistic locking
}
ERROS
| Status | Motivo |
|---|---|
400 | Status invalido ou nenhum campo enviado |
401 | Nao autenticado |
409 | Conflito de versao (outro usuario editou) |
Adiciona uma nota interna a um bug. Requer autenticacao. Apenas membros da equipe.
REQUEST BODY{
"content": "Investigando o problema. Parece ser memory leak."
}
RESPONSE 200
{
"success": true,
"note": {
"id": "uuid",
"content": "Investigando o problema...",
"author": { "name": "Ana Souza" }
}
}
Upload de arquivos para anexar a bug reports. Rota publica.
REQUESTContent-Type: multipart/form-data
| Campo | Tipo | Descricao |
|---|---|---|
file | File | Arquivo para upload |
project_slug | string | Slug do projeto |
- Tamanho maximo: 100 MB por arquivo
- Tipos permitidos: JPG, PNG, WebP, MP4, MOV, WebM
- Maximo 3 arquivos por bug report
Banco de Dados
PostgreSQL via Supabase com Row Level Security, triggers automaticos e indices otimizados.
Tabelas
projects
| Coluna | Tipo | Descricao |
|---|---|---|
id | UUID PK | Identificador unico |
name | TEXT | Nome do projeto |
slug | TEXT UNIQUE | Identificador URL-safe (regex validado) |
description | TEXT | Descricao (opcional) |
is_active | BOOLEAN | Projeto ativo (default true) |
created_at | TIMESTAMPTZ | Data de criacao |
bugs
| Coluna | Tipo | Descricao |
|---|---|---|
id | UUID PK | Identificador unico |
number | INTEGER | Numero sequencial por projeto (auto-gerado) |
project_id | UUID FK | Referencia ao projeto |
title | TEXT | Titulo (5-200 chars) |
where_found | TEXT | Onde encontrou (3-300 chars) |
steps_taken | TEXT | Passos para reproduzir (5-1000 chars) |
expected_behavior | TEXT | Comportamento esperado (5-1000 chars) |
actual_behavior | TEXT | Comportamento real (5-1000 chars) |
severity | TEXT | critical, high, medium, low |
status | TEXT | new, analyzing, fixing, awaiting_validation, resolved, closed, reopened |
assigned_to | UUID FK | Membro responsavel (nullable) |
version | INTEGER | Versao para optimistic locking |
device_info | TEXT | Info do dispositivo (nullable) |
reporter_name | TEXT | Nome do reporter (nullable) |
reporter_email | TEXT | Email do reporter (nullable) |
reporter_ip | INET | IP do reporter |
idempotency_key | TEXT UNIQUE | Chave anti-duplicata |
created_at | TIMESTAMPTZ | Data de criacao |
updated_at | TIMESTAMPTZ | Data de atualizacao (auto) |
team_members
| Coluna | Tipo | Descricao |
|---|---|---|
id | UUID PK | Identificador unico |
auth_user_id | UUID FK | Referencia ao auth.users do Supabase |
name | TEXT | Nome do membro |
email | TEXT UNIQUE | |
role | TEXT | dev, pm, admin |
is_active | BOOLEAN | Membro ativo |
bug_attachments
| Coluna | Tipo | Descricao |
|---|---|---|
id | UUID PK | Identificador |
bug_id | UUID FK | Bug associado (CASCADE) |
file_name | TEXT | Nome do arquivo |
file_type | TEXT | MIME type |
file_size | BIGINT | Tamanho em bytes |
storage_path | TEXT | Caminho no Supabase Storage |
bug_notes & bug_audit_log
| Tabela | Descricao | Campos-chave |
|---|---|---|
bug_notes | Notas internas (append-only) | bug_id, author_id, content |
bug_audit_log | Historico de mudancas | bug_id, actor_id, action, old_value, new_value |
rate_limits | Controle de rate limiting | ip_address, endpoint, created_at |
Triggers & Functions
| Trigger | Tabela | Descricao |
|---|---|---|
update_updated_at() | bugs | Atualiza updated_at automaticamente |
generate_bug_number() | bugs | Gera numero sequencial por projeto |
log_bug_changes() | bugs | Registra mudancas no audit log e incrementa versao |
clean_old_rate_limits() | rate_limits | Remove entradas com mais de 1 hora |
Row Level Security (RLS)
| Tabela | Anon | Authenticated |
|---|---|---|
| projects | Leitura (ativos) | CRUD completo |
| team_members | - | Leitura + gestao |
| bugs | - | Leitura + atualizacao |
| bug_attachments | - | Leitura |
| bug_notes | - | Leitura |
| bug_audit_log | - | Leitura |
Seguranca
Fluxo de Autenticacao
Cada requisicao autenticada envia Authorization: Bearer <access_token>. O server valida via supabase.auth.getUser(token).
Rate Limiting
- 10 submissoes por hora por IP
- Rastreado por IP + endpoint na tabela
rate_limits - Auto-limpeza de registros com mais de 1 hora
- Retorna
429 Too Many Requestsquando excedido
Protecao Anti-Duplicata
- Hash gerado com: project_id + titulo + passos + IP + janela de 5 minutos
- Constraint UNIQUE na coluna
idempotency_key - Retorna o bug existente se duplicata detectada
Optimistic Locking
- Campo
versionem cada bug - PATCH envia
versionatual do cliente - Se versao no banco diferir, retorna
409 Conflict - Incrementa automaticamente via trigger
Headers de Seguranca
| Header | Valor |
|---|---|
X-Frame-Options | DENY |
X-Content-Type-Options | nosniff |
Referrer-Policy | strict-origin-when-cross-origin |
Strict-Transport-Security | max-age=63072000; includeSubDomains; preload |
Testes
64 testes E2E com Playwright cobrindo toda a aplicacao.
npx playwright test (requer server na porta 3333)
Cobertura
| Categoria | Testes | Descricao |
|---|---|---|
| Login Page | 5 | Form, credenciais invalidas, redirect, loading state, subtitle |
| Dashboard | 17 | Lista, filtros, busca, drawer, notas, status, ordenacao, logout |
| Bug Report Form | 14 | Validacao, submit, upload, remocao, severidade, auto-save |
| API Security | 6 | Auth obrigatoria, token invalido, validacao de campos |
| API Auth Edge Cases | 2 | Body vazio, resposta de sessao valida |
| API Bug Detail | 3 | Auth, token invalido, bug inexistente |
| API Patch Bug | 4 | Token invalido, status invalido, body vazio, update valido |
| API Notes | 4 | Auth, token invalido, content vazio, criacao valida |
| API Upload | 1 | Rejeita request sem arquivo |
| API Bugs List | 4 | Filtros: search, severity, sorting, status |
| Navigation | 1 | Root redirect para /login |
| Total | 64 |
Dados de Seed
O script seed.mjs popula o banco com dados de teste realistas.
Usuarios
| Nome | Papel | |
|---|---|---|
| Ricardo Mendes | admin@hub360.com.br | Admin |
| Ana Souza | dev@hub360.com.br | Dev |
| Carlos Lima | pm@hub360.com.br | PM |
Projetos
| Nome | Slug | Descricao |
|---|---|---|
| AZ-IB | az-ib | App bancario AZ-IB |
| Liscan | liscan | App Liscan iOS |
| NEX Solar | nex-solar | Plataforma de financiamento solar |
Inclui 12 bugs de exemplo com severidades e status variados, e 4 notas internas de amostra.
Hub360@2025
Variaveis de Ambiente
Crie um arquivo .env.local na raiz do projeto:
NEXT_PUBLIC_SUPABASE_URL=https://seu-projeto.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGci...
SUPABASE_SERVICE_ROLE_KEY=eyJhbGci...
.env.local no repositorio. Ele ja esta no .gitignore.