尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Aplicação web pessoal de controle financeiro: receitas, despesas, categorias, saldo e dashboard.
O projeto atende a disciplina de Testes de Software do Bacharelado em Sistemas de Informação (BSI) da UFRN.
O SpendSmart é um monolito fullstack Next.js (App Router) com Supabase, sem servidor HTTP
próprio. As rotas de API são funções serverless em src/app/api/ (createProfile, deleteAccount,
health, status), e não há código de assinatura ou validação de token: a sessão é inteira do
Supabase Auth.
Um backend Node.js/Express existiu até o commit 2599ad9 e foi removido; o front-end migrou de
pages/ (Pages Router) para src/app/ (App Router). Tudo aqui descreve o código atual.
| Membro | Papel | GitHub |
|---|---|---|
| José Samuel Silva Lima | Gerente / Testador (QA) | @José-Samuel-Lima |
| Marcus Vinícius de Souza Azevedo | Desenvolvedor principal | @MViniciusCoffe |
O passo a passo completo (pré-requisitos e instalação do Docker e do Supabase CLI, variáveis de ambiente, todas as suítes de teste, problemas comuns) está no Manual de execução.
Resumo, com Node.js 24+, Docker e Supabase CLI instalados:
npm install
supabase start # sobe Postgres + Auth + RLS + Studio locais
cp .env.local.example .env.local # preencha com as chaves de 'npm run infra:status'
npm run dev # aguarda o Supabase ficar saudável e inicia o Next.js
A aplicação responde em http://localhost:3000. Para os testes:
npm test # unidade (só Node.js)
npm run test:coverage # unidade + cobertura
npm run test:integration # integração com pg-mem (só Node.js)
npm run test:mutation # testes de mutação (Stryker)
O nome da chave pública é NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY — o Supabase renomeou a antiga
anon para publishable, e ANON_KEY não é mais válido.
SUPABASE_SERVICE_ROLE_KEY não pode ter prefixo NEXT_PUBLIC_. Com esse prefixo ela vira
parte do bundle enviado ao navegador e qualquer visitante ganha acesso à conta inteira. Ela só é
lida dentro de src/app/api/.
SpendSmart/
src/
app/ páginas (App Router): dashboard, transactions, categories, settings,
login, register, about, contact, status
api/ rotas serverless: createProfile, deleteAccount, health, status
components/
ui/ design system: Button, Input, Card, Table, Tabs, Dropdown, ChartContainer...
forms/ TransactionForm, CategoryForm
feedback/ Toast, ConfirmDialog, EmptyState, LoadingSpinner, RouteError
layout/ Header, Footer, PageContainer/PageHeader, AuthShell (login e cadastro)
withAuth.js guarda das páginas privadas
contexts/ AuthContext (sessão e usuário) e ToastContext
services/ camada de negócio: validação, tradução de domínio, mapeamento de erros
lib/ cliente Supabase (supabase.js), formatadores (utils/format.js), config
styles/ globals.css e design-tokens.css (variáveis de cor, espaço, raio, sombra...)
supabase/migrations/ schema do banco (node-pg-migrate)
infra/ Docker Compose do Postgres puro
tests/ suíte Jest — ver o estado real abaixo
docs/ documentação
A separação de responsabilidades adotada:
| Camada | Arquivo | Responsabilidade |
|---|---|---|
| Interface | src/app/ | React, validação de formulário, chamada ao service |
| Componentes | src/components/ | UI reutilizável; CSS Modules com os tokens de design-tokens.css |
| Sessão | src/contexts/ | AuthContext é a fonte única do usuário logado (Header, withAuth) |
| Negócio | src/services/ | Regra de negócio, tradução PT/EN, mensagem de erro em português |
| Cliente | src/lib/supabase.js | Instância única do createClient |
| Privilegiado | src/app/api/ | Único lugar que lê SUPABASE_SERVICE_ROLE_KEY |
user_id vem sempre da sessão, nunca do corpo da requisição. referência:
os .eq("user_id", session.user.id) de src/services/categoryService.js e
src/services/transactionService.js.user_id em toda leitura e escrita, além
da política.numeric(12,2) com check (amount > 0). Nunca float.type aceita apenas income ou expense no banco. A tradução para receita/despesa
acontece só na fronteira do service.deleted_at). Uma categoria com transações pode ser excluída (US-009):
as transações continuam no histórico e no dashboard, exibindo a categoria como "Nome (deletada)",
e a categoria pode ser restaurada. Mudar o tipo de uma categoria com transações pede confirmação
e propaga o tipo às transações (CA-008.03).alert/confirm. Feedback por toast e confirmações pelo ConfirmDialog.| Item | Estado |
|---|---|
| Cadastro, login, logout, perfil | Funcionando |
| Categorias: criar, listar, alterar, excluir | Funcionando, com exclusão lógica, contagem de usos e restauração |
| Transações: criar, listar, editar, excluir | Funcionando — uma página com abas, seleção de linha e ações no cabeçalho da tabela |
| Dashboard com gráficos | Funcionando |
| Excluir conta | Funcionando |
| Interface | Toda em português, tema escuro, valores em R$ e datas em dd/mm/aaaa |
| Testes de unidade | 188 testes, 100% de linhas, ramos e funções em src/services/ |
| Testes de integração (pg-mem) | 5 suítes, 28 testes (constraints, FK, unicidade) |
| Testes de integração (Supabase/RLS) | 1 suíte, 17 testes (tests/integration/supabase/rls.test.js) — isolamento real entre 2 usuários |
| Testes de regressão | 5 suítes, 27 testes (issues #10, #21, #32, data no fuso, categoria excluída/tipo) |
npm test | Passa — 188/188 |
Build de produção (next build) | Passa — 15 rotas |
| CI no GitHub Actions | 4 workflows — test.yml (com job de RLS), lint.yml, sonar.yml, mutation.yml |
| RLS aplicado e validado | Validado via tests/integration/supabase/rls.test.js (requer supabase start + .env.local) |
| Testes de front-end | Não existem — src/app/ e sem cobertura automatizada (issue #33) |
| # | Problema |
|---|---|
| #24 | Rotas privadas sem proteção no servidor e sem headers de segurança |
| #20 | Desenvolvimento, Preview e Produção usam o mesmo projeto Supabase |
| — | AuthContext não escuta mudanças de sessão; expiração só é detectada pelos serviços |
Corrigidos no código atual (podem ser fechados no GitHub): #6 e #7 (páginas unificadas e
componentizadas), #13 (toasts no lugar de alert), #22
(navbar duplicada), #23 (rotas públicas), #32 (valor com vírgula e separador de milhar) e #43
(senha mínima no cadastro).
As políticas só são criadas quando auth.users existe
(supabase/migrations/1790304277000_create_financial_schema.sql:58). No
PostgreSQL local (Docker Compose) essa tabela não existe, portanto o RLS não é aplicado ali.
Com Supabase CLI (supabase start), o RLS é real e o isolamento entre dois usuários é testado
em tests/integration/supabase/rls.test.js (17 testes cobrindo leitura/escrita cross-user).
O teste requer .env.local preenchido e supabase start rodando — não roda no CI GitHub Actions.
Cada assunto tem um único documento canônico. Não há duas fontes para o mesmo fato.
Os identificadores RF01 a RF16, RNF01 a RNF07 e US-001 a US-016 vêm dos documentos da disciplina.
As versões .docx desses documentos não são versionadas: o conteúdo relevante está reescrito nos
arquivos abaixo, em Markdown.
| Documento | Conteúdo |
|---|---|
| Documento de Visão | Escopo, personas, RF01-RF16, RNF01-RNF07, riscos e equipe |
| User Stories | US-001 a US-016, derivadas de RF01 a RF16, com critérios de aceitação |
| Plano de testes | Níveis de teste, 10 casos de integração, matriz US/RF, riscos, papéis |
| Plano de teste das iterações 1, 2 e 3 | 31 casos de teste com passos, dados de entrada, resultado esperado e sintaxe Gherkin |
| Testes de mutação | Stryker em services/: score 97,10%, evolução por rodada e mutantes aceitos |
| Estado atual dos testes | Registro histórico do diagnóstico inicial dos testes (estado atual: seção acima) |
| Documento | Conteúdo |
|---|---|
| Plano de iterações | 6 iterações no semestre, com distribuição de US por membro e período |
| Plano da iteração 1 | Tarefas detalhadas, cronograma e critérios de entrada/saída (I1) |
| Documento | Conteúdo |
|---|---|
| Esquema do banco | Tabelas, constraints, índices, 3FN, RLS, limites conhecidos |
| Opções de arquitetura | ADR de 2026-09-22: as opções avaliadas e a adotada |
| Migrações futuras | Propostas em SQL para profiles em inglês, updated_at e coerência de type |
| Infraestrutura local | Docker Compose, comandos e o que o Postgres local não valida |
| Documento | Conteúdo |
|---|---|
| Manual de execução | Instalação, configuração, execução da aplicação e de todas as suítes de teste |
| Ambientes | Matriz de ambientes, variáveis, o problema do npm run dev |
| SonarQube | Análise estática no LABENS: escopo medido, cobertura, resultado e pendências |
| Decisões de ferramenta | Por que cada versão foi escolhida: ESLint 9, Jest, Husky, escopo do Sonar |
| Script | Comando | Quando usar |
|---|---|---|
npm run dev | concurrently infra:up + next:dev | Padrão — desenvolvimento diário |
npm run infra:up | supabase start | Só sobe infra (já tem .env.local) |
npm run next:dev | next dev | Next.js só (infra já rodando) |
npm run infra:down | supabase stop | Para infra |
npm run infra:reset | supabase db reset | Recria banco + migrations |
npm run infra:studio | supabase studio | Abre dashboard local |
npm run infra:status | supabase status | Mostra URLs e chaves |
npm run services:up | docker compose up -d | Postgres puro (sem RLS) |
npm run migrations:up | node-pg-migrate up | Aplica migrations (usa .env.development) |
npm run test | jest tests/unit | Testes unitários |
npm run test:integration | jest integration | Integração pg-mem |
npm run test:all | unit + pg-mem + regressão + RLS | Todos os testes |
npm run test:mutation | stryker run | Testes de mutação em services/ |
Issues abertas, em ordem de dependência:
| # | Assunto | Bloqueia |
|---|---|---|
| #24 | Proteção server-side e headers | — |
| #20 | Separar ambientes | — |
| #33 | Cobertura de front-end | — |
| #30 | Isolamento por RLS (teste em CI) | #20 |
Resolvidos pela frente de testes, CI e SonarQube: #2, #10, #15, #16, #17, #18, #19, #21, #25, #26, #29, #31. Resolvidos pela frente de front-end: #6, #7, #13, #22, #23, #32, #43.
Conventional Commits, em português:
docs: feat: fix: refactor: test: chore:
Regra dura: não misturar migração de banco, refactor visual e infra no mesmo commit. O corpo do commit explica o porquê, não o o que. Nenhum commit deve afirmar que algo funciona sem dizer como foi verificado.
src/components/| Ambientes separados | Não existem — um único banco para tudo (issue #20) |