# Servidor xamiSDK — Instalación

Guía rápida para dejar el xamiSDK funcionando en tu infraestructura. El servidor firma
con tu chip Xami **sin que los documentos salgan de tu red**.

## Requisitos

- Python 3.9 o superior.
- Conexión saliente hacia Xami (`https://api.xami.run`).
- Una **SDK Key** (matrícula) emitida desde la consola de Xami.

## Instalación (primera vez)

Instala el paquete con `pip`:

```
pip install https://sdk.xami.run/files/xamisdk-0.1.0-py3-none-any.whl
```

Eso deja disponible el comando `xamisdk`. Todos los comandos se invocan con ese
prefijo, por ejemplo `xamisdk status`, `xamisdk serve`, `xamisdk console`.

> **Si al escribir `xamisdk` te dice "no se reconoce como un comando"** (suele pasar
> en Windows cuando la carpeta de scripts de Python no está en el PATH), usa la forma
> equivalente con `python -m`:
>
> ```
> python -m xamisdk status
> ```
>
> Funciona exactamente igual: donde el manual dice `xamisdk <algo>`, puedes escribir
> `python -m xamisdk <algo>`.

**¿Dónde queda instalado?** El paquete se instala *dentro de Python* (en su carpeta
`site-packages`), no en una carpeta suelta. Su carpeta de datos —donde guarda la
configuración, el caché de credenciales y diseños, y los scripts auxiliares— es
`~/.xamisdk` (con punto al inicio). En Windows eso es
`C:\Users\<tu-usuario>\.xamisdk`. Si abres una carpeta llamada `xamiSDK` (sin punto)
y la ves vacía, es normal: el SDK no vive ahí.

Parea el SDK con Xami (ceremonia única):

```
xamisdk init --sdk-key xsdk_live_... --secret ...
```

Comprueba que quedó listo:

```
xamisdk status
```

Cuando el estado sea **PAREADO** y las llaves **OK**, continúa con los dos pasos de abajo.

---

## Actualizar el SDK

Cuando publiquemos una corrección, actualizar es un solo comando:

```
xamisdk reinstall
```

`reinstall` comprueba si hay una versión más reciente publicada. Si la hay, hace todo
el ciclo por ti en una ventana nueva: detiene el servicio, reinstala el paquete, lo
vuelve a levantar y abre la consola. Si ya estás al día, no hace nada (usa
`xamisdk reinstall --force` para reinstalar de todas formas).

> **Ojo:** `reinstall` es un *subcomando* del SDK, no un programa suelto. Se escribe
> `xamisdk reinstall` (o `python -m xamisdk reinstall`), **no** `reinstall` a secas —
> si escribes solo `reinstall`, el sistema no lo reconoce.

**La primera actualización es a mano.** Tu versión instalada todavía no trae el comando
`reinstall`, así que esta primera vez actualiza con `pip`:

```
python -m pip install --force-reinstall --no-cache-dir https://sdk.xami.run/files/xamisdk-0.1.0-py3-none-any.whl
```

De ahí en adelante ya tendrás `xamisdk reinstall` y no necesitas volver a copiar ese
comando largo. Si el servicio estaba corriendo, deténlo antes (en la consola: `stop`)
para que ningún archivo quede bloqueado durante la reinstalación.

> **¿Por qué un `pip install` normal no basta?** El número de versión es siempre el
> mismo (0.1.0); las correcciones van *dentro*. Un `pip install` normal ve el mismo
> número y no reemplaza nada — por eso hace falta `--force-reinstall --no-cache-dir`
> (o directamente `xamisdk reinstall`, que ya lo hace por ti).

---

## Paso 1 · Levantar el servicio

El servicio HTTP local es lo que usan las librerías (XamiLib) para firmar. Se levanta con:

```
xamisdk serve --port 8300
```

### ¿Push o pull? Elige según dónde corres el SDK

Cuando firmas, Xami tiene que **devolverte** el resultado. Hay dos formas, y esto
determina si la firma funcionará en tu entorno:

- **Modo push (por defecto).** Xami te envía el resultado a tu `receive_url`. Requiere
  que Xami **pueda alcanzar tu servicio desde internet**. Sirve cuando el SDK corre en un
  **servidor con IP pública** o con el puerto expuesto.

