FINANÇAS COMPORTAMENTAIS · PSICOLOGIA ECONÔMICA

Por que admin = pode ver tudo quebra em sistemas de denúncia

Quando você olha de fora, um sistema de denúncias anônimas parece um CRUD relativamente comum. Alguém envia um relato. Um…

Quando você olha de fora, um sistema de denúncias anônimas parece um CRUD relativamente comum.

Alguém envia um relato.

Um administrador recebe.

Alguns arquivos são anexados.

O caso passa por alguns status.

No final, alguém encerra.

A primeira modelagem provavelmente fica parecida com isso:

denuncianteinvestigadoradmin

E as permissões:

denunciante   -> cria denúncia, acompanha o próprio casoinvestigador  -> visualiza casos, adiciona informaçõesadmin         -> visualiza tudo, gerencia usuários

Até aqui, tranquilo.

O problema aparece quando chega um caso realmente sensível.

Imagine que um funcionário denuncie o próprio gestor.

Esse gestor também possui perfil administrativo no sistema.

A regra continua sendo:

admin = pode_ver_tudo

?

Obviamente não deveria.

E é aí que um modelo simples de RBAC começa a não ser suficiente.

O papel do usuário não conta a história inteira

RBAC funciona muito bem quando as permissões acompanham funções relativamente estáveis.

Financeiro acessa informações financeiras.

Suporte acessa tickets.

Administrador configura o sistema.

Só que uma investigação sensível introduz uma variável nova:

o contexto daquele caso específico.

Uma pessoa pode ter permissão para investigar denúncias no sistema inteiro e, ao mesmo tempo, não poder acessar uma determinada denúncia.

Algo conceitualmente parecido com:

pode_acessar_caso =    possui_permissao_de_investigacao    && esta_atribuido_ao_caso    && !esta_envolvido_no_caso    && !possui_conflito_de_interesse

O papel não mudou.

O contexto mudou.

Isso começa a empurrar a autorização para uma combinação de:

RBAC+permissões por caso+atribuições+exclusões+conflitos de interesse+overrides auditáveis

O famoso admin começa a perder muito do sentido.

“Pode ver o caso” também é uma permissão ampla demais

Outro atalho tentador é tratar a denúncia inteira como um único objeto protegido.

Mas um caso pode conter coisas bem diferentes:

Caso├── relato inicial├── identidade do denunciante├── anexos├── notas internas├── entrevistas├── análise└── conclusão

A pessoa que pode visualizar o relato necessariamente precisa saber quem denunciou?

Não.

Quem analisa um documento precisa visualizar todas as entrevistas?

Também não necessariamente.

Quem aprova uma decisão final precisa ter acesso irrestrito a todos os dados pessoais coletados?

De novo: não.

Então uma permissão genérica como:

can_view_case

começa a virar algo mais granular:

can_view_reportcan_view_reporter_identitycan_view_evidencecan_view_internal_notescan_add_evidencecan_assign_casecan_close_case

E isso deixa de ser somente um problema de autorização.

Começa a afetar o próprio modelo de dados.

Se a identidade do denunciante é muito mais sensível que o restante do relato, talvez ela não devesse ser simplesmente mais uma propriedade retornada por:

GET /cases/:id

Talvez precise de:

  • política de acesso diferente;
  • trilha de auditoria diferente;
  • armazenamento separado;
  • criptografia ou proteção adicional.

O modelo de dados deveria refletir o nível de sensibilidade dos dados.

Anonimato não é um booleano

É fácil imaginar algo assim:

{  "anonymous": true}

Mas anonimato não é uma propriedade isolada da denúncia.

É uma propriedade do sistema inteiro.

Você pode remover o campo “nome” e ainda coletar:

  • endereço IP;
  • identificadores de analytics;
  • cookies;
  • sessão;
  • dados de autenticação;
  • logs de proxy;
  • fingerprint de dispositivo;
  • informações enviadas para serviços de terceiros.

A interface diz:

Sua denúncia é anônima.

Mas a infraestrutura consegue correlacionar o envio com uma pessoa.

Isso nem sempre acontece por má-fé.

Muitas vezes acontece porque ninguém tratou anonimato como requisito de arquitetura.

Uma pergunta melhor seria:

Quais informações deste fluxo poderiam identificar o denunciante e quais delas realmente precisamos armazenar?

Essa pergunta muda bastante coisa.

Como conversar com alguém que você não identifica?

Outro problema aparece logo depois.

Se o denunciante é anônimo, como o investigador pede mais informações?

Exemplo:

Você lembra aproximadamente quando isso aconteceu?

ou:

Você ainda possui o arquivo original?

Um sistema tradicional resolve comunicação usando uma conta.

E-mail.

Login.

Usuário.

Só que isso pode destruir o anonimato que você estava tentando preservar.

Uma abordagem possível é gerar uma credencial opaca no momento da denúncia:

report_idaccess_token

Algo conceitualmente assim:

POST /reports

Retornando:

{  "report_id": "RPT-8FH2K",  "access_token": "<opaque-secret>"}

Aquele token não representa uma identidade.

Ele apenas comprova que quem possui a credencial pode acessar o lado do denunciante daquele caso.

Você ganha comunicação bidirecional sem exigir uma conta.

Mas aparecem outros problemas:

  • o token é armazenado em plaintext?
  • deveria ser armazenado como hash?
  • pode ser rotacionado?
  • expira?
  • um administrador consegue visualizá-lo?
  • o que acontece se ele vazar?
  • como funciona “recuperação de acesso” quando você deliberadamente não sabe quem é o usuário?

Um requisito aparentemente simples — “permitir acompanhamento anônimo” — vira um problema de autenticação.

Evidência não deveria ser apenas um attachment

Outro ponto interessante é upload de arquivos.

A implementação inicial pode ser:

attachments

Subiu o arquivo, salva no storage e acabou.

Só que, se esse arquivo pode influenciar uma decisão séria, começam outras perguntas:

  • Quem enviou?
  • Quando chegou?
  • Qual era o arquivo original?
  • Ele foi substituído?
  • Quem acessou?
  • Quem fez download?
  • Ele foi descartado da investigação?
  • Por quê?

Um registro pode começar a ficar mais próximo disso:

Evidence--------idcase_idoriginal_filenamestorage_keycontent_hashsubmitted_atsubmitted_bysource_typestatus

E algumas operações importantes podem virar eventos:

EVIDENCE_UPLOADEDEVIDENCE_VIEWEDEVIDENCE_DOWNLOADEDEVIDENCE_RESTRICTEDEVIDENCE_MARKED_IRRELEVANT

Tem um evento que provavelmente não deveria existir:

EVIDENCE_SILENTLY_DISAPPEARED

Esse é um daqueles domínios em que DELETE merece um pouco de desconfiança.

Em vez de:

DELETE FROM evidenceWHERE id = ?;

talvez o domínio precise de algo como:

status = discardedreason = duplicatechanged_by = investigator_42changed_at = ...

O arquivo pode deixar de ser considerado sem que a história da investigação seja apagada.

Isso não significa que todo sistema de denúncias precisa de blockchain, WORM storage ou uma implementação forense completa.

Significa apenas que auditabilidade precisa ser pensada antes do dia em que alguém perguntar “o que aconteceu com esse arquivo?”.

Log de aplicação não é audit log

Esse registro:

GET /api/cases/381 200

pode ser ótimo para observabilidade.

Mas diz pouco sobre uma investigação.

Para uma ação sensível, eu prefiro conseguir reconstruir algo parecido com:

actor: user_827action: viewed_reporter_identitycase: case_381timestamp: ...reason: assigned_investigator

O ponto não é registrar tudo indiscriminadamente.

É registrar as ações que mudam ou expõem informações importantes.

Por exemplo:

  • quem visualizou a identidade;
  • quem adicionou uma evidência;
  • quem alterou a conclusão;
  • quem transferiu o caso;
  • quem usou uma permissão excepcional.

E existe outra questão:

quem pode alterar o próprio audit log?

Se o usuário que realizou uma ação consegue editar silenciosamente o registro daquela ação, a trilha perde boa parte do valor.

open e closed também começam a não servir

Outro problema que parece pequeno é status.

Primeira versão:

openclosed

Depois:

newtriageinvestigatingresolvedclosed

Só que existe uma confusão aí.

Uma coisa é em qual etapa o caso está.

Outra coisa é qual foi a conclusão da investigação.

Um caso pode estar:

workflow_status = closed

e ter como resultado:

outcome = inconclusive

Talvez faça mais sentido separar:

workflow_status:  new  triage  investigating  awaiting_information  decision_pending  closedoutcome:  substantiated  partially_substantiated  unsubstantiated  inconclusive

Por que isso importa?

Porque software também cria comportamento.

Se a interface obriga alguém a escolher apenas:

truefalse

a aplicação está impondo uma interpretação do mundo real.

Nem todo caso consegue ser reduzido a “aconteceu” ou “não aconteceu”.

Às vezes simplesmente não existem elementos suficientes para chegar a uma conclusão.

