cpeforge-cpe-validator 0.2.0

Validación de CPE SUNAT con hojas XSL (XSLT 1.0 con libxslt) y perfil seguro.
# cpeforge-cpe-validator

Validación de comprobantes SUNAT con hojas XSL: `XmlTypeResolver` detecta el
tipo por la raíz del XML, `XslPathResolver` ubica la hoja en un **directorio
local de reglas** (`2.X/ValidaExprRegFactura-2.0.1.xsl`, …), `XslValidator`
la ejecuta con libxslt (XSLT 1.0 + EXSLT) y `ErrorResultParser` convierte cada
`xsl:message` `nivel|código|mensaje[|ruta|valor]` en un `CpeError`.

El crate **no distribuye las reglas SUNAT**: el resultado depende de la
versión de las hojas que provea el consumidor. Las hojas tal como las publica
SUNAT («Archivo XSL – 2.1») no se ejecutan directamente: incluyen
`local:///commons/…` de IBM DataPower (no publicados) y usan EXSLT
`regexp:match`; se rechazan al compilar sin leer nada fuera del directorio de
reglas. Deben convertirse como en la referencia (`regexp:match` →
`MATCHES_HANDLER`, `commons` incluidos en el directorio de reglas).

```rust,no_run
use cpeforge_cpe_validator::CpeValidator;

# fn main() -> Result<(), Box<dyn std::error::Error>> {
let validator = CpeValidator::new("/ruta/a/reglas");
let xml = std::fs::read("20000000001-01-F001-1.xml")?;
for error in validator.validate_xml("20000000001-01-F001-1.xml", &xml)? {
    println!("{:?} {:?} {:?}", error.level, error.code, error.message);
}
# Ok(()) }
```

Las hojas pueden llamar a la función de extensión de expresiones regulares
registrada como `MATCHES_HANDLER`
(`CPEForge\Validator\Xml\XsltFunctions::matches`) con semántica PCRE en modo
de bytes y límites de retroceso y recursión. Las reglas que usen otro nombre
de función deben adaptarse a ese.

**Perfil seguro:** se rechaza todo `DOCTYPE`; no hay red ni escritura;
`xsl:include`, `xsl:import` y `document()` solo leen dentro del directorio de
reglas autorizado (enlaces simbólicos resueltos); hay límites de tamaño, de
operaciones XPath (si la libxml2 lo aplica, ver `engine_info()`) y de PCRE.
Los fallos de infraestructura son `CpeValidatorError` (con `error_class()`),
nunca una lista vacía.

Requisitos: libxml2 ≥ 2.9.11, libxslt ≥ 1.1.34 y libexslt del sistema
(`libxslt1-dev` en Debian/Ubuntu; el SDK en macOS), comprobadas al compilar y
al iniciar. Windows no está soportado. Antes de libxml2 el XML pasa por
`cpeforge_xml_limits::check_markup` (sin `DOCTYPE`, como máximo 256 atributos
por elemento).

**Limitación conocida, sin soporte:** la libxml2 de Apple en macOS < 13 no
ofrece el límite de operaciones XPath (`engine_info().xpath_operation_limit`
es `false`); con ella una hoja de reglas costosa no se corta por
`Limits::xpath_operations`. Con reglas que no sean de confianza usar macOS 13
o posterior, o Linux con libxml2 ≥ 2.9.11.

## Estado

Versión 0.2.0 en desarrollo. Lo que falta para la primera versión estable está en
[docs/pendientes.md](https://github.com/alvarez25leo/cpeforge/blob/main/docs/pendientes.md).

## Licencia

MIT. Ver `LICENSE` y, para el material de terceros incluido, `LICENSE-THIRD-PARTY` y `NOTICE`.