Repository: TBD54566975/ssi-service (go)

Issue:
[Bug] ID includes `localhost`
**Describe the bug**
When using the Credential API, the service returns the `id` field with `http://localhost`

**To Reproduce**
1. Create a credential with the service.
2. Observe the `id` field in the response. It should start with `localhost`
3. Call GET to get credentials from the service.
4. Observe the `id` field in the response. It should start with `localhost`

**Expected behavior**
The `id` field should only return the credential ID

**Supporting Material**
<img width="970" alt="Screenshot 2023-06-15 at 3 22 18 AM" src="https://github.com/TBD54566975/ssi-service/assets/102400653/61a8fb4b-057c-454b-9d87-e71c05bedbf8">


Pull request:
Distinguish between container.ID and container.Credential.ID
# Overview
Fixed #544 by distinguishing between `credentialResponse.ID` and `credentialResponse.Credential.ID`.

# Description

This PR makes explicit the distinction between the two elements, which previously caused confusion. Documentation was also updated. 

# How Has This Been Tested?
All tests were updated with simple renaming.


Patch:
diff --git a/doc/swagger.yaml b/doc/swagger.yaml
index fc467e6..a3e4046 100644
--- a/doc/swagger.yaml
+++ b/doc/swagger.yaml
@@ -547,8 +547,8 @@ definitions:
         type: string
       id:
         description: |-
-          Credential ID. This is the same value as the id within the secured credential. It is typically a URL that can be
-          dereferenced. For example, `https://ssi-service.com/v1/credentials/48958871-6a6d-4a25-889f-88c9c6835780`.
+          UUID assigned by the ssi-service. For example, 48958871-6a6d-4a25-889f-88c9c6835780. The `credential.id`
+          value will be a URL that can be dereferenced, which includes this ID.
         type: string
       issuerKid:
         description: The KID of the private key used to sign `credentialJwt`.
@@ -1042,8 +1042,8 @@ definitions:
         type: string
       id:
         description: |-
-          Credential ID. This is the same value as the id within the secured credential. It is typically a URL that can be
-          dereferenced. For example, `https://ssi-service.com/v1/credentials/48958871-6a6d-4a25-889f-88c9c6835780`.
+          UUID assigned by the ssi-service. For example, 48958871-6a6d-4a25-889f-88c9c6835780. The `credential.id`
+          value will be a URL that can be dereferenced, which includes this ID.
         type: string
       issuerKid:
         description: The KID of the private key used to sign `credentialJwt`.
@@ -1371,8 +1371,8 @@ definitions:
         type: string
       id:
         description: |-
-          Credential ID. This is the same value as the id within the secured credential. It is typically a URL that can be
-          dereferenced. For example, `https://ssi-service.com/v1/credentials/48958871-6a6d-4a25-889f-88c9c6835780`.
+          UUID assigned by the ssi-service. For example, 48958871-6a6d-4a25-889f-88c9c6835780. The `credential.id`
+          value will be a URL that can be dereferenced, which includes this ID.
         type: string
       issuerKid:
         description: The KID of the private key used to sign `credentialJwt`.
