Repository: TBD54566975/ssi-service
Pull request #229 (2022-12-20 13:27:21)

[OSE-292] SubmitApplication now returns an Operation
# Overview
A credential application needs to be reviewed (by an automated or manual process). This asynchronous nature is better suited to be a long running operation.

# Description
This is part of the changes needed to support manual and automated issuance of credentials after an application is submitted.
Some of the changes include moving files into their own packages. This was done so break dependency cycles.

# How Has This Been Tested?
This is a refactor. Tests still pass (with some slight modifications)

# Checklist

Before submitting this PR, please make sure:

- [x] I have read the CONTRIBUTING document.
- [x] My code is consistent with the rest of the project 
- [x] I have tagged the relevant reviewers and/or interested parties
- [x] I have updated the READMEs and other documentation of affected packages

## References
SIP5



Patch:
diff --git a/doc/swagger.yaml b/doc/swagger.yaml
index add0567..321517b 100644
--- a/doc/swagger.yaml
+++ b/doc/swagger.yaml
@@ -877,18 +877,6 @@ definitions:
     required:
     - applicationJwt
     type: object
-  github.com_tbd54566975_ssi-service_pkg_server_router.SubmitApplicationResponse:
-    properties:
-      credential_response:
-        $ref: '#/definitions/manifest.CredentialResponse'
-      responseJwt:
-        type: string
-      verifiableCredentials:
-        description: this is an interface type to union Data Integrity and JWT style
-          VCs
-        items: {}
-        type: array
-    type: object
   github.com_tbd54566975_ssi-service_pkg_server_router.UpdateCredentialStatusRequest:
     properties:
       revoked:
@@ -1471,18 +1459,6 @@ definitions:
     required:
     - applicationJwt
     type: object
-  pkg_server_router.SubmitApplicationResponse:
-    properties:
-      credential_response:
-        $ref: '#/definitions/manifest.CredentialResponse'
-      responseJwt:
-        type: string
-      verifiableCredentials:
-        description: this is an interface type to union Data Integrity and JWT style
-          VCs
-        items: {}
-        type: array
-    type: object
   pkg_server_router.UpdateCredentialStatusRequest:
     properties:
       revoked:
@@ -1914,7 +1890,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetDIDMethodsResponse'
+            $ref: '#/definitions/pkg_server_router.GetDIDMethodsResponse'
       summary: Get DID Methods
       tags:
       - DecentralizedIdentityAPI
@@ -1935,7 +1911,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetDIDsByMethodResponse'
+            $ref: '#/definitions/pkg_server_router.GetDIDsByMethodResponse'
         "400":
           description: Bad request
           schema:
@@ -1953,7 +1929,7 @@ paths:
         name: request
         required: true
         schema:
-          $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.CreateDIDByMethodRequest'
+          $ref: '#/definitions/pkg_server_router.CreateDIDByMethodRequest'
       - description: Method
         in: path
         name: method
@@ -1965,7 +1941,7 @@ paths:
         "201":
           description: Created
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.CreateDIDByMethodResponse'
+            $ref: '#/definitions/pkg_server_router.CreateDIDByMethodResponse'
         "400":
           description: Bad request
           schema:
@@ -1988,7 +1964,7 @@ paths:
         name: request
         required: true
         schema:
-          $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.CreateDIDByMethodRequest'
+          $ref: '#/definitions/pkg_server_router.CreateDIDByMethodRequest'
       - description: Method
         in: path
         name: method
@@ -2005,7 +1981,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetDIDByMethodResponse'
+            $ref: '#/definitions/pkg_server_router.GetDIDByMethodResponse'
         "400":
           description: Bad request
           schema:
@@ -2030,7 +2006,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.ResolveDIDResponse'
+            $ref: '#/definitions/pkg_server_router.ResolveDIDResponse'
         "400":
           description: Bad request
           schema:
@@ -2250,9 +2226,10 @@ paths:
       - application/json
       responses:
         "201":
-          description: Created
+          description: Operation with a SubmitApplicationResponse type in the `result.response`
+            field.
           schema:
-            $ref: '#/definitions/pkg_server_router.SubmitApplicationResponse'
+            $ref: '#/definitions/pkg_server_router.Operation'
         "400":
           description: Bad request
           schema:
@@ -2693,7 +2670,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetSchemasResponse'
+            $ref: '#/definitions/pkg_server_router.GetSchemasResponse'
         "500":
           description: Internal server error
           schema:
@@ -2711,14 +2688,14 @@ paths:
         name: request
         required: true
         schema:
-          $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.CreateSchemaRequest'
+          $ref: '#/definitions/pkg_server_router.CreateSchemaRequest'
       produces:
       - application/json
       responses:
         "201":
           description: Created
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.CreateSchemaResponse'
+            $ref: '#/definitions/pkg_server_router.CreateSchemaResponse'
         "400":
           description: Bad request
           schema:
@@ -2775,7 +2752,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetSchemaResponse'
+            $ref: '#/definitions/pkg_server_router.GetSchemaResponse'
         "400":
           description: Bad request
           schema:
@@ -2794,14 +2771,14 @@ paths:
         name: request
         required: true
         schema:
-          $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.VerifySchemaRequest'
+          $ref: '#/definitions/pkg_server_router.VerifySchemaRequest'
       produces:
       - application/json
       responses:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.VerifySchemaResponse'
+            $ref: '#/definitions/pkg_server_router.VerifySchemaResponse'
         "400":
           description: Bad request
           schema:
