Repository navigation
Decisions
A lightweight ADR (Architecture Decision Record) log. One entry per decision that is expensive to reverse or that people will otherwise ask about repeatedly. Each entry has Context, Decision, Consequences and Status.
Status values: proposed · accepted · deferred · rejected · superseded by ADR-nnn.
| ADR | Title | Status |
|---|---|---|
| ADR-001 | AS4 out of scope | accepted |
| ADR-002 | TSR/EUSR submission out of scope | accepted |
| ADR-003 | Document validation via a configured Phorm instance | accepted |
| ADR-004 | Project name peppol-cli, executable peppol
|
accepted |
| ADR-005 | Java 25 baseline | accepted |
| ADR-006 | picocli as the CLI framework | accepted |
Context. The obvious next question after "can this participant receive my invoice?" is "then send it". AS4 sending would require message-level configuration, signing and encryption material, MIME and compression handling, reliable storage of sent messages and receipts, and retry logic. AS4 receiving additionally requires a long-running, publicly reachable HTTPS server. Both already exist in the AP software, which is built, tested and certified for exactly this.
Decision. peppol-cli does not send or receive AS4 messages, does not inspect AS4 messages, and does not
provide a mock AP. Diagnostics stop at the transport layer: TLS and HTTP reachability of the endpoint URL.
Consequences.
- The tool stays a short-lived, stateless process with no persistent message store and no receiving port.
- No AS4 signing or encryption keys are needed for the core feature set, which keeps the security surface small. Keys are still needed for SML/SMP write operations and TLS client authentication.
- Users who need to send will be pointed at the AP software. The wiki must say this clearly so the omission does not read as an oversight.
- A genuine gap remains: nobody can do a true end-to-end delivery test with this tool. Accepted.
- The endpoint diagnostics must be honest about their limits — a successful TLS handshake is not proof that an AS4 exchange would succeed.
Status. accepted
Context. Transaction Statistics Reports and End User Statistics Reports are produced by a service provider
from its own message history and submitted under its own identity. The input data lives in the AP's database;
the reporting libraries already exist (> TODO(verify): a peppol-reporting project exists alongside this one; confirm it is the intended library for TSR/EUSR and what its current scope is).
A CLI has neither the message history nor a legitimate claim to the submitting identity.
Decision. peppol-cli does not submit TSR or EUSR reports.
Consequences.
- No reporting period state, no submission credentials and no report storage in the CLI.
- Operators keep using their AP's reporting facility, which is where the source data is.
- Open, deliberately not decided here: whether local, read-only helpers (validate a report file, pretty-print one) would be acceptable, since they need no identity and no submission. If wanted, that is a new ADR.
> TODO(verify): the current specification names, versions and submission channel, so this entry names them correctly
Status. accepted
Context. Validating a business document means running a large, frequently updated set of validation artefacts. Embedding them in the CLI would tie document-level correctness to the CLI's own release cycle, make the distribution considerably larger, and mean every user runs whatever artefact version they last updated to. A Phorm instance already performs validation as a service, and an organisation typically wants one authoritative instance so that its developers, its CI and its support staff all get the same verdict.
Decision. peppol validate sends the document to a Phorm instance configured by the user and renders
the returned report. The CLI does not bundle validation artefacts and does not run validation locally. Document
type / customization ID auto-detection is done locally, so the user does not have to name the artefact by hand.
Consequences.
- Validation requires network access to the configured instance, and the instance's URL and credentials become part of the configuration. There is no useful offline validation.
- Verdicts stay consistent across a team, and artefact updates are an operational matter for whoever runs the instance, not a CLI release.
- The CLI sends business document content to that instance. This must be stated plainly in the documentation, since invoices are commercially sensitive. Pointing the tool at a third-party instance is a data-sharing decision the user must make knowingly.
- A transport error must be clearly distinguishable from a validation failure — hence exit code 5 versus 4.
- The Phorm API has since been verified against its source, and the details are recorded in the
Feature Catalogue:
POST /api/dd_and_validateandPOST /api/validate/{vesid}, the raw document as the request body, a shared secret in theX-Tokenheader, and JSON/XML/HTML reports selected by theAcceptheader. -
No reusable Phorm client library exists — verified.
com.helger:phormis the server WAR; the only existing caller isphoss-ap'sPhormDocumentVerifier, which is coupled tophoss-apand not reusable as-is. So this decision carries a cost: either a private client inpeppol-cli, or extracting a sharedphorm-client. See Library Gaps #2. - Local document type detection is available through the
dddlibrary (DocumentDetailsDeterminator.findDocumentDetails), so auto-detection does not require a server round trip.
Status. accepted
Context. The project needs a repository name and an executable name. Candidates ranged from ph-prefixed
puns consistent with the surrounding ecosystem to conventional -ctl tool names. The primary audience is AP and
SMP operators and integrators, not existing users of the phax libraries.
Decision. The project is peppol-cli; the executable is peppol. Alternatives and the reason for rejecting
each are recorded in Naming.
Consequences.
- Commands read naturally and are guessable:
peppol smp lookup,peppol cert verify. - The executable name is short and generic, so a
$PATHcollision check is needed before release. - "Peppol" is an OpenPeppol trademark. A prominent "not an official OpenPeppol tool" disclaimer is required on
every wiki page (see
_Footer.md) and in the README, plus a courtesy check with OpenPeppol. - Name-availability checks on GitHub, Homebrew, npm/PyPI and distro packages are follow-up tasks in Naming.
Status. accepted
Context. The surrounding libraries are Java-based and the shared parent POM currently defaults to a Java 17
baseline (ph-parent-pom, property java.version). A CLI has no servlet container or customer-managed runtime
to accommodate: the distribution decides which JRE it needs, and the only affected party is the person
installing it.
Decision. peppol-cli targets Java 25 and overrides the inherited java.version property accordingly.
Consequences.
- Current language and API features are available without conditional code.
- Users need a Java 25 runtime. This must be stated in the README and checked at startup with a clear error
rather than a
UnsupportedClassVersionError, and it makes bundling a runtime in the distribution archive worth considering. - Depended-upon libraries may target a lower baseline, which is fine — they only have to be readable by Java 25, not compiled with it.
> TODO(verify): that every intended phax dependency is usable on Java 25 (module path / JPMS and any reflection-based code in particular)- Java 25's ahead-of-time class loading and linking improvements are relevant to CLI startup time and may
reduce the pressure for a native image.
> TODO(verify): the exact JDK 25 AOT cache mechanism, its flags and its measured effect before relying on this argument
Status. accepted
Context. The tool needs argument parsing, a two-level command tree, help generation, shell completion and
exit code handling. Writing this by hand is avoidable work. picocli is already the framework used by the sibling
CLI tools in this ecosystem — verified in norma-cli, kaltblut-cli, ph-redact-cli, en16931-purifier-cli,
en16931-ubl2cii-cli, en16931-cii2ubl-cli and phoss-peppol-mcp, at version 4.7.7.
Decision. Use picocli. Its CommandLine.ExitCode constants define the first three exit codes in
CLI Conventions; its picocli-codegen companion generates the completion scripts.
Consequences.
- Consistent help output, option syntax and behaviour with the other tools in the ecosystem, and no in-house parser to maintain.
- The command tree structure follows picocli's annotation model, which suits the
peppol <area> <action>shape. - picocli is annotation- and reflection-driven, so a future native image needs its annotation processor configured. picocli supports this; it is one more reason to keep the native image question separate rather than open-ended. See Open Questions #1.
> TODO(decide): pin the picocli version in this project or inherit it from a shared parent POM property
Status. accepted
peppol-cli — licensed under the Apache License, Version 2.0.
Not an official OpenPeppol tool. This is an independent open source project and is neither endorsed by nor affiliated with OpenPeppol AISBL. "Peppol" is a trademark of OpenPeppol AISBL.
Status: planning
Overview
Design
Decisions
Reference