Web (Next.js 15) + API REST (NestJS 11) + Mobile (Expo SDK 54) + PostgreSQL 16/PostGIS + Redis. Multi-tenant, RBAC, cadeia SHA-256 e dossiês PDF. Zero licenciamento, deploy via Docker Compose.
Tudo abaixo é mensurado direto no banco PostgreSQL e no log do Nest. Não há mock — são registros reais semeados via prisma/seed.ts e prisma/seed_legal.ts.
App Router, Server Components, Turbopack. 42 páginas em 7 portais (público, admin, ong, clínico, jurídico, inteligência, auth). Tailwind 4 com design tokens GDF.
22 controllers, 139 endpoints documentados via Swagger. JWT HS256 + refresh rotativo. Multi-tenant via AsyncLocalStorage. SWC compile sub-segundo.
App MEL Campo. iOS + Android via Expo Go ou EAS Build, e versão web (Expo Web) bundlada via Metro. WatermelonDB offline-first (nativo) com fallback API (web).
23 modelos Prisma. Indexes compostos (tenantId, status). Geo via PostGIS para lat/long e mapa de calor. 6 migrations aplicadas.
Cache de sessão, rate limiting, filas (geração de PDF, envio de email/WhatsApp). BullMQ workers podem escalar horizontalmente.
Stack completa em docker/docker-compose.yml: postgres + redis + healthchecks. Reproduzível em qualquer ambiente. Pronta para deploy on-premise no datacenter do GDF.
Plataforma completa rodando em produção na infraestrutura Hostinger + Dokploy. URLs fixas, com SSL Let's Encrypt automático, sem dependência de túneis temporários.
Apresentação pública do projeto · roadmap, perfis, documentação técnica.
https://info.projetomel.com.br
Portal logado · todas as áreas administrativas, jurídicas e públicas.
https://projetomel.com.br
Backend completo. Auth JWT Bearer. Base path /api/v1.
https://api.projetomel.com.br/api/v1
Via Expo Go (App Store / Google Play) · canal production.
@phil.antunes/mel-campo
| Senha | Nome | Papel efetivo | Onde testar | |
|---|---|---|---|---|
admin@projetomel.com.br |
admin123 |
Administrador MEL | Admin Global | /credenciais-demo · /tenants · /audit · /whatsapp · /expo |
governo@gdf.gov.br |
senha123 |
Carlos Lima | Operador | Tudo do admin exceto remover/criar Admins |
gestora@patinhas.org.br |
senha123 |
Maria Santos | Gestora ONG | /patinhas-cerrado/dashboard · doações com saldo + aprovar |
voluntario@gmail.com |
senha123 |
João Oliveira | Voluntário | App MEL Campo (mobile/web) · registro de resgates |
vet@clinica.com.br |
senha123 |
Dra. Ana Pereira | Veterinária | /patinhas-cerrado/prontuarios · /vacinas · /laudos |
promotor@mpdft.mp.br |
senha123 |
Dra. Beatriz Costa | Promotor MP | /evidencias · /custodia · /dossies · /verificacao |
policia@pmdf.gov.br |
senha123 |
Sgt. Ricardo Alves | Polícia Ambiental | /dashboard · /mapa · /hotspots |
conselho@gdf.gov.br |
senha123 |
Fernanda Rocha | Conselheira | /dashboard cross-tenant (somente leitura) |
doador@gmail.com |
senha123 |
Pedro Mendes | Doador | /patinhas-cerrado/doar · transparência pública |
luizbueno463@gmail.com |
— | Bueno | Admin Global | 2º admin do sistema |
patinhas-cerrado · CNPJ 12.345.678/0001-01
sos-animal-df · CNPJ 23.456.789/0001-02
anjos-de-patas · CNPJ 34.567.890/0001-03
cerrado-vivo · CNPJ 45.678.901/0001-04
amigos-dos-bichos · CNPJ 56.789.012/0001-05
protecao-animal-bsb · CNPJ 67.890.123/0001-06
Cada controller tem auth JWT (exceto endpoints públicos marcados com @Public), guards de RBAC e contexto de tenant injetado via interceptor.
18 endpoints — gestão de tenants, usuários globais, audit log, expo-tunnel dinâmico.
10 endpoints — list, stats, balance, approve, reject, applications, webhook MercadoPago.
9 endpoints — evidence, custody, dossier (get + generate + download), verify chain, integrity blocks.
9 endpoints — CRUD de ONGs, listagem pública, branding, slug routing.
9 endpoints — CRUD com fotos georreferenciadas, histórico clínico, status, status público.
9 endpoints — state machine de 8 estados, transições com hash, timeline.
8 endpoints — dashboard cross-tenant da Conselheira, KPIs agregados, leitura pura.
8 endpoints — perfil próprio (/me), update, password change.
8 endpoints — login, register, register-ong, refresh, logout, me.
7 endpoints — membership N:N usuário↔ONG, aprovação de voluntários.
6 endpoints — stats públicas, timeline mensal, mapa anonimizado, lista de ONGs.
6 endpoints — prontuários (22), vacinações (29), histórico imutável.
5 endpoints — list, markAsRead, broadcast. 35 notificações ativas.
5 endpoints — SEPAN report, MercadoPago preference, sync externo.
5 endpoints — lares temporários, capacidade, espécies aceitas. 4 cadastros.
4 endpoints — Baileys session, QR code, send message.
4 endpoints — heatmap PostGIS, hotspots, regiões administrativas.
4 endpoints — triagem, período de teste, finalização. 12 adoções concluídas.
2 endpoints — pull/push para mobile offline (WatermelonDB).
1 endpoint — upload multipart com sharp + path traversal protection.
1 endpoint — verifica DB + Redis + retorna timestamps.
1 endpoint — list audit logs (filtros por user, action, entity, IP). 28 logs.
Schema relacional normalizado em PostgreSQL 16 + PostGIS. Todos os modelos têm tenantId (UUID) para isolamento multi-tenant via interceptor de contexto.
TenantONGs cadastradas. CNPJ, slug único, cor primária, descrição. 6 registros.
Userbcrypt 12 rounds. GlobalRole (ADMIN/OPERATOR/USER). 10 registros.
UserTenantMembership N:M com TenantRole (9 papéis).
Animal · AnimalPhotoFoto com EXIF/GPS, hash de integridade. 59 animais.
Case · CaseAnimalState machine de 8 estados. 48 casos (36 abertos).
CaseTransition · CaseTaskTransições com hash. Tasks atribuídas a usuários.
MedicalRecordDiagnóstico, tratamento, prescrição. 22 prontuários.
VaccinationVacinação com lote, data, próxima dose. 29 registros.
AdoptionTriagem → trial → completed. 12 concluídas.
FosterHomeLares temporários. Capacidade, espécies. 4 cadastros.
EvidencefileHash + integrityHash + prevHash. 199 registros.
CustodyRecordCadeia de custódia. 144 transferências.
DossierPDF gerado por pdfkit. 36 PDFs em disco.
IntegrityBlockBlockchain lógico SHA-256. 412 blocos.
DonationPENDING/APPROVED/REJECTED/REFUNDED. 79 doações.
DonationApplicationPrestação de contas (gastos por categoria).
BankAccountConta bancária por ONG. PIX, banco, agência.
NotificationIn-app, email, WhatsApp, push. 35 ativas.
AuditLog100% mutações com IP/UA/oldValue/newValue. 28 logs.
RefreshTokenSHA-256 hashed, rotativo, expira em 7d.
-- Conta o que está semeado SELECT (SELECT COUNT(*) FROM users) AS users, -- 10 (SELECT COUNT(*) FROM tenants) AS tenants, -- 6 (SELECT COUNT(*) FROM animals) AS animals, -- 59 (SELECT COUNT(*) FROM cases) AS cases, -- 48 (SELECT COUNT(*) FROM evidences) AS evidences, -- 199 (SELECT COUNT(*) FROM custody_records) AS custody, -- 144 (SELECT COUNT(*) FROM dossiers) AS dossiers, -- 36 (SELECT COUNT(*) FROM integrity_blocks) AS integrity, -- 412 (SELECT COUNT(*) FROM donations) AS donations; -- 79
Arquitetura simples, sem microservices prematuros. Fácil de entender, deployar e auditar. Escalabilidade horizontal via réplicas + Redis cluster + PG read replicas.
O TenantInterceptor resolve tenantId a partir do header x-tenant-slug ou JWT, e armazena no contexto async. Decorators @TenantId() e @TenantSlug() injetam onde precisar. Queries Prisma sempre filtram por tenantId.
Decorator @Roles('ADMIN','ONG_MANAGER') em cada handler. RolesGuard verifica o JWT (globalRole) e o tenant context (tenantRole). 403 retornado se não bate.
AuditInterceptor captura method+path+oldValue+newValue+IP+userAgent em toda mutação (POST/PUT/PATCH/DELETE) e grava em audit_logs. Não precisa código manual.
Toda operação legal cria um IntegrityBlock com hash do bloco anterior. Verificação por entityType (Evidence/CustodyRecord/Dossier) detecta adulteração. Ver tab "Integridade".
App nativo usa WatermelonDB (SQLite) com schema próprio. Sync engine pull/push via POST /sync resolve conflitos last-write-wins por updated_at.
100 req/60s global por IP via @nestjs/throttler. Helmet com HSTS, CSP, X-Frame-Options, X-Content-Type-Options. CORS configurável por env.
Replica exatamente o algoritmo do IntegrityService em produção. Cada bloco encadeia ao anterior — adulteração de qualquer byte quebra a verificação.
Implementada em apps/api/src/modules/legal/integrity.service.ts:
function computeHash( sequence: number, entityType: string, entityId: string, payload: unknown, prevHash: string | null, timestamp: Date ): string { // Keys do payload são ordenadas alfabeticamente (determinístico) const sorted = JSON.stringify(sortObjectKeys(payload)); const data = [ String(sequence), entityType, entityId, sorted, prevHash ?? '', timestamp.toISOString() ].join('|'); return createHash('sha256').update(data).digest('hex'); }
# 1. Login TOKEN=$(curl -sX POST "https://api/auth/login" \ -H "Content-Type: application/json" \ -d '{"email":"promotor@mpdft.mp.br","password":"senha123"}' \ | jq -r .accessToken) # 2. Verificar caso curl -H "Authorization: Bearer $TOKEN" \ -H "x-tenant-slug: amigos-dos-bichos" \ "https://api/legal/cases/0de9a76b.../verify" | jq # Resposta: { "allValid": true, "chains": { "evidence": { "valid": true }, "custody": { "valid": true }, "dossier": { "valid": true } }, "entityVerifications": [ { "entityId": "e07e9fd5-...", "valid": true, "blockCount": 1 }, ... ] }
# Stream do PDF gerado por pdfkit curl -H "Authorization: Bearer $TOKEN" \ -H "x-tenant-slug: amigos-dos-bichos" \ "https://api/legal/cases/<id>/dossier/download" \ -o dossie.pdf # Resposta: application/pdf · 5537 bytes · 2 páginas # Conteúdo: caso, evidências, custódia, verificação SHA-256
Sem dependência de vendor proprietário. Pronta para deploy on-premise no datacenter do GDF ou em nuvem soberana.
v11 · API backend modular
v15.5 · App Router + RSC
SDK 54 · iOS+Android+Web
v19.1 · concurrent rendering
v0.81 · Hermes engine
v16 · com PostGIS 3.4
v6.19 · 23 modelos
v7 · cache + filas
v5 · jobs assíncronos
v6 · strict + SWC
v4 · @theme tokens
SVG inline open source
deploy reproduzível
15min + refresh 7d
12 rounds
geração de dossiês
processing de imagens
logs estruturados
security headers HTTP
SQLite offline mobile
mapas com OSM
gráficos React
WhatsApp via web
PIX + checkout
Toda interação importante na plataforma dispara uma notificação real — email transacional via SMTP, WhatsApp via API oficial e push no aplicativo. Templates versionados em código, prontos para auditoria.
A doadora Mariana recebe duas mensagens reais: a primeira ao confirmar o pagamento, a segunda quando a ONG efetivamente aplica o valor. Mesmo padrão para resgates, casos jurídicos, aprovações de ONG e atribuição de responsável.
Cada card mostra a mensagem real disparada — alterne entre canais.
Aderência ao arcabouço jurídico brasileiro de proteção de dados, transparência e bem-estar animal. Não é "compliance posterior" — está no DNA da arquitetura.
@Roles() em cada handlerGET /admin/audit-logs/legal/.../verifyDELETE /users/meAnonimização, audit, consentimento, direito ao esquecimento.
Portal de transparência ativa em /transparencia sem login.
Cadeia de custódia digital para denúncias ao MP.
Apoio à lei de aumento de penas para maus-tratos.
Governança de dados · isolamento multi-tenant.
Contraste 4.5:1 · navegação por teclado · semantic HTML.