Jumentix
Blueprint SaaS modular

Lance um deploy, preserve cada limite de domínio

Entregue mais rápido como monólito modular com multitenancy, RBAC, organizações, usuários e colaboração orientada a eventos já modelados.

Mascote open source do Jumentix

O que este blueprint entrega à sua equipe

  • Menor custo operacional na primeira versão
  • Módulos por feature mantêm mudanças locais
  • Contratos de mensagem suportam extração futura
bun install
bun run cli
bun run dev:express

Do zero ao primeiro MVP

Uma sequência prática de lançamento para este blueprint

Use este caminho quando o primeiro MVP é uma fatia SaaS completa: login, escopo de tenant ou organização, um fluxo central e um deploy.

Defina o fluxo do tenant

Escolha a primeira capacidade da organização, como tarefas por categoria, e defina quem cria, vê e conclui.

  • Defina TenantContext com organizationId e userId em todo request.
  • Modele Task com organizationId para cada registro pertencer a um tenant.
  • Escreva a regra da TenantPolicy: um tenant só escreve nos próprios registros.
  • Escreva critérios de aceite: escrita cross-tenant é negada com erro explícito.

Saída MVP: um contexto delimitado com expectativas de tenant e RBAC.

type TenantContext = { organizationId: string; userId: string };
type Task = { id: string; organizationId: string; title: string; categoryId: string };

class TenantPolicy {
  canWriteTask(context: TenantContext, organizationId: string) {
    return context.organizationId === organizationId;
  }
}

Critérios de pronto do primeiro MVP

  • Leitura ou escrita cross-tenant falha em teste automatizado.
  • Mudanças da primeira feature ficam dentro do limite do módulo.
  • Um processo supervisionado roda o fluxo do tenant de ponta a ponta.
  • Docs, rotas e limites de módulo concordam na evidência de release.

Fora de escopo de propósito

  • Billing, planos e ciclo de vida de assinatura.
  • SSO e provedores externos de identidade.
  • Audit log completo e matriz fina de permissões.
  • Extração de módulos para serviços separados.

Escopo MVP

Mantenha a primeira versão pequena o bastante para comprovar

Um fluxo tenant

Organization, user, Category e Task provam tenancy e comportamento real de feature.

Fatia de produto

Um deploy

Mantenha operação simples preservando módulos de feature e limites de composição.

Fatia de entrega

Uma política de papel

Prove superadmin/admin/user antes de uma matriz completa de permissões.

Fatia de segurança
Área de provaPergunta a responderMecanismo JumentixEvidência MVP
Segurança tenantUma organização consegue ver dados de outra?Testes tenant-aware de use-case e checks de policy.Leituras e escritas cross-tenant falham.
Limite de móduloA primeira feature muda sem tocar módulos não relacionados?Pasta por feature e checks de workspace boundary.Mudanças ficam locais ao contexto delimitado.
Pronto para pilotoO MVP inteiro roda como um app supervisionado?Perfil dev/staging, smoke test, docs e evidência prepublish.Um deploy está pronto para primeiros usuários.

Implementação prática

Código completo para a primeira fatia funcional

Estes exemplos mantêm Category e Task como vocabulário de produto e mostram controller, contrato, client, worker ou camada de estado necessários para chegar a um MVP executável.

type TenantContext = { organizationId: string; userId: string };
type Task = { id: string; organizationId: string; title: string; categoryId: string };

class TenantPolicy {
  canWriteTask(context: TenantContext, organizationId: string) {
    return context.organizationId === organizationId;
  }
}

class TaskModule {
  private readonly tasks = new Map<string, Task>();

  constructor(private readonly tenantPolicy: TenantPolicy) {}

  create(context: TenantContext, input: { title: string; categoryId: string }) {
    if (!this.tenantPolicy.canWriteTask(context, context.organizationId)) {
      return { ok: false, error: 'tenant access denied' };
    }
    const task: Task = {
      id: crypto.randomUUID(),
      organizationId: context.organizationId,
      title: input.title,
      categoryId: input.categoryId
    };
    this.tasks.set(task.id, task);
    return { ok: true, result: task };
  }
}

const taskModule = new TaskModule(new TenantPolicy());
export const modules = { taskModule };

Construa o produto. Preserve a arquitetura.

Explore o código, execute a fábrica localmente e transforme seu próximo serviço Node.js em uma capacidade repetível de plataforma.