Skip to content

[GOPACS] Migrate GOPACS UFTP Participants API from V2 to V3 #28

@Miggets7

Description

@Miggets7

Background

GOPACS has announced (email, April 2026) that the UFTP Participants API V2 is deprecated and will be removed starting 26 October 2026. The acceptance environment is removed first, then production. Our EMS integration in ems/manager/gopacs/ calls this API whenever Shapeshifter needs a peer's public key to verify an incoming UFTP message signature, so if we miss the deadline, inbound GOPACS messaging stops working.

The main functional change in V3 is that participants can now be looked up by ContractID + role as well as by domain, which lets GOPACS route activation messages to per-contract handlers. We are not adopting that new capability in this migration — it would require restructuring GOPACSHandler (currently one handler per EAN) and can be a follow-up if we ever need per-Capacity-Steering-Contract / per-Time-bound-Transport-Right behaviour. This migration is a minimal drop-in replacement to stay functional past the deadline.

What's changing in V3

V2 V3
Base URL (prod) https://clc-message-broker.gopacs-services.eu https://api.gopacs-services.eu
Base URL (acc) n/a via our config https://api.acc.gopacs-services.eu
Participant lookup GET /v2/participants/DSO?contractedEan={ean} → list of all DSOs for an EAN GET /uftp-participants/v3/participants/{uftpDomainName} → single ParticipantView
Content type XML JSON
Auth (not enforced in our client) Bearer JWT
Response fields domain, publicKey, endpoint, … domain, publicKey only

V3 also adds GET /uftp-participants/v3/participants/contracts/{contractId}/roles/{uftpRole} (roles: AGR, DSO; CRO listed as not supported). Our signature-verification call site always has the sender domain so the by-domain endpoint is the direct substitute — we don't need the contract/role endpoint for this migration.

Swagger documentation:

Scope of this change

  • Update GOPACSAddressBookResource to the V3 by-domain endpoint (JSON, Authorization header).
  • Add ParticipantView DTO record mirroring the V3 response schema.
  • Rewrite GOPACSHandler.getParticipantInformation(...) to call the V3 endpoint with a Bearer token from the existing OAuth2 client-credentials flow. Extract the token acquisition into a shared fetchBearerToken() helper.
  • Change DEFAULT_GOPACS_PARTICIPANT_URL to https://api.gopacs-services.eu.
  • Drop the endpoint field from cached UftpParticipantInformation (V3 no longer returns it — we pass null).

Out of scope (follow-up if needed):

  • Per-ContractID / per-role handler registration using GET /participants/contracts/{contractId}/roles/{uftpRole}.

Deployment note

Any deployment that overrides GOPACS_PARTICIPANT_URL (for example, pinning acceptance to https://clc-message-broker-acc.gopacs-services.eu) must be updated to the new host:

  • Production: GOPACS_PARTICIPANT_URL=https://api.gopacs-services.eu (or leave unset to use the default).
  • Acceptance: GOPACS_PARTICIPANT_URL=https://api.acc.gopacs-services.eu.

Known follow-up: outbound messaging needs a broker-URL fallback

V3's ParticipantView no longer carries an endpoint field, so the cached UftpParticipantInformation stores endpoint=null. Reading shapeshifter-core 3.2.2 (and confirmed identical in 3.5.0), the outbound send path is:

  1. GOPACSHandler.notifyNewOutgoingMessageUftpSendMessageService.attemptToSendMessage
  2. UftpSendMessageService.doSend (line 124–133 in 3.2.2, 135–144 in 3.5.0):
    UftpParticipantInformation participantInformation = participantService.getParticipantInformation(details.recipient());
    String url = participantInformation.endpoint();     // null after this migration
    ...
    send(signedXml, url, additionalHeaders, MAX_FOLLOW_REDIRECTS);
  3. UftpSendMessageService.send(...):
    var requestBuilder = HttpRequest.newBuilder().uri(new URI(url)) ...   // new URI(null) → NullPointerException

Timeline

  • 25 October 2026 — last day GOPACS guarantees V2 is available.
  • 26 October 2026 — GOPACS begins removing V2, starting with the acceptance environment.

Aim to have this merged and deployed to the acceptance environment well ahead of 26 October 2026 so we can validate against acceptance before production removal.

Metadata

Metadata

Assignees

Labels

EnhancementImprovement of an existing feature
No fields configured for Feature.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions