Pular para conteúdo

Escaneamento de Formulários

Visão Geral

O sistema de Form Scanning do Complyr detecta e categoriza automaticamente campos de formulários que coletam dados pessoais, ajudando sua empresa a manter compliance com a LGPD (Lei Geral de Proteção de Dados). O sistema identifica campos sensíveis como CPF, email, telefone, endereço, e alerta quando há coleta de dados sem consentimento adequado.

Características

  • ✅ Detecção automática de campos de formulário
  • ✅ Categorização de dados pessoais (CPF, email, telefone, etc.)
  • ✅ Validação de consentimento antes da coleta
  • ✅ Alertas de compliance LGPD
  • ✅ Bloqueio de submissão sem consentimento
  • ✅ Relatórios de auditoria
  • ✅ Integração com sistema de consentimento
  • ✅ Suporte a formulários dinâmicos (AJAX/React)

Casos de Uso

  1. Auditoria de Formulários - Identificar quais dados pessoais são coletados
  2. Compliance LGPD - Garantir consentimento antes da coleta (Art. 7º)
  3. Prevenção de Vazamentos - Detectar campos sensíveis não autorizados
  4. Documentação - Manter registro de coleta de dados para relatórios ANPD

Conceitos Fundamentais

Categorias de Dados Pessoais (LGPD)

O Complyr categoriza automaticamente campos de formulário baseado na LGPD:

Dados Pessoais Comuns (Art. 5º, I): - Nome completo - Email - Telefone - Endereço - Data de nascimento

Dados Pessoais Sensíveis (Art. 5º, II): - CPF/CNPJ - RG - CNH - Dados de saúde - Orientação sexual - Dados biométricos - Dados financeiros

Dados de Crianças e Adolescentes (Art. 14): - Formulários direcionados a menores de 18 anos - Requer consentimento parental

Antes de coletar dados, é necessário validar a base legal (Art. 7º LGPD):

  1. Consentimento - Usuário autorizou expressamente
  2. Contrato - Necessário para execução de contrato
  3. Obrigação Legal - Exigido por lei
  4. Legítimo Interesse - Interesse legítimo do controlador

Instalação e Configuração

Instalação Básica

<!-- Incluir script do Complyr com form scanning habilitado -->
<script
  src="https://app.complyr.com.br/tag/js"
  data-workspace-id="SEU_WORKSPACE_ID"
  data-complyr-script
  data-enable-form-scanning="true"
  async
  defer>
</script>

Configuração Avançada

window.complyrConfig = {
  workspace: 'SEU_WORKSPACE_ID',
  formScanning: {
    enabled: true,
    autoScan: true,                    // Scan automático ao carregar página
    scanInterval: 5000,                // Re-scan a cada 5 segundos (formulários dinâmicos)
    blockWithoutConsent: true,         // Bloquear submissão sem consentimento
    showWarnings: true,                // Exibir alertas de compliance
    validateOnSubmit: true,            // Validar consentimento ao submeter

    // Campos para detectar
    detectFields: {
      personalData: true,              // Email, nome, telefone
      sensitiveData: true,             // CPF, RG, dados de saúde
      financialData: true,             // Cartão de crédito, conta bancária
      biometricData: false,            // Dados biométricos (desabilitado por padrão)
    },

    // Seletores customizados
    formSelectors: [
      'form',
      '[data-form]',
      '.contact-form',
      '#checkout-form',
    ],

    // Campos para ignorar
    excludeFields: [
      '[type="hidden"]',
      '[name="csrf_token"]',
      '.non-personal',
    ],

    // Categorização customizada
    customCategories: {
      'customer_id': 'identifier',
      'loyalty_number': 'commercial',
      'favorite_color': 'preferences',
    },
  },
};

API de Escaneamento

Métodos Disponíveis

window.complyr.forms.scan()

Executa scan manual de todos os formulários:

document.addEventListener('complyr:loaded', async () => {
  // Scan todos os formulários na página
  const forms = await window.complyr.forms.scan();

  console.log('Formulários detectados:', forms.length);
  forms.forEach(form => {
    console.log('Formulário:', form.id);
    console.log('Campos sensíveis:', form.sensitiveFields.length);
  });
});

window.complyr.forms.getAll()

