diff --git a/core/lib/verifiable-presentation-lib/src/main/java/org/eclipse/edc/identithub/verifiablecredential/CredentialStatusCheckServiceImpl.java b/core/lib/verifiable-presentation-lib/src/main/java/org/eclipse/edc/identithub/verifiablecredential/CredentialStatusCheckServiceImpl.java index 7e628a9ac..5e221302e 100644 --- a/core/lib/verifiable-presentation-lib/src/main/java/org/eclipse/edc/identithub/verifiablecredential/CredentialStatusCheckServiceImpl.java +++ b/core/lib/verifiable-presentation-lib/src/main/java/org/eclipse/edc/identithub/verifiablecredential/CredentialStatusCheckServiceImpl.java @@ -27,6 +27,7 @@ import static org.eclipse.edc.spi.result.Result.failure; import static org.eclipse.edc.spi.result.Result.success; + public class CredentialStatusCheckServiceImpl implements CredentialStatusCheckService { private static final String SUSPENSION = "suspension"; private static final String REVOCATION = "revocation"; @@ -53,12 +54,13 @@ public Result checkStatus(VerifiableCredentialResource resource) { } try { + if (isRevoked(resource)) { + return success(VcStatus.REVOKED); //irreversible, cannot be overwritten + } if (isSuspended(resource)) { targetStatus = VcStatus.SUSPENDED; } - if (isRevoked(resource)) { - targetStatus = VcStatus.REVOKED; - } + } catch (EdcException ex) { return failure(ex.getMessage()); } diff --git a/extensions/common/credential-watchdog/src/main/java/org/eclipse/edc/identityhub/common/credentialwatchdog/CredentialWatchdog.java b/extensions/common/credential-watchdog/src/main/java/org/eclipse/edc/identityhub/common/credentialwatchdog/CredentialWatchdog.java index 6ebd7f76f..4ef3d7b90 100644 --- a/extensions/common/credential-watchdog/src/main/java/org/eclipse/edc/identityhub/common/credentialwatchdog/CredentialWatchdog.java +++ b/extensions/common/credential-watchdog/src/main/java/org/eclipse/edc/identityhub/common/credentialwatchdog/CredentialWatchdog.java @@ -34,9 +34,11 @@ * and update their status. Every execution (fetch-all - check-each - update-each) will run in a transaction. *

* Note that this will materialize all credentials into memory at once, as the general assumption is that typically, wallets don't - * store an enormous amount of credentials. + * store an enormous amount of credentials. To mitigate this, the watchdog only considers credentials in states {@link VcStatus#ISSUED}, + * {@link VcStatus#SUSPENDED} and {@link VcStatus#NOT_YET_VALID}, c.f. {@link CredentialWatchdog#ALLOWED_STATES}. + * *

- * Note also, that a credential's status will only be updated if it did in fact change, to avoid unnecessary database interactions. + * Note also, that a credentials status will only be updated if it did in fact change, to avoid unnecessary database interactions. */ public class CredentialWatchdog implements Runnable { //todo: add more states once we have to check issuance status @@ -63,14 +65,14 @@ public void run() { monitor.debug("checking %d credentials".formatted(allCredentials.size())); allCredentials.forEach(credential -> { - var status = credentialStatusCheckService.checkStatus(credential) + var newStatus = credentialStatusCheckService.checkStatus(credential) .orElse(f -> { monitor.warning("Error determining status for credential '%s': %s. Will move to the ERROR state.".formatted(credential.getId(), f.getFailureDetail())); return VcStatus.ERROR; }); - var changed = credential.getState() != status.code(); + var changed = credential.getState() != newStatus.code(); if (changed) { - credential.setCredentialStatus(status); + credential.setCredentialStatus(newStatus); credentialStore.update(credential); } }); diff --git a/spi/verifiable-credential-spi/src/main/java/org/eclipse/edc/identityhub/spi/verifiablecredentials/CredentialStatusCheckService.java b/spi/verifiable-credential-spi/src/main/java/org/eclipse/edc/identityhub/spi/verifiablecredentials/CredentialStatusCheckService.java index 8caf4ba71..5f793dc53 100644 --- a/spi/verifiable-credential-spi/src/main/java/org/eclipse/edc/identityhub/spi/verifiablecredentials/CredentialStatusCheckService.java +++ b/spi/verifiable-credential-spi/src/main/java/org/eclipse/edc/identityhub/spi/verifiablecredentials/CredentialStatusCheckService.java @@ -18,7 +18,20 @@ import org.eclipse.edc.identityhub.spi.verifiablecredentials.model.VerifiableCredentialResource; import org.eclipse.edc.spi.result.Result; +/** + * Checks if a {@link VerifiableCredentialResource} is revoked, expired, not-yet-valid or suspended. Once a credential is {@link VcStatus#EXPIRED}, + * it can never transition to another status. + * {@link VcStatus#EXPIRED} and {@link VcStatus#REVOKED} are non-reversible (terminal) states. Once reversible + * states ({@link VcStatus#NOT_YET_VALID} and {@link VcStatus#SUSPENDED}) are cleared, the default state {@link VcStatus#ISSUED} is assumed. + */ @FunctionalInterface public interface CredentialStatusCheckService { + /** + * Checks the current status of a {@link VerifiableCredentialResource}. Note that the status returned by this method + * is not an indicator of a state transition, so client code should check for a change. + * + * @param resource The resource to check. {@link VerifiableCredentialResource#getVerifiableCredential()} cannot be null. + * @return A successful result with the new status, or a failure if a check (e.g. a remote call) failed. + */ Result checkStatus(VerifiableCredentialResource resource); }