Skip to content

EU registry integration: what remains, and what it is blocked on #90

Description

@LKSNDRTMLKV

The EU digital product passport registry became operational on 20 July 2026, with operating rules in Commission Implementing Regulation (EU) 2026/1778 (in force 6 August 2026). A round of work has closed the gaps that were fixable from the regulation text alone. This issue records what is still missing, so the next person picking it up knows which items are work and which are waiting.

Already in place

Registration and transfer-of-responsibility both go through transactional outboxes with backoff. Registration is treated as asynchronous — an accepted submission moves to a submitted state and is polled for its verdict, never resubmitted. Payload validation is fail-closed. The model/batch/item registration level, the operator identifier's scheme, the commodity code and the back-up link all travel on the payload.


Blocked on the Commission's published API specification

Nothing here can be built without guessing a wire contract, and guessing produces code that looks finished and is wrong.

The authentication model is structurally wrong

The adapter models an OAuth2 client-credentials token exchange. Registry identity is not that: a verified economic operator proves identity with a qualified electronic seal, or a qualified electronic attestation of attributes (IR 2026/1778 Arts. 4–5). This is a wrong mechanism, not a wrong URL, and it is the single largest remaining item.

Resource paths and API version are inherited guesses

The hosts are now the Commission's published ones. Everything beneath them is not:

  • /registrations, /registrations/{id}/status, /registrations/{id}/transfer — invented.
  • The /api/v1 prefix is observed on the registry's own web client, not read from a specification.
  • api_version "1.0" is provisional.

Proof of registration is not modelled

Art. 9 entitles an operator to request proof of registration: a secure electronic document, downloadable from the registry, valid for 90 calendar days with regeneration. It is a pull operation against an endpoint we cannot specify. Building the storage and lifecycle without the fetch would be an empty box.


Constraints to confirm before they bite

The unique product identifier may be capped at 50 characters

The registry's own operator-facing form states a 50-character maximum for the UPI. Our GS1 Digital Link carrier URL is 65 characters (https://<host>/01/<gtin-14>/21/<20-char serial>), and 77 with a batch segment. Even a minimal host stays over.

Unresolved whether 50 is a constraint of that form or of the API. If it is the API's, the carrier URL shape has to change — which affects every printed label. Worth a helpdesk question early rather than discovering it at integration.

DPP registration cannot currently succeed for anyone

The registry documents that registration is not yet available for its first product group, because the semantic catalogue for that group is undefined. Enrolment is the only reachable milestone today. Any end-to-end registration gate should be sequenced against that, not against our own readiness.

Enrolment needs a different sealing artefact than passport sealing

Organisation enrolment works by counter-sealing an EC-generated PDF declaration, and the seal must be PAdES Baseline (B/T/LT/LTA) embedded in that PDF; other containers are documented as not accepted. The seal adapter produces a detached CAdES over a digest, which is the right artefact for sealing passport data and the wrong one for the declaration. These are two separate procurement/integration questions that have been treated as one.


Modelling gaps with no external blocker

Commodity code ranges are unvalidated

The code is validated structurally (HS-6, CN-8 or TARIC-10). Whether a given code falls inside the range a product group permits is checked by the registry (Art. 8(7)(d)) against ranges that live in the applicable delegated act. We could carry those ranges once a delegated act names them; today we cannot.

Status intents are recorded and never drained

Suspend and deactivate intents are held durably per passport and counted, but nothing consumes them: the registry publishes no status-push API. They are parked deliberately, not stuck — but the backlog has no expiry and will grow.


Notes for whoever picks this up

  • GET /api/v1/registry and GET /api/v1/dpp/{dppId}/registry report the current position, including operator verification standing and any published passports with no queue row.
  • Verified-operator status lapses at most three years after verification (Art. 4(4)). The drain holds — without consuming attempts — when it has lapsed, so a node whose operator has never recorded a verification date will queue registrations and send nothing. That is intended, and the rollup says so.
  • The registry types live in the dpp-registry crate of dpp-core; the adapter, outboxes and drains live here.

Companion issue: the registry types — payload/envelope shapes, endpoint constants, status vocabulary and the proof-of-registration gap — are tracked in odal-node/dpp-core#98. This issue covers the adapter, outboxes, drains and operator-facing surface that consume them.

Metadata

Metadata

Assignees

No one assigned

    Labels

    complianceRegulatory/compliance correctness issueenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions