*, *::before, *::after { box-sizing: border-box; }
:root {
–orange: #F47721;
–text: #1A1D2E;
–text2: #4A5070;
–card: #F8F9FC;
–border: #D8DCE8;
–green: #1A7F4B;
–yellow: #8B6A00;
–red: #B91C1C;
–red-bg: #FFF1F2;
–red-acc: #DC2626;
–amb-acc: #D97706;
–radius: 8px;
–font: -apple-system, BlinkMacSystemFont, “Segoe UI”, system-ui, sans-serif;
–mono: “SF Mono”, “Fira Code”, Menlo, Consolas, monospace;
}
body { font-family: var(–font); color: var(–text); line-height: 1.65; max-width: 780px; margin: 0 auto; padding: 0 20px 80px; }
h1 { font-size: 2rem; font-weight: 800; line-height: 1.2; margin: 0 0 .5rem; text-wrap: balance; }
h2 { font-size: 1.3rem; font-weight: 700; margin: 2.5rem 0 .75rem; line-height: 1.3; }
h3 { font-size: 1.05rem; font-weight: 700; margin: 1.75rem 0 .5rem; }
p { margin: 0 0 1rem; }
ul, ol { margin: 0 0 1rem; padding-left: 1.4rem; }
li { margin-bottom: .4rem; }
strong { font-weight: 700; }
code { font-family: var(–mono); font-size: .84em; background: #EEF0F8; padding: 2px 6px; border-radius: 3px; white-space: nowrap; }
pre { font-family: var(–mono); font-size: .82em; background: #1A1D2E; color: #E8ECF5; padding: 14px 16px; border-radius: var(–radius); overflow-x: auto; margin: 1rem 0; line-height: 1.6; }
a { color: var(–orange); text-decoration: none; }
a:hover { text-decoration: underline; }
.breadcrumb { font-size: .78rem; color: var(–text2); margin-bottom: 1.5rem; }
.breadcrumb a { color: var(–text2); }
.breadcrumb span { margin: 0 .4rem; }
.meta-bar { display: flex; gap: 16px; flex-wrap: wrap; font-size: .78rem; color: var(–text2); margin-bottom: 2rem; padding-bottom: 1rem; border-bottom: 1px solid var(–border); }
.meta-bar .author { font-weight: 600; color: var(–text); }
.lead { font-size: 1.1rem; color: var(–text2); line-height: 1.65; margin-bottom: 1.5rem; }
.cta-box { background: linear-gradient(135deg,#FFF3E8,#FFF8F0); border: 1px solid rgba(244,119,33,.3); border-left: 4px solid var(–orange); border-radius: var(–radius); padding: 18px 20px; margin: 2rem 0; }
.cta-box p { margin: 0 0 .5rem; font-size: .9rem; }
.cta-btn { display: inline-block; background: var(–orange); color: #fff; padding: 10px 20px; border-radius: 6px; font-weight: 700; font-size: .88rem; text-decoration: none; margin-top: 10px; }
.cta-btn:hover { background: #D96A1E; text-decoration: none; }
.toc { background: var(–card); border: 1px solid var(–border); border-radius: var(–radius); padding: 18px 22px; margin: 2rem 0; }
.toc h2 { margin: 0 0 .75rem; font-size: 1rem; }
.toc ol { margin: 0; padding-left: 1.2rem; }
.toc li { margin-bottom: .3rem; font-size: .88rem; }
.toc a { color: var(–text2); }
.tbl-wrap { overflow-x: auto; margin: 1.5rem 0; border-radius: var(–radius); border: 1px solid var(–border); }
table { width: 100%; border-collapse: collapse; font-size: .85rem; }
th { background: #EEF0F8; padding: 9px 12px; text-align: left; font-weight: 700; font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; color: var(–text2); border-bottom: 1px solid var(–border); white-space: nowrap; }
td { padding: 9px 12px; border-bottom: 1px solid var(–border); vertical-align: top; }
tbody tr:last-child td { border-bottom: none; }
tbody tr:nth-child(even) td { background: #FAFBFE; }
.note { padding: 13px 16px; border-radius: var(–radius); margin: 1.5rem 0; font-size: .88rem; line-height: 1.55; }
.note p { margin: 0; }
.note-warn { background: #FFFBEB; border-left: 4px solid #D97706; }
.note-info { background: #EFF6FF; border-left: 4px solid #3B82F6; }
.note-tech { background: #F0FDF4; border-left: 4px solid #16A34A; }
.note-danger { background: #FFF1F2; border-left: 4px solid #B91C1C; }
/* ── Threat cards ─────────────────────────────────────────────── */
.threat-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin: 1.5rem 0;
}
.threat-card {
border: 1px solid var(–border);
border-left: 3px solid var(–tc-accent, var(–border));
border-radius: 0 var(–radius) var(–radius) 0;
padding: 14px 16px;
display: flex;
flex-direction: column;
gap: 6px;
}
.tc-alto { –tc-accent: var(–red-acc); }
.tc-med { –tc-accent: var(–amb-acc); }
.threat-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.threat-title-row {
display: flex;
align-items: center;
gap: 7px;
min-width: 0;
}
.threat-title-row svg {
flex-shrink: 0;
color: var(–orange);
}
.threat-name {
font-weight: 700;
font-size: .88rem;
line-height: 1.3;
}
.threat-sev {
font-size: .68rem;
font-weight: 700;
letter-spacing: .06em;
text-transform: uppercase;
display: flex;
align-items: center;
gap: 4px;
flex-shrink: 0;
white-space: nowrap;
}
.threat-sev::before {
content: ”;
display: block;
width: 5px;
height: 5px;
border-radius: 50%;
background: currentColor;
}
.sev-alto { color: var(–red-acc); }
.sev-med { color: var(–amb-acc); }
.threat-desc {
font-size: .79rem;
color: var(–text2);
line-height: 1.55;
margin: 0;
}
/* ── Layer stack ──────────────────────────────────────────────── */
.layer-stack { display: flex; flex-direction: column; gap: 0; margin: 1.5rem 0; border: 1px solid var(–border); border-radius: var(–radius); overflow: hidden; }
.layer-row { display: flex; align-items: center; gap: 14px; padding: 11px 16px; border-bottom: 1px solid var(–border); }
.layer-row:last-child { border-bottom: none; }
.layer-num { font-variant-numeric: tabular-nums; font-size: .72rem; font-weight: 800; letter-spacing: .04em; color: #fff; background: var(–ln-bg, #1A1D2E); width: 22px; height: 22px; border-radius: 4px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.layer-label { font-weight: 700; font-size: .88rem; min-width: 140px; flex-shrink: 0; }
.layer-desc { font-size: .82rem; color: var(–text2); }
.ln-1 { –ln-bg: #DC2626; }
.ln-2 { –ln-bg: #D97706; }
.ln-3 { –ln-bg: #1D4ED8; }
.ln-4 { –ln-bg: #16A34A; }
.ln-5 { –ln-bg: #7C3AED; }
/* ── Checklist / FAQ / misc ───────────────────────────────────── */
.checklist { list-style: none; padding: 0; }
.checklist li { padding: .4rem 0 .4rem 1.8rem; position: relative; border-bottom: 1px solid var(–border); font-size: .9rem; }
.checklist li::before { content: “✓”; position: absolute; left: 0; color: var(–green); font-weight: 700; }
.checklist li:last-child { border-bottom: none; }
.faq { margin: 1.5rem 0; }
.faq-item { border-bottom: 1px solid var(–border); }
.faq-q { font-weight: 700; font-size: .95rem; padding: 14px 0 10px; cursor: pointer; display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.faq-q::after { content: “+”; font-size: 1.2rem; color: var(–orange); flex-shrink: 0; }
.faq-item.open .faq-q::after { content: “−”; }
.faq-a { display: none; font-size: .88rem; color: var(–text2); padding-bottom: 14px; line-height: 1.6; }
.faq-item.open .faq-a { display: block; }
.divider { border: none; border-top: 1px solid var(–border); margin: 2rem 0; }
.source { font-size: .72rem; color: var(–text2); margin-top: -.5rem; margin-bottom: 1rem; }
.related-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 1.5rem 0; }
.related-card { border: 1px solid var(–border); border-radius: var(–radius); padding: 12px 14px; }
.related-card a { font-weight: 600; font-size: .9rem; color: var(–text); display: block; margin-bottom: 4px; }
.related-card span { font-size: .78rem; color: var(–text2); }
@media (max-width: 600px) {
h1 { font-size: 1.5rem; }
.threat-grid, .related-grid { grid-template-columns: 1fr; }
.layer-label { min-width: 100px; }
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme=”light”]) {
–text: #E8ECF5; –text2: #9AA0BC; –card: #1C2030; –border: #2A2F45;
–red-bg: #2D0A0A; –red-acc: #F87171; –amb-acc: #FCD34D;
}
body { background: #0F1117; }
code { background: #22273A; color: #E8ECF5; }
th { background: #1C2030; }
tbody tr:nth-child(even) td { background: rgba(255,255,255,.02); }
.toc, .related-card { background: #1C2030; }
.threat-card { background: #14172A; }
.layer-row { background: transparent; }
.note-warn { background: #2D2000; }
.note-info { background: #0A1628; }
.note-tech { background: #0A1F12; }
.note-danger { background: #2D0A0A; }
.cta-box { background: linear-gradient(135deg,#2D1A08,#3D2410); }
}
[data-theme=”light”] body { background: #fff; }
[data-theme=”dark”] body { background: #0F1117; }
<!– SVG icon defs (reused via ) –>
Segurança em infraestrutura de IA: do modelo à API
Revisão técnica: [Revisor]·
Publicado em agosto de 2026·
13 min de leitura
Colocar um LLM em produção cria uma superfície de ataque que não existia no software tradicional: prompt injection, exfiltração de dados de treinamento, APIs de inferência expostas e modelos com acesso irrestrito a ferramentas. Este guia cobre as camadas de segurança — rede, modelo, API e dados — com controles práticos para cada uma.
Infraestrutura de IA em ambiente privado e isolado.
A Adentro oferece GPU dedicada em rede isolada, sem compartilhamento de hardware com outros clientes. Seus modelos, seus dados, sua infraestrutura.
1. Principais ameaças em infraestrutura de IA
A segurança em IA tem vetores específicos que se somam aos riscos tradicionais de infraestrutura. Conhecer cada ameaça é o ponto de partida para escolher os controles certos.
Prompt Injection
Alto
Entrada maliciosa manipula o comportamento do modelo — ignora instruções do sistema, extrai dados ou executa ações não autorizadas via ferramentas (function calling).
Exfiltração de dados de treinamento
Alto
Modelos fine-tunados com dados sensíveis podem memorizá-los e revelá-los em resposta a prompts específicos. Risco maior com dados PII e financeiros.
API de inferência exposta
Alto
Endpoint sem autenticação ou rate limiting permite uso não autorizado, abuso de recursos e acesso indireto ao modelo e ao contexto do sistema prompt.
Credenciais em dados de treinamento
Alto
Datasets com chaves de API, senhas ou tokens que o modelo aprende e pode reproduzir. Risco frequente em datasets raspados da web sem sanitização.
Acesso irrestrito a ferramentas
Alto
Modelos com function calling (banco de dados, e-mail, APIs externas) sem validação de parâmetros podem executar ações destrutivas via prompt injection.
Modelo comprometido (supply chain)
Médio
Modelos obtidos de repositórios não verificados podem conter backdoors ou comportamentos adversariais. Pesos de modelos são difíceis de auditar.
Compartilhamento de GPU (side-channel)
Médio
Em ambientes multi-tenant com GPUs compartilhadas, ataques de side-channel podem vazar informações entre processos. Risco relevante em nuvem pública.
Logging sem sanitização
Médio
Logs de inferência com prompts e respostas em claro expõem dados sensíveis dos usuários. Risco de compliance especialmente relevante sob LGPD.
2. As 5 camadas de segurança para IA em produção
Rede e isolamento
GPU em rede privada, sem acesso público direto, segmentação de ambientes (dev / prod / fine-tuning)
Modelo
Verificação de integridade dos pesos, system prompt hardening, guardrails de output
API de inferência
Autenticação, rate limiting, validação de input, timeout de contexto, TLS obrigatório
Dados
Sanitização de datasets, anonimização de PII, criptografia em repouso, adequação LGPD
Acesso e auditoria
RBAC, MFA, logs de inferência, retenção de evidências, revisão periódica de acessos
3. Camada 1: rede e isolamento de infraestrutura
O controle mais eficaz em segurança de infraestrutura é reduzir a superfície de ataque antes de qualquer outra medida. Uma GPU que não é acessível diretamente da internet não pode ser atacada diretamente.
Isolamento de rede
- GPU em VPC/rede privada: o servidor de GPU nunca deve ter IP público. O acesso deve ser via VPN, bastion host ou load balancer com TLS terminado.
- Firewall de entrada restritivo: apenas as portas necessárias abertas — tipicamente 8000 (vLLM), 9400 (DCGM Prometheus) e 22 (SSH, somente da rede de gestão).
- Segmentação por ambiente: GPU de produção em sub-rede separada da GPU de fine-tuning e de desenvolvimento. Um comprometimento em dev não deve alcançar prod.
GPU dedicada vs. compartilhada
| Aspecto | GPU dedicada | GPU compartilhada (nuvem pública) |
|---|---|---|
| Isolamento de hardware | Hardware exclusivo | Hypervisor compartilhado |
| Risco de side-channel | Sem risco | Risco teórico entre tenants |
| Dados em memória GPU | Apenas seus dados | Partilha de VRAM física |
| Auditoria de acesso físico | Controlável | Dependente do provedor |
| Custo | Previsível (mensal fixo) | Variável (por hora) |
Para cargas com dados sensíveis (PII, financeiros, saúde, dados cobertos pela LGPD), GPU dedicada com hardware exclusivo elimina categoricamente os riscos de side-channel e co-residência que existem em ambientes de GPU compartilhada.
4. Camada 2: segurança do modelo
Verificação de integridade de modelos
Modelos baixados de repositórios públicos devem ter seus hashes verificados antes do uso em produção. A Hugging Face publica hashes SHA256 dos pesos em cada repositório.
# Verificar hash SHA256 dos pesos após download sha256sum model.safetensors # Comparar com o hash publicado pelo repositório oficial # Qualquer divergência indica arquivo corrompido ou substituído
System prompt hardening
O system prompt é a primeira linha de defesa contra prompt injection. Princípios:
- Instruções explícitas de recusa: defina o que o modelo deve se recusar a fazer — não assuma que ele inferirá os limites corretos.
- Separação de contextos: nunca injete dados não confiáveis (entrada do usuário, resultados de ferramentas) diretamente no system prompt. Mantenha o system prompt imutável.
- Não revele o system prompt: instrua o modelo a não reproduzir o conteúdo do system prompt — mesmo disfarçado de “debug” ou “repetição”.
Guardrails de output
- Detecção de PII no output: bloquear ou mascarar CPF, e-mail e número de cartão na resposta antes de entregar ao cliente.
- Limite de contexto por sessão: restringir o histórico de conversa injetado no contexto. Um histórico longo é um vetor para extrair dados de sessões anteriores.
- Validação de chamadas de ferramentas: se o modelo tem acesso a function calling, valide todos os parâmetros antes de executá-los — nunca execute comandos gerados pelo modelo sem sanitização.
Prompt injection via conteúdo externo: se o modelo lê URLs, documentos ou e-mails e toma ações com base nesse conteúdo, qualquer um que controle esse conteúdo pode executar comandos via o modelo. Trate todo conteúdo externo como não confiável — valide ações antes de executar.
5. Camada 3: API de inferência
A API de inferência é o principal ponto de contato entre o mundo externo e o modelo. Um endpoint mal configurado expõe tanto o modelo quanto os dados que transitam por ele.
Autenticação e autorização
- API keys com escopo: cada cliente ou aplicação deve ter sua própria API key. Nunca use uma key compartilhada — ela não pode ser revogada seletivamente.
- JWT com claims de permissão: para APIs expostas a usuários finais, use JWT com claims que definam quais modelos e parâmetros o usuário pode acessar.
- Bloqueio do endpoint de administração: endpoints como
/v1/modelse/metricsnunca devem ser públicos — restringir à rede de gestão.
Rate limiting e throttling
| Nível | Controle | Proteção |
|---|---|---|
| Por IP | Max 10 req/min por IP | Ataques de força bruta e abuso por automação |
| Por API key | Max tokens/dia configurável | Consumo excessivo por key comprometida |
| Por sessão | Max 50 turnos por sessão | Ataques de contexto longo para extração de dados |
| Por tamanho de input | Max 32.000 tokens por requisição | DoS via inputs gigantes que esgotam VRAM |
TLS e transmissão segura
# Configuração nginx reverso com TLS + headers de segurança
server {
listen 443 ssl;
ssl_certificate /etc/ssl/certs/api.pem;
ssl_certificate_key /etc/ssl/private/api.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Content-Type-Options nosniff;
location /v1/ {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr;
}
# Bloquear acesso externo a endpoints internos
location ~ ^/(metrics|docs|health)$ {
allow 10.0.0.0/8;
deny all;
proxy_pass http://127.0.0.1:8000;
}
}
6. Camada 4: dados de treinamento e LGPD
Dados usados em fine-tuning têm ciclo de vida de segurança próprio: coleta, armazenamento, uso no treinamento e descarte.
Sanitização de datasets
- Remoção de PII antes do treinamento: CPF, CNPJ, e-mail, telefone, número de cartão e endereços devem ser removidos ou mascarados. Ferramentas como Microsoft Presidio fazem detecção automática.
- Detecção de credenciais: escanear datasets por padrões de API keys, senhas e tokens antes do uso. A ferramenta
trufflehoge regex por padrão de provedor cobrem os casos mais comuns. - Deduplicação: dados duplicados aumentam o risco de memorização de exemplos específicos. Deduplicar o dataset reduz a probabilidade de reprodução de dados sensíveis.
LGPD e dados pessoais em IA
| Aspecto LGPD | Implicação em IA | Controle recomendado |
|---|---|---|
| Base legal para tratamento | Fine-tuning com dados de clientes requer base legal (consentimento, legítimo interesse, contrato) | Documentar base legal antes de incluir dados no dataset |
| Direito de exclusão | Dados de treinamento são incorporados aos pesos — não podem ser removidos cirurgicamente | Manter registro de dados por versão de modelo; avaliar retreinamento em casos críticos |
| Minimização de dados | Usar apenas os dados necessários para a tarefa | Definir escopo antes da coleta; remover campos não utilizados |
| Transferência internacional | Treinamento em nuvem estrangeira exige cláusulas contratuais específicas | Preferir infraestrutura no Brasil para dados cobertos pela LGPD |
Referência: LGPD (Lei 13.709/2018) e guias ANPD, agosto de 2026. Este conteúdo é informacional — consulte assessoria jurídica para avaliação de conformidade específica.
Criptografia de dados em repouso
- Pesos do modelo: armazenar em volumes criptografados (LUKS no Linux). Pesos de modelos fine-tunados com dados proprietários têm valor de negócio e devem ser protegidos como ativos.
- Datasets: criptografar com AES-256. Controlar acesso com chaves gerenciadas (HashiCorp Vault ou AWS KMS para ambientes híbridos).
- Backups: aplicar mesma proteção dos dados originais — um backup em claro é tão vulnerável quanto os dados originais.
7. Camada 5: controle de acesso e auditoria
RBAC para infraestrutura de IA
| Papel | Permissões | Permissões negadas |
|---|---|---|
| Operador de produção | Monitorar GPU, reiniciar serviços, visualizar logs (sem prompts) | Acessar dados de treinamento, modificar pesos, ver conteúdo de sessões |
| Engenheiro de ML | Fine-tuning, experimentação, acesso a datasets em ambiente isolado | Acesso a prod com dados de usuários reais, chaves de API de produção |
| Desenvolvedor de aplicação | Chamar a API de inferência com sua API key, ver suas próprias métricas | Acesso ao servidor de GPU, pesos do modelo, logs de outros clientes |
| Admin de infraestrutura | Configuração de rede, firewall, backup | Acesso ao conteúdo de sessões, dados de treinamento (separação de deveres) |
Logs de inferência e auditoria
- O que logar: timestamp, API key (hash), tokens de prompt e resposta, latência, modelo, status. Nunca o conteúdo do prompt em logs de acesso geral.
- Logs de conteúdo: quando a regulação exige retenção de conteúdo, logar em destino separado com acesso restrito, criptografado e retenção definida.
- Retenção e descarte: 90 dias é um ponto de partida razoável para logs de acesso. Logs com PII exigem prazo definido conforme a base legal da LGPD.
MFA e acesso ao servidor
- SSH apenas via chave pública — desabilitar autenticação por senha (
PasswordAuthentication nono sshd_config). - MFA obrigatório para todos os acessos administrativos ao servidor de GPU.
- Revisão trimestral de acessos — revogar acessos de ex-colaboradores no mesmo dia da saída.
8. Checklist de segurança para IA em produção
- GPU em rede privada — sem IP público direto
- Firewall de entrada: apenas portas necessárias abertas
- Ambientes dev / staging / prod em sub-redes separadas
- Hash dos pesos do modelo verificado antes de deploy
- System prompt hardened contra prompt injection
- Guardrails de output: detecção de PII na resposta
- API com autenticação obrigatória (sem endpoint público sem auth)
- Rate limiting por IP, por API key e por tamanho de input
- TLS 1.2+ em todos os endpoints públicos
- Endpoints internos (metrics, docs, health) bloqueados externamente
- Dataset de fine-tuning sanitizado (PII, credenciais, deduplicação)
- Base legal LGPD documentada para dados pessoais em treinamento
- Pesos e datasets criptografados em repouso
- RBAC definido com separação de deveres
- SSH por chave pública — senha desabilitada
- MFA para todos os acessos administrativos
- Política de retenção e descarte de logs definida
- Revisão trimestral de acessos
Conteúdos relacionados
Perguntas frequentes
{
“@context”: “https://schema.org”,
“@graph”: [
{
“@type”: “Article”,
“headline”: “Segurança em infraestrutura de IA: do modelo à API”,
“description”: “Como proteger infraestrutura de IA: isolamento de GPU, controle de acesso a modelos, segurança de APIs de inferência e proteção de dados de treinamento.”,
“url”: “https://adentro.com.br/seguranca-infraestrutura-ia/”,
“datePublished”: “2026-08-11”,
“dateModified”: “2026-08-11”,
“publisher”: { “@type”: “Organization”, “name”: “Adentro”, “url”: “https://adentro.com.br” },
“inLanguage”: “pt-BR”
},
{
“@type”: “BreadcrumbList”,
“itemListElement”: [
{“@type”:”ListItem”,”position”:1,”name”:”Adentro”,”item”:”https://adentro.com.br”},
{“@type”:”ListItem”,”position”:2,”name”:”Blog”,”item”:”https://adentro.com.br/blog/”},
{“@type”:”ListItem”,”position”:3,”name”:”Infraestrutura para IA”,”item”:”https://adentro.com.br/infraestrutura-para-inteligencia-artificial/”},
{“@type”:”ListItem”,”position”:4,”name”:”Segurança em infraestrutura de IA”,”item”:”https://adentro.com.br/seguranca-infraestrutura-ia/”}
]
},
{
“@type”: “FAQPage”,
“mainEntity”: [
{
“@type”: “Question”,
“name”: “Prompt injection é realmente uma ameaça relevante em produção?”,
“acceptedAnswer”: { “@type”: “Answer”, “text”: “Sim, especialmente em sistemas com function calling. Um prompt injection bem-sucedido permite executar ações como enviar e-mails, acessar bancos de dados ou fazer chamadas de API. Sistemas de RAG que buscam conteúdo externo são particularmente vulneráveis.” }
},
{
“@type”: “Question”,
“name”: “Como tratar o direito de exclusão da LGPD quando os dados foram usados em fine-tuning?”,
“acceptedAnswer”: { “@type”: “Answer”, “text”: “Dados de fine-tuning são incorporados nos pesos de forma difusa — não é possível removê-los cirurgicamente. Manter registro exato dos dados por versão de modelo é essencial, além de avaliar a necessidade de retreinamento em casos críticos.” }
}
]
}
]
}
document.querySelectorAll(‘.faq-q’).forEach(q => q.addEventListener(‘click’, () => q.parentElement.classList.toggle(‘open’)));