Ambiente bancário fictício para demonstração, aprendizado e testes. Nenhum valor ou transferência realizada nesta plataforma possui valor financeiro real.
- Aplicação publicada: https://v-bank-three.vercel.app/
- Health check: https://v-bank-three.vercel.app/api/health
O VBank Sandbox é um simulador educacional, aberto e sob licença MIT. Ele demonstra como construir uma aplicação transacional com Java 21, Spring Boot, React, TypeScript e PostgreSQL sem integrar Pix real, bancos, Banco Central, Open Finance, cartões, boletos, criptomoedas, e-mail ou SMS.
Cada conta de demonstração recebe R$ 50.000,00 fictícios. Usuários criam chaves internas, localizam outra conta, transferem saldo sandbox, consultam ledger/extrato, recebem notificações e baixam comprovantes PDF. O backend é sempre a fonte da verdade.
- Não é uma instituição financeira.
- “Chave Pix simulada” e “chave interna” só funcionam nesta plataforma.
- Não use CPF, CNPJ, cartão, conta bancária real ou dado governamental.
- Não existe dinheiro real, saque, depósito, cobrança, pagamento ou promessa de rendimento.
- Não use este projeto como sistema financeiro de produção.
- cadastro, login, logout, recuperação de sessão e logout global;
- JWT de acesso em memória e refresh token rotativo em cookie HttpOnly;
- senha e PIN com BCrypt, bloqueio após cinco tentativas de PIN;
- saldo inicial, recarga sandbox de 24 horas e ajustes administrativos;
- chaves internas
EMAIL,PHONE,USERNAMEeRANDOM; - transferência atômica com
Idempotency-Key, limite diário e locks pessimistas; - ledger de débito/crédito para toda alteração de saldo;
- extrato, filtros, paginação, comprovante web, impressão e PDF;
- notificações internas e auditoria sem segredos;
- administração de usuários, bloqueios, ajustes, transferências e auditoria;
- Problem Details, Swagger em desenvolvimento e health check seguro;
- interface responsiva desde 360 px, teclado, foco visível e movimento reduzido.
| Camada | Tecnologias |
|---|---|
| Backend | Java 21, Spring Boot, Security, JPA, Flyway, JWT, PDFBox |
| Frontend | React 19, TypeScript, Vite, Router, Hook Form, Zod, Axios |
| Banco | PostgreSQL, recomendado Neon Free com conexão pooled e SSL |
| Testes | JUnit, Mockito, Testcontainers, Vitest, Testing Library |
| Entrega | Docker multi-stage, Vercel OCI, GitHub Actions |
| Serviço | Plano | Custo esperado | Finalidade |
|---|---|---|---|
| GitHub | Free | R$ 0 | Repositório público |
| GitHub Actions | Público | R$ 0 | Testes e builds em runner padrão |
| Vercel | Hobby | R$ 0 | Aplicação pessoal/não comercial |
| Neon | Free | R$ 0 | PostgreSQL |
| Domínio | .vercel.app |
R$ 0 | Endereço público |
Planos, cotas e regras mudam. Consulte as páginas oficiais antes do deploy. Não cadastre cartão, não ative add-ons, não use larger runners, não compre domínio e não habilite recursos pagos. Configure orçamento/limite em zero quando houver essa opção e prefira indisponibilidade ao atingir uma cota em vez de cobrança. Veja custos e limites.
O Hobby da Vercel é destinado a uso pessoal/não comercial. Este projeto é educacional; para uso comercial, revise os termos e escolha outra hospedagem/licença de serviço compatível.
flowchart LR
B["Navegador"] --> V["Vercel Hobby<br/>imagem OCI"]
V --> S["Spring Boot<br/>API REST + React compilado"]
S --> N["PostgreSQL Neon Free<br/>pooled + SSL"]
Em produção, React e Spring são um único artefato. O Dockerfile.vercel compila o React, copia dist para classpath:/static, gera o JAR e executa Java 21 como usuário não-root. A Vercel define $PORT; server.port=${PORT:8080} aceita esse valor. O contêiner é stateless: apenas o PostgreSQL persiste dados.
Detalhes: arquitetura, banco e segurança.
Docker não é obrigatório. Você precisa somente de:
- Git;
- Java 21;
- Node.js 24 (ou Node 22.22+);
- npm;
- banco PostgreSQL gratuito no Neon.
Siga a seção Criar PostgreSQL gratuito no Neon. Guarde URL, usuário e senha fora do Git.
Copie .env.example para .env. O .env está ignorado pelo Git. O Spring Boot não lê .env sozinho; os scripts run-local o carregam no processo sem imprimir valores.
Gere um segredo JWT local com 32 bytes ou mais:
# PowerShell
$bytes = New-Object byte[] 48
[Security.Cryptography.RandomNumberGenerator]::Fill($bytes)
[Convert]::ToBase64String($bytes)# Linux/macOS
openssl rand -base64 48Preencha:
SPRING_PROFILES_ACTIVE=dev
SPRING_DATASOURCE_URL=jdbc:postgresql://SEU-ENDPOINT-pooler.REGIAO.aws.neon.tech/neondb?sslmode=require
SPRING_DATASOURCE_USERNAME=SEU_USUARIO
SPRING_DATASOURCE_PASSWORD=SUA_SENHA
JWT_SECRET=SEGREDO_ALEATORIO_COM_32_BYTES_OU_MAIS
COOKIE_SECURE=false
SWAGGER_ENABLED=true.\scripts\run-local.ps1chmod +x backend/mvnw scripts/*.sh
./scripts/run-local.sh- Frontend: http://localhost:5173
- Backend: http://localhost:8080
- Health: http://localhost:8080/api/health
- Swagger: http://localhost:8080/swagger-ui/index.html
O Vite encaminha /api para http://localhost:8080.
PowerShell:
$env:SPRING_PROFILES_ACTIVE='dev'
$env:SPRING_DATASOURCE_URL='jdbc:postgresql://HOST-pooler/DB?sslmode=require'
$env:SPRING_DATASOURCE_USERNAME='USUARIO'
$env:SPRING_DATASOURCE_PASSWORD='SENHA'
$env:JWT_SECRET='SEGREDO_ALEATORIO_COM_32_BYTES_OU_MAIS'
cd backend
.\mvnw.cmd spring-boot:runEm outro terminal:
cd frontend
npm ci
npm run devLinux/macOS:
export SPRING_PROFILES_ACTIVE=dev
export SPRING_DATASOURCE_URL='jdbc:postgresql://HOST-pooler/DB?sslmode=require'
export SPRING_DATASOURCE_USERNAME='USUARIO'
export SPRING_DATASOURCE_PASSWORD='SENHA'
export JWT_SECRET='SEGREDO_ALEATORIO_COM_32_BYTES_OU_MAIS'
cd backend && ./mvnw spring-boot:runEm outro terminal: cd frontend && npm ci && npm run dev.
Testes unitários não exigem Docker:
cd backend
.\mvnw.cmd test
cd ..\frontend
npm ci
npm test
npm run buildLinux/macOS usa ./mvnw test. Integração usa PostgreSQL real em Testcontainers e é separada:
cd backend
./mvnw -Pintegration-test verifyEsse último comando requer Docker e é executado pelo GitHub Actions. A falta de Docker local não impede testes unitários, desenvolvimento ou deploy.
Com backend e banco ativos, execute o smoke test completo:
.\scripts\smoke-test.ps1./scripts/smoke-test.shEle valida health, dois cadastros, PIN, chave, resolução, transferência de R$ 1.000,00, saldos R$ 49.000,00/R$ 51.000,00, extratos, comprovante e PDF.
Somente para contribuidores que já tenham Docker:
docker compose up --buildA aplicação unificada fica em http://localhost:8080. O Compose usa PostgreSQL local e credenciais exclusivamente de desenvolvimento. Não use os valores padrão em ambiente público.
Validar a mesma imagem usada na Vercel:
docker build -f Dockerfile.vercel -t vbank-sandbox .Você não precisa instalar Docker para publicar: GitHub Actions valida a imagem e a Vercel a constrói remotamente.
- Acesse Neon e crie uma conta.
- Crie um projeto no plano Free; não adicione pagamento e não selecione plano pago.
- Escolha uma região próxima da região de execução, quando disponível.
- No projeto, abra Connect.
- Ative Pooled connection. O host normalmente contém
-pooler. - Mantenha
sslmode=require. - Copie a connection string para um gerenciador de senhas; nunca a cole em issue, commit ou log.
- Separe host/banco, usuário e senha. Exemplo apenas com placeholders:
PostgreSQL: postgresql://USUARIO:SENHA@HOST-pooler/DB?sslmode=require
JDBC: jdbc:postgresql://HOST-pooler/DB?sslmode=require
Usuário: USUARIO
Senha: SENHA
- Use a JDBC em
SPRING_DATASOURCE_URLe as outras partes nas variáveis separadas. - Flyway cria o schema automaticamente ao iniciar um banco vazio.
Alternativa na Vercel: depois de importar o repositório, instale Neon pelo Marketplace da Vercel. Confirme que o recurso criado é Free e copie/mapeie os valores fornecidos para as três variáveis SPRING_DATASOURCE_*. Não use DATABASE_URL diretamente como JDBC sem adaptar o prefixo.
Documentação oficial: conexão pooled e preços atuais.
- Crie um repositório público vazio no GitHub.
- Não marque a criação automática de README,
.gitignoreou licença; estes arquivos já existem. - Antes do commit, confirme que
.envnão aparece emgit status. - Na raiz:
Antes de publicar, substitua SEU_USUARIO pelo seu usuário GitHub em frontend/src/pages/LandingPage.tsx e .github/ISSUE_TEMPLATE/config.yml.
git init
git add .
git status
git commit -m "feat: initial VBank Sandbox"
git branch -M main
git remote add origin ENDERECO_DO_REPOSITORIO
git push -u origin mainO workflow usa somente ubuntu-latest, permissões de leitura e runners padrão. Em repositório público, runners padrão são gratuitos segundo a documentação do GitHub Actions. Larger runners continuam proibidos.
- Envie o projeto ao GitHub.
- Entre na Vercel e mantenha o plano Hobby.
- Clique em Add New → Project e importe o repositório.
- Use a raiz do repositório como Root Directory.
- A Vercel detecta
Dockerfile.vercel, constrói a imagem OCI e encaminha o tráfego ao contêiner. - Instale/crie o Neon Free antes do primeiro build operacional.
- Em Settings → Environment Variables, cadastre as variáveis abaixo no ambiente Production. Não exponha valores no frontend.
- Faça o deploy.
- Aguarde Flyway aplicar migrations.
- Acesse
https://SEU-PROJETO.vercel.app/api/healthe confiraUP. - Acesse a landing page e crie duas contas de teste.
- Se precisar de admin, habilite o bootstrap uma única vez; depois defina
ADMIN_BOOTSTRAP_ENABLED=falsee faça novo deploy.
A Vercel injeta $PORT; não fixe outra porta no painel. O Java mantém o processo em primeiro plano e encerra de forma graciosa ao receber SIGTERM.
Consulte Container Images, a explicação oficial sobre Docker deployments e o guia detalhado de deploy.
Obrigatórias em produção:
SPRING_PROFILES_ACTIVE=prod
SPRING_DATASOURCE_URL=jdbc:postgresql://HOST-pooler/DB?sslmode=require
SPRING_DATASOURCE_USERNAME=
SPRING_DATASOURCE_PASSWORD=
JWT_SECRET=
JWT_ACCESS_EXPIRATION_MINUTES=15
JWT_REFRESH_EXPIRATION_DAYS=7
COOKIE_SECURE=true
COOKIE_DOMAIN=
DB_POOL_SIZE=3
DB_MINIMUM_IDLE=0
SWAGGER_ENABLED=false
APP_VERSION=1.0.0
ADMIN_BOOTSTRAP_ENABLED=false
Somente no primeiro bootstrap administrativo, se desejado:
ADMIN_BOOTSTRAP_ENABLED=true
ADMIN_BOOTSTRAP_NAME=
ADMIN_BOOTSTRAP_EMAIL=
ADMIN_BOOTSTRAP_USERNAME=
ADMIN_BOOTSTRAP_PASSWORD=
ADMIN_BOOTSTRAP_PIN=
Não use credencial fixa. A aplicação falha com mensagem objetiva se JWT/banco estiverem ausentes, JWT for curto, cookie estiver inseguro em produção ou JDBC de produção não exigir SSL.
- Push em
main: GitHub Actions testa; a integração Git/Vercel cria o deploy de produção. - Pull request/branch: Vercel pode criar preview. Não dê a previews acesso ao banco de produção; use variáveis separadas ou desabilite previews com banco.
- Frontend e backend são sempre atualizados juntos.
- Flyway aplica migrations para frente. Faça alterações compatíveis e aditivas antes de remover colunas.
- Rollback de código pode usar um deployment anterior na Vercel, mas migration destrutiva exige restauração/ação manual.
- Neon e Vercel podem entrar em scale-to-zero; a primeira requisição pode sofrer cold start.
- CPU, memória, duração, armazenamento, transferência e conexões têm cotas.
- O projeto usa Hikari pequeno (
3/0) e paginação para reduzir consumo. - Ao atingir a cota, aguarde renovação, reduza uso ou deixe a aplicação indisponível; não ative cobrança.
- O projeto não foi projetado para alta escala, SLA, dinheiro real ou uso comercial no Hobby.
- Limites e preços mudam; consulte FREE-TIER.md.
| Sintoma | Verificação |
|---|---|
| Docker não está instalado | Use o fluxo principal sem Docker; Vercel/Actions constroem remotamente. |
java -version não mostra 21 |
Instale/selecione JDK 21 e reabra o terminal. |
| Node/npm incorreto | Use Node 24 e execute npm ci novamente. |
| Porta 8080/5173 ocupada | Encerre o processo anterior; não altere o proxy sem ajustar ambos. |
| Falha JDBC | Use prefixo jdbc:postgresql://, host pooled, banco correto e sslmode=require. |
JWT_SECRET ausente/curto |
Gere pelo menos 32 bytes aleatórios. |
| Flyway falha | Não edite migration já aplicada; crie uma nova versão. Confira permissões do usuário. |
| 404 ao atualizar rota React | Confirme que frontend/dist foi copiado ao JAR; no Docker isso é automático. |
| Cookie não volta | Local usa COOKIE_SECURE=false; produção exige true e mesma origem. |
Health DOWN |
Neon pode estar retomando; aguarde e tente novamente. Nenhuma transferência é presumida como concluída. |
$PORT |
Não configure manualmente na Vercel; a plataforma injeta. |
| GitHub Actions falha em integração | Veja logs do Testcontainers e confirme uso de ubuntu-latest. |
| Build Docker remoto falha | Confira lockfile, caminhos na raiz e logs de build da Vercel. |
| Cota gratuita atingida | Verifique consumo nos painéis e aguarde renovação; não habilite pagamento. |
backend/ Spring Boot, Flyway, Maven Wrapper, testes
frontend/ React/Vite, CSS, Vitest, package-lock
docs/ arquitetura, banco, deploy, segurança e custo
scripts/ execução local e smoke test
.github/ templates e CI
Dockerfile* imagens unificadas local/Vercel
Leia CONTRIBUTING.md, SECURITY.md e CODE_OF_CONDUCT.md. Não abra issue pública com vulnerabilidade explorável ou qualquer credencial.
MIT. Bibliotecas continuam sob suas respectivas licenças abertas.