- **Modo pull (recomendado para probar desde una PC).** Tu SDK le **pregunta** a Xami por
  los resultados cada pocos segundos. No hace falta que Xami te alcance: funciona en
  **cualquier PC o red normal, detrás de NAT o firewall**, sin configurar nada.

> **Si estás probando desde tu computadora, usa modo pull.** El modo push solo funciona en
> servidores que Xami puede alcanzar desde internet; en una PC normal la firma no
> regresaría. Detalle en *Solución de problemas*, más abajo.

Para levantar en **modo pull**, añade `--polling` con el intervalo en segundos:

```
xamisdk serve --port 8300 --polling 2
```

Al arrancar verás un log con la fecha, el nivel y el detalle de cada paso:

```
2026-08-07 09:15:02  INFO  xamiSDK escuchando en 127.0.0.1:8300
2026-08-07 09:15:02  INFO  modo PULL activo: recogiendo resultados de Xami cada 2s
2026-08-07 09:15:02  INFO  Xami notificado: modo pull (encolara los resultados)
2026-08-07 09:15:03  INFO  configuración sincronizada: 5 credencial(es), 3 diseño(s)
```

Sin `--polling`, el servicio arranca en modo push (el clásico, para servidores
alcanzables).

### El SDK sincroniza su configuración al arrancar

Fíjate en la última línea del log: **cada vez que levantas el servicio, el SDK descarga de
Xami toda tu configuración** (credenciales y diseños de firma) y la guarda en su caché
local. Esto pasa siempre, en push y en pull.

Por eso, si creas o cambias algo en la consola (una credencial, el diseño de un sello),
la forma de que el SDK lo tome es:

- **En modo push:** llega solo, en caliente, sin hacer nada.
- **En modo pull:** como Xami no puede alcanzarte, **reinicia el servicio** (ciérralo y
  vuelve a levantarlo) para que baje la configuración actualizada. La consola te avisa
  cuando esto es necesario.

Si al firmar el sello no aparece o falta una credencial, casi siempre se resuelve
reiniciando el servicio para forzar esta sincronización.

### Dejarlo escuchando sin que bloquee la sesión

`xamisdk serve` se queda **en primer plano** (ocupa la terminal). Para que siga
escuchando sin bloquear tu sesión y sin que se detenga al cerrar la ventana, usa una de
estas formas según tu sistema. (Añade `--polling 2` al comando si vas en modo pull.)

### En Windows

**Sesión de trabajo** (una ventana aparte que puedes minimizar):

```
start "xamiSDK" cmd /c "xamisdk serve --port 8300 > xamisdk.log 2>&1"
```

Abre otra ventana con el servicio y guarda toda su salida (incluidos errores) en
`xamisdk.log`. Puedes seguir trabajando en tu terminal.

