Skip to content

P1: e-invoice core — EN16931 → e-SLOG 2.0 / UBL (generate + validate)#1

Merged
terrxo merged 1 commit into
mainfrom
p1-e-invoice-core
May 25, 2026
Merged

P1: e-invoice core — EN16931 → e-SLOG 2.0 / UBL (generate + validate)#1
terrxo merged 1 commit into
mainfrom
p1-e-invoice-core

Conversation

@terrxo

@terrxo terrxo commented May 25, 2026

Copy link
Copy Markdown
Contributor

What this is

P1 of the fiscalization toolkit (ticket: grunt-it/tickets/fiscalization-einvoicing-toolkit.md): the e-invoice core. A clean, EN16931-aligned Invoice domain model → three outputs:

  • e-SLOG 2.0 — our owned serializer (UN/EDIFACT-INVOIC XML, urn:eslog:2.00). The Slovenian delta the upstream lib lacks.
  • UBL / CII — via @e-invoice-eu/core (model → ubl:Invoice internal JSON → lib).
  • EN16931 validation — structural, via the lib's JSON Schema (Ajv draft 2019-09).

Standalone + framework-agnostic, Effect-native API, with a Promise boundary (createEInvoice) so the separate @grunt-it/medusa-plugin-si-fiscalization track can wrap it as a leaf dep. No Medusa coupling.

Key decision (approved by coordinator): depend-on + adapt, not fork

@e-invoice-eu/core is WTFPL, on npm, bun-installable. We depend on it for the maintained EN16931 model + UBL/CII/Peppol/Factur-X serialization + validation, and own only the e-SLOG 2.0 serializer. Forking the upstream pnpm/NestJS monorepo would fork us off its update path — which fights the ticket's "track EN16931/Peppol rule changes via upkeep" goal.

Correction surfaced during the build

e-SLOG 2.0 is not "UBL + a CIUS" — it's EN16931-compliant but has its own XSD (UN/EDIFACT INVOIC-derived). So the e-SLOG serializer is real owned work, not a thin UBL wrapper. Verdict (don't fork) unchanged and reinforced.

Architecture

Module Role
src/lib/invoice/ Public EN16931 core-invoice model (valibot, BT-annotated) + parseInvoice
src/lib/eslog/ Owned e-SLOG 2.0 serializer (serializeEslog) + documented EDIFACT qualifier codes
src/lib/einvoice/ Bridge to @e-invoice-eu/core: model → internal JSON, generateEInvoice, validateEn16931
src/lib/foundation/ Effect house helpers (tagged errors, runSafe)

createEInvoice(input, { format }) runs parse → (validate for ubl/cii) → generate, returning { ok, data | error }.

Grounding (compliance correctness)

e-SLOG mapping grounded in the official spec (epos.si) and cross-checked element-by-element against the MIT-licensed reference generator Media24si/eslog2 (its inv.xml sample). Mapping is keyed to EN16931 Business Terms throughout (document totals → MOA 79/260/259/389/176/388/9, VAT breakdown → G_SG52, etc.). SI VAT EAS code 9949 verified against the Peppol code list.

Verification

  • bun test25 pass / 0 fail (e-SLOG segment assertions, UBL/CII generation via the lib, EN16931 validation, parse positive/negative, end-to-end pipeline).
  • bunx tsc --noEmit → clean.
  • Exercised under the bun runtime (per the bun rule): @e-invoice-eu/core + transitive deps install and generate UBL/CII with no native-dep issues.

Scope & deferrals

P1 maps the mandatory + common core. Deferred (in ROADMAP.md): e-SLOG XSD/schematron output validation, document/line-level allowances/charges, contacts/delivery address, multiple payment means, cross-border EAS map, XAdES signature, credit-note negative-amount rules. P2 = FURS (ZOI/EOR); P3 = integration surface; P4 = service + MCP.

Reviewer notes / judgment calls

  • License: MIT (ticket says "open-source"; derives from WTFPL + MIT sources). Flagging in case grunt-it prefers a different OSS license.
  • Publishes to GitHub Packages (like @grunt-it/utility-belt) so the medusa-plugin track can install it.
  • e-SLOG output is structurally faithful to the reference generator but is not yet XSD/schematron-validated — that's the first P1.x slice before any production exchange.

🤖 Generated with Claude Code

Public EN16931 core-invoice model (valibot, BT-annotated) → three outputs:
- e-SLOG 2.0 (owned serializer; UN/EDIFACT-INVOIC XML, urn:eslog:2.00)
- UBL / CII via @e-invoice-eu/core (model → ubl:Invoice internal JSON)
- EN16931 structural validation via the lib's JSON Schema (Ajv 2019-09)

Effect-native API (parseInvoice / validateEn16931 / generateEInvoice) plus a
Promise boundary (createEInvoice) for non-Effect hosts. Framework-agnostic —
no Medusa coupling; the medusa plugin track wraps this as a leaf dep.

e-SLOG mapping grounded in the epos.si spec + cross-checked vs the MIT
Media24si/eslog2 reference. 25 tests pass; tsc clean. Coverage/roadmap in
ROADMAP.md (e-SLOG XSD/schematron output validation + allowances deferred).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@terrxo terrxo merged commit fb41c05 into main May 25, 2026
2 checks passed
@terrxo terrxo deleted the p1-e-invoice-core branch May 25, 2026 04:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant