carlos@cesaints: ~/projects/multi-company-onboarding.md — zsh

Comando: cat projects/multi-company-onboarding.md

projects/multi-company-onboarding.md · 1,4 KB

Plataforma de onboarding multiempresa com isolamento no banco

Duas empresas de um grupo empresarial usam a mesma plataforma para integrar quem acabou de entrar, no mesmo banco, sem que uma enxergue um único dado da outra. Cada pessoa recebe uma trilha guiada por fases, montada para o seu setor, cargo e contrato, e o painel acompanha o progresso em tempo real sem mandar nenhum dado pessoal pelo canal de tempo real.

abrir demonstraçãosimulação do sistema com dados fictícios · 6 telas

Papel
Único engenheiro, do produto à operação
Período
jul/2026 – set/2026
O que eu fiz

Eu: Produto, arquitetura, modelo de dados, regras de acesso no banco, todas as telas do app e do painel, testes, deploy e operação.

Projeto privado, descrito sem identificar cliente, produto ou empresa.

Diagrama

Empresas no mesmo banco, separadas pelo próprio banco

O app do colaborador, com a trilha por fases, e o painel da área de pessoas, onde também atua o operador de plataforma, passam por Server Actions. Os dados ficam num Postgres só, e a fronteira entre as empresas é do banco: RLS em todas as tabelas, chaves compostas com a empresa e gatilhos contra vínculo entre empresas. Os arquivos ficam no Storage, conferidos pelos primeiros bytes e servidos por links assinados que expiram. O Realtime publica só o aviso de que um escopo mudou, e a tela refaz a consulta com as mesmas regras de acesso.

Contexto

Um grupo com duas empresas precisava integrar quem acabava de entrar sem depender de planilhas e de repasses de mão em mão. Cada empresa tem a sua identidade, os seus setores, cargos e contratos, e os dados de uma não podem aparecer para a outra.

O que eu construí

  • O app do colaborador. Um início que diz o próximo passo e a prontidão, a trilha por fases (pré-embarque, primeiro dia, primeira semana, 30, 60 e 90 dias), a leitura de cada etapa com vídeo, documento e checklist, a biblioteca de documentos, a escada de carreira e a equipe.
  • O painel da área de pessoas. Estrutura da empresa, documentos versionados, framework de carreira, editor de trilhas com prévia idêntica à do colaborador, fichas e acessos, visão geral com time-to-productivity e gargalos por etapa, auditoria e exportação.
  • O operador de plataforma. Uma conta transversal que troca de empresa num seletor. A empresa ativa fica no servidor, e todas as regras do banco passam a servir a outra empresa.
  • A cor de cada empresa com contraste calculado. O servidor escolhe texto claro ou escuro pelo contraste da WCAG e avisa quando nenhum dos dois atinge 4,5:1.

O que eu faria diferente

Separaria desde o primeiro dia a empresa de origem de uma conta da empresa que ela está gerenciando. Misturar as duas trancou o próprio dono fora do produto num incidente, e a correção exigiu mover a identidade para colunas imutáveis garantidas pelo banco.

Restrições

  • Duas empresas no mesmo banco, sem que uma veja um dado da outra, nem por erro de consulta.
  • Dado pessoal só vai para o navegador de quem precisa dele, inclusive no tempo real.
  • Uma única pessoa técnica para construir e operar.
  • Conteúdo montado pela área de pessoas, sem depender de desenvolvedor para cada mudança.

Decisões

Isolamento no banco, e não só na aplicação

Contexto
Com duas empresas na mesma base, um filtro esquecido numa consulta bastaria para mostrar os colaboradores de uma para a outra.
Escolha
Row-Level Security em todas as tabelas, chaves estrangeiras compostas com a empresa e gatilhos que recusam qualquer vínculo entre empresas diferentes.
Ganhos
  • Um bug na aplicação não atravessa a fronteira entre empresas.
  • O isolamento é testado contra as migrations reais, e não contra um mock.
Custos
  • Regras avaliadas linha a linha pesaram no desempenho e precisaram ser reescritas.

Tempo real sem dado pessoal

Contexto
A replicação padrão de linhas mandaria nome, e-mail e gestor de cada colaborador para o navegador de todos os administradores.
Escolha
O banco publica só um aviso de que algo mudou naquele escopo; a tela refaz a consulta com as mesmas regras de acesso de sempre.
Ganhos
  • Nenhum dado pessoal trafega no canal de tempo real.
  • Quando o mecanismo do provedor falhou, deu para trocar o transporte sem mudar a decisão.
Custos
  • Cada aviso custa uma nova consulta, o que exigiu debounce e intervalo mínimo por tela.

Trilhas por composição, com inclusão aditiva

Contexto
Cada pessoa precisa da soma certa de conteúdos para o seu setor, cargo e tipo de contrato.
Escolha
Trilhas com escopo em camadas, somadas automaticamente pelo perfil, mais a inclusão de alguém pelo nome. Remover uma pessoa de uma trilha não apaga o que ela já concluiu.
Ganhos
  • A área de pessoas monta o onboarding sem pedir código.
  • Recolocar alguém traz de volta as etapas já concluídas.
Custos
  • Mais regras para explicar no painel, o que pediu uma prévia de como o colaborador vê.

Stack e por quê

Next.js 15 e React 19
App do colaborador e painel no mesmo projeto, com Server Actions.
TypeScript estrito
Tipos de ponta a ponta, com acesso a índice verificado.
Supabase (Postgres, Auth, Storage, Realtime)
Isolamento por empresa no próprio banco.
Vitest com PGlite
Testes de isolamento que rodam as migrations reais num Postgres em processo.
Playwright
Fluxos completos com uma empresa de teste criada e removida a cada execução.
Vercel
Funções fixadas na mesma região do banco.

Resultados

  • Row-Level Security habilitada em todas as 25 tabelas, com suítes de isolamento e de escalada de privilégio rodando contra as migrations reais.

    repositório privado auditadoMigrations e testes do repositório(Auditoria do repositório privado, set/2026)
  • 26 decisões de arquitetura registradas em ADRs, incluindo a correção de decisões anteriores.

    repositório privado auditadoRegistro de decisões do projeto(Auditoria do repositório privado, set/2026)
  • Regras de acesso de 130 ms para 4,4 ms na leitura de 223 etapas, depois de reescritas para avaliar uma vez por consulta, com prova de que ninguém passou a ver nada diferente.

    declaradoRegistro de desempenho do projeto

Ângulo de segurança

Superfície de ataque

  • Painel administrativo com dados pessoais de colaboradores.
  • Canal de tempo real entre o banco e os navegadores.
  • Upload de documentos para a biblioteca de cada empresa.
  • Conteúdo das etapas escrito em markdown pelo painel.

Controles implementados

  • Row-Level Security, chaves compostas e gatilhos contra vínculo entre empresas.
  • Colunas de identidade imutáveis, garantidas por gatilho no banco.
  • Avisos de tempo real que carregam só o escopo, nunca o dado.
  • Arquivo validado pela assinatura real dos primeiros bytes, e links assinados que expiram em uma hora.
  • Markdown num subconjunto seguro, sem HTML e com esquema de link validado.
  • Exportação CSV protegida contra injeção de fórmula, e trilha de auditoria só de inserção.

O que eu testaria hoje

  • Troca de empresa pelo operador de plataforma tentando ler dados da empresa anterior.
  • Assinatura dos canais de tempo real de outra empresa.
  • Upload de arquivo com extensão forjada.

Evidências

  • repositório privado auditadoRepositório privado auditado(Auditoria do repositório privado, set/2026)