01Infraestrutura
O Mekovault roda na AWS Lightsail, região us-east-1, em quatro máquinas conectadas por rede privada. Apenas uma delas recebe tráfego da Internet.
| Host | Função | Serviços | Exposição |
|---|---|---|---|
mekovault-app | Aplicação | nginx, Next.js, serviços FastAPI, addons | Única exposta: portas 80/443 atrás do Cloudflare |
mekovault-data | Dados | PostgreSQL 16, Redis (2 instâncias), RabbitMQ | Somente rede privada |
mekovault-vault | Segredos | Infisical self-hosted, um project por tenant | Somente rede privada |
mekovault-obs | Observabilidade | Grafana, Loki, Prometheus, Tempo, OpenTelemetry Collector | Somente rede privada |
- Administração exclusivamente via Tailscale (WireGuard). Nenhum host tem SSH aberto à Internet.
- Firewall
ufwativo em cada máquina com política de negar por padrão. - Os serviços internos (PostgreSQL, Redis, RabbitMQ, Infisical, Grafana e os processos FastAPI) escutam em loopback ou na interface privada. O nginx é o único processo que atende tráfego público.
- O Cloudflare termina o TLS e filtra o tráfego antes que chegue ao nginx.
02Arquitetura de serviços
A interface web é uma aplicação Next.js 16. O backend é composto por serviços FastAPI em Python 3.12 com SQLAlchemy assíncrono, cada um com uma responsabilidade delimitada.
| Serviço | Responsabilidade |
|---|---|
svc-auth | Autenticação, sessões, MFA e redefinição de senha |
svc-tenancy | Empresas, associações, papéis, revendedores e exclusão de tenants |
svc-requests | Solicitações de admissão, mudança e desligamento; fluxo de aprovações |
svc-tickets | Tickets de suporte e seu acompanhamento |
svc-billing | Planos, assinaturas e faturamento |
svc-notifications | E-mail e notificações aos usuários |
| addons | Módulos conectores. Exemplo: super-workspace, que opera sobre Google Workspace |
Eventos e trabalhos em segundo plano
- Os serviços se comunicam por eventos via RabbitMQ, no exchange de tipo topic
mekovault.events. - Os trabalhos pesados (provisionamento, exclusões, exportações) são registrados em um livro-razão de jobs no PostgreSQL e executados por um worker único.
- Cada job tenta novamente com backoff exponencial. Seus passos são idempotentes: reexecutar um passo já concluído não produz efeitos duplicados no diretório.
- Quando um job esgota as tentativas, um alerta é gerado e o job permanece visível com o último erro para intervenção manual.
03Identidade e sessão
Os usuários do Mekovault (administradores de TI, aprovadores, revendedores) se autenticam com OAuth do Google ou com e-mail e senha. A sessão foi desenhada para que um token roubado sirva por pouco tempo e seja revogável.
| Mecanismo | Detalhe |
|---|---|
| Métodos de acesso | OAuth com Google, ou e-mail e senha |
| Token de acesso | JWT assinado com RS256, validade de 15 minutos, com claims de papel e de estado do MFA |
| Refresh token | Validade de 30 dias. Vive apenas em um cookie HttpOnly (inacessível via JavaScript). É rotacionado a cada uso e revogável individualmente por jti no Redis. Herda o estado do MFA da sessão e revalida a associação do usuário à empresa a cada renovação. |
| MFA | TOTP (apps autenticadores padrão). Limite de 5 tentativas por minuto; bloqueio de 15 minutos após 10 falhas consecutivas. |
| Operações sensíveis | Exigem que a sessão tenha MFA verificado, mesmo que o usuário já esteja autenticado. |
| Redefinição de senha | Token de uso único com validade de 30 minutos. |
Consequência prática: um access token vazado expira em no máximo 15 minutos; o refresh não pode ser exportado do navegador; e revogar o jti no Redis encerra a sessão imediatamente, sem esperar que nada expire.
04Isolamento multi-tenant
O Mekovault é multi-tenant: vários clientes compartilham a mesma infraestrutura. O isolamento entre eles é imposto em camadas independentes, de modo que um defeito em uma delas não exponha dados de outro cliente.
| Camada | Controle |
|---|---|
| Modelo de dados | Toda linha com dados de cliente carrega company_id. |
| Aplicação | Toda consulta filtra pela empresa que vem no token de sessão. Nunca por um parâmetro enviado pelo cliente. |
| Banco de dados | Row-Level Security do PostgreSQL como barreira adicional: mesmo que uma consulta esquecesse o filtro, o banco não retorna linhas de outra empresa. |
| Superadmin | Papel de plataforma separado dos papéis de cliente. Suas ações exigem confirmação por código e MFA verificado. |
| Revendedores | Um revendedor vê e opera apenas sobre os tenants que administra. |
05Credenciais de provedores e auditoria de uso
Para operar no seu diretório, o Mekovault recebe credenciais com permissões de administração: o JSON de uma Service Account do Google com delegação em todo o domínio. São o ativo mais sensível que manipulamos.
- Armazenadas criptografadas no Infisical (self-hosted, em
mekovault-vault), em um project dedicado por tenant. - Nunca são gravadas no banco de dados, em logs ou em respostas de API. O banco guarda apenas uma referência ao segredo.
- São carregadas em memória no momento de chamar o provedor e descartadas ao fim da operação.
Registro imutável de cada uso
Cada chamada ao Google com as credenciais do cliente grava uma linha na tabela credential_usage_log.
| Campo | Conteúdo |
|---|---|
| Tenant | company_id do cliente dono da credencial |
| Provedor | Google Workspace |
| Operação | Ação executada, por exemplo create_user, suspend_user, add_group_member |
| Scopes | Scopes ou permissões consumidos por essa operação |
| Quem | Usuário que originou a ação, ou o processo automático (worker, timer) que a executou |
| Motivo | Referência à solicitação, ticket ou tarefa que justificou a chamada |
| Resultado | Sucesso ou falha, com código de erro quando aplicável |
| Latência | Duração da chamada ao provedor em milissegundos |
- A tabela tem triggers do PostgreSQL que rejeitam qualquer
UPDATEouDELETE. Nem a equipe do Mekovault consegue editar ou apagar uma linha individual. - Cada linha tem um id determinístico derivado da operação. Uma nova tentativa do mesmo job não gera uma segunda linha, então o registro não infla nem se contradiz.
- Uma rajada de falhas sobre as credenciais de um tenant dispara um alerta para a equipe de operação.
Retenção
| Parâmetro | Valor |
|---|---|
| Mínimo | 24 meses |
| Máximo | 84 meses |
| Configuração | Por tenant, dentro dessa faixa |
| Exclusão do tenant | Apagado junto com o tenant, ou após 24 meses, o que ocorrer primeiro |
| Expurgo | Semanal, apenas de linhas fora do período configurado. Cada lote expurgado fica registrado na auditoria. |
Exportação para auditores
O registro é exportado em CSV ou JSON. Cada arquivo é assinado com HMAC-SHA256 e inclui o identificador da chave usada, de modo que um auditor pode verificar que o arquivo não foi alterado depois de gerado.
06Permissões que o Mekovault solicita
O Mekovault pede apenas as permissões necessárias para gerenciar usuários, grupos e unidades organizacionais. Não solicita acesso a e-mail, arquivos, calendário nem conteúdo de nenhum usuário.
| Scope | Para que é usado |
|---|---|
admin.directory.user | Criar, suspender, reativar e modificar contas de usuário; definir senha inicial e forçar sua troca. |
admin.directory.group | Criar grupos e listas, e adicionar ou remover membros durante admissões, mudanças e desligamentos. |
admin.directory.orgunit | Ler e mover usuários entre unidades organizacionais conforme o fluxo de onboarding ou offboarding. |
As chamadas são feitas com a Service Account personificando o administrador delegado que o cliente designa ao conectar o domínio. Esse administrador fica registrado em cada linha de credential_usage_log.
07Senhas iniciais e redefinição
- Quando o Mekovault cria uma conta ou redefine uma senha, a senha temporária fica visível para o administrador que executou a ação por 15 minutos.
- Depois desse prazo ela é expurgada do sistema. Não pode ser recuperada: se foi perdida, gera-se uma nova.
- Senhas nunca são gravadas em logs, eventos nem no registro de uso de credenciais.
08Exclusão de um tenant
Um cliente pode pedir a exclusão completa do seu tenant (direito ao esquecimento, GDPR art. 17 e Lei 21.719 do Chile). O processo foi desenhado para que as credenciais desapareçam antes de qualquer outro dado.
- Um administrador do tenant solicita a exclusão. A solicitação é enfileirada como job.
- O tenant fica inacessível imediatamente: suas sessões e novos logins são rejeitados.
- O job revoga os segredos do tenant e exclui seu project no Infisical. A partir desse ponto o Mekovault não consegue mais chamar o diretório do cliente.
- Só então os dados do tenant são excluídos em cascata do PostgreSQL: usuários, solicitações, tickets, configuração.
- A exclusão fica registrada na auditoria da plataforma.
- Os administradores recebem um e-mail de confirmação com o detalhe do que foi excluído.
09Addons: módulos com limites
Os conectores a provedores e outras extensões são empacotados como addons. Um addon com defeito não deve conseguir degradar a plataforma inteira, e o registro de addons impõe essa regra.
| Etapa | Controle |
|---|---|
| Declaração | Cada módulo é descrito em um manifesto com suas portas, rotas, tabelas, migrações e verificação de saúde. |
| Validação | Automática antes da ativação: esquema do manifesto, colisões de portas, rotas e tabelas com outros módulos, migrações aplicáveis e resposta da verificação de saúde. |
| Execução | Roda com limites de memória e CPU. Um módulo que estoura é reiniciado sem afetar os demais. |
| Supervisão | Verificação de saúde a cada 60 segundos, com resultado visível no painel de operação. |
| Kill switch | Qualquer módulo pode ser desativado sem deploy: em 15 segundos ou menos suas rotas respondem 503 e o restante da plataforma segue operando. |
10Perímetro e navegador
| Controle | Efeito |
|---|---|
| HSTS | O navegador só se conecta ao domínio por HTTPS, mesmo que o usuário digite http. |
| Content-Security-Policy | Restringe as origens das quais o portal pode carregar scripts, estilos e conexões. |
| X-Content-Type-Options: nosniff | Impede que o navegador reinterprete o tipo de um arquivo. |
| frame-ancestors 'none' | O portal não pode ser embutido em um iframe de outro site (clickjacking). |
| CORS restrito | Apenas as origens do Mekovault podem chamar a API a partir de um navegador. |
| Sem source maps em produção | O código-fonte do frontend não é publicado. |
| Sem documentação pública de API | Os esquemas OpenAPI dos serviços não ficam expostos em produção. |
| Erros sem rastros | As respostas de erro não incluem stack traces nem detalhes internos. |
11Operação e observabilidade
| Sinal | Destino |
|---|---|
| Logs estruturados (JSON) | Loki, consultados pelo Grafana |
| Métricas | Prometheus |
| Rastros distribuídos | OpenTelemetry para o Tempo |
- Antes de cada deploy é feito um backup do banco de dados.
- Os serviços são implantados de forma controlada; um deploy com falha é revertido ao backup anterior.
Timers de higiene
| Tarefa | O que faz |
|---|---|
| Expurgo de PII | Exclui dados pessoais que já cumpriram seu período de retenção. |
| Fechamento de tickets | Fecha tickets resolvidos sem atividade após o prazo configurado. |
| Expiração de segredos | Avisa os administradores 30, 7 e 0 dias antes de uma credencial de provedor expirar. |
| Expurgo do registro de uso | Semanal; exclui apenas linhas fora da retenção configurada e registra o lote. |
12Resumo das camadas de segurança
| Camada | Controles |
|---|---|
| Perímetro | Cloudflare, nginx como único processo público, ufw |
| Rede | Rede privada do Lightsail, Tailscale para administração, serviços em loopback |
| Identidade | JWT RS256 de 15 min, refresh HttpOnly rotacionado e revogável, MFA TOTP com rate limit |
| Aplicação | Filtro pelo company_id do token em toda consulta |
| Dados | Row-Level Security no PostgreSQL 16 |
| Segredos | Infisical self-hosted, um project por tenant, nunca em banco nem logs |
| Auditoria | credential_usage_log imutável, exportação assinada com HMAC-SHA256 |
| Módulos | Manifesto validado, limites de recursos, supervisão a cada 60 s, kill switch |
| Operação | Backups antes do deploy, timers de higiene, logs, métricas e rastros |
13O que está em andamento
Preferimos dizer o que falta antes que um questionário pergunte. Estes itens estão em trabalho e não devem ser considerados vigentes até que esta página os mova para a seção correspondente.
| Item | Status |
|---|---|
ENVIRONMENT=production em todos os serviços (hoje alguns rodam com a configuração de desenvolvimento endurecida) | Em andamento |
| Alertas de operação para o Slack | Em andamento |
| Papel do PostgreSQL dedicado por addon, para que cada módulo acesse apenas suas tabelas | Em andamento |
| SOC 2 | Não planejado por enquanto; o framework orienta nossos controles |
FAQPerguntas frequentes de auditoria
Respostas diretas ao que equipes de segurança e auditores costumam perguntar.
- Onde ficam minhas credenciais?
- No Infisical, uma instância self-hosted na máquina
mekovault-vault, dentro da rede privada da AWS Lightsail em us-east-1. Cada tenant tem seu próprio project. O banco de dados guarda apenas uma referência ao segredo, nunca seu valor. - Quem pode vê-las?
- Nenhuma pessoa as vê em operação normal. Os serviços as carregam em memória no momento de chamar o provedor e as descartam ao terminar. O acesso à máquina do vault exige Tailscale e é restrito à equipe de plataforma. As senhas temporárias geradas pelo Mekovault ficam visíveis ao administrador do cliente por 15 minutos e depois são expurgadas.
- O que acontece se eu deixar o Mekovault?
- Um administrador solicita a exclusão do tenant. O acesso é cortado imediatamente; depois os segredos são revogados e o project do Infisical é excluído; só então os dados são excluídos em cascata do PostgreSQL. Fica registro na auditoria da plataforma e os administradores recebem um e-mail com o detalhe. Os suboperadores com dados residuais estão listados na página de suboperadores.
- Como provo que minhas permissões não foram usadas para outra coisa?
- Com
credential_usage_log: cada chamada ao Google com suas credenciais fica registrada com operação, scopes, quem originou, motivo, resultado e latência. A tabela não aceita UPDATE nem DELETE. Você pode exportá-la em CSV ou JSON assinado com HMAC-SHA256 e verificar a assinatura com o id de chave incluído. - Um token de sessão roubado serve para algo?
- O access token expira em 15 minutos. O refresh token vive apenas em um cookie HttpOnly, é rotacionado a cada uso e pode ser revogado por
jtino Redis. Operações sensíveis exigem ainda MFA verificado nessa sessão. - Um módulo com falhas pode derrubar a plataforma?
- Não foi desenhado para conseguir. Cada addon roda com limites de memória e CPU, é supervisionado a cada 60 segundos e tem um kill switch que o desativa em 15 segundos ou menos sem deploy. Os demais serviços seguem operando.