> ## Documentation Index
> Fetch the complete documentation index at: https://lifters.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Session Replay — Masking & PII

> Hierarquia block/mask/ignore, classes CSS Atlas, proteções hardcoded e config para iGaming.

<Warning>
  **PII nunca sai do browser.** O masking acontece ANTES do payload entrar no
  Worker de compressão. Mesmo que o operador desabilite todas as proteções
  custom, as regras hardcoded (password, cc-\*, cpf/cnpj/ssn) permanecem ativas.
</Warning>

## Hierarquia

rrweb (motor de gravação) trabalha com 3 níveis. Atlas expõe todos via
config + classes CSS:

| Nível      | Efeito                                                           | Quando usar                                                    |
| ---------- | ---------------------------------------------------------------- | -------------------------------------------------------------- |
| **BLOCK**  | Subárvore inteira vira placeholder cinza no replay               | Vídeo, iframes de terceiros, dados ultra-sensíveis             |
| **MASK**   | Texto/inputs viram `*****` no replay                             | Maioria dos campos de cadastro/KYC                             |
| **IGNORE** | Input value não é capturado, mas eventos (focus/blur/change) sim | Campos onde quero saber que houve digitação mas não o conteúdo |

## Classes CSS Atlas

Adicione no HTML do operador para ativar masking sem mexer no config JS:

| Classe            | Nível    | Efeito                                      |
| ----------------- | -------- | ------------------------------------------- |
| `ig-no-capture`   | BLOCK    | Subárvore inteira removida do replay        |
| `ig-mask`         | MASK     | Texto mascarado com `*`                     |
| `ig-ignore-input` | IGNORE   | Input value omitido                         |
| `ig-no-rageclick` | (Tipo 1) | Não dispara `rage.click` para esse elemento |

```html theme={null}
<!-- Subárvore inteira escondida -->
<div class="ig-no-capture">
  <video src="/cassino/blackjack-live.mp4"></video>
</div>

<!-- Texto mascarado mas estrutura visível -->
<span class="ig-mask">CPF: 123.456.789-00</span>

<!-- Input registra digitação sem capturar valor -->
<input type="text" name="security_question" class="ig-ignore-input" />
```

## Proteções hardcoded

Não podem ser desabilitadas por config. O recorder verifica cada `<input>`
em runtime:

```typescript theme={null}
// src/replay/masking.ts (extraído do SDK)
const HARDCODED_NAME_PATTERNS = [
  /password/i, /passwd/i, /pwd/i,
  /(^|\s)cc(\s|$)/i, /credit[\s_\-]?card/i, /card[\s_\-]?number/i,
  /cardnum/i, /cvv/i, /cvc/i, /\bcsc\b/i,
  /\bssn\b/i, /\bcpf\b/i, /\bcnpj\b/i,
  /document[\s_\-]?number/i, /security[\s_\-]?code/i,
];
```

Cobertura por categoria:

* **Inputs de senha**: `<input type="password">` sempre mascarado, independente
  de nome ou classe.
* **Cartão de crédito**: campos com `autocomplete` começando em `cc-` ou nome
  contendo `creditCard`, `cardNumber`, `cardnum`, `cvv`, `cvc`, `csc`.
* **Documentos BR**: `cpf`, `cnpj`, `document_number`.
* **Documentos US**: `ssn`, `security_code`.
* **Geral**: `current-password`, `new-password` via autocomplete.

Matching é **case-insensitive** e normaliza separadores (`_`, `-`, `.`) para
espaço — `user_ssn`, `CardNumber`, `document-number` são todos detectados.

## Configuração recomendada (iGaming)

```javascript theme={null}
window.iGamingSDK.init({
  // ... core config ...
  sessionReplay: {
    enabled:    true,
    sampleRate: 0.1,

    masking: {
      // Mascarar TODOS os inputs por padrão. iGaming = muito KYC/financial.
      maskAllInputs: true,

      // NÃO mascarar texto livre — operador quer ver navegação do jogador.
      maskAllText: false,

      // Seletor para esconder áreas inteiras (alerts financeiros, balances).
      blockSelector: '.player-balance, .deposit-history, .withdraw-form',

      // Seletor para mascarar texto sem esconder estrutura.
      maskTextSelector: '.player-name, .transaction-amount',

      // Inputs onde queremos saber que houve interação mas não o valor.
      ignoreSelector: 'input[name="2fa-code"], input[name="security-answer"]',

      // Classes CSS customizadas (defaults: ig-no-capture / ig-mask / ig-ignore-input).
      blockClass:  'app-no-capture',
      maskClass:   'app-mask',
      ignoreClass: 'app-ignore',

      // Por tipo de input HTML.
      maskInputOptions: {
        password: true,   // sempre true (hardcoded), aceita explícito
        email:    true,
        tel:      true,
        number:   false,  // valores numéricos genéricos: visíveis
        search:   false,
        text:     false,
        textarea: false
      },

      // Função custom — última palavra. Retorna o valor masked OR o original
      // (rrweb-record vai usar o resultado direto no DOM clonado).
      maskInputFn: (text, el) => {
        // Mascarar apenas CPF (regex 11 dígitos).
        if (/^\d{11}$/.test(text)) {
          return '***.***.***-**';
        }
        return text; // resto: passa direto
      }
    }
  }
});
```

<Tip>
  **Sempre comece restritivo**, depois relaxe. Em produção, é mais fácil
  liberar campos específicos do que descobrir que dados PII vazaram para o
  replay. Atlas recomenda começar com `maskAllInputs: true` + `blockSelector`
  amplo, e remover restrições conforme operações de compliance aprovam.
</Tip>

## Como auditar

```bash theme={null}
# 1. Inspecionar o replay no Dashboard
# Dashboard → Web Analytics → Replays → abrir um replay → ativar overlay "Masked"

# 2. Validação programática
# Operador deve testar campos PII conhecidos antes de habilitar em prod.
# Atlas oferece smoke endpoint que retorna o payload rrweb DECRIPTOGRAFADO:
curl -X POST https://api.atlas.io/v1/replays/preview \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"replay_id": "rp_xxx", "include_masked_preview": true}'
# (Apenas roles compliance/admin podem chamar este endpoint.)

# 3. Auditoria contínua via ClickHouse
SELECT actor_role, COUNT(*) as views
FROM atlas.audit_replay_views
WHERE event_time >= now() - INTERVAL 1 DAY
GROUP BY actor_role
ORDER BY views DESC;
```

## O que NÃO é capturado (mesmo sem config)

* **password** inputs (sempre hardcoded)
* **`<input type="file">`** content — apenas filename é registrado
* **Request bodies e headers** (a menos que `network.recordBody: true`, opt-in)
* **`Authorization`/`Cookie` headers** (hardcoded blocklist)
* **Query params sensíveis** em URLs (`token`, `access_token`, `cpf`, etc) —
  veja [Network & Console](/sdk/web-analytics/session-replay-network-console)

## Próximos passos

<CardGroup cols={2}>
  <Card title="Triggers" icon="bolt" href="/sdk/web-analytics/session-replay-triggers">
    Gravar SÓ sessões críticas com `urlMatchRegex` ou `eventMatch`.
  </Card>

  <Card title="Network & Console" icon="terminal" href="/sdk/web-analytics/session-replay-network-console">
    Política metric-only + scrubURL.
  </Card>
</CardGroup>
