# Introducción a SII SDK

> Qué es SII SDK, qué hace, qué no hace y el modelo mental de la librería: Resultado<T, ErrorSii>, texto literal del SII y tu sistema decide cuándo llamar.

Fuente: https://sii.devlas.cl/docs/introduccion

# Introducción a SII SDK

SII SDK es una librería TypeScript de Devlas SpA (paquetes `@devlas-cl/*`, versión publicada 0.6.0) para emitir y recibir documentos tributarios electrónicos ante el SII de Chile. Se instala como dependencia y corre dentro del sistema del integrador; no es un servicio alojado ni consulta servidores de Devlas al ejecutarse. Esta página resume qué hace, qué deja en manos de tu sistema y las reglas que siguen todas sus funciones.

SII SDK no es un producto del Servicio de Impuestos Internos ni está afiliado a él.

## Qué hace

- Valida los datos de un documento contra las reglas del SII y los largos del XSD, sin recortar nada en silencio.
- Calcula montos (neto, IVA, exento, descuentos, impuestos adicionales), arma el XML en el orden del esquema, lo timbra con el CAF, lo firma y lo valida contra el XSD oficial antes de enviarlo.
- Se autentica (semilla y token), envía (boletas 39 y 41 por la API REST del SII; facturas, notas y guías por `DTEUpload`) y consulta estados.
- Pide, reobtiene y anula folios (CAF) y los repone con `autoCaf` (paquete `@devlas-cl/folios`).
- Lee el Registro de Compras y Ventas (RCV), responde el intercambio entre contribuyentes y registra aceptación o reclamo.
- Recorre la certificación ante el SII con un motor por etapas (paquete `@devlas-cl/certificacion`) y verifica la habilitación en producción.
- Genera la representación impresa (ticket térmico y PDF) con el timbre PDF417.

## Qué no hace (y qué hace tu sistema)

| La librería no... | Qué hace tu sistema |
|---|---|
| Persiste nada: ni folios, ni sesiones, ni CAF, ni el XML emitido, ni el estado de un envío. | Guarda el XML firmado (la ley obliga a conservarlo 6 años), el track id (como texto) y el estado. Folios, sesiones y CAF entran por los puertos `AlmacenCaf` y `AlmacenSesion`, que implementas tú. |
| Planifica: no hay cola, temporizadores ni reintentos de negocio. | Decide cuándo llamar. La librería responde "qué hacer ahora" con funciones puras: `siguienteConsultaDeEstado`, `siguienteAccionDeEnvio`, `decidirReenvio`, `autoCaf`, `avanzarCorrida`. |
| Agrupa boletas por tiempo. | Cierra el grupo cuando `siguienteAccionDeEnvio` responde `armar_sobres`; la librería arma el sobre de hasta 500 boletas. |
| Recorta o corrige datos: un giro de 41 caracteres es un error, no se corta a 40. | Corrige el dato. |
| Lee tu correo. | Entrega el adjunto `EnvioDTE` o las glosas del correo del SII a las funciones de intercambio y de `protocolo`. |
| Cifra tus secretos. | Cifra en reposo el `.pfx`, su clave, el CAF (trae una llave privada) y las cookies de sesión. |
| Decide tu negocio (medios de pago, inventario, qué se documenta en una venta mixta). | Lo resuelve antes de llamar. |
| Llama a servidores de Devlas al ejecutarse. | Nada. Un servidor caído de Devlas no puede impedir emitir. |
| Tiene estado global. | Pasa la configuración y los puertos a cada llamada. Varias instancias y réplicas no se pisan. |

## Modelo mental

### 1. Resultado en vez de excepciones

Toda operación devuelve `Resultado<T, ErrorSii>`:

```ts
import type { ErrorSii, Resultado } from '@devlas-cl/comun'

// type Resultado<T, E = ErrorSii> = { readonly ok: true; readonly valor: T } | { readonly ok: false; readonly error: E }

declare const r: Resultado<{ trackId: string }, ErrorSii>
if (!r.ok) {
  r.error.codigo      // CodigoError: catálogo cerrado ('VALIDACION', 'TRANSPORTE', 'LIMITE_SESIONES', ..., 'DESCONOCIDO')
  r.error.accion      // 'reintentar' | 'esperar' | 'corregir' | 'tramitar' | 'escalar'
  r.error.mensajeSii  // texto LITERAL del SII, o null si el error nace en la librería
} else {
  r.valor.trackId
}
```

- Nada lanza por datos tuyos ni del SII. Solo lanza un argumento mal formado en la llamada (error de programación).
- El patrón de uso es `if (!r.ok) return r`.
- Decide por `codigo`, `codigoSii` y `accion`, nunca comparando subcadenas de `mensajeSii`.
- El estado de un sobre no es un error: `consultarEstadoEnvio` devuelve `ok: true` incluso con veredicto `rechazado`.

### 2. El texto del SII llega literal

`mensajeSii` es el texto exacto del SII, decodificado del transporte (juego de caracteres y entidades HTML) y sin traducir ni recortar. Un mensaje que el catálogo no reconoce llega como `DESCONOCIDO` con su texto intacto y acción `escalar`. Para mostrar un error a una persona, `mensajeParaUsuario(error)` de `@devlas-cl/comun` devuelve `{ titulo, queHacer, detalle, nivel, reintentable }` en español neutro, con el literal del SII aparte en `detalle`.

