# 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

: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)