A segurança não é uma camada adicionada depois, é o centro da arquitetura. O isolamento de dados, a separação de identidade e a gravação idempotente estão impressos na camada mais profunda do código — não é uma configuração que possa ser desligada, é a forma como o sistema funciona.
Isolamento em nível de linha
Gravação idempotente
Consulta parametrizada
Isolamento por loopback
Isolamento de dados
Isolamento em nível de linha — fail-closed
Em cada tabela com escopo de inquilino, o Row-Level Security FORCE do PostgreSQL está ativo; a política vincula cada linha à condição "tenant_id = current_setting('app.current_tenant')".
Uma consulta que chega sem o context de tenant definido retorna zero linhas — nem sequer um erro, apenas silenciosamente vazia. Ver os dados de uma clínica com a sessão de outra é arquiteturalmente impossível.
O teste de isolamento entre tenants é obrigatoriamente verde na integração contínua (CI); se estiver vermelho, o código não é mesclado.
Gravação atômica
Identidade local à transação, operação atômica
A identidade do inquilino é definida NO INÍCIO da transaction em cada operação de escrita e é válida apenas durante essa transaction; não fica presa ao pool de conexões nem vaza para outras requisições.
As operações multientidade (fatura + item + pagamento + baixa de estoque) são atômicas dentro de uma única transação: ou tudo é gravado em conjunto, ou nada é. Não há registro pela metade ou inconsistente.
Permissão
Permissão baseada em função (RBAC) imposta no servidor
O controle de permissão é feito na camada da API; nunca se confia no cliente ou na interface. Ocultar um menu no navegador diz respeito apenas à aparência — a decisão real está no servidor.
As mutações do núcleo (Fase 1) são protegidas conforme as funções de admin, recepção e médico. Mesmo que uma função não autorizada chame o endpoint, a requisição é recusada.
Proteção contra repetição
Gravação idempotente — sem operação em duplicidade
Cada requisição de gravação carrega uma Idempotency-Key; o bloqueio no lado do servidor impede uma segunda operação que chegue com a mesma chave.
Mesmo quando a rede cai ou o cliente reenvia a mesma solicitação, não é criada uma segunda cobrança ou fatura. O resultado é sempre único e previsível.
Segurança de consulta
SQL injection impossível — consulta parametrizada
Todas as consultas ao banco de dados são instruções totalmente parametrizadas, geradas em tempo de compilação com o sqlc. Não há uma única linha na base de código que construa SQL concatenando strings manualmente com entrada do usuário.
Isso elimina estruturalmente a classe de ataques de SQL injection — não depende de "filtragem" ou "escape", mas da forma como a consulta é construída.
Superfície de rede
Isolamento por loopback — núcleo fechado ao exterior
A API central escuta apenas 127.0.0.1 (loopback). Qualquer tentativa de vincular a 0.0.0.0 ou a um IP público é rejeitada na inicialização; a central nunca fica exposta à internet, em hipótese alguma.
A única superfície pública é uma porta fina (BFF): não retém regras de negócio além de sessão, renderização e CSRF. O navegador nunca consegue ver nem endereçar diretamente a API central.
Identidade e sessão
Senha argon2id, chave de sessão opaca
As senhas são geradas com hash usando argon2id, um padrão do setor resistente à memória; hashes fracos ou em texto simples não são utilizados.
As chaves de sessão são valores opacos criptograficamente aleatórios de 32 bytes, armazenados no Redis e expirados por TTL. Ao navegador só se reflete um cookie HttpOnly + Secure + SameSite; a chave nunca é exposta ao JavaScript.
Auditoria
Log de auditoria imutável (append-only)
As operações importantes são gravadas no log de auditoria append-only dentro da MESMA transação que as dispara. Se a operação for revertida, o log de auditoria também não é gravado — os dois são inseparáveis.
A permissão de UPDATE/DELETE foi retirada da tabela de auditoria; os registros não podem ser editados nem excluídos posteriormente. O histórico permanece como está.
Privacidade
Mascaramento de dados sensíveis
TCKN, senha, chave de sessão e dados de saúde não entram nos logs de forma alguma. Esses campos são mascarados até mesmo nas saídas de depuração.
Quando necessário, os campos sensíveis são criptografados em nível de coluna. Os dados de saúde de natureza especial são protegidos por regras embutidas desde o início do projeto.
Integridade monetária
Segurança monetária — numeric, lançamento reverso
O dinheiro é mantido em todos os lugares como numeric(14,2); não se faz cálculo monetário com float. O arredondamento ocorre em um único ponto, no servidor — não há deslocamento de centavos nem diferença de arredondamento.
O cancelamento e o estorno são processados como um lançamento reverso, em vez de excluir o registro. O saldo de conta corrente não é escrito manualmente; é sempre derivado do total de faturas e pagamentos. O histórico não é corrompido.
Transferência
Segurança de transporte e navegador
Todo o tráfego é transportado por HTTPS/TLS e o HSTS está ativo; o navegador estabelece a conexão apenas de forma criptografada.
Uma política rígida de segurança de conteúdo (CSP) bloqueia scripts inline; X-Frame-Options DENY previne clickjacking e X-Content-Type-Options nosniff previne a confusão de tipos. Referrer-Policy e Permissions-Policy também são aplicadas.
Importante
Separação de tier de identidade + plano de administração separado
Usuário da clínica, portal do paciente e operador da plataforma são tiers de identidade SEPARADOS: cabeçalho separado, espaço de sessão separado. A chave de um tier não funciona em outro — os limites de autorização são estritamente separados.
Os endpoints de plataforma e administração (provisionamento de inquilino, faturamento, gestão de automação/plugins, geração de chaves de API) NÃO ESTÃO presentes na API pública.
Essas funções operam em um plano de controle separado, interno, com um padrão de identidade diferente (chave de administração dedicada); ele não é acessível nem detectável do exterior. Assim, a superfície de ataque é reduzida de forma significativa.
COMO FUNCIONA
Transação única, isolamento fail-closed
O fluxo conceitual abaixo mostra como cada gravação é bloqueada ao tenant e permanece idempotente. É apenas ilustrativo.
# 1) O contexto do inquilino é estabelecido NO INÍCIO da transaction (exclusivo apenas dessa tx)
BEGIN;
SELECT set_config('app.current_tenant', :session_tenant_id, true);
# 2) Bloqueio de Idempotency-Key — a mesma chave não gera uma segunda operaçãoSELECT lock_idempotency(:idempotency_key);
# 3) Escrita de múltiplas entidades — todas atômicas em uma única txINSERT INTO invoices ...; # RLS: tenant_id coberto automaticamenteINSERT INTO payments ...;
INSERT INTO audit_log ...; # append-only, mesma tx
COMMIT;
# Se o context não for definido, a política RLS não retorna nenhuma linha:SELECT * FROM patients; --> 0 linhas (não é erro, silenciosamente vazio)
Verificável de forma independente
Parte da segurança de transporte pode ser observada externamente: você mesmo pode inspecionar o certificado HTTPS/TLS da sua conexão e cabeçalhos de segurança de resposta, como HSTS e a política de segurança de conteúdo, pelas ferramentas de desenvolvedor do seu navegador. Nossas afirmações baseiam-se em controles de arquitetura, não em frases de marketing.
Tem alguma dúvida sobre a arquitetura de segurança?
Nossa equipe terá prazer em conversar com você sobre os detalhes técnicos e seus requisitos de conformidade.