diff --git a/README.md b/README.md index e1f7883..8ce5268 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,41 @@ -# VC Test Suite Implementations _(vc-test-suite-implementations)_ + -> Implementations list used across various W3C CCG test suites. +# W3C Credentials Community Group VC Test Suite Implementations + +This implementations list is used by the various +[W3C Credentials Community Group](https://www.w3.org/groups/cg/credentials/) +Verifiable Credentials test suites (see [Tags](#tags) for the full list). ## Table of Contents -- [VC Test Suite Implementations _(vc-test-suite-implementations)_](#vc-test-suite-implementations-vc-test-suite-implementations) - - [Table of Contents](#table-of-contents) - - [Background](#background) - - [Security](#security) - - [Install](#install) - - [NPM](#npm) - - [Development](#development) - - [Usage](#usage) - - [Adding a new implementation](#adding-a-new-implementation) - - [Testing locally](#testing-locally) - - [Opting into a Test Suite](#opting-into-a-test-suite) - - [Contribute](#contribute) - - [License](#license) +- [Background](#background) +- [Security](#security) +- [Install](#install) + - [NPM](#npm) + - [Development](#development) +- [Usage](#usage) + - [Adding a new implementation](#adding-a-new-implementation) + - [Testing locally](#testing-locally) + - [Test Suite Settings](#test-suite-settings) + - [Tags](#tags) +- [Contribute](#contribute) +- [License](#license) ## Background Implementations added to this package are tested against various test suites -in order to demonstrate interoperability. +[listed below](#tags) in order to demonstrate interoperability. ## Security -Please do not commit any sensitive materials such as oauth2 client secret or -client secrets used for signing zcaps or HTTP Signature Headers. +Please do not commit any sensitive materials such as oauth2 client secrets or +private key information used for signing +[Authorization Capabilities](https://w3c-ccg.github.io/zcap-spec/) or +[HTTP Message Signatures](https://www.ietf.org/archive/id/draft-ietf-httpbis-message-signatures-08.html). ## Install @@ -38,7 +45,7 @@ client secrets used for signing zcaps or HTTP Signature Headers. To install via NPM: -``` +```sh npm install w3c-ccg/vc-test-suite-implementations ``` @@ -46,7 +53,7 @@ npm install w3c-ccg/vc-test-suite-implementations To install locally (for development): -``` +```sh git clone https://github.com/w3c-ccg/vc-test-suite-implementations.git cd vc-test-suite-implementations npm install @@ -54,8 +61,7 @@ npm install ## Usage - -### Adding a new implementation +#### Adding a new implementation Please add implementations to the `./implementations` directory. Implementation configuration files are expressed in JSON and use roughly the following form: @@ -91,129 +97,99 @@ following form: } ``` -Please note: implementations may have security using oauth2 or zcaps, but not -both. -Implementations may also contain no security (do not add a OAUTH2 or ZCAP -section in that case). +Please note: implementations may specify authorization parameters for oauth2 or +zcaps, but not both. Implementations may also not specify any authorization +parameters, in which case they do not specify `oauth2` or `zcap` properties. -### Testing locally +Please check specific test suite READMEs for further details on implementation properties and endpoints. +Test suites MAY specify additional properties and features for endpoints such as +mandatory JSON-LD contexts, keyTypes settings, additional tags for specific tests such as Enveloped Proofs, +and supported VC Data Model versions. In most cases, endpoints are expected to: be capable +of using the test suite API; be capable of signing and/or verifying using `did:key`; and support the following contexts: -If you need to test implementations for endpoints running locally, create a -config file in the root dir of the test suite: +- https://www.w3.org/ns/credentials/examples/v2 +- https://www.w3.org/2018/credentials/v1 +- https://www.w3.org/ns/credentials/v2 -``` -.localImplementationsConfig.cjs -``` +#### Testing locally -This file must be a CommonJS module that exports an array of implementations: +To test implementations with endpoints running locally, create a configuration file named +`localConfig.cjs` in the root directory of the test suite. `localConfig.cjs` should export +a json object. Add the property `implementations` to the exported object. `implementations` +should be an array of objects such as the one below: ```js -// file .localImplementationsConfig.cjs -module.exports = [{ - "name": "My Company", - "implementation": "My Implementation Name", - "issuers": [{ - "id": "urn:uuid:my:implementation:issuer:id", - "endpoint": "https://localhost:40443/issuers/foo/credentials/issue", - "tags": ["vc-api", "localhost"] - }], - "verifiers": [{ - "id": "https://localhost:40443/verifiers/z19uokPn3b1Z4XDbQSHo7VhFR", - "endpoint": "https://localhost:40443/verifiers/z19uokPn3b1Z4XDbQSHo7VhFR/credentials/verify", - "tags": ["vc-api", "localhost"] - }] -}]; +// localConfig.cjs defining local implementations +module.exports = { + "implementations": [{ + "name": "My Company", + "implementation": "My Implementation Name", + "issuers": [{ + "id": "urn:uuid:my:implementation:issuer:id", + "endpoint": "https://localhost:40443/issuers/foo/credentials/issue", + "tags": ["eddsa-rdfc-2022"] + }], + "verifiers": [{ + "id": "https://localhost:40443/verifiers/z19uokPn3b1Z4XDbQSHo7VhFR", + "endpoint": "https://localhost:40443/verifiers/z19uokPn3b1Z4XDbQSHo7VhFR/credentials/verify", + "tags": ["eddsa-rdfc-2022"] + }] + }]; +}; ``` -To run the tests only against the localhost implementation, update the test -suite to filter implementations using the specified tag in your config file. +After adding the config file, only implementations in `localConfig.cjs` will run. -For instance, if your `.localImplementationsConfig.cjs` looks like above -in the `vc-api-issuer-test-suite`, you can adjust the -[tag](https://github.com/w3c-ccg/vc-api-issuer-test-suite/blob/main/tests/10-issuer.js#L14) -to filter the implementation by `localhost` rather than `vc-api` and -then run the tests. +### Test Suite Settings -### Opting into a Test Suite +Additional test suite runtime configuration can be done via the `settings` key +in a `localConfig.cjs`. The current global settings are: -Please Note: + * `enableInteropTests` - enable/disable the cross-implementation "interop" tests + * `testAllImplementations` - enable/disable testing _all_ implementations (not + just what's in `localConfig.cjs`) -1. Tags serve as identifiers to determine which test suites to run on your -issuers and verifiers. The first issuer/verifier found with a specific -tag from your list will be run against the test suite, while subsequent issuers -and verifiers bearing the same tag won't. This applies to most of the test -suites associated with this implementations repository listed below. +Both of these settings are `false` when `localConfig.cjs` is present, but may be +overridden as below: -For instance, if you have added the tag `vc-api` to all your issuers and -verifiers to run them with vc api issuer and verifier test suites, only the -first match will be used in the test suites. In the sample configuration below, -only the issuer and verifier with the IDs -https://product.example.com/issuers/z1AEwLo7tZ3TrsPgRcgLJqQvR and -https://product.example.com/verifiers/z1AEwLo7tZ3TrsPgRcgLJqQvR will be selected. -Therefore, please avoid adding duplicate tags. - -Example ```js -// Only the first match https://product.example.com/issuers/z1AEwLo7tZ3TrsPgRcgLJqQvR -// and https://product.example.com/verifiers/z1AEwLo7tZ3TrsPgRcgLJqQvR will be -// run against the VC API issuer and verifier test suites. -{ - "issuers": [{ - "id": "https://product.example.com/issuers/z1AEwLo7tZ3TrsPgRcgLJqQvR", - "endpoint": "https://product.example.com/issuers/z1AEwLo7tZ3TrsPgRcgLJqQvR/credentials/issue", - "tags": ["vc-api"] - }, { - "id": "https://product.example.com/issuers/z4Rq7N1lT6zVwFgXk8JYdCcKpU", - "endpoint": "https://product.example.com/issuers/z4Rq7N1lT6zVwFgXk8JYdCcKpU/credentials/issue", - "tags": ["vc-api"] - }], - "verifiers": [{ - "id": "https://product.example.com/verifiers/z1AEwLo7tZ3TrsPgRcgLJqQvR", - "endpoint": "https://product.example.com/verifiers/z1AEwLo7tZ3TrsPgRcgLJqQvR/credentials/verify", - "tags": ["vc-api"] +module.exports = { + "settings": { + // overriding the default, false, for local testing + "enableInteropTests": true, + "testAllImplementations": true + }, + "implementations": [{ + "name": "My Company", + "implementation": "My Implementation Name", + "issuers": [{ + "id": "urn:uuid:my:implementation:issuer:id", + "endpoint": "https://localhost:40443/issuers/foo/credentials/issue", + "tags": ["eddsa-rdfc-2022"] + }], + "verifiers": [{ + "id": "https://localhost:40443/verifiers/z19uokPn3b1Z4XDbQSHo7VhFR", + "endpoint": "https://localhost:40443/verifiers/z19uokPn3b1Z4XDbQSHo7VhFR/credentials/verify", + "tags": ["eddsa-rdfc-2022"] + }] }, { - "id": "https://product.example.com/verifiers/z4Rq7N1lT6zVwFgXk8JYdCcKpU", - "endpoint": "https://product.example.com/verifiers/z4Rq7N1lT6zVwFgXk8JYdCcKpU/credentials/verify", - "tags": ["vc-api"] - }] -} + // Add additional implementations as needed + }]; ``` -2. If you want your issuer or verifier to run against multiple test suites, you -can assign multiple tags to them, eliminating the need for redundant entries. -For instance, if an issuer with the ID -https://product.example.com/issuers/z1AEwLo7tZ3TrsPgRcgLJqQvR can be run with -both the VC Bitstring Status List and VC API test suites, a single entry with -multiple tags can be used. This consolidated entry, containing tags for -both VC API and VC Bitstring Status List test suites, ensures that the issuer and -the verifier will be run against both test suites. Here is an example of how to -structure the entry: - -For Example: -```js -{ - "issuers": [{ - "id": "https://product.example.com/issuers/z4Rq7N1lT6zVwFgXk8JYdCcKpU", - "endpoint": "https://product.example.com/issuers/z4Rq7N1lT6zVwFgXk8JYdCcKpU/credentials/issue", - "tags": ["vc-api", "BitstringStatusList", "Suspension"] - }], - "verifiers": [{ - "id": "https://product.example.com/verifiers/z4Rq7N1lT6zVwFgXk8JYdCcKpU", - "endpoint": "https://product.example.com/verifiers/z4Rq7N1lT6zVwFgXk8JYdCcKpU/credentials/verify", - "tags": ["vc-api"] - }] -} -``` +### Tags -#### VC API Issuer and Verifier Test Suites +Tags tell the test suites which implementations' endpoints to run the test suites against. -* `vc-api` - This tag will run the [vc-api-issuer tests](https://github.com/w3c-ccg/vc-api-issuer-test-suite) -on your issuer and the [vc-api-verifier tests](https://github.com/w3c-ccg/vc-api-verifier-test-suite) -on your verifier. +* `vc-api` - This tag will run the +[VC API Issuer test suite](https://github.com/w3c-ccg/vc-api-issuer-test-suite) +on an `issuer` endpoint and the +[VC API Verifier test suite](https://github.com/w3c-ccg/vc-api-verifier-test-suite) +on a `verifier` endpoint. -NOTE: Currently the vc api verifier test suite uses `Ed25519Signature2020` as +NOTE: Currently the VC API Verifier test suite uses `Ed25519Signature2020` as the default signature for the mock VCs that are sent to the verifiers since it -is most widely implemented. So, the verifier you add for `vc-api` must support +is widely implemented. So, the verifier you add for `vc-api` must support verification of VCs with `Ed25519Signature2020` signature to pass verification tests. @@ -221,20 +197,17 @@ As of 2023, `Ed25519Signature2018` is no longer supported, so please update your existing implementations to use `Ed25519Signature2020` if you were previously using `Ed25519Signature2018`. -#### DID Key Test Suite - -* `did-key` - This tag will run the [DID Key Test Suite](https://github.com/w3c-ccg/did-key-test-suite) -on your DID resolver endpoint. +* `did-key` - This tag will run the +[DID Key Test Suite](https://github.com/w3c-ccg/did-key-test-suite) +on a DID resolver endpoint. ## Contribute -See [the contribute file](https://github.com/digitalbazaar/bedrock/blob/master/CONTRIBUTING.md)! - -PRs accepted. +See [the CONTRIBUTING.md file](CONTRIBUTING.md). -If editing the Readme, please conform to the -[standard-readme](https://github.com/RichardLitt/standard-readme) specification. +Pull Requests are welcome! ## License -[New BSD License (3-clause)](LICENSE) © Digital Bazaar +[BSD-3-Clause](LICENSE) Copyright 2022-2025, World Wide Web Consortium and +Digital Bazaar, Inc. diff --git a/implementations/index.js b/implementations/index.js index d2be7e7..b5c9792 100644 --- a/implementations/index.js +++ b/implementations/index.js @@ -1,28 +1,52 @@ -/*! - * Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved. +/* + * Copyright 2022-2025 Digital Bazaar, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause */ + import appRoot from 'app-root-path'; import {createRequire} from 'node:module'; import {join} from 'node:path'; const require = createRequire(import.meta.url); const requireDir = require('require-dir'); +// get all the remote implementations in this dir +const remote = Object.values(requireDir('./')); -const dir = requireDir('./'); - -// gets local implementations from an optional config file -const getLocalImplementations = () => { +// gets local manifests from an optional config file +const getLocalManifest = fileName => { try { const path = join( - appRoot.toString(), '.localImplementationsConfig.cjs'); + appRoot.toString(), fileName); return require(path); } catch(e) { if(e?.code === 'MODULE_NOT_FOUND') { - return []; + return {}; } throw e; } }; -export const implementerFiles = Object.values(dir) - .concat(getLocalImplementations()); +const localConfig = getLocalManifest('localConfig.cjs'); +export const localSettings = (Object.keys(localConfig).length > 0) ? + // if there is a localConfig.settings overwrite local defaults + {...{enableInteropTests: false, testAllImplementations: false}, + ...localConfig?.settings} : + // otherwise, return the global defaults + // FIXME: ...consider renaming `localSettings` as it can hold global ones... + {enableInteropTests: true, testAllImplementations: true}; + +// get localConfig and look for an implementations property +let local = localConfig?.implementations || []; +// it's an easy typo to set `implementations` to an object...instead of an array +if(!Array.isArray(local)) { + local = [local]; +} +// concat all the implementation manifests together +const all = remote.concat(local); + +// if local implementations are defined only return local implementations +export const implementerFiles = local.length ? + // unless testAllImplementations is true...in which case, include them all + (localSettings.testAllImplementations === true ? all : local) : + all;