Pular para o conteúdo principal

📊 Relatório Minucioso: Sistema de Permissões e Equipes ArboreoLab

Data: 08 de Janeiro de 2026
Responsável: Engenheiro de Software Sênior
Foco: Usuários Convidados para Projetos
Versão: 1.0.0


Índice

  1. Resumo Executivo
  2. Arquitetura de Databases
  3. Estrutura de Tabelas ArboreolabADM
  4. Sistema de Permissões RBAC
  5. Fluxo de Convite de Usuários
  6. O Que o Usuário Convidado Pode Ver
  7. Comparativo com a Indústria
  8. Recomendações e Melhorias

Resumo Executivo

O ArboreoLab implementa um sistema Multi-Tenant com RBAC Contextual (Role-Based Access Control), onde:

AspectoEstado Atual
Isolamento de Dados✅ Por Database ([Projeto]Vector)
Autenticação✅ JWT + Google OAuth
Autorização✅ RBAC com 5 níveis hierárquicos
Convites de Equipe✅ Implementado (gestor+ pode convidar)
Limites por Plano✅ Controlado por assinaturas
Auditoria✅ Logs de projeto (arb_projeto_logs)

Databases Identificados

┌──────────────────────────────────────────────────────┐
│ Servidor MariaDB 11.8 │
├──────────────────────────────────────────────────────┤
│ ArboreolabADM │ Governança centralizada │
│ ClioVector │ Tenant: Template/Clio │
│ GeopoliticasVector │ Tenant: Geopolíticas │
│ arboreolabconn │ Conexões (legado?) │
└──────────────────────────────────────────────────────┘

Arquitetura de Databases

Separação Multi-Tenant

O ArboreoLab utiliza isolamento completo por database:

┌───────────────────────────────────────────────────────────────┐
│ ArboreolabADM (Governança) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ arb_usuarios │ Todos os usuários do sistema │ │
│ │ arb_projetos │ Registro de todos os projetos │ │
│ │ arb_projeto_usuarios │ Relação N:N (equipes/convites) │ │
│ │ arb_assinaturas │ Limites por plano │ │
│ │ arb_projeto_logs │ Auditoria de ações │ │
│ │ arb_config │ Configurações globais │ │
│ └─────────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────┘

┌───────────────┼───────────────┐
▼ ▼ ▼
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐
│ ClioVector │ │GeopoliticasVector │ │ [Novo]Vector │
├───────────────────┤ ├───────────────────┤ ├───────────────────┤
│ clio_ocr │ │ clio_ocr │ │ clio_ocr │
│ clio_ocr_segments │ │ clio_ocr_segments │ │ clio_ocr_segments │
│ clio_entidades │ │ clio_entidades │ │ clio_entidades │
│ clio_documentos │ │ clio_documentos │ │ clio_documentos │
│ embeddings_768 │ │ embeddings_768 │ │ embeddings_768 │
└───────────────────┘ └───────────────────┘ └───────────────────┘

Benefício de Segurança: Um usuário convidado para o projeto "Geopoliticas" NUNCA terá acesso aos dados de "Clio" ou outros projetos.


Estrutura de Tabelas ArboreolabADM

1. arb_usuarios - Cadastro Global de Usuários

CampoTipoDescrição
idINT PKIdentificador único
emailVARCHAR(255) UNIQUEEmail (login)
nomeVARCHAR(255)Nome completo
organizacaoVARCHAR(255)Organização/empresa
google_idVARCHAR(100)ID do Google OAuth
auth_providerENUMgoogle, email, sso
statusENUMpendente, ativo, suspenso, inativo
roleENUMadmin, gestor, usuario, visitante (global)
plano_selecionadoENUMgratuito, basico, profissional, enterprise

Dados Atuais:

| id | email                          | status   | role    | plano       |
|----|--------------------------------|----------|---------|-------------|
| 3 | adm.geopoliticas@gmail.com | ativo | admin | gratuito |
| 25 | romao.doug@gmail.com | ativo | usuario | gratuito |
| 28 | recruta@gmail.com | ativo | usuario | gratuito |
| 29 | teste.convite.novo@exemplo.com | pendente | usuario | gratuito |

