> For the complete documentation index, see [llms.txt](https://docs.facephi.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.facephi.com/sdks/backend-sdk/iad/technical_documentation/technical_specifications.md).

# Especificaciones técnicas

## Requisitos mínimos

| Componente | Requisito                     |
| ---------- | ----------------------------- |
| SO         | Linux x86\_64 (Ubuntu 20.04+) |
| CPU        | 4 núcleos                     |
| Memoria    | 4 GB RAM                      |
| Disco      | 1 GB de espacio libre         |

## Recomendado para producción

| Componente     | Recomendación             |
| -------------- | ------------------------- |
| SO             | Ubuntu 24.04 LTS          |
| CPU            | 8+ núcleos                |
| Memoria        | 8 GB+ RAM                 |
| Red            | Conexión de baja latencia |
| Almacenamiento | SSD para logs             |

## Requisitos de red

### Conectividad saliente

El servicio debe poder alcanzar:

* Los servidores de licencia de Facephi (para la validación de la licencia)

### Acceso al servidor de licencias

**IPs y puertos requeridos:**

| IP           | Puerto | Protocolo |
| ------------ | ------ | --------- |
| 52.223.22.71 | 443    | TCP/IP    |
| 35.71.188.31 | 443    | TCP/IP    |
| 75.2.113.112 | 443    | TCP/IP    |
| 99.83.149.57 | 443    | TCP/IP    |

**URLs requeridas:**

* `https://api.cryptlex.com:443`
* `https://api.eu.cryptlex.com:443`

Configura las reglas del firewall para permitir el tráfico HTTPS saliente hacia estos endpoints.

## Arquitectura de despliegue

IAD Service opera como una API REST sin estado que evalúa payloads de captura y devuelve un contrato público de Facephi:

```
Client → IAD Service (Port 6982)
```

* Se pueden ejecutar varias instancias del servicio detrás de un balanceador de carga
* Cada instancia mantiene los recursos internos necesarios para el procesamiento de capturas
* El servicio no almacena estado de sesión

## Compatibilidad de la API pública

{% hint style="danger" %}
**Aviso de cambio incompatible (2.0.0)** La API REST pública expuesta por la versión 2.0.0 rompe la compatibilidad con la serie 1.x.x. Esto afecta al contrato de comunicación, no solo a la documentación. Las integraciones deben migrar las rutas de los endpoints, los nombres de los campos multipart y las reglas de análisis de las respuestas correctas.
{% endhint %}

| Área de integración             | 1.x.x                       | 2.0.0                           |
| ------------------------------- | --------------------------- | ------------------------------- |
| Endpoint de liveness            | `/api/v1/iad/check-capture` | `/api/v1/iad/liveness/evaluate` |
| Endpoint de extracción          | `/api/v1/iad/extract-image` | `/api/v1/iad/extract`           |
| Campo de la solicitud multipart | `file`                      | `capture`                       |
| Payload correcto de liveness    | Campos privados heredados   | Campos públicos de Facephi      |

## Mitigación experimental de ataques de repetición (replay)

El servicio puede aplicar una ventana de vigencia (freshness window) a los payloads de captura entrantes. Esta protección experimental está deshabilitada por defecto.

* Actívala con `FACEPHI_IAD_REPLAY_ATTACK_CHECKER_ENABLED=true`
* Ajusta la ventana de vigencia con `FACEPHI_IAD_REPLAY_ATTACK_TOLERANCE_TIME=<seconds>`
* Ventana de vigencia por defecto: `300` segundos
* Se aplica a los endpoints de procesamiento de capturas como `POST /api/v1/iad/liveness/evaluate` y `POST /api/v1/iad/extract`
* Cuando se supera la ventana de vigencia, la API pública devuelve HTTP `400` con `message` igual a `Replay attack detected`

Esta funcionalidad se configura al inicio mediante variables de entorno. No forma parte de `config.json` ni se expone a través de `GET|POST /api/v1/iad/config`.

## Autenticación JWT

La autenticación JWT se puede habilitar al inicio mediante `config.json` o mediante variables de entorno `FACEPHI_IAD_REST_AUTH_*`.

* Claves de inicio soportadas: `auth_enabled`, `auth_jwt_secret`, `auth_accept_authorization_header`, `auth_accept_api_key_header`, `auth_api_key_header_name`
* `GET /api/v1/iad/config` omite esas claves de la vista pública de configuración
* `POST /api/v1/iad/config` rechaza esas claves y no puede usarse para rotar la configuración de autenticación JWT en tiempo de ejecución

## Características de rendimiento

| Métrica                    | Valor típico                                                                             |
| -------------------------- | ---------------------------------------------------------------------------------------- |
| Latencia                   | < 100ms                                                                                  |
| Rendimiento (throughput)   | Depende del dimensionamiento del servicio y de la capacidad de procesamiento de capturas |
| Conexiones concurrentes    | Limitadas por `number_of_threads` y `engine_pool_size`                                   |
| Tamaño máximo de solicitud | Configurable mediante `client_max_body_size`                                             |

## Consideraciones de seguridad

* Despliega detrás de un proxy inverso o de una puerta de enlace de API (API gateway)
* Habilita SSL/TLS para todas las comunicaciones
* Prioriza inyectar `auth_jwt_secret` mediante variables de entorno o un gestor de secretos en lugar de incluirlo en archivos
* Protege el archivo de licencia con los permisos adecuados (chmod 644)
* Usa reglas de firewall para restringir las conexiones entrantes

### Mensajes de error normalizados por Facephi

Para `POST /api/v1/iad/liveness/evaluate`, los fallos de validación de captura se normalizan a valores públicos de `message`, incluyendo:

* `NoneBecauseFaceTooClose`
* `NoneBecauseFaceNotFound`
* `NoneBecauseFaceCropped`
* `NoneBecauseFaceOccluded`
* `NoneBecauseTooManyFaces`
* `NoneBecauseAngleTooLarge`
* `NoneBecauseFaceTooSmall`
* `NoneBecauseFaceTooCloseToBorder`
* `NoneBecauseEyesClosed`
* `NoneBecauseImageDataError`
* `NoneBecauseLicenseError`
* `Replay attack detected`
* `ErrorProcessing`

Para `POST /api/v1/iad/extract`, los fallos de análisis y desencriptado del payload se devuelven como `NoneBecauseImageDataError`; las capturas expiradas rechazadas por la protección contra repeticiones devuelven `Replay attack detected`; los fallos de extracción sin clasificar se devuelven como `ErrorFacialImage`.

Las respuestas correctas de liveness se mapean a los campos públicos `diagnostic`, `reason`, `probability`, `score`, `faceProbability` opcional, `sdkDuration` y `queueDuration`. Los campos privados heredados y los payloads sin procesar del engine no se exponen.

Los valores posibles para `reason` en `POST /api/v1/iad/liveness/evaluate` son:

* `None`
* `Unknown`
* `UntrustedEnvironment`
* `SuspiciousActivity`
* `UntrustedDevice`
* `SdkIntegrityViolation`
* `UntrustedCorruptedPayload`
* `UntrustedContent`
* `UntrustedContentLowConfidence`

El significado de cada valor público de `reason` es:

| `reason`                        | Significado                                                                                                                                           |
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `None`                          | La captura fue aceptada como `Live` y no aplica ningún motivo de rechazo.                                                                             |
| `Unknown`                       | El servicio no pudo asignar la respuesta a un motivo de rechazo público documentado.                                                                  |
| `UntrustedEnvironment`          | La captura fue rechazada porque el entorno de ejecución no se considera de confianza.                                                                 |
| `SuspiciousActivity`            | La captura fue rechazada porque el dispositivo mostró patrones de actividad asociados a un ataque.                                                    |
| `UntrustedDevice`               | La captura fue rechazada porque no se pudo confiar en que el dispositivo fuera el que dice ser.                                                       |
| `SdkIntegrityViolation`         | La captura fue rechazada porque el SDK de captura o sus librerías parecen haber sido alterados.                                                       |
| `UntrustedCorruptedPayload`     | La captura fue rechazada porque el payload parece estar corrupto o manipulado.                                                                        |
| `UntrustedContent`              | La captura fue rechazada porque se detectó un ataque de inyección.                                                                                    |
| `UntrustedContentLowConfidence` | La captura fue rechazada porque el servicio detectó indicios de un ataque de inyección con menor confianza; debe tratarse igualmente como un rechazo. |