**Permanente** (que arranque solo con el equipo): instala el servicio con
[NSSM](https://nssm.cc/) o créalo como tarea del Programador de tareas de Windows,
apuntando al comando `xamisdk serve --port 8300`.

### En Linux

**Sesión de trabajo** (segundo plano, sobrevive al cierre de sesión):

```
nohup xamisdk serve --port 8300 > xamisdk.log 2>&1 &
```

El `&` lo manda a segundo plano y `nohup` evita que muera al cerrar la sesión.

**Permanente** (recomendado en producción): crea un servicio `systemd`. Ejemplo de
`/etc/systemd/system/xamisdk.service`:

```
[Unit]
Description=xamiSDK
After=network.target

[Service]
ExecStart=/ruta/al/venv/bin/xamisdk serve --port 8300
Restart=always
User=tu_usuario

[Install]
WantedBy=multi-user.target
```

Luego:

```
sudo systemctl enable --now xamisdk
```

Arranca al iniciar el equipo y se reinicia solo si se cae.

### Ver los logs

Con las formas de arriba, toda la salida del servicio queda en `xamisdk.log` gracias a la
redirección `> xamisdk.log 2>&1` (el `2>&1` es lo que también manda los errores al
archivo).

- **Windows:** `type xamisdk.log`
- **Linux:** `tail -f xamisdk.log` (en vivo)

Con `systemd`, los logs también están en `journalctl -u xamisdk -f`.

El log usa el formato estándar `fecha hora  NIVEL  mensaje`, con tres niveles:

- **`INFO`** — operación normal (arranque, resultados recibidos, sincronización).
- **`WARN`** — algo a revisar que no detiene el servicio (Xami no disponible un momento,
  `receive_url` mal configurado). El servicio reintenta solo.
- **`ERROR`** — un fallo inesperado.

Si Xami deja de responder un instante, verás un solo `WARN` (no se repite en cada intento)
y un `INFO` de *conexión restablecida* cuando vuelve.

### Solución de problemas

**La firma se queda esperando y termina en timeout, sin errores.**
Es el síntoma clásico de estar en modo push desde una PC que Xami no puede alcanzar.
Al levantar el servicio en modo push verás este aviso:

```
⚠  ADVERTENCIA: no hay receive_url configurado en el pareo.
   Xami no podra empujarte los resultados de firma; toda firma se
   quedara esperando indefinidamente (timeout silencioso).
```

**Solución:** levanta el servicio en **modo pull**, que funciona desde cualquier PC:

```
xamisdk serve --port 8300 --polling 2
```

Con eso, tu SDK recoge los resultados preguntándole a Xami, sin necesidad de que Xami te
alcance. El aviso desaparece y la firma se completa con normalidad.

---

## Paso 2 · Crear credenciales de librería

Para que tu aplicación pueda firmar a través del servicio, necesita una credencial de
acceso. Se emite con:

```
xamisdk wrapper:create --name mi-aplicacion
```

Esto devuelve un **`wrapper_key`** (`wrp_...`) y un **`wrapper_secret`** (`wsec_...`).
Guárdalos: son las credenciales con las que tu aplicación se autentica contra el servicio
local. (Puedes listar las emitidas con `xamisdk wrapper:list` y revocar una con
`xamisdk wrapper:revoke`.)

---

## Prueba rápida · Firmar un documento

Con el servicio corriendo, verifica que todo funciona firmando un PDF de prueba. Coloca un
PDF cualquiera en la carpeta donde estás y ejecuta (todo en **una sola línea**):

```
xamisdk pades:sign --credential-key <TU_CREDENTIAL_KEY> --signer-name "Nombre Apellido" --var name="Nombre Apellido" --out firmado.pdf --wait --timeout 40 documento.pdf
```

Reemplaza:

- `<TU_CREDENTIAL_KEY>` por la clave de una credencial de firma (ver más abajo cómo
  obtenerla).
- `documento.pdf` por el nombre de tu PDF de entrada.
- `firmado.pdf` es donde se guardará el resultado.

### ¿De dónde saco el `credential_key`?

Tienes dos formas:

**Desde la consola** (la visual):

1. Entra a **Dispositivos**.
2. Haz clic en tu **chip** (miniHSM). Se abre su panel lateral.
3. En el panel, abre **Credenciales** (Certificados P12 y address).
4. Busca el certificado que quieras usar y **abre su acordeón** (haz clic para
   desplegarlo).
5. Verás el campo **`credential_key`** con un botón de **copiar** al lado. Cópialo y úsalo
   en el comando.

**Desde la línea de comando** (lo que tu SDK tiene en caché):

```
xamisdk credentials:list
```

Lista las credenciales que tu SDK conoce, cada una con su `credential_key`. Útil para
confirmar rápido con qué puedes firmar sin salir de la terminal.

Si todo está bien, verás:

```
Preparando y enviando el hash a Xami (el documento NO sale)...
  requestId: sig_...
Esperando la firma del chip...
  Firmado -> firmado.pdf
```

Y tendrás el `firmado.pdf` con la firma digital. **Solo el hash del documento viaja a
Xami; el PDF nunca sale de tu equipo.**

> **¿Se queda esperando y no termina?** Es casi siempre el modo push desde una PC. Ver
> *Solución de problemas*, más arriba.

---

## Listo · Usar una librería

Con el servicio corriendo (Paso 1) y tus credenciales (Paso 2), descarga la **librería
del lenguaje que uses** desde [sdk.xami.run](https://sdk.xami.run) y configúrala con esas
credenciales:

- **XamiLib para PHP** → ver *XamiLib · PHP*.
- **XamiLib para Python** → ver *XamiLib · Python*.

Cada librería explica su instalación y cómo firmar. Todas usan el mismo `wrapper_key` /
`wrapper_secret` para hablar con el servicio local.

> ¿Quieres saber qué hace cada comando en detalle? Consulta *Comandos*. ¿Y los endpoints
> del servicio? Consulta *Servicios*.
