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

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.
- NestJS
- Prisma 6
- PostgreSQL
- Redis
- Next.js
- React
- TypeScript
- Socket.IO
- BullMQ
- Evolution API
- Docker (Hetzner VPS)
- GitHub Actions
- 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.
- 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.