Repository: TBD54566975/ssi-service
Pull request #272 (2023-01-30 21:59:33)

Fixing cred revocation bug where schema was not being saved
# Overview
Fixing cred revocation bug

# Description
There was an issue where multiple status list credentials were being created for the same <issuer,schema> pair.
This was because schema was not being saved when the status list credential was created or updated

# How Has This Been Tested?

- [ ✅ ] New unit tests
- [✅ ] Integration Test works
- [✅ ] Manual POSTMAN testing

Debug Output from manual testing:


```
Create Credential:
{
    "credential": {
        "@context": [
            "https://www.w3.org/2018/credentials/v1"
        ],
        "id": "e140cd99-5a42-44b0-b29a-d162dfcbfa41",
        "type": [
            "VerifiableCredential"
        ],
        "issuer": "did:key:z6MkvML6owUEvwUr8P7qsYANnzTBANDq1bBRKdpXoDvTA6sq",
        "issuanceDate": "2023-01-30T21:42:31Z",
        "expirationDate": "2051-10-05T14:48:00.000Z",
        "credentialStatus": {
            "id": "http://localhost:8080/v1/credentials/e140cd99-5a42-44b0-b29a-d162dfcbfa41/status",
            "statusListCredential": "http://localhost:8080/v1/credentials/status/56bf85e4-82ed-49d6-804d-9abf957c34d2",
            "statusListIndex": "93914",
            "statusPurpose": "revocation",
            "type": "StatusList2021Entry"
        },
        "credentialSubject": {
            "employedAt": "2022-08-20T13:20:10.000+0000",
            "givenName": "Alice",
            "id": "did:key:z6MkvML6owUEvwUr8P7qsYANnzTBANDq1bBRKdpXoDvTA6sq"
        },
        "credentialSchema": {
            "id": "d3501080-7f2f-4b63-952c-c243b6f1bdb8",
            "type": "JsonSchemaValidator2018"
        }
    },
    "credentialJwt": "eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa3ZNTDZvd1VFdndVcjhQN3FzWUFObnpUQkFORHExYkJSS2RwWG9EdlRBNnNxIiwidHlwIjoiSldUIn0.eyJleHAiOjI1ODAxMzAwODAsImlzcyI6ImRpZDprZXk6ejZNa3ZNTDZvd1VFdndVcjhQN3FzWUFObnpUQkFORHExYkJSS2RwWG9EdlRBNnNxIiwianRpIjoiZTE0MGNkOTktNWE0Mi00NGIwLWIyOWEtZDE2MmRmY2JmYTQxIiwibmJmIjoxNjc1MTE0OTUxLCJzdWIiOiJkaWQ6a2V5Ono2TWt2TUw2b3dVRXZ3VXI4UDdxc1lBTm56VEJBTkRxMWJCUktkcFhvRHZUQTZzcSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIl0sImlkIjoiZTE0MGNkOTktNWE0Mi00NGIwLWIyOWEtZDE2MmRmY2JmYTQxIiwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCJdLCJpc3N1ZXIiOiJkaWQ6a2V5Ono2TWt2TUw2b3dVRXZ3VXI4UDdxc1lBTm56VEJBTkRxMWJCUktkcFhvRHZUQTZzcSIsImlzc3VhbmNlRGF0ZSI6IjIwMjMtMDEtMzBUMjE6NDI6MzFaIiwiZXhwaXJhdGlvbkRhdGUiOiIyMDUxLTEwLTA1VDE0OjQ4OjAwLjAwMFoiLCJjcmVkZW50aWFsU3RhdHVzIjp7ImlkIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3YxL2NyZWRlbnRpYWxzL2UxNDBjZDk5LTVhNDItNDRiMC1iMjlhLWQxNjJkZmNiZmE0MS9zdGF0dXMiLCJzdGF0dXNMaXN0Q3JlZGVudGlhbCI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC92MS9jcmVkZW50aWFscy9zdGF0dXMvNTZiZjg1ZTQtODJlZC00OWQ2LTgwNGQtOWFiZjk1N2MzNGQyIiwic3RhdHVzTGlzdEluZGV4IjoiOTM5MTQiLCJzdGF0dXNQdXJwb3NlIjoicmV2b2NhdGlvbiIsInR5cGUiOiJTdGF0dXNMaXN0MjAyMUVudHJ5In0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImVtcGxveWVkQXQiOiIyMDIyLTA4LTIwVDEzOjIwOjEwLjAwMCswMDAwIiwiZ2l2ZW5OYW1lIjoiQWxpY2UiLCJpZCI6ImRpZDprZXk6ejZNa3ZNTDZvd1VFdndVcjhQN3FzWUFObnpUQkFORHExYkJSS2RwWG9EdlRBNnNxIn0sImNyZWRlbnRpYWxTY2hlbWEiOnsiaWQiOiJkMzUwMTA4MC03ZjJmLTRiNjMtOTUyYy1jMjQzYjZmMWJkYjgiLCJ0eXBlIjoiSnNvblNjaGVtYVZhbGlkYXRvcjIwMTgifX19.YeJoWjiY2u0oWiJsTvg2vU4QnpsJc4jgA0tgGaRT0o7tE_TEAeEnTIipGghtCJx1NvLG9Vw9P-I7imNcOJ7ABg"
}



Credential Status: - http://localhost:8080/v1/credentials/e140cd99-5a42-44b0-b29a-d162dfcbfa41/status
{"revoked":false}



Status List Credential - http://localhost:8080/v1/credentials/status/56bf85e4-82ed-49d6-804d-9abf957c34d2
{
   "id":"http://localhost:8080/v1/credentials/status/56bf85e4-82ed-49d6-804d-9abf957c34d2",
   "credential":{
      "@context":[
         "https://www.w3.org/2018/credentials/v1",
         "https://w3id.org/vc/status-list/2021/v1"
      ],
      "id":"http://localhost:8080/v1/credentials/status/56bf85e4-82ed-49d6-804d-9abf957c34d2",
      "type":[
         "VerifiableCredential",
         "StatusList2021Credential"
      ],
      "issuer":"did:key:z6MkvML6owUEvwUr8P7qsYANnzTBANDq1bBRKdpXoDvTA6sq",
      "issuanceDate":"2023-01-30T21:42:31Z",
      "credentialSubject":{
         "encodedList":"H4sIAAAAAAAA/2IAAweGUTAKRsEoGAWjYBSMPAAIAAD//9BoYmEICAAA",
         "id":"http://localhost:8080/v1/credentials/status/56bf85e4-82ed-49d6-804d-9abf957c34d2",
         "statusPurpose":"revocation",
         "type":"StatusList2021"
      },
      "credentialSchema":{
         "id":"d3501080-7f2f-4b63-952c-c243b6f1bdb8",
         "type":"JsonSchemaValidator2018"
      }
   },
   "credentialJwt":"eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa3ZNTDZvd1VFdndVcjhQN3FzWUFObnpUQkFORHExYkJSS2RwWG9EdlRBNnNxIiwidHlwIjoiSldUIn0.eyJpc3MiOiJkaWQ6a2V5Ono2TWt2TUw2b3dVRXZ3VXI4UDdxc1lBTm56VEJBTkRxMWJCUktkcFhvRHZUQTZzcSIsImp0aSI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC92MS9jcmVkZW50aWFscy9zdGF0dXMvNTZiZjg1ZTQtODJlZC00OWQ2LTgwNGQtOWFiZjk1N2MzNGQyIiwibmJmIjoxNjc1MTE0OTUxLCJzdWIiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvdjEvY3JlZGVudGlhbHMvc3RhdHVzLzU2YmY4NWU0LTgyZWQtNDlkNi04MDRkLTlhYmY5NTdjMzRkMiIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93M2lkLm9yZy92Yy9zdGF0dXMtbGlzdC8yMDIxL3YxIl0sImlkIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3YxL2NyZWRlbnRpYWxzL3N0YXR1cy81NmJmODVlNC04MmVkLTQ5ZDYtODA0ZC05YWJmOTU3YzM0ZDIiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiU3RhdHVzTGlzdDIwMjFDcmVkZW50aWFsIl0sImlzc3VlciI6ImRpZDprZXk6ejZNa3ZNTDZvd1VFdndVcjhQN3FzWUFObnpUQkFORHExYkJSS2RwWG9EdlRBNnNxIiwiaXNzdWFuY2VEYXRlIjoiMjAyMy0wMS0zMFQyMTo0MjozMVoiLCJjcmVkZW50aWFsU3ViamVjdCI6eyJlbmNvZGVkTGlzdCI6Ikg0c0lBQUFBQUFBQS8ySUFBd2VHVVRBS1JzRW9HQVdqWUJTTVBBQUlBQUQvLzlCb1ltRUlDQUFBIiwiaWQiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvdjEvY3JlZGVudGlhbHMvc3RhdHVzLzU2YmY4NWU0LTgyZWQtNDlkNi04MDRkLTlhYmY5NTdjMzRkMiIsInN0YXR1c1B1cnBvc2UiOiJyZXZvY2F0aW9uIiwidHlwZSI6IlN0YXR1c0xpc3QyMDIxIn0sImNyZWRlbnRpYWxTY2hlbWEiOnsiaWQiOiJkMzUwMTA4MC03ZjJmLTRiNjMtOTUyYy1jMjQzYjZmMWJkYjgiLCJ0eXBlIjoiSnNvblNjaGVtYVZhbGlkYXRvcjIwMTgifX19.pTB7bLQoFZnO_JZmyDDropiX9uG5znrj1YvVarQH8ShcjTlYqUPE9c7wIM1dWejsjoL6TXqluXplPVSdESEcAg"
}


PUT - http://localhost:8080/v1/credentials/e140cd99-5a42-44b0-b29a-d162dfcbfa41/status
{
    "revoked": true
}


Status List Credential (updated encoded list) - http://localhost:8080/v1/credentials/status/56bf85e4-82ed-49d6-804d-9abf957c34d2
{
   "id":"http://localhost:8080/v1/credentials/status/56bf85e4-82ed-49d6-804d-9abf957c34d2",
   "credential":{
      "@context":[
         "https://www.w3.org/2018/credentials/v1",
         "https://w3id.org/vc/status-list/2021/v1"
      ],
      "id":"http://localhost:8080/v1/credentials/status/56bf85e4-82ed-49d6-804d-9abf957c34d2",
      "type":[
         "VerifiableCredential",
         "StatusList2021Credential"
      ],
      "issuer":"did:key:z6MkvML6owUEvwUr8P7qsYANnzTBANDq1bBRKdpXoDvTA6sq",
      "issuanceDate":"2023-01-30T21:47:39Z",
      "credentialSubject":{
         "encodedList":"H4sIAAAAAAAA/+zAQQkAIBRAsSeY18KWEVP8y9a3zg0AAAAAAAAAAAAAgHG7egEAAP//FE5O++gtAAA=",
         "id":"http://localhost:8080/v1/credentials/status/56bf85e4-82ed-49d6-804d-9abf957c34d2",
         "statusPurpose":"revocation",
         "type":"StatusList2021"
      },
      "credentialSchema":{
         "id":"d3501080-7f2f-4b63-952c-c243b6f1bdb8",
         "type":"JsonSchemaValidator2018"
      }
   },
   "credentialJwt":"eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa3ZNTDZvd1VFdndVcjhQN3FzWUFObnpUQkFORHExYkJSS2RwWG9EdlRBNnNxIiwidHlwIjoiSldUIn0.eyJpc3MiOiJkaWQ6a2V5Ono2TWt2TUw2b3dVRXZ3VXI4UDdxc1lBTm56VEJBTkRxMWJCUktkcFhvRHZUQTZzcSIsImp0aSI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC92MS9jcmVkZW50aWFscy9zdGF0dXMvNTZiZjg1ZTQtODJlZC00OWQ2LTgwNGQtOWFiZjk1N2MzNGQyIiwibmJmIjoxNjc1MTE1MjU5LCJzdWIiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvdjEvY3JlZGVudGlhbHMvc3RhdHVzLzU2YmY4NWU0LTgyZWQtNDlkNi04MDRkLTlhYmY5NTdjMzRkMiIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly93M2lkLm9yZy92Yy9zdGF0dXMtbGlzdC8yMDIxL3YxIl0sImlkIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3YxL2NyZWRlbnRpYWxzL3N0YXR1cy81NmJmODVlNC04MmVkLTQ5ZDYtODA0ZC05YWJmOTU3YzM0ZDIiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiU3RhdHVzTGlzdDIwMjFDcmVkZW50aWFsIl0sImlzc3VlciI6ImRpZDprZXk6ejZNa3ZNTDZvd1VFdndVcjhQN3FzWUFObnpUQkFORHExYkJSS2RwWG9EdlRBNnNxIiwiaXNzdWFuY2VEYXRlIjoiMjAyMy0wMS0zMFQyMTo0NzozOVoiLCJjcmVkZW50aWFsU3ViamVjdCI6eyJlbmNvZGVkTGlzdCI6Ikg0c0lBQUFBQUFBQS8rekFRUWtBSUJSQXNTZVkxOEtXRVZQOHk5YTN6ZzBBQUFBQUFBQUFBQUFBZ0hHN2VnRUFBUC8vRkU1TysrZ3RBQUE9IiwiaWQiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvdjEvY3JlZGVudGlhbHMvc3RhdHVzLzU2YmY4NWU0LTgyZWQtNDlkNi04MDRkLTlhYmY5NTdjMzRkMiIsInN0YXR1c1B1cnBvc2UiOiJyZXZvY2F0aW9uIiwidHlwZSI6IlN0YXR1c0xpc3QyMDIxIn0sImNyZWRlbnRpYWxTY2hlbWEiOnsiaWQiOiJkMzUwMTA4MC03ZjJmLTRiNjMtOTUyYy1jMjQzYjZmMWJkYjgiLCJ0eXBlIjoiSnNvblNjaGVtYVZhbGlkYXRvcjIwMTgifX19.ljbYI9h6zLJaWwJY__VrHjnQzVnRsQLq5HV4LlkyIxmcXyz60iyk1o_teS2FjmoSqvtZQO26iWE1vaAg_v1ODA"
}

Create Credential (same issuer and schema, same statusListCredential):
{
    "credential": {
        "@context": [
            "https://www.w3.org/2018/credentials/v1"
        ],
        "id": "8b7b2130-3d56-4ab0-a6e3-ab0e5bcf6161",
        "type": [
            "VerifiableCredential"
        ],
        "issuer": "did:key:z6MkvML6owUEvwUr8P7qsYANnzTBANDq1bBRKdpXoDvTA6sq",
        "issuanceDate": "2023-01-30T21:49:24Z",
        "expirationDate": "2051-10-05T14:48:00.000Z",
        "credentialStatus": {
            "id": "http://localhost:8080/v1/credentials/8b7b2130-3d56-4ab0-a6e3-ab0e5bcf6161/status",
            "statusListCredential": "http://localhost:8080/v1/credentials/status/56bf85e4-82ed-49d6-804d-9abf957c34d2",
            "statusListIndex": "125650",
            "statusPurpose": "revocation",
            "type": "StatusList2021Entry"
        },
        "credentialSubject": {
            "employedAt": "2022-08-20T13:20:10.000+0000",
            "givenName": "Alice",
            "id": "did:key:z6MkvML6owUEvwUr8P7qsYANnzTBANDq1bBRKdpXoDvTA6sq"
        },
        "credentialSchema": {
            "id": "d3501080-7f2f-4b63-952c-c243b6f1bdb8",
            "type": "JsonSchemaValidator2018"
        }
    },
    "credentialJwt": "eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa3ZNTDZvd1VFdndVcjhQN3FzWUFObnpUQkFORHExYkJSS2RwWG9EdlRBNnNxIiwidHlwIjoiSldUIn0.eyJleHAiOjI1ODAxMzAwODAsImlzcyI6ImRpZDprZXk6ejZNa3ZNTDZvd1VFdndVcjhQN3FzWUFObnpUQkFORHExYkJSS2RwWG9EdlRBNnNxIiwianRpIjoiOGI3YjIxMzAtM2Q1Ni00YWIwLWE2ZTMtYWIwZTViY2Y2MTYxIiwibmJmIjoxNjc1MTE1MzY0LCJzdWIiOiJkaWQ6a2V5Ono2TWt2TUw2b3dVRXZ3VXI4UDdxc1lBTm56VEJBTkRxMWJCUktkcFhvRHZUQTZzcSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIl0sImlkIjoiOGI3YjIxMzAtM2Q1Ni00YWIwLWE2ZTMtYWIwZTViY2Y2MTYxIiwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCJdLCJpc3N1ZXIiOiJkaWQ6a2V5Ono2TWt2TUw2b3dVRXZ3VXI4UDdxc1lBTm56VEJBTkRxMWJCUktkcFhvRHZUQTZzcSIsImlzc3VhbmNlRGF0ZSI6IjIwMjMtMDEtMzBUMjE6NDk6MjRaIiwiZXhwaXJhdGlvbkRhdGUiOiIyMDUxLTEwLTA1VDE0OjQ4OjAwLjAwMFoiLCJjcmVkZW50aWFsU3RhdHVzIjp7ImlkIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3YxL2NyZWRlbnRpYWxzLzhiN2IyMTMwLTNkNTYtNGFiMC1hNmUzLWFiMGU1YmNmNjE2MS9zdGF0dXMiLCJzdGF0dXNMaXN0Q3JlZGVudGlhbCI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC92MS9jcmVkZW50aWFscy9zdGF0dXMvNTZiZjg1ZTQtODJlZC00OWQ2LTgwNGQtOWFiZjk1N2MzNGQyIiwic3RhdHVzTGlzdEluZGV4IjoiMTI1NjUwIiwic3RhdHVzUHVycG9zZSI6InJldm9jYXRpb24iLCJ0eXBlIjoiU3RhdHVzTGlzdDIwMjFFbnRyeSJ9LCJjcmVkZW50aWFsU3ViamVjdCI6eyJlbXBsb3llZEF0IjoiMjAyMi0wOC0yMFQxMzoyMDoxMC4wMDArMDAwMCIsImdpdmVuTmFtZSI6IkFsaWNlIiwiaWQiOiJkaWQ6a2V5Ono2TWt2TUw2b3dVRXZ3VXI4UDdxc1lBTm56VEJBTkRxMWJCUktkcFhvRHZUQTZzcSJ9LCJjcmVkZW50aWFsU2NoZW1hIjp7ImlkIjoiZDM1MDEwODAtN2YyZi00YjYzLTk1MmMtYzI0M2I2ZjFiZGI4IiwidHlwZSI6Ikpzb25TY2hlbWFWYWxpZGF0b3IyMDE4In19fQ.m8kAkVtSAAe4vib0_YlndiTSsZ-tGMhCAJcA10Fd56kz1c6JbZeoDqs_lRncYP1cDnO_hTTdZQ6W-N6fwdeYDg"
}

Encoded List didn't Change
"encodedList":"H4sIAAAAAAAA/+zAQQkAIBRAsSeY18KWEVP8y9a3zg0AAAAAAAAAAAAAgHG7egEAAP//FE5O++gtAAA=",

Revoked 2nd cred
Status list changes - H4sIAAAAAAAA/+zOQQ0AIBADsJGcf3O4QAVBxR60CppnnR0AAAAAAAAAAAAAAOqmHQAAAIAfTHIDAAD//yY2kr5oPQAA


Create Credential(new schema)

{
    "credential": {
        "@context": [
            "https://www.w3.org/2018/credentials/v1"
        ],
        "id": "52a0d4bb-64af-46e4-b1ca-a7ba7940e9b2",
        "type": [
            "VerifiableCredential"
        ],
        "issuer": "did:key:z6MkvML6owUEvwUr8P7qsYANnzTBANDq1bBRKdpXoDvTA6sq",
        "issuanceDate": "2023-01-30T21:51:31Z",
        "expirationDate": "2051-10-05T14:48:00.000Z",
        "credentialStatus": {
            "id": "http://localhost:8080/v1/credentials/52a0d4bb-64af-46e4-b1ca-a7ba7940e9b2/status",
            "statusListCredential": "http://localhost:8080/v1/credentials/status/a5bc3d7f-d850-46fd-a4b8-8f65adb13ba2",
            "statusListIndex": "59681",
            "statusPurpose": "revocation",
            "type": "StatusList2021Entry"
        },
        "credentialSubject": {
            "employedAt": "2022-08-20T13:20:10.000+0000",
            "givenName": "Alice",
            "id": "did:key:z6MkvML6owUEvwUr8P7qsYANnzTBANDq1bBRKdpXoDvTA6sq"
        },
        "credentialSchema": {
            "id": "83cf658e-85a8-444d-8363-9822c135ac42",
            "type": "JsonSchemaValidator2018"
        }
    },
    "credentialJwt": "eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDprZXk6ejZNa3ZNTDZvd1VFdndVcjhQN3FzWUFObnpUQkFORHExYkJSS2RwWG9EdlRBNnNxIiwidHlwIjoiSldUIn0.eyJleHAiOjI1ODAxMzAwODAsImlzcyI6ImRpZDprZXk6ejZNa3ZNTDZvd1VFdndVcjhQN3FzWUFObnpUQkFORHExYkJSS2RwWG9EdlRBNnNxIiwianRpIjoiNTJhMGQ0YmItNjRhZi00NmU0LWIxY2EtYTdiYTc5NDBlOWIyIiwibmJmIjoxNjc1MTE1NDkxLCJzdWIiOiJkaWQ6a2V5Ono2TWt2TUw2b3dVRXZ3VXI4UDdxc1lBTm56VEJBTkRxMWJCUktkcFhvRHZUQTZzcSIsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIl0sImlkIjoiNTJhMGQ0YmItNjRhZi00NmU0LWIxY2EtYTdiYTc5NDBlOWIyIiwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCJdLCJpc3N1ZXIiOiJkaWQ6a2V5Ono2TWt2TUw2b3dVRXZ3VXI4UDdxc1lBTm56VEJBTkRxMWJCUktkcFhvRHZUQTZzcSIsImlzc3VhbmNlRGF0ZSI6IjIwMjMtMDEtMzBUMjE6NTE6MzFaIiwiZXhwaXJhdGlvbkRhdGUiOiIyMDUxLTEwLTA1VDE0OjQ4OjAwLjAwMFoiLCJjcmVkZW50aWFsU3RhdHVzIjp7ImlkIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3YxL2NyZWRlbnRpYWxzLzUyYTBkNGJiLTY0YWYtNDZlNC1iMWNhLWE3YmE3OTQwZTliMi9zdGF0dXMiLCJzdGF0dXNMaXN0Q3JlZGVudGlhbCI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC92MS9jcmVkZW50aWFscy9zdGF0dXMvYTViYzNkN2YtZDg1MC00NmZkLWE0YjgtOGY2NWFkYjEzYmEyIiwic3RhdHVzTGlzdEluZGV4IjoiNTk2ODEiLCJzdGF0dXNQdXJwb3NlIjoicmV2b2NhdGlvbiIsInR5cGUiOiJTdGF0dXNMaXN0MjAyMUVudHJ5In0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImVtcGxveWVkQXQiOiIyMDIyLTA4LTIwVDEzOjIwOjEwLjAwMCswMDAwIiwiZ2l2ZW5OYW1lIjoiQWxpY2UiLCJpZCI6ImRpZDprZXk6ejZNa3ZNTDZvd1VFdndVcjhQN3FzWUFObnpUQkFORHExYkJSS2RwWG9EdlRBNnNxIn0sImNyZWRlbnRpYWxTY2hlbWEiOnsiaWQiOiI4M2NmNjU4ZS04NWE4LTQ0NGQtODM2My05ODIyYzEzNWFjNDIiLCJ0eXBlIjoiSnNvblNjaGVtYVZhbGlkYXRvcjIwMTgifX19.-o9pU9ZAxMmw6Rso6rLwhCxMpkdgimMWrbEQffQ7xg8Yd-EuxYYR0RPncvYhIDjIsNgAWA8Pv_Jo-sgldJIgCQ"
}


Different statusCredentialList! :check:
```



