Nicchon.
Todos os projetos
SistemaEm produção· 2026

KTask

Gestão de tarefas multi-tenant pra estúdios criativos — cards, aprovações de cliente, automações e notificações WhatsApp.

Capa do projeto KTask

Sobre

Sistema multi-tenant que construí pra resolver um problema concreto: substituir uma ferramenta SaaS cara de gestão de tarefas que uma agência criativa usava. A diferença pro Trello/Asana clássicos é que o KTask resolve o triângulo estúdio + cliente + fornecedor — cliente aprova entregas via token sem criar conta, e tudo notifica no WhatsApp via Evolution API. Inspirado em Ummense, com diferenciais arquiteturais (CardPresence multi-fluxo, CardStatus ortogonal). Aproximadamente 362 commits, 51 migrations Prisma, ~30 módulos NestJS. Em produção em VPS Hetzner via Docker.

Stack

  • NestJS
  • Prisma 6
  • PostgreSQL
  • Redis
  • Next.js
  • React
  • TypeScript
  • Socket.IO
  • BullMQ
  • Evolution API
  • Docker (Hetzner VPS)
  • GitHub Actions

Decisões

  • Engine de automações própria em automations.engine.ts (1685 linhas) com 10 triggers + 18 actions implementadas, anti-loop por chainDepth=5, conditions AND com 3 fields (tags / lead / dueDate), scheduler @nestjs/schedule separado pra triggers temporais com idempotência por janela.
  • Aprovação externa por token: cliente recebe link, abre página sem cadastro, vê card rico (descrição TipTap + anexos com presigned URL + checklists + comments + activities), aprova/reprova com undo de 5 minutos, bloqueio anti-pisar-em-pisada via query Activity.automationRunId IS NULL.
  • CardPresence: card existe em N boards com estado independente via PK composta (cardId, boardId) — multi-fluxo emergente, diferencial vs Trello/clones.
  • CardStatus ortogonal à coluna (ACTIVE/COMPLETED/WAITING/CANCELED) — espelha comportamento do Ummense, não do Trello.
  • Fallback silencioso documentado pra Evolution API: helper retorna boolean, nunca propaga exceção; engine marca run como SUCCESS com delivered: false mesmo se WhatsApp caiu. Cadeia de automação nunca trava por instância caída — decisão consciente comentada no código.
  • Multi-tenancy via tenant_id em todas as tabelas + TenantGuard NestJS — começa simples e escala até alguns milhares de orgs sem refactor.
  • JWT access + refresh em cookies httpOnly + SameSite=Strict — sem session storage. Convite via signupFromInvite com mailer + Promise.allSettled (não bloqueia se um destinatário falhar).
  • Importer Ummense rodou 10.617 cards em produção com wizard de mapeamento, OrgImportMapping persistido pra próximos imports, idempotência por shortCode unique [orgId, shortCode]. 3 ciclos de nuke-reimport documentados.

Desafios técnicos

  • Aprovação externa sem race condition: undo de 5 min com bloqueio anti-pisar-em-pisada via Activity.automationRunId — duplo clique do cliente não dispara cadeia duas vezes.
  • Engine de automações com 1685 linhas mantida limpa e auditável: routeAction grande mas com handlers extraídos, 4 actions declaradas-não-implementadas sinalizadas (FILL_FIELDS, SAVE_DESCRIPTION_VERSION, LINK_FLOW, UNLINK_FLOW) pra gap honesto.
  • Importação massiva de 10.617 cards do Ummense sem duplicar nem perder ordem: shortCode unique, OrgImportMapping persistido, 9 migrations documentadas como 'fix de bug arquitetural' descobertas no caminho.
  • Garantir isolamento entre orgs sem queries vazadas: TenantGuard que valida header/cookie contra relacionamento DB antes de qualquer operação.
  • CRM vinculando Contact ↔ User (FK 1:1) com identidade read-only do usuário convidado.

Galeria

Quadro Kanban — colunas customizáveis com WIP visível, drag-and-drop, cards com prazo e equipe.
Tela inicial — visão consolidada do dia: tarefas pendentes, calendário e cards recentes.
Card detalhado (parte 1) — descrição rica em editor TipTap, equipe, prioridade, etiquetas e anexos.
Card detalhado (parte 2) — checklist de tarefas, sub-cards (CardPresence multi-fluxo), anexos via presigned URL e timeline de anotações com @mentions.
Aprovação por cliente externo — link tokenizado sem cadastro. Cliente vê descrição, equipe, prazo e decide com um clique.
Tela do cliente externo aprovando entrega — view rica do card com descrição em TipTap, anexos via presigned URL, checklists e timeline de comentários.
Undo de 5 minutos na decisão do cliente — bloqueio anti-pisar-em-pisada via query Activity.automationRunId IS NULL impede que clique duplicado dispare cadeia duas vezes.
Painel de indicadores — Lead time, Throughput, WIP, atrasados, saúde por coluna e cards parados.
Timesheet da organização — controle manual ou cronômetro, filtros por período/fluxo/usuário, exportação CSV.
Hub de navegação — todos os quadros da organização com permissões respeitadas via tenant_id + scope de membership.
Login com JWT em cookies httpOnly e opção 'permanecer logado neste dispositivo'. Tema escuro nativo.
Onboarding via convite tokenizado — usuário convidado recebe link no celular e entra sem precisar criar conta antes. Mailer com Promise.allSettled não bloqueia se um destinatário falhar.
Notificação WhatsApp real via Evolution API — cliente recebe alerta no celular sem precisar abrir o sistema. Fallback silencioso garante que cadeia de automação nunca trava por instância caída.