Um enum aparentemente inocente pode acabar virando política interna.

Conflito de interesse deveria existir no domínio

Em muitas empresas existe uma regra semelhante a:

Se você estiver envolvido no caso, não pode investigá-lo.

Ótimo.

Mas se isso existe somente em um PDF de política interna, o sistema depende de alguém lembrar da regra.

Podemos representar a relação:

CaseParticipant---------------case_iduser_idrelationship

Com relações como:

reportersubjectwitnessinvestigatorreviewerconflicted

E a autorização começa a consultar essa informação:

def can_access_case(user, case):    if not user.has_permission("investigate"):        return False    if case.has_conflict(user):        return False    return case.is_assigned_to(user)

Claro que uma implementação real provavelmente terá mais regras.

Mas a ideia é interessante:

uma regra de governança deixa de depender exclusivamente de comportamento humano e passa a ser reforçada pelo software.

E quando alguém realmente precisar quebrar a regra?

Existe o outro extremo.

Algum dia vai aparecer uma exceção.

Todos os investigadores disponíveis podem estar envolvidos.

Pode existir uma solicitação jurídica.

Pode haver uma situação emergencial.

Bloquear tudo rigidamente pode tornar o sistema impossível de operar.

Mas isso não significa precisar de:

super_admin = god_mode

Uma alternativa é tratar isso como um break-glass access.

Algo como:

override requires:- permissão elevada- justificativa explícita- reautenticação- evento no audit log- segunda aprovação, quando necessário

A ação continua possível.

Só que passa a ser:

intencional, excepcional e rastreável.

Nesse tipo de domínio, um pouco de fricção pode ser uma feature.

Admin da empresa não significa dono de todos os dados

Esse talvez seja um dos pontos mais estranhos para quem está acostumado com SaaS B2B.

Normalmente pensamos:

customer_admin = everything_inside_tenant

Faz sentido para diversos sistemas.

Só que imagine:

O administrador da conta é justamente a pessoa denunciada.

Ou trabalha na área investigada.

Ou comprou o software, mas não deveria ter qualquer participação em investigações.

Nesse cenário:

tenant_owner != unrestricted_case_access

Configurar a organização e acessar dados sensíveis são permissões diferentes.

Esse detalhe muda bastante a forma como um painel administrativo precisa ser desenhado.

A complexidade começa depois do POST /reports

Quando você olha para o produto pela primeira vez, é fácil pensar que a parte difícil é o formulário.

Validação.

Upload.

Anonimato.

Talvez CAPTCHA.

Mas boa parte dos problemas interessantes começa depois:

submission   ↓triage   ↓conflict detection   ↓assignment   ↓evidence preservation   ↓interviews   ↓analysis   ↓decision   ↓anonymous follow-up   ↓retention

Cada seta esconde alguma decisão de autorização.

Cada etapa cria ou manipula informação sensível.

E vários atalhos que seriam aceitáveis em um CRUD comum começam a ficar perigosos.

Hoje eu acho mais útil pensar nesse tipo de sistema não como:

um formulário anônimo com um painel administrativo

mas como:

um sistema de autorização contextual, evidências e auditoria construído ao redor de um workflow de investigação.

O formulário é só onde os dados entram.

Algumas perguntas que eu faria antes de criar o schema

Se tivesse que começar um sistema sensível desse tipo hoje, tentaria responder cedo:

  • Um usuário pode ter permissão global e ainda ser bloqueado em um caso específico?
  • A identidade do denunciante possui uma permissão própria?
  • Uma evidência pode desaparecer sem deixar histórico?
  • É possível conversar com alguém sem descobrir sua identidade?
  • O sistema consegue representar conflitos de interesse?
  • Existe um mecanismo controlado para exceções?
  • Administrar o tenant significa necessariamente poder acessar os casos?
  • Status operacional e conclusão são coisas diferentes no modelo?
  • Daqui seis meses conseguiremos reconstruir por que determinada decisão foi tomada?

Se essas perguntas aparecem depois que tudo já está em produção, normalmente a mudança dói bastante.

Se aparecem antes, provavelmente influenciam schema, autorização, logging e até a forma como o produto é dividido.

No fim, a parte mais simples de um sistema de denúncias pode ser justamente o formulário.

A arquitetura começa a ficar interessante depois que alguém aperta Enviar.


Trabalho como CTO e cofundador da Sigilo, onde lidamos com sistemas de denúncias e feedback organizacional. Boa parte dessas questões surgiu ao pensar nos edge cases que aparecem depois que um relato sensível entra no sistema.

