# Propuesta — micro-SIF VERI\*FACTU para AbroadLink · Fase 1 (registros de alta)

**Estado:** propuesta de especificación (no implementada)
**Fecha:** 2026-09-01
**Ámbito:** `/var/www/html/verifactu` · vhost `verifactu.xtrf.abroadlink.com` (puerto interno 8089)

---

## 1. Qué se construye

Un **Sistema Informático de Facturación (SIF) propio, en modalidad exclusivamente VERI\*FACTU**,
que se intercala entre XTRF (el gestor de traducciones de AbroadLink) y la AEAT, y que:

1. Recibe de XTRF, por HTTP, la factura completa en JSON cuando XTRF la marca como *ready* con la
   categoría "send to verifactu".
2. Genera el **registro de facturación de alta**, calcula su **huella SHA-256 encadenada** y lo
   persiste de forma inmutable.
3. **Genera el PDF de la factura**, que pasa a ser **la factura legal** (sustituye al PDF de XTRF),
   con el **código QR tributario** y las leyendas obligatorias, y lo deposita en el directorio de
   facturas de XTRF.
4. **Remite el registro a la AEAT** por el servicio web VERI\*FACTU, respetando el mecanismo de
   control de flujo, y gestiona el ciclo completo de respuestas (correcto, aceptado con errores,
   rechazado, `SoapFault`, indisponibilidad).
5. **Devuelve el resultado a XTRF** cambiando la categoría de la factura vía su Home API REST.
6. Ofrece una **interfaz web interna** para consultar registros, gestionar errores y reenvíos,
   vigilar la salud del sistema y editar la configuración.

### 1.1 Por qué

- **Obligación legal.** El RD 1007/2023 y la Orden HAC/1177/2024 obligan a que todo sistema de
  facturación genere registros de facturación encadenados y a que la factura lleve QR tributario.
  Las fechas vigentes son **1/1/2027** (obligados por Impuesto sobre Sociedades) y **1/7/2027**
  (resto), fijadas por el RD-ley 15/2025 (`docs/README.md`, tabla `boe/`).
- **XTRF no lo hace.** XTRF emite el PDF de la factura pero no genera registros de facturación
  VERI\*FACTU ni QR tributario. Sustituir XTRF entero no es viable; interponer un micro-SIF que se
  invoque desde su sistema de triggers sí lo es.
- **Adopción temprana recomendada.** La AEAT declara que los servicios están en producción desde el
  23/04/2025 y recomienda la adopción anticipada
  (`docs/aeat-especificaciones/FAQs-Desarrolladores.pdf`, apdo. 2). No hay penalización por empezar
  antes de la fecha obligatoria.

### 1.2 Contexto real observado (no supuesto)

Verificado sobre el propio host el 2026-09-01:

- El montaje CIFS `//192.168.123.150/ak` está activo en `/home/jboss/xtrf`, y las facturas viven en
  `/home/jboss/xtrf/03_Invoices/Customer_invoices/YYYY/MM/`.
- La nomenclatura real de fichero es `{numero}_{año}-{Cliente_saneado}.pdf`
  (p. ej. `195_2026-Gebr__Brasseler_GmbH_&_Co__KG.pdf`), y el número de factura impreso en el PDF es
  `195/2026` — **con barra, no con guion bajo**. El nombre de fichero y el `NumSerieFactura` no
  coinciden literalmente.
- El volumen es bajo: **20 facturas en agosto de 2026**. Esto es determinante para varias decisiones
  de diseño (ver `design.md`, D10 y D16).
- La plantilla actual de XTRF **ya es multiidioma** (se observaron facturas en castellano y alemán,
  con literales `FACTURA`/`RECHNUNG`, `IVA`/`MWST.`, `Total`/`Gesamt`).
- Los dos casos fiscales reales son:
  - **Cliente español**: IVA 21 % repercutido (ej. factura 186/2026, base 482,55 €, IVA 101,33 €).
  - **Cliente intracomunitario B2B**: cuota 0,00 (ej. factura 195/2026, cliente alemán con
    `VAT number: DE125657245`) → **`CalificacionOperacion` = `N2`** e identificación por `IDOtro` con
    `IDType=02`. Este es el caso *habitual* de la agencia, y es también el que más restricciones
    tiene (ver `specs/validacion-fiscal/spec.md`).

---

## 2. Alcance de esta especificación

### 2.1 Dentro de alcance

