Transaction Security travando o CPQ: o preço de blindar a API sem saber quem está do outro lado
Um cliente quis bloquear queries pesadas via Shield e descobriu que o CPQ fala a mesma língua que um exportador mal-intencionado

Bloquear consultas de API com mais de 200 registros parece simples até o Transaction Security começar a derrubar as próprias chamadas do Salesforce CPQ. O problema não é a política, é a falta de um identificador confiável para separar tráfego interno de tráfego de risco.
Tem um padrão de projeto que se repete: o time de segurança pede uma política de Transaction Security para impedir exportação em massa via API, alguém configura a condição óbvia (Rows Processed >= 200 combinado com Query, QueryAll, QueryMore, DeleteHard, DeleteSoft), testa, funciona, comemora. Aí o CPQ para de calcular preço em produção e o chat de incidente começa.
O cenário descrito é exatamente esse. A política bloqueia corretamente qualquer operação de query, queryAll ou queryMore que processe 200 registros ou mais, mas o Salesforce CPQ, sendo um managed package que roda em Apex e faz chamadas SOQL internas em volume (cálculo de bundle, lookup de price rules, geração de quote lines), gera eventos de API que batem exatamente nas mesmas condições. Do ponto de vista do ApiEvent, não existe diferença estrutural entre uma query pesada feita por um integrador externo tentando extrair dados e uma query pesada feita pelo próprio CPQ processando uma proposta com 300 linhas de produto.
O problema de fundo, e isso é importante entender antes de sair caçando gambiarra: o objeto ApiEvent não expõe, de forma nativa e confiável, um campo que identifique a origem como "managed package X" ou "CPQ especificamente". Existem campos como Application, ClientVersion, UserAgent e ApiType, mas nenhum deles é populado de forma consistente pelo CPQ como uma assinatura própria. Você pode inspecionar o Event Log File de API e tentar mapear padrões (SESSION_KEY, API_FAMILY, CLIENT_NAME), mas isso é engenharia reversa de comportamento de um pacote gerenciado, não um contrato suportado. Ou seja: qualquer coisa que você construir hoje pode quebrar no próximo release do CPQ sem aviso.
Na prática, quem já bateu de frente com esse tipo de exigência de segurança costuma seguir por três caminhos, cada um com trade-off diferente:
- Excluir por usuário/perfil de integração: se o CPQ (ou o processo que dispara os cálculos) rodar sob um usuário de integração dedicado, dá para usar
Actor.User.ProfileouActor.User.Idcomo condição de exclusão na política. É o caminho mais suportado e mais previsível, mas exige que a arquitetura de execução do CPQ realmente separe esse contexto de usuário do usuário final. - Restringir a política a contextos de API pública/externa: em vez de tentar identificar o CPQ, inverta a lógica e identifique o que você quer bloquear (client IDs de ferramentas de integração conhecidas, Connected Apps específicos, IPs fora do range corporativo). Isso tende a ser mais estável do que tentar fingerprintar um pacote gerenciado.
- Mover a decisão para Connected App Policies e OAuth scopes: em vez de Transaction Security genérica por volume, controlar quem pode fazer bulk query via política de Connected App, com IP restriction e session policies específicas por app conectado. O CPQ, quando executa internamente, não passa pelo mesmo fluxo OAuth de um client externo.
Nenhuma dessas opções é "a resposta oficial da Salesforce", porque não existe hoje um flag documentado tipo Source = 'CPQ' dentro de Transaction Security. É importante ser honesto sobre isso: quem for implementar essa exclusão está tomando uma decisão de arquitetura baseada em comportamento observado, não em contrato suportado, e precisa documentar isso como risco técnico assumido.
Transaction Security é uma ferramenta poderosa, mas ela opera em cima de eventos de API, não em cima de intenção de negócio. Qualquer processo interno que use volume de API alto (CPQ, Billing, integrações batch, Data Loader corporativo) corre o risco de ser pego pela mesma rede que você desenhou para pescar exfiltração de dados. Isso vira um problema real de governança quando o time de segurança e o time de aplicação não conversam antes de a política ir para produção.
Para quem arquiteta ambientes com Shield, esse caso é um recado direto: política de segurança de API precisa ser desenhada em conjunto com o mapeamento de todos os processos automatizados que rodam volume alto, não só depois que algo quebra.
Não existe, até o momento, um campo suportado e documentado no ApiEvent que identifique de forma nativa e estável chamadas originadas pelo Salesforce CPQ. As soluções por exclusão de usuário de integração ou de Connected App são práticas de mercado, não uma feature oficial para esse fim específico. Trate qualquer implementação nesse sentido como decisão de arquitetura sob risco, sujeita a revalidação em cada release do CPQ.
Antes de publicar qualquer política de Transaction Security baseada em volume, faça o inventário de todos os processos automatizados (managed packages, integrações batch, Flows com callout, jobs agendados) que fazem operações de API em escala. Depois, garanta que esses processos rodem sob um usuário de integração dedicado e use Actor.User.Id ou Actor.User.Profile como condição de exclusão explícita na política, em vez de tentar identificar o CPQ pelo comportamento da query.
Se a exigência de segurança vier de auditoria externa, documente a decisão de exclusão por usuário como controle compensatório e monitore o Event Monitoring regularmente para garantir que esse usuário de integração não seja usado para nada fora do escopo esperado.
Cuidado com a tentação de tentar fingerprintar o CPQ usando UserAgent ou ClientVersion observados hoje. Esse comportamento não é contrato suportado e pode mudar sem aviso em qualquer release, o que reabriria o incidente de produção exatamente na pior hora, durante o fechamento de uma proposta grande.
Outro ponto: se a política de Transaction Security dispara uma ação de bloqueio (Block) em vez de apenas notificação, teste extensivamente em sandbox com carga real de CPQ antes de promover para produção. Bloqueio silencioso de cálculo de quote é o tipo de bug que só aparece quando o time comercial já está no telefone com o cliente.
Este conteúdo foi reescrito e analisado editorialmente em português a partir de informações públicas da fonte indicada.