Ublime

UBL 2.1

Où injecter le modèle dans l'UBL ?

L'export Ublime est un seul fichier JSON qui contient à la fois la feuille XSL compilée et la palette — exactement ce qui s'embarque dans l'UBL. À l'empaquetage, ces deux champs deviennent deux pièces jointes UBL distinctes (ublime-xsl et ublime-palette), toujours issues du même export.

Format d'export : `ublime-template.json`

Après compilation dans le studio, l'export pour intégration ressemble à ceci. Pas de fichier séparé pour la palette — c'est voulu.

{
  "version": 1,
  "xsl": "<xsl:stylesheet version=\"1.0\">…</xsl:stylesheet>",
  "palette": {
    "colors": [{ "nom": "Indigo", "hex": "#6366f1" }],
    "roles": { "titre": 0, "texte": 0, "…": 0 }
  }
}

Ce format est distinct du modèle éditable (ublime-modele.json, arbre de blocs pour rouvrir le studio ou tester dans la démo). Seulublime-template.json est prêt à embarquer dans une facture.

Chaîne de transformation

  1. Studio → composition visuelle, puis compilation WASM /ublime-template::compile
  2. Export → un fichierublime-template.jsonavec les champs xsl et palette
  3. Empaquetage UBLublime_ubl::embed_attachments découpe l'export en deuxAdditionalDocumentReference (Base64), avant les parties
  4. Rendu → ré-extraction du XSL depuis l'UBL, revalidation, puisublime-render + variables CSS issues de la palette embarquée

Les deux pièces jointes Ublime

L'UBL ne porte pas le JSON d'export tel quel : il le éclateen deux pièces jointes standard, chacune identifiée par soncbc:ID, avec le contenu encodé en Base64.

cbc:IDContenumimeCodeObligatoire
ublime-xsl
Feuille de mise en page
Champ `xsl` du fichier d'export
application/xslt+xmlOui
ublime-palette
Palette de couleurs
Champ `palette` du même fichier d'export
application/jsonNon

Le logo du gabarit est compilé dans la feuille XSL (data URI validé), pas comme troisième pièce jointe UBL — choix de sûreté documenté dans le projet.

Structure XML (extrait)

Les pièces jointes sont placées au niveau racine Invoice, immédiatement avantcac:AccountingSupplierParty (contrainte de séquence UBL). Le contenu binaire est en Base64 danscbc:EmbeddedDocumentBinaryObject.

<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
         xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
         xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
  <cbc:ID>F-2026-001</cbc:ID>
  <cbc:IssueDate>2026-07-27</cbc:IssueDate>

  <!-- ① Feuille compilée (OBLIGATOIRE pour le rendu Ublime) -->
  <cac:AdditionalDocumentReference>
    <cbc:ID>ublime-xsl</cbc:ID>
    <cac:Attachment>
      <cbc:EmbeddedDocumentBinaryObject
          mimeCode="application/xslt+xml"
          filename="ublime.xsl">
        PHg6c3RsO...Base64DuXSL...==
      </cbc:EmbeddedDocumentBinaryObject>
    </cac:Attachment>
  </cac:AdditionalDocumentReference>

  <!-- ② Palette (OPTIONNELLE — couleurs / rôles) -->
  <cac:AdditionalDocumentReference>
    <cbc:ID>ublime-palette</cbc:ID>
    <cac:Attachment>
      <cbc:EmbeddedDocumentBinaryObject
          mimeCode="application/json"
          filename="palette.json">
        eyJjb2xvcnMiO...Base64DuJSON...==
      </cbc:EmbeddedDocumentBinaryObject>
    </cac:Attachment>
  </cac:AdditionalDocumentReference>

  <cac:AccountingSupplierParty>...</cac:AccountingSupplierParty>
  <!-- … reste de la facture EN16931 … -->
</Invoice>

Intégration serveur (POC)

Le binaire ublime-server expose trois endpoints utiles :

En pur client (studio / démo WASM), la compilation et le rendu suivent la même logique sans passer par HTTP — seule la source du XSL change (calculé en mémoire vs extrait de l'UBL).

Comment garantir l'intégrité ?

L'intégrité couvre deux niveaux : le template embarqué (personne ne substitue une feuille dangereuse) et le dossier de facture (preuve qu'un UBL n'a pas été altéré en transit).

1Export en un seul fichier

Le template exporté regroupe délibérément XSL et palette dans un même JSON (`ublime-template.json`). Deux fichiers séparés ouvriraient le mode d'échec « j'ai embarqué la feuille et oublié la palette », qui produirait silencieusement des factures sans couleurs.

2Identification par `cbc:ID`, pas par position

L'extraction cherche un `AdditionalDocumentReference` dont le `cbc:ID` vaut `ublime-xsl` ou `ublime-palette`. L'ordre des pièces jointes dans l'UBL ne change pas ce qui est interprété comme feuille ou palette.

3Vérifier-avant-rendu

À chaque rendu (`/api/render` ou preview), le XSL est ré-extrait depuis l'UBL, puis repasse `ublime_xsl::validate`. Un document trafiqué avec une feuille malveillante est rejeté — on ne rend jamais depuis un XSL « en cache » hors UBL.

4Liste blanche Ublime-XSL

Seuls HTML/XSL sûrs sont autorisés : pas de `style=` inline, pas de `<script>`, pas de XPath arbitraire injecté par l'auteur du template. La compilation revalide la feuille produite (défense en profondeur).

5Palette validée à l'empaquetage

Lors du scellement (`/api/package`), une palette invalide fait échouer la requête. Au rendu, une palette absente ou illisible est tolérée (couleurs par défaut) — la facture doit pouvoir s'afficher même si la pièce jointe palette manque.

6Échappement XML et Base64

Les données métier de la facture sont échappées à la construction UBL. Les pièces jointes template/palette sont encodées en Base64 dans `EmbeddedDocumentBinaryObject`.

7Scellement de dossier (`ublime-evidence`)

Pour un flux de preuve complet, la crate `ublime-evidence` peut sceller un dossier (UBL original, HTML rendu, échanges PA) avec manifeste signé. Les pièces jointes Ublime dans l'UBL sont alors couvertes par le sceau du document.

Checklist intégrateur