| Bloque | Contenido |
|---|---|
| Endpoint de entrada | Contrato HTTP, validación del payload, idempotencia, token previsto-pero-desactivado |
| Validación fiscal local | Reglas de `Validaciones_Errores_VERIFACTU_1.2.2.pdf` aplicables a altas, previas al envío |
| Registro, huella y cadena | `RegistroAlta` (F1/F2), huella SHA-256, encadenamiento, escritor único, primer registro |
| Envío AEAT | XML a mano, mTLS por cURL, control de flujo, dos vías de error, máquina de estados |
| Ciclo de error del alta | ALTA, ALTA POR RECHAZO, ALTA DE SUBSANACIÓN, reintentos, consulta previa obligatoria |
| PDF y QR | Plantilla traducible, QR tributario, leyendas, despliegue en el share de XTRF, colisiones |
| Integración XTRF | Home API REST, categorías de éxito/fallo, comportamiento ante no-respuesta |
| Interfaz interna | 4 áreas (listado, errores, salud, configuración), acciones manuales explícitas |
| Operación | Modelo de datos, logs, timers, integridad de cadena, caducidad de certificado, backup |

Los tipos de factura cubiertos son **F1** (factura completa) y **F2** (simplificada), que son los
únicos que la agencia emite en el alta ordinaria.

### 2.2 Fuera de alcance (fase 2+)

Estas capacidades **no** se especifican aquí, pero el diseño reserva sitio para ellas (ver
`design.md` D26):

- **Facturas rectificativas** R1–R5 (`TipoRectificativa`, `FacturasRectificadas`,
  `ImporteRectificacion`).
- **Registro de anulación** (`RegistroAnulacion`) y las operativas de anulación del anexo 6.
- **Registro de eventos** (`EventosSIF.xsd`) — **excluido por diseño, no aplazado**: el registro de
  eventos corresponde a sistemas NO VERI\*FACTU (art. 3 Orden HAC/1177/2024) y el SIF opera
  exclusivamente en modalidad VERI\*FACTU.
- **Modalidad NO VERI\*FACTU** y remisión bajo requerimiento (binding `sfRequerimiento`) — excluidas.
- **Firma electrónica XAdES** de los registros — no exigible: el art. 16.3 del RD 1007/2023 exime a
  los sistemas VERI\*FACTU de firmar, bastando la huella; el XSD declara `ds:Signature` como
  `minOccurs="0"` (HALLAZGOS §0, punto confirmado).
- **Multi-emisor / multi-obligado**: el SIF es mono-emisor por decisión del usuario
  (`IndicadorMultiplesOT=N`, `TipoUsoPosibleMultiOT=N`).
- **Autenticación activa** de UI y endpoint: se diseña el módulo, se deja desactivado.

---

## 3. Dependencias externas pendientes

Ninguna de estas bloquea la escritura de la especificación; todas bloquean partes concretas de la
implementación. La tabla dice exactamente **qué desbloquea cada una**.

| # | Dependencia | Quién la aporta | Qué desbloquea | Bloquea la fase |
|---|---|---|---|---|
| **DEP-1** | **JSON de ejemplo de factura XTRF** en `docs/` | Usuario | Congela la tabla de mapeo JSON → `RegistroAlta`. Sin él, el mapeo de `specs/endpoint-entrada/spec.md` §4 es **provisional, a confirmar** | F2 (cierre), F3 |
| **DEP-2** | **PDF de factura actual de ejemplo** en `docs/` | Usuario | Congela la plantilla PDF (tipografías, rejilla, bloques, pie). Ya se ha inspeccionado una factura real del share como sustituto provisional | F6 |
| **DEP-3** | **Certificado `.p12` + contraseña** | Empresa | Cualquier llamada real a la AEAT, incluso a preproducción | F5 |
| **DEP-4** | **URL base + token Home API de XTRF** + IDs de las dos categorías (éxito / fallo) | Usuario / admin XTRF | La devolución de resultado a XTRF | F7 |
| **DEP-5** | **NIF y razón social del obligado emisor** | Empresa | `Cabecera/ObligadoEmision` y `NombreRazonEmisor`; sin ellos ni siquiera preproducción acepta el envío (error 4104) | F5 |
| **DEP-6** | **NIF y razón social de la productora del sistema** (la propia AbroadLink, autodesarrollo) | Empresa | Bloque `SistemaInformatico` | F5 |
| **DEP-7** | **Regla exacta de saneado del nombre de cliente** que usa XTRF para nombrar el fichero PDF | Usuario / admin XTRF | El despliegue del PDF sobre el fichero correcto del share sin colisiones | F6 |
| **DEP-8** | **Confirmación de que el share `//192.168.123.150/ak` entra en un backup** | Admin de sistemas | Cierra el plan de conservación legal | F9 |
| **DEP-9** | **Declaración responsable del productor** (documento firmado) | Empresa | Entregable documental exigido por el art. 13 RD 1007/2023; no bloquea código | F9 |

---

## 4. Restricciones ya fijadas (decisiones del usuario, no reabiertas)

