@41devs/naya-id-js 0.1.0 → 0.3.0
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 +117 -208
- package/dist/naya-id.cjs +422 -207
- package/dist/naya-id.cjs.map +1 -1
- package/dist/naya-id.d.cts +233 -81
- package/dist/naya-id.d.ts +233 -81
- package/dist/naya-id.min.js +422 -207
- package/dist/naya-id.min.js.map +1 -1
- package/dist/naya-id.mjs +422 -207
- package/dist/naya-id.mjs.map +1 -1
- package/package.json +36 -4
package/README.md
CHANGED
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @41devs/naya-id-js
|
|
2
2
|
|
|
3
|
-
SDK JavaScript officiel de **Naya ID
|
|
4
|
-
main pour l'Afrique de l'Ouest
|
|
5
|
-
|
|
6
|
-
seule méthode**, l'interface Naya s'ouvre en plein écran, prend en charge la
|
|
7
|
-
capture du document, la détection de vivacité et la décision, puis vous rend le
|
|
8
|
-
résultat et rend la main à votre page.
|
|
3
|
+
SDK JavaScript officiel de **Naya ID** — vérification d'identité (eKYC) clé en
|
|
4
|
+
main pour l'Afrique de l'Ouest. Une balise `<script>`, un Web Component ou un
|
|
5
|
+
import npm ; aucune dépendance à l'exécution ; ~40 Ko compressés.
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- **npm** : [`@41devs/naya-id-js`](https://www.npmjs.com/package/@41devs/naya-id-js)
|
|
15
|
-
- **Site** : https://naya.41devs.com
|
|
7
|
+
Le parcours : consentement → capture guidée du document (recto, verso pour la
|
|
8
|
+
CNI) → selfie avec **défi de vivacité imposé par le serveur** → confirmation des
|
|
9
|
+
données lues → décision expliquée. Sur ordinateur, relais vers le téléphone par
|
|
10
|
+
QR code. Trois langues : français, anglais, portugais.
|
|
16
11
|
|
|
17
12
|
---
|
|
18
13
|
|
|
19
|
-
##
|
|
14
|
+
## Démarrage rapide
|
|
15
|
+
|
|
16
|
+
### 1. Votre backend ouvre la session (recommandé)
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
curl -X POST https://api.naya.41devs.com/v1/verifications/start \
|
|
20
|
+
-H "X-API-Key: naya_live_xxx" -H "Content-Type: application/json" \
|
|
21
|
+
-d '{"documentType":"cni","country":"BJ","callbackUrl":"https://votre-backend.com/naya/hook"}'
|
|
22
|
+
# → { "data": { "verificationId": "…", "sessionToken": "…", "challenge": ["blink","turn-left","smile"] } }
|
|
23
|
+
```
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
La clé ne quitte jamais votre serveur. Rendez `verificationId` + `sessionToken`
|
|
26
|
+
au navigateur (voir `docs/backend-session.md` pour Node, PHP, Python).
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
`NayaId` :
|
|
28
|
+
### 2. Votre page lance le parcours
|
|
25
29
|
|
|
26
30
|
```html
|
|
27
|
-
<script
|
|
31
|
+
<script
|
|
32
|
+
src="https://sdk.naya.41devs.com/sdk/0.3.0/naya-id.min.js"
|
|
33
|
+
integrity="sha384-…"
|
|
34
|
+
crossorigin="anonymous"
|
|
35
|
+
></script>
|
|
28
36
|
<script>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
apiKey: 'naya_live_xxx',
|
|
32
|
-
config: { country: 'BJ' },
|
|
33
|
-
});
|
|
34
|
-
console.log(result.status, result.verificationId, result.ocrData);
|
|
35
|
-
});
|
|
37
|
+
const result = await NayaId.startVerification({ verificationId, sessionToken });
|
|
38
|
+
// result.status : 'approved' | 'review' | 'rejected' | 'cancelled' | 'error'
|
|
36
39
|
</script>
|
|
37
40
|
```
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
> fonctionne de la même façon : `https://unpkg.com/@41devs/naya-id-js`.
|
|
41
|
-
|
|
42
|
-
### Par npm (bundlers : Vite, webpack, Rollup…)
|
|
42
|
+
Ou avec npm :
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
45
|
npm install @41devs/naya-id-js
|
|
@@ -47,226 +47,135 @@ npm install @41devs/naya-id-js
|
|
|
47
47
|
|
|
48
48
|
```ts
|
|
49
49
|
import { startVerification } from '@41devs/naya-id-js';
|
|
50
|
-
|
|
51
|
-
const result = await startVerification({
|
|
52
|
-
apiKey: 'naya_live_xxx',
|
|
53
|
-
config: { country: 'BJ' },
|
|
54
|
-
});
|
|
50
|
+
const result = await startVerification({ verificationId, sessionToken, config: { locale: 'fr' } });
|
|
55
51
|
```
|
|
56
52
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
(MediaPipe) est chargée à la demande depuis un CDN au moment du selfie.
|
|
53
|
+
Ne décidez jamais sur le résultat rendu par le navigateur : seul le webhook (ou
|
|
54
|
+
`GET /verifications/:id` avec votre clé) fait foi.
|
|
60
55
|
|
|
61
56
|
---
|
|
62
57
|
|
|
63
58
|
## Prérequis
|
|
64
59
|
|
|
65
|
-
| Élément
|
|
66
|
-
|
|
67
|
-
| **
|
|
68
|
-
| **
|
|
69
|
-
| **
|
|
70
|
-
| **
|
|
60
|
+
| Élément | Détail |
|
|
61
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
62
|
+
| **Compte Naya vérifié (KYB)** | Sinon l'API répond `403` (`kyb_pending`). |
|
|
63
|
+
| **HTTPS** | La caméra exige un contexte sécurisé (`http://localhost` en développement). |
|
|
64
|
+
| **Navigateur** | Chrome, Safari, Firefox, Edge récents. Les navigateurs intégrés (WhatsApp, Facebook, Instagram) sont détectés : le SDK propose d'ouvrir le lien dans le navigateur. |
|
|
65
|
+
| **Origine (mode clé)** | Une clé **live** transmise au navigateur doit déclarer ses origines dans le dashboard. Sans objet avec le jeton de session. |
|
|
71
66
|
|
|
72
67
|
---
|
|
73
68
|
|
|
74
|
-
##
|
|
75
|
-
|
|
76
|
-
`startVerification` retourne une promesse qui se résout quand l'utilisateur
|
|
77
|
-
ressort du parcours, avec le résultat.
|
|
78
|
-
|
|
79
|
-
```js
|
|
80
|
-
const result = await NayaId.startVerification({
|
|
81
|
-
apiKey: 'naya_live_xxx',
|
|
82
|
-
config: {
|
|
83
|
-
country: 'BJ', // pré-sélectionne le pays
|
|
84
|
-
callbackUrl: 'https://votre-backend.com/naya/hook', // notification serveur (optionnel)
|
|
85
|
-
},
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
switch (result.status) {
|
|
89
|
-
case 'approved': // Identité vérifiée. result.ocrData contient les champs extraits.
|
|
90
|
-
break;
|
|
91
|
-
case 'review': // Revue manuelle : décision finale notifiée plus tard via callbackUrl.
|
|
92
|
-
break;
|
|
93
|
-
case 'rejected': // Refus (result.note explique pourquoi).
|
|
94
|
-
break;
|
|
95
|
-
case 'cancelled': // L'utilisateur a fermé le parcours avant la fin.
|
|
96
|
-
break;
|
|
97
|
-
case 'error': // Problème technique : result.errorMessage.
|
|
98
|
-
console.error(result.errorMessage);
|
|
99
|
-
break;
|
|
100
|
-
}
|
|
101
|
-
```
|
|
69
|
+
## API
|
|
102
70
|
|
|
103
|
-
`startVerification
|
|
104
|
-
revient toujours sous forme de `NayaResult` (`status: 'error'` ou `'cancelled'`).
|
|
71
|
+
### `startVerification(params) → Promise<NayaResult>`
|
|
105
72
|
|
|
106
|
-
|
|
73
|
+
| Champ | Type | Rôle |
|
|
74
|
+
| --------------------------------- | ------------ | --------------------------------------------------------------------- |
|
|
75
|
+
| `verificationId` + `sessionToken` | `string` | Session ouverte par votre backend. **Production.** |
|
|
76
|
+
| `apiKey` | `string` | Clé d'application transmise au navigateur. Démos et fronts maîtrisés. |
|
|
77
|
+
| `config` | `NayaConfig` | Voir ci-dessous. |
|
|
107
78
|
|
|
108
|
-
|
|
79
|
+
Ne rejette jamais : erreurs et annulation reviennent en `NayaResult`.
|
|
109
80
|
|
|
110
|
-
|
|
81
|
+
### `create(params) → NayaVerification`
|
|
111
82
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
3. **Capture du document** — recto, puis verso pour la CNI (bande MRZ). Cadre vert quand l'image est nette ; l'utilisateur déclenche.
|
|
115
|
-
4. **Vivacité** — selfie avec défi actif : regarder droit → cligner → tourner la tête.
|
|
116
|
-
5. **Traitement** — OCR, biométrie, décision côté serveur.
|
|
117
|
-
6. **Résultat** — approuvé / en revue / rejeté, puis retour à votre page.
|
|
83
|
+
Instance avec `open()`, `close()`, `on(event, cb)`, `destroy()`, `isOpen` —
|
|
84
|
+
pour les enveloppes de framework et l'analytique (`docs/frameworks.md`).
|
|
118
85
|
|
|
119
|
-
|
|
120
|
-
n'affecte le SDK, ni l'inverse.
|
|
121
|
-
|
|
122
|
-
---
|
|
86
|
+
### `isSupported() → NayaSupport`
|
|
123
87
|
|
|
124
|
-
|
|
88
|
+
À appeler avant d'afficher votre bouton : `ok`, `code`, `inAppBrowserName`,
|
|
89
|
+
`deviceClass`…
|
|
125
90
|
|
|
126
|
-
###
|
|
91
|
+
### `<naya-id-verification>`
|
|
127
92
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
| `apiKey` | `string` | Clé d'application, transmise depuis le navigateur. |
|
|
131
|
-
| `sessionToken` | `string` | Jeton de session éphémère obtenu par votre backend (à privilégier). |
|
|
132
|
-
| `auth` | `{ apiKey?, sessionToken? }` | Alternative aux deux champs ci-dessus, en objet. |
|
|
133
|
-
| `config` | `NayaConfig` | Configuration optionnelle (voir ci-dessous). |
|
|
93
|
+
Web Component enregistré automatiquement par le bundle `<script>` ;
|
|
94
|
+
`defineElement()` en ESM/CJS.
|
|
134
95
|
|
|
135
96
|
### Configuration (`config`)
|
|
136
97
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
|
141
|
-
|
|
142
|
-
| `
|
|
143
|
-
| `
|
|
144
|
-
| `
|
|
145
|
-
| `
|
|
146
|
-
| `
|
|
147
|
-
| `
|
|
148
|
-
| `
|
|
149
|
-
| `
|
|
150
|
-
| `livenessAssets`
|
|
151
|
-
| `
|
|
98
|
+
| Champ | Défaut | Rôle |
|
|
99
|
+
| --------------------------------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
100
|
+
| `country`, `countries`, `documentTypes` | tous | Pré-sélection ; l'écran de choix est sauté si un seul document et un pays. |
|
|
101
|
+
| `locale` | langue du navigateur | `fr`, `en`, `pt`. |
|
|
102
|
+
| `consent` | `true` | Écran de consentement ; `{ policyUrl, version }` ou `false` si recueilli en amont. |
|
|
103
|
+
| `confirmOcr` | `false` | Écran des données lues : `'display'` (lecture seule, l'utilisateur dit si c'est exact) ou `'edit'` (corrections saisies). `ocrData` n'est jamais altéré : le déclaré part à part (`declaredData`), un écart plafonne à la revue. |
|
|
104
|
+
| `capture` | `{ autoCapture: true, maxDimension: 1600, fileUpload: 'auto' }` | Capture automatique, taille d'image, import de fichier (ordinateur). |
|
|
105
|
+
| `liveness` | `{ timeoutMs: 45000, allowPassive: true, preload: true }` | Délai avant conseils, parcours sans geste, préchargement. |
|
|
106
|
+
| `handoff` | `true` | Relais QR vers mobile sur ordinateur ; `{ baseUrl }` pour une page hébergée par vous. |
|
|
107
|
+
| `container` | `null` | Monte dans un élément au lieu d'un overlay plein écran. |
|
|
108
|
+
| `theme` | encre / flamme | `primaryColor`, `accentColor`, `fontFamily`, `radius`, `mode` (`light`, `dark`, `auto`). Le texte des boutons reste lisible quelle que soit la couleur. |
|
|
109
|
+
| `clientLogoUrl` | — | Logo affiché à côté de « Propulsé par Naya ID ». |
|
|
110
|
+
| `strings` | — | Surcharge de libellés par clé. |
|
|
111
|
+
| `livenessAssets` | CDN Naya | Auto-hébergement de MediaPipe (`docs/csp-and-self-hosting.md`). |
|
|
112
|
+
| `callbackUrl` | — | Mode clé uniquement ; en session serveur, l'URL est posée à l'ouverture. |
|
|
113
|
+
| `maxAttempts` | `2` | Nouveaux essais après rejet (mode clé). |
|
|
114
|
+
| `eagerSession` | `false` | Ouvre la session dès le choix du document (latence) — attention à la facturation. |
|
|
115
|
+
| `telemetry` | `true` | Télémétrie anonyme (`docs/telemetry.md`). |
|
|
116
|
+
| `debug` | `false` | Journal `[NayaId]` dans la console. |
|
|
117
|
+
| `haptics` | `true` | Retour haptique sur mobile. |
|
|
118
|
+
| `onEvent` | — | Hook d'événements (`ready`, `step`, `session`, `document_captured`, `liveness_step`, `submitted`, `result`, `error`…). |
|
|
152
119
|
|
|
153
120
|
### Résultat (`NayaResult`)
|
|
154
121
|
|
|
155
|
-
| Champ
|
|
156
|
-
|
|
157
|
-
| `status` | `
|
|
158
|
-
| `verificationId`
|
|
159
|
-
| `
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
164
|
-
| `ocrData` | `NayaOcrData` | champs extraits (nom, prénoms, date de naissance, n° document, NPI…) |
|
|
165
|
-
| `note` | `string` | note d'analyse du pipeline |
|
|
166
|
-
| `errorMessage` | `string` | uniquement si `status === 'error'` |
|
|
167
|
-
|
|
168
|
-
---
|
|
169
|
-
|
|
170
|
-
## Authentification
|
|
171
|
-
|
|
172
|
-
Un seul des deux champs est à renseigner :
|
|
173
|
-
|
|
174
|
-
| Mode | Usage |
|
|
175
|
-
|---|---|
|
|
176
|
-
| `apiKey` | Simple, mais la clé est **lisible dans le navigateur** (outils de dev). À réserver aux démos et aux intégrations où le front est maîtrisé. |
|
|
177
|
-
| `sessionToken` | Jeton éphémère obtenu par **votre backend**, limité à une vérification. **À privilégier en production** : la clé ne quitte jamais votre serveur. |
|
|
178
|
-
|
|
179
|
-
```js
|
|
180
|
-
// Production : votre backend échange sa clé contre un jeton de session.
|
|
181
|
-
await NayaId.startVerification({
|
|
182
|
-
sessionToken: jetonObtenuDeVotreBackend,
|
|
183
|
-
config: { country: 'BJ' },
|
|
184
|
-
});
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
Passer de l'un à l'autre ne change rien au reste de l'intégration.
|
|
188
|
-
|
|
189
|
-
---
|
|
190
|
-
|
|
191
|
-
## Notifications serveur (`callbackUrl`)
|
|
192
|
-
|
|
193
|
-
En passant `callbackUrl`, votre backend est notifié à chaque décision, sans
|
|
194
|
-
interroger l'API. Deux événements possibles par session :
|
|
195
|
-
`verification.completed` (décision automatique) puis, le cas échéant,
|
|
196
|
-
`verification.reviewed` (après revue d'un analyste). Les envois sont signés
|
|
197
|
-
(`X-Naya-Signature`, HMAC-SHA256). Détails côté documentation de l'API.
|
|
198
|
-
|
|
199
|
-
---
|
|
200
|
-
|
|
201
|
-
## Détection de vivacité
|
|
202
|
-
|
|
203
|
-
La vivacité s'exécute **sur l'appareil** via [MediaPipe Face Landmarker]. Le
|
|
204
|
-
module et le modèle sont chargés depuis un CDN public **au moment du selfie**
|
|
205
|
-
seulement — aucune configuration requise, et rien n'alourdit le chargement
|
|
206
|
-
initial de votre page. L'analyse est **locale** : la photo n'est transmise qu'à
|
|
207
|
-
la fin du défi.
|
|
208
|
-
|
|
209
|
-
Pour une page à **CSP stricte** (hôtes externes bloqués), auto-hébergez ces
|
|
210
|
-
ressources et indiquez leurs URL :
|
|
211
|
-
|
|
212
|
-
```js
|
|
213
|
-
config: {
|
|
214
|
-
country: 'BJ',
|
|
215
|
-
livenessAssets: {
|
|
216
|
-
esmUrl: '/assets/naya/vision_bundle.mjs', // module @mediapipe/tasks-vision
|
|
217
|
-
wasmBaseUrl: '/assets/naya/wasm', // dossier wasm/ du paquet
|
|
218
|
-
modelUrl: '/assets/naya/face_landmarker.task', // modèle MediaPipe
|
|
219
|
-
},
|
|
220
|
-
}
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
Copiez `vision_bundle.mjs`, le dossier `wasm/` et le modèle
|
|
224
|
-
`face_landmarker.task` de `@mediapipe/tasks-vision@1.0.1`.
|
|
225
|
-
|
|
226
|
-
[MediaPipe Face Landmarker]: https://ai.google.dev/edge/mediapipe/solutions/vision/face_landmarker
|
|
122
|
+
| Champ | Présent | Rôle |
|
|
123
|
+
| ------------------------------------------------------ | ------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
124
|
+
| `status` | toujours | `approved`, `review`, `rejected`, `cancelled`, `error`. |
|
|
125
|
+
| `verificationId` | dès qu'une session existe | À conserver pour rapprocher webhooks et dashboard. |
|
|
126
|
+
| `reasonCodes` | décision | Motifs stables : `DOC_EXPIRED`, `FACE_MISMATCH`, `LIVENESS_LOW`, `AML_SANCTION`… (`docs/errors.md`). |
|
|
127
|
+
| `livenessMode` | décision | `active` ou `passive`. |
|
|
128
|
+
| `errorCode`, `errorMessage`, `statusCode`, `requestId` | `status: 'error'` | Catalogue dans `docs/errors.md` ; `requestId` pour le support. |
|
|
129
|
+
| scores, `ocrData`, `note` | décision | Indicatifs ; la vérité est côté serveur. `ocrData` est l'extraction brute, jamais modifiée. |
|
|
130
|
+
| `declaredData`, `dataMismatches`, `dataDisputed` | décision | Ce que l'utilisateur a déclaré ou contesté, conservé à part ; à vous de l'afficher ou non. |
|
|
227
131
|
|
|
228
132
|
---
|
|
229
133
|
|
|
230
|
-
##
|
|
134
|
+
## Sécurité, en deux lignes
|
|
231
135
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
- L'interface s'ouvre en superposition plein écran (Shadow DOM) et fige le
|
|
237
|
-
défilement de la page tant que le parcours est ouvert.
|
|
136
|
+
Le jeton de session n'ouvre qu'une vérification, expire en 4 h et meurt à la
|
|
137
|
+
soumission. Le défi de vivacité est tiré par le serveur et vérifié par lui ;
|
|
138
|
+
le score calculé sur l'appareil ne décide jamais. Les ressources MediaPipe
|
|
139
|
+
viennent du CDN Naya, empreinte du modèle vérifiée, repli public possible.
|
|
238
140
|
|
|
239
141
|
---
|
|
240
142
|
|
|
241
|
-
##
|
|
143
|
+
## Documentation
|
|
242
144
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
145
|
+
- `docs/backend-session.md` — ouvrir la session côté serveur (Node, PHP, Python)
|
|
146
|
+
- `docs/webhooks.md` — notifications signées
|
|
147
|
+
- `docs/errors.md` — catalogue des `errorCode`
|
|
148
|
+
- `docs/csp-and-self-hosting.md` — CSP, pare-feu, auto-hébergement, SRI
|
|
149
|
+
- `docs/frameworks.md` — Web Component, React, Vue, Angular, conteneur
|
|
150
|
+
- `docs/liveness-challenge-spec.md` — spécification du défi (commune aux SDK)
|
|
151
|
+
- `docs/telemetry.md`, `docs/accessibility.md`, `docs/migration-0.2-to-0.3.md`
|
|
152
|
+
- `hosting/README.md` — CDN `sdk.naya.41devs.com`
|
|
250
153
|
|
|
251
154
|
---
|
|
252
155
|
|
|
253
|
-
## Développement
|
|
156
|
+
## Développement
|
|
254
157
|
|
|
255
158
|
```bash
|
|
256
|
-
npm
|
|
257
|
-
npm run
|
|
258
|
-
npm run
|
|
159
|
+
npm ci
|
|
160
|
+
npm run typecheck && npm run lint && npm test # unitaires (vitest, jsdom)
|
|
161
|
+
npm run build && npm run size # dist/ + budget de taille
|
|
162
|
+
npm run assets:fetch # MediaPipe local pour le parcours complet e2e
|
|
163
|
+
npx playwright install chromium && npm run test:e2e # parcours réel, caméra factice, API simulée
|
|
164
|
+
npm run serve # example/index.html
|
|
259
165
|
```
|
|
260
166
|
|
|
261
|
-
|
|
262
|
-
`example/index.html` sur `http://localhost` (contexte sécurisé requis) :
|
|
263
|
-
|
|
264
|
-
```bash
|
|
265
|
-
npm run serve # puis http://localhost:3000/example/
|
|
266
|
-
```
|
|
167
|
+
Publication : tag `vX.Y.Z` → CI → `npm publish --provenance`.
|
|
267
168
|
|
|
268
169
|
---
|
|
269
170
|
|
|
270
|
-
##
|
|
171
|
+
## Dépannage
|
|
172
|
+
|
|
173
|
+
| Symptôme | Cause probable |
|
|
174
|
+
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
175
|
+
| `errorCode: 'origin_not_allowed'` | Clé live utilisée depuis une origine non déclarée : dashboard → clé → Origines autorisées, ou passez au jeton de session. |
|
|
176
|
+
| `errorCode: 'network'` | Hors-ligne, pare-feu ou proxy qui bloque `api.naya.41devs.com` ; CSP trop stricte (`docs/csp-and-self-hosting.md`). |
|
|
177
|
+
| `errorCode: 'in_app_browser'` | Lien ouvert dans WhatsApp/Facebook : le SDK propose de copier le lien. |
|
|
178
|
+
| `errorCode: 'liveness_assets'` | Module MediaPipe injoignable : autoriser `sdk.naya.41devs.com` ou auto-héberger. |
|
|
179
|
+
| Décision `review` avec `LIVENESS_PASSIVE` | L'utilisateur a choisi le parcours sans geste : revue humaine attendue. |
|
|
271
180
|
|
|
272
|
-
|
|
181
|
+
Licence : voir `LICENSE`.
|