diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 15e76e0..3ed2d30 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,3 +1,9 @@ +/* + * Copyright 2025 Digital Bazaar, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + module.exports = { root: true, extends: [ diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 40aa34c..f871b94 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,4 +1,4 @@ -name: Node.js CI +name: Lint and Test on: [push] diff --git a/.gitignore b/.gitignore index 74c12ad..c2658d7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,108 +1 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# Next.js build output -.next - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and *not* Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# Editor files -*~ -*.sw[nop] diff --git a/CHANGELOG.md b/CHANGELOG.md index 47f3806..a1fc702 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ + + # vc-test-suite-implementations Changelog ## 4.0.0 - 2024-01-TBD diff --git a/LICENSE b/LICENSE index 652af85..d2a5251 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,6 @@ BSD 3-Clause License -Copyright (c) 2022, Digital Bazaar, Inc. -All rights reserved. +Copyright (c) 2023-2025, World Wide Web Consortium Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/lib/Endpoint.js b/lib/Endpoint.js index 22bf82b..f5a5b60 100644 --- a/lib/Endpoint.js +++ b/lib/Endpoint.js @@ -1,6 +1,9 @@ -/*! - * Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved. +/* + * Copyright 2022-2025 Digital Bazaar, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause */ + import {makeHttpsRequest, zcapRequest} from './requests.js'; /** diff --git a/lib/Implementation.js b/lib/Implementation.js index f7fa076..ba15529 100644 --- a/lib/Implementation.js +++ b/lib/Implementation.js @@ -1,6 +1,9 @@ -/*! - * Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved. +/* + * Copyright 2022-2025 Digital Bazaar, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause */ + import {Endpoint} from './Endpoint.js'; export class Implementation { diff --git a/lib/constants.js b/lib/constants.js index 24be2bd..b27395e 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -1,6 +1,9 @@ -/*! - * Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved. +/* + * Copyright 2022-2025 Digital Bazaar, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause */ + import * as didKey from '@digitalbazaar/did-method-key'; import https from 'https'; diff --git a/lib/main.js b/lib/main.js index 0b6f4eb..e7338de 100644 --- a/lib/main.js +++ b/lib/main.js @@ -1,13 +1,16 @@ -/*! - * Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved. +/* + * Copyright 2022-2025 Digital Bazaar, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause */ + import {Implementation} from './Implementation.js'; import {implementerFiles} from '../implementations/index.js'; -export {Endpoint} from './Endpoint.js'; const keyValues = implementerFiles.map( implementation => [implementation.name, new Implementation(implementation)]); +export {localSettings} from '../implementations/index.js'; export const implementations = new Map(keyValues); export const allImplementations = implementations; @@ -22,9 +25,9 @@ export const allImplementations = implementations; * @param {Map} [options.implementations=allImplementations] - A Map of * implementations. * @param {Function} options.filter - A function to - * filter the map's entries on that returns true or false. + * filter the map's entries, that returns true or false. * - * @returns {{match: Map, nonMatch: Map}} Returns an object with matching + * @returns {Object} Returns an object with matching * and non-matching maps. */ export const filterImplementations = ({ @@ -47,7 +50,7 @@ export const filterImplementations = ({ /** * Filters implementations by tags on a property in the settings. * - * @example filterByTag({property: 'issuers', tags: ['VC-HTTP-API']}) + * @example filterByTag({property: 'issuers', tags: ['ecdsa-rdfc-2019']}) * * @param {object} options - Options to use. * @param {Map} [options.implementations=allImplementations] - @@ -56,7 +59,7 @@ export const filterImplementations = ({ * @param {string} [options.property='issuers'] - The property to search for on * an implementation. * - * @returns {{match: Map, nonMatch: Map}} Returns an object with matching + * @returns {Object} Returns an object with matching * and non-matching maps. */ export const filterByTag = ({ @@ -84,7 +87,7 @@ export const endpoints = { * @param {Map} [options.implementations=allImplementations] - A Map of * implementations. * @param {Function} options.filter - A function to - * filter the map's entries that returns true or false. + * filter the map's entries, that returns true or false. * * @returns {{match: Map, nonMatch: Map}} Returns an object with matching * and non-matching Maps with respective endpoints. @@ -108,7 +111,9 @@ export const endpoints = { /** * Filters endpoints by tags on a property in the settings. * - * @example endpoints.filterByTag({property: 'issuers', tags: ['vc-api']}) + * @example endpoints.filterByTag({ + * property: 'issuers', tags: ['ecdsa-rdfc-2019'] + * }) * * @param {object} options - Options to use. * @param {Map} [options.implementations=allImplementations] - diff --git a/lib/oauth2.js b/lib/oauth2.js index dffa877..9f1bef8 100644 --- a/lib/oauth2.js +++ b/lib/oauth2.js @@ -1,6 +1,9 @@ -/*! - * Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved. +/* + * Copyright 2022-2025 Digital Bazaar, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause */ + import LruCache from 'lru-cache'; import {makeHttpsRequest} from './requests.js'; diff --git a/lib/requests.js b/lib/requests.js index 794b2e7..aa737ed 100644 --- a/lib/requests.js +++ b/lib/requests.js @@ -1,6 +1,9 @@ -/*! - * Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved. +/* + * Copyright 2022-2025 Digital Bazaar, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause */ + import { agent, defaultHeaders, @@ -47,12 +50,12 @@ export async function makeHttpsRequest({ body, method, json, headers, agent, searchParams }); } catch(e) { - error = _sanitizeErrorHeaders({error: e}); + error = _sanitizeError({error: e}); } const {data, statusCode} = _getDataAndStatus({result, error}); // if a result is returned sanitize it if(result) { - result = _sanitizeResponseHeaders({response: result, data}); + result = _sanitizeResponse({response: result, data}); } return {result, error, data, statusCode}; } @@ -88,12 +91,12 @@ export async function zcapRequest({ capability }); } catch(e) { - error = _sanitizeErrorHeaders({error: e}); + error = _sanitizeError({error: e}); } const {data, statusCode} = _getDataAndStatus({result, error}); // if a result is returned sanitize it if(result) { - result = _sanitizeResponseHeaders({response: result, data}); + result = _sanitizeResponse({response: result, data}); } return {result, error, data, statusCode}; } @@ -111,7 +114,7 @@ async function _getZcapClient({secretKeySeed}) { function _getDataAndStatus({result = {}, error = {}}) { let data = result.data || error.data; - // FIXME remove this once VC-API returns from the issuer + // FIXME remove this once data returned from the issuers // are finalized. if(data && data.verifiableCredential) { data = data.verifiableCredential; @@ -120,22 +123,20 @@ function _getDataAndStatus({result = {}, error = {}}) { return {data, statusCode}; } -function _sanitizeErrorHeaders({error}) { +function _sanitizeError({error}) { if(error.response) { - error.response = _sanitizeResponseHeaders({ + error.response = _sanitizeResponse({ response: error.response, data: error.data }); } if(error.request) { - error.request = new global.Request(error.request, { - headers: _sanitizeHeaders({httpMessage: error.request}) - }); + error.request = _sanitizeRequest({request: error.request}); } return error; } -function _sanitizeResponseHeaders({response, data}) { +function _sanitizeResponse({response, data}) { const newResponse = new global.Response(JSON.stringify(data), { headers: _sanitizeHeaders({httpMessage: response}), status: response.status, @@ -149,6 +150,25 @@ function _sanitizeResponseHeaders({response, data}) { return newResponse; } +function _sanitizeRequest({request}) { + // get the url and the remaining properties from the request + const {url, ...props} = request; + // create an options object to pass to the new request + const options = {}; + // do not copy these properties from the request + const skipKeys = new Set(['body', 'headers']); + for(const key in props) { + if(skipKeys.has(key)) { + continue; + } + options[key] = request[key]; + } + return new global.Request(url, { + ...options, + headers: _sanitizeHeaders({httpMessage: request}) + }); +} + /** * Takes in either a response or request & sanitizes the headers. * @@ -171,7 +191,7 @@ function _sanitizeHeaders({httpMessage, headers = sanitizeHeaders}) { for(const header of headers) { // sanitize the headers to prevent // authn tokens / information potentially in logs - newHeaders.set(header, '** SANITIZED TO PREVENT EXPOSING OF SECRETS ***'); + newHeaders.set(header, 'sanitized to prevent exposure of secrets'); } return newHeaders; } diff --git a/package.json b/package.json index e45c8f3..4648569 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,18 @@ { "name": "vc-test-suite-implementations", "version": "0.0.1", - "description": "", + "description": "W3C Credentials Community Group test suite implementations", "homepage": "https://github.com/w3c-ccg/vc-test-suite-implementations", "author": { + "name": "W3C Verifiable Credentials Working Group", + "email": "public-vc-wg@w3.org", + "url": "https://www.w3.org/groups/wg/vc/" + }, + "contributors": [{ "name": "Digital Bazaar, Inc.", "email": "support@digitalbazaar.com", "url": "https://digitalbazaar.com/" - }, + }], "type": "module", "main": "./lib/main.js", "repository": { @@ -16,7 +21,7 @@ }, "bugs": { "url": "https://github.com/w3c-ccg/vc-test-suite-implementations/issues", - "email": "support@digitalbazaar.com" + "email": "public-credentials@w3.org" }, "license": "BSD-3-Clause", "files": [ @@ -61,8 +66,8 @@ "node": ">=18" }, "keywords": [ - "Decentralized", - "Linked Data" + "W3C", + "Verifiable Credentials" ], "scripts": { "test": "npm run test-node && npm run lint", diff --git a/test/.eslintrc.cjs b/test/.eslintrc.cjs index bf3479f..9abd4d4 100644 --- a/test/.eslintrc.cjs +++ b/test/.eslintrc.cjs @@ -1,3 +1,9 @@ +/* + * Copyright 2025 Digital Bazaar, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + module.exports = { env: { mocha: true