1. **PHP 8.3** con **pool FPM dedicado** (`/etc/php/8.3/fpm/pool.d/verifactu.conf` + `FilesMatch`
   dentro del `<Directory>` del vhost). **Nunca `a2enconf php8.3-fpm`** — regla de oro del host
   (`/var/www/html/CLAUDE.md`): el postinst de sury auto-habilita y recargaría Apache, cambiando
   **todos** los sitios a esa versión.
2. **Sin extensión `php-soap`**: el XML se construye a mano con `XMLWriter` y se envía por cURL con
   certificado cliente (mTLS) y cabecera `SOAPAction: ""` vacía.
3. **MariaDB 10.11** local (verificado: 10.11.14 activo), esquema propio `verifactu`.
4. **PDF del SIF = factura legal**, sustituye al de XTRF. Plantilla traducible multiidioma; leyendas
   VERI\*FACTU siempre en castellano.
5. **Mono-emisor**: un solo NIF obligado. `IndicadorMultiplesOT=N`, `TipoUsoPosibleMultiOT=N`,
   `TipoUsoPosibleSoloVerifactu=S`. `SistemaInformatico` declarado en autodesarrollo (la propia
   empresa como productora).
6. **Acceso público de momento** para UI y endpoint, con módulo de autenticación previsto y
   desactivado por *feature flag*. Riesgo documentado en §5.
7. **Entorno de pruebas primero**: todo apunta a preproducción AEAT; el paso a producción es pura
   configuración.
8. Este encargo es **solo especificar**. No se escribe código.

---

## 5. Riesgo abierto y explícito: exposición pública

El usuario ha decidido que la UI y el endpoint queden públicos de momento. Consecuencias que quedan
por escrito:

- **RIESGO-1 — Inyección de registros de facturación por terceros.** Cualquiera que alcance
  `https://verifactu.xtrf.abroadlink.com` puede llamar al endpoint y provocar que el SIF genere y
  remita a la AEAT registros de facturación falsos **a nombre del NIF real de la empresa**. Un
  registro remitido y aceptado **no se puede borrar**: solo se puede anular o subsanar, y ambas cosas
  quedan registradas en la AEAT para siempre
  (`FAQs-Desarrolladores.pdf`: *"ese RF quedaría para siempre con esos errores en la AEAT"*).
  Además, cada registro espurio **consume un eslabón de la cadena de huellas** y la desplaza.
- **RIESGO-2 — Fuga de datos de clientes.** La UI expone facturas, NIF/VAT de clientes, importes y
  PDFs. Publicarlos es un incidente RGPD.
- **RIESGO-3 — Denegación de servicio sobre el control de flujo.** Un atacante puede llenar la cola y
  hacer que las facturas legítimas esperen días detrás de miles de registros basura, respetando el
  `TiempoEsperaEnvio`.

**Recomendación (no vinculante, es decisión del usuario):** restringir en Nginx Proxy Manager por
lista de IP de origen — el trigger de XTRF viene de una sola máquina conocida — **antes de conectar
el certificado real**, aunque sea con el módulo de autenticación aún desactivado. Es una medida de
cinco minutos en NPM y elimina RIESGO-1 y RIESGO-3 por completo.

Mitigaciones que la fase 1 sí incorpora aunque el acceso sea público (ver
`specs/operacion-y-seguridad/spec.md`):

- El endpoint **nunca** envía nada a la AEAT de forma síncrona: siempre pasa por cola, y la cola es
  parable con un solo *feature flag* (`cola.pausada`).
- Existe un **modo de pausa global** y una **cuota diaria máxima de registros** configurable, que al
  superarse pausa la cola y genera una incidencia en lugar de seguir enviando.
- Todo el módulo de autenticación está construido y probado, solo que con el flag a `false`.

---

## 6. Criterio de "hecho" de la fase 1

La fase 1 se considera terminada cuando, **contra el entorno de preproducción de la AEAT**:

1. Una factura F1 de cliente español (IVA 21 %) recorre el flujo completo: endpoint → registro →
   huella → PDF con QR en el share → envío → `EstadoRegistro=Correcto` con CSV → categoría de éxito
   en XTRF.
2. Una factura F1 de cliente intracomunitario (`N2`, `IDOtro/IDType=02`) hace lo mismo.
3. Los **tres vectores de prueba oficiales de la huella** pasan como test unitario
   (`design.md` D7.4).
4. Un rechazo provocado a propósito deja el registro en `RECHAZADO`, lo muestra traducido en la UI y
   permite lanzar un **ALTA POR RECHAZO** manual desde la interfaz.
5. Un `SoapFault` o timeout provocado deja el registro en `ESTADO_INDETERMINADO`, **bloquea la
   cabecera de la cola** y exige una consulta a la AEAT antes de permitir ninguna acción.
6. La verificación de integridad de la cadena recorre todos los registros y da OK.
