@neofaceid/web-sdk 1.40.2 → 1.41.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,34 @@
1
1
  # NeoFace ID SDK Web
2
2
 
3
- SDK para captura e reconhecimento facial em aplicações web.
3
+ SDK JavaScript/TypeScript (React) para autenticação, cadastro e verificação
4
+ facial em aplicações web, publicado no npm como
5
+ [`@neofaceid/web-sdk`](https://www.npmjs.com/package/@neofaceid/web-sdk).
6
+
7
+ Veja o [`CHANGELOG.md`](CHANGELOG.md) para o histórico de versões.
8
+
9
+ ## Índice
10
+
11
+ - [Instalação](#instalação)
12
+ - [Requisitos do consumer](#requisitos-do-consumer)
13
+ - [Início rápido](#início-rápido)
14
+ - [LGPD e consentimento](#lgpd-e-consentimento)
15
+ - [Fluxos principais](#fluxos-principais)
16
+ - [Login facial (`startFaceLogin`)](#login-facial-startfacelogin)
17
+ - [Login por mão / automático](#login-por-mão--automático-starthandlogin-startautologin)
18
+ - [Cadastro biométrico (`startBiometricRegistration`)](#cadastro-biométrico-startbiometricregistration)
19
+ - [Captura de liveness (`startLivenessCapture`)](#captura-de-liveness-startlivenesscapture)
20
+ - [Onboarding completo (`startOnboarding`)](#onboarding-completo-startonboarding)
21
+ - [Captura de documento (`startDocumentCapture`)](#captura-de-documento-startdocumentcapture)
22
+ - [Autorização por biometria (`authorize` / `authorizeOperation`)](#autorização-por-biometria-authorize--authorizeoperation)
23
+ - [Classe `NeoFaceID` (`proofOfLife` e afins)](#classe-neofaceid-proofoflife-e-afins)
24
+ - [Tratamento de erros](#tratamento-de-erros)
25
+ - [Componentes React exportados](#componentes-react-exportados)
26
+ - [Sessão de captura e desafio de liveness (baixo nível)](#sessão-de-captura-e-desafio-de-liveness-baixo-nível)
27
+ - [Trilha de consentimento (auditoria LGPD)](#trilha-de-consentimento-auditoria-lgpd)
28
+ - [API de baixo nível (`api.ts`)](#api-de-baixo-nível-apits)
29
+ - [Versão do SDK](#versão-do-sdk)
30
+ - [Compatibilidade](#compatibilidade)
31
+ - [Licença](#licença)
4
32
 
5
33
  ## Instalação
6
34
 
@@ -8,318 +36,509 @@ SDK para captura e reconhecimento facial em aplicações web.
8
36
  npm install @neofaceid/web-sdk
9
37
  ```
10
38
 
11
- ## Uso Básico
12
-
13
- ```javascript
14
- import { start } from '@neofaceid/web-sdk';
15
-
16
- // Inicialize o SDK com seu token de aplicação
17
- start('seu-token-de-aplicacao', {
18
- onSuccess: (user) => {
19
- console.log('Usuário autenticado:', user);
20
- // user contém: { name, email, documentId }
39
+ `react` e `react-dom` são `peerDependencies` (`^18.0.0 || ^19.0.0`) — o
40
+ projeto consumidor precisa já ter as duas instaladas.
41
+
42
+ ## Requisitos do consumer
43
+
44
+ Antes de usar qualquer fluxo do SDK, confirme os itens abaixo no projeto que
45
+ vai consumi-lo:
46
+
47
+ 1. **HTTPS.** O SDK acessa a câmera via `getUserMedia`, que exige contexto
48
+ seguro. `localhost` funciona em desenvolvimento; produção precisa de
49
+ HTTPS (recomendado configurar HSTS no servidor).
50
+ 2. **`face-api.js` já vem como dependência transitiva** do
51
+ `@neofaceid/web-sdk` (não precisa instalar de novo) — mas os **pesos do
52
+ modelo (weights) não são publicados no bundle** e precisam ser
53
+ auto-hospedados pelo consumer. O SDK carrega os modelos em runtime via
54
+ `faceapi.nets.<rede>.loadFromUri('/models')`, ou seja, relativos à própria
55
+ origem do seu app. Baixe os arquivos abaixo do repositório oficial de
56
+ pesos do face-api.js e sirva-os em `public/models/` (ou equivalente do seu
57
+ bundler) para que fiquem acessíveis em `/models/*`:
58
+ - `tiny_face_detector_model-weights_manifest.json` +
59
+ `tiny_face_detector_model-shard1`
60
+ - `face_landmark_68_model-weights_manifest.json` +
61
+ `face_landmark_68_model-shard1`
62
+
63
+ Sem esses arquivos em `/models`, qualquer fluxo que dependa de detecção
64
+ facial local (blink detection do liveness, `biometricDetection`) falha ao
65
+ carregar o modelo.
66
+ 3. **Ícone/logo do SDK não precisa de asset externo.** Desde a 1.29.0 a marca
67
+ é renderizada via SVG inline (`src/assets/brand.ts`) — não há mais PNG
68
+ para hospedar.
69
+ 4. **`applicationToken`** válido, obtido no painel administrativo do
70
+ NeoFace ID.
71
+ 5. **Ambiente correto configurado via `init`** — veja
72
+ [Início rápido](#início-rápido). O default (sem `init`) é `sandbox`.
73
+
74
+ ## Início rápido
75
+
76
+ ```ts
77
+ import { init } from '@neofaceid/web-sdk';
78
+
79
+ init({
80
+ environment: 'sandbox', // 'development' | 'sandbox' | 'production'
81
+ applicationToken: 'seu-token-de-aplicacao',
82
+ appName: 'Minha Aplicação', // exibido no topo dos modais
83
+ consent: {
84
+ purpose: 'authentication',
85
+ legalBasis: 'fraud_prevention', // 'consent' | 'legal_obligation' | 'fraud_prevention'
86
+ privacyPolicyUrl: 'https://minha-app.com/privacidade',
87
+ retentionDays: 0,
21
88
  },
22
- onError: (code, message) => {
23
- console.error('Erro:', code, message);
24
- }
25
89
  });
26
90
  ```
27
91
 
28
- ## Versão
92
+ Mapeamento de `environment` → URL base ([`src/config.ts`](src/config.ts)):
29
93
 
30
- O SDK segue o padrão de versionamento semântico (SemVer):
94
+ | `environment` | URL base |
95
+ | -------------- | ------------------------------------ |
96
+ | `development` | `http://localhost:8000` |
97
+ | `sandbox` | `https://sandbox-core.neofaceid.com` |
98
+ | `production` | `https://core.neofaceid.com.br` |
31
99
 
32
- ```javascript
33
- import { VERSION, RELEASE_DATE } from '@neofaceid/web-sdk';
100
+ Use `baseUrl` em vez de `environment` para apontar para uma URL customizada
101
+ (tem precedência sobre `environment`). Outras opções de `init` — tema visual
102
+ do integrador:
34
103
 
35
- console.log(`Usando NeoFace ID SDK versão ${VERSION} (lançada em ${RELEASE_DATE})`);
104
+ ```ts
105
+ init({
106
+ accent: '#0059C4', // cor do botão primário; contraste < 4.5 vs branco = fallback + warn
107
+ radius: 16, // 8 | 16 | 24, fallback 16 se fora da lista
108
+ theme: 'auto', // 'light' | 'dark' | 'auto' (respeita prefers-color-scheme)
109
+ locale: 'pt-BR',
110
+ });
36
111
  ```
37
112
 
38
- ### Histórico de Versões
113
+ Getters correspondentes: `getBaseUrl()`, `getEnvironment()`,
114
+ `getApplicationToken()`, `getConsent()`, `isInitialized()`, `getConfig()`,
115
+ `getAppName()`, `getAccent()`, `getRadius()`, `getTheme()`, `getLocale()`,
116
+ `getResolvedThemeMode()`, e o mapa `ENVIRONMENT_URLS`.
117
+
118
+ ## LGPD e consentimento
119
+
120
+ Todo fluxo que abre a câmera (`start`, `startBiometricRegistration`,
121
+ `startLivenessCapture`, `startFaceLogin`, `startHandLogin`, `startAutoLogin`,
122
+ `startOnboarding`, `startDocumentCapture`, `authorizeOperation`, `authorize`)
123
+ chama internamente `requestConsent({ appName, flow })` **antes** de qualquer
124
+ `getUserMedia()`. Se o titular recusar, o callback de erro recebe
125
+ `NeoFaceError` com `ErrorType.CONSENT_DENIED` e a câmera nunca é aberta.
126
+
127
+ Configure a base legal uma vez em `init({ consent })` (ver
128
+ [Início rápido](#início-rápido)) — omitir gera `console.warn` e usa defaults
129
+ conservadores (`fraud_prevention`, sem URL de política, retenção
130
+ indefinida). Também é possível chamar `requestConsent` diretamente para UI
131
+ customizada:
132
+
133
+ ```ts
134
+ import { requestConsent, DEFAULT_CONSENT_INFO } from '@neofaceid/web-sdk';
135
+
136
+ const accepted = await requestConsent({
137
+ ...DEFAULT_CONSENT_INFO,
138
+ appName: 'Minha Aplicação',
139
+ flow: 'registration', // 'verification' (imagem descartada) | 'registration' (guarda vetor matemático)
140
+ });
141
+ ```
39
142
 
40
- | Versão | Data | Mudanças |
41
- |--------|------|----------|
42
- | 1.0.0 | 2023-06-15 | Lançamento inicial do SDK |
143
+ Toda decisão de consentimento pode ser auditada — veja
144
+ [Trilha de consentimento](#trilha-de-consentimento-auditoria-lgpd).
43
145
 
44
- ## Parâmetros
146
+ ## Fluxos principais
45
147
 
46
- ### applicationToken (string)
47
- Token de autenticação da sua aplicação. Obtenha este token no painel de administração do NeoFace ID.
148
+ ### Login facial (`startFaceLogin`)
48
149
 
49
- ### callbacks (object)
150
+ Overlay minimalista estilo Face ID (não mostra a câmera na tela).
50
151
 
51
- #### onSuccess (function)
52
- Chamado quando o reconhecimento facial é bem-sucedido.
53
- - Parâmetros: `user` (object) - Contém `name`, `email` e `documentId` do usuário reconhecido.
152
+ ```ts
153
+ import { startFaceLogin } from '@neofaceid/web-sdk';
54
154
 
55
- #### onError (function)
56
- Chamado quando ocorre um erro durante o processo.
57
- - Parâmetros:
58
- - `code` (string) - Código do erro
59
- - `message` (string) - Mensagem descritiva do erro
155
+ await startFaceLogin({
156
+ applicationToken: 'seu-token-de-aplicacao',
157
+ appName: 'Minha Aplicação',
158
+ onSuccess: result => console.log('Login ok:', result),
159
+ onError: err => console.error(err.type, err.getFriendlyMessage()),
160
+ onCancel: () => console.log('Usuário cancelou'),
161
+ onFallbackRequest: () => {
162
+ /* opcional — default já abre EmailPasswordModal */
163
+ },
164
+ });
165
+ ```
60
166
 
61
- ### Códigos de Erro
167
+ ### Login por mão / automático (`startHandLogin`, `startAutoLogin`)
62
168
 
63
- | Código | Descrição |
64
- |--------|-----------|
65
- | `TOKEN_VALIDATION_ERROR` | Token de aplicação inválido ou expirado |
66
- | `NO_CAMERA` | Câmera não disponível ou permissão negada |
67
- | `FACE_NOT_DETECTED` | Nenhum rosto detectado na imagem |
68
- | `MULTIPLE_FACES` | Múltiplos rostos detectados na imagem |
69
- | `FACE_NOT_CENTERED` | Rosto não está centralizado no frame |
70
- | `LIVENESS_CHECK_FAILED` | Verificação de vivacidade falhou |
71
- | `RECOGNITION_FAILED` | Falha no reconhecimento facial |
72
- | `NETWORK_ERROR` | Erro de conexão com o servidor |
73
- | `TIMEOUT` | Tempo limite excedido durante o processo |
169
+ Mesma assinatura de `startFaceLogin` (`BiometricLoginOptions`); `startAutoLogin`
170
+ detecta rosto ou mão automaticamente.
74
171
 
75
- ## Customização
172
+ ```ts
173
+ import { startHandLogin, startAutoLogin } from '@neofaceid/web-sdk';
76
174
 
77
- O modal de captura facial pode ser customizado através de CSS. Adicione as seguintes classes ao seu CSS:
175
+ await startHandLogin({ applicationToken, onSuccess, onError });
176
+ await startAutoLogin({ applicationToken, onSuccess, onError });
177
+ ```
78
178
 
79
- ```css
80
- /* Container principal */
81
- #neoface-modal-container {
82
- /* Estilos para o container */
83
- }
179
+ ### Cadastro biométrico (`startBiometricRegistration`)
84
180
 
85
- /* Modal */
86
- #neoface-modal-container .modal {
87
- /* Estilos para o modal */
88
- }
181
+ ```ts
182
+ import { startBiometricRegistration } from '@neofaceid/web-sdk';
89
183
 
90
- /* Botões */
91
- #neoface-modal-container .button {
92
- /* Estilos para os botões */
93
- }
184
+ startBiometricRegistration(
185
+ {
186
+ name: 'Maria Silva',
187
+ birth_date: '1990-05-20',
188
+ cpf: '12345678900',
189
+ email: 'maria@exemplo.com',
190
+ password: 'senha-forte',
191
+ },
192
+ 'seu-token-de-aplicacao',
193
+ {
194
+ onSuccess: result => console.log('Cadastro concluído:', result.person_id),
195
+ onError: err => console.error(err.type, err.message),
196
+ },
197
+ { appName: 'Minha Aplicação' }
198
+ );
199
+ ```
94
200
 
95
- /* Mensagens */
96
- #neoface-modal-container .message {
97
- /* Estilos para as mensagens */
98
- }
201
+ ### Captura de liveness (`startLivenessCapture`)
99
202
 
100
- /* Guia de posicionamento */
101
- #neoface-modal-container .guide {
102
- /* Estilos para o guia de posicionamento */
103
- }
203
+ Só a captura de fotos com prova de vida, sem cadastro — útil quando o
204
+ consumer já tem seu próprio pipeline de reconhecimento.
205
+
206
+ ```ts
207
+ import { startLivenessCapture } from '@neofaceid/web-sdk';
208
+
209
+ startLivenessCapture(
210
+ 'seu-token-de-aplicacao',
211
+ {
212
+ onSuccess: (photos: Blob[]) => console.log(`${photos.length} fotos capturadas`),
213
+ onError: err => console.error(err.type, err.message),
214
+ onCancel: () => console.log('Usuário fechou o modal'),
215
+ },
216
+ { appName: 'Minha Aplicação' }
217
+ );
104
218
  ```
105
219
 
106
- ## Requisitos de Segurança
220
+ ### Onboarding completo (`startOnboarding`)
107
221
 
108
- ### HTTPS
109
- O SDK requer uma conexão HTTPS para funcionar. Em ambiente de desenvolvimento, você pode usar `localhost`.
222
+ Orquestra: validação do link → consentimento → captura de rosto e
223
+ documento → conclusão no backend.
110
224
 
111
- ### Permissões
112
- O SDK solicita permissão para acessar a câmera do dispositivo. Esta permissão é essencial para o funcionamento do reconhecimento facial.
225
+ ```ts
226
+ import { startOnboarding } from '@neofaceid/web-sdk';
113
227
 
114
- ### HSTS
115
- Recomendamos configurar HTTP Strict Transport Security (HSTS) no servidor para garantir que todas as conexões sejam feitas via HTTPS.
228
+ await startOnboarding({
229
+ applicationToken: 'seu-token-de-aplicacao',
230
+ onboardingToken: 'token-do-link-de-onboarding',
231
+ appName: 'Minha Aplicação',
232
+ onSuccess: result => console.log('Onboarding concluído:', result.person_id),
233
+ onError: err => console.error(err.type, err.message),
234
+ onCancel: () => console.log('Usuário cancelou'),
235
+ });
236
+ ```
116
237
 
117
- ### Privacidade
118
- O SDK não armazena dados biométricos localmente. Todas as imagens são processadas em tempo real e descartadas após o reconhecimento.
238
+ ### Captura de documento (`startDocumentCapture`)
119
239
 
120
- ## Notas de Performance
240
+ ```ts
241
+ import { startDocumentCapture } from '@neofaceid/web-sdk';
121
242
 
122
- - **Resolução Adaptativa**: O SDK ajusta automaticamente a resolução da câmera com base nas capacidades do dispositivo.
123
- - **Compressão JPEG**: As imagens são comprimidas antes do envio para otimizar o uso de banda.
124
- - **Timeout**: O processo de reconhecimento tem um timeout de 10 segundos para evitar que o usuário fique aguardando indefinidamente.
243
+ const result = await startDocumentCapture({
244
+ appName: 'Minha Aplicação',
245
+ preSelectedDocument: 'CNH', // 'RG' | 'CNH' | 'CPF' — pula a tela de seleção
246
+ useBackCamera: true,
247
+ });
125
248
 
126
- ## Compatibilidade
249
+ if (result.success) {
250
+ console.log('Frente:', result.frontImage);
251
+ console.log('Verso:', result.backImage); // null se o documento não tem verso
252
+ }
253
+ ```
127
254
 
128
- ### Navegadores Suportados
129
- - Chrome 60+
130
- - Firefox 55+
131
- - Safari 11+
132
- - Edge 79+
255
+ ### Autorização por biometria (`authorize` / `authorizeOperation`)
133
256
 
134
- ### Responsividade
135
- O SDK é totalmente responsivo e funciona em dispositivos desktop e mobile. Em dispositivos móveis, o modal ocupa a tela inteira para uma melhor experiência do usuário.
257
+ `authorize` é a API atual (protocolo Focus Frame, orquestra
258
+ `runLivenessChallenge` — o servidor decide a sequência de gestos e a
259
+ aprovação final):
136
260
 
137
- ## Integração com .NET Framework
261
+ ```ts
262
+ import { authorize } from '@neofaceid/web-sdk';
138
263
 
139
- O NeoFace ID SDK Web pode ser facilmente integrado em aplicações web desenvolvidas com .NET Framework 4.8 ou superior. Siga os passos abaixo para implementar a autenticação facial em seu projeto ASP.NET:
264
+ await authorize({
265
+ applicationToken: 'seu-token-de-aplicacao',
266
+ subject: '12345678900', // CPF, e-mail ou id opaco do titular
267
+ appName: 'Minha Aplicação',
268
+ amount: 1250, // exibido como "R$ 1.250,00"
269
+ challenges: 2, // 0-3, teto sugerido; servidor decide a sequência real
270
+ onChallengeStart: (gesture, index, total) => console.log(gesture, index, total),
271
+ onSuccess: collectResult => {
272
+ // envie collectResult.capturedGestures ao seu próprio endpoint de recognition
273
+ },
274
+ onError: err => console.error(err.type, err.message),
275
+ onCancel: () => console.log('Usuário cancelou'),
276
+ });
277
+ ```
140
278
 
141
- ### 1. Instalação via NuGet
279
+ `authorizeOperation` é a variante legada, mais baixo nível (captura 4 fotos
280
+ com gestos fixos e chama `recognizeByPurpose('AUTHORIZATION')` diretamente):
142
281
 
143
- Adicione o pacote ao seu projeto .NET:
282
+ ```ts
283
+ import { authorizeOperation } from '@neofaceid/web-sdk';
144
284
 
145
- ```powershell
146
- Install-Package NeoFaceId.WebSdk
285
+ const result = await authorizeOperation('seu-token-de-aplicacao', '12345678900', {
286
+ appName: 'Minha Aplicação',
287
+ onProgress: (step, total, instruction) => console.log(instruction, step, total),
288
+ onPhotoTaken: (n, blob) => console.log('Foto', n, blob),
289
+ });
147
290
  ```
148
291
 
149
- Ou adicione a referência ao seu arquivo `.csproj`:
292
+ ### Classe `NeoFaceID` (`proofOfLife` e afins)
150
293
 
151
- ```xml
152
- <PackageReference Include="NeoFaceId.WebSdk" Version="1.0.2" />
153
- ```
294
+ `NeoFaceID` reúne operações que não têm (ainda) uma função `start*`
295
+ dedicada: prova de vida com gravação de vídeo, captura de múltiplos frames,
296
+ login com assinatura para integrações externas, registro de aplicação e
297
+ registro de documento pós-cadastro.
298
+
299
+ ```ts
300
+ import { NeoFaceID } from '@neofaceid/web-sdk';
301
+
302
+ const sdk = new NeoFaceID({ appToken: 'seu-token-de-aplicacao' });
154
303
 
155
- ### 2. Configuração no Web.config
304
+ // Prova de vida: grava vídeo curto, envia para o backend, faz polling do resultado
305
+ const proof = await sdk.proofOfLife({
306
+ videoDurationMs: 3000,
307
+ onRecordingProgress: progress => console.log(`Gravando: ${progress}%`),
308
+ onTaskStatusChange: (status, progress) => console.log(status, progress),
309
+ });
310
+ if (proof.success && proof.isLive) {
311
+ console.log('Liveness score:', proof.livenessScore);
312
+ console.log('Dados da pessoa:', proof.personalData);
313
+ }
156
314
 
157
- Adicione a configuração do token no seu arquivo `Web.config`:
315
+ // Login com assinatura (integrações externas — ex.: sistemas que já geram HMAC)
316
+ const sdkExterno = new NeoFaceID({
317
+ appToken: 'seu-token-de-aplicacao',
318
+ signature: signatureFromBackend, // HMAC-SHA256 hex, mínimo 64 chars
319
+ sessionData: { email: 'user@exemplo.com', cpf: '12345678900', sessionId: 'session-uuid' },
320
+ });
321
+ const frames = await sdkExterno.captureFaceFrames({ numFrames: 5, livenessCheck: true });
322
+ const login = await sdkExterno.loginRecognition({
323
+ biometricData: frames,
324
+ typeOfIdentification: 'FACE',
325
+ purpose: 'LOGIN',
326
+ });
158
327
 
159
- ```xml
160
- <configuration>
161
- <appSettings>
162
- <add key="NeoFaceId:ApplicationToken" value="seu-token-de-aplicacao" />
163
- </appSettings>
164
- </configuration>
328
+ // Registro de documento para pessoa já cadastrada
329
+ const docResult = await sdk.registerDocumentByImage(personId, userJwtToken);
330
+ console.log('Task ID:', docResult.taskId);
165
331
  ```
166
332
 
167
- ### 3. Implementação no Código
168
-
169
- #### No Controller (C#)
170
-
171
- ```csharp
172
- using System.Web.Mvc;
173
- using NeoFaceId.WebSdk;
174
-
175
- public class AuthenticationController : Controller
176
- {
177
- private readonly string _applicationToken;
178
-
179
- public AuthenticationController()
180
- {
181
- _applicationToken = System.Configuration.ConfigurationManager.AppSettings["NeoFaceId:ApplicationToken"];
182
- }
183
-
184
- public ActionResult Index()
185
- {
186
- return View();
187
- }
188
-
189
- [HttpPost]
190
- public JsonResult AuthenticateUser(string name, string email, string documentId)
191
- {
192
- // Processar a autenticação do usuário
193
- // Este método é chamado após o reconhecimento facial bem-sucedido
194
-
195
- // Exemplo: Criar sessão do usuário
196
- Session["UserName"] = name;
197
- Session["UserEmail"] = email;
198
- Session["UserDocumentId"] = documentId;
199
-
200
- return Json(new { success = true });
201
- }
333
+ ## Tratamento de erros
334
+
335
+ Toda falha do SDK (nos fluxos novos) é uma instância de `NeoFaceError`, com
336
+ `error.type` (`ErrorType`) e `error.getFriendlyMessage()` para exibir ao
337
+ usuário final sem termos técnicos:
338
+
339
+ ```ts
340
+ import { NeoFaceError, ErrorType } from '@neofaceid/web-sdk';
341
+
342
+ function onError(err: NeoFaceError) {
343
+ if (err.type === ErrorType.CONSENT_DENIED) {
344
+ // usuário recusou o consentimento — não abriu câmera
345
+ }
346
+ alert(err.getFriendlyMessage());
202
347
  }
203
348
  ```
204
349
 
205
- #### Na View (Razor)
350
+ > Desde a 1.41.0, `start`, `startBiometricRegistration` e
351
+ > `startLivenessCapture` também usam `onError(err: NeoFaceError)` — antes
352
+ > usavam `onError(code: string, message: string)`. Veja o `CHANGELOG.md`
353
+ > (breaking change) se seu código ainda depende da assinatura antiga.
354
+
355
+ | `ErrorType` | Quando ocorre |
356
+ | ----------------------- | --------------------------------------------------------------- |
357
+ | `NETWORK` | Erro de conexão com o servidor |
358
+ | `INVALID_TOKEN` | `applicationToken` inválido ou expirado |
359
+ | `RECOGNITION_FAILED` | Falha no reconhecimento facial |
360
+ | `LOGIN_FAILED` | Falha no login biométrico |
361
+ | `VALIDATION_ERROR` | Dados inválidos ou rosto não detectado corretamente |
362
+ | `API_ERROR` | Erro genérico de API (400/500) |
363
+ | `PERSON_NOT_FOUND` | Pessoa não encontrada na base |
364
+ | `INITIALIZATION_ERROR` | Falha ao inicializar um fluxo |
365
+ | `CAMERA_ERROR` | Erro genérico de câmera |
366
+ | `NO_CAMERA` | Câmera não disponível ou permissão negada |
367
+ | `CAPTURE_ERROR` | Falha durante a captura de imagem/vídeo |
368
+ | `NOT_FOUND` | Recurso não encontrado |
369
+ | `UNKNOWN` | Erro não categorizado |
370
+ | `CONSENT_DENIED` | Titular recusou o consentimento LGPD |
371
+ | `LIVENESS_BLINK_MISSING`| Piscada real (EAR) não detectada na janela de liveness (3s) |
372
+
373
+ ## Componentes React exportados
374
+
375
+ Para quem prefere montar a própria árvore React em vez de usar as funções
376
+ `start*` (que já cuidam de criar/desmontar o container):
377
+
378
+ ```tsx
379
+ import {
380
+ FaceCaptureModal,
381
+ BiometricRegistrationModal,
382
+ ConsentModal,
383
+ EmailPasswordModal,
384
+ ForgotPasswordModal,
385
+ BiometricStatusOverlay,
386
+ FallbackPrompt,
387
+ DocumentCaptureModal,
388
+ } from '@neofaceid/web-sdk';
389
+ ```
206
390
 
207
- ```html
208
- @{
209
- ViewBag.Title = "Autenticação Facial";
210
- }
391
+ Todos recebem `accessToken`/`applicationToken`, `onSuccess`/`onError` e
392
+ `onClose` conforme o fluxo — consulte a assinatura de cada `start*`
393
+ correspondente acima para as props equivalentes.
211
394
 
212
- <div class="container">
213
- <h2>Autenticação Facial</h2>
214
-
215
- <button id="startFaceAuth" class="btn btn-primary">Iniciar Autenticação Facial</button>
216
-
217
- <div id="authResult"></div>
218
- </div>
219
-
220
- @section Scripts {
221
- <script src="~/Scripts/neoface-id-sdk.js"></script>
222
- <script>
223
- document.getElementById('startFaceAuth').addEventListener('click', function() {
224
- // Inicializar o SDK com o token da aplicação
225
- NeoFaceId.start('@System.Configuration.ConfigurationManager.AppSettings["NeoFaceId:ApplicationToken"]', {
226
- onSuccess: function(user) {
227
- // Enviar dados do usuário para o servidor
228
- $.ajax({
229
- url: '@Url.Action("AuthenticateUser", "Authentication")',
230
- type: 'POST',
231
- data: {
232
- name: user.name,
233
- email: user.email,
234
- documentId: user.documentId
235
- },
236
- success: function(response) {
237
- if (response.success) {
238
- document.getElementById('authResult').innerHTML =
239
- '<div class="alert alert-success">Autenticação bem-sucedida!</div>';
240
- // Redirecionar para a página principal após autenticação
241
- setTimeout(function() {
242
- window.location.href = '@Url.Action("Index", "Home")';
243
- }, 1500);
244
- }
245
- },
246
- error: function() {
247
- document.getElementById('authResult').innerHTML =
248
- '<div class="alert alert-danger">Erro ao processar autenticação no servidor.</div>';
249
- }
250
- });
251
- },
252
- onError: function(code, message) {
253
- document.getElementById('authResult').innerHTML =
254
- '<div class="alert alert-danger">Erro: ' + message + '</div>';
255
- }
256
- });
257
- });
258
- </script>
259
- }
395
+ ## Sessão de captura e desafio de liveness (baixo nível)
396
+
397
+ Usado internamente por `authorize`/`authorizeOperation`, mas exportado para
398
+ quem monta o próprio orquestrador de liveness:
399
+
400
+ ```ts
401
+ import {
402
+ openCaptureSession,
403
+ requestLivenessChallenge,
404
+ runLivenessChallenge,
405
+ } from '@neofaceid/web-sdk';
406
+
407
+ const session = await openCaptureSession({
408
+ applicationToken: 'seu-token-de-aplicacao',
409
+ purpose: 'authorization', // 'login' | 'onboarding' | 'authorization' | 'identification' | 'liveness'
410
+ });
411
+
412
+ const challenge = await requestLivenessChallenge({
413
+ applicationToken: 'seu-token-de-aplicacao',
414
+ sessionId: session.session_id,
415
+ });
416
+
417
+ // Ou o fluxo completo (session → challenge → coleta via callback → retorno):
418
+ const collected = await runLivenessChallenge({
419
+ applicationToken: 'seu-token-de-aplicacao',
420
+ purpose: 'login',
421
+ collectFramesForGesture: async (gesture, index, total) => {
422
+ // capture o(s) frame(s) correspondente(s) ao gesto e retorne os Blobs
423
+ return [] as Blob[];
424
+ },
425
+ });
260
426
  ```
261
427
 
262
- ### 4. Personalização do Modal
428
+ ## Trilha de consentimento (auditoria LGPD)
263
429
 
264
- Para personalizar a aparência do modal de captura facial, adicione os estilos CSS ao seu arquivo `Site.css` ou ao layout principal:
430
+ ```ts
431
+ import { recordConsent, getConsentTrail, clearConsentTrail } from '@neofaceid/web-sdk';
265
432
 
266
- ```css
267
- /* Estilos para o modal de captura facial */
268
- #neoface-modal-container .modal {
269
- border-radius: 8px;
270
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
271
- }
433
+ // Grava no localStorage apenas hash(userAgent+purpose+timestamp), timestamp,
434
+ // finalidade, base legal e versão do SDK — zero PII. Usa por padrão o
435
+ // `consent` configurado em `init()`; pode ser sobrescrito pontualmente:
436
+ await recordConsent({ purpose: 'authentication', legalBasis: 'fraud_prevention' });
272
437
 
273
- #neoface-modal-container .button {
274
- background-color: #007bff;
275
- color: white;
276
- border: none;
277
- padding: 8px 16px;
278
- border-radius: 4px;
279
- cursor: pointer;
280
- }
438
+ const trail = getConsentTrail(); // ConsentRecord[] — histórico local (máx. 100, FIFO)
439
+ clearConsentTrail(); // limpa o histórico (ex.: logout)
440
+ ```
281
441
 
282
- #neoface-modal-container .button:hover {
283
- background-color: #0069d9;
284
- }
442
+ ## API de baixo nível (`api.ts`)
443
+
444
+ Funções que os fluxos `start*` já usam por baixo dos panos, expostas para
445
+ integrações que precisam de controle fino sobre a chamada HTTP:
446
+
447
+ ```ts
448
+ import {
449
+ validateToken,
450
+ validateOnboardingToken,
451
+ recognize,
452
+ recognizeBiometric,
453
+ simpleIdentification,
454
+ recognizeByPurpose,
455
+ loginWithBiometric,
456
+ loginWithEmail,
457
+ registerPersonWithoutFace,
458
+ registerPersonWithBiometric,
459
+ registerBiometric,
460
+ identifyPerson,
461
+ identifyPersonAsync,
462
+ checkUserExistence,
463
+ requestPasswordReset,
464
+ confirmPasswordReset,
465
+ completeOnboarding,
466
+ completeOnboardingWithData,
467
+ } from '@neofaceid/web-sdk';
468
+
469
+ await validateToken('seu-token-de-aplicacao'); // boolean
470
+ await validateOnboardingToken('seu-token-de-aplicacao', 'token-do-onboarding'); // boolean
471
+
472
+ await recognize(faceBlob, 'seu-token-de-aplicacao');
473
+ await recognizeBiometric(faceBlob, 'seu-token-de-aplicacao', /* livenessCheck */ true, 0.8);
474
+ await simpleIdentification('CPF', '12345678900', 'seu-token-de-aplicacao');
475
+ await recognizeByPurpose(faceBlob, 'seu-token-de-aplicacao', 'LOGIN', 0.8);
476
+
477
+ await loginWithBiometric(faceBlob, 'seu-token-de-aplicacao');
478
+ await loginWithEmail('user@exemplo.com', 'senha', 'seu-token-de-aplicacao');
479
+
480
+ await registerPersonWithoutFace(
481
+ { name: 'Maria Silva', birth_date: '1990-05-20', cpf: '12345678900', email: 'maria@exemplo.com', password: 'senha-forte' },
482
+ 'seu-token-de-aplicacao'
483
+ );
484
+ await registerPersonWithBiometric(
485
+ { name: 'Maria Silva', birth_date: '1990-05-20', cpf: '12345678900', email: 'maria@exemplo.com', password: 'senha-forte' },
486
+ [faceBlob1, faceBlob2],
487
+ 'seu-token-de-aplicacao'
488
+ );
489
+ await registerBiometric(personId, faceBlob, 'seu-token-de-aplicacao');
490
+
491
+ await identifyPerson(faceBlob, 'seu-token-de-aplicacao');
492
+ await identifyPersonAsync(faceBlob, 'seu-token-de-aplicacao', { maxRetries: 5, interval: 1000 });
493
+ await checkUserExistence({ email: 'user@exemplo.com' }); // ou { cpf }
494
+
495
+ await requestPasswordReset('user@exemplo.com', 'seu-token-de-aplicacao');
496
+ await confirmPasswordReset('token-do-email', 'nova-senha');
497
+
498
+ await completeOnboarding('seu-token-de-aplicacao', 'token-do-onboarding', faceBlob, documentBlob);
499
+ await completeOnboardingWithData(
500
+ 'seu-token-de-aplicacao',
501
+ 'token-do-onboarding',
502
+ { name: 'Maria Silva', cpf: '12345678900' },
503
+ [faceBlob1, faceBlob2],
504
+ documentBlob
505
+ );
285
506
  ```
286
507
 
287
- ### 5. Considerações de Segurança
508
+ Utilitário de performance para pré-carregar os modelos de detecção facial
509
+ antes do primeiro uso (evita o delay do primeiro `loadFromUri` acontecer
510
+ durante a interação do usuário):
511
+
512
+ ```ts
513
+ import { preloadFaceDetectionModels } from '@neofaceid/web-sdk';
288
514
 
289
- - Sempre valide os dados recebidos do cliente no servidor
290
- - Utilize HTTPS para todas as comunicações
291
- - Armazene o token de aplicação de forma segura (nunca no código-fonte)
292
- - Considere implementar rate limiting para evitar abusos
293
- - Implemente logs de auditoria para rastrear tentativas de autenticação
515
+ preloadFaceDetectionModels(); // dispara o carregamento de /models em background
516
+ ```
294
517
 
295
- ## Deploy Automático
518
+ ## Versão do SDK
296
519
 
297
- O SDK é publicado automaticamente no NPM quando há push na branch `master`. O workflow:
520
+ ```ts
521
+ import { VERSION, RELEASE_DATE } from '@neofaceid/web-sdk';
298
522
 
299
- 1. **Valida** que está rodando na branch master
300
- 2. **Verifica** se a versão atual já existe no NPM (idempotente)
301
- 3. **Determina** o tipo de bump (patch/minor) baseado no commit message
302
- 4. **Incrementa** a versão em todos os arquivos (package.json, package-lock.json, src/version.ts)
303
- 5. **Commita** e faz push das mudanças com retry logic
304
- 6. **Builda** o pacote
305
- 7. **Publica** no NPM com retry automático em caso de falhas temporárias
523
+ console.log(`NeoFace ID SDK ${VERSION} (${RELEASE_DATE})`);
524
+ ```
306
525
 
307
- ### Convenções de Commit
526
+ Histórico completo em [`CHANGELOG.md`](CHANGELOG.md).
308
527
 
309
- - `feat:` ou `feature:` → bump **minor** (1.0.0 → 1.1.0)
310
- - `fix:` ou `patch:` → bump **patch** (1.0.0 → 1.0.1)
311
- - Outros commits → bump **patch** por padrão
528
+ ## Compatibilidade
312
529
 
313
- ### Idempotência
530
+ ### Navegadores suportados
314
531
 
315
- O workflow é idempotente: se a versão já existe no NPM, o deploy é pulado automaticamente sem erro.
532
+ - Chrome 60+
533
+ - Firefox 55+
534
+ - Safari 11+
535
+ - Edge 79+
316
536
 
317
- ### Retry Logic
537
+ ### Responsividade
318
538
 
319
- - **Git sync**: 3 tentativas com backoff exponencial
320
- - **NPM publish**: 3 tentativas com backoff exponencial
321
- - **Erro 409**: Verifica se versão existe antes de falhar
539
+ O SDK é totalmente responsivo. Em dispositivos móveis, os modais ocupam a
540
+ tela inteira.
322
541
 
323
542
  ## Licença
324
543
 
325
- MIT
544
+ MIT