diff --git a/internal/credential/model.go b/internal/credential/model.go
index 64770d9..bcc310b 100644
--- a/internal/credential/model.go
+++ b/internal/credential/model.go
@@ -7,15 +7,14 @@ import (
 	"github.com/TBD54566975/ssi-sdk/credential"
 	"github.com/goccy/go-json"
 	"github.com/pkg/errors"
-
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 )
 
 // Container acts as an abstraction over both possible credential representations
 // JWT representations are parsed upon container creation, while the original JWT is maintained
 type Container struct {
-	// Credential ID. This is the same value as the id within the secured credential. It is typically a URL that can be
-	// dereferenced. For example, `https://ssi-service.com/v1/credentials/48958871-6a6d-4a25-889f-88c9c6835780`.
+	// UUID assigned by the ssi-service. For example, 48958871-6a6d-4a25-889f-88c9c6835780. The `credential.id`
+	// value will be a URL that can be dereferenced, which includes this ID.
 	ID string `json:"id,omitempty"`
 
 	// The KID of the private key used to sign `credentialJwt`.
@@ -41,7 +40,7 @@ func (c Container) JWTString() string {
 }
 
 func (c Container) IsValid() bool {
-	return c.ID != "" && (c.HasDataIntegrityCredential() || c.HasJWTCredential())
+	return c.Credential != nil && c.Credential.ID != "" && (c.HasDataIntegrityCredential() || c.HasJWTCredential())
 }
 
 func (c Container) HasSignedCredential() bool {
@@ -63,7 +62,6 @@ func NewCredentialContainerFromJWT(credentialJWT string) (*Container, error) {
 		return nil, errors.Wrap(err, "could not parse credential from JWT")
 	}
 	return &Container{
-		ID:            cred.ID,
 		Credential:    cred,
 		CredentialJWT: keyaccess.JWTPtr(credentialJWT),
 	}, nil
@@ -77,7 +75,6 @@ func NewCredentialContainerFromMap(credMap map[string]any) (*Container, error) {
 		return nil, errors.Wrap(err, "could not parse credential from map")
 	}
 	container := Container{
-		ID:         cred.ID,
 		Credential: cred,
 	}
 	if container.HasDataIntegrityCredential() {
diff --git a/pkg/service/credential/service.go b/pkg/service/credential/service.go
index 6206454..3cbb012 100644
--- a/pkg/service/credential/service.go
+++ b/pkg/service/credential/service.go
@@ -13,7 +13,6 @@ import (
 	"github.com/google/uuid"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
-
 	"github.com/tbd54566975/ssi-service/config"
 	credint "github.com/tbd54566975/ssi-service/internal/credential"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
@@ -228,7 +227,7 @@ func (s Service) createCredential(ctx context.Context, request CreateCredentialR
 	}
 
 	container := credint.Container{
-		ID:            cred.ID,
+		ID:            credentialID,
 		IssuerKID:     request.IssuerKID,
 		Credential:    cred,
 		CredentialJWT: credJWT,
@@ -237,7 +236,6 @@ func (s Service) createCredential(ctx context.Context, request CreateCredentialR
 	}
 
 	credentialStorageRequest := StoreCredentialRequest{
-		ID:        credentialID,
 		Container: container,
 	}
 	if err = s.storage.StoreCredentialTx(ctx, tx, credentialStorageRequest); err != nil {
@@ -329,7 +327,7 @@ func (s Service) GetCredential(ctx context.Context, request GetCredentialRequest
 	}
 	response := GetCredentialResponse{
 		credint.Container{
-			ID:            gotCred.CredentialID,
+			ID:            gotCred.LocalCredentialID,
 			Credential:    gotCred.Credential,
 			CredentialJWT: gotCred.CredentialJWT,
 			Revoked:       gotCred.Revoked,
@@ -350,7 +348,7 @@ func (s Service) ListCredentials(ctx context.Context) (*ListCredentialsResponse,
 	creds := make([]credint.Container, 0, len(gotCreds))
 	for _, cred := range gotCreds {
 		container := credint.Container{
-			ID:            cred.CredentialID,
+			ID:            cred.LocalCredentialID,
 			Credential:    cred.Credential,
 			CredentialJWT: cred.CredentialJWT,
 			Revoked:       cred.Revoked,
@@ -374,7 +372,7 @@ func (s Service) ListCredentialsByIssuer(ctx context.Context, request ListCreden
 	creds := make([]credint.Container, 0, len(gotCreds))
 	for _, cred := range gotCreds {
 		container := credint.Container{
-			ID:            cred.CredentialID,
+			ID:            cred.LocalCredentialID,
 			Credential:    cred.Credential,
 			CredentialJWT: cred.CredentialJWT,
 			Revoked:       cred.Revoked,
@@ -398,7 +396,7 @@ func (s Service) ListCredentialsBySubject(ctx context.Context, request ListCrede
 	creds := make([]credint.Container, 0, len(gotCreds))
 	for _, cred := range gotCreds {
 		container := credint.Container{
-			ID:            cred.CredentialID,
+			ID:            cred.LocalCredentialID,
 			Credential:    cred.Credential,
 			CredentialJWT: cred.CredentialJWT,
 			Revoked:       cred.Revoked,
@@ -421,7 +419,7 @@ func (s Service) ListCredentialsBySchema(ctx context.Context, request ListCreden
 	creds := make([]credint.Container, 0, len(gotCreds))
 	for _, cred := range gotCreds {
 		container := credint.Container{
-			ID:            cred.CredentialID,
+			ID:            cred.LocalCredentialID,
 			Credential:    cred.Credential,
 			CredentialJWT: cred.CredentialJWT,
 			Revoked:       cred.Revoked,
@@ -462,7 +460,7 @@ func (s Service) GetCredentialStatusList(ctx context.Context, request GetCredent
 	}
 	response := GetCredentialStatusListResponse{
 		credint.Container{
-			ID:            gotCred.CredentialID,
+			ID:            gotCred.LocalCredentialID,
 			Credential:    gotCred.Credential,
 			CredentialJWT: gotCred.CredentialJWT,
 			Revoked:       false, // Credential Status List cannot be revoked
@@ -479,7 +477,7 @@ func (s Service) UpdateCredentialStatus(ctx context.Context, request UpdateCrede
 	}
 
 	if gotCred.Credential.CredentialStatus == nil {
-		return nil, sdkutil.LoggingNewErrorf("credential %q has no credentialStatus field", gotCred.CredentialID)
+		return nil, sdkutil.LoggingNewErrorf("credential %q has no credentialStatus field", gotCred.LocalCredentialID)
 	}
 
 	statusPurpose := gotCred.Credential.CredentialStatus.(map[string]any)["statusPurpose"].(string)
@@ -556,7 +554,7 @@ func (s Service) updateCredentialStatusBusinessLogic(ctx context.Context, tx sto
 func updateCredentialStatus(ctx context.Context, tx storage.Tx, s Service, gotCred *StoredCredential, request UpdateCredentialStatusRequest, slcMetadata StatusListCredentialMetadata) (*credint.Container, error) {
 	// store the credential with updated status
 	container := credint.Container{
-		ID:            gotCred.Key,
+		ID:            gotCred.LocalCredentialID,
 		IssuerKID:     gotCred.IssuerKID,
 		Credential:    gotCred.Credential,
 		CredentialJWT: gotCred.CredentialJWT,
@@ -565,7 +563,6 @@ func updateCredentialStatus(ctx context.Context, tx storage.Tx, s Service, gotCr
 	}
 
 	storageRequest := StoreCredentialRequest{
-		ID:        request.ID,
 		Container: container,
 	}
 
@@ -603,7 +600,7 @@ func updateCredentialStatus(ctx context.Context, tx storage.Tx, s Service, gotCr
 		}
 	}
 
-	// add current one since it has not been saved yet and wont be available in the creds array
+	// add current one since it has not been saved yet and won't be available in the creds array
 	if request.Revoked == true || request.Suspended == true {
 		revokedOrSuspendedStatusCreds = append(revokedOrSuspendedStatusCreds, *gotCred.Credential)
 	}
@@ -628,14 +625,13 @@ func updateCredentialStatus(ctx context.Context, tx storage.Tx, s Service, gotCr
 
 	// store the status list credential
 	statusListContainer := credint.Container{
-		ID:            generatedStatusListCredential.ID,
+		ID:            statusListCredentialID,
 		IssuerKID:     gotCred.IssuerKID,
 		Credential:    generatedStatusListCredential,
 		CredentialJWT: statusListCredJWT,
 	}
 
 	storageRequest = StoreCredentialRequest{
-		ID:        statusListCredentialID,
 		Container: statusListContainer,
 	}
 
diff --git a/pkg/service/credential/status.go b/pkg/service/credential/status.go
index 720b3ff..77a9cf0 100644
--- a/pkg/service/credential/status.go
+++ b/pkg/service/credential/status.go
@@ -80,14 +80,13 @@ func (s Service) createStatusListCredential(ctx context.Context, tx storage.Tx,
 	}
 
 	statusListContainer := credint.Container{
-		ID:            generatedStatusListCredential.ID,
+		ID:            statusListID,
 		IssuerKID:     issuerKID,
 		Credential:    generatedStatusListCredential,
 		CredentialJWT: statusListCredJWT,
 	}
 
 	statusListStorageRequest := StoreCredentialRequest{
-		ID:        statusListID,
 		Container: statusListContainer,
 	}
 
diff --git a/pkg/service/credential/storage.go b/pkg/service/credential/storage.go
index ecd70cb..8749887 100644
--- a/pkg/service/credential/storage.go
+++ b/pkg/service/credential/storage.go
@@ -4,7 +4,6 @@ import (
 	"context"
 	"fmt"
 	"math/rand"
-	"regexp"
 	"strings"
 
 	"github.com/TBD54566975/ssi-sdk/credential"
@@ -21,8 +20,6 @@ import (
 )
 
 type StoreCredentialRequest struct {
-	// Unique ID associated to this credential. Should be a UUID.
-	ID string
 	credint.Container
 }
 
@@ -30,8 +27,8 @@ type StoredCredential struct {
 	// This Key is generated by the storage module upon first write.
 	Key string `json:"key"`
 
-	// This is the same as `credential.id`. Typically, a URL that can be dereferenced.
-	CredentialID string `json:"credentialId"`
+	// ID of the credential that identifies it within ssi service.
+	LocalCredentialID string `json:"LocalCredentialId"`
 
 	// only one of these fields should be present
 	Credential    *credential.VerifiableCredential `json:"credential,omitempty"`
@@ -216,7 +213,7 @@ func (cs *Storage) StoreStatusListCredentialTx(ctx context.Context, tx storage.T
 
 	storedCredBytes, err := json.Marshal(storedCredential)
 	if err != nil {
-		return sdkutil.LoggingErrorMsgf(err, "could not store request: %s", storedCredential.CredentialID)
+		return sdkutil.LoggingErrorMsgf(err, "could not store request: %s", storedCredential.LocalCredentialID)
 	}
 
 	return tx.Write(ctx, slcMetadata.statusListCredentialWatchKey.Namespace, slcMetadata.statusListCredentialWatchKey.Key, storedCredBytes)
@@ -239,13 +236,14 @@ func (cs *Storage) GetStatusListCredential(ctx context.Context, id string) (*Sto
 		if err = json.Unmarshal(credBytes, &cred); err != nil {
 			logrus.WithError(err).Errorf("unmarshalling credential with key: %s", key)
 		}
-		if ExtractID(cred.CredentialID) == id {
+		if cred.LocalCredentialID == id {
 			storedCreds = append(storedCreds, cred)
 		}
 	}
 
 	if len(storedCreds) == 0 {
 		logrus.Infof("no credentials able to be retrieved for id: %s", id)
+		return nil, errors.Errorf("status list credential not found for id: %s", id)
 	}
 
 	if len(storedCreds) > 1 {
@@ -268,7 +266,7 @@ func (cs *Storage) getStoreCredentialWriteContext(request StoreCredentialRequest
 
 	storedCredBytes, err := json.Marshal(storedCredential)
 	if err != nil {
-		return nil, sdkutil.LoggingErrorMsgf(err, "could not store request: %s", storedCredential.CredentialID)
+		return nil, sdkutil.LoggingErrorMsgf(err, "could not store request: %s", storedCredential.LocalCredentialID)
 	}
 
 	wc := WriteContext{
@@ -294,8 +292,7 @@ func buildStoredCredential(request StoreCredentialRequest) (*StoredCredential, e
 		cred = parsedCred
 	}
 
-	credID := request.ID
-	credURI := cred.ID
+	credID := request.Container.ID
 	// Note: we assume the issuer is always a string for now
 	issuer := cred.Issuer.(string)
 	subject := cred.CredentialSubject.GetID()
@@ -306,17 +303,17 @@ func buildStoredCredential(request StoreCredentialRequest) (*StoredCredential, e
 		schema = cred.CredentialSchema.ID
 	}
 	return &StoredCredential{
-		Key:           createPrefixKey(credID, issuer, subject, schema),
-		CredentialID:  credURI,
-		Credential:    cred,
-		CredentialJWT: request.CredentialJWT,
-		Issuer:        issuer,
-		IssuerKID:     request.IssuerKID,
-		Subject:       subject,
-		Schema:        schema,
-		IssuanceDate:  cred.IssuanceDate,
-		Revoked:       request.Revoked,
-		Suspended:     request.Suspended,
+		Key:               createPrefixKey(credID, issuer, subject, schema),
+		LocalCredentialID: credID,
+		Credential:        cred,
+		CredentialJWT:     request.CredentialJWT,
+		Issuer:            issuer,
+		IssuerKID:         request.IssuerKID,
+		Subject:           subject,
+		Schema:            schema,
+		IssuanceDate:      cred.IssuanceDate,
+		Revoked:           request.Revoked,
+		Suspended:         request.Suspended,
 	}, nil
 }
 
@@ -673,20 +670,6 @@ func (cs *Storage) GetStatusListCredentialKeyData(ctx context.Context, issuer st
 	return &storedStatusListCreds[0], nil
 }
 
-// ExtractID is a function that takes a string input and returns a string that contains an ID extracted from the input string.
-// The ID is extracted by searching for a string that matches the regular expression, which matches a forward slash followed
-// by one or more characters that are either letters (upper or lower case), digits (0-9), or hyphens (-), at the end of the input string.
-// If a match is found, the function returns the matched string with the forward slash removed (i.e., everything after the forward slash).
-// If no match is found, an empty string is returned.
-func ExtractID(input string) string {
-	re := regexp.MustCompile(`/[a-zA-Z0-9-]+$`)
-	match := re.FindString(input)
-	if len(match) > 0 {
-		return match[1:]
-	}
-	return ""
-}
-
 func getStatusListKey(issuer, schema, statusPurpose string) string {
 	return strings.Join([]string{"is:" + issuer, "sc:" + schema, "sp:" + statusPurpose}, "-")
 }
diff --git a/pkg/service/manifest/response.go b/pkg/service/manifest/response.go
index 7d04d78..bb0b332 100644
--- a/pkg/service/manifest/response.go
+++ b/pkg/service/manifest/response.go
@@ -148,7 +148,7 @@ func (s Service) fulfillmentCredentialResponse(ctx context.Context, responseBuil
 			format = string(exchange.JWTVC)
 		}
 		descriptors = append(descriptors, exchange.SubmissionDescriptor{
-			ID:     c.ID,
+			ID:     c.Credential.ID,
 			Format: format,
 			Path:   fmt.Sprintf("$.verifiableCredentials[%d]", i),
 		})
@@ -167,7 +167,7 @@ func (s Service) fulfillmentCredentialResponse(ctx context.Context, responseBuil
 
 func (s Service) applyIssuanceTemplate(credentialRequest credential.CreateCredentialRequest, template issuance.CredentialTemplate,
 	applicationJSON map[string]any, credManifest manifest.CredentialManifest, submission exchange.PresentationSubmission) (*credential.CreateCredentialRequest, error) {
-	cred, err := getCredentialForInputDescriptor(applicationJSON, template.CredentialInputDescriptor, credManifest, submission)
+	credentialForInputDescriptor, err := getCredentialForInputDescriptor(applicationJSON, template.CredentialInputDescriptor, credManifest, submission)
 	if err != nil {
 		return nil, err
 	}
@@ -175,7 +175,7 @@ func (s Service) applyIssuanceTemplate(credentialRequest credential.CreateCreden
 		claimValue := v
 		if vs, ok := v.(string); ok {
 			if strings.HasPrefix(vs, "$") {
-				claimValue, err = jsonpath.JsonPathLookup(cred, vs)
+				claimValue, err = jsonpath.JsonPathLookup(credentialForInputDescriptor, vs)
 				if err != nil {
 					return nil, errors.Wrapf(err, "looking up json path \"%s\" for key=\"%s\"", vs, k)
 				}


Test patch:
diff --git a/pkg/server/router/credential_test.go b/pkg/server/router/credential_test.go
index 14a4173..75e4d77 100644
--- a/pkg/server/router/credential_test.go
+++ b/pkg/server/router/credential_test.go
@@ -117,7 +117,8 @@ func TestCredentialRouter(t *testing.T) {
 				assert.NoError(tt, err)
 				assert.Len(tt, bySubject.Credentials, 1)
 
-				assert.Equal(tt, cred.ID, bySubject.Credentials[0].ID)
+				assert.Equal(tt, createdCred.ID, bySubject.Credentials[0].ID)
+				assert.Equal(tt, cred.ID, bySubject.Credentials[0].Credential.ID)
 				assert.Equal(tt, cred.CredentialSubject[credsdk.VerifiableCredentialIDProperty], bySubject.Credentials[0].Credential.CredentialSubject[credsdk.VerifiableCredentialIDProperty])
 
 				// get by issuer
@@ -171,14 +172,16 @@ func TestCredentialRouter(t *testing.T) {
 				assert.NoError(tt, err)
 				assert.Len(tt, bySchema.Credentials, 1)
 
-				assert.Equal(tt, cred.ID, bySchema.Credentials[0].ID)
+				assert.Equal(tt, createdCred.ID, bySchema.Credentials[0].ID)
+				assert.Equal(tt, cred.ID, bySchema.Credentials[0].Credential.ID)
 				assert.EqualValues(tt, cred.CredentialSchema, bySchema.Credentials[0].Credential.CredentialSchema)
 
 				bySubject, err = credService.ListCredentialsBySubject(context.Background(), credential.ListCredentialBySubjectRequest{Subject: subject})
 				assert.NoError(tt, err)
 				assert.Len(tt, bySubject.Credentials, 1)
 
-				assert.Equal(tt, cred.ID, bySubject.Credentials[0].ID)
+				assert.Equal(tt, createdCred.ID, bySubject.Credentials[0].ID)
+				assert.Equal(tt, cred.ID, bySubject.Credentials[0].Credential.ID)
 				assert.Equal(tt, cred.CredentialSubject[credsdk.VerifiableCredentialIDProperty], bySubject.Credentials[0].Credential.CredentialSubject[credsdk.VerifiableCredentialIDProperty])
 
 				// delete a cred that doesn't exist (no error since idempotent)
@@ -224,7 +227,7 @@ func TestCredentialRouter(t *testing.T) {
 				issuer := issuerDID.DID.ID
 				subject := "did:test:345"
 
-				createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
+				createdCredResp, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
 					Issuer:    issuer,
 					IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
 					Subject:   subject,
@@ -237,17 +240,17 @@ func TestCredentialRouter(t *testing.T) {
 				})
 
 				assert.NoError(tt, err)
-				assert.NotEmpty(tt, createdCred)
-				assert.NotEmpty(tt, createdCred.CredentialJWT)
+				assert.NotEmpty(tt, createdCredResp)
+				assert.NotEmpty(tt, createdCredResp.CredentialJWT)
 
-				credStatusMap, ok := createdCred.Credential.CredentialStatus.(map[string]any)
+				credStatusMap, ok := createdCredResp.Credential.CredentialStatus.(map[string]any)
 				assert.True(tt, ok)
 
-				assert.Equal(tt, credStatusMap["id"], createdCred.ID+"/status")
+				assert.Equal(tt, credStatusMap["id"], createdCredResp.Credential.ID+"/status")
 				assert.Contains(tt, credStatusMap["statusListCredential"], "v1/credentials/status")
 				assert.NotEmpty(tt, credStatusMap["statusListIndex"])
 
-				createdCredTwo, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
+				createdCredRespTwo, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
 					Issuer:    issuer,
 					IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
 					Subject:   subject,
@@ -260,13 +263,13 @@ func TestCredentialRouter(t *testing.T) {
 				})
 
 				assert.NoError(tt, err)
-				assert.NotEmpty(tt, createdCredTwo)
-				assert.NotEmpty(tt, createdCredTwo.CredentialJWT)
+				assert.NotEmpty(tt, createdCredRespTwo)
+				assert.NotEmpty(tt, createdCredRespTwo.CredentialJWT)
 
-				credStatusMapTwo, ok := createdCredTwo.Credential.CredentialStatus.(map[string]any)
+				credStatusMapTwo, ok := createdCredRespTwo.Credential.CredentialStatus.(map[string]any)
 				assert.True(tt, ok)
 
-				assert.Equal(tt, credStatusMapTwo["id"], createdCredTwo.ID+"/status")
+				assert.Equal(tt, credStatusMapTwo["id"], createdCredRespTwo.Credential.ID+"/status")
 				assert.Contains(tt, credStatusMapTwo["statusListCredential"], "v1/credentials/status")
 				assert.NotEmpty(tt, credStatusMapTwo["statusListIndex"])
 
@@ -277,7 +280,7 @@ func TestCredentialRouter(t *testing.T) {
 				assert.NoError(tt, err)
 				assert.NotEmpty(tt, createdSchemaTwo)
 
-				createdCredThree, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
+				createdCredRespThree, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
 					Issuer:    issuer,
 					IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
 					Subject:   subject,
@@ -290,13 +293,13 @@ func TestCredentialRouter(t *testing.T) {
 				})
 
 				assert.NoError(tt, err)
-				assert.NotEmpty(tt, createdCredThree)
-				assert.NotEmpty(tt, createdCredThree.CredentialJWT)
+				assert.NotEmpty(tt, createdCredRespThree)
+				assert.NotEmpty(tt, createdCredRespThree.CredentialJWT)
 
-				credStatusMapThree, ok := createdCredThree.Credential.CredentialStatus.(map[string]any)
+				credStatusMapThree, ok := createdCredRespThree.Credential.CredentialStatus.(map[string]any)
 				assert.True(tt, ok)
 
-				assert.Contains(tt, credStatusMapThree["id"], createdCredThree.ID)
+				assert.Contains(tt, credStatusMapThree["id"], createdCredRespThree.Credential.ID)
 				assert.Contains(tt, credStatusMapThree["statusListCredential"], "v1/credentials/status")
 				assert.NotEmpty(tt, credStatusMapThree["statusListIndex"])
 
@@ -329,7 +332,7 @@ func TestCredentialRouter(t *testing.T) {
 				issuer := issuerDID.DID.ID
 				subject := "did:test:345"
 
-				createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
+				createdCredResp, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
 					Issuer:    issuer,
 					IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
 					Subject:   subject,
@@ -341,17 +344,17 @@ func TestCredentialRouter(t *testing.T) {
 				})
 
 				assert.NoError(tt, err)
-				assert.NotEmpty(tt, createdCred)
-				assert.NotEmpty(tt, createdCred.CredentialJWT)
+				assert.NotEmpty(tt, createdCredResp)
+				assert.NotEmpty(tt, createdCredResp.CredentialJWT)
 
-				credStatusMap, ok := createdCred.Credential.CredentialStatus.(map[string]any)
+				credStatusMap, ok := createdCredResp.Credential.CredentialStatus.(map[string]any)
 				assert.True(tt, ok)
 
-				assert.Contains(tt, credStatusMap["id"], fmt.Sprintf("%s/status", createdCred.ID))
+				assert.Contains(tt, credStatusMap["id"], fmt.Sprintf("%s/status", createdCredResp.Credential.ID))
 				assert.Contains(tt, credStatusMap["statusListCredential"], "v1/credentials/status")
 				assert.NotEmpty(tt, credStatusMap["statusListIndex"])
 
-				createdCredTwo, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
+				createdCredRespTwo, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
 					Issuer:    issuer,
 					IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
 					Subject:   subject,
@@ -363,13 +366,13 @@ func TestCredentialRouter(t *testing.T) {
 				})
 
 				assert.NoError(tt, err)
-				assert.NotEmpty(tt, createdCredTwo)
-				assert.NotEmpty(tt, createdCredTwo.CredentialJWT)
+				assert.NotEmpty(tt, createdCredRespTwo)
+				assert.NotEmpty(tt, createdCredRespTwo.CredentialJWT)
 
-				credStatusMapTwo, ok := createdCredTwo.Credential.CredentialStatus.(map[string]any)
+				credStatusMapTwo, ok := createdCredRespTwo.Credential.CredentialStatus.(map[string]any)
 				assert.True(tt, ok)
 
-				assert.Contains(tt, credStatusMapTwo["id"], fmt.Sprintf("%s/status", createdCredTwo.ID))
+				assert.Contains(tt, credStatusMapTwo["id"], fmt.Sprintf("%s/status", createdCredRespTwo.Credential.ID))
 				assert.Contains(tt, credStatusMapTwo["statusListCredential"], "v1/credentials/status")
 				assert.NotEmpty(tt, credStatusMapTwo["statusListIndex"])
 
@@ -381,7 +384,7 @@ func TestCredentialRouter(t *testing.T) {
 				assert.NoError(tt, err)
 				assert.NotEmpty(tt, createdSchema)
 
-				createdCredThree, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
+				createdCredRespThree, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
 					Issuer:    issuer,
 					IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
 					Subject:   subject,
@@ -394,13 +397,13 @@ func TestCredentialRouter(t *testing.T) {
 				})
 
 				assert.NoError(tt, err)
-				assert.NotEmpty(tt, createdCredThree)
-				assert.NotEmpty(tt, createdCredThree.CredentialJWT)
+				assert.NotEmpty(tt, createdCredRespThree)
+				assert.NotEmpty(tt, createdCredRespThree.CredentialJWT)
 
-				credStatusMapThree, ok := createdCredThree.Credential.CredentialStatus.(map[string]any)
+				credStatusMapThree, ok := createdCredRespThree.Credential.CredentialStatus.(map[string]any)
 				assert.True(tt, ok)
 
-				assert.Contains(tt, credStatusMapThree["id"], fmt.Sprintf("%s/status", createdCredThree.ID))
+				assert.Contains(tt, credStatusMapThree["id"], fmt.Sprintf("%s/status", createdCredRespThree.Credential.ID))
 				assert.Contains(tt, credStatusMapThree["statusListCredential"], "v1/credentials/status")
 				assert.NotEmpty(tt, credStatusMapThree["statusListIndex"])
 
@@ -448,7 +451,7 @@ func TestCredentialRouter(t *testing.T) {
 				})
 				assert.NoError(tt, err)
 
-				_, err = credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: idFromURI(nonRevokableCred.ID), Revoked: true})
+				_, err = credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: nonRevokableCred.ID, Revoked: true})
 				assert.ErrorContains(tt, err, "has no credentialStatus field")
 
 				createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
@@ -474,11 +477,11 @@ func TestCredentialRouter(t *testing.T) {
 				err = json.Unmarshal(statusBytes, &statusEntry)
 				assert.NoError(tt, err)
 
-				assert.Contains(tt, statusEntry.ID, fmt.Sprintf("%s/status", createdCred.ID))
+				assert.Contains(tt, statusEntry.ID, fmt.Sprintf("%s/status", createdCred.Credential.ID))
 				assert.Contains(tt, statusEntry.StatusListCredential, "http://localhost:1234/v1/credentials/status")
 				assert.NotEmpty(tt, statusEntry.StatusListIndex)
 
-				credStatus, err := credService.GetCredentialStatus(context.Background(), credential.GetCredentialStatusRequest{ID: idFromURI(createdCred.ID)})
+				credStatus, err := credService.GetCredentialStatus(context.Background(), credential.GetCredentialStatusRequest{ID: createdCred.ID})
 				assert.NoError(tt, err)
 				assert.Equal(tt, credStatus.Revoked, false)
 
@@ -501,15 +504,15 @@ func TestCredentialRouter(t *testing.T) {
 				assert.NoError(tt, err)
 				assert.False(tt, valid)
 
-				updatedStatus, err := credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: idFromURI(createdCred.ID), Revoked: true})
+				updatedStatus, err := credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: createdCred.ID, Revoked: true})
 				assert.NoError(tt, err)
 				assert.Equal(tt, updatedStatus.Revoked, true)
 
-				updatedCred, err := credService.GetCredential(context.Background(), credential.GetCredentialRequest{ID: idFromURI(createdCred.ID)})
+				updatedCred, err := credService.GetCredential(context.Background(), credential.GetCredentialRequest{ID: createdCred.ID})
 				assert.NoError(tt, err)
 				assert.Equal(tt, updatedCred.Revoked, true)
 
-				credStatusListAfterRevoke, err := credService.GetCredentialStatusList(context.Background(), credential.GetCredentialStatusListRequest{ID: idFromURI(credStatusListID)})
+				credStatusListAfterRevoke, err := credService.GetCredentialStatusList(context.Background(), credential.GetCredentialStatusListRequest{ID: credStatusListID})
 				assert.NoError(tt, err)
 				assert.Equal(tt, credStatusListAfterRevoke.Credential.ID, statusEntry.StatusListCredential)
 
@@ -568,7 +571,7 @@ func TestCredentialRouter(t *testing.T) {
 				})
 				assert.NoError(tt, err)
 
-				_, err = credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: idFromURI(nonSuspendableCred.ID), Suspended: true})
+				_, err = credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: nonSuspendableCred.ID, Suspended: true})
 				assert.ErrorContains(tt, err, "has no credentialStatus field")
 
 				createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
@@ -594,11 +597,11 @@ func TestCredentialRouter(t *testing.T) {
 				err = json.Unmarshal(statusBytes, &statusEntry)
 				assert.NoError(tt, err)
 
-				assert.Contains(tt, statusEntry.ID, fmt.Sprintf("%s/status", createdCred.ID))
+				assert.Contains(tt, statusEntry.ID, fmt.Sprintf("%s/status", createdCred.Credential.ID))
 				assert.Contains(tt, statusEntry.StatusListCredential, "http://localhost:1234/v1/credentials/status")
 				assert.NotEmpty(tt, statusEntry.StatusListIndex)
 
-				credStatus, err := credService.GetCredentialStatus(context.Background(), credential.GetCredentialStatusRequest{ID: idFromURI(createdCred.ID)})
+				credStatus, err := credService.GetCredentialStatus(context.Background(), credential.GetCredentialStatusRequest{ID: createdCred.ID})
 				assert.NoError(tt, err)
 				assert.Equal(tt, credStatus.Suspended, false)
 
@@ -621,11 +624,11 @@ func TestCredentialRouter(t *testing.T) {
 				assert.NoError(tt, err)
 				assert.False(tt, valid)
 
-				updatedStatus, err := credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: idFromURI(createdCred.ID), Suspended: true})
+				updatedStatus, err := credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: createdCred.ID, Suspended: true})
 				assert.NoError(tt, err)
 				assert.Equal(tt, updatedStatus.Suspended, true)
 
-				updatedCred, err := credService.GetCredential(context.Background(), credential.GetCredentialRequest{ID: idFromURI(createdCred.ID)})
+				updatedCred, err := credService.GetCredential(context.Background(), credential.GetCredentialRequest{ID: createdCred.ID})
 				assert.NoError(tt, err)
 				assert.Equal(tt, updatedCred.Suspended, true)
 
@@ -759,11 +762,11 @@ func TestCredentialRouter(t *testing.T) {
 				err = json.Unmarshal(statusBytes, &statusEntry)
 				assert.NoError(tt, err)
 
-				assert.Contains(tt, statusEntry.ID, fmt.Sprintf("%s/status", createdCred.ID))
+				assert.Contains(tt, statusEntry.ID, fmt.Sprintf("%s/status", createdCred.Credential.ID))
 				assert.Contains(tt, statusEntry.StatusListCredential, "http://localhost:1234/v1/credentials/status")
 				assert.NotEmpty(tt, statusEntry.StatusListIndex)
 
-				credStatus, err := credService.GetCredentialStatus(context.Background(), credential.GetCredentialStatusRequest{ID: idFromURI(createdCred.ID)})
+				credStatus, err := credService.GetCredentialStatus(context.Background(), credential.GetCredentialStatusRequest{ID: createdCred.ID})
 				assert.NoError(tt, err)
 				assert.Equal(tt, credStatus.Revoked, false)
 				assert.Equal(tt, credStatus.Suspended, false)
@@ -815,11 +818,11 @@ func TestCredentialRouter(t *testing.T) {
 				err = json.Unmarshal(statusBytes, &statusEntry)
 				assert.NoError(tt, err)
 
-				assert.Contains(tt, statusEntry.ID, fmt.Sprintf("%s/status", createdCred.ID))
+				assert.Contains(tt, statusEntry.ID, fmt.Sprintf("%s/status", createdCred.Credential.ID))
 				assert.Contains(tt, statusEntry.StatusListCredential, "http://localhost:1234/v1/credentials/status")
 				assert.NotEmpty(tt, statusEntry.StatusListIndex)
 
-				credStatus, err := credService.GetCredentialStatus(context.Background(), credential.GetCredentialStatusRequest{ID: idFromURI(createdCred.ID)})
+				credStatus, err := credService.GetCredentialStatus(context.Background(), credential.GetCredentialStatusRequest{ID: createdCred.ID})
 				assert.NoError(tt, err)
 				assert.Equal(tt, credStatus.Revoked, false)
 				assert.Equal(tt, credStatus.Suspended, false)
@@ -843,7 +846,7 @@ func TestCredentialRouter(t *testing.T) {
 				assert.NoError(tt, err)
 				assert.False(tt, valid)
 
-				updatedStatus, err := credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: idFromURI(createdCred.ID), Suspended: true})
+				updatedStatus, err := credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: createdCred.ID, Suspended: true})
 				assert.NoError(tt, err)
 				assert.Equal(tt, updatedStatus.Suspended, true)
 				assert.Equal(tt, updatedStatus.Revoked, false)
@@ -893,11 +896,11 @@ func TestCredentialRouter(t *testing.T) {
 				err = json.Unmarshal(statusBytes, &statusEntry)
 				assert.NoError(tt, err)
 
-				assert.Contains(tt, statusEntry.ID, fmt.Sprintf("%s/status", createdCred.ID))
+				assert.Contains(tt, statusEntry.ID, fmt.Sprintf("%s/status", createdCred.Credential.ID))
 				assert.Contains(tt, statusEntry.StatusListCredential, "http://localhost:1234/v1/credentials/status")
 				assert.NotEmpty(tt, statusEntry.StatusListIndex)
 
-				credStatus, err := credService.GetCredentialStatus(context.Background(), credential.GetCredentialStatusRequest{ID: idFromURI(createdCred.ID)})
+				credStatus, err := credService.GetCredentialStatus(context.Background(), credential.GetCredentialStatusRequest{ID: createdCred.ID})
 				assert.NoError(tt, err)
 				assert.Equal(tt, credStatus.Revoked, false)
 				assert.Equal(tt, credStatus.Suspended, false)
@@ -921,7 +924,7 @@ func TestCredentialRouter(t *testing.T) {
 				assert.NoError(tt, err)
 				assert.False(tt, valid)
 
-				updatedStatus, err := credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: idFromURI(createdCred.ID), Suspended: true})
+				updatedStatus, err := credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: createdCred.ID, Suspended: true})
 				assert.NoError(tt, err)
 				assert.Equal(tt, updatedStatus.Suspended, true)
 				assert.Equal(tt, updatedStatus.Revoked, false)
@@ -943,7 +946,7 @@ func TestCredentialRouter(t *testing.T) {
 
 				assert.NotEqualValues(tt, encodedListAfterSuspended, encodedList)
 
-				updatedStatus, err = credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: idFromURI(createdCred.ID), Suspended: false})
+				updatedStatus, err = credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: createdCred.ID, Suspended: false})
 				assert.NoError(tt, err)
 				assert.Equal(tt, updatedStatus.Suspended, false)
 				assert.Equal(tt, updatedStatus.Revoked, false)
@@ -990,7 +993,7 @@ func TestCredentialRouter(t *testing.T) {
 				assert.NoError(tt, err)
 				assert.NotEmpty(tt, createdCred)
 
-				updatedStatus, err := credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: idFromURI(createdCred.ID), Revoked: true, Suspended: true})
+				updatedStatus, err := credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: createdCred.ID, Revoked: true, Suspended: true})
 				assert.Nil(tt, updatedStatus)
 				assert.Error(tt, err)
 				assert.ErrorContains(tt, err, "cannot update both suspended and revoked status")
@@ -1015,7 +1018,7 @@ func TestCredentialRouter(t *testing.T) {
 				assert.NoError(tt, err)
 				assert.NotEmpty(tt, createdCred)
 
-				updatedStatus, err := credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: idFromURI(createdCred.ID), Suspended: true})
+				updatedStatus, err := credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: createdCred.ID, Suspended: true})
 				assert.Nil(tt, updatedStatus)
 				assert.Error(tt, err)
 				assert.ErrorContains(tt, err, "has a different status purpose<revocation> value than the status credential<suspension>")
diff --git a/pkg/server/router/manifest_test.go b/pkg/server/router/manifest_test.go
index 6c2c4e8..61492cc 100644
--- a/pkg/server/router/manifest_test.go
+++ b/pkg/server/router/manifest_test.go
@@ -188,7 +188,7 @@ func TestManifestRouter(t *testing.T) {
 
 					// good application request
 					containers := []credmodel.Container{{
-						ID:            createdCred.ID,
+						ID:            createdCred.Credential.ID,
 						CredentialJWT: createdCred.CredentialJWT,
 					}}
 					applicationRequest := getValidApplicationRequest(m.ID, m.PresentationDefinition.ID, m.PresentationDefinition.InputDescriptors[0].ID, containers)
diff --git a/pkg/server/server_credential_test.go b/pkg/server/server_credential_test.go
index bdfaedb..49100f3 100644
--- a/pkg/server/server_credential_test.go
+++ b/pkg/server/server_credential_test.go
@@ -302,7 +302,8 @@ func TestCredentialAPI(t *testing.T) {
 				assert.NotEmpty(tt, getCredsResp)
 				assert.Len(tt, getCredsResp.Credentials, 1)
 
-				assert.Equal(tt, resp.Credential.ID, getCredsResp.Credentials[0].ID)
+				assert.Equal(tt, resp.ID, getCredsResp.Credentials[0].ID)
+				assert.Equal(tt, resp.Credential.ID, getCredsResp.Credentials[0].Credential.ID)
 				assert.Equal(tt, resp.Credential.CredentialSchema.ID, getCredsResp.Credentials[0].Credential.CredentialSchema.ID)
 
 				// reset the http recorder
@@ -484,7 +485,8 @@ func TestCredentialAPI(t *testing.T) {
 				assert.NotEmpty(tt, getCredsResp)
 				assert.Len(tt, getCredsResp.Credentials, 1)
 
-				assert.Equal(tt, resp.Credential.ID, getCredsResp.Credentials[0].ID)
+				assert.Equal(tt, resp.ID, getCredsResp.Credentials[0].ID)
+				assert.Equal(tt, resp.Credential.ID, getCredsResp.Credentials[0].Credential.ID)
 				assert.Equal(tt, resp.Credential.CredentialSchema.ID, getCredsResp.Credentials[0].Credential.CredentialSchema.ID)
 			})
 
@@ -542,7 +544,8 @@ func TestCredentialAPI(t *testing.T) {
 				assert.NotEmpty(tt, getCredsResp)
 
 				assert.Len(tt, getCredsResp.Credentials, 1)
-				assert.Equal(tt, resp.Credential.ID, getCredsResp.Credentials[0].ID)
+				assert.Equal(tt, resp.ID, getCredsResp.Credentials[0].ID)
+				assert.Equal(tt, resp.Credential.ID, getCredsResp.Credentials[0].Credential.ID)
 			})
 
 			t.Run("Test Get Credential By Issuer", func(tt *testing.T) {
@@ -599,7 +602,8 @@ func TestCredentialAPI(t *testing.T) {
 				assert.NotEmpty(tt, getCredsResp)
 
 				assert.Len(tt, getCredsResp.Credentials, 1)
-				assert.Equal(tt, resp.Credential.ID, getCredsResp.Credentials[0].ID)
+				assert.Equal(tt, resp.ID, getCredsResp.Credentials[0].ID)
+				assert.Equal(tt, resp.Credential.ID, getCredsResp.Credentials[0].Credential.ID)
 			})
 
 			t.Run("Test Get Credential By Subject", func(tt *testing.T) {
@@ -657,7 +661,8 @@ func TestCredentialAPI(t *testing.T) {
 				assert.NotEmpty(tt, listCredentialsResponse)
 
 				assert.Len(tt, listCredentialsResponse.Credentials, 1)
-				assert.Equal(tt, createCredentialResponse.Credential.ID, listCredentialsResponse.Credentials[0].ID)
+				assert.Equal(tt, createCredentialResponse.ID, listCredentialsResponse.Credentials[0].ID)
+				assert.Equal(tt, createCredentialResponse.Credential.ID, listCredentialsResponse.Credentials[0].Credential.ID)
 				assert.Equal(tt, createCredentialResponse.Credential.CredentialSubject[credsdk.VerifiableCredentialIDProperty], listCredentialsResponse.Credentials[0].Credential.CredentialSubject[credsdk.VerifiableCredentialIDProperty])
 			})
 
diff --git a/pkg/service/credential/storage_test.go b/pkg/service/credential/storage_test.go
deleted file mode 100644
index 67c254a..0000000
--- a/pkg/service/credential/storage_test.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package credential
-
-import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-)
-
-func TestCredentialStorage(t *testing.T) {
-	t.Run("Extract UUID returns UUID", func(tt *testing.T) {
-
-		uuid := ExtractID("/v1/credentials/status/ceccb36e-a386-494a-8bf5-d86f953485dd")
-		assert.NotEmpty(tt, uuid)
-		assert.Equal(tt, uuid, "ceccb36e-a386-494a-8bf5-d86f953485dd")
-
-		uuid = ExtractID("http://localhost:1234/v1/credentials/status/ceccb36e-a386-494a-8bf5-d86f953485dd")
-		assert.NotEmpty(tt, uuid)
-		assert.Equal(tt, uuid, "ceccb36e-a386-494a-8bf5-d86f953485dd")
-
-		uuid = ExtractID("ANYTHING/ceccb36e-a386-494a-8bf5-d86f953485dd")
-		assert.NotEmpty(tt, uuid)
-		assert.Equal(tt, uuid, "ceccb36e-a386-494a-8bf5-d86f953485dd")
-
-		uuid = ExtractID("badinput")
-		assert.Empty(tt, uuid)
-	})
-}