> For the complete documentation index, see [llms.txt](https://docs.caf.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.caf.io/caf-sdk/caf-sdk-pt-br/flutter/getting-started-with-the-sdk.md).

# Primeiros passos com o SDK

## Sobre o CafSDK

Esta documentação técnica aborda a **implementação do CafSDK para Flutter**, detalhando a configuração, inicialização, execução dos fluxos de captura e customizações avançadas.

O CafSDK é um SDK unificado que integra múltiplos módulos para verificação de identidade: **Liveness Facial (FL)** e **Detector de Documentos (DD)**, executados sequencialmente com uma interface de configuração unificada.

### O que é Face Liveness

Face Liveness é o módulo que valida a autenticidade de um rosto capturado por um aplicativo de foto, garantindo que a imagem corresponde a uma pessoa real e não a uma tentativa de spoofing.

**Características técnicas:**

* Configuração da URL para autenticação (`authBaseUrl`) e verificação de liveness (`livenessBaseUrl`)
* Suporte para configuração de proxy reverso com pinagem de certificado
* Flags para habilitar captura de tela e modo de depuração
* Tentativas de repetição configuráveis e execução da autenticação facial
* Suporte para múltiplos provedores de autenticação

### O que é Document Detector

Document Detector é o módulo que permite a captura e o processamento de documentos (por exemplo, RG, cartão de seguridade social, passaporte etc.).

**Características técnicas:**

* Configuração de um fluxo passo a passo definido por `CafDocumentDetectorFlow` para captura de documentos
* Suporte para múltiplos tipos de documentos (RG, CNH, Passaporte etc.)
* Parâmetros operacionais, como timeout, flags de captura manual e outras configurações
* Possibilidade de usar a câmera para validações de enquadramento ou upload de arquivo de documento
* Opções avançadas de personalização para UI, mensagens e comportamento

***

## Exemplo

Confira o [aplicativo de exemplo](https://github.com/combateafraude/caf-sdk-flutter-exemple) para um exemplo completo de implementação.

***

## Instalação

### Requisitos

Para usar os módulos do CafSDK no Flutter, certifique-se de que seu projeto atende aos requisitos mínimos:

#### Flutter

| Requisito             | Versão |
| --------------------- | ------ |
| **Versão do Flutter** | 3.3.0+ |
| **Dart**              | 3.9.0+ |

#### Android

| Requisito                                               | Versão |
| ------------------------------------------------------- | ------ |
| **Android SDK API - versão mínima (minSdk)**            | 26     |
| **Android SDK API - versão de compilação (compileSdk)** | 36+    |
| **Kotlin**                                              | 1.8+   |
| **Gradle**                                              | 8.0+   |
| **Android Gradle Plugin (AGP)**                         | 8.0+   |

#### iOS

| Requisito                        | Versão |
| -------------------------------- | ------ |
| **Target de implantação do iOS** | 13.0+  |
| **Xcode**                        | 14.0+  |
| **Swift**                        | 5.0+   |

### Passo 1: Instale o SDK

Instale o pacote principal do SDK:

```sh
flutter pub add caf_sdk
```

### Passo 2: Configure a seleção de módulos

Crie um `caf-modules-config.json` arquivo na raiz do seu projeto para especificar quais módulos incluir:

> **Observação**: Se você omitir este arquivo, todos os módulos serão habilitados por padrão e **`iproov-lite`** será usado como provedor padrão de Face Liveness.

```json
{
  "documentDetector": true,
  "faceLiveness": true,
  "documentDetectorUI": true,
  "faceLivenessUI": true,
  "livenessProviders": "iproov-lite",
  "fingerprint": true
}
```

Defina como `true` os módulos que você quer usar em sua aplicação.

Para um único provedor, `livenessProviders` pode ser uma string. Os valores permitidos são `iproov-lite`, `iproov-full`, `payface`, e `facetec`. Para usar vários provedores, use um array (veja o exemplo abaixo).

```json
{
  "documentDetector": true,
  "faceLiveness": true,
  "documentDetectorUI": true,
  "faceLivenessUI": true,
  "livenessProviders": [
    "iproov-lite",
    "payface",
    "facetec"
  ],
  "fingerprint": true
}
```

**iProov e Protobuf**

* **`iproov-lite`**: use quando seu app tiver como alvo **Protobuf JavaLite**— a escolha usual para uma menor ocupação binária no Android.
* **`iproov-full`**: use quando você precisar de **Protobuf Java** (completo) junto com iProov.

Você pode declarar **mais de um** provedor definindo `livenessProviders` para um array quando sua integração exigir isso.

{% hint style="warning" %}
Se você incluir o provedor **PayFace** , você também deve usar **iProov Lite** (`iproov-lite`). O PayFace é construído sobre Protobuf JavaLite; combiná-lo com **`iproov-full`** causa conflitos de dependência do Protobuf no momento da compilação.
{% endhint %}

Defina como `true` os módulos que você quer usar em sua aplicação.

**Fingerprint**

O módulo Fingerprint é opcional e é configurado em `caf-modules-config.json` por meio da `fingerprint` propriedade (booleano). O padrão é `false`, então você não precisa adicionar a propriedade a menos que queira usá-la. Para habilitar o módulo, defina explicitamente `"fingerprint": true`.

**Requer um módulo Face Liveness.** Fingerprint é coletado como parte do fluxo de liveness, então só é incluído quando `faceLiveness` ou `faceLivenessUI` também está habilitado. Definir `"fingerprint": true` sem um módulo de liveness habilitado não tem efeito.

**Importante:** Entre em contato com o Suporte da CAF para solicitar a ativação. Se isso não estiver habilitado do nosso lado, o SDK não acionará a biblioteca de fingerprint e nenhum dado será enviado, mesmo que a propriedade esteja definida como `true` localmente.

### Passo 3: Configuração do Android

#### Adicionar repositórios Maven

Configure o arquivo `build.gradle.kts` do projeto (normalmente localizado na raiz):

```kotlin
repositories {
    // Repositório da CAF
    maven { url = uri("https://repo.combateafraude.com/android/release") }
    
    // Repositório iProov (necessário para Face Liveness)
    maven { url = uri("https://raw.githubusercontent.com/iProov/android/master/maven/") }
    
    // Repositório FingerPrintJS
    maven { setUrl("https://maven.fpregistry.io/releases") }
    
    // JitPack
    maven { setUrl("https://jitpack.io") }

    // Repositório Fortface - necessário para usar o provedor PayFace
    maven {
        url = uri("https://cdn-fortface-sdk.fortface.com.br")
        credentials(HttpHeaderCredentials::class) {
            name = "X-Sdk"
            value = "CAF"
        }
        authentication {
            create<HttpHeaderAuthentication>("header")
        }
    }
}
```

### Passo 4: Configuração do iOS

Navegue até o diretório `ios/` do seu projeto Flutter e execute:

```sh
pod install
```

* Este passo é obrigatório para que o iOS faça corretamente o link dos módulos nativos e suas dependências exigidas.
* Sempre execute novamente `pod install` sempre que dependências nativas forem adicionadas ou atualizadas.

***

## Permissões

### Android

Para que os módulos funcionem corretamente, você deve declarar as seguintes permissões no seu **AndroidManifest.xml**:

**Para Face Liveness**

| Permissão                     | Descrição                                                                               | Necessidade |
| ----------------------------- | --------------------------------------------------------------------------------------- | ----------- |
| `android.permission.CAMERA`   | Permite acesso à câmera para capturar imagens e realizar verificação facial (liveness). | Obrigatória |
| `android.permission.INTERNET` | Permite comunicação com serviços de autenticação e verificação (HTTPS/WSS).             | Obrigatória |

**Para Document Detector**

| Permissão                                  | Descrição                                                                                       | Necessidade          |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------- | -------------------- |
| `android.permission.CAMERA`                | Permite acesso à câmera para capturar imagens de documentos.                                    | Somente para captura |
| `android.permission.INTERNET`              | Permite que as imagens capturadas sejam enviadas aos servidores para processamento e validação. | Obrigatória          |
| `android.permission.READ_EXTERNAL_STORAGE` | Permite acesso a arquivos e imagens armazenados para processamento, se necessário.              | Somente para upload  |

### iOS

Para que os módulos do SDK funcionem corretamente, você deve declarar as seguintes permissões no seu **Info.plist**:

**Para Face Liveness:**

| Permissão                  | Descrição                                                                               | Necessidade |
| -------------------------- | --------------------------------------------------------------------------------------- | ----------- |
| `NSCameraUsageDescription` | Permite acesso à câmera para capturar imagens e realizar verificação facial (liveness). | Obrigatória |
| `Acesso à rede`            | Permite comunicação com serviços de autenticação e verificação (HTTPS/WSS).             | Obrigatória |

**Para Document Detector:**

| Permissão                        | Descrição                                                                                       | Necessidade          |
| -------------------------------- | ----------------------------------------------------------------------------------------------- | -------------------- |
| `NSCameraUsageDescription`       | Permite acesso à câmera para capturar imagens de documentos.                                    | Somente para captura |
| `Acesso à rede`                  | Permite que as imagens capturadas sejam enviadas aos servidores para processamento e validação. | Obrigatória          |
| `NSPhotoLibraryUsageDescription` | Permite acesso a arquivos e imagens armazenados para processamento, se necessário.              | Somente para upload  |

***

## Implementação Básica

### Exemplo Simples

Aqui está um exemplo básico de implementação:

```dart
import 'dart:async';
import 'package:caf_sdk/types/index.dart';
import 'package:flutter/material.dart';
import 'package:caf_sdk/caf_sdk.dart';

void main() => runApp(const App());

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Exemplo do CAF SDK',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home: const SimpleExamplePage(),
    );
  }
}

class SimpleExamplePage extends StatefulWidget {
  const SimpleExamplePage({super.key});

  @override
  State<SimpleExamplePage> createState() => _SimpleExamplePageState();
}

class _SimpleExamplePageState extends State<SimpleExamplePage> {
  final _cafSdk = CafSdk();
  StreamSubscription<CafResponse>? _eventSubscription;

  @override
  void initState() {
    super.initState();
    _initializeEventStream();
  }

  @override
  void dispose() {
    _eventSubscription?.cancel();
    super.dispose();
  }

  void _initializeEventStream() {
    _eventSubscription = _cafSdk.eventStream.listen((event) {
      if (!mounted) return;

      if (event.success != null) {
        print('Sucesso: ${event.success!.moduleName} -> ${event.success!.signedResponse}');
      } else if (event.error != null) {
        print('Erro: ${event.error!.type} - ${event.error!.description}');
      } else if (event.failure != null) {
        print('Falha: ${event.failure!.type} - ${event.failure!.description}');
      }
    });
  }

  Future<void> _initialize() async {
    try {
      // Configuração do SDK
      final config = CafSdkConfiguration(
        mobileToken: 'token',
        personId: 'personId',
        environment: CafEnvironment.dev,
        configuration: CafSdkBuilderConfiguration(
          presentationOrder: [
            CafModuleType.faceLiveness,
            CafModuleType.documentDetector,
          ],
          enableSecurityModule: true,
          waitForAllServices: true,
        ),
      );

      // Configuração do Face Liveness
      final faceLivenessConfig = CafFaceLivenessConfiguration(
        loading: true,
        debugModeEnabled: true,
        payFaceDebugMode: false,
      );

      // Configuração do Document Detector
      final documentDetectorConfig = CafDocumentDetectorConfiguration(
        flow: [
          CafDocumentDetectorFlow(document: CafDocument.rgFront),
          CafDocumentDetectorFlow(document: CafDocument.rgBack),
        ],
        uploadSettings: CafDocumentDetectorUploadSettings(enable: false),
        manualCaptureEnabled: false,
        manualCaptureTime: 45,
        showPopup: true,
        previewShow: false,
        securitySettings: CafDocumentDetectorSecuritySettings(
          useAdb: true,
          useDebug: true,
          useDevelopmentMode: true,
        ),
      );

      await _cafSdk.initializeCafSdk(
        cafSdkConfiguration: config,
        faceLivenessConfiguration: faceLivenessConfig,
        documentDetectorConfiguration: documentDetectorConfig,
      );
    } catch (e) {
      print('Erro: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Exemplo Simples do CAF SDK'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Center(
                child: ElevatedButton(
                  onPressed: _initialize,
                  child: Text('Iniciar')
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
```

***

## Configuração

### Idioma

#### Android

O idioma é definido automaticamente de acordo com o idioma configurado no dispositivo, sem nenhuma configuração adicional.

#### iOS

De acordo com a documentação da Apple, a configuração de `Localizações` e `CFBundleLocalizations` deve ser feita no Xcode:

[Adição de suporte para idiomas e regiões](https://developer.apple.com/documentation/xcode/adding-support-for-languages-and-regions)

[CFBundleLocalizations](https://developer.apple.com/documentation/bundleresources/information-property-list/cfbundlelocalizations)

Após essas configurações, o SDK reconhecerá o idioma do dispositivo.

### Configuração Global

A `CafSdk` classe serve como o contêiner central para todas as configurações. Essa configuração define a ordem de execução dos módulos e a identidade visual.

**Parâmetros essenciais:**

* **mobileToken**: Token que autentica a solicitação e garante que apenas clientes autorizados iniciem o fluxo
* **personId**: Identificador exclusivo do usuário para o qual o fluxo será executado
* **environment**: Define o ambiente de execução (PROD, BETA, DEV)
* **presentationOrder**: Define a sequência em que os módulos serão executados
* **enableSecurityModule**: Habilita ou desabilita o módulo de segurança. Opcional, o padrão é `true`

**Exemplo de código para criar a configuração global:**

```dart
final _cafSdk = CafSdk();

// Configuração do SDK
final config = CafSdkConfiguration(
  mobileToken: "mobile-token",
  personId: "person-id",
  environment: CafEnvironment.prod,
  configuration: CafSdkBuilderConfiguration(
    presentationOrder: [
      CafModuleType.faceLiveness,    // ou CafModuleType.faceLivenessUi
      CafModuleType.documentDetector // ou CafModuleType.documentDetectorUi
    ],
    enableSecurityModule: true,       // Opcional, o padrão é true
    waitForAllServices: true,         // Opcional, o padrão é true
    enableTransitionScreens: true,    // Opcional, o padrão é true
    colorConfiguration: CafColorConfiguration(
      primaryColor: "#0000FF",
      secondaryColor: "#00FF00",
      backgroundColor: "#FFFFFF",
      contentColor: "#000000",
      mediumColor: "#CCCCCC",
      dialogBackgroundColor: "#FFFFFF",
      dialogBorderColor: "#E5E5E7",
    ),
  ),
);

// Inicialize o SDK
await _cafSdk.initializeCafSdk(
  cafSdkConfiguration: config,
  documentDetectorConfiguration: documentDetectorConfig,
  documentDetectorUIConfiguration: documentDetectorUIConfig,
  faceLivenessConfiguration: faceLivenessConfig,
  faceLivenessUIConfiguration: faceLivenessUIConfig,
);
```

### Configuração específica do módulo

#### Configuração de Face Liveness

Você pode configurar o módulo Face Liveness criando uma `CafFaceLivenessConfiguration`. Ao usar o provedor opcional PayFace (Fortface), use `payFaceDebugMode` para ativar o modo de depuração para esse provedor.

```dart
final faceLivenessConfig = CafFaceLivenessConfiguration(
  loading: true,                                                  // Exibe a tela de carregamento durante o processamento
  authBaseUrl: 'https://base-url.com',                            // Opcional, endpoint para autenticação
  livenessBaseUrl: 'wss://base-url.com',                          // Opcional, endpoint para verificação de liveness
  certificates: ['4d69f16113bed7d62ca56feb68d32a0fcb7293d3960='], // Opcional, somente ao usar proxy reverso
  screenCaptureEnabled: true,                                     // Permite captura de tela, se necessário
  debugModeEnabled: true,                                         // Ativa logs de depuração
  executeFaceAuth: false,                                         // Ativa a autenticação facial
  maxRetryAttempts: 2,                                            // Número máximo de tentativas de nova tentativa
  payFaceDebugMode: false,                                        // Opcional, ativa o modo de depuração para o provedor PayFace (Fortface)
);
```

#### Configuração do Detector de Documentos

Você pode configurar o módulo Document Detector criando uma `CafDocumentDetectorConfiguration`:

```dart
final documentDetectorConfig = CafDocumentDetectorConfiguration(
  flow: [
    CafDocumentDetectorFlow(document: CafDocument.rgFront),
    CafDocumentDetectorFlow(document: CafDocument.rgBack),
  ],
  securitySettings: CafDocumentDetectorSecuritySettings(
    useAdb: true,
    useDebug: true,
    useDevelopmentMode: true,
  ),
  manualCaptureEnabled: true,
  manualCaptureTime: 30,
  requestTimeout: 60,
  showPopup: true,
  maxRetryAttempts: 2,
  uploadSettings: CafDocumentDetectorUploadSettings(
    enable: true,
    compress: true,
    fileFormats: [CafFileFormat.png, CafFileFormat.jpg],
    maxFileSize: 5, // 5MB
  ),
);
```

***

## Tratamento de eventos

{% hint style="warning" %}
Garanta que a resposta JWT seja avaliada no backend. Esse processo deve incluir a validação da assinatura do token e a verificação dos `estáVivo` e `éCorrespondente` campos. Não realize essas validações no lado do cliente.
{% endhint %}

A `eventStream` da `CafSdk` classe fornece um **tipado** `Stream<CafResponse>` gerado durante a execução do fluxo de captura. Cada `CafResponse` tem exatamente um campo preenchido, que indica o tipo de evento:

| Campo       | Tipo                  | Descrição                                                                               |
| ----------- | --------------------- | --------------------------------------------------------------------------------------- |
| `loading`   | `bool`                | Indica o início do processamento do módulo                                              |
| `loaded`    | `bool`                | Indica que o módulo foi processado                                                      |
| `success`   | `CafSuccessResponse?` | Ao concluir com sucesso; contém `moduleName` e `signedResponse`                         |
| `error`     | `CafErrorResponse?`   | Ocorreu um problema durante a execução; contém `type` e `description`                   |
| `failure`   | `CafFailureResponse?` | Indica uma falha de Face Liveness; contém `type`, `description`, e `response`           |
| `log`       | `CafLog?`             | Mensagens de log com diferentes níveis; contém `level` (DEBUG, USAGE, INFO) e `message` |
| `cancelled` | `bool`                | Indica que o usuário ou o sistema interrompeu o fluxo                                   |

> **Observação de migração (v2.0.0):** `eventStream` agora emite objetos `CafResponse` tipados em vez de `Map` brutos. Substitua qualquer `event['eventName']` / `event['response']` acesso pelos campos tipados mostrados acima.

**Exemplo de tratamento de eventos:**

```dart
final _cafSdk = CafSdk();
StreamSubscription<CafResponse>? _eventSubscription;

void _initializeEventStream() {
  _eventSubscription = _cafSdk.eventStream.listen((event) {
    if (!mounted) return;

    if (event.loading) {
      print('Carregando...');
    } else if (event.loaded) {
      print('Sessão carregada');
    } else if (event.success != null) {
      print('Sucesso: ${event.success!.moduleName} -> ${event.success!.signedResponse}');
    } else if (event.error != null) {
      print('Erro: ${event.error!.type} - ${event.error!.description}');
    } else if (event.failure != null) {
      print('Falha: ${event.failure!.type} - ${event.failure!.description}');
    } else if (event.log != null) {
      print('Log: ${event.log!.level} - ${event.log!.message}');
    } else if (event.cancelled) {
      print('Cancelado pelo usuário');
    }
  });
}

@override
void dispose() {
  _eventSubscription?.cancel();
  super.dispose();
}
```

### Tipos de erro (CafErrorType)

| Caso do enum                       | Condição de disparo                                      |
| ---------------------------------- | -------------------------------------------------------- |
| `CAMERA_PERMISSION`                | Acesso à câmera negado                                   |
| `UNSUPPORTED_DEVICE`               | Especificações do dispositivo não suportadas             |
| `NETWORK_EXCEPTION`                | Problemas de conectividade de rede                       |
| `SERVER_EXCEPTION`                 | Falha no processamento do backend                        |
| `TOKEN_EXCEPTION`                  | Token inválido/expirado                                  |
| `CAPTURE_ALREADY_ACTIVE_EXCEPTION` | Sessão de captura simultânea                             |
| `UNEXPECTED_ERROR_EXCEPTION`       | Erro crítico irrecuperável                               |
| `USER_TIMEOUT_EXCEPTION`           | Tempo limite de captura excedido                         |
| `IMAGE_NOT_FOUND_EXCEPTION`        | Dados de imagem ausentes                                 |
| `TOO_MANY_REQUESTS_EXCEPTION`      | Limite de taxa da API excedido                           |
| `UNKNOWN_EXCEPTION`                | Erro não classificado                                    |
| `LIBRARY_EXCEPTION`                | Erro de framework de baixo nível                         |
| `PERMISSION_EXCEPTION`             | Permissões do sistema ausentes                           |
| `INVALID_EXCEPTION`                | Resposta inválida recebida                               |
| `SEQUENCE_INVALID`                 | Sequência de operação inválida                           |
| `LIVENESS_EXCEPTION`               | Erro específico de face liveness                         |
| `FINGERPRINT_EXCEPTION`            | Erro relacionado à impressão digital                     |
| `STORAGE_EXCEPTION`                | Erro de acesso ao armazenamento                          |
| `PROXY_EXCEPTION`                  | Erro de configuração do proxy                            |
| `SECURITY_EXCEPTION`               | Erro de validação de segurança                           |
| `INVALID_RESPONSE_EXCEPTION`       | Payload de resposta inválido recebido de um módulo       |
| `CAMERA_EXCEPTION`                 | Falha de inicialização da câmera ou em tempo de execução |
| `FACE_AUTHENTICATION`              | Erro durante a autenticação facial (executeFaceAuth)     |
| `BRIDGE_EXCEPTION`                 | Erro de comunicação da ponte nativa ↔ Flutter            |

### Tipos de falha (CafFailureType)

|     Caso do enum    | Condição de disparo                 | GPA |  LA |
| :-----------------: | ----------------------------------- | :-: | :-: |
|      `UNKNOWN`      | Falha genérica                      |  ✅  |  ❌  |
| `TOO_MUCH_MOVEMENT` | Movimento excessivo da cabeça       |  ✅  |  ❌  |
|     `TOO_BRIGHT`    | Iluminação excessiva                |  ✅  |  ❌  |
|      `TOO_DARK`     | Condições de pouca luz              |  ✅  |  ❌  |
|  `MISALIGNED_FACE`  | Falha no alinhamento do rosto       |  ✅  |  ❌  |
|    `FACE_TOO_FAR`   | Rosto muito distante                |  ✅  |  ❌  |
|   `FACE_TOO_CLOSE`  | Rosto muito próximo                 |  ✅  |  ❌  |
|     `SUNGLASSES`    | Óculos que cobrem os olhos          |  ✅  |  ❌  |
|   `OBSCURED_FACE`   | Obstrução parcial do rosto          |  ✅  |  ✅  |
|    `EYES_CLOSED`    | Olhos fechados durante a captura    |  ✅  |  ✅  |
|   `MULTIPLE_FACES`  | Vários rostos detectados            |  ✅️ |  ✅️ |
|  `BACKGROUND_ISSUE` | Fundo inadequado                    |  ❌  |  ✅  |
|    `DEVICE_ISSUE`   | Dispositivo incompatível            |  ❌  |  ✅  |
|      `EYEWEAR`      | Óculos detectados                   |  ❌  |  ✅  |
|   `FACE_NOT_FOUND`  | Falha na detecção do rosto          |  ❌  |  ✅  |
|   `FRAMES_BLURRY`   | Quadros borrados detectados         |  ❌  |  ✅  |
|    `MOTION_ISSUE`   | Erro de movimento do dispositivo    |  ❌  |  ✅  |
|  `LIGHTING_ISSUES`  | Condições de iluminação inadequadas |  ❌  |  ✅  |
|      `REJECTED`     | Transação rejeitada                 |  ❌  |  ✅  |
|    `SYSTEM_ERROR`   | Erro interno do sistema             |  ❌  |  ✅  |
|      `TIMEOUT`      | Tempo limite da sessão              |  ❌  |  ✅  |
|   `USER_NOT_FOUND`  | Falha na busca do usuário           |  ❌  |  ✅  |
|   `DEVICE_RESTART`  | Erro de estado do dispositivo       |  ❌  |  ✅  |
|  `PROCESSING_FAULT` | Erro de processamento               |  ❌  |  ✅  |

***

## Tipos de documentos

### Documentos suportados (CafDocument)

| Nome         | Descrição                                                                                                                     |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| `RG_FRONT`   | Frente do documento RG, onde fica a foto                                                                                      |
| `RG_BACK`    | Verso do documento RG                                                                                                         |
| `RG_FULL`    | Documento RG aberto, exibindo a frente e o verso juntos                                                                       |
| `CNH_FRONT`  | Frente do documento CNH, onde fica a foto                                                                                     |
| `CNH_BACK`   | Verso do documento CNH                                                                                                        |
| `CNH_FULL`   | Documento CNH aberto, exibindo a frente e o verso juntos                                                                      |
| `CRLV`       | Documento CRLV                                                                                                                |
| `RNE_FRONT`  | Frente do documento RNE ou RNM                                                                                                |
| `RNE_BACK`   | Verso do documento RNE ou RNM                                                                                                 |
| `CTPS_FRONT` | Frente do documento CTPS, onde fica a foto                                                                                    |
| `CTPS_BACK`  | Verso do documento CTPS                                                                                                       |
| `PASSPORT`   | Documento de passaporte, exibindo a foto e os dados pessoais                                                                  |
| `ANY`        | Permite o envio de qualquer tipo de documento, incluindo todos os listados acima ou qualquer outro documento não classificado |

### Formatos de arquivo suportados (CafFileFormat)

| Tipo   | Valor             |
| ------ | ----------------- |
| `PNG`  | `image/png`       |
| `JPG`  | `image/jpg`       |
| `JPEG` | `image/jpeg`      |
| `PDF`  | `application/pdf` |
| `HEIF` | `image/heif`      |
| `HEIC` | `image/heic`      |

***

## Configuração avançada

### Configuração de UI de Face Liveness

Ao usar o módulo de UI, você pode personalizar as telas de instruções:

```dart
final faceLivenessUIConfig = CafFaceLivenessUIConfiguration(
  loading: true,
  authBaseUrl: "https://my.proxy.io/v1/faces/", 
  livenessBaseUrl: "wss://my.proxy.io/ws/",    
  certificates: [
    "4d69f16113bed7d62ca56feb68d32a0fcb7293d3960=",
    "50f71c5dda30741ee4be1ac378e12539b0d1d511f99=",
    "9f85e26c1ae41f7ac97adc4099be7f2a40759510ab9=",
  ],
  screenCaptureEnabled: true,
  debugModeEnabled: true,
  executeFaceAuth: false, 
  maxRetryAttempts: 2,
  payFaceDebugMode: false,
  instructionScreen: CafFaceLivenessUIInstructionScreenConfiguration(
    image: "scan_icon", // URL da imagem ou nome do asset local
    title: "Título personalizado",
    description: "Siga os passos abaixo:",
    steps: ["Mantenha o telefone parado", "Garanta boa iluminação"],
    buttonText: "Iniciar verificação",
  ),
);
```

### Configuração de UI do Detector de Documentos

```dart
final documentDetectorUIConfig = CafDocumentDetectorUIConfiguration(
  flow: [CafDocumentDetectorFlow(document: CafDocument.rgFront)], 
  manualCaptureEnabled: true,
  manualCaptureTime: 45,
  requestTimeout: 60,
  showPopup: true,
  securitySettings: CafDocumentDetectorSecuritySettings(
    useDebug: true,
    useDevelopmentMode: true,
    useAdb: true,
  ),
  maxRetryAttempts: 2,
  instructionScreen: CafDocumentDetectorUIInstructionScreenConfiguration(
    enable: true,
    captureTitle: "Capture seu documento",
    captureSteps: [
      "Mantenha o telefone parado",
      "Garanta boa iluminação",
      "Evite reflexos"
    ],
    buttonText: "Iniciar",
  ),
  documentSelectionScreen: CafDocumentDetectorUIDocumentSelectionScreenConfiguration(
    title: "Selecione o tipo de documento",
    description: "Escolha qual documento você quer enviar",
  ),
);
```

### Configuração de proxy

Para as configurações de proxy do Detector de Documentos:

```dart
final documentDetectorConfig = CafDocumentDetectorConfiguration(
  flow: [CafDocumentDetectorFlow(document: CafDocument.rgFront)],
  proxySettings: CafDocumentDetectorProxySettings(
    hostname: "proxy.example.com",
    port: 8080,
    authentication: CafDocumentDetectorProxySettingsAuthentication(
      user: "username",
      password: "password"
    ),
  ),
);
```

### Personalização de mensagens

Personalize as mensagens exibidas durante o fluxo de captura:

```dart
final documentDetectorConfig = CafDocumentDetectorConfiguration(
  flow: [CafDocumentDetectorFlow(document: CafDocument.rgFront)],
  messageCustomization: CafDocumentDetectorMessageCustomization(
    waitMessage: "Preparando a câmera...",
    fitTheDocumentMessage: "Posicione o documento dentro da moldura",
    holdItMessage: "Mantenha firme...",
    verifyingQualityMessage: "Verificando a qualidade do documento...",
    lowQualityDocumentMessage: "A qualidade do documento está muito baixa. Tente novamente.",
    uploadingImageMessage: "Enviando documento...",
    positiveButtonMessage: "Continuar",
  ),
);
```

***

## Exemplo completo de implementação

Aqui está um exemplo completo mostrando tanto a UI de Face Liveness quanto a UI do Detector de Documentos:

```dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:caf_sdk/caf_sdk.dart';
import 'package:caf_sdk/types/index.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Exemplo do CAF SDK',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home: const CafSdkExamplePage(),
    );
  }
}

class CafSdkExamplePage extends StatefulWidget {
  const CafSdkExamplePage({super.key});

  @override
  State<CafSdkExamplePage> createState() => _CafSdkExamplePageState();
}

class _CafSdkExamplePageState extends State<CafSdkExamplePage> {
  final _cafSdk = CafSdk();
  StreamSubscription<CafResponse>? _eventSubscription;

  final String _mobileToken = "token";
  final String _personId = "personId";
  final CafEnvironment _environment = CafEnvironment.dev;

  @override
  void initState() {
    super.initState();
    _initializeEventStream();
  }

  @override
  void dispose() {
    _eventSubscription?.cancel();
    super.dispose();
  }

  void _initializeEventStream() {
    _eventSubscription = _cafSdk.eventStream.listen((event) {
      if (!mounted) return;

      if (event.loading) {
        print('[EVENTO DO CAF SDK]: carregando');
      } else if (event.loaded) {
        print('[EVENTO DO CAF SDK]: carregado');
      } else if (event.success != null) {
        print('[EVENTO DO CAF SDK]: sucesso');
        print('[EVENTO DO CAF SDK]: ${event.success!.moduleName} -> ${event.success!.signedResponse}');
      } else if (event.error != null) {
        print('[EVENTO DO CAF SDK]: erro');
        print('[EVENTO DO CAF SDK]: ${event.error!.type} - ${event.error!.description}');
      } else if (event.failure != null) {
        print('[EVENTO DO CAF SDK]: falha');
        print('[EVENTO DO CAF SDK]: ${event.failure!.type} - ${event.failure!.description}');
      } else if (event.log != null) {
        print('[EVENTO DO CAF SDK]: registro');
        print('[EVENTO DO CAF SDK]: ${event.log!.level} - ${event.log!.message}');
      } else if (event.cancelled) {
        print('[EVENTO DO CAF SDK]: cancelado');
      }
    });
  }

  Future<void> _initializeCafSdk() async {
    try {
      // Configuração do SDK
      final config = CafSdkConfiguration(
        mobileToken: _mobileToken,
        personId: _personId,
        environment: _environment,
        configuration: CafSdkBuilderConfiguration(
          presentationOrder: [
            CafModuleType.faceLivenessUi,
            CafModuleType.documentDetectorUi,
          ],
          enableSecurityModule: true,
          waitForAllServices: true,
        ),
      );

      // Configuração da interface de Liveness facial
      CafFaceLivenessUIConfiguration?
      faceLivenessUIConfig = CafFaceLivenessUIConfiguration(
        loading: true,
        debugModeEnabled: true,
        payFaceDebugMode: false,
        instructionScreen:
            CafFaceLivenessUIInstructionScreenConfiguration(
              title: "Liveness facial",
              description:
                  "Posicione seu rosto no centro e siga as instruções",
              steps: [
                "Centralize seu rosto",
                "Siga as instruções",
                "Permaneça imóvel",
              ],
              buttonText: "Iniciar",
            ),
      );

      // Configuração da interface do Detector de documentos
      CafDocumentDetectorUIConfiguration?
      documentDetectorUIConfig = CafDocumentDetectorUIConfiguration(
        flow: [
          CafDocumentDetectorFlow(document: CafDocument.rgFront),
          CafDocumentDetectorFlow(document: CafDocument.rgBack),
          CafDocumentDetectorFlow(document: CafDocument.rgFull),
          CafDocumentDetectorFlow(document: CafDocument.cnhFront),
          CafDocumentDetectorFlow(document: CafDocument.cnhBack),
          CafDocumentDetectorFlow(document: CafDocument.cnhFull),
          CafDocumentDetectorFlow(document: CafDocument.crlv),
          CafDocumentDetectorFlow(document: CafDocument.rneFront),
          CafDocumentDetectorFlow(document: CafDocument.rneBack),
          CafDocumentDetectorFlow(document: CafDocument.ctpsFront),
          CafDocumentDetectorFlow(document: CafDocument.ctpsBack),
          CafDocumentDetectorFlow(document: CafDocument.passport),
          CafDocumentDetectorFlow(document: CafDocument.any),
        ],
        uploadSettings: CafDocumentDetectorUploadSettings(enable: true),
        manualCaptureEnabled: false,
        manualCaptureTime: 45,
        showPopup: true,
        previewShow: false,
        securitySettings: CafDocumentDetectorSecuritySettings(
          useAdb: true,
          useDebug: true,
          useDevelopmentMode: true,
        ),
        instructionScreen:
            CafDocumentDetectorUIInstructionScreenConfiguration(
              enable: true,
              captureTitle: "Título da captura",
              captureSteps: ["Etapa de captura 1", "Etapa de captura 2"],
              uploadTitle: "Título do envio",
              uploadSteps: ["Etapa de envio 1", "Etapa de envio 2"],
              buttonText: "Texto do botão",
            ),
        documentSelectionScreen:
            CafDocumentDetectorUIDocumentSelectionScreenConfiguration(
              title: "Título da seleção de documento",
              description: "Descrição da seleção de documento",
            ),
      );

      await _cafSdk.initializeCafSdk(
        cafSdkConfiguration: config,
        documentDetectorUIConfiguration: documentDetectorUIConfig,
        faceLivenessUIConfiguration: faceLivenessUIConfig,
      );

      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('CAF SDK inicializado com sucesso!'),
            backgroundColor: Colors.green,
          ),
        );
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Erro: $e'), backgroundColor: Colors.red),
        );
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Exemplo do CAF SDK'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            _ConfigurationCard(
              mobileToken: _mobileToken,
              personId: _personId,
              environment: _environment,
            ),
            const SizedBox(height: 16),

            _ActionButtons(onInitialize: _initializeCafSdk),
            const SizedBox(height: 16),
          ],
        ),
      ),
    );
  }
}

class _ConfigurationCard extends StatelessWidget {
  const _ConfigurationCard({
    required this.mobileToken,
    required this.personId,
    required this.environment,
  });

  final String mobileToken;
  final String personId;
  final CafEnvironment environment;

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              'Configuração do CAF SDK',
              style: Theme.of(context).textTheme.titleLarge,
            ),
            const SizedBox(height: 16),
            Text(
              'Token móvel: ${mobileToken.length > 20 ? '${mobileToken.substring(0, 20)}...' : mobileToken}',
              style: Theme.of(context).textTheme.bodyMedium,
            ),
            const SizedBox(height: 8),
            Text(
              'ID da pessoa: $personId',
              style: Theme.of(context).textTheme.bodyMedium,
            ),
            const SizedBox(height: 8),
            Text(
              'Ambiente: $environment',
              style: Theme.of(context).textTheme.bodyMedium,
            ),
          ],
        ),
      ),
    );
  }
}

class _ActionButtons extends StatelessWidget {
  const _ActionButtons({
    required this.onInitialize,
  });

  final VoidCallback onInitialize;

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Expanded(
          child: ElevatedButton(
            onPressed: onInitialize,
            style: ElevatedButton.styleFrom(
              padding: const EdgeInsets.symmetric(vertical: 16),
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(8),
              ),
            ),
            child: Text('Inicializar SDK'),
          ),
        ),
        const SizedBox(width: 8),
      ],
    );
  }
}
```

***

## Regras ProGuard/R8

Adicione estas regras ProGuard/R8 ao seu `proguard-rules.pro` arquivo para Android:

```proguard
# Regras Flutter ProGuard/R8 para o Caf SDK
# Estas regras garantem que o plugin CAF SDK funcione corretamente em builds de release

# O pré-handler Android para exceções é carregado de forma reflexiva (via ServiceLoader).
-keep class kotlinx.coroutines.experimental.android.AndroidExceptionPreHandler { *; }

### GSON ##################################################################
# O Gson usa informações de tipo genérico armazenadas em um arquivo de classe ao trabalhar com campos.
# O ProGuard remove essas informações por padrão, então configure-o para manter tudo.
-keepattributes Signature
# Para usar a anotação GSON @Expose
-keepattributes *Annotation*
### FIM GSON ##################################################################

### Retrofit ##################################################################
# Preserve assinaturas genéricas, classes internas e métodos envolventes para reflexão do Retrofit.
-keepattributes Signature, InnerClasses, EnclosingMethod
# Retenha anotações visíveis em tempo de execução em métodos e parâmetros.
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
# Mantenha os valores padrão das anotações.
-keepattributes AnnotationDefault
# Retenha os parâmetros de métodos de serviço para interfaces com anotações do Retrofit.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
    @retrofit2.http.* <methods>;
}
# Suprima avisos para ferramentas de build e certas anotações JSR 305.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn javax.annotation.**
-dontwarn kotlin.Unit
-dontwarn retrofit2.KotlinExtensions
-dontwarn retrofit2.KotlinExtensions$*
# Mantenha explicitamente as interfaces Retrofit para evitar a anulação pelo R8.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface * extends <1>
# Preserve as continuations usadas pelas funções suspend do Kotlin.
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
# Para o modo completo do R8: mantenha tipos de retorno genéricos para métodos Retrofit.
-if interface * { @retrofit2.http.* public *** *(...); }
-keep,allowoptimization,allowshrinking,allowobfuscation class <3>
# Preserve a classe Response do Retrofit.
-keep,allowobfuscation,allowshrinking class retrofit2.Response
### FIM Retrofit ##############################################################

### OkHttp ####################################################################
# Suprima avisos para anotações JSR 305.
-dontwarn javax.annotation.**
# Ajuste os nomes de arquivos de recursos para o banco de dados interno de public suffix.
-adaptresourcefilenames okhttp3/internal/publicsuffix/PublicSuffixDatabase.gz
# Suprima avisos para o Animal Sniffer e classes específicas da plataforma.
-dontwarn org.codehaus.mojo.animal_sniffer.*
-dontwarn okhttp3.internal.platform.**
-dontwarn org.conscrypt.**
-dontwarn org.bouncycastle.**
-dontwarn org.openjsse.**
# Mantenha todas as classes do OkHttp e do Okio.
-keep class okhttp3.** { *; }
-dontwarn okhttp3.**
-keep class okio.** { *; }
-dontwarn okio.**
-dontwarn javax.annotation.Nullable
-dontwarn javax.annotation.ParametersAreNonnullByDefault
### FIM OkHttp ################################################################

### Kotlin Serialization ######################################################
# Mantenha objetos Companion para classes serializáveis.
-if @kotlinx.serialization.Serializable class **
-keepclassmembers class <1> {
    static <1>$Companion Companion;
}
# Mantenha funções serializer em objetos companion.
-if @kotlinx.serialization.Serializable class ** {
    static **$* *;
}
-keepclassmembers class <2>$<3> {
    kotlinx.serialization.KSerializer serializer(...);
}
# Mantenha INSTANCE e serializer para objetos serializáveis.
-if @kotlinx.serialization.Serializable class ** {
    public static ** INSTANCE;
}
-keepclassmembers class <1> {
    public static <1> INSTANCE;
    kotlinx.serialization.KSerializer serializer(...);
}
# Preserve objetos Companion em kotlinx.serialization.json.
-keepclassmembers class kotlinx.serialization.json.** {
    *** Companion;
}
-keepclasseswithmembers class kotlinx.serialization.json.** {
    kotlinx.serialization.KSerializer serializer(...);
}
# Preserve a busca do serializer para classes serializáveis (ajuste o nome do pacote conforme necessário).
-keepclassmembers @kotlinx.serialization.Serializable class packeage.** {
    *** Companion;
    *** INSTANCE;
    kotlinx.serialization.KSerializer serializer(...);
}
### FIM Kotlin Serialization #################################################

### AutoValue ################################################################
-dontwarn com.google.auto.**
-dontwarn autovalue.shaded.com.**
-dontwarn sun.misc.Unsafe
-dontwarn javax.lang.model.element.Modifier
### FIM AutoValue ############################################################

### Flutter Plugin ###########################################################
# Mantenha as classes do plugin Flutter
-keep class io.flutter.plugins.** { *; }

# Mantenha as classes do canal de método
-keep class * extends io.flutter.plugin.common.MethodChannel$MethodCallHandler { *; }
-keep class * extends io.flutter.plugin.common.MethodChannel$Result { *; }

# Mantenha o registrador do plugin
-keep class io.flutter.plugins.GeneratedPluginRegistrant { *; }

# Mantenha as classes do plugin Flutter do CAF SDK
-keep class io.caf.sdk.flutter.** { *; }
### FIM Flutter Plugin #######################################################

### CAF - Combate à Fraude ######################################################
# Mantenha os atributos de exceções.
-keepattributes Exceptions
# Preserve todas as classes, interfaces e membros de classe para os módulos CAF.
-keep class com.caf.facelivenessiproov.** { *; }
-keep class com.combateafraude.documentdetector.** { *; }
-keep class com.combateafraude.** { *; }
-keep interface com.combateafraude.** { *; }
-keep class io.caf.** { *; }
-keep interface io.caf.** { *; }
-keepclassmembers class com.combateafraude.** { *; }
# Suprima avisos para java.nio.file e certas classes internas do OkHttp.
-dontwarn java.nio.file.*
-dontwarn com.squareup.okhttp.internal.Platform
# Mantenha campos em classes que estendem GeneratedMessageLite (para uso do Tink).
-keepclassmembers class * extends com.google.crypto.tink.shaded.protobuf.GeneratedMessageLite {
  <fields>;
}
# Preserve classes do TensorFlow.
-keep class org.tensorflow.** { *; }
-keep class org.tensorflow.**$* { *; }
-dontwarn org.tensorflow.**
# Preserve classes do IProov e classes do Protobuf.
-keep public class com.iproov.sdk.IProov { public *; }
-keep class com.iproov.** { *; }
-keep class com.iproov.**$* { *; }
-keep class com.google.protobuf.** { *; }
-keep class com.google.protobuf.**$* { *; }
-dontwarn com.google.protobuf.**
# Suprima avisos para classes Flow concorrentes.
-dontwarn java.util.concurrent.Flow*
# Preserve classes Kotlin e kotlinx.
-keep class kotlin.** { *; }
-keep class kotlinx.** { *; }
# Preserve todas as classes do SDK FortFace/PayFace para evitar problemas de ofuscação
-keep class br.com.fortface.** { *; }
-keep interface br.com.fortface.** { *; }
-keepclassmembers class br.com.fortface.** { *; }
# Mantenha todas as classes internas e enums
-keepclassmembers class br.com.fortface.**$* { *; }
# Preserve completamente as classes JSON (crítico para o PayFace)
-keep class org.json.** { *; }
-keepclassmembers class org.json.** { *; }
# Preserve classes relacionadas a JSON usadas pelo SDK PayFace
-keepclassmembers class * {
    @org.json.** *;
}
# Suprima avisos para o SDK PayFace
-dontwarn br.com.fortface.**
-dontwarn com.android.tools.lint.**
-dontwarn io.caf.sdk.common.jvmshared.lint.**
### FIM CAF - Combate à Fraude ##################################################
```

***

## Suporte técnico e dicas de uso

**Suporte técnico** Se você tiver dúvidas ou dificuldades com a integração, entre em contato com o suporte técnico da Caf.

**Dicas de uso**

* **Execute testes:** Faça testes em dispositivos reais para validar os requisitos e o desempenho do fluxo
* **Explore personalizações:** Use opções avançadas de personalização para adaptar o fluxo às necessidades do seu projeto
* **Monitore o desempenho:** Integre ferramentas de monitoramento para acompanhar os logs e o desempenho do fluxo em produção
* **Lide com erros de forma adequada:** Implemente o tratamento adequado de erros para todos os cenários possíveis de erro e falha
* **Teste com dispositivos diferentes:** Garanta compatibilidade entre várias especificações de dispositivos e tamanhos de tela

***

## Notas de versão

### caf\_sdk\@2.2.0

#### **Data de lançamento**

* 08/14/2026

#### **Destaques**

* **Compatibilidade com Android 16:** Plugin Flutter atualizado para oferecer suporte ao Android 16 (`compileSdk` / `targetSdk` 36), alinhando-se aos requisitos do Google Play para apps voltados para versões recentes do Android.

#### **Correções**

**Liveness facial:** Corrigido um problema no fluxo do Payface em que uma validação facial com falha ainda podia ser reportada como sucesso. Agora o SDK trata corretamente falhas de validação e exibe a mensagem apropriada ao usuário.

**Detector de documentos:** Corrigidos problemas de captura e envio em tablets e dispositivos no modo paisagem, incluindo um breve flash incorreto da orientação da imagem na prévia, falhas de captura automática com fotos finais desalinhadas e pequenos ajustes de interface nas margens do layout e no botão de fechar.

#### **Atualizações**

* Plugin Flutter `compileSdk` / `targetSdk` atualizado para **36**.

### caf\_sdk\@2.1.0

#### Data de lançamento

* 08-03-2026

{% hint style="warning" %}
**Mudança incompatível:** O módulo Fingerprint agora é opcional e pode ser configurado em `caf-modules-config.json` por meio da nova `fingerprint` propriedade (booleano). Por padrão, o fingerprint é definido como `false`o que significa que você não precisa adicionar essa propriedade ao JSON, a menos que queira usá-la. Para habilitar o módulo, você deve adicionar explicitamente `"fingerprint": true`. Importante: o Fingerprint também deve estar habilitado no Backoffice. Se ele não estiver habilitado no Backoffice, o SDK nunca chamará a biblioteca de fingerprint e nenhum dado será enviado, mesmo se a propriedade estiver definida como `true` localmente.&#x20;
{% endhint %}

#### Destaques

* **Módulo Fingerprint opcional:** Controle a inclusão do recurso de fingerprint diretamente a partir de `caf-modules-config.json`. Ele vem desabilitado por padrão, garantindo que você inclua a dependência apenas quando estritamente necessário.

#### Atualizações

* Novo `fingerprint` campo booleano em `caf-modules-config.json` para Android e iOS.

```json
{
  "documentDetector": true,
  "faceLiveness": true,
  "documentDetectorUI": true,
  "faceLivenessUI": true,
  "livenessProviders": [
    "iproov-lite",
    "payface",
    "facetec"
  ],
  "fingerprint": true
}
```

### caf\_sdk\@2.0.0

#### Data de lançamento

* 07-06-2026

{% hint style="warning" %}
**Mudança incompatível:** A `eventStream` agora emite um **tipado `Stream<CafResponse>`** em vez de um `Stream<dynamic>` com dados brutos `Map` payloads. Atualize todos os listeners: substitua `event['eventName']` / `event['response']` com os campos tipados — `event.success`, `event.error`, `event.failure`, `event.log`, `event.loading`, `event.loaded`, e `event.cancelled`. Veja [Tratamento de eventos](#event-handling) para o exemplo completo de migração.
{% endhint %}

#### Destaques

* **Relato de erros mais consistente**: Erros que ocorrem durante a inicialização do fluxo e que se relacionam com a integração interna do SDK agora são emitidos via `error` evento como `BRIDGE_EXCEPTION`, para que possam ser tratados da mesma forma que qualquer outro erro do SDK.

#### Mudanças que Quebram Compatibilidade

* **Fluxo de eventos tipado**: `CafSdk.eventStream` agora é `Stream<CafResponse>`. Os consumidores devem acessar os campos tipados de `CafResponse` (`success`, `error`, `failure`, `log`, `loading`, `loaded`, `cancelled`) em vez de indexar um `Map`.
* **Classes de configuração de módulo planas**: As `...BuilderConfiguration` wrappers foram removidos. Os campos agora são passados diretamente nos objetos de configuração do módulo, e as configurações de UI estendem a configuração base em vez de aninhá-la:
  * `CafFaceLivenessBuilderConfiguration` removido — passe os campos diretamente em `CafFaceLivenessConfiguration`.
  * `CafDocumentDetectorBuilderConfiguration` removido — passe os campos diretamente em `CafDocumentDetectorConfiguration`.
  * `CafFaceLivenessUIBuilderInstructionScreenConfiguration` → `CafFaceLivenessUIInstructionScreenConfiguration`, e o campo `instructionScreenConfiguration` → `instructionScreen`.
  * `CafDocumentDetectorUIBuilderInstructionScreenConfiguration` → `CafDocumentDetectorUIInstructionScreenConfiguration`, e o campo `instructionScreenConfiguration` → `instructionScreen`.
  * `CafDocumentDetectorUIBuilderDocumentSelectionScreenConfiguration` → `CafDocumentDetectorUIDocumentSelectionScreenConfiguration`, e o campo `documentSelectionScreenConfiguration` → `documentSelectionScreen`.
  * No nível do SDK, `CafSdkConfiguration` permanece inalterado e ainda recebe `configuração: CafSdkBuilderConfiguration(...)`.
* **`initializeCafSdk` tipo de retorno**: mudou de `Future<bool?>` para `Future<bool>`.

#### Atualizações

* **Constantes de nomes de eventos**: Adicionadas as `CafSdkEventName` constantes (`CafUnifiedEvent.*`) para identificar eventos emitidos.
* **Novo `CafErrorType` valores**: Adicionados `INVALID_RESPONSE_EXCEPTION`, `CAMERA_EXCEPTION`, `FACE_AUTHENTICATION`, e `BRIDGE_EXCEPTION`. Note que `BRIDGE_EXCEPTION` relata erros que ocorrem ao inicializar ou iniciar o fluxo; ouça-o no `error` evento e trate-o como parte do seu tratamento normal de erros.
* **`CafSuccessResponse`**: `signedResponse` agora é tipado como `String?` (anteriormente `dynamic`), e `moduleName` a resolução é mais resiliente a variações de identificadores nativos.

#### Guia de Migração — 1.x → 2.0.0

Três coisas mudaram para os integradores: como você lê eventos, como constrói configurações de módulos e o tipo de retorno de `initializeCafSdk`. No nível do SDK, `CafSdkConfiguration` (com `CafSdkBuilderConfiguration`) permanece inalterado.

**1. Leia eventos do fluxo tipado**

```dart
// Antes (1.x) — Map bruto
_cafSdk.eventStream.listen((event) {
  final name = event['eventName'];
  final response = event['response'];
});

// Depois (2.0.0) — CafResponse tipado
_cafSdk.eventStream.listen((event) {
  if (event.success != null) {
    print('${event.success!.moduleName} -> ${event.success!.signedResponse}');
  } else if (event.error != null) {
    print('${event.error!.type} - ${event.error!.description}');
  }
  // também: event.failure, event.log, event.loading, event.loaded, event.cancelled
});
```

**2. Remova o módulo `...BuilderConfiguration` wrapper**

Passe os campos diretamente no objeto de configuração do módulo.

```dart
// Antes (1.x)
final faceLivenessConfig = CafFaceLivenessConfiguration(
  configuração: CafFaceLivenessBuilderConfiguration(
    loading: true,
    maxRetryAttempts: 2,
  ),
);

// Depois (2.0.0)
final faceLivenessConfig = CafFaceLivenessConfiguration(
  loading: true,
  maxRetryAttempts: 2,
);
```

```dart
// Antes (1.x)
final documentDetectorConfig = CafDocumentDetectorConfiguration(
  configuração: CafDocumentDetectorBuilderConfiguration(
    flow: [CafDocumentDetectorFlow(document: CafDocument.rgFront)],
    manualCaptureEnabled: false,
  ),
);

// Depois (2.0.0)
final documentDetectorConfig = CafDocumentDetectorConfiguration(
  flow: [CafDocumentDetectorFlow(document: CafDocument.rgFront)],
  manualCaptureEnabled: false,
);
```

**3. Atualize as configurações de UI (wrapper + tipos e campos renomeados)**

```dart
// Antes (1.x)
final faceLivenessUIConfig = CafFaceLivenessUIConfiguration(
  configuração: CafFaceLivenessBuilderConfiguration(loading: true),
  instructionScreenConfiguration:
      CafFaceLivenessUIBuilderInstructionScreenConfiguration(title: 'Face Liveness'),
);

// Depois (2.0.0)
final faceLivenessUIConfig = CafFaceLivenessUIConfiguration(
  loading: true,
  instructionScreen:
      CafFaceLivenessUIInstructionScreenConfiguration(title: 'Face Liveness'),
);
```

```dart
// Antes (1.x)
final documentDetectorUIConfig = CafDocumentDetectorUIConfiguration(
  configuração: CafDocumentDetectorBuilderConfiguration(
    flow: [CafDocumentDetectorFlow(document: CafDocument.rgFront)],
  ),
  instructionScreenConfiguration:
      CafDocumentDetectorUIBuilderInstructionScreenConfiguration(enable: true),
  documentSelectionScreenConfiguration:
      CafDocumentDetectorUIBuilderDocumentSelectionScreenConfiguration(title: 'Choose document'),
);

// Depois (2.0.0)
final documentDetectorUIConfig = CafDocumentDetectorUIConfiguration(
  flow: [CafDocumentDetectorFlow(document: CafDocument.rgFront)],
  instructionScreen:
      CafDocumentDetectorUIInstructionScreenConfiguration(enable: true),
  documentSelectionScreen:
      CafDocumentDetectorUIDocumentSelectionScreenConfiguration(title: 'Choose document'),
);
```

**4. Renomeie os imports de tipos (se você importou os tipos removidos)**

| Removido (1.x)                                                     | Use em vez disso (2.0.0)                                    |
| ------------------------------------------------------------------ | ----------------------------------------------------------- |
| `CafFaceLivenessBuilderConfiguration`                              | `CafFaceLivenessConfiguration`                              |
| `CafDocumentDetectorBuilderConfiguration`                          | `CafDocumentDetectorConfiguration`                          |
| `CafFaceLivenessUIBuilderInstructionScreenConfiguration`           | `CafFaceLivenessUIInstructionScreenConfiguration`           |
| `CafDocumentDetectorUIBuilderInstructionScreenConfiguration`       | `CafDocumentDetectorUIInstructionScreenConfiguration`       |
| `CafDocumentDetectorUIBuilderDocumentSelectionScreenConfiguration` | `CafDocumentDetectorUIDocumentSelectionScreenConfiguration` |

**5. Atualize o `initializeCafSdk` tipo de retorno**

`initializeCafSdk` agora retorna `Future<bool>` em vez de `Future<bool?>`. Remova quaisquer verificações de nulo no resultado aguardado.

```dart
// Antes (1.x)
final bool? started = await _cafSdk.initializeCafSdk(
  cafSdkConfiguration: config,
);
if (started == true) {
  // ...
}

// Depois (2.0.0)
final bool started = await _cafSdk.initializeCafSdk(
  cafSdkConfiguration: config,
);
if (started) {
  // ...
}
```

### caf\_sdk\@1.5.0

#### Data de lançamento

* 05-25-2026

#### Atualizações

* **Provedor de Liveness do Payface (Android)**: Atualize a versão de `1.18.2` para `1.19.2`.
* **Provedor de Liveness do Payface (iOS)**: Atualize a versão de `1.5.2` para `1.8.2`.

#### Correções

**FaceLiveness**

* O erro de carregamento infinito ocorre quando o SDK retorna um erro.
* A primeira inicialização não funciona ao usar `Payface` provedor.

### caf\_sdk\@1.4.0

#### Data de lançamento

* 05-08-2026

#### Correções

* **DocumentDetector**: Comportamento corrigido ao lidar com RG (Carteira de Identidade Nacional brasileira) com a opção de documento digital.

### caf\_sdk\@1.3.0

#### Data de lançamento

* 04-13-2026

{% hint style="warning" %}
**Mudança incompatível:** Os provedores de Face Liveness agora podem ser configurados em `caf-modules-config.json` via **`livenessProviders`** (string ou array). Quando fornecido, deve listar o(s) provedor(es) escolhido(s). Não use **`iproov-lite`** e **`iproov-full`** juntos—**`iproov-full`** usa uma versão diferente do Protobuf, e combiná-los causará erros de classes duplicadas no momento da compilação. **PayFace** requer **`iproov-lite`** (Protobuf JavaLite); emparelhar PayFace com **`iproov-full`** causa conflitos de Protobuf na compilação. Se omitido, o SDK usa como padrão **`iproov-lite`** em ambas as plataformas. Um **valor vazio ou inválido** causa um erro de compilação em **Android**; em **iOS**, um valor vazio também recorre a `iproov-lite`, mas um valor inválido causa falha na compilação. Veja [Passo 2: Configure a seleção de módulos](#step-2-configure-module-selection) para detalhes.
{% endhint %}

#### Destaques

* **Provedores de Face Liveness configuráveis**: Escolha `iproov-lite`, `iproov-full`, `payface`, e/ou `facetec` de `caf-modules-config.json` em vez de depender dos padrões nativos implícitos.

#### Atualizações

* **Configuração do provedor de Liveness**:
  * Novo **`livenessProviders`** campo em `caf-modules-config.json` para Android e iOS.
  * Documentado **Protobuf JavaLite** vs **Protobuf Java** mapeamento para **`iproov-lite`** vs **`iproov-full`**.
  * Esclarecido **multi-provedor** configurações usando um array, e o **PayFace + iProov Lite** requisito.
* **Provedor de Liveness iProov**: A documentação e os padrões foram atualizados para refletir o novo modelo de seleção de provedor.
* **Android ProGuard / R8**: Se o R8 relatar classes ausentes para os stubs de lint enviados com o SDK, adicione o seguinte ao `proguard-rules.pro` (também listado em [Regras ProGuard/R8](#proguardr8-rules)):

```proguard
-dontwarn com.android.tools.lint.**
-dontwarn io.caf.sdk.common.jvmshared.lint.**
```

### caf\_sdk\@1.2.0

#### Data de lançamento

* 02-09-2026

{% hint style="warning" %}
Versões anteriores à 1.2.0 farão com que o iProov Liveness fique inoperante a partir de 12 de março de 2026. Para garantir o funcionamento adequado e a continuidade do serviço, use a versão 1.2.0 ou posterior.
{% endhint %}

#### Destaques

* **Provedor de Liveness atualizado**: Atualização crítica para a versão do provedor iProov para melhorar a estabilidade

#### Atualizações

* **Provedor de Liveness iProov**: Atualizada a versão interna do provedor iProov.

### caf\_sdk\@1.1.0

#### Data de lançamento

* 02-09-2026

#### Destaques

* **Novo Módulo de Segurança**: Introdução do `CafSecurity` módulo para validações de segurança
* **Integração PayFace**: Adicionado suporte ao PayFace (Fortface) como provedor opcional de Face Liveness
* **Melhorias de estabilidade**: Correções importantes de falhas e melhorias de estabilidade para o módulo Document Detector

#### Funcionalidades

* **Módulo CafSecurity**:
  * Adicionado um novo módulo especificamente para validações de segurança
  * **Configuração**: Adicionados `enableSecurityModule` sinalizador em `CafSdkConfiguration` (valor padrão: `true`)
* **Integração PayFace (Fortface)**:
  * Integração opcional de provedor de Face Liveness
  * **Configuração**: Nova propriedade `payFaceDebugMode` em `CafFaceLivenessConfiguration` para ativar o modo de depuração do provedor PayFace

#### Correções

* **DocumentDetector**:
  * **Ciclo de vida da atividade**: Resolvidos múltiplos crashes relacionados ao gerenciamento do ciclo de vida da atividade (estados de inicialização, pausa e retomada)
  * **Ciclo de vida da câmera**: Melhorado o gerenciamento de recursos da câmera e o ciclo de vida das threads para evitar crashes durante o encerramento do SDK
  * **Componentes de UI**: Resolvidos problemas de compatibilidade de tema e exceções de transações de fragmentos
  * **Requisições de rede**: Corrigido o tratamento do corpo da resposta para evitar erros ao ler respostas de rede
  * **Acesso a dados**: Melhorada a inicialização e a validação do cursor antes de acessar dados do banco de dados
  * **Prevenção de ANR**: Otimizadas as verificações de instância do controlador de documento para evitar problemas de "Application Not Responding"
  * **Geral**: Melhorias internas e correções de estabilidade
* **FaceLiveness**:
  * **Sessões**: Corrigidos erros de criação de sessão
  * **UI**: Corrigido o tom de cor em imagens remotas na tela de Instruções

#### Atualizações

* **Configuração de compilação**:
  * **Regras do ProGuard**: Adicionadas as regras necessárias do ProGuard para a integração com PayFace

### caf\_sdk\@1.0.1

#### Data de lançamento

* 03-09-2026

#### Atualizações

* **Provedor de Liveness iProov atualizado**: Atualize a versão do provedor iProov.
* **Target mínimo de implantação do iOS atualizado**: Atualizado para `15.0`.

#### Correções

* **DocumentDetector**
  * **Corrigidas falhas no módulo Document Detector**: Resolvidos múltiplos crashes relacionados ao gerenciamento do ciclo de vida da atividade, incluindo estados de inicialização, pausa e retomada.
  * **Corrigidas falhas relacionadas ao ciclo de vida da câmera**: Melhorado o gerenciamento de recursos da câmera e o ciclo de vida das threads para evitar crashes durante o encerramento do SDK e as transições de estado.
  * **Corrigidas falhas em componentes de UI**: Resolvidos problemas de compatibilidade de tema e exceções de transações de fragmentos para garantir o comportamento adequado da UI.
  * **Corrigidas falhas em requisições de rede**: Corrigido o tratamento do corpo da resposta para evitar erros ao ler respostas de rede.
  * **Corrigidas falhas no acesso a dados**: Melhorada a inicialização e a validação do cursor antes de acessar dados do banco de dados.
  * **Corrigido ANR no Document Controller**: Otimizadas as verificações de instância do controlador de documento para evitar problemas de aplicação sem resposta.
  * **Melhorias e correções internas**: Melhorias adicionais de estabilidade e correções de bugs.

### caf\_sdk\@1.0.0

#### Data de lançamento

* 10-27-2025

#### Destaques

* **Primeiro lançamento do SDK Flutter**: Implementação completa em Flutter do SDK CAF para verificação de identidade
* **SDK unificado**: Pacote único contendo todos os módulos CAF (Face Liveness e Document Detector) com variantes core e UI
* **Integração Flutter-Nativo**: Integração perfeita com o sistema de widgets e o gerenciamento de estado do Flutter
* **Suporte multiplataforma**: Suporte total para as plataformas Android e iOS
* **Configuração com segurança de tipos**: Classes de configuração Dart fortemente tipadas para uma melhor experiência de desenvolvimento

#### Funcionalidades

* **Sistema de configuração de módulos**:
  * **`caf-modules-config.json`**: Arquivo de configuração na raiz do projeto para especificar quais módulos incluir
  * Módulos disponíveis:
    * `documentDetector`: Ativar/desativar o módulo Document Detector
    * `faceLiveness`: Ativar/desativar o módulo Face Liveness
    * `documentDetectorUI`: Ativar/desativar o módulo de UI do Document Detector
    * `faceLivenessUI`: Ativar/desativar o módulo de UI do Face Liveness
  * Exemplo de configuração:

    ```json
    {
      "documentDetector": true,
      "faceLiveness": true,
      "documentDetectorUI": false,
      "faceLivenessUI": false
    }
    ```
* **Recursos principais do SDK**:
  * **Classe CafSdk**: Classe principal do SDK para inicialização e configuração
  * **Fluxo de eventos**: Tratamento de eventos em tempo real por meio de streams Dart
  * **Gerenciamento de módulos**: Execução sequencial de módulos com ordem de apresentação configurável
  * **Tratamento de erros**: Tipos de erro abrangentes e tratamento de falhas
  * **Construtor de configuração**: Configuração com segurança de tipos usando o padrão builder
* **Módulo Face Liveness**:
  * **Módulo central**: `CafFaceLivenessConfiguration` para controle programático
  * **Módulo de UI**: `CafFaceLivenessUIConfiguration` com telas de instruções personalizáveis
  * **Funcionalidades**: URLs de autenticação, pinagem de certificado, modo de depuração, tentativas de repetição
  * **Personalização**: Telas de instruções com imagens, títulos, descrições e etapas
* **Módulo Document Detector**:
  * **Módulo central**: `CafDocumentDetectorConfiguration` para controle programático
  * **Módulo de UI**: `CafDocumentDetectorUIConfiguration` com personalização completa da UI
  * **Tipos de documentos**: Suporte para RG, CNH, Passaporte, RNE, CTPS e muito mais
  * **Suporte a upload**: Upload de arquivos com compressão, controle de formato e limites de tamanho
  * **Configuração de proxy**: Suporte para servidores proxy com autenticação
  * **Personalização de mensagens**: Mensagens de usuário personalizáveis ao longo de todo o fluxo
* **Configuração avançada**:
  * **Tema de cores**: Personalização completa das cores da UI por meio de `CafColorConfiguration`
  * **Configurações de segurança**: Sinalizadores de desenvolvimento, modo de depuração e controles de segurança
  * **Controle de fluxo**: Captura manual, timeouts, tentativas de repetição e controles de popup
  * **Telas de instrução**: Telas de instrução personalizáveis para ambos os módulos

#### Implementação técnica

* **Integração Flutter**:
  * **Canais de método**: Comunicação nativa por meio do sistema de method channels do Flutter
  * **Eventos baseados em streams**: Tratamento de eventos em tempo real usando streams Dart
  * **Gerenciamento de estado**: Gerenciamento adequado do ciclo de vida com `StatefulWidget` suporte
  * **Tratamento de erros**: Tratamento abrangente de erros com exceções tipadas
* **Suporte à plataforma**:
  * **Android**: Suporte total com regras do ProGuard/R8 e configuração de repositório Maven
  * **iOS**: Integração completa com CocoaPods e módulos nativos do iOS
  * **Permissões**: Tratamento adequado de permissões para acesso à câmera e à rede
* **Desempenho**:
  * **Carregamento seletivo de módulos**: Carregue somente módulos habilitados para otimizar o tamanho do bundle
  * **Gerenciamento de Memória**: Limpeza adequada de recursos e gerenciamento de memória
  * **Otimização de Rede**: Comunicação de rede eficiente com mecanismos de repetição

#### Instalação e Configuração

* **Instalação de Pacotes**: Instalação simples via `flutter pub add caf_sdk`
* **Configuração do Módulo**: Fácil seleção de módulos por meio de arquivo de configuração JSON
* **Configuração da Plataforma**: Instruções claras para a configuração das plataformas Android e iOS
* **Gerenciamento de Permissões**: Configuração abrangente de permissões para ambas as plataformas

#### Documentação

* **Exemplos Completos**: Exemplos completos de implementação para uso básico e avançado
* **Guia de Configuração**: Opções detalhadas de configuração para todos os módulos
* **Tratamento de eventos**: Exemplos e padrões abrangentes de tratamento de eventos
* **Referência de Erros**: Documentação completa dos tipos de erro e cenários de falha

#### Mudanças que Quebram Compatibilidade

* **Primeira Versão**: Esta é a primeira versão do SDK Flutter, então não há mudanças que quebrem compatibilidade em relação às versões anteriores.

#### Problemas Conhecidos

* **Simulador do iOS**: Alguns recursos podem não funcionar corretamente no Simulador do iOS devido a limitações da câmera
* **Emulador Android**: Recursos dependentes da câmera exigem dispositivos físicos para testes
* **Requisitos de Rede**: Todos os módulos exigem conectividade com a internet para funcionar corretamente


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.caf.io/caf-sdk/caf-sdk-pt-br/flutter/getting-started-with-the-sdk.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
