Monitore SLA, produtividade e risco operacional da sua TI em tempo real.
InfraPulse é uma plataforma SaaS para gestão operacional de suporte de TI, pensada para times que precisam escalar com previsibilidade, governança e isolamento por empresa sem perder controle técnico sobre SLA, fila e resolução.
- Multi-tenant explícito por
companyIdem todas as rotas protegidas - JWT carrega
sub,email,roleecompanyId - RBAC aplicado nos pontos sensíveis do produto
- Fluxo operacional orientado a abertura, SLA, resolução e auditoria
- Operação orientada por indicadores: SLA, fila, criticidade e throughput em tempo real
- Redução de risco com alertas acionáveis e priorização por impacto operacional
- Arquitetura SaaS multiempresa com isolamento de dados por tenant (
companyId) - Gestão de crescimento com planos, limites e regras de assinatura por empresa
- Onboarding rápido com criação de empresa, administrador e sessão autenticada no mesmo fluxo
- Onboarding self-service de empresa e administrador
- Autenticação JWT com payload do tenant e perfis (
ADMIN,GESTOR,ANALISTA) - Multi-tenant real com middleware de isolamento por empresa
- Dashboard executivo com KPIs de SLA e risco
- Dashboard operacional com fila por técnico
- Gestão de assinatura por plano com limites por empresa
- RBAC documentado para operações sensíveis
- Importação de CSV/Excel para carga de chamados
- Alertas de risco e relatórios com exportação CSV
O tenant é resolvido a partir do JWT e usado como chave obrigatória em consultas protegidas. Isso evita vazamento entre empresas e mantém isolamento real de dados no backend.
POST /api/auth/signup-companycria empresa em trial, usuário administrador e sessão autenticadaPOST /api/auth/loginvalida usuário, empresa ativa e status da assinatura antes de emitir o token- O token retorna
companyId,roleesub, que são reutilizados nas rotas protegidas
O controle de acesso é explícito nos pontos de maior impacto operacional:
| Ação | Perfis permitidos | Endpoint |
|---|---|---|
| Criar usuário | ADMIN, GESTOR |
POST /api/users |
| Atualizar plano da empresa | ADMIN |
PATCH /api/companies/current/plan |
| Operar chamados e dashboards do tenant | usuário autenticado da empresa | rotas protegidas por JWT |
- O usuário abre o chamado com prioridade, categoria e setor.
- O sistema associa o chamado à empresa, calcula o SLA e grava os prazos de resposta e resolução.
- A fila operacional é organizada por técnico, com visão de sobrecarga e criticidade.
- O chamado segue por
ABERTO,EM_ANDAMENTO,PENDENTE, atéCONCLUIDOouCANCELADO. - Ao concluir, o sistema registra a resolução e recalcula o status de SLA como
OK,EM_RISCOouVIOLADO. - Toda mudança relevante pode ser auditada para governança e compliance.
Quer ver o fluxo completo em ambiente guiado? Solicitar demo via GitHub Issues e avalie como o InfraPulse organiza SLA, filas e governança operacional em um único painel.
curl -X POST http://localhost:3001/api/auth/signup-company \
-H "Content-Type: application/json" \
-d '{
"companyName": "Acme Support",
"adminName": "Maria Admin",
"adminEmail": "maria@acme.com",
"adminPassword": "SenhaForte123"
}'Resposta esperada (resumo):
{
"access_token": "<jwt>",
"user": {
"id": "...",
"email": "maria@acme.com",
"role": "ADMIN",
"companyId": "..."
}
}curl -X GET http://localhost:3001/api/companies/current \
-H "Authorization: Bearer <jwt>"curl -X POST http://localhost:3001/api/tickets \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"title": "Erro no checkout",
"description": "Pagamento retorna timeout",
"priority": "HIGH",
"status": "OPEN"
}'- Acesse
/signupno frontend. - Cadastre empresa e administrador.
- O sistema cria automaticamente:
- empresa em
TRIAL(14 dias) - usuário administrador
- sessão autenticada
- empresa em
- Acompanhe consumo e faça upgrade em
/assinatura.
| Plano | Usuários ativos | Chamados/mês |
|---|---|---|
TRIAL |
5 | 200 |
STARTER |
15 | 2.000 |
GROWTH |
50 | 10.000 |
ENTERPRISE |
500 | 100.000 |
POST /api/auth/loginPOST /api/auth/signup-company
GET /api/companies/currentPATCH /api/companies/current/plan(somenteADMIN)
GET /api/ticketsGET /api/tickets/queueGET /api/tickets/:idPOST /api/ticketsPUT /api/tickets/:idPOST /api/tickets/recalculate-sla
GET /api/metrics/sla- Métricas agregadas de SLAGET /api/teams/performance- Performance de cada analistaGET /api/incidents- Incidentes críticos e em risco (query param:limit)
- Criação de usuário respeita limite de assentos do plano
- Criação de chamado respeita cota mensal do plano
- Login bloqueia empresa inativa, trial expirado e assinatura cancelada/inadimplente
- Busca/atualização de chamados com isolamento por
companyId
| Camada | Tecnologia |
|---|---|
| Frontend | Next.js 14 + TypeScript |
| Estilo | Tailwind CSS + shadcn/ui |
| Backend | NestJS |
| Banco | Firebase Cloud Firestore |
| ORM | Prisma |
| Auth | JWT |
| Infra | Vercel (frontend) + Cloud Run (backend) |
Observacao: o acesso ao Firestore no backend ja esta preparado via
firebase-admin. Partes legadas do projeto ainda utilizam Prisma durante a transicao incremental.
- Deploy do projeto Next.js a partir da pasta
frontend - Variavel obrigatoria:
NEXT_PUBLIC_API_URLapontando para a URL publica do backend no Cloud Run
- Container de producao com
npm run start:prode porta dinamica (PORT) - Endpoint de validacao de conectividade Firestore:
GET /api/infra/firestore/ping - Acesso ao banco via
firebase-admincom service account do runtime (ou credenciais por env)
InfraPulse implementa isolamento real de dados por empresa em toda a plataforma:
- companyId obrigatório: Todos os queries ao banco incluem isolamento por
companyId - Middleware de isolamento: Força isolamento em rotas protegidas
- JWT com companyId: Cada token de usuário contém identificador da empresa
- Erro em tempo de compilação: Qualquer query sem isolamento falha na compilação TypeScript
// ❌ INSEGURO (não compila):
const tickets = await prisma.ticket.findMany({
where: companyId ? { companyId } : {} // Retorna TUDO se undefined
});
// ✅ SEGURO (padrão InfraPulse):
async findAll(filters: FilterTicketsDto, companyId: string) {
// companyId é OBRIGATÓRIO, não opcional
const where: any = { companyId }; // Sempre isolado
// ... resto da lógica
}Todos os serviços abaixo garantem isolamento:
| Serviço | Endpoints | Isolamento |
|---|---|---|
| Tickets | GET /api/tickets, POST, PUT | ✅ companyId obrigatório |
| Dashboard | GET /api/dashboard/executive, operational | ✅ companyId obrigatório |
| Usuários | GET /api/users, /users/technicians | ✅ companyId obrigatório |
| Relatórios | GET /api/reports/tickets | ✅ companyId obrigatório |
| Alertas | GET /api/alerts | ✅ companyId obrigatório |
Alguns endpoints agregam dados de TODA a plataforma (sem isolamento):
| Endpoint | Propósito | Dados |
|---|---|---|
| GET /api/metrics/sla | Métricas globais de SLA | Todas as empresas |
| GET /api/teams/performance | Performance de todos analistas | Todas as empresas |
| GET /api/incidents | Incidentes críticos globais | Todas as empresas |
InfraPulse implementa rastreamento automático de ações para conformidade regulatória:
Todas as ações são registradas automaticamente:
| Ação | Entidade | Capturado |
|---|---|---|
| CREATE | Ticket, Usuário | Dados criados, quem criou, quando, IP |
| UPDATE | Ticket, Usuário | Campos alterados (before/after), quem, quando, IP |
| DELETE | Ticket, Usuário | Dados deletados, quem deletou, quando, IP |
| LOGIN | Autenticação | Usuário, empresa, IP, User-Agent, horário |
| LOGOUT | Autenticação | Usuário, empresa, IP, horário |
| ASSIGN | Ticket | Técnico atribuído, quem atribuiu, quando |
| CLOSE | Ticket | Quem fechou, quando, como |
Cada log de auditoria registra:
{
"id": "uuid",
"action": "CREATE | UPDATE | DELETE | LOGIN | LOGOUT | EXPORT | IMPORT | ASSIGN | REASSIGN | CLOSE | REOPEN",
"entity": "TICKET | USER | COMPANY | SLARULE | IMPORTBATCH | AUTH",
"entityId": "id-do-recurso",
"companyId": "isolamento-multi-tenant",
"userId": "quem-fez-a-acao",
"changes": {
"before": { "status": "ABERTO" },
"after": { "status": "CONCLUIDO" }
},
"description": "Ticket #123 atualizado",
"ipAddress": "192.168.1.100",
"userAgent": "Mozilla/5.0...",
"createdAt": "2026-04-19T22:35:41.179Z"
}- Isolamento: Cada empresa vê apenas seus próprios logs
- Direito ao esquecimento: Logs antigos (>2 anos) podem ser deletados
- Rastreabilidade: IP e User-Agent capturados para investigações
- Minimização: Apenas dados necessários são registrados
curl -X GET http://localhost:3001/api/audit/TICKET/ticket-id-123 \
-H "Authorization: Bearer <jwt>"Resposta:
[
{
"id": "audit-log-123",
"action": "UPDATE",
"entity": "TICKET",
"entityId": "ticket-id-123",
"description": "Ticket atualizado",
"changes": {
"priority": { "before": "ALTA", "after": "CRITICA" }
},
"user": {
"id": "user-123",
"name": "Maria Admin",
"email": "maria@infrapulse.com"
},
"createdAt": "2026-04-19T22:35:41.179Z"
}
]# Últimos 100 logs
curl -X GET http://localhost:3001/api/audit/company/logs \
-H "Authorization: Bearer <jwt>"
# Filtrar por ação
curl -X GET "http://localhost:3001/api/audit/company/logs?action=UPDATE&entity=TICKET" \
-H "Authorization: Bearer <jwt>"
# Últimos 7 dias
curl -X GET "http://localhost:3001/api/audit/company/logs?days=7" \
-H "Authorization: Bearer <jwt>"curl -X GET "http://localhost:3001/api/audit/export/compliance?startDate=2026-01-01&endDate=2026-04-19" \
-H "Authorization: Bearer <jwt>"Retorna JSON com todos os logs do período para auditorias internas e externas.
A auditoria suporta requisitos de governança:
| Requisito ISO | Suporte | Como |
|---|---|---|
| A.12.4.1 - Event logging | ✅ | Todos os eventos capturados em AuditLog |
| A.12.4.3 - Protection of audit info | ✅ | Isolamento por companyId + apenas ADMIN acessa |
| A.13.1.3 - Segregation of duties | ✅ | Roles (ADMIN, GESTOR, ANALISTA) com permissões |
| A.14.2.1 - Change management | ✅ | Rastreamento before/after de mudanças |
| A.14.2.5 - Access restrictions | ✅ | Middleware obriga autenticação + isolamento |
InfraPulse monitora proativamente a operação e gera alertas contextualizados para:
| Alerta | Severidade | Ação |
|---|---|---|
| SLA em Risco | Ticket com 70%+ do SLA consumido | |
| SLA Violado | 🔴 CRÍTICO | Ticket ultrapassou deadline |
| Equipe Sobrecarregada | Técnico com >10 tickets abertos | |
| Ticket Crítico Não Atribuído | 🔴 CRÍTICO | Prioridade CRITICA sem responsável |
| Fila Crítica | 🔴 CRÍTICO / 🛑 BLOQUEADOR | >20 tickets aguardando atendimento |
INFO - Informativo (não requer ação)
AVISO - Requer atenção (70-80% SLA consumido)
CRITICO - Ação necessária (80%+ SLA ou equipe overload)
BLOQUEADOR - Operação comprometida (SLA violado ou fila >30)
curl -X GET http://localhost:3001/api/alerts/detect \
-H "Authorization: Bearer <jwt>"curl -X GET http://localhost:3001/api/alerts/dashboard \
-H "Authorization: Bearer <jwt>"curl -X PUT "http://localhost:3001/api/alerts/alert-123/acknowledge" \
-H "Authorization: Bearer <jwt>"curl -X PUT "http://localhost:3001/api/alerts/alert-123/resolve" \
-H "Authorization: Bearer <jwt>"Para cumprir o direito ao esquecimento (LGPD Art. 17), execute:
# Via script
curl -X POST http://localhost:3001/api/audit/cleanup \
-H "Authorization: Bearer <admin-jwt>" \
-H "Content-Type: application/json" \
-d '{"daysOld": 730}' # Delete logs com >2 anosinfrapulse/
├── frontend/ # App Next.js
├── backend/ # API NestJS
├── docs/prints/ # Prints e imagens do README
├── docker-compose.yml
└── README.md
- Node.js 18+
- Conta Vercel (frontend)
- Projeto no Google Cloud com Cloud Run e Firestore habilitados
- Google Cloud SDK (
gcloud) para deploy do backend - npm ou yarn
- Root Directory:
frontend - Build Command:
npm run build - Install Command:
npm install - Variavel obrigatoria:
NEXT_PUBLIC_API_URL=https://SEU_BACKEND_CLOUD_RUN.run.appNo backend, configure as variaveis de ambiente e execute o deploy:
cd backend
gcloud run deploy infrapulse-backend \
--source . \
--region us-central1 \
--allow-unauthenticatedDepois do deploy, valide:
- Health Firestore:
GET /api/infra/firestore/ping - Swagger:
https://SEU_BACKEND_CLOUD_RUN.run.app/api/docs
Se quiser validar os fluxos antigos baseados em Prisma/PostgreSQL localmente, use o setup abaixo.
cd backend
cp .env.example .env
npm install
npm.cmd exec prisma db push
npm.cmd exec prisma generate
npm.cmd exec prisma db seed
npm run start:devcd frontend
cp .env.example .env.local
npm install
npm run dev| Senha | Perfil | |
|---|---|---|
admin@infrapulse.com |
admin123 | Admin |
gestor@infrapulse.com |
gestor123 | Gestor |
analista@infrapulse.com |
analista123 | Analista |
joao@infrapulse.com |
analista123 | Analista |
maria@infrapulse.com |
analista123 | Analista |
pedro@infrapulse.com |
analista123 | Analista |
juliana@infrapulse.com |
analista123 | Analista |
bruno@infrapulse.com |
analista123 | Analista |
Esta seed foi desenhada para demo executiva e gera automaticamente:
- 1200 chamados com status variados (
ABERTO,EM_ANDAMENTO,PENDENTE,CONCLUIDO,CANCELADO) - SLA misto (
OK,EM_RISCO,VIOLADO) - distribuição entre múltiplos analistas
- categorias e setores realistas para cenário hospitalar/operações
No ambiente de demo, a seed será carregada para entregar uma experiência de validação mais realista e guiada, com dados operacionais prontos para que qualquer testador consiga explorar, medir e validar rapidamente os fluxos de SLA, fila e resolução.
- Suba apenas o banco PostgreSQL:
docker compose up -d postgres- Valide se o host local responde em
localhost:5432:
Test-NetConnection -ComputerName localhost -Port 5432- Prepare e aplique o schema no banco:
cd backend
npm.cmd install
npm.cmd exec prisma db push
npm.cmd exec prisma generate- Execute a seed:
npm.cmd exec prisma db seed- Resultado esperado no terminal:
Seed concluido com sucesso!
Chamados gerados: 1200
- A seed recria os chamados da empresa demo (
infrapulse-demo) a cada execução, evitando duplicação infinita. - Se preferir ambiente 100% local sem Docker, garanta que o PostgreSQL esteja rodando em
localhost:5432antes de rodar o seed. - Em ambientes sem bloqueio de política do PowerShell,
npx prisma ...também funciona.
A InfraPulse expõe três endpoints públicos para monitoramento em tempo real da plataforma:
Retorna métricas agregadas de SLA de toda a plataforma.
curl -X GET http://localhost:3001/api/metrics/slaResposta exemplo:
{
"total": 1200,
"ok": 952,
"emRisco": 152,
"violado": 96,
"percentualOk": 79,
"percentualRisco": 13,
"percentualViolado": 8,
"tempoMedioAtendimento": 13.6,
"timestamp": "2026-04-19T22:35:41.179Z"
}Retorna performance de cada analista com tickets atribuídos.
curl -X GET http://localhost:3001/api/teams/performanceResposta exemplo:
{
"teams": [
{
"id": "3d87c146-953c-423e-8608-db837a008ac5",
"name": "Ana Martins",
"email": "analista@infrapulse.com",
"totalTickets": 333,
"concluidos": 84,
"emAberto": 249,
"slaOk": 286,
"emRisco": 29,
"violado": 18,
"taxaSlaCompliance": 86,
"tempoMedioResolucao": 11.3,
"ticketsCriticos": 63
}
],
"timestamp": "2026-04-19T22:35:41.179Z"
}Retorna incidentes críticos (prioridade CRÍTICA) e em risco de SLA (status EM_RISCO ou VIOLADO).
Query parameters:
limit(opcional, padrão 50): número máximo de incidentes
curl -X GET "http://localhost:3001/api/incidents?limit=10"Resposta exemplo:
{
"total": 424,
"incidents": [
{
"id": "a3f0d1f9-5822-4579-afe3-a49f32207a69",
"title": "Servidor de arquivos com pouco espaco #0699",
"description": "Volume de rede atingiu nivel critico e a operacao precisa de limpeza imediata.",
"status": "ABERTO",
"priority": "CRITICA",
"slaStatus": "OK",
"daysOpen": 0,
"company": "InfraPulse Demo",
"assignedTo": "Pedro Costa",
"openedAt": "2026-04-19T21:58:07.288Z",
"resolvedAt": null
}
],
"timestamp": "2026-04-19T22:35:41.179Z"
}DATABASE_URL=postgresql://infrapulse:infrapulse@localhost:5432/infrapulse
DATA_PROVIDER=firebase
JWT_SECRET=sua_chave_jwt_super_secreta
JWT_EXPIRES_IN=7d
PORT=3001
FIREBASE_PROJECT_ID=seu_projeto_firebase
FIREBASE_CLIENT_EMAIL=firebase-adminsdk-xxxx@seu_projeto.iam.gserviceaccount.com
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\\nSUA_CHAVE\\n-----END PRIVATE KEY-----\\n"No Cloud Run, quando a service account da aplicacao tiver permissao no Firestore,
FIREBASE_CLIENT_EMAIL e FIREBASE_PRIVATE_KEY podem ser omitidas (o firebase-admin
usa as credenciais padrao do runtime).
NEXT_PUBLIC_API_URL=http://localhost:3001cd backend
npm.cmd install
npm.cmd test -- --runInBand
npm.cmd run test:covcd frontend
npm.cmd install
npm.cmd run test:run
npm.cmd run test:coverage- Relatório de cobertura backend:
backend/coverage/ - Relatório de cobertura frontend:
frontend/coverage/
MIT