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

Update implementions index.js and README. #121

Merged
merged 8 commits into from
Feb 4, 2025
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
243 changes: 108 additions & 135 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,41 @@
# VC Test Suite Implementations _(vc-test-suite-implementations)_
<!--
Copyright 2025 Digital Bazaar, Inc.

[![Build status](https://img.shields.io/github/workflow/status/w3c-ccg/vc-test-suite-implementations/Node.js%20CI)](https://github.com/w3c-ccg/vc-test-suite-implementations/actions?query=workflow%3A%22Node.js+CI%22)
SPDX-License-Identifier: BSD-3-Clause
-->

> 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

Expand All @@ -38,24 +45,23 @@ client secrets used for signing zcaps or HTTP Signature Headers.

To install via NPM:

```
```sh
npm install w3c-ccg/vc-test-suite-implementations
```

### Development

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
```

## 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:
Expand Down Expand Up @@ -91,150 +97,117 @@ 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.

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.
44 changes: 34 additions & 10 deletions implementations/index.js
Original file line number Diff line number Diff line change
@@ -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;