Saltar a contenido

Integración SII · cis-sii-gateway

Última revisión: 2026-05-09 · Owner: cis-sii-gateway team Fuentes canónicas: /srv/projects/cds/cis/cis-sii-gateway/CLAUDE.md, AGENT-CONTEXT.md, CERTIFICATION-STATUS.md.

Qué es

cis-sii-gateway es el gateway interno CIS que media entre los servicios del ecosistema (cis-admin, cis-claudia, cis-mailer, etc.) y el Servicio de Impuestos Internos (SII) de Chile. Es el único servicio del ecosistema que habla SII; nadie más debe abrir conexiones directas a maullin.sii.cl / palena.sii.cl / www2.sii.cl.

  • Puerto: 127.0.0.1:8270 (loopback)
  • Systemd unit: cis-sii-gateway.service
  • Stack: FastAPI + Playwright (scrape) + httpx (api) + slowapi (rate-limit) + Prometheus
  • Path: /srv/projects/cds/cis/cis-sii-gateway (symlink /srv/projects/cis/cis-sii-gateway)

Multi-tenant desde día uno: cada operación lleva un tenant (RUT tributario). El token SII se cachea en memoria por (tenant, sii_env) con TTL ≈ 18 minutos.

Reglas duras

  1. Nunca tocar la PFX directamente. Toda operación criptográfica va por HTTP a cis-sign en 127.0.0.1:8250.
  2. SII_ENV=cert por default (maullin · ambiente certificación). Producción (palena) no se habilita hasta que CIS esté certificado como emisor por el SII.
  3. Scrape de portal usa Playwright con sesión logueada vía cert centralizado, no PFX local. Esa vía es solo para api_engine.
  4. Rate limit: slowapi aplica 20 req/min en emisión y 60 req/min en recepción. Scraping: máximo 1×/día por RUT (riesgo ban IP).
  5. No commitear fixtures con datos reales del SII. Usar mocks (ver tests/conftest.py).

Quién lo consume

Consumidor Uso típico
cis-admin (módulo tributario, ADR-032) Carpeta tributaria, situación SII, declaraciones F29/F22, libros IVA, emisión DTE.
cis-claudia Queries tributarias del asistente (validación RUT, lookups de contribuyente, estado de DTE).
cis-mailer Triggering de notificaciones cuando llega un evento SII (vía notif/inbox.py → cis-inbox).

Servicios no listados no deben llamar al gateway directamente. Si necesitan datos tributarios, pasan por cis-admin.

Endpoints expuestos

Todos en 127.0.0.1:8270. Auth interna: header X-Internal-Key con shared-key (ADR-012 — service-to-service auth).

Implementados

Método + path Descripción Notas
GET /health · GET /healthz Health check. Público (no requiere auth interna).
POST /sii/auth/token Seed → sign (vía cis-sign) → token. Cache 18 min por (tenant, env).
DELETE /sii/auth/token Invalida cache de token. Para forzar re-auth.
POST /sii/auth/import-session Importa cookies de sesión SII (browser). Para scrape de RUTs ajenos donde el cert holder es mandatario.
GET /sii/auth/import-session/status Estado de la sesión importada.
DELETE /sii/auth/import-session/{representado_rut} Limpia sesión por representado.
GET /sii/contribuyente/estado Estado tributario (vigente, exento, etc.). Cache 24h.
GET /sii/contribuyente/datos Datos canónicos (razón social, dirección, giros). Source of truth para validación RUT (regla anti-alucinación). Cache 24h.
GET /sii/contribuyente/datos-rut/{rut} Igual al anterior pero con RUT en path. Útil para webhooks.
GET /sii/contribuyente/giros Lista de giros activos del contribuyente. Cache 24h.
GET /sii/contribuyente/representantes Representantes legales. Cache 24h.
POST /sii/contribuyente/cache/clear Invalida cache contribuyente. 204.
POST /sii/scrape/carpeta Carpeta tributaria (PDF). Playwright + REST cte-api. Rate limit 1×/día por RUT.
POST /sii/scrape/carpeta/json Carpeta tributaria estructurada (CarpetaTributaria schema). Wrapper sobre los endpoints REST de la SPA Vue del SII.
POST /sii/caf/upload Sube archivo CAF (folios timbrados). Body: multipart con XML CAF.
GET /sii/caf/status Estado de folios disponibles por tipo DTE.
POST /sii/caf/resync Re-sincroniza folios contra el SII.
POST /sii/dte/emitir Emite DTE (factura/NC/ND/exenta). Requiere CAF activo. Rate limit 20/min.
GET /sii/dte/estado Estado de envío DTE al SII. Por trackid.
GET /sii/dte/get/{emision_id} Detalle de DTE emitido (XML + tracking).
GET /sii/dte/pending DTEs pendientes (no enviados o con error).
GET /sii/dte/{emision_id}/pdf PDF timbrado del DTE. Re-genera si no existe.
POST /sii/libros/generar Genera libro IVA (compras/ventas) del periodo. Devuelve LibroResponse.
POST /sii/libros/enviar/{libro_id} Envía libro al SII.
GET /sii/libros · GET /sii/libros/{libro_id} Listado / detalle de libros.
POST /sii/recepcion/dte Recibe DTE entrante (proveedor → CIS). Rate limit 60/min.
GET /sii/recepcion Listado de DTEs recibidos.
GET /sii/registro/empresa/{rut} Registro de empresas SII (Empresa schema).
GET /sii/registro/empresa/{rut}/historial Modificaciones registradas.
POST /sii/registro/cache/clear 204.
GET /sii/notificaciones · /{notif_id} Notificaciones SII (buzón electrónico).
GET /sii/documentos · /{doc_id}/pdf Documentos del SII (resoluciones, certificados).
POST /sii/notificaciones/cache/clear 204.
GET /sii/certificacion/sets Sets de certificación disponibles. Ver CERTIFICATION-STATUS.md.
POST /sii/certificacion/run Corre un set de certificación. Devuelve summary por caso.
POST /banco/refresh · GET /banco/health (Pivot reciente, ver gateway team). Refresh de movimientos bancarios cacheados.
GET /metrics Prometheus metrics. 9 contadores/histogramas.