Retorna todos os formulários detectados:

const allForms = window.complyr.forms.getAll();

console.log('Total de formulários:', allForms.length);

allForms.forEach(form => {
  console.log({
    id: form.id,
    action: form.action,
    method: form.method,
    fields: form.fields.length,
    sensitiveFields: form.sensitiveFields.length,
    hasConsent: form.hasConsent,
  });
});

Retorno:

[
  {
    id: 'contact-form',
    element: HTMLFormElement,
    action: '/api/contact',
    method: 'POST',
    fields: [
      {
        name: 'email',
        type: 'email',
        category: 'personal_data',
        sensitive: false,
        required: true,
      },
      {
        name: 'cpf',
        type: 'text',
        category: 'identifier',
        sensitive: true,
        required: true,
      },
      {
        name: 'phone',
        type: 'tel',
        category: 'personal_data',
        sensitive: false,
        required: false,
      },
    ],
    sensitiveFields: ['cpf'],
    hasConsent: true,
    consentRequired: ['analytics', 'personalization'],
    scannedAt: '2025-01-15T10:30:00.000Z',
  },
  // ... mais formulários
]

window.complyr.forms.getById(formId)

Obtém dados de um formulário específico:

// Por ID do elemento
const contactForm = window.complyr.forms.getById('contact-form');

// Por seletor CSS
const checkoutForm = window.complyr.forms.get('#checkout-form');

console.log('Campos do formulário:', contactForm.fields);

window.complyr.forms.getSensitiveFields(formId)

Retorna apenas campos sensíveis de um formulário:

const sensitiveFields = window.complyr.forms.getSensitiveFields('checkout-form');

console.log('Campos sensíveis detectados:');
sensitiveFields.forEach(field => {
  console.log(`- ${field.name}: ${field.category} (${field.type})`);
});

// Output:
// - cpf: identifier (text)
// - credit_card_number: financial (text)
// - cvv: financial (text)

window.complyr.forms.validateConsent(formId)

Valida se há consentimento para coletar dados do formulário:

const isValid = await window.complyr.forms.validateConsent('contact-form');

if (isValid) {
  console.log('Consentimento válido - pode submeter');
} else {
  console.error('Consentimento ausente ou inválido');
  // Exibir banner de consentimento
  window.complyr.showBanner();
}

Retorno detalhado:

const validation = await window.complyr.forms.validateConsent('contact-form', { detailed: true });

console.log({
  valid: validation.valid,
  missingConsents: validation.missingConsents,    // ['analytics', 'marketing']
  requiredPurposes: validation.requiredPurposes,  // Propósitos necessários
  currentConsent: validation.currentConsent,      // Consentimento atual do usuário
  recommendations: validation.recommendations,    // Sugestões de compliance
});

window.complyr.forms.categorize(fieldName, category)

Categoriza um campo manualmente:

// Categorizar campo customizado
window.complyr.forms.categorize('customer_loyalty_id', 'commercial');

// Categorizar múltiplos campos
const customCategories = {
  'referral_code': 'commercial',
  'discount_code': 'commercial',
  'survey_response': 'preferences',
};

Object.entries(customCategories).forEach(([name, category]) => {
  window.complyr.forms.categorize(name, category);
});

window.complyr.forms.generateReport()

Gera relatório completo de formulários e compliance:

const report = window.complyr.forms.generateReport();

console.log('Relatório de Formulários:');
console.log('Total de formulários:', report.totalForms);
console.log('Formulários com dados sensíveis:', report.formsWithSensitiveData);
console.log('Campos sensíveis total:', report.totalSensitiveFields);
console.log('Compliance status:', report.complianceStatus);
console.log('Violações LGPD:', report.violations);

Formato do Relatório:

{
  totalForms: 3,
  formsWithSensitiveData: 2,
  totalFields: 24,
  totalSensitiveFields: 6,
  complianceStatus: 'WARNING',  // OK, WARNING, VIOLATION
  byCategory: {
    personal_data: 12,
    identifier: 4,
    financial: 2,
    preferences: 6,
  },
  violations: [
    {
      formId: 'checkout-form',
      issue: 'Collecting CPF without consent',
      severity: 'HIGH',
      article: 'Art. 7º, I - LGPD',
      recommendation: 'Require explicit consent for identifier collection',
    },
  ],
  forms: [ /* array completo de formulários */ ],
  generatedAt: '2025-01-15T10:35:00.000Z',
}