### 3. El ambiente es explícito

`Ambiente = 'certificacion' | 'produccion'`. Son registros distintos del SII: el folio, la resolución, el RCV y las sesiones de uno no existen en el otro. Se pasa en la configuración de cada llamada (`ConfigToken.ambiente`, `ConfigPortal.ambiente`) y en la clave de folios (`ClaveCaf.ambiente`).

### 4. El reloj es un parámetro

Las funciones puras reciben `ahora: Date`; las llamadas reciben un `Reloj` (`{ ahora: () => Date }`). Ningún paquete usa `Date.now` ni `process.env` por su cuenta. La fecha tributaria se calcula en hora de Chile con `fechaTributaria(instante)` de `@devlas-cl/dominio`, nunca con `toISOString()`: entre las 20:00 y las 24:00 de Chile la fecha UTC ya es la del día siguiente y el SII responde `FECHA NO CORRESPONDE AL ENVIO`.

### 5. Cuatro puertos

Lo que varía entre instalaciones entra por puertos que implementa tu sistema (la librería trae versiones en memoria para pruebas):

| Puerto | Contrato (de `@devlas-cl/comun`) | Para qué |
|---|---|---|
| `Http` | `{ solicitar(solicitud: SolicitudHttp): Promise<RespuestaHttp> }` | Llegar al SII. No sigue redirecciones, no guarda cookies, no reintenta y entrega el cuerpo en bytes. |
| `AlmacenSesion` + `Bloqueos` | `obtener/guardar/borrar` y `adquirir/renovar/liberar` | La sesión del portal y el token, compartidos entre réplicas, y quién tiene el turno. |
| `AlmacenCaf` | `guardarCaf/reservarFolio/liberarFolio/consultarCaf` | Los folios. `reservarFolio` debe ser atómico entre réplicas. |
| `Registro` | `{ emitir(evento: EventoRegistro): void }` | Eventos y errores (por ejemplo `emitir.envio_incierto`, `folios.bajos`). No promete entrega. |

### 6. Una sola sesión por RUT

El SII cuenta las sesiones autenticadas por RUT y bloquea al superar el cupo (`01.01.215.500.720`, código `LIMITE_SESIONES`, acción `esperar`, al menos 35 minutos). Cerrar sesión no libera el cupo. Por eso las llamadas al portal comparten una sesión mediante `AlmacenSesion` y `Bloqueos`. Nunca reintentes un `LIMITE_SESIONES`: cada intento abre otra sesión.

## Tres niveles de uso

| Nivel | Paquetes | Qué es |
|---|---|---|
| Piezas | `comun`, `dominio`, `xml`, `protocolo`, `impresion` | Funciones puras: sin red, sin disco, sin reloj del sistema. Validar un RUT, calcular totales, armar y firmar un DTE, leer una respuesta del SII, dibujar el PDF417. |
| Llamadas | `sii` | Una operación con el SII por el puerto `Http`. Hace una cosa y termina: `emitir`, `enviarBoletas`, `enviarDte`, `consultarEstadoEnvio`, `resumenRcv`. |
| Soluciones | `soluciones`, `folios`, `certificacion` | Recetas que juntan lo anterior: `habilitar`, `diagnosticarEmisor`, `autoCaf`, el motor de certificación. |

Dependencias en un solo sentido: `comun` <- `dominio` <- `xml` <- `protocolo` <- `sii` <- `soluciones` <- `folios` <- `certificacion`. `impresion` usa solo `dominio` y `xml`.

`emitir` (de `@devlas-cl/sii`) compone validar, armar, timbrar, firmar, validar el XSD y enviar en una llamada. Cada paso también se usa suelto (`prepararDte`, `prepararSobre`, `enviarBoletas`, `enviarDte`) cuando necesitas intervenir entre pasos o agrupar boletas.

## Requisitos

- Node.js 24 o superior. Solo ESM.
- `comun`, `dominio`, `impresion` y el catálogo de errores corren también en el navegador, Electron y Capacitor. La firma, los certificados y la red al SII son solo de servidor.
- Un certificado digital (`.pfx` y su clave) del contribuyente o de un usuario autorizado, y una empresa certificada ante el SII para emitir en producción.

## Páginas de esta documentación

- `docs/instalacion`: registro privado, `.npmrc`, token y paquetes por nivel.
- `docs/primeros-pasos`: emitir una boleta 39 y consultar su estado.
- `docs/autocaf`: CAF, `AlmacenCaf`, pedir, reobtener, anular y `autoCaf`.
- `docs/estado`: `consultarEstadoEnvio`, códigos del SII y `siguienteConsultaDeEstado`.
- `docs/certificacion`: motor `avanzarCorrida`, etapas, esperas y habilitación.
- `docs/tiers`: niveles, paquetes y licencia.
- `docs/referencia-api`: firmas de las funciones públicas y catálogo de `ErrorSii`.
- `docs/errores`: errores comunes y cómo resolverlos.
