From 0522e436ab464f5ef5ea90b100b814615f7822d1 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Wed, 5 Aug 2026 12:48:46 +0200 Subject: [PATCH] feat: add compact on egress messages --- .../common-core/src/main/resources/dcp.v1.0.jsonld | 3 ++- .../identityhub/core/CoreServicesExtension.java | 1 + .../CredentialRequestManagerImpl.java | 14 ++++++++++++-- .../CredentialRequestManagerImplTest.java | 8 +++++++- .../credentials/CredentialServiceExtension.java | 5 ++++- .../offers/IssuerCredentialOfferServiceImpl.java | 10 ++++++++-- .../IssuerCredentialOfferServiceImplTest.java | 8 +++++++- 7 files changed, 41 insertions(+), 8 deletions(-) diff --git a/core/common-core/src/main/resources/dcp.v1.0.jsonld b/core/common-core/src/main/resources/dcp.v1.0.jsonld index e35fa9bbd..82b6e28e3 100644 --- a/core/common-core/src/main/resources/dcp.v1.0.jsonld +++ b/core/common-core/src/main/resources/dcp.v1.0.jsonld @@ -88,7 +88,8 @@ }, "credentials": { "@id": "dcp:credentials", - "@type": "@json" + "@type": "@json", + "@container": "@set" } } }, diff --git a/core/identity-hub-core/src/main/java/org/eclipse/edc/identityhub/core/CoreServicesExtension.java b/core/identity-hub-core/src/main/java/org/eclipse/edc/identityhub/core/CoreServicesExtension.java index ffee8c591..b5b115813 100644 --- a/core/identity-hub-core/src/main/java/org/eclipse/edc/identityhub/core/CoreServicesExtension.java +++ b/core/identity-hub-core/src/main/java/org/eclipse/edc/identityhub/core/CoreServicesExtension.java @@ -224,6 +224,7 @@ public CredentialRequestManager createDefaultCredentialRequestService(ServiceExt .store(credentialRequestStore) .didResolverRegistry(didResolverRegistry) .typeTransformerRegistry(typeTransformerRegistry.forContext(DCP_SCOPE_V_1_0)) + .jsonLd(jsonLd) .httpClient(httpClient) .secureTokenService(secureTokenService) .transactionContext(transactionContext) diff --git a/core/identity-hub-core/src/main/java/org/eclipse/edc/identityhub/core/services/verifiablecredential/CredentialRequestManagerImpl.java b/core/identity-hub-core/src/main/java/org/eclipse/edc/identityhub/core/services/verifiablecredential/CredentialRequestManagerImpl.java index 6dfd68940..9aad4612e 100644 --- a/core/identity-hub-core/src/main/java/org/eclipse/edc/identityhub/core/services/verifiablecredential/CredentialRequestManagerImpl.java +++ b/core/identity-hub-core/src/main/java/org/eclipse/edc/identityhub/core/services/verifiablecredential/CredentialRequestManagerImpl.java @@ -33,6 +33,7 @@ import org.eclipse.edc.identityhub.spi.participantcontext.IdentityHubParticipantContextService; import org.eclipse.edc.identityhub.spi.participantcontext.model.IdentityHubParticipantContext; import org.eclipse.edc.identityhub.spi.verifiablecredentials.CredentialRequestManager; +import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.spi.iam.TokenRepresentation; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.persistence.EdcPersistenceException; @@ -60,6 +61,7 @@ import java.util.function.Function; import static java.util.Objects.requireNonNull; +import static org.eclipse.edc.identityhub.protocols.dcp.spi.DcpConstants.DCP_SCOPE_V_1_0; import static org.eclipse.edc.identityhub.spi.credential.request.model.HolderRequestState.CREATED; import static org.eclipse.edc.identityhub.spi.credential.request.model.HolderRequestState.ERROR; import static org.eclipse.edc.identityhub.spi.credential.request.model.HolderRequestState.REQUESTING; @@ -77,6 +79,7 @@ public class CredentialRequestManagerImpl extends AbstractStateEntityManager updateRequest(HolderCredentialRequest request) { } private Processor processRequestsInState(HolderRequestState state, Function>> function) { - var filter = new Criterion[]{ hasState(state.code()), isNotPending() }; + var filter = new Criterion[]{hasState(state.code()), isNotPending()}; return createProcessor(function, filter); } @@ -208,7 +211,8 @@ private Result createCredentialsRequest(TokenRepresentation token, Stri idsAndFormats.forEach((rq) -> rqMessage.credential(new CredentialRequestSpecifier(rq.id()))); - var jsonObj = dcpTypeTransformerRegistry.transform(rqMessage.build(), JsonObject.class); + var jsonObj = dcpTypeTransformerRegistry.transform(rqMessage.build(), JsonObject.class) + .compose(json -> jsonLd.compact(json, DCP_SCOPE_V_1_0)); return jsonObj.map(JsonObject::toString) .map(json -> new Request.Builder() @@ -301,6 +305,11 @@ public Builder typeTransformerRegistry(TypeTransformerRegistry typeTransformerRe return this; } + public Builder jsonLd(JsonLd jsonLd) { + manager.jsonLd = jsonLd; + return this; + } + public Builder httpClient(EdcHttpClient httpClient) { manager.httpClient = httpClient; return this; @@ -343,6 +352,7 @@ public CredentialRequestManagerImpl build() { super.build(); requireNonNull(manager.didResolverRegistry); requireNonNull(manager.dcpTypeTransformerRegistry); + requireNonNull(manager.jsonLd); requireNonNull(manager.httpClient); requireNonNull(manager.secureTokenService); requireNonNull(manager.transactionContext); diff --git a/core/identity-hub-core/src/test/java/org/eclipse/edc/identityhub/core/services/verifiablecredential/CredentialRequestManagerImplTest.java b/core/identity-hub-core/src/test/java/org/eclipse/edc/identityhub/core/services/verifiablecredential/CredentialRequestManagerImplTest.java index ea5c1487d..94b63f00d 100644 --- a/core/identity-hub-core/src/test/java/org/eclipse/edc/identityhub/core/services/verifiablecredential/CredentialRequestManagerImplTest.java +++ b/core/identity-hub-core/src/test/java/org/eclipse/edc/identityhub/core/services/verifiablecredential/CredentialRequestManagerImplTest.java @@ -30,6 +30,7 @@ import org.eclipse.edc.identityhub.spi.credential.request.store.HolderCredentialRequestStore; import org.eclipse.edc.identityhub.spi.participantcontext.IdentityHubParticipantContextService; import org.eclipse.edc.identityhub.spi.participantcontext.model.IdentityHubParticipantContext; +import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.spi.iam.TokenRepresentation; import org.eclipse.edc.spi.persistence.EdcPersistenceException; import org.eclipse.edc.spi.query.Criterion; @@ -51,6 +52,7 @@ import java.util.function.Function; import static org.awaitility.Awaitility.await; +import static org.eclipse.edc.identityhub.protocols.dcp.spi.DcpConstants.DCP_SCOPE_V_1_0; import static org.eclipse.edc.identityhub.spi.credential.request.model.HolderRequestState.ERROR; import static org.eclipse.edc.identityhub.spi.credential.request.model.HolderRequestState.REQUESTED; import static org.eclipse.edc.identityhub.spi.credential.request.model.HolderRequestState.REQUESTING; @@ -85,10 +87,12 @@ class CredentialRequestManagerImplTest { private final EdcHttpClient httpClient = mock(); private final ParticipantSecureTokenService sts = mock(); private final IdentityHubParticipantContextService participantContextService = mock(); + private final JsonLd jsonLd = mock(); private final CredentialRequestManagerImpl credentialRequestService = CredentialRequestManagerImpl.Builder.newInstance() .store(store) .didResolverRegistry(resolver) .typeTransformerRegistry(transformerRegistry) + .jsonLd(jsonLd) .httpClient(httpClient) .secureTokenService(sts) .participantContextService(participantContextService) @@ -101,6 +105,7 @@ class CredentialRequestManagerImplTest { void setUp() { when(transformerRegistry.transform(any(CredentialRequestMessage.class), eq(JsonObject.class))) .thenReturn(success(Json.createObjectBuilder().build())); + when(jsonLd.compact(any(), eq(DCP_SCOPE_V_1_0))).thenReturn(success(Json.createObjectBuilder().build())); when(sts.createToken(anyString(), anyMap(), ArgumentMatchers.isNull())).thenReturn(success(TokenRepresentation.Builder.newInstance().build())); when(participantContextService.getParticipantContext(anyString())).thenReturn(ServiceResult.success(participantContext())); when(store.findById(anyString())).thenReturn(null); @@ -189,10 +194,11 @@ void processInitial_shouldSendRequest(String stateString) { credentialRequestService.start(); await().atMost(MAX_DURATION).untilAsserted(() -> { - var inOrder = inOrder(resolver, store, httpClient, sts); + var inOrder = inOrder(resolver, store, httpClient, sts, jsonLd); inOrder.verify(resolver).resolve(eq(ISSUER_DID)); inOrder.verify(store).save(argThat(r -> r.getState() == REQUESTING.code())); inOrder.verify(sts).createToken(anyString(), anyMap(), ArgumentMatchers.isNull()); + inOrder.verify(jsonLd).compact(any(), eq(DCP_SCOPE_V_1_0)); inOrder.verify(httpClient).execute(any(), (Function>) any()); inOrder.verify(store).save(argThat(r -> r.getState() == REQUESTED.code() && r.getIssuerPid() != null)); }); diff --git a/core/issuerservice/issuerservice-credentials/src/main/java/org/eclipse/edc/issuerservice/credentials/CredentialServiceExtension.java b/core/issuerservice/issuerservice-credentials/src/main/java/org/eclipse/edc/issuerservice/credentials/CredentialServiceExtension.java index 763174673..bfa0e9281 100644 --- a/core/issuerservice/issuerservice-credentials/src/main/java/org/eclipse/edc/issuerservice/credentials/CredentialServiceExtension.java +++ b/core/issuerservice/issuerservice-credentials/src/main/java/org/eclipse/edc/issuerservice/credentials/CredentialServiceExtension.java @@ -28,6 +28,7 @@ import org.eclipse.edc.issuerservice.spi.credentials.statuslist.StatusListManager; import org.eclipse.edc.issuerservice.spi.holder.store.HolderStore; import org.eclipse.edc.issuerservice.spi.issuance.generator.CredentialGeneratorRegistry; +import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.runtime.metamodel.annotation.Provider; @@ -69,6 +70,8 @@ public class CredentialServiceExtension implements ServiceExtension { private StatusListInfoFactoryRegistry statusListInfoFactoryRegistry; @Inject private StatusListManager statusListManager; + @Inject + private JsonLd jsonLd; @Override public String name() { @@ -86,7 +89,7 @@ public CredentialStatusService getStatusListService(ServiceExtensionContext cont public IssuerCredentialOfferService credentialOfferService(ServiceExtensionContext context) { return new IssuerCredentialOfferServiceImpl(transactionContext, holderStore, credentialServiceUrlResolver, sts, participantContextService, httpClient, context.getMonitor(), transformerRegistry.forContext(DCP_SCOPE_V_1_0), - issuerMetadataService); + issuerMetadataService, jsonLd); } } diff --git a/core/issuerservice/issuerservice-credentials/src/main/java/org/eclipse/edc/issuerservice/credentials/offers/IssuerCredentialOfferServiceImpl.java b/core/issuerservice/issuerservice-credentials/src/main/java/org/eclipse/edc/issuerservice/credentials/offers/IssuerCredentialOfferServiceImpl.java index fe115127f..9339d681f 100644 --- a/core/issuerservice/issuerservice-credentials/src/main/java/org/eclipse/edc/issuerservice/credentials/offers/IssuerCredentialOfferServiceImpl.java +++ b/core/issuerservice/issuerservice-credentials/src/main/java/org/eclipse/edc/issuerservice/credentials/offers/IssuerCredentialOfferServiceImpl.java @@ -29,6 +29,7 @@ import org.eclipse.edc.identityhub.spi.participantcontext.model.IdentityHubParticipantContext; import org.eclipse.edc.issuerservice.spi.credentials.IssuerCredentialOfferService; import org.eclipse.edc.issuerservice.spi.holder.store.HolderStore; +import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.spi.iam.TokenRepresentation; import org.eclipse.edc.spi.monitor.Monitor; import org.eclipse.edc.spi.result.Result; @@ -44,6 +45,7 @@ import java.util.Map; import static java.util.stream.Collectors.toSet; +import static org.eclipse.edc.identityhub.protocols.dcp.spi.DcpConstants.DCP_SCOPE_V_1_0; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.AUDIENCE; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.EXPIRATION_TIME; import static org.eclipse.edc.jwt.spi.JwtRegisteredClaimNames.ISSUED_AT; @@ -61,6 +63,7 @@ public class IssuerCredentialOfferServiceImpl implements IssuerCredentialOfferSe private final EdcHttpClient httpClient; private final TypeTransformerRegistry dcpTransformerRegistry; private final DcpIssuerMetadataService dcpIssuerMetadataService; + private final JsonLd jsonLd; public IssuerCredentialOfferServiceImpl(TransactionContext transactionContext, HolderStore holderStore, @@ -68,7 +71,8 @@ public IssuerCredentialOfferServiceImpl(TransactionContext transactionContext, ParticipantSecureTokenService secureTokenService, IdentityHubParticipantContextService participantContextService, EdcHttpClient httpClient, Monitor monitor, - TypeTransformerRegistry dcpTransformerRegistry, DcpIssuerMetadataService dcpIssuerMetadataService) { + TypeTransformerRegistry dcpTransformerRegistry, DcpIssuerMetadataService dcpIssuerMetadataService, + JsonLd jsonLd) { this.transactionContext = transactionContext; this.holderStore = holderStore; this.credentialServiceUrlResolver = credentialServiceUrlResolver; @@ -78,6 +82,7 @@ public IssuerCredentialOfferServiceImpl(TransactionContext transactionContext, this.httpClient = httpClient; this.dcpTransformerRegistry = dcpTransformerRegistry; this.dcpIssuerMetadataService = dcpIssuerMetadataService; + this.jsonLd = jsonLd; } @Override @@ -190,7 +195,8 @@ private Result createOfferMessage(String issuerDid, Collection(credentialObjects)) .build(); - return dcpTransformerRegistry.transform(credentialOfferMessage, JsonObject.class); + return dcpTransformerRegistry.transform(credentialOfferMessage, JsonObject.class) + .compose(json -> jsonLd.compact(json, DCP_SCOPE_V_1_0)); } diff --git a/core/issuerservice/issuerservice-credentials/src/test/java/org/eclipse/edc/issuerservice/credentials/offers/IssuerCredentialOfferServiceImplTest.java b/core/issuerservice/issuerservice-credentials/src/test/java/org/eclipse/edc/issuerservice/credentials/offers/IssuerCredentialOfferServiceImplTest.java index 1aabb941c..7d46eae0e 100644 --- a/core/issuerservice/issuerservice-credentials/src/test/java/org/eclipse/edc/issuerservice/credentials/offers/IssuerCredentialOfferServiceImplTest.java +++ b/core/issuerservice/issuerservice-credentials/src/test/java/org/eclipse/edc/issuerservice/credentials/offers/IssuerCredentialOfferServiceImplTest.java @@ -28,6 +28,7 @@ import org.eclipse.edc.issuerservice.spi.credentials.IssuerCredentialOfferService; import org.eclipse.edc.issuerservice.spi.holder.model.Holder; import org.eclipse.edc.issuerservice.spi.holder.store.HolderStore; +import org.eclipse.edc.jsonld.spi.JsonLd; import org.eclipse.edc.spi.iam.TokenRepresentation; import org.eclipse.edc.spi.result.Result; import org.eclipse.edc.spi.result.ServiceResult; @@ -40,6 +41,7 @@ import java.util.List; import java.util.function.Function; +import static org.eclipse.edc.identityhub.protocols.dcp.spi.DcpConstants.DCP_SCOPE_V_1_0; import static org.eclipse.edc.junit.assertions.AbstractResultAssert.assertThat; import static org.eclipse.edc.spi.result.Result.success; import static org.mockito.ArgumentMatchers.any; @@ -69,6 +71,7 @@ class IssuerCredentialOfferServiceImplTest { private final TypeTransformerRegistry typeTransformerRegistry = mock(); private final DcpIssuerMetadataService issuerMetadataService = mock(); + private final JsonLd jsonLd = mock(); private final IssuerCredentialOfferService credentialOfferService = new IssuerCredentialOfferServiceImpl(new NoopTransactionContext(), holderStore, credentialServiceUrlResolver, @@ -76,7 +79,8 @@ class IssuerCredentialOfferServiceImplTest { participantContextService, httpClient, mock(), typeTransformerRegistry, - issuerMetadataService + issuerMetadataService, + jsonLd ); @BeforeEach @@ -87,6 +91,7 @@ void setUp() { when(credentialServiceUrlResolver.resolve(anyString())).thenReturn(success(HOLDER_CS_ENDPOINT)); when(participantContextService.getParticipantContext(eq(PARTICIPANT_CONTEXT_ID))).thenReturn(ServiceResult.success(issuerParticipant())); when(typeTransformerRegistry.transform(any(), eq(JsonObject.class))).thenReturn(success(Json.createObjectBuilder().build())); + when(jsonLd.compact(any(), eq(DCP_SCOPE_V_1_0))).thenReturn(success(Json.createObjectBuilder().build())); when(issuerMetadataService.getIssuerMetadata(any())).thenReturn(ServiceResult.success(IssuerMetadata.Builder.newInstance() .issuer(ISSUER_DID) .credentialSupported(CredentialObject.Builder.newInstance() @@ -107,6 +112,7 @@ void sendCredentialOffer_success() { verify(participantContextService).getParticipantContext(eq(PARTICIPANT_CONTEXT_ID)); verify(sts).createToken(anyString(), anyMap(), isNull()); verify(credentialServiceUrlResolver).resolve(anyString()); + verify(jsonLd).compact(any(), eq(DCP_SCOPE_V_1_0)); verify(httpClient).execute(any(), (Function>) any()); verifyNoMoreInteractions(holderStore, participantContextService, sts, httpClient); }