Detecção Automática de Campos

Padrões de Detecção

O Complyr usa múltiplos métodos para detectar campos sensíveis:

1. Por Nome do Campo

// Padrões built-in (exemplos)
const fieldPatterns = {
  // Identificadores
  cpf: /cpf|cadastro.?pessoa|registro.?pessoa/i,
  cnpj: /cnpj|cadastro.?nacional/i,
  rg: /rg|registro.?geral|identidade/i,

  // Contato
  email: /e.?mail|correio/i,
  phone: /phone|tel|celular|telefone|fone/i,
  mobile: /cel|mobile|whatsapp/i,

  // Endereço
  address: /address|endereco|rua|logradouro/i,
  zipcode: /cep|zip|postal/i,
  city: /city|cidade/i,

  // Financeiro
  creditCard: /card|cartao|credit/i,
  cvv: /cvv|cvc|security.?code/i,
  bankAccount: /conta|account|agencia/i,

  // Pessoal
  name: /name|nome|first.?name|last.?name/i,
  birthdate: /birth|nascimento|data.?nasc/i,
  age: /age|idade/i,
};

2. Por Tipo de Input

<!-- Detectados automaticamente por type -->
<input type="email">         <!-- personal_data -->
<input type="tel">           <!-- personal_data -->
<input type="date">          <!-- personal_data (se birth/nascimento) -->
<input type="number">        <!-- Analisado por contexto -->
<input type="password">      <!-- sensitive_data -->

3. Por Atributo Data

<!-- Categorização explícita -->
<input
  type="text"
  name="customer_id"
  data-complyr-category="identifier"
  data-complyr-sensitive="true">

<input
  type="text"
  name="favorite_color"
  data-complyr-category="preferences"
  data-complyr-sensitive="false">

4. Por Placeholder e Label

<!-- Detectado por placeholder -->
<input type="text" placeholder="Digite seu CPF">

<!-- Detectado por label associado -->
<label for="cpf-input">CPF:</label>
<input type="text" id="cpf-input" name="document">

Validação de Formato

O sistema valida formatos comuns brasileiros:

// Validações automáticas
const validators = {
  cpf: /^\d{3}\.\d{3}\.\d{3}-\d{2}$/,
  cnpj: /^\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}$/,
  cep: /^\d{5}-\d{3}$/,
  phone: /^\(\d{2}\)\s?\d{4,5}-\d{4}$/,
  email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
};

// Executar validação
document.querySelector('#cpf').addEventListener('blur', (e) => {
  const field = window.complyr.forms.getField(e.target);

  if (field && field.category === 'identifier') {
    const isValid = window.complyr.forms.validateFormat(e.target.value, 'cpf');

    if (!isValid) {
      e.target.setCustomValidity('CPF inválido');
    } else {
      e.target.setCustomValidity('');
    }
  }
});

Bloqueio de Submissão

Bloqueio Automático

// Configurar bloqueio automático
window.complyrConfig = {
  formScanning: {
    blockWithoutConsent: true,
    showWarnings: true,
  },
};

// Formulário será bloqueado automaticamente se:
// 1. Contém campos sensíveis
// 2. Não há consentimento para coleta
// 3. Base legal não está definida

Bloqueio Manual

// Adicionar validação customizada ao formulário
document.querySelector('#contact-form').addEventListener('submit', async (e) => {
  e.preventDefault();

  // Validar consentimento antes de submeter
  const isValid = await window.complyr.forms.validateConsent('contact-form');

  if (!isValid) {
    alert('Por favor, aceite nossa política de privacidade antes de continuar.');

    // Exibir banner de consentimento
    window.complyr.showBanner();
    return;
  }

  // Validar campos sensíveis
  const sensitiveFields = window.complyr.forms.getSensitiveFields('contact-form');

  if (sensitiveFields.length > 0) {
    const hasConsent = await window.complyr.hasConsent('personalization');

    if (!hasConsent) {
      alert('Consentimento necessário para coletar dados pessoais.');
      return;
    }
  }

  // Submeter formulário
  e.target.submit();
});

