Skip to content

Repository files navigation

Marina Labs logo
Marina Labs

Singapore Peppol / InvoiceNow document validation platform
Validate UBL e-invoices against the official Singapore Peppol specifications, inspect human-readable validation reports, and convert invoices into presentation-quality PDFs. Ships as a web dashboard, a REST API, and a one-command Docker deployment.

Java 21 Spring Boot 4.1 Docker Compose License: MIT


What this project is. Marina Labs is a portfolio project built to showcase the full breadth of a real product in one codebase: deep familiarity with the Peppol / InvoiceNow e-invoicing domain, security engineering in a real Spring Boot application, documentation as a first-class feature, a clean Docker packaging story, and a Java + Node full-stack build (Maven orchestrates the npm frontend pipeline end-to-end). It is fully functional, but its purpose is to demonstrate craft, not to replace certified Access Point infrastructure.


📜 Faithful to the official Singapore specifications

Every validation artifact in this repository, every XSD schema, Schematron ruleset, and XSLT stylesheet, is an unmodified copy of the files published on peppolguide.sg, the official Singapore Peppol guide. The validation pipeline runs exactly the artifacts the specification publishes, organized per ruleset:

Ruleset Folder What it validates
SG Peppol BIS Billing 3.0 validation/sg-peppol-bis-billing-3.0 Invoices & credit notes (UBL 2.1)
PINT-SG Billing validation/pint-sg-billing PINT invoices & credit notes for Singapore
GST InvoiceNow validation/gst-invoicenow GST requirements layered on InvoiceNow invoices
SG BIS Order Balance validation/sg-bis-order-balance Order documents (UBL 2.1)
Additional BIS documents validation/additional-bis-documents Orders, order responses, application responses & related BIS transactions (UBL 2.1 / 2.3)

Each bundle is kept self-contained and intact, including the shared UBL schemas duplicated per ruleset, precisely so the repository mirrors the official distributions file-for-file and future spec releases can be dropped in cleanly. The matching XSLT stylesheets under src/main/resources/stylesheets/ are the official presentation transforms used for PDF rendering.

⚠️ Small print: Marina Labs is an independent project, still under active refinement, and is not affiliated with, endorsed by, or certified by IMDA, OpenPeppol, or any Peppol Authority. While the validation artifacts come straight from the official source, the surrounding pipeline is a work in progress and results may not be 100% accurate in every edge case. Do not treat it as a substitute for validation by a certified Access Point.


✨ What it does

Validation

  • Two-stage pipeline: XSD schema validation (Xerces) followed by Schematron business-rule validation (ph-schematron + Saxon-HE), producing a structured pass/warn/fail report per rule.
  • Instant anonymous validation from the landing page, no account needed to try it.
  • Bulk validation: upload a ZIP of up to 100 documents and get a consolidated report.
  • Persistent validation history and downloadable logs for registered users.

PDF generation

  • Transforms UBL XML through the official XSLT stylesheets into HTML, then renders it to PDF with wkhtmltopdf, turning machine-readable invoices into documents humans can actually read.

Service API

  • REST endpoints for validation (/api/service/validation/invoice, /bulk), validation logs, and PDF generation (/api/service/generate-pdf), authenticated with user-generated API keys managed from the dashboard.

Platform

  • Web dashboard (Thymeleaf + htmx) with usage statistics, validation history, PDF conversion, and API-key management.
  • Full account lifecycle: registration (optionally gated by single-use invite keys, disabled by default, toggle with marina.beta.enabled), email verification, password reset, all backed by transactional email.
  • Scheduled housekeeping: monthly usage-counter resets and automatic cleanup of never-verified accounts.

📚 Built-in documentation

Documentation is part of the product, not an afterthought:

  • /docs: a built-in documentation site explaining the platform and how to integrate with it.
  • /swagger-ui.html: interactive OpenAPI reference (springdoc) scoped to the public Service API, with try-it-out support and persisted API-key authorization.

🔐 Security design

  • Asymmetric JWT auth: "remember me" access/refresh token cookie pair (ml_at 15 min / ml_rt 30 days) signed with RSA keypairs that are generated automatically on first boot and kept outside the codebase.
  • Separate keypairs for session tokens and service API keys, so compromising one never compromises the other.
  • Rate limiting & lockouts with Bucket4j + Caffeine: per-account and per-IP thresholds on login, registration, email verification, and password reset, with automatic eviction (no cleanup jobs, no DB tables).
  • Hardened cookies (HttpOnly, SameSite=Lax) and proxy-aware forwarded-header handling for correct HTTPS behavior behind a reverse proxy.
  • Invite-key gate (optional): registration can require single-use beta keys generated by super-admins. Disabled by default; toggle with marina.beta.enabled.
  • Secrets hygiene: local secrets live in a gitignored properties file, Docker secrets flow through environment variables, and the .dockerignore guarantees credentials can never be baked into a published image.

🐳 Run it with Docker (recommended)

The entire stack (app, wkhtmltopdf, and PostgreSQL) ships as a Docker Compose package. You need nothing installed except Docker.

Clone this repository, then:

cp .env.example .env       # set DB_PASSWORD (and SMTP settings if you want email)
docker compose up --build

Then open http://localhost:8085. The multi-stage build compiles the app (Maven + frontend assets) and produces a slim runtime image with the official patched-Qt wkhtmltopdf baked in; Postgres data, signing keys, and logs persist in named volumes across restarts.

Running locally without Docker

You'll need Java 21, PostgreSQL (database marinalabs), and wkhtmltopdf on your PATH. Create src/main/resources/application-local.properties with your spring.datasource.password and SMTP settings, then:

./mvnw spring-boot:run

🛠️ Tech stack

Backend: Java 21 · Spring Boot (Web, Security, Data JPA, Mail, Actuator) · PostgreSQL · JJWT + BouncyCastle · Bucket4j + Caffeine · springdoc-openapi

Peppol pipeline: Saxon-HE & Xerces · ph-schematron / ph-ubl (Philip Helger's Peppol toolchain) · official XSLT stylesheets · wkhtmltopdf

Frontend: Thymeleaf + htmx · Node.js/npm build integrated into Maven (frontend-maven-plugin) · PurgeCSS-optimized Material Design Icons

Packaging: Docker multi-stage build · Docker Compose


📄 License

Released under the MIT License.

About

Singapore Peppol / InvoiceNow document validation platform

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages