Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Credo integration PR - squashed commits #38

Merged
merged 6 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .adr-dir
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
apps/vc-api/docs/architecture/decisions
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ const did = generateDID(key); // Code from ssi-did lib. Returns initial DID Docu
#### KMS Interface

## Technology Decisions
### Rationale for Spruce DIDKit
Spruce's DIDKit is used for DID generation and credential issuance & verification.
The rational for DIDKit's use is that it:
- Is written in Rust and so suitable for use in any mobile app development framework
- Supports JSON-LD and JWT credential issuance and verification
- Supports did:key, did:ethr, did:web
- DIDKit (and its libraries) are open-source

Architecture Decision Records are used to track technology and architecture decsions
(see [ADR 01](./apps/vc-api/docs/architecture/decisions/0001-record-architecture-decisions.md)).

The Architecture Decisions Records can be found [here](apps/vc-api/docs/architecture/decisions).

The [ADR Tools command line tool](https://github.com/npryce/adr-tools) can be used to add new ADRs.

## Installation
This repository is a monorepo that uses [Rush](https://rushjs.io/) with the PNPM package manager.
Expand Down
4 changes: 1 addition & 3 deletions apps/vc-api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
FROM node:18.19-alpine as base
FROM node:18.19 as base

WORKDIR /app

FROM base as builder

RUN apk add g++ make py3-pip

COPY common common
COPY rush.json .
COPY apps/vc-api/package.json apps/vc-api/package.json
Expand Down
6 changes: 3 additions & 3 deletions apps/vc-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ The key module allows for the import and export of key pairs.
A tutorial demonstrating this available here: [Key Export/Import Tutorial](./docs/tutorials/key-export-import-tutorial.md)

## Database
Currently, the app uses an **in-memory DB** for now for app execution and tests.
The rationale for this for executions that, as the app is only being used in a demo context, it is not necessary to persist data between executions.
The rationale for this for tests (rather than mocking the db) is that it speeds test writing time, elimates mocking boilerplate and possibly buggy DB mocks.
SQLite is used as the database engine.
See [ADR-003](./docs/architecture/decisions/0003-use-sqlite-for-credo-db.md) for rationale details.
Databases can be found at the `~/.vc-api`, by default.

## License

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 1. Record architecture decisions

Date: 2024-09-25

## Status

Accepted

## Context

We need to record the architectural decisions made on this project.

## Decision

We will use Architecture Decision Records, as [described by Michael Nygard](http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions).

## Consequences

See Michael Nygard's article, linked above. For a lightweight ADR toolset, see Nat Pryce's [adr-tools](https://github.com/npryce/adr-tools).
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 2. Use Credo for key and credential operations

Date: 2024-09-25

## Status

Accepted

## Context

Prior to this decision, Spruce's DIDKit was used for DID generation and credential issuance & verification.
The rational for DIDKit's use is that it:
- Is written in Rust and so suitable for use in any mobile app development framework
- Supports JSON-LD and JWT credential issuance and verification
- Supports did:key, did:ethr, did:web
- DIDKit (and its libraries) are open-source

However, a significant limitation of DIDKit is that only inline JSON-LD contexts are supported
(see [this discussion on the Spruce Discord server](https://discord.com/channels/862419652286218251/1021707856401141760/1021709845931495444)),
which limits the usability of the VC API application.

[GitHub Issue #20](https://github.com/openwallet-foundation-labs/vc-api/issues/20) proposed using Credo
to address the JSON-LD context limitation and provide other benefits.

## Decision

Credo (formerly Aries Framework Javascript) is an alternative library for key and credential operations.
We have decided to replace DIDKit with Credo.

## Consequences

Expected benefits from using Credo are:
- The ability to provide additional JSON-LD context documents to a document loader
- Synergy with another Open Wallet Foundation project
- Improved typing, bug patching and debugging due to Credo also being written in Typescript

A possible risk is that Credo encapsulates the database access
and so the project will have less control over the database schema used for key storage.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 3. Use SQLite for Credo DB

Date: 2024-09-30

## Status

Accepted

## Context

The issue motivating this decision, and any context that influences or constrains the decision.

[Credo requires a wallet and storage implement](https://credo.js.org/guides/getting-started/set-up#adding-a-wallet-and-storage-implementation).
At the time of writing, only Aries Askar is provided out of the box.

[Aries Askar](https://github.com/hyperledger/aries-askar) is a database abstract that supports several different underlying databases.
At the time of writing, in-memory (for testing), SQLite and PostgreSQL are supported.

## Decision

The change that we're proposing or have agreed to implement.

We have decided to use Aries Askar as the underlying storage for Credo.
No other known option was available.

We have decides to use SQLite
The rationale is twofold:
1. SQLite is less effort than PostgreSQL for a developer to run the app locally.
2. SQLite is less effort for an initial integration with Credo.
This decision doesn't preclude the addition of PostgreSQL as an option in the future.

## Consequences

SQLite is superior for experimentation and proof-of-concept but may not be suitable for production usage
depending on scalability requirements.
Support for PostgreSQL as backing store for Credo can be supported in the future.
129 changes: 59 additions & 70 deletions apps/vc-api/docs/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@
"KeyDescriptionDto": {
"type": "object",
"properties": {
"keyId": { "type": "string", "description": "id of key (for example, JWK thumbprint)" }
"keyId": { "type": "string", "description": "id of key (for example, public key base58 string)" }
},
"required": ["keyId"]
},
Expand All @@ -653,14 +653,15 @@
},
"required": ["statusCode", "message", "error"]
},
"DidMethod": { "type": "string", "enum": ["key", "ethr"] },
"DidMethod": {
"type": "string",
"description": "DID Method to create.\nMust be one of \"key\" or \"ethr\"",
"enum": ["key", "ethr"]
},
"CreateDidOptionsDto": {
"type": "object",
"properties": {
"method": {
"description": "DID Method to create.\nMust be one of \"key\" or \"ethr\"",
"$ref": "#/components/schemas/DidMethod"
},
"method": { "$ref": "#/components/schemas/DidMethod" },
"keyId": {
"type": "string",
"description": "id of key (for example, JWK thumbprint).\nThis key must be known to the server already.\nIf provided, DID will be created using this key.\nCurrently only supported for did:key."
Expand Down Expand Up @@ -801,64 +802,36 @@
},
"required": ["@context", "type", "issuer", "issuanceDate", "credentialSubject", "proof"]
},
"ProofPurpose": {
"type": "string",
"enum": [
"assertionMethod",
"authentication",
"keyAgreement",
"contactAgreement",
"capabilityInvocation",
"capabilityDelegation"
]
},
"VerifyOptionsDto": {
"type": "object",
"properties": {
"verificationMethod": {
"type": "string",
"description": "The URI of the verificationMethod used for the proof. Default assertionMethod URI."
},
"proofPurpose": {
"description": "The purpose of the proof. Default 'assertionMethod'.",
"$ref": "#/components/schemas/ProofPurpose"
},
"created": {
"type": "string",
"description": "The date and time of the proof (with a maximum accuracy in seconds). Default current system time."
},
"challenge": {
"type": "string",
"description": "A challenge provided by the requesting party of the proof. For example 6e62f66e-67de-11eb-b490-ef3eeefa55f2"
},
"domain": {
"type": "string",
"description": "The intended domain of validity for the proof. For example website.example"
}
}
},
"VerifyCredentialDto": {
"type": "object",
"properties": {
"verifiableCredential": {
"description": "A JSON-LD Verifiable Credential with a proof. https://w3c-ccg.github.io/vc-api/issuer.html#operation/issueCredential",
"allOf": [{ "$ref": "#/components/schemas/VerifiableCredentialDto" }]
},
"options": {
"description": "Parameters for verifying a verifiable credential or a verifiable presentation https://w3c-ccg.github.io/vc-api/verifier.html#operation/verifyCredential https://w3c-ccg.github.io/vc-api/verifier.html#operation/verifyPresentation",
"allOf": [{ "$ref": "#/components/schemas/VerifyOptionsDto" }]
}
},
"required": ["verifiableCredential", "options"]
"required": ["verifiableCredential"]
},
"VerificationResultDto": {
"type": "object",
"properties": {
"checks": { "description": "The checks performed", "type": "array", "items": { "type": "string" } },
"warnings": { "description": "Warnings", "type": "array", "items": { "type": "string" } },
"errors": { "description": "Errors", "type": "array", "items": { "type": "string" } }
"errors": { "description": "Errors", "type": "array", "items": { "type": "string" } },
"verified": { "type": "boolean", "description": "Is the credential valid" }
},
"required": ["checks", "warnings", "errors"]
"required": ["warnings", "errors", "verified"]
},
"ProofPurpose": {
"type": "string",
"description": "The purpose of the proof. Default 'assertionMethod'.",
"enum": [
"assertionMethod",
"authentication",
"keyAgreement",
"contactAgreement",
"capabilityInvocation",
"capabilityDelegation"
]
},
"ProvePresentationOptionsDto": {
"type": "object",
Expand All @@ -871,10 +844,7 @@
"type": "string",
"description": "The URI of the verificationMethod used for the proof. Default assertionMethod URI."
},
"proofPurpose": {
"description": "The purpose of the proof. Default 'assertionMethod'.",
"$ref": "#/components/schemas/ProofPurpose"
},
"proofPurpose": { "$ref": "#/components/schemas/ProofPurpose" },
"created": {
"type": "string",
"description": "The date and time of the proof (with a maximum accuracy in seconds). Default current system time."
Expand Down Expand Up @@ -969,6 +939,28 @@
},
"required": ["presentation", "options"]
},
"VerifyOptionsDto": {
"type": "object",
"properties": {
"verificationMethod": {
"type": "string",
"description": "The URI of the verificationMethod used for the proof. Default assertionMethod URI."
},
"proofPurpose": { "$ref": "#/components/schemas/ProofPurpose" },
"created": {
"type": "string",
"description": "The date and time of the proof (with a maximum accuracy in seconds). Default current system time."
},
"challenge": {
"type": "string",
"description": "A challenge provided by the requesting party of the proof. For example 6e62f66e-67de-11eb-b490-ef3eeefa55f2"
},
"domain": {
"type": "string",
"description": "The intended domain of validity for the proof. For example website.example"
}
}
},
"VerifyPresentationDto": {
"type": "object",
"properties": {
Expand All @@ -989,12 +981,7 @@
},
"ExchangeInteractServiceDefinitionDto": {
"type": "object",
"properties": {
"type": {
"description": "The \"type\" of the interact service.\nSee Verifiable Presentation Request [Interaction Types](https://w3c-ccg.github.io/vp-request-spec/#interaction-types) for background.",
"$ref": "#/components/schemas/VpRequestInteractServiceType"
}
},
"properties": { "type": { "$ref": "#/components/schemas/VpRequestInteractServiceType" } },
"required": ["type"]
},
"PresentationDefinitionDto": {
Expand All @@ -1016,14 +1003,15 @@
"required": ["presentationDefinition"]
},
"VpRequestDidAuthQueryDto": { "type": "object", "properties": {} },
"VpRequestQueryType": { "type": "string", "enum": ["DIDAuth", "PresentationDefinition"] },
"VpRequestQueryType": {
"type": "string",
"description": "Query types as listed in the VP Request spec.\nhttps://w3c-ccg.github.io/vp-request-spec/#query-and-response-types\n\nThe \"PresentationDefinition\" type is proposed here: https://github.com/w3c-ccg/vp-request-spec/issues/7",
"enum": ["DIDAuth", "PresentationDefinition"]
},
"VpRequestQueryDto": {
"type": "object",
"properties": {
"type": {
"description": "Query types as listed in the VP Request spec.\nhttps://w3c-ccg.github.io/vp-request-spec/#query-and-response-types\n\nThe \"PresentationDefinition\" type is proposed here: https://github.com/w3c-ccg/vp-request-spec/issues/7",
"$ref": "#/components/schemas/VpRequestQueryType"
},
"type": { "$ref": "#/components/schemas/VpRequestQueryType" },
"credentialQuery": {
"type": "array",
"description": "The credential query.\nIt should correspond to the query type.",
Expand Down Expand Up @@ -1169,14 +1157,15 @@
},
"required": ["transactionId", "exchangeId", "vpRequest"]
},
"ReviewResult": { "type": "string", "enum": ["approved", "rejected"] },
"ReviewResult": {
"type": "string",
"description": "The judgement made by the reviewer",
"enum": ["approved", "rejected"]
},
"SubmissionReviewDto": {
"type": "object",
"properties": {
"result": {
"description": "The judgement made by the reviewer",
"$ref": "#/components/schemas/ReviewResult"
},
"result": { "$ref": "#/components/schemas/ReviewResult" },
"vp": {
"description": "A reviewer may want to include credentials (wrapped in a VP) to the holder",
"allOf": [{ "$ref": "#/components/schemas/VerifiablePresentationDto" }]
Expand Down
16 changes: 10 additions & 6 deletions apps/vc-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
"update-openapi": "npm run write-openapi; git add docs/openapi.json"
},
"dependencies": {
"@energyweb/ssi-did": "0.0.1",
"@energyweb/w3c-ccg-webkms": "0.0.1",
"@energyweb/ssi-did": "workspace:*",
"@energyweb/w3c-ccg-webkms": "workspace:*",
"@nestjs/common": "^10.0.4",
"@nestjs/config": "^3.0.0",
"@nestjs/core": "^10.0.4",
Expand All @@ -37,19 +37,23 @@
"rimraf": "^4.0.0",
"rxjs": "^7.8.1",
"typeorm": "^0.3.17",
"better-sqlite3": "~8.4.0",
"@spruceid/didkit-wasm-node": "~0.2.1",
"did-resolver": "~4.1.0",
"class-validator": "~0.14.0",
"class-transformer": "~0.5.1",
"@nestjs/swagger": "^7.0.12",
"swagger-ui-express": "~4.6.3",
"uuid": "~9.0.0",
"@sphereon/pex": "~1.1.0",
"@sphereon/pex": "1.1.3",
"@nestjs/axios": "^3.0.0",
"@nestjs/serve-static": "^4.0.0",
"joi": "^17.9.2",
"axios": "~1.4.0"
"axios": "~1.4.0",
"@credo-ts/askar": "^0.5.3",
"@credo-ts/core": "^0.5.3",
"@credo-ts/node": "^0.5.3",
"@hyperledger/aries-askar-nodejs": "^0.2.1",
"@hyperledger/aries-askar-shared": "^0.2.3",
"sqlite3": "~5.1.7"
},
"devDependencies": {
"@nestjs/cli": "^10.1.0",
Expand Down
Loading
Loading