2. arb_projetos - Registro de Projetos

CampoTipoDescrição
idINT PKIdentificador único
usuario_idINT FKProprietário (owner) do projeto
nomeVARCHAR(255)Nome do projeto
slugVARCHAR(100)Identificador URL-friendly
database_nameVARCHAR(100) UNIQUENome do database ([Nome]Vector)
storage_typeENUMlocal, google_drive, onedrive, icloud, s3
statusENUMconfigurando, ativo, pausado, arquivado
instalacao_completaTINYINT0/1 - Wizard concluído

Dados Atuais:

| id | usuario_id | nome                        | database_name      | status |
|----|------------|-----------------------------|--------------------|--------|
| 4 | 3 | Geopoliticas Institucionais | GeopoliticasVector | ativo |

⚠️ Observação: O campo usuario_id define o OWNER do projeto (nível 100).


3. arb_projeto_usuarios - Equipe do Projeto (CRÍTICA)

Esta é a tabela central de permissões para usuários convidados:

CampoTipoDescrição
idINT PKIdentificador único
projeto_idINT FKProjeto ao qual pertence
usuario_idINT FKUsuário membro
roleENUMadmin, gestor, usuario, visitante
permissao_leituraTINYINT1 = pode visualizar
permissao_escritaTINYINT1 = pode editar/upload
permissao_exclusaoTINYINT1 = pode deletar
permissao_adminTINYINT1 = acesso administrativo
statusENUMpendente, ativo, suspenso, removido
convidado_porINT FKQuem enviou o convite
convite_aceito_emTIMESTAMPData de aceite

Dados Atuais:

| usuario     | projeto      | role    | leitura | escrita | exclusão | status   | convidado_por |
|-------------|--------------|---------|---------|---------|----------|----------|---------------|
| user 3 | Geopoliticas | admin | ✓ | ✓ | ✓ | ativo | NULL (owner) |
| user 25 | Geopoliticas | usuario | ✓ | ✗ | ✗ | removido | 3 |
| user 28 | Geopoliticas | usuario | ✓ | ✗ | ✗ | ativo | 3 |
| user 29 | Geopoliticas | usuario | ✓ | ✗ | ✗ | removido | 3 |

4. arb_assinaturas - Limites por Plano

CampoTipoDescrição
projeto_idINT FKProjeto associado
planoENUMgratuito, basico, profissional, enterprise
statusENUMativo, expirado, cancelado, trial
limite_documentosINTMáximo de documentos
limite_storage_gbDECIMALLimite de armazenamento
limite_ocr_mensalINTOCR por mês
limite_usuariosINTMáximo de membros na equipe

Dados Atuais:

| projeto_id | plano      | status | limite_docs | limite_storage | limite_usuarios |
|------------|------------|--------|-------------|----------------|-----------------|
| 4 | enterprise | ativo | 10.000 | 50 GB | 5 |

5. arb_projeto_logs - Auditoria

CampoTipoDescrição
projeto_idINT FKProjeto
usuario_idINT FKQuem executou a ação
acaoENUMTipo de ação (30+ tipos)
descricaoTEXTDescrição legível
dados_anterioresJSONSnapshot antes
dados_novosJSONSnapshot depois
ip_origemVARCHAR(45)IP do usuário
nivelENUMdebug, info, warning, error, critical

Ações Relevantes para Equipes:

  • config_alterada - Quando membro é adicionado/alterado/removido
  • usuario_login, usuario_logout - Sessões

6. arb_projeto_credentials - Credenciais por Projeto

Armazena tokens OAuth, API keys, etc. de forma criptografada:

CampoTipoDescrição
projeto_idINT FKProjeto dono
credential_typeENUMgoogle_oauth_token, gemini_api_key, etc.
credential_value_encryptedTEXTValor criptografado (AES-256)
is_activeTINYINTSe está ativa