Tenho curiosidade de saber como vocês modelariam isso:

vocês manteriam RBAC + regras de domínio na aplicação ou levariam esse tipo de autorização contextual para uma camada/policy engine separada?

Fonte: TabNews

Perguntas frequentes

Respostas institucionais sobre esta cobertura, fontes e limites editoriais.

Sobre o que trata “Por que admin = pode ver tudo quebra em sistemas…”?
Quando você olha de fora, um sistema de denúncias anônimas parece um CRUD relativamente comum.Alguém envia um relato.Um administrador recebe.Alguns arquivos são anexados.O caso passa por alguns status.No final, alguém encerra.A primeira modelagem provavelmente fica parecida…
O que a matéria explica sobre “O papel do usuário não conta a história inteira”?
RBAC funciona muito bem quando as permissões acompanham funções relativamente estáveis.Financeiro acessa informações financeiras.Suporte acessa tickets.Administrador configura o sistema.Só que uma investigação sensível introduz uma variável nova:o contexto daquele caso específico.Uma pessoa pode ter permissão para investigar denúncias no sistema inteiro e,…
O que a matéria explica sobre “"Pode ver o caso" também é uma permissão ampla demais”?
Outro atalho tentador é tratar a denúncia inteira como um único objeto protegido.Mas um caso pode conter coisas bem diferentes:Caso├── relato inicial├── identidade do denunciante├── anexos├── notas internas├── entrevistas├── análise└── conclusãoA pessoa que pode visualizar o relato necessariamente precisa saber quem denunciou?Não.Quem…
O que a matéria explica sobre “Anonimato não é um booleano”?
É fácil imaginar algo assim:{ "anonymous": true}Mas anonimato não é uma propriedade isolada da denúncia.É uma propriedade do sistema inteiro.Você pode remover o campo "nome" e ainda coletar:endereço IP;identificadores de analytics;cookies;sessão;dados de autenticação;logs de proxy;fingerprint de dispositivo;informações enviadas para serviços de terceiros.A…
Como conversar com alguém que você não identifica?
Outro problema aparece logo depois.Se o denunciante é anônimo, como o investigador pede mais informações?Exemplo:Você lembra aproximadamente quando isso aconteceu?ou:Você ainda possui o arquivo original?Um sistema tradicional resolve comunicação usando uma conta.E-mail.Login.Usuário.Só que isso pode destruir o anonimato que você estava tentando…
Quem edita o conteúdo do Estrato Mente?
A cobertura é produzida e revisada pela equipe editorial do Estrato Mente, com editor-chefe responsável pela linha editorial. Conheça a redação em https://mente.estrato.cc/equipe/.
Quais fontes o Estrato prioriza?
Priorizamos fontes primárias (órgãos oficiais, balanços, estudos revisados, documentos públicos) e cruzamos informações antes da publicação, conforme a política editorial.
Como solicitar correção de uma matéria?
Envie o pedido pela página de Correções (https://mente.estrato.cc/correcoes/) ou Contato (https://mente.estrato.cc/contato/). Erros materiais são corrigidos com registro da atualização.
WhatsApp X LinkedIn
Compartilhar: LinkedIn
Nina Barros

Nina Barros

Nina Barros integra a equipe editorial do Estrato Mente, vertical da rede Estrato, na função de Repórter de Finanças comportamentais. O escopo permanente de cobertura inclui vieses e decisões, com atenção ao leitor brasileiro que busca contexto factual, datas oficiais e implicações práticas. Na produção diária, prioriza fontes primárias (órgãos públicos, balanços, papers e documentos oficiais), cruza pelo menos duas referências independentes quando o tema é contestado e evita manchetes que prometam certeza onde há incerteza. Critérios de qualidade: lead com o fato principal, atribuição clara de autoria da equipe Estrato, atualização com selo quando há mudança material e linguagem acessível sem simplificar demais o risco ou o contexto. Trabalha sob revisão da mesa editorial e do editor-chefe do portal. Matérias YMYL recebem segunda leitura antes da publicação e podem ser atualizadas quando surgem novos dados oficiais. Limites: este perfil descreve o papel editorial na marca Estrato. O conteúdo publicado é informativo e não constitui aconselhamento médico, financeiro, jurídico ou profissional personalizado. Transparência ao leitor: metodologia em /metodologia/, ética em /etica-editorial/, correções em /correcoes/, equipe em /equipe/ e canal em /contato/ ([email protected]). Na página-mãe da rede, a bio ampliada e o arquivo de matérias ficam em estrato.cc/blog/, com link para o arquivo do autor em cada portal.

Deixe um comentário