diff --git a/pkg/server/router/manifest.go b/pkg/server/router/manifest.go
index c9678d9..1056380 100644
--- a/pkg/server/router/manifest.go
+++ b/pkg/server/router/manifest.go
@@ -8,6 +8,7 @@ import (
 	"github.com/TBD54566975/ssi-sdk/credential/exchange"
 	manifestsdk "github.com/TBD54566975/ssi-sdk/credential/manifest"
 	"github.com/goccy/go-json"
+	"github.com/tbd54566975/ssi-service/pkg/service/manifest/model"
 
 	"github.com/tbd54566975/ssi-service/internal/credential"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
@@ -50,8 +51,8 @@ type CreateManifestRequest struct {
 	PresentationDefinition *exchange.PresentationDefinition `json:"presentationDefinition,omitempty" validate:"omitempty,dive"`
 }
 
-func (c CreateManifestRequest) ToServiceRequest() manifest.CreateManifestRequest {
-	return manifest.CreateManifestRequest{
+func (c CreateManifestRequest) ToServiceRequest() model.CreateManifestRequest {
+	return model.CreateManifestRequest{
 		Name:                   c.Name,
 		Description:            c.Description,
 		IssuerDID:              c.IssuerDID,
@@ -128,7 +129,7 @@ func (mr ManifestRouter) GetManifest(ctx context.Context, w http.ResponseWriter,
 		return framework.NewRequestErrorMsg(errMsg, http.StatusBadRequest)
 	}
 
-	gotManifest, err := mr.service.GetManifest(manifest.GetManifestRequest{ID: *id})
+	gotManifest, err := mr.service.GetManifest(model.GetManifestRequest{ID: *id})
 	if err != nil {
 		errMsg := fmt.Sprintf("could not get manifest with id: %s", *id)
 		logrus.WithError(err).Error(errMsg)
@@ -201,7 +202,7 @@ func (mr ManifestRouter) DeleteManifest(ctx context.Context, w http.ResponseWrit
 		return framework.NewRequestErrorMsg(errMsg, http.StatusBadRequest)
 	}
 
-	if err := mr.service.DeleteManifest(manifest.DeleteManifestRequest{ID: *id}); err != nil {
+	if err := mr.service.DeleteManifest(model.DeleteManifestRequest{ID: *id}); err != nil {
 		errMsg := fmt.Sprintf("could not delete manifest with id: %s", *id)
 		logrus.WithError(err).Error(errMsg)
 		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusInternalServerError)
@@ -222,7 +223,7 @@ const (
 	verifiableCredentialsJSONProperty = "verifiableCredentials"
 )
 
-func (sar SubmitApplicationRequest) ToServiceRequest() (*manifest.SubmitApplicationRequest, error) {
+func (sar SubmitApplicationRequest) ToServiceRequest() (*model.SubmitApplicationRequest, error) {
 	signature, token, err := util.ParseJWT(sar.ApplicationJWT)
 	if err != nil {
 		logrus.WithError(err).Error("could not parse application JWT")
@@ -270,7 +271,7 @@ func (sar SubmitApplicationRequest) ToServiceRequest() (*manifest.SubmitApplicat
 	if err != nil {
 		return nil, errors.Wrap(err, "could not parse submitted credentials")
 	}
-	return &manifest.SubmitApplicationRequest{
+	return &model.SubmitApplicationRequest{
 		ApplicantDID:    kid,
 		Application:     application,
 		Credentials:     credContainer,
@@ -294,7 +295,7 @@ type SubmitApplicationResponse struct {
 // @Accept       json
 // @Produce      json
 // @Param        request  body      SubmitApplicationRequest  true  "request body"
-// @Success      201      {object}  SubmitApplicationResponse
+// @Success      201      {object}  Operation "Operation with a SubmitApplicationResponse type in the `result.response` field."
 // @Failure      400      {string}  string  "Bad request"
 // @Failure      500      {string}  string  "Internal server error"
 // @Router       /v1/manifests/applications [put]
@@ -313,20 +314,14 @@ func (mr ManifestRouter) SubmitApplication(ctx context.Context, w http.ResponseW
 		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusBadRequest)
 	}
 
-	submitApplicationResponse, err := mr.service.ProcessApplicationSubmission(*req)
+	op, err := mr.service.ProcessApplicationSubmission(*req)
 	if err != nil {
 		errMsg := "could not submit application"
 		logrus.WithError(err).Error(errMsg)
 		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusInternalServerError)
 	}
 
-	resp := SubmitApplicationResponse{
-		Response:    submitApplicationResponse.Response,
-		Credentials: submitApplicationResponse.Credentials,
-		ResponseJWT: submitApplicationResponse.ResponseJWT,
-	}
-
-	return framework.Respond(ctx, w, resp, http.StatusCreated)
+	return framework.Respond(ctx, w, routerModel(*op), http.StatusCreated)
 }
 
 type GetApplicationResponse struct {
@@ -352,7 +347,7 @@ func (mr ManifestRouter) GetApplication(ctx context.Context, w http.ResponseWrit
 		return framework.NewRequestErrorMsg(errMsg, http.StatusBadRequest)
 	}
 
-	gotApplication, err := mr.service.GetApplication(manifest.GetApplicationRequest{ID: *id})
+	gotApplication, err := mr.service.GetApplication(model.GetApplicationRequest{ID: *id})
 	if err != nil {
 		errMsg := fmt.Sprintf("could not get application with id: %s", *id)
 		logrus.WithError(err).Error(errMsg)
@@ -415,7 +410,7 @@ func (mr ManifestRouter) DeleteApplication(ctx context.Context, w http.ResponseW
 		return framework.NewRequestErrorMsg(errMsg, http.StatusBadRequest)
 	}
 
-	if err := mr.service.DeleteApplication(manifest.DeleteApplicationRequest{ID: *id}); err != nil {
+	if err := mr.service.DeleteApplication(model.DeleteApplicationRequest{ID: *id}); err != nil {
 		errMsg := fmt.Sprintf("could not delete application with id: %s", *id)
 		logrus.WithError(err).Error(errMsg)
 		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusInternalServerError)
@@ -447,7 +442,7 @@ func (mr ManifestRouter) GetResponse(ctx context.Context, w http.ResponseWriter,
 		return framework.NewRequestErrorMsg(errMsg, http.StatusBadRequest)
 	}
 
-	gotResponse, err := mr.service.GetResponse(manifest.GetResponseRequest{ID: *id})
+	gotResponse, err := mr.service.GetResponse(model.GetResponseRequest{ID: *id})
 	if err != nil {
 		errMsg := fmt.Sprintf("could not get response with id: %s", *id)
 		logrus.WithError(err).Error(errMsg)
@@ -510,7 +505,7 @@ func (mr ManifestRouter) DeleteResponse(ctx context.Context, w http.ResponseWrit
 		return framework.NewRequestErrorMsg(errMsg, http.StatusBadRequest)
 	}
 
-	if err := mr.service.DeleteResponse(manifest.DeleteResponseRequest{ID: *id}); err != nil {
+	if err := mr.service.DeleteResponse(model.DeleteResponseRequest{ID: *id}); err != nil {
 		errMsg := fmt.Sprintf("could not delete response with id: %s", *id)
 		logrus.WithError(err).Error(errMsg)
 		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusInternalServerError)
diff --git a/pkg/server/router/operation.go b/pkg/server/router/operation.go
index 52de757..2e3623c 100644
--- a/pkg/server/router/operation.go
+++ b/pkg/server/router/operation.go
@@ -10,6 +10,7 @@ import (
 	"github.com/tbd54566975/ssi-service/internal/util"
 	"github.com/tbd54566975/ssi-service/pkg/server/framework"
 	svcframework "github.com/tbd54566975/ssi-service/pkg/service/framework"
+	manifestsvc "github.com/tbd54566975/ssi-service/pkg/service/manifest/model"
 	"github.com/tbd54566975/ssi-service/pkg/service/operation"
 	"go.einride.tech/aip/filtering"
 )
@@ -152,14 +153,26 @@ func (o OperationRouter) GetOperations(ctx context.Context, w http.ResponseWrite
 }
 
 func routerModel(op operation.Operation) Operation {
-	return Operation{
+	routerOp := Operation{
 		ID:   op.ID,
 		Done: op.Done,
 		Result: OperationResult{
-			Error:    op.Result.Error,
-			Response: op.Result.Response,
+			Error: op.Result.Error,
 		},
 	}
+	if op.Result.Response != nil {
+		switch r := op.Result.Response.(type) {
+		case manifestsvc.SubmitApplicationResponse:
+			routerOp.Result.Response = SubmitApplicationResponse{
+				Response:    r.Response,
+				Credentials: r.Credentials,
+				ResponseJWT: r.ResponseJWT,
+			}
+		default:
+			routerOp.Result.Response = r
+		}
+	}
+	return routerOp
 }
 
 // CancelOperation godoc
@@ -188,3 +201,22 @@ func (o OperationRouter) CancelOperation(ctx context.Context, w http.ResponseWri
 	}
 	return framework.Respond(ctx, w, routerModel(*op), http.StatusOK)
 }
+
+type Operation struct {
+	// The name of the resource related to this operation. E.g. "presentations/submissions/<uuid>"
+	ID string `json:"id"`
+
+	// Whether this operation has finished.
+	Done bool `json:"done"`
+
+	// Populated if Done == true.
+	Result OperationResult `json:"result,omitempty"`
+}
+
+type OperationResult struct {
+	// Populated when there was an error with the operation.
+	Error string `json:"error,omitempty"`
+
+	// Populated iff Error == "". The type should be specified in the calling APIs documentation.
+	Response any `json:"response,omitempty"`
+}
diff --git a/pkg/server/router/presentation.go b/pkg/server/router/presentation.go
index 35a6bcc..f6bee6f 100644
--- a/pkg/server/router/presentation.go
+++ b/pkg/server/router/presentation.go
@@ -220,25 +220,6 @@ func (r CreateSubmissionRequest) toServiceRequest() (*model.CreateSubmissionRequ
 		Credentials:   credContainers}, nil
 }
 
-type Operation struct {
-	// The name of the resource related to this operation. E.g. "presentations/submissions/<uuid>"
-	ID string `json:"id"`
-
-	// Whether this operation has finished.
-	Done bool `json:"done"`
-
-	// Populated Done == true.
-	Result OperationResult `json:"result,omitempty"`
-}
-
-type OperationResult struct {
-	// Populated when there was an error with the operation.
-	Error string `json:"error,omitempty"`
-
-	// Populated iff Error == "". The type should be specified in the calling APIs documentation.
-	Response any `json:"response,omitempty"`
-}
-
 // CreateSubmission godoc
 // @Summary      Create Submission
 // @Description  Creates a submission in this server ready to be reviewed.
diff --git a/pkg/service/manifest/application.go b/pkg/service/manifest/application.go
index 16683a2..5cbfad1 100644
--- a/pkg/service/manifest/application.go
+++ b/pkg/service/manifest/application.go
@@ -5,6 +5,7 @@ import (
 	"strings"
 
 	"github.com/tbd54566975/ssi-service/pkg/jwt"
+	"github.com/tbd54566975/ssi-service/pkg/service/manifest/model"
 
 	"github.com/TBD54566975/ssi-sdk/credential/manifest"
 	errresp "github.com/TBD54566975/ssi-sdk/error"
@@ -20,7 +21,7 @@ func (s Service) verifyApplicationJWT(did string, token keyaccess.JWT) error {
 // validateCredentialApplication validates the credential application's signature(s) in addition to making sure it
 // is a valid credential application, and complies with its corresponding manifest. it returns the ids of unfulfilled
 // input descriptors along with an error if validation fails.
-func (s Service) validateCredentialApplication(credManifest manifest.CredentialManifest, request SubmitApplicationRequest) (inputDescriptorIDs []string, err error) {
+func (s Service) validateCredentialApplication(credManifest manifest.CredentialManifest, request model.SubmitApplicationRequest) (inputDescriptorIDs []string, err error) {
 	// validate the payload's signature
 	if verificationErr := s.verifyApplicationJWT(request.ApplicantDID, request.ApplicationJWT); verificationErr != nil {
 		err = util.LoggingErrorMsgf(err, "could not verify application<%s>'s signature", request.Application.ID)
diff --git a/pkg/service/manifest/model.go b/pkg/service/manifest/model/model.go
similarity index 84%
rename from pkg/service/manifest/model.go
rename to pkg/service/manifest/model/model.go
index d955ff2..30c49bd 100644
--- a/pkg/service/manifest/model.go
+++ b/pkg/service/manifest/model/model.go
@@ -1,11 +1,11 @@
-package manifest
+package model
 
 import (
 	"github.com/TBD54566975/ssi-sdk/credential/exchange"
 	manifestsdk "github.com/TBD54566975/ssi-sdk/credential/manifest"
-
 	cred "github.com/tbd54566975/ssi-service/internal/credential"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
+	"github.com/tbd54566975/ssi-service/pkg/service/manifest/storage"
 )
 
 // Manifest
@@ -73,6 +73,9 @@ type GetApplicationRequest struct {
 }
 
 type GetApplicationResponse struct {
+	// One of "pending", "fulfilled", "rejected". When Status is either fulfilled or rejected, a corresponding
+	// SubmissionApplicationResponse is guaranteed to exist.
+	Status      string
 	Application manifestsdk.CredentialApplication `json:"application"`
 }
 
@@ -101,3 +104,12 @@ type GetResponsesResponse struct {
 type DeleteResponseRequest struct {
 	ID string `json:"id" validate:"required"`
 }
+
+// ServiceModel creates a SubmitApplicationResponse from a given StoredResponse.
+func ServiceModel(storedResponse *storage.StoredResponse) SubmitApplicationResponse {
+	return SubmitApplicationResponse{
+		Response:    storedResponse.Response,
+		Credentials: cred.ContainersToInterface(storedResponse.Credentials),
+		ResponseJWT: storedResponse.ResponseJWT,
+	}
+}
diff --git a/pkg/service/manifest/service.go b/pkg/service/manifest/service.go
index 99a1ba3..378458f 100644
--- a/pkg/service/manifest/service.go
+++ b/pkg/service/manifest/service.go
@@ -7,7 +7,14 @@ import (
 	didsdk "github.com/TBD54566975/ssi-sdk/did"
 	errresp "github.com/TBD54566975/ssi-sdk/error"
 	sdkutil "github.com/TBD54566975/ssi-sdk/util"
+	"github.com/goccy/go-json"
+	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
+	"github.com/tbd54566975/ssi-service/pkg/service/manifest/model"
+	manifeststg "github.com/tbd54566975/ssi-service/pkg/service/manifest/storage"
+	"github.com/tbd54566975/ssi-service/pkg/service/operation"
+	opcredential "github.com/tbd54566975/ssi-service/pkg/service/operation/credential"
+	opstorage "github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
 
 	"github.com/tbd54566975/ssi-service/config"
 	credint "github.com/tbd54566975/ssi-service/internal/credential"
@@ -19,8 +26,9 @@ import (
 )
 
 type Service struct {
-	storage *Storage
-	config  config.ManifestServiceConfig
+	storage    *manifeststg.Storage
+	opsStorage *operation.Storage
+	config     config.ManifestServiceConfig
 
 	// external dependencies
 	keyStore    *keystore.Service
@@ -60,12 +68,17 @@ func (s Service) Config() config.ManifestServiceConfig {
 }
 
 func NewManifestService(config config.ManifestServiceConfig, s storage.ServiceStorage, keyStore *keystore.Service, didResolver *didsdk.Resolver, credential *credential.Service) (*Service, error) {
-	manifestStorage, err := NewManifestStorage(s)
+	manifestStorage, err := manifeststg.NewManifestStorage(s)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not instantiate storage for the manifest service")
 	}
+	opsStorage, err := operation.NewOperationStorage(s)
+	if err != nil {
+		return nil, util.LoggingErrorMsg(err, "could not instantiate storage for the operations")
+	}
 	return &Service{
 		storage:     manifestStorage,
+		opsStorage:  opsStorage,
 		config:      config,
 		keyStore:    keyStore,
 		didResolver: didResolver,
@@ -78,7 +91,7 @@ type CredentialManifestContainer struct {
 	Manifest manifest.CredentialManifest `json:"credential_manifest"`
 }
 
-func (s Service) CreateManifest(request CreateManifestRequest) (*CreateManifestResponse, error) {
+func (s Service) CreateManifest(request model.CreateManifestRequest) (*model.CreateManifestResponse, error) {
 
 	logrus.Debugf("creating manifest: %+v", request)
 
@@ -138,7 +151,7 @@ func (s Service) CreateManifest(request CreateManifestRequest) (*CreateManifestR
 	}
 
 	// store the manifest
-	storageRequest := StoredManifest{
+	storageRequest := manifeststg.StoredManifest{
 		ID:          m.ID,
 		Issuer:      m.Issuer.ID,
 		Manifest:    *m,
@@ -150,25 +163,25 @@ func (s Service) CreateManifest(request CreateManifestRequest) (*CreateManifestR
 	}
 
 	// return the result
-	response := CreateManifestResponse{Manifest: *m, ManifestJWT: *manifestJWT}
+	response := model.CreateManifestResponse{Manifest: *m, ManifestJWT: *manifestJWT}
 	return &response, nil
 }
 
 // VerifyManifest verifies a manifest's signature and makes sure the manifest is compliant with the specification
-func (s Service) VerifyManifest(request VerifyManifestRequest) (*VerifyManifestResponse, error) {
+func (s Service) VerifyManifest(request model.VerifyManifestRequest) (*model.VerifyManifestResponse, error) {
 	m, err := s.verifyManifestJWT(request.ManifestJWT)
 	if err != nil {
-		return &VerifyManifestResponse{Verified: false, Reason: "could not verify manifest's signature: " + err.Error()}, nil
+		return &model.VerifyManifestResponse{Verified: false, Reason: "could not verify manifest's signature: " + err.Error()}, nil
 	}
 
 	// check the manifest is valid against its specification
 	if err := m.IsValid(); err != nil {
-		return &VerifyManifestResponse{Verified: false, Reason: "manifest is not valid: " + err.Error()}, nil
+		return &model.VerifyManifestResponse{Verified: false, Reason: "manifest is not valid: " + err.Error()}, nil
 	}
-	return &VerifyManifestResponse{Verified: true}, nil
+	return &model.VerifyManifestResponse{Verified: true}, nil
 }
 
-func (s Service) GetManifest(request GetManifestRequest) (*GetManifestResponse, error) {
+func (s Service) GetManifest(request model.GetManifestRequest) (*model.GetManifestResponse, error) {
 
 	logrus.Debugf("getting manifest: %s", request.ID)
 
@@ -177,27 +190,27 @@ func (s Service) GetManifest(request GetManifestRequest) (*GetManifestResponse,
 		return nil, util.LoggingErrorMsgf(err, "could not get manifest: %s", request.ID)
 	}
 
-	response := GetManifestResponse{Manifest: gotManifest.Manifest, ManifestJWT: gotManifest.ManifestJWT}
+	response := model.GetManifestResponse{Manifest: gotManifest.Manifest, ManifestJWT: gotManifest.ManifestJWT}
 	return &response, nil
 }
 
-func (s Service) GetManifests() (*GetManifestsResponse, error) {
+func (s Service) GetManifests() (*model.GetManifestsResponse, error) {
 	gotManifests, err := s.storage.GetManifests()
 
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not get manifests(s)")
 	}
 
-	manifests := make([]GetManifestResponse, 0, len(gotManifests))
+	manifests := make([]model.GetManifestResponse, 0, len(gotManifests))
 	for _, m := range gotManifests {
-		response := GetManifestResponse{Manifest: m.Manifest, ManifestJWT: m.ManifestJWT}
+		response := model.GetManifestResponse{Manifest: m.Manifest, ManifestJWT: m.ManifestJWT}
 		manifests = append(manifests, response)
 	}
-	response := GetManifestsResponse{Manifests: manifests}
+	response := model.GetManifestsResponse{Manifests: manifests}
 	return &response, nil
 }
 
-func (s Service) DeleteManifest(request DeleteManifestRequest) error {
+func (s Service) DeleteManifest(request model.DeleteManifestRequest) error {
 
 	logrus.Debugf("deleting manifest: %s", request.ID)
 
@@ -214,7 +227,7 @@ type CredentialResponseContainer struct {
 	Credentials []any                       `json:"verifiableCredentials,omitempty"`
 }
 
-func (s Service) ProcessApplicationSubmission(request SubmitApplicationRequest) (*SubmitApplicationResponse, error) {
+func (s Service) ProcessApplicationSubmission(request model.SubmitApplicationRequest) (*operation.Operation, error) {
 	// get the manifest associated with the application
 	manifestID := request.Application.ManifestID
 	gotManifest, err := s.storage.GetManifest(manifestID)
@@ -227,6 +240,7 @@ func (s Service) ProcessApplicationSubmission(request SubmitApplicationRequest)
 	}
 	credManifest := gotManifest.Manifest
 
+	opID := opcredential.IDFromResponseID(applicationID)
 	// validate the application
 	if unfulfilledInputDescriptorIDs, validationErr := s.validateCredentialApplication(gotManifest.Manifest, request); validationErr != nil {
 		resp := errresp.GetErrorResponse(validationErr)
@@ -235,14 +249,27 @@ func (s Service) ProcessApplicationSubmission(request SubmitApplicationRequest)
 			if err != nil {
 				return nil, util.LoggingErrorMsg(err, "could not build denial credential response")
 			}
-			return &SubmitApplicationResponse{Response: *denialResp}, nil
+			sarData, err := json.Marshal(manifeststg.StoredResponse{Response: *denialResp})
+			if err != nil {
+				return nil, errors.Wrap(err, "marshalling response")
+			}
+			storedOp := opstorage.StoredOperation{
+				ID:       opID,
+				Done:     true,
+				Response: sarData,
+			}
+			if err := s.opsStorage.StoreOperation(storedOp); err != nil {
+				return nil, errors.Wrap(err, "storing operation")
+			}
+
+			return operation.ServiceModel(storedOp)
 		}
 		return nil, util.LoggingErrorMsg(validationErr, "could not validate application")
 	}
 
 	// store the application
 	applicantDID := request.ApplicantDID
-	storageRequest := StoredApplication{
+	storageRequest := manifeststg.StoredApplication{
 		ID:             applicationID,
 		ManifestID:     manifestID,
 		ApplicantDID:   applicantDID,
@@ -273,7 +300,7 @@ func (s Service) ProcessApplicationSubmission(request SubmitApplicationRequest)
 	}
 
 	// store the response we've generated
-	storeResponseRequest := StoredResponse{
+	storeResponseRequest := manifeststg.StoredResponse{
 		ID:           credResp.ID,
 		ManifestID:   manifestID,
 		ApplicantDID: applicantDID,
@@ -285,11 +312,22 @@ func (s Service) ProcessApplicationSubmission(request SubmitApplicationRequest)
 		return nil, util.LoggingErrorMsg(err, "could not store manifest response")
 	}
 
-	response := SubmitApplicationResponse{Response: *credResp, Credentials: credentials, ResponseJWT: *responseJWT}
-	return &response, nil
+	sarData, err := json.Marshal(storeResponseRequest)
+	if err != nil {
+		return nil, errors.Wrap(err, "marshalling response")
+	}
+	storedOp := opstorage.StoredOperation{
+		ID:       opID,
+		Done:     true,
+		Response: sarData,
+	}
+	if err = s.opsStorage.StoreOperation(storedOp); err != nil {
+		return nil, errors.Wrap(err, "storing operation")
+	}
+	return operation.ServiceModel(storedOp)
 }
 
-func (s Service) GetApplication(request GetApplicationRequest) (*GetApplicationResponse, error) {
+func (s Service) GetApplication(request model.GetApplicationRequest) (*model.GetApplicationResponse, error) {
 
 	logrus.Debugf("getting application: %s", request.ID)
 
@@ -298,11 +336,11 @@ func (s Service) GetApplication(request GetApplicationRequest) (*GetApplicationR
 		return nil, util.LoggingErrorMsgf(err, "could not get application: %s", request.ID)
 	}
 
-	response := GetApplicationResponse{Application: gotApp.Application}
+	response := model.GetApplicationResponse{Application: gotApp.Application}
 	return &response, nil
 }
 
-func (s Service) GetApplications() (*GetApplicationsResponse, error) {
+func (s Service) GetApplications() (*model.GetApplicationsResponse, error) {
 
 	logrus.Debugf("getting application(s)")
 
@@ -316,11 +354,11 @@ func (s Service) GetApplications() (*GetApplicationsResponse, error) {
 		apps = append(apps, cred.Application)
 	}
 
-	response := GetApplicationsResponse{Applications: apps}
+	response := model.GetApplicationsResponse{Applications: apps}
 	return &response, nil
 }
 
-func (s Service) DeleteApplication(request DeleteApplicationRequest) error {
+func (s Service) DeleteApplication(request model.DeleteApplicationRequest) error {
 
 	logrus.Debugf("deleting application: %s", request.ID)
 
@@ -331,7 +369,7 @@ func (s Service) DeleteApplication(request DeleteApplicationRequest) error {
 	return nil
 }
 
-func (s Service) GetResponse(request GetResponseRequest) (*GetResponseResponse, error) {
+func (s Service) GetResponse(request model.GetResponseRequest) (*model.GetResponseResponse, error) {
 
 	logrus.Debugf("getting response: %s", request.ID)
 
@@ -340,11 +378,11 @@ func (s Service) GetResponse(request GetResponseRequest) (*GetResponseResponse,
 		return nil, util.LoggingErrorMsgf(err, "could not get response: %s", request.ID)
 	}
 
-	response := GetResponseResponse{Response: gotResponse.Response}
+	response := model.GetResponseResponse{Response: gotResponse.Response}
 	return &response, nil
 }
 
-func (s Service) GetResponses() (*GetResponsesResponse, error) {
+func (s Service) GetResponses() (*model.GetResponsesResponse, error) {
 
 	logrus.Debugf("getting response(s)")
 
@@ -358,11 +396,11 @@ func (s Service) GetResponses() (*GetResponsesResponse, error) {
 		responses = append(responses, res.Response)
 	}
 
-	response := GetResponsesResponse{Responses: responses}
+	response := model.GetResponsesResponse{Responses: responses}
 	return &response, nil
 }
 
-func (s Service) DeleteResponse(request DeleteResponseRequest) error {
+func (s Service) DeleteResponse(request model.DeleteResponseRequest) error {
 
 	logrus.Debugf("deleting response: %s", request.ID)
 
diff --git a/pkg/service/manifest/storage.go b/pkg/service/manifest/storage/storage.go
similarity index 99%
rename from pkg/service/manifest/storage.go
rename to pkg/service/manifest/storage/storage.go
index 1083e0d..b28648d 100644
--- a/pkg/service/manifest/storage.go
+++ b/pkg/service/manifest/storage/storage.go
@@ -1,4 +1,4 @@
-package manifest
+package storage
 
 import (
 	"fmt"
diff --git a/pkg/service/operation/credential/response.go b/pkg/service/operation/credential/response.go
new file mode 100644
index 0000000..e1e1f4d
--- /dev/null
+++ b/pkg/service/operation/credential/response.go
@@ -0,0 +1,35 @@
+package credential
+
+import "fmt"
+
+const (
+	// ParentResource is the prefix of the credential application parent resource.
+	ParentResource = "credentials/responses"
+)
+
+// IDFromResponseID returns an operation ID from the application ID.
+func IDFromResponseID(id string) string {
+	return fmt.Sprintf("%s/%s", ParentResource, id)
+}
+
+type Status uint8
+
+func (s Status) String() string {
+	switch s {
+	case StatusPending:
+		return "pending"
+	case StatusFulfilled:
+		return "fulfilled"
+	case StatusRejected:
+		return "rejected"
+	default:
+		return "unknown"
+	}
+}
+
+const (
+	StatusUnknown Status = iota
+	StatusPending
+	StatusFulfilled
+	StatusRejected
+)
diff --git a/pkg/service/operation/service.go b/pkg/service/operation/service.go
index 09dad33..5fe23e3 100644
--- a/pkg/service/operation/service.go
+++ b/pkg/service/operation/service.go
@@ -10,6 +10,9 @@ import (
 	"github.com/sirupsen/logrus"
 	"github.com/tbd54566975/ssi-service/internal/util"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
+	manifestmodel "github.com/tbd54566975/ssi-service/pkg/service/manifest/model"
+	manifeststg "github.com/tbd54566975/ssi-service/pkg/service/manifest/storage"
+	"github.com/tbd54566975/ssi-service/pkg/service/operation/credential"
 	opstorage "github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
 	"github.com/tbd54566975/ssi-service/pkg/service/operation/submission"
 	"github.com/tbd54566975/ssi-service/pkg/service/presentation/model"
@@ -54,7 +57,7 @@ func (s Service) GetOperations(request GetOperationsRequest) (*GetOperationsResp
 	}
 	for i, op := range ops {
 		op := op
-		newOp, err := serviceModel(op)
+		newOp, err := ServiceModel(op)
 		if err != nil {
 			logrus.WithError(err).WithField("operation_id", op.ID).Error("converting to storage operations to model")
 			continue
@@ -66,7 +69,9 @@ func (s Service) GetOperations(request GetOperationsRequest) (*GetOperationsResp
 
 type ServiceModelFunc func(any) any
 
-func serviceModel(op opstorage.StoredOperation) (*Operation, error) {
+// ServiceModel converts a storage.StoredOperation to an Operation. The Result.Response field is introspected and
+// converted into the service layer's model.
+func ServiceModel(op opstorage.StoredOperation) (*Operation, error) {
 	newOp := &Operation{
 		ID:   op.ID,
 		Done: op.Done,
@@ -80,9 +85,15 @@ func serviceModel(op opstorage.StoredOperation) (*Operation, error) {
 		case strings.HasPrefix(op.ID, submission.ParentResource):
 			var s prestorage.StoredSubmission
 			if err := json.Unmarshal(op.Response, &s); err != nil {
-				return nil, err
+				return nil, errors.Wrap(err, "unmarshalling submission response")
 			}
 			newOp.Result.Response = model.ServiceModel(&s)
+		case strings.HasPrefix(op.ID, credential.ParentResource):
+			var s manifeststg.StoredResponse
+			if err := json.Unmarshal(op.Response, &s); err != nil {
+				return nil, errors.Wrap(err, "unmarshalling cred response")
+			}
+			newOp.Result.Response = manifestmodel.ServiceModel(&s)
 		default:
 			return nil, errors.New("unknown response type")
 		}
@@ -100,7 +111,7 @@ func (s Service) GetOperation(request GetOperationRequest) (*Operation, error) {
 	if err != nil {
 		return nil, errors.Wrap(err, "fetching from storage")
 	}
-	return serviceModel(storedOp)
+	return ServiceModel(storedOp)
 }
 
 func (s Service) CancelOperation(request CancelOperationRequest) (*Operation, error) {
@@ -112,7 +123,7 @@ func (s Service) CancelOperation(request CancelOperationRequest) (*Operation, er
 	if err != nil {
 		return nil, errors.Wrap(err, "marking as done")
 	}
-	return serviceModel(*storedOp)
+	return ServiceModel(*storedOp)
 }
 
 func NewOperationService(s storage.ServiceStorage) (*Service, error) {
diff --git a/pkg/service/operation/storage/namespace/namespace.go b/pkg/service/operation/storage/namespace/namespace.go
index 55a2f2c..99ecc63 100644
--- a/pkg/service/operation/storage/namespace/namespace.go
+++ b/pkg/service/operation/storage/namespace/namespace.go
@@ -3,10 +3,14 @@ package namespace
 import (
 	"strings"
 
+	"github.com/tbd54566975/ssi-service/pkg/service/operation/credential"
 	"github.com/tbd54566975/ssi-service/pkg/service/operation/submission"
 )
 
-const namespace = "operation_submission"
+const (
+	namespace                   = "operation_submission"
+	credentialResponseNamespace = "operation_credential_response"
+)
 
 // FromID returns a namespace from a given operation ID. An empty string is returned when the namespace cannot
 // be determined.
@@ -24,6 +28,8 @@ func FromParent(parent string) string {
 	switch parent {
 	case submission.ParentResource:
 		return namespace
+	case credential.ParentResource:
+		return credentialResponseNamespace
 	default:
 		return ""
 	}


Test patch:
diff --git a/integration/didweb_integration_test.go b/integration/didweb_integration_test.go
index dfbeb35..73ddb92 100644
--- a/integration/didweb_integration_test.go
+++ b/integration/didweb_integration_test.go
@@ -156,11 +156,11 @@ func TestDidWebSubmitApplicationIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, credentialResponseOutput)
 
-	crManifestID, err := getJSONElement(credentialResponseOutput, "$.credential_response.manifest_id")
+	crManifestID, err := getJSONElement(credentialResponseOutput, "$.result.response.credential_response.manifest_id")
 	assert.NoError(t, err)
 	assert.Equal(t, manifestID, crManifestID)
 
-	vc, err := getJSONElement(credentialResponseOutput, "$.verifiableCredentials[0]")
+	vc, err := getJSONElement(credentialResponseOutput, "$.result.response.verifiableCredentials[0]")
 	assert.NoError(t, err)
 	assert.NotEmpty(t, vc)
 }
diff --git a/integration/steelthread_integration_test.go b/integration/steelthread_integration_test.go
index 93e3a6c..bb718d2 100644
--- a/integration/steelthread_integration_test.go
+++ b/integration/steelthread_integration_test.go
@@ -156,11 +156,11 @@ func TestSubmitApplicationIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, credentialResponseOutput)
 
-	crManifestID, err := getJSONElement(credentialResponseOutput, "$.credential_response.manifest_id")
+	crManifestID, err := getJSONElement(credentialResponseOutput, "$.result.response.credential_response.manifest_id")
 	assert.NoError(t, err)
 	assert.Equal(t, manifestID, crManifestID)
 
-	vc, err := getJSONElement(credentialResponseOutput, "$.verifiableCredentials[0]")
+	vc, err := getJSONElement(credentialResponseOutput, "$.result.response.verifiableCredentials[0]")
 	assert.NoError(t, err)
 	assert.NotEmpty(t, vc)
 }
diff --git a/pkg/server/router/manifest_test.go b/pkg/server/router/manifest_test.go
index d379ead..db17427 100644
--- a/pkg/server/router/manifest_test.go
+++ b/pkg/server/router/manifest_test.go
@@ -10,13 +10,14 @@ import (
 	"github.com/google/uuid"
 	"github.com/mr-tron/base58"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+	"github.com/tbd54566975/ssi-service/pkg/service/manifest/model"
 
 	credmodel "github.com/tbd54566975/ssi-service/internal/credential"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/pkg/service/credential"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
-	"github.com/tbd54566975/ssi-service/pkg/service/manifest"
 	"github.com/tbd54566975/ssi-service/pkg/service/schema"
 )
 
@@ -94,7 +95,7 @@ func TestManifestRouter(t *testing.T) {
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdManifest)
 
-		verificationResponse, err := manifestService.VerifyManifest(manifest.VerifyManifestRequest{ManifestJWT: createdManifest.ManifestJWT})
+		verificationResponse, err := manifestService.VerifyManifest(model.VerifyManifestRequest{ManifestJWT: createdManifest.ManifestJWT})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, verificationResponse)
 		assert.True(tt, verificationResponse.Verified)
@@ -122,8 +123,10 @@ func TestManifestRouter(t *testing.T) {
 		submitApplicationRequest := SubmitApplicationRequest{ApplicationJWT: *signed}
 		sar, err := submitApplicationRequest.ToServiceRequest()
 		assert.NoError(tt, err)
-		createdApplicationResponse, err := manifestService.ProcessApplicationSubmission(*sar)
+		createdApplicationResponseOp, err := manifestService.ProcessApplicationSubmission(*sar)
 		assert.NoError(tt, err)
+		createdApplicationResponse, ok := createdApplicationResponseOp.Result.Response.(model.SubmitApplicationResponse)
+		require.True(tt, ok)
 		assert.NotEmpty(tt, createdManifest)
 		assert.NotEmpty(tt, createdApplicationResponse.Response.ID)
 		assert.NotEmpty(tt, createdApplicationResponse.Response.Fulfillment)
@@ -133,8 +136,8 @@ func TestManifestRouter(t *testing.T) {
 }
 
 // getValidManifestRequest returns a valid manifest request, expecting a single JWT-VC EdDSA credential
-func getValidManifestRequest(issuerDID, schemaID string) manifest.CreateManifestRequest {
-	createManifestRequest := manifest.CreateManifestRequest{
+func getValidManifestRequest(issuerDID, schemaID string) model.CreateManifestRequest {
+	createManifestRequest := model.CreateManifestRequest{
 		IssuerDID: issuerDID,
 		ClaimFormat: &exchange.ClaimFormat{
 			JWTVC: &exchange.JWTType{Alg: []crypto.SignatureAlgorithm{crypto.EdDSA}},
diff --git a/pkg/server/server_manifest_test.go b/pkg/server/server_manifest_test.go
index ac8f17c..f15f035 100644
--- a/pkg/server/server_manifest_test.go
+++ b/pkg/server/server_manifest_test.go
@@ -12,13 +12,13 @@ import (
 	"github.com/mr-tron/base58"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+	manifestsvc "github.com/tbd54566975/ssi-service/pkg/service/manifest/model"
 
 	credmodel "github.com/tbd54566975/ssi-service/internal/credential"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/pkg/server/router"
 	"github.com/tbd54566975/ssi-service/pkg/service/credential"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
-	manifestsvc "github.com/tbd54566975/ssi-service/pkg/service/manifest"
 	"github.com/tbd54566975/ssi-service/pkg/service/schema"
 )
 
@@ -412,8 +412,14 @@ func TestManifestAPI(t *testing.T) {
 		err = manifestRouter.SubmitApplication(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
+		var op router.Operation
+		err = json.NewDecoder(w.Body).Decode(&op)
+		assert.NoError(tt, err)
+
 		var appResp router.SubmitApplicationResponse
-		err = json.NewDecoder(w.Body).Decode(&appResp)
+		respData, err := json.Marshal(op.Result.Response)
+		assert.NoError(tt, err)
+		err = json.Unmarshal(respData, &appResp)
 		assert.NoError(tt, err)
 
 		assert.NotEmpty(tt, appResp.Response)
@@ -533,8 +539,14 @@ func TestManifestAPI(t *testing.T) {
 		err = manifestRouter.SubmitApplication(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
+		var op router.Operation
+		err = json.NewDecoder(w.Body).Decode(&op)
+		assert.NoError(tt, err)
+
 		var appResp router.SubmitApplicationResponse
-		err = json.NewDecoder(w.Body).Decode(&appResp)
+		respData, err := json.Marshal(op.Result.Response)
+		assert.NoError(tt, err)
+		err = json.Unmarshal(respData, &appResp)
 		assert.NoError(tt, err)
 
 		assert.NotEmpty(tt, appResp.Response)
@@ -558,7 +570,12 @@ func TestManifestAPI(t *testing.T) {
 		err = manifestRouter.SubmitApplication(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
-		err = json.NewDecoder(w.Body).Decode(&appResp)
+		err = json.NewDecoder(w.Body).Decode(&op)
+		assert.NoError(tt, err)
+
+		respData, err = json.Marshal(op.Result.Response)
+		assert.NoError(tt, err)
+		err = json.Unmarshal(respData, &appResp)
 		assert.NoError(tt, err)
 
 		assert.NotEmpty(tt, appResp.Response)
@@ -664,8 +681,14 @@ func TestManifestAPI(t *testing.T) {
 		err = manifestRouter.SubmitApplication(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
+		var op router.Operation
+		err = json.NewDecoder(w.Body).Decode(&op)
+		assert.NoError(tt, err)
+
 		var appResp router.SubmitApplicationResponse
-		err = json.NewDecoder(w.Body).Decode(&appResp)
+		respData, err := json.Marshal(op.Result.Response)
+		assert.NoError(tt, err)
+		err = json.Unmarshal(respData, &appResp)
 		assert.NoError(tt, err)
 
 		assert.NotEmpty(tt, appResp.Response.Fulfillment)
diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go
index fde5af0..2e8fddd 100644
--- a/pkg/server/server_test.go
+++ b/pkg/server/server_test.go
@@ -11,6 +11,7 @@ import (
 	"time"
 
 	"github.com/TBD54566975/ssi-sdk/credential/exchange"
+	"github.com/tbd54566975/ssi-service/pkg/service/manifest/model"
 	"github.com/tbd54566975/ssi-service/pkg/testutil"
 
 	manifestsdk "github.com/TBD54566975/ssi-sdk/credential/manifest"
@@ -119,8 +120,8 @@ func newRequestContextWithParams(params map[string]string) context.Context {
 	return httptreemux.AddParamsToContext(ctx, params)
 }
 
-func getValidManifestRequest(issuerDID, schemaID string) manifest.CreateManifestRequest {
-	createManifestRequest := manifest.CreateManifestRequest{
+func getValidManifestRequest(issuerDID, schemaID string) model.CreateManifestRequest {
+	createManifestRequest := model.CreateManifestRequest{
 		IssuerDID: issuerDID,
 		ClaimFormat: &exchange.ClaimFormat{
 			JWTVC: &exchange.JWTType{Alg: []crypto.SignatureAlgorithm{crypto.EdDSA}},