Mensagens de Bloqueio Customizadas

window.complyrConfig = {
  formScanning: {
    blockMessages: {
      noConsent: 'É necessário aceitar nossa política de privacidade para enviar este formulário.',
      sensitiveData: 'Este formulário coleta dados pessoais sensíveis. Por favor, revise seu consentimento.',
      minorData: 'Coleta de dados de menores requer consentimento parental.',
    },
  },
};

Integração com Consentimento

Validar Consentimento por Propósito

document.addEventListener('complyr:loaded', async () => {
  // Formulário de newsletter - requer consent para marketing
  const newsletterForm = document.querySelector('#newsletter-form');

  newsletterForm.addEventListener('submit', async (e) => {
    e.preventDefault();

    const hasMarketingConsent = await window.complyr.hasConsent('marketing');

    if (!hasMarketingConsent) {
      alert('Para receber nossa newsletter, precisamos do seu consentimento para comunicações de marketing.');
      window.complyr.showBanner();
      return;
    }

    // Submeter com consentimento
    e.target.submit();
  });
});

Mapear Campos para Propósitos

window.complyrConfig = {
  formScanning: {
    fieldPurposeMapping: {
      'email': ['marketing', 'personalization'],
      'cpf': ['personalization', 'third_party'],
      'phone': ['marketing'],
      'address': ['third_party'],
    },
  },
};

// Validar múltiplos propósitos
async function validateFormConsent(formId) {
  const form = window.complyr.forms.getById(formId);
  const requiredPurposes = new Set();

  // Coletar propósitos necessários
  form.fields.forEach(field => {
    const purposes = window.complyrConfig.formScanning.fieldPurposeMapping[field.name];
    if (purposes) {
      purposes.forEach(p => requiredPurposes.add(p));
    }
  });

  // Validar cada propósito
  for (const purpose of requiredPurposes) {
    const hasConsent = await window.complyr.hasConsent(purpose);
    if (!hasConsent) {
      console.error(`Missing consent for purpose: ${purpose}`);
      return false;
    }
  }

  return true;
}
// Criar link direto entre formulário e consent
document.addEventListener('complyr:consent-updated', async (event) => {
  const { purposes } = event.detail;

  // Se revogou marketing, desabilitar campos de marketing
  if (!purposes.marketing.granted) {
    const marketingFields = document.querySelectorAll('[data-purpose="marketing"]');

    marketingFields.forEach(field => {
      field.disabled = true;
      field.value = '';
      field.placeholder = 'Consentimento de marketing necessário';
    });
  }

  // Re-validar todos os formulários
  const forms = window.complyr.forms.getAll();
  forms.forEach(async form => {
    const isValid = await window.complyr.forms.validateConsent(form.id);

    if (!isValid) {
      form.element.classList.add('consent-required');
      form.element.querySelector('button[type="submit"]')?.setAttribute('disabled', 'disabled');
    }
  });
});

Formulários Dinâmicos

Suporte a SPA (React, Vue, Angular)

// Re-scan após renderização de componentes
window.complyrConfig = {
  formScanning: {
    scanInterval: 2000,  // Re-scan a cada 2 segundos
    observeDom: true,    // Usar MutationObserver
  },
};

// OU scan manual após renderização
function MyReactComponent() {
  useEffect(() => {
    // Re-scan após componente montar
    window.complyr.forms.scan();
  }, []);

  return <form id="dynamic-form">...</form>;
}

MutationObserver

// Observar mudanças no DOM automaticamente
window.complyrConfig = {
  formScanning: {
    observeDom: true,
    observeOptions: {
      childList: true,
      subtree: true,
      attributes: true,
      attributeFilter: ['type', 'name', 'data-complyr-category'],
    },
  },
};

// Callback quando novo formulário detectado
document.addEventListener('complyr:form-detected', (event) => {
  const form = event.detail;

  console.log('Novo formulário detectado:', form.id);
  console.log('Campos sensíveis:', form.sensitiveFields.length);

  // Adicionar validação customizada
  if (form.sensitiveFields.length > 0) {
    form.element.addEventListener('submit', validateFormConsent);
  }
});

AJAX Forms