🔒 Segurança: Credenciais são isoladas por projeto - um usuário convidado para Projeto A não tem acesso às credenciais do Projeto B.


Sistema de Permissões RBAC

Hierarquia de Roles

┌─────────────────────────────────────────────────────────────────────┐
│ HIERARQUIA DE PERMISSÕES │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ OWNER (100) ─────────────────────────────────────────────────────► │
│ │ ✓ Deletar projeto │
│ │ ✓ Gerenciar credenciais (OAuth, API Keys) │
│ │ ✓ Finalizar instalação │
│ │ ✓ Tudo abaixo │
│ │ │
│ ADMIN (90) ──────────────────────────────────────────────────────► │
│ │ ✓ Editar configurações do projeto │
│ │ ✓ Remover membros da equipe │
│ │ ✓ Alterar roles de membros │
│ │ ✓ Configurar storage │
│ │ ✓ Tudo abaixo │
│ │ │
│ GESTOR (50) ─────────────────────────────────────────────────────► │
│ │ ✓ Convidar membros │
│ │ ✓ Deletar documentos │
│ │ ✓ Sincronizar Tainacan │
│ │ ✓ Tudo abaixo │
│ │ │
│ USUÁRIO (10) ────────────────────────────────────────────────────► │
│ │ ✓ Upload de arquivos │
│ │ ✓ Editar documentos/metadados │
│ │ ✓ Executar OCR │
│ │ ✓ Tudo abaixo │
│ │ │
│ VISITANTE (0) ───────────────────────────────────────────────────► │
│ ✓ Apenas visualização (GET requests) │
│ ✓ Buscar documentos │
│ ✓ Ver entidades │
│ │
└─────────────────────────────────────────────────────────────────────┘

Implementação Backend

Middleware Chain (ordem obrigatória):

verifyJwt → selectDatabase → requireRole(minRole)

Arquivo: node/backend/middleware/verifyPermissions.js

// Níveis definidos
const ROLES = {
owner: { level: 100 },
admin: { level: 90 },
gestor: { level: 50 },
usuario: { level: 10 },
visitante: { level: 0 }
};

// Middleware factory
function requireRole(minRole) {
return async (req, res, next) => {
const userLevel = getRoleLevel(req.projectInfo?.role);
const requiredLevel = getRoleLevel(minRole);

if (userLevel >= requiredLevel) {
req.userPermissions = {
role: userRole,
isOwner: userRole === 'owner',
isAdmin: userLevel >= 90,
canManage: userLevel >= 50,
canWrite: userLevel >= 10
};
return next();
}

return res.status(403).json({ error: 'Acesso Negado' });
};
}

Implementação Frontend

Arquivo: iface-frontend-vuejs/src/composables/usePermissions.ts

// Uso no componente
const { canAdmin, canWrite, isOwner } = usePermissions()

// No template
<button v-if="canAdmin" @click="removerMembro">Remover</button>

Fluxo de Convite de Usuários

Diagrama de Sequência

┌───────────────┐    ┌───────────────┐    ┌───────────────┐    ┌───────────────┐
│ Admin/Gestor │ │ Backend │ │ Database │ │ Novo Membro │
└───────┬───────┘ └───────┬───────┘ └───────┬───────┘ └───────┬───────┘
│ │ │ │
│ POST /projeto/:id/equipe │ │
│ { email, role } │ │ │
│───────────────────►│ │ │
│ │ │ │
│ │ Verifica permissão │ │
│ │ (gestor+ pode) │ │
│ │ │ │
│ │ Verifica plano │ │
│ │ (tem limite?) │ │
│ │───────────────────►│ │
│ │ │ │
│ │ Usuário existe? │ │
│ │◄───────────────────│ │
│ │ │ │
│ │ Se não: cria com │ │
│ │ status='pendente' │ │
│ │───────────────────►│ │
│ │ │ │
│ │ INSERT │ │
│ │ arb_projeto_usuarios│ │
│ │ status='pendente' │ │
│ │───────────────────►│ │
│ │ │ │
│ 200 OK (membro │ │ │
│ adicionado) │ │ │
│◄───────────────────│ │ │
│ │ │ │
│ │ │ │
│ │ │ Faz login │
│ │ │◄───────────────────│
│ │ │ │
│ │ GET /convites/pendentes │
│ │◄────────────────────────────────────────│
│ │ │ │
│ │ Lista convites │ │
│ │────────────────────────────────────────►│
│ │ │ │
│ │ POST /convites/:id/aceitar │
│ │◄────────────────────────────────────────│
│ │ │ │
│ │ UPDATE status= │ │
│ │ 'ativo' │ │
│ │───────────────────►│ │
│ │ │ │
│ │ Acesso liberado │ │
│ │────────────────────────────────────────►│