codecov-commenter: # [Codecov](https://codecov.io/gh/TBD54566975/ssi-service/pull/272?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) Report
> Merging [#272](https://codecov.io/gh/TBD54566975/ssi-service/pull/272?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) (47bd006) into [main](https://codecov.io/gh/TBD54566975/ssi-service/commit/13ea9a07869343abeb74cb0f5d95baaa9a2ad28a?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) (13ea9a0) will **not change** coverage.
> The diff coverage is `n/a`.

```diff
@@           Coverage Diff           @@
##             main     #272   +/-   ##
=======================================
  Coverage   24.22%   24.22%           
=======================================
  Files          31       31           
  Lines        3142     3142           
=======================================
  Hits          761      761           
  Misses       2263     2263           
  Partials      118      118           
```



Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975)


Patch:
diff --git a/go.mod b/go.mod
index 3be72b1..2a085ef 100644
--- a/go.mod
+++ b/go.mod
@@ -4,14 +4,14 @@ go 1.19
 
 require (
 	github.com/BurntSushi/toml v1.2.1
-	github.com/TBD54566975/ssi-sdk v0.0.2-alpha.0.20221214220628-e2badfb960fa
+	github.com/TBD54566975/ssi-sdk v0.0.2-alpha.0.20230131192959-6519a59e9e5e
 	github.com/alicebob/miniredis/v2 v2.30.0
 	github.com/ardanlabs/conf v1.5.0
 	github.com/benbjohnson/clock v1.3.0
 	github.com/cenkalti/backoff/v4 v4.2.0
 	github.com/dimfeld/httptreemux/v5 v5.5.0
 	github.com/go-playground/locales v0.14.1
-	github.com/go-playground/universal-translator v0.18.0
+	github.com/go-playground/universal-translator v0.18.1
 	github.com/go-redis/redis/v8 v8.11.5
 	github.com/goccy/go-json v0.10.0
 	github.com/google/cel-go v0.13.0
@@ -41,14 +41,14 @@ require (
 require (
 	github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
 	github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect
-	github.com/bits-and-blooms/bitset v1.4.0 // indirect
+	github.com/bits-and-blooms/bitset v1.5.0 // indirect
 	github.com/cespare/xxhash/v2 v2.1.2 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 	github.com/go-logr/logr v1.2.3 // indirect
 	github.com/go-logr/stdr v1.2.2 // indirect
-	github.com/go-playground/validator/v10 v10.11.1 // indirect
+	github.com/go-playground/validator/v10 v10.11.2 // indirect
 	github.com/leodido/go-urn v1.2.1 // indirect
 	github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect
 	github.com/lestrrat-go/blackmagic v1.0.1 // indirect
@@ -57,13 +57,13 @@ require (
 	github.com/lestrrat-go/option v1.0.0 // indirect
 	github.com/multiformats/go-base32 v0.1.0 // indirect
 	github.com/multiformats/go-base36 v0.1.0 // indirect
-	github.com/multiformats/go-multicodec v0.7.0 // indirect
+	github.com/multiformats/go-multicodec v0.8.0 // indirect
 	github.com/onsi/gomega v1.20.0 // indirect
 	github.com/piprate/json-gold v0.5.0 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/pquerna/cachecontrol v0.1.0 // indirect
 	github.com/rogpeppe/go-internal v1.8.1 // indirect
-	github.com/santhosh-tekuri/jsonschema/v5 v5.1.1 // indirect
+	github.com/santhosh-tekuri/jsonschema/v5 v5.2.0 // indirect
 	github.com/stoewer/go-strcase v1.2.0 // indirect
 	github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 // indirect
 	golang.org/x/sys v0.4.0 // indirect
diff --git a/go.sum b/go.sum
index 6d4f7bc..ec3c7e9 100644
--- a/go.sum
+++ b/go.sum
@@ -2,6 +2,8 @@ github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak
 github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
 github.com/TBD54566975/ssi-sdk v0.0.2-alpha.0.20221214220628-e2badfb960fa h1:d1O2F8c/AwCHmOOeQQFPySEz+Jou0EayyjM/66m6Vck=
 github.com/TBD54566975/ssi-sdk v0.0.2-alpha.0.20221214220628-e2badfb960fa/go.mod h1:GIfJZUiXKxnyFJs3H0SLoFL5tVezav6p5Zcs8TddKJE=
+github.com/TBD54566975/ssi-sdk v0.0.2-alpha.0.20230131192959-6519a59e9e5e h1:QFCDIImupc/3uAFqDs725eJgqvLJGjxMstMhi+9li4I=
+github.com/TBD54566975/ssi-sdk v0.0.2-alpha.0.20230131192959-6519a59e9e5e/go.mod h1:3cemvvTGIjWZN8kZ2NJ3T+P/Ra7kNvDPoyy0xw6ngCQ=
 github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk=
 github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
 github.com/alicebob/miniredis/v2 v2.30.0 h1:uA3uhDbCxfO9+DI/DuGeAMr9qI+noVWwGPNTFuKID5M=
@@ -14,6 +16,8 @@ github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT
 github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
 github.com/bits-and-blooms/bitset v1.4.0 h1:+YZ8ePm+He2pU3dZlIZiOeAKfrBkXi1lSrXJ/Xzgbu8=
 github.com/bits-and-blooms/bitset v1.4.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
+github.com/bits-and-blooms/bitset v1.5.0 h1:NpE8frKRLGHIcEzkR+gZhiioW1+WbYV6fKwD6ZIpQT8=
+github.com/bits-and-blooms/bitset v1.5.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
 github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
 github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
 github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
@@ -41,13 +45,18 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
 github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
 github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
 github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
 github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
 github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
 github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
 github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
 github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
 github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
 github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
+github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
+github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
 github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
 github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
 github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
@@ -102,6 +111,8 @@ github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyD
 github.com/multiformats/go-multibase v0.1.1/go.mod h1:ZEjHE+IsUrgp5mhlEAYjMtZwK1k4haNkcaPg9aoe1a8=
 github.com/multiformats/go-multicodec v0.7.0 h1:rTUjGOwjlhGHbEMbPoSUJowG1spZTVsITRANCjKTUAQ=
 github.com/multiformats/go-multicodec v0.7.0/go.mod h1:GUC8upxSBE4oG+q3kWZRw/+6yC1BqO550bjhWsJbZlw=
+github.com/multiformats/go-multicodec v0.8.0 h1:evBmgkbSQux+Ds2IgfhkO38Dl2GDtRW8/Rp6YiSHX/Q=
+github.com/multiformats/go-multicodec v0.8.0/go.mod h1:GUC8upxSBE4oG+q3kWZRw/+6yC1BqO550bjhWsJbZlw=
 github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
 github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
 github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
@@ -127,6 +138,8 @@ github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo=
 github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
 github.com/santhosh-tekuri/jsonschema/v5 v5.1.1 h1:lEOLY2vyGIqKWUI9nzsOJRV3mb3WC9dXYORsLEUcoeY=
 github.com/santhosh-tekuri/jsonschema/v5 v5.1.1/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0=
+github.com/santhosh-tekuri/jsonschema/v5 v5.2.0 h1:WCcC4vZDS1tYNxjWlwRJZQy28r8CMoggKnxNzxsVDMQ=
+github.com/santhosh-tekuri/jsonschema/v5 v5.2.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0=
 github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
 github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU=
diff --git a/pkg/service/credential/service.go b/pkg/service/credential/service.go
index 58ce79b..ec110df 100644
--- a/pkg/service/credential/service.go
+++ b/pkg/service/credential/service.go
@@ -178,7 +178,7 @@ func (s Service) createCredentialBusinessLogic(ctx context.Context, request Crea
 		issuerID := request.Issuer
 		schemaID := request.JSONSchema
 
-		statusListCredential, err := getStatusListCredential(ctx, s, issuerID, schemaID)
+		statusListCredential, err := getOrCreateStatusListCredential(ctx, s, issuerID, schemaID, tx)
 		if err != nil {
 			return nil, util.LoggingErrorMsgf(err, "problem with getting status list credential")
 		}
@@ -188,6 +188,10 @@ func (s Service) createCredentialBusinessLogic(ctx context.Context, request Crea
 			return nil, util.LoggingErrorMsg(err, "problem with getting status list index")
 		}
 
+		if err := s.storage.IncrementStatusListIndexTx(ctx, tx); err != nil {
+			return nil, errors.Wrap(err, "incrementing status list index")
+		}
+
 		status := statussdk.StatusList2021Entry{
 			ID:                   fmt.Sprintf(`%s/v1/credentials/%s/status`, s.config.ServiceEndpoint, credID),
 			Type:                 statussdk.StatusList2021EntryType,
@@ -199,29 +203,6 @@ func (s Service) createCredentialBusinessLogic(ctx context.Context, request Crea
 		if err := builder.SetCredentialStatus(status); err != nil {
 			return nil, util.LoggingErrorMsg(err, "could not set credential status")
 		}
-
-		statusListCredJWT, err := s.signCredentialJWT(ctx, request.Issuer, *statusListCredential)
-		if err != nil {
-			return nil, util.LoggingErrorMsg(err, "could not sign status list credential")
-		}
-
-		statusListContainer := credint.Container{
-			ID:            statusListCredential.ID,
-			Credential:    statusListCredential,
-			CredentialJWT: statusListCredJWT,
-		}
-
-		statusListStorageRequest := StoreCredentialRequest{
-			Container: statusListContainer,
-		}
-
-		if err := s.storage.IncrementStatusListIndexTx(ctx, tx); err != nil {
-			return nil, errors.Wrap(err, "incrementing status list index")
-		}
-
-		if err := s.storage.StoreStatusListCredentialTx(ctx, statusListStorageRequest, tx); err != nil {
-			return nil, errors.Wrap(err, "storing status list credential")
-		}
 	}
 
 	cred, err := builder.Build()
@@ -261,7 +242,7 @@ func (s Service) createCredentialBusinessLogic(ctx context.Context, request Crea
 	return &response, nil
 }
 
-func getStatusListCredential(ctx context.Context, s Service, issuerID string, schemaID string) (*credential.VerifiableCredential, error) {
+func getOrCreateStatusListCredential(ctx context.Context, s Service, issuerID string, schemaID string, tx storage.Tx) (*credential.VerifiableCredential, error) {
 	storedStatusListCreds, err := s.storage.GetStatusListCredentialsByIssuerAndSchema(ctx, issuerID, schemaID)
 	if err != nil {
 		return nil, util.LoggingNewErrorf("getting status list credential for issuer: %s schema: %s", issuerID, schemaID)
@@ -283,6 +264,33 @@ func getStatusListCredential(ctx context.Context, s Service, issuerID string, sc
 		}
 
 		statusListCredential = generatedStatusListCredential
+
+		if schemaID != "" {
+			credSchema := credential.CredentialSchema{
+				ID:   schemaID,
+				Type: SchemaLDType,
+			}
+			statusListCredential.CredentialSchema = &credSchema
+		}
+
+		statusListCredJWT, err := s.signCredentialJWT(ctx, issuerID, *statusListCredential)
+		if err != nil {
+			return nil, util.LoggingErrorMsg(err, "could not sign status list credential")
+		}
+
+		statusListContainer := credint.Container{
+			ID:            statusListCredential.ID,
+			Credential:    statusListCredential,
+			CredentialJWT: statusListCredJWT,
+		}
+
+		statusListStorageRequest := StoreCredentialRequest{
+			Container: statusListContainer,
+		}
+
+		if err := s.storage.StoreStatusListCredentialTx(ctx, statusListStorageRequest, tx); err != nil {
+			return nil, errors.Wrap(err, "storing status list credential")
+		}
 	} else {
 		statusListCredential = storedStatusListCreds[0].Credential
 	}
@@ -571,6 +579,8 @@ func updateCredentialStatus(ctx context.Context, s Service, gotCred *StoredCrede
 		return nil, util.LoggingErrorMsg(err, "could not generate status list")
 	}
 
+	generatedStatusListCredential.CredentialSchema = gotCred.Credential.CredentialSchema
+
 	statusListCredJWT, err := s.signCredentialJWT(ctx, gotCred.Issuer, *generatedStatusListCredential)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not sign status list credential")


Test patch:
diff --git a/integration/credential_revocation_integration_test.go b/integration/credential_revocation_integration_test.go
index 700615d..5488e3f 100644
--- a/integration/credential_revocation_integration_test.go
+++ b/integration/credential_revocation_integration_test.go
@@ -3,6 +3,9 @@ package integration
 import (
 	"testing"
 
+	"github.com/TBD54566975/ssi-sdk/credential"
+	"github.com/TBD54566975/ssi-sdk/credential/status"
+	"github.com/goccy/go-json"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -60,6 +63,11 @@ func TestRevocationCreateVerifiableCredentialIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, vcOutput)
 
+	cred, err := getJSONElement(vcOutput, "$.credential")
+	SetValue(credentialRevocationContext, "cred", cred)
+	assert.NoError(t, err)
+	assert.NotEmpty(t, cred)
+
 	credStatusURL, err := getJSONElement(vcOutput, "$.credential.credentialStatus.id")
 	SetValue(credentialRevocationContext, "credStatusURL", credStatusURL)
 	assert.NoError(t, err)
@@ -142,6 +150,42 @@ func TestRevocationCheckStatusListCredentialIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, encodedListOriginal)
 
-	// TODO: (Neal) Fix Revocation Bug https://github.com/TBD54566975/ssi-service/issues/264
-	// assert.NotEqual(t, encodedListOriginal.(string), encodedList)
+	assert.NotEqual(t, encodedListOriginal.(string), encodedList)
+}
+
+func TestRevocationValidateCredentialInStatusListIntegration(t *testing.T) {
+	if testing.Short() {
+		t.Skip("skipping integration test")
+	}
+
+	credJSON, err := GetValue(credentialRevocationContext, "cred")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, credJSON)
+
+	var vc credential.VerifiableCredential
+	err = json.Unmarshal([]byte(credJSON.(string)), &vc)
+	assert.NoError(t, err)
+	assert.NotEmpty(t, vc)
+
+	statusListCredentialURL, err := GetValue(credentialRevocationContext, "statusListCredentialURL")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, statusListCredentialURL)
+
+	credStatusListCredentialOutput, err := get(statusListCredentialURL.(string))
+	assert.NoError(t, err)
+	assert.NotEmpty(t, credStatusListCredentialOutput)
+
+	credStatusListCredentialJSON, err := getJSONElement(credStatusListCredentialOutput, "$.credential")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, credStatusListCredentialJSON)
+
+	var vcStatusList credential.VerifiableCredential
+	err = json.Unmarshal([]byte(credStatusListCredentialJSON), &vcStatusList)
+	assert.NoError(t, err)
+	assert.NotEmpty(t, vcStatusList)
+
+	// Validate the StatusListIndex in flipped in the credStatusList
+	valid, err := status.ValidateCredentialInStatusList(vc, vcStatusList)
+	assert.NoError(t, err)
+	assert.True(t, valid)
 }
diff --git a/pkg/server/router/credential_test.go b/pkg/server/router/credential_test.go
index 8a6ea9e..e207e46 100644
--- a/pkg/server/router/credential_test.go
+++ b/pkg/server/router/credential_test.go
@@ -3,14 +3,17 @@ package router
 import (
 	"context"
 	"fmt"
+	"strings"
 	"testing"
 	"time"
 
 	credsdk "github.com/TBD54566975/ssi-sdk/credential"
+	"github.com/TBD54566975/ssi-sdk/credential/status"
 	"github.com/TBD54566975/ssi-sdk/crypto"
 	didsdk "github.com/TBD54566975/ssi-sdk/did"
 	"github.com/stretchr/testify/assert"
 
+	"github.com/goccy/go-json"
 	"github.com/tbd54566975/ssi-service/config"
 	"github.com/tbd54566975/ssi-service/pkg/service/credential"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
@@ -274,5 +277,256 @@ func TestCredentialRouter(t *testing.T) {
 		assert.Contains(tt, credStatusMapTwo["statusListCredential"], "v1/credentials/status")
 		assert.NotEmpty(tt, credStatusMapTwo["statusListIndex"])
 
+		// Cred with same <issuer, schema> pair share the same statusListCredential
+		assert.Equal(tt, credStatusMapTwo["statusListCredential"], credStatusMap["statusListCredential"])
+
+		createdSchemaTwo, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: "me", Name: "simple schema", Schema: emailSchema})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdSchemaTwo)
+
+		createdCredThree, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
+			Issuer:     issuer,
+			Subject:    subject,
+			JSONSchema: createdSchemaTwo.ID,
+			Data: map[string]any{
+				"email": "Satoshi2@Nakamoto2.btc",
+			},
+			Expiry:    time.Now().Add(24 * time.Hour).Format(time.RFC3339),
+			Revocable: true,
+		})
+
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdCredThree)
+		assert.NotEmpty(tt, createdCredThree.CredentialJWT)
+
+		credStatusMapThree, ok := createdCredThree.Credential.CredentialStatus.(map[string]any)
+		assert.True(tt, ok)
+
+		assert.Contains(tt, credStatusMapThree["id"], fmt.Sprintf("v1/credentials/%s/status", createdCredThree.ID))
+		assert.Contains(tt, credStatusMapThree["statusListCredential"], "v1/credentials/status")
+		assert.NotEmpty(tt, credStatusMapThree["statusListIndex"])
+
+		// Cred with different <issuer, schema> pair have different statusListCredential
+		assert.NotEqual(tt, credStatusMapThree["statusListCredential"], credStatusMap["statusListCredential"])
+	})
+
+	t.Run("Credential Status List Test No Schemas", func(tt *testing.T) {
+		bolt := setupTestDB(tt)
+		assert.NotNil(tt, bolt)
+
+		serviceConfig := config.CredentialServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "credential"}}
+		keyStoreService := testKeyStoreService(tt, bolt)
+		didService := testDIDService(tt, bolt, keyStoreService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credService, err := credential.NewCredentialService(serviceConfig, bolt, keyStoreService, didService.GetResolver(), schemaService)
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, credService)
+
+		// check type and status
+		assert.Equal(tt, framework.Credential, credService.Type())
+		assert.Equal(tt, framework.StatusReady, credService.Status().Status)
+
+		// create a did
+		issuerDID, err := didService.CreateDIDByMethod(context.Background(), did.CreateDIDRequest{Method: didsdk.KeyMethod, KeyType: crypto.Ed25519})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, issuerDID)
+
+		issuer := issuerDID.DID.ID
+		subject := "did:test:345"
+
+		createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
+			Issuer:  issuer,
+			Subject: subject,
+			Data: map[string]any{
+				"email": "Satoshi@Nakamoto.btc",
+			},
+			Expiry:    time.Now().Add(24 * time.Hour).Format(time.RFC3339),
+			Revocable: true,
+		})
+
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdCred)
+		assert.NotEmpty(tt, createdCred.CredentialJWT)
+
+		credStatusMap, ok := createdCred.Credential.CredentialStatus.(map[string]any)
+		assert.True(tt, ok)
+
+		assert.Contains(tt, credStatusMap["id"], fmt.Sprintf("v1/credentials/%s/status", createdCred.ID))
+		assert.Contains(tt, credStatusMap["statusListCredential"], "v1/credentials/status")
+		assert.NotEmpty(tt, credStatusMap["statusListIndex"])
+
+		createdCredTwo, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
+			Issuer:  issuer,
+			Subject: subject,
+			Data: map[string]any{
+				"email": "Satoshi2@Nakamoto2.btc",
+			},
+			Expiry:    time.Now().Add(24 * time.Hour).Format(time.RFC3339),
+			Revocable: true,
+		})
+
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdCredTwo)
+		assert.NotEmpty(tt, createdCredTwo.CredentialJWT)
+
+		credStatusMapTwo, ok := createdCredTwo.Credential.CredentialStatus.(map[string]any)
+		assert.True(tt, ok)
+
+		assert.Contains(tt, credStatusMapTwo["id"], fmt.Sprintf("v1/credentials/%s/status", createdCredTwo.ID))
+		assert.Contains(tt, credStatusMapTwo["statusListCredential"], "v1/credentials/status")
+		assert.NotEmpty(tt, credStatusMapTwo["statusListIndex"])
+
+		// Cred with same <issuer, schema> pair share the same statusListCredential
+		assert.Equal(tt, credStatusMapTwo["statusListCredential"], credStatusMap["statusListCredential"])
+
+		emailSchema := map[string]any{
+			"type": "object",
+			"properties": map[string]any{
+				"email": map[string]any{
+					"type": "string",
+				},
+			},
+			"required":             []any{"email"},
+			"additionalProperties": false,
+		}
+
+		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: "me", Name: "simple schema", Schema: emailSchema})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdSchema)
+
+		createdCredThree, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
+			Issuer:     issuer,
+			Subject:    subject,
+			JSONSchema: createdSchema.ID,
+			Data: map[string]any{
+				"email": "Satoshi2@Nakamoto2.btc",
+			},
+			Expiry:    time.Now().Add(24 * time.Hour).Format(time.RFC3339),
+			Revocable: true,
+		})
+
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdCredThree)
+		assert.NotEmpty(tt, createdCredThree.CredentialJWT)
+
+		credStatusMapThree, ok := createdCredThree.Credential.CredentialStatus.(map[string]any)
+		assert.True(tt, ok)
+
+		assert.Contains(tt, credStatusMapThree["id"], fmt.Sprintf("v1/credentials/%s/status", createdCredThree.ID))
+		assert.Contains(tt, credStatusMapThree["statusListCredential"], "v1/credentials/status")
+		assert.NotEmpty(tt, credStatusMapThree["statusListIndex"])
+
+		// Cred with different <issuer, schema> pair have different statusListCredential
+		assert.NotEqual(tt, credStatusMapThree["statusListCredential"], credStatusMap["statusListCredential"])
+	})
+
+	t.Run("Credential Status List Test Update Revoked Status", func(tt *testing.T) {
+		bolt := setupTestDB(tt)
+		assert.NotNil(tt, bolt)
+
+		serviceConfig := config.CredentialServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "credential", ServiceEndpoint: "http://localhost:1234"}}
+		keyStoreService := testKeyStoreService(tt, bolt)
+		didService := testDIDService(tt, bolt, keyStoreService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credService, err := credential.NewCredentialService(serviceConfig, bolt, keyStoreService, didService.GetResolver(), schemaService)
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, credService)
+
+		// check type and status
+		assert.Equal(tt, framework.Credential, credService.Type())
+		assert.Equal(tt, framework.StatusReady, credService.Status().Status)
+
+		// create a did
+		issuerDID, err := didService.CreateDIDByMethod(context.Background(), did.CreateDIDRequest{Method: didsdk.KeyMethod, KeyType: crypto.Ed25519})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, issuerDID)
+
+		// create a schema
+		emailSchema := map[string]any{
+			"type": "object",
+			"properties": map[string]any{
+				"email": map[string]any{
+					"type": "string",
+				},
+			},
+			"required":             []any{"email"},
+			"additionalProperties": false,
+		}
+
+		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: "me", Name: "simple schema", Schema: emailSchema})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdSchema)
+
+		issuer := issuerDID.DID.ID
+		subject := "did:test:345"
+
+		createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
+			Issuer:     issuer,
+			Subject:    subject,
+			JSONSchema: createdSchema.ID,
+			Data: map[string]any{
+				"email": "Satoshi@Nakamoto.btc",
+			},
+			Expiry:    time.Now().Add(24 * time.Hour).Format(time.RFC3339),
+			Revocable: true,
+		})
+
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdCred)
+		assert.NotEmpty(tt, createdCred.CredentialJWT)
+
+		statusBytes, err := json.Marshal(createdCred.Credential.CredentialStatus)
+		assert.NoError(tt, err)
+
+		var statusEntry status.StatusList2021Entry
+		err = json.Unmarshal(statusBytes, &statusEntry)
+		assert.NoError(tt, err)
+
+		assert.Contains(tt, statusEntry.ID, fmt.Sprintf("http://localhost:1234/v1/credentials/%s/status", createdCred.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: createdCred.ID})
+		assert.NoError(tt, err)
+		assert.Equal(tt, credStatus.Revoked, false)
+
+		credStatusListStr := statusEntry.StatusListCredential
+
+		credStatusListID := strings.Split(credStatusListStr, "/")[len(strings.Split(credStatusListStr, "/"))-1]
+		credStatusList, err := credService.GetCredentialStatusList(context.Background(), credential.GetCredentialStatusListRequest{ID: credStatusListID})
+		assert.NoError(tt, err)
+		assert.Equal(tt, credStatusList.Credential.ID, statusEntry.StatusListCredential)
+
+		credentialSubject := credStatusList.Container.Credential.CredentialSubject
+		assert.NotEmpty(tt, credentialSubject)
+
+		encodedList := credentialSubject["encodedList"]
+		assert.NotEmpty(tt, encodedList)
+
+		// Validate the StatusListIndex in not flipped in the credStatusList
+		valid, err := status.ValidateCredentialInStatusList(*createdCred.Credential, *credStatusList.Credential)
+		assert.NoError(tt, err)
+		assert.False(tt, valid)
+
+		updatedStatus, err := credService.UpdateCredentialStatus(context.Background(), credential.UpdateCredentialStatusRequest{ID: createdCred.ID, Revoked: true})
+		assert.NoError(tt, err)
+		assert.Equal(tt, updatedStatus.Revoked, true)
+
+		credStatusListAfterRevoke, err := credService.GetCredentialStatusList(context.Background(), credential.GetCredentialStatusListRequest{ID: credStatusListID})
+		assert.NoError(tt, err)
+		assert.Equal(tt, credStatusListAfterRevoke.Credential.ID, statusEntry.StatusListCredential)
+
+		// Validate the StatusListIndex in flipped in the credStatusList
+		valid, err = status.ValidateCredentialInStatusList(*createdCred.Credential, *credStatusListAfterRevoke.Credential)
+		assert.NoError(tt, err)
+		assert.True(tt, valid)
+
+		credentialSubjectAfterRevoke := credStatusListAfterRevoke.Container.Credential.CredentialSubject
+		assert.NotEmpty(tt, credentialSubjectAfterRevoke)
+
+		encodedListAfterRevoke := credentialSubjectAfterRevoke["encodedList"]
+		assert.NotEmpty(tt, encodedListAfterRevoke)
+
+		assert.NotEqualValues(tt, encodedListAfterRevoke, encodedList)
 	})
 }