diff --git a/.eslintignore b/.eslintignore index 7dc67925..e3229750 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,6 +1,6 @@ node_modules coverage dist -src/__generated__ +__generated__ vc-test-suite *.d.ts diff --git a/.eslintrc.json b/.eslintrc.json index 37003312..f4fd218f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -10,7 +10,8 @@ "@typescript-eslint/no-unused-vars": [ "error", { - "argsIgnorePattern": "^_" + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_" } ], "func-names": ["error", "as-needed"], diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2daa49fd..cb46f66a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,6 +2,7 @@ on: push: branches: - master + - alpha - beta - +([0-9])?(.{+([0-9]),x}).x @@ -30,12 +31,8 @@ jobs: node-version: 18.x - run: npm ci && npm run postinstall - run: npm run build - - uses: codfish/semantic-release-action@v2 - id: semantic + - name: Release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - name: Output new release version - if: steps.semantic.outputs.new-release-published == 'true' - run: | - echo "🎉 New Release Published: ${{ steps.semantic.outputs.release-version }}" + run: npx semantic-release diff --git a/.gitignore b/.gitignore index e1632f13..efd31b1a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ yarn.lock *.iml /public /vc-test-suite +/.vscode diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 00000000..7e154687 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npm run lint-staged diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100755 index 00000000..610c2a54 --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +npm test diff --git a/.lintstagedrc b/.lintstagedrc new file mode 100644 index 00000000..b794d936 --- /dev/null +++ b/.lintstagedrc @@ -0,0 +1,5 @@ +{ + "src/4.0/types.ts": ["npm run generate-v4-json-schemas", "git add src/4.0/jsonSchemas/__generated__"], + "src/4.0/fixtures.ts": ["npm run generate-v4-fixtures", "git add test/fixtures/v4/__generated__"], + "*.{js,ts}": "eslint --fix" +} \ No newline at end of file diff --git a/.releaserc b/.releaserc new file mode 100644 index 00000000..2fe8a0f6 --- /dev/null +++ b/.releaserc @@ -0,0 +1,13 @@ +{ + "branches": [ + "master", + { + "name": "alpha", + "prerelease": true + }, + { + "name": "beta", + "prerelease": true + } + ] +} diff --git a/package-lock.json b/package-lock.json index e8f200a3..e1dc2e82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,21 +10,26 @@ "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { + "@aws-crypto/sha256-universal": "^5.2.0", "@ethersproject/abstract-signer": "^5.7.0", "@ethersproject/bytes": "^5.7.0", "@ethersproject/logger": "^5.7.0", "@ethersproject/wallet": "^5.7.0", "@govtechsg/jsonld": "^0.1.0", "ajv-formats": "^2.1.1", + "buffer": "^6.0.3", "cross-fetch": "^3.1.5", "debug": "^4.3.2", "flatley": "^5.2.0", "js-base64": "^3.6.1", "js-sha3": "^0.8.0", + "jsonld": "^8.3.2", "lodash": "^4.17.21", + "randombytes": "^2.1.0", "runtypes": "^6.3.2", "uuid": "^8.3.2", - "validator": "^13.7.0" + "validator": "^13.7.0", + "zod": "^3.22.4" }, "devDependencies": { "@commitlint/cli": "^17.6.7", @@ -34,9 +39,10 @@ "@types/debug": "^4.1.7", "@types/jest": "^29.5.3", "@types/js-base64": "^3.3.1", - "@types/jsonld": "^1.5.6", + "@types/jsonld": "^1.5.13", "@types/lodash": "^4.14.171", "@types/qrcode": "^1.4.1", + "@types/randombytes": "^2.0.3", "@types/uuid": "^8.3.1", "@types/validator": "^13.6.3", "@typescript-eslint/eslint-plugin": "^6.9.0", @@ -52,17 +58,19 @@ "eslint-plugin-prettier": "^3.4.0", "git-cz": "^4.7.6", "husky": "^8.0.3", - "jest": "^29.6.2", + "jest": "^29.7.0", "jest-watch-typeahead": "^2.2.2", + "lint-staged": "^15.2.2", "prettier": "^2.3.2", "qrcode": "^1.5.1", "quicktype": "^15.0.260", "rollup": "^2.79.1", "rollup-plugin-commonjs": "^10.1.0", "semantic-release": "^22.0.8", - "ts-jest": "^29.1.1", - "ts-node": "^9.1.1", - "typescript": "^5.1.6" + "ts-jest": "^29.1.2", + "ts-node": "^10.9.2", + "typescript": "^5.1.6", + "zod-to-json-schema": "^3.23.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -87,106 +95,179 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, + "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-crypto/sha256-universal": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-universal/-/sha256-universal-5.2.0.tgz", + "integrity": "sha512-fnBT+9QvcJLXHOuGAPSq3FNVxOsE2lvuJiRjJidaIyeabASmvJWzFEIw9xJaLBY7JPqtD9faMIGCVZv39IbXrg==", "dependencies": { - "color-convert": "^1.9.0" + "@aws-crypto/sha256-browser": "^5.2.0", + "@aws-sdk/hash-node": "^3.110.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=4" + "node": ">=16.0.0" } }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, + "node_modules/@aws-crypto/sha256-universal/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/hash-node": { + "version": "3.374.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.374.0.tgz", + "integrity": "sha512-5GmU64bwoQhkebMv7NzHa+Mw+p7ZmrKz9e3A6hKClxVGeZFE/+jME46gMuFYzO0iz3WqX4CCzUVOhNbS0x8EMQ==", + "deprecated": "This package has moved to @smithy/hash-node", + "dependencies": { + "@smithy/hash-node": "^1.0.1", + "tslib": "^2.5.0" }, "engines": { - "node": ">=4" + "node": ">=14.0.0" } }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, + "node_modules/@aws-sdk/hash-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/types": { + "version": "3.567.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.567.0.tgz", + "integrity": "sha512-JBznu45cdgQb8+T/Zab7WpBmfEAh77gsk99xuF4biIb2Sw1mdseONdoGDjEJX57a25TzIv/WUJ2oABWumckz1A==", "dependencies": { - "color-name": "1.1.3" + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "node_modules/@aws-sdk/types/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz", + "integrity": "sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==", + "dependencies": { + "tslib": "^2.6.2" + }, "engines": { - "node": ">=4" + "node": ">=16.0.0" } }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@aws-sdk/util-locate-window/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { - "node": ">=4" + "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", - "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", + "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", - "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", + "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helpers": "^7.23.2", - "@babel/parser": "^7.23.0", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.1", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.1", + "@babel/parser": "^7.24.1", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -223,14 +304,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", + "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", "dev": true, "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -238,9 +319,9 @@ } }, "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -248,14 +329,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -322,21 +403,21 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", "dev": true, "dependencies": { - "@babel/types": "^7.22.15" + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", - "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", @@ -353,9 +434,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", "dev": true, "engines": { "node": ">=6.9.0" @@ -386,9 +467,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -404,37 +485,38 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", - "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", + "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", "dev": true, "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -503,9 +585,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", + "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -575,12 +657,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -677,12 +759,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -692,34 +774,34 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -736,12 +818,12 @@ } }, "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, @@ -766,16 +848,16 @@ } }, "node_modules/@commitlint/cli": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.8.1.tgz", - "integrity": "sha512-ay+WbzQesE0Rv4EQKfNbSMiJJ12KdKTDzIt0tcK4k11FdsWmtwP0Kp1NWMOUswfIWo6Eb7p7Ln721Nx9FLNBjg==", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.7.1.tgz", + "integrity": "sha512-BCm/AT06SNCQtvFv921iNhudOHuY16LswT0R3OeolVGLk8oP+Rk9TfQfgjH7QPMjhvp76bNqGFEcpKojxUNW1g==", "dev": true, "dependencies": { - "@commitlint/format": "^17.8.1", - "@commitlint/lint": "^17.8.1", - "@commitlint/load": "^17.8.1", - "@commitlint/read": "^17.8.1", - "@commitlint/types": "^17.8.1", + "@commitlint/format": "^17.4.4", + "@commitlint/lint": "^17.7.0", + "@commitlint/load": "^17.7.1", + "@commitlint/read": "^17.5.1", + "@commitlint/types": "^17.4.4", "execa": "^5.0.0", "lodash.isfunction": "^3.0.9", "resolve-from": "5.0.0", @@ -790,9 +872,9 @@ } }, "node_modules/@commitlint/config-conventional": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.8.1.tgz", - "integrity": "sha512-NxCOHx1kgneig3VLauWJcDWS40DVjg7nKOpBEEK9E5fjJpQqLCilcnKkIIjdBH98kEO1q3NpE5NSrZ2kl/QGJg==", + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.7.0.tgz", + "integrity": "sha512-iicqh2o6et+9kWaqsQiEYZzfLbtoWv9uZl8kbI8EGfnc0HeGafQBF7AJ0ylN9D/2kj6txltsdyQs8+2fTMwWEw==", "dev": true, "dependencies": { "conventional-changelog-conventionalcommits": "^6.1.0" @@ -802,12 +884,12 @@ } }, "node_modules/@commitlint/config-validator": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.8.1.tgz", - "integrity": "sha512-UUgUC+sNiiMwkyiuIFR7JG2cfd9t/7MV8VB4TZ+q02ZFkHoduUS4tJGsCBWvBOGD9Btev6IecPMvlWUfJorkEA==", + "version": "17.6.7", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.6.7.tgz", + "integrity": "sha512-vJSncmnzwMvpr3lIcm0I8YVVDJTzyjy7NZAeXbTXy+MPUdAr9pKyyg7Tx/ebOQ9kqzE6O9WT6jg2164br5UdsQ==", "dev": true, "dependencies": { - "@commitlint/types": "^17.8.1", + "@commitlint/types": "^17.4.4", "ajv": "^8.11.0" }, "engines": { @@ -815,12 +897,12 @@ } }, "node_modules/@commitlint/ensure": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.8.1.tgz", - "integrity": "sha512-xjafwKxid8s1K23NFpL8JNo6JnY/ysetKo8kegVM7c8vs+kWLP8VrQq+NbhgVlmCojhEDbzQKp4eRXSjVOGsow==", + "version": "17.6.7", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.6.7.tgz", + "integrity": "sha512-mfDJOd1/O/eIb/h4qwXzUxkmskXDL9vNPnZ4AKYKiZALz4vHzwMxBSYtyL2mUIDeU9DRSpEUins8SeKtFkYHSw==", "dev": true, "dependencies": { - "@commitlint/types": "^17.8.1", + "@commitlint/types": "^17.4.4", "lodash.camelcase": "^4.3.0", "lodash.kebabcase": "^4.1.1", "lodash.snakecase": "^4.1.1", @@ -832,21 +914,21 @@ } }, "node_modules/@commitlint/execute-rule": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.8.1.tgz", - "integrity": "sha512-JHVupQeSdNI6xzA9SqMF+p/JjrHTcrJdI02PwesQIDCIGUrv04hicJgCcws5nzaoZbROapPs0s6zeVHoxpMwFQ==", + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.4.0.tgz", + "integrity": "sha512-LIgYXuCSO5Gvtc0t9bebAMSwd68ewzmqLypqI2Kke1rqOqqDbMpYcYfoPfFlv9eyLIh4jocHWwCK5FS7z9icUA==", "dev": true, "engines": { "node": ">=v14" } }, "node_modules/@commitlint/format": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.8.1.tgz", - "integrity": "sha512-f3oMTyZ84M9ht7fb93wbCKmWxO5/kKSbwuYvS867duVomoOsgrgljkGGIztmT/srZnaiGbaK8+Wf8Ik2tSr5eg==", + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.4.4.tgz", + "integrity": "sha512-+IS7vpC4Gd/x+uyQPTAt3hXs5NxnkqAZ3aqrHd5Bx/R9skyCAWusNlNbw3InDbAK6j166D9asQM8fnmYIa+CXQ==", "dev": true, "dependencies": { - "@commitlint/types": "^17.8.1", + "@commitlint/types": "^17.4.4", "chalk": "^4.1.0" }, "engines": { @@ -854,12 +936,12 @@ } }, "node_modules/@commitlint/is-ignored": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.8.1.tgz", - "integrity": "sha512-UshMi4Ltb4ZlNn4F7WtSEugFDZmctzFpmbqvpyxD3la510J+PLcnyhf9chs7EryaRFJMdAKwsEKfNK0jL/QM4g==", + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.7.0.tgz", + "integrity": "sha512-043rA7m45tyEfW7Zv2vZHF++176MLHH9h70fnPoYlB1slKBeKl8BwNIlnPg4xBdRBVNPaCqvXxWswx2GR4c9Hw==", "dev": true, "dependencies": { - "@commitlint/types": "^17.8.1", + "@commitlint/types": "^17.4.4", "semver": "7.5.4" }, "engines": { @@ -867,31 +949,31 @@ } }, "node_modules/@commitlint/lint": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.8.1.tgz", - "integrity": "sha512-aQUlwIR1/VMv2D4GXSk7PfL5hIaFSfy6hSHV94O8Y27T5q+DlDEgd/cZ4KmVI+MWKzFfCTiTuWqjfRSfdRllCA==", + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.7.0.tgz", + "integrity": "sha512-TCQihm7/uszA5z1Ux1vw+Nf3yHTgicus/+9HiUQk+kRSQawByxZNESeQoX9ujfVd3r4Sa+3fn0JQAguG4xvvbA==", "dev": true, "dependencies": { - "@commitlint/is-ignored": "^17.8.1", - "@commitlint/parse": "^17.8.1", - "@commitlint/rules": "^17.8.1", - "@commitlint/types": "^17.8.1" + "@commitlint/is-ignored": "^17.7.0", + "@commitlint/parse": "^17.7.0", + "@commitlint/rules": "^17.7.0", + "@commitlint/types": "^17.4.4" }, "engines": { "node": ">=v14" } }, "node_modules/@commitlint/load": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.8.1.tgz", - "integrity": "sha512-iF4CL7KDFstP1kpVUkT8K2Wl17h2yx9VaR1ztTc8vzByWWcbO/WaKwxsnCOqow9tVAlzPfo1ywk9m2oJ9ucMqA==", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.7.1.tgz", + "integrity": "sha512-S/QSOjE1ztdogYj61p6n3UbkUvweR17FQ0zDbNtoTLc+Hz7vvfS7ehoTMQ27hPSjVBpp7SzEcOQu081RLjKHJQ==", "dev": true, "dependencies": { - "@commitlint/config-validator": "^17.8.1", - "@commitlint/execute-rule": "^17.8.1", - "@commitlint/resolve-extends": "^17.8.1", - "@commitlint/types": "^17.8.1", - "@types/node": "20.5.1", + "@commitlint/config-validator": "^17.6.7", + "@commitlint/execute-rule": "^17.4.0", + "@commitlint/resolve-extends": "^17.6.7", + "@commitlint/types": "^17.4.4", + "@types/node": "20.4.7", "chalk": "^4.1.0", "cosmiconfig": "^8.0.0", "cosmiconfig-typescript-loader": "^4.0.0", @@ -900,71 +982,28 @@ "lodash.uniq": "^4.5.0", "resolve-from": "^5.0.0", "ts-node": "^10.8.1", - "typescript": "^4.6.4 || ^5.2.2" + "typescript": "^4.6.4 || ^5.0.0" }, "engines": { "node": ">=v14" } }, - "node_modules/@commitlint/load/node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, "node_modules/@commitlint/message": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-17.8.1.tgz", - "integrity": "sha512-6bYL1GUQsD6bLhTH3QQty8pVFoETfFQlMn2Nzmz3AOLqRVfNNtXBaSY0dhZ0dM6A2MEq4+2d7L/2LP8TjqGRkA==", + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-17.4.2.tgz", + "integrity": "sha512-3XMNbzB+3bhKA1hSAWPCQA3lNxR4zaeQAQcHj0Hx5sVdO6ryXtgUBGGv+1ZCLMgAPRixuc6en+iNAzZ4NzAa8Q==", "dev": true, "engines": { "node": ">=v14" } }, "node_modules/@commitlint/parse": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.8.1.tgz", - "integrity": "sha512-/wLUickTo0rNpQgWwLPavTm7WbwkZoBy3X8PpkUmlSmQJyWQTj0m6bDjiykMaDt41qcUbfeFfaCvXfiR4EGnfw==", + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.7.0.tgz", + "integrity": "sha512-dIvFNUMCUHqq5Abv80mIEjLVfw8QNuA4DS7OWip4pcK/3h5wggmjVnlwGCDvDChkw2TjK1K6O+tAEV78oxjxag==", "dev": true, "dependencies": { - "@commitlint/types": "^17.8.1", + "@commitlint/types": "^17.4.4", "conventional-changelog-angular": "^6.0.0", "conventional-commits-parser": "^4.0.0" }, @@ -973,14 +1012,14 @@ } }, "node_modules/@commitlint/prompt": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/prompt/-/prompt-17.8.1.tgz", - "integrity": "sha512-adK+6oaR/8SSSa/Lnp7KU+lu28j/jWfR2sX/5qRDFc2WTTMM59yJ+33k8FMHKZAZIU1FdyCGr11yP3btL6VdLA==", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/@commitlint/prompt/-/prompt-17.7.1.tgz", + "integrity": "sha512-TWPATfSarPHdUOGkE/irBtzE+ZhEuUQI8U8PMcrLYi26NtJTHmRWpwZGug5gehcmlvQuLCjoFg3naYrs1BMHEQ==", "dev": true, "dependencies": { - "@commitlint/ensure": "^17.8.1", - "@commitlint/load": "^17.8.1", - "@commitlint/types": "^17.8.1", + "@commitlint/ensure": "^17.6.7", + "@commitlint/load": "^17.7.1", + "@commitlint/types": "^17.4.4", "chalk": "^4.1.0", "inquirer": "^6.5.2" }, @@ -989,13 +1028,13 @@ } }, "node_modules/@commitlint/read": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.8.1.tgz", - "integrity": "sha512-Fd55Oaz9irzBESPCdMd8vWWgxsW3OWR99wOntBDHgf9h7Y6OOHjWEdS9Xzen1GFndqgyoaFplQS5y7KZe0kO2w==", + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.5.1.tgz", + "integrity": "sha512-7IhfvEvB//p9aYW09YVclHbdf1u7g7QhxeYW9ZHSO8Huzp8Rz7m05aCO1mFG7G8M+7yfFnXB5xOmG18brqQIBg==", "dev": true, "dependencies": { - "@commitlint/top-level": "^17.8.1", - "@commitlint/types": "^17.8.1", + "@commitlint/top-level": "^17.4.0", + "@commitlint/types": "^17.4.4", "fs-extra": "^11.0.0", "git-raw-commits": "^2.0.11", "minimist": "^1.2.6" @@ -1005,13 +1044,13 @@ } }, "node_modules/@commitlint/resolve-extends": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.8.1.tgz", - "integrity": "sha512-W/ryRoQ0TSVXqJrx5SGkaYuAaE/BUontL1j1HsKckvM6e5ZaG0M9126zcwL6peKSuIetJi7E87PRQF8O86EW0Q==", + "version": "17.6.7", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.6.7.tgz", + "integrity": "sha512-PfeoAwLHtbOaC9bGn/FADN156CqkFz6ZKiVDMjuC2N5N0740Ke56rKU7Wxdwya8R8xzLK9vZzHgNbuGhaOVKIg==", "dev": true, "dependencies": { - "@commitlint/config-validator": "^17.8.1", - "@commitlint/types": "^17.8.1", + "@commitlint/config-validator": "^17.6.7", + "@commitlint/types": "^17.4.4", "import-fresh": "^3.0.0", "lodash.mergewith": "^4.6.2", "resolve-from": "^5.0.0", @@ -1022,15 +1061,15 @@ } }, "node_modules/@commitlint/rules": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.8.1.tgz", - "integrity": "sha512-2b7OdVbN7MTAt9U0vKOYKCDsOvESVXxQmrvuVUZ0rGFMCrCPJWWP1GJ7f0lAypbDAhaGb8zqtdOr47192LBrIA==", + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.7.0.tgz", + "integrity": "sha512-J3qTh0+ilUE5folSaoK91ByOb8XeQjiGcdIdiB/8UT1/Rd1itKo0ju/eQVGyFzgTMYt8HrDJnGTmNWwcMR1rmA==", "dev": true, "dependencies": { - "@commitlint/ensure": "^17.8.1", - "@commitlint/message": "^17.8.1", - "@commitlint/to-lines": "^17.8.1", - "@commitlint/types": "^17.8.1", + "@commitlint/ensure": "^17.6.7", + "@commitlint/message": "^17.4.2", + "@commitlint/to-lines": "^17.4.0", + "@commitlint/types": "^17.4.4", "execa": "^5.0.0" }, "engines": { @@ -1038,18 +1077,18 @@ } }, "node_modules/@commitlint/to-lines": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-17.8.1.tgz", - "integrity": "sha512-LE0jb8CuR/mj6xJyrIk8VLz03OEzXFgLdivBytoooKO5xLt5yalc8Ma5guTWobw998sbR3ogDd+2jed03CFmJA==", + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-17.4.0.tgz", + "integrity": "sha512-LcIy/6ZZolsfwDUWfN1mJ+co09soSuNASfKEU5sCmgFCvX5iHwRYLiIuoqXzOVDYOy7E7IcHilr/KS0e5T+0Hg==", "dev": true, "engines": { "node": ">=v14" } }, "node_modules/@commitlint/top-level": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-17.8.1.tgz", - "integrity": "sha512-l6+Z6rrNf5p333SHfEte6r+WkOxGlWK4bLuZKbtf/2TXRN+qhrvn1XE63VhD8Oe9oIHQ7F7W1nG2k/TJFhx2yA==", + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-17.4.0.tgz", + "integrity": "sha512-/1loE/g+dTTQgHnjoCy0AexKAEFyHsR2zRB4NWrZ6lZSMIxAhBJnmCqwao7b4H8888PsfoTBCLBYIw8vGnej8g==", "dev": true, "dependencies": { "find-up": "^5.0.0" @@ -1120,9 +1159,9 @@ } }, "node_modules/@commitlint/types": { - "version": "17.8.1", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.8.1.tgz", - "integrity": "sha512-PXDQXkAmiMEG162Bqdh9ChML/GJZo6vU+7F03ALKDK8zYc6SuAr47LjG7hGYRqUOz+WK0dU7bQ0xzuqFMdxzeQ==", + "version": "17.4.4", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.4.4.tgz", + "integrity": "sha512-amRN8tRLYOsxRr6mTnGGGvB5EmW/4DDjLMgiwK3CCVEmN6Sr/6xePGEpWaspKkckILuUORCwe6VfDBw6uj4axQ==", "dev": true, "dependencies": { "chalk": "^4.1.0" @@ -1152,6 +1191,19 @@ "node": ">=4.9.1" } }, + "node_modules/@digitalbazaar/http-client": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@digitalbazaar/http-client/-/http-client-3.4.1.tgz", + "integrity": "sha512-Ahk1N+s7urkgj7WvvUND5f8GiWEPfUw0D41hdElaqLgu8wZScI8gdI0q+qWw5N1d35x7GCRH2uk9mi+Uzo9M3g==", + "dependencies": { + "ky": "^0.33.3", + "ky-universal": "^0.11.0", + "undici": "^5.21.2" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -1261,6 +1313,32 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "node_modules/@ethersproject/abi": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", + "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, "node_modules/@ethersproject/abstract-provider": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", @@ -1422,6 +1500,33 @@ "@ethersproject/bignumber": "^5.7.0" } }, + "node_modules/@ethersproject/contracts": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", + "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abi": "^5.7.0", + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0" + } + }, "node_modules/@ethersproject/hash": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", @@ -1507,11 +1612,6 @@ "scrypt-js": "3.0.1" } }, - "node_modules/@ethersproject/json-wallets/node_modules/aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" - }, "node_modules/@ethersproject/keccak256": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", @@ -1601,6 +1701,43 @@ "@ethersproject/logger": "^5.7.0" } }, + "node_modules/@ethersproject/providers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", + "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0", + "bech32": "1.1.4", + "ws": "7.4.6" + } + }, "node_modules/@ethersproject/random": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", @@ -1682,6 +1819,29 @@ "hash.js": "1.1.7" } }, + "node_modules/@ethersproject/solidity": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", + "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, "node_modules/@ethersproject/strings": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", @@ -1728,10 +1888,10 @@ "@ethersproject/signing-key": "^5.7.0" } }, - "node_modules/@ethersproject/wallet": { + "node_modules/@ethersproject/units": { "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", - "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", + "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", "funding": [ { "type": "individual", @@ -1743,13 +1903,33 @@ } ], "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/wallet": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", + "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", "@ethersproject/json-wallets": "^5.7.0", "@ethersproject/keccak256": "^5.7.0", "@ethersproject/logger": "^5.7.0", @@ -1804,6 +1984,14 @@ "@ethersproject/strings": "^5.7.0" } }, + "node_modules/@fastify/busboy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz", + "integrity": "sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==", + "engines": { + "node": ">=14" + } + }, "node_modules/@govtechsg/jsonld": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@govtechsg/jsonld/-/jsonld-0.1.1.tgz", @@ -2092,15 +2280,31 @@ } }, "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -2128,9 +2332,9 @@ } }, "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -2194,9 +2398,9 @@ } }, "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -2221,19 +2425,29 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", @@ -2244,9 +2458,9 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "engines": { "node": ">=6.0.0" @@ -2579,16 +2793,16 @@ } }, "node_modules/@octokit/core": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.2.tgz", - "integrity": "sha512-cZUy1gUvd4vttMic7C0lwPed8IYXWYp8kHIMatyhY8t8n3Cpw2ILczkV5pGMPqef7v0bLo0pOHrEHarsau2Ydg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz", + "integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==", "dev": true, "dependencies": { "@octokit/auth-token": "^4.0.0", "@octokit/graphql": "^7.0.0", "@octokit/request": "^8.0.2", "@octokit/request-error": "^5.0.0", - "@octokit/types": "^12.0.0", + "@octokit/types": "^11.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" }, @@ -2597,12 +2811,13 @@ } }, "node_modules/@octokit/endpoint": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.4.tgz", - "integrity": "sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz", + "integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==", "dev": true, "dependencies": { - "@octokit/types": "^12.0.0", + "@octokit/types": "^11.0.0", + "is-plain-object": "^5.0.0", "universal-user-agent": "^6.0.0" }, "engines": { @@ -2610,13 +2825,13 @@ } }, "node_modules/@octokit/graphql": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.2.tgz", - "integrity": "sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz", + "integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==", "dev": true, "dependencies": { "@octokit/request": "^8.0.1", - "@octokit/types": "^12.0.0", + "@octokit/types": "^11.0.0", "universal-user-agent": "^6.0.0" }, "engines": { @@ -2624,18 +2839,18 @@ } }, "node_modules/@octokit/openapi-types": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.2.tgz", - "integrity": "sha512-8li32fUDUeml/ACRp/njCWTsk5t17cfTM1jp9n08pBrqs5cDFJubtjsSnuz56r5Tad6jdEPJld7LxNp9dNcyjQ==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", + "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==", "dev": true }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "9.1.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.1.4.tgz", - "integrity": "sha512-MvZx4WvfhBnt7PtH5XE7HORsO7bBk4er1FgRIUr1qJ89NR2I6bWjGyKsxk8z42FPQ34hFQm0Baanh4gzdZR4gQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-8.0.0.tgz", + "integrity": "sha512-2xZ+baZWUg+qudVXnnvXz7qfrTmDeYPCzangBVq/1gXxii/OiS//4shJp9dnCCvj1x+JAm9ji1Egwm1BA47lPQ==", "dev": true, "dependencies": { - "@octokit/types": "^12.3.0" + "@octokit/types": "^11.0.0" }, "engines": { "node": ">= 18" @@ -2645,13 +2860,13 @@ } }, "node_modules/@octokit/plugin-retry": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.0.1.tgz", - "integrity": "sha512-SKs+Tz9oj0g4p28qkZwl/topGcb0k0qPNX/i7vBKmDsjoeqnVfFUquqrE/O9oJY7+oLzdCtkiWSXLpLjvl6uog==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.0.0.tgz", + "integrity": "sha512-a1/A4A+PB1QoAHQfLJxGHhLfSAT03bR1jJz3GgQJZvty2ozawFWs93MiBQXO7SL2YbO7CIq0Goj4qLOBj8JeMQ==", "dev": true, "dependencies": { "@octokit/request-error": "^5.0.0", - "@octokit/types": "^12.0.0", + "@octokit/types": "^11.0.0", "bottleneck": "^2.15.3" }, "engines": { @@ -2662,12 +2877,12 @@ } }, "node_modules/@octokit/plugin-throttling": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-8.1.3.tgz", - "integrity": "sha512-pfyqaqpc0EXh5Cn4HX9lWYsZ4gGbjnSmUILeu4u2gnuM50K/wIk9s1Pxt3lVeVwekmITgN/nJdoh43Ka+vye8A==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-7.0.0.tgz", + "integrity": "sha512-KL2k/d0uANc8XqP5S64YcNFCudR3F5AaKO39XWdUtlJIjT9Ni79ekWJ6Kj5xvAw87udkOMEPcVf9xEge2+ahew==", "dev": true, "dependencies": { - "@octokit/types": "^12.2.0", + "@octokit/types": "^11.0.0", "bottleneck": "^2.15.3" }, "engines": { @@ -2678,14 +2893,15 @@ } }, "node_modules/@octokit/request": { - "version": "8.1.6", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.6.tgz", - "integrity": "sha512-YhPaGml3ncZC1NfXpP3WZ7iliL1ap6tLkAp6MvbK2fTTPytzVUyUesBBogcdMm86uRYO5rHaM1xIWxigWZ17MQ==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz", + "integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==", "dev": true, "dependencies": { "@octokit/endpoint": "^9.0.0", "@octokit/request-error": "^5.0.0", - "@octokit/types": "^12.0.0", + "@octokit/types": "^11.1.0", + "is-plain-object": "^5.0.0", "universal-user-agent": "^6.0.0" }, "engines": { @@ -2693,12 +2909,12 @@ } }, "node_modules/@octokit/request-error": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz", - "integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz", + "integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==", "dev": true, "dependencies": { - "@octokit/types": "^12.0.0", + "@octokit/types": "^11.0.0", "deprecation": "^2.0.0", "once": "^1.4.0" }, @@ -2707,12 +2923,12 @@ } }, "node_modules/@octokit/types": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.3.0.tgz", - "integrity": "sha512-nJ8X2HRr234q3w/FcovDlA+ttUU4m1eJAourvfUUtwAWeqL8AsyRqfnLvVnYn3NFbUnsmzQCzLNdFerPwdmcDQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz", + "integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^19.0.2" + "@octokit/openapi-types": "^18.0.0" } }, "node_modules/@pnpm/config.env-replace": { @@ -2891,20 +3107,20 @@ } }, "node_modules/@semantic-release/github": { - "version": "9.2.3", - "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-9.2.3.tgz", - "integrity": "sha512-FAjXb1F84CVI6IG8fWi+XS9ErYD+s3MHkP03zBa3+GyUrV4kqwYu/WPppIciHxujGFR51SAWPkOY5rnH6ZlrxA==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-9.0.4.tgz", + "integrity": "sha512-kQCGFAsBErvCR6hzNuzu63cj4erQN2krm9zQlg8vl4j5X0mL0d/Ras0wmL5Gkr1TuSS2lweME7M4J5zvtDDDSA==", "dev": true, "dependencies": { "@octokit/core": "^5.0.0", - "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/plugin-paginate-rest": "^8.0.0", "@octokit/plugin-retry": "^6.0.0", - "@octokit/plugin-throttling": "^8.0.0", + "@octokit/plugin-throttling": "^7.0.0", "@semantic-release/error": "^4.0.0", - "aggregate-error": "^5.0.0", + "aggregate-error": "^4.0.1", "debug": "^4.3.4", "dir-glob": "^3.0.1", - "globby": "^14.0.0", + "globby": "^13.1.4", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "issue-parser": "^6.0.0", @@ -2921,53 +3137,40 @@ } }, "node_modules/@semantic-release/github/node_modules/globby": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz", - "integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==", + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", "dev": true, "dependencies": { - "@sindresorhus/merge-streams": "^1.0.0", - "fast-glob": "^3.3.2", + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" + "merge2": "^1.4.1", + "slash": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/github/node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true, "engines": { - "node": ">=12" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@semantic-release/github/node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", "dev": true, "engines": { - "node": ">=14.16" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@semantic-release/npm": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-11.0.1.tgz", - "integrity": "sha512-nFcT0pgVwpXsPkzjqP3ObH+pILeN1AbYscCDuYwgZEPZukL+RsGhrtdT4HA1Gjb/y1bVbE90JNtMIcgRi5z/Fg==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-11.0.3.tgz", + "integrity": "sha512-KUsozQGhRBAnoVg4UMZj9ep436VEGwT536/jwSqB7vcEfA6oncCUU7UIYTRdLx7GvTtqn0kBjnkfLVkcnBa2YQ==", "dev": true, "dependencies": { "@semantic-release/error": "^4.0.0", @@ -2977,7 +3180,7 @@ "lodash-es": "^4.17.21", "nerf-dart": "^1.0.0", "normalize-url": "^8.0.0", - "npm": "^10.0.0", + "npm": "^10.5.0", "rc": "^1.2.8", "read-pkg": "^9.0.0", "registry-auth-token": "^5.0.0", @@ -2991,6 +3194,49 @@ "semantic-release": ">=20.1.0" } }, + "node_modules/@semantic-release/npm/node_modules/aggregate-error": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz", + "integrity": "sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==", + "dev": true, + "dependencies": { + "clean-stack": "^5.2.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/clean-stack": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz", + "integrity": "sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@semantic-release/npm/node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", @@ -3047,6 +3293,18 @@ "node": ">=16.17.0" } }, + "node_modules/@semantic-release/npm/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@semantic-release/npm/node_modules/is-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", @@ -3060,9 +3318,9 @@ } }, "node_modules/@semantic-release/npm/node_modules/lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -3096,9 +3354,9 @@ } }, "node_modules/@semantic-release/npm/node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, "dependencies": { "path-key": "^4.0.0" @@ -3198,9 +3456,9 @@ } }, "node_modules/@semantic-release/npm/node_modules/type-fest": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.8.2.tgz", - "integrity": "sha512-mcvrCjixA5166hSrUoJgGb9gBQN4loMYyj9zxuMs/66ibHNEFd5JXMw37YVDx58L4/QID9jIzdTBB4mDwDJ6KQ==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.18.1.tgz", + "integrity": "sha512-qXhgeNsX15bM63h5aapNFcQid9jRF/l3ojDoDFmekDQEUufZ9U4ErVt6SjDxnHp48Ltrw616R8yNc3giJ3KvVQ==", "dev": true, "engines": { "node": ">=16" @@ -3300,9 +3558,9 @@ } }, "node_modules/@semantic-release/release-notes-generator/node_modules/lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -3411,9 +3669,9 @@ } }, "node_modules/@semantic-release/release-notes-generator/node_modules/type-fest": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.8.2.tgz", - "integrity": "sha512-mcvrCjixA5166hSrUoJgGb9gBQN4loMYyj9zxuMs/66ibHNEFd5JXMw37YVDx58L4/QID9jIzdTBB4mDwDJ6KQ==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.18.1.tgz", + "integrity": "sha512-qXhgeNsX15bM63h5aapNFcQid9jRF/l3ojDoDFmekDQEUufZ9U4ErVt6SjDxnHp48Ltrw616R8yNc3giJ3KvVQ==", "dev": true, "engines": { "node": ">=16" @@ -3440,22 +3698,10 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, - "node_modules/@sindresorhus/merge-streams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz", - "integrity": "sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, "dependencies": { "type-detect": "4.0.8" @@ -3470,6 +3716,137 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@smithy/hash-node": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-1.1.0.tgz", + "integrity": "sha512-yiNKDGMzrQjnpnbLfkYKo+HwIxmBAsv0AI++QIJwvhfkLpUTBylelkv6oo78/YqZZS6h+bGfl0gILJsKE2wAKQ==", + "dependencies": { + "@smithy/types": "^1.2.0", + "@smithy/util-buffer-from": "^1.1.0", + "@smithy/util-utf8": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/hash-node/node_modules/@smithy/types": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.2.0.tgz", + "integrity": "sha512-z1r00TvBqF3dh4aHhya7nz1HhvCg4TRmw51fjMrh5do3h+ngSstt/yKlNbHeb9QxJmFbmN8KEVSWgb1bRvfEoA==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/hash-node/node_modules/@smithy/util-utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-1.1.0.tgz", + "integrity": "sha512-p/MYV+JmqmPyjdgyN2UxAeYDj9cBqCjp0C/NsTWnnjoZUVqoeZ6IrW915L9CAKWVECgv9lVQGc4u/yz26/bI1A==", + "dependencies": { + "@smithy/util-buffer-from": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/hash-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/is-array-buffer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-1.1.0.tgz", + "integrity": "sha512-twpQ/n+3OWZJ7Z+xu43MJErmhB/WO/mMTnqR6PwWQShvSJ/emx5d1N59LQZk6ZpTAeuRWrc+eHhkzTp9NFjNRQ==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/is-array-buffer/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/types": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.12.0.tgz", + "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/types/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-buffer-from": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-1.1.0.tgz", + "integrity": "sha512-9m6NXE0ww+ra5HKHCHig20T+FAwxBAm7DIdwc/767uGWbRcY720ybgPacQNB96JMOI7xVr/CDa3oMzKmW4a+kw==", + "dependencies": { + "@smithy/is-array-buffer": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-buffer-from/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -3495,9 +3872,9 @@ "dev": true }, "node_modules/@types/babel__core": { - "version": "7.20.3", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz", - "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "dependencies": { "@babel/parser": "^7.20.7", @@ -3508,18 +3885,18 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.6", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz", - "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==", + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", "dev": true, "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz", - "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "dependencies": { "@babel/parser": "^7.1.0", @@ -3527,18 +3904,18 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.3.tgz", - "integrity": "sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", "dev": true, "dependencies": { "@babel/types": "^7.20.7" } }, "node_modules/@types/debug": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.10.tgz", - "integrity": "sha512-tOSCru6s732pofZ+sMv9o4o3Zc+Sa8l3bxd/tweTQudFn06vAzb13ZX46Zi6m6EJ+RUbRTHvgQJ1gBtSgkaUYA==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", + "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", "dev": true, "dependencies": { "@types/ms": "*" @@ -3551,42 +3928,42 @@ "dev": true }, "node_modules/@types/graceful-fs": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.8.tgz", - "integrity": "sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", "dev": true }, "node_modules/@types/istanbul-lib-report": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.2.tgz", - "integrity": "sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.3.tgz", - "integrity": "sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } }, "node_modules/@types/jest": { - "version": "29.5.6", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.6.tgz", - "integrity": "sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==", + "version": "29.5.3", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz", + "integrity": "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -3604,9 +3981,9 @@ } }, "node_modules/@types/json-schema": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", - "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", "dev": true }, "node_modules/@types/json5": { @@ -3616,60 +3993,69 @@ "dev": true }, "node_modules/@types/jsonld": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@types/jsonld/-/jsonld-1.5.11.tgz", - "integrity": "sha512-/B5yjthc6MEJMR4+TUtaj5LgE3bByVSNIXvPcUxiecj5F7GZKQJS5oery5rbOni7T9QBpjDF0RufCcVVlCe4hw==", + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@types/jsonld/-/jsonld-1.5.13.tgz", + "integrity": "sha512-n7fUU6W4kSYK8VQlf/LsE9kddBHPKhODoVOjsZswmve+2qLwBy6naWxs/EiuSZN9NU0N06Ra01FR+j87C62T0A==", "dev": true }, "node_modules/@types/lodash": { - "version": "4.14.200", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.200.tgz", - "integrity": "sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==", + "version": "4.14.197", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", + "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==", "dev": true }, "node_modules/@types/minimist": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.4.tgz", - "integrity": "sha512-Kfe/D3hxHTusnPNRbycJE1N77WHDsdS4AjUYIzlDzhDrS47NrwuL3YW4VITxwR7KCVpzwgy4Rbj829KSSQmwXQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", "dev": true }, "node_modules/@types/ms": { - "version": "0.7.33", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.33.tgz", - "integrity": "sha512-AuHIyzR5Hea7ij0P9q7vx7xu4z0C28ucwjAZC0ja7JhINyCnOw8/DnvAPQQ9TfOlCtZAmCERKQX9+o1mgQhuOQ==", + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", "dev": true }, "node_modules/@types/node": { - "version": "20.5.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.1.tgz", - "integrity": "sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg==", + "version": "20.4.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.7.tgz", + "integrity": "sha512-bUBrPjEry2QUTsnuEjzjbS7voGWCc30W0qzgMf90GPeDGFRakvrz47ju+oqDAKCXLUCe39u57/ORMl/O/04/9g==", "dev": true }, "node_modules/@types/normalize-package-data": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.3.tgz", - "integrity": "sha512-ehPtgRgaULsFG8x0NeYJvmyH1hmlfsNLujHe9dQEia/7MAJYdzMSi19JtchUHjmBA6XC/75dK55mzZH+RyieSg==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, "node_modules/@types/qrcode": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.4.tgz", - "integrity": "sha512-ufYqUO7wUBq49hugJry+oIYKscvxIQerJSmXeny215aJKfrepN04DDZP8FCgxvV82kOqKPULCE4PIW3qUmZrRA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.1.tgz", + "integrity": "sha512-HpSN675K0PmxIDRpjMI3Mc2GiKo3dNu+X/F5SoItiaDS1lVfgC6Wac1c5lQDfKWbTJUSHWiHKzpJpBZG7k9gaA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/randombytes": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/randombytes/-/randombytes-2.0.3.tgz", + "integrity": "sha512-+NRgihTfuURllWCiIAhm1wsJqzsocnqXM77V/CalsdJIYSRGEHMnritxh+6EsBklshC+clo1KgnN14qgSGeQdw==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/stack-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.2.tgz", - "integrity": "sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, "node_modules/@types/uuid": { @@ -3679,37 +4065,37 @@ "dev": true }, "node_modules/@types/validator": { - "version": "13.11.5", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.5.tgz", - "integrity": "sha512-xW4qsT4UIYILu+7ZrBnfQdBYniZrMLYYK3wN9M/NdeIHgBN5pZI2/8Q7UfdWIcr5RLJv/OGENsx91JIpUUoC7Q==", + "version": "13.11.1", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.1.tgz", + "integrity": "sha512-d/MUkJYdOeKycmm75Arql4M5+UuXmf4cHdHKsyw1GcvnNgL6s77UkgSgJ8TE/rI5PYsnwYq5jkcWBLuN/MpQ1A==", "dev": true }, "node_modules/@types/yargs": { - "version": "17.0.29", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.29.tgz", - "integrity": "sha512-nacjqA3ee9zRF/++a3FUY1suHTFKZeHba2n8WeDw9cCVdmzmHpIxyzOJBcpHvvEmS8E9KqWlSnWHUkOrkhWcvA==", + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "21.0.2", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.2.tgz", - "integrity": "sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==", + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.0.tgz", - "integrity": "sha512-lgX7F0azQwRPB7t7WAyeHWVfW1YJ9NIgd9mvGhfQpRY56X6AVf8mwM8Wol+0z4liE7XX3QOt8MN1rUKCfSjRIA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.9.0", - "@typescript-eslint/type-utils": "6.9.0", - "@typescript-eslint/utils": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -3735,13 +4121,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.0.tgz", - "integrity": "sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -3752,9 +4138,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz", - "integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -3765,12 +4151,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz", - "integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -3818,15 +4204,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.9.0.tgz", - "integrity": "sha512-GZmjMh4AJ/5gaH4XF2eXA8tMnHWP+Pm1mjQR2QN4Iz+j/zO04b9TOvJYOX2sCNIQHtRStKTxRY1FX7LhpJT4Gw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.9.0", - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/typescript-estree": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4" }, "engines": { @@ -3846,13 +4232,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.0.tgz", - "integrity": "sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -3863,9 +4249,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz", - "integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -3876,16 +4262,17 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.0.tgz", - "integrity": "sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, @@ -3903,12 +4290,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz", - "integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -3919,6 +4306,15 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", @@ -3931,14 +4327,29 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", - "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", + "node_modules/@typescript-eslint/parser/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/visitor-keys": "4.33.0" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", + "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0" }, "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" @@ -3949,13 +4360,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.0.tgz", - "integrity": "sha512-XXeahmfbpuhVbhSOROIzJ+b13krFmgtc4GlEuu1WBT+RpyGPIA4Y/eGnXzjbDj5gZLzpAXO/sj+IF/x2GtTMjQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.9.0", - "@typescript-eslint/utils": "6.9.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -3976,9 +4387,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz", - "integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -3989,16 +4400,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.0.tgz", - "integrity": "sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, @@ -4016,12 +4428,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz", - "integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -4032,6 +4444,15 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@typescript-eslint/type-utils/node_modules/eslint-visitor-keys": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", @@ -4044,6 +4465,21 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/types": { "version": "4.33.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", @@ -4085,17 +4521,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.0.tgz", - "integrity": "sha512-5Wf+Jsqya7WcCO8me504FBigeQKVLAMPmUzYgDbWchINNh1KJbxCgVya3EQ2MjvJMVeXl3pofRmprqX6mfQkjQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.9.0", - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/typescript-estree": "6.9.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", "semver": "^7.5.4" }, "engines": { @@ -4110,13 +4546,13 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.0.tgz", - "integrity": "sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -4127,9 +4563,9 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz", - "integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -4140,16 +4576,17 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.0.tgz", - "integrity": "sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", - "@typescript-eslint/visitor-keys": "6.9.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, @@ -4167,12 +4604,12 @@ } }, "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz", - "integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.9.0", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -4183,6 +4620,15 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/utils/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@typescript-eslint/utils/node_modules/eslint-visitor-keys": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", @@ -4195,6 +4641,21 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@typescript-eslint/utils/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@typescript-eslint/visitor-keys": { "version": "4.33.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", @@ -4212,6 +4673,17 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -4242,6 +4714,11 @@ "node": ">=0.4.0" } }, + "node_modules/aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" + }, "node_modules/agent-base": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", @@ -4255,16 +4732,16 @@ } }, "node_modules/aggregate-error": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz", - "integrity": "sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", "dev": true, "dependencies": { - "clean-stack": "^5.2.0", + "clean-stack": "^4.0.0", "indent-string": "^5.0.0" }, "engines": { - "node": ">=18" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4424,15 +4901,15 @@ "dev": true }, "node_modules/array-includes": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", - "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", "is-string": "^1.0.7" }, "engines": { @@ -4452,16 +4929,16 @@ } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz", + "integrity": "sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "get-intrinsic": "^1.1.3" }, "engines": { "node": ">= 0.4" @@ -4471,14 +4948,14 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -4489,14 +4966,14 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -4507,15 +4984,14 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", + "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", "call-bind": "^1.0.2", "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", "get-intrinsic": "^1.2.1", "is-array-buffer": "^3.0.2", "is-shared-array-buffer": "^1.0.2" @@ -4603,31 +5079,6 @@ "node": ">=8" } }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/babel-plugin-jest-hoist": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", @@ -4692,7 +5143,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -4708,6 +5158,11 @@ } ] }, + "node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" + }, "node_modules/before-after-hook": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", @@ -4725,6 +5180,30 @@ "readable-stream": "^3.4.0" } }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/bn.js": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", @@ -4747,12 +5226,12 @@ } }, "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { - "fill-range": "^7.1.1" + "fill-range": "^7.0.1" }, "engines": { "node": ">=8" @@ -4831,9 +5310,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ { @@ -4850,9 +5329,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, "bin": { @@ -4884,10 +5363,9 @@ } }, "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "funding": [ { "type": "github", @@ -4904,7 +5382,7 @@ ], "dependencies": { "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "ieee754": "^1.2.1" } }, "node_modules/buffer-equal": { @@ -4932,14 +5410,13 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, "dependencies": { - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4981,9 +5458,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001551", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001551.tgz", - "integrity": "sha512-vtBAez47BoGMMzlbYhfXrMV1kvRF2WP/lqiMuDu1Sb4EE4LKEgjopFDSRtZfdVnslNRpOqV/woE+Xgrwj6VQlg==", + "version": "1.0.30001599", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001599.tgz", + "integrity": "sha512-LRAQHZ4yT1+f9LemSMeqdMpMxZcc4RMWdj4tiFe3G8tNkWK+E58g+/tzotb5cU6TbcVJLr4fySiAW7XmxQvZQA==", "dev": true, "funding": [ { @@ -5071,9 +5548,9 @@ "dev": true }, "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", "dev": true, "funding": [ { @@ -5092,15 +5569,15 @@ "dev": true }, "node_modules/clean-stack": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz", - "integrity": "sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", "dev": true, "dependencies": { "escape-string-regexp": "5.0.0" }, "engines": { - "node": ">=14.16" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5131,9 +5608,9 @@ } }, "node_modules/cli-spinners": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", - "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz", + "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==", "dev": true, "engines": { "node": ">=6" @@ -5143,9 +5620,9 @@ } }, "node_modules/cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.4.tgz", + "integrity": "sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==", "dev": true, "dependencies": { "string-width": "^4.2.0" @@ -5157,6 +5634,112 @@ "@colors/colors": "1.5.0" } }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/cli-width": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", @@ -5235,6 +5818,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, "node_modules/command-line-args": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-4.0.7.tgz", @@ -5326,6 +5915,15 @@ "node": ">=4" } }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, "node_modules/commitizen": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.3.0.tgz", @@ -5697,14 +6295,14 @@ "dev": true }, "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", + "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", "dev": true, "dependencies": { - "import-fresh": "^3.3.0", + "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", + "parse-json": "^5.0.0", "path-type": "^4.0.0" }, "engines": { @@ -5712,14 +6310,6 @@ }, "funding": { "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } } }, "node_modules/cosmiconfig-typescript-loader": { @@ -5904,6 +6494,14 @@ "node": ">=8" } }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -5996,27 +6594,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", "dev": true, "dependencies": { - "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -6166,9 +6749,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.563", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.563.tgz", - "integrity": "sha512-dg5gj5qOgfZNkPNeyKBZQAQitIQ/xwfIDmEQJHCbXaD9ebTZxwJXUsDYcBlAvZGZLi+/354l35J1wkmP6CqYaw==", + "version": "1.4.713", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.713.tgz", + "integrity": "sha512-vDarADhwntXiULEdmWd77g2dV6FrNGa8ecAC29MZ4TwPut2fvosD0/5sJd1qWNNe8HcJFAC+F5Lf9jW1NPtWmw==", "dev": true }, "node_modules/elliptic": { @@ -6345,9 +6928,9 @@ } }, "node_modules/env-ci/node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, "dependencies": { "path-key": "^4.0.0" @@ -6420,18 +7003,18 @@ } }, "node_modules/es-abstract": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz", - "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", + "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.1", "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", + "function.prototype.name": "^1.1.5", "get-intrinsic": "^1.2.1", "get-symbol-description": "^1.0.0", "globalthis": "^1.0.3", @@ -6447,23 +7030,23 @@ "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", + "is-typed-array": "^1.1.10", "is-weakref": "^1.0.2", "object-inspect": "^1.12.3", "object-keys": "^1.1.1", "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", + "regexp.prototype.flags": "^1.5.0", + "safe-array-concat": "^1.0.0", "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", "typed-array-buffer": "^1.0.0", "typed-array-byte-length": "^1.0.0", "typed-array-byte-offset": "^1.0.0", "typed-array-length": "^1.0.4", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.10" }, "engines": { "node": ">= 0.4" @@ -7104,6 +7687,67 @@ "node": ">=0.10.0" } }, + "node_modules/ethers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", + "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -7215,9 +7859,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -7260,6 +7904,28 @@ "bser": "2.1.1" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -7285,9 +7951,9 @@ } }, "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -7393,17 +8059,16 @@ } }, "node_modules/flat-cache": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", - "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", + "flatted": "^3.1.0", "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.0.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatley": { @@ -7415,9 +8080,9 @@ } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, "node_modules/for-each": { @@ -7429,6 +8094,17 @@ "is-callable": "^1.1.3" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -7496,9 +8172,9 @@ "dev": true }, "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "hasInstallScript": true, "optional": true, @@ -7510,24 +8186,21 @@ } }, "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" }, "engines": { "node": ">= 0.4" @@ -7569,6 +8242,18 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", @@ -7806,9 +8491,9 @@ } }, "node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -7931,10 +8616,13 @@ } }, "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, "engines": { "node": ">= 0.4.0" } @@ -8083,9 +8771,9 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", - "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.1.tgz", + "integrity": "sha512-Eun8zV0kcYS1g19r78osiQLEFIRspRUDd9tIfBCTBPBeMieF/EsJNL8VI3xOIdYRDEkjQnqOYPsZ2DsWsVsFwQ==", "dev": true, "dependencies": { "agent-base": "^7.0.2", @@ -8135,7 +8823,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, "funding": [ { "type": "github", @@ -8186,9 +8873,9 @@ } }, "node_modules/import-from-esm": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/import-from-esm/-/import-from-esm-1.3.3.tgz", - "integrity": "sha512-U3Qt/CyfFpTUv6LOP2jRTLYjphH6zg3okMfHbyqRa/W2w6hr8OsJWVggNlR4jxuojQy81TgTJTxgSkyoteRGMQ==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/import-from-esm/-/import-from-esm-1.3.4.tgz", + "integrity": "sha512-7EyUlPFC0HOlBDpUFGfYstsU7XHxZJKAAMzCT8wZ0hMW7b+hG51LIKTDcsgtz8Pu6YC0HqRVbX+rVUtsGMUKvg==", "dev": true, "dependencies": { "debug": "^4.3.4", @@ -8218,9 +8905,9 @@ } }, "node_modules/import-meta-resolve": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz", - "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", "dev": true, "funding": { "type": "github", @@ -8670,6 +9357,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-reference": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", @@ -8888,19 +9584,28 @@ } }, "node_modules/istanbul-lib-instrument": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", - "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" + "semver": "^6.3.0" }, "engines": { - "node": ">=10" + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, "node_modules/istanbul-lib-report": { @@ -8932,9 +9637,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -9074,6 +9779,39 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, "node_modules/jest-config": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", @@ -9691,39 +10429,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jest/node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", - "dev": true, - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, "node_modules/js-base64": { "version": "3.7.5", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz", @@ -9764,12 +10469,6 @@ "node": ">=4" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -9844,6 +10543,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/jsonld": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/jsonld/-/jsonld-8.3.2.tgz", + "integrity": "sha512-MwBbq95szLwt8eVQ1Bcfwmgju/Y5P2GdtlHE2ncyfuYjIdEhluUVyj1eudacf1mOkWIoS9GpDBTECqhmq7EOaA==", + "dependencies": { + "@digitalbazaar/http-client": "^3.4.1", + "canonicalize": "^1.0.1", + "lru-cache": "^6.0.0", + "rdf-canonize": "^3.4.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", @@ -9869,15 +10582,6 @@ "node": "*" } }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -9896,6 +10600,58 @@ "node": ">=6" } }, + "node_modules/ky": { + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/ky/-/ky-0.33.3.tgz", + "integrity": "sha512-CasD9OCEQSFIam2U8efFK81Yeg8vNMTBUqtMOHlrcWQHqUX3HeCl9Dr31u4toV7emlH8Mymk5+9p0lL6mKb/Xw==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/ky?sponsor=1" + } + }, + "node_modules/ky-universal": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/ky-universal/-/ky-universal-0.11.0.tgz", + "integrity": "sha512-65KyweaWvk+uKKkCrfAf+xqN2/epw1IJDtlyCPxYffFCMR8u1sp2U65NtWpnozYfZxQ6IUzIlvUcw+hQ82U2Xw==", + "dependencies": { + "abort-controller": "^3.0.0", + "node-fetch": "^3.2.10" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/ky-universal?sponsor=1" + }, + "peerDependencies": { + "ky": ">=0.31.4", + "web-streams-polyfill": ">=3.2.1" + }, + "peerDependenciesMeta": { + "web-streams-polyfill": { + "optional": true + } + } + }, + "node_modules/ky-universal/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", @@ -9930,28 +10686,315 @@ "node": ">= 0.8.0" } }, + "node_modules/lilconfig": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, - "node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "node_modules/lint-staged": { + "version": "15.2.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", + "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", "dev": true, "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + "chalk": "5.3.0", + "commander": "11.1.0", + "debug": "4.3.4", + "execa": "8.0.1", + "lilconfig": "3.0.0", + "listr2": "8.0.1", + "micromatch": "4.0.5", + "pidtree": "0.6.0", + "string-argv": "0.3.2", + "yaml": "2.3.4" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": ">=4" + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" } }, - "node_modules/load-json-file/node_modules/parse-json": { + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/lint-staged/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/lint-staged/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/yaml": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/listr2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", + "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", + "dev": true, + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.0.0", + "rfdc": "^1.3.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", @@ -10092,32 +11135,204 @@ "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", "dev": true }, - "node_modules/lodash.uniqby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", - "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", - "dev": true + "node_modules/lodash.uniqby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", + "dev": true + }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "dev": true, + "dependencies": { + "ansi-escapes": "^6.2.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/lodash.upperfirst": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", - "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", - "dev": true + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/longest": { @@ -10216,33 +11431,30 @@ } }, "node_modules/marked-terminal": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-6.1.0.tgz", - "integrity": "sha512-QaCSF6NV82oo6K0szEnmc65ooDeW0T/Adcyf0fcW+Hto2GT1VADFg8dn1zaeHqzj65fqDH1hMNChGNRaC/lbkA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-6.2.0.tgz", + "integrity": "sha512-ubWhwcBFHnXsjYNsu+Wndpg0zhY4CahSpPlA70PlO0rR9r2sZpkyU+rkCsOWH+KMEkx847UpALON+HWgxowFtw==", "dev": true, "dependencies": { "ansi-escapes": "^6.2.0", "cardinal": "^2.1.1", "chalk": "^5.3.0", "cli-table3": "^0.6.3", - "node-emoji": "^2.1.0", + "node-emoji": "^2.1.3", "supports-hyperlinks": "^3.0.0" }, "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "marked": ">=1 <11" + "marked": ">=1 <12" } }, "node_modules/marked-terminal/node_modules/ansi-escapes": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", - "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", "dev": true, - "dependencies": { - "type-fest": "^3.0.0" - }, "engines": { "node": ">=14.16" }, @@ -10262,18 +11474,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/marked-terminal/node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/mem": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", @@ -10484,6 +11684,24 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-emoji": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", @@ -10500,9 +11718,9 @@ } }, "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -10525,9 +11743,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/nofilter": { @@ -10567,9 +11785,9 @@ } }, "node_modules/normalize-url": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", - "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", + "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", "dev": true, "engines": { "node": ">=14.16" @@ -10579,9 +11797,9 @@ } }, "node_modules/npm": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/npm/-/npm-10.8.2.tgz", - "integrity": "sha512-x/AIjFIKRllrhcb48dqUNAAZl0ig9+qMuN91RpZo3Cb2+zuibfh+KISl6+kVVyktDz230JKc208UkQwwMqyB+w==", + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/npm/-/npm-10.7.0.tgz", + "integrity": "sha512-FXylyYSXNjgXx3l82BT8RSQvCoGIQ3h8YdRFGKNvo3Pv/bKscK4pdWkx/onwTpHDqGw+oeLf4Rxln9WVyxAxlQ==", "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", @@ -10653,73 +11871,80 @@ "write-file-atomic" ], "dev": true, + "workspaces": [ + "docs", + "smoke-tests", + "mock-globals", + "mock-registry", + "workspaces/*" + ], "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^7.5.4", - "@npmcli/config": "^8.3.4", - "@npmcli/fs": "^3.1.1", + "@npmcli/arborist": "^7.2.1", + "@npmcli/config": "^8.0.2", + "@npmcli/fs": "^3.1.0", "@npmcli/map-workspaces": "^3.0.6", - "@npmcli/package-json": "^5.2.0", - "@npmcli/promise-spawn": "^7.0.2", - "@npmcli/redact": "^2.0.1", + "@npmcli/package-json": "^5.1.0", + "@npmcli/promise-spawn": "^7.0.1", + "@npmcli/redact": "^2.0.0", "@npmcli/run-script": "^8.1.0", - "@sigstore/tuf": "^2.3.4", + "@sigstore/tuf": "^2.3.2", "abbrev": "^2.0.0", "archy": "~1.0.0", - "cacache": "^18.0.3", + "cacache": "^18.0.2", "chalk": "^5.3.0", "ci-info": "^4.0.0", "cli-columns": "^4.0.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", - "glob": "^10.4.2", + "glob": "^10.3.12", "graceful-fs": "^4.2.11", - "hosted-git-info": "^7.0.2", - "ini": "^4.1.3", - "init-package-json": "^6.0.3", - "is-cidr": "^5.1.0", - "json-parse-even-better-errors": "^3.0.2", - "libnpmaccess": "^8.0.6", - "libnpmdiff": "^6.1.4", - "libnpmexec": "^8.1.3", - "libnpmfund": "^5.0.12", - "libnpmhook": "^10.0.5", - "libnpmorg": "^6.0.6", - "libnpmpack": "^7.0.4", - "libnpmpublish": "^9.0.9", - "libnpmsearch": "^7.0.6", - "libnpmteam": "^6.0.5", - "libnpmversion": "^6.0.3", + "hosted-git-info": "^7.0.1", + "ini": "^4.1.2", + "init-package-json": "^6.0.2", + "is-cidr": "^5.0.5", + "json-parse-even-better-errors": "^3.0.1", + "libnpmaccess": "^8.0.1", + "libnpmdiff": "^6.0.3", + "libnpmexec": "^8.0.0", + "libnpmfund": "^5.0.1", + "libnpmhook": "^10.0.0", + "libnpmorg": "^6.0.1", + "libnpmpack": "^7.0.0", + "libnpmpublish": "^9.0.2", + "libnpmsearch": "^7.0.0", + "libnpmteam": "^6.0.0", + "libnpmversion": "^6.0.0", "make-fetch-happen": "^13.0.1", - "minimatch": "^9.0.5", - "minipass": "^7.1.1", + "minimatch": "^9.0.4", + "minipass": "^7.0.4", "minipass-pipeline": "^1.2.4", "ms": "^2.1.2", "node-gyp": "^10.1.0", - "nopt": "^7.2.1", - "normalize-package-data": "^6.0.2", + "nopt": "^7.2.0", + "normalize-package-data": "^6.0.0", "npm-audit-report": "^5.0.0", "npm-install-checks": "^6.3.0", "npm-package-arg": "^11.0.2", - "npm-pick-manifest": "^9.1.0", - "npm-profile": "^10.0.0", - "npm-registry-fetch": "^17.1.0", - "npm-user-validate": "^2.0.1", + "npm-pick-manifest": "^9.0.0", + "npm-profile": "^9.0.2", + "npm-registry-fetch": "^17.0.0", + "npm-user-validate": "^2.0.0", "p-map": "^4.0.0", - "pacote": "^18.0.6", + "pacote": "^18.0.3", "parse-conflict-json": "^3.0.1", "proc-log": "^4.2.0", "qrcode-terminal": "^0.12.0", "read": "^3.0.1", - "semver": "^7.6.2", + "semver": "^7.6.0", "spdx-expression-parse": "^4.0.0", - "ssri": "^10.0.6", + "ssri": "^10.0.5", "supports-color": "^9.4.0", "tar": "^6.2.1", "text-table": "~0.2.0", "tiny-relative-date": "^1.3.0", "treeverse": "^3.0.0", - "validate-npm-package-name": "^5.0.1", + "validate-npm-package-name": "^5.0.0", "which": "^4.0.0", "write-file-atomic": "^5.0.1" }, @@ -10833,36 +12058,35 @@ } }, "node_modules/npm/node_modules/@npmcli/arborist": { - "version": "7.5.4", + "version": "7.5.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/fs": "^3.1.1", + "@npmcli/fs": "^3.1.0", "@npmcli/installed-package-contents": "^2.1.0", "@npmcli/map-workspaces": "^3.0.2", - "@npmcli/metavuln-calculator": "^7.1.1", + "@npmcli/metavuln-calculator": "^7.1.0", "@npmcli/name-from-folder": "^2.0.0", "@npmcli/node-gyp": "^3.0.0", "@npmcli/package-json": "^5.1.0", "@npmcli/query": "^3.1.0", "@npmcli/redact": "^2.0.0", "@npmcli/run-script": "^8.1.0", - "bin-links": "^4.0.4", - "cacache": "^18.0.3", + "bin-links": "^4.0.1", + "cacache": "^18.0.0", "common-ancestor-path": "^1.0.1", - "hosted-git-info": "^7.0.2", - "json-parse-even-better-errors": "^3.0.2", + "hosted-git-info": "^7.0.1", + "json-parse-even-better-errors": "^3.0.0", "json-stringify-nice": "^1.1.4", - "lru-cache": "^10.2.2", "minimatch": "^9.0.4", - "nopt": "^7.2.1", + "nopt": "^7.0.0", "npm-install-checks": "^6.2.0", "npm-package-arg": "^11.0.2", - "npm-pick-manifest": "^9.0.1", - "npm-registry-fetch": "^17.0.1", - "pacote": "^18.0.6", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^17.0.0", + "pacote": "^18.0.1", "parse-conflict-json": "^3.0.0", "proc-log": "^4.2.0", "proggy": "^2.0.0", @@ -10870,7 +12094,7 @@ "promise-call-limit": "^3.0.1", "read-package-json-fast": "^3.0.2", "semver": "^7.3.7", - "ssri": "^10.0.6", + "ssri": "^10.0.5", "treeverse": "^3.0.0", "walk-up-path": "^3.0.1" }, @@ -10882,17 +12106,17 @@ } }, "node_modules/npm/node_modules/@npmcli/config": { - "version": "8.3.4", + "version": "8.3.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/map-workspaces": "^3.0.2", - "@npmcli/package-json": "^5.1.1", "ci-info": "^4.0.0", "ini": "^4.1.2", - "nopt": "^7.2.1", + "nopt": "^7.0.0", "proc-log": "^4.2.0", + "read-package-json-fast": "^3.0.2", "semver": "^7.3.5", "walk-up-path": "^3.0.1" }, @@ -10901,7 +12125,7 @@ } }, "node_modules/npm/node_modules/@npmcli/fs": { - "version": "3.1.1", + "version": "3.1.0", "dev": true, "inBundle": true, "license": "ISC", @@ -10913,13 +12137,12 @@ } }, "node_modules/npm/node_modules/@npmcli/git": { - "version": "5.0.8", + "version": "5.0.6", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/promise-spawn": "^7.0.0", - "ini": "^4.1.3", "lru-cache": "^10.0.1", "npm-pick-manifest": "^9.0.0", "proc-log": "^4.0.0", @@ -10964,7 +12187,7 @@ } }, "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { - "version": "7.1.1", + "version": "7.1.0", "dev": true, "inBundle": true, "license": "ISC", @@ -10998,7 +12221,7 @@ } }, "node_modules/npm/node_modules/@npmcli/package-json": { - "version": "5.2.0", + "version": "5.1.0", "dev": true, "inBundle": true, "license": "ISC", @@ -11016,7 +12239,7 @@ } }, "node_modules/npm/node_modules/@npmcli/promise-spawn": { - "version": "7.0.2", + "version": "7.0.1", "dev": true, "inBundle": true, "license": "ISC", @@ -11040,7 +12263,7 @@ } }, "node_modules/npm/node_modules/@npmcli/redact": { - "version": "2.0.1", + "version": "2.0.0", "dev": true, "inBundle": true, "license": "ISC", @@ -11076,12 +12299,12 @@ } }, "node_modules/npm/node_modules/@sigstore/bundle": { - "version": "2.3.2", + "version": "2.3.1", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/protobuf-specs": "^0.3.2" + "@sigstore/protobuf-specs": "^0.3.1" }, "engines": { "node": "^16.14.0 || >=18.0.0" @@ -11097,7 +12320,7 @@ } }, "node_modules/npm/node_modules/@sigstore/protobuf-specs": { - "version": "0.3.2", + "version": "0.3.1", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -11106,44 +12329,42 @@ } }, "node_modules/npm/node_modules/@sigstore/sign": { - "version": "2.3.2", + "version": "2.3.0", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/bundle": "^2.3.2", + "@sigstore/bundle": "^2.3.0", "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.2", - "make-fetch-happen": "^13.0.1", - "proc-log": "^4.2.0", - "promise-retry": "^2.0.1" + "@sigstore/protobuf-specs": "^0.3.1", + "make-fetch-happen": "^13.0.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/@sigstore/tuf": { - "version": "2.3.4", + "version": "2.3.2", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/protobuf-specs": "^0.3.2", - "tuf-js": "^2.2.1" + "@sigstore/protobuf-specs": "^0.3.0", + "tuf-js": "^2.2.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/@sigstore/verify": { - "version": "1.2.1", + "version": "1.2.0", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/bundle": "^2.3.2", + "@sigstore/bundle": "^2.3.1", "@sigstore/core": "^1.1.0", - "@sigstore/protobuf-specs": "^0.3.2" + "@sigstore/protobuf-specs": "^0.3.1" }, "engines": { "node": "^16.14.0 || >=18.0.0" @@ -11159,13 +12380,13 @@ } }, "node_modules/npm/node_modules/@tufjs/models": { - "version": "2.0.1", + "version": "2.0.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "@tufjs/canonical-json": "2.0.0", - "minimatch": "^9.0.4" + "minimatch": "^9.0.3" }, "engines": { "node": "^16.14.0 || >=18.0.0" @@ -11245,7 +12466,7 @@ "license": "MIT" }, "node_modules/npm/node_modules/bin-links": { - "version": "4.0.4", + "version": "4.0.3", "dev": true, "inBundle": true, "license": "ISC", @@ -11280,8 +12501,17 @@ "balanced-match": "^1.0.0" } }, + "node_modules/npm/node_modules/builtins": { + "version": "5.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "semver": "^7.0.0" + } + }, "node_modules/npm/node_modules/cacache": { - "version": "18.0.3", + "version": "18.0.2", "dev": true, "inBundle": true, "license": "ISC", @@ -11340,7 +12570,7 @@ } }, "node_modules/npm/node_modules/cidr-regex": { - "version": "4.1.1", + "version": "4.0.5", "dev": true, "inBundle": true, "license": "BSD-2-Clause", @@ -11374,7 +12604,7 @@ } }, "node_modules/npm/node_modules/cmd-shim": { - "version": "6.0.3", + "version": "6.0.2", "dev": true, "inBundle": true, "license": "ISC", @@ -11448,7 +12678,7 @@ } }, "node_modules/npm/node_modules/debug": { - "version": "4.3.5", + "version": "4.3.4", "dev": true, "inBundle": true, "license": "MIT", @@ -11532,7 +12762,7 @@ } }, "node_modules/npm/node_modules/foreground-child": { - "version": "3.2.1", + "version": "3.1.1", "dev": true, "inBundle": true, "license": "ISC", @@ -11559,24 +12789,32 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/npm/node_modules/function-bind": { + "version": "1.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/npm/node_modules/glob": { - "version": "10.4.2", + "version": "10.3.12", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -11588,8 +12826,20 @@ "inBundle": true, "license": "ISC" }, + "node_modules/npm/node_modules/hasown": { + "version": "2.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/npm/node_modules/hosted-git-info": { - "version": "7.0.2", + "version": "7.0.1", "dev": true, "inBundle": true, "license": "ISC", @@ -11620,7 +12870,7 @@ } }, "node_modules/npm/node_modules/https-proxy-agent": { - "version": "7.0.5", + "version": "7.0.4", "dev": true, "inBundle": true, "license": "MIT", @@ -11646,7 +12896,7 @@ } }, "node_modules/npm/node_modules/ignore-walk": { - "version": "6.0.5", + "version": "6.0.4", "dev": true, "inBundle": true, "license": "ISC", @@ -11676,7 +12926,7 @@ } }, "node_modules/npm/node_modules/ini": { - "version": "4.1.3", + "version": "4.1.2", "dev": true, "inBundle": true, "license": "ISC", @@ -11685,7 +12935,7 @@ } }, "node_modules/npm/node_modules/init-package-json": { - "version": "6.0.3", + "version": "6.0.2", "dev": true, "inBundle": true, "license": "ISC", @@ -11728,17 +12978,29 @@ } }, "node_modules/npm/node_modules/is-cidr": { - "version": "5.1.0", + "version": "5.0.5", "dev": true, "inBundle": true, "license": "BSD-2-Clause", "dependencies": { - "cidr-regex": "^4.1.1" + "cidr-regex": "^4.0.4" }, "engines": { "node": ">=14" } }, + "node_modules/npm/node_modules/is-core-module": { + "version": "2.13.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/npm/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "dev": true, @@ -11761,7 +13023,7 @@ "license": "ISC" }, "node_modules/npm/node_modules/jackspeak": { - "version": "3.4.0", + "version": "2.3.6", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", @@ -11785,7 +13047,7 @@ "license": "MIT" }, "node_modules/npm/node_modules/json-parse-even-better-errors": { - "version": "3.0.2", + "version": "3.0.1", "dev": true, "inBundle": true, "license": "MIT", @@ -11824,31 +13086,31 @@ "license": "MIT" }, "node_modules/npm/node_modules/libnpmaccess": { - "version": "8.0.6", + "version": "8.0.5", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "npm-package-arg": "^11.0.2", - "npm-registry-fetch": "^17.0.1" + "npm-registry-fetch": "^17.0.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/libnpmdiff": { - "version": "6.1.4", + "version": "6.1.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^7.5.4", + "@npmcli/arborist": "^7.2.1", "@npmcli/installed-package-contents": "^2.1.0", "binary-extensions": "^2.3.0", "diff": "^5.1.0", "minimatch": "^9.0.4", "npm-package-arg": "^11.0.2", - "pacote": "^18.0.6", + "pacote": "^18.0.1", "tar": "^6.2.1" }, "engines": { @@ -11856,16 +13118,16 @@ } }, "node_modules/npm/node_modules/libnpmexec": { - "version": "8.1.3", + "version": "8.1.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^7.5.4", + "@npmcli/arborist": "^7.2.1", "@npmcli/run-script": "^8.1.0", "ci-info": "^4.0.0", "npm-package-arg": "^11.0.2", - "pacote": "^18.0.6", + "pacote": "^18.0.1", "proc-log": "^4.2.0", "read": "^3.0.1", "read-package-json-fast": "^3.0.2", @@ -11877,111 +13139,111 @@ } }, "node_modules/npm/node_modules/libnpmfund": { - "version": "5.0.12", + "version": "5.0.9", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^7.5.4" + "@npmcli/arborist": "^7.2.1" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/libnpmhook": { - "version": "10.0.5", + "version": "10.0.4", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "aproba": "^2.0.0", - "npm-registry-fetch": "^17.0.1" + "npm-registry-fetch": "^17.0.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/libnpmorg": { - "version": "6.0.6", + "version": "6.0.5", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "aproba": "^2.0.0", - "npm-registry-fetch": "^17.0.1" + "npm-registry-fetch": "^17.0.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/libnpmpack": { - "version": "7.0.4", + "version": "7.0.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/arborist": "^7.5.4", + "@npmcli/arborist": "^7.2.1", "@npmcli/run-script": "^8.1.0", "npm-package-arg": "^11.0.2", - "pacote": "^18.0.6" + "pacote": "^18.0.1" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/libnpmpublish": { - "version": "9.0.9", + "version": "9.0.7", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "ci-info": "^4.0.0", - "normalize-package-data": "^6.0.1", + "normalize-package-data": "^6.0.0", "npm-package-arg": "^11.0.2", - "npm-registry-fetch": "^17.0.1", + "npm-registry-fetch": "^17.0.0", "proc-log": "^4.2.0", "semver": "^7.3.7", "sigstore": "^2.2.0", - "ssri": "^10.0.6" + "ssri": "^10.0.5" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/libnpmsearch": { - "version": "7.0.6", + "version": "7.0.4", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "npm-registry-fetch": "^17.0.1" + "npm-registry-fetch": "^17.0.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/libnpmteam": { - "version": "6.0.5", + "version": "6.0.4", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "aproba": "^2.0.0", - "npm-registry-fetch": "^17.0.1" + "npm-registry-fetch": "^17.0.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/libnpmversion": { - "version": "6.0.3", + "version": "6.0.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "@npmcli/git": "^5.0.7", + "@npmcli/git": "^5.0.6", "@npmcli/run-script": "^8.1.0", - "json-parse-even-better-errors": "^3.0.2", + "json-parse-even-better-errors": "^3.0.0", "proc-log": "^4.2.0", "semver": "^7.3.7" }, @@ -12022,7 +13284,7 @@ } }, "node_modules/npm/node_modules/minimatch": { - "version": "9.0.5", + "version": "9.0.4", "dev": true, "inBundle": true, "license": "ISC", @@ -12037,7 +13299,7 @@ } }, "node_modules/npm/node_modules/minipass": { - "version": "7.1.2", + "version": "7.0.4", "dev": true, "inBundle": true, "license": "ISC", @@ -12058,7 +13320,7 @@ } }, "node_modules/npm/node_modules/minipass-fetch": { - "version": "3.0.5", + "version": "3.0.4", "dev": true, "inBundle": true, "license": "MIT", @@ -12098,6 +13360,28 @@ "node": ">=8" } }, + "node_modules/npm/node_modules/minipass-json-stream": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/npm/node_modules/minipass-json-stream/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/npm/node_modules/minipass-pipeline": { "version": "1.2.4", "dev": true, @@ -12241,7 +13525,7 @@ } }, "node_modules/npm/node_modules/nopt": { - "version": "7.2.1", + "version": "7.2.0", "dev": true, "inBundle": true, "license": "ISC", @@ -12256,12 +13540,13 @@ } }, "node_modules/npm/node_modules/normalize-package-data": { - "version": "6.0.2", + "version": "6.0.0", "dev": true, "inBundle": true, "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4" }, @@ -12279,7 +13564,7 @@ } }, "node_modules/npm/node_modules/npm-bundled": { - "version": "3.0.1", + "version": "3.0.0", "dev": true, "inBundle": true, "license": "ISC", @@ -12339,7 +13624,7 @@ } }, "node_modules/npm/node_modules/npm-pick-manifest": { - "version": "9.1.0", + "version": "9.0.0", "dev": true, "inBundle": true, "license": "ISC", @@ -12354,29 +13639,29 @@ } }, "node_modules/npm/node_modules/npm-profile": { - "version": "10.0.0", + "version": "9.0.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "npm-registry-fetch": "^17.0.1", + "npm-registry-fetch": "^17.0.0", "proc-log": "^4.0.0" }, "engines": { - "node": ">=18.0.0" + "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/npm-registry-fetch": { - "version": "17.1.0", + "version": "17.0.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/redact": "^2.0.0", - "jsonparse": "^1.3.1", "make-fetch-happen": "^13.0.0", "minipass": "^7.0.2", "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", "minizlib": "^2.1.2", "npm-package-arg": "^11.0.0", "proc-log": "^4.0.0" @@ -12386,7 +13671,7 @@ } }, "node_modules/npm/node_modules/npm-user-validate": { - "version": "2.0.1", + "version": "2.0.0", "dev": true, "inBundle": true, "license": "BSD-2-Clause", @@ -12409,14 +13694,8 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm/node_modules/package-json-from-dist": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "BlueOak-1.0.0" - }, "node_modules/npm/node_modules/pacote": { - "version": "18.0.6", + "version": "18.0.3", "dev": true, "inBundle": true, "license": "ISC", @@ -12440,7 +13719,7 @@ "tar": "^6.1.11" }, "bin": { - "pacote": "bin/index.js" + "pacote": "lib/bin.js" }, "engines": { "node": "^16.14.0 || >=18.0.0" @@ -12470,7 +13749,7 @@ } }, "node_modules/npm/node_modules/path-scurry": { - "version": "1.11.1", + "version": "1.10.2", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", @@ -12479,14 +13758,14 @@ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "6.1.0", + "version": "6.0.16", "dev": true, "inBundle": true, "license": "MIT", @@ -12554,7 +13833,7 @@ } }, "node_modules/npm/node_modules/promzard": { - "version": "1.0.2", + "version": "1.0.1", "dev": true, "inBundle": true, "license": "ISC", @@ -12624,10 +13903,13 @@ "optional": true }, "node_modules/npm/node_modules/semver": { - "version": "7.6.2", + "version": "7.6.0", "dev": true, "inBundle": true, "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { "semver": "bin/semver.js" }, @@ -12635,6 +13917,18 @@ "node": ">=10" } }, + "node_modules/npm/node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/npm/node_modules/shebang-command": { "version": "2.0.0", "dev": true, @@ -12669,17 +13963,17 @@ } }, "node_modules/npm/node_modules/sigstore": { - "version": "2.3.1", + "version": "2.3.0", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/bundle": "^2.3.2", + "@sigstore/bundle": "^2.3.1", "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.2", - "@sigstore/sign": "^2.3.2", - "@sigstore/tuf": "^2.3.4", - "@sigstore/verify": "^1.2.1" + "@sigstore/protobuf-specs": "^0.3.1", + "@sigstore/sign": "^2.3.0", + "@sigstore/tuf": "^2.3.1", + "@sigstore/verify": "^1.2.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" @@ -12710,14 +14004,14 @@ } }, "node_modules/npm/node_modules/socks-proxy-agent": { - "version": "8.0.4", + "version": "8.0.3", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.1", "debug": "^4.3.4", - "socks": "^2.8.3" + "socks": "^2.7.1" }, "engines": { "node": ">= 14" @@ -12760,7 +14054,7 @@ } }, "node_modules/npm/node_modules/spdx-license-ids": { - "version": "3.0.18", + "version": "3.0.17", "dev": true, "inBundle": true, "license": "CC0-1.0" @@ -12772,7 +14066,7 @@ "license": "BSD-3-Clause" }, "node_modules/npm/node_modules/ssri": { - "version": "10.0.6", + "version": "10.0.5", "dev": true, "inBundle": true, "license": "ISC", @@ -12921,14 +14215,14 @@ } }, "node_modules/npm/node_modules/tuf-js": { - "version": "2.2.1", + "version": "2.2.0", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { - "@tufjs/models": "2.0.1", + "@tufjs/models": "2.0.0", "debug": "^4.3.4", - "make-fetch-happen": "^13.0.1" + "make-fetch-happen": "^13.0.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" @@ -12985,10 +14279,13 @@ } }, "node_modules/npm/node_modules/validate-npm-package-name": { - "version": "5.0.1", + "version": "5.0.0", "dev": true, "inBundle": true, "license": "ISC", + "dependencies": { + "builtins": "^5.0.0" + }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } @@ -13152,9 +14449,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13188,28 +14485,28 @@ } }, "node_modules/object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", + "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "engines": { "node": ">= 0.4" } }, "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "engines": { "node": ">= 0.4" @@ -13219,26 +14516,26 @@ } }, "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.0.tgz", + "integrity": "sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", + "es-abstract": "^1.21.2", "get-intrinsic": "^1.2.1" } }, "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "engines": { "node": ">= 0.4" @@ -13573,61 +14870,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-map/node_modules/aggregate-error": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", - "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", - "dev": true, - "dependencies": { - "clean-stack": "^4.0.0", - "indent-string": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map/node_modules/clean-stack": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", - "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map/node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-reduce": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-3.0.0.tgz", @@ -13754,6 +14996,18 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", @@ -13997,9 +15251,9 @@ } }, "node_modules/pure-rand": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", - "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true, "funding": [ { @@ -14353,6 +15607,14 @@ "xtend": "~4.0.1" } }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -14517,14 +15779,14 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -14581,9 +15843,9 @@ "dev": true }, "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", "dev": true, "dependencies": { "is-core-module": "^2.13.0", @@ -14696,6 +15958,12 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "dev": true + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -14823,13 +16091,13 @@ } }, "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", + "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", + "get-intrinsic": "^1.2.0", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -14844,7 +16112,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -14886,9 +16153,9 @@ "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" }, "node_modules/semantic-release": { - "version": "22.0.8", - "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-22.0.8.tgz", - "integrity": "sha512-55rb31jygqIYsGU/rY+gXXm2fnxBIWo9azOjxbqKsPnq7p70zwZ5v+xnD7TxJC+zvS3sy1eHLGXYWCaX3WI76A==", + "version": "22.0.12", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-22.0.12.tgz", + "integrity": "sha512-0mhiCR/4sZb00RVFJIUlMuiBkW3NMpVIW2Gse7noqEMoFGkvfPPAImEQbkBV8xga4KOPP4FdTRYuLLy32R1fPw==", "dev": true, "dependencies": { "@semantic-release/commit-analyzer": "^11.0.0", @@ -14928,6 +16195,49 @@ "node": "^18.17 || >=20.6.1" } }, + "node_modules/semantic-release/node_modules/aggregate-error": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz", + "integrity": "sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==", + "dev": true, + "dependencies": { + "clean-stack": "^5.2.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/clean-stack": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz", + "integrity": "sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/semantic-release/node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", @@ -14964,9 +16274,9 @@ } }, "node_modules/semantic-release/node_modules/figures": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/figures/-/figures-6.0.1.tgz", - "integrity": "sha512-0oY/olScYD4IhQ8u//gCPA4F3mlTn2dacYmiDm/mbDQvpmLjV4uH+zhsQ5IyXRyvqkvtUkXkNdGvg5OFJTCsuQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", "dev": true, "dependencies": { "is-unicode-supported": "^2.0.0" @@ -14999,6 +16309,18 @@ "node": ">=16.17.0" } }, + "node_modules/semantic-release/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/semantic-release/node_modules/is-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", @@ -15024,9 +16346,9 @@ } }, "node_modules/semantic-release/node_modules/lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -15180,9 +16502,9 @@ } }, "node_modules/semantic-release/node_modules/type-fest": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.8.2.tgz", - "integrity": "sha512-mcvrCjixA5166hSrUoJgGb9gBQN4loMYyj9zxuMs/66ibHNEFd5JXMw37YVDx58L4/QID9jIzdTBB4mDwDJ6KQ==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.18.1.tgz", + "integrity": "sha512-qXhgeNsX15bM63h5aapNFcQid9jRF/l3ojDoDFmekDQEUufZ9U4ErVt6SjDxnHp48Ltrw616R8yNc3giJ3KvVQ==", "dev": true, "engines": { "node": ">=16" @@ -15239,35 +16561,6 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, - "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -15499,9 +16792,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", - "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", "dev": true }, "node_modules/split2": { @@ -15772,6 +17065,15 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -15846,14 +17148,14 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "engines": { "node": ">= 0.4" @@ -15863,28 +17165,28 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -16211,21 +17513,21 @@ } }, "node_modules/ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { - "node": ">=16.13.0" + "node": ">=16" }, "peerDependencies": { "typescript": ">=4.2.0" } }, "node_modules/ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", + "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -16241,7 +17543,7 @@ "ts-jest": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", @@ -16287,39 +17589,46 @@ } }, "node_modules/ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "source-map-support": "^0.5.17", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js", "ts-script": "dist/bin-script-deprecated.js" }, - "engines": { - "node": ">=10.0.0" - }, "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", "typescript": ">=2.7" - } - }, - "node_modules/ts-node/node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, "node_modules/tsconfig-paths": { @@ -16469,9 +17778,9 @@ "dev": true }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -16515,6 +17824,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici": { + "version": "5.28.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", + "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/unicode-emoji-modifier-base": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", @@ -16568,9 +17888,9 @@ } }, "node_modules/universal-user-agent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", - "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", "dev": true }, "node_modules/universalify": { @@ -16662,9 +17982,9 @@ "dev": true }, "node_modules/v8-to-istanbul": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", - "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", @@ -16676,9 +17996,9 @@ } }, "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -16727,15 +18047,23 @@ "defaults": "^1.0.3" } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "engines": { + "node": ">= 8" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/whatwg-fetch": { - "version": "3.6.19", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz", - "integrity": "sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw==", + "version": "3.6.17", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.17.tgz", + "integrity": "sha512-c4ghIvG6th0eudYwKZY5keb81wtFz9/WeAHAoy8+r18kcWlitUIrmGFQ2rWEl4UCKUilD3zCLHOIPheHx5ypRQ==", "dev": true }, "node_modules/whatwg-url": { @@ -16785,13 +18113,13 @@ "dev": true }, "node_modules/which-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", - "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.4", + "call-bind": "^1.0.2", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-tostringtag": "^1.0.0" @@ -16867,6 +18195,26 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -16955,6 +18303,23 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.23.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.6.tgz", + "integrity": "sha512-RTHJlZhsRbuA8Hmp/iNL7jnfc4nZishjsanDAfEY1QpDQZCahUp3xDzl+zfweE9BklxMUcgBgS1b7Lvie/ZVwA==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.23.0.tgz", + "integrity": "sha512-az0uJ243PxsRIa2x1WmNE/pnuA05gUq/JB8Lwe1EDCCL/Fz9MgjYQ0fPlyc2Tcv6aF2ZA7WM5TWaRZVEFaAIag==", + "dev": true, + "peerDependencies": { + "zod": "^3.23.3" + } } } } diff --git a/package.json b/package.json index bb8d4cce..22143852 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,25 @@ "module": "dist/esm/index.js", "browser": "dist/index.umd.js", "types": "dist/types/index.d.ts", + "exports": { + ".": { + "import": "./dist/esm/index.js", + "require": "./dist/cjs/index.js", + "types": "./dist/types/index.d.ts" + }, + "./4.0": { + "import": "./dist/esm/4.0/exports/index.js", + "require": "./dist/cjs/4.0/exports/index.js", + "types": "./dist/types/4.0/exports/index.d.ts" + }, + "./4.0/*": { + "import": "./dist/esm/4.0/exports/*.js", + "require": "./dist/cjs/4.0/exports/*.js", + "types": "./dist/types/4.0/exports/*.d.ts" + } + }, "scripts": { + "lint-staged": "lint-staged", "benchmark:qr-code": "ts-node --transpile-only benchmarks/qr-code", "build": "npm run clean && npm run build:cjs && npm run build:esm && npm run build:umd && npm run build:type", "build:cjs": "tsc --module commonjs --outDir dist/cjs --project ./tsconfig.prod.json", @@ -22,9 +40,12 @@ "test:vc": "scripts/runVcTest.sh", "lint": "eslint . --ext .ts,.json --max-warnings 0", "lint:fix": "npm run lint -- --fix", + "generate-v4-fixtures": "npx ts-node scripts/generateV4JsonFixtures.ts", + "generate-v4-json-schemas": "npx ts-node scripts/generateV4JsonSchemas.ts", "publish:schema": "./scripts/publishSchema.sh", - "postinstall": "node scripts/postInstall", - "prebuild": "node scripts/preBuild" + "postinstall": "node scripts/postInstall;", + "prebuild": "node scripts/preBuild", + "prepare": "husky install" }, "files": [ "/dist", @@ -43,9 +64,10 @@ "@types/debug": "^4.1.7", "@types/jest": "^29.5.3", "@types/js-base64": "^3.3.1", - "@types/jsonld": "^1.5.6", + "@types/jsonld": "^1.5.13", "@types/lodash": "^4.14.171", "@types/qrcode": "^1.4.1", + "@types/randombytes": "^2.0.3", "@types/uuid": "^8.3.1", "@types/validator": "^13.6.3", "@typescript-eslint/eslint-plugin": "^6.9.0", @@ -61,34 +83,41 @@ "eslint-plugin-prettier": "^3.4.0", "git-cz": "^4.7.6", "husky": "^8.0.3", - "jest": "^29.6.2", + "jest": "^29.7.0", "jest-watch-typeahead": "^2.2.2", + "lint-staged": "^15.2.2", "prettier": "^2.3.2", "qrcode": "^1.5.1", "quicktype": "^15.0.260", "rollup": "^2.79.1", "rollup-plugin-commonjs": "^10.1.0", "semantic-release": "^22.0.8", - "ts-jest": "^29.1.1", - "ts-node": "^9.1.1", - "typescript": "^5.1.6" + "ts-jest": "^29.1.2", + "ts-node": "^10.9.2", + "typescript": "^5.1.6", + "zod-to-json-schema": "^3.23.0" }, "dependencies": { + "@aws-crypto/sha256-universal": "^5.2.0", "@ethersproject/abstract-signer": "^5.7.0", "@ethersproject/bytes": "^5.7.0", "@ethersproject/logger": "^5.7.0", "@ethersproject/wallet": "^5.7.0", "@govtechsg/jsonld": "^0.1.0", + "buffer": "^6.0.3", "ajv-formats": "^2.1.1", "cross-fetch": "^3.1.5", "debug": "^4.3.2", "flatley": "^5.2.0", "js-base64": "^3.6.1", "js-sha3": "^0.8.0", + "jsonld": "^8.3.2", "lodash": "^4.17.21", + "randombytes": "^2.1.0", "runtypes": "^6.3.2", "uuid": "^8.3.2", - "validator": "^13.7.0" + "validator": "^13.7.0", + "zod": "^3.22.4" }, "directories": { "test": "test" diff --git a/scripts/generateV4JsonFixtures.ts b/scripts/generateV4JsonFixtures.ts new file mode 100644 index 00000000..fc62f13a --- /dev/null +++ b/scripts/generateV4JsonFixtures.ts @@ -0,0 +1,18 @@ +import fs from "fs"; +import path from "path"; +import * as V4_FIXTURES from "../src/4.0/fixtures"; + +const OUTPUT_DIR = path.resolve("./test/fixtures/v4/__generated__"); + +// make sure the output directory exists +if (fs.existsSync(OUTPUT_DIR)) { + fs.rmSync(OUTPUT_DIR, { recursive: true }); +} +fs.mkdirSync(OUTPUT_DIR, { recursive: true }); + +for (const [key, value] of Object.entries(V4_FIXTURES)) { + fs.writeFileSync( + path.join(OUTPUT_DIR, key.replace(/_/g, "-").toLowerCase() + ".json"), + JSON.stringify(value, null, 2) + ); +} diff --git a/scripts/generateV4JsonSchemas.ts b/scripts/generateV4JsonSchemas.ts new file mode 100644 index 00000000..93cb144b --- /dev/null +++ b/scripts/generateV4JsonSchemas.ts @@ -0,0 +1,36 @@ +import fs from "fs"; +import path from "path"; +import { zodToJsonSchema } from "zod-to-json-schema"; +import { V4OpenAttestationDocument, V4WrappedDocument, V4SignedWrappedDocument } from "../src/4.0/types"; + +const OUTPUT_DIR = path.resolve("./src/4.0/jsonSchemas/__generated__"); + +// make sure the output directory exists +if (fs.existsSync(OUTPUT_DIR)) { + fs.rmSync(OUTPUT_DIR, { recursive: true }); +} +fs.mkdirSync(OUTPUT_DIR, { recursive: true }); + +const ZOD_SCHEMAS = [ + { + filename: "v4-document.schema.json", + schemaName: "v4Document", + zodSchema: V4OpenAttestationDocument, + }, + { + filename: "v4-wrapped-document.schema.json", + schemaName: "v4WrappedDocument", + zodSchema: V4WrappedDocument, + }, + { + filename: "v4-signed-wrapped-document.schema.json", + schemaName: "v4SignedWrappedDocument", + zodSchema: V4SignedWrappedDocument, + }, +]; + +for (const { filename, zodSchema, schemaName } of ZOD_SCHEMAS) { + const jsonSchema = zodToJsonSchema(zodSchema, schemaName); + + fs.writeFileSync(path.join(OUTPUT_DIR, filename), JSON.stringify(jsonSchema, null, 2)); +} diff --git a/src/2.0/utils.ts b/src/2.0/utils.ts new file mode 100644 index 00000000..923def71 --- /dev/null +++ b/src/2.0/utils.ts @@ -0,0 +1,7 @@ +import { unsaltData } from "./salt"; +import { OpenAttestationDocument, WrappedDocument } from "./types"; + +type Extract

= P extends WrappedDocument ? T : never; +export const getData = >(document: T): Extract => { + return unsaltData(document.data); +}; diff --git a/src/2.0/wrap.ts b/src/2.0/wrap.ts index b8eb5663..5987bfe5 100644 --- a/src/2.0/wrap.ts +++ b/src/2.0/wrap.ts @@ -59,7 +59,7 @@ export const wrapDocuments = { const merkleProof = merkleTree .getProof(hashToBuffer(document.signature.targetHash)) - .map((buffer: Buffer) => buffer.toString("hex")); + .map((buffer) => buffer.toString("hex")); return { ...document, signature: { diff --git a/src/3.0/salt.ts b/src/3.0/salt.ts index edd75b43..4b17eac3 100644 --- a/src/3.0/salt.ts +++ b/src/3.0/salt.ts @@ -1,5 +1,5 @@ import { Salt } from "./types"; -import { randomBytes } from "crypto"; +import randomBytes from "randombytes"; import { Base64 } from "js-base64"; import { traverseAndFlatten } from "./traverseAndFlatten"; diff --git a/src/3.0/wrap.ts b/src/3.0/wrap.ts index 661f9f0a..288e5fe4 100644 --- a/src/3.0/wrap.ts +++ b/src/3.0/wrap.ts @@ -46,7 +46,7 @@ export const wrapDocument = async ( const merkleTree = new MerkleTree(batchBuffers); const merkleRoot = merkleTree.getRoot().toString("hex"); - const merkleProof = merkleTree.getProof(hashToBuffer(digest)).map((buffer: Buffer) => buffer.toString("hex")); + const merkleProof = merkleTree.getProof(hashToBuffer(digest)).map((buffer) => buffer.toString("hex")); const verifiableCredential: WrappedDocument = { ...document, @@ -89,7 +89,7 @@ export const wrapDocuments = async ( // for each document, update the merkle root and add the proofs needed return verifiableCredentials.map((verifiableCredential) => { const digest = verifiableCredential.proof.targetHash; - const merkleProof = merkleTree.getProof(hashToBuffer(digest)).map((buffer: Buffer) => buffer.toString("hex")); + const merkleProof = merkleTree.getProof(hashToBuffer(digest)).map((buffer) => buffer.toString("hex")); return { ...verifiableCredential, diff --git a/src/4.0/__tests__/digest.test.ts b/src/4.0/__tests__/digest.test.ts new file mode 100644 index 00000000..d36e2a39 --- /dev/null +++ b/src/4.0/__tests__/digest.test.ts @@ -0,0 +1,175 @@ +import { digestCredential } from "../digest"; +import { decodeSalt } from "../salt"; +import { SIGNED_WRAPPED_DOCUMENT_DID as ROOT_CREDENTIAL } from "../fixtures"; +import { V4SignedWrappedDocument } from "../types"; +import { obfuscateVerifiableCredential } from "../obfuscate"; + +// All obfuscated documents are generated from the ROOT_CREDENTIAL +const ROOT_CREDENTIAL_TARGET_HASH = ROOT_CREDENTIAL.proof.targetHash; + +describe("V4 digestCredential", () => { + test("given all testobfuscated documents are generated from the ROOT_CREDENTIAL, ROOT_CREDENTIAL_TARGET_HASH should match snapshot", () => { + expect(ROOT_CREDENTIAL_TARGET_HASH).toMatchInlineSnapshot( + `"dd55a7d96d47e58350f2cfb03ebdf3f859684c9f97ba75eed55b1bdcc761c5aa"` + ); + }); + + test("given a document with ALL FIELDS VISIBLE, should digest and match the root credential's target hash", () => { + expect(ROOT_CREDENTIAL.credentialSubject).toMatchInlineSnapshot(` + { + "id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + "licenses": [ + { + "class": "3", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00", + }, + { + "class": "3A", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00", + }, + ], + "name": "John Doe", + "type": [ + "DriversLicense", + ], + } + `); + expect(ROOT_CREDENTIAL.proof.privacy.obfuscated).toMatchInlineSnapshot(`[]`); + + const digest = digestCredential(ROOT_CREDENTIAL, decodeSalt(ROOT_CREDENTIAL.proof.salts), []); + expect(digest).toBe(ROOT_CREDENTIAL_TARGET_HASH); + }); + + test("given a document with ONE element obfuscated, should digest and match the root credential's target hash", () => { + const OBFUSCATED_WRAPPED_DOCUMENT = obfuscateVerifiableCredential(ROOT_CREDENTIAL, "credentialSubject.id"); + expect(OBFUSCATED_WRAPPED_DOCUMENT.credentialSubject).toMatchInlineSnapshot(` + { + "licenses": [ + { + "class": "3", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00", + }, + { + "class": "3A", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00", + }, + ], + "name": "John Doe", + "type": [ + "DriversLicense", + ], + } + `); + expect(OBFUSCATED_WRAPPED_DOCUMENT.proof.privacy.obfuscated).toMatchInlineSnapshot(` + [ + "410849f7c317307141d4cecd4d72fe7efb9655abaa0ee37374b2ec53a3588ee7", + ] + `); + + const digest = digestCredential( + OBFUSCATED_WRAPPED_DOCUMENT, + decodeSalt(OBFUSCATED_WRAPPED_DOCUMENT.proof.salts), + OBFUSCATED_WRAPPED_DOCUMENT.proof.privacy.obfuscated + ); + expect(digest).toBe(ROOT_CREDENTIAL_TARGET_HASH); + expect(digest).toBe(OBFUSCATED_WRAPPED_DOCUMENT.proof.targetHash); + }); + + test("given a document with THREE elements obfuscated, should digest and match the root credential's target hash", () => { + const OBFUSCATED_WRAPPED_DOCUMENT = obfuscateVerifiableCredential(ROOT_CREDENTIAL, [ + "credentialSubject.id", + "credentialSubject.name", + "credentialSubject.licenses[0].description", + ]); + expect(OBFUSCATED_WRAPPED_DOCUMENT.credentialSubject).toMatchInlineSnapshot(` + { + "licenses": [ + { + "class": "3", + "effectiveDate": "2013-05-16T00:00:00+08:00", + }, + { + "class": "3A", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00", + }, + ], + "type": [ + "DriversLicense", + ], + } + `); + expect(OBFUSCATED_WRAPPED_DOCUMENT.proof.privacy.obfuscated).toMatchInlineSnapshot(` + [ + "410849f7c317307141d4cecd4d72fe7efb9655abaa0ee37374b2ec53a3588ee7", + "21f8a6f2f464ff14afbc52e4dcb965d7891a7c63fd37eb93f8f98477dcdfc7f9", + "228eb6b469ca3a475238455f11125b7edc826c6dc3ae727d023d1eb71d0e60d6", + ] + `); + + const digest = digestCredential( + OBFUSCATED_WRAPPED_DOCUMENT, + decodeSalt(OBFUSCATED_WRAPPED_DOCUMENT.proof.salts), + OBFUSCATED_WRAPPED_DOCUMENT.proof.privacy.obfuscated + ); + expect(digest).toBe(ROOT_CREDENTIAL_TARGET_HASH); + expect(digest).toBe(OBFUSCATED_WRAPPED_DOCUMENT.proof.targetHash); + }); + + test("given a document with NO VISIBLE FIELDS, should digest and match the root credential's target hash", () => { + // this has to be manually generated, since obfuscateVerifiableCredential does not allow obfuscating fields that + // result in a non compliant V4 OA document + const OBFUSCATED_WRAPPED_DOCUMENT = { + // no visible fields + proof: { + type: "OpenAttestationMerkleProofSignature2018", + proofPurpose: "assertionMethod", + targetHash: "dd55a7d96d47e58350f2cfb03ebdf3f859684c9f97ba75eed55b1bdcc761c5aa", + proofs: [], + merkleRoot: "dd55a7d96d47e58350f2cfb03ebdf3f859684c9f97ba75eed55b1bdcc761c5aa", + salts: "W10=", + privacy: { + obfuscated: [ + "0fd4ac5ade244ee2fe47437ea43cd142479540b878fffc86662600fce4d47ef5", + "0cc6e4c50bb090af720d224a9bd73be4c0d72831fc701907339693cdcb34ede3", + "d2afadbec39872577eae0d5e4ea3b590608cab744f214a2f703f65a5b41683cb", + "569b596d71fb145e9c87be1b301da3cbc89cfc104627f6dd95c8123f7974e9c6", + "5dee7aa2b48b9a5edae5042459c7c3eeaa8c5b13132b1477641c727a89471b36", + "2a1ff14be659821afa68edc245f67b9e25331b450715b41348ed2405334d5abd", + "0f1d172b5352464121dffc550e16f64b8019637e39768c506fd2e517a0da305d", + "ff4eeed1d7bb70aef646d46dc75b3408cf019e0daeaf2ef0313974690d8beef2", + "2a4e9fd43be0221af2f02a6b959edf704b630559268a0b2a657fe046e282fbb8", + "bbdf2b05cc0bd2a64fc3483211806e2f863bea05fba81f63092ec07c4ee8ebd9", + "bd9acf6bef05f94720f0fa9c5540bb9db7d6370c39e2bbbee31e408842985dae", + "410849f7c317307141d4cecd4d72fe7efb9655abaa0ee37374b2ec53a3588ee7", + "32a55f464387e37df8f74cf3de6a8e04626e19c2f4d5ec8931aee4b866329fb8", + "21f8a6f2f464ff14afbc52e4dcb965d7891a7c63fd37eb93f8f98477dcdfc7f9", + "6bc7b2350b59b02a44d2593ee7538590114544bc3a39fe9564ee49b387c883c4", + "228eb6b469ca3a475238455f11125b7edc826c6dc3ae727d023d1eb71d0e60d6", + "d6e7027dd62b265e83aaf306f095446efab2677e940a0fbb118cc91dd8226fdb", + "da26ce90128b1cfd747218cad4c7e86b83f6ab236598ce18aecc3b10426b1b71", + "5edea35aa869577c2fd14159534b08da061a7833665cf1cc28f400474c26be01", + "d55b72f926f7adaa5ea4f271ffc2f574e4859b05c16042f5b604e52f044a11d0", + "dd69de699de90b82cfb658fc304ae4f3131e841d56fd68eb20e17af73613a4d3", + "280bc622006d5ec28a42096b57f15f8238df27762c3f754d56dcd89f3aa02c25", + "3d8bc5cbcd2826489cdc80a64d586a4d220d975bc2848aa535bd1e4f17dc619f", + ], + }, + key: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller", + signature: + "0xa3ac9f73a7314c0aad47bad875921f5c88d2af9440d6c309fc2f93dbf43bd8235e84b744cb1ff1c09c214b559ce3bd6eb148c2f68c677cb8408d96e9b5411dfb1c", + }, + } as unknown as V4SignedWrappedDocument; + + const digest = digestCredential( + OBFUSCATED_WRAPPED_DOCUMENT, + decodeSalt(OBFUSCATED_WRAPPED_DOCUMENT.proof.salts), + OBFUSCATED_WRAPPED_DOCUMENT.proof.privacy.obfuscated + ); + expect(digest).toBe(ROOT_CREDENTIAL_TARGET_HASH); + }); +}); diff --git a/src/4.0/__tests__/documentBuilder.test.ts b/src/4.0/__tests__/documentBuilder.test.ts new file mode 100644 index 00000000..a218db75 --- /dev/null +++ b/src/4.0/__tests__/documentBuilder.test.ts @@ -0,0 +1,543 @@ +import { verify } from "../verify"; +import { DocumentBuilder, DocumentBuilderErrors } from "../documentBuilder"; +import { isSignedWrappedDocument, isWrappedDocument, signDocument } from "../exports"; +import { SAMPLE_SIGNING_KEYS } from "../fixtures"; + +describe(`DocumentBuilder`, () => { + describe("given a single document", () => { + const document = new DocumentBuilder({ credentialSubject: { name: "John Doe" }, name: "Diploma" }) + .embeddedRenderer({ + rendererUrl: "https://example.com", + templateName: "example", + }) + .oscpRevocation({ + oscpUrl: "https://oscp.example.com", + }) + .dnsTxtIssuance({ + identityProofDomain: "example.com", + issuerId: "did:example:123", + issuerName: "Example University", + }); + + test("given sign and wrap is called, return a single signed document", async () => { + const signed = await document.wrapAndSign({ signer: SAMPLE_SIGNING_KEYS }); + expect(signed.issuer).toMatchInlineSnapshot(` + { + "id": "did:example:123", + "identityProof": { + "identifier": "example.com", + "identityProofType": "DNS-TXT", + }, + "name": "Example University", + "type": "OpenAttestationIssuer", + } + `); + expect(signed.credentialSubject).toMatchInlineSnapshot(` + { + "name": "John Doe", + } + `); + expect(signed.renderMethod).toMatchInlineSnapshot(` + [ + { + "id": "https://example.com", + "templateName": "example", + "type": "OpenAttestationEmbeddedRenderer", + }, + ] + `); + expect(signed.credentialStatus).toMatchInlineSnapshot(` + { + "id": "https://oscp.example.com", + "type": "OpenAttestationOcspResponder", + } + `); + expect(isSignedWrappedDocument(signed)).toBe(true); + expect(verify(signed)).toBe(true); + }); + + test("given wrap is called, return a wrapped document", async () => { + const wrapped = await document.justWrapWithoutSigning(); + expect(wrapped.issuer).toMatchInlineSnapshot(` + { + "id": "did:example:123", + "identityProof": { + "identifier": "example.com", + "identityProofType": "DNS-TXT", + }, + "name": "Example University", + "type": "OpenAttestationIssuer", + } + `); + expect(wrapped.credentialSubject).toMatchInlineSnapshot(` + { + "name": "John Doe", + } + `); + expect(wrapped.renderMethod).toMatchInlineSnapshot(` + [ + { + "id": "https://example.com", + "templateName": "example", + "type": "OpenAttestationEmbeddedRenderer", + }, + ] + `); + expect(wrapped.credentialStatus).toMatchInlineSnapshot(` + { + "id": "https://oscp.example.com", + "type": "OpenAttestationOcspResponder", + } + `); + expect(isWrappedDocument(wrapped)).toBe(true); + expect(isSignedWrappedDocument(wrapped)).toBe(false); + }); + }); + + describe("given a multiple documents", () => { + const document = new DocumentBuilder([ + { credentialSubject: { name: "John Doe" }, name: "Diploma" }, + { credentialSubject: { name: "Jane Foster" }, name: "Degree" }, + ]) + .embeddedRenderer({ + rendererUrl: "https://example.com", + templateName: "example", + }) + .noRevocation() + .dnsTxtIssuance({ + identityProofDomain: "example.com", + issuerId: "did:example:123", + issuerName: "Example University", + }); + + test("given sign and wrap is called, return a list of signed document", async () => { + const signed = await document.wrapAndSign({ signer: SAMPLE_SIGNING_KEYS }); + expect(signed[0].issuer).toMatchInlineSnapshot(` + { + "id": "did:example:123", + "identityProof": { + "identifier": "example.com", + "identityProofType": "DNS-TXT", + }, + "name": "Example University", + "type": "OpenAttestationIssuer", + } + `); + expect(signed[0].credentialSubject).toMatchInlineSnapshot(` + { + "name": "John Doe", + } + `); + expect(signed[0].renderMethod).toMatchInlineSnapshot(` + [ + { + "id": "https://example.com", + "templateName": "example", + "type": "OpenAttestationEmbeddedRenderer", + }, + ] + `); + expect(signed[0].credentialStatus).toBeUndefined(); + expect(isSignedWrappedDocument(signed[0])).toBe(true); + expect(verify(signed[0])).toBe(true); + + expect(signed[1].issuer).toMatchInlineSnapshot(` + { + "id": "did:example:123", + "identityProof": { + "identifier": "example.com", + "identityProofType": "DNS-TXT", + }, + "name": "Example University", + "type": "OpenAttestationIssuer", + } + `); + expect(signed[1].credentialSubject).toMatchInlineSnapshot(` + { + "name": "Jane Foster", + } + `); + expect(signed[1].renderMethod).toMatchInlineSnapshot(` + [ + { + "id": "https://example.com", + "templateName": "example", + "type": "OpenAttestationEmbeddedRenderer", + }, + ] + `); + expect(signed[1].credentialStatus).toBeUndefined(); + expect(isSignedWrappedDocument(signed[1])).toBe(true); + expect(verify(signed[1])).toBe(true); + }); + + test("given wrap is called, return a list of wrapped document", async () => { + const wrapped = await document.justWrapWithoutSigning(); + expect(wrapped[0].issuer).toMatchInlineSnapshot(` + { + "id": "did:example:123", + "identityProof": { + "identifier": "example.com", + "identityProofType": "DNS-TXT", + }, + "name": "Example University", + "type": "OpenAttestationIssuer", + } + `); + expect(wrapped[0].credentialSubject).toMatchInlineSnapshot(` + { + "name": "John Doe", + } + `); + expect(wrapped[0].renderMethod).toMatchInlineSnapshot(` + [ + { + "id": "https://example.com", + "templateName": "example", + "type": "OpenAttestationEmbeddedRenderer", + }, + ] + `); + expect(isWrappedDocument(wrapped[0])).toBe(true); + expect(isSignedWrappedDocument(wrapped[0])).toBe(false); + + expect(wrapped[1].issuer).toMatchInlineSnapshot(` + { + "id": "did:example:123", + "identityProof": { + "identifier": "example.com", + "identityProofType": "DNS-TXT", + }, + "name": "Example University", + "type": "OpenAttestationIssuer", + } + `); + expect(wrapped[1].credentialSubject).toMatchInlineSnapshot(` + { + "name": "Jane Foster", + } + `); + expect(wrapped[1].renderMethod).toMatchInlineSnapshot(` + [ + { + "id": "https://example.com", + "templateName": "example", + "type": "OpenAttestationEmbeddedRenderer", + }, + ] + `); + expect(isWrappedDocument(wrapped[1])).toBe(true); + expect(isSignedWrappedDocument(wrapped[1])).toBe(false); + }); + }); + + test("given additional properties in constructor payload, should not be added into the document", async () => { + const signed = await new DocumentBuilder({ + credentialSubject: { name: "John Doe" }, + name: "Diploma", + anotherProperty: "value", + }) + .embeddedRenderer({ + rendererUrl: "https://example.com", + templateName: "example", + }) + .noRevocation() + .dnsTxtIssuance({ + identityProofDomain: "example.com", + issuerId: "did:example:123", + issuerName: "Example University", + }) + .wrapAndSign({ signer: SAMPLE_SIGNING_KEYS }); + + expect(signed).not.toHaveProperty("anotherProperty"); + }); + + test("given svg rendering method, should be added into the document", async () => { + const signed = await new DocumentBuilder({ + credentialSubject: { + name: "John Doe", + attachments: [ + { + data: "data", + filename: "file", + mimeType: "application/pdf", + }, + ], + }, + name: "Diploma", + }) + .svgRenderer({ + type: "EMBEDDED", + svgTemplate: "{{ name }}", + }) + .noRevocation() + .dnsTxtIssuance({ + identityProofDomain: "example.com", + issuerId: "did:example:123", + issuerName: "Example University", + }) + .wrapAndSign({ signer: SAMPLE_SIGNING_KEYS }); + + expect(signed.renderMethod).toMatchInlineSnapshot(` + [ + { + "id": "{{ name }}", + "type": "SvgRenderingTemplate2023", + }, + ] + `); + }); + + test("given no rendering method, should reflect in the output document", async () => { + const signed = await new DocumentBuilder({ + credentialSubject: { + name: "John Doe", + attachments: [ + { + data: "data", + filename: "file", + mimeType: "application/pdf", + }, + ], + }, + name: "Diploma", + }) + .noRenderer() + .noRevocation() + .dnsTxtIssuance({ + identityProofDomain: "example.com", + issuerId: "did:example:123", + issuerName: "Example University", + }) + .wrapAndSign({ signer: SAMPLE_SIGNING_KEYS }); + + expect(signed.renderMethod).toMatchInlineSnapshot(`undefined`); + }); + + test("given attachment is added, should be added into the document", async () => { + const signed = await new DocumentBuilder({ + credentialSubject: { + name: "John Doe", + attachments: [ + { + data: "data", + filename: "file", + mimeType: "application/pdf", + }, + ], + }, + name: "Diploma", + }) + .embeddedRenderer({ + rendererUrl: "https://example.com", + templateName: "example", + }) + .noRevocation() + .dnsTxtIssuance({ + identityProofDomain: "example.com", + issuerId: "did:example:123", + issuerName: "Example University", + }) + .wrapAndSign({ signer: SAMPLE_SIGNING_KEYS }); + + expect(signed.credentialSubject.attachments).toMatchInlineSnapshot(` + [ + { + "data": "data", + "filename": "file", + "mimeType": "application/pdf", + }, + ] + `); + }); + + test("given revocation store revocation is added, should be added into credential status of the document", async () => { + const signed = await new DocumentBuilder({ + credentialSubject: { name: "John Doe" }, + name: "Diploma", + attachments: [ + { + data: "data", + fileName: "file", + mimeType: "application/pdf", + }, + ], + }) + .embeddedRenderer({ + rendererUrl: "https://example.com", + templateName: "example", + }) + .revocationStoreRevocation({ + storeAddress: "0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + }) + .dnsTxtIssuance({ + identityProofDomain: "example.com", + issuerId: "did:example:123", + issuerName: "Example University", + }) + .wrapAndSign({ signer: SAMPLE_SIGNING_KEYS }); + + expect(signed.credentialStatus).toMatchInlineSnapshot(` + { + "id": "0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + "type": "OpenAttestationRevocationStore", + } + `); + }); + + test("given wrap only is called, should be able to sign the wrapped document with the standalone sign fn", async () => { + const wrapped = await new DocumentBuilder({ + credentialSubject: { name: "John Doe" }, + name: "Diploma", + }) + .embeddedRenderer({ + rendererUrl: "https://example.com", + templateName: "example", + }) + .noRevocation() + .dnsTxtIssuance({ + identityProofDomain: "example.com", + issuerId: "did:example:123", + issuerName: "Example University", + }) + .justWrapWithoutSigning(); + + const signed = await signDocument(wrapped, "Secp256k1VerificationKey2018", SAMPLE_SIGNING_KEYS); + + expect(isSignedWrappedDocument(signed)).toBe(true); + expect(verify(signed)).toBe(true); + }); + + test("given re-setting of values, should throw", async () => { + const builder = await new DocumentBuilder({ + credentialSubject: { name: "John Doe" }, + name: "Diploma", + }); + + const documentWithRenderMethod = builder.embeddedRenderer({ + rendererUrl: "https://example.com", + templateName: "example", + }); + + expect(() => + builder.embeddedRenderer({ + rendererUrl: "https://another.com", + templateName: "another", + }) + ).toThrowError(DocumentBuilderErrors.ShouldNotModifyAfterSettingError); + + const documentWithNoRevocation = documentWithRenderMethod.noRevocation(); + expect(() => documentWithRenderMethod.oscpRevocation({ oscpUrl: "https://oscp.example.com" })).toThrowError( + DocumentBuilderErrors.ShouldNotModifyAfterSettingError + ); + + documentWithNoRevocation.dnsTxtIssuance({ + identityProofDomain: "example.com", + issuerId: "did:example:123", + issuerName: "Example University", + }); + + expect(() => + documentWithNoRevocation.dnsTxtIssuance({ + identityProofDomain: "another.com", + issuerId: "did:example:123", + issuerName: "Example University", + }) + ).toThrowError(DocumentBuilderErrors.ShouldNotModifyAfterSettingError); + }); + + describe("given invalid props", () => { + test("given an invalid attachment, should throw", () => { + let error; + expect(() => { + try { + new DocumentBuilder({ + credentialSubject: { + name: "John Doe", + attachments: [ + { + data: "data", + fileName: "file", + } as any, + ], + }, + name: "Diploma", + }); + } catch (e) { + error = e; + throw e; + } + }).toThrowError(DocumentBuilderErrors.PropsValidationError); + expect(error).toBeInstanceOf(DocumentBuilderErrors.PropsValidationError); + }); + + test("given an invalid identity identifier, should throw", () => { + const builder = new DocumentBuilder({ + credentialSubject: { name: "John Doe" }, + name: "Diploma", + }) + .embeddedRenderer({ + rendererUrl: "https://example.com", + templateName: "example", + }) + .noRevocation(); + let error; + expect(() => { + try { + builder.dnsTxtIssuance({ + identityProofDomain: "example.com", + issuerId: "invalid", + issuerName: "Example University", + }); + } catch (e) { + error = e; + throw e; + } + }).toThrowErrorMatchingInlineSnapshot(` + "Invalid props: + { + "_errors": [], + "issuerId": { + "_errors": [ + "Invalid URI" + ] + } + }" + `); + expect(error).toBeInstanceOf(DocumentBuilderErrors.PropsValidationError); + }); + + test("given an invalid ethereum address for revocation store, should throw", () => { + const builder = new DocumentBuilder({ + credentialSubject: { name: "John Doe" }, + name: "Diploma", + }).embeddedRenderer({ + rendererUrl: "https://example.com", + templateName: "example", + }); + + let error; + expect(() => { + try { + builder.revocationStoreRevocation({ + storeAddress: "0x123", + }); + } catch (e) { + error = e; + throw e; + } + }).toThrowErrorMatchingInlineSnapshot(` + "Invalid props: + { + "_errors": [], + "storeAddress": { + "_errors": [ + "Invalid Ethereum address" + ] + } + }" + `); + expect(error).toBeInstanceOf(DocumentBuilderErrors.PropsValidationError); + }); + }); +}); diff --git a/src/4.0/__tests__/e2e.test.ts b/src/4.0/__tests__/e2e.test.ts new file mode 100644 index 00000000..12e5e17e --- /dev/null +++ b/src/4.0/__tests__/e2e.test.ts @@ -0,0 +1,221 @@ +import { obfuscate, validateSchema, verifySignature } from "../.."; +import { cloneDeep, omit } from "lodash"; +import { RAW_DOCUMENT_DID, SIGNED_WRAPPED_DOCUMENT_DID, WRAPPED_DOCUMENT_DID } from "../fixtures"; +import { V4OpenAttestationDocument } from "../types"; +import { wrapDocument, wrapDocuments } from "../wrap"; + +const DOCUMENT_ONE = { + ...RAW_DOCUMENT_DID, + credentialSubject: { + ...RAW_DOCUMENT_DID.credentialSubject, + key1: "test", + }, +} satisfies V4OpenAttestationDocument; +const DOCUMENT_TWO = { + ...RAW_DOCUMENT_DID, + credentialSubject: { + ...RAW_DOCUMENT_DID.credentialSubject, + key1: "hello", + key2: "item2", + }, +} satisfies V4OpenAttestationDocument; + +const DOCUMENT_THREE = { + ...RAW_DOCUMENT_DID, + credentialSubject: { + ...RAW_DOCUMENT_DID.credentialSubject, + key1: "item1", + key2: "true", + key3: 3.14159, + key4: false, + }, +} satisfies V4OpenAttestationDocument; + +const DOCUMENT_FOUR = { + ...RAW_DOCUMENT_DID, + credentialSubject: { + ...RAW_DOCUMENT_DID.credentialSubject, + key1: "item2", + }, +}; +const DATUM = [DOCUMENT_ONE, DOCUMENT_TWO, DOCUMENT_THREE, DOCUMENT_FOUR] satisfies V4OpenAttestationDocument[]; + +describe("V4 E2E Test Scenarios", () => { + describe("Issuing a single document", () => { + test("fails for missing data", async () => { + const missingData = { + ...omit(cloneDeep(DOCUMENT_ONE), "issuer"), + }; + await expect(wrapDocument(missingData as unknown as V4OpenAttestationDocument)).rejects + .toThrowErrorMatchingInlineSnapshot(` + "Input document does not conform to Open Attestation v4.0 Data Model: + { + "_errors": [], + "issuer": { + "_errors": [ + "Required" + ] + } + }" + `); + }); + + test("creates a wrapped document", async () => { + const wrappedDocument = await wrapDocument(RAW_DOCUMENT_DID); + expect(wrappedDocument["@context"]).toEqual([ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ]); + expect(wrappedDocument.type).toEqual(["VerifiableCredential", "OpenAttestationCredential"]); + expect(wrappedDocument.proof.type).toBe("OpenAttestationMerkleProofSignature2018"); + expect(wrappedDocument.proof.targetHash).toBeDefined(); + expect(wrappedDocument.proof.merkleRoot).toBeDefined(); + expect(wrappedDocument.proof.proofs).toEqual([]); + expect(wrappedDocument.proof.merkleRoot).toBe(wrappedDocument.proof.targetHash); + }); + + test("checks that document is wrapped correctly", async () => { + const wrappedDocument = await wrapDocument(DOCUMENT_ONE); + const verified = verifySignature(wrappedDocument); + expect(verified).toBe(true); + }); + + test("checks that document conforms to the schema", async () => { + const wrappedDocument = await wrapDocument(DOCUMENT_ONE); + expect(validateSchema(wrappedDocument)).toBe(true); + }); + + test("does not allow for the same merkle root to be generated", async () => { + // This test takes some time to run, so we set the timeout to 14s + const wrappedDocument = await wrapDocument(DOCUMENT_ONE); + const newDocument = await wrapDocument(DOCUMENT_ONE); + expect(wrappedDocument.proof.merkleRoot).not.toBe(newDocument.proof.merkleRoot); + }, 14000); + + test("obfuscate data correctly", async () => { + const newDocument = await wrapDocument(DOCUMENT_THREE); + expect(newDocument.credentialSubject.key2).toBeDefined(); + const obfuscatedDocument = obfuscate(newDocument, ["credentialSubject.key2"]); + expect(verifySignature(obfuscatedDocument)).toBe(true); + expect(validateSchema(obfuscatedDocument)).toBe(true); + expect(obfuscatedDocument.credentialSubject.key2).toBeUndefined(); + }); + + test("obfuscate data transistively", async () => { + const newDocument = await wrapDocument(DOCUMENT_THREE); + const intermediateDocument = obfuscate(newDocument, ["credentialSubject.key2"]); + const obfuscatedDocument = obfuscate(intermediateDocument, ["credentialSubject.key3"]); + expect(obfuscate(newDocument, ["credentialSubject.key2", "credentialSubject.key3"])).toEqual(obfuscatedDocument); + }); + + describe("Issuing a batch of documents", () => { + test("fails if there is a malformed document", async () => { + const malformedDatum = [ + ...DATUM, + { + laurent: "task force, assemble!!", + } as unknown as V4OpenAttestationDocument, + ]; + await expect(wrapDocuments(malformedDatum)).rejects.toThrow( + "Input document does not conform to Verifiable Credentials" + ); + }); + + test("creates a batch of documents if all are in the right format", async () => { + const wrappedDocuments = await wrapDocuments(DATUM); + wrappedDocuments.forEach((doc, i: number) => { + expect(doc.type).toEqual(["VerifiableCredential", "OpenAttestationCredential"]); + expect(doc.proof.type).toBe("OpenAttestationMerkleProofSignature2018"); + expect(doc.proof.type).toBe("OpenAttestationMerkleProofSignature2018"); + expect(doc.credentialSubject.key1).toEqual(expect.stringContaining(DATUM[i].credentialSubject.key1)); + expect(doc.proof.targetHash).toBeDefined(); + expect(doc.proof.merkleRoot).toBeDefined(); + expect(doc.proof.proofs.length).toEqual(2); + }); + }); + + test("checks that documents are wrapped correctly", async () => { + const wrappedDocuments = await wrapDocuments(DATUM); + const verified = wrappedDocuments.reduce((prev, curr) => verifySignature(curr) && prev, true); + expect(verified).toBe(true); + }); + + test("checks that documents conforms to the schema", async () => { + const wrappedDocuments = await wrapDocuments(DATUM); + const validatedSchema = wrappedDocuments.reduce( + (prev: boolean, curr: any) => validateSchema(curr) && prev, + true + ); + expect(validatedSchema).toBe(true); + }); + + test("does not allow for same merkle root to be generated", async () => { + const wrappedDocuments = await wrapDocuments(DATUM); + const newWrappedDocuments = await wrapDocuments(DATUM); + expect(wrappedDocuments[0].proof.merkleRoot).not.toBe(newWrappedDocuments[0].proof.merkleRoot); + }); + }); + }); + + describe("validate", () => { + test("should return true when document is a valid wrapped v4 document and identityProof is DNS-DID", () => { + expect(validateSchema(WRAPPED_DOCUMENT_DID)).toStrictEqual(true); + }); + + test("should return true when signed document is a valid signed wrapped v4 document and identityProof is DNS-DID", () => { + expect(validateSchema(SIGNED_WRAPPED_DOCUMENT_DID)).toStrictEqual(true); + }); + + test("should return false when document is invalid due to no DNS-DID identifier", () => { + const modifiedIssuer = cloneDeep(RAW_DOCUMENT_DID.issuer); + delete (modifiedIssuer as any).id; + const credential = { + ...RAW_DOCUMENT_DID, + issuer: modifiedIssuer, + } satisfies V4OpenAttestationDocument; + expect(validateSchema(credential)).toStrictEqual(false); + }); + + test("should default to 2.0 when document is valid and version is undefined", () => { + expect( + validateSchema({ + version: undefined, + data: { + issuers: [ + { + name: "issuer.name", + certificateStore: "0x9178F546D3FF57D7A6352bD61B80cCCD46199C2d", + }, + ], + }, + signature: { + merkleRoot: "0xabc", + proof: [], + targetHash: "0xabc", + type: "SHA3MerkleProof", + }, + }) + ).toStrictEqual(true); + }); + }); + + describe("unicode", () => { + test("should not corrupt unicode document", async () => { + const document = { + ...RAW_DOCUMENT_DID, + credentialSubject: { + key1: "哦喷啊特特是他题哦你", + key2: "นยำืฟะะำหะฟะรนื", + key3: "おぺなってsたちおn", + key4: "خحثىشففثسفشفهخى", + }, + }; + const wrapped = await wrapDocument(document); + expect(wrapped.proof.merkleRoot).toBeTruthy(); + expect(wrapped.credentialSubject.key1).toBe(document.credentialSubject.key1); + expect(wrapped.credentialSubject.key2).toBe(document.credentialSubject.key2); + expect(wrapped.credentialSubject.key3).toBe(document.credentialSubject.key3); + expect(wrapped.credentialSubject.key4).toBe(document.credentialSubject.key4); + }); + }); +}); diff --git a/src/4.0/__tests__/fixtures.test.ts b/src/4.0/__tests__/fixtures.test.ts new file mode 100644 index 00000000..4ab9554c --- /dev/null +++ b/src/4.0/__tests__/fixtures.test.ts @@ -0,0 +1,17 @@ +import fs from "fs"; +import path from "path"; +import * as FIXTURES from "../fixtures"; + +const PATH_TO_GENERATED_FIXTURES = path.resolve(__dirname, "../../../test/fixtures/v4/__generated__"); + +describe(`assert fixtures matches generated JSON fixtures, if this fails, run "npm i" or "npm run postinstall" to update the json fixtures, and commit changes if needed`, () => { + for (const fixtureName of Object.keys(FIXTURES)) { + const jsonFixtureFilename = fixtureName.replace(/_/g, "-").toLowerCase() + ".json"; + + test(`${jsonFixtureFilename} should match the one defined in fixtures.ts`, () => { + const fixture = FIXTURES[fixtureName as keyof typeof FIXTURES]; + const jsonFixture = fs.readFileSync(path.resolve(PATH_TO_GENERATED_FIXTURES, jsonFixtureFilename), "utf-8"); + expect(fixture).toEqual(JSON.parse(jsonFixture)); + }); + } +}); diff --git a/src/4.0/__tests__/guard.test.ts b/src/4.0/__tests__/guard.test.ts new file mode 100644 index 00000000..f7dcee28 --- /dev/null +++ b/src/4.0/__tests__/guard.test.ts @@ -0,0 +1,162 @@ +import { SUPPORTED_SIGNING_ALGORITHM } from "../../shared/@types/sign"; +import { RAW_DOCUMENT_DID } from "../fixtures"; +import { signDocument } from "../sign"; +import { + W3cVerifiableCredential, + V4OpenAttestationDocument, + V4WrappedDocument, + V4SignedWrappedDocument, +} from "../types"; +import { wrapDocument } from "../wrap"; + +const RAW_DOCUMENT = { + ...RAW_DOCUMENT_DID, + credentialSubject: { + ...RAW_DOCUMENT_DID.credentialSubject, + attachments: [ + { + mimeType: "image/png", + filename: "aaa", + data: "abcd", + }, + ], + }, +} satisfies V4OpenAttestationDocument; + +describe("V4.0 guard", () => { + let WRAPPED_DOCUMENT: V4WrappedDocument; + let SIGNED_WRAPPED_DOCUMENT: V4SignedWrappedDocument; + beforeAll(async () => { + WRAPPED_DOCUMENT = await wrapDocument(RAW_DOCUMENT); + SIGNED_WRAPPED_DOCUMENT = await signDocument( + WRAPPED_DOCUMENT, + SUPPORTED_SIGNING_ALGORITHM.Secp256k1VerificationKey2018, + { + public: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller", + private: "0x497c85ed89f1874ba37532d1e33519aba15bd533cdcb90774cc497bfe3cde655", + } + ); + }); + + describe("given a raw document", () => { + test("should pass w3c vc validation without removal of any data", () => { + const w3cVerifiableCredential: W3cVerifiableCredential = RAW_DOCUMENT_DID; + const results = W3cVerifiableCredential.parse(w3cVerifiableCredential); + expect(results).toEqual(RAW_DOCUMENT_DID); + }); + + test("should pass document validation without removal of any data", () => { + const results = V4OpenAttestationDocument.parse(RAW_DOCUMENT_DID); + expect(results).toEqual(RAW_DOCUMENT_DID); + }); + + test("should fail wrapped document validation", () => { + const results = V4WrappedDocument.safeParse(RAW_DOCUMENT_DID); + expect(results.success).toBe(false); + expect((results as { error: unknown }).error).toMatchInlineSnapshot(` + [ZodError: [ + { + "code": "invalid_type", + "expected": "object", + "received": "undefined", + "path": [ + "proof" + ], + "message": "Required" + } + ]] + `); + }); + + test("should fail signed wrapped document validation", () => { + const results = V4SignedWrappedDocument.safeParse(RAW_DOCUMENT_DID); + expect(results.success).toBe(false); + expect((results as { error: unknown }).error).toMatchInlineSnapshot(` + [ZodError: [ + { + "code": "invalid_type", + "expected": "object", + "received": "undefined", + "path": [ + "proof" + ], + "message": "Required" + } + ]] + `); + }); + }); + + describe("given a wrapped document", () => { + test("should pass w3c vc validation without removal of any data", () => { + const w3cVerifiableCredential: W3cVerifiableCredential = WRAPPED_DOCUMENT; + const results = W3cVerifiableCredential.parse(w3cVerifiableCredential); + expect(results).toEqual(WRAPPED_DOCUMENT); + }); + + test("should pass document validation without removal of any data", () => { + const v4Document: V4OpenAttestationDocument = WRAPPED_DOCUMENT; + const results = V4OpenAttestationDocument.parse(v4Document); + expect(results).toEqual(WRAPPED_DOCUMENT); + }); + + test("should pass wrapped document validation without removal of any data", () => { + const results = V4WrappedDocument.parse(WRAPPED_DOCUMENT); + expect(results).toEqual(WRAPPED_DOCUMENT); + }); + + test("should fail signed wrapped document validation", () => { + const results = V4SignedWrappedDocument.safeParse(WRAPPED_DOCUMENT); + expect(results.success).toBe(false); + expect((results as { error: unknown }).error).toMatchInlineSnapshot(` + [ZodError: [ + { + "code": "invalid_type", + "expected": "string", + "received": "undefined", + "path": [ + "proof", + "key" + ], + "message": "Required" + }, + { + "code": "invalid_type", + "expected": "string", + "received": "undefined", + "path": [ + "proof", + "signature" + ], + "message": "Required" + } + ]] + `); + }); + }); + + describe("given a signed wrapped document", () => { + test("should pass w3c vc validation without removal of any data", () => { + const w3cVerifiableCredential: W3cVerifiableCredential = SIGNED_WRAPPED_DOCUMENT; + const results = W3cVerifiableCredential.parse(w3cVerifiableCredential); + expect(results).toEqual(SIGNED_WRAPPED_DOCUMENT); + }); + + test("should pass document validation without removal of any data", () => { + const v4Document: V4OpenAttestationDocument = SIGNED_WRAPPED_DOCUMENT; + const results = V4OpenAttestationDocument.parse(v4Document); + expect(results).toEqual(SIGNED_WRAPPED_DOCUMENT); + }); + + test("should pass wrapped document validation without removal of any data", () => { + const v4WrappedDocument: V4WrappedDocument = SIGNED_WRAPPED_DOCUMENT; + const results = V4WrappedDocument.parse(v4WrappedDocument); + expect(results).toEqual(SIGNED_WRAPPED_DOCUMENT); + }); + + test("should pass signed wrapped document validation without removal of any data", () => { + const results = V4SignedWrappedDocument.parse(SIGNED_WRAPPED_DOCUMENT); + expect(results).toEqual(SIGNED_WRAPPED_DOCUMENT); + }); + }); +}); diff --git a/src/4.0/__tests__/obfuscate.test.ts b/src/4.0/__tests__/obfuscate.test.ts new file mode 100644 index 00000000..079db9e6 --- /dev/null +++ b/src/4.0/__tests__/obfuscate.test.ts @@ -0,0 +1,319 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { obfuscateVerifiableCredential } from "../obfuscate"; +import { get } from "lodash"; +import { decodeSalt } from "../salt"; +import { wrapDocument } from "../wrap"; +import { Salt, V4OpenAttestationDocument, V4WrappedDocument } from "../types"; +import { verifySignature } from "../../"; +import { RAW_DOCUMENT_DID, SIGNED_WRAPPED_DOCUMENT_DID_OBFUSCATED, WRAPPED_DOCUMENT_DID } from "../fixtures"; +import { hashLeafNode } from "../digest"; +import { getObfuscatedData, isObfuscated } from "../../shared/utils"; + +const makeV4RawDocument = >(props: T) => + ({ + ...RAW_DOCUMENT_DID, + ...(props as T), + } satisfies V4OpenAttestationDocument); + +const findSaltByPath = (salts: string, path: string): Salt | undefined => { + return decodeSalt(salts).find((salt) => salt.path === path); +}; + +/** + * /!\ This method doesn't work with array like notation + * This method will ensure + * - the field has been added to the obfuscated array + * - the salt bound to the field has been removed + * - the field has been removed + */ +const expectRemovedFieldsWithoutArrayNotation = ( + field: string, + document: V4WrappedDocument, + obfuscatedDocument: V4WrappedDocument +) => { + const value = get(document, field); + const salt = findSaltByPath(document.proof.salts, field); + + if (!salt) throw new Error("Salt not found for ${field}"); + + expect(obfuscatedDocument.proof.privacy.obfuscated).toContain( + hashLeafNode({ value, salt: salt.value, path: salt.path }, { toHexString: true }) + ); + expect(findSaltByPath(obfuscatedDocument.proof.salts, field)).toBeUndefined(); + expect(obfuscatedDocument).not.toHaveProperty(field); +}; + +describe("privacy", () => { + describe("obfuscateDocument", () => { + test("removes one field from the root object", async () => { + const PATH_TO_REMOVE = "name"; + const wrappedDocument = await wrapDocument( + makeV4RawDocument({ credentialSubject: { id: "S1234567A", name: "John Doe" } }) + ); + const obfuscatedDocument = obfuscateVerifiableCredential(wrappedDocument, PATH_TO_REMOVE); + const verified = verifySignature(obfuscatedDocument); + expect(verified).toBe(true); + + expectRemovedFieldsWithoutArrayNotation(PATH_TO_REMOVE, wrappedDocument, obfuscatedDocument); + expect(obfuscatedDocument.proof.privacy.obfuscated).toHaveLength(1); + }); + + test("removes paths that result in an invalid wrapped document, should throw", async () => { + const PATHS_TO_REMOVE = ["credentialSubject", "renderMethod.0.id", "name"]; + const wrappedDocument = await wrapDocument( + makeV4RawDocument({ credentialSubject: { id: "S1234567A", name: "John Doe" } }) + ); + expect(() => obfuscateVerifiableCredential(wrappedDocument, PATHS_TO_REMOVE)).toThrowError( + `"credentialSubject", "renderMethod.0.id"` + ); + }); + + test("removes one key of an object from an array", async () => { + const PATH_TO_REMOVE = "credentialSubject.arrayOfObject[0].foo" as const; + const newDocument = await wrapDocument( + makeV4RawDocument({ + credentialSubject: { + id: "did:example:ebfeb1f712ebc6f1c276e12ec21", + alumniOf: "Example University", + array: ["one", "two", "three", "four"], + arrayOfObject: [ + { foo: "bar", doo: "foo" }, + { foo: "baz", doo: "faz" }, + ], + }, + }) + ); + const obfuscatedDocument = await obfuscateVerifiableCredential(newDocument, PATH_TO_REMOVE); + + const verified = verifySignature(obfuscatedDocument); + expect(verified).toBe(true); + + const value = get(newDocument, PATH_TO_REMOVE); + const salt = findSaltByPath(newDocument.proof.salts, PATH_TO_REMOVE); + + if (!salt) throw new Error(`Salt not found for ${PATH_TO_REMOVE}`); + + expect(obfuscatedDocument.proof.privacy.obfuscated).toContain( + hashLeafNode({ value, salt: salt.value, path: PATH_TO_REMOVE }, { toHexString: true }) + ); + expect(findSaltByPath(obfuscatedDocument.proof.salts, PATH_TO_REMOVE)).toBeUndefined(); + expect(obfuscatedDocument.credentialSubject.arrayOfObject?.[0]).toStrictEqual({ doo: "foo" }); + expect(obfuscatedDocument.proof.privacy.obfuscated).toHaveLength(1); + }); + + test("given an object is to be removed, should remove the object itself, as well as add each of its key's hash into privacy.obfuscated", async () => { + const PATH_TO_REMOVE = "credentialSubject.hee"; + const wrappedDocument = await wrapDocument( + makeV4RawDocument({ + credentialSubject: { + hee: { foo: "bar", doo: "foo" }, + haa: { foo: "baz", doo: "faz" }, + }, + }) + ); + const obfuscatedDocument = obfuscateVerifiableCredential(wrappedDocument, PATH_TO_REMOVE); + + const verified = verifySignature(obfuscatedDocument); + expect(verified).toBe(true); + + // assert that each key of the object has been moved to privacy.obfuscated + ["credentialSubject.hee.foo", "credentialSubject.hee.doo"].forEach((expectedRemovedField) => { + const value = get(wrappedDocument, expectedRemovedField); + const salt = findSaltByPath(wrappedDocument.proof.salts, expectedRemovedField); + + if (!salt) throw new Error(`Salt not found for ${expectedRemovedField}`); + + expect(obfuscatedDocument.proof.privacy.obfuscated).toContain( + hashLeafNode({ value, salt: salt.value, path: expectedRemovedField }, { toHexString: true }) + ); + expect(findSaltByPath(obfuscatedDocument.proof.salts, expectedRemovedField)).toBeUndefined(); + }); + + expect(obfuscatedDocument.credentialSubject?.hee).toBeUndefined(); // let's make sure only the first item has been removed + expect(obfuscatedDocument.proof.privacy.obfuscated).toHaveLength(2); + }); + + test("given an entire array of objects to remove, should remove the array itself, then for every item, add each of its key's hash into privacy.obfuscated", async () => { + const PATH_TO_REMOVE = "credentialSubject.attachments"; + const wrappedDocument = await wrapDocument( + makeV4RawDocument({ + credentialSubject: { + arrayOfObject: [ + { foo: "bar", doo: "foo" }, + { foo: "baz", doo: "faz" }, + ], + attachments: [ + { + mimeType: "image/png", + filename: "aaa", + data: "abcd", + }, + { + mimeType: "image/png", + filename: "bbb", + data: "abcd", + }, + ], + }, + }) + ); + const obfuscatedDocument = await obfuscateVerifiableCredential(wrappedDocument, PATH_TO_REMOVE); + + const verified = verifySignature(obfuscatedDocument); + expect(verified).toBe(true); + + [ + "credentialSubject.attachments[0].mimeType", + "credentialSubject.attachments[0].filename", + "credentialSubject.attachments[0].data", + "credentialSubject.attachments[1].mimeType", + "credentialSubject.attachments[1].filename", + "credentialSubject.attachments[1].data", + ].forEach((expectedRemovedField) => { + const value = get(wrappedDocument, expectedRemovedField); + const salt = findSaltByPath(wrappedDocument.proof.salts, expectedRemovedField); + + if (!salt) throw new Error(`Salt not found for ${expectedRemovedField}`); + + expect(obfuscatedDocument.proof.privacy.obfuscated).toContain( + hashLeafNode({ value, salt: salt.value, path: expectedRemovedField }, { toHexString: true }) + ); + expect(findSaltByPath(obfuscatedDocument.proof.salts, expectedRemovedField)).toBeUndefined(); + }); + expect(obfuscatedDocument.credentialSubject.attachments).toBeUndefined(); + expect(obfuscatedDocument.proof.privacy.obfuscated).toHaveLength(6); + }); + + test("given multiple fields to be removed, should remove fields and add their hash into privacy.obfuscated", async () => { + const PATHS_TO_REMOVE = ["credentialSubject.key1", "credentialSubject.key2"]; + const wrappedDocument = await wrapDocument( + makeV4RawDocument({ + credentialSubject: { + key1: "value1", + key2: "value2", + key3: "value3", + }, + }) + ); + const obfuscatedDocument = await obfuscateVerifiableCredential(wrappedDocument, PATHS_TO_REMOVE); + const verified = verifySignature(obfuscatedDocument); + expect(verified).toBe(true); + + PATHS_TO_REMOVE.forEach((expectedRemovedField) => { + expectRemovedFieldsWithoutArrayNotation(expectedRemovedField, wrappedDocument, obfuscatedDocument); + }); + expect(obfuscatedDocument.proof.privacy.obfuscated).toHaveLength(2); + }); + + test("given a path to remove an entire item from an array, should throw", async () => { + const wrappedDocument = await wrapDocument( + makeV4RawDocument({ + credentialSubject: { + arrayOfObject: [ + { foo: "bar", doo: "foo" }, + { foo: "baz", doo: "faz" }, + ], + attachments: [ + { + mimeType: "image/png", + filename: "aaa", + data: "abcd", + }, + { + mimeType: "image/png", + filename: "bbb", + data: "abcd", + }, + { + mimeType: "image/png", + filename: "ccc", + data: "abcd", + }, + ], + }, + }) + ); + + expect(() => + obfuscateVerifiableCredential(wrappedDocument, [ + "credentialSubject.attachments[0]", + "credentialSubject.attachments[2]", + ]) + ).toThrow(); + }); + + test("given a path to remove all elements in an object, should throw", async () => { + const wrappedDocument = await wrapDocument( + makeV4RawDocument({ + credentialSubject: { + arrayOfObject: [ + { foo: "bar", doo: "foo" }, + { foo: "baz", doo: "faz" }, + ], + object: { + foo: "bar", + }, + }, + }) + ); + + expect(() => + obfuscateVerifiableCredential(wrappedDocument, [ + "credentialSubject.arrayOfObject[0].foo", + "credentialSubject.arrayOfObject[0].doo", + ]) + ).toThrowErrorMatchingInlineSnapshot( + `"Obfuscation of "credentialSubject.arrayOfObject[0].doo" has resulted in an empty {}, this is currently not supported. Alternatively, if the object is not part of an array, you may choose to obfuscate the parent of "credentialSubject.arrayOfObject[0].doo"."` + ); + expect(() => + obfuscateVerifiableCredential(wrappedDocument, ["credentialSubject.object.foo"]) + ).toThrowErrorMatchingInlineSnapshot( + `"Obfuscation of "credentialSubject.object.foo" has resulted in an empty {}, this is currently not supported. Alternatively, if the object is not part of an array, you may choose to obfuscate the parent of "credentialSubject.object.foo"."` + ); + }); + + test("is transitive", async () => { + const wrappedDocument = await wrapDocument( + makeV4RawDocument({ + credentialSubject: { + key1: "value1", + key2: "value2", + key3: "value3", + }, + }) + ); + const intermediateDoc = obfuscateVerifiableCredential(wrappedDocument, "key1"); + const finalDoc1 = obfuscateVerifiableCredential(intermediateDoc, "key2"); + const finalDoc2 = obfuscateVerifiableCredential(wrappedDocument, ["key1", "key2"]); + + expect(finalDoc1).toEqual(finalDoc2); + expect(intermediateDoc).not.toHaveProperty("key1"); + expect(finalDoc1).not.toHaveProperty("key1"); + expect(finalDoc1).not.toHaveProperty("key2"); + expect(finalDoc2).not.toHaveProperty("key1"); + expect(finalDoc2).not.toHaveProperty("key2"); + }); + }); + + describe("getObfuscated", () => { + test("should return empty array when there is no obfuscated data in document", () => { + expect(getObfuscatedData(WRAPPED_DOCUMENT_DID)).toHaveLength(0); + }); + + test("should return array of hashes when there is obfuscated data in document", () => { + const obfuscatedData = getObfuscatedData(SIGNED_WRAPPED_DOCUMENT_DID_OBFUSCATED); + expect(obfuscatedData.length).toBe(1); + expect(obfuscatedData?.[0]).toBe("0394c26c5be1bde929bf5aec2e076fc6843ace379be541c30707dab467baa59f"); + }); + }); + + describe("isObfuscated", () => { + test("should return false when there is no obfuscated data in document", () => { + expect(isObfuscated(WRAPPED_DOCUMENT_DID)).toBe(false); + }); + + test("should return true where there is obfuscated data in document", () => { + expect(isObfuscated(SIGNED_WRAPPED_DOCUMENT_DID_OBFUSCATED)).toBe(true); + }); + }); +}); diff --git a/src/4.0/__tests__/salt.test.ts b/src/4.0/__tests__/salt.test.ts new file mode 100644 index 00000000..a512668f --- /dev/null +++ b/src/4.0/__tests__/salt.test.ts @@ -0,0 +1,116 @@ +import { salt, decodeSalt } from "../salt"; +import { Base64 } from "js-base64"; + +describe("V4.0 digest", () => { + describe("salt", () => { + test("handles shadowed keys correctly (type 1: root, dot notation)", () => { + const document = { + "credentialSubject.alumniOf": + "0xSomeMaliciousDocumentStore, this would be at credentialSubject.alumniOf after flatMap if uncaught", + }; + expect(() => { + salt(document); + }).toThrow("Key names must not have . in them"); + }); + test("handles shadowed keys correctly (type 2: root, array index)", () => { + const document = { + "type[1]": "MaliciousCredential, this would be at type[1] after flatMap if uncaught", + }; + expect(() => { + salt(document); + }).toThrow("Key names must not have '[' or ']' in them"); + }); + test("handles shadowed keys correctly (type 3: nested as object, dot notation)", () => { + const document = { + nested: { + "credentialSubject.alumniOf": + "0xSomeMaliciousDocumentStore, this would be at nested.credentialSubject.alumniOf after flatMap if uncaught", + }, + }; + expect(() => { + salt(document); + }).toThrow("Key names must not have . in them"); + }); + test("handles shadowed keys correctly (type 4: nested as object, array index)", () => { + const document = { + nested: { "type[1]": "this would be at nested.type[1] after flatMap if uncaught" }, + }; + expect(() => { + salt(document); + }).toThrow("Key names must not have '[' or ']' in them"); + }); + test("handles shadowed keys correctly (type 5: nested as array, dot notation)", () => { + const document = { + nested: [{ "shadowed.key": "this would be at nested[0].shadowed.key after flatMap if uncaught" }], + }; + expect(() => { + salt(document); + }).toThrow("Key names must not have . in them"); + }); + test("handles shadowed keys correctly (type 6: nested as array, array index)", () => { + const document = { + nested: [{ "type[1]": "this would be at nested[0].type[1] after flatMap if uncaught" }], + }; + expect(() => { + salt(document); + }).toThrow("Key names must not have '[' or ']' in them"); + }); + + test("handles null values correctly", () => { + const document = { + grades: null, + }; + const salted = salt(document); + expect(salted).toContainEqual(expect.objectContaining({ path: "grades" })); + }); + test("handles undefined values correctly", () => { + const document = { + grades: undefined, + }; + expect(() => { + salt(document); + }).toThrow("Unexpected data 'undefined' in 'grades'"); // Cannot convert undefined or null to object? + }); + test("handles numbers and booleans correctly", () => { + const document = { + grades: ["A+", 100, 50.28, true, "B+"], + }; + const salted = salt(document); + expect(salted).toContainEqual(expect.objectContaining({ path: "grades[0]" })); + expect(salted).toContainEqual(expect.objectContaining({ path: "grades[1]" })); + expect(salted).toContainEqual(expect.objectContaining({ path: "grades[2]" })); + expect(salted).toContainEqual(expect.objectContaining({ path: "grades[3]" })); + expect(salted).toContainEqual(expect.objectContaining({ path: "grades[4]" })); + }); + test("throw on sparse arrays (we do not support obfuscation of array item as JSON turns empty slots into null values)", () => { + const document = { + grades: ["A+", 100, , , , true, "B+"], + }; + expect(() => salt(document)).toThrow(`Unexpected data 'undefined'`); + }); + }); + + describe("decodeSalt", () => { + it("should throw when salt is of wrong length to prevent attack on value", () => { + const encodedSalt = Base64.encode( + JSON.stringify([{ path: "foo", value: "123456789012345678901234567890123456789012345678901234567890" }]) + ); + expect(() => decodeSalt(encodedSalt)).toThrowError("Salt must be 32 bytes"); + }); + + it("should decode salt correctly", () => { + const encodedSalt = Base64.encode( + JSON.stringify([{ path: "foo", value: "1234567890123456789012345678901234567890123456789012345678901234" }]) + ); + const decoded = decodeSalt(encodedSalt); + expect(decoded).toMatchInlineSnapshot(` + [ + { + "path": "foo", + "value": "1234567890123456789012345678901234567890123456789012345678901234", + }, + ] + `); + }); + }); +}); diff --git a/src/4.0/__tests__/sign.test.ts b/src/4.0/__tests__/sign.test.ts new file mode 100644 index 00000000..30d1042c --- /dev/null +++ b/src/4.0/__tests__/sign.test.ts @@ -0,0 +1,105 @@ +import { SUPPORTED_SIGNING_ALGORITHM } from "../../shared/@types/sign"; +import { Wallet } from "ethers"; +import { WRAPPED_DOCUMENT_DID } from "../fixtures"; +import { V4SignedWrappedDocument } from "../types"; +import { signDocument } from "../sign"; + +describe("V4 sign", () => { + it("should sign a document", async () => { + const signedWrappedDocument = await signDocument( + WRAPPED_DOCUMENT_DID, + SUPPORTED_SIGNING_ALGORITHM.Secp256k1VerificationKey2018, + { + public: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller", + private: "0x497c85ed89f1874ba37532d1e33519aba15bd533cdcb90774cc497bfe3cde655", + } + ); + const parsedResults = V4SignedWrappedDocument.safeParse(signedWrappedDocument); + if (!parsedResults.success) { + throw new Error("Parsing failed"); + } + const { proof } = parsedResults.data; + expect(Object.keys(proof).length).toBe(9); + expect(proof.key).toBe("did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller"); + expect(proof.signature).toBe( + "0xa3ac9f73a7314c0aad47bad875921f5c88d2af9440d6c309fc2f93dbf43bd8235e84b744cb1ff1c09c214b559ce3bd6eb148c2f68c677cb8408d96e9b5411dfb1c" + ); + }); + it("should sign a document with a wallet", async () => { + const wallet = Wallet.fromMnemonic( + "tourist quality multiply denial diary height funny calm disease buddy speed gold" + ); + const signedWrappedDocument = await signDocument( + WRAPPED_DOCUMENT_DID, + SUPPORTED_SIGNING_ALGORITHM.Secp256k1VerificationKey2018, + wallet + ); + const parsedResults = V4SignedWrappedDocument.safeParse(signedWrappedDocument); + if (!parsedResults.success) { + throw new Error("Parsing failed"); + } + const { proof } = parsedResults.data; + expect(Object.keys(proof).length).toBe(9); + expect(proof.key).toBe("did:ethr:0x906FB815De8976b1e38D9a4C1014a3acE16Ce53C#controller"); + expect(proof.signature).toBe( + "0xb850c0f34d834a7de4185eead5295eeebf9a56ada4603d94f10a72e0fe144179140ce534ddb4123c6fffbf5594d112e1f679e537b29c5188ccd2b940c4798dd11b" + ); + }); + + it("should a signed document to be resigned", async () => { + const signedDocument = await signDocument( + WRAPPED_DOCUMENT_DID, + SUPPORTED_SIGNING_ALGORITHM.Secp256k1VerificationKey2018, + { + public: "did:ethr:0xb6De3744E1259e1aB692f5a277f053B79429c5a2#controller", + private: "0x812269266b34d2919f737daf22db95f02642f8cdc0ca673bf3f701599f4971f5", + } + ); + + const resignedDocument = await signDocument( + WRAPPED_DOCUMENT_DID, + SUPPORTED_SIGNING_ALGORITHM.Secp256k1VerificationKey2018, + { + public: "did:ethr:0xb6De3744E1259e1aB692f5a277f053B79429c5a2#controller", + private: "0x812269266b34d2919f737daf22db95f02642f8cdc0ca673bf3f701599f4971f5", + } + ); + + expect(signedDocument).toEqual(resignedDocument); + }); + + it("should throw error if a key or signer is invalid", async () => { + await expect( + signDocument(WRAPPED_DOCUMENT_DID, SUPPORTED_SIGNING_ALGORITHM.Secp256k1VerificationKey2018, {} as any) + ).rejects.toThrowErrorMatchingInlineSnapshot(`"Either a keypair or ethers.js Signer must be provided"`); + }); + + it("should throw error if proof is malformed", async () => { + await expect( + signDocument( + { + ...WRAPPED_DOCUMENT_DID, + proof: { ...WRAPPED_DOCUMENT_DID.proof, merkleRoot: undefined as unknown as string }, + }, + SUPPORTED_SIGNING_ALGORITHM.Secp256k1VerificationKey2018, + { + public: "did:ethr:0xb6De3744E1259e1aB692f5a277f053B79429c5a2#controller", + private: "0x812269266b34d2919f737daf22db95f02642f8cdc0ca673bf3f701599f4971f5", + } + ) + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "Document has not been properly wrapped: + { + "_errors": [], + "proof": { + "_errors": [], + "merkleRoot": { + "_errors": [ + "Required" + ] + } + } + }" + `); + }); +}); diff --git a/src/4.0/__tests__/verify.test.ts b/src/4.0/__tests__/verify.test.ts new file mode 100644 index 00000000..edd587fb --- /dev/null +++ b/src/4.0/__tests__/verify.test.ts @@ -0,0 +1,209 @@ +import { cloneDeep } from "lodash"; +import { BATCHED_SIGNED_WRAPPED_DOCUMENTS_DID, SIGNED_WRAPPED_DOCUMENT_DID } from "../fixtures"; +import { V4SignedWrappedDocument } from "../types"; +import { verify } from "../verify"; + +const TEST_DOCUMENTS = { + "Documents without proofs mean these documents are wrapped individually (i.e. targetHash == merkleRoot)": + SIGNED_WRAPPED_DOCUMENT_DID, + "Documents with proofs mean these documents are wrapped as a batch (i.e. proofs exist, and targetHash !== merkleRoot)": + BATCHED_SIGNED_WRAPPED_DOCUMENTS_DID[0], +} as const; + +describe("V4 verify", () => { + Object.entries(TEST_DOCUMENTS).forEach(([description, document]) => { + describe(`${description}`, () => { + test("given a document wiht unaltered data, should return true", () => { + expect(verify(document)).toBe(true); + }); + + describe("tempering", () => { + test("given a value of a key in object is changed, should return false", () => { + const newName = "Fake Name"; + expect(document.issuer.name).not.toBe(newName); + expect( + verify({ + ...document, + issuer: { + ...document.issuer, + name: "Fake Name", // Value was originally "DEMO STORE" + }, + }) + ).toBe(false); + }); + + test("given a key in an object is altered (value kept the same), should return false", () => { + const { name, ...issuerWithoutName } = document.issuer; + + expect( + verify({ + ...document, + issuer: { + ...issuerWithoutName, + fakename: name, // Key was originally "name" + } as unknown as V4SignedWrappedDocument["issuer"], + }) + ).toBe(false); + }); + + test("given a new array item is added, should return false", () => { + const modifiedCredentialSubject = cloneDeep(document.credentialSubject); + expect(modifiedCredentialSubject.licenses[2]).toBeUndefined(); + modifiedCredentialSubject.licenses.push({ + class: "Class 2A", + effectiveDate: "2020-06-05T00:00:00Z", + description: "Motorcycle", + }); + expect(modifiedCredentialSubject.licenses[2].description).toBeDefined(); + + expect( + verify({ + ...document, + credentialSubject: modifiedCredentialSubject, + }) + ).toBe(false); + }); + + test("given a key in an item is removed, should return false", () => { + const modifiedCredentialSubject = cloneDeep(document.credentialSubject); + expect(modifiedCredentialSubject.licenses[0].description).toBeDefined(); + delete (modifiedCredentialSubject.licenses[0] as any).description; + expect(modifiedCredentialSubject.licenses[0].description).toBeUndefined(); + + expect( + verify({ + ...document, + credentialSubject: modifiedCredentialSubject, + }) + ).toBe(false); + }); + + describe("given insertion of an empty object, should return false", () => { + test("given insertion into an object", () => { + expect( + verify({ + ...document, + credentialSubject: { + ...document.credentialSubject, + newField: {}, + }, + }) + ).toBe(false); + }); + + test("given insertion into an array", () => { + const modifiedCredentialSubject = cloneDeep(document.credentialSubject); + expect(modifiedCredentialSubject.licenses[2]).toBeUndefined(); + modifiedCredentialSubject.licenses.push({} as any); + expect(modifiedCredentialSubject.licenses[2]).toEqual({}); + + expect( + verify({ + ...document, + credentialSubject: modifiedCredentialSubject, + }) + ).toBe(false); + }); + }); + + describe("given insertion of an empty array, should return false", () => { + test("given insertion into an object", () => { + expect( + verify({ + ...document, + credentialSubject: { + ...document.credentialSubject, + newField: [], + }, + }) + ).toBe(false); + }); + + test("given insertion into an array", () => { + const modifiedCredentialSubject = cloneDeep(document.credentialSubject); + expect(modifiedCredentialSubject.licenses[2]).toBeUndefined(); + modifiedCredentialSubject.licenses.push([] as any); + expect(modifiedCredentialSubject.licenses[2]).toEqual([]); + + expect( + verify({ + ...document, + credentialSubject: modifiedCredentialSubject, + }) + ).toBe(false); + }); + }); + + test("given insertion of a null value into an object, should return false", () => { + expect( + verify({ + ...document, + credentialSubject: { + ...document.credentialSubject, + newField: null, + }, + }) + ).toBe(false); + + const modifiedCredentialSubject = cloneDeep(document.credentialSubject); + expect(modifiedCredentialSubject.licenses[2]).toBeUndefined(); + modifiedCredentialSubject.licenses.push({} as any); + expect(modifiedCredentialSubject.licenses[2]).toEqual({}); + + expect( + verify({ + ...document, + credentialSubject: modifiedCredentialSubject, + }) + ).toBe(false); + }); + + test("given a null value is inserted into an array, should return false", () => { + const modifiedCredentialSubject = cloneDeep(document.credentialSubject); + expect(modifiedCredentialSubject.licenses[2]).toBeUndefined(); + modifiedCredentialSubject.licenses.push(null as any); + expect(modifiedCredentialSubject.licenses[2]).toBe(null); + + expect( + verify({ + ...document, + credentialSubject: modifiedCredentialSubject, + }) + ).toBe(false); + }); + + test("given an altered value type that string coerce to the same value, should return false", () => { + const modifiedCredentialSubject = cloneDeep(document.credentialSubject); + expect(typeof modifiedCredentialSubject.licenses[0].class).toBe("string"); + modifiedCredentialSubject.licenses[0].class = 3 as unknown as string; + expect(typeof modifiedCredentialSubject.licenses[0].class).toBe("number"); + + expect( + verify({ + ...document, + credentialSubject: modifiedCredentialSubject, + }) + ).toBe(false); + }); + + test("given a key and value is moved, should return false", () => { + const modifiedCredentialSubject = cloneDeep(document.credentialSubject); + + // move "id" from credentialSubject to root + expect(modifiedCredentialSubject.id).toBe("urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42"); + const id = modifiedCredentialSubject.id; + delete (modifiedCredentialSubject as any).id; + expect(modifiedCredentialSubject.id).toBeUndefined(); + + expect( + verify({ + ...document, + id, + credentialSubject: modifiedCredentialSubject, + }) + ).toBe(false); + }); + }); + }); + }); +}); diff --git a/src/4.0/__tests__/wrap.test.ts b/src/4.0/__tests__/wrap.test.ts new file mode 100644 index 00000000..ebd628c6 --- /dev/null +++ b/src/4.0/__tests__/wrap.test.ts @@ -0,0 +1,132 @@ +import { V4OpenAttestationDocument, V4WrappedDocument, W3cVerifiableCredential } from "../types"; +import { wrapDocument } from "../wrap"; + +describe("V4.0 wrap document", () => { + test("given a valid v4 document, should wrap correctly", async () => { + const wrapped = await wrapDocument({ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + type: ["VerifiableCredential", "OpenAttestationCredential"], + credentialSubject: { + id: "0x1234567890123456789012345678901234567890", + name: "John Doe", + country: "SG", + }, + issuer: { + id: "did:ethr:0xB26B4941941C51a4885E5B7D3A1B861E54405f90", + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { identityProofType: "DNS-DID", identifier: "example.openattestation.com" }, + }, + }); + const parsedResults = V4WrappedDocument.safeParse(wrapped); + if (!parsedResults.success) { + throw new Error("Parsing failed"); + } + const { proof } = parsedResults.data; + expect(proof.merkleRoot.length).toBe(64); + expect(proof.privacy.obfuscated).toEqual([]); + expect(proof.proofPurpose).toBe("assertionMethod"); + expect(proof.proofs).toEqual([]); + expect(proof.salts.length).toBeGreaterThan(0); + expect(proof.targetHash.length).toBe(64); + expect(proof.type).toBe("OpenAttestationMerkleProofSignature2018"); + }); + + test("given a document with explicit v4 contexts, but does not conform to the V4 document schema, should throw", async () => { + await expect( + wrapDocument({ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + + type: ["VerifiableCredential", "OpenAttestationCredential"], + credentialSubject: { + id: "0x1234567890123456789012345678901234567890", + name: "John Doe", + country: "SG", + }, + issuer: { + id: "did:ethr:0xB26B4941941C51a4885E5B7D3A1B861E54405f90", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { identityProofType: "DNS-DID", identifier: "example.openattestation.com" }, + } as V4OpenAttestationDocument["issuer"], + }) + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "Input document does not conform to Open Attestation v4.0 Data Model: + { + "_errors": [], + "issuer": { + "_errors": [], + "type": { + "_errors": [ + "Invalid literal value, expected \\"OpenAttestationIssuer\\"" + ] + } + } + }" + `); + }); + + test("given a valid v4 document but has an extra field, should throw", async () => { + await expect( + wrapDocument({ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + + type: ["VerifiableCredential", "OpenAttestationCredential"], + credentialSubject: { + id: "0x1234567890123456789012345678901234567890", + name: "John Doe", + country: "SG", + }, + issuer: { + id: "did:ethr:0xB26B4941941C51a4885E5B7D3A1B861E54405f90", + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + extraField: "extra", + identityProof: { identityProofType: "DNS-DID", identifier: "example.openattestation.com" }, + }, + // this should not exist + extraField: "extra", + } as V4OpenAttestationDocument) + ).rejects.toThrowErrorMatchingInlineSnapshot(` + "Input document does not conform to Open Attestation v4.0 Data Model: + { + "_errors": [ + "Unrecognized key(s) in object: 'extraField'" + ] + }" + `); + }); + + test("given a generic w3c vc, should wrap with context and type corrected", async () => { + const genericW3cVc: W3cVerifiableCredential = { + "@context": ["https://www.w3.org/ns/credentials/v2"], + type: ["VerifiableCredential"], + credentialSubject: { + id: "0x1234567890123456789012345678901234567890", + name: "John Doe", + country: "SG", + }, + issuer: { + id: "https://example.com/issuer/123", + }, + }; + const wrapped = await wrapDocument(genericW3cVc as unknown as V4OpenAttestationDocument); + const parsedResults = V4WrappedDocument.pick({ "@context": true, type: true }).passthrough().safeParse(wrapped); + expect(parsedResults.success).toBe(true); + expect(wrapped.proof.merkleRoot.length).toBe(64); + expect(wrapped.proof.privacy.obfuscated).toEqual([]); + expect(wrapped.proof.proofPurpose).toBe("assertionMethod"); + expect(wrapped.proof.proofs).toEqual([]); + expect(wrapped.proof.salts.length).toBeGreaterThan(0); + expect(wrapped.proof.targetHash.length).toBe(64); + expect(wrapped.proof.type).toBe("OpenAttestationMerkleProofSignature2018"); + }); +}); diff --git a/src/4.0/computeDigestMultibase.ts b/src/4.0/computeDigestMultibase.ts new file mode 100644 index 00000000..18c02e0c --- /dev/null +++ b/src/4.0/computeDigestMultibase.ts @@ -0,0 +1,20 @@ +import { Sha256 } from "@aws-crypto/sha256-universal"; +import { base58 } from "ethers/lib/utils"; + +/** + * Computes a SHA-256 digest of the provided data and encodes it in Base58 with a 'z' prefix, + * conforming to the Multibase encoding standard. This function is intended for generating + * a multibase-encoded multihash, specifically using SHA-2 with 256-bits of output. + * The multibase value is fixed as 'z' to match the specifications. + * + * @param {ArrayBuffer|string} data - The data to hash. This can be either a string or an ArrayBuffer. + * @returns {Promise} A promise that resolves to the Base58 encoded SHA-256 hash of the input data, + * prefixed with 'z' as per the Multibase specification. + */ +export async function computeDigestMultibase(data: ArrayBuffer | string): Promise { + const sha256 = new Sha256(); + sha256.update(data); + const sha256Digest = await sha256.digest(); + // manually prefix with 'z' as per https://w3c-ccg.github.io/multibase/#mh-registry + return `z${base58.encode(sha256Digest)}`; +} diff --git a/src/4.0/context.ts b/src/4.0/context.ts new file mode 100644 index 00000000..196e72b4 --- /dev/null +++ b/src/4.0/context.ts @@ -0,0 +1,59 @@ +import { expand, Options, JsonLdDocument } from "jsonld"; +import { fetch } from "cross-fetch"; + +export const ContextUrl = { + v2_vc: "https://www.w3.org/ns/credentials/v2", + v4_alpha: "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", +} as const; + +export const ContextType = { + BaseContext: "VerifiableCredential", + V4AlphaContext: "OpenAttestationCredential", +} as const; + +const preloadedContextList = [ContextUrl.v2_vc, ContextUrl.v4_alpha]; +const contexts: Map = new Map(); + +// Preload frequently used contexts +// https://github.com/digitalbazaar/jsonld.js?tab=readme-ov-file#custom-document-loader +let isFirstLoad = true; +// FIXME: @types/json-ld seems to be outdated as callback is supposed to be options +const documentLoader: Options.DocLoader["documentLoader"] = async (url, _) => { + if (isFirstLoad) { + isFirstLoad = false; + for (const url of preloadedContextList) { + const document = await fetch(url).then((res) => res.json()); + contexts.set(url, document); + } + } + if (contexts.get(url)) { + return { + contextUrl: undefined, // this is for a context via a link header + document: contexts.get(url), // this is the actual document that was loaded + documentUrl: url, // this is the actual context URL after redirects + }; + } else { + const document = await fetch(url).then((res) => res.json()); + return { contextUrl: undefined, document, documentUrl: url }; + } +}; + +export const interpretContexts = async (input: JsonLdDocument) => { + const expanded = await expand(input, { documentLoader }).catch((e) => { + throw new UnableToInterpretContextError(JSON.stringify(e, null, 2)); + }); + + const type = (expanded[0]["@type"] as string[]) || []; + const unknownTypes = type.filter((t) => t.startsWith("https://www.w3.org/ns/credentials/issuer-dependent#")); // Workaround as expansionMap no longer supported + + if (unknownTypes.length > 0) { + throw new UnableToInterpretContextError(`Unknown types found: ${unknownTypes.map((t) => t.split("#")[1])}`); + } +}; + +export class UnableToInterpretContextError extends Error { + constructor(details: string) { + super(`Unable to interpret @context:\n${details}`); + Object.setPrototypeOf(this, UnableToInterpretContextError.prototype); + } +} diff --git a/src/4.0/diagnose.ts b/src/4.0/diagnose.ts new file mode 100644 index 00000000..0a17a8f3 --- /dev/null +++ b/src/4.0/diagnose.ts @@ -0,0 +1,30 @@ +import type { Diagnose } from "../shared/utils/@types/diagnose"; +import { V4WrappedDocument, V4SignedWrappedDocument, V4OpenAttestationDocument } from "./types"; + +export const v4Diagnose: Diagnose = ({ document, kind, debug }) => { + let Validator: typeof V4OpenAttestationDocument | typeof V4WrappedDocument | typeof V4SignedWrappedDocument = + V4OpenAttestationDocument; + if (kind === "raw") { + Validator = V4OpenAttestationDocument; + } else if (kind === "wrapped") { + Validator = V4WrappedDocument; + } else { + Validator = V4SignedWrappedDocument; + } + + const results = Validator.safeParse(document); + + if (results.success) { + return []; + } + + return results.error.errors.map(({ code, message, path }) => { + const errorMessage = `${code}: ${message} at ${path.join(".")}`; + if (debug) { + console.debug(errorMessage); + } + return { + message: errorMessage, + }; + }); +}; diff --git a/src/4.0/digest.ts b/src/4.0/digest.ts new file mode 100644 index 00000000..c2c85cb7 --- /dev/null +++ b/src/4.0/digest.ts @@ -0,0 +1,74 @@ +import { sortBy } from "lodash"; +import { keccak256 } from "js-sha3"; +import { W3cVerifiableCredential, Salt } from "./types"; +import { LeafValue, traverseAndFlatten } from "./traverseAndFlatten"; +import { hashToBuffer } from "../shared/utils/hashing"; + +export const digestCredential = (document: W3cVerifiableCredential, salts: Salt[], obfuscatedData: string[]) => { + // find all leaf nodes in the document and hash them + // proof is not part of the digest + const { proof: _, ...documentWithoutProof } = document; + const saltsMap = new Map(salts.map((salt) => [salt.path, salt.value])); + const isEmptyDocument = Object.keys(documentWithoutProof).length === 0; + const hashedLeafNodes = + // skip if document without proof is empty as it will treat the empty document as a leaf node + isEmptyDocument + ? [] + : traverseAndFlatten(documentWithoutProof, ({ value, path }) => { + const salt = saltsMap.get(path); + if (!salt) throw new SaltNotFoundError(path); + return hashLeafNode({ path, salt, value }); + }); + + // combine both array and sort them to ensure determinism + const combinedHashes = obfuscatedData.concat(hashedLeafNodes); + const sortedHashes = sortBy(combinedHashes); + + // finally, return the digest of the entire set of data + return keccak256(JSON.stringify(sortedHashes)); +}; + +type HashParams = { + salt: string; + value: LeafValue; + path: string; +}; +type HashOptions = { + toHexString: true; +}; +export function hashLeafNode({ path, salt, value }: HashParams, options?: HashOptions) { + const type = deriveType(value); + const hash = keccak256(JSON.stringify({ [path]: `${salt}:${type}:${value}` })); + return !options?.toHexString ? hash : hashToBuffer(hash).toString("hex"); +} + +export function deriveType(value: unknown): "string" | "number" | "boolean" | "null" | "object" | "array" { + if (Array.isArray(value)) { + return "array"; + } else if (value === null) { + return "null"; + } else { + switch (typeof value) { + case "string": + return "string"; + case "number": + return "number"; + case "object": + return "object"; + case "boolean": + return "boolean"; + default: + throw new Error(`Unsupported type ${typeof value}`); + } + } +} + +export class SaltNotFoundError extends Error { + constructor(public path: string) { + super(`Salt not found for ${path}`); + + // we shd consider changing the compilation target to >= es6 + // https://www.dannyguo.com/blog/how-to-fix-instanceof-not-working-for-custom-errors-in-typescript + Object.setPrototypeOf(this, SaltNotFoundError.prototype); + } +} diff --git a/src/4.0/documentBuilder.ts b/src/4.0/documentBuilder.ts new file mode 100644 index 00000000..0fa8d348 --- /dev/null +++ b/src/4.0/documentBuilder.ts @@ -0,0 +1,469 @@ +import { wrapDocument, wrapDocuments, wrapDocumentErrors } from "./wrap"; +import { signDocument, signDocumentErrors } from "./sign"; +import { + Override, + DecentralisedEmbeddedRenderer, + SvgRenderer, + OscpResponderRevocation, + RevocationStoreRevocation, + V4OpenAttestationDocument, + V4SignedWrappedDocument, + V4WrappedDocument, +} from "./types"; + +import { ZodError, z } from "zod"; + +const SingleDocumentProps = z.object({ + name: V4OpenAttestationDocument.shape.name.unwrap(), + credentialSubject: V4OpenAttestationDocument.shape.credentialSubject, +}); + +const DocumentProps = z.union([SingleDocumentProps, z.array(SingleDocumentProps)]); + +const OscpRevocationProps = z.object({ + oscpUrl: OscpResponderRevocation.shape.id, +}); + +const RevocationStoreRevocationProps = z.object({ + storeAddress: RevocationStoreRevocation.shape.id, +}); + +const EmbeddedRendererProps = z.object({ + rendererUrl: DecentralisedEmbeddedRenderer.shape.id, + templateName: DecentralisedEmbeddedRenderer.shape.templateName, +}); + +const SvgRendererProps = z.discriminatedUnion("type", [ + z.object({ + type: z.literal("REMOTE"), + svgUrl: z.string().url(), + digestMultibase: SvgRenderer.shape.digestMultibase.optional(), + }), + z.object({ + type: z.literal("EMBEDDED"), + svgTemplate: z.string(), + }), +]); + +const DnsTextIssuanceProps = z.object({ + issuerId: V4OpenAttestationDocument.shape.issuer.shape.id, + issuerName: V4OpenAttestationDocument.shape.issuer.shape.name, + identityProofDomain: V4OpenAttestationDocument.shape.issuer.shape.identityProof.shape.identifier, +}); + +/** + * Validation errors within properties. + */ +class PropsValidationError extends Error { + constructor(public error: ZodError) { + super(`Invalid props: \n ${JSON.stringify(error.format(), null, 2)}`); + Object.setPrototypeOf(this, PropsValidationError.prototype); + } +} + +/** + * Error to indicate that modifications to set properties are not allowed. + */ +class ShouldNotModifyAfterSettingError extends Error { + constructor() { + super("Modifying what was already set can lead to unexpected behaviour, please consider creating a new instance"); + Object.setPrototypeOf(this, ShouldNotModifyAfterSettingError.prototype); + } +} + +type DocumentProps = { + /** + * Human readable name of the document. + * + * Maps to "name" + */ + name: string; + /** + * Main content of the document. + * + * Maps to "credentialSubject" + */ + credentialSubject: z.infer; +}; + +type State = { + documentMainProps: DocumentProps | DocumentProps[]; + renderMethod: V4OpenAttestationDocument["renderMethod"]; + issuer: V4OpenAttestationDocument["issuer"] | undefined; + credentialStatus: V4OpenAttestationDocument["credentialStatus"]; +}; + +/** + * A builder class to facilitate the creation of OpenAttestation v4 documents. + * Assumes a shared issuer, render method, and credential status across all documents in batch mode. + * For use cases requiring direct control, consider using the lower-level wrap and sign functions. + */ +export class DocumentBuilder { + private getState: () => State; + private setState: (key: Key, value: Pick[Key]) => void; + constructor(props: Props) { + const parsedResults = DocumentProps.safeParse(props); + if (!parsedResults.success) throw new PropsValidationError(parsedResults.error); + + // define state here rather than in the instance to enforce immutability via setState. + const state: State = { + documentMainProps: parsedResults.data, + renderMethod: undefined, + issuer: undefined, + credentialStatus: undefined, + }; + + const hasBeenSet = new Set(); + this.getState = () => state; + this.setState = (key, value) => { + if (hasBeenSet.has(key)) throw new ShouldNotModifyAfterSettingError(); + hasBeenSet.add(key); + state[key] = value; + }; + } + + private wrap = async (): Promise> => { + const { documentMainProps: data, issuer, renderMethod, credentialStatus } = this.getState(); + + // this should never happen + if (!issuer) throw new Error("Issuer is required"); + if (Array.isArray(data)) { + const toWrap = data.map( + ({ name, credentialSubject }) => + ({ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + type: ["VerifiableCredential", "OpenAttestationCredential"], + issuer, + name, + credentialSubject, + ...(renderMethod && { renderMethod }), + ...(credentialStatus && { credentialStatus }), + } satisfies V4OpenAttestationDocument) + ); + + return wrapDocuments(toWrap) as unknown as WrappedReturn; + } + + // this should never happen + if (!data) throw new Error("CredentialSubject is required"); + + const { name, credentialSubject } = data; + return wrapDocument({ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + type: ["VerifiableCredential", "OpenAttestationCredential"], + issuer, + name, + credentialSubject, + ...(renderMethod && { renderMethod }), + ...(credentialStatus && { credentialStatus }), + }) as unknown as WrappedReturn; + }; + + private sign = async (props: { signer: Parameters[2] }): Promise> => { + const wrapped = await this.wrap(); + if (Array.isArray(wrapped)) { + return Promise.all(wrapped.map((d) => signDocument(d, "Secp256k1VerificationKey2018", props.signer))) as Promise< + SignedReturn + >; + } + + return signDocument(wrapped, "Secp256k1VerificationKey2018", props.signer) as Promise>; + }; + + // add issuance methods here + private ISSUANCE_METHODS = { + // not supported right now + // blockchainIssuance: (props: { + // /** A unique ID of the issuer that MUST BE in a URI */ + // issuerId: string; + // issuerName: string; + // /** should be in the form of "did:ethr:0x${string}#controller" */ + // ethDid: string; + // /** */ + // identityProofDomain: string; + // }) => { + // this.issuer = { + // id: props.issuerId, + // name: props.issuerName, + // type: "OpenAttestationIssuer", + // identityProof: { + // identityProofType: "DNS-DID", + // identifier: props.ethDid, + // }, + // }; + // return { + // wrap: this.wrap, + // }; + // }, + + /** + * The document will be digitally signed, and identity proof will be provided via a DNS-TXT record. + * + * Sets "issuer.type" to "OpenAttestationIssuer" and "issuer.identityProof.identityProofType" to "DNS-TXT" + */ + dnsTxtIssuance: (props: { + /** + * The unique identifier for the issuer, which must be formatted as a URI. + * + * Maps to "issuer.id" + */ + issuerId: string; + /** + * The issuer's name in a human-readable format. + * + * Maps to "issuer.name" + */ + issuerName: string; + /** + * The domain where the DNS TXT record, used for identity proof, is located. + * + * Maps to "issuer.identityProof.identifier" + */ + identityProofDomain: string; + }) => { + const parsedResults = DnsTextIssuanceProps.safeParse(props); + if (!parsedResults.success) throw new PropsValidationError(parsedResults.error); + const { issuerId, issuerName, identityProofDomain } = parsedResults.data; + + const issuer = { + id: issuerId, + name: issuerName, + type: "OpenAttestationIssuer", + identityProof: { + identityProofType: "DNS-TXT", + identifier: identityProofDomain, + }, + } satisfies V4OpenAttestationDocument["issuer"]; + this.setState("issuer", issuer); + + return { + /** + * Wraps and signs the entire batch in a single operation. This method does not use internal batching logic, + * which could lead to too many concurrent remote calls when signing large batches. Use this function with caution in such scenarios. + */ + wrapAndSign: this.sign, + /** + * Provides an option to wrap documents without signing them, allowing for more control over the signing process. + * This is particularly useful when you need to sign documents in smaller batches or at different stages. + */ + justWrapWithoutSigning: this.wrap, + }; + }, + } satisfies Record<`${string}Issuance`, (...args: any[]) => any>; + + // add revocation methods here + private REVOCATION_METHODS = { + /** + * The document(s) will be issued without the capability for revocation; they remain valid indefinitely. + */ + noRevocation: () => { + this.setState("credentialStatus", undefined); + + return this.ISSUANCE_METHODS; + }, + /** + * The document(s) can be revoked using an OCSP responder, allowing for the verification of the revocation status through the specified URL. + * + * Sets "credentialStatus.type" to "OpenAttestationOcspResponder" + */ + oscpRevocation: (props: { + /** + * URL of the OCSP responder. + * + * Maps to "credentialStatus.id" + */ + oscpUrl: string; + }) => { + const parsedResults = OscpRevocationProps.safeParse(props); + if (!parsedResults.success) throw new PropsValidationError(parsedResults.error); + const { oscpUrl } = parsedResults.data; + + const credentialStatus = { + id: oscpUrl, + type: "OpenAttestationOcspResponder", + } satisfies V4OpenAttestationDocument["credentialStatus"]; + this.setState("credentialStatus", credentialStatus); + + return this.ISSUANCE_METHODS; + }, + /** + * The document(s) can be revoked using a revocation store, implemented as a smart contract on the Ethereum blockchain. + * + * Sets "credentialStatus.type" to "OpenAttestationRevocationStore" + */ + revocationStoreRevocation: (props: { + /** + * The Ethereum smart contract address to the revocation store. + * + * Maps to "credentialStatus.id" + */ + storeAddress: string; + }) => { + const parsedResults = RevocationStoreRevocationProps.safeParse(props); + if (!parsedResults.success) throw new PropsValidationError(parsedResults.error); + const { storeAddress } = parsedResults.data; + + const credentialStatus = { + id: storeAddress, + type: "OpenAttestationRevocationStore", + } satisfies V4OpenAttestationDocument["credentialStatus"]; + + this.setState("credentialStatus", credentialStatus); + + return this.ISSUANCE_METHODS; + }, + } satisfies Record<`${string}Revocation`, (...args: any[]) => typeof this.ISSUANCE_METHODS>; + + /** + * Configures the document to be rendered using OpenAttestation's decentralized React components, + * see (https://github.com/Open-Attestation/decentralized-renderer-react-components). + * + * Sets "renderMethod[0].type" to "OpenAttestationEmbeddedRenderer" + */ + public embeddedRenderer = (props: { + /** + * The URL where the decentralized renderer is hosted. + * + * Maps to "renderMethod[0].id" + */ + rendererUrl: string; + /** + * The identifier for the template used by the renderer to display the document correctly. + * + * Maps to "renderMethod[0].templateName" + */ + templateName: string; + }) => { + const parsedResults = EmbeddedRendererProps.safeParse(props); + if (!parsedResults.success) throw new PropsValidationError(parsedResults.error); + const { rendererUrl, templateName } = parsedResults.data; + + const renderMethod = [ + { + id: rendererUrl, + type: "OpenAttestationEmbeddedRenderer", + templateName, + }, + ] satisfies V4OpenAttestationDocument["renderMethod"]; + this.setState("renderMethod", renderMethod); + + return this.REVOCATION_METHODS; + }; + + /** + * Renders the document using an SVG handlebar template, either embedded directly or hosted remotely. + * The root object of the handlebar template corresponds to the credentialSubject of the document. + * For instance, if the document credentialSubject is { name: "John Doe" }, + * the handlebar template should reference the name as {{name}} to correctly map data fields. + * + * Sets "renderMethod[0].type" to "SvgRenderingTemplate2023" + */ + public svgRenderer = ( + props: + | { + type: "REMOTE"; + /** + * A URL that dereferences to an SVG handlebar template with an associated image/svg+xml media type. + * + * Maps to "renderMethod[0].id" + */ + svgUrl: string; + /** + * An optional multibase-encoded multihash of the SVG image. The multibase value MUST be z and the multihash value MUST be SHA-2 with 256-bits of output (0x12). + * + * Maps to "renderMethod[0].digestMultibase" + */ + digestMultibase?: string; + } + | { + type: "EMBEDDED"; + /** + * Directly provided SVG handlebar template content. + * + * Maps to "renderMethod[0].id" + */ + svgTemplate: string; + } + ) => { + const parsedResults = SvgRendererProps.safeParse(props); + if (!parsedResults.success) throw new PropsValidationError(parsedResults.error); + + const renderMethod = + parsedResults.data.type === "EMBEDDED" + ? [ + { + id: parsedResults.data.svgTemplate, + type: "SvgRenderingTemplate2023" as const, + }, + ] + : ([ + { + id: parsedResults.data.svgUrl, + type: "SvgRenderingTemplate2023" as const, + digestMultibase: parsedResults.data.digestMultibase, + }, + ] satisfies V4OpenAttestationDocument["renderMethod"]); + this.setState("renderMethod", renderMethod); + + return this.REVOCATION_METHODS; + }; + + /** + * Disables rendering for the document. + */ + public noRenderer = () => { + this.setState("renderMethod", undefined); + return this.REVOCATION_METHODS; + }; +} + +type SignedReturn = Props extends Array + ? Override< + V4SignedWrappedDocument, + { + name: Props[number]["name"]; + credentialSubject: Props[number]["credentialSubject"]; + } + >[] + : Props extends DocumentProps + ? Override< + V4SignedWrappedDocument, + { + name: Props["name"]; + credentialSubject: Props["credentialSubject"]; + } + > + : never; + +type WrappedReturn = Props extends Array + ? Override< + V4WrappedDocument, + { + name: Props[number]["name"]; + credentialSubject: Props[number]["credentialSubject"]; + } + >[] + : Props extends DocumentProps + ? Override< + V4WrappedDocument, + { + name: Props["name"]; + credentialSubject: Props["credentialSubject"]; + } + > + : never; + +const { UnableToInterpretContextError } = wrapDocumentErrors; +const { CouldNotSignDocumentError } = signDocumentErrors; +export const DocumentBuilderErrors = { + PropsValidationError, + ShouldNotModifyAfterSettingError, + UnableToInterpretContextError, + CouldNotSignDocumentError, +}; diff --git a/src/4.0/exports/builder.ts b/src/4.0/exports/builder.ts new file mode 100644 index 00000000..9d129cf1 --- /dev/null +++ b/src/4.0/exports/builder.ts @@ -0,0 +1 @@ +export { DocumentBuilder, DocumentBuilderErrors } from "../documentBuilder"; diff --git a/src/4.0/exports/index.ts b/src/4.0/exports/index.ts new file mode 100644 index 00000000..40d37afe --- /dev/null +++ b/src/4.0/exports/index.ts @@ -0,0 +1,7 @@ +export * from "./wrap"; +export * from "./sign"; +export * from "./obfuscate"; +export * from "./verify"; +export * from "./utils"; +export * from "./types"; +export * from "./builder"; diff --git a/src/4.0/exports/obfuscate.ts b/src/4.0/exports/obfuscate.ts new file mode 100644 index 00000000..98fe058f --- /dev/null +++ b/src/4.0/exports/obfuscate.ts @@ -0,0 +1 @@ +export { obfuscateVerifiableCredential as obfuscate, obfuscateErrors } from "../obfuscate"; diff --git a/src/4.0/exports/sign.ts b/src/4.0/exports/sign.ts new file mode 100644 index 00000000..d313eb7b --- /dev/null +++ b/src/4.0/exports/sign.ts @@ -0,0 +1 @@ +export { signDocument, signDocumentErrors } from "../sign"; diff --git a/src/4.0/exports/types.ts b/src/4.0/exports/types.ts new file mode 100644 index 00000000..70c99577 --- /dev/null +++ b/src/4.0/exports/types.ts @@ -0,0 +1,5 @@ +export type { + V4OpenAttestationDocument as OpenAttestationDocument, + V4WrappedDocument as WrappedDocument, + V4SignedWrappedDocument as SignedWrappedDocument, +} from "../types"; diff --git a/src/4.0/exports/utils.ts b/src/4.0/exports/utils.ts new file mode 100644 index 00000000..9e28fa7a --- /dev/null +++ b/src/4.0/exports/utils.ts @@ -0,0 +1,7 @@ +export { v4Diagnose as diagnose } from "../diagnose"; +export { + isV4OpenAttestationDocument as isOpenAttestationDocument, + isV4WrappedDocument as isWrappedDocument, + isV4SignedWrappedDocument as isSignedWrappedDocument, +} from "../types"; +export { computeDigestMultibase } from "../computeDigestMultibase"; diff --git a/src/4.0/exports/verify.ts b/src/4.0/exports/verify.ts new file mode 100644 index 00000000..28c88f93 --- /dev/null +++ b/src/4.0/exports/verify.ts @@ -0,0 +1 @@ +export { verify as verifySignature } from "../verify"; diff --git a/src/4.0/exports/wrap.ts b/src/4.0/exports/wrap.ts new file mode 100644 index 00000000..ce57c015 --- /dev/null +++ b/src/4.0/exports/wrap.ts @@ -0,0 +1 @@ +export { wrapDocument, wrapDocuments, wrapDocumentErrors } from "../wrap"; diff --git a/src/4.0/fixtures.ts b/src/4.0/fixtures.ts new file mode 100644 index 00000000..17d2082f --- /dev/null +++ b/src/4.0/fixtures.ts @@ -0,0 +1,695 @@ +import { V4OpenAttestationDocument, V4SignedWrappedDocument, V4WrappedDocument } from "./types"; + +const ISSUER_ID = "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89" as const; +export const SAMPLE_SIGNING_KEYS = { + public: `${ISSUER_ID}#controller`, + private: "0x497c85ed89f1874ba37532d1e33519aba15bd533cdcb90774cc497bfe3cde655", +} as const; + +export const RAW_DOCUMENT_DID = freezeObject({ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + type: ["VerifiableCredential", "OpenAttestationCredential"], + validFrom: "2021-03-08T12:00:00+08:00", + name: "Republic of Singapore Driving Licence", + issuer: { + id: ISSUER_ID, + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { identityProofType: "DNS-DID", identifier: "example.openattestation.com" }, + }, + renderMethod: [ + { + id: "https://demo-renderer.opencerts.io", + type: "OpenAttestationEmbeddedRenderer", + templateName: "GOVTECH_DEMO", + }, + ], + credentialSubject: { + id: "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + type: ["DriversLicense"], + name: "John Doe", + licenses: [ + { + class: "3", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + { + class: "3A", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + ], + }, +} satisfies V4OpenAttestationDocument); + +export const RAW_DOCUMENT_DID_OSCP = freezeObject({ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + type: ["VerifiableCredential", "OpenAttestationCredential"], + validFrom: "2021-03-08T12:00:00+08:00", + name: "Republic of Singapore Driving Licence", + issuer: { + id: ISSUER_ID, + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { identityProofType: "DNS-DID", identifier: "example.openattestation.com" }, + }, + credentialStatus: { + id: "https://ocsp-sandbox.openattestation.com", + type: "OpenAttestationOcspResponder", + }, + renderMethod: [ + { + id: "https://demo-renderer.opencerts.io", + type: "OpenAttestationEmbeddedRenderer", + templateName: "GOVTECH_DEMO", + }, + ], + credentialSubject: { + id: "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + type: ["DriversLicense"], + name: "John Doe", + licenses: [ + { + class: "3", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + { + class: "3A", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + ], + }, +} satisfies V4OpenAttestationDocument); + +export const BATCHED_RAW_DOCUMENTS_DID = freezeObject([ + { + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + name: "Republic of Singapore Driving Licence", + type: ["VerifiableCredential", "OpenAttestationCredential"], + issuer: { + id: ISSUER_ID, + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { + identityProofType: "DNS-DID", + identifier: "example.openattestation.com", + }, + }, + validFrom: "2021-03-08T12:00:00+08:00", + credentialSubject: { + id: "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + type: ["DriversLicense"], + name: "John Doe", + licenses: [ + { + class: "3", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + { + class: "3A", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + ], + }, + renderMethod: [ + { + id: "https://demo-renderer.opencerts.io", + type: "OpenAttestationEmbeddedRenderer", + templateName: "GOVTECH_DEMO", + }, + ], + }, + { + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + name: "Republic of Singapore Driving Licence", + type: ["VerifiableCredential", "OpenAttestationCredential"], + issuer: { + id: ISSUER_ID, + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { + identityProofType: "DNS-DID", + identifier: "example.openattestation.com", + }, + }, + validFrom: "2021-03-08T12:00:00+08:00", + credentialSubject: { + id: "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + type: ["DriversLicense"], + name: "Jane Doe", + licenses: [ + { + class: "3000A", + description: "Motor spaceships with unladen weight <= 3000tonnes", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + ], + }, + renderMethod: [ + { + id: "https://demo-renderer.opencerts.io", + type: "OpenAttestationEmbeddedRenderer", + templateName: "GOVTECH_DEMO", + }, + ], + }, +] satisfies V4OpenAttestationDocument[]); + +export const WRAPPED_DOCUMENT_DID = freezeObject({ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + name: "Republic of Singapore Driving Licence", + type: ["VerifiableCredential", "OpenAttestationCredential"], + issuer: { + id: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { + identityProofType: "DNS-DID", + identifier: "example.openattestation.com", + }, + }, + validFrom: "2021-03-08T12:00:00+08:00", + credentialSubject: { + id: "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + type: ["DriversLicense"], + name: "John Doe", + licenses: [ + { + class: "3", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + { + class: "3A", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + ], + }, + renderMethod: [ + { + id: "https://demo-renderer.opencerts.io", + type: "OpenAttestationEmbeddedRenderer", + templateName: "GOVTECH_DEMO", + }, + ], + proof: { + type: "OpenAttestationMerkleProofSignature2018", + proofPurpose: "assertionMethod", + targetHash: "dd55a7d96d47e58350f2cfb03ebdf3f859684c9f97ba75eed55b1bdcc761c5aa", + proofs: [], + merkleRoot: "dd55a7d96d47e58350f2cfb03ebdf3f859684c9f97ba75eed55b1bdcc761c5aa", + salts: + "W3sidmFsdWUiOiJjYTE3MjI0YTg3NTk0NzNhNGUyZjM2YTM3NjljODU0OGM5M2RjZTQ3NmI0MjEwMTNmYTEzYTA2OTUxYTI1YzhjIiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6IjMyYzk3MDRhMmIxMWU1MzhjYTBlZWJhYWMzNmU0ZmRlYTU4ZGY0MDI4ZGVmZmJjOTkzODBjYjZkZjU3MTdiODEiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiNDE3YTFhNzY2YWM5MzhkOWVlY2FhNWRmMDdhOTBhODkyZTM3ZjA1ZmI3MzY5ZWRjNGQwYWNmNWZkMjE4YjhlMiIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6ImE1Y2FkZDIzMmQ4ZjhlMGU4ZmFhODA3OTMyYWNkZjJhODc1OWY4MWEyMDNmNmEwMjdjMTJhOTBhNjg0MWE1NWYiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiI2NGE4NjBmMmQwOGZjNGIyMDhjZWE3NmU2MjBjM2YwMDRlYzhiMmRhYjdhZTc5ZTZkZmMxZjllYjU1MWMxMmM3IiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiMzcyZmJlNDllMTdjMTA2MGEzNTk1NjVhNDA2M2VlMjkyODU1ODg0OWZhZWRkODE1MGQwYWZjZmY3NzQ2M2NmMyIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiYTE0ODAwOGQxY2JjMzM3ODJmNmNlN2UyOTFhMTM5ODE1YmRhYWFjZjg2MWYxNGYwMDk0NWU5YWIwZTk2ZjdkNiIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiI5Yzg4NTc4ZTAzZWRiNjc3NTdiNDI0NzY4MTliNWZiMGQwMDlhMGU0ZjZmMjllOGNhNTBlMWJmNWI4NWQ2ZmZiIiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6ImJhOTk1NDA1YWQ4ZmZlZmJmYTExMDA2MzE2ZDdkNjM4NDRlODk2ZmMxNDhkZjdlMWViZjNkYWZhYzI0NTY4YjQiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiZWY1ZTEzODU4YWM1MzYwNTMzODkxZjkxOGJhYjlmZjI3YmQ5YjhiYzA5MzQ4ZTc4NWMwMmI2YjYzZTcxZDNhYSIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6ImY2N2ZmNGMyZTUwYzU0M2ZmYmEyNGJiMzA4OTY5NGUxOWViZDNjOWJhMmE5MTM3NTA3N2YzOWRlN2M0ODVmY2MiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6ImIyYzQ2MjkwMDQwMDMwOGM1YjA3MmM1Y2NlMjQ4YmQ2YjRiOTgxODBjOGQ2ZDQ2YjIwNWE0MGE2YzNjMDhmMzciLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiM2QwMThlMjllOTI3MTcxN2UwNGI5ZWYwMDJkNWVmNTRmMTRiZmI3NmJlYzdhMTlkN2ZlYjcyMzM3NjU2NzU4ZiIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6ImYxNDllNmM5M2ZhNTU5ZjM4OWRjZTcwMDMwYmRmYmVlNmU3OWRjODM1NjJhYmVhN2FkOTMzNTA0OWM4MTI5NGQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiIyZGZjM2VmNDQ2NzA0MmMzMDI4NDU0MTNmMWE5MDQxYmQ2NjY3NThmNDM4MWU4OWU5NWIzZjc4NjYyYzE1NTc5IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6IjY3MjNhYjA4MzhkODMzNTJlMjhhNjQxMjliMzEwOWQzNzA5YTk3NWYyMDljZmM2NjE0MTNmODUyYzFmZTY0YzYiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiMWZiNTRmMGVhZDgyZmEyMzVlMmU5Y2RkY2ViMGQ2NTllMjRhYzhhMzM4OThmODdmMzkzZTBmZmY5OTE1Y2NmZSIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6IjhjMzJlZmNlOGE2ZTIzZGMxNzUzOTVmNzMxM2ZjMGQ4ZTk0ZTA0YjU3ZGMwMzI4YmEyNTk0NTgxMTJjNWQ4MjQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMV0uY2xhc3MifSx7InZhbHVlIjoiYmQ1YzM2Yjc1YTVmNzEwYmQ2MzJhOWM1MTY1ZGVkNmI4N2YzODY1MTg5YWRjZTc3M2FlNDMxMTlkYzljMGFiNCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1sxXS5kZXNjcmlwdGlvbiJ9LHsidmFsdWUiOiI1MmYzYTU1ZWI3MGZmZjMyYjEzZWMyNjlkZjJmODM4Mjg4NTc5YmUyMDg1NmQ3Mjc5NmI3YmY3MDFmMjY5MjU3IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzFdLmVmZmVjdGl2ZURhdGUifSx7InZhbHVlIjoiZTJjZWZiMjkzZGEzZGNmNTIzZjAwNjkwN2YyNTljNTIyOTc3MzQwZjYzNmY4YmU1MmM5ZTg5ZTEzZGVlZTk0MiIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0uaWQifSx7InZhbHVlIjoiNDNiMjFkZGU2NTY2NjI5MTNjNzJiMDExMzBkMjM0MzlkY2NjMTNiZjVhYjYwMjY5YTVmYjM3NmFlMzBkNjlkMiIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udHlwZSJ9LHsidmFsdWUiOiI0NDRmZmU3OTMzMmRkZjExOWRiZWUzZjYzYWQyZTQyYzE2ZTczMDdkMGVmOTE3NDJlZDEzNTkxYWY5M2U0NWRjIiwicGF0aCI6InJlbmRlck1ldGhvZFswXS50ZW1wbGF0ZU5hbWUifV0=", + privacy: { + obfuscated: [], + }, + }, +} satisfies V4WrappedDocument); + +export const WRAPPED_DOCUMENT_DID_OSCP = freezeObject({ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + name: "Republic of Singapore Driving Licence", + type: ["VerifiableCredential", "OpenAttestationCredential"], + issuer: { + id: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { + identityProofType: "DNS-DID", + identifier: "example.openattestation.com", + }, + }, + validFrom: "2021-03-08T12:00:00+08:00", + credentialSubject: { + id: "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + type: ["DriversLicense"], + name: "John Doe", + licenses: [ + { + class: "3", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + { + class: "3A", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + ], + }, + credentialStatus: { + id: "https://ocsp-sandbox.openattestation.com", + type: "OpenAttestationOcspResponder", + }, + renderMethod: [ + { + id: "https://demo-renderer.opencerts.io", + type: "OpenAttestationEmbeddedRenderer", + templateName: "GOVTECH_DEMO", + }, + ], + proof: { + type: "OpenAttestationMerkleProofSignature2018", + proofPurpose: "assertionMethod", + targetHash: "96a8e79b4c9b14dde88d9d6db26916215502ed09f458d0dc387c1ca73f3549f0", + proofs: [], + merkleRoot: "96a8e79b4c9b14dde88d9d6db26916215502ed09f458d0dc387c1ca73f3549f0", + salts: + "W3sidmFsdWUiOiI2ZGM0NzZkYmZlOTBiMjMxYzg5MjFiYmIyNTg3NTFkZGJlNzExMGFhOGM2Y2U3ODQwOGZiNmFhMDBiYzI3NTZjIiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6ImY3MTA2OTA3YzJhMDRjNzRiOWYyMzg2Yjg3MGJhMmE1MmYxMmFiZDA1Y2FiOGUyOGFhOTdhZWJhYTk1ZTRhMjAiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiNGEyNzhiYmM0MTllYTY4YTRlN2M1Y2YxMDdmZDUxNWNkNDgwYmNhNDZlZjdjNjQ1NGFiMjQwZWRmY2JjODM4NyIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6IjVhNDQyMTE0M2YxNGZjYmY4MTdhMjgwMWJhOTUzZDY1ZWQ2NDUxNDE5YTkzY2VkM2Y2MWY1NzcxNjI0YzA3MzUiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiJiY2M1OGMwZTU3NjgzYmM3NDA2NjM5ZWMwYzI3MjIxMGYzZmQzMGVkYmQ4ZjU5MjM2MjBiMzgxNzYyM2U4YWEwIiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiYzUxYWJlZGE2MTNjNGZiMDY5ZDQ2MzNhMTcwNzIyYWE2YmRiMGFlZDkzOTAzZjRiMmJjZTAyZjU1NWZiNDY5OSIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiM2U3MjVhNzk1YzZmNDQyNDc5NzZkNWUzNGQ3M2YyMzA4ZTEyNjc3MzNjODY1YWNjYTUwYTc1ODVmNDIwNDI4ZSIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiJkY2QyMzM5MTVmODVkMjIzNzFlNWFkMzc2Y2I3M2ZkNGVkODcxNzVjNWUzYTgxYjhiMjhmNWE1ZDA3NDllMzdkIiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6IjJlY2MyOGVmZDNjNTU5ZmU5MGNiYTg2NDQ4MmM3YTk0YmU5NTRhNzY4NWY2ZmI5ZGQ5MDJiZTUwMDE5OTRjMzgiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiOTI3ZDM1ZDUzZTE3MThkMWE3ZWM2NDFkMzFmYmU4OThiMGI5YzkyZGRhZmMwMmU4MGU5NjgwMThlNmUyZTgyNCIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6IjI3OTVkNzgxODY2ZjNmYTI4YThhMzIxMmI4ODdjMGNjMzkyMWM2Njc2NmIxZDJmZDdkYjY1NzBhMGM1Y2ExZTEiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6IjA2ZmViZjYyNTZhY2FlMWIyZjg5MTE0MjM2NzY2YjNkMzIzZDMwNzQzZGJiZDRmODI0NWU1NjA5MTRhZjcwZmQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiNjBkY2E2Njg3MGNmNzMxZDkwNjcwZTA5YTg2MDA2ZTJlNjRjYzRiZGQ3ZWYyYTQyZjMwYWUwY2M4N2Q3ZmY3MSIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6IjdhMjBiMmMwMTk3MDE0YjA5OWY2MDg4NGM4YjA1NWMzYmIxNjY3YzRiZWRiMjIzMDY4NGI2YTMxZjY1ZjQ4ZTgiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiJiYzRiMGJiODkzZTIxNGYyMzlkZmQ4ZGY2MGQ1ZDdkZjZmNzBjNjI4N2YzNmQ3ZWVlZGVhMjE1NDMzNjE5ODA2IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6ImY4N2ZhNjNmMDY1MmY2NzJjYjkyOWI2YzFiYWMwOGFmOTNiZjc5NTgwOWYzMjlmZmEyYmJlMmE1NGJmOThiODEiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiYzc4MDE5Njk4NWEzNDFjYzJkZmQwMzA0YTdhOTUzZGFkZGE2MmZhYjhlOGYyZTFlZWViNGNlZDM3YTIwZDJiMyIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6Ijc0Y2ZmNjIxZDhhZTM2YmQxNWFlMzFkZTIwMTE1Mzg1MDZmNDhlMjkxNjExYmM3ZmIzNjVkYjNkMTI3ZGYxYzYiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMV0uY2xhc3MifSx7InZhbHVlIjoiZDg2ZGQ0ZjNkNDA1N2FiN2I3NzI2ZWU0ZmE5Y2U1NjlkZTc3YmZiNGNhNzBmYTY5NzVlNWZjOWEwOTAwZjdkNCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1sxXS5kZXNjcmlwdGlvbiJ9LHsidmFsdWUiOiI4ZDhmZTQ3MGY3NmEyODNkNzQ1ZmM4MGYwZjEyZmZjOGU5ZjU3OGE5NjY5NDRkODBmOTM2MDhjNWZjOTM4ZTAzIiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzFdLmVmZmVjdGl2ZURhdGUifSx7InZhbHVlIjoiNjkwOGFlOTBiYTI0YzZjNmRhZDcxZmEzZmQxNGJiYWYxNTMyOGJhZDliN2Y0NDI5Y2IzN2Q5YjIyYWM4MzRjNCIsInBhdGgiOiJjcmVkZW50aWFsU3RhdHVzLmlkIn0seyJ2YWx1ZSI6IjM2MDU1ODQzZWU1MTNkZDVlYmY5MjUzMTM5ZTI0YjkxZWM5MDk4NzI1Y2ZhZDQzYmE3ODkxNWRiMGFhODJjYTEiLCJwYXRoIjoiY3JlZGVudGlhbFN0YXR1cy50eXBlIn0seyJ2YWx1ZSI6IjQzMjJhMDA0NzNjYzIzNWVmNzFkYWNiMDFlNjcwMGNkZWE1YjUxNWIzNzM2MDY0ZWU0NzJhNjM4ZWFmYjUxNzMiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLmlkIn0seyJ2YWx1ZSI6IjRmNTJjZTRjN2JmNTQxMWNhMGFhOTJhZWY1YWE5NWQyNDYwOThhZmE5N2Q2YWI0YTMwY2JkYTBhNzM5ZTg0ODAiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLnR5cGUifSx7InZhbHVlIjoiMzM3YTkyODViYjFkYzgyYzYyMTFhMTBhMDA5ODkxOTNjMzQyZjczMDFiZTYwZjEzY2E4M2IzYWMxMTQ2MDkzMyIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udGVtcGxhdGVOYW1lIn1d", + privacy: { + obfuscated: [], + }, + }, +} satisfies V4WrappedDocument); + +export const BATCHED_WRAPPED_DOCUMENTS_DID = freezeObject([ + { + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + name: "Republic of Singapore Driving Licence", + type: ["VerifiableCredential", "OpenAttestationCredential"], + issuer: { + id: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { + identityProofType: "DNS-DID", + identifier: "example.openattestation.com", + }, + }, + validFrom: "2021-03-08T12:00:00+08:00", + credentialSubject: { + id: "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + type: ["DriversLicense"], + name: "John Doe", + licenses: [ + { + class: "3", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + { + class: "3A", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + ], + }, + renderMethod: [ + { + id: "https://demo-renderer.opencerts.io", + type: "OpenAttestationEmbeddedRenderer", + templateName: "GOVTECH_DEMO", + }, + ], + proof: { + type: "OpenAttestationMerkleProofSignature2018", + proofPurpose: "assertionMethod", + targetHash: "b449f7fb56ed2961749110037a1c40464548db71c386c925e58211505785e6ce", + proofs: ["9d71ec0572df22c133656a45bd644a7e6bb1f44cb4670473263d7f2b6f2d4b04"], + merkleRoot: "2e8038ad3403396fad4af3158f132c06d34fd31516b328b07001bc44f48fbeff", + salts: + "W3sidmFsdWUiOiIwMmFjZWRiYmRlZTcwMTQwOTA1MjgxN2ZmNDRlNzE3YzMyNTM0MDEyNjM4NzQyYTE1MzEyMjJkNWRhNTMyZDUyIiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6IjMwZDlmZDBkOWU2ZTc1YTg5ZTYwM2JkZjE3YWZjYzY1NDgzYzIxOWNkMTZiYjJhNmZjOTdhNjI3MjNjZTczNDciLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiZjQxY2JlNzMyMjVjMDI3YjY0ZmQzMDhlMTMxY2FmMTZkYjVkYTNiNTM1ZDE0NDQ0NThmYjk5NDUwMWU0NGU4MCIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6IjE3OTU1NzVkZjZkYzZmOTg4NzFmMDk2M2I3MTdkZDg2ZmU4MmQzMjg1NzliMGYyNDhlMDIzMDE4ZTU4NjVlMmIiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiI1MTFhZTZjMzA3NzNlZDhkMWUyZmYwMjU0ZWI3MWUxMGMxNDVmMWRhMGIzNzQ2ZjliNjE5NjNiMTFjYzA1Njg5IiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiODQ0YzEwZDVlNDhmNTM4NzY4YjkxNTJkOGFkZWE0NDk2NDlmOTk2MjQ1OGQwZTIwYzg0NmRlYjJiZDRhZTg2ZSIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiN2I1MjY1ZjVlYTUwNGI4ZTQ4YTczMWFjNzMzMGE4NWY0OGIzMTQyMTZiOWY0ZDVjM2I5MzQ0ZDZlY2U0MGFhNyIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiJjODc5OWRhMWVkNTdiZTk2YWRkNjRlNDc5Y2E0YWNiODVjNzgzMDYxZmM3ODU1NDNkZWZlODdlMmRmYmUzNWMxIiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6ImMxYjUyNTkyN2MyM2IwZGJkNWU1ODlkMjFiOWYzODIwMTg3Y2M2MTdiNjhmMjlkMTI4YWU0Njc0MjA0Njg2M2UiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiYjZhOWM4M2I4Y2MzYjZjNzlhOWYxNDE3NWJkODgwYjAxZDhkMzJjYTY5N2FkNDUzZWQyYWQyNTM2OWQ0ZGRjMyIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6IjBhZTM4MjhiZmVhMDk0MDZkZmI3MzliNjI0OTE3NTUxMGM4NWZhMzU2NWM1MjViNWYyMjAwNTMzYzMxN2I4Y2EiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6IjQ2MTVhMTNmNjU4NzA1MjdlNmJlYjc0Y2FhNzVkNTM5ODU0YzA3MjRjMmFhOWNkN2JmMTkxZjE4ZTk1MjViMTQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiM2EyZDJkYWQ2MmFiYjAyOGMzZGUzZDMxNzUyNTE4YTQ1MGY1NGZhMjc5YjcwYWU2ZDlhNWQ5ODhkMDQwZGQwNyIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6ImM0OWExYjc4ZjVkNjM5MzIyMzMxNzg4MTBkMzMwMmIzY2Y3MzUwYjJkMTk3YTAyNzRkNWE0MGVjODE1MzE3NTEiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiJiYjNkMzZhMTI4OGE4NTc0ODhjZDRmNjFmMmU1ZGNmNmM5MmE5YWVhNTM0MTM2ZjJmYjIyZTVmMGM3ZWZjZjYzIiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6ImNhYzcwOGEzMTRhYTE3MDU1Y2YwMTRlZjNiOTc4MTUzYTc5Mzk0OGQyZTJhZDgyZmY5MzY2YzA5ODUxMjY5NmEiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiMGQ5OTE4MzJhNWJmMTMzMmVlMDczZTNiMTE0ZjgzOTUwZTU5ODJkZmU4OWU0YzYwMDM5ZjliZjE4M2FjNDQ4MiIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6IjUzMzlkY2I0MDg1YTVlNmJjNWQzMjc5NGY0NjA5MzUwN2EzZGYwNDMxNzBkOTFiZDViOTAwZDA1MjBhYThjZTMiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMV0uY2xhc3MifSx7InZhbHVlIjoiNDc3MGRlNzRkNTkzYzAwZGNjMTQ5OTA0OTExZTNmOTFjODE0NmQyZGM2MTUyZDQ5NjMzNjFiMzE4M2JjZWE5NyIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1sxXS5kZXNjcmlwdGlvbiJ9LHsidmFsdWUiOiJlNzAyM2Q4YjQ1NTAyY2JlM2M2MmY4ZjRhMWU2MWJhOGI5YzRjMDQ0NThiMmM1YzY1OGU0NzE5YTllOTBmZTQ2IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzFdLmVmZmVjdGl2ZURhdGUifSx7InZhbHVlIjoiY2FhOGM0YWQ0MjFiNDgxODA1ZTIxMTRhNDExOWI2MjZmNmQ3YTk1Y2ExMjI4YmI4NmM3MTU3ZDI0ZDQ3NGM5ZSIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0uaWQifSx7InZhbHVlIjoiMDQyZmNiZjBmNTcyMzQ3Y2IxNDIwNmEwOGVmZjc4NTM3YjE0NmIwYzE2NjQyMzZmOTkyNjQwZjUwNDc4NjNiNSIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udHlwZSJ9LHsidmFsdWUiOiJmZjU4OTM0OTUyNGM4MGJhYjlhYzM4YTJlNDAzM2Y2MDc5NmM0ZTJjNDMzY2QwODZmMTE5MWE2NmJiNmYzYjdmIiwicGF0aCI6InJlbmRlck1ldGhvZFswXS50ZW1wbGF0ZU5hbWUifV0=", + privacy: { + obfuscated: [], + }, + }, + }, + { + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + name: "Republic of Singapore Driving Licence", + type: ["VerifiableCredential", "OpenAttestationCredential"], + issuer: { + id: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { + identityProofType: "DNS-DID", + identifier: "example.openattestation.com", + }, + }, + validFrom: "2021-03-08T12:00:00+08:00", + credentialSubject: { + id: "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + type: ["DriversLicense"], + name: "Jane Doe", + licenses: [ + { + class: "3000A", + description: "Motor spaceships with unladen weight <= 3000tonnes", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + ], + }, + renderMethod: [ + { + id: "https://demo-renderer.opencerts.io", + type: "OpenAttestationEmbeddedRenderer", + templateName: "GOVTECH_DEMO", + }, + ], + proof: { + type: "OpenAttestationMerkleProofSignature2018", + proofPurpose: "assertionMethod", + targetHash: "9d71ec0572df22c133656a45bd644a7e6bb1f44cb4670473263d7f2b6f2d4b04", + proofs: ["b449f7fb56ed2961749110037a1c40464548db71c386c925e58211505785e6ce"], + merkleRoot: "2e8038ad3403396fad4af3158f132c06d34fd31516b328b07001bc44f48fbeff", + salts: + "W3sidmFsdWUiOiIxMmQ0OTZmZjhmN2E3Yzc5YzhhNzJlMDA4ZTc4NGFhNDRkNjkwMmUyNDFlMGM4YTA3NTNmMzY5MjM3YzEzODY5IiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6IjI5NjRjZDQxMzgzZjllYjRlN2I3NmY2NjAzMmI1OWFiNDIwOWFjMDY3YTQ2YjUxNGQ5ZDI2NDAyMWNmMmI1YWIiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiZDhmNzcwNjI4ZDNjZjMyY2FkNjc4NmRlODIxMjYwMjE5MmY5NDEyNzEwYTk4OWQ2NmVhOTliNDIwYmRhYmYxYSIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6IjA2NGM5NzQyZWRhODgzMzUxNjAwNDIyYWY5YjU3MmU1NzkwMmFiMjMxNDExNzEyMTc1ZDYwYjA5ZWJmNjcyZTYiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiJhZDQ3NTM3M2Y0MGNmZjA1YTY0OGI2OGNkYjllMDA4Zjk1Zjg1Njg3YzNiM2I5ODJkMTNmNmI1ZmQxMGQ4ODU3IiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiNzEzYjcyMWVhNDA5MGQzNDFhMTg2ZmVjYWM3Nzc0ZGJhYjExYjE5ZjYzOTg3ZjZmZDM1ZWZjODkwNjgyNDAzZSIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiZGNkNjY4MTFmMGVlNGQxMTdjZGIzYWQ5NTFjNTE1MmIwYWZjYTlmNmZlY2I1YjQwODc2MDRlMGVjMmY3YzAxNiIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiIxYTU4YzJiOWQ4YzQwYjUzMTdmYjFmNjcwNmM5Yzc4YTI4OWJiZTFiZTQ4Y2I1MGE5NTdkYzkwMjIzNjdmY2I4IiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6ImFkYjM3ZDAwYWU0ODhiZDgyOTFkOTAxZWY2NmIyNTY5ZTQwNDRmZjBhN2U5YTU2MTI2N2U2NGYwZmJiOWE3ZWQiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiZGY2NDNiMGM0ZjI3Y2RiYmJmMDJkZmY2MjVmM2ZlMjA2MGMxMjI4MDNjZDM5ZDA0YWY5YTg0N2M3ZmFlOGUwZSIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6ImMzNGE0ODBjM2YxYWMyYmY1ZjgyNjc5NDQ0ZDM1ZWE1ODYwMmQ5ZGU0YjA2ZTc3MmI2YTMyYzI2ZWUyMTA2YjEiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6Ijc5MWM1Yjc1ZjkwZjQ4NzEwY2E5ZjY4ZDIzYTBjZTU2MjE0YWZjYjhkOTIwNTljYTRhMzUzNmJmNzYxNTY5N2IiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiODJmMjdjMGY4MDk5OTkxMDhmZGRhYmQ4ZTNiN2NjYTQ3YmNhMTVkZmI4ZjE4MzE4MTVmY2VkNjdiMmYwNjhlYyIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6IjNlYjFjNDdjZTkwOWRiNWQ1MzhmNjE2OWNiMjlkY2M2NzY0YzAwNWRjY2Y3ZGMwZTU4OTI1YmUzMmFmNTJiOTMiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiJlMGJmYmI1MWI4YTc5NTNhZWM2OTE5ZjgwZGU0MzRmOWM1ZWVhZDY2Zjc0MTA1YmY0ZDAxM2Y1MjVjNGE0ZDczIiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6ImE5YjU3YTU2NWRmMjYxZTVkNWQ0YTJiMDM2YjQzMzgwN2NjNTlhZmE0NGU1MjZjOGY2MGViYjJlNzYzZWUwYjciLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiZDJmMDA4OGRiZWU2YjhhZGExZDlmZWJiNzIxZGJmOTZmMDU5MDVmNDc0YjVhYjZjNjNiYzZhYTg0NjdhNzVlOCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6ImU2ODc2MDBiNGU4NTEzMjc1ZGUxNDU1YjNiYmU5ODczMTZkMGMwNDI3ZTA3YjgwYWZhZWE2ZDQ5YjZlYzBhMWYiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLmlkIn0seyJ2YWx1ZSI6ImZmOTVmZjlmNGExYTQ0ZTVhMjFlNzQzMWFkODFhOGI2MzAzZjhjODQzOWJhYWFiZmRhYjU4NDhmNTkyN2Y0ZGEiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLnR5cGUifSx7InZhbHVlIjoiYTcxNGVmZGUyYzdiODhjY2IzODIyMzY0OWMxM2U3MmVhNjNmNWViODcyNGM2MzkxMGJhZWJmOTE0YWYyYWJmZCIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udGVtcGxhdGVOYW1lIn1d", + privacy: { + obfuscated: [], + }, + }, + }, +] satisfies V4WrappedDocument[]); + +export const SIGNED_WRAPPED_DOCUMENT_DID = freezeObject({ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + name: "Republic of Singapore Driving Licence", + type: ["VerifiableCredential", "OpenAttestationCredential"], + issuer: { + id: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { + identityProofType: "DNS-DID", + identifier: "example.openattestation.com", + }, + }, + validFrom: "2021-03-08T12:00:00+08:00", + credentialSubject: { + id: "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + type: ["DriversLicense"], + name: "John Doe", + licenses: [ + { + class: "3", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + { + class: "3A", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + ], + }, + renderMethod: [ + { + id: "https://demo-renderer.opencerts.io", + type: "OpenAttestationEmbeddedRenderer", + templateName: "GOVTECH_DEMO", + }, + ], + proof: { + type: "OpenAttestationMerkleProofSignature2018", + proofPurpose: "assertionMethod", + targetHash: "dd55a7d96d47e58350f2cfb03ebdf3f859684c9f97ba75eed55b1bdcc761c5aa", + proofs: [], + merkleRoot: "dd55a7d96d47e58350f2cfb03ebdf3f859684c9f97ba75eed55b1bdcc761c5aa", + salts: + "W3sidmFsdWUiOiJjYTE3MjI0YTg3NTk0NzNhNGUyZjM2YTM3NjljODU0OGM5M2RjZTQ3NmI0MjEwMTNmYTEzYTA2OTUxYTI1YzhjIiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6IjMyYzk3MDRhMmIxMWU1MzhjYTBlZWJhYWMzNmU0ZmRlYTU4ZGY0MDI4ZGVmZmJjOTkzODBjYjZkZjU3MTdiODEiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiNDE3YTFhNzY2YWM5MzhkOWVlY2FhNWRmMDdhOTBhODkyZTM3ZjA1ZmI3MzY5ZWRjNGQwYWNmNWZkMjE4YjhlMiIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6ImE1Y2FkZDIzMmQ4ZjhlMGU4ZmFhODA3OTMyYWNkZjJhODc1OWY4MWEyMDNmNmEwMjdjMTJhOTBhNjg0MWE1NWYiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiI2NGE4NjBmMmQwOGZjNGIyMDhjZWE3NmU2MjBjM2YwMDRlYzhiMmRhYjdhZTc5ZTZkZmMxZjllYjU1MWMxMmM3IiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiMzcyZmJlNDllMTdjMTA2MGEzNTk1NjVhNDA2M2VlMjkyODU1ODg0OWZhZWRkODE1MGQwYWZjZmY3NzQ2M2NmMyIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiYTE0ODAwOGQxY2JjMzM3ODJmNmNlN2UyOTFhMTM5ODE1YmRhYWFjZjg2MWYxNGYwMDk0NWU5YWIwZTk2ZjdkNiIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiI5Yzg4NTc4ZTAzZWRiNjc3NTdiNDI0NzY4MTliNWZiMGQwMDlhMGU0ZjZmMjllOGNhNTBlMWJmNWI4NWQ2ZmZiIiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6ImJhOTk1NDA1YWQ4ZmZlZmJmYTExMDA2MzE2ZDdkNjM4NDRlODk2ZmMxNDhkZjdlMWViZjNkYWZhYzI0NTY4YjQiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiZWY1ZTEzODU4YWM1MzYwNTMzODkxZjkxOGJhYjlmZjI3YmQ5YjhiYzA5MzQ4ZTc4NWMwMmI2YjYzZTcxZDNhYSIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6ImY2N2ZmNGMyZTUwYzU0M2ZmYmEyNGJiMzA4OTY5NGUxOWViZDNjOWJhMmE5MTM3NTA3N2YzOWRlN2M0ODVmY2MiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6ImIyYzQ2MjkwMDQwMDMwOGM1YjA3MmM1Y2NlMjQ4YmQ2YjRiOTgxODBjOGQ2ZDQ2YjIwNWE0MGE2YzNjMDhmMzciLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiM2QwMThlMjllOTI3MTcxN2UwNGI5ZWYwMDJkNWVmNTRmMTRiZmI3NmJlYzdhMTlkN2ZlYjcyMzM3NjU2NzU4ZiIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6ImYxNDllNmM5M2ZhNTU5ZjM4OWRjZTcwMDMwYmRmYmVlNmU3OWRjODM1NjJhYmVhN2FkOTMzNTA0OWM4MTI5NGQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiIyZGZjM2VmNDQ2NzA0MmMzMDI4NDU0MTNmMWE5MDQxYmQ2NjY3NThmNDM4MWU4OWU5NWIzZjc4NjYyYzE1NTc5IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6IjY3MjNhYjA4MzhkODMzNTJlMjhhNjQxMjliMzEwOWQzNzA5YTk3NWYyMDljZmM2NjE0MTNmODUyYzFmZTY0YzYiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiMWZiNTRmMGVhZDgyZmEyMzVlMmU5Y2RkY2ViMGQ2NTllMjRhYzhhMzM4OThmODdmMzkzZTBmZmY5OTE1Y2NmZSIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6IjhjMzJlZmNlOGE2ZTIzZGMxNzUzOTVmNzMxM2ZjMGQ4ZTk0ZTA0YjU3ZGMwMzI4YmEyNTk0NTgxMTJjNWQ4MjQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMV0uY2xhc3MifSx7InZhbHVlIjoiYmQ1YzM2Yjc1YTVmNzEwYmQ2MzJhOWM1MTY1ZGVkNmI4N2YzODY1MTg5YWRjZTc3M2FlNDMxMTlkYzljMGFiNCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1sxXS5kZXNjcmlwdGlvbiJ9LHsidmFsdWUiOiI1MmYzYTU1ZWI3MGZmZjMyYjEzZWMyNjlkZjJmODM4Mjg4NTc5YmUyMDg1NmQ3Mjc5NmI3YmY3MDFmMjY5MjU3IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzFdLmVmZmVjdGl2ZURhdGUifSx7InZhbHVlIjoiZTJjZWZiMjkzZGEzZGNmNTIzZjAwNjkwN2YyNTljNTIyOTc3MzQwZjYzNmY4YmU1MmM5ZTg5ZTEzZGVlZTk0MiIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0uaWQifSx7InZhbHVlIjoiNDNiMjFkZGU2NTY2NjI5MTNjNzJiMDExMzBkMjM0MzlkY2NjMTNiZjVhYjYwMjY5YTVmYjM3NmFlMzBkNjlkMiIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udHlwZSJ9LHsidmFsdWUiOiI0NDRmZmU3OTMzMmRkZjExOWRiZWUzZjYzYWQyZTQyYzE2ZTczMDdkMGVmOTE3NDJlZDEzNTkxYWY5M2U0NWRjIiwicGF0aCI6InJlbmRlck1ldGhvZFswXS50ZW1wbGF0ZU5hbWUifV0=", + privacy: { + obfuscated: [], + }, + key: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller", + signature: + "0xa3ac9f73a7314c0aad47bad875921f5c88d2af9440d6c309fc2f93dbf43bd8235e84b744cb1ff1c09c214b559ce3bd6eb148c2f68c677cb8408d96e9b5411dfb1c", + }, +} satisfies V4SignedWrappedDocument); + +export const SIGNED_WRAPPED_DOCUMENT_DID_OSCP = freezeObject({ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + name: "Republic of Singapore Driving Licence", + type: ["VerifiableCredential", "OpenAttestationCredential"], + issuer: { + id: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { + identityProofType: "DNS-DID", + identifier: "example.openattestation.com", + }, + }, + validFrom: "2021-03-08T12:00:00+08:00", + credentialSubject: { + id: "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + type: ["DriversLicense"], + name: "John Doe", + licenses: [ + { + class: "3", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + { + class: "3A", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + ], + }, + credentialStatus: { + id: "https://ocsp-sandbox.openattestation.com", + type: "OpenAttestationOcspResponder", + }, + renderMethod: [ + { + id: "https://demo-renderer.opencerts.io", + type: "OpenAttestationEmbeddedRenderer", + templateName: "GOVTECH_DEMO", + }, + ], + proof: { + type: "OpenAttestationMerkleProofSignature2018", + proofPurpose: "assertionMethod", + targetHash: "db256b67a181b7c5a1b312b64901a0c332d72a5f2f631473ba2c28a725c3ab21", + proofs: [], + merkleRoot: "db256b67a181b7c5a1b312b64901a0c332d72a5f2f631473ba2c28a725c3ab21", + salts: + "W3sidmFsdWUiOiI2ZTJhN2E4MjM1NzMzOTM2MGJkYzE0OTYzMTUwNzAyNTg2N2QyOWYxM2YxYjMwZmFmMDQ4Y2VmM2QyMzc2YWM2IiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6ImRkZGI5MDVmNmIzZWQ0OGVlMzkwZDljYjQ4MTdkMjk4OWMyY2VmMzQyM2UxNGE4YjQzMDMzYmFhNDM0NmY2ZGUiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiMWNiZjBjYjY2ODZkNWIyMzJkM2QwZDZiNTk1MTA0NDc0OGY4NmNlMjJkZDE1OGIxNzUwZTc2YWUyYzAzZDkwNyIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6ImJlZjJmZjNhM2MxNDEzMDYxMDVkNGMzMTJlZmZkN2M2OTUxN2U3ZjM5YTBjYTQ3ZTZkZTk4Y2M1ZTFkMzllY2UiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiI1N2M5YWIzYzRlM2RiNjE5Nzc0NjZhNjQ4ZmM5ZThjNjI2NzQ1ZDE4NmIyYWRlZDIxNDhiNDQwYWU0MWRmYjhiIiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiZmYwNDE0MjcxYWYwNzk5ZWM4YzgwMTQzMzI2NmVmNGE5YzAwNzQxMDVlNTNmMmQ3OWYwYjYzYjBjNjk1Y2Q2MCIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiOTEyNjc2YWZjZTkyYjBhNGU4MzhkNzZjZDYyZmNmMGY0YTc1NmE1MTI0NWI0YWU4YTQxN2ZkNzYxNmVhMDVkMSIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiJmNDYzYmNkYWIzYTcwNGYzMWRhOWQ5MjUwNTM3OTE1MDBiYTdjMDQzZTNiZDEzNzU3ZTgyNTI5MzYzZGNhNjc0IiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6Ijc2YWIzZWQwODk2NzZkOGJmM2FhZjE3OGQyYTUzYzI3NGZjMGUyMmFiMjJkNjU3NmIxYTUzYTAxMjMxNjUxYjAiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiNjMyYzI5MzdhZGYwMGIwYWU0NGRlYzZkNGI1NmJmN2RkYTU3ZDEzYjk3MWUxNzhlZjJiZTdmNDMwNDJlMTI4YiIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6IjkxOGNiYjU1MDg4ZGFjNDEzMzYxODEwZDE0ZTBlM2U4Mzk4N2Y2N2NjZDU1YTE5OGQ2YzZhOWEzYWM4Y2VkMDQiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6ImI5NmVkN2FjZDZjZjQwNmViZGMxZmJlY2VhY2M1ZWYxZDhkODlmZDNhZTZmZTRjMzkyMTM3M2NhY2YxYTc5NDAiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiOTVmNDFmYWZiYjNhZmY4NmM4ODU0ZTRjOWQ4MTAzY2E3NGM0NTBiODg3ZmQwOGMwNDFiYzI4NzlmN2RiMDAzYyIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6IjU2ZmU1YjZmZDYwNjE0OWZmYzhhZGZkNjY2ZDgxNGJiYzZjNWMzZjU0YjA2ZmQ4YjJjZTFmNDc2M2RkNWMwNmMiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiJmNWZhM2MyMDhiODRiNDdkZDczYTIwYmM5YjczYWY1MTI3MzIwZGUxNTIwNGExMjA0NjgzZDI0NGUwNzhkYmU5IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6IjkzODcxZTQ2MmEzZjIyNDE1YzU2ODhhOGQ3NGYyZjFlZjMwZTEwYWNlOWZiMmIyNTllOWVjMmVlZWVjMWI2NGQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiN2FmNWFjNzViYjNkZWYyNTQwOTViNWE4ZDFiNGFkZmJiZmQ3YTM3MTY4N2UzZGY2OTJmYjhlMmM2YTMyZjZiNCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6IjAwZDA2MTlhNzQ0ZWUxODIwMzQ5NzZhZmRjZmU2ZjE5ZDE1NWZkMjgwZDQzYjM0ZjhjNDM4OGJiMDQwOTBkOTQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMV0uY2xhc3MifSx7InZhbHVlIjoiOTUyNTdkMjJmMGMyYzRkNTY3MjkzMWM0OGY1OTBjY2RmMGU4NzNmY2ZmMTdjZDA2NmRmNjBjNzMxMzgxZGMwNyIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1sxXS5kZXNjcmlwdGlvbiJ9LHsidmFsdWUiOiI3ZTZlODE5MmM1OWVhMDllOGUxZDM3NTI4NGEzN2JhMTFkNmFlNTVmNmFiNGIwMjRhMGU4YjM0M2MwZTlhMWI4IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzFdLmVmZmVjdGl2ZURhdGUifSx7InZhbHVlIjoiMTRmN2U1ZWU4Zjk0ZTAyZDFiODcxYjE4YzRmZjAwOTA0ZDc4OGNhMjU4NDhlYjVlOTMwOTZmNTFhMzI0NGIwYiIsInBhdGgiOiJjcmVkZW50aWFsU3RhdHVzLmlkIn0seyJ2YWx1ZSI6IjFjNzRmODhjODNhOWZhYWQ5YjU1MjE4NjcwZDg5NzM0NTY0MjY2OTg5MzdlYTQyNmFkZmY4ZmVmOTYzMWVkNzMiLCJwYXRoIjoiY3JlZGVudGlhbFN0YXR1cy50eXBlIn0seyJ2YWx1ZSI6IjA0N2I1YzA0NDAzMjlmM2ZkODZmMDQxODRmMTk1OGZlZDQyNDhiMDI2YmM2NGI5NDM5MmNiMGRjYmU5M2VlYWYiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLmlkIn0seyJ2YWx1ZSI6IjQyZGM4Y2EzZGJiMjI2NGI4ODg0OWIyNWFkZWQ0ZWE2NWQ2ZmMzYTZlNWUyNjExMGE1MDUwNmRjYzdhYzhmNzciLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLnR5cGUifSx7InZhbHVlIjoiODg2MjJkNDRjMTBiY2VlMzUxMGRiNmE4ZjNhMGYxM2M1ODBmNmZlNWY3OGNkODVmM2FjYTIzMGE2M2QyYTZjMyIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udGVtcGxhdGVOYW1lIn1d", + privacy: { + obfuscated: [], + }, + key: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller", + signature: + "0x1d889961f3b28e3433ee56e1d3226d1b069d6696f2cac99d1f1504f31c1257b216e9e42bfa8c434eaeb80bc38b0af269cab3ffd03d4410539589d9173bc4ba881c", + }, +} satisfies V4SignedWrappedDocument); + +export const SIGNED_WRAPPED_DOCUMENT_DID_OBFUSCATED = freezeObject({ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + name: "Republic of Singapore Driving Licence", + type: ["VerifiableCredential", "OpenAttestationCredential"], + issuer: { + id: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { + identityProofType: "DNS-DID", + identifier: "example.openattestation.com", + }, + }, + validFrom: "2021-03-08T12:00:00+08:00", + credentialSubject: { + id: "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + type: ["DriversLicense"], + name: "John Doe", + licenses: [ + { + class: "3", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + { + class: "3A", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + ], + }, + proof: { + type: "OpenAttestationMerkleProofSignature2018", + proofPurpose: "assertionMethod", + targetHash: "4b178a75faf7d7ecff1341ee1e0907810df23c88a217b814eb12c2a4454631ec", + proofs: [], + merkleRoot: "4b178a75faf7d7ecff1341ee1e0907810df23c88a217b814eb12c2a4454631ec", + salts: + "W3sidmFsdWUiOiIyMzkyMzE4OGQ0MzIwYzlkMGEyZGY0MjU2ZTQ2ZTkzZTgzM2FlMWQ4YTU5YzFlYmQ5MTBkOTUxNDc1MjNiMjhmIiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6IjZjMGEzZTZmZDI0NTEyZjg5MWE4ZDY0N2RlZGU1NmIwYjBlMTNkZDcxOTVmMDRiM2EwMzY2ZDZmNDk5OWFkMTAiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiMWFhNDY3NmQwY2FjZGU1ZTljY2MyZmNiYzc1OWRjZTJlNWFhOGY5YTg1ODI5NzFlNjNlM2MzZmVjMzE2OWNiOSIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6IjZmYjU2MDJkYjg1MjY1M2Y2NDg0M2I0ODcyNTNmNGU3ZWI2NzlmZDY3Mjg4NjNmMWRkNjcyY2U1ZWEzMDAzM2YiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiJkMmZiMGQ4YzBlMzFkNmIwZDgxODQ1NGYyZDgxNGZkOTg3ODFjNjk4ZDA0OTg3MGJmOTAwNzA2M2Y4ZDAyNjNlIiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiNzBjNDk0MzM5ZDQxZjZkOTBmY2ViNzg5ODk2ZjExMTVjMDI1NWY2Njg4Yzg1MGQxNmUxMGRiNzhhZmJjOWYyMSIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiMDkyYThhMTc0NjYwNjA0YTdmZWNiOTgyNGVhNmMwYTk3ZjMyODM2MzE0MmVjMTg3NWUzZTBjZTFhNzFjZTc1ZSIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiJmZTM5YTA3ZDYwNDVmZDdlMWQxMjRlOTc1ZmQxNjYxZTQ5NzNlM2Q0NDdkMjBiOTdmZmE0YWRkMDA0YzcyZjhhIiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6IjljY2ZlNzNkMjllZDhmYTU2MWRiMTE5NjZhN2RiZWNhY2JhYTNlOWNmNDI5OTg4Y2VjMzNmNTRkOTQ0NTdhYzIiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiMDNhNWMwMDYyMzFlNWQ1MjJhNmYzOGFkNDE3YjEzYmQyYzgwMjVhZjY5ZGVhYTA0MzkwMjkwNjljNjEzMjE3ZCIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6IjNjNzhjMzdlMDA2ZjZlMTkyY2ZhZmZjYzM0NzZhODk0MmMxODNiY2JkN2NlMjJlYjhkZWNmNGQ0YTI5OGJmZmIiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6IjNiMDI3MjkwOThmMTQxY2I3Y2E5OGM2ZmIxODMyZjVhYmMyN2JmZDA5NTlkNzk5ZjUzNDRkYzVjZWY2YmMyMTQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiMzQyYmMwYWM0MjU3MmExY2U1N2YxMjcwZGRhNTlmMDFlMzZiMTM5NzhlOTdhODgzMzMxMGVjZGMyYTgzOGUyNCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6IjlmZGIwN2YwNGNiOTllZWViZTVjODFiZmRkZmIwMDRiNWVlMTVmZTBhMGE4ZDIyNjYzZmMxZGRkMzk5NmI3MjgiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiJlMTY0NTBiODVmNjJlY2JkMTgyODg4ZDQ0YjIzZGQ1YTVkZTdiNjBiN2UzZWI5YzQ1NDRmZjYzM2E4MzBlNTkxIiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6IjZjZWRmYjg5MTM3MTI3NzYwNjZlNjJkMjE1OTFjY2M0NGNiOTM5ZmNlODA0ZWI2Y2E1MWViNmUyMWE0Zjc3NTAiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZWZmZWN0aXZlRGF0ZSJ9LHsidmFsdWUiOiIxY2ZjMzA0ZjczZGUxZTUxYWMxZjA3M2RiNWI1MGIxMzRjMjY4Y2M0Y2YyMTQyMGZlYTJmNDYzNWJjM2U5ZTMxIiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzFdLmNsYXNzIn0seyJ2YWx1ZSI6ImZhMWQxMDYwZDU3OTU1NWFkZGNiMGQ1OGRiODIzZDAzMzljZDU4YjBlMzk3YTcyY2ViNjQ4M2U2NzYzYzI4MWIiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMV0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiNTkwNTA4N2JlOTVhNGFiMzI2NDRkMmQ2M2MxNGIxODhlNGU3MTg2MDdjNWI2MTlkZjc0MjYyMWU2NzdkNmVhZCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1sxXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6IjM0YWUzN2JhMzY2NzNkNzMzNDg4YTc5ZDM2ZGQyNDQwZDc2YjMwYTBlMjBjZDM1NGI2Mjk1OGU5Y2U1NjUwODciLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLmlkIn0seyJ2YWx1ZSI6IjFjNjUzNmJiNDA1NTgzMjEzMDdmNjcxNTE3ODIwNzc1NmEwZTcwYjUxNTcwMTNkOTFiMDdjMTFlZTg3Yzc2MmIiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLnR5cGUifSx7InZhbHVlIjoiMmNhODYyYzA3Y2M5MGU3M2IwN2ZkMTJlNGIzNjg4YzQ0ZGQ3OTkyN2UwMzlkNDVlOTY3NGMzNGZmMjJjMGE1MSIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udGVtcGxhdGVOYW1lIn1d", + privacy: { + obfuscated: ["0394c26c5be1bde929bf5aec2e076fc6843ace379be541c30707dab467baa59f"], + }, + key: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller", + signature: + "0x1744f9615fa8d725cf4ae14f2654762dd8e0ee88a9b6d8af13cec688019a7a501e9bae10fa407fdbe359977f8124a26a0061a0ef0ea212c42fd1d91e0998928d1c", + }, + renderMethod: [ + { + id: "https://demo-renderer.opencerts.io", + type: "OpenAttestationEmbeddedRenderer", + templateName: "GOVTECH_DEMO", + }, + ], +} satisfies V4SignedWrappedDocument); + +export const BATCHED_SIGNED_WRAPPED_DOCUMENTS_DID = freezeObject([ + { + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + name: "Republic of Singapore Driving Licence", + type: ["VerifiableCredential", "OpenAttestationCredential"], + issuer: { + id: "did:ethr:did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { + identityProofType: "DNS-DID", + identifier: "example.openattestation.com", + }, + }, + validFrom: "2021-03-08T12:00:00+08:00", + credentialSubject: { + id: "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + type: ["DriversLicense"], + name: "John Doe", + licenses: [ + { + class: "3", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + { + class: "3A", + description: "Motor cars with unladen weight <= 3000kg", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + ], + }, + renderMethod: [ + { + id: "https://demo-renderer.opencerts.io", + type: "OpenAttestationEmbeddedRenderer", + templateName: "GOVTECH_DEMO", + }, + ], + proof: { + type: "OpenAttestationMerkleProofSignature2018", + proofPurpose: "assertionMethod", + targetHash: "08969c7baf46807ee65e495b2a93c0e27dfdc77085562ce9ab1249a7fb261681", + proofs: ["ce284d21e98ac301c0e963ea6d020570091e05591dc2b787a698512e82b39001"], + merkleRoot: "6fa0bdfa20b114c3e9e92fb511be62f416533a35df99a440ecc28ff4a3f601d2", + salts: + "W3sidmFsdWUiOiIwMzgyZWU0MjFlNTgyMzJlMGJjNTI0MDY1NjhhZTdiNWZhNDhlOWRjYzczZmVkM2VhOTZkOTAzNGQ4ZWZkNDlhIiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6ImViMmI1ZmIwODhlZDk5YzY0NzJmYmQ4MjMyNjVhYjlkMzZhNmQ0MDFiMGEyNmM5N2Q3Zjc0MDkwYWJiYTE4OGEiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiYWNmNGFhMGJmZDEyMTRmZGEwZDAzNzczNmNhMDFiMzhkOTBlZDA4MzQ5ODUwMWY5NDlmOTgyNjg1NmE2MTM3OSIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6IjM5Yzc1MjFmNDdlNTJlNWZlOGI2NmEyYjhjZmEzYTQwNDM1ZjQ2Y2NiOWY3MGQxYWY4MThkNmNkNzk1MzQ4MzQiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiJiNWY3MmI3N2M1NjU3YjZiOTMyN2QyMGYwZTUwYzQxMGVmNzRlNDMzYTM0NTRlOTRmMTEzOTZmMTIwYzJjMjc5IiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiOTU1MjExMzNmNzgzZjI5NzlkODgyMzI4MDlmMDgxNmUzNDVmMjE4MTk0ZTJkMTgwYzZmYTcwMTBhNDI4ODFkYyIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiMTQwZmVlNjI5Y2M2MjY3Njk1NzA4YzY2ZTg2OGI0ZjVhZTBiMDg1YjYzNDczM2I1YWE1N2M4ZTQxM2I1NTliNiIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiJiMjFmZTkyMDNlNWYxNzFjMjE1NDIyY2Y2ZTZkOWEzNzFkMmIyZGJkMjU5ZDE0Y2JmMDZiYTllZjQ4NzEzYzk3IiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6ImE5Mjg0OTFiMzYyNzcyMjUxNzM0ZDEwNGQwOGJiMTgzMjczM2JlYzZiYjdmYWI0YTE4ZTdiNGRlY2QzMjE0YmMiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiNWViMmMyNTU2ODgyZjgzZjM0MTQ5MTczMGM0OWI4NTE4OTljMTA3NzY2Yzk5YWQwYzhhMGRkZTQxNDkzZjYxYyIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6IjVlMTgyNThiODdjMjJiMGIzY2Y4OWVhMjZhOTI5N2ZkYjVmYjI0NTA2Mzg0MzNlYzcxN2YyYTBmMzE0NTJlMmYiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6ImIyYWU3ODllZmVjZmE4ZmEzMmZmNTdlYTNjYTJmZjJjZmVmOThmOThmZGVhY2U4M2Q0NGEwNTVjZGU4MDE2MDgiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiMGQ1ZWI3YmY3OTE1MmI0M2EwMTQyYjhkNTVkMzRmMzRlOGQ0N2U5MzgwMDVhYTVjMTRjMjk2MWNiMjM0OWFkYSIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6ImIyZWM0NTYzMjhlMzhjYWYyYmNlYTk5YWM5NTc0ZWEzZGExNjJkNmJlZDVlZTRkZGM3MzI5NjhkMmIwMDZjZGQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiI3OTIwNmQwNDNlNjVhYmU2MmFmYmIwNmViNGMxMWNmZTg2NjkzNWRhOGYyYzkzODI4NjVlZjg1YjVhMzc1NTUwIiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6IjAyYjJjMTlhNDY2ZjNiYWU5ZDhmNWI0NzUyZGEzZmU2MWM1MTIxYzc1Mzc0N2I1NzNmNTdlYzBmOGExODIzZDciLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiNTNiOTA2MjdlNWY1OTM4YjdkNWY0NzhjM2JiNDE4NjkwOWI1OTY1MjVhM2I4NWNlZWU2M2JjNGYyZGQ1ZmRkNCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6ImNhOGFlMzIwZjU5NWJmMmUwMmQ3MTAxOGE5YjA0YWI1MDNiOGJiMTIyM2I2NDM5MWNjYTZiY2MyOTk5MjdmOTciLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMV0uY2xhc3MifSx7InZhbHVlIjoiYjk1MzhlMjkwNzdlMzg1MzlmN2E0MTliZGMzNmFhYWVjMTMyNGY0MjQzOTA2YzIyN2JmMzhkZDU4NTA4M2NlZCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1sxXS5kZXNjcmlwdGlvbiJ9LHsidmFsdWUiOiIyN2RmYWY1Y2M1NzJlMTFmODhkMDFmNGUwMzQ0ZWRiMzA4OWQ2NDc5YmY0ODIyODBiZmNmNGE4YzZjOTY1NmIwIiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzFdLmVmZmVjdGl2ZURhdGUifSx7InZhbHVlIjoiZTBjMjFhMzQ1NTZjZTMzNjViOTE5YmUwNjlmODVkM2EyNmQ2MTcyM2Q4YjlmN2QwZjY5ZTkzMjMxZDY4ZGM2ZiIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0uaWQifSx7InZhbHVlIjoiODY4YzNjOTYwNGJlYWMxMDZiZDQzMTc3NDRjYTNjZTI2YzU3YWFiODc2YWUwMWQwZWU5NzNmYWE1NDNlNWRmOCIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udHlwZSJ9LHsidmFsdWUiOiJiNzY3YTcyMmUzNmU4MjAxYWNjMjg2MTAzYzBkZmY4Y2I2MjI4YWQyMmVkZWJmMjc4ODcxOTQ1MDVmMGVlNmNkIiwicGF0aCI6InJlbmRlck1ldGhvZFswXS50ZW1wbGF0ZU5hbWUifV0=", + privacy: { + obfuscated: [], + }, + key: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller", + signature: + "0x153aeb0f59bef692f1b5bec2f20fc08f72863b0a670e87ac7c68460d311fc7a574189bb92056a15f1ef283c1784303528364d2124a006de3dba586f6162df5481b", + }, + }, + { + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json", + ], + name: "Republic of Singapore Driving Licence", + type: ["VerifiableCredential", "OpenAttestationCredential"], + issuer: { + id: "did:ethr:did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + type: "OpenAttestationIssuer", + name: "Government Technology Agency of Singapore (GovTech)", + identityProof: { + identityProofType: "DNS-DID", + identifier: "example.openattestation.com", + }, + }, + validFrom: "2021-03-08T12:00:00+08:00", + credentialSubject: { + id: "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + type: ["DriversLicense"], + name: "Jane Doe", + licenses: [ + { + class: "3000A", + description: "Motor spaceships with unladen weight <= 3000tonnes", + effectiveDate: "2013-05-16T00:00:00+08:00", + }, + ], + }, + renderMethod: [ + { + id: "https://demo-renderer.opencerts.io", + type: "OpenAttestationEmbeddedRenderer", + templateName: "GOVTECH_DEMO", + }, + ], + proof: { + type: "OpenAttestationMerkleProofSignature2018", + proofPurpose: "assertionMethod", + targetHash: "ce284d21e98ac301c0e963ea6d020570091e05591dc2b787a698512e82b39001", + proofs: ["08969c7baf46807ee65e495b2a93c0e27dfdc77085562ce9ab1249a7fb261681"], + merkleRoot: "6fa0bdfa20b114c3e9e92fb511be62f416533a35df99a440ecc28ff4a3f601d2", + salts: + "W3sidmFsdWUiOiI1ZGU5NjM1OGRlZGVjODIwMWFhYTJjZjRkOGI4ZjYyNzA0NDc2ZTRkYzdiZDQ5OGEwOTc5MGI1MDc1NzY0NWQyIiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6ImI2YzkyMDc4YjM5OTU3NmM1YmNlZjVhOTBjYmMwMzQxNjEzN2UyZTBjODAzM2JhM2FiZDNkYTU3NjEzZGYwZGMiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiNjM0Nzk4NGNiN2Q3MDA4NTczNjJlYmFjZTgwMDEzZjQwODA0NzNiMDkyYjAyMzQ3ZDY1MGUwMGM4MGRjMTQ5ZiIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6ImVkNGJiMDQwMWQ0NDY0NTljNjQ1YWUyMjI2MGQ5M2YxYzllOTkwYzg3ZGZhYzM2YjI2N2QwMTVlZTM4MDRlMWYiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiI1NTU4OThjZmE3ZWUxZThjY2VmOGIxYWMyYjBjY2RlNWJlZmFkMDE2NTJjOTY3NmVlM2VlNGExNTNmODlhM2JhIiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiNmVmYjc3ZDY2ZDQ3MDcxNzQ5NTIyOTI4MzE1MDI5OTlkYjViN2FmOWQ2NjQ3OWRiYzFiMzlhZjhiNmI0ZTU1NSIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiMmNjOGU1OTcxMDFhYmE0NzIyYmYzZGY0MWQwYjYyNjM3MGFiNzRhOGZiZjhjMmM2MTlmNDIzN2Y3ZWFhMzJmOCIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiJmY2IxNDNjOWUwNmQzMTZlNzdlYmIzMDkxNDFiMWI5ZDE1YTRhMTQwYzk4ODFhYTY0OTY0MTQ1NDVhM2RhYzUxIiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6Ijc0NDVkNDQzMDdmOWU2ODBjNTFkMWYxZjEzYzE5YTU2NDFkNmFiNmMzYmE0NmRjMDFmMWIyZDU0YTE4ZWJkMTEiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiYmVjYjY3OTBjMWQ1MmE2YmRlMjFkMzRjYTUxZDQ5ZGViNDBkMmE0MzQ2MGYyZjI4ZDA1NzY0YjVhNzFmODFhNCIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6IjkzMzQ2ZDg0NmI1MzJkZmY0NTc5NGQ0OTVkNzk3ZDZmYzZkYTRjYTgyMzRmMzQwNjljODNjYTU0MWQwNzA4NzgiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6ImU5OTZiYTM2NTFiZjZiMGY2YWU4NDUyYjljOTM3NjBiZjRkYzRiNDYwNjZlNGZkYTQ0YzBiZTJkY2FhMmFjZTEiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiZGIwZGQ0NjcyYWYxZjdkZGJiNGVhNTYwOGMzZjBkMjc5MDljMTAxM2FjYmJkZDcwOWVjMDZjYmQ0YTM3OGZmMCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6IjA1MWZkNTUzN2Q0ZjViNzVmNWY2MTk2NmI1ODc4MDhkNGNlZTQ1N2EzOTNlMmQ0MWZmZGFjMzllZjk5ZjcwNTUiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiI3NTU3NzYxY2VhZTgzYzVmN2YwZTNkMmM4YjYxYzllMWVkZTNmMTIyNzVmZDgzOTIyNDNjNmQ4ZDNhNTYzNTM4IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6ImQ3NzE4NTkxMDUwNjc1MDhlMGQ5ZTMxMWYxZDRhZTEyNmM3ZTNkMjhjMzY4OWUxNThhNjFjNmUwZGQxZTRkMjEiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiZWEzZmEzNDdjNGUxODVhNDhhY2NiMTY4NjMzNDY2ZmMyMjc4YjdkYmEzNzNiNDM1ODI1YmIzNDdiNzMxMDA3YiIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6ImVjNDZhODc5ODI0MGQwMGNkOTJkNTBjYzE5ZTVhZDE3NjUyYjJiZjJmOGQyOTlhOWVhOTNlYWE4YmE2MDgwNzgiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLmlkIn0seyJ2YWx1ZSI6ImZhYTk2NWViNjIwMmNlNDhhNjczNzRiZTA5M2VhNTJjNDRhM2JhMzZmYmNkZjBhMWY1MzZjNTZkM2NmOGVlNzMiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLnR5cGUifSx7InZhbHVlIjoiYjlkZTJiZDRkMGZjMmVlYmZkNDE1ZTcwZTRlMjYzY2Y5MDEwM2MyYzEyMTlkZDU0OGYzOWE4Y2I2NWNlYjU5YyIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udGVtcGxhdGVOYW1lIn1d", + privacy: { + obfuscated: [], + }, + key: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller", + signature: + "0x153aeb0f59bef692f1b5bec2f20fc08f72863b0a670e87ac7c68460d311fc7a574189bb92056a15f1ef283c1784303528364d2124a006de3dba586f6162df5481b", + }, + }, +] satisfies V4SignedWrappedDocument[]); + +// Freeze fixture to prevent accidental changes during tests +function freezeObject(obj: T): T { + return deepFreeze(obj) as T; +} + +function deepFreeze(obj: unknown) { + if (obj && typeof obj === "object" && !Object.isFrozen(obj)) { + Object.freeze(obj); + Object.getOwnPropertyNames(obj).forEach((prop) => deepFreeze(obj[prop as keyof typeof obj])); + } + return obj; +} diff --git a/src/4.0/jsonSchemas/__generated__/v4-document.schema.json b/src/4.0/jsonSchemas/__generated__/v4-document.schema.json new file mode 100644 index 00000000..e927c969 --- /dev/null +++ b/src/4.0/jsonSchemas/__generated__/v4-document.schema.json @@ -0,0 +1,401 @@ +{ + "$ref": "#/definitions/v4Document", + "definitions": { + "v4Document": { + "type": "object", + "properties": { + "@context": { + "type": "array", + "minItems": 2, + "items": [ + { + "type": "string", + "const": "https://www.w3.org/ns/credentials/v2" + }, + { + "type": "string", + "const": "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + } + ], + "additionalItems": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": {} + } + ] + } + }, + "name": { + "type": "string" + }, + "id": { + "type": "string", + "pattern": "^(?=.)(?!https?:\\/(?:$|[^/]))(?!https?:\\/\\/\\/)(?!https?:[^/])(?:[a-zA-Z][a-zA-Z\\d+-\\.]*:(?:(?:\\/\\/(?:[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:]*@)?(?:\\[(?:(?:(?:[\\dA-Fa-f]{1,4}:){6}(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|::(?:[\\dA-Fa-f]{1,4}:){5}(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:[\\dA-Fa-f]{1,4})?::(?:[\\dA-Fa-f]{1,4}:){4}(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:(?:[\\dA-Fa-f]{1,4}:){0,1}[\\dA-Fa-f]{1,4})?::(?:[\\dA-Fa-f]{1,4}:){3}(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:(?:[\\dA-Fa-f]{1,4}:){0,2}[\\dA-Fa-f]{1,4})?::(?:[\\dA-Fa-f]{1,4}:){2}(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:(?:[\\dA-Fa-f]{1,4}:){0,3}[\\dA-Fa-f]{1,4})?::[\\dA-Fa-f]{1,4}:(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:(?:[\\dA-Fa-f]{1,4}:){0,4}[\\dA-Fa-f]{1,4})?::(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:(?:[\\dA-Fa-f]{1,4}:){0,5}[\\dA-Fa-f]{1,4})?::[\\dA-Fa-f]{1,4}|(?:(?:[\\dA-Fa-f]{1,4}:){0,6}[\\dA-Fa-f]{1,4})?::)|v[\\dA-Fa-f]+\\.[\\w-\\.~!\\$&'\\(\\)\\*\\+,;=:]+)\\]|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])|[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=]{1,255})(?::\\d*)?(?:\\/[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]*)*)|\\/(?:[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]+(?:\\/[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]*)*)?|[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]+(?:\\/[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]*)*|(?:\\/\\/\\/[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]*(?:\\/[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]*)*)))(?:\\?[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@\\/\\?]*(?=#|$))?(?:#[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@\\/\\?]*)?$" + }, + "type": { + "type": "array", + "minItems": 2, + "items": [ + { + "type": "string", + "const": "VerifiableCredential" + }, + { + "type": "string", + "const": "OpenAttestationCredential" + } + ], + "additionalItems": { + "type": "string" + } + }, + "credentialSchema": { + "anyOf": [ + { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4Document/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": true + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4Document/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": true + } + } + ] + }, + "issuer": { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4Document/properties/id" + }, + "type": { + "type": "string", + "const": "OpenAttestationIssuer" + }, + "name": { + "type": "string" + }, + "identityProof": { + "type": "object", + "properties": { + "identityProofType": { + "type": "string", + "enum": [ + "DNS-TXT", + "DNS-DID", + "DID" + ] + }, + "identifier": { + "type": "string" + } + }, + "required": [ + "identityProofType", + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "id", + "type", + "name", + "identityProof" + ], + "additionalProperties": false + }, + "validFrom": { + "type": "string", + "format": "date-time" + }, + "validUntil": { + "type": "string", + "format": "date-time" + }, + "credentialSubject": { + "type": "object", + "properties": { + "attachments": { + "type": "array", + "items": { + "type": "object", + "properties": { + "data": { + "type": "string", + "description": "Base64 encoding of this attachment" + }, + "filename": { + "type": "string", + "minLength": 1, + "description": "Name of this attachment, with appropriate extensions" + }, + "mimeType": { + "type": "string", + "minLength": 1, + "description": "Media type (or MIME type) of this attachment" + } + }, + "required": [ + "data", + "filename", + "mimeType" + ], + "additionalProperties": false + } + } + }, + "additionalProperties": true + }, + "credentialStatus": { + "anyOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uri", + "description": "URL of the OCSP responder endpoint" + }, + "type": { + "type": "string", + "const": "OpenAttestationOcspResponder" + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^(0x)?[0-9a-fA-F]{40}$", + "description": "Ethereum address of the revocation store contract" + }, + "type": { + "type": "string", + "const": "OpenAttestationRevocationStore" + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": false + } + ] + }, + "termsOfUse": { + "anyOf": [ + { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4Document/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "type" + ], + "additionalProperties": true + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4Document/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "type" + ], + "additionalProperties": true + } + } + ] + }, + "evidence": { + "anyOf": [ + { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4Document/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "type" + ], + "additionalProperties": true + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4Document/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "type" + ], + "additionalProperties": true + } + } + ] + }, + "proof": { + "anyOf": [ + { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ], + "additionalProperties": true + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + }, + "required": [ + "type" + ], + "additionalProperties": true + } + } + ] + }, + "renderMethod": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uri", + "description": "URL of a decentralised renderer to render this document" + }, + "type": { + "type": "string", + "const": "OpenAttestationEmbeddedRenderer" + }, + "templateName": { + "type": "string" + } + }, + "required": [ + "id", + "type", + "templateName" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "format": "uri" + } + ], + "description": "A URL that dereferences to an SVG image [SVG] with an associated image/svg+xml media type. Or an embedded SVG image [SVG]" + }, + "type": { + "type": "string", + "const": "SvgRenderingTemplate2023" + }, + "name": { + "type": "string" + }, + "digestMultibase": { + "type": "string", + "description": "An optional multibase-encoded multihash of the SVG image. The multibase value MUST be z and the multihash value MUST be SHA-2 with 256-bits of output (0x12)." + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "@context", + "type", + "issuer", + "credentialSubject" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/src/4.0/jsonSchemas/__generated__/v4-signed-wrapped-document.schema.json b/src/4.0/jsonSchemas/__generated__/v4-signed-wrapped-document.schema.json new file mode 100644 index 00000000..4cced7a2 --- /dev/null +++ b/src/4.0/jsonSchemas/__generated__/v4-signed-wrapped-document.schema.json @@ -0,0 +1,432 @@ +{ + "$ref": "#/definitions/v4SignedWrappedDocument", + "definitions": { + "v4SignedWrappedDocument": { + "type": "object", + "properties": { + "@context": { + "type": "array", + "minItems": 2, + "items": [ + { + "type": "string", + "const": "https://www.w3.org/ns/credentials/v2" + }, + { + "type": "string", + "const": "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + } + ], + "additionalItems": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": {} + } + ] + } + }, + "name": { + "type": "string" + }, + "id": { + "type": "string", + "pattern": "^(?=.)(?!https?:\\/(?:$|[^/]))(?!https?:\\/\\/\\/)(?!https?:[^/])(?:[a-zA-Z][a-zA-Z\\d+-\\.]*:(?:(?:\\/\\/(?:[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:]*@)?(?:\\[(?:(?:(?:[\\dA-Fa-f]{1,4}:){6}(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|::(?:[\\dA-Fa-f]{1,4}:){5}(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:[\\dA-Fa-f]{1,4})?::(?:[\\dA-Fa-f]{1,4}:){4}(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:(?:[\\dA-Fa-f]{1,4}:){0,1}[\\dA-Fa-f]{1,4})?::(?:[\\dA-Fa-f]{1,4}:){3}(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:(?:[\\dA-Fa-f]{1,4}:){0,2}[\\dA-Fa-f]{1,4})?::(?:[\\dA-Fa-f]{1,4}:){2}(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:(?:[\\dA-Fa-f]{1,4}:){0,3}[\\dA-Fa-f]{1,4})?::[\\dA-Fa-f]{1,4}:(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:(?:[\\dA-Fa-f]{1,4}:){0,4}[\\dA-Fa-f]{1,4})?::(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:(?:[\\dA-Fa-f]{1,4}:){0,5}[\\dA-Fa-f]{1,4})?::[\\dA-Fa-f]{1,4}|(?:(?:[\\dA-Fa-f]{1,4}:){0,6}[\\dA-Fa-f]{1,4})?::)|v[\\dA-Fa-f]+\\.[\\w-\\.~!\\$&'\\(\\)\\*\\+,;=:]+)\\]|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])|[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=]{1,255})(?::\\d*)?(?:\\/[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]*)*)|\\/(?:[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]+(?:\\/[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]*)*)?|[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]+(?:\\/[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]*)*|(?:\\/\\/\\/[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]*(?:\\/[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]*)*)))(?:\\?[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@\\/\\?]*(?=#|$))?(?:#[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@\\/\\?]*)?$" + }, + "type": { + "type": "array", + "minItems": 2, + "items": [ + { + "type": "string", + "const": "VerifiableCredential" + }, + { + "type": "string", + "const": "OpenAttestationCredential" + } + ], + "additionalItems": { + "type": "string" + } + }, + "credentialSchema": { + "anyOf": [ + { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4SignedWrappedDocument/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": true + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4SignedWrappedDocument/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": true + } + } + ] + }, + "issuer": { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4SignedWrappedDocument/properties/id" + }, + "type": { + "type": "string", + "const": "OpenAttestationIssuer" + }, + "name": { + "type": "string" + }, + "identityProof": { + "type": "object", + "properties": { + "identityProofType": { + "type": "string", + "enum": [ + "DNS-TXT", + "DNS-DID", + "DID" + ] + }, + "identifier": { + "type": "string" + } + }, + "required": [ + "identityProofType", + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "id", + "type", + "name", + "identityProof" + ], + "additionalProperties": false + }, + "validFrom": { + "type": "string", + "format": "date-time" + }, + "validUntil": { + "type": "string", + "format": "date-time" + }, + "credentialSubject": { + "type": "object", + "properties": { + "attachments": { + "type": "array", + "items": { + "type": "object", + "properties": { + "data": { + "type": "string", + "description": "Base64 encoding of this attachment" + }, + "filename": { + "type": "string", + "minLength": 1, + "description": "Name of this attachment, with appropriate extensions" + }, + "mimeType": { + "type": "string", + "minLength": 1, + "description": "Media type (or MIME type) of this attachment" + } + }, + "required": [ + "data", + "filename", + "mimeType" + ], + "additionalProperties": false + } + } + }, + "additionalProperties": true + }, + "credentialStatus": { + "anyOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uri", + "description": "URL of the OCSP responder endpoint" + }, + "type": { + "type": "string", + "const": "OpenAttestationOcspResponder" + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^(0x)?[0-9a-fA-F]{40}$", + "description": "Ethereum address of the revocation store contract" + }, + "type": { + "type": "string", + "const": "OpenAttestationRevocationStore" + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": false + } + ] + }, + "termsOfUse": { + "anyOf": [ + { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4SignedWrappedDocument/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "type" + ], + "additionalProperties": true + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4SignedWrappedDocument/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "type" + ], + "additionalProperties": true + } + } + ] + }, + "evidence": { + "anyOf": [ + { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4SignedWrappedDocument/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "type" + ], + "additionalProperties": true + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4SignedWrappedDocument/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "type" + ], + "additionalProperties": true + } + } + ] + }, + "proof": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "OpenAttestationMerkleProofSignature2018" + }, + "proofPurpose": { + "type": "string", + "const": "assertionMethod" + }, + "targetHash": { + "type": "string" + }, + "proofs": { + "type": "array", + "items": { + "type": "string" + } + }, + "merkleRoot": { + "type": "string" + }, + "salts": { + "type": "string" + }, + "privacy": { + "type": "object", + "properties": { + "obfuscated": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "obfuscated" + ], + "additionalProperties": false + }, + "key": { + "type": "string" + }, + "signature": { + "type": "string" + } + }, + "required": [ + "type", + "proofPurpose", + "targetHash", + "proofs", + "merkleRoot", + "salts", + "privacy", + "key", + "signature" + ], + "additionalProperties": false + }, + "renderMethod": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uri", + "description": "URL of a decentralised renderer to render this document" + }, + "type": { + "type": "string", + "const": "OpenAttestationEmbeddedRenderer" + }, + "templateName": { + "type": "string" + } + }, + "required": [ + "id", + "type", + "templateName" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "format": "uri" + } + ], + "description": "A URL that dereferences to an SVG image [SVG] with an associated image/svg+xml media type. Or an embedded SVG image [SVG]" + }, + "type": { + "type": "string", + "const": "SvgRenderingTemplate2023" + }, + "name": { + "type": "string" + }, + "digestMultibase": { + "type": "string", + "description": "An optional multibase-encoded multihash of the SVG image. The multibase value MUST be z and the multihash value MUST be SHA-2 with 256-bits of output (0x12)." + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "@context", + "type", + "issuer", + "credentialSubject", + "proof" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/src/4.0/jsonSchemas/__generated__/v4-wrapped-document.schema.json b/src/4.0/jsonSchemas/__generated__/v4-wrapped-document.schema.json new file mode 100644 index 00000000..7eb3e61b --- /dev/null +++ b/src/4.0/jsonSchemas/__generated__/v4-wrapped-document.schema.json @@ -0,0 +1,424 @@ +{ + "$ref": "#/definitions/v4WrappedDocument", + "definitions": { + "v4WrappedDocument": { + "type": "object", + "properties": { + "@context": { + "type": "array", + "minItems": 2, + "items": [ + { + "type": "string", + "const": "https://www.w3.org/ns/credentials/v2" + }, + { + "type": "string", + "const": "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + } + ], + "additionalItems": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "object", + "additionalProperties": {} + } + ] + } + }, + "name": { + "type": "string" + }, + "id": { + "type": "string", + "pattern": "^(?=.)(?!https?:\\/(?:$|[^/]))(?!https?:\\/\\/\\/)(?!https?:[^/])(?:[a-zA-Z][a-zA-Z\\d+-\\.]*:(?:(?:\\/\\/(?:[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:]*@)?(?:\\[(?:(?:(?:[\\dA-Fa-f]{1,4}:){6}(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|::(?:[\\dA-Fa-f]{1,4}:){5}(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:[\\dA-Fa-f]{1,4})?::(?:[\\dA-Fa-f]{1,4}:){4}(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:(?:[\\dA-Fa-f]{1,4}:){0,1}[\\dA-Fa-f]{1,4})?::(?:[\\dA-Fa-f]{1,4}:){3}(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:(?:[\\dA-Fa-f]{1,4}:){0,2}[\\dA-Fa-f]{1,4})?::(?:[\\dA-Fa-f]{1,4}:){2}(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:(?:[\\dA-Fa-f]{1,4}:){0,3}[\\dA-Fa-f]{1,4})?::[\\dA-Fa-f]{1,4}:(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:(?:[\\dA-Fa-f]{1,4}:){0,4}[\\dA-Fa-f]{1,4})?::(?:[\\dA-Fa-f]{1,4}:[\\dA-Fa-f]{1,4}|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|(?:(?:[\\dA-Fa-f]{1,4}:){0,5}[\\dA-Fa-f]{1,4})?::[\\dA-Fa-f]{1,4}|(?:(?:[\\dA-Fa-f]{1,4}:){0,6}[\\dA-Fa-f]{1,4})?::)|v[\\dA-Fa-f]+\\.[\\w-\\.~!\\$&'\\(\\)\\*\\+,;=:]+)\\]|(?:(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:0{0,2}\\d|0?[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])|[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=]{1,255})(?::\\d*)?(?:\\/[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]*)*)|\\/(?:[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]+(?:\\/[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]*)*)?|[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]+(?:\\/[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]*)*|(?:\\/\\/\\/[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]*(?:\\/[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@]*)*)))(?:\\?[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@\\/\\?]*(?=#|$))?(?:#[\\w-\\.~%\\dA-Fa-f!\\$&'\\(\\)\\*\\+,;=:@\\/\\?]*)?$" + }, + "type": { + "type": "array", + "minItems": 2, + "items": [ + { + "type": "string", + "const": "VerifiableCredential" + }, + { + "type": "string", + "const": "OpenAttestationCredential" + } + ], + "additionalItems": { + "type": "string" + } + }, + "credentialSchema": { + "anyOf": [ + { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4WrappedDocument/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": true + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4WrappedDocument/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": true + } + } + ] + }, + "issuer": { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4WrappedDocument/properties/id" + }, + "type": { + "type": "string", + "const": "OpenAttestationIssuer" + }, + "name": { + "type": "string" + }, + "identityProof": { + "type": "object", + "properties": { + "identityProofType": { + "type": "string", + "enum": [ + "DNS-TXT", + "DNS-DID", + "DID" + ] + }, + "identifier": { + "type": "string" + } + }, + "required": [ + "identityProofType", + "identifier" + ], + "additionalProperties": false + } + }, + "required": [ + "id", + "type", + "name", + "identityProof" + ], + "additionalProperties": false + }, + "validFrom": { + "type": "string", + "format": "date-time" + }, + "validUntil": { + "type": "string", + "format": "date-time" + }, + "credentialSubject": { + "type": "object", + "properties": { + "attachments": { + "type": "array", + "items": { + "type": "object", + "properties": { + "data": { + "type": "string", + "description": "Base64 encoding of this attachment" + }, + "filename": { + "type": "string", + "minLength": 1, + "description": "Name of this attachment, with appropriate extensions" + }, + "mimeType": { + "type": "string", + "minLength": 1, + "description": "Media type (or MIME type) of this attachment" + } + }, + "required": [ + "data", + "filename", + "mimeType" + ], + "additionalProperties": false + } + } + }, + "additionalProperties": true + }, + "credentialStatus": { + "anyOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uri", + "description": "URL of the OCSP responder endpoint" + }, + "type": { + "type": "string", + "const": "OpenAttestationOcspResponder" + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^(0x)?[0-9a-fA-F]{40}$", + "description": "Ethereum address of the revocation store contract" + }, + "type": { + "type": "string", + "const": "OpenAttestationRevocationStore" + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": false + } + ] + }, + "termsOfUse": { + "anyOf": [ + { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4WrappedDocument/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "type" + ], + "additionalProperties": true + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4WrappedDocument/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "type" + ], + "additionalProperties": true + } + } + ] + }, + "evidence": { + "anyOf": [ + { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4WrappedDocument/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "type" + ], + "additionalProperties": true + }, + { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "#/definitions/v4WrappedDocument/properties/id" + }, + "type": { + "type": "string" + } + }, + "required": [ + "type" + ], + "additionalProperties": true + } + } + ] + }, + "proof": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "OpenAttestationMerkleProofSignature2018" + }, + "proofPurpose": { + "type": "string", + "const": "assertionMethod" + }, + "targetHash": { + "type": "string" + }, + "proofs": { + "type": "array", + "items": { + "type": "string" + } + }, + "merkleRoot": { + "type": "string" + }, + "salts": { + "type": "string" + }, + "privacy": { + "type": "object", + "properties": { + "obfuscated": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "obfuscated" + ], + "additionalProperties": false + } + }, + "required": [ + "type", + "proofPurpose", + "targetHash", + "proofs", + "merkleRoot", + "salts", + "privacy" + ], + "additionalProperties": true + }, + "renderMethod": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uri", + "description": "URL of a decentralised renderer to render this document" + }, + "type": { + "type": "string", + "const": "OpenAttestationEmbeddedRenderer" + }, + "templateName": { + "type": "string" + } + }, + "required": [ + "id", + "type", + "templateName" + ], + "additionalProperties": false + }, + { + "type": "object", + "properties": { + "id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "string", + "format": "uri" + } + ], + "description": "A URL that dereferences to an SVG image [SVG] with an associated image/svg+xml media type. Or an embedded SVG image [SVG]" + }, + "type": { + "type": "string", + "const": "SvgRenderingTemplate2023" + }, + "name": { + "type": "string" + }, + "digestMultibase": { + "type": "string", + "description": "An optional multibase-encoded multihash of the SVG image. The multibase value MUST be z and the multihash value MUST be SHA-2 with 256-bits of output (0x12)." + } + }, + "required": [ + "id", + "type" + ], + "additionalProperties": false + } + ] + } + } + }, + "required": [ + "@context", + "type", + "issuer", + "credentialSubject", + "proof" + ], + "additionalProperties": false + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" +} \ No newline at end of file diff --git a/src/4.0/obfuscate.ts b/src/4.0/obfuscate.ts new file mode 100644 index 00000000..a6519c3b --- /dev/null +++ b/src/4.0/obfuscate.ts @@ -0,0 +1,140 @@ +import { cloneDeep, get, unset, pick, toPath } from "lodash"; +import { decodeSalt, encodeSalt } from "./salt"; +import { traverseAndFlatten } from "./traverseAndFlatten"; +import { Override, PartialDeep, V4SignedWrappedDocument, V4WrappedDocument } from "./types"; +import { hashLeafNode } from "./digest"; + +const obfuscate = (_data: V4WrappedDocument, fields: string[] | string) => { + const data = cloneDeep(_data); // Prevents alteration of original data + const fieldsAsArray = ([] as string[]).concat(fields); + + // fields to remove will contain the list of each expanded keys from the fields passed in parameter, it's for instance useful in case of + // object obfuscation, where the object itself is not part of the salts, but each individual keys are + const toBeRemovedLeafNodes = traverseAndFlatten(pick(data, fieldsAsArray), ({ path }) => path); + const salts = decodeSalt(data.proof.salts); + + const obfuscatedData = toBeRemovedLeafNodes.map((field) => { + const value = get(data, field); + const salt = salts.find((s) => s.path === field); + + if (!salt) { + throw new Error(`Salt not found for ${field}`); + } + + return hashLeafNode({ value, salt: salt.value, path: salt.path }, { toHexString: true }); + }); + + // remove fields from the object + for (const field of fieldsAsArray) { + const path = toPath(field); + const isRemoved = unset(data, path); + if (isRemoved) { + // assertions to ensure that obfuscation does not result in additional leaf nodes + // that would render the resultant document as invalid + path.pop(); + if (path.length > 0) { + const parent = get(data, path); + if (Array.isArray(parent)) { + // Why removing elements in an array is not supported? + // removing an item from an array leaves an empty item/undefined in the array + // but when serialized to JSON, empty items are converted to null + // null is a leaf node and will lead to a problem similar to what is described below + throw new CannotObfuscateArrayItemError(field); + } else if (typeof parent === "object") { + // Why removing elements that lead to empty objects is not supported? + // our obfucsation algoritm works as such: + // given an object { a: { b: 1 }, c: [{ d: 2, e: 3 }] } + // the leaf nodes will be [a.b, c[0].d, c[0].e] + // and the hash, lets call it X, is computed over these leaf nodes + // when we obfuscate say c[0].d, we prehash c[0].d and add it to obfuscatedData and remove c[0].d from the object + // now the hash is computed over [a.b, c[0].e] and prehash(c[0].d) and still equates to X + // the problem comes when we remove both c[0].d and c[0].e, or a.b, which in both cases leaves an empty object behind + // empty objects are considered leaf nodes. so given we obfuscate a.b, a will be an empty object, a leaf node + // the hash now is computed over [a, c[0].d, c[0].e] and prehash(a.b), which does not equate to X + if (Object.keys(parent).length === 0) { + throw new CannotResultInEmptyObjectError(field); + } + } + } + } + } + + data.proof.salts = encodeSalt(salts.filter((s) => !toBeRemovedLeafNodes.includes(s.path))); + return { + data, + obfuscatedData, + }; +}; + +export type ObfuscateVerifiableCredentialResult = Override< + T, + { + credentialSubject: Override< + PartialDeep, + { + attachments?: T["credentialSubject"]["attachments"] extends Array + ? T["credentialSubject"]["attachments"] + : undefined; + } + >; + } +>; +export const obfuscateVerifiableCredential = ( + document: T, + fields: string[] | string +): ObfuscateVerifiableCredentialResult => { + const { data, obfuscatedData } = obfuscate(document, fields); + const currentObfuscatedData = document.proof.privacy.obfuscated; + const newObfuscatedData = currentObfuscatedData.concat(obfuscatedData); + + // assert that obfuscated is still compliant to our schema + const parsedResults = V4WrappedDocument.safeParse({ + ...data, + proof: { + ...data.proof, + privacy: { + ...data.proof.privacy, + obfuscated: newObfuscatedData, + }, + }, + }); + if (!parsedResults.success) { + const paths = parsedResults.error.errors.map(({ path }) => path.join(".")); + throw new CannotObfuscateProtectedPathsError(paths); + } + return parsedResults.data as ObfuscateVerifiableCredentialResult; +}; + +class CannotObfuscateProtectedPathsError extends Error { + constructor(public paths: string[]) { + super( + `The resultant obfuscated document is not V4 Wrapped Document compliant, please ensure that the following path(s) are not obfuscated: ${paths + .map((val) => `"${val}"`) + .join(", ")}` + ); + // https://www.dannyguo.com/blog/how-to-fix-instanceof-not-working-for-custom-errors-in-typescript + Object.setPrototypeOf(this, CannotObfuscateProtectedPathsError.prototype); + } +} + +class CannotObfuscateArrayItemError extends Error { + constructor(public field: string) { + super("Obfuscation of an array item is not supported"); + Object.setPrototypeOf(this, CannotObfuscateArrayItemError.prototype); + } +} + +class CannotResultInEmptyObjectError extends Error { + constructor(public field: string) { + super( + `Obfuscation of "${field}" has resulted in an empty {}, this is currently not supported. Alternatively, if the object is not part of an array, you may choose to obfuscate the parent of "${field}".` + ); + Object.setPrototypeOf(this, CannotResultInEmptyObjectError.prototype); + } +} + +export const obfuscateErrors = { + CannotObfuscateProtectedPathsError, + CannotObfuscateArrayItemError, + CannotResultInEmptyObjectError, +}; diff --git a/src/4.0/salt.ts b/src/4.0/salt.ts new file mode 100644 index 00000000..5de5a92d --- /dev/null +++ b/src/4.0/salt.ts @@ -0,0 +1,39 @@ +import { Salt } from "./types"; +import { Base64 } from "js-base64"; +import { traverseAndFlatten } from "./traverseAndFlatten"; +import randomBytes from "randombytes"; + +const ENTROPY_IN_BYTES = 32; + +const illegalCharactersCheck = (data: Record) => { + Object.entries(data).forEach(([key, value]) => { + if (key.includes(".")) { + throw new Error("Key names must not have . in them"); + } + if (key.includes("[") || key.includes("]")) { + throw new Error("Key names must not have '[' or ']' in them"); + } + if (value && typeof value === "object") { + return illegalCharactersCheck(value); // Recursively search if property contains sub-properties + } + }); +}; + +// Using 32 bytes of entropy as compared to 16 bytes in uuid +// Using hex encoding as compared to base64 for constant string length +export const secureRandomString = () => randomBytes(ENTROPY_IN_BYTES).toString("hex"); + +export const salt = (data: any): Salt[] => { + // Check for illegal characters e.g. '.', '[' or ']' + illegalCharactersCheck(data); + return traverseAndFlatten(data, ({ path }) => ({ value: secureRandomString(), path })); +}; + +export const encodeSalt = (salts: Salt[]): string => Base64.encode(JSON.stringify(salts)); +export const decodeSalt = (salts: string): Salt[] => { + const decoded: Salt[] = JSON.parse(Base64.decode(salts)); + decoded.forEach((salt) => { + if (salt.value.length !== ENTROPY_IN_BYTES * 2) throw new Error(`Salt must be ${ENTROPY_IN_BYTES} bytes`); + }); + return decoded; +}; diff --git a/src/4.0/sign.ts b/src/4.0/sign.ts new file mode 100644 index 00000000..93c69d9e --- /dev/null +++ b/src/4.0/sign.ts @@ -0,0 +1,57 @@ +import { sign } from "../shared/signer"; +import { SigningKey } from "../shared/@types/sign"; +import { ethers } from "ethers"; +import { V4OpenAttestationDocument, V4WrappedDocument, V4SignedWrappedDocument } from "./types"; +import type { ZodError } from "zod"; + +export const signDocument = async ( + document: V4SignedWrappedDocument | V4WrappedDocument, + algorithm: "Secp256k1VerificationKey2018", + keyOrSigner: SigningKey | ethers.Signer +): Promise> => { + const parsedResults = V4WrappedDocument.pick({ proof: true }).passthrough().safeParse(document); + if (!parsedResults.success) { + throw new WrappedDocumentValidationError(parsedResults.error); + } + + if (!SigningKey.guard(keyOrSigner) && keyOrSigner.signMessage === undefined) { + throw new Error(`Either a keypair or ethers.js Signer must be provided`); + } + + const { proof: validatedProof } = parsedResults.data; + const merkleRoot = `0x${validatedProof.merkleRoot}`; + + try { + const signature = await sign(algorithm, merkleRoot, keyOrSigner); + const proof: V4SignedWrappedDocument["proof"] = { + ...validatedProof, + key: "public" in keyOrSigner ? keyOrSigner.public : `did:ethr:${await keyOrSigner.getAddress()}#controller`, + signature, + }; + return { ...document, proof }; + } catch (error) { + throw new CouldNotSignDocumentError(error); + } +}; + +class WrappedDocumentValidationError extends Error { + constructor(public error: ZodError) { + super(`Document has not been properly wrapped:\n${JSON.stringify(error.format(), null, 2)}`); + Object.setPrototypeOf(this, WrappedDocumentValidationError.prototype); + } +} + +/** + * Cases where this can be thrown includes: network error, invalid keys or signer + */ +class CouldNotSignDocumentError extends Error { + constructor(public error: unknown) { + super(`Could not sign document:\n${error instanceof Error ? error.message : JSON.stringify(error, null, 2)}`); + Object.setPrototypeOf(this, CouldNotSignDocumentError.prototype); + } +} + +export const signDocumentErrors = { + WrappedDocumentValidationError, + CouldNotSignDocumentError, +}; diff --git a/src/4.0/traverseAndFlatten.ts b/src/4.0/traverseAndFlatten.ts new file mode 100644 index 00000000..53a39f49 --- /dev/null +++ b/src/4.0/traverseAndFlatten.ts @@ -0,0 +1,51 @@ +export type LeafValue = string | number | boolean | null | Record | []; + +function _traverseAndFlatten( + data: unknown, + iteratee: (data: { value: LeafValue; path: string }) => IterateeValue, + path = "" +): IterateeValue | IterateeValue[] { + if (Array.isArray(data)) { + // an empty array is considered a leaf node + if (data.length === 0) return iteratee({ value: [], path }); + + // dont use flat map as it skips empty items in the array + const results: IterateeValue[] = []; + for (let index = 0; index < data.length; index++) { + const value = data[index]; + const result = _traverseAndFlatten(value, iteratee, `${path}[${index}]`); + if (Array.isArray(result)) { + results.push(...result); + } else { + results.push(result); + } + } + + return results; + } + + if (typeof data === "object" && data !== null) { + const keys = Object.keys(data); + // an empty object is considered a leaf node + if (keys.length === 0) return iteratee({ value: {}, path }); + return Object.keys(data).flatMap((key) => + _traverseAndFlatten(data[key as keyof typeof data], iteratee, path ? `${path}.${key}` : key) + ); + } + + if (typeof data === "string" || typeof data === "number" || typeof data === "boolean" || data === null) { + return iteratee({ value: data, path }); + } + + throw new Error(`Unexpected data '${data}' in '${path}'`); +} + +/** Given a record, returns a list of all leaf nodes of value that is not undefined */ +export function traverseAndFlatten( + data: Record, + iteratee: (data: { value: LeafValue; path: string }) => IterateeValue, + path = "" +): IterateeValue[] { + const results = _traverseAndFlatten(data, iteratee, path); + return Array.isArray(results) ? results : []; +} diff --git a/src/4.0/types.ts b/src/4.0/types.ts new file mode 100644 index 00000000..5fc3ed2b --- /dev/null +++ b/src/4.0/types.ts @@ -0,0 +1,329 @@ +import z from "zod"; +import { ContextUrl, ContextType } from "./context"; + +// Custom URI validation function +const URI_REGEX = + /^(?=.)(?!https?:\/(?:$|[^/]))(?!https?:\/\/\/)(?!https?:[^/])(?:[a-zA-Z][a-zA-Z\d+-\.]*:(?:(?:\/\/(?:[\w-\.~%\dA-Fa-f!\$&'\(\)\*\+,;=:]*@)?(?:\[(?:(?:(?:[\dA-Fa-f]{1,4}:){6}(?:[\dA-Fa-f]{1,4}:[\dA-Fa-f]{1,4}|(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|::(?:[\dA-Fa-f]{1,4}:){5}(?:[\dA-Fa-f]{1,4}:[\dA-Fa-f]{1,4}|(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(?:[\dA-Fa-f]{1,4})?::(?:[\dA-Fa-f]{1,4}:){4}(?:[\dA-Fa-f]{1,4}:[\dA-Fa-f]{1,4}|(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(?:(?:[\dA-Fa-f]{1,4}:){0,1}[\dA-Fa-f]{1,4})?::(?:[\dA-Fa-f]{1,4}:){3}(?:[\dA-Fa-f]{1,4}:[\dA-Fa-f]{1,4}|(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(?:(?:[\dA-Fa-f]{1,4}:){0,2}[\dA-Fa-f]{1,4})?::(?:[\dA-Fa-f]{1,4}:){2}(?:[\dA-Fa-f]{1,4}:[\dA-Fa-f]{1,4}|(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(?:(?:[\dA-Fa-f]{1,4}:){0,3}[\dA-Fa-f]{1,4})?::[\dA-Fa-f]{1,4}:(?:[\dA-Fa-f]{1,4}:[\dA-Fa-f]{1,4}|(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(?:(?:[\dA-Fa-f]{1,4}:){0,4}[\dA-Fa-f]{1,4})?::(?:[\dA-Fa-f]{1,4}:[\dA-Fa-f]{1,4}|(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(?:(?:[\dA-Fa-f]{1,4}:){0,5}[\dA-Fa-f]{1,4})?::[\dA-Fa-f]{1,4}|(?:(?:[\dA-Fa-f]{1,4}:){0,6}[\dA-Fa-f]{1,4})?::)|v[\dA-Fa-f]+\.[\w-\.~!\$&'\(\)\*\+,;=:]+)\]|(?:(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:0{0,2}\d|0?[1-9]\d|1\d\d|2[0-4]\d|25[0-5])|[\w-\.~%\dA-Fa-f!\$&'\(\)\*\+,;=]{1,255})(?::\d*)?(?:\/[\w-\.~%\dA-Fa-f!\$&'\(\)\*\+,;=:@]*)*)|\/(?:[\w-\.~%\dA-Fa-f!\$&'\(\)\*\+,;=:@]+(?:\/[\w-\.~%\dA-Fa-f!\$&'\(\)\*\+,;=:@]*)*)?|[\w-\.~%\dA-Fa-f!\$&'\(\)\*\+,;=:@]+(?:\/[\w-\.~%\dA-Fa-f!\$&'\(\)\*\+,;=:@]*)*|(?:\/\/\/[\w-\.~%\dA-Fa-f!\$&'\(\)\*\+,;=:@]*(?:\/[\w-\.~%\dA-Fa-f!\$&'\(\)\*\+,;=:@]*)*)))(?:\?[\w-\.~%\dA-Fa-f!\$&'\(\)\*\+,;=:@\/\?]*(?=#|$))?(?:#[\w-\.~%\dA-Fa-f!\$&'\(\)\*\+,;=:@\/\?]*)?$/; +const Uri = z.string().regex(URI_REGEX, { message: "Invalid URI" }); +const ETHEREUM_ADDRESS_REGEX = /^(0x)?[0-9a-fA-F]{40}$/; +const EthereumAddress = z.string().regex(ETHEREUM_ADDRESS_REGEX, { message: "Invalid Ethereum address" }); + +const _W3cVerifiableCredential = z.object({ + "@context": z.union([ + z.record(z.any()), + z.string(), + // If array: First item must be baseContext, while remaining items can be string or object + z.tuple([z.literal(ContextUrl.v2_vc)]).rest(z.union([z.string(), z.record(z.any())])), + ]), + + // [Optional] + name: z.string().optional(), + + // [Optional] If string: Must match uri pattern + id: Uri.optional(), + + type: z.union([ + z.string(), + // If array: Must have VerifiableCredential, while remaining items can be any string + z.array(z.string()).refine((types) => types.includes(ContextType.BaseContext), { + message: `Type must include ${ContextType.BaseContext}`, + }), + ]), + + credentialSchema: z + .union([ + // If object: Must have id match uri pattern and type defined + z + .object({ + id: Uri, + type: z.string(), + }) + .passthrough(), + // If array: Every object must have id match uri pattern and type defined + z.array( + z + .object({ + id: Uri, + type: z.string(), + }) + .passthrough() + ), + ]) + .optional(), + + issuer: z.union([ + // If string: Must match uri pattern + Uri, + // If object: Must have id match uri pattern + z + .object({ + id: Uri, + }) + .passthrough(), + ]), + + validFrom: z.string().datetime({ offset: true }).optional(), + + validUntil: z.string().datetime({ offset: true }).optional(), + + credentialSubject: z.union([ + // If object: Cannot be empty (i.e. minimum 1 key) + z.record(z.any()).refine((obj) => Object.keys(obj).length > 0, { + message: "Must have at least one key", + }), + // If array: Every object cannot be empty (i.e. minimum 1 key) + z.array( + z.record(z.any()).refine((obj) => Object.keys(obj).length > 0, { + message: "Must have at least one key", + }) + ), + ]), + + credentialStatus: z + .object({ + // If id is present, id must match uri pattern (credentialStatus.id is optional and can be undefined) + id: Uri.optional(), + // Must have type defined + type: z.string(), + }) + .passthrough() + .optional(), + + termsOfUse: z + .union([ + // If object: Must have type defined. If id is present, id must match uri pattern (termsOfUse.id is optional and can be undefined) + z + .object({ + id: Uri.optional(), + type: z.string(), + }) + .passthrough(), + // If array: Every object must have type defined. If id is present, id must match uri pattern (termsOfUse.id is optional and can be undefined) + z.array( + z + .object({ + id: Uri.optional(), + type: z.string(), + }) + .passthrough() + ), + ]) + .optional(), + + evidence: z + .union([ + // If object: Must have type defined. If id is present, id must match uri pattern (evidence.id is optional and can be undefined) + z + .object({ + id: Uri.optional(), + type: z.string(), + }) + .passthrough(), + // If array: Every object must have type defined. If id is present, id must match uri pattern (evidence.id is optional and can be undefined) + z.array( + z + .object({ + id: Uri.optional(), + type: z.string(), + }) + .passthrough() + ), + ]) + .optional(), + + proof: z + .union([ + // If object: Must have type defined + z + .object({ + type: z.string(), + }) + .passthrough(), + // If array: Every object must have type defined + z.array( + z + .object({ + type: z.string(), + }) + .passthrough() + ), + ]) + .optional(), +}); +// W3cVerifiableCredential should always allow extra root properties +export const W3cVerifiableCredential = _W3cVerifiableCredential.passthrough(); + +const IdentityProofType = z.union([z.literal("DNS-TXT"), z.literal("DNS-DID"), z.literal("DID")]); +const Salt = z.object({ value: z.string(), path: z.string() }); + +export const DecentralisedEmbeddedRenderer = z.object({ + // Must have id match url pattern + id: z.string().url().describe("URL of a decentralised renderer to render this document"), + type: z.literal("OpenAttestationEmbeddedRenderer"), + templateName: z.string(), +}); + +export const SvgRenderer = z.object({ + // Must have id match url pattern or embeded SVG string + id: z + .union([z.string(), z.string().url()]) + .describe( + "A URL that dereferences to an SVG image [SVG] with an associated image/svg+xml media type. Or an embedded SVG image [SVG]" + ), + type: z.literal("SvgRenderingTemplate2023"), + name: z.string().optional(), + digestMultibase: z + .string() + .describe( + "An optional multibase-encoded multihash of the SVG image. The multibase value MUST be z and the multihash value MUST be SHA-2 with 256-bits of output (0x12)." + ) + .optional(), +}); + +export const OscpResponderRevocation = z.object({ + // Must have id match url pattern (OCSP endpoint) + id: z.string().url().describe("URL of the OCSP responder endpoint"), + type: z.literal("OpenAttestationOcspResponder"), +}); + +// [Optional] Attachments +export const Attachment = z.object({ + data: z.string().describe("Base64 encoding of this attachment"), + filename: z.string().min(1).describe("Name of this attachment, with appropriate extensions"), + mimeType: z.string().min(1).describe("Media type (or MIME type) of this attachment"), +}); + +export const RevocationStoreRevocation = z.object({ + id: EthereumAddress.describe("Ethereum address of the revocation store contract"), + type: z.literal("OpenAttestationRevocationStore"), +}); + +export const V4OpenAttestationDocument = _W3cVerifiableCredential + .extend({ + "@context": z + + // Must be an array that starts with [baseContext, v4Context, ...] + .tuple([z.literal(ContextUrl.v2_vc), z.literal(ContextUrl.v4_alpha)]) + // Remaining items can be string or object + .rest(z.union([z.string(), z.record(z.any())])), + + type: z + // Must be an array that starts with [VerifiableCredential, OpenAttestationCredential, ...] + .tuple([z.literal(ContextType.BaseContext), z.literal(ContextType.V4AlphaContext)]) + // Remaining items can be string + .rest(z.string()), + + issuer: z.object({ + // Must have id match uri pattern + id: Uri, + type: z.literal("OpenAttestationIssuer"), + name: z.string(), + identityProof: z.object({ + identityProofType: IdentityProofType, + identifier: z.string(), + }), + }), + + credentialSubject: z + .object({ + attachments: z.array(Attachment).optional(), + }) + .passthrough() + .refine((obj) => Object.keys(obj).length > 0, { + message: "Must have at least one key", + }), + + // [Optional] Credential Status + credentialStatus: z.discriminatedUnion("type", [OscpResponderRevocation, RevocationStoreRevocation]).optional(), + + // [Optional] Render Method + renderMethod: z.array(z.discriminatedUnion("type", [DecentralisedEmbeddedRenderer, SvgRenderer])).optional(), + }) + .strict(); + +const WrappedProof = z.object({ + type: z.literal("OpenAttestationMerkleProofSignature2018"), + proofPurpose: z.literal("assertionMethod"), + targetHash: z.string(), + proofs: z.array(z.string()), + merkleRoot: z.string(), + salts: z.string(), + privacy: z.object({ obfuscated: z.array(z.string()) }), +}); +const WrappedDocumentExtrasShape = { proof: WrappedProof.passthrough() } as const; +// V4WrappedDocument should never allow extra root properties +export const V4WrappedDocument = V4OpenAttestationDocument.extend(WrappedDocumentExtrasShape).strict(); + +const SignedWrappedProof = WrappedProof.extend({ key: z.string(), signature: z.string() }); +const SignedWrappedDocumentExtrasShape = { proof: SignedWrappedProof } as const; +// V4SignedWrappedDocument should never allow extra root properties +export const V4SignedWrappedDocument = V4OpenAttestationDocument.extend(SignedWrappedDocumentExtrasShape).strict(); + +export type W3cVerifiableCredential = z.infer; + +// AssertStricterOrEqual is used to ensure that we have zod extended from the base type while +// still being assignable to the base type. For example, if we accidentally extend and +// replaced '@context' to a boolean, this would fail the assertion. +export type V4OpenAttestationDocument = AssertStricterOrEqual< + W3cVerifiableCredential, + z.infer +>; + +export type V4WrappedDocument = Override< + T, + Pick, keyof typeof WrappedDocumentExtrasShape> +>; + +export type V4SignedWrappedDocument = Override< + T, + Pick, keyof typeof SignedWrappedDocumentExtrasShape> +>; + +type IdentityProofType = z.infer; + +export type Salt = z.infer; + +// Utility types +/** Overrides properties in the Target (a & b does not override a props with b props) */ +export type Override, OverrideWith extends Record> = Omit< + Target, + keyof OverrideWith +> & + OverrideWith; + +/** Used to assert that StricterType is a stricter or equal version of LooserType, and most importantly, that + * StricterType is STILL assignable to LooserType. */ +type AssertStricterOrEqual = StricterType extends LooserType ? StricterType : never; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export type NoExtraProperties = NewObj extends Reference & infer _ExtraProps ? Reference : NewObj; + +export type PartialDeep = T extends string | number | bigint | boolean | null | undefined | symbol | Date + ? T | undefined + : T extends Array + ? Array> + : T extends ReadonlyArray + ? ReadonlyArray + : T extends Set + ? Set> + : T extends ReadonlySet + ? ReadonlySet + : T extends Map + ? Map, PartialDeep> + : T extends ReadonlyMap + ? ReadonlyMap, PartialDeep> + : { + [K in keyof T]?: PartialDeep; + }; + +export const isV4OpenAttestationDocument = (document: unknown): document is V4OpenAttestationDocument => { + return V4OpenAttestationDocument.safeParse(document).success; +}; + +export const isV4WrappedDocument = (document: unknown): document is V4WrappedDocument => { + return V4WrappedDocument.safeParse(document).success; +}; + +export const isV4SignedWrappedDocument = (document: unknown): document is V4SignedWrappedDocument => { + return V4SignedWrappedDocument.safeParse(document).success; +}; diff --git a/src/4.0/verify.ts b/src/4.0/verify.ts new file mode 100644 index 00000000..2f07b64e --- /dev/null +++ b/src/4.0/verify.ts @@ -0,0 +1,30 @@ +import { V4WrappedDocument } from "./types"; +import { SaltNotFoundError, digestCredential } from "./digest"; +import { checkProof } from "../shared/merkle"; +import { decodeSalt } from "./salt"; + +export const verify = (document: T): document is T => { + if (!document.proof) { + return false; + } + + // Remove proof from document + // eslint-disable-next-line no-unused-vars,@typescript-eslint/no-unused-vars + const { proof, ...documentWithoutProof } = document; + const decodedSalts = decodeSalt(document.proof.salts); + + // Checks target hash + try { + const digest = digestCredential(documentWithoutProof, decodedSalts, document.proof.privacy.obfuscated); + const targetHash = document.proof.targetHash; + if (digest !== targetHash) return false; + + // Calculates merkle root from target hash and proof, then compare to merkle root in document + return checkProof(document.proof.proofs, document.proof.merkleRoot, document.proof.targetHash); + } catch (error: unknown) { + if (error instanceof SaltNotFoundError) { + return false; + } + throw error; + } +}; diff --git a/src/4.0/wrap.ts b/src/4.0/wrap.ts new file mode 100644 index 00000000..407b1627 --- /dev/null +++ b/src/4.0/wrap.ts @@ -0,0 +1,160 @@ +import { hashToBuffer } from "../shared/utils/hashing"; +import { MerkleTree } from "../shared/merkle"; +import { ContextUrl, ContextType, UnableToInterpretContextError, interpretContexts } from "./context"; +import { NoExtraProperties, V4OpenAttestationDocument, V4WrappedDocument, W3cVerifiableCredential } from "./types"; +import { digestCredential } from "../4.0/digest"; +import { encodeSalt, salt } from "./salt"; +import { ZodError } from "zod"; + +export const wrapDocument = async ( + // NoExtraProperties prevents the user from passing in a document with extra properties, which is more aligned to our validation strategy of strict + document: NoExtraProperties +): Promise> => { + /* 1a. try OpenAttestation VC validation, since most user will be issuing oa v4*/ + const oav4context = await V4OpenAttestationDocument.pick({ "@context": true }).passthrough().safeParseAsync(document); // Superficial check on user intention + let validatedRawDocument: W3cVerifiableCredential | undefined; + if (oav4context.success) { + const oav4 = await V4OpenAttestationDocument.safeParseAsync(document); + if (!oav4.success) { + throw new DataModelValidationError("Open Attestation v4.0", oav4.error); + } + validatedRawDocument = oav4.data; + } + + /* 1b. only if OA VC validation fail do we continue with W3C VC data model validation */ + if (!validatedRawDocument) { + const vc = await W3cVerifiableCredential.safeParseAsync(document); + if (!vc.success) { + throw new DataModelValidationError("Verifiable Credentials v2.0", vc.error); + } + validatedRawDocument = vc.data; + } + + /* 2. Ensure provided @context are interpretable (e.g. valid @context URL, all types are mapped, etc.) */ + await interpretContexts(validatedRawDocument); + + /* 3. Context validation */ + // Ensure that required contexts are present and in the correct order + // type: [Base, OA, ...] + const REQUIRED_CONTEXTS = [ContextUrl.v2_vc, ContextUrl.v4_alpha] as const; + const contexts = new Set(REQUIRED_CONTEXTS); + if (typeof validatedRawDocument["@context"] === "string") { + contexts.add(validatedRawDocument["@context"]); + } else if (isStringArray(validatedRawDocument["@context"])) { + validatedRawDocument["@context"].forEach((context) => contexts.add(context)); + } + REQUIRED_CONTEXTS.forEach((c) => contexts.delete(c)); + const finalContexts: V4OpenAttestationDocument["@context"] = [...REQUIRED_CONTEXTS, ...Array.from(contexts)]; + + /* 4. Type validation */ + // Ensure that required types are present and in the correct order + // type: ["VerifiableCredential", "OpenAttestationCredential", ...] + const REQUIRED_TYPES = [ContextType.BaseContext, ContextType.V4AlphaContext] as const; + const types = new Set([ContextType.BaseContext, ContextType.V4AlphaContext]); + if (typeof validatedRawDocument["type"] === "string") { + types.add(validatedRawDocument["type"]); + } else if (isStringArray(validatedRawDocument["type"])) { + types.forEach((type) => types.add(type)); + } + REQUIRED_TYPES.forEach((t) => types.delete(t)); + const finalTypes: V4OpenAttestationDocument["type"] = [...REQUIRED_TYPES, ...Array.from(types)]; + + const documentReadyForWrapping = { + ...validatedRawDocument, + ...extractAndAssertAsV4OpenAttestationDocumentProps(validatedRawDocument, [ + "issuer", + "credentialStatus", + "credentialSubject", + ]), + "@context": finalContexts, + type: finalTypes, + } satisfies W3cVerifiableCredential; + + /* 5. OA wrapping */ + const salts = salt(documentReadyForWrapping); + const digest = digestCredential(documentReadyForWrapping, salts, []); + + const batchBuffers = [digest].map(hashToBuffer); + + const merkleTree = new MerkleTree(batchBuffers); + const merkleRoot = merkleTree.getRoot().toString("hex"); + const merkleProof = merkleTree.getProof(hashToBuffer(digest)).map((buffer) => buffer.toString("hex")); + const verifiableCredential: V4WrappedDocument = { + ...documentReadyForWrapping, + proof: { + type: "OpenAttestationMerkleProofSignature2018", + proofPurpose: "assertionMethod", + targetHash: digest, + proofs: merkleProof, + merkleRoot, + salts: encodeSalt(salts), + privacy: { + obfuscated: [], + }, + }, + }; + + return verifiableCredential as V4WrappedDocument; +}; + +export const wrapDocuments = async ( + // NoExtraProperties prevents the user from passing in a document with extra properties, which is more aligned to our validation strategy of strict + documents: NoExtraProperties[] +): Promise[]> => { + // create individual verifiable credential + const verifiableCredentials = await Promise.all(documents.map((document) => wrapDocument(document))); + + // get all the target hashes to compute the merkle tree and the merkle root + const merkleTree = new MerkleTree( + verifiableCredentials.map((verifiableCredential) => verifiableCredential.proof.targetHash).map(hashToBuffer) + ); + const merkleRoot = merkleTree.getRoot().toString("hex"); + + // for each document, update the merkle root and add the proofs needed + return verifiableCredentials.map((verifiableCredential) => { + const digest = verifiableCredential.proof.targetHash; + const merkleProof = merkleTree.getProof(hashToBuffer(digest)).map((buffer) => buffer.toString("hex")); + + return { + ...verifiableCredential, + proof: { + ...verifiableCredential.proof, + proofs: merkleProof, + merkleRoot, + }, + }; + }); +}; + +/** Extract a set of properties from w3cVerifiableCredential but only include the ones + * that are defined in the original document. For example, if we extract + * "a" and "b" from { b: "something" } we should only get { b: "something" } NOT + * { a: undefined, b: "something" }. We also assert that the extracted properties + * are of V4OpenAttestationDocument type. + **/ +function extractAndAssertAsV4OpenAttestationDocumentProps( + original: W3cVerifiableCredential, + keys: K[] +) { + const temp: Record = {}; + Object.entries(original).forEach(([k, v]) => { + if (keys.includes(k as K)) temp[k] = v; + }); + return temp as { [key in K]: V4OpenAttestationDocument[key] }; +} + +class DataModelValidationError extends Error { + constructor(dataModel: "Open Attestation v4.0" | "Verifiable Credentials v2.0", public error: ZodError) { + super(`Input document does not conform to ${dataModel} Data Model: \n ${JSON.stringify(error.format(), null, 2)}`); + Object.setPrototypeOf(this, DataModelValidationError.prototype); + } +} + +export const wrapDocumentErrors = { + DataModelValidationError, + UnableToInterpretContextError, +}; + +function isStringArray(input: unknown): input is string[] { + return Array.isArray(input) && input.every((i) => typeof i === "string"); +} diff --git a/src/index.ts b/src/index.ts index b019f6d2..54375b69 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,25 +1,50 @@ -import { validateSchema as validate } from "./shared/validate"; -import { verify } from "./2.0/verify"; -import { verify as verifyV3 } from "./3.0/verify"; -import { wrapDocument as wrapV2Document, wrapDocuments as wrapV2Documents } from "./2.0/wrap"; -import { signDocument as signV2Document } from "./2.0/sign"; -import { WrappedDocument as WrappedDocumentV2 } from "./2.0/types"; -import { WrappedDocument as WrappedDocumentV3 } from "./3.0/types"; -import { wrapDocument as wrapV3Document, wrapDocuments as wrapV3Documents } from "./3.0/wrap"; -import { signDocument as signV3Document } from "./3.0/sign"; -import { SchemaId, WrappedDocument, OpenAttestationDocument } from "./shared/@types/document"; +import { Signer } from "@ethersproject/abstract-signer"; + +import { getSchema } from "./shared/ajv"; import * as utils from "./shared/utils"; +import { validateSchema as validate } from "./shared/validate"; +import { SchemaId, WrappedDocument, OpenAttestationDocument, SignedWrappedDocument } from "./shared/@types/document"; +import { WrapDocumentOptionV2, WrapDocumentOptionV3 } from "./shared/@types/wrap"; +import { SigningKey, SUPPORTED_SIGNING_ALGORITHM } from "./shared/@types/sign"; + import * as v2 from "./2.0/types"; +import { WrappedDocument as WrappedDocumentV2 } from "./2.0/types"; +import { wrapDocument as wrapDocumentV2, wrapDocuments as wrapDocumentsV2 } from "./2.0/wrap"; +import { signDocument as signDocumentV2 } from "./2.0/sign"; +import { verify } from "./2.0/verify"; +import { obfuscateDocument as obfuscateDocumentV2 } from "./2.0/obfuscate"; import { OpenAttestationDocument as OpenAttestationDocumentV2 } from "./__generated__/schema.2.0"; + import * as v3 from "./3.0/types"; +import { WrappedDocument as WrappedDocumentV3 } from "./3.0/types"; +import { wrapDocument as wrapDocumentV3, wrapDocuments as wrapDocumentsV3 } from "./3.0/wrap"; +import { signDocument as signDocumentV3 } from "./3.0/sign"; +import { verify as verifyV3 } from "./3.0/verify"; +import { digestCredential as digestCredentialV3 } from "./3.0/digest"; +import { obfuscateVerifiableCredential as obfuscateVerifiableCredentialV3 } from "./3.0/obfuscate"; import { OpenAttestationDocument as OpenAttestationDocumentV3 } from "./__generated__/schema.3.0"; -import { obfuscateDocument as obfuscateDocumentV2 } from "./2.0/obfuscate"; -import { obfuscateVerifiableCredential } from "./3.0/obfuscate"; -import { WrapDocumentOptionV2, WrapDocumentOptionV3 } from "./shared/@types/wrap"; -import { SchemaValidationError } from "./shared/utils"; -import { SigningKey, SUPPORTED_SIGNING_ALGORITHM } from "./shared/@types/sign"; -import { getSchema } from "./shared/ajv"; -import { Signer } from "@ethersproject/abstract-signer"; + +import { verify as verifyV4 } from "./4.0/verify"; +import { + ObfuscateVerifiableCredentialResult, + obfuscateVerifiableCredential as obfuscateVerifiableCredentialV4, +} from "./4.0/obfuscate"; +import { v4Diagnose } from "./4.0/diagnose"; +import { V4WrappedDocument, isV4WrappedDocument } from "./4.0/types"; + +export function wrapDocument( + data: T, + options?: WrapDocumentOptionV2 +): WrappedDocumentV2 { + return wrapDocumentV2(data, { externalSchemaId: options?.externalSchemaId }); +} + +export function wrapDocuments( + dataArray: T[], + options?: WrapDocumentOptionV2 +): WrappedDocumentV2[] { + return wrapDocumentsV2(dataArray, { externalSchemaId: options?.externalSchemaId }); +} /** * @deprecated will be removed in the next major release in favour of OpenAttestation v4.0 (more info: https://github.com/Open-Attestation/open-attestation/tree/alpha) @@ -28,7 +53,7 @@ export function __unsafe__use__it__at__your__own__risks__wrapDocument> { - return wrapV3Document(data, options ?? { version: SchemaId.v3 }); + return wrapDocumentV3(data, options ?? { version: SchemaId.v3 }); } /** @@ -38,85 +63,72 @@ export function __unsafe__use__it__at__your__own__risks__wrapDocuments[]> { - return wrapV3Documents(dataArray, options ?? { version: SchemaId.v3 }); -} - -export function wrapDocument( - data: T, - options?: WrapDocumentOptionV2 -): WrappedDocumentV2 { - return wrapV2Document(data, { externalSchemaId: options?.externalSchemaId }); -} - -export function wrapDocuments( - dataArray: T[], - options?: WrapDocumentOptionV2 -): WrappedDocumentV2[] { - return wrapV2Documents(dataArray, { externalSchemaId: options?.externalSchemaId }); + return wrapDocumentsV3(dataArray, options ?? { version: SchemaId.v3 }); } export const validateSchema = (document: WrappedDocument): boolean => { + if (utils.isWrappedV2Document(document) || document?.version === SchemaId.v2) + return validate(document, getSchema(SchemaId.v2)).length === 0; + else if (utils.isWrappedV3Document(document) || document?.version === SchemaId.v3) + return validate(document, getSchema(SchemaId.v3)).length === 0; + else if (isV4WrappedDocument(document)) { + return v4Diagnose({ document, kind: "wrapped", debug: false, mode: "strict" }).length === 0; + } + return validate(document, getSchema(`${document?.version || SchemaId.v2}`)).length === 0; }; export function verifySignature>(document: T) { - return utils.isWrappedV3Document(document) ? verifyV3(document) : verify(document); + if (utils.isWrappedV2Document(document)) return verify(document); + else if (utils.isWrappedV3Document(document)) return verifyV3(document); + else if (isV4WrappedDocument(document)) return verifyV4(document); + + throw new Error("Unsupported document type: Only OpenAttestation v2, v3 or v4 documents can be signature verified"); } -export function obfuscate( - document: WrappedDocument, - fields: string[] | string -): WrappedDocument; -export function obfuscate( - document: WrappedDocument, - fields: string[] | string -): WrappedDocument; -export function obfuscate(document: any, fields: string[] | string) { - return document.version === SchemaId.v3 - ? obfuscateVerifiableCredential(document, fields) - : obfuscateDocumentV2(document, fields); +export function digest(document: OpenAttestationDocumentV3, salts: v3.Salt[], obfuscatedData: string[]): string { + if (utils.isRawV3Document(document)) return digestCredentialV3(document, salts, obfuscatedData); + throw new Error( + "Unsupported credential type: This function only supports digest generation for OpenAttestation v3 credentials" + ); } -export const isSchemaValidationError = (error: any): error is SchemaValidationError => { - return !!error.validationErrors; -}; +type ObfuscateReturn = T extends V4WrappedDocument ? ObfuscateVerifiableCredentialResult : T; +export function obfuscate>( + document: T, + fields: string[] | string +): ObfuscateReturn { + if (utils.isWrappedV2Document(document)) return obfuscateDocumentV2(document, fields) as ObfuscateReturn; + else if (utils.isWrappedV3Document(document)) + return obfuscateVerifiableCredentialV3(document, fields) as ObfuscateReturn; + else if (isV4WrappedDocument(document)) + return obfuscateVerifiableCredentialV4(document, fields) as ObfuscateReturn; -/** - * @deprecated signing of v3 documents will be removed in the next major release in favour of OpenAttestation v4.0 (more info: https://github.com/Open-Attestation/open-attestation/tree/alpha) - */ -export async function signDocument( - document: v3.SignedWrappedDocument | v3.WrappedDocument, - algorithm: SUPPORTED_SIGNING_ALGORITHM, - keyOrSigner: SigningKey | Signer -): Promise>; -export async function signDocument( - document: v2.SignedWrappedDocument | v2.WrappedDocument, - algorithm: SUPPORTED_SIGNING_ALGORITHM, - keyOrSigner: SigningKey | Signer -): Promise>; -export async function signDocument( - document: any, + throw new Error("Unsupported document type: Only OpenAttestation v2, v3 or v4 documents can be obfuscated"); +} + +export async function signDocument( + document: WrappedDocument | SignedWrappedDocument, algorithm: SUPPORTED_SIGNING_ALGORITHM, keyOrSigner: SigningKey | Signer -) { +): Promise> { // rj was worried it could happen deep in the code, so I moved it to the boundaries if (!SigningKey.guard(keyOrSigner) && !Signer.isSigner(keyOrSigner)) { throw new Error(`Either a keypair or ethers.js Signer must be provided`); } - switch (true) { - case utils.isWrappedV2Document(document): - return signV2Document(document, algorithm, keyOrSigner); - case utils.isWrappedV3Document(document): - return signV3Document(document, algorithm, keyOrSigner); - default: - // Unreachable code atm until utils.isWrappedV2Document & utils.isWrappedV3Document becomes more strict - throw new Error("Unsupported document type: Only OpenAttestation v2 & v3 documents can be signed"); - } + + let results: unknown; + if (utils.isWrappedV2Document(document)) results = signDocumentV2(document, algorithm, keyOrSigner); + else if (utils.isWrappedV3Document(document)) results = signDocumentV3(document, algorithm, keyOrSigner); + + if (results) return results as SignedWrappedDocument; + + throw new Error("Unsupported document type: Only OpenAttestation v2 or v3 documents can be signed"); } export { digestDocument } from "./2.0/digest"; -export { digestCredential } from "./3.0/digest"; export { checkProof, MerkleTree } from "./shared/merkle"; +export { digest as digestCredential }; export { obfuscate as obfuscateDocument }; export { utils }; export * from "./shared/@types/document"; @@ -125,3 +137,4 @@ export * from "./shared/signer"; export { getData } from "./shared/utils"; // keep it to avoid breaking change, moved from privacy to utils export { v2 }; export { v3 }; +export * as v4 from "./4.0/exports"; diff --git a/src/shared/@types/document.ts b/src/shared/@types/document.ts index 97c8b08f..d3dd1dbf 100644 --- a/src/shared/@types/document.ts +++ b/src/shared/@types/document.ts @@ -11,17 +11,22 @@ import { } from "../../3.0/types"; import { Literal, Static, String } from "runtypes"; import { isHexString } from "@ethersproject/bytes"; +import { V4OpenAttestationDocument, V4SignedWrappedDocument, V4WrappedDocument } from "../../4.0/types"; -export type OpenAttestationDocument = OpenAttestationDocumentV2 | OpenAttestationDocumentV3; +export type OpenAttestationDocument = OpenAttestationDocumentV2 | OpenAttestationDocumentV3 | V4OpenAttestationDocument; export type WrappedDocument = T extends OpenAttestationDocumentV2 ? WrappedDocumentV2 : T extends OpenAttestationDocumentV3 ? WrappedDocumentV3 + : T extends V4WrappedDocument + ? T : unknown; export type SignedWrappedDocument = T extends OpenAttestationDocumentV2 ? SignedWrappedDocumentV2 : T extends OpenAttestationDocumentV3 ? SignedWrappedDocumentV3 + : T extends V4SignedWrappedDocument + ? T : unknown; export enum SchemaId { diff --git a/src/shared/@types/wrap.ts b/src/shared/@types/wrap.ts index 7e24fc8f..42dc609f 100644 --- a/src/shared/@types/wrap.ts +++ b/src/shared/@types/wrap.ts @@ -17,10 +17,3 @@ export interface WrapDocumentOptionV3 { externalSchemaId?: string; version: SchemaId.v3; } - -/** - * @deprecated will be removed in the next major release in favour of OpenAttestation v4.0 (more info: https://github.com/Open-Attestation/open-attestation/tree/alpha) - */ -export const isWrapDocumentOptionV3 = (options: any): options is WrapDocumentOptionV3 => { - return options?.version === SchemaId.v3; -}; diff --git a/src/shared/merkle/merkle.ts b/src/shared/merkle/merkle.ts index b1e1ae80..796deaab 100644 --- a/src/shared/merkle/merkle.ts +++ b/src/shared/merkle/merkle.ts @@ -1,4 +1,5 @@ -import { Hash, hashArray, toBuffer, hashToBuffer, combineHashBuffers } from "../utils"; +import { Hash, hashArray, toBuffer, hashToBuffer, combineHashBuffers } from "../utils/hashing"; +import { Buffer } from "buffer/"; function getNextLayer(elements: Buffer[]) { return elements.reduce((layer: Buffer[], element, index, arr) => { diff --git a/src/shared/utils/@types/diagnose.ts b/src/shared/utils/@types/diagnose.ts index 91fb12af..dfcdcf7e 100644 --- a/src/shared/utils/@types/diagnose.ts +++ b/src/shared/utils/@types/diagnose.ts @@ -1,2 +1,5 @@ export type Kind = "raw" | "wrapped" | "signed"; export type Mode = "strict" | "non-strict"; +export type Diagnose = (props: { kind: Kind; document: any; debug: boolean; mode?: Mode }) => { + message: string; +}[]; diff --git a/src/shared/utils/__tests__/utils.test.ts b/src/shared/utils/__tests__/utils.test.ts index 85b2e071..3dc61c95 100644 --- a/src/shared/utils/__tests__/utils.test.ts +++ b/src/shared/utils/__tests__/utils.test.ts @@ -1,4 +1,5 @@ import * as utils from "../utils"; +import * as hashingUtils from "../hashing"; import { wrapDocument } from "../../.."; import { OpenAttestationDocument, WrappedDocument } from "../../../shared/@types/document"; import * as v2 from "../../../__generated__/schema.2.0"; @@ -12,11 +13,12 @@ import v3WrappedDidDocument from "../../../../test/fixtures/v3/did-wrapped.json" import v2WrappedDidDocumentOscpResponder from "../../../../test/fixtures/v2/did-signed-ocsp-responder.json"; import v2WrappedTransferableDocument from "../../../../test/fixtures/v2/wrapped-transferable-document.json"; import v3WrappedTransferableDocument from "../../../../test/fixtures/v3/wrapped-transferable-document.json"; +import { Buffer } from "buffer/"; describe("Util Functions", () => { describe("hashArray", () => { test("should work", () => { - const res = utils.hashArray(["a", "b", "1", 5]); + const res = hashingUtils.hashArray(["a", "b", "1", 5]); const expectedHashResults = [ "660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc", @@ -31,7 +33,7 @@ describe("Util Functions", () => { describe("bufSortJoin", () => { test("should work", () => { - const res = utils.bufSortJoin(Buffer.from("c"), Buffer.from("b"), Buffer.from("a")); + const res = hashingUtils.bufSortJoin(Buffer.from("c"), Buffer.from("b"), Buffer.from("a")); const expectedResults = "616263"; expect(res.toString("hex")).toEqual(expectedResults); }); @@ -39,35 +41,35 @@ describe("Util Functions", () => { describe("hashToBuffer", () => { test("should work", () => { - expect(utils.hashToBuffer("foo")).toEqual(Buffer.from("foo", "hex")); + expect(hashingUtils.hashToBuffer("foo")).toEqual(Buffer.from("foo", "hex")); }); test("should do nothing if the input is a hash", () => { const originalBuffer = Buffer.from("foo", "utf8"); - expect(utils.hashToBuffer(originalBuffer)).toEqual(originalBuffer); + expect(hashingUtils.hashToBuffer(originalBuffer)).toEqual(originalBuffer); }); }); describe("toBuffer", () => { test("should work", () => { - expect(utils.toBuffer("foo").toString("hex")).toEqual( + expect(hashingUtils.toBuffer("foo").toString("hex")).toEqual( "837fb5aa99ab7d0392fa43e61f529f072a693fd38032cd4a039793a9f9b4ea42" ); }); test("should do nothing if the input is a hash", () => { - const originalBuffer = utils.toBuffer("foo"); - expect(utils.toBuffer(originalBuffer)).toEqual(originalBuffer); + const originalBuffer = hashingUtils.toBuffer("foo"); + expect(hashingUtils.toBuffer(originalBuffer)).toEqual(originalBuffer); }); }); describe("combineHashBuffers", () => { test("should combine two hashes (in buffer format) and return result as a string", () => { expect( - utils + hashingUtils .combineHashBuffers( - utils.hashToBuffer("660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc"), - utils.hashToBuffer("9261495095bfbb82deedb97b2be90d0f4c0d9a03fdd90a9da62c1bbcc45d7eb2") + hashingUtils.hashToBuffer("660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc"), + hashingUtils.hashToBuffer("9261495095bfbb82deedb97b2be90d0f4c0d9a03fdd90a9da62c1bbcc45d7eb2") ) .toString("hex") ).toBe("6a4fe9cb57c9f79964c0408f25d70a73b3448bc6e975d0a905f0f8694764954b"); @@ -75,15 +77,17 @@ describe("Util Functions", () => { test("should return original hash if only one is given", () => { expect( - utils - .combineHashBuffers(utils.hashToBuffer("660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc")) + hashingUtils + .combineHashBuffers( + hashingUtils.hashToBuffer("660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc") + ) .toString("hex") ).toBe("660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc"); expect( - utils + hashingUtils .combineHashBuffers( undefined, - utils.hashToBuffer("660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc") + hashingUtils.hashToBuffer("660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc") ) .toString("hex") ).toBe("660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc"); @@ -93,7 +97,7 @@ describe("Util Functions", () => { describe("combineHashString", () => { test("should combine two hashes (in string format) and return result as a string", () => { expect( - utils.combineHashString( + hashingUtils.combineHashString( "660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc", "9261495095bfbb82deedb97b2be90d0f4c0d9a03fdd90a9da62c1bbcc45d7eb2" ) @@ -101,11 +105,11 @@ describe("Util Functions", () => { }); test("should return original hash if only one is given", () => { - expect(utils.combineHashString("660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc")).toBe( + expect(hashingUtils.combineHashString("660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc")).toBe( "660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc" ); expect( - utils.combineHashString(undefined, "660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc") + hashingUtils.combineHashString(undefined, "660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc") ).toBe("660c9a8d0051d07b1abd38e8a6f68076d98fdf948abd2a13e2870fe08a1343cc"); }); }); @@ -224,7 +228,7 @@ describe("Util Functions", () => { }; expect(() => utils.getTargetHash(document)).toThrow( new Error( - "Unsupported document type: Only can retrieve target hash from wrapped OpenAttestation v2 & v3 documents." + "Unsupported document type: Only can retrieve target hash from wrapped OpenAttestation v2, v3 & v4 documents." ) ); }); @@ -280,7 +284,9 @@ describe("Util Functions", () => { }, }; expect(() => utils.getTemplateURL(document)).toThrow( - new Error("Unsupported document type: Only can retrieve template url from OpenAttestation v2 & v3 documents.") + new Error( + "Unsupported document type: Only can retrieve template url from OpenAttestation v2, v3 & v4 documents." + ) ); }); }); @@ -451,7 +457,7 @@ describe("Util Functions", () => { }, }; expect(() => utils.getDocumentData(document)).toThrow( - "Unsupported document type: Only can retrieve document data for wrapped OpenAttestation v2 & v3 documents." + "Unsupported document type: Only can retrieve document data for wrapped OpenAttestation v2, v3 & v4 documents." ); }); }); diff --git a/src/shared/utils/diagnose.ts b/src/shared/utils/diagnose.ts index 21df1826..a4bbd6ee 100644 --- a/src/shared/utils/diagnose.ts +++ b/src/shared/utils/diagnose.ts @@ -2,15 +2,16 @@ import { Logger } from "@ethersproject/logger"; import { SchemaId } from "../@types/document"; import { validateSchema as validate } from "../validate"; import { - VerifiableCredentialSignedProof, - VerifiableCredentialWrappedProof, - VerifiableCredentialWrappedProofStrict, + VerifiableCredentialWrappedProof as WrappedProofV3, + VerifiableCredentialWrappedProofStrict as WrappedProofStrictV3, + VerifiableCredentialSignedProof as SignedWrappedProofV3, } from "../../3.0/types"; import { ArrayProof, Signature, SignatureStrict } from "../../2.0/types"; import { getSchema } from "../ajv"; import { Kind, Mode } from "./@types/diagnose"; +import { v4Diagnose } from "../../4.0/diagnose"; -type Version = "2.0" | "3.0"; +export type Version = "2.0" | "3.0" | "4.0"; //https://github.com/ethers-io/ethers.js/blob/ec1b9583039a14a0e0fa15d0a2a6082a2f41cf5b/packages/ethers/src.ts/ethers.ts#L36 const ethersLogger = new Logger("ethers/5.7.0"); @@ -30,7 +31,7 @@ const handleError = (debug: boolean, ...messages: string[]) => { /** * Tools to give information about the validity of a document. It will return and eventually output the errors found. - * @param version 2.0 or 3.0 + * @param version 2.0, 3.0 or 4.0 * @param kind raw, wrapped or signed * @param debug turn on to output in the console, the errors found * @param mode strict or non-strict. Strict will perform additional check on the data. For instance strict validation will ensure that a target hash is a 32 bytes hex string while non strict validation will just check that target hash is a string. @@ -57,25 +58,38 @@ export const diagnose = ({ return handleError(debug, "The document must be an object"); } - const errors = validate(document, getSchema(version === "3.0" ? SchemaId.v3 : SchemaId.v2, mode), kind); + const versionToSchemaId: Record = { + "2.0": SchemaId.v2, + "3.0": SchemaId.v3, + "4.0": undefined, + }; - if (errors.length > 0) { - // TODO this can be improved later - return handleError( - debug, - `The document does not match OpenAttestation schema ${version === "3.0" ? "3.0" : "2.0"}`, - ...errors.map((error) => `${error.instancePath || "document"} - ${error.message}`) - ); + const schemaId = versionToSchemaId[version]; + if (schemaId) { + const errors = validate(document, getSchema(schemaId, mode), kind); + + if (errors.length > 0) { + // TODO this can be improved later + return handleError( + debug, + `The document does not match OpenAttestation schema ${version}`, + ...errors.map((error) => `${error.instancePath || "document"} - ${error.message}`) + ); + } } - if (kind === "raw") { + if (kind === "raw" && version !== "4.0") { return []; } - if (version === "3.0") { - return diagnoseV3({ mode, debug, document, kind }); - } else { - return diagnoseV2({ mode, debug, document, kind }); + switch (version) { + case "4.0": + return v4Diagnose({ debug, document, kind }); + case "3.0": + return diagnoseV3({ mode, debug, document, kind }); + case "2.0": + default: + return diagnoseV2({ mode, debug, document, kind }); } }; @@ -118,9 +132,7 @@ const diagnoseV3 = ({ kind, document, debug, mode }: { kind: Kind; document: any try { // eslint-disable-next-line @typescript-eslint/no-unused-expressions - mode === "strict" - ? VerifiableCredentialWrappedProofStrict.check(document.proof) - : VerifiableCredentialWrappedProof.check(document.proof); + mode === "strict" ? WrappedProofStrictV3.check(document.proof) : WrappedProofV3.check(document.proof); } catch (e) { if (e instanceof Error) { return handleError(debug, e.message); @@ -134,7 +146,7 @@ const diagnoseV3 = ({ kind, document, debug, mode }: { kind: Kind; document: any return handleError(debug, `The document does not have a proof`); } try { - VerifiableCredentialSignedProof.check(document.proof); + SignedWrappedProofV3.check(document.proof); } catch (e) { if (e instanceof Error) { return handleError(debug, e.message); diff --git a/src/shared/utils/guard.ts b/src/shared/utils/guard.ts index 5cca3de0..cfb52b3c 100644 --- a/src/shared/utils/guard.ts +++ b/src/shared/utils/guard.ts @@ -1,12 +1,12 @@ import { SignedWrappedDocument } from "../@types/document"; -import { - OpenAttestationDocument as OpenAttestationDocumentV3, - WrappedDocument as WrappedDocumentV3, -} from "../../3.0/types"; import { OpenAttestationDocument as OpenAttestationDocumentV2, WrappedDocument as WrappedDocumentV2, } from "../../2.0/types"; +import { + OpenAttestationDocument as OpenAttestationDocumentV3, + WrappedDocument as WrappedDocumentV3, +} from "../../3.0/types"; import { diagnose } from "./diagnose"; import { Mode } from "./@types/diagnose"; @@ -39,11 +39,11 @@ export const isRawV3Document = ( * @param document * @param mode strict or non-strict. Strict will perform additional check on the data. For instance strict validation will ensure that a target hash is a 32 bytes hex string while non strict validation will just check that target hash is a string. */ -export const isWrappedV3Document = ( +export const isWrappedV2Document = ( document: any, { mode }: { mode: Mode } = { mode: "non-strict" } -): document is WrappedDocumentV3 => { - return diagnose({ version: "3.0", kind: "wrapped", document, debug: false, mode }).length === 0; +): document is WrappedDocumentV2 => { + return diagnose({ version: "2.0", kind: "wrapped", document, debug: false, mode }).length === 0; }; /** @@ -51,11 +51,11 @@ export const isWrappedV3Document = ( * @param document * @param mode strict or non-strict. Strict will perform additional check on the data. For instance strict validation will ensure that a target hash is a 32 bytes hex string while non strict validation will just check that target hash is a string. */ -export const isWrappedV2Document = ( +export const isWrappedV3Document = ( document: any, { mode }: { mode: Mode } = { mode: "non-strict" } -): document is WrappedDocumentV2 => { - return diagnose({ version: "2.0", kind: "wrapped", document, debug: false, mode }).length === 0; +): document is WrappedDocumentV3 => { + return diagnose({ version: "3.0", kind: "wrapped", document, debug: false, mode }).length === 0; }; /** @@ -81,3 +81,9 @@ export const isSignedWrappedV3Document = ( ): document is SignedWrappedDocument => { return diagnose({ version: "3.0", kind: "signed", document, debug: false, mode }).length === 0; }; + +export { + isV4OpenAttestationDocument as isRawV4Document, + isV4WrappedDocument as isWrappedV4Document, + isV4SignedWrappedDocument as isSignedWrappedV4Document, +} from "../../4.0/types"; diff --git a/src/shared/utils/hashing.ts b/src/shared/utils/hashing.ts new file mode 100644 index 00000000..e07eb3dc --- /dev/null +++ b/src/shared/utils/hashing.ts @@ -0,0 +1,57 @@ +import { keccak256 } from "js-sha3"; +import { Buffer } from "buffer/"; + +export type Hash = string | Buffer; +/** + * Sorts the given Buffers lexicographically and then concatenates them to form one continuous Buffer + */ +export function bufSortJoin(...args: Buffer[]): Buffer { + return Buffer.concat([...args].sort(Buffer.compare)); +} + +// If hash is not a buffer, convert it to buffer (without hashing it) +export function hashToBuffer(hash: Hash): Buffer { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore https://github.com/Microsoft/TypeScript/issues/23155 + return Buffer.isBuffer(hash) && hash.length === 32 ? hash : Buffer.from(hash, "hex"); +} + +// If element is not a buffer, stringify it and then hash it to be a buffer +export function toBuffer(element: any): Buffer { + return Buffer.isBuffer(element) && element.length === 32 ? element : hashToBuffer(keccak256(JSON.stringify(element))); +} +/** + * Turns array of data into sorted array of hashes + */ +export function hashArray(arr: any[]) { + return arr.map((i) => toBuffer(i)).sort(Buffer.compare); +} + +/** + * Returns the keccak hash of two buffers after concatenating them and sorting them + * If either hash is not given, the input is returned + */ +export function combineHashBuffers(first?: Buffer, second?: Buffer): Buffer { + if (!second) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return first!; // it should always be valued if second is not + } + if (!first) { + return second; + } + return hashToBuffer(keccak256(bufSortJoin(first, second))); +} + +/** + * Returns the keccak hash of two string after concatenating them and sorting them + * If either hash is not given, the input is returned + * @param first A string to be hashed (without 0x) + * @param second A string to be hashed (without 0x) + * @returns Resulting string after the hash is combined (without 0x) + */ +export function combineHashString(first?: string, second?: string): string { + return first && second + ? combineHashBuffers(hashToBuffer(first), hashToBuffer(second)).toString("hex") + : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + (first || second)!; // this should always return a value right ? :) +} diff --git a/src/shared/utils/index.ts b/src/shared/utils/index.ts index 7c5d9a32..063acd8d 100644 --- a/src/shared/utils/index.ts +++ b/src/shared/utils/index.ts @@ -1,3 +1,5 @@ export * from "./utils"; export * from "./guard"; export * from "./diagnose"; +export * from "../../2.0/utils"; +export * from "./hashing"; diff --git a/src/shared/utils/utils.ts b/src/shared/utils/utils.ts index 38e3a983..145b9ff5 100644 --- a/src/shared/utils/utils.ts +++ b/src/shared/utils/utils.ts @@ -1,74 +1,27 @@ -import { keccak256 } from "js-sha3"; -import { OpenAttestationDocument as OpenAttestationDocumentV2, TemplateObject } from "../../__generated__/schema.2.0"; -import { OpenAttestationDocument as OpenAttestationDocumentV3 } from "../../__generated__/schema.3.0"; -import { WrappedDocument as WrappedDocumentV2 } from "../../2.0/types"; -import { WrappedDocument as WrappedDocumentV3 } from "../../3.0/types"; -import { unsaltData } from "../../2.0/salt"; import { ErrorObject } from "ajv"; -import { isRawV2Document, isRawV3Document, isWrappedV2Document, isWrappedV3Document } from "./guard"; -import { OpenAttestationDocument, WrappedDocument } from "../@types/document"; -import * as v2 from "../../__generated__/schema.2.0"; -import * as v3 from "../../__generated__/schema.3.0"; - -export type Hash = string | Buffer; -type Extract

= P extends WrappedDocumentV2 ? T : never; -export const getData = >(document: T): Extract => { - return unsaltData(document.data); -}; -/** - * Sorts the given Buffers lexicographically and then concatenates them to form one continuous Buffer - */ -export function bufSortJoin(...args: Buffer[]): Buffer { - return Buffer.concat([...args].sort(Buffer.compare)); -} - -// If hash is not a buffer, convert it to buffer (without hashing it) -export function hashToBuffer(hash: Hash): Buffer { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore https://github.com/Microsoft/TypeScript/issues/23155 - return Buffer.isBuffer(hash) && hash.length === 32 ? hash : Buffer.from(hash, "hex"); -} +import * as v2 from "../../__generated__/schema.2.0"; +import { getData } from "../../2.0/utils"; +import { WrappedDocument as WrappedDocumentV2 } from "../../2.0/types"; +import { OpenAttestationDocument as OpenAttestationDocumentV2 } from "../../__generated__/schema.2.0"; -// If element is not a buffer, stringify it and then hash it to be a buffer -export function toBuffer(element: any): Buffer { - return Buffer.isBuffer(element) && element.length === 32 ? element : hashToBuffer(keccak256(JSON.stringify(element))); -} -/** - * Turns array of data into sorted array of hashes - */ -export function hashArray(arr: any[]) { - return arr.map((i) => toBuffer(i)).sort(Buffer.compare); -} +import * as v3 from "../../__generated__/schema.3.0"; +import { WrappedDocument as WrappedDocumentV3 } from "../../3.0/types"; +import { OpenAttestationDocument as OpenAttestationDocumentV3 } from "../../__generated__/schema.3.0"; -/** - * Returns the keccak hash of two buffers after concatenating them and sorting them - * If either hash is not given, the input is returned - */ -export function combineHashBuffers(first?: Buffer, second?: Buffer): Buffer { - if (!second) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return first!; // it should always be valued if second is not - } - if (!first) { - return second; - } - return hashToBuffer(keccak256(bufSortJoin(first, second))); -} +import { V4WrappedDocument } from "../../4.0/types"; +import { ContextUrl } from "../../4.0/context"; -/** - * Returns the keccak hash of two string after concatenating them and sorting them - * If either hash is not given, the input is returned - * @param first A string to be hashed (without 0x) - * @param second A string to be hashed (without 0x) - * @returns Resulting string after the hash is combined (without 0x) - */ -export function combineHashString(first?: string, second?: string): string { - return first && second - ? combineHashBuffers(hashToBuffer(first), hashToBuffer(second)).toString("hex") - : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - (first || second)!; // this should always return a value right ? :) -} +import { OpenAttestationDocument, WrappedDocument, SchemaId } from "../@types/document"; +import { + isRawV2Document, + isWrappedV2Document, + isRawV3Document, + isWrappedV3Document, + isWrappedV4Document, + isRawV4Document, +} from "./guard"; +import { Version } from "./diagnose"; export function getIssuerAddress(document: any): any { if (isWrappedV2Document(document)) { @@ -77,63 +30,67 @@ export function getIssuerAddress(document: any): any { } else if (isWrappedV3Document(document)) { return document.openAttestationMetadata.proof.value; } + // TODO: OA v4 proof schema not updated to support document store issuance yet + // else if (isWrappedV4Document(document)) { + // return document.proof.? + // } throw new Error( "Unsupported document type: Only can retrieve issuer address from wrapped OpenAttestation v2 & v3 documents." ); } export const getMerkleRoot = (document: any): string => { - switch (true) { - case isWrappedV2Document(document): - return document.signature.merkleRoot; - case isWrappedV3Document(document): - return document.proof.merkleRoot; - default: - throw new Error( - "Unsupported document type: Only can retrieve merkle root from wrapped OpenAttestation v2 & v3 documents." - ); - } + if (isWrappedV2Document(document)) return document.signature.merkleRoot; + else if (isWrappedV3Document(document)) return document.proof.merkleRoot; + else if (isWrappedV4Document(document)) return document.proof.merkleRoot; + + throw new Error( + "Unsupported document type: Only can retrieve merkle root from wrapped OpenAttestation v2, v3 & v4 documents." + ); }; export const getTargetHash = (document: any): string => { - switch (true) { - case isWrappedV2Document(document): - return document.signature.targetHash; - case isWrappedV3Document(document): - return document.proof.targetHash; - default: - throw new Error( - "Unsupported document type: Only can retrieve target hash from wrapped OpenAttestation v2 & v3 documents." - ); - } + if (isWrappedV2Document(document)) return document.signature.targetHash; + else if (isWrappedV3Document(document)) return document.proof.targetHash; + else if (isWrappedV4Document(document)) return document.proof.targetHash; + + throw new Error( + "Unsupported document type: Only can retrieve target hash from wrapped OpenAttestation v2, v3 & v4 documents." + ); }; // get template url from raw document for document renderer preview. export const getTemplateURL = (document: any): string | undefined => { - switch (true) { - case isWrappedV2Document(document): - return (getData(document).$template as TemplateObject).url; - case isRawV2Document(document): - return document.$template.url; - case isRawV3Document(document) || isWrappedV3Document(document): - return document.openAttestationMetadata.template.url; - default: - throw new Error( - "Unsupported document type: Only can retrieve template url from OpenAttestation v2 & v3 documents." - ); + if (isWrappedV2Document(document)) { + const unwrappedDocument = getData(document); + if (typeof unwrappedDocument.$template === "string") return unwrappedDocument.$template; + else return unwrappedDocument.$template?.url; + } else if (isRawV2Document(document)) { + if (typeof document.$template === "string") return document.$template; + else return document.$template?.url; + } else if (isRawV3Document(document) || isWrappedV3Document(document)) { + return document.openAttestationMetadata.template?.url; + } else if (isRawV4Document(document) || isWrappedV4Document(document)) { + return document.renderMethod && document.renderMethod[0].id; } + + throw new Error( + "Unsupported document type: Only can retrieve template url from OpenAttestation v2, v3 & v4 documents." + ); }; export const getDocumentData = (document: WrappedDocument): OpenAttestationDocument => { - if (isWrappedV3Document(document)) { + if (isWrappedV3Document(document) || isWrappedV4Document(document)) { const omit = (keys: any, obj: any): any => Object.fromEntries(Object.entries(obj).filter(([k]) => !keys.includes(k))); return omit(["proof"], document); } else if (isWrappedV2Document(document)) { return getData(document); - } else { - throw "Unsupported document type: Only can retrieve document data for wrapped OpenAttestation v2 & v3 documents."; } + + throw new Error( + "Unsupported document type: Only can retrieve document data for wrapped OpenAttestation v2, v3 & v4 documents." + ); }; export const isTransferableAsset = (document: any): boolean => { @@ -144,35 +101,41 @@ export const isTransferableAsset = (document: any): boolean => { }; export const isDocumentRevokable = (document: any): boolean => { - switch (true) { - case isTransferableAsset(document): - return false; - - case isWrappedV2Document(document): - const issuer = getData(document)?.issuers[0]; - const isDidRevokableV2 = - (issuer.identityProof?.type === v2.IdentityProofType.Did || - issuer.identityProof?.type === v2.IdentityProofType.DNSDid) && - (issuer.revocation?.type === v2.RevocationType.RevocationStore || - issuer.revocation?.type === v2.RevocationType.OcspResponder); - const isDocumentStoreRevokableV2 = !!issuer.certificateStore || !!issuer.documentStore; - - return isDocumentStoreRevokableV2 || isDidRevokableV2; - - case isWrappedV3Document(document): - const isDidRevokableV3 = - (document.openAttestationMetadata.proof.method === v3.IdentityProofType.Did || - document.openAttestationMetadata.proof.method === v3.IdentityProofType.DNSDid) && - document.openAttestationMetadata.proof.revocation?.type === v3.RevocationType.RevocationStore; - const isDocumentStoreRevokableV3 = - document.openAttestationMetadata.proof.method === v3.Method.DocumentStore && - !!document.openAttestationMetadata.proof.value; - - return isDocumentStoreRevokableV3 || isDidRevokableV3; - - default: - return false; + if (isTransferableAsset(document)) { + return false; + } else if (isWrappedV2Document(document)) { + const issuer = getData(document)?.issuers[0]; + const isDidRevokableV2 = + (issuer.identityProof?.type === v2.IdentityProofType.Did || + issuer.identityProof?.type === v2.IdentityProofType.DNSDid) && + (issuer.revocation?.type === v2.RevocationType.RevocationStore || + issuer.revocation?.type === v2.RevocationType.OcspResponder); + const isDocumentStoreRevokableV2 = !!issuer.certificateStore || !!issuer.documentStore; + + return isDocumentStoreRevokableV2 || isDidRevokableV2; + } else if (isWrappedV3Document(document)) { + const isDidRevokableV3 = + (document.openAttestationMetadata.proof.method === (v3.IdentityProofType.Did as string) || + document.openAttestationMetadata.proof.method === (v3.IdentityProofType.DNSDid as string)) && + document.openAttestationMetadata.proof.revocation?.type === v3.RevocationType.RevocationStore; + const isDocumentStoreRevokableV3 = + document.openAttestationMetadata.proof.method === v3.Method.DocumentStore && + !!document.openAttestationMetadata.proof.value; + + return isDocumentStoreRevokableV3 || isDidRevokableV3; + } else if (isWrappedV4Document(document)) { + if (typeof document.issuer === "string" || !document.credentialStatus) return false; + const isDidRevokableV4 = + document.issuer.identityProof?.identityProofType === "DNS-DID" + ? document.credentialStatus.type === "OpenAttestationOcspResponder" + : false; + // TODO: OA v4 issuer schema not updated to support document store issuance yet + // const isDocumentStoreRevokableV4 = ? + + return isDidRevokableV4; } + + return false; }; export const getAssetId = (document: any): string => { @@ -198,14 +161,17 @@ export const isSchemaValidationError = (error: any): error is SchemaValidationEr export { keccak256 } from "js-sha3"; export const isObfuscated = ( - document: WrappedDocumentV3 | WrappedDocumentV2 + document: + | WrappedDocumentV2 + | WrappedDocumentV3 + | V4WrappedDocument ): boolean => { - if (isWrappedV3Document(document)) { - return !!document.proof.privacy?.obfuscated?.length; - } - if (isWrappedV2Document(document)) { return !!document.privacy?.obfuscatedData?.length; + } else if (isWrappedV3Document(document)) { + return !!document.proof.privacy.obfuscated.length; + } else if (isWrappedV4Document(document)) { + return !!document.proof.privacy.obfuscated.length; } throw new Error( @@ -214,17 +180,39 @@ export const isObfuscated = ( }; export const getObfuscatedData = ( - document: WrappedDocumentV3 | WrappedDocumentV2 + document: + | WrappedDocumentV2 + | WrappedDocumentV3 + | V4WrappedDocument ): string[] => { - if (isWrappedV3Document(document)) { - return document.proof.privacy?.obfuscated; - } - if (isWrappedV2Document(document)) { return document.privacy?.obfuscatedData || []; + } else if (isWrappedV3Document(document)) { + return document.proof.privacy.obfuscated || []; + } else if (isWrappedV4Document(document)) { + return document.proof.privacy.obfuscated || []; } throw new Error( "Unsupported document type: Can only retrieve obfuscated data from wrapped OpenAttestation v2 & v3 documents." ); }; + +export const getVersion = (document: unknown): Version => { + if (typeof document === "object" && document !== null) { + if ("version" in document && typeof document.version === "string") { + switch (document.version) { + case SchemaId.v2: + return "2.0"; + case SchemaId.v3: + return "3.0"; + } + } else if ("@context" in document && Array.isArray(document["@context"])) { + if (document["@context"].includes(ContextUrl.v4_alpha)) { + return "4.0"; + } + } + } + + throw new Error("Unknown document version: Can only determine between OpenAttestation v2, v3 & v4 documents."); +}; diff --git a/src/shared/validate/validate.ts b/src/shared/validate/validate.ts index 4bff84aa..badb007f 100644 --- a/src/shared/validate/validate.ts +++ b/src/shared/validate/validate.ts @@ -1,10 +1,11 @@ +import { ValidateFunction } from "ajv/dist/core"; +import { ErrorObject } from "ajv"; import { getLogger } from "../logger"; import { SchemaId } from "../@types/document"; -// don't change this otherwise there is a cycle -import { getData } from "../utils/utils"; import { Kind } from "../utils/@types/diagnose"; -import { ValidateFunction } from "ajv/dist/core"; -import { ErrorObject } from "ajv"; +import { ContextUrl } from "../../4.0/context"; +import { getData } from "../../2.0/utils"; + const logger = getLogger("validate"); export const validateSchema = (document: any, validator: ValidateFunction, kind?: Kind): ErrorObject[] => { @@ -12,7 +13,16 @@ export const validateSchema = (document: any, validator: ValidateFunction, kind? throw new Error("No schema validator provided"); } - const valid = validator(document.version === SchemaId.v3 || kind === "raw" ? document : getData(document)); + // FIXME: Unable to use isWrappedV4OpenAttestationDocument() type guard here because it also calls validateSchema (endless recursive call) + // Need a better way to determine whether a document needs to be unwrapped first + const valid = validator( + (Array.isArray(document["@context"]) && document["@context"].includes(ContextUrl.v2_vc)) || + (Array.isArray(document["@context"]) && document["@context"].includes(ContextUrl.v4_alpha)) || + document.version === SchemaId.v3 || + kind === "raw" + ? document + : getData(document) + ); if (!valid) { logger.debug(`There are errors in the document: ${JSON.stringify(validator.errors)}`); diff --git a/test/fixtures/v4/__generated__/batched-raw-documents-did.json b/test/fixtures/v4/__generated__/batched-raw-documents-did.json new file mode 100644 index 00000000..965d391e --- /dev/null +++ b/test/fixtures/v4/__generated__/batched-raw-documents-did.json @@ -0,0 +1,91 @@ +[ + { + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + ], + "name": "Republic of Singapore Driving Licence", + "type": [ + "VerifiableCredential", + "OpenAttestationCredential" + ], + "issuer": { + "id": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + "type": "OpenAttestationIssuer", + "name": "Government Technology Agency of Singapore (GovTech)", + "identityProof": { + "identityProofType": "DNS-DID", + "identifier": "example.openattestation.com" + } + }, + "validFrom": "2021-03-08T12:00:00+08:00", + "credentialSubject": { + "id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + "type": [ + "DriversLicense" + ], + "name": "John Doe", + "licenses": [ + { + "class": "3", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + }, + { + "class": "3A", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + } + ] + }, + "renderMethod": [ + { + "id": "https://demo-renderer.opencerts.io", + "type": "OpenAttestationEmbeddedRenderer", + "templateName": "GOVTECH_DEMO" + } + ] + }, + { + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + ], + "name": "Republic of Singapore Driving Licence", + "type": [ + "VerifiableCredential", + "OpenAttestationCredential" + ], + "issuer": { + "id": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + "type": "OpenAttestationIssuer", + "name": "Government Technology Agency of Singapore (GovTech)", + "identityProof": { + "identityProofType": "DNS-DID", + "identifier": "example.openattestation.com" + } + }, + "validFrom": "2021-03-08T12:00:00+08:00", + "credentialSubject": { + "id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + "type": [ + "DriversLicense" + ], + "name": "Jane Doe", + "licenses": [ + { + "class": "3000A", + "description": "Motor spaceships with unladen weight <= 3000tonnes", + "effectiveDate": "2013-05-16T00:00:00+08:00" + } + ] + }, + "renderMethod": [ + { + "id": "https://demo-renderer.opencerts.io", + "type": "OpenAttestationEmbeddedRenderer", + "templateName": "GOVTECH_DEMO" + } + ] + } +] \ No newline at end of file diff --git a/test/fixtures/v4/__generated__/batched-signed-wrapped-documents-did.json b/test/fixtures/v4/__generated__/batched-signed-wrapped-documents-did.json new file mode 100644 index 00000000..658d22d9 --- /dev/null +++ b/test/fixtures/v4/__generated__/batched-signed-wrapped-documents-did.json @@ -0,0 +1,121 @@ +[ + { + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + ], + "name": "Republic of Singapore Driving Licence", + "type": [ + "VerifiableCredential", + "OpenAttestationCredential" + ], + "issuer": { + "id": "did:ethr:did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + "type": "OpenAttestationIssuer", + "name": "Government Technology Agency of Singapore (GovTech)", + "identityProof": { + "identityProofType": "DNS-DID", + "identifier": "example.openattestation.com" + } + }, + "validFrom": "2021-03-08T12:00:00+08:00", + "credentialSubject": { + "id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + "type": [ + "DriversLicense" + ], + "name": "John Doe", + "licenses": [ + { + "class": "3", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + }, + { + "class": "3A", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + } + ] + }, + "renderMethod": [ + { + "id": "https://demo-renderer.opencerts.io", + "type": "OpenAttestationEmbeddedRenderer", + "templateName": "GOVTECH_DEMO" + } + ], + "proof": { + "type": "OpenAttestationMerkleProofSignature2018", + "proofPurpose": "assertionMethod", + "targetHash": "08969c7baf46807ee65e495b2a93c0e27dfdc77085562ce9ab1249a7fb261681", + "proofs": [ + "ce284d21e98ac301c0e963ea6d020570091e05591dc2b787a698512e82b39001" + ], + "merkleRoot": "6fa0bdfa20b114c3e9e92fb511be62f416533a35df99a440ecc28ff4a3f601d2", + "salts": "W3sidmFsdWUiOiIwMzgyZWU0MjFlNTgyMzJlMGJjNTI0MDY1NjhhZTdiNWZhNDhlOWRjYzczZmVkM2VhOTZkOTAzNGQ4ZWZkNDlhIiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6ImViMmI1ZmIwODhlZDk5YzY0NzJmYmQ4MjMyNjVhYjlkMzZhNmQ0MDFiMGEyNmM5N2Q3Zjc0MDkwYWJiYTE4OGEiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiYWNmNGFhMGJmZDEyMTRmZGEwZDAzNzczNmNhMDFiMzhkOTBlZDA4MzQ5ODUwMWY5NDlmOTgyNjg1NmE2MTM3OSIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6IjM5Yzc1MjFmNDdlNTJlNWZlOGI2NmEyYjhjZmEzYTQwNDM1ZjQ2Y2NiOWY3MGQxYWY4MThkNmNkNzk1MzQ4MzQiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiJiNWY3MmI3N2M1NjU3YjZiOTMyN2QyMGYwZTUwYzQxMGVmNzRlNDMzYTM0NTRlOTRmMTEzOTZmMTIwYzJjMjc5IiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiOTU1MjExMzNmNzgzZjI5NzlkODgyMzI4MDlmMDgxNmUzNDVmMjE4MTk0ZTJkMTgwYzZmYTcwMTBhNDI4ODFkYyIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiMTQwZmVlNjI5Y2M2MjY3Njk1NzA4YzY2ZTg2OGI0ZjVhZTBiMDg1YjYzNDczM2I1YWE1N2M4ZTQxM2I1NTliNiIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiJiMjFmZTkyMDNlNWYxNzFjMjE1NDIyY2Y2ZTZkOWEzNzFkMmIyZGJkMjU5ZDE0Y2JmMDZiYTllZjQ4NzEzYzk3IiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6ImE5Mjg0OTFiMzYyNzcyMjUxNzM0ZDEwNGQwOGJiMTgzMjczM2JlYzZiYjdmYWI0YTE4ZTdiNGRlY2QzMjE0YmMiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiNWViMmMyNTU2ODgyZjgzZjM0MTQ5MTczMGM0OWI4NTE4OTljMTA3NzY2Yzk5YWQwYzhhMGRkZTQxNDkzZjYxYyIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6IjVlMTgyNThiODdjMjJiMGIzY2Y4OWVhMjZhOTI5N2ZkYjVmYjI0NTA2Mzg0MzNlYzcxN2YyYTBmMzE0NTJlMmYiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6ImIyYWU3ODllZmVjZmE4ZmEzMmZmNTdlYTNjYTJmZjJjZmVmOThmOThmZGVhY2U4M2Q0NGEwNTVjZGU4MDE2MDgiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiMGQ1ZWI3YmY3OTE1MmI0M2EwMTQyYjhkNTVkMzRmMzRlOGQ0N2U5MzgwMDVhYTVjMTRjMjk2MWNiMjM0OWFkYSIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6ImIyZWM0NTYzMjhlMzhjYWYyYmNlYTk5YWM5NTc0ZWEzZGExNjJkNmJlZDVlZTRkZGM3MzI5NjhkMmIwMDZjZGQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiI3OTIwNmQwNDNlNjVhYmU2MmFmYmIwNmViNGMxMWNmZTg2NjkzNWRhOGYyYzkzODI4NjVlZjg1YjVhMzc1NTUwIiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6IjAyYjJjMTlhNDY2ZjNiYWU5ZDhmNWI0NzUyZGEzZmU2MWM1MTIxYzc1Mzc0N2I1NzNmNTdlYzBmOGExODIzZDciLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiNTNiOTA2MjdlNWY1OTM4YjdkNWY0NzhjM2JiNDE4NjkwOWI1OTY1MjVhM2I4NWNlZWU2M2JjNGYyZGQ1ZmRkNCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6ImNhOGFlMzIwZjU5NWJmMmUwMmQ3MTAxOGE5YjA0YWI1MDNiOGJiMTIyM2I2NDM5MWNjYTZiY2MyOTk5MjdmOTciLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMV0uY2xhc3MifSx7InZhbHVlIjoiYjk1MzhlMjkwNzdlMzg1MzlmN2E0MTliZGMzNmFhYWVjMTMyNGY0MjQzOTA2YzIyN2JmMzhkZDU4NTA4M2NlZCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1sxXS5kZXNjcmlwdGlvbiJ9LHsidmFsdWUiOiIyN2RmYWY1Y2M1NzJlMTFmODhkMDFmNGUwMzQ0ZWRiMzA4OWQ2NDc5YmY0ODIyODBiZmNmNGE4YzZjOTY1NmIwIiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzFdLmVmZmVjdGl2ZURhdGUifSx7InZhbHVlIjoiZTBjMjFhMzQ1NTZjZTMzNjViOTE5YmUwNjlmODVkM2EyNmQ2MTcyM2Q4YjlmN2QwZjY5ZTkzMjMxZDY4ZGM2ZiIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0uaWQifSx7InZhbHVlIjoiODY4YzNjOTYwNGJlYWMxMDZiZDQzMTc3NDRjYTNjZTI2YzU3YWFiODc2YWUwMWQwZWU5NzNmYWE1NDNlNWRmOCIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udHlwZSJ9LHsidmFsdWUiOiJiNzY3YTcyMmUzNmU4MjAxYWNjMjg2MTAzYzBkZmY4Y2I2MjI4YWQyMmVkZWJmMjc4ODcxOTQ1MDVmMGVlNmNkIiwicGF0aCI6InJlbmRlck1ldGhvZFswXS50ZW1wbGF0ZU5hbWUifV0=", + "privacy": { + "obfuscated": [] + }, + "key": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller", + "signature": "0x153aeb0f59bef692f1b5bec2f20fc08f72863b0a670e87ac7c68460d311fc7a574189bb92056a15f1ef283c1784303528364d2124a006de3dba586f6162df5481b" + } + }, + { + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + ], + "name": "Republic of Singapore Driving Licence", + "type": [ + "VerifiableCredential", + "OpenAttestationCredential" + ], + "issuer": { + "id": "did:ethr:did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + "type": "OpenAttestationIssuer", + "name": "Government Technology Agency of Singapore (GovTech)", + "identityProof": { + "identityProofType": "DNS-DID", + "identifier": "example.openattestation.com" + } + }, + "validFrom": "2021-03-08T12:00:00+08:00", + "credentialSubject": { + "id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + "type": [ + "DriversLicense" + ], + "name": "Jane Doe", + "licenses": [ + { + "class": "3000A", + "description": "Motor spaceships with unladen weight <= 3000tonnes", + "effectiveDate": "2013-05-16T00:00:00+08:00" + } + ] + }, + "renderMethod": [ + { + "id": "https://demo-renderer.opencerts.io", + "type": "OpenAttestationEmbeddedRenderer", + "templateName": "GOVTECH_DEMO" + } + ], + "proof": { + "type": "OpenAttestationMerkleProofSignature2018", + "proofPurpose": "assertionMethod", + "targetHash": "ce284d21e98ac301c0e963ea6d020570091e05591dc2b787a698512e82b39001", + "proofs": [ + "08969c7baf46807ee65e495b2a93c0e27dfdc77085562ce9ab1249a7fb261681" + ], + "merkleRoot": "6fa0bdfa20b114c3e9e92fb511be62f416533a35df99a440ecc28ff4a3f601d2", + "salts": "W3sidmFsdWUiOiI1ZGU5NjM1OGRlZGVjODIwMWFhYTJjZjRkOGI4ZjYyNzA0NDc2ZTRkYzdiZDQ5OGEwOTc5MGI1MDc1NzY0NWQyIiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6ImI2YzkyMDc4YjM5OTU3NmM1YmNlZjVhOTBjYmMwMzQxNjEzN2UyZTBjODAzM2JhM2FiZDNkYTU3NjEzZGYwZGMiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiNjM0Nzk4NGNiN2Q3MDA4NTczNjJlYmFjZTgwMDEzZjQwODA0NzNiMDkyYjAyMzQ3ZDY1MGUwMGM4MGRjMTQ5ZiIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6ImVkNGJiMDQwMWQ0NDY0NTljNjQ1YWUyMjI2MGQ5M2YxYzllOTkwYzg3ZGZhYzM2YjI2N2QwMTVlZTM4MDRlMWYiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiI1NTU4OThjZmE3ZWUxZThjY2VmOGIxYWMyYjBjY2RlNWJlZmFkMDE2NTJjOTY3NmVlM2VlNGExNTNmODlhM2JhIiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiNmVmYjc3ZDY2ZDQ3MDcxNzQ5NTIyOTI4MzE1MDI5OTlkYjViN2FmOWQ2NjQ3OWRiYzFiMzlhZjhiNmI0ZTU1NSIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiMmNjOGU1OTcxMDFhYmE0NzIyYmYzZGY0MWQwYjYyNjM3MGFiNzRhOGZiZjhjMmM2MTlmNDIzN2Y3ZWFhMzJmOCIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiJmY2IxNDNjOWUwNmQzMTZlNzdlYmIzMDkxNDFiMWI5ZDE1YTRhMTQwYzk4ODFhYTY0OTY0MTQ1NDVhM2RhYzUxIiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6Ijc0NDVkNDQzMDdmOWU2ODBjNTFkMWYxZjEzYzE5YTU2NDFkNmFiNmMzYmE0NmRjMDFmMWIyZDU0YTE4ZWJkMTEiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiYmVjYjY3OTBjMWQ1MmE2YmRlMjFkMzRjYTUxZDQ5ZGViNDBkMmE0MzQ2MGYyZjI4ZDA1NzY0YjVhNzFmODFhNCIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6IjkzMzQ2ZDg0NmI1MzJkZmY0NTc5NGQ0OTVkNzk3ZDZmYzZkYTRjYTgyMzRmMzQwNjljODNjYTU0MWQwNzA4NzgiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6ImU5OTZiYTM2NTFiZjZiMGY2YWU4NDUyYjljOTM3NjBiZjRkYzRiNDYwNjZlNGZkYTQ0YzBiZTJkY2FhMmFjZTEiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiZGIwZGQ0NjcyYWYxZjdkZGJiNGVhNTYwOGMzZjBkMjc5MDljMTAxM2FjYmJkZDcwOWVjMDZjYmQ0YTM3OGZmMCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6IjA1MWZkNTUzN2Q0ZjViNzVmNWY2MTk2NmI1ODc4MDhkNGNlZTQ1N2EzOTNlMmQ0MWZmZGFjMzllZjk5ZjcwNTUiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiI3NTU3NzYxY2VhZTgzYzVmN2YwZTNkMmM4YjYxYzllMWVkZTNmMTIyNzVmZDgzOTIyNDNjNmQ4ZDNhNTYzNTM4IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6ImQ3NzE4NTkxMDUwNjc1MDhlMGQ5ZTMxMWYxZDRhZTEyNmM3ZTNkMjhjMzY4OWUxNThhNjFjNmUwZGQxZTRkMjEiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiZWEzZmEzNDdjNGUxODVhNDhhY2NiMTY4NjMzNDY2ZmMyMjc4YjdkYmEzNzNiNDM1ODI1YmIzNDdiNzMxMDA3YiIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6ImVjNDZhODc5ODI0MGQwMGNkOTJkNTBjYzE5ZTVhZDE3NjUyYjJiZjJmOGQyOTlhOWVhOTNlYWE4YmE2MDgwNzgiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLmlkIn0seyJ2YWx1ZSI6ImZhYTk2NWViNjIwMmNlNDhhNjczNzRiZTA5M2VhNTJjNDRhM2JhMzZmYmNkZjBhMWY1MzZjNTZkM2NmOGVlNzMiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLnR5cGUifSx7InZhbHVlIjoiYjlkZTJiZDRkMGZjMmVlYmZkNDE1ZTcwZTRlMjYzY2Y5MDEwM2MyYzEyMTlkZDU0OGYzOWE4Y2I2NWNlYjU5YyIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udGVtcGxhdGVOYW1lIn1d", + "privacy": { + "obfuscated": [] + }, + "key": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller", + "signature": "0x153aeb0f59bef692f1b5bec2f20fc08f72863b0a670e87ac7c68460d311fc7a574189bb92056a15f1ef283c1784303528364d2124a006de3dba586f6162df5481b" + } + } +] \ No newline at end of file diff --git a/test/fixtures/v4/__generated__/batched-wrapped-documents-did.json b/test/fixtures/v4/__generated__/batched-wrapped-documents-did.json new file mode 100644 index 00000000..49d074f8 --- /dev/null +++ b/test/fixtures/v4/__generated__/batched-wrapped-documents-did.json @@ -0,0 +1,117 @@ +[ + { + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + ], + "name": "Republic of Singapore Driving Licence", + "type": [ + "VerifiableCredential", + "OpenAttestationCredential" + ], + "issuer": { + "id": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + "type": "OpenAttestationIssuer", + "name": "Government Technology Agency of Singapore (GovTech)", + "identityProof": { + "identityProofType": "DNS-DID", + "identifier": "example.openattestation.com" + } + }, + "validFrom": "2021-03-08T12:00:00+08:00", + "credentialSubject": { + "id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + "type": [ + "DriversLicense" + ], + "name": "John Doe", + "licenses": [ + { + "class": "3", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + }, + { + "class": "3A", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + } + ] + }, + "renderMethod": [ + { + "id": "https://demo-renderer.opencerts.io", + "type": "OpenAttestationEmbeddedRenderer", + "templateName": "GOVTECH_DEMO" + } + ], + "proof": { + "type": "OpenAttestationMerkleProofSignature2018", + "proofPurpose": "assertionMethod", + "targetHash": "b449f7fb56ed2961749110037a1c40464548db71c386c925e58211505785e6ce", + "proofs": [ + "9d71ec0572df22c133656a45bd644a7e6bb1f44cb4670473263d7f2b6f2d4b04" + ], + "merkleRoot": "2e8038ad3403396fad4af3158f132c06d34fd31516b328b07001bc44f48fbeff", + "salts": "W3sidmFsdWUiOiIwMmFjZWRiYmRlZTcwMTQwOTA1MjgxN2ZmNDRlNzE3YzMyNTM0MDEyNjM4NzQyYTE1MzEyMjJkNWRhNTMyZDUyIiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6IjMwZDlmZDBkOWU2ZTc1YTg5ZTYwM2JkZjE3YWZjYzY1NDgzYzIxOWNkMTZiYjJhNmZjOTdhNjI3MjNjZTczNDciLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiZjQxY2JlNzMyMjVjMDI3YjY0ZmQzMDhlMTMxY2FmMTZkYjVkYTNiNTM1ZDE0NDQ0NThmYjk5NDUwMWU0NGU4MCIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6IjE3OTU1NzVkZjZkYzZmOTg4NzFmMDk2M2I3MTdkZDg2ZmU4MmQzMjg1NzliMGYyNDhlMDIzMDE4ZTU4NjVlMmIiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiI1MTFhZTZjMzA3NzNlZDhkMWUyZmYwMjU0ZWI3MWUxMGMxNDVmMWRhMGIzNzQ2ZjliNjE5NjNiMTFjYzA1Njg5IiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiODQ0YzEwZDVlNDhmNTM4NzY4YjkxNTJkOGFkZWE0NDk2NDlmOTk2MjQ1OGQwZTIwYzg0NmRlYjJiZDRhZTg2ZSIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiN2I1MjY1ZjVlYTUwNGI4ZTQ4YTczMWFjNzMzMGE4NWY0OGIzMTQyMTZiOWY0ZDVjM2I5MzQ0ZDZlY2U0MGFhNyIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiJjODc5OWRhMWVkNTdiZTk2YWRkNjRlNDc5Y2E0YWNiODVjNzgzMDYxZmM3ODU1NDNkZWZlODdlMmRmYmUzNWMxIiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6ImMxYjUyNTkyN2MyM2IwZGJkNWU1ODlkMjFiOWYzODIwMTg3Y2M2MTdiNjhmMjlkMTI4YWU0Njc0MjA0Njg2M2UiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiYjZhOWM4M2I4Y2MzYjZjNzlhOWYxNDE3NWJkODgwYjAxZDhkMzJjYTY5N2FkNDUzZWQyYWQyNTM2OWQ0ZGRjMyIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6IjBhZTM4MjhiZmVhMDk0MDZkZmI3MzliNjI0OTE3NTUxMGM4NWZhMzU2NWM1MjViNWYyMjAwNTMzYzMxN2I4Y2EiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6IjQ2MTVhMTNmNjU4NzA1MjdlNmJlYjc0Y2FhNzVkNTM5ODU0YzA3MjRjMmFhOWNkN2JmMTkxZjE4ZTk1MjViMTQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiM2EyZDJkYWQ2MmFiYjAyOGMzZGUzZDMxNzUyNTE4YTQ1MGY1NGZhMjc5YjcwYWU2ZDlhNWQ5ODhkMDQwZGQwNyIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6ImM0OWExYjc4ZjVkNjM5MzIyMzMxNzg4MTBkMzMwMmIzY2Y3MzUwYjJkMTk3YTAyNzRkNWE0MGVjODE1MzE3NTEiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiJiYjNkMzZhMTI4OGE4NTc0ODhjZDRmNjFmMmU1ZGNmNmM5MmE5YWVhNTM0MTM2ZjJmYjIyZTVmMGM3ZWZjZjYzIiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6ImNhYzcwOGEzMTRhYTE3MDU1Y2YwMTRlZjNiOTc4MTUzYTc5Mzk0OGQyZTJhZDgyZmY5MzY2YzA5ODUxMjY5NmEiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiMGQ5OTE4MzJhNWJmMTMzMmVlMDczZTNiMTE0ZjgzOTUwZTU5ODJkZmU4OWU0YzYwMDM5ZjliZjE4M2FjNDQ4MiIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6IjUzMzlkY2I0MDg1YTVlNmJjNWQzMjc5NGY0NjA5MzUwN2EzZGYwNDMxNzBkOTFiZDViOTAwZDA1MjBhYThjZTMiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMV0uY2xhc3MifSx7InZhbHVlIjoiNDc3MGRlNzRkNTkzYzAwZGNjMTQ5OTA0OTExZTNmOTFjODE0NmQyZGM2MTUyZDQ5NjMzNjFiMzE4M2JjZWE5NyIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1sxXS5kZXNjcmlwdGlvbiJ9LHsidmFsdWUiOiJlNzAyM2Q4YjQ1NTAyY2JlM2M2MmY4ZjRhMWU2MWJhOGI5YzRjMDQ0NThiMmM1YzY1OGU0NzE5YTllOTBmZTQ2IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzFdLmVmZmVjdGl2ZURhdGUifSx7InZhbHVlIjoiY2FhOGM0YWQ0MjFiNDgxODA1ZTIxMTRhNDExOWI2MjZmNmQ3YTk1Y2ExMjI4YmI4NmM3MTU3ZDI0ZDQ3NGM5ZSIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0uaWQifSx7InZhbHVlIjoiMDQyZmNiZjBmNTcyMzQ3Y2IxNDIwNmEwOGVmZjc4NTM3YjE0NmIwYzE2NjQyMzZmOTkyNjQwZjUwNDc4NjNiNSIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udHlwZSJ9LHsidmFsdWUiOiJmZjU4OTM0OTUyNGM4MGJhYjlhYzM4YTJlNDAzM2Y2MDc5NmM0ZTJjNDMzY2QwODZmMTE5MWE2NmJiNmYzYjdmIiwicGF0aCI6InJlbmRlck1ldGhvZFswXS50ZW1wbGF0ZU5hbWUifV0=", + "privacy": { + "obfuscated": [] + } + } + }, + { + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + ], + "name": "Republic of Singapore Driving Licence", + "type": [ + "VerifiableCredential", + "OpenAttestationCredential" + ], + "issuer": { + "id": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + "type": "OpenAttestationIssuer", + "name": "Government Technology Agency of Singapore (GovTech)", + "identityProof": { + "identityProofType": "DNS-DID", + "identifier": "example.openattestation.com" + } + }, + "validFrom": "2021-03-08T12:00:00+08:00", + "credentialSubject": { + "id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + "type": [ + "DriversLicense" + ], + "name": "Jane Doe", + "licenses": [ + { + "class": "3000A", + "description": "Motor spaceships with unladen weight <= 3000tonnes", + "effectiveDate": "2013-05-16T00:00:00+08:00" + } + ] + }, + "renderMethod": [ + { + "id": "https://demo-renderer.opencerts.io", + "type": "OpenAttestationEmbeddedRenderer", + "templateName": "GOVTECH_DEMO" + } + ], + "proof": { + "type": "OpenAttestationMerkleProofSignature2018", + "proofPurpose": "assertionMethod", + "targetHash": "9d71ec0572df22c133656a45bd644a7e6bb1f44cb4670473263d7f2b6f2d4b04", + "proofs": [ + "b449f7fb56ed2961749110037a1c40464548db71c386c925e58211505785e6ce" + ], + "merkleRoot": "2e8038ad3403396fad4af3158f132c06d34fd31516b328b07001bc44f48fbeff", + "salts": "W3sidmFsdWUiOiIxMmQ0OTZmZjhmN2E3Yzc5YzhhNzJlMDA4ZTc4NGFhNDRkNjkwMmUyNDFlMGM4YTA3NTNmMzY5MjM3YzEzODY5IiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6IjI5NjRjZDQxMzgzZjllYjRlN2I3NmY2NjAzMmI1OWFiNDIwOWFjMDY3YTQ2YjUxNGQ5ZDI2NDAyMWNmMmI1YWIiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiZDhmNzcwNjI4ZDNjZjMyY2FkNjc4NmRlODIxMjYwMjE5MmY5NDEyNzEwYTk4OWQ2NmVhOTliNDIwYmRhYmYxYSIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6IjA2NGM5NzQyZWRhODgzMzUxNjAwNDIyYWY5YjU3MmU1NzkwMmFiMjMxNDExNzEyMTc1ZDYwYjA5ZWJmNjcyZTYiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiJhZDQ3NTM3M2Y0MGNmZjA1YTY0OGI2OGNkYjllMDA4Zjk1Zjg1Njg3YzNiM2I5ODJkMTNmNmI1ZmQxMGQ4ODU3IiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiNzEzYjcyMWVhNDA5MGQzNDFhMTg2ZmVjYWM3Nzc0ZGJhYjExYjE5ZjYzOTg3ZjZmZDM1ZWZjODkwNjgyNDAzZSIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiZGNkNjY4MTFmMGVlNGQxMTdjZGIzYWQ5NTFjNTE1MmIwYWZjYTlmNmZlY2I1YjQwODc2MDRlMGVjMmY3YzAxNiIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiIxYTU4YzJiOWQ4YzQwYjUzMTdmYjFmNjcwNmM5Yzc4YTI4OWJiZTFiZTQ4Y2I1MGE5NTdkYzkwMjIzNjdmY2I4IiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6ImFkYjM3ZDAwYWU0ODhiZDgyOTFkOTAxZWY2NmIyNTY5ZTQwNDRmZjBhN2U5YTU2MTI2N2U2NGYwZmJiOWE3ZWQiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiZGY2NDNiMGM0ZjI3Y2RiYmJmMDJkZmY2MjVmM2ZlMjA2MGMxMjI4MDNjZDM5ZDA0YWY5YTg0N2M3ZmFlOGUwZSIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6ImMzNGE0ODBjM2YxYWMyYmY1ZjgyNjc5NDQ0ZDM1ZWE1ODYwMmQ5ZGU0YjA2ZTc3MmI2YTMyYzI2ZWUyMTA2YjEiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6Ijc5MWM1Yjc1ZjkwZjQ4NzEwY2E5ZjY4ZDIzYTBjZTU2MjE0YWZjYjhkOTIwNTljYTRhMzUzNmJmNzYxNTY5N2IiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiODJmMjdjMGY4MDk5OTkxMDhmZGRhYmQ4ZTNiN2NjYTQ3YmNhMTVkZmI4ZjE4MzE4MTVmY2VkNjdiMmYwNjhlYyIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6IjNlYjFjNDdjZTkwOWRiNWQ1MzhmNjE2OWNiMjlkY2M2NzY0YzAwNWRjY2Y3ZGMwZTU4OTI1YmUzMmFmNTJiOTMiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiJlMGJmYmI1MWI4YTc5NTNhZWM2OTE5ZjgwZGU0MzRmOWM1ZWVhZDY2Zjc0MTA1YmY0ZDAxM2Y1MjVjNGE0ZDczIiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6ImE5YjU3YTU2NWRmMjYxZTVkNWQ0YTJiMDM2YjQzMzgwN2NjNTlhZmE0NGU1MjZjOGY2MGViYjJlNzYzZWUwYjciLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiZDJmMDA4OGRiZWU2YjhhZGExZDlmZWJiNzIxZGJmOTZmMDU5MDVmNDc0YjVhYjZjNjNiYzZhYTg0NjdhNzVlOCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6ImU2ODc2MDBiNGU4NTEzMjc1ZGUxNDU1YjNiYmU5ODczMTZkMGMwNDI3ZTA3YjgwYWZhZWE2ZDQ5YjZlYzBhMWYiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLmlkIn0seyJ2YWx1ZSI6ImZmOTVmZjlmNGExYTQ0ZTVhMjFlNzQzMWFkODFhOGI2MzAzZjhjODQzOWJhYWFiZmRhYjU4NDhmNTkyN2Y0ZGEiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLnR5cGUifSx7InZhbHVlIjoiYTcxNGVmZGUyYzdiODhjY2IzODIyMzY0OWMxM2U3MmVhNjNmNWViODcyNGM2MzkxMGJhZWJmOTE0YWYyYWJmZCIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udGVtcGxhdGVOYW1lIn1d", + "privacy": { + "obfuscated": [] + } + } + } +] \ No newline at end of file diff --git a/test/fixtures/v4/__generated__/raw-document-did-oscp.json b/test/fixtures/v4/__generated__/raw-document-did-oscp.json new file mode 100644 index 00000000..14d8e19c --- /dev/null +++ b/test/fixtures/v4/__generated__/raw-document-did-oscp.json @@ -0,0 +1,51 @@ +{ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + ], + "type": [ + "VerifiableCredential", + "OpenAttestationCredential" + ], + "validFrom": "2021-03-08T12:00:00+08:00", + "name": "Republic of Singapore Driving Licence", + "issuer": { + "id": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + "type": "OpenAttestationIssuer", + "name": "Government Technology Agency of Singapore (GovTech)", + "identityProof": { + "identityProofType": "DNS-DID", + "identifier": "example.openattestation.com" + } + }, + "credentialStatus": { + "id": "https://ocsp-sandbox.openattestation.com", + "type": "OpenAttestationOcspResponder" + }, + "renderMethod": [ + { + "id": "https://demo-renderer.opencerts.io", + "type": "OpenAttestationEmbeddedRenderer", + "templateName": "GOVTECH_DEMO" + } + ], + "credentialSubject": { + "id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + "type": [ + "DriversLicense" + ], + "name": "John Doe", + "licenses": [ + { + "class": "3", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + }, + { + "class": "3A", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + } + ] + } +} \ No newline at end of file diff --git a/test/fixtures/v4/__generated__/raw-document-did.json b/test/fixtures/v4/__generated__/raw-document-did.json new file mode 100644 index 00000000..98a032ca --- /dev/null +++ b/test/fixtures/v4/__generated__/raw-document-did.json @@ -0,0 +1,47 @@ +{ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + ], + "type": [ + "VerifiableCredential", + "OpenAttestationCredential" + ], + "validFrom": "2021-03-08T12:00:00+08:00", + "name": "Republic of Singapore Driving Licence", + "issuer": { + "id": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + "type": "OpenAttestationIssuer", + "name": "Government Technology Agency of Singapore (GovTech)", + "identityProof": { + "identityProofType": "DNS-DID", + "identifier": "example.openattestation.com" + } + }, + "renderMethod": [ + { + "id": "https://demo-renderer.opencerts.io", + "type": "OpenAttestationEmbeddedRenderer", + "templateName": "GOVTECH_DEMO" + } + ], + "credentialSubject": { + "id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + "type": [ + "DriversLicense" + ], + "name": "John Doe", + "licenses": [ + { + "class": "3", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + }, + { + "class": "3A", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + } + ] + } +} \ No newline at end of file diff --git a/test/fixtures/v4/__generated__/sample-signing-keys.json b/test/fixtures/v4/__generated__/sample-signing-keys.json new file mode 100644 index 00000000..bb83bb41 --- /dev/null +++ b/test/fixtures/v4/__generated__/sample-signing-keys.json @@ -0,0 +1,4 @@ +{ + "public": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller", + "private": "0x497c85ed89f1874ba37532d1e33519aba15bd533cdcb90774cc497bfe3cde655" +} \ No newline at end of file diff --git a/test/fixtures/v4/__generated__/signed-wrapped-document-did-obfuscated.json b/test/fixtures/v4/__generated__/signed-wrapped-document-did-obfuscated.json new file mode 100644 index 00000000..4d2c8ed5 --- /dev/null +++ b/test/fixtures/v4/__generated__/signed-wrapped-document-did-obfuscated.json @@ -0,0 +1,61 @@ +{ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + ], + "name": "Republic of Singapore Driving Licence", + "type": [ + "VerifiableCredential", + "OpenAttestationCredential" + ], + "issuer": { + "id": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + "type": "OpenAttestationIssuer", + "name": "Government Technology Agency of Singapore (GovTech)", + "identityProof": { + "identityProofType": "DNS-DID", + "identifier": "example.openattestation.com" + } + }, + "validFrom": "2021-03-08T12:00:00+08:00", + "credentialSubject": { + "id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + "type": [ + "DriversLicense" + ], + "name": "John Doe", + "licenses": [ + { + "class": "3", + "effectiveDate": "2013-05-16T00:00:00+08:00" + }, + { + "class": "3A", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + } + ] + }, + "proof": { + "type": "OpenAttestationMerkleProofSignature2018", + "proofPurpose": "assertionMethod", + "targetHash": "4b178a75faf7d7ecff1341ee1e0907810df23c88a217b814eb12c2a4454631ec", + "proofs": [], + "merkleRoot": "4b178a75faf7d7ecff1341ee1e0907810df23c88a217b814eb12c2a4454631ec", + "salts": "W3sidmFsdWUiOiIyMzkyMzE4OGQ0MzIwYzlkMGEyZGY0MjU2ZTQ2ZTkzZTgzM2FlMWQ4YTU5YzFlYmQ5MTBkOTUxNDc1MjNiMjhmIiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6IjZjMGEzZTZmZDI0NTEyZjg5MWE4ZDY0N2RlZGU1NmIwYjBlMTNkZDcxOTVmMDRiM2EwMzY2ZDZmNDk5OWFkMTAiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiMWFhNDY3NmQwY2FjZGU1ZTljY2MyZmNiYzc1OWRjZTJlNWFhOGY5YTg1ODI5NzFlNjNlM2MzZmVjMzE2OWNiOSIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6IjZmYjU2MDJkYjg1MjY1M2Y2NDg0M2I0ODcyNTNmNGU3ZWI2NzlmZDY3Mjg4NjNmMWRkNjcyY2U1ZWEzMDAzM2YiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiJkMmZiMGQ4YzBlMzFkNmIwZDgxODQ1NGYyZDgxNGZkOTg3ODFjNjk4ZDA0OTg3MGJmOTAwNzA2M2Y4ZDAyNjNlIiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiNzBjNDk0MzM5ZDQxZjZkOTBmY2ViNzg5ODk2ZjExMTVjMDI1NWY2Njg4Yzg1MGQxNmUxMGRiNzhhZmJjOWYyMSIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiMDkyYThhMTc0NjYwNjA0YTdmZWNiOTgyNGVhNmMwYTk3ZjMyODM2MzE0MmVjMTg3NWUzZTBjZTFhNzFjZTc1ZSIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiJmZTM5YTA3ZDYwNDVmZDdlMWQxMjRlOTc1ZmQxNjYxZTQ5NzNlM2Q0NDdkMjBiOTdmZmE0YWRkMDA0YzcyZjhhIiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6IjljY2ZlNzNkMjllZDhmYTU2MWRiMTE5NjZhN2RiZWNhY2JhYTNlOWNmNDI5OTg4Y2VjMzNmNTRkOTQ0NTdhYzIiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiMDNhNWMwMDYyMzFlNWQ1MjJhNmYzOGFkNDE3YjEzYmQyYzgwMjVhZjY5ZGVhYTA0MzkwMjkwNjljNjEzMjE3ZCIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6IjNjNzhjMzdlMDA2ZjZlMTkyY2ZhZmZjYzM0NzZhODk0MmMxODNiY2JkN2NlMjJlYjhkZWNmNGQ0YTI5OGJmZmIiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6IjNiMDI3MjkwOThmMTQxY2I3Y2E5OGM2ZmIxODMyZjVhYmMyN2JmZDA5NTlkNzk5ZjUzNDRkYzVjZWY2YmMyMTQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiMzQyYmMwYWM0MjU3MmExY2U1N2YxMjcwZGRhNTlmMDFlMzZiMTM5NzhlOTdhODgzMzMxMGVjZGMyYTgzOGUyNCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6IjlmZGIwN2YwNGNiOTllZWViZTVjODFiZmRkZmIwMDRiNWVlMTVmZTBhMGE4ZDIyNjYzZmMxZGRkMzk5NmI3MjgiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiJlMTY0NTBiODVmNjJlY2JkMTgyODg4ZDQ0YjIzZGQ1YTVkZTdiNjBiN2UzZWI5YzQ1NDRmZjYzM2E4MzBlNTkxIiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6IjZjZWRmYjg5MTM3MTI3NzYwNjZlNjJkMjE1OTFjY2M0NGNiOTM5ZmNlODA0ZWI2Y2E1MWViNmUyMWE0Zjc3NTAiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZWZmZWN0aXZlRGF0ZSJ9LHsidmFsdWUiOiIxY2ZjMzA0ZjczZGUxZTUxYWMxZjA3M2RiNWI1MGIxMzRjMjY4Y2M0Y2YyMTQyMGZlYTJmNDYzNWJjM2U5ZTMxIiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzFdLmNsYXNzIn0seyJ2YWx1ZSI6ImZhMWQxMDYwZDU3OTU1NWFkZGNiMGQ1OGRiODIzZDAzMzljZDU4YjBlMzk3YTcyY2ViNjQ4M2U2NzYzYzI4MWIiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMV0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiNTkwNTA4N2JlOTVhNGFiMzI2NDRkMmQ2M2MxNGIxODhlNGU3MTg2MDdjNWI2MTlkZjc0MjYyMWU2NzdkNmVhZCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1sxXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6IjM0YWUzN2JhMzY2NzNkNzMzNDg4YTc5ZDM2ZGQyNDQwZDc2YjMwYTBlMjBjZDM1NGI2Mjk1OGU5Y2U1NjUwODciLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLmlkIn0seyJ2YWx1ZSI6IjFjNjUzNmJiNDA1NTgzMjEzMDdmNjcxNTE3ODIwNzc1NmEwZTcwYjUxNTcwMTNkOTFiMDdjMTFlZTg3Yzc2MmIiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLnR5cGUifSx7InZhbHVlIjoiMmNhODYyYzA3Y2M5MGU3M2IwN2ZkMTJlNGIzNjg4YzQ0ZGQ3OTkyN2UwMzlkNDVlOTY3NGMzNGZmMjJjMGE1MSIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udGVtcGxhdGVOYW1lIn1d", + "privacy": { + "obfuscated": [ + "0394c26c5be1bde929bf5aec2e076fc6843ace379be541c30707dab467baa59f" + ] + }, + "key": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller", + "signature": "0x1744f9615fa8d725cf4ae14f2654762dd8e0ee88a9b6d8af13cec688019a7a501e9bae10fa407fdbe359977f8124a26a0061a0ef0ea212c42fd1d91e0998928d1c" + }, + "renderMethod": [ + { + "id": "https://demo-renderer.opencerts.io", + "type": "OpenAttestationEmbeddedRenderer", + "templateName": "GOVTECH_DEMO" + } + ] +} \ No newline at end of file diff --git a/test/fixtures/v4/__generated__/signed-wrapped-document-did-oscp.json b/test/fixtures/v4/__generated__/signed-wrapped-document-did-oscp.json new file mode 100644 index 00000000..f1c406a5 --- /dev/null +++ b/test/fixtures/v4/__generated__/signed-wrapped-document-did-oscp.json @@ -0,0 +1,64 @@ +{ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + ], + "name": "Republic of Singapore Driving Licence", + "type": [ + "VerifiableCredential", + "OpenAttestationCredential" + ], + "issuer": { + "id": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + "type": "OpenAttestationIssuer", + "name": "Government Technology Agency of Singapore (GovTech)", + "identityProof": { + "identityProofType": "DNS-DID", + "identifier": "example.openattestation.com" + } + }, + "validFrom": "2021-03-08T12:00:00+08:00", + "credentialSubject": { + "id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + "type": [ + "DriversLicense" + ], + "name": "John Doe", + "licenses": [ + { + "class": "3", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + }, + { + "class": "3A", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + } + ] + }, + "credentialStatus": { + "id": "https://ocsp-sandbox.openattestation.com", + "type": "OpenAttestationOcspResponder" + }, + "renderMethod": [ + { + "id": "https://demo-renderer.opencerts.io", + "type": "OpenAttestationEmbeddedRenderer", + "templateName": "GOVTECH_DEMO" + } + ], + "proof": { + "type": "OpenAttestationMerkleProofSignature2018", + "proofPurpose": "assertionMethod", + "targetHash": "db256b67a181b7c5a1b312b64901a0c332d72a5f2f631473ba2c28a725c3ab21", + "proofs": [], + "merkleRoot": "db256b67a181b7c5a1b312b64901a0c332d72a5f2f631473ba2c28a725c3ab21", + "salts": "W3sidmFsdWUiOiI2ZTJhN2E4MjM1NzMzOTM2MGJkYzE0OTYzMTUwNzAyNTg2N2QyOWYxM2YxYjMwZmFmMDQ4Y2VmM2QyMzc2YWM2IiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6ImRkZGI5MDVmNmIzZWQ0OGVlMzkwZDljYjQ4MTdkMjk4OWMyY2VmMzQyM2UxNGE4YjQzMDMzYmFhNDM0NmY2ZGUiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiMWNiZjBjYjY2ODZkNWIyMzJkM2QwZDZiNTk1MTA0NDc0OGY4NmNlMjJkZDE1OGIxNzUwZTc2YWUyYzAzZDkwNyIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6ImJlZjJmZjNhM2MxNDEzMDYxMDVkNGMzMTJlZmZkN2M2OTUxN2U3ZjM5YTBjYTQ3ZTZkZTk4Y2M1ZTFkMzllY2UiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiI1N2M5YWIzYzRlM2RiNjE5Nzc0NjZhNjQ4ZmM5ZThjNjI2NzQ1ZDE4NmIyYWRlZDIxNDhiNDQwYWU0MWRmYjhiIiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiZmYwNDE0MjcxYWYwNzk5ZWM4YzgwMTQzMzI2NmVmNGE5YzAwNzQxMDVlNTNmMmQ3OWYwYjYzYjBjNjk1Y2Q2MCIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiOTEyNjc2YWZjZTkyYjBhNGU4MzhkNzZjZDYyZmNmMGY0YTc1NmE1MTI0NWI0YWU4YTQxN2ZkNzYxNmVhMDVkMSIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiJmNDYzYmNkYWIzYTcwNGYzMWRhOWQ5MjUwNTM3OTE1MDBiYTdjMDQzZTNiZDEzNzU3ZTgyNTI5MzYzZGNhNjc0IiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6Ijc2YWIzZWQwODk2NzZkOGJmM2FhZjE3OGQyYTUzYzI3NGZjMGUyMmFiMjJkNjU3NmIxYTUzYTAxMjMxNjUxYjAiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiNjMyYzI5MzdhZGYwMGIwYWU0NGRlYzZkNGI1NmJmN2RkYTU3ZDEzYjk3MWUxNzhlZjJiZTdmNDMwNDJlMTI4YiIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6IjkxOGNiYjU1MDg4ZGFjNDEzMzYxODEwZDE0ZTBlM2U4Mzk4N2Y2N2NjZDU1YTE5OGQ2YzZhOWEzYWM4Y2VkMDQiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6ImI5NmVkN2FjZDZjZjQwNmViZGMxZmJlY2VhY2M1ZWYxZDhkODlmZDNhZTZmZTRjMzkyMTM3M2NhY2YxYTc5NDAiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiOTVmNDFmYWZiYjNhZmY4NmM4ODU0ZTRjOWQ4MTAzY2E3NGM0NTBiODg3ZmQwOGMwNDFiYzI4NzlmN2RiMDAzYyIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6IjU2ZmU1YjZmZDYwNjE0OWZmYzhhZGZkNjY2ZDgxNGJiYzZjNWMzZjU0YjA2ZmQ4YjJjZTFmNDc2M2RkNWMwNmMiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiJmNWZhM2MyMDhiODRiNDdkZDczYTIwYmM5YjczYWY1MTI3MzIwZGUxNTIwNGExMjA0NjgzZDI0NGUwNzhkYmU5IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6IjkzODcxZTQ2MmEzZjIyNDE1YzU2ODhhOGQ3NGYyZjFlZjMwZTEwYWNlOWZiMmIyNTllOWVjMmVlZWVjMWI2NGQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiN2FmNWFjNzViYjNkZWYyNTQwOTViNWE4ZDFiNGFkZmJiZmQ3YTM3MTY4N2UzZGY2OTJmYjhlMmM2YTMyZjZiNCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6IjAwZDA2MTlhNzQ0ZWUxODIwMzQ5NzZhZmRjZmU2ZjE5ZDE1NWZkMjgwZDQzYjM0ZjhjNDM4OGJiMDQwOTBkOTQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMV0uY2xhc3MifSx7InZhbHVlIjoiOTUyNTdkMjJmMGMyYzRkNTY3MjkzMWM0OGY1OTBjY2RmMGU4NzNmY2ZmMTdjZDA2NmRmNjBjNzMxMzgxZGMwNyIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1sxXS5kZXNjcmlwdGlvbiJ9LHsidmFsdWUiOiI3ZTZlODE5MmM1OWVhMDllOGUxZDM3NTI4NGEzN2JhMTFkNmFlNTVmNmFiNGIwMjRhMGU4YjM0M2MwZTlhMWI4IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzFdLmVmZmVjdGl2ZURhdGUifSx7InZhbHVlIjoiMTRmN2U1ZWU4Zjk0ZTAyZDFiODcxYjE4YzRmZjAwOTA0ZDc4OGNhMjU4NDhlYjVlOTMwOTZmNTFhMzI0NGIwYiIsInBhdGgiOiJjcmVkZW50aWFsU3RhdHVzLmlkIn0seyJ2YWx1ZSI6IjFjNzRmODhjODNhOWZhYWQ5YjU1MjE4NjcwZDg5NzM0NTY0MjY2OTg5MzdlYTQyNmFkZmY4ZmVmOTYzMWVkNzMiLCJwYXRoIjoiY3JlZGVudGlhbFN0YXR1cy50eXBlIn0seyJ2YWx1ZSI6IjA0N2I1YzA0NDAzMjlmM2ZkODZmMDQxODRmMTk1OGZlZDQyNDhiMDI2YmM2NGI5NDM5MmNiMGRjYmU5M2VlYWYiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLmlkIn0seyJ2YWx1ZSI6IjQyZGM4Y2EzZGJiMjI2NGI4ODg0OWIyNWFkZWQ0ZWE2NWQ2ZmMzYTZlNWUyNjExMGE1MDUwNmRjYzdhYzhmNzciLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLnR5cGUifSx7InZhbHVlIjoiODg2MjJkNDRjMTBiY2VlMzUxMGRiNmE4ZjNhMGYxM2M1ODBmNmZlNWY3OGNkODVmM2FjYTIzMGE2M2QyYTZjMyIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udGVtcGxhdGVOYW1lIn1d", + "privacy": { + "obfuscated": [] + }, + "key": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller", + "signature": "0x1d889961f3b28e3433ee56e1d3226d1b069d6696f2cac99d1f1504f31c1257b216e9e42bfa8c434eaeb80bc38b0af269cab3ffd03d4410539589d9173bc4ba881c" + } +} \ No newline at end of file diff --git a/test/fixtures/v4/__generated__/signed-wrapped-document-did.json b/test/fixtures/v4/__generated__/signed-wrapped-document-did.json new file mode 100644 index 00000000..2faaaa32 --- /dev/null +++ b/test/fixtures/v4/__generated__/signed-wrapped-document-did.json @@ -0,0 +1,60 @@ +{ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + ], + "name": "Republic of Singapore Driving Licence", + "type": [ + "VerifiableCredential", + "OpenAttestationCredential" + ], + "issuer": { + "id": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + "type": "OpenAttestationIssuer", + "name": "Government Technology Agency of Singapore (GovTech)", + "identityProof": { + "identityProofType": "DNS-DID", + "identifier": "example.openattestation.com" + } + }, + "validFrom": "2021-03-08T12:00:00+08:00", + "credentialSubject": { + "id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + "type": [ + "DriversLicense" + ], + "name": "John Doe", + "licenses": [ + { + "class": "3", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + }, + { + "class": "3A", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + } + ] + }, + "renderMethod": [ + { + "id": "https://demo-renderer.opencerts.io", + "type": "OpenAttestationEmbeddedRenderer", + "templateName": "GOVTECH_DEMO" + } + ], + "proof": { + "type": "OpenAttestationMerkleProofSignature2018", + "proofPurpose": "assertionMethod", + "targetHash": "dd55a7d96d47e58350f2cfb03ebdf3f859684c9f97ba75eed55b1bdcc761c5aa", + "proofs": [], + "merkleRoot": "dd55a7d96d47e58350f2cfb03ebdf3f859684c9f97ba75eed55b1bdcc761c5aa", + "salts": "W3sidmFsdWUiOiJjYTE3MjI0YTg3NTk0NzNhNGUyZjM2YTM3NjljODU0OGM5M2RjZTQ3NmI0MjEwMTNmYTEzYTA2OTUxYTI1YzhjIiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6IjMyYzk3MDRhMmIxMWU1MzhjYTBlZWJhYWMzNmU0ZmRlYTU4ZGY0MDI4ZGVmZmJjOTkzODBjYjZkZjU3MTdiODEiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiNDE3YTFhNzY2YWM5MzhkOWVlY2FhNWRmMDdhOTBhODkyZTM3ZjA1ZmI3MzY5ZWRjNGQwYWNmNWZkMjE4YjhlMiIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6ImE1Y2FkZDIzMmQ4ZjhlMGU4ZmFhODA3OTMyYWNkZjJhODc1OWY4MWEyMDNmNmEwMjdjMTJhOTBhNjg0MWE1NWYiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiI2NGE4NjBmMmQwOGZjNGIyMDhjZWE3NmU2MjBjM2YwMDRlYzhiMmRhYjdhZTc5ZTZkZmMxZjllYjU1MWMxMmM3IiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiMzcyZmJlNDllMTdjMTA2MGEzNTk1NjVhNDA2M2VlMjkyODU1ODg0OWZhZWRkODE1MGQwYWZjZmY3NzQ2M2NmMyIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiYTE0ODAwOGQxY2JjMzM3ODJmNmNlN2UyOTFhMTM5ODE1YmRhYWFjZjg2MWYxNGYwMDk0NWU5YWIwZTk2ZjdkNiIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiI5Yzg4NTc4ZTAzZWRiNjc3NTdiNDI0NzY4MTliNWZiMGQwMDlhMGU0ZjZmMjllOGNhNTBlMWJmNWI4NWQ2ZmZiIiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6ImJhOTk1NDA1YWQ4ZmZlZmJmYTExMDA2MzE2ZDdkNjM4NDRlODk2ZmMxNDhkZjdlMWViZjNkYWZhYzI0NTY4YjQiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiZWY1ZTEzODU4YWM1MzYwNTMzODkxZjkxOGJhYjlmZjI3YmQ5YjhiYzA5MzQ4ZTc4NWMwMmI2YjYzZTcxZDNhYSIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6ImY2N2ZmNGMyZTUwYzU0M2ZmYmEyNGJiMzA4OTY5NGUxOWViZDNjOWJhMmE5MTM3NTA3N2YzOWRlN2M0ODVmY2MiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6ImIyYzQ2MjkwMDQwMDMwOGM1YjA3MmM1Y2NlMjQ4YmQ2YjRiOTgxODBjOGQ2ZDQ2YjIwNWE0MGE2YzNjMDhmMzciLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiM2QwMThlMjllOTI3MTcxN2UwNGI5ZWYwMDJkNWVmNTRmMTRiZmI3NmJlYzdhMTlkN2ZlYjcyMzM3NjU2NzU4ZiIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6ImYxNDllNmM5M2ZhNTU5ZjM4OWRjZTcwMDMwYmRmYmVlNmU3OWRjODM1NjJhYmVhN2FkOTMzNTA0OWM4MTI5NGQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiIyZGZjM2VmNDQ2NzA0MmMzMDI4NDU0MTNmMWE5MDQxYmQ2NjY3NThmNDM4MWU4OWU5NWIzZjc4NjYyYzE1NTc5IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6IjY3MjNhYjA4MzhkODMzNTJlMjhhNjQxMjliMzEwOWQzNzA5YTk3NWYyMDljZmM2NjE0MTNmODUyYzFmZTY0YzYiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiMWZiNTRmMGVhZDgyZmEyMzVlMmU5Y2RkY2ViMGQ2NTllMjRhYzhhMzM4OThmODdmMzkzZTBmZmY5OTE1Y2NmZSIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6IjhjMzJlZmNlOGE2ZTIzZGMxNzUzOTVmNzMxM2ZjMGQ4ZTk0ZTA0YjU3ZGMwMzI4YmEyNTk0NTgxMTJjNWQ4MjQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMV0uY2xhc3MifSx7InZhbHVlIjoiYmQ1YzM2Yjc1YTVmNzEwYmQ2MzJhOWM1MTY1ZGVkNmI4N2YzODY1MTg5YWRjZTc3M2FlNDMxMTlkYzljMGFiNCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1sxXS5kZXNjcmlwdGlvbiJ9LHsidmFsdWUiOiI1MmYzYTU1ZWI3MGZmZjMyYjEzZWMyNjlkZjJmODM4Mjg4NTc5YmUyMDg1NmQ3Mjc5NmI3YmY3MDFmMjY5MjU3IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzFdLmVmZmVjdGl2ZURhdGUifSx7InZhbHVlIjoiZTJjZWZiMjkzZGEzZGNmNTIzZjAwNjkwN2YyNTljNTIyOTc3MzQwZjYzNmY4YmU1MmM5ZTg5ZTEzZGVlZTk0MiIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0uaWQifSx7InZhbHVlIjoiNDNiMjFkZGU2NTY2NjI5MTNjNzJiMDExMzBkMjM0MzlkY2NjMTNiZjVhYjYwMjY5YTVmYjM3NmFlMzBkNjlkMiIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udHlwZSJ9LHsidmFsdWUiOiI0NDRmZmU3OTMzMmRkZjExOWRiZWUzZjYzYWQyZTQyYzE2ZTczMDdkMGVmOTE3NDJlZDEzNTkxYWY5M2U0NWRjIiwicGF0aCI6InJlbmRlck1ldGhvZFswXS50ZW1wbGF0ZU5hbWUifV0=", + "privacy": { + "obfuscated": [] + }, + "key": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller", + "signature": "0xa3ac9f73a7314c0aad47bad875921f5c88d2af9440d6c309fc2f93dbf43bd8235e84b744cb1ff1c09c214b559ce3bd6eb148c2f68c677cb8408d96e9b5411dfb1c" + } +} \ No newline at end of file diff --git a/test/fixtures/v4/__generated__/wrapped-document-did-oscp.json b/test/fixtures/v4/__generated__/wrapped-document-did-oscp.json new file mode 100644 index 00000000..7710fbb2 --- /dev/null +++ b/test/fixtures/v4/__generated__/wrapped-document-did-oscp.json @@ -0,0 +1,62 @@ +{ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + ], + "name": "Republic of Singapore Driving Licence", + "type": [ + "VerifiableCredential", + "OpenAttestationCredential" + ], + "issuer": { + "id": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + "type": "OpenAttestationIssuer", + "name": "Government Technology Agency of Singapore (GovTech)", + "identityProof": { + "identityProofType": "DNS-DID", + "identifier": "example.openattestation.com" + } + }, + "validFrom": "2021-03-08T12:00:00+08:00", + "credentialSubject": { + "id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + "type": [ + "DriversLicense" + ], + "name": "John Doe", + "licenses": [ + { + "class": "3", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + }, + { + "class": "3A", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + } + ] + }, + "credentialStatus": { + "id": "https://ocsp-sandbox.openattestation.com", + "type": "OpenAttestationOcspResponder" + }, + "renderMethod": [ + { + "id": "https://demo-renderer.opencerts.io", + "type": "OpenAttestationEmbeddedRenderer", + "templateName": "GOVTECH_DEMO" + } + ], + "proof": { + "type": "OpenAttestationMerkleProofSignature2018", + "proofPurpose": "assertionMethod", + "targetHash": "96a8e79b4c9b14dde88d9d6db26916215502ed09f458d0dc387c1ca73f3549f0", + "proofs": [], + "merkleRoot": "96a8e79b4c9b14dde88d9d6db26916215502ed09f458d0dc387c1ca73f3549f0", + "salts": "W3sidmFsdWUiOiI2ZGM0NzZkYmZlOTBiMjMxYzg5MjFiYmIyNTg3NTFkZGJlNzExMGFhOGM2Y2U3ODQwOGZiNmFhMDBiYzI3NTZjIiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6ImY3MTA2OTA3YzJhMDRjNzRiOWYyMzg2Yjg3MGJhMmE1MmYxMmFiZDA1Y2FiOGUyOGFhOTdhZWJhYTk1ZTRhMjAiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiNGEyNzhiYmM0MTllYTY4YTRlN2M1Y2YxMDdmZDUxNWNkNDgwYmNhNDZlZjdjNjQ1NGFiMjQwZWRmY2JjODM4NyIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6IjVhNDQyMTE0M2YxNGZjYmY4MTdhMjgwMWJhOTUzZDY1ZWQ2NDUxNDE5YTkzY2VkM2Y2MWY1NzcxNjI0YzA3MzUiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiJiY2M1OGMwZTU3NjgzYmM3NDA2NjM5ZWMwYzI3MjIxMGYzZmQzMGVkYmQ4ZjU5MjM2MjBiMzgxNzYyM2U4YWEwIiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiYzUxYWJlZGE2MTNjNGZiMDY5ZDQ2MzNhMTcwNzIyYWE2YmRiMGFlZDkzOTAzZjRiMmJjZTAyZjU1NWZiNDY5OSIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiM2U3MjVhNzk1YzZmNDQyNDc5NzZkNWUzNGQ3M2YyMzA4ZTEyNjc3MzNjODY1YWNjYTUwYTc1ODVmNDIwNDI4ZSIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiJkY2QyMzM5MTVmODVkMjIzNzFlNWFkMzc2Y2I3M2ZkNGVkODcxNzVjNWUzYTgxYjhiMjhmNWE1ZDA3NDllMzdkIiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6IjJlY2MyOGVmZDNjNTU5ZmU5MGNiYTg2NDQ4MmM3YTk0YmU5NTRhNzY4NWY2ZmI5ZGQ5MDJiZTUwMDE5OTRjMzgiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiOTI3ZDM1ZDUzZTE3MThkMWE3ZWM2NDFkMzFmYmU4OThiMGI5YzkyZGRhZmMwMmU4MGU5NjgwMThlNmUyZTgyNCIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6IjI3OTVkNzgxODY2ZjNmYTI4YThhMzIxMmI4ODdjMGNjMzkyMWM2Njc2NmIxZDJmZDdkYjY1NzBhMGM1Y2ExZTEiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6IjA2ZmViZjYyNTZhY2FlMWIyZjg5MTE0MjM2NzY2YjNkMzIzZDMwNzQzZGJiZDRmODI0NWU1NjA5MTRhZjcwZmQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiNjBkY2E2Njg3MGNmNzMxZDkwNjcwZTA5YTg2MDA2ZTJlNjRjYzRiZGQ3ZWYyYTQyZjMwYWUwY2M4N2Q3ZmY3MSIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6IjdhMjBiMmMwMTk3MDE0YjA5OWY2MDg4NGM4YjA1NWMzYmIxNjY3YzRiZWRiMjIzMDY4NGI2YTMxZjY1ZjQ4ZTgiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiJiYzRiMGJiODkzZTIxNGYyMzlkZmQ4ZGY2MGQ1ZDdkZjZmNzBjNjI4N2YzNmQ3ZWVlZGVhMjE1NDMzNjE5ODA2IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6ImY4N2ZhNjNmMDY1MmY2NzJjYjkyOWI2YzFiYWMwOGFmOTNiZjc5NTgwOWYzMjlmZmEyYmJlMmE1NGJmOThiODEiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiYzc4MDE5Njk4NWEzNDFjYzJkZmQwMzA0YTdhOTUzZGFkZGE2MmZhYjhlOGYyZTFlZWViNGNlZDM3YTIwZDJiMyIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6Ijc0Y2ZmNjIxZDhhZTM2YmQxNWFlMzFkZTIwMTE1Mzg1MDZmNDhlMjkxNjExYmM3ZmIzNjVkYjNkMTI3ZGYxYzYiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMV0uY2xhc3MifSx7InZhbHVlIjoiZDg2ZGQ0ZjNkNDA1N2FiN2I3NzI2ZWU0ZmE5Y2U1NjlkZTc3YmZiNGNhNzBmYTY5NzVlNWZjOWEwOTAwZjdkNCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1sxXS5kZXNjcmlwdGlvbiJ9LHsidmFsdWUiOiI4ZDhmZTQ3MGY3NmEyODNkNzQ1ZmM4MGYwZjEyZmZjOGU5ZjU3OGE5NjY5NDRkODBmOTM2MDhjNWZjOTM4ZTAzIiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzFdLmVmZmVjdGl2ZURhdGUifSx7InZhbHVlIjoiNjkwOGFlOTBiYTI0YzZjNmRhZDcxZmEzZmQxNGJiYWYxNTMyOGJhZDliN2Y0NDI5Y2IzN2Q5YjIyYWM4MzRjNCIsInBhdGgiOiJjcmVkZW50aWFsU3RhdHVzLmlkIn0seyJ2YWx1ZSI6IjM2MDU1ODQzZWU1MTNkZDVlYmY5MjUzMTM5ZTI0YjkxZWM5MDk4NzI1Y2ZhZDQzYmE3ODkxNWRiMGFhODJjYTEiLCJwYXRoIjoiY3JlZGVudGlhbFN0YXR1cy50eXBlIn0seyJ2YWx1ZSI6IjQzMjJhMDA0NzNjYzIzNWVmNzFkYWNiMDFlNjcwMGNkZWE1YjUxNWIzNzM2MDY0ZWU0NzJhNjM4ZWFmYjUxNzMiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLmlkIn0seyJ2YWx1ZSI6IjRmNTJjZTRjN2JmNTQxMWNhMGFhOTJhZWY1YWE5NWQyNDYwOThhZmE5N2Q2YWI0YTMwY2JkYTBhNzM5ZTg0ODAiLCJwYXRoIjoicmVuZGVyTWV0aG9kWzBdLnR5cGUifSx7InZhbHVlIjoiMzM3YTkyODViYjFkYzgyYzYyMTFhMTBhMDA5ODkxOTNjMzQyZjczMDFiZTYwZjEzY2E4M2IzYWMxMTQ2MDkzMyIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udGVtcGxhdGVOYW1lIn1d", + "privacy": { + "obfuscated": [] + } + } +} \ No newline at end of file diff --git a/test/fixtures/v4/__generated__/wrapped-document-did.json b/test/fixtures/v4/__generated__/wrapped-document-did.json new file mode 100644 index 00000000..19039c49 --- /dev/null +++ b/test/fixtures/v4/__generated__/wrapped-document-did.json @@ -0,0 +1,58 @@ +{ + "@context": [ + "https://www.w3.org/ns/credentials/v2", + "https://schemata.openattestation.com/com/openattestation/4.0/alpha-context.json" + ], + "name": "Republic of Singapore Driving Licence", + "type": [ + "VerifiableCredential", + "OpenAttestationCredential" + ], + "issuer": { + "id": "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89", + "type": "OpenAttestationIssuer", + "name": "Government Technology Agency of Singapore (GovTech)", + "identityProof": { + "identityProofType": "DNS-DID", + "identifier": "example.openattestation.com" + } + }, + "validFrom": "2021-03-08T12:00:00+08:00", + "credentialSubject": { + "id": "urn:uuid:a013fb9d-bb03-4056-b696-05575eceaf42", + "type": [ + "DriversLicense" + ], + "name": "John Doe", + "licenses": [ + { + "class": "3", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + }, + { + "class": "3A", + "description": "Motor cars with unladen weight <= 3000kg", + "effectiveDate": "2013-05-16T00:00:00+08:00" + } + ] + }, + "renderMethod": [ + { + "id": "https://demo-renderer.opencerts.io", + "type": "OpenAttestationEmbeddedRenderer", + "templateName": "GOVTECH_DEMO" + } + ], + "proof": { + "type": "OpenAttestationMerkleProofSignature2018", + "proofPurpose": "assertionMethod", + "targetHash": "dd55a7d96d47e58350f2cfb03ebdf3f859684c9f97ba75eed55b1bdcc761c5aa", + "proofs": [], + "merkleRoot": "dd55a7d96d47e58350f2cfb03ebdf3f859684c9f97ba75eed55b1bdcc761c5aa", + "salts": "W3sidmFsdWUiOiJjYTE3MjI0YTg3NTk0NzNhNGUyZjM2YTM3NjljODU0OGM5M2RjZTQ3NmI0MjEwMTNmYTEzYTA2OTUxYTI1YzhjIiwicGF0aCI6IkBjb250ZXh0WzBdIn0seyJ2YWx1ZSI6IjMyYzk3MDRhMmIxMWU1MzhjYTBlZWJhYWMzNmU0ZmRlYTU4ZGY0MDI4ZGVmZmJjOTkzODBjYjZkZjU3MTdiODEiLCJwYXRoIjoiQGNvbnRleHRbMV0ifSx7InZhbHVlIjoiNDE3YTFhNzY2YWM5MzhkOWVlY2FhNWRmMDdhOTBhODkyZTM3ZjA1ZmI3MzY5ZWRjNGQwYWNmNWZkMjE4YjhlMiIsInBhdGgiOiJuYW1lIn0seyJ2YWx1ZSI6ImE1Y2FkZDIzMmQ4ZjhlMGU4ZmFhODA3OTMyYWNkZjJhODc1OWY4MWEyMDNmNmEwMjdjMTJhOTBhNjg0MWE1NWYiLCJwYXRoIjoidHlwZVswXSJ9LHsidmFsdWUiOiI2NGE4NjBmMmQwOGZjNGIyMDhjZWE3NmU2MjBjM2YwMDRlYzhiMmRhYjdhZTc5ZTZkZmMxZjllYjU1MWMxMmM3IiwicGF0aCI6InR5cGVbMV0ifSx7InZhbHVlIjoiMzcyZmJlNDllMTdjMTA2MGEzNTk1NjVhNDA2M2VlMjkyODU1ODg0OWZhZWRkODE1MGQwYWZjZmY3NzQ2M2NmMyIsInBhdGgiOiJpc3N1ZXIuaWQifSx7InZhbHVlIjoiYTE0ODAwOGQxY2JjMzM3ODJmNmNlN2UyOTFhMTM5ODE1YmRhYWFjZjg2MWYxNGYwMDk0NWU5YWIwZTk2ZjdkNiIsInBhdGgiOiJpc3N1ZXIudHlwZSJ9LHsidmFsdWUiOiI5Yzg4NTc4ZTAzZWRiNjc3NTdiNDI0NzY4MTliNWZiMGQwMDlhMGU0ZjZmMjllOGNhNTBlMWJmNWI4NWQ2ZmZiIiwicGF0aCI6Imlzc3Vlci5uYW1lIn0seyJ2YWx1ZSI6ImJhOTk1NDA1YWQ4ZmZlZmJmYTExMDA2MzE2ZDdkNjM4NDRlODk2ZmMxNDhkZjdlMWViZjNkYWZhYzI0NTY4YjQiLCJwYXRoIjoiaXNzdWVyLmlkZW50aXR5UHJvb2YuaWRlbnRpdHlQcm9vZlR5cGUifSx7InZhbHVlIjoiZWY1ZTEzODU4YWM1MzYwNTMzODkxZjkxOGJhYjlmZjI3YmQ5YjhiYzA5MzQ4ZTc4NWMwMmI2YjYzZTcxZDNhYSIsInBhdGgiOiJpc3N1ZXIuaWRlbnRpdHlQcm9vZi5pZGVudGlmaWVyIn0seyJ2YWx1ZSI6ImY2N2ZmNGMyZTUwYzU0M2ZmYmEyNGJiMzA4OTY5NGUxOWViZDNjOWJhMmE5MTM3NTA3N2YzOWRlN2M0ODVmY2MiLCJwYXRoIjoidmFsaWRGcm9tIn0seyJ2YWx1ZSI6ImIyYzQ2MjkwMDQwMDMwOGM1YjA3MmM1Y2NlMjQ4YmQ2YjRiOTgxODBjOGQ2ZDQ2YjIwNWE0MGE2YzNjMDhmMzciLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QuaWQifSx7InZhbHVlIjoiM2QwMThlMjllOTI3MTcxN2UwNGI5ZWYwMDJkNWVmNTRmMTRiZmI3NmJlYzdhMTlkN2ZlYjcyMzM3NjU2NzU4ZiIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC50eXBlWzBdIn0seyJ2YWx1ZSI6ImYxNDllNmM5M2ZhNTU5ZjM4OWRjZTcwMDMwYmRmYmVlNmU3OWRjODM1NjJhYmVhN2FkOTMzNTA0OWM4MTI5NGQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubmFtZSJ9LHsidmFsdWUiOiIyZGZjM2VmNDQ2NzA0MmMzMDI4NDU0MTNmMWE5MDQxYmQ2NjY3NThmNDM4MWU4OWU5NWIzZjc4NjYyYzE1NTc5IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzBdLmNsYXNzIn0seyJ2YWx1ZSI6IjY3MjNhYjA4MzhkODMzNTJlMjhhNjQxMjliMzEwOWQzNzA5YTk3NWYyMDljZmM2NjE0MTNmODUyYzFmZTY0YzYiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMF0uZGVzY3JpcHRpb24ifSx7InZhbHVlIjoiMWZiNTRmMGVhZDgyZmEyMzVlMmU5Y2RkY2ViMGQ2NTllMjRhYzhhMzM4OThmODdmMzkzZTBmZmY5OTE1Y2NmZSIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1swXS5lZmZlY3RpdmVEYXRlIn0seyJ2YWx1ZSI6IjhjMzJlZmNlOGE2ZTIzZGMxNzUzOTVmNzMxM2ZjMGQ4ZTk0ZTA0YjU3ZGMwMzI4YmEyNTk0NTgxMTJjNWQ4MjQiLCJwYXRoIjoiY3JlZGVudGlhbFN1YmplY3QubGljZW5zZXNbMV0uY2xhc3MifSx7InZhbHVlIjoiYmQ1YzM2Yjc1YTVmNzEwYmQ2MzJhOWM1MTY1ZGVkNmI4N2YzODY1MTg5YWRjZTc3M2FlNDMxMTlkYzljMGFiNCIsInBhdGgiOiJjcmVkZW50aWFsU3ViamVjdC5saWNlbnNlc1sxXS5kZXNjcmlwdGlvbiJ9LHsidmFsdWUiOiI1MmYzYTU1ZWI3MGZmZjMyYjEzZWMyNjlkZjJmODM4Mjg4NTc5YmUyMDg1NmQ3Mjc5NmI3YmY3MDFmMjY5MjU3IiwicGF0aCI6ImNyZWRlbnRpYWxTdWJqZWN0LmxpY2Vuc2VzWzFdLmVmZmVjdGl2ZURhdGUifSx7InZhbHVlIjoiZTJjZWZiMjkzZGEzZGNmNTIzZjAwNjkwN2YyNTljNTIyOTc3MzQwZjYzNmY4YmU1MmM5ZTg5ZTEzZGVlZTk0MiIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0uaWQifSx7InZhbHVlIjoiNDNiMjFkZGU2NTY2NjI5MTNjNzJiMDExMzBkMjM0MzlkY2NjMTNiZjVhYjYwMjY5YTVmYjM3NmFlMzBkNjlkMiIsInBhdGgiOiJyZW5kZXJNZXRob2RbMF0udHlwZSJ9LHsidmFsdWUiOiI0NDRmZmU3OTMzMmRkZjExOWRiZWUzZjYzYWQyZTQyYzE2ZTczMDdkMGVmOTE3NDJlZDEzNTkxYWY5M2U0NWRjIiwicGF0aCI6InJlbmRlck1ldGhvZFswXS50ZW1wbGF0ZU5hbWUifV0=", + "privacy": { + "obfuscated": [] + } + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index ab9b0b7b..c3cde936 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,17 +3,23 @@ "files": true }, "compilerOptions": { - "lib": ["es2019"], - "target": "es5", + "strict": true, + // affects emission "module": "commonjs", "moduleResolution": "node", - "strict": true, - "baseUrl": ".", + // affects emission + // 98% browser support (https://caniuse.com/?search=es6) + // Node >12 already supports ES2019 (https://node.green/#ES2019) + "target": "ES6", + // 96% browser support (https://caniuse.com/array-flat) + "lib": ["ES2019.Array"], "typeRoots": ["./src/@types", "./node_modules/@types"], "skipLibCheck": true, "resolveJsonModule": true, + // affects emission "esModuleInterop": true, - "allowJs": true + "allowJs": true, + "outDir": "./dist" }, "include": ["./src/**/*"] }