// Formulário AJAX com validação
document.querySelector('#ajax-form').addEventListener('submit', async (e) => {
  e.preventDefault();

  // Validar consentimento
  const isValid = await window.complyr.forms.validateConsent('ajax-form');

  if (!isValid) {
    alert('Consentimento necessário');
    return;
  }

  // Preparar dados
  const formData = new FormData(e.target);

  // Adicionar consentimento aos dados
  const consent = await window.complyr.getConsent();
  formData.append('consent_id', consent.id);

  // Enviar via fetch
  try {
    const response = await fetch('/api/contact', {
      method: 'POST',
      body: formData,
    });

    const data = await response.json();

    // Registrar coleta de dados no Complyr
    await window.complyr.data.collect({
      form: 'ajax-form',
      fields: Object.fromEntries(formData),
      consentId: consent.id,
    });

    alert('Formulário enviado com sucesso!');
  } catch (error) {
    console.error('Erro ao enviar:', error);
  }
});

Eventos de Formulário

complyr:form-detected

Dispara quando novo formulário é detectado:

document.addEventListener('complyr:form-detected', (event) => {
  const form = event.detail;

  console.log('Novo formulário:', form.id);
  console.log('Campos sensíveis:', form.sensitiveFields);

  // Adicionar banner de aviso se tiver dados sensíveis
  if (form.sensitiveFields.length > 0) {
    const warning = document.createElement('div');
    warning.className = 'lgpd-warning';
    warning.textContent = 'Este formulário coleta dados pessoais conforme LGPD.';
    form.element.prepend(warning);
  }
});

complyr:sensitive-field-detected

Dispara quando campo sensível é detectado:

document.addEventListener('complyr:sensitive-field-detected', (event) => {
  const field = event.detail;

  console.warn('Campo sensível detectado:', {
    name: field.name,
    category: field.category,
    type: field.type,
    formId: field.formId,
  });

  // Adicionar ícone de aviso ao lado do campo
  const icon = document.createElement('span');
  icon.className = 'lgpd-field-icon';
  icon.title = 'Este campo coleta dados pessoais';
  icon.textContent = '🔒';
  field.element.parentNode.appendChild(icon);
});

complyr:form-submit-blocked

Dispara quando submissão é bloqueada:

document.addEventListener('complyr:form-submit-blocked', (event) => {
  const { formId, reason, missingConsents } = event.detail;

  console.error('Submissão bloqueada:', {
    form: formId,
    motivo: reason,
    consentimentosFaltando: missingConsents,
  });

  // Exibir modal customizado
  showConsentModal({
    message: 'Para continuar, precisamos do seu consentimento para:',
    purposes: missingConsents,
    onAccept: async () => {
      // Atualizar consentimento
      await window.complyr.updateConsent(missingConsents);

      // Re-submeter formulário
      document.getElementById(formId).submit();
    },
  });
});

complyr:form-scan-complete

Dispara quando scan completo termina:

document.addEventListener('complyr:form-scan-complete', (event) => {
  const { totalForms, sensitiveFields, duration } = event.detail;

  console.log(`Scan completo: ${totalForms} formulários em ${duration}ms`);
  console.log('Campos sensíveis encontrados:', sensitiveFields);

  // Gerar relatório automático
  if (sensitiveFields > 0) {
    const report = window.complyr.forms.generateReport();
    console.table(report.violations);
  }
});

Relatórios e Auditoria

Geração de Relatório LGPD

