---
# System prepended metadata

title: Wallet - Credential Issuance

---

# Wallet - Credential Issuance


# Sequence Diagram

:warning: **WIP. NOT COMPLETE**

```mermaid
sequenceDiagram

  autonumber
  participant WP as Web Page
  actor A as Alice
  participant BG as Wallet
  participant UI as Wallet UI
  
  WP->>WP: Render "Apply for X" button/link
  A->>WP: Click button
  WP->>BG: web5.credentials.apply(manifest_link)
  BG->>UI: { cmd: CRED_APP, data: manifest_link }
  UI->>UI: fetch CM using manifest_link
  UI->>UI: process CM
```


# Rendering a Credential Application Form

![example-vc-app-form](https://i.imgur.com/RFJIxmg.png)


:warning: **NOTE: This section is incomplete**

:warning: **TODO**: Get answers to [these questions](https://hackmd.io/EBTNW-42Q_2bjSldeFvzEA?view#Credential-Manifest) in order to finish this section

## Context
No one has verifiable credentials yet so we're dealing with a cold start. This means that we'll need to support the ability to present a user with a form that they fill out in order to apply for a credential. The user provided-input will be used to generate a self-issued verifiable credential. This verifiable credential is then added to a [Credential Application](https://identity.foundation/credential-manifest/#credential-application) (in addition to the other required fields like `presentation_submission`) and shipped off to the issuer.

## Required Steps
- Use`presentation_definition.input_descriptors[*].fields` to render a form that is presented to the user to fill out
- _User fills out form and hits submit_
- Use user-provided input to generate a self-issued verifiable credential by following these steps:
  - Create an empty object, VC
  - Populate it with any static VC fields (e.g. `@context`)
  - Use the user's selected DID to populate `issuer` and `credentialSubject.id`
  - Use `$.presentation_definition.input_descriptors[*].fields[*].path` to place user-provided input into the expected locations within the VC
  - Make the VC verifiable by constructing a `vc-jwt` 
    - include appropriate `kid` in JWT header
    - set appropriate `alg` in JWT header based on the key being used to sign
    - set `sub` and `iss` to the user's selected DID
    - Sign the JWT using the key associated to the user's selected DID identified by the `kid` set in the JWT header
  
- Construct a [Credential Application](https://identity.foundation/credential-manifest/#credential-application) object
  - set `spec_version` to `https://identity.foundation/credential-manifest/spec/v1.0.0/`
  - set `id` to some rando uuid
  - set `manifest_id` to the id of the credential manifest used to render the form
  - set `format` to an acceptable format
    - :warning: highly considering limiting `format` to just `vc-jwt` / `EdDSA` for steel thread
  - create `presentation_submission` object
    - set `id` to some rando uuid
    - set `definition_id` to the id of the appropriate `presentation_definition` object used to render the form
    - create `descriptor_map` object
      - set `id` to id of the appropriate `input_descriptor`object used to render the form
      - set `path` to `$.verifiableCredential[0]`
        - :warning: **NOTE**: hardcoding to `$.verifiableCredential[0]` because i'm limiting scope to a single credential for the steel thread. supporting additional credentials will be a stretch goal that i won't hit
  - create a `verifiableCredential` array
    - add JWT'ified VC
- Ship Credential Application to Issuer


# Credential Manifest Example
KYC Example

```json=
{
  "id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
  "spec_version": "https://identity.foundation/credential-manifest/spec/v1.0.0/",
  "output_descriptors": [
    {
      "id": "kyc_credential",
      "schema": "https://compliance-is-kewl.com/json-schemas/kyc.json"
    }
  ],
  "presentation_definition": {
    "id": "32f54163-7166-48f1-93d8-ff217bdb0653",
    "name": "KYC Requirements",
    "purpose": "TBD. i donno rn",
    "format": {
      "jwt": {
        "alg": [
          "EdDSA"
        ]
      }
    },
    "input_descriptors": [
      {
        "id": "kyc1",
        "name": "Personal Info",
        "constraints": {
          "subject_is_issuer": "required"
          "fields": [
            {
              "id": "kycSchema",
              "path": [
                "$.vc.credentialSchema.id"
              ],
              "filter": {
                "type": "string",
                "const": "https://compliance-is-kewl.com/json-schemas/kyc.json"
              }
            },
            {
              "name": "First Name"
              "id": "givenName",
              "path": [
                "$.vc.credentialSubject.givenName"
              ],
              "filter": {
                "type": "string",
                "pattern": "[a-zA-Z \\-\\.].+"
              }
            },
            {
              "id": "additionalName",
              "path": [
                "$.vc.credentialSubject.additionalName"
              ],
              "filter": {
                "type": "string",
                "pattern": "[a-zA-Z \\-\\.].+"
              }
            },
            {
              "id": "familyName",
              "path": [
                "$.vc.credentialSubject.familyName"
              ],
              "filter": {
                "type": "string",
                "pattern": "[a-zA-Z \\-\\.].+"
              }
            },
            {
              "id": "birthDate",
              "path": [
                "$.vc.credentialSubject.birthDate"
              ],
              "filter": {
                "type": "string",
                "format": "date"
              }
            },
            {
              "id": "postalAddress",
              "path": [
                "$.vc.credentialSubject.postalAddress"
              ],
              "filter": {
                "type": "string"
              }
            },
            {
              "id": "taxID",
              "path": [
                "$.vc.credentialSubject.taxID"
              ],
              "filter": {
                "type": "string"
              }
            }
          ]
        }
      }
    ]
  }
}
```

# Credential Application Example
```json=
{
  "id": "c0c6e312-ad44-4f18-935e-a6efaad91612",
  "spec_version": "https://identity.foundation/credential-manifest/spec/v1.0.0/",
  "manifest_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
  "format": {
    "jwt_vc": {
      "alg": [
        "EdDSA"
      ]
    }
  },
  "presentation_submission": {
    "id": "00239c16-3e64-4438-8dda-641e963fa853",
    "definition_id": "32f54163-7166-48f1-93d8-ff217bdb0653",
    "descriptor_map": [
      {
        "id": "kyc1",
        "format": "vc-jwt",
        "path": "$.verifiableCredential[0]"
      }
    ]
  },
  "verifiableCredential": [
    "eyJraWQiOiJkaWQ6amFua3k6YWxpY2UjZGlkOmphbmt5OmFsaWNlIiwiYWxnIjoiRWREU0EifQ.eyJpc3MiOiJkaWQ6amFua3k6YWxpY2UiLCJzdWIiOiJkaWQ6amFua3k6YWxpY2UiLCJ2YyI6eyJAY29udGV4dCI6WyJodHRwczpcL1wvd3d3LnczLm9yZ1wvMjAxOFwvY3JlZGVudGlhbHNcL3YxIl0sInR5cGUiOlsiS3ljQ3JlZGVudGlhbCJdLCJpc3N1ZXIiOiJkaWQ6amFua3k6YWxpY2UiLCJpc3N1YW5jZURhdGUiOiIyMDIyLTA5LTI5VDAwOjAwOjAwWiIsImNyZWRlbnRpYWxTY2hlbWEiOnsiaWQiOiJodHRwczpcL1wvY29tcGxpYW5jZS1pcy1rZXdsLmNvbVwvanNvbi1zY2hlbWFzXC9reWMuanNvbiIsInR5cGUiOiJKc29uU2NoZW1hVmFsaWRhdG9yMjAxOCJ9LCJjcmVkZW50aWFsU3ViamVjdCI6eyJpZCI6ImRpZDpqYW5reTphbGljZSIsImdpdmVuTmFtZSI6IlJhbmR5IiwiYWRkaXRpb25hbE5hbWUiOiJOXC9BIiwiZmFtaWx5TmFtZSI6Ik1jSmFua3kiLCJiaXJ0aERhdGUiOiIxOTg4LTAzLTI4IiwicG9zdGFsQWRkcmVzcyI6eyJhZGRyZXNzQ291bnRyeSI6IlVTQSIsImFkZHJlc3NMb2NhbGl0eSI6IkF1c3RpbiIsImFkZHJlc3NSZWdpb24iOiJUWCIsInBvc3RhbENvZGUiOiI3ODcyNCIsInN0cmVldEFkZHJlc3MiOiIxMjMgSmFua3RvcGlhIEF2ZS4ifSwidGF4SUQiOiIxMjMtNDUtNjc4OSJ9fX0.OIga_ix7x4Tk4fEThfu_akXCVuI0aZ770CSSztSJ1NkBiGm4V_NOSQRk0EOo3heh6F6LiK9g9sa_527rNH_wCw"
  ]
}
```

## Decoded Verifiable Credential
the VC in the example above (1st element of the `verifiableCredential`) property is a JWT (specifically `vc-jwt`). Head over to [jwt.io](https://jwt.io/) and copy paste the long ugly string. the output should match the JSON object below

```json=
{
  "vc": {
    "@context": ["https://www.w3.org/2018/credentials/v1"],
    "type": ["KycCredential"],
    "issuer": "did:janky:alice",
    "issuanceDate": "2022-09-29T00:00:00Z",
    "credentialSchema": {
      "id": "https://compliance-is-kewl.com/json-schemas/kyc.json",
      "type": "JsonSchemaValidator2018"
    },
    "credentialSubject": {
      "id": "did:janky:alice",
      "givenName": "Randy",
      "additionalName": "N/A",
      "familyName": "McJanky",
      "birthDate": "1988-03-28",
      "postalAddress": {
        "addressCountry": "USA",
        "addressLocality": "Austin",
        "addressRegion": "TX",
        "postalCode": "78724",
        "streetAddress": "7405 Janktopia Ave."
      },
      "taxID": "123-45-6789"
    }
  },
  "iss": "did:janky:alice",
  "sub": "did:janky:alice"
}
```

# Questions

## Credential Manifest
is [`is_holder`](https://identity.foundation/presentation-exchange/#relational-constraint-feature) required in `constraints` if we have to generate a credential?
- na bruvv. not needed


---

is [`same_subject`](https://identity.foundation/presentation-exchange/#relational-constraint-feature) required in `constraints` if we have to generate a credential?
- na bruvv. not needed


---

does `$.presentation_definition[*].input_descriptors[*].filter` support `type: object`? For example, how do I target `postalAddress.addressLocality` in the example below?

```json=
{
  "vc": {
    "@context": ["https://www.w3.org/2018/credentials/v1"],
    "type": ["KycCredential"],
    "issuer": "did:janky:alice",
    "issuanceDate": "2022-09-29T00:00:00Z",
    "credentialSchema": {
      "id": "https://compliance-is-kewl.com/json-schemas/kyc.json",
      "type": "JsonSchemaValidator2018"
    },
    "credentialSubject": {
      "id": "did:janky:alice",
      "givenName": "Randy",
      "additionalName": "N/A",
      "familyName": "McJanky",
      "birthDate": "1988-03-28",
      "postalAddress": {
        "addressCountry": "USA",
        "addressLocality": "Austin",
        "addressRegion": "TX",
        "postalCode": "78724",
        "streetAddress": "7405 Janktopia Ave."
      },
      "taxID": "123-45-6789"
    }
  },
  "iss": "did:janky:alice",
  "sub": "did:janky:alice"
}
```

can `filter` be like...
```json=
{
  "type": "object",
  "properties": {
    "addressCountry": {
      "type": "string"
    },
    "addressLocality": {
      "type": "string"
    },
    "addressRegion": {
      "type": "string"
    },
    "postalCode": {
      "type": "string"
    },
    "streetAddress": {
      "type": "string"
    }
  },
  "required": [
    "addressCountry",
    "addressLocality",
    "addressRegion",
    "postalCode",
    "streetAddress"
  ]
}
```

---

Is there any way other than using `submission_requirements` to support an optional field? e.g. `middleName`. Include it if you have it. It'd be really annoying if optional fields aren't supported in a way aside from using `submission_requirements` wherein two `input_descriptor` objects are provided for the same group and only 1 must be satisfied. 1 `input_descriptor` would include the optional field in its `fields` array and one would exclude it.. thus creating support for optional fields (albeit in the worst way possible)

---

# Notes
- [`subject_is_issuer`](https://identity.foundation/presentation-exchange/#note-2)