Pendientes / TBD

Estos endpoints aparecen en el plan pero requieren input humano (folios, certificación) antes de poder operar. Si tu servicio los va a consumir, verificá con cis-sii-gateway team que el flujo end-to-end esté disponible.

  • /sii/dte/emitir para producción (palena) — bloqueado por certificación SII pendiente.
  • /sii/boleta/emitir (REST boleta electrónica) — implementación parcial; requiere número de atención SII por RUT emisor.
  • /sii/rcv/libro (libro de compras/ventas vs. RCV oficial) — implementado el envío básico (/sii/libros); reconciliación con RCV pendiente.
  • /sii/caf upload + ciclo completo de timbraje — endpoints existen (ver tabla); falta runbook humano para subir folios timbrados nuevos.
  • Audit log FES por cada operación (vía cis-sign /sign/cms) — pendiente.
  • Métricas Prometheus extra (latencia por endpoint SII upstream) — parcial.
  • Multi-tenant production-ready — hoy soporta tenant en cada request, pero el cache es in-memory per-process y no escala más allá de un solo nodo.

Auth interna (ADR-012)

Service-to-service va con shared-key header (no trusted-IP):

POST /sii/auth/token HTTP/1.1
Host: 127.0.0.1:8270
X-Internal-Key: <shared-key del caller>
Content-Type: application/json

{"tenant": "78384591-1"}

Cada caller (cis-admin, cis-claudia, cis-mailer) tiene su propia key registrada en vault del gateway:

vault get cis-sii-gateway INTERNAL_KEY_CIS_ADMIN
vault get cis-sii-gateway INTERNAL_KEY_CIS_CLAUDIA
vault get cis-sii-gateway INTERNAL_KEY_CIS_MAILER

El gateway compara contra una lista declarada en app/config.py. Si una key falta o no matchea → 401 unauthorized.

Auth de usuarios humanos (OIDC vía cis-auth) está fuera del scope del gateway: el gateway solo confía en sus consumidores internos, que son quienes ya autenticaron al usuario aguas arriba.

Datos canónicos (regla anti-alucinación)

El RUT empresa debe validarse contra GET /sii/contribuyente/datos antes de: - Crear una nueva empresa en cualquier base CIS (cis_admin.empresas, cis_claudia.assistants_empresas, etc.). - Emitir cualquier DTE / boleta. - Mostrar la razón social en cualquier UI.

El gateway responde con la razón social oficial SII y normaliza el RUT (con DV, sin puntos). Esto es la única source of truth: nada de tomar la razón social de un campo libre del usuario, ni de un OCR, ni de Claudia.

Cómo agregar un endpoint nuevo

Patrón canónico (basado en app/routes/sii_contribuyente.py):

  1. Router en app/routes/<area>.py con prefix="/sii/<area>".
  2. Schema Pydantic en app/schemas/<area>.py (request + response). No exponer modelos SQLAlchemy.
  3. Servicio en app/services/<area>_service.py que:
  4. Recibe tenant y obtiene token vía auth.get_token(tenant, env).
  5. Llama al SII vía sii_client (httpx) o scrape_engine (Playwright) según corresponda.
  6. Escapa cookies y headers SII antes de loggearlos (PII, session leakage).
  7. Cache opcional: si la respuesta del SII es idempotente para una ventana de tiempo, cachear con cachetools.TTLCache (24h estado contribuyente, 18min token).
  8. Rate limit: agregar decorador @limiter.limit("20/minute") si toca al SII upstream.
  9. Test en tests/test_<area>.py con mocks de sii_client y scrape_engine. Integración real en tests/integration/ con SII_INTEGRATION=1.
  10. Audit FES (cuando esté listo): cada operación critical/high pasa por cis-sign /sign/cms para receipt firmado (ADR-008).
  11. Documentar en este file + en /srv/projects/cis/CONTRACTS.md (provider=cis-sii-gateway).

Pendientes humanos (HUMAN)

Estos no son tareas de Claude — requieren acción del owner técnico/legal:

  • Cert FEA producción: comprar y registrar el cert PFX para producción palena. Hoy operamos con cert de Martín en cert/maullin.
  • Folios CAF: solicitar timbraje al SII por RUT emisor (CIS, CDS) y subir CAFs vía POST /sii/caf/upload. Ver CERTIFICATION-STATUS.md — bloqueador actual de la certificación.
  • Número de atención SII para boleta electrónica por RUT emisor. Trámite humano en oficina virtual SII.
  • Multi-tenant: hoy el gateway atiende todos los tenants en un solo proceso; si crece a >50 tenants activos, evaluar split por shard (cis-sii-gateway-cis, cis-sii-gateway-cds, etc.) o token cache distribuido (Redis).

Referencias