async function generateLgpdReport() {
  const report = window.complyr.forms.generateReport();

  const html = `
    <div class="lgpd-report">
      <h2>Relatório de Compliance LGPD</h2>
      <p>Gerado em: ${new Date().toLocaleString('pt-BR')}</p>

      <div class="summary">
        <h3>Resumo</h3>
        <ul>
          <li>Total de formulários: ${report.totalForms}</li>
          <li>Formulários com dados sensíveis: ${report.formsWithSensitiveData}</li>
          <li>Total de campos sensíveis: ${report.totalSensitiveFields}</li>
          <li>Status de compliance: <strong>${report.complianceStatus}</strong></li>
        </ul>
      </div>

      <div class="fields-by-category">
        <h3>Campos por Categoria</h3>
        <table>
          <thead>
            <tr>
              <th>Categoria</th>
              <th>Quantidade</th>
            </tr>
          </thead>
          <tbody>
            ${Object.entries(report.byCategory).map(([category, count]) => `
              <tr>
                <td>${formatCategory(category)}</td>
                <td>${count}</td>
              </tr>
            `).join('')}
          </tbody>
        </table>
      </div>

      ${report.violations.length > 0 ? `
        <div class="violations">
          <h3>⚠️ Violações Detectadas</h3>
          <table>
            <thead>
              <tr>
                <th>Formulário</th>
                <th>Problema</th>
                <th>Severidade</th>
                <th>Base Legal</th>
                <th>Recomendação</th>
              </tr>
            </thead>
            <tbody>
              ${report.violations.map(v => `
                <tr class="severity-${v.severity.toLowerCase()}">
                  <td>${v.formId}</td>
                  <td>${v.issue}</td>
                  <td>${v.severity}</td>
                  <td>${v.article}</td>
                  <td>${v.recommendation}</td>
                </tr>
              `).join('')}
            </tbody>
          </table>
        </div>
      ` : '<p class="success">✅ Nenhuma violação detectada</p>'}

      <div class="forms-detail">
        <h3>Detalhamento de Formulários</h3>
        ${report.forms.map(form => `
          <div class="form-detail">
            <h4>${form.id}</h4>
            <p>Ação: ${form.action || 'N/A'} | Método: ${form.method || 'N/A'}</p>
            <p>Total de campos: ${form.fields.length}</p>
            <p>Campos sensíveis: ${form.sensitiveFields.length}</p>
            <p>Consentimento: ${form.hasConsent ? '✅ Válido' : '❌ Ausente'}</p>

            ${form.sensitiveFields.length > 0 ? `
              <h5>Campos Sensíveis:</h5>
              <ul>
                ${form.sensitiveFields.map(f => `
                  <li>${f} (${form.fields.find(field => field.name === f)?.category})</li>
                `).join('')}
              </ul>
            ` : ''}
          </div>
        `).join('')}
      </div>
    </div>
  `;

  document.getElementById('lgpd-report-container').innerHTML = html;
}

function formatCategory(category) {
  const labels = {
    personal_data: 'Dados Pessoais',
    identifier: 'Identificadores',
    financial: 'Dados Financeiros',
    sensitive_data: 'Dados Sensíveis',
    preferences: 'Preferências',
    commercial: 'Dados Comerciais',
  };
  return labels[category] || category;
}

Export para CSV

function exportReportToCsv() {
  const report = window.complyr.forms.generateReport();

  const rows = [
    ['Formulário', 'Campo', 'Categoria', 'Tipo', 'Sensível', 'Obrigatório', 'Consentimento'].join(','),
  ];

  report.forms.forEach(form => {
    form.fields.forEach(field => {
      rows.push([
        form.id,
        field.name,
        field.category,
        field.type,
        field.sensitive ? 'Sim' : 'Não',
        field.required ? 'Sim' : 'Não',
        form.hasConsent ? 'Válido' : 'Ausente',
      ].join(','));
    });
  });

  const csv = rows.join('\n');

  // Download CSV
  const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `lgpd-forms-report-${Date.now()}.csv`;
  a.click();
  URL.revokeObjectURL(url);
}

Troubleshooting

Problema 1: Campos não detectados

Sintomas: - Scan não encontra campos sensíveis - Formulários aparecem vazios

Soluções:

// 1. Verificar se form scanning está habilitado
console.log('Form scanning enabled:', window.complyrConfig?.formScanning?.enabled);

// 2. Executar scan manual
const forms = await window.complyr.forms.scan();
console.log('Forms found:', forms);

// 3. Verificar seletores customizados
window.complyrConfig = {
  formScanning: {
    formSelectors: [
      'form',
      '[data-form]',
      '.your-custom-form-class',
    ],
  },
};

// 4. Re-scan após carregar
window.complyr.forms.scan();

Problema 2: Categorização incorreta

Sintomas: - Campos categorizados erroneamente - Campos sensíveis marcados como normais

Soluções:

// Re-categorizar manualmente
window.complyr.forms.categorize('customer_id', 'identifier');

// Adicionar padrão customizado
window.complyrConfig = {
  formScanning: {
    customCategories: {
      'customer_id': 'identifier',
      'loyalty_*': 'commercial',  // Suporta wildcards
    },
  },
};