Endpoints Relevantes

MétodoEndpointDescriçãoMínimo
POST/api/projeto/:id/equipeConvidar membrogestor
GET/api/projeto/:id/equipeListar equipevisitante
PUT/api/projeto/:id/equipe/:usuarioIdAlterar roleadmin
DELETE/api/projeto/:id/equipe/:usuarioIdRemover membroadmin
GET/api/projeto/convites/pendentesListar convitesusuário
POST/api/projeto/convites/:id/aceitarAceitar conviteusuário

O Que o Usuário Convidado Pode Ver

Por Role

RecursoOwnerAdminGestorUsuárioVisitante
Documentos
Visualizar lista
Ver conteúdo OCR
Ver entidades
Busca semântica
Upload novos
Editar metadados
Deletar
Equipe
Ver membros
Convidar
Remover
Alterar roles
Projeto
Ver configurações
Editar configurações
Conectar storage
Deletar projeto
Credenciais
Ver API Keys
Gerenciar OAuth

Isolamento Entre Projetos

Um usuário convidado para Projeto A:

  • ✅ Vê apenas dados do Projeto A
  • ✅ Acessa apenas o database ProjetoAVector
  • NUNCA acessa dados do Projeto B
  • NUNCA vê credenciais de outros projetos
  • NUNCA lista projetos dos quais não é membro

Comparativo com a Indústria

Modelo ArboreoLab vs Padrões de Mercado

1. Modelo SaaS Clássico (Slack, Notion, Figma)

┌─────────────────────────────────────────────────────────────────────┐
│ MODELO TÍPICO SAAS │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ │
│ │ ORGANIZAÇÃO │ ← Conta do assinante (billing) │
│ │ (Workspace) │ │
│ └────────┬────────┘ │
│ │ │
│ ├──── Owner/Admin (quem paga) │
│ │ │
│ └──── Membros com roles: │
│ • Admin (tudo) │
│ • Member (padrão) │
│ • Guest/Viewer (limitado) │
│ │
│ Recursos compartilhados: │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Projeto │ │ Projeto │ │ Projeto │ ← Todos acessam │
│ │ A │ │ B │ │ C │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ Problema: Todos veem tudo (ou precisam de granularidade extra) │
└─────────────────────────────────────────────────────────────────────┘

2. Modelo ArboreoLab (Isolamento por Projeto)

┌─────────────────────────────────────────────────────────────────────┐
│ MODELO ARBOREOLAB │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ PROJETO A │ │ PROJETO B │ ← Databases separados │
│ │ (Database A) │ │ (Database B) │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
│ ├── Owner (paga A) ├── Owner (paga B) │
│ │ │ │
│ └── Equipe A └── Equipe B │
│ • Admin • Gestor │
│ • Gestor • Usuário │
│ • Usuário │
│ │
│ ✅ Isolamento TOTAL entre projetos │
│ ✅ Cada projeto = tenant independente │
│ ✅ Um usuário pode estar em múltiplos projetos com roles │
│ diferentes em cada um │
│ │
└─────────────────────────────────────────────────────────────────────┘

Comparação com Referências de Mercado

