node-xmlvalidation

Validazione XML contro schemi XSD per integrazioni con sistemi esterni.
integration
/xmlvalidauth: nginx

node-xmlvalidation

In sintesi

Servizio specializzato nella validazione di documenti XML rispetto a schemi XSD versionati e a regole di business specifiche per il contesto fiscale italiano. Combina la validazione strutturale (XSD via xmllint-wasm) con un motore a regole pluggabili che, per la Fattura Elettronica PA, copre oltre 50 controlli normativi (algoritmo codice fiscale, coerenza P.IVA, aliquote IVA, codice destinatario, firma digitale P7M, ecc.). Esiste come microservizio dedicato perché concentra dipendenze native pesanti (xmllint-wasm, node-forge, xml-crypto), una libreria di XSD versionati con selezione automatica per data documento, e regole business riusabili che sarebbe controproducente duplicare nei singoli servizi consumer.

Funzionalità principali

  • Validazione XSD multi-versione: gli schemi sono registrati per configurazione con validFrom/validTo; il servizio sceglie automaticamente lo schema corretto in base alla data del documento, con fallback a schema di default o a schema "open-ended" se non c'è match esatto
  • Motore regole pluggabili (50+ regole italiane): codice fiscale, partita IVA, aliquote IVA vs riepilogo, natura/esigibilità, calcolo imponibile e imposta, coerenza tipo documento, duplicati di lotto, numero fattura, codice ufficio, dichiarazione d'intento, gruppo IVA
  • Verifica firma digitale PKI su file .xml.p7m (PKCS#7): catena al CA, scadenza/revoca certificato, riferimento temporale, conformità AgID
  • Modalità sincrona e asincrona: validazione sincrona per file singoli e XML inline; job asincrono con lifecycle tracking (pendingprocessingcompleted/failed) e endpoint di stato/risultato
  • Batch processing di più file XML per configurazione
  • Notifiche di stato job opzionali via webhook HTTP, email SMTP o coda messaggi (NATS/RabbitMQ)
  • Integrazione orchestrator: il servizio si registra come modulo presso node-orchestrator esponendo task validate-xml-sync-base64 / validate-xml-sync-string quando ORCHESTRATOR_ENABLED=true
  • Storage pluggabile (locale o S3) per upload temporanei e file XSD
  • Configurazioni multiple: lo stesso servizio può servire profili di validazione differenti (es. fatture-da-inviare, fatture-ricevute, EDI custom) ognuno con il proprio set di regole e XSD

Architettura

Stack: Fastify v5 · TypeScript strict · @pzeta/fastify-utils (auth nginx, security, healthcheck, OpenAPI) · @pzeta/log · xmllint-wasm (validazione XSD WebAssembly, no native bindings) · node-forge + xml-crypto + @xmldom/xmldom + xpath (firma digitale e canonicalizzazione) · xml2js (parsing per regole business) · @pzeta/orchestrator-node (registrazione modulo opzionale) · Zod per request/response validation.

Layout DDD (src/):

LayerContenuto
domain/validation-rules/italian-invoice/ (50+ regole), services/XsdSchemaManager + XsdSchemaSelector (selezione schema per data), strategie (XsdBusinessRulesStrategy, SchematronValidationStrategy, ExternalServiceValidationStrategy), value object (ValidationResult, ValidationError), repository interfaces, eventi
application/ValidatorOrchestrator (entry point validazione), StrategizedValidatorOrchestrator, SchemaValidatorService, RuleRegistryService, ValidationJobManager + NotifyingValidationJobManager, JobExecutorService, ConfigurationManagerService, NotificationService, DTO request/response
infrastructure/XsdSchemaManager con preload xmllint-wasm, rule-loading/ (FileSystem/Database/Api rule loader + factory), storage/ (Local + S3 strategy), file-handling/ (upload e temp file manager), notifications/ (Webhook/Email/Queue notifier), orchestrator/OrchestratorAdapter, monitoring/ (Prometheus), repositories/RuleRepository
presentation/Controller (ValidationController, JobController, SchemaController, ConfigurationController, RuleController), route (XmlValidationRoutes, JobRoutes, SchemaRoutes, ConfigurationRoutes, RuleRoutes), schemi Zod, formatters di errore

Pattern adottati: Strategy (motori di validazione intercambiabili: XSD+business, Schematron, external service), Factory (rule loader, storage, document date extractor), Repository, Event Publisher in-memory per eventi di dominio (ValidationStarted, ValidationCompleted, ValidationFailed), Adapter (orchestrator).

Schema registry: gli XSD non sono embedded nell'immagine. Sono caricati a runtime da una configurazione JSON versionata (storage/configuration.json) che, per ciascun profilo (fatture-da-inviare, ecc.), elenca gli schemi con id, name, version, validFrom, validTo. I file XSD veri e propri vivono nello storage (locale storage/uploads/ o S3) e possono essere caricati/sostituiti via API (POST /configurations/{id}/xsd). XsdSchemaManager esegue il preload tramite xmllint-wasm risolvendo gli import di schemi esterni; XsdSchemaSelector applica la logica di scelta in base alla data del documento.

Output validazione: ogni richiesta restituisce un ValidationResult strutturato con isValid, errors[] e warnings[]. Ogni errore include code, severity (error/warning/info), message localizzato, ruleId, ed eventuali coordinate XML (line, column, xpath) quando emergono da xmllint-wasm. Il batch produce un AggregatedValidationResult per file con un summary aggregato.

Casi d'uso

  • Validazione pre-invio Fattura Elettronica SDI: il flusso fatturazione invoca POST /validate/{configId}/single/sync prima di trasmettere il file allo SDI. Il servizio applica XSD FatturaPA v1.2.x, regole fiscali e, se il file è .xml.p7m, verifica della firma digitale CAdES
  • Controllo massivo fatture ricevute: import notturno di un lotto di fatture passive — il servizio fatturazione carica i file via POST /validate/{configId}/batch e itera sul AggregatedValidationResult per separare i documenti conformi da quelli da contestare al fornitore
  • Validazione asincrona orchestrata: un workflow di node-orchestrator riceve un XML da una pipeline EDI, chiama il task validate-xml-sync-base64 esposto dall'OrchestratorAdapter e, in base al risultato, instrada il documento verso l'import oppure verso una coda di anomalie
  • Validazione documenti EDI/custom: nuove configurazioni vengono create via POST /configurations con i propri XSD e regole, permettendo di riusare la stessa infrastruttura per schemi non-fattura (ordini, DDT, tracciati custom B2B)
  • Diagnostica regole: durante l'introduzione di una nuova regola fiscale, l'operatore consulta GET /rules/diagnostics/{configId} per verificare quali regole sono attive e GET /rules/statistics/{configId} per le metriche di applicazione su validazioni passate

Identità & esposizione

CampoValore
Categoriaintegration
Versione cluster1.0.0
Imagegitea.pzetatouch.it/pzeta_touch/node-xmlvalidation:1.0.14
URL pubblicohttps://ditta.pzeta.it/xmlvalid
Path regex ingress`/xmlvalid(/
Rewrite a backend/$2
DNS internonode-xmlvalidation-ditta.ditta.svc.cluster.local:3000
Auth nginxauth_requestnode-user-auth
Repositorynode-xmlvalidation
Endpoint REST20 (vedi sezione "API reference")

Endpoint operazionali

Endpoint convenzionali esposti da tutti i microservizi PZeta basati su @pzeta/fastify-utils:

Path pubblicoScopo
https://ditta.pzeta.it/xmlvalid/healthliveness probe
https://ditta.pzeta.it/xmlvalid/readyreadiness probe
https://ditta.pzeta.it/xmlvalid/metricsmetriche Prometheus
https://ditta.pzeta.it/xmlvalid/api-docs.jsonspec OpenAPI runtime (richiede OPENAPI_EXPOSE_IN_PRODUCTION=true)
https://ditta.pzeta.it/xmlvalid/api-docsSwagger UI (solo in NODE_ENV !== production)

Configurazione

Variabili d'ambiente che un integratore deve conoscere (lista completa in .env.default):

VariabileRuolo
HOST / PORTBind del server Fastify (default 0.0.0.0:3000)
DATABASE_HOST / _PORT / _USER / _PASSWORD / _NAMEConnessione PostgreSQL — usata da DatabaseRuleLoader quando le regole sono caricate da DB invece che da filesystem
STORAGE_TYPElocal (default) o s3; determina la strategy di FileStorageFactory per XSD e upload temporanei
STORAGE_LOCAL_BASE_PATHPath base per storage locale (default /usr/src/app/storage)
CONFIG_PATHOverride del path del file configuration.json con i profili di validazione
JOB_RETENTION_MSTTL dei job completati prima del cleanup (default 3600000 = 1 h)
JOB_CLEANUP_INTERVAL_MSFrequenza del cleanup automatico (default 300000 = 5 min, 0 per disabilitare)
NOTIFICATIONS_ENABLED / NOTIFICATION_EVENTSAbilita notifiche di stato job e filtra gli eventi (started,processing,completed,failed,cancelled)
NOTIFICATION_WEBHOOK_* / NOTIFICATION_EMAIL_* / NOTIFICATION_QUEUE_*Configurazione dei tre canali di notifica (HTTP, SMTP, message queue)
ORCHESTRATOR_ENABLEDSe true, registra il servizio come modulo presso node-orchestrator
ORCHESTRATOR_URL / ORCHESTRATOR_MODULE_ID / ORCHESTRATOR_API_KEYCoordinate per la registrazione modulo
ORCHESTRATOR_NATS_URL / ORCHESTRATOR_NATS_NAMESPACENATS opzionale usato dall'orchestrator-node SDK per event publishing dei task
ENABLE_CORS / CORS_ORIGINCORS per l'uso diretto dal frontend Vue
APP_URLURL pubblico dell'applicazione (usato in link nei messaggi di notifica)

I profili di validazione (XSD + regole + soglie file size) non si configurano via env: sono definiti in storage/configuration.json e gestibili via API REST (/configurations, /configurations/{id}/xsd, /rules/load).

Note eventing NATS

Lo scanner statico non rileva subject NATS — il servizio non pubblica né sottoscrive subject di dominio in modo dichiarativo (nats.json vuoto). L'unica integrazione con NATS è indiretta e opzionale: quando ORCHESTRATOR_ENABLED=true, l'SDK @pzeta/orchestrator-node apre una connessione a ORCHESTRATOR_NATS_URL per ricevere task in request/reply dall'orchestrator e pubblicare eventi di task completion sul namespace configurato (ORCHESTRATOR_NATS_NAMESPACE, default xml-validation). I subject sono derivati a runtime dal manifest del modulo, quindi non figurano nel report statico.

Il canale NOTIFICATION_QUEUE_* può a sua volta pubblicare notifiche di stato job su NATS/RabbitMQ/Redis (default topic xml-validation.notifications), ma è una funzionalità opt-in pensata per integrazioni esterne, non per l'eventing inter-servizio del cluster.

Dipendenze e dipendenti

Dipende da (servizi che questo servizio chiama):

Consumato da (chi chiama questo servizio):

Infrastruttura (PostgreSQL, NATS, Redis, MinIO) non è elencata qui — vedi sezione Architettura del singolo servizio.

Loading OpenAPI…
Loading NATS contracts…