Repository navigation
Library Gaps
Things peppol-cli needs that the existing libraries do not currently provide. Each was verified by reading
the source; nothing here is inferred from documentation or from memory.
The Where it belongs column matters: most of these are better fixed upstream than worked around in the CLI,
because other consumers need them too. A gap fixed in peppol-commons helps phoss-smp and phoss-ap as well;
the same code hidden inside peppol-cli helps nobody else.
| # | Gap | Verified finding | Where it belongs |
|---|---|---|---|
| 1 | GLN check-digit validation |
peppol-id-checks validates participant values through IParticipantIdentifierValidatorSPI, but only two implementations are registered: ParticipantIdentifierValidatorNorwayOrgNumber (mod-11) and ParticipantIdentifierValidatorBelgium (mod-97). No GLN/Luhn check-digit validator exists in any src/main; "GLN" appears only in Javadoc and as the constant PeppolParticipantCountryHelper.ICD_GLN = "0088". |
peppol-id-checks, as a new SPI implementation. The plumbing is already there, so this is small. > TODO(verify): is rejecting a bad GLN check digit correct behaviour, or must it only warn? That decides whether it is a validator or a separate advisory check.
|
| 2 | Peppol Directory client |
peppol-directory-businesscard provides the business card data model (v1/v2/v3) and marshallers. No Directory search client class was found anywhere in peppol-commons. |
Ideally a new peppol-directory-client module in peppol-commons, so peppol-cli and others share it. > TODO(verify): whether phoss-directory already contains reusable client code that should be extracted rather than written afresh.
|
| 3 | Phorm client library |
com.helger:phorm is the server WAR; there is no phorm-client module and no published client artefact. The only real caller is phoss-ap's PhormDocumentVerifier, which is coupled to phoss-ap-api and phoss-ap-basic and so cannot be reused as-is. Two copy-paste examples live in Phorm's own test tree. |
A small shared phorm-client module — consumed by both phoss-ap and peppol-cli — is the better outcome than a third hand-rolled HTTP client. It would also give the API a single documented client-side contract. |
| 4 | Runtime access to code list data | The code list XMLs are bundled in peppol-id's JAR under external/codelists/, but no src/main class reads them — the generated enums are the entire runtime API, and each carries its own CODE_LIST_VERSION (currently "9.7"). A single JAR therefore exposes exactly one code list version. |
Blocks peppol codelist diff outright. Options: a runtime reader for the bundled XMLs in peppol-id, or an authoritative published versioned code list artefact to download. Needs a decision before that feature can be planned properly. |
| 5 | A single code list version constant | The version is repeated as CODE_LIST_VERSION on each generated enum; there is no repo-wide constant. |
A CPeppolCodeLists.VERSION in peppol-id would let a consumer report one version instead of five, and would catch a generation that updated some enums but not others. Minor, cheap. |
| 6 | SML read/query operations |
peppol-sml-client provides the management callers (ManageServiceMetadataServiceCaller, ManageParticipantIdentifierServiceCaller, BDMSLClient) and has no DNS code in src/main (dnsjava is test scope only). Whether a non-owning client can query registrations is unclear from the source alone. |
> TODO(verify): if the SML management API has no read path for third parties, then peppol sml query cannot exist as specified and should become an alias for peppol dns resolve. This needs a domain answer, not more code reading. |
| 7 | Seat ID extraction from a certificate | The format is verified — PeppolIdentifierHelper.REGEX_SEAT_ID = "P[A-Z]{2}[0-9]{6}" — but no helper that extracts a Seat ID from an X509Certificate was found. |
A helper in peppol-commons' com.helger.peppol.security package. > TODO(verify): which certificate field carries it (subject CN component?), from the Peppol PKI documentation.
|
| 8 | Constants for the SML and Directory trust stores |
peppol-commons/src/main/resources/truststore/ contains sml-truststore.jks and directory-truststore.jks, but neither has a Java constant in PeppolTrustStores — they are referenced only from a test-scope hash tool. Every other trust store has *_CLASSPATH, *_DESCRIPTOR_* and loaded-instance constants. |
PeppolTrustStores, for symmetry. Needed if the CLI is to verify SML or Directory TLS certificates against the Peppol chain rather than the JDK default trust store. > TODO(verify): are those two trust stores still current, given the G2→G3 move? They sit outside the 2018/2025 directory structure.
|
| 9 | No "next CA generation" constant |
PeppolTrustStores has Config2018 (G2, @Deprecated since 12.3.8, JKS) and Config2025 (G3, current, PKCS12). PeppolTrustedCA is wired to Config2025 only. There is no G4 or "next" constant. |
Not a gap today — a forward dependency. It does mean peppol cert verify --generation currently has exactly one meaningful value, and the flag should be designed so adding G4 later is not a breaking change. |
| 10 | Two diverging transport profile enums | Generated EPredefinedTransportProfileIdentifier in peppol-id (from code list 9.7) and hand-maintained ESMPTransportProfile in peppol-commons (which is what the SMP code actually uses, via SMPTransportProfileRegistry). Nothing keeps them in agreement. |
peppol-commons. Not a missing feature but a real consistency risk: a CLI that lists one and validates against the other would produce contradictory answers. A test asserting the two agree would be cheap insurance. |
| 11 | Per-user config file discovery |
ph-config resolves the classpath, the working directory and whatever config.file points at. It has no notion of XDG base directories or %APPDATA%. |
ph-config, as a reusable helper. Every CLI in this ecosystem needs it — norma-cli, kaltblut-cli, ph-redact-cli, the en16931-*-cli tools — so solving it once upstream is clearly better than a fourth private copy. See Configuration. |
| 12 | Config value provenance |
peppol config show should print where each value came from. Sources carry a priority, but it is unclear how much origin information ConfiguredValue / IConfigurationSource expose. |
ph-config, if the information is not already reachable. > TODO(verify): read ConfiguredValue and IConfigurationSource to establish what is available before assuming this is a gap.
|
| 13 | Config secret handling |
ph-config has no notion of a secret value, no redaction and no file-permission checking. |
Arguably the CLI's own concern, but a "this key is secret" marker in ph-config would let every consumer redact consistently instead of each maintaining its own key-name pattern. > TODO(decide): upstream or local?
|
These came out of the research and are not peppol-cli requirements, but they will mislead whoever implements it.
-
peppol-commonsREADME is out of date. The usage examples around lines 270–290 usePeppolURLProvider.INSTANCEandESML.DIGIT_TEST; neither exists in 13.0.1-SNAPSHOT. The current equivalents arePeppolNaptrURLProvider.INSTANCEandESML.PEPPOL_TEST/ESML.PEPPOL_PRODUCTION.ESML's own class Javadoc still lists the removedDIGIT_PRODUCTION/DIGIT_TESTconstants. -
The MD5 misconception. The participant hash is SHA-256 + Base32 with padding stripped
(
AbstractBDXLURLProvider); the MD5-basedPeppolURLProviderwas removed. Stale documentation saying MD5 is an easy way for an implementer — or an AI assistant — to get this wrong, and it is worth correcting at the source. -
Phorm:
GET /api/get/vesidsis effectively unauthenticated. InApiGetAllVESIDs.javathe token check is behind a disabled guard:Every other API endpoint enforcesif (false) if (!verifyAuthOrSetForbidden (aRequestScope, aUnifiedResponse, sLogPrefix)) return;
X-Token. This may well be deliberate — it makes the endpoint usable as a connectivity probe, whichpeppol-cliwould benefit from — but a deadif (false)does not say whether it is intended. Worth either removing or replacing with a comment explaining the intent. Flagging it because it is a security-relevant asymmetry, not because the CLI needs it changed. -
Generated sources.
peppol-id-datatypes,peppol-smp-datatypes,peppol-sbdhandpeppol-sml-clientneedmvn generate-sourcesbefore IDE use. A CONTRIBUTING note would save a new contributor an hour.
| Gap | Affected feature | Consequence if not closed |
|---|---|---|
| 1 | peppol id check-value |
GLN identifiers get syntax-only validation; the command silently under-delivers. |
| 2 | peppol dir search |
Needs its own HTTP client, or the feature slips out of M2. |
| 3 | peppol validate * |
A hand-rolled client duplicates phoss-ap's logic, so a Phorm API change breaks two places. |
| 4 | peppol codelist diff |
Cannot be built as specified. Should be marked deferred rather than proposed until gap 4 is resolved. |
| 6 | peppol sml query |
May not be implementable; would become an alias for peppol dns resolve. |
| 7 | peppol cert seat-id |
Needs its own extraction code, with a real risk of reading the wrong certificate field. |
| 8 | Endpoint/TLS checks against SML and Directory | Falls back to the JDK trust store, which is a weaker check than verifying against the Peppol chain. |
| 11 | Config discovery | Every CLI in the ecosystem keeps reinventing it. |
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