// Forçar categoria via atributo HTML
<input
  type="text"
  name="field"
  data-complyr-category="sensitive_data"
  data-complyr-sensitive="true">

Problema 3: Bloqueio não funciona

Sintomas: - Formulário submete sem consentimento - Validação não executada

Soluções:

// 1. Verificar configuração de bloqueio
console.log('Block enabled:', window.complyrConfig?.formScanning?.blockWithoutConsent);

// 2. Adicionar listener manual
document.querySelector('#form').addEventListener('submit', async (e) => {
  e.preventDefault();

  const isValid = await window.complyr.forms.validateConsent('form');
  if (!isValid) {
    alert('Consentimento necessário');
    return;
  }

  e.target.submit();
});

// 3. Verificar eventos
document.addEventListener('complyr:form-submit-blocked', (e) => {
  console.log('Submit blocked:', e.detail);
});

Segurança e Privacidade

Não Armazenar Valores

// Form scanner NÃO armazena valores dos campos
// Apenas metadados (nome, tipo, categoria)

const forms = window.complyr.forms.getAll();
forms.forEach(form => {
  form.fields.forEach(field => {
    console.log(field.name);   // ✅ OK
    console.log(field.type);   // ✅ OK
    console.log(field.value);  // ⚠️ Não persistido (apenas leitura local)
  });
});

Hash de Dados Sensíveis (Opcional)

// Se precisar enviar dados para analytics, use hash
import { sha256 } from 'crypto-js';

document.querySelector('#form').addEventListener('submit', async (e) => {
  e.preventDefault();

  const formData = new FormData(e.target);
  const hashedData = {};

  // Hash campos sensíveis
  for (const [key, value] of formData.entries()) {
    const field = window.complyr.forms.getField(key);

    if (field?.sensitive) {
      hashedData[key] = sha256(value).toString();
    } else {
      hashedData[key] = value;
    }
  }

  // Enviar dados com hash
  await fetch('/api/submit', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(hashedData),
  });
});

Best Practices

1. Sempre Validar Consentimento

// Validar antes de cada submissão
form.addEventListener('submit', async (e) => {
  e.preventDefault();

  const isValid = await window.complyr.forms.validateConsent(form.id);
  if (!isValid) {
    window.complyr.showBanner();
    return;
  }

  e.target.submit();
});
<!-- Adicionar base legal explícita -->
<form id="contact-form" data-complyr-legal-basis="consent">
  <input type="email" name="email" data-complyr-purpose="marketing">
  <input type="text" name="cpf" data-complyr-purpose="personalization">
  <button type="submit">Enviar</button>
</form>

3. Minimizar Coleta de Dados

// Detectar campos desnecessários
const report = window.complyr.forms.generateReport();

report.forms.forEach(form => {
  // Alertar se coletar mais de 5 dados sensíveis
  if (form.sensitiveFields.length > 5) {
    console.warn(`Form ${form.id} collects too many sensitive fields`);
    console.warn('Consider data minimization (LGPD Art. 6º, III)');
  }
});

4. Transparência com Usuário

// Exibir lista de dados coletados
function showDataCollectionNotice(formId) {
  const form = window.complyr.forms.getById(formId);
  const sensitiveFields = window.complyr.forms.getSensitiveFields(formId);

  const notice = `
    <div class="data-notice">
      <h3>Dados Coletados</h3>
      <p>Este formulário coleta os seguintes dados pessoais:</p>
      <ul>
        ${sensitiveFields.map(f => `
          <li><strong>${f.name}</strong> (${formatCategory(f.category)})</li>
        `).join('')}
      </ul>
      <p>Seus dados serão tratados conforme nossa
         <a href="/privacy-policy">Política de Privacidade</a>.</p>
    </div>
  `;

  form.element.insertAdjacentHTML('afterbegin', notice);
}

Próximos Passos

Após implementar Form Scanning:

  1. Data Collection - Colete dados com consentimento e portabilidade
  2. Request Interception - Controle requisições HTTP baseado em consentimento
  3. Cross-Domain - Sincronize consentimento entre domínios

Precisa de ajuda? Entre em contato com nosso suporte em suporte@complyr.com.br.