AspectoSlackNotionFigmaGitHubArboreoLab
Unidade de billingWorkspaceWorkspaceOrgOrg/UserProjeto
IsolamentoCanaisPáginasProjetosReposDatabase
RBAC4 níveis4 níveis3 níveis5 níveis5 níveis
ConvitesEmailEmailEmailUsernameEmail
Multi-tenantShared DBShared DBShared DBShared DBIsolado
LimitesPor planoPor planoPor planoPor planoPor plano

Vantagens do Modelo ArboreoLab

  1. Segurança por Design

    • Dados de um cliente NUNCA tocam o database de outro
    • Vazamento de dados entre tenants é estruturalmente impossível
  2. Compliance Facilitado

    • LGPD/GDPR: Exclusão de dados por tenant é DROP DATABASE
    • Auditoria isolada por projeto
  3. Escalabilidade

    • Cada projeto pode ser migrado independentemente
    • Backup/restore granular por tenant
  4. Flexibilidade de Roles

    • Mesmo usuário pode ser Owner em Projeto A e Visitante em Projeto B
    • Roles contextuais por projeto

Desvantagens e Riscos

  1. Complexidade Operacional

    • Mais databases para gerenciar
    • Migrations precisam rodar em todos os tenants
  2. Overhead de Conexões

    • Cada tenant precisa de seu próprio pool
    • Limite de max_connections do MariaDB
  3. Onboarding do Usuário

    • Usuário precisa entender o conceito de "projetos"
    • Troca de contexto entre projetos

Recomendações e Melhorias

Curto Prazo (1-2 semanas)

PrioridadeMelhoriaJustificativa
🔴 AltaImplementar notificação de convite (email)Usuário não sabe que foi convidado
🔴 AltaAdicionar role admin na tabela arb_projeto_usuariosAtualmente só owner tem admin_flag
🟡 MédiaDashboard de convites pendentes no loginUX para novos usuários
🟡 MédiaExpiração de convites (30 dias)Segurança

Médio Prazo (1-2 meses)

PrioridadeMelhoriaJustificativa
🟡 MédiaPermissões granulares por recursoEx: acesso só a determinadas pastas
🟡 MédiaGrupos de permissão"Equipe OCR", "Equipe Metadados"
🟢 BaixaSSO corporativo (SAML/OIDC)Clientes enterprise

Longo Prazo (3-6 meses)

PrioridadeMelhoriaJustificativa
🟢 BaixaPermissões por pasta/coleçãoAcervo X só para Equipe Y
🟢 BaixaHierarquia de organizaçõesHolding → Empresas → Projetos
🟢 BaixaAPI de gerenciamento de equipesAutomação de provisionamento

📊 Métricas de Segurança

Checklist de Auditoria

✅ Senhas: Nunca armazenadas em texto claro
✅ Tokens: Criptografados com AES-256-GCM
✅ JWT: Expira em 24h
✅ Sessions: Invalidadas no logout
✅ Logs: Todas as ações sensíveis são logadas
✅ HTTPS: Forçado em produção
✅ Isolamento: Databases separados por tenant
✅ RBAC: 5 níveis hierárquicos
✅ Convites: Verificação de limite por plano

Testes de Intrusão Recomendados

  1. IDOR (Insecure Direct Object Reference)

    • Tentar acessar projeto_id de outro tenant
    • Tentar acessar usuário_id de outro projeto
  2. Privilege Escalation

    • Usuário tentando alterar própria role
    • Visitante tentando fazer POST
  3. Token Manipulation

    • JWT modificado
    • Token expirado

📝 Conclusão

O sistema de permissões do ArboreoLab está bem estruturado para o modelo multi-tenant com equipes:

AspectoStatusNota
Arquitetura RBAC✅ Implementado5 níveis hierárquicos
Isolamento de dados✅ RobustoPor database
Fluxo de convites✅ FuncionalCom notificação por email
Limites por plano✅ ImplementadoAssinaturas controlam
Auditoria✅ Completa30+ tipos de ação

O que o usuário convidado pode ver:

  • Documentos do projeto ao qual foi convidado
  • Entidades e OCR do projeto
  • Membros da equipe do projeto
  • Configurações (se role permitir)

O que o usuário convidado NÃO pode ver:

  • Qualquer dado de outros projetos
  • Credenciais do projeto (exceto owner)
  • Usuários de outros projetos
  • Logs de outros projetos

🔄 Atualizações

09/01/2026 - Sistema de Notificação por Email

  • Postfix + OpenDKIM + TLS configurados e operacionais
  • SPF, DKIM, DMARC passando verificação Gmail
  • Página de aceite de convite implementada no frontend
  • Fluxo completo testado - convite enviado, aceito, usuário com acesso
  • Permissões aplicadas corretamente conforme role definido

09/01/2026 - Sistema de Permissões Dinâmicas (RBAC Configurável)

  • Tabela arb_projeto_permissoes - Permite ao owner definir roles mínimas por recurso
  • Endpoint /api/permissoes - CRUD completo para gerenciamento
  • Store permissoesStore - Cache de permissões no frontend
  • Router Guard atualizado - Verifica permissões antes de permitir navegação
  • Interface de gerenciamento - /projeto/permissoes para o owner configurar

09/01/2026 - Correção: Role aparecendo como visitante para o Owner

  • Causa raiz: o GET /api/permissoes retornava minha_role = visitante quando req.userPermissions não era preenchido (faltava middleware de role nessa rota).
  • Correção: adicionada validação mínima de leitura no endpoint (verifyJwt → selectDatabase → requireRead), garantindo injeção de req.userPermissions e retorno correto de minha_role/meu_nivel.
  • Hardening do JWT: normalização do payload para preencher email a partir de userId/id quando esses campos contiverem um email (evita logs “anônimo” e falhas de cálculo de role).
  • Efeito prático: owner volta a ser identificado como owner (100) e o router guard deixa de bloquear telas como /armazenamento indevidamente.

Arquitetura de Permissões Dinâmicas

┌─────────────────────────────────────────────────────────────────┐
│ CAMADA DE CONFIGURAÇÃO │
│ (Owner configura via /projeto/permissoes) │
├─────────────────────────────────────────────────────────────────┤
│ arb_projeto_permissoes (por projeto/tenant) │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ projeto_id │ recurso │ role_minima │ visivel │ edit │ │
│ │ 4 │ /busca │ usuario │ true │ true │ │
│ │ 4 │ /armazenamento │ gestor │ true │ false│ │
│ │ 4 │ /entidades │ admin │ true │ true │ │
│ └────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│ CAMADA DE APLICAÇÃO │
├─────────────────────────────────────────────────────────────────┤
│ Backend: Middleware verifica permissão por recurso │
│ Frontend: Router guard + permissoesStore │
└─────────────────────────────────────────────────────────────────┘

Recursos Configuráveis (17 views)

GrupoRecursosRole Padrão
Dashboard/inicio, /estatisticasvisitante, usuario
Busca/busca-documentos, /view-docs-rel, /entidades-rel-d3visitante, visitante, usuario
Documentos/gerenciadores, /gerenciador-dados, etc.gestor
Armazenamento/armazenamento, /propriedadesgestor, usuario
IA/aigestor
Projeto/projeto, /projeto/wizard, /projeto/permissoesadmin, owner, owner
Perfil/perfilvisitante

🔜 Próxima Fase: Controle de Conteúdo por Roles

  1. Controle de campos por roles - Definir quais campos são visíveis/editáveis por role
  2. Componentes condicionais - v-if baseado em permissões granulares

🔜 Melhorias de Interface (Backlog)

  • Botão "Reenviar convite" para convites expirados
  • Opção de cancelar convite pendente
  • Lista de convites pendentes na interface

Relatório criado em 08/01/2026
Atualizado em 09/01/2026
Engenheiro de Software Sênior - ArboreoLab