From c6f9fc6292f3ef695db131a4be7a6cceb53df2ee Mon Sep 17 00:00:00 2001 From: Joao Santos Date: Tue, 9 Mar 2021 10:57:50 -0300 Subject: [PATCH 1/6] new liveIdDocument --- src/creds/definitions.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/creds/definitions.js b/src/creds/definitions.js index 0ad2ad2a..612250e1 100644 --- a/src/creds/definitions.js +++ b/src/creds/definitions.js @@ -82,6 +82,29 @@ const definitions = [ 'claim-cvc:Document.evidences-v1', ], }, + { + identifier: 'credential-cvc:LiveIdDocument-v1', + version: '1', + depends: [ + 'claim-cvc:Document.type-v1', + 'claim-cvc:Document.number-v1', + 'claim-cvc:Document.name-v1', + 'claim-cvc:Document.gender-v1', + 'claim-cvc:Document.issueCountry-v1', + 'claim-cvc:Document.placeOfBirth-v1', + 'claim-cvc:Document.dateOfBirth-v1', + 'claim-cvc:Document.dateOfExpiry-v1', + 'claim-cvc:Document.nationality-v1', + 'claim-cvc:Document.evidences-v1', + ], + required: [ + 'claim-cvc:Document.type-v1', + 'claim-cvc:Document.name-v1', + 'claim-cvc:Document.dateOfBirth-v1', + 'claim-cvc:Document.issueCountry-v1', + 'claim-cvc:Document.evidences-v1', + ], + }, { identifier: 'credential-cvc:Address-v1', version: '1', From b0fe167f759bb729c5737222adf1d0a261ca0f97 Mon Sep 17 00:00:00 2001 From: Lucas Cunha Date: Tue, 9 Mar 2021 14:54:15 -0300 Subject: [PATCH 2/6] Add dist folder --- .gitignore | 4 +- dist/browser/AggregationHandler.js | 1 + dist/browser/SecureRandom.js | 1 + dist/browser/claim/Claim.js | 1 + dist/browser/claim/__mocks__/definitions.js | 1 + dist/browser/claim/definitions.js | 1 + dist/browser/constants/headers.js | 1 + dist/browser/constants/index.js | 1 + dist/browser/creds/ClaimModel.js | 1 + dist/browser/creds/CvcMerkleProof.js | 1 + dist/browser/creds/VerifiableCredential.js | 1 + dist/browser/creds/__mocks__/definitions.js | 1 + dist/browser/creds/definitions.js | 1 + dist/browser/errors/definitions.js | 1 + dist/browser/errors/idvErrors.js | 1 + dist/browser/errors/index.js | 1 + dist/browser/index.js | 1 + dist/browser/isClaimRelated.js | 1 + dist/browser/isValidGlobalIdentifier.js | 1 + dist/browser/lib/crypto.js | 1 + dist/browser/logger.js | 1 + .../schemas/generator/SchemaGenerator.js | 1 + .../services/DefaultAnchorServiceImpl.js | 1 + .../services/DummyAnchorServiceImpl.js | 1 + .../browser/services/MiniCryptoManagerImpl.js | 1 + .../browser/services/__mocks__/httpService.js | 1 + dist/browser/services/anchorService.js | 1 + dist/browser/services/config.js | 1 + dist/browser/services/httpService.js | 1 + dist/browser/services/index.js | 1 + dist/browser/timeHelper.js | 1 + dist/cjs/AggregationHandler.js | 68 ++ dist/cjs/SecureRandom.js | 42 + dist/cjs/claim/Claim.js | 365 +++++++++ dist/cjs/claim/__mocks__/definitions.js | 33 + dist/cjs/claim/definitions.js | 618 ++++++++++++++ dist/cjs/constants/headers.js | 10 + dist/cjs/constants/index.js | 7 + dist/cjs/creds/ClaimModel.js | 25 + dist/cjs/creds/CvcMerkleProof.js | 62 ++ dist/cjs/creds/VerifiableCredential.js | 759 ++++++++++++++++++ dist/cjs/creds/__mocks__/definitions.js | 18 + dist/cjs/creds/definitions.js | 68 ++ dist/cjs/errors/definitions.js | 446 ++++++++++ dist/cjs/errors/idvErrors.js | 34 + dist/cjs/errors/index.js | 10 + dist/cjs/index.js | 35 + dist/cjs/isClaimRelated.js | 41 + dist/cjs/isValidGlobalIdentifier.js | 40 + dist/cjs/lib/crypto.js | 9 + dist/cjs/logger.js | 13 + dist/cjs/schemas/generator/SchemaGenerator.js | 257 ++++++ dist/cjs/services/DefaultAnchorServiceImpl.js | 162 ++++ dist/cjs/services/DummyAnchorServiceImpl.js | 134 ++++ dist/cjs/services/MiniCryptoManagerImpl.js | 83 ++ dist/cjs/services/__mocks__/httpService.js | 80 ++ dist/cjs/services/anchorService.js | 20 + dist/cjs/services/config.js | 50 ++ dist/cjs/services/httpService.js | 26 + dist/cjs/services/index.js | 58 ++ dist/cjs/timeHelper.js | 37 + dist/es/AggregationHandler.js | 66 ++ dist/es/SecureRandom.js | 40 + dist/es/claim/Claim.js | 363 +++++++++ dist/es/claim/__mocks__/definitions.js | 31 + dist/es/claim/definitions.js | 616 ++++++++++++++ dist/es/constants/headers.js | 8 + dist/es/constants/index.js | 5 + dist/es/creds/ClaimModel.js | 23 + dist/es/creds/CvcMerkleProof.js | 60 ++ dist/es/creds/VerifiableCredential.js | 741 +++++++++++++++++ dist/es/creds/__mocks__/definitions.js | 16 + dist/es/creds/definitions.js | 66 ++ dist/es/errors/definitions.js | 444 ++++++++++ dist/es/errors/idvErrors.js | 32 + dist/es/errors/index.js | 8 + dist/es/index.js | 33 + dist/es/isClaimRelated.js | 39 + dist/es/isValidGlobalIdentifier.js | 38 + dist/es/lib/crypto.js | 7 + dist/es/logger.js | 11 + dist/es/schemas/generator/SchemaGenerator.js | 255 ++++++ dist/es/services/DefaultAnchorServiceImpl.js | 124 +++ dist/es/services/DummyAnchorServiceImpl.js | 100 +++ dist/es/services/MiniCryptoManagerImpl.js | 81 ++ dist/es/services/__mocks__/httpService.js | 68 ++ dist/es/services/anchorService.js | 18 + dist/es/services/config.js | 48 ++ dist/es/services/httpService.js | 16 + dist/es/services/index.js | 56 ++ dist/es/timeHelper.js | 35 + 91 files changed, 7090 insertions(+), 2 deletions(-) create mode 100644 dist/browser/AggregationHandler.js create mode 100644 dist/browser/SecureRandom.js create mode 100644 dist/browser/claim/Claim.js create mode 100644 dist/browser/claim/__mocks__/definitions.js create mode 100644 dist/browser/claim/definitions.js create mode 100644 dist/browser/constants/headers.js create mode 100644 dist/browser/constants/index.js create mode 100644 dist/browser/creds/ClaimModel.js create mode 100644 dist/browser/creds/CvcMerkleProof.js create mode 100644 dist/browser/creds/VerifiableCredential.js create mode 100644 dist/browser/creds/__mocks__/definitions.js create mode 100644 dist/browser/creds/definitions.js create mode 100644 dist/browser/errors/definitions.js create mode 100644 dist/browser/errors/idvErrors.js create mode 100644 dist/browser/errors/index.js create mode 100644 dist/browser/index.js create mode 100644 dist/browser/isClaimRelated.js create mode 100644 dist/browser/isValidGlobalIdentifier.js create mode 100644 dist/browser/lib/crypto.js create mode 100644 dist/browser/logger.js create mode 100644 dist/browser/schemas/generator/SchemaGenerator.js create mode 100644 dist/browser/services/DefaultAnchorServiceImpl.js create mode 100644 dist/browser/services/DummyAnchorServiceImpl.js create mode 100644 dist/browser/services/MiniCryptoManagerImpl.js create mode 100644 dist/browser/services/__mocks__/httpService.js create mode 100644 dist/browser/services/anchorService.js create mode 100644 dist/browser/services/config.js create mode 100644 dist/browser/services/httpService.js create mode 100644 dist/browser/services/index.js create mode 100644 dist/browser/timeHelper.js create mode 100644 dist/cjs/AggregationHandler.js create mode 100644 dist/cjs/SecureRandom.js create mode 100644 dist/cjs/claim/Claim.js create mode 100644 dist/cjs/claim/__mocks__/definitions.js create mode 100644 dist/cjs/claim/definitions.js create mode 100644 dist/cjs/constants/headers.js create mode 100644 dist/cjs/constants/index.js create mode 100644 dist/cjs/creds/ClaimModel.js create mode 100644 dist/cjs/creds/CvcMerkleProof.js create mode 100644 dist/cjs/creds/VerifiableCredential.js create mode 100644 dist/cjs/creds/__mocks__/definitions.js create mode 100644 dist/cjs/creds/definitions.js create mode 100644 dist/cjs/errors/definitions.js create mode 100644 dist/cjs/errors/idvErrors.js create mode 100644 dist/cjs/errors/index.js create mode 100644 dist/cjs/index.js create mode 100644 dist/cjs/isClaimRelated.js create mode 100644 dist/cjs/isValidGlobalIdentifier.js create mode 100644 dist/cjs/lib/crypto.js create mode 100644 dist/cjs/logger.js create mode 100644 dist/cjs/schemas/generator/SchemaGenerator.js create mode 100644 dist/cjs/services/DefaultAnchorServiceImpl.js create mode 100644 dist/cjs/services/DummyAnchorServiceImpl.js create mode 100644 dist/cjs/services/MiniCryptoManagerImpl.js create mode 100644 dist/cjs/services/__mocks__/httpService.js create mode 100644 dist/cjs/services/anchorService.js create mode 100644 dist/cjs/services/config.js create mode 100644 dist/cjs/services/httpService.js create mode 100644 dist/cjs/services/index.js create mode 100644 dist/cjs/timeHelper.js create mode 100644 dist/es/AggregationHandler.js create mode 100644 dist/es/SecureRandom.js create mode 100644 dist/es/claim/Claim.js create mode 100644 dist/es/claim/__mocks__/definitions.js create mode 100644 dist/es/claim/definitions.js create mode 100644 dist/es/constants/headers.js create mode 100644 dist/es/constants/index.js create mode 100644 dist/es/creds/ClaimModel.js create mode 100644 dist/es/creds/CvcMerkleProof.js create mode 100644 dist/es/creds/VerifiableCredential.js create mode 100644 dist/es/creds/__mocks__/definitions.js create mode 100644 dist/es/creds/definitions.js create mode 100644 dist/es/errors/definitions.js create mode 100644 dist/es/errors/idvErrors.js create mode 100644 dist/es/errors/index.js create mode 100644 dist/es/index.js create mode 100644 dist/es/isClaimRelated.js create mode 100644 dist/es/isValidGlobalIdentifier.js create mode 100644 dist/es/lib/crypto.js create mode 100644 dist/es/logger.js create mode 100644 dist/es/schemas/generator/SchemaGenerator.js create mode 100644 dist/es/services/DefaultAnchorServiceImpl.js create mode 100644 dist/es/services/DummyAnchorServiceImpl.js create mode 100644 dist/es/services/MiniCryptoManagerImpl.js create mode 100644 dist/es/services/__mocks__/httpService.js create mode 100644 dist/es/services/anchorService.js create mode 100644 dist/es/services/config.js create mode 100644 dist/es/services/httpService.js create mode 100644 dist/es/services/index.js create mode 100644 dist/es/timeHelper.js diff --git a/.gitignore b/.gitignore index b62323d3..7c311142 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ node_modules/ npm-debug.log build .DS_Store -dist +#dist .history/ -.history \ No newline at end of file +.history diff --git a/dist/browser/AggregationHandler.js b/dist/browser/AggregationHandler.js new file mode 100644 index 00000000..8f6b879d --- /dev/null +++ b/dist/browser/AggregationHandler.js @@ -0,0 +1 @@ +'use strict';var _toConsumableArray2=require("babel-runtime/helpers/toConsumableArray"),_toConsumableArray3=_interopRequireDefault(_toConsumableArray2);function _interopRequireDefault(a){return a&&a.__esModule?a:{default:a}}var _=require("lodash"),validateEmptyParametersOperators=function(a){if(!_.isEmpty(a))throw new Error("parameters should be empty");return!0},validateNotEmptyParametersOperators=function(a){if(!a&&_.isEmpty(a))throw new Error("parameters should not be empty");return!0},validatePathParametersOperators=function(a){if(!_.isString(a))throw new Error("parameters should be string");return!0},validateNumberParametersOperators=function(a){if(!_.isNumber(a))throw new Error("parameters should be number");return!0},validateObjectParametersOperators=function(a){if(!_.isObject(a))throw new Error("parameters should be object");return!0},sort=function(a,b){var c=_.keys(b)[0],d=b[c],e=_.sortBy(a,c);return"ASC"===d?e:_.reverse(e)},AGGREGATION_OPERATORS_MAP={none:function(a,b){return validateEmptyParametersOperators(b)?[].concat((0,_toConsumableArray3.default)(a)):null},$limit:function(a,b){return validateNumberParametersOperators(b)?[].concat((0,_toConsumableArray3.default)(_.slice(a,0,b))):null},$min:function(a,b){return validatePathParametersOperators(b)?[_.minBy(a,b)]:null},$max:function(a,b){return validatePathParametersOperators(b)?[_.maxBy(a,b)]:null},$first:function(a,b){return validateNotEmptyParametersOperators(b)?[_.first(a)]:null},$last:function(a,b){return validateNotEmptyParametersOperators(b)?[_.last(a)]:null},$sort:function(a,b){return validateObjectParametersOperators(b)?[].concat((0,_toConsumableArray3.default)(sort(a,b))):null}};function aggregate(a,b){var c=[].concat((0,_toConsumableArray3.default)(a));return _.forEach(b,function(a){var b=_.keys(a)[0];if(!_.includes(_.keys(AGGREGATION_OPERATORS_MAP),b))throw new Error("Invalid operator: "+b);var d=a[b],e=AGGREGATION_OPERATORS_MAP[b];c=e(c,d)}),c}module.exports=aggregate; \ No newline at end of file diff --git a/dist/browser/SecureRandom.js b/dist/browser/SecureRandom.js new file mode 100644 index 00000000..6f366569 --- /dev/null +++ b/dist/browser/SecureRandom.js @@ -0,0 +1 @@ +'use strict';var _classCallCheck2=require("babel-runtime/helpers/classCallCheck"),_classCallCheck3=_interopRequireDefault(_classCallCheck2),_createClass2=require("babel-runtime/helpers/createClass"),_createClass3=_interopRequireDefault(_createClass2);function _interopRequireDefault(a){return a&&a.__esModule?a:{default:a}}var sjcl=require("sjcl"),logger=require("./logger"),SecureRandom=function(){function a(b){if((0,_classCallCheck3.default)(this,a),logger.debug("Init Secure Random"),this.sjclRandom=new sjcl.prng(10),b){var c=sjcl.codec.hex.toBits(b);this.sjclRandom.addEntropy(c,void 0,"csprng"),this.isSeeded=!0}else try{logger.debug("Trying crypto");var d=require("crypto").randomBytes(1024).toString("hex"),e=sjcl.codec.hex.toBits(d);this.sjclRandom.addEntropy(e,void 0,"csprng"),this.isSeeded=!0}catch(a){logger.warn("Crypto: "+a),this.isSeeded=!1}}return(0,_createClass3.default)(a,[{key:"wordWith",value:function(a){if(!this.isSeeded)throw new Error("Can't user SecureRandom before seeding");var b=this.sjclRandom.randomWords(a/8,10);return sjcl.codec.hex.fromBits(b)}}]),a}();module.exports=SecureRandom; \ No newline at end of file diff --git a/dist/browser/claim/Claim.js b/dist/browser/claim/Claim.js new file mode 100644 index 00000000..7d6c9d8d --- /dev/null +++ b/dist/browser/claim/Claim.js @@ -0,0 +1 @@ +'use strict';var _toConsumableArray2=require("babel-runtime/helpers/toConsumableArray"),_toConsumableArray3=_interopRequireDefault(_toConsumableArray2),_getIterator2=require("babel-runtime/core-js/get-iterator"),_getIterator3=_interopRequireDefault(_getIterator2),_getPrototypeOf=require("babel-runtime/core-js/object/get-prototype-of"),_getPrototypeOf2=_interopRequireDefault(_getPrototypeOf),_classCallCheck2=require("babel-runtime/helpers/classCallCheck"),_classCallCheck3=_interopRequireDefault(_classCallCheck2),_createClass2=require("babel-runtime/helpers/createClass"),_createClass3=_interopRequireDefault(_createClass2),_possibleConstructorReturn2=require("babel-runtime/helpers/possibleConstructorReturn"),_possibleConstructorReturn3=_interopRequireDefault(_possibleConstructorReturn2),_get2=require("babel-runtime/helpers/get"),_get3=_interopRequireDefault(_get2),_inherits2=require("babel-runtime/helpers/inherits"),_inherits3=_interopRequireDefault(_inherits2);function _interopRequireDefault(a){return a&&a.__esModule?a:{default:a}}var _=require("lodash"),sjcl=require("sjcl"),_require=require("@identity.com/uca"),UserCollectableAttribute=_require.UserCollectableAttribute,definitions=require("./definitions"),_require2=require("../services"),services=_require2.services,validIdentifiers=_.map(definitions,function(a){return a.identifier}),getDefinition=function(a,b){return b?_.find(definitions,{identifier:a,version:b}):_.find(definitions,{identifier:a})},isArrayAttestableValue=function(a){return-1t.getTime()&&k.push(b)}}return _.isEmpty(j)&&_.isEmpty(l)&&_.isEmpty(m)&&_.isEmpty(n)&&_.isEmpty(k)&&(f=!0),f}function requesterGrantVerify(a,b,c,d){var e=_.get(a.proof,"anchor.subject.label"),f=_.get(a.proof,"anchor.subject.pub"),g=_.get(a.proof,"anchor.subject.data");if(_.isEmpty(a.granted)||_.isEmpty(e)||_.isEmpty(f))return!1;var h=sha256(""+e+g+b+c),i=services.container.CryptoManager,j=d;if(_.isEmpty(j)){if(!_.isFunction(i.installKey))throw new Error("CryptoManager does not support installKey, please use a `keyName` instead.");j="TEMP_KEY_NAME_"+new Date().getTime(),i.installKey(j,f)}return i.verify(j,h,a.granted)}function transformDate(a){return new Date(a.year,a.month-1,a.day).getTime()/1e3}var VERIFY_LEVELS={INVALID:-1,PROOFS:0,ANCHOR:1,GRANTED:2,BLOCKCHAIN:3};function verifyRequiredClaims(a,b){if(!_.isEmpty(a.required)){var c=b.map(function(a){return a.identifier}),d=_.difference(a.required,c);if(!_.isEmpty(d))throw new Error("Missing required claim(s): "+_.join(d,", "))}}function verifyRequiredClaimsFromJSON(a,b){var c=_.get(b,"proof.leaves");if(!_.isEmpty(a.required)&&c){var d=c.map(function(a){return a.identifier}),e=_.difference(a.required,d);if(!_.isEmpty(e))throw new Error("Missing required claim(s): "+_.join(e,", "))}}function getCredentialDefinition(a,b){var c;if(c=b?_.find(definitions,{identifier:a,version:""+b}):_.find(definitions,{identifier:a}),!c)throw new Error("Credential definition for "+a+" v"+b+" not found");return c}function VerifiableCredentialBaseConstructor(a,b,c,d,e,f){var g=this;this.id=uuidv4(),this.issuer=b;var h=new Claim("cvc:Meta:issuer",this.issuer);this.issuanceDate=new Date().toISOString();var i=new Claim("cvc:Meta:issuanceDate",this.issuanceDate);this.identifier=a,this.expirationDate=c?timestamp.toDate(timestamp.now(c)).toISOString():null;var j=new Claim("cvc:Meta:expirationDate",this.expirationDate?this.expirationDate:"null"),k=j?_.concat(d,h,i,j):_.concat(d,h,i);if(!_.includes(validIdentifiers(),a))throw new Error(a+" is not defined");var l=getCredentialDefinition(a,e);if(this.version=""+e||l.version,this.type=["Credential",a],this.transient=l.transient||!1,f&&(this.evidence=serializeEvidence(f)),!_.isEmpty(d)){if(verifyRequiredClaims(l,d),this.claim=new ClaimModel(d),this.proof=new CvcMerkleProof(k),!_.isEmpty(l.excludes)){var m=_.remove(this.proof.leaves,function(a){return _.includes(l.excludes,a.identifier)});_.forEach(m,function(a){_.unset(g.claim,a.claimPath)})}this.granted=null}this.getGlobalIdentifier=function(){return"credential-"+g.identifier+"-"+g.version},this.filter=function(a){var b=_.cloneDeep(g);return _.remove(b.proof.leaves,function(b){return!_.includes(a,b.identifier)}),b.claim={},_.forEach(b.proof.leaves,function(a){_.set(b.claim,a.claimPath,_.get(g.claim,a.claimPath))}),b},this.requestAnchor=function(){var a=(0,_asyncToGenerator3.default)(_regenerator2.default.mark(function a(b){var c,d,e;return _regenerator2.default.wrap(function(a){for(;;)switch(a.prev=a.next){case 0:if(!g.transient){a.next=3;break}return g.proof.anchor={type:"transient",subject:{label:g.identifier,data:g.proof.merkleRoot}},a.abrupt("return",g);case 3:return c=services.container.AnchorService,d=_.merge({},b,{subject:{label:g.identifier,data:g.proof.merkleRoot}}),a.next=7,c.anchor(d);case 7:return e=a.sent,g.proof.anchor=e,a.abrupt("return",g);case 10:case"end":return a.stop();}},a,g)}));return function(){return a.apply(this,arguments)}}(),this.updateAnchor=(0,_asyncToGenerator3.default)(_regenerator2.default.mark(function a(){var b,c;return _regenerator2.default.wrap(function(a){for(;;)switch(a.prev=a.next){case 0:if(!g.transient){a.next=3;break}return g.proof.anchor={type:"transient",subject:{label:g.identifier,data:g.proof.merkleRoot}},a.abrupt("return",g);case 3:return b=services.container.AnchorService,a.next=6,b.update(g.proof.anchor);case 6:return c=a.sent,g.proof.anchor=c,a.abrupt("return",g);case 9:case"end":return a.stop();}},a,g)})),this.verifyProofs=function(){return nonCryptographicallySecureVerify(g)},this.verify=function(a,b){var c=b||{},d=c.requestorId,e=c.requestId,f=c.keyName,h=_.isNil(a)?VERIFY_LEVELS.GRANTED:a,i=VERIFY_LEVELS.INVALID;return i===VERIFY_LEVELS.INVALID&&h>=VERIFY_LEVELS.PROOFS&&g.verifyProofs()&&(i=VERIFY_LEVELS.PROOFS),i===VERIFY_LEVELS.PROOFS&&h>=VERIFY_LEVELS.ANCHOR&&g.verifyAttestation()&&(i=VERIFY_LEVELS.ANCHOR),i===VERIFY_LEVELS.ANCHOR&&h>=VERIFY_LEVELS.GRANTED&&g.verifyGrant(d,e,f)&&(i=VERIFY_LEVELS.GRANTED),i},this.verifySignature=function(a){return"transient"===g.proof.anchor.type||services.container.AnchorService.verifySignature(g.proof,a)},this.verifyAttestation=(0,_asyncToGenerator3.default)(_regenerator2.default.mark(function a(){return _regenerator2.default.wrap(function(a){for(;;)switch(a.prev=a.next){case 0:if("transient"!==g.proof.anchor.type&&"dummynet"!==g.proof.anchor.network){a.next=2;break}return a.abrupt("return",!0);case 2:return a.abrupt("return",services.container.AnchorService.verifyAttestation(g.proof));case 3:case"end":return a.stop();}},a,g)})),this.revokeAttestation=(0,_asyncToGenerator3.default)(_regenerator2.default.mark(function a(){return _regenerator2.default.wrap(function(a){for(;;)switch(a.prev=a.next){case 0:if("transient"!==g.proof.type){a.next=2;break}return a.abrupt("return");case 2:return a.abrupt("return",services.container.AnchorService.revokeAttestation(g.proof));case 3:case"end":return a.stop();}},a,g)})),this.isRevoked=(0,_asyncToGenerator3.default)(_regenerator2.default.mark(function a(){return _regenerator2.default.wrap(function(a){for(;;)switch(a.prev=a.next){case 0:if("transient"!==g.proof.type){a.next=2;break}return a.abrupt("return",!1);case 2:return a.abrupt("return",services.container.AnchorService.isRevoked(g.proof));case 3:case"end":return a.stop();}},a,g)}));var n=function(a){return _.isString(a)?convertDeltaToTimestamp(a):a};return this.isMatch=function(a){var b=_.cloneDeep(g.claim),c=transformConstraint(a),d=function(a){var c=_.keys(a)[0],d=_.get(b,c);return isDateStructure(d)&&(_.set(b,c,transformDate(d)),_.set(a,c,_.mapValues(a[c],n))),sift(a)([b])};return c.reduce(function(a,b){return a&&d(b)},!0)},this.grantUsageFor=function(a,b,c){var d=c.keyName,e=c.pvtKey;if(_.isEmpty(_.get(g.proof,"anchor.subject.label"))||_.isEmpty(_.get(g.proof,"anchor.subject.data")))throw new Error("Invalid credential attestation/anchor");if(!g.verifySignature())throw new Error("Invalid credential attestation/anchor signature");if(!a||!b||!(d||e))throw new Error("Missing required parameter: requestorId, requestId or key");var f=""+g.proof.anchor.subject.label+g.proof.anchor.subject.data+a+b,h=sha256(f),i=services.container.CryptoManager,j=d;if(e){if(!_.isFunction(i.installKey))throw new Error("You provide a `pvtKey` but the CryptoManager does not support it, use a `keyName` instead.");j="TEMP_KEY_NAME_"+new Date().getTime(),i.installKey(j,e)}var k=i.sign(j,h);g.granted=k},this.verifyGrant=function(a,b,c){return requesterGrantVerify(g,a,b,c)},this}var CREDENTIAL_META_FIELDS=["id","identifier","issuer","issuanceDate","expirationDate","version","type"],getCredentialMeta=function(a){return _.pick(a,CREDENTIAL_META_FIELDS)};function transformMetaConstraint(a){var b=[],c=_.keys(a.meta);return _.forEach(c,function(c){var d=a.meta[c],e={};if("credential"===c)e.identifier=d;else if(d.is)e[c]=d.is;else throw new Error("Malformed meta constraint \""+c+"\": missing the IS");b.push(e)}),b}var isMatchCredentialMeta=function(a,b){var c=transformMetaConstraint(b);if(_.isEmpty(c))return!1;var d=function(b){return sift(b)([a])};return c.reduce(function(a,b){return a&&d(b)},!0)};VerifiableCredentialBaseConstructor.CREDENTIAL_META_FIELDS=CREDENTIAL_META_FIELDS,VerifiableCredentialBaseConstructor.getCredentialMeta=getCredentialMeta,VerifiableCredentialBaseConstructor.isMatchCredentialMeta=isMatchCredentialMeta,VerifiableCredentialBaseConstructor.fromJSON=function(a){var b=getCredentialDefinition(a.identifier,a.version);verifyRequiredClaimsFromJSON(b,a);var c=new VerifiableCredentialBaseConstructor(a.identifier,a.issuer);return c.id=_.clone(a.id),c.issuanceDate=_.clone(a.issuanceDate),c.expirationDate=_.clone(a.expirationDate),c.identifier=_.clone(a.identifier),c.version=_.clone(a.version),c.type=_.cloneDeep(a.type),c.claim=_.cloneDeep(a.claim),c.proof=_.cloneDeep(a.proof),c.granted=_.clone(a.granted)||null,c},VerifiableCredentialBaseConstructor.getAllProperties=function(a){var b=_.find(definitions,{identifier:a});if(b){var c=[];_.forEach(b.depends,function(a){c.push.apply(c,(0,_toConsumableArray3.default)(Claim.getAllProperties(a)))});var d=[];return _.forEach(b.excludes,function(a){d.push.apply(d,(0,_toConsumableArray3.default)(Claim.getAllProperties(a)))}),_.difference(c,d)}return null},VerifiableCredentialBaseConstructor.VERIFY_LEVELS=VERIFY_LEVELS,VerifiableCredentialBaseConstructor.nonCryptographicallySecureVerify=nonCryptographicallySecureVerify,VerifiableCredentialBaseConstructor.cryptographicallySecureVerify=cryptographicallySecureVerify,VerifiableCredentialBaseConstructor.requesterGrantVerify=requesterGrantVerify,module.exports=VerifiableCredentialBaseConstructor; \ No newline at end of file diff --git a/dist/browser/creds/__mocks__/definitions.js b/dist/browser/creds/__mocks__/definitions.js new file mode 100644 index 00000000..29ec111b --- /dev/null +++ b/dist/browser/creds/__mocks__/definitions.js @@ -0,0 +1 @@ +'use strict';var definitions=[{identifier:"civ:Credential:SimpleIdentity",version:"1",depends:["civ:Identity:name","civ:Identity:DateOfBirth"]},{identifier:"civ:Credential:SimpleTest",version:"1",depends:["civ:Identity:name","civ:Identity:DateOfBirth"]},{identifier:"civ:Credential:TestWithExcludes",version:"1",depends:["civ:Identity:name","civ:Identity:DateOfBirth"],excludes:["civ:Identity:name.middle"]}];module.exports=definitions; \ No newline at end of file diff --git a/dist/browser/creds/definitions.js b/dist/browser/creds/definitions.js new file mode 100644 index 00000000..1754ed86 --- /dev/null +++ b/dist/browser/creds/definitions.js @@ -0,0 +1 @@ +'use strict';var definitions=[{identifier:"credential-cvc:Email-v1",version:"1",depends:["claim-cvc:Contact.email-v1"]},{identifier:"credential-cvc:PhoneNumber-v1",version:"1",depends:["claim-cvc:Contact.phoneNumber-v1"]},{identifier:"credential-cvc:GenericDocumentId-v1",version:"1",depends:["claim-cvc:Document.type-v1","claim-cvc:Document.number-v1","claim-cvc:Document.name-v1","claim-cvc:Document.gender-v1","claim-cvc:Document.issueLocation-v1","claim-cvc:Document.issueAuthority-v1","claim-cvc:Document.issueCountry-v1","claim-cvc:Document.placeOfBirth-v1","claim-cvc:Document.dateOfBirth-v1","claim-cvc:Document.address-v1","claim-cvc:Document.properties-v1","cvc:Document:image"]},{identifier:"credential-cvc:IdDocument-v1",version:"1",depends:["claim-cvc:Document.type-v1","claim-cvc:Document.number-v1","claim-cvc:Document.name-v1","claim-cvc:Document.gender-v1","claim-cvc:Document.issueCountry-v1","claim-cvc:Document.placeOfBirth-v1","claim-cvc:Document.dateOfBirth-v1","claim-cvc:Document.dateOfExpiry-v1","claim-cvc:Document.nationality-v1","claim-cvc:Document.evidences-v1"],required:["claim-cvc:Document.type-v1","claim-cvc:Document.name-v1","claim-cvc:Document.dateOfBirth-v1","claim-cvc:Document.issueCountry-v1"]},{identifier:"credential-cvc:IdDocument-v2",version:"1",depends:["claim-cvc:Document.type-v1","claim-cvc:Document.number-v1","claim-cvc:Document.name-v1","claim-cvc:Document.gender-v1","claim-cvc:Document.issueCountry-v1","claim-cvc:Document.placeOfBirth-v1","claim-cvc:Document.dateOfBirth-v1","claim-cvc:Document.dateOfExpiry-v1","claim-cvc:Document.nationality-v1","claim-cvc:Document.evidences-v1"],required:["claim-cvc:Document.type-v1","claim-cvc:Document.name-v1","claim-cvc:Document.dateOfBirth-v1","claim-cvc:Document.issueCountry-v1","claim-cvc:Document.evidences-v1"]},{identifier:"credential-cvc:LiveIdDocument-v1",version:"1",depends:["claim-cvc:Document.type-v1","claim-cvc:Document.number-v1","claim-cvc:Document.name-v1","claim-cvc:Document.gender-v1","claim-cvc:Document.issueCountry-v1","claim-cvc:Document.placeOfBirth-v1","claim-cvc:Document.dateOfBirth-v1","claim-cvc:Document.dateOfExpiry-v1","claim-cvc:Document.nationality-v1","claim-cvc:Document.evidences-v1"],required:["claim-cvc:Document.type-v1","claim-cvc:Document.name-v1","claim-cvc:Document.dateOfBirth-v1","claim-cvc:Document.issueCountry-v1","claim-cvc:Document.evidences-v1"]},{identifier:"credential-cvc:Address-v1",version:"1",depends:["claim-cvc:Identity.address-v1"]},{identifier:"credential-cvc:Identity-v1",version:"1",depends:["claim-cvc:Identity.name-v1","claim-cvc:Identity.dateOfBirth-v1"]},{identifier:"credential-cvc:IDVaaS-v1",version:"1",depends:["claim-cvc:Identity.name-v1","claim-cvc:Identity.dateOfBirth-v1","claim-cvc:Identity.address-v1","claim-cvc:Contact.email-v1","claim-cvc:SocialSecurity.number-v1","claim-cvc:Contact.phoneNumber-v1"]},{identifier:"credential-cvc:UnverifiedSsn-v1",version:"1",transient:!0,depends:["claim-cvc:SocialSecurity.number-v1"]},{identifier:"credential-cvc:UnverifiedAddress-v1",version:"1",transient:!0,depends:["claim-cvc:Identity.address-v1"]},{identifier:"credential-cvc:Covid19-v1",version:"1",depends:["claim-cvc:Medical.covid19-v1"]},{identifier:"credential-alt:Identity-v1",version:"1",depends:["claim-cvc:Identity.name-v1","claim-cvc:Identity.dateOfBirth-v1","claim-cvc:Identity.address-v1"]}];module.exports=definitions; \ No newline at end of file diff --git a/dist/browser/errors/definitions.js b/dist/browser/errors/definitions.js new file mode 100644 index 00000000..cc744ce0 --- /dev/null +++ b/dist/browser/errors/definitions.js @@ -0,0 +1 @@ +'use strict';var ErrorCodes={ERROR_IDV_MRT_INVALID_DOC:"error.idv.mrt.invalid.doc",ERROR_IDV_MRT_UNSUPPORTED_DOC:"error.idv.mrt.unsupported.doc",ERROR_IDV_MRT_INVALID_UTILITY:"error.idv.mrt.invalid.utility",ERROR_IDV_MRT_QUALITY:"error.idv.mrt.quality",ERROR_IDV_MRT_EXPIRED:"error.idv.mrt.expired",ERROR_IDV_MRT_MISMATCH:"error.idv.mrt.mismatch",ERROR_IDV_MRT_REQUIREMENTS_FAIL:"error.idv.mrt.requirements.fail",ERROR_IDV_VALIDATION_INVALID_DOC:"error.idv.validation.invalid.doc",ERROR_IDV_VALIDATION_INVALID_PHONE:"error.idv.validation.invalid.phone",ERROR_IDV_VALIDATION_INVALID_EMAIL:"error.idv.validation.invalid.email",ERROR_IDV_VALIDATION_UNSUPPORTED_DOC:"error.idv.validation.unsupported.doc",ERROR_IDV_VALIDATION_INVALID_UTILITY:"error.idv.validation.invalid.utility",ERROR_IDV_VALIDATION_QUALITY:"error.idv.validation.quality",ERROR_IDV_VALIDATION_EXPIRED:"error.idv.validation.expired",ERROR_IDV_VALIDATION_MISMATCH:"error.idv.validation.mismatch",ERROR_IDV_VALIDATION_MISSING_NAME:"error.idv.validation.missing.name",ERROR_IDV_VALIDATION_MISSING_DOB:"error.idv.validation.missing.dob",ERROR_IDV_VALIDATION_MISSING_COUNTRY:"error.idv.validation.missing.country",ERROR_IDV_VALIDATION_MISSING_DOC_TYPE:"error.idv.validation.missing.doc.type",ERROR_IDV_VALIDATION_REQUIREMENTS_FAIL:"error.idv.validation.requirements.fail",ERROR_IDV_VALIDATION_UCA_VALUE_MISMATCH:"error.idv.validation.uca.value.mismatch",ERROR_IDV_UCA_MISSING_PROPERTY:"error.idv.uca.missing.property",ERROR_IDV_UCA_NO_RETRIES:"error.idv.uca.no.retries",ERROR_IDV_PROCESS_HAS_FINAL_STATUS:"error.idv.process.has.final.status",ERROR_IDV_UCA_HAS_FINAL_STATUS:"error.idv.uca.has.final.status",ERROR_IDV_UCA_BATCH_HAS_FINAL_STATUS:"error.idv.uca.batch.has.final.status",ERROR_IDV_CR_INVALID_CREDENTIAL_ITEM:"error.idv.cr.invalid.credentialItem",ERROR_IDV_CREDENTIAL_INVALID_SIGNATURE:"error.idv.credential.invalid.signature",ERROR_IDV_CR_ALREADY_SIGNED:"error.idv.cr.already.signed",ERROR_IDV_CR_MISSING_PROPERTY:"error.idv.cr.missing.property",ERROR_IDV_UCA_SERVER:"error.idv.uca.server",ERROR_IDV_MISSING_UCA:"error.idv.missing.uca",ERROR_IDV_UCA_WRONG_VERSION:"error.idv.uca.wrong.version",ERROR_IDV_MISSING_PLAN:"error.idv.missing.plan",ERROR_IDV_MISSING_PROCESS:"error.idv.missing.process",ERROR_IDV_UCA_BAD_VALUE:"error.idv.uca.bad.value",ERROR_IDV_UCA_UPDATE_NO_STATUS:"error.idv.uca.update.no.status",ERROR_IDV_UCA_UPDATE_NO_PROCESS_STATUS:"error.idv.uca.update.no.process.status",ERROR_IDV_TOKEN_RECEIVED_BEFORE_ISSUE:"error.idv.token.received.before.issue",ERROR_IDV_TOKEN_SENDING_FAILED:"error.idv.token.sending.failed",ERROR_IDV_TOKEN_EXPIRED:"error.idv.token.expired",ERROR_IDV_TOKEN_MISMATCH:"error.idv.token.mismatch",ERROR_CW_DSR_INVALID_SCOPE_REQUEST:"error.dsr.invalid.scope.request",ERROR_CW_IDV_INVALID_REQUEST:"error.cw.idv.request.failed.generic.4XX",ERROR_CW_IDV_ERROR:"error.cw.idv.server.failed.generic.5XX",ERROR_CW_GENERIC:"error.generic",ERROR_CW_DSR_RESPONSE_MISSING_EVENT_URL:"error.dsr.missing.event.url",ERROR_CW_DSR_RESPONSE_INVALID_EVENT_TYPE:"error.dsr.invalid.event.type",ERROR_CW_CLIENT_ID_NOT_FOUND:"client.id.not.found",ERROR_CW_CERTIFICATE_NOT_FOUND:"error.certificate.not.found",ERROR_CW_CERTIFICATE_UNPARSABLE:"error.certificate.unparsable",ERROR_CW_WRONG_QUERY_OPERATOR_SCOPE_REQUEST:"error.dsr.wrong.sift.operator",ERROR_CW_VERIFY_CREDENTIAL:"error.verify.credential",ERROR_CW_WRONG_UCA_IDENTIFIER:"error.wrong.uca.identifier",ERROR_CW_WRONG_VC_IDENTIFIER:"error.wrong.credential.identifier",ERROR_CW_VCR_NOT_FOUND:"vcr.not.found",ERROR_CW_VCR_INVALID_STATE:"vcr.invalid.state",ERROR_CW_VCR_INVALID_CREDENTIAL:"vcr.invalid.credential",ERROR_CW_VCR_INVALID_REQUEST:"vcr.invalid.request",ERROR_CW_VCR_ERROR_PATCH_SIGNED_SUBJECT:"vcr.error.patch.signed.subject",ERROR_CW_KEY_MANAGER_CANT_ENSURE_KEY:"key.manager.cant.ensure.key",ERROR_CW_NETWORK_GENERIC:"error.network.generic",ERROR_RETRYABLE_NETWORK_ERROR:"error.retryable.network"},ErrorContextTypes={MISSING_PROPERTY:"missing_property",UCA_STATE:"uca_state",UCA_VALUE:"uca_value",UCA_VERSION:"uca_version",PLAN_UCA_VERSION:"plan_uca_version",PROCESS_ID:"process_id",UCA_NAME:"uca_name",UCA_ID:"uca_id",CREDENTIAL_ITEM:"credential_item",UCA_ERROR:"uca_error"};module.exports={ErrorCodes:ErrorCodes,ErrorContextTypes:ErrorContextTypes}; \ No newline at end of file diff --git a/dist/browser/errors/idvErrors.js b/dist/browser/errors/idvErrors.js new file mode 100644 index 00000000..cdc2cde2 --- /dev/null +++ b/dist/browser/errors/idvErrors.js @@ -0,0 +1 @@ +'use strict';var _classCallCheck2=require("babel-runtime/helpers/classCallCheck"),_classCallCheck3=_interopRequireDefault(_classCallCheck2);function _interopRequireDefault(a){return a&&a.__esModule?a:{default:a}}var _=require("lodash"),_require=require("./definitions"),ErrorCodes=_require.ErrorCodes,ErrorContextTypes=_require.ErrorContextTypes,IDVErrorCodes=_.pickBy(ErrorCodes,function(a,b){return b.startsWith("ERROR_IDV")}),IDVError=function a(b){(0,_classCallCheck3.default)(this,a),this.message=b.message,this.errorCode=b.name,this.errorContext=b.data};module.exports={IDVErrorCodes:IDVErrorCodes,ErrorContextTypes:ErrorContextTypes,IDVError:IDVError}; \ No newline at end of file diff --git a/dist/browser/errors/index.js b/dist/browser/errors/index.js new file mode 100644 index 00000000..6d29b531 --- /dev/null +++ b/dist/browser/errors/index.js @@ -0,0 +1 @@ +'use strict';var idvErrors=require("./idvErrors"),_require=require("./definitions"),ErrorCodes=_require.ErrorCodes,ErrorContextTypes=_require.ErrorContextTypes;module.exports={ErrorCodes:ErrorCodes,ErrorContextTypes:ErrorContextTypes,idvErrors:idvErrors}; \ No newline at end of file diff --git a/dist/browser/index.js b/dist/browser/index.js new file mode 100644 index 00000000..124de65b --- /dev/null +++ b/dist/browser/index.js @@ -0,0 +1 @@ +'use strict';var _require=require("./claim/Claim"),Claim=_require.Claim,VC=require("./creds/VerifiableCredential"),_require2=require("./services/index"),initServices=_require2.initServices,services=_require2.services,isValidGlobalIdentifier=require("./isValidGlobalIdentifier"),isClaimRelated=require("./isClaimRelated"),errors=require("./errors"),constants=require("./constants"),claimDefinitions=require("./claim/definitions"),credentialDefinitions=require("./creds/definitions"),aggregate=require("./AggregationHandler");function CredentialCommons(){return this.Claim=Claim,this.VC=VC,this.init=initServices,this.isValidGlobalIdentifier=isValidGlobalIdentifier,this.isClaimRelated=isClaimRelated,this.services=services,this.aggregate=aggregate,this.errors=errors,this.constants=constants,this.claimDefinitions=claimDefinitions,this.credentialDefinitions=credentialDefinitions,this}module.exports=new CredentialCommons; \ No newline at end of file diff --git a/dist/browser/isClaimRelated.js b/dist/browser/isClaimRelated.js new file mode 100644 index 00000000..1ecfa483 --- /dev/null +++ b/dist/browser/isClaimRelated.js @@ -0,0 +1 @@ +'use strict';var _=require("lodash"),_require=require("./claim/Claim"),definitions=_require.definitions,Claim=_require.Claim,vcDefinitions=require("./creds/definitions");function isClaimRelated(a,b,c){var d=b.substring(b.indexOf("-")+1,b.lastIndexOf("-")),e=definitions.find(function(a){return a.identifier===d});if(e){var f=Claim.getAllProperties(d);if(_.includes(f,a)){var g=vcDefinitions.find(function(a){return a.identifier===c});if(g)return _.includes(g.depends,d);throw new Error("Credential identifier does not exist")}else throw new Error("Claim property path does not exist on UCA definitions")}else throw new Error("UCA identifier does not exist")}module.exports=isClaimRelated; \ No newline at end of file diff --git a/dist/browser/isValidGlobalIdentifier.js b/dist/browser/isValidGlobalIdentifier.js new file mode 100644 index 00000000..e067a0f3 --- /dev/null +++ b/dist/browser/isValidGlobalIdentifier.js @@ -0,0 +1 @@ +'use strict';var _=require("lodash"),_require=require("@identity.com/uca"),definitions=_require.definitions,vcDefinitions=require("./creds/definitions"),claimDefinitions=require("./claim/definitions"),validUCAIdentifiers=_.map(definitions,function(a){return a.identifier}),validClaimIdentifiers=_.map(claimDefinitions,function(a){return a.identifier}),validVCIdentifiers=_.map(vcDefinitions,function(a){return a.identifier}),validPrefixes=["claim","credential"];function isValidGlobalIdentifier(a){var b=_.split(a,"-");if(3!==b.length)throw new Error("Malformed Global Identifier");if(!_.includes(validPrefixes,b[0]))throw new Error("Invalid Global Identifier Prefix");switch(b[0]){case"claim":if(!_.includes(validUCAIdentifiers,b[1])&&!_.includes(validClaimIdentifiers,a))throw new Error(a+" is not valid");return!0;case"credential":if(!_.includes(validVCIdentifiers,b[1])&&!_.includes(validVCIdentifiers,a))throw new Error(a+" is not valid");return!0;default:return!1;}}module.exports=isValidGlobalIdentifier; \ No newline at end of file diff --git a/dist/browser/lib/crypto.js b/dist/browser/lib/crypto.js new file mode 100644 index 00000000..1e6f2cb5 --- /dev/null +++ b/dist/browser/lib/crypto.js @@ -0,0 +1 @@ +'use strict';var sjcl=require("sjcl"),sha256=function(a){return sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(a))};module.exports={sha256:sha256}; \ No newline at end of file diff --git a/dist/browser/logger.js b/dist/browser/logger.js new file mode 100644 index 00000000..76ad7b9d --- /dev/null +++ b/dist/browser/logger.js @@ -0,0 +1 @@ +'use strict';var _require=require("winston"),createLogger=_require.createLogger,format=_require.format,transports=_require.transports,logger=createLogger({level:"info",format:format.combine(format.splat(),format.simple()),transports:[new transports.Console]});module.exports=logger; \ No newline at end of file diff --git a/dist/browser/schemas/generator/SchemaGenerator.js b/dist/browser/schemas/generator/SchemaGenerator.js new file mode 100644 index 00000000..1760d0ae --- /dev/null +++ b/dist/browser/schemas/generator/SchemaGenerator.js @@ -0,0 +1 @@ +'use strict';var _typeof2=require("babel-runtime/helpers/typeof"),_typeof3=_interopRequireDefault(_typeof2),_getIterator2=require("babel-runtime/core-js/get-iterator"),_getIterator3=_interopRequireDefault(_getIterator2),_slicedToArray2=require("babel-runtime/helpers/slicedToArray"),_slicedToArray3=_interopRequireDefault(_slicedToArray2),_entries=require("babel-runtime/core-js/object/entries"),_entries2=_interopRequireDefault(_entries);function _interopRequireDefault(a){return a&&a.__esModule?a:{default:a}}var _=require("lodash"),randomString=require("randomstring"),Type=require("type-of-is"),RandExp=require("randexp"),_require=require("@identity.com/uca"),UCA=_require.UserCollectableAttribute,ucaDefinitions=_require.definitions,_require2=require("../../claim/Claim"),Claim=_require2.Claim,definitions=_require2.definitions,getBaseIdentifiers=_require2.getBaseIdentifiers,DRAFT="http://json-schema.org/draft-07/schema#",getPropertyNameFromDefinition=function(a){return getBaseIdentifiers(a.identifier).identifierComponents[2]},getPropertyType=function(a){return Type.string(a).toLowerCase()},processObject=function a(b,c,d){var e=c||{},f=b,g=f.definition;delete f.definition,e.type=getPropertyType(f),e.properties=e.properties||{};var h=(0,_entries2.default)(f),i=function(b,c){var f=getPropertyType(c);if("object"===f)e.properties[b]=a(c,e.properties[b],d+"."+b);else if("array"===f)e.properties[b]=processArray(c,e.properties[b],b);else if(e.properties[b]={},e.properties[b].type="null"===f?["null","string"]:f,g&&g.type.properties){var h=g.type.properties.find(function(a){return a.name===b});h&&h.type.includes(":")&&(h=definitions.find(function(a){return a.identifier===h.type})),e.properties[b]=addMinimumMaximum(h,e.properties[b])}else e.properties[b]=addMinimumMaximum(g,e.properties[b])},j=!0,k=!1,l=void 0;try{for(var m,n=(0,_getIterator3.default)(h);!(j=(m=n.next()).done);j=!0){var o=m.value,p=(0,_slicedToArray3.default)(o,2),q=p[0],r=p[1];i(q,r)}}catch(a){k=!0,l=a}finally{try{!j&&n.return&&n.return()}finally{if(k)throw l}}if(d.includes("claim")&&4===d.split(".").length){var s=d.substring(11),t=(s.substring(0,1).toUpperCase()+s.substring(1)).replace(".",":"),u=definitions.find(function(a){return a.identifier.includes(t)});if(null==u){var v=s.substring(0,1).toUpperCase()+s.substring(1);t="claim-cvc:"+v+"-v1",u=definitions.find(function(a){return a.identifier.includes(t)})}null==u&&(t="claim-cvc:"+s+"-v1",u=definitions.find(function(a){return a.identifier.includes(t)})),e.required=u.type.required}return e.additionalProperties=!1,e},processArray=function(a,b){var c=b||{};c.type=getPropertyType(a),c.items=c.items||{};var d=getPropertyType(a[0]);return c.items.type=d,c.additionalProperties=!1,c},process=function(a,b){var c=b,d=a.identifier,e=void 0,f={$schema:DRAFT};return f.title=d,f.type=Type.string(c).toLowerCase(),"object"===f.type&&(e=processObject(c,{},"root"),f.type=e.type,f.properties=e.properties),f.additionalProperties=!1,f},buildSampleJson=function(a){var b=!!(1a.maximum&&(b=a.maximum),"undefined"!==a.exclusiveMaximum&&null!==a.exclusiveMaximum&&b>=a.exclusiveMaximum&&(b=a.exclusiveMaximum-.1)),b},generateRandomValueForType=function(a){var b=!!(1 { + if (!_.isEmpty(parameters)) { + throw new Error('parameters should be empty'); + } + return true; +}; +const validateNotEmptyParametersOperators = parameters => { + if (!parameters && _.isEmpty(parameters)) { + throw new Error('parameters should not be empty'); + } + return true; +}; +const validatePathParametersOperators = parameters => { + if (!_.isString(parameters)) { + throw new Error('parameters should be string'); + } + return true; +}; +const validateNumberParametersOperators = parameters => { + if (!_.isNumber(parameters)) { + throw new Error('parameters should be number'); + } + return true; +}; +const validateObjectParametersOperators = parameters => { + if (!_.isObject(parameters)) { + throw new Error('parameters should be object'); + } + return true; +}; + +const sort = (colllection, params) => { + const path = _.keys(params)[0]; + const order = params[path]; + const ordered = _.sortBy(colllection, path); + return order === 'ASC' ? ordered : _.reverse(ordered); +}; + +const AGGREGATION_OPERATORS_MAP = { + none: (collection, params) => validateEmptyParametersOperators(params) ? [...collection] : null, + $limit: (collection, params) => validateNumberParametersOperators(params) ? [..._.slice(collection, 0, params)] : null, + $min: (collection, params) => validatePathParametersOperators(params) ? [_.minBy(collection, params)] : null, + $max: (collection, params) => validatePathParametersOperators(params) ? [_.maxBy(collection, params)] : null, + $first: (collection, params) => validateNotEmptyParametersOperators(params) ? [_.first(collection)] : null, + $last: (collection, params) => validateNotEmptyParametersOperators(params) ? [_.last(collection)] : null, + $sort: (collection, params) => validateObjectParametersOperators(params) ? [...sort(collection, params)] : null +}; + +function aggregate(credentials, stages) { + let filtered = [...credentials]; + _.forEach(stages, stage => { + const operator = _.keys(stage)[0]; + + if (!_.includes(_.keys(AGGREGATION_OPERATORS_MAP), operator)) { + throw new Error(`Invalid operator: ${operator}`); + } + const params = stage[operator]; + const operatorImplementation = AGGREGATION_OPERATORS_MAP[operator]; + filtered = operatorImplementation(filtered, params); + }); + return filtered; +} + +module.exports = aggregate; \ No newline at end of file diff --git a/dist/cjs/SecureRandom.js b/dist/cjs/SecureRandom.js new file mode 100644 index 00000000..19756750 --- /dev/null +++ b/dist/cjs/SecureRandom.js @@ -0,0 +1,42 @@ +'use strict'; + +const sjcl = require('sjcl'); +const logger = require('./logger'); + +class SecureRandom { + constructor(seedHexString) { + logger.debug('Init Secure Random'); + // eslint-disable-next-line new-cap + this.sjclRandom = new sjcl.prng(10); + + if (seedHexString) { + const seed = sjcl.codec.hex.toBits(seedHexString); + this.sjclRandom.addEntropy(seed, undefined, 'csprng'); + this.isSeeded = true; + } else { + try { + logger.debug('Trying crypto'); + /* eslint-disable global-require */ + const hexString = require('crypto').randomBytes(1024).toString('hex'); + /* eslint-enable global-require */ + const seed = sjcl.codec.hex.toBits(hexString); + this.sjclRandom.addEntropy(seed, undefined, 'csprng'); + this.isSeeded = true; + } catch (error) { + logger.warn(`Crypto: ${error}`); + this.isSeeded = false; + } + } + } + + wordWith(size) { + if (!this.isSeeded) { + throw new Error("Can't user SecureRandom before seeding"); + } + + const randomBytes = this.sjclRandom.randomWords(size / 8, 10); + return sjcl.codec.hex.fromBits(randomBytes); + } +} + +module.exports = SecureRandom; \ No newline at end of file diff --git a/dist/cjs/claim/Claim.js b/dist/cjs/claim/Claim.js new file mode 100644 index 00000000..f6957969 --- /dev/null +++ b/dist/cjs/claim/Claim.js @@ -0,0 +1,365 @@ +'use strict'; + +const _ = require('lodash'); +const sjcl = require('sjcl'); +const { UserCollectableAttribute } = require('@identity.com/uca'); +const definitions = require('./definitions'); +const { services } = require('../services'); + +const validIdentifiers = _.map(definitions, d => d.identifier); + +const getDefinition = (identifier, version) => version ? _.find(definitions, { identifier, version }) : _.find(definitions, { identifier }); + +const isArrayAttestableValue = aValue => aValue.indexOf('[') > -1 && aValue.indexOf(']') > -1; + +function getBaseIdentifiers(identifier) { + const claimRegex = /claim-cvc:(.*)\.(.*)-v\d*/; + let isNewIdentifier = true; + + let identifierComponents = claimRegex.exec(identifier); + if (identifierComponents === null) { + identifierComponents = _.split(identifier, ':'); + isNewIdentifier = false; + } + return { identifierComponents, isNewIdentifier }; +} + +function adaptIdentifierIfNeeded(identifier, version) { + const definition = getDefinition(identifier, version); + const resolvedIdentifier = definition && definition.alias ? definition.type : identifier; + + const { isNewIdentifier, identifierComponents } = getBaseIdentifiers(resolvedIdentifier); + + if (!isNewIdentifier && !getDefinition(resolvedIdentifier, version)) { + const newIdentifier = `claim-cvc:${identifierComponents[1]}.${identifierComponents[2]}-v1`; + const foundNewIdentifier = _.find(definitions, { identifier: newIdentifier }); + if (foundNewIdentifier) { + return newIdentifier; + } + throw new Error(`${resolvedIdentifier} is not defined`); + } + return identifier; +} + +class Claim extends UserCollectableAttribute { + constructor(identifier, value, version) { + const currentIdentifier = adaptIdentifierIfNeeded(identifier, version); + super(currentIdentifier, value, version, definitions); + this.initialize(currentIdentifier, value, version); + } + + initialize(identifier, value, version) { + super.initialize(identifier, value, version); + if (!this.salt) { + const secureRandom = services.container.SecureRandom; + this.salt = sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(secureRandom.wordWith(64))); + } + } + + initializeValuesWithArrayItems(identifier, values, version) { + const definition = getDefinition(this.identifier, this.version); + const ucaArray = []; + + if (!_.isArray(values)) throw new Error(`Value for ${identifier}-${version} should be an array`); + + _.forEach(values, value => { + const claim = new Claim(_.get(definition, 'items.type'), value); + ucaArray.push(claim); + }); + + this.value = ucaArray; + } + + initializeAttestableValue() { + const { value } = this; + const definition = getDefinition(this.identifier, this.version); + const parsedAttestableValue = Claim.parseAttestableValue(value); + + // Trying to construct UCA with a existing attestableValue + if (parsedAttestableValue.length === 1) { + // This is a simple attestableValue + this.timestamp = null; + this.salt = parsedAttestableValue[0].salt; + const ucaValue = parsedAttestableValue[0].value; + this.value = definition.type === 'Array' ? _.map(ucaValue, item => new Claim(definition.items.type, { attestableValue: item })) : this.value = _.includes(['null', 'undefined'], ucaValue) ? null : ucaValue; + } else { + const ucaValue = {}; + for (let i = 0; i < parsedAttestableValue.length; i += 1) { + const { propertyName } = parsedAttestableValue[i]; + // we have stored only the property name on the urn, so we have to find the UCA definition + + let filteredIdentifier; + let ucaPropertyName; + const ucaType = UserCollectableAttribute.resolveType(definition, definitions); + const ucaDef = ucaType.properties.find(prop => prop.name === propertyName); + if (ucaDef) { + filteredIdentifier = ucaDef.type; + ucaPropertyName = propertyName; + } else { + const splitPropertyName = propertyName.split('.'); + // this property is used to check if the recursion tree has more than an depth + const ucaNamespace = splitPropertyName[splitPropertyName.length - 2]; + const ucaNamespacePascal = ucaNamespace.substring(0, 1).toUpperCase() + ucaNamespace.substring(1); + ucaPropertyName = splitPropertyName[splitPropertyName.length - 1]; + filteredIdentifier = `cvc:${ucaNamespacePascal}:${ucaPropertyName}`; + } + + // test if definition exists + const filteredDefinition = definitions.find(def => def.identifier === filteredIdentifier); + if (!filteredDefinition) { + // this must have an claim path with no recursive definition + filteredIdentifier = this.findDefinitionByAttestableValue(ucaPropertyName, definition); + } + ucaValue[propertyName] = new Claim(filteredIdentifier, { attestableValue: parsedAttestableValue[i].stringValue }); + } + this.value = ucaValue; + } + } + + /* eslint-disable class-methods-use-this */ + getValidIdentifiers() { + return validIdentifiers; + } + + static resolveType(definition) { + return UserCollectableAttribute.resolveType(definition, definitions); + } + + static parseAttestableArrayValue(value) { + const splitDots = value.attestableValue.split(':'); + + const propertyName = splitDots[1]; + const salt = splitDots[2]; + const attestableValueItems = value.attestableValue.substring(value.attestableValue.indexOf('[') + 1, value.attestableValue.indexOf(']') - 1).split(','); + const parsedArrayItems = _.map(attestableValueItems, item => Claim.parseAttestableValue({ attestableValue: item })); + return { + propertyName, salt, value: parsedArrayItems + }; + } + + static parseAttestableValue(value) { + const values = []; + + if (_.isArray(value.attestableValue)) { + // Already parsed in a previous recursion + return value.attestableValue; + } + + if (isArrayAttestableValue(value.attestableValue)) { + const arrayValues = Claim.parseAttestableArrayValue(value); + return [arrayValues]; + } + + // If is not an ArrayValue we parse it now + const splitPipes = _.split(value.attestableValue, '|'); + const attestableValueRegex = /^urn:(\w+(?:\.\w+)*):(\w+):(.+)/; + _.each(splitPipes, stringValue => { + const match = attestableValueRegex.exec(stringValue); + if (match && match.length === 4) { + const v = { + propertyName: match[1], + salt: match[2], + value: match[3], + stringValue + }; + values.push(v); + } + }); + if (splitPipes.length !== values.length && splitPipes.length !== values.length + 1) { + throw new Error('Invalid attestableValue'); + } + return values; + } + + findDefinitionByAttestableValue(attestableValuePropertyName, rootDefinition) { + const ucaType = UserCollectableAttribute.resolveType(rootDefinition, definitions); + for (const property of ucaType.properties) { + // eslint-disable-line no-restricted-syntax + const resolvedDefinition = _.find(definitions, { identifier: property.type }); + resolvedDefinition.type = UserCollectableAttribute.resolveType(resolvedDefinition, definitions); + if (!resolvedDefinition.type.properties && property.name === attestableValuePropertyName) { + return property.type; + } + if (resolvedDefinition.type.properties) { + return this.findDefinitionByAttestableValue(attestableValuePropertyName, resolvedDefinition); + } + } + return null; + } + + getAttestableValue(path, isArrayItem = false) { + // all UCA properties they have the form of :propertyName or :something.propertyName + const { identifierComponents } = getBaseIdentifiers(this.identifier); + let propertyName = identifierComponents[2]; + + if (isArrayItem) { + // we need to supress the root path + propertyName = null; + } + + if (path) { + propertyName = `${path}.${propertyName}`; + } + + // it was defined that the attestable value would be on the URN type https://tools.ietf.org/html/rfc8141 + if (['String', 'Number', 'Boolean'].indexOf(this.type) >= 0) { + return `urn:${propertyName}:${this.salt}:${this.value}|`; + }if (this.type === 'Array') { + const itemsValues = _.reduce(this.value, (result, item) => `${result}${item.getAttestableValue(null, true)},`, ''); + return `urn:${propertyName}:${this.salt}:[${itemsValues}]`; + } + return _.reduce(_.sortBy(_.keys(this.value)), (s, k) => `${s}${this.value[k].getAttestableValue(propertyName)}`, ''); + } + + /** + * Returns the global CredentialItem of the Credential + */ + getGlobalIdentifier() { + return `claim-${this.identifier}-${this.version}`; + } + + getClaimRootPropertyName() { + const { identifierComponents } = getBaseIdentifiers(this.identifier); + return identifierComponents[1].toLowerCase() === 'type' ? '' : _.camelCase(identifierComponents[1]); + } + + getClaimPropertyName() { + const { identifierComponents } = getBaseIdentifiers(this.identifier); + return identifierComponents[2]; + } + + getClaimPath() { + return Claim.getPath(this.identifier); + } + + static getPath(identifier) { + const { identifierComponents } = getBaseIdentifiers(identifier); + const baseName = _.camelCase(identifierComponents[1]); + return baseName !== 'type' ? `${baseName}.${identifierComponents[2]}` : identifierComponents[2]; + } + + getAttestableValues(path, isItemArray = false) { + const joinPaths = (head, tail) => { + const headComponents = head ? _.split(head, '.') : []; + let tailComponents = tail ? _.split(tail, '.') : []; + tailComponents = _.last(headComponents) === _.first(tailComponents) ? tailComponents.splice(1) : tailComponents; + const newPath = _.join([...headComponents, ...tailComponents], '.'); + return newPath; + }; + + let values = []; + const def = _.find(definitions, { identifier: this.identifier, version: this.version }); + if (def.credentialItem || def.attestable) { + const claimPath = joinPaths(path, !isItemArray ? this.getClaimPath() : null); + values.push({ identifier: this.identifier, value: this.getAttestableValue(null, isItemArray), claimPath }); + if (this.type === 'Object') { + _.forEach(_.keys(this.value), k => { + const innerValues = this.value[k].getAttestableValues(claimPath); + values = _.concat(values, innerValues); + }); + } else if (this.type === 'Array') { + _.forEach(this.value, (item, idx) => { + values.push(...item.getAttestableValues(`${claimPath}.${idx}`, true)); + }); + } + } + return values; + } + + /** + * extract the expected Type name for the value when constructing an UCA + * @param {*} definition + */ + static getTypeName(definition) { + if (_.isString(definition.type)) { + if (_.includes(validIdentifiers, definition.type)) { + const innerDefinition = _.find(definitions, { identifier: definition.type }); + return this.getTypeName(innerDefinition); + } + + return definition.type; + } + return 'Object'; + } + + static getAllProperties(identifier, pathName) { + const definition = _.find(definitions, { identifier }); + const properties = []; + const type = UserCollectableAttribute.resolveType(definition, definitions); + const typeDefinition = _.isString(type) ? _.find(definitions, { identifier: type }) : definition; + + if (typeDefinition && this.getTypeName(typeDefinition) === 'Object') { + let typeDefProps; + if (typeDefinition.type.properties) { + typeDefProps = typeDefinition.type.properties; + } else { + const typeDefDefinition = _.find(definitions, { identifier: typeDefinition.type }); + typeDefProps = UserCollectableAttribute.resolveType(typeDefDefinition, definitions).properties; + } + + let basePropName; + const { identifierComponents: baseIdentifierComponents } = getBaseIdentifiers(identifier); + if (pathName) { + if (_.includes(pathName, _.lowerCase(baseIdentifierComponents[1]))) { + basePropName = `${pathName}`; + } else { + basePropName = `${pathName}.${_.lowerCase(baseIdentifierComponents[1])}.${baseIdentifierComponents[2]}`; + } + } else { + basePropName = `${_.lowerCase(baseIdentifierComponents[1])}.${baseIdentifierComponents[2]}`; + } + + if (_.includes(['String', 'Number', 'Boolean'], `${typeDefProps.type}`)) { + // Properties is not an object + properties.push(`${basePropName}.${typeDefProps.name}`); + } else { + _.forEach(typeDefProps, prop => { + const { isNewIdentifier } = getBaseIdentifiers(prop.type); + const newBasePropName = !isNewIdentifier ? basePropName : `${basePropName}.${prop.name}`; + const proProperties = this.getAllProperties(prop.type, newBasePropName); + _.forEach(proProperties, p => properties.push(p)); + }); + } + } else if (pathName) { + const { identifierComponents } = getBaseIdentifiers(definition.identifier); + let propertiesName; + if (pathName.indexOf(identifierComponents[2]) >= 0) { + propertiesName = `${pathName}`; + } else { + propertiesName = `${pathName}.${identifierComponents[2]}`; + } + properties.push(propertiesName); + } else { + const { identifierComponents } = getBaseIdentifiers(identifier); + const propertiesName = `${_.lowerCase(identifierComponents[1])}.${identifierComponents[2]}`; + properties.push(propertiesName); + } + return properties; + } +} + +function convertIdentifierToClassName(identifier) { + const { identifierComponents } = getBaseIdentifiers(identifier); + const baseName = identifierComponents[1]; + const detailName = _.upperFirst(_.camelCase(identifierComponents[2])); + return `${baseName}${detailName}`; +} + +function mixinIdentifiers(UCA) { + // Extend UCA Semantic + _.forEach(_.filter(definitions, d => d.credentialItem), def => { + const name = convertIdentifierToClassName(def.identifier); + const source = {}; + const { identifier } = def; + + function UCAConstructor(value, version) { + return new Claim(identifier, value, version); + } + + source[name] = UCAConstructor; + _.mixin(Claim, source); + }); + return UCA; +} + +module.exports = { Claim: mixinIdentifiers(Claim), definitions, getBaseIdentifiers }; \ No newline at end of file diff --git a/dist/cjs/claim/__mocks__/definitions.js b/dist/cjs/claim/__mocks__/definitions.js new file mode 100644 index 00000000..14ead95d --- /dev/null +++ b/dist/cjs/claim/__mocks__/definitions.js @@ -0,0 +1,33 @@ +'use strict'; + +const definitions = [{ + identifier: 'civ:Mock:booleans', + version: '1', + type: 'Boolean', + attestable: true +}, { + identifier: 'civ:Mock:excMax', + version: '1', + type: 'Number', + exclusiveMaximum: true, + maximum: 20 +}, { + identifier: 'civ:Mock:max', + version: '1', + type: 'Number', + exclusiveMaximum: false, + maximum: 50 +}, { + identifier: 'civ:Mock:excMax', + version: '1', + type: 'Number', + value: [10, 20, 30] +}, { + identifier: 'civ:Mock:max', + version: '1', + type: 'Number', + exclusiveMinimum: false, + minimum: 5 +}]; + +module.exports = definitions; \ No newline at end of file diff --git a/dist/cjs/claim/definitions.js b/dist/cjs/claim/definitions.js new file mode 100644 index 00000000..c85b5856 --- /dev/null +++ b/dist/cjs/claim/definitions.js @@ -0,0 +1,618 @@ +'use strict'; + +const { definitions: ucaDefinitions } = require('@identity.com/uca'); + +// ######################################### DEFINITIONS ########################################### +const definitions = [{ + identifier: 'claim-cvc:Email.domain-v1', + version: '1', + type: 'cvc:Type:domain', + credentialItem: true +}, { + identifier: 'claim-cvc:Contact.email-v1', + version: '1', + type: 'claim-cvc:Type.email-v1', + credentialItem: true +}, { + identifier: 'claim-cvc:User.id-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:User.realm-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Phone.countryCode-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Phone.number-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Phone.extension-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Phone.lineType-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:PhoneNumber.countryCode-v1', + type: 'claim-cvc:Phone.countryCode-v1', + version: '1', + credentialItem: true +}, { + identifier: 'claim-cvc:PhoneNumber.number-v1', + type: 'claim-cvc:Phone.number-v1', + version: '1', + credentialItem: true +}, { + identifier: 'claim-cvc:PhoneNumber.extension-v1', + type: 'claim-cvc:Phone.extension-v1', + version: '1', + credentialItem: true +}, { + identifier: 'claim-cvc:PhoneNumber.lineType-v1', + type: 'claim-cvc:Phone.lineType-v1', + version: '1', + credentialItem: true +}, { + identifier: 'claim-cvc:Contact.phoneNumber-v1', + version: '1', + type: 'claim-cvc:Type.phoneNumber-v1', + credentialItem: true +}, { + identifier: 'claim-cvc:Name.givenNames-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Name.familyNames-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Name.otherNames-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Type.Name-v1', + version: '1', + type: { + properties: [{ + name: 'givenNames', + type: 'claim-cvc:Name.givenNames-v1' + }, { + name: 'familyNames', + type: 'claim-cvc:Name.familyNames-v1' + }, { + name: 'otherNames', + type: 'claim-cvc:Name.otherNames-v1' + }], + required: ['givenNames'] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Document.name-v1', + version: '1', + type: 'claim-cvc:Type.Name-v1', + credentialItem: true +}, { + identifier: 'claim-cvc:Identity.name-v1', + version: '1', + type: 'claim-cvc:Type.Name-v1', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.nationality-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.number-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Identity.dateOfBirth-v1', + version: '1', + type: 'cvc:Type:date', + credentialItem: true +}, { + identifier: 'claim-cvc:Address.city-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Address.postalCode-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Address.state-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Address.county-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Address.country-v1', + version: '1', + type: 'cvc:Type:country', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.address-v1', + version: '1', + type: 'claim-cvc:Type.address-v1', + credentialItem: true +}, { + identifier: 'claim-cvc:Identity.address-v1', + version: '1', + type: 'claim-cvc:Type.address-v1', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.dateOfIssue-v1', + version: '1', + type: 'cvc:Type:date', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.dateOfExpiry-v1', + version: '1', + type: 'cvc:Type:date', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.dateOfBirth-v1', + version: '1', + type: 'cvc:Type:date', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.enum-v1', + version: '1', + type: 'String' +}, { + identifier: 'claim-cvc:Document.type-v1', + version: '1', + type: 'cvc:Type:documentType', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.gender-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.issueLocation-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.issueAuthority-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.issueCountry-v1', + version: '1', + type: 'cvc:Type:country', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.placeOfBirth-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Type.email-v1', + version: '1', + type: { + properties: [{ + name: 'username', + type: 'cvc:Email:username' + }, { + name: 'domain', + type: 'claim-cvc:Email.domain-v1' + }] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Type.phoneNumber-v1', + version: '1', + type: { + properties: [{ + name: 'country', + type: 'claim-cvc:PhoneNumber.country-v1' + }, { + name: 'countryCode', + type: 'claim-cvc:PhoneNumber.countryCode-v1' + }, { + name: 'number', + type: 'claim-cvc:PhoneNumber.number-v1' + }, { + name: 'extension', + type: 'claim-cvc:PhoneNumber.extension-v1' + }, { + name: 'lineType', + type: 'claim-cvc:PhoneNumber.lineType-v1' + }], + required: ['country', 'countryCode', 'number', 'lineType'] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:PhoneNumber.country-v1', + type: 'cvc:Type:country', + version: '1', + credentialItem: true +}, { + identifier: 'claim-cvc:Type.Name-v1', + version: '1', + type: { + properties: [{ + name: 'givenNames', + type: 'claim-cvc:Name.givenNames-v1' + }, { + name: 'familyNames', + type: 'claim-cvc:Name.familyNames-v1' + }, { + name: 'otherNames', + type: 'claim-cvc:Name.otherNames-v1' + }], + required: ['givenNames'] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Type.address-v1', + version: '1', + type: { + properties: [{ + name: 'country', + type: 'claim-cvc:Address.country-v1' + }, { + name: 'county', + type: 'claim-cvc:Address.county-v1' + }, { + name: 'state', + type: 'claim-cvc:Address.state-v1' + }, { + name: 'street', + type: 'claim-cvc:Address.street-v1' + }, { + name: 'unit', + type: 'claim-cvc:Address.unit-v1' + }, { + name: 'city', + type: 'claim-cvc:Address.city-v1' + }, { + name: 'postalCode', + type: 'claim-cvc:Address.postalCode-v1' + }], + required: ['street', 'city', 'state', 'country'] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Address.street-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Address.unit-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.properties-v1', + version: '1', + attestable: true, + type: { + properties: [{ + name: 'dateOfIssue', + type: 'claim-cvc:Document.dateOfIssue-v1' + }, { + name: 'dateOfExpiry', + type: 'claim-cvc:Document.dateOfExpiry-v1' + }], + required: ['dateOfIssue'] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:SocialSecurity.number-v1', + version: '1', + type: 'cvc:Type:socialSecurityNumber', + credentialItem: true +}, { + identifier: 'claim-cvc:Validation:evidences.idDocumentFront-v1', + version: '1', + type: 'cvc:Evidences:idDocumentFront', + credentialItem: true +}, { + identifier: 'claim-cvc:Validation:evidences.idDocumentBack-v1', + version: '1', + type: 'cvc:Evidences:idDocumentBack', + credentialItem: true +}, { + identifier: 'claim-cvc:Validation:evidences.selfie-v1', + version: '1', + type: 'cvc:Evidences:selfie', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.evidences-v1', + version: '1', + attestable: true, + type: { + properties: [{ + name: 'idDocumentFront', + type: 'claim-cvc:Validation:evidences.idDocumentFront-v1' + }, { + name: 'idDocumentBack', + type: 'claim-cvc:Validation:evidences.idDocumentBack-v1' + }, { + name: 'selfie', + type: 'claim-cvc:Validation:evidences.selfie-v1' + }] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Vaccination.date-v1', + version: '1', + type: 'cvc:Type:timestamp', + credentialItem: false +}, { + identifier: 'claim-cvc:Test.date-v1', + version: '1', + type: 'cvc:Type:timestamp', + credentialItem: false +}, { + identifier: 'claim-cvc:Vaccination.name-v1', + version: '1', + type: 'String', + credentialItem: false +}, { + identifier: 'claim-cvc:Vaccination.recordDetail-v1', + version: '1', + type: { + properties: [{ + name: 'createdAt', + type: 'cvc:Type:date' + }, { + name: 'updatedAt', + type: 'cvc:Type:date' + }] + }, + required: ['createdAt'], + credentialItem: false +}, { + identifier: 'claim-cvc:Type.organizationName-v1', + version: '1', + type: 'String', + credentialItem: false +}, { + identifier: 'claim-cvc:Type.organizationId-v1', + version: '1', + type: 'String', + credentialItem: false +}, { + identifier: 'claim-cvc:Type.organization-v1', + version: '1', + type: { + properties: [{ + name: 'name', + type: 'claim-cvc:Type.organizationName-v1' + }, { + name: 'id', + type: 'claim-cvc:Type.organizationId-v1' + }] + }, + required: ['name'], + credentialItem: false +}, { + identifier: 'claim-cvc:Type.patient-v1', + version: '1', + type: { + properties: [{ + name: 'fullName', + type: 'cvc:Type:fullName' + }, { + name: 'dateOfBirth', + type: 'cvc:Type:date' + }] + }, + required: ['name'], + credentialItem: true +}, { + identifier: 'claim-cvc:Medical.code-v1', + version: '1', + type: { + properties: [{ + name: 'name', + type: 'cvc:Code:name' + }, { + name: 'code', + type: 'cvc:Code:code' + }, { + name: 'codeSystem', + type: 'cvc:Code:codeSystem' + }, { + name: 'codeSystemName', + type: 'cvc:Code:codeSystemName' + }] + }, + required: ['name', 'code'], + credentialItem: false +}, { + identifier: 'claim-cvc:Manufacturer.name-v1', + version: '1', + type: 'String', + credentialItem: false +}, { + identifier: 'claim-cvc:Vaccination.manufacturer-v1', + version: '1', + type: { + properties: [{ + name: 'name', + type: 'claim-cvc:Manufacturer.name-v1' + }, { + name: 'code', + type: 'claim-cvc:Medical.code-v1' + }], + required: ['name'] + }, + credentialItem: false +}, { + identifier: 'claim-cvc:Vaccination.id-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Medical.codes-v1', + version: '1', + type: 'Array', + items: { + type: 'claim-cvc:Medical.code-v1' + }, + credentialItem: false +}, { + identifier: 'claim-cvc:Codes.records-v1', + version: '1', + type: 'Array', + items: { + type: 'claim-cvc:Medical.code-v1' + }, + credentialItem: false +}, { + identifier: 'claim-cvc:Vaccination.record-v1', + version: '1', + type: { + properties: [{ + name: 'vaccinationId', + type: 'claim-cvc:Vaccination.id-v1' + }, { + name: 'dateOfAdministration', + type: 'claim-cvc:Vaccination.date-v1' + }, { + name: 'manufacturer', + type: 'claim-cvc:Vaccination.manufacturer-v1' + }, { + name: 'name', + type: 'claim-cvc:Vaccination.name-v1' + }, { + name: 'detail', + type: 'claim-cvc:Vaccination.recordDetail-v1' + }, { + name: 'organization', + type: 'cvc:Type:organization' + }, { + name: 'codes', + type: 'claim-cvc:Codes.records-v1' + }], + required: ['vaccinationId', 'dateOfAdministration', 'name', 'organization'] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Vaccination.records-v1', + version: '1', + type: 'Array', + items: { + type: 'claim-cvc:Vaccination.record-v1' + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Test.type-v1', + version: '1', + type: 'String', + credentialItem: false +}, { + identifier: 'claim-cvc:Test.result-v1', + version: '1', + type: 'String', + credentialItem: false +}, { + identifier: 'claim-cvc:Test.id-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Test.record-v1', + version: '1', + type: { + properties: [{ + name: 'testId', + type: 'claim-cvc:Test.id-v1' + }, { + name: 'testDate', + type: 'claim-cvc:Test.date-v1' + }, { + name: 'resultDate', + type: 'claim-cvc:Test.date-v1' + }, { + name: 'type', + type: 'claim-cvc:Test.type-v1' + }, { + name: 'result', + type: 'claim-cvc:Test.result-v1' + }, { + name: 'organization', + type: 'claim-cvc:Type.organization-v1' + }, { + name: 'codes', + type: 'claim-cvc:Codes.records-v1' + }], + required: ['testId', 'testDate', 'type', 'result'] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Test.records-v1', + version: '1', + type: 'Array', + items: { + type: 'claim-cvc:Test.record-v1' + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Medical.covid19-v1', + version: '1', + type: { + properties: [{ + name: 'vaccinations', + type: 'claim-cvc:Vaccination.records-v1' + }, { + name: 'tests', + type: 'claim-cvc:Test.records-v1' + }, { + name: 'patient', + type: 'claim-cvc:Type.patient-v1' + }] + }, + require: ['patient'], + credentialItem: true +}]; + +function transformUcaIdToClaimId(identifier) { + const identifierComponents = identifier.split(':'); + return `claim-cvc:${identifierComponents[1]}.${identifierComponents[2]}-v1`; +} + +function isDefinitionEqual(definition, ucaDefinition) { + return definition.identifier === transformUcaIdToClaimId(ucaDefinition.identifier) || definition.identifier === ucaDefinition.identifier; +} + +ucaDefinitions.forEach(ucaDefinition => { + let found = false; + definitions.some(definition => { + if (isDefinitionEqual(definition, ucaDefinition)) { + found = true; + } + return found; + }); + if (!found) { + definitions.push(ucaDefinition); + } +}); + +module.exports = definitions; \ No newline at end of file diff --git a/dist/cjs/constants/headers.js b/dist/cjs/constants/headers.js new file mode 100644 index 00000000..43e468c4 --- /dev/null +++ b/dist/cjs/constants/headers.js @@ -0,0 +1,10 @@ +'use strict'; + +const HeaderType = { + EXTERNAL_ID_HEADER: 'X-External-ID', + FLOW_ID_HEADER: 'X-Civic-FlowId', + IDENTITY_HEADER: 'X-Identity-Self' +}; +module.exports = { + HeaderType +}; \ No newline at end of file diff --git a/dist/cjs/constants/index.js b/dist/cjs/constants/index.js new file mode 100644 index 00000000..c7876b24 --- /dev/null +++ b/dist/cjs/constants/index.js @@ -0,0 +1,7 @@ +'use strict'; + +const headers = require('./headers'); + +module.exports = { + headers +}; \ No newline at end of file diff --git a/dist/cjs/creds/ClaimModel.js b/dist/cjs/creds/ClaimModel.js new file mode 100644 index 00000000..38c92e9c --- /dev/null +++ b/dist/cjs/creds/ClaimModel.js @@ -0,0 +1,25 @@ +'use strict'; + +const _ = require('lodash'); + +/** + * Transforms a list of UCAs into the claim property of the verifiable cliams + */ +class ClaimModel { + constructor(ucas) { + _.forEach(ucas, uca => { + const rootPropertyName = uca.getClaimRootPropertyName(); + if (!_.isEmpty(rootPropertyName)) { + if (!this[rootPropertyName]) { + this[rootPropertyName] = {}; + } + + this[rootPropertyName][uca.getClaimPropertyName()] = uca.getPlainValue(); + } else { + this[uca.getClaimPropertyName()] = uca.getPlainValue(); + } + }); + } +} + +module.exports = { ClaimModel }; \ No newline at end of file diff --git a/dist/cjs/creds/CvcMerkleProof.js b/dist/cjs/creds/CvcMerkleProof.js new file mode 100644 index 00000000..a66b65c7 --- /dev/null +++ b/dist/cjs/creds/CvcMerkleProof.js @@ -0,0 +1,62 @@ +'use strict'; + +const _ = require('lodash'); +const MerkleTools = require('merkle-tools'); + +const { sha256 } = require('../lib/crypto'); +const { Claim } = require('../claim/Claim'); +const { services } = require('../services'); + +/** + * Transforms a list of UCAs into the signature property of the verifiable claims + + */ +class CvcMerkleProof { + static get PADDING_INCREMENTS() { + return 16; + } + + constructor(ucas) { + const withRandomUcas = CvcMerkleProof.padTree(ucas); + this.type = 'CvcMerkleProof2018'; + this.merkleRoot = null; + this.anchor = 'TBD (Civic Blockchain Attestation)'; + this.leaves = CvcMerkleProof.getAllAttestableValue(withRandomUcas); + this.buildMerkleTree(); + } + + buildMerkleTree() { + const merkleTools = new MerkleTools(); + const hashes = _.map(this.leaves, n => sha256(n.value)); + merkleTools.addLeaves(hashes); + merkleTools.makeTree(); + _.forEach(hashes, (hash, idx) => { + this.leaves[idx].targetHash = hash; + this.leaves[idx].node = merkleTools.getProof(idx); + }); + this.leaves = _.filter(this.leaves, el => !(el.identifier === 'cvc:Random:node')); + this.merkleRoot = merkleTools.getMerkleRoot().toString('hex'); + } + + static padTree(nodes) { + const currentLength = nodes.length; + const targetLength = currentLength < CvcMerkleProof.PADDING_INCREMENTS ? CvcMerkleProof.PADDING_INCREMENTS : _.ceil(currentLength / CvcMerkleProof.PADDING_INCREMENTS) * CvcMerkleProof.PADDING_INCREMENTS; + const newNodes = _.clone(nodes); + const secureRandom = services.container.SecureRandom; + while (newNodes.length < targetLength) { + newNodes.push(new Claim('cvc:Random:node', secureRandom.wordWith(16))); + } + return newNodes; + } + + static getAllAttestableValue(ucas) { + let values = []; + _.forEach(ucas, uca => { + const innerValues = uca.getAttestableValues(); + values = _.concat(values, innerValues); + }); + return values; + } +} + +module.exports = { CvcMerkleProof }; \ No newline at end of file diff --git a/dist/cjs/creds/VerifiableCredential.js b/dist/cjs/creds/VerifiableCredential.js new file mode 100644 index 00000000..7a79f808 --- /dev/null +++ b/dist/cjs/creds/VerifiableCredential.js @@ -0,0 +1,759 @@ +'use strict'; + +/** + * Cryptographically secure verify the Credential. + * Performs a non cryptographically secure verification, attestation check and signature validation. + * @param credential - A credential object with expirationDate, claim and proof + * @param verifyAttestationFunc - Async method to verify a credential attestation + * @param verifySignatureFunc - Async method to verify a credential signature + * @return true if verified, false otherwise. + */ +let cryptographicallySecureVerify = (() => { + var _ref = _asyncToGenerator(function* (credential, verifyAttestationFunc, verifySignatureFunc) { + if (!nonCryptographicallySecureVerify(credential)) { + return false; + } + + if (verifyAttestationFunc) { + const attestationCheck = yield verifyAttestationFunc(credential.proof); + if (!attestationCheck) return false; + } + + if (verifySignatureFunc) { + const signatureCheck = yield verifySignatureFunc(credential.proof); + if (!signatureCheck) return false; + } + + return true; + }); + + return function cryptographicallySecureVerify(_x, _x2, _x3) { + return _ref.apply(this, arguments); + }; +})(); + +/** + * Verify if a credential was granted for a specific requester and requestId. + * @param credential - A credential object with expirationDate, claim and proof + * @return true if verified, false otherwise. + */ + + +function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + +const _ = require('lodash'); +const validUrl = require('valid-url'); +const sift = require('sift').default; + +const timestamp = require('unix-timestamp'); +const flatten = require('flat'); +const uuidv4 = require('uuid/v4'); +const MerkleTools = require('merkle-tools'); + +const { sha256 } = require('../lib/crypto'); +const { Claim } = require('../claim/Claim'); + +const definitions = require('./definitions'); +const { services } = require('../services'); +const time = require('../timeHelper'); +const { CvcMerkleProof } = require('./CvcMerkleProof'); +const { ClaimModel } = require('./ClaimModel'); + +// convert a time delta to a timestamp +const convertDeltaToTimestamp = delta => time.applyDeltaToDate(delta).getTime() / 1000; + +function validIdentifiers() { + const vi = _.map(definitions, d => d.identifier); + return vi; +} + +function getClaimsWithFlatKeys(claims) { + const flattenDepth3 = flatten(claims, { maxDepth: 3 }); + const flattenDepth2 = flatten(claims, { maxDepth: 2 }); + const flattenClaim = _.merge({}, flattenDepth3, flattenDepth2); + return _(flattenClaim).toPairs().sortBy(0).fromPairs().value(); +} + +function getLeavesClaimPaths(signLeaves) { + return _.map(signLeaves, 'claimPath'); +} + +function verifyLeave(leave, merkleTools, claims, signature, invalidValues, invalidHashs, invalidProofs) { + // 1. verify valid targetHashs + // 1.1 "leave.value" should be equal claim values + const ucaValue = new Claim(leave.identifier, { attestableValue: leave.value }); + if (ucaValue.type === 'String' || ucaValue.type === 'Number') { + if (ucaValue.value !== _.get(claims, leave.claimPath)) { + invalidValues.push(leave.value); + } + } else if (ucaValue.type === 'Object') { + const ucaValueValue = ucaValue.value; + const innerClaimValue = _.get(claims, leave.claimPath); + const claimPathSufix = _.last(_.split(leave.claimPath, '.')); + + const claimValue = {}; + claimValue[claimPathSufix] = innerClaimValue; + const ucaValueKeys = _.keys(ucaValue.value); + _.each(ucaValueKeys, k => { + const expectedClaimValue = _.get(claimValue, k); + if (expectedClaimValue && `${_.get(ucaValueValue[k], 'value')}` !== `${expectedClaimValue}`) { + invalidValues.push(claimValue[k]); + } + }); + } else if (ucaValue.type === 'Array') { + const innerClaimValue = _.get(claims, leave.claimPath); + + _.forEach(ucaValue.value, (arrayItem, idx) => { + const itemInnerClaimValue = innerClaimValue[idx]; + const ucaValueKeys = _.keys(arrayItem.value); + _.each(ucaValueKeys, k => { + const expectedClaimValue = _.get(itemInnerClaimValue, k); + if (expectedClaimValue && `${_.get(arrayItem.value, [k, 'value'])}` !== `${expectedClaimValue}`) { + invalidValues.push(itemInnerClaimValue[k]); + } + }); + }); + } else { + // Invalid ucaValue.type + invalidValues.push(leave.value); + } + + // 1.2 hash(leave.value) should be equal leave.targetHash + const hash = sha256(leave.value); + if (hash !== leave.targetHash) invalidHashs.push(leave.targetHash); + + // 2. Validate targetHashs + proofs with merkleRoot + const isValidProof = merkleTools.validateProof(leave.node, leave.targetHash, signature.merkleRoot); + if (!isValidProof) invalidProofs.push(leave.targetHash); +} + +function validateEvidence(evidenceItem) { + const requiredFields = ['type', 'verifier', 'evidenceDocument', 'subjectPresence', 'documentPresence']; + _.forEach(requiredFields, field => { + if (!(field in evidenceItem)) { + throw new Error(`Evidence ${field} is required`); + } + }); + // id property is optional, but if present, SHOULD contain a URL + if ('id' in evidenceItem && !validUrl.isWebUri(evidenceItem.id)) { + throw new Error('Evidence id is not a valid URL'); + } + if (!_.isArray(evidenceItem.type)) { + throw new Error('Evidence type is not an Array object'); + } +} + +function serializeEvidence(evidence) { + const evidenceList = _.isArray(evidence) ? evidence : [evidence]; + return _.map(evidenceList, evidenceItem => { + validateEvidence(evidenceItem); + return { + id: evidenceItem.id, + type: evidenceItem.type, + verifier: evidenceItem.verifier, + evidenceDocument: evidenceItem.evidenceDocument, + subjectPresence: evidenceItem.subjectPresence, + documentPresence: evidenceItem.documentPresence + }; + }); +} + +/** + * Transform DSR constraints to sift constraits + * @param {*} constraints + */ +function transformConstraint(constraints) { + const resultConstraints = []; + + _.forEach(constraints.claims, constraint => { + if (!constraint.path) { + throw new Error('Malformed contraint: missing PATTH'); + } + if (!constraint.is) { + throw new Error('Malformed contraint: missing IS'); + } + + const siftConstraint = {}; + siftConstraint[constraint.path] = constraint.is; + resultConstraints.push(siftConstraint); + }); + + return resultConstraints; +} + +/** + * Checks if object is a Date Structure (has day, month, year properties) + * + * @param obj - Structure to test + * @return {boolean} + */ +function isDateStructure(obj) { + const objKeys = _.keys(obj); + if (objKeys.length !== 3) { + // it has more or less keys the (day, month, year) + return false; + } + return _.includes(objKeys, 'day') && _.includes(objKeys, 'month') && _.includes(objKeys, 'year'); +} + +/** + * Non cryptographically secure verify the Credential + * Performs a proofs verification only. + * @param credential - A credential object with expirationDate, claim and proof + * @return true if verified, false otherwise. + */ +function nonCryptographicallySecureVerify(credential) { + const expiry = _.clone(credential.expirationDate); + const claims = _.clone(credential.claim); + const signature = _.clone(credential.proof); + const signLeaves = _.get(signature, 'leaves'); + let valid = false; + + const merkleTools = new MerkleTools(); + const claimsWithFlatKeys = getClaimsWithFlatKeys(claims); + const leavesClaimPaths = getLeavesClaimPaths(signLeaves); + const invalidClaim = []; + const invalidExpiry = []; + const invalidValues = []; + const invalidHashs = []; + const invalidProofs = []; + _.forEach(_.keys(claimsWithFlatKeys), claimKey => { + // check if `claimKey` has a `claimPath` proof + const leaveIdx = _.indexOf(leavesClaimPaths, claimKey); + // if not found + if (leaveIdx === -1) { + // .. still test if parent key node may have a `claimPath` proof + _.findLastIndex(claimKey, '.'); + const parentClaimKey = claimKey.substring(0, _.lastIndexOf(claimKey, '.')); + if (_.indexOf(leavesClaimPaths, parentClaimKey) > -1) { + // if yes, no problem, go to next loop + return; + } + // if no, include on invalidClaim array + invalidClaim.push(claimKey); + } else { + const leave = signLeaves[leaveIdx]; + verifyLeave(leave, merkleTools, claims, signature, invalidValues, invalidHashs, invalidProofs); + } + }); + + // It has to be present Credential expiry even with null value + const expiryIdx = _.indexOf(leavesClaimPaths, 'meta.expirationDate'); + if (expiryIdx >= 0) { + const expiryLeave = signLeaves[expiryIdx]; + const metaClaim = { + meta: { + expirationDate: expiry + } + }; + const totalLengthBefore = invalidValues.length + invalidHashs.length + invalidProofs.length; + verifyLeave(expiryLeave, merkleTools, metaClaim, signature, invalidValues, invalidHashs, invalidProofs); + const totalLengthAfter = invalidValues.length + invalidHashs.length + invalidProofs.length; + if (totalLengthAfter === totalLengthBefore) { + // expiry has always to be string formatted date or null value + // if it is null it means it's indefinitely + if (expiry !== null) { + const now = new Date(); + const expiryDate = new Date(expiry); + if (now.getTime() > expiryDate.getTime()) { + invalidExpiry.push(expiry); + } + } + } + } + if (_.isEmpty(invalidClaim) && _.isEmpty(invalidValues) && _.isEmpty(invalidHashs) && _.isEmpty(invalidProofs) && _.isEmpty(invalidExpiry)) { + valid = true; + } + return valid; +}function requesterGrantVerify(credential, requesterId, requestId, keyName) { + const label = _.get(credential.proof, 'anchor.subject.label'); + const anchorPubKey = _.get(credential.proof, 'anchor.subject.pub'); + const anchorData = _.get(credential.proof, 'anchor.subject.data'); + + if (_.isEmpty(credential.granted) || _.isEmpty(label) || _.isEmpty(anchorPubKey)) { + return false; + } + + const stringToHash = `${label}${anchorData}${requesterId}${requestId}`; + const hexHash = sha256(stringToHash); + + const cryptoManager = services.container.CryptoManager; + + let verifyKey = keyName; + if (_.isEmpty(verifyKey)) { + if (!_.isFunction(cryptoManager.installKey)) { + throw new Error('CryptoManager does not support installKey, please use a `keyName` instead.'); + } + verifyKey = `TEMP_KEY_NAME_${new Date().getTime()}`; + cryptoManager.installKey(verifyKey, anchorPubKey); + } + + return cryptoManager.verify(verifyKey, hexHash, credential.granted); +} + +/** + * Trasnform {day, month, year } to Unix Date + * + * @param obj {day, month, year } + * @return {number} an unix-timestamp in seconds + */ +function transformDate(obj) { + return new Date(obj.year, obj.month - 1, obj.day).getTime() / 1000; +} + +const VERIFY_LEVELS = { + INVALID: -1, // Verifies if the VC structure and/or signature proofs is not valid, or credential is expired + PROOFS: 0, // Verifies if the VC structure and/or signature proofs are valid, including the expiry + ANCHOR: 1, // Verifies if the VC Attestation Anchor structure is valid + GRANTED: 2, // Verifies if the owner granted the VC usage for a specific request + BLOCKCHAIN: 3 // Verifies if the VC Attestation is valid on the blockchain +}; + +/** + * Throws exception if the definition has missing required claims + * @param {*} definition - the credential definition + * @param {*} ucas - the list of ucas + */ +function verifyRequiredClaims(definition, ucas) { + if (!_.isEmpty(definition.required)) { + const identifiers = ucas.map(uca => uca.identifier); + const missings = _.difference(definition.required, identifiers); + if (!_.isEmpty(missings)) { + throw new Error(`Missing required claim(s): ${_.join(missings, ', ')}`); + } + } +} + +/** + * Throws exception if the definition has missing required claims + * @param {*} definition - the credential definition + * @param {*} verifiableCredentialJSON - the verifiable credential JSON + */ +function verifyRequiredClaimsFromJSON(definition, verifiableCredentialJSON) { + const leaves = _.get(verifiableCredentialJSON, 'proof.leaves'); + + if (!_.isEmpty(definition.required) && leaves) { + const identifiers = leaves.map(leave => leave.identifier); + const missings = _.difference(definition.required, identifiers); + if (!_.isEmpty(missings)) { + throw new Error(`Missing required claim(s): ${_.join(missings, ', ')}`); + } + } +} + +/** + * Retrieves the credential definition + * @param {string} identifier - credential identifier + * @param {*} [version] - definition version + */ +function getCredentialDefinition(identifier, version) { + let definition; + if (version) { + definition = _.find(definitions, { identifier, version: `${version}` }); + } else { + definition = _.find(definitions, { identifier }); + } + if (!definition) { + throw new Error(`Credential definition for ${identifier} v${version} not found`); + } + return definition; +} + +/** + * Creates a new Verifiable Credential based on an well-known identifier and it's claims dependencies + * @param {*} identifier + * @param {*} issuer + * @param {*} ucas + * @param {*} version + * @param {*} [evidence] + */ +function VerifiableCredentialBaseConstructor(identifier, issuer, expiryIn, ucas, version, evidence) { + var _this = this; + + this.id = uuidv4(); + this.issuer = issuer; + const issuerUCA = new Claim('cvc:Meta:issuer', this.issuer); + this.issuanceDate = new Date().toISOString(); + const issuanceDateUCA = new Claim('cvc:Meta:issuanceDate', this.issuanceDate); + this.identifier = identifier; + this.expirationDate = expiryIn ? timestamp.toDate(timestamp.now(expiryIn)).toISOString() : null; + const expiryUCA = new Claim('cvc:Meta:expirationDate', this.expirationDate ? this.expirationDate : 'null'); + + const proofUCAs = expiryUCA ? _.concat(ucas, issuerUCA, issuanceDateUCA, expiryUCA) : _.concat(ucas, issuerUCA, issuanceDateUCA); + + if (!_.includes(validIdentifiers(), identifier)) { + throw new Error(`${identifier} is not defined`); + } + + const definition = getCredentialDefinition(identifier, version); + this.version = `${version}` || definition.version; + this.type = ['Credential', identifier]; + this.transient = definition.transient || false; + + if (evidence) { + this.evidence = serializeEvidence(evidence); + } + + // ucas can be empty here if it is been constructed from JSON + if (!_.isEmpty(ucas)) { + verifyRequiredClaims(definition, ucas); + this.claim = new ClaimModel(ucas); + this.proof = new CvcMerkleProof(proofUCAs); + if (!_.isEmpty(definition.excludes)) { + const removed = _.remove(this.proof.leaves, el => _.includes(definition.excludes, el.identifier)); + _.forEach(removed, r => { + _.unset(this.claim, r.claimPath); + }); + } + // The VC Grantted session (see .grantUsageFor) + this.granted = null; + } + + /** + * Returns the global identifier of the Credential + */ + this.getGlobalIdentifier = () => `credential-${this.identifier}-${this.version}`; + + /** + * Creates a filtered credential exposing only the requested claims + * @param {*} requestedClaims + */ + this.filter = requestedClaims => { + const filtered = _.cloneDeep(this); + _.remove(filtered.proof.leaves, el => !_.includes(requestedClaims, el.identifier)); + + filtered.claim = {}; + _.forEach(filtered.proof.leaves, el => { + _.set(filtered.claim, el.claimPath, _.get(this.claim, el.claimPath)); + }); + + return filtered; + }; + + /** + * Request that this credential MerkleRoot is anchored on the Blockchain. + * This will return a _temporary_ anchor meaning that the blockchain entry is still not confirmed. + * + * @param options options to be passed + * @param options.subject the local signed subject with the user private key + * @param options.subject.label a short description of the subject + * @param options.subject.data hash of the merkle root + * @param options.subject.pub xpub of the signing private key + * @param options.subject.signature the value of the signature of the private key + * @param options.network testnet for test env, bitcoin for production + * @param options.cosigner object containing private and public key for cosigning + * @param options.cosigner.xpub public key of the cosigner + * @param options.cosigner.xprv private key of the cosigner + * + * @returns the json object containing the whole anchor attestation + * + */ + this.requestAnchor = (() => { + var _ref2 = _asyncToGenerator(function* (options) { + if (_this.transient) { + // If credential is transient no Blockchain attestation is issued + _this.proof.anchor = { + type: 'transient', + subject: { + label: _this.identifier, + data: _this.proof.merkleRoot + } + }; + return _this; + } + + const anchorService = services.container.AnchorService; + const updatedOption = _.merge({}, options, { + subject: { + label: _this.identifier, + data: _this.proof.merkleRoot + } + }); + const anchor = yield anchorService.anchor(updatedOption); + _this.proof.anchor = anchor; + return _this; + }); + + return function (_x4) { + return _ref2.apply(this, arguments); + }; + })(); + + /** + * Trys to renew the current anchor. replecinf the _temporary_ anchor for a _permanent_ one, + * already confirmed on the blockchain. + */ + this.updateAnchor = _asyncToGenerator(function* () { + // If credential is transient no Blockchain attestation is issued + if (_this.transient) { + // If credential is transient no Blockchain attestation is issued + _this.proof.anchor = { + type: 'transient', + subject: { + label: _this.identifier, + data: _this.proof.merkleRoot + } + }; + return _this; + } + const anchorService = services.container.AnchorService; + const anchor = yield anchorService.update(_this.proof.anchor); + _this.proof.anchor = anchor; + return _this; + }); + + /** + * Iterate over all leaves and see if their proofs are valid + * @returns {boolean} + */ + this.verifyProofs = () => nonCryptographicallySecureVerify(this); + + /** + * Verify the Credential and return a verification level. + * @return Any of VC.VERIFY_LEVELS + */ + this.verify = (higherVerifyLevel, options) => { + const { requestorId, requestId, keyName } = options || {}; + const hVerifyLevel = !_.isNil(higherVerifyLevel) ? higherVerifyLevel : VERIFY_LEVELS.GRANTED; + let verifiedlevel = VERIFY_LEVELS.INVALID; + + // Test next level + if (verifiedlevel === VERIFY_LEVELS.INVALID && hVerifyLevel >= VERIFY_LEVELS.PROOFS && this.verifyProofs()) verifiedlevel = VERIFY_LEVELS.PROOFS; + + // Test next level + if (verifiedlevel === VERIFY_LEVELS.PROOFS && hVerifyLevel >= VERIFY_LEVELS.ANCHOR && this.verifyAttestation()) verifiedlevel = VERIFY_LEVELS.ANCHOR; + + // Test next level + if (verifiedlevel === VERIFY_LEVELS.ANCHOR && hVerifyLevel >= VERIFY_LEVELS.GRANTED && this.verifyGrant(requestorId, requestId, keyName)) verifiedlevel = VERIFY_LEVELS.GRANTED; + + return verifiedlevel; + }; + + /** + * This method checks if the signature matches for the root of the Merkle Tree + * @return true or false for the validation + */ + this.verifySignature = pinnedPubKey => { + if (this.proof.anchor.type === 'transient') { + return true; + } + return services.container.AnchorService.verifySignature(this.proof, pinnedPubKey); + }; + + /** + * This method checks that the attestation / anchor exists on the BC + */ + this.verifyAttestation = _asyncToGenerator(function* () { + // Don't check attestation for credentials that are never attested on blockchain + if (_this.proof.anchor.type === 'transient' || _this.proof.anchor.network === 'dummynet') { + return true; + } + + return services.container.AnchorService.verifyAttestation(_this.proof); + }); + + /** + * This method will revoke the attestation on the chain + * @returns {Promise|void>} + */ + this.revokeAttestation = _asyncToGenerator(function* () { + if (_this.proof.type === 'transient') { + return; + } + // eslint-disable-next-line consistent-return + return services.container.AnchorService.revokeAttestation(_this.proof); + }); + + /** + * This method will check on the chain the balance of the transaction and if it's still unspent, than it's not revoked + * @returns {Promise|void>} + */ + this.isRevoked = _asyncToGenerator(function* () { + if (_this.proof.type === 'transient') { + return false; + } + return services.container.AnchorService.isRevoked(_this.proof); + }); + + const convertTimestampIfString = obj => _.isString(obj) ? convertDeltaToTimestamp(obj) : obj; + + this.isMatch = constraints => { + const claims = _.cloneDeep(this.claim); + const siftCompatibleConstraints = transformConstraint(constraints); + + const claimsMatchConstraint = constraint => { + const path = _.keys(constraint)[0]; + const pathValue = _.get(claims, path); + if (isDateStructure(pathValue)) { + _.set(claims, path, transformDate(pathValue)); + // transforms delta values like "-18y" to a proper timestamp + _.set(constraint, path, _.mapValues(constraint[path], convertTimestampIfString)); + } + // The Constraints are ANDed here - if one is false, the entire + return sift(constraint)([claims]); + }; + + return siftCompatibleConstraints.reduce((matchesAllConstraints, nextConstraint) => matchesAllConstraints && claimsMatchConstraint(nextConstraint), true); + }; + + /** + * Updates the credential with a "granted" token based on the requestorId and a unique requestId (a nonce) that + * can be verified later using .verify() function. + * + * @param {string} requestorId - The IDR id (DID). + * @param {string} requestId - A unique requestID. This should be a nonce for proof chanlange. + * @param {Object} option - You should provide either a keyName or a pvtKey. + * @param {string} option.keyName - A keyName - if CryptoManager is been used. + * @param {string} option.pvtKey - A pvtKey in base58 format (default impl). + */ + this.grantUsageFor = (requestorId, requestId, { keyName, pvtKey }) => { + if (_.isEmpty(_.get(this.proof, 'anchor.subject.label')) || _.isEmpty(_.get(this.proof, 'anchor.subject.data'))) { + throw new Error('Invalid credential attestation/anchor'); + } + if (!this.verifySignature()) { + throw new Error('Invalid credential attestation/anchor signature'); + } + if (!requestorId || !requestId || !(keyName || pvtKey)) { + throw new Error('Missing required parameter: requestorId, requestId or key'); + } + // eslint-disable-next-line max-len + const stringToHash = `${this.proof.anchor.subject.label}${this.proof.anchor.subject.data}${requestorId}${requestId}`; + const hexHash = sha256(stringToHash); + + const cryptoManager = services.container.CryptoManager; + + let signKey = keyName; + if (pvtKey) { + if (!_.isFunction(cryptoManager.installKey)) { + throw new Error('You provide a `pvtKey` but the CryptoManager does not support it, use a `keyName` instead.'); + } + signKey = `TEMP_KEY_NAME_${new Date().getTime()}`; + cryptoManager.installKey(signKey, pvtKey); + } + + const hexSign = cryptoManager.sign(signKey, hexHash); + this.granted = hexSign; + }; + + /** + * @param {} requestorId + * @param {} requestId + * @param {} [keyName] + */ + this.verifyGrant = (requesterId, requestId, keyName) => requesterGrantVerify(this, requesterId, requestId, keyName); + + return this; +} + +/** + * CREDENTIAL_META_FIELDS - Array with meta fields of a credential + */ +const CREDENTIAL_META_FIELDS = ['id', 'identifier', 'issuer', 'issuanceDate', 'expirationDate', 'version', 'type']; + +/** + * + * @param {*} vc + */ +const getCredentialMeta = vc => _.pick(vc, CREDENTIAL_META_FIELDS); + +/** + * Sift constraints to throw errors for constraints missing IS + * @param {*} constraintsMeta + * @param Array + */ +function transformMetaConstraint(constraintsMeta) { + const resultConstraints = []; + + // handle special field constraints.meta.credential + const constraintsMetaKeys = _.keys(constraintsMeta.meta); + _.forEach(constraintsMetaKeys, constraintKey => { + const constraint = constraintsMeta.meta[constraintKey]; + const siftConstraint = {}; + // handle special field constraints.meta.credential + if (constraintKey === 'credential') { + siftConstraint.identifier = constraint; + } else if (constraint.is) { + siftConstraint[constraintKey] = constraint.is; + } else { + throw new Error(`Malformed meta constraint "${constraintKey}": missing the IS`); + } + resultConstraints.push(siftConstraint); + }); + return resultConstraints; +} + +/** + * isMatchCredentialMeta + * @param {*} credentialMeta An Object contains only VC meta fields. Other object keys will be ignored. + * @param {*} constraintsMeta Example: + * // constraints.meta = { + * // "credential": "credential-civ:Credential:CivicBasic-1", + * // "issuer": { + * // "is": { + * // "$eq": "did:ethr:0xaf9482c84De4e2a961B98176C9f295F9b6008BfD" + * // } + * // } + * @returns boolean + */ +const isMatchCredentialMeta = (credentialMeta, constraintsMeta) => { + const siftCompatibleConstraints = transformMetaConstraint(constraintsMeta); + + if (_.isEmpty(siftCompatibleConstraints)) return false; + + const credentialMetaMatchesConstraint = constraint => sift(constraint)([credentialMeta]); + + return siftCompatibleConstraints.reduce((matchesAllConstraints, nextConstraint) => matchesAllConstraints && credentialMetaMatchesConstraint(nextConstraint), true); +}; + +VerifiableCredentialBaseConstructor.CREDENTIAL_META_FIELDS = CREDENTIAL_META_FIELDS; +VerifiableCredentialBaseConstructor.getCredentialMeta = getCredentialMeta; +VerifiableCredentialBaseConstructor.isMatchCredentialMeta = isMatchCredentialMeta; + +/** + * Factory function that creates a new Verifiable Credential based on a JSON object + * @param {*} verifiableCredentialJSON + * @returns VerifiableCredentialBaseConstructor + */ +VerifiableCredentialBaseConstructor.fromJSON = verifiableCredentialJSON => { + const definition = getCredentialDefinition(verifiableCredentialJSON.identifier, verifiableCredentialJSON.version); + + verifyRequiredClaimsFromJSON(definition, verifiableCredentialJSON); + + const newObj = new VerifiableCredentialBaseConstructor(verifiableCredentialJSON.identifier, verifiableCredentialJSON.issuer); + newObj.id = _.clone(verifiableCredentialJSON.id); + newObj.issuanceDate = _.clone(verifiableCredentialJSON.issuanceDate); + newObj.expirationDate = _.clone(verifiableCredentialJSON.expirationDate); + newObj.identifier = _.clone(verifiableCredentialJSON.identifier); + newObj.version = _.clone(verifiableCredentialJSON.version); + newObj.type = _.cloneDeep(verifiableCredentialJSON.type); + newObj.claim = _.cloneDeep(verifiableCredentialJSON.claim); + newObj.proof = _.cloneDeep(verifiableCredentialJSON.proof); + newObj.granted = _.clone(verifiableCredentialJSON.granted) || null; + return newObj; +}; + +/** + * List all properties of a Verifiable Credential + */ +VerifiableCredentialBaseConstructor.getAllProperties = identifier => { + const vcDefinition = _.find(definitions, { identifier }); + if (vcDefinition) { + const allProperties = []; + _.forEach(vcDefinition.depends, ucaIdentifier => { + allProperties.push(...Claim.getAllProperties(ucaIdentifier)); + }); + const excludesProperties = []; + _.forEach(vcDefinition.excludes, ucaIdentifier => { + excludesProperties.push(...Claim.getAllProperties(ucaIdentifier)); + }); + return _.difference(allProperties, excludesProperties); + } + return null; +}; + +VerifiableCredentialBaseConstructor.VERIFY_LEVELS = VERIFY_LEVELS; +VerifiableCredentialBaseConstructor.nonCryptographicallySecureVerify = nonCryptographicallySecureVerify; +VerifiableCredentialBaseConstructor.cryptographicallySecureVerify = cryptographicallySecureVerify; +VerifiableCredentialBaseConstructor.requesterGrantVerify = requesterGrantVerify; + +module.exports = VerifiableCredentialBaseConstructor; \ No newline at end of file diff --git a/dist/cjs/creds/__mocks__/definitions.js b/dist/cjs/creds/__mocks__/definitions.js new file mode 100644 index 00000000..6112924d --- /dev/null +++ b/dist/cjs/creds/__mocks__/definitions.js @@ -0,0 +1,18 @@ +'use strict'; + +const definitions = [{ + identifier: 'civ:Credential:SimpleIdentity', + version: '1', + depends: ['civ:Identity:name', 'civ:Identity:DateOfBirth'] +}, { + identifier: 'civ:Credential:SimpleTest', + version: '1', + depends: ['civ:Identity:name', 'civ:Identity:DateOfBirth'] +}, { + identifier: 'civ:Credential:TestWithExcludes', + version: '1', + depends: ['civ:Identity:name', 'civ:Identity:DateOfBirth'], + excludes: ['civ:Identity:name.middle'] +}]; + +module.exports = definitions; \ No newline at end of file diff --git a/dist/cjs/creds/definitions.js b/dist/cjs/creds/definitions.js new file mode 100644 index 00000000..333a5cf7 --- /dev/null +++ b/dist/cjs/creds/definitions.js @@ -0,0 +1,68 @@ +'use strict'; + +/** + * name: 'attgenericId', + * name: 'attBaseIdentity', + * name: 'attAddress', + * @type {*[]} + */ +const definitions = [{ + identifier: 'credential-cvc:Email-v1', + version: '1', + depends: ['claim-cvc:Contact.email-v1'] +}, { + identifier: 'credential-cvc:PhoneNumber-v1', + version: '1', + depends: ['claim-cvc:Contact.phoneNumber-v1'] +}, { + identifier: 'credential-cvc:GenericDocumentId-v1', + version: '1', + depends: ['claim-cvc:Document.type-v1', 'claim-cvc:Document.number-v1', 'claim-cvc:Document.name-v1', 'claim-cvc:Document.gender-v1', 'claim-cvc:Document.issueLocation-v1', 'claim-cvc:Document.issueAuthority-v1', 'claim-cvc:Document.issueCountry-v1', 'claim-cvc:Document.placeOfBirth-v1', 'claim-cvc:Document.dateOfBirth-v1', 'claim-cvc:Document.address-v1', 'claim-cvc:Document.properties-v1', 'cvc:Document:image'] +}, { + identifier: 'credential-cvc:IdDocument-v1', + version: '1', + depends: ['claim-cvc:Document.type-v1', 'claim-cvc:Document.number-v1', 'claim-cvc:Document.name-v1', 'claim-cvc:Document.gender-v1', 'claim-cvc:Document.issueCountry-v1', 'claim-cvc:Document.placeOfBirth-v1', 'claim-cvc:Document.dateOfBirth-v1', 'claim-cvc:Document.dateOfExpiry-v1', 'claim-cvc:Document.nationality-v1', 'claim-cvc:Document.evidences-v1'], + required: ['claim-cvc:Document.type-v1', 'claim-cvc:Document.name-v1', 'claim-cvc:Document.dateOfBirth-v1', 'claim-cvc:Document.issueCountry-v1'] +}, { + identifier: 'credential-cvc:IdDocument-v2', + version: '1', + depends: ['claim-cvc:Document.type-v1', 'claim-cvc:Document.number-v1', 'claim-cvc:Document.name-v1', 'claim-cvc:Document.gender-v1', 'claim-cvc:Document.issueCountry-v1', 'claim-cvc:Document.placeOfBirth-v1', 'claim-cvc:Document.dateOfBirth-v1', 'claim-cvc:Document.dateOfExpiry-v1', 'claim-cvc:Document.nationality-v1', 'claim-cvc:Document.evidences-v1'], + required: ['claim-cvc:Document.type-v1', 'claim-cvc:Document.name-v1', 'claim-cvc:Document.dateOfBirth-v1', 'claim-cvc:Document.issueCountry-v1', 'claim-cvc:Document.evidences-v1'] +}, { + identifier: 'credential-cvc:LiveIdDocument-v1', + version: '1', + depends: ['claim-cvc:Document.type-v1', 'claim-cvc:Document.number-v1', 'claim-cvc:Document.name-v1', 'claim-cvc:Document.gender-v1', 'claim-cvc:Document.issueCountry-v1', 'claim-cvc:Document.placeOfBirth-v1', 'claim-cvc:Document.dateOfBirth-v1', 'claim-cvc:Document.dateOfExpiry-v1', 'claim-cvc:Document.nationality-v1', 'claim-cvc:Document.evidences-v1'], + required: ['claim-cvc:Document.type-v1', 'claim-cvc:Document.name-v1', 'claim-cvc:Document.dateOfBirth-v1', 'claim-cvc:Document.issueCountry-v1', 'claim-cvc:Document.evidences-v1'] +}, { + identifier: 'credential-cvc:Address-v1', + version: '1', + depends: ['claim-cvc:Identity.address-v1'] +}, { + identifier: 'credential-cvc:Identity-v1', + version: '1', + depends: ['claim-cvc:Identity.name-v1', 'claim-cvc:Identity.dateOfBirth-v1'] +}, { + identifier: 'credential-cvc:IDVaaS-v1', + version: '1', + depends: ['claim-cvc:Identity.name-v1', 'claim-cvc:Identity.dateOfBirth-v1', 'claim-cvc:Identity.address-v1', 'claim-cvc:Contact.email-v1', 'claim-cvc:SocialSecurity.number-v1', 'claim-cvc:Contact.phoneNumber-v1'] +}, { + identifier: 'credential-cvc:UnverifiedSsn-v1', + version: '1', + transient: true, + depends: ['claim-cvc:SocialSecurity.number-v1'] +}, { + identifier: 'credential-cvc:UnverifiedAddress-v1', + version: '1', + transient: true, + depends: ['claim-cvc:Identity.address-v1'] +}, { + identifier: 'credential-cvc:Covid19-v1', + version: '1', + depends: ['claim-cvc:Medical.covid19-v1'] +}, { + identifier: 'credential-alt:Identity-v1', + version: '1', + depends: ['claim-cvc:Identity.name-v1', 'claim-cvc:Identity.dateOfBirth-v1', 'claim-cvc:Identity.address-v1'] +}]; + +module.exports = definitions; \ No newline at end of file diff --git a/dist/cjs/errors/definitions.js b/dist/cjs/errors/definitions.js new file mode 100644 index 00000000..10674b71 --- /dev/null +++ b/dist/cjs/errors/definitions.js @@ -0,0 +1,446 @@ +'use strict'; + +/** + * Enum for ErrorCodes + * @readonly + * @enum { string } + */ +const ErrorCodes = { + + // IDV + // Manual Review Tool + /** + * Reason: Manual Review detected that the provided document is invalid. + * Troubleshooting: Make sure the provided document is a valid one. + */ + ERROR_IDV_MRT_INVALID_DOC: 'error.idv.mrt.invalid.doc', + + /** + * Reason: Manual Review detected that the provided document is unsupported. + * Troubleshooting: Make sure the provided document is a valid one. + */ + ERROR_IDV_MRT_UNSUPPORTED_DOC: 'error.idv.mrt.unsupported.doc', + + /** + * Reason: Manual Review detected that the provided utility is invalid. + * Troubleshooting: Make sure the provided utility is a valid one. + */ + ERROR_IDV_MRT_INVALID_UTILITY: 'error.idv.mrt.invalid.utility', + + /** + * Reason: Manual Review detected that the provided document scan has a low quality resolution. + * Troubleshooting: Make sure the provided document scan has a good resolution. + */ + ERROR_IDV_MRT_QUALITY: 'error.idv.mrt.quality', + + /** + * Reason: Manual Review detected that the provided document is expired. + * Troubleshooting: Make sure the provided document has a valid date of expiry. + */ + ERROR_IDV_MRT_EXPIRED: 'error.idv.mrt.expired', + + /** + * Reason: Manual Review detected that the provided document and photo don't have facial similiarity + * Troubleshooting: Make sure the provided document and photo have a good face similarity. + */ + ERROR_IDV_MRT_MISMATCH: 'error.idv.mrt.mismatch', + + /** + * Reason: Manual Review detected that the requirements fail. + * Troubleshooting: Make sure the provided document do fit the requirements. + */ + ERROR_IDV_MRT_REQUIREMENTS_FAIL: 'error.idv.mrt.requirements.fail', + + // Validation + /** + * Reason: The IDV detected that the provided document is invalid. + * Troubleshooting: Make sure the provided document is a valid one. + */ + ERROR_IDV_VALIDATION_INVALID_DOC: 'error.idv.validation.invalid.doc', + + /** + * Reason: The IDV detected that the provided phone is invalid. + * Troubleshooting: Make sure the provided phone is a valid one. + */ + ERROR_IDV_VALIDATION_INVALID_PHONE: 'error.idv.validation.invalid.phone', + + /** + * Reason: The IDV detected that the provided email is invalid. + * Troubleshooting: Make sure the provided email is a valid one. + */ + ERROR_IDV_VALIDATION_INVALID_EMAIL: 'error.idv.validation.invalid.email', + + /** + * Reason: The IDV detected that the provided document is unsupported. + * Troubleshooting: Make sure the provided document is a valid one. + */ + ERROR_IDV_VALIDATION_UNSUPPORTED_DOC: 'error.idv.validation.unsupported.doc', + + /** + * Reason: The IDV detected that the provided utility is invalid. + * Troubleshooting: Make sure the provided utility is a valid one. + */ + ERROR_IDV_VALIDATION_INVALID_UTILITY: 'error.idv.validation.invalid.utility', + + /** + * Reason: The IDV detected that the provided document scan has a low quality resolution. + * Troubleshooting: Make sure the provided document scan has a good resolution. + */ + ERROR_IDV_VALIDATION_QUALITY: 'error.idv.validation.quality', + + /** + * Reason: The IDV detected that the provided document is expired. + * Troubleshooting: Make sure the provided document has a valid date of expiry. + */ + ERROR_IDV_VALIDATION_EXPIRED: 'error.idv.validation.expired', + + /** + * Reason: The IDV detected that the provided document and photo don't have facial similiarity + * Troubleshooting: Make sure the provided document and photo have a good face similarity. + */ + ERROR_IDV_VALIDATION_MISMATCH: 'error.idv.validation.mismatch', + + /** + * Reason: The IDV detected that the provided document does not contain the user name. + * Troubleshooting: Make sure the provided document contains the user name. + */ + ERROR_IDV_VALIDATION_MISSING_NAME: 'error.idv.validation.missing.name', + + /** + * Reason: The IDV detected that the provided document does not contain the user date of birth. + * Troubleshooting: Make sure the provided document contains the user date of birth. + */ + ERROR_IDV_VALIDATION_MISSING_DOB: 'error.idv.validation.missing.dob', + + /** + * Reason: The IDV detected that the provided document does not contain the issuing country. + * Troubleshooting: Make sure the provided document contains the issuing country. + */ + ERROR_IDV_VALIDATION_MISSING_COUNTRY: 'error.idv.validation.missing.country', + + /** + * Reason: The IDV detected that the provided document does not contain a valid document type. + * Troubleshooting: Make sure the provided document contains a valid document type. + */ + ERROR_IDV_VALIDATION_MISSING_DOC_TYPE: 'error.idv.validation.missing.doc.type', + + /** + * Reason: The IDV detected that the requirements fail. + * Troubleshooting: Make sure the provided document do fit the requirements. + */ + ERROR_IDV_VALIDATION_REQUIREMENTS_FAIL: 'error.idv.validation.requirements.fail', + + /** + * Reason: The data provided by the user is not the same as the one that the IDV got from the document + * Troubleshooting: Make sure the provided data is equal to the data in the document. + */ + ERROR_IDV_VALIDATION_UCA_VALUE_MISMATCH: 'error.idv.validation.uca.value.mismatch', + + /** + * Reason: Missing required property when sending UCAs + * Troubleshooting: Make sure the provided UCA has all the required properties filled. + * Look at the UCA definition to make sure you provided all the values. + */ + ERROR_IDV_UCA_MISSING_PROPERTY: 'error.idv.uca.missing.property', + + /** + * Reason: UCA has no more retries remaining + * Troubleshooting: The maximum number of retries has reached. + * You must request a new credentialRequest and start over again + */ + ERROR_IDV_UCA_NO_RETRIES: 'error.idv.uca.no.retries', + + /** + * Reason: The process is in a final status "FAILED","COMPLETED" + * Troubleshooting: if you got a FINAL state error, + * you must request a new credentialRequest and start over again + */ + ERROR_IDV_PROCESS_HAS_FINAL_STATUS: 'error.idv.process.has.final.status', + + /** + * Reason: The UCA is in a final status + * Troubleshooting: Make sure to change the state of a UCA that is not in the final status. + * you must request a new credentialRequest and start over again + */ + ERROR_IDV_UCA_HAS_FINAL_STATUS: 'error.idv.uca.has.final.status', + + /** + * Reason: A UCA of the batch is in a final status + * Troubleshooting: Make sure to change the state of a UCA that is not in the final status. + */ + ERROR_IDV_UCA_BATCH_HAS_FINAL_STATUS: 'error.idv.uca.batch.has.final.status', + + /** + * Reason: The credentialItem is not valid/unknown to the IDV + * Troubleshooting: Make sure to provide the valid identifier of a credentialItem by checking the plan + */ + ERROR_IDV_CR_INVALID_CREDENTIAL_ITEM: 'error.idv.cr.invalid.credentialItem', + + /** + * Reason: The signature could not be verified + * Troubleshooting: Try to sign again a credential + */ + ERROR_IDV_CREDENTIAL_INVALID_SIGNATURE: 'error.idv.credential.invalid.signature', + + /** + * Reason: The credential has already been signed. + * Troubleshooting: The credential is already signed. You must not sign it again + */ + ERROR_IDV_CR_ALREADY_SIGNED: 'error.idv.cr.already.signed', + + /** + * Reason: The payload is missing a required property + * Troubleshooting: Make sure the payload of a credential contains all the required properties. + * In the error values will be suplied the missing properties + */ + ERROR_IDV_CR_MISSING_PROPERTY: 'error.idv.cr.missing.property', + + /** + * Reason: One of the external services required for phone number validation could not be reached (Authy, Twilio ) + * Troubleshooting: Try again later + */ + ERROR_IDV_UCA_SERVER: 'error.idv.uca.server', + + /** + * Reason: thrown if there are no UCAs in the process or if the UCA specified in the event is missing + * Troubleshooting: Make sure to provide the missing specified UCA + */ + ERROR_IDV_MISSING_UCA: 'error.idv.missing.uca', + + /** + * Reason: UCA is in a wrong version + * Troubleshooting: Make sure you're providing the UCA in the version declared on the plan + */ + ERROR_IDV_UCA_WRONG_VERSION: 'error.idv.uca.wrong.version', + + /** + * Reason: Could not find a validation plan for credential item + * Troubleshooting: Check if you're providing the right validation plan + * and credential item + */ + ERROR_IDV_MISSING_PLAN: 'error.idv.missing.plan', + + /** + * Reason: Could not find process with the provided ID + * Troubleshooting: Check if you're providing the right process id + */ + ERROR_IDV_MISSING_PROCESS: 'error.idv.missing.process', + + /** + * Reason: The value specified for a UCA isn't good for the UCA type + * Troubleshooting: Check the provided UCA value + */ + ERROR_IDV_UCA_BAD_VALUE: 'error.idv.uca.bad.value', + + /** + * Reason: The UCA doesn't have a status in the data store + * Troubleshooting: Try again + */ + ERROR_IDV_UCA_UPDATE_NO_STATUS: 'error.idv.uca.update.no.status', + + /** + * Reason: Unable to determine if the UCA can be updated, because the process it belongs to has no status + * Troubleshooting: Try again + */ + ERROR_IDV_UCA_UPDATE_NO_PROCESS_STATUS: 'error.idv.uca.update.no.process.status', + + /** + * Reason: A token is received before one is issued + * Troubleshooting: Try again + */ + ERROR_IDV_TOKEN_RECEIVED_BEFORE_ISSUE: 'error.idv.token.received.before.issue', + + /** + * Reason: Unable to send the token + * Troubleshooting: Try again + */ + ERROR_IDV_TOKEN_SENDING_FAILED: 'error.idv.token.sending.failed', + + /** + * Reason: The provided token is expired + * Troubleshooting: Request a new token + */ + ERROR_IDV_TOKEN_EXPIRED: 'error.idv.token.expired', + + /** + * Reason: The provided token does not match the generated one + * Troubleshooting: Make sure to provide the received token + */ + ERROR_IDV_TOKEN_MISMATCH: 'error.idv.token.mismatch', + + // CW ERRORS + + /** + * Reason: Thrown when CredentialWallet.validateDsr or CredentialWallet.fetch when a DSR is empty or invalid + * Troubleshooting: Check if the DSR provided is correct and it's not empty + */ + ERROR_CW_DSR_INVALID_SCOPE_REQUEST: 'error.dsr.invalid.scope.request', + + /** + * Reason: IDV has returned 'Bad request' anwser + * Troubleshooting: Check if the value of your UCA is correct or your request params + */ + ERROR_CW_IDV_INVALID_REQUEST: 'error.cw.idv.request.failed.generic.4XX', + + /** + * Reason: IDV has returned unexpected error + * Troubleshooting: Check the attached message + */ + ERROR_CW_IDV_ERROR: 'error.cw.idv.server.failed.generic.5XX', + + /** + * Reason: CW has returned unexpected error + * Troubleshooting: Check the attached message + */ + ERROR_CW_GENERIC: 'error.generic', + + /** + * Reason: DSR is missing 'eventURL' attribute + * Troubleshooting: Provide 'eventURL' attribute + */ + ERROR_CW_DSR_RESPONSE_MISSING_EVENT_URL: 'error.dsr.missing.event.url', + + /** + * Reason: eventType value is not a valid one + * Troubleshooting: Make sure you are providing one of the values: + * CANCELLED, VERIFYING', COMPLETED, + */ + ERROR_CW_DSR_RESPONSE_INVALID_EVENT_TYPE: 'error.dsr.invalid.event.type', + + /** + * Reason: No clientID found while calling LegacyService.getUploadDetails + * Troubleshooting: Make sure LegacyService.legacyDeviceRegistration is being called. + */ + ERROR_CW_CLIENT_ID_NOT_FOUND: 'client.id.not.found', + + /** + * Reason: No certificate found for UCA while calling LegacyService.getCertificatesFor + * Troubleshooting: Make sure there is a certificate saved on localStorage, key 'StorageScope.CERTIFICATE', + * for the related UCA. + */ + ERROR_CW_CERTIFICATE_NOT_FOUND: 'error.certificate.not.found', + + /** + * Reason: Unparsable certificate for UCA while calling getCertificatesFor + * Troubleshooting: Make sure there is a valid certificate saved on localStorage, key 'StorageScope.CERTIFICATE', + * for the related UCA. + */ + ERROR_CW_CERTIFICATE_UNPARSABLE: 'error.certificate.unparsable', + + /** + * Reason: Invalid operator when tried to 'constructHumanReadableForm'. + * Troubleshooting: Make sure the operator is one of the listed ones here: + * @see HumanReadableForm.convertSiftOperator + */ + ERROR_CW_WRONG_QUERY_OPERATOR_SCOPE_REQUEST: 'error.dsr.wrong.sift.operator', + + /** + * Reason: Could not verify credential during build dsr response. + * Troubleshooting: Unexpected error during verifying credential. Check logs and try again. + */ + ERROR_CW_VERIFY_CREDENTIAL: 'error.verify.credential', + + /** + * Reason: Legacy UCA identifier is not valid. + * Troubleshooting: must be one of the followings: + * 'credential-cvc:Email-v1' + * 'credential-cvc:PhoneNumber-v1' + * 'credential-cvc:GenericDocumentId-v1' + * 'credential-cvc:Address-v1' + * 'credential-cvc:Identity-v1' + */ + ERROR_CW_WRONG_UCA_IDENTIFIER: 'error.wrong.uca.identifier', + + /** + * Reason: Legacy Verifiable Credential identifier is not valid. + * Troubleshooting: must be one of the followings: + * 'credential-cvc:Email-v1' + * 'credential-cvc:PhoneNumber-v1' + * 'credential-cvc:GenericDocumentId-v1' + * 'credential-cvc:Address-v1' + * 'credential-cvc:Identity-v1' + */ + ERROR_CW_WRONG_VC_IDENTIFIER: 'error.wrong.credential.identifier', + + /** + * Reason: Verifiable Credential Request was not found. + * Troubleshooting: please check if the provided id is correct. + * Also, this happens only on 'IdvApiServiceLocal'. + * Make sure you want to use that implementation or the 'IdvApiService'. + * You can toggle implementation by setting the flag: disableLegacy = true + */ + ERROR_CW_VCR_NOT_FOUND: 'vcr.not.found', + + /** + * Reason: CredentialRequest is assigned with a wrong status. + * Troubleshooting: It must be either ACCEPTED or ISSUED. + * Also, this happens only on 'IdvApiServiceLocal'. + * Make sure you want to use that implementation or the 'IdvApiService'. + * You can toggle implementation by setting the flag: disableLegacy = true + */ + ERROR_CW_VCR_INVALID_STATE: 'vcr.invalid.state', + + /** + * Reason: Could not retrieve Credential from a Credential Request. + * Troubleshooting: Make sure the Credential Request is ready to check its status + */ + ERROR_CW_VCR_INVALID_CREDENTIAL: 'vcr.invalid.credential', + + /** + * Reason: Provided Credential Request is invalid. + * Troubleshooting: Make sure the provided Credential Request meets the following rules: + * - It's not null + * - Has a 'credentialRequest.idv' attribute + * - Has a 'credentialItem' attribute + * - 'credentialItem' attribute has an 'identifier' + */ + ERROR_CW_VCR_INVALID_REQUEST: 'vcr.invalid.request', + + /** + * Reason: idvService.patchSubjectCredentialRequest has returned null Credential Request + * Troubleshooting: Make sure the provided subject is correct + */ + ERROR_CW_VCR_ERROR_PATCH_SIGNED_SUBJECT: 'vcr.error.patch.signed.subject', + + /** + * Reason: Could not ensure DID extenal key during 'resolveMissingCredentials' + * Troubleshooting: Check the attached error + */ + ERROR_CW_KEY_MANAGER_CANT_ENSURE_KEY: 'key.manager.cant.ensure.key', + + /** + * Reason: Unexpected error during communication with CW backend + * Troubleshooting: Check the attached error + */ + ERROR_CW_NETWORK_GENERIC: 'error.network.generic', + + /** + * Reason: Unexpected error during communication with any endpoint that should be retried + * Troubleshooting: Retry the network call again + */ + ERROR_RETRYABLE_NETWORK_ERROR: 'error.retryable.network' + +}; + +/** + * Enum for ErrorContextTypes + * @readonly + * @enum { string } + */ +const ErrorContextTypes = { + MISSING_PROPERTY: 'missing_property', + UCA_STATE: 'uca_state', + UCA_VALUE: 'uca_value', + UCA_VERSION: 'uca_version', + PLAN_UCA_VERSION: 'plan_uca_version', + PROCESS_ID: 'process_id', + UCA_NAME: 'uca_name', + UCA_ID: 'uca_id', + CREDENTIAL_ITEM: 'credential_item', + UCA_ERROR: 'uca_error' +}; + +module.exports = { + ErrorCodes, + ErrorContextTypes +}; \ No newline at end of file diff --git a/dist/cjs/errors/idvErrors.js b/dist/cjs/errors/idvErrors.js new file mode 100644 index 00000000..8269d482 --- /dev/null +++ b/dist/cjs/errors/idvErrors.js @@ -0,0 +1,34 @@ +'use strict'; + +const _ = require('lodash'); +const { ErrorCodes, ErrorContextTypes } = require('./definitions'); + +// These codes are passed in the 'name' value of the error object when the IDV-toolkit +// throws an error +// @deprecated - left here for retrofit, use ErrorConstants instead for future versions +const IDVErrorCodes = _.pickBy(ErrorCodes, (v, k) => k.startsWith('ERROR_IDV')); + +/* +* IDVError parses a HTTP Error response body from the IDV-toolkit +* Usage: the IDVError can be instantiated directly from the HTTPResponse body e.g. +* const idvError = new IDVError(response.body); +* @param errorObj: parsed directly from the HTTP Response body which should contain +* message: human readable explanation of the error e.g. 'Missing required UCA fields' +* name: Error-Code, defined in IDVErrorCodes, e.g. IDVErrorCodes.ERROR_IDV_UCA_MISSING_PROPERTY +* data: an array of objects with { name: "name", value: "value" } properties e.g. +* [{ name: ErrorContextType.MISSING_PROPERTY, value: missingProperty }] +* @returns an instance of IDVError +* */ +class IDVError { + constructor(errorObj) { + this.message = errorObj.message; + this.errorCode = errorObj.name; + this.errorContext = errorObj.data; + } +} + +module.exports = { + IDVErrorCodes, + ErrorContextTypes, + IDVError +}; \ No newline at end of file diff --git a/dist/cjs/errors/index.js b/dist/cjs/errors/index.js new file mode 100644 index 00000000..c9e155b4 --- /dev/null +++ b/dist/cjs/errors/index.js @@ -0,0 +1,10 @@ +'use strict'; + +const idvErrors = require('./idvErrors'); +const { ErrorCodes, ErrorContextTypes } = require('./definitions'); + +module.exports = { + ErrorCodes, + ErrorContextTypes, + idvErrors // For retrofit, will be deprecated on the future +}; \ No newline at end of file diff --git a/dist/cjs/index.js b/dist/cjs/index.js new file mode 100644 index 00000000..d68a0c06 --- /dev/null +++ b/dist/cjs/index.js @@ -0,0 +1,35 @@ +'use strict'; + +const { Claim } = require('./claim/Claim'); +const VC = require('./creds/VerifiableCredential'); +const { initServices, services } = require('./services/index'); +const isValidGlobalIdentifier = require('./isValidGlobalIdentifier'); +const isClaimRelated = require('./isClaimRelated'); +const errors = require('./errors'); +const constants = require('./constants'); +const claimDefinitions = require('./claim/definitions'); +const credentialDefinitions = require('./creds/definitions'); +const aggregate = require('./AggregationHandler'); + +/** + * Entry Point for Civic Credential Commons + * @returns {CredentialCommons} + * @constructor + */ +function CredentialCommons() { + this.Claim = Claim; + this.VC = VC; + this.init = initServices; + this.isValidGlobalIdentifier = isValidGlobalIdentifier; + this.isClaimRelated = isClaimRelated; + this.services = services; + this.aggregate = aggregate; + this.errors = errors; + this.constants = constants; + this.claimDefinitions = claimDefinitions; + this.credentialDefinitions = credentialDefinitions; + return this; +} + +// to work with entry points in multi module manage the best way +module.exports = new CredentialCommons(); \ No newline at end of file diff --git a/dist/cjs/isClaimRelated.js b/dist/cjs/isClaimRelated.js new file mode 100644 index 00000000..af2c7d5b --- /dev/null +++ b/dist/cjs/isClaimRelated.js @@ -0,0 +1,41 @@ +'use strict'; + +const _ = require('lodash'); +const { definitions, Claim } = require('./claim/Claim'); +const vcDefinitions = require('./creds/definitions'); +/** + * Validate an claim path against it's parent UserCollectableAttribute, and the parent Claim against the + * dependencies of an Credential + * @param claim path, eg: name.first + * @param uca the global identifier for the UCA/Claim, eg: claim-civ:Identity:name-1 + * @param credential the parent identifier, eg: civ:Credential:GenericId + * @return true if the dependency exists and false if it doesn't + */ +function isClaimRelated(claim, uca, credential) { + // first get the UCA identifier + const ucaIdentifier = uca.substring(uca.indexOf('-') + 1, uca.lastIndexOf('-')); + // check on the credential commons if this identifier exists + const ucaDefinition = definitions.find(definition => definition.identifier === ucaIdentifier); + // does the UCA exist? + if (ucaDefinition) { + const ucaProperties = Claim.getAllProperties(ucaIdentifier); + + // does the claim exists in the Claim? + if (_.includes(ucaProperties, claim)) { + // we now have the composite uca, the uca for the claim property, they both are correct + // we need to check now the UCA is inside the dependencies of the credential refered as parent + const credentialDefinition = vcDefinitions.find(definition => definition.identifier === credential); + if (credentialDefinition) { + return _.includes(credentialDefinition.depends, ucaIdentifier); + } + throw new Error('Credential identifier does not exist'); + } else { + throw new Error('Claim property path does not exist on UCA definitions'); + } + } else { + // return error about wrong uca identifier + throw new Error('UCA identifier does not exist'); + } +} + +module.exports = isClaimRelated; \ No newline at end of file diff --git a/dist/cjs/isValidGlobalIdentifier.js b/dist/cjs/isValidGlobalIdentifier.js new file mode 100644 index 00000000..1140dbc6 --- /dev/null +++ b/dist/cjs/isValidGlobalIdentifier.js @@ -0,0 +1,40 @@ +'use strict'; + +const _ = require('lodash'); +const { definitions } = require('@identity.com/uca'); +const vcDefinitions = require('./creds/definitions'); +const claimDefinitions = require('./claim/definitions'); + +const validUCAIdentifiers = _.map(definitions, d => d.identifier); +const validClaimIdentifiers = _.map(claimDefinitions, d => d.identifier); +const validVCIdentifiers = _.map(vcDefinitions, d => d.identifier); +const validPrefixes = ['claim', 'credential']; + +function isValidGlobalIdentifier(identifier) { + const splited = _.split(identifier, '-'); + + if (splited.length !== 3) { + throw new Error('Malformed Global Identifier'); + } + + if (!_.includes(validPrefixes, splited[0])) { + throw new Error('Invalid Global Identifier Prefix'); + } + + switch (splited[0]) { + case 'claim': + if (!_.includes(validUCAIdentifiers, splited[1]) && !_.includes(validClaimIdentifiers, identifier)) { + throw new Error(`${identifier} is not valid`); + } + return true; + case 'credential': + if (!_.includes(validVCIdentifiers, splited[1]) && !_.includes(validVCIdentifiers, identifier)) { + throw new Error(`${identifier} is not valid`); + } + return true; + default: + return false; + } +} + +module.exports = isValidGlobalIdentifier; \ No newline at end of file diff --git a/dist/cjs/lib/crypto.js b/dist/cjs/lib/crypto.js new file mode 100644 index 00000000..2269ff8f --- /dev/null +++ b/dist/cjs/lib/crypto.js @@ -0,0 +1,9 @@ +'use strict'; + +const sjcl = require('sjcl'); + +const sha256 = stringToHash => sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(stringToHash)); + +module.exports = { + sha256 +}; \ No newline at end of file diff --git a/dist/cjs/logger.js b/dist/cjs/logger.js new file mode 100644 index 00000000..a65dd94e --- /dev/null +++ b/dist/cjs/logger.js @@ -0,0 +1,13 @@ +'use strict'; + +const { createLogger, format, transports } = require('winston'); + +// Configure the Winston logger. For the complete documentation see https://github.com/winstonjs/winston +const logger = createLogger({ + // To see more detailed errors, change this to 'debug' + level: 'info', + format: format.combine(format.splat(), format.simple()), + transports: [new transports.Console()] +}); + +module.exports = logger; \ No newline at end of file diff --git a/dist/cjs/schemas/generator/SchemaGenerator.js b/dist/cjs/schemas/generator/SchemaGenerator.js new file mode 100644 index 00000000..d9c29b71 --- /dev/null +++ b/dist/cjs/schemas/generator/SchemaGenerator.js @@ -0,0 +1,257 @@ +'use strict'; + +/* eslint-disable no-use-before-define */ +const _ = require('lodash'); +const randomString = require('randomstring'); +const Type = require('type-of-is'); +const RandExp = require('randexp'); +const { UserCollectableAttribute: UCA, definitions: ucaDefinitions } = require('@identity.com/uca'); +const { Claim, definitions, getBaseIdentifiers } = require('../../claim/Claim'); + +const DRAFT = 'http://json-schema.org/draft-07/schema#'; + +const getPropertyNameFromDefinition = definition => getBaseIdentifiers(definition.identifier).identifierComponents[2]; + +const getPropertyType = value => Type.string(value).toLowerCase(); + +const processObject = (object, outputParam, parentKey) => { + const output = outputParam || {}; + const objectProperties = object; + const { definition } = objectProperties; + delete objectProperties.definition; + + output.type = getPropertyType(objectProperties); + output.properties = output.properties || {}; + const keys = Object.entries(objectProperties); + + // too much debate on this eslint + // https://github.com/airbnb/javascript/issues/1122 + // eslint-disable-next-line no-restricted-syntax + for (const [key, value] of keys) { + // we have to get the required array from the definitions properties + + const type = getPropertyType(value); + if (type === 'object') { + output.properties[key] = processObject(value, output.properties[key], `${parentKey}.${key}`); + } else if (type === 'array') { + // recursion + // eslint-disable-next-line + output.properties[key] = processArray(value, output.properties[key], key); + } else { + output.properties[key] = {}; + output.properties[key].type = type === 'null' ? ['null', 'string'] : type; + if (definition && definition.type.properties) { + let propType = definition.type.properties.find(prop => prop.name === key); + // simple composite, one depth level civ:Identity.name for example + if (propType && propType.type.includes(':')) { + propType = definitions.find(def => def.identifier === propType.type); + } + + output.properties[key] = addMinimumMaximum(propType, output.properties[key]); + } else { + output.properties[key] = addMinimumMaximum(definition, output.properties[key]); + } + } + } + // it must be 4 here, we start the json of the VC with root + // then it's claim, then all standardize Claim are type:name + if (parentKey.includes('claim') && parentKey.split('.').length === 4) { + // with the json key of the claim + const baseUcaName = parentKey.substring('root.claim.'.length); + let typeName = (baseUcaName.substring(0, 1).toUpperCase() + baseUcaName.substring(1)).replace('.', ':'); + // regenerate uca + let refDefinition = definitions.find(def => def.identifier.includes(typeName)); + if (refDefinition == null) { + const baseName = baseUcaName.substring(0, 1).toUpperCase() + baseUcaName.substring(1); + typeName = `claim-cvc:${baseName}-v1`; + refDefinition = definitions.find(def => def.identifier.includes(typeName)); + } + if (refDefinition == null) { + typeName = `claim-cvc:${baseUcaName}-v1`; + refDefinition = definitions.find(def => def.identifier.includes(typeName)); + } + // get it's required definitions + output.required = refDefinition.type.required; + } + output.additionalProperties = false; + return output; +}; + +const processArray = (array, outputParam) => { + const output = outputParam || {}; + output.type = getPropertyType(array); + output.items = output.items || {}; + const type = getPropertyType(array[0]); + output.items.type = type; + output.additionalProperties = false; + return output; +}; + +/** + * Entry point of this class. Use this to generate an sample json data + * then an json schema from that data. That way you do not need to + * create sample or mocks json from Credentials + * + * @param definition Claim/VC definition + * @param json generated json + * @returns {{$schema: string}} expected json schema to validate this data + */ +const process = (definition, json) => { + const object = json; + const title = definition.identifier; + let processOutput; + const output = { + $schema: DRAFT + }; + output.title = title; + // Set initial object type + output.type = Type.string(object).toLowerCase(); + + // Process object + if (output.type === 'object') { + processOutput = processObject(object, {}, 'root'); + output.type = processOutput.type; + output.properties = processOutput.properties; + } + + // never allow additionalProperties + output.additionalProperties = false; + // Output + return output; +}; + +/** + * Build a sample json from an definition identifier + * Recursively make the Claim from nested properties and Claim references + * + * @param definition receive an Claim and build an sample json from it's properties + * @returns {{$schema: string}} + */ +const buildSampleJson = (definition, includeDefinitions = false) => { + let output = {}; + output = makeJsonRecursion(definition, includeDefinitions); + return output; +}; + +/** + * Recursion to build the schema from an json value + * @param ucaDefinition + */ +const makeJsonRecursion = (ucaDefinition, includeDefinitions = false) => { + let output = {}; + const typeName = Claim.getTypeName(ucaDefinition); + if (typeof ucaDefinition.type === 'object' && ucaDefinition.type.properties !== undefined) { + // array of properties + ucaDefinition.type.properties.forEach(property => { + output[property.name] = generateRandomValueForType(property, includeDefinitions); + }); + } else if (typeName === 'Array') { + const itemType = ucaDefinition.items.type; + const itemDefinition = _.find(definitions, { identifier: itemType }); + output = [makeJsonRecursion(itemDefinition, includeDefinitions)]; + } else if (typeName !== 'Object') { + // not a reference + const propertyName = getPropertyNameFromDefinition(ucaDefinition); + if (typeof ucaDefinition.pattern !== 'undefined' && ucaDefinition.pattern !== null) { + output[propertyName] = new RandExp(ucaDefinition.pattern).gen(); + } else { + output[propertyName] = generateRandomValueForType(ucaDefinition, includeDefinitions); + } + } else { + // a direct reference to a composite type + output = generateRandomValueForType(ucaDefinition, includeDefinitions); + } + if (includeDefinitions && output.definition == null) { + output.definition = ucaDefinition; + } + return output; +}; + +/** + * This method is an auxiliary method to allow random values to easy create + * json schemas from JSON values generated from Claim/VC + * + * @param definition + * @returns {number} + */ +const generateRandomNumberValueWithRange = definition => { + let genRandomNumber = Math.random() * 100; + + if (definition !== null) { + if (typeof definition.minimum !== 'undefined' && definition.minimum !== null && genRandomNumber < definition.minimum) { + genRandomNumber = definition.minimum; + } + + if (definition.exclusiveMinimum !== 'undefined' && definition.exclusiveMinimum !== null && genRandomNumber <= definition.exclusiveMinimum) { + genRandomNumber = definition.exclusiveMinimum + 0.1; + } + + if (typeof definition.maximum !== 'undefined' && definition.maximum !== null && genRandomNumber > definition.maximum) { + genRandomNumber = definition.maximum; + } + + if (definition.exclusiveMaximum !== 'undefined' && definition.exclusiveMaximum !== null && genRandomNumber >= definition.exclusiveMaximum) { + genRandomNumber = definition.exclusiveMaximum - 0.1; + } + } + + return genRandomNumber; +}; + +const generateRandomValueForType = (definition, includeDefinitions = false) => { + const typeName = definition.type; + let refDefinition = definition; + let resolvedTypeName = typeName; + if (typeName.includes(':')) { + // simple composite, one depth level civ:Identity.name for example + refDefinition = definitions.find(def => def.identifier === typeName); + if (refDefinition != null) { + resolvedTypeName = Claim.resolveType(refDefinition); + } else { + refDefinition = ucaDefinitions.find(def => def.identifier === typeName); + if (refDefinition) { + resolvedTypeName = UCA.resolveType(refDefinition); + } + } + } + // generate sample data + // that's why the magic numbers are here + switch (resolvedTypeName) { + case 'String': + if (refDefinition.enum) { + return _.values(refDefinition.enum)[0]; + } + return refDefinition && refDefinition.pattern ? new RandExp(refDefinition.pattern).gen() : randomString.generate(10); + case 'Number': + return generateRandomNumberValueWithRange(refDefinition); + case 'Boolean': + return Math.round(Math.random()) === 1; + default: + return makeJsonRecursion(refDefinition, includeDefinitions); + } +}; + +const addMinimumMaximum = (definition, object) => { + const output = object; + // for simple Claim get json schema properties + if (typeof definition !== 'undefined' && definition !== null) { + if (definition.exclusiveMinimum != null) { + output.exclusiveMinimum = definition.exclusiveMinimum; + } + + if (definition.minimum != null) { + output.minimum = definition.minimum; + } + + if (definition.exclusiveMaximum != null) { + output.exclusiveMaximum = definition.exclusiveMaximum; + } + + if (definition.maximum != null) { + output.maximum = definition.maximum; + } + } + return output; +}; + +module.exports = { process, buildSampleJson }; \ No newline at end of file diff --git a/dist/cjs/services/DefaultAnchorServiceImpl.js b/dist/cjs/services/DefaultAnchorServiceImpl.js new file mode 100644 index 00000000..c57db253 --- /dev/null +++ b/dist/cjs/services/DefaultAnchorServiceImpl.js @@ -0,0 +1,162 @@ +'use strict'; + +function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + +/** + * Current Anchor/Attester service + * + */ +const uuid = require('uuid/v4'); +const { HDNode, ECSignature } = require('bitcoinjs-lib'); +const sjcl = require('sjcl'); +const logger = require('../logger'); + +/** + * An Anchor/Attester implementation + * + * @param {*} config + * @param {*} http + */ +function DummyAnchorServiceImpl(config, http) { + var _this = this; + + this.config = config; + this.http = http; + const pollService = (() => { + var _ref = _asyncToGenerator(function* (statusUrl) { + try { + const attestation = yield _this.http.request({ + url: statusUrl, + method: 'GET', + simple: true, + json: true + }); + + if (!attestation || !attestation.type) { + // eslint-disable-next-line no-unused-vars + return yield pollService(statusUrl); + } + if (attestation && attestation.type !== 'permanent') { + attestation.statusUrl = statusUrl; + return attestation; + } + return attestation; + } catch (error) { + logger.error(`Error polling: ${statusUrl}`, JSON.stringify(error, null, 2)); + throw new Error(`Error polling: ${statusUrl}`); + } + }); + + return function pollService(_x) { + return _ref.apply(this, arguments); + }; + })(); + + this.anchor = (() => { + var _ref2 = _asyncToGenerator(function* (options = {}) { + return Promise.resolve({ + subject: { + pub: 'xpub:dummy', + label: options.subject && options.subject.label ? options.subject.label : null, + data: options.subject && options.subject.data ? options.subject.data : null, + signature: 'signed:dummy' + }, + walletId: 'none', + cosigners: [{ + pub: 'xpub:dummy' + }, { + pub: 'xpub:dummy' + }], + authority: { + pub: 'xpub:dummy', + path: '/' + }, + coin: 'dummycoin', + tx: uuid(), + network: 'dummynet', + type: 'temporary', + civicAsPrimary: false, + schema: 'dummy-20180201' + }); + }); + + return function () { + return _ref2.apply(this, arguments); + }; + })(); + + this.update = (() => { + var _ref3 = _asyncToGenerator(function* (tempAnchor) { + tempAnchor.type = 'permanent'; // eslint-disable-line + tempAnchor.value = new uuid(); // eslint-disable-line + return Promise.resolve(tempAnchor); + }); + + return function (_x2) { + return _ref3.apply(this, arguments); + }; + })(); + + this.verifySignature = (proof, pinnedPubKey) => { + const { subject } = proof.anchor; + const anchorSubjectValidation = this.verifySubjectSignature(subject, pinnedPubKey); + return anchorSubjectValidation && subject.data === proof.merkleRoot; + }; + + /** + * This method checks if the subject signature matches the pub key + * @param subject a json with label, data, signature, pub + * @returns {*} true or false for the validation + */ + this.verifySubjectSignature = (subject, pinnedPubKey) => { + // Do not use JS destruct on the next line, We need to predict the JSON order + const toHash = JSON.stringify({ xpub: subject.pub, label: subject.label, data: subject.data }); + const hash = sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(toHash)); + const subjectSignature = ECSignature.fromDER(Buffer.from(subject.signature, 'hex')); + return HDNode.fromBase58(pinnedPubKey || subject.pub).keyPair.verify(Buffer.from(hash, 'hex'), subjectSignature); + }; + + /** + * This method checks that the attestation / anchor exists on the BC + */ + this.verifyAttestation = (() => { + var _ref4 = _asyncToGenerator(function* (proof, offline = true) { + const path = '/proof'; + const endpoint = `${_this.config.attestationService}${path}`; + + const requestOptions = { + url: endpoint, + body: { attestation: proof.anchor, offline }, + method: 'POST', + json: true, + simple: true // reject if not 2XX + }; + + const response = yield _this.http.request(requestOptions); + return response.valid; + }); + + return function (_x3) { + return _ref4.apply(this, arguments); + }; + })(); + + this.revokeAttestation = (() => { + var _ref5 = _asyncToGenerator(function* (signature) { + signature.revoked = true; // eslint-disable-line + return Promise.resolve(signature); + }); + + return function (_x4) { + return _ref5.apply(this, arguments); + }; + })(); + + this.isRevoked = signature => signature.revoked ? signature.revoked : false; + + return this; +} + +module.exports = { + CurrentCivicAnchor: DummyAnchorServiceImpl +}; \ No newline at end of file diff --git a/dist/cjs/services/DummyAnchorServiceImpl.js b/dist/cjs/services/DummyAnchorServiceImpl.js new file mode 100644 index 00000000..70647746 --- /dev/null +++ b/dist/cjs/services/DummyAnchorServiceImpl.js @@ -0,0 +1,134 @@ +'use strict'; + +function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + +/** + * Current Anchor/Attester service + * + */ +const uuid = require('uuid/v4'); +const logger = require('../logger'); + +/** + * An Anchor/Attester implementation + * + * @param {*} config + * @param {*} http + */ +function DummyAnchorServiceImpl(config, http) { + var _this = this; + + this.config = config; + this.http = http; + const pollService = (() => { + var _ref = _asyncToGenerator(function* (statusUrl) { + try { + const attestation = yield _this.http.request({ + url: statusUrl, + method: 'GET', + simple: true, + json: true + }); + + if (!attestation || !attestation.type) { + // eslint-disable-next-line no-unused-vars + return yield pollService(statusUrl); + } + if (attestation && attestation.type !== 'permanent') { + attestation.statusUrl = statusUrl; + return attestation; + } + return attestation; + } catch (error) { + logger.error(`Error polling: ${statusUrl}`, JSON.stringify(error, null, 2)); + throw new Error(`Error polling: ${statusUrl}`); + } + }); + + return function pollService(_x) { + return _ref.apply(this, arguments); + }; + })(); + + this.anchor = (() => { + var _ref2 = _asyncToGenerator(function* (options = {}) { + return Promise.resolve({ + subject: { + pub: 'xpub:dummy', + label: options.subject && options.subject.label ? options.subject.label : null, + data: options.subject && options.subject.data ? options.subject.data : null, + signature: 'signed:dummy' + }, + walletId: 'none', + cosigners: [{ + pub: 'xpub:dummy' + }, { + pub: 'xpub:dummy' + }], + authority: { + pub: 'xpub:dummy', + path: '/' + }, + coin: 'dummycoin', + tx: new uuid(), // eslint-disable-line + network: 'dummynet', + type: 'temporary', + civicAsPrimary: false, + schema: 'dummy-20180201' + }); + }); + + return function () { + return _ref2.apply(this, arguments); + }; + })(); + + this.update = (() => { + var _ref3 = _asyncToGenerator(function* (tempAnchor) { + // eslint-disable-next-line no-param-reassign + tempAnchor.type = 'permanent'; + // eslint-disable-next-line no-param-reassign + tempAnchor.value = uuid(); + return Promise.resolve(tempAnchor); + }); + + return function (_x2) { + return _ref3.apply(this, arguments); + }; + })(); + + this.verifySignature = () => true; + + /** + * This method checks if the subject signature matches the pub key + * @returns {*} true or false for the validation + */ + this.verifySubjectSignature = () => true; + + /** + * This method checks that the attestation / anchor exists on the BC + */ + this.verifyAttestation = _asyncToGenerator(function* () { + return true; + }); + + this.revokeAttestation = (() => { + var _ref5 = _asyncToGenerator(function* (signature) { + // eslint-disable-next-line no-param-reassign + signature.revoked = true; + return Promise.resolve(signature); + }); + + return function (_x3) { + return _ref5.apply(this, arguments); + }; + })(); + + this.isRevoked = signature => signature.revoked ? signature.revoked : false; + + return this; +} + +module.exports = { + CurrentCivicAnchor: DummyAnchorServiceImpl +}; \ No newline at end of file diff --git a/dist/cjs/services/MiniCryptoManagerImpl.js b/dist/cjs/services/MiniCryptoManagerImpl.js new file mode 100644 index 00000000..23f20484 --- /dev/null +++ b/dist/cjs/services/MiniCryptoManagerImpl.js @@ -0,0 +1,83 @@ +'use strict'; + +const { HDNode, ECSignature } = require('bitcoinjs-lib'); + +/** + * MiniCryptoManagerImpl - A minimal CryptoManagerImpl for the portable CryptoManagerInterface + * to provide only default sign() and verify() functions to credential-commons with minimal dependencies. + * + * Particularities of this Mini Implementation: + * + * 1. Only sign() and verify() function are available; + * + * 2. This implementation is based on HDNode key material from bitcoinjs library; + * + * 3. There is a volatile in memory only Storage Implementation to allow `installKey()`. + * You should `installKey` a PVT key or a PUB key (verify only) before call `sign()` or `verify()`. + * The installed key is removed after `sign()` or `verify()` function was called. + */ +class MiniCryptoManagerImpl { + constructor() { + this.KEY_STORAGE = {}; + } + + /** + * Install a pvt or a pub key on a keyName to be used on `sign()` or `verify()` function later. + * @param {} keyName - name of the key to be installed. + * @param {} key - a pvt or a pub key in base58 format. + */ + installKey(keyName, key) { + try { + // Test if key is a valid HDNode key + HDNode.fromBase58(key); + this.KEY_STORAGE[keyName] = key; + } catch (err) { + throw new Error(`Invalid key format: ${err.message}`); + } + } + + /** + * Return input data signed using the specified key. + * + * Signature return value will be to be a DER encoded value. + * + * @param { string } keyName - name of the key to be used to sign. + * @param { string } hexHash - hex string representation of the hash + */ + sign(keyName, hexHash) { + const privateKey = this.KEY_STORAGE[keyName]; + const keyPair = HDNode.fromBase58(privateKey); + + const hash = Buffer.from(hexHash, 'hex'); + const signature = keyPair.sign(hash); + const hexSignature = signature.toDER().toString('hex'); + + // keys are volatile in this impl, removes + delete this.KEY_STORAGE[keyName]; + + return hexSignature; + } + + /** + * Return true if signature has been verified, false otherwise. + * + * @param { string } keyName - name of the key to be used to verify signature. + * @param { string } hexHash - hex string representation of the hash + * @param { string } hexSignature - DER encoded signature. + */ + verify(keyName, hexHash, hexSignature) { + const key = this.KEY_STORAGE[keyName]; + const keyPair = HDNode.fromBase58(key); + + const hash = Buffer.from(hexHash, 'hex'); + const signature = Buffer.from(hexSignature, 'hex'); + const ecSignature = ECSignature.fromDER(signature); + + // keys are volatile in this impl, removes + delete this.KEY_STORAGE[keyName]; + + return keyPair.verify(hash, ecSignature); + } +} + +module.exports = MiniCryptoManagerImpl; \ No newline at end of file diff --git a/dist/cjs/services/__mocks__/httpService.js b/dist/cjs/services/__mocks__/httpService.js new file mode 100644 index 00000000..0a616eb4 --- /dev/null +++ b/dist/cjs/services/__mocks__/httpService.js @@ -0,0 +1,80 @@ +'use strict'; + +function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + +/* eslint-disable max-len */ + +const _ = require('lodash'); +const logger = require('../../logger'); + +function HttpServiceConstructor() { + this.name = 'mockHttp'; + this.request = (() => { + var _ref = _asyncToGenerator(function* (uri, options) { + logger.debug(`Mocking request for: ${JSON.stringify({ uri, options }, null, 2)}`); + const params = _.isString(uri) ? { url: uri } : uri; + _.assign(params, options); + const responses = [{ + path: '/registry', + response: { + clientID: '6e0ce9b31eb13064a194c1482ed3d9d330f22df6fb4cbcc0dbebf3169dc2325b', + xpub: '0469919359510a703516503299c77ef0e00f18255a32db19a3e69636e203f25f29be24b685df9f8a70548751f53a2e4c235ec0fbdc82d0783bd30e315ebfd6bd1e', + cas: '{"iv":"TEtgZuJdyJFkgcuHoBC52w==","v":1,"iter":10000,"ks":128,"ts":64,"mode":"gcm","adata":"","cipher":"aes","salt":"SA0z5h6IlfA=","ct":"8h6ys3fD31HsWH3s5rrbF6o54ekJf6owhSJBW6FBIhkftJWSWVWVEt0u0FJFqhCqPaEl+DMM6olH9fAcB7bD7i2DRPjLYiC+"}', + sak: {} + } + }, { + path: '/jwt', + response: { jwt: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJqdGkiOiIyYzdlNjQ4YS1hNDhmLTQxNTgtOGZmMS02MTY0YzM5OWNlNDMiLCJpYXQiOjE1Mjg4MjE1ODUuNDM0LCJleHAiOjE1Mjg4MjE3NjUuNDM0LCJpc3MiOiJodHRwczovL2FwaS5jaXZpYy5jb20vand0IiwiYXVkIjoiQXR0ZXN0ZXJTZXJ2aWNlIiwic3ViIjoiYzhhNjRhODE4NWRlMzNkMTlkZTgwMjFmYmUyMjhkMmE1YTc3YzExMTdkYjc1NDJlZDE0ODM1NGNiZjdkNGVmMSIsImRhdGEiOnsibWV0aG9kIjoiUE9TVCIsInBhdGgiOiJodHRwczovL2Rldi5hcGkuY2l2aWMuY29tL3JlcXVlc3QtYXR0ZXN0YXRpb24tdGJjaC9yZXF1ZXN0QXR0ZXN0YXRpb24ifX0.2Rp8XLTLvzu51raTQRpce8kIiilsMeiPZeWAsuNv5n7hFZGl-ce-fx9DgxsZ0OTaIUgo8frbiGmHjQh0WlUG7A' } + }, { + path: '/requestAttestation', + response: { statusUrl: '/status/372091f0-6e5f-11e8-ab04-8d6f9c9b4e5a' } + }, { + path: '/requestAttestation', + response: { statusUrl: '/status/372091f0-6e5f-11e8-ab04-8d6f9c9b4e5a' } + }, { + path: '/status', + response: { + schema: 'dummy-20180201', + tx: '01000000018815822815dbd6c355ad47af5d753a00000000fc00473044022042426820da1f2fac328a408d538638143177168b575da66825bc99a3f487472baa0751b67355407b4a4e99da04a3186c520220578b820dd051c919c2fb57b26aa29667483b547f6766a23e3c821e47a5d1237b0147304402201316cc0ee8a968f4d86a616fcf710b663e0bb7021e95d7a300036b65e95ca34602204f05162db06278af2a8abdd7ab4d92e973dc4154a92bf37a4056f3298fa9ecad014c695221028f9205846d9b23dd9a17588ae13603aa3eda3599582750904716c827d02269db210340f8f56a56b2af2a9698f66574882068cf8bd8fa95a26136ac34edabfe5eb5d021029d52d336232eb3d4f37730822df9d3993a84c3edba20f14d3ee0f20141c0bdfd53aeffffffff01551500000000000017a91460312cbbb8ec560305a239d56398f0d8aa57ecf68700000000', + subject: { + label: 'teste', + pub: 'xpub:dummy', + data: 'testesdsd', + signature: '304502210089e94f11587bf7fa202817ace9664639855a146565d4e54b9f853f31f4d7ce31022077098a904e0dda7ab947db92a3e7dd7a5d52654c286151c3cc97feb0ef4a3310' + }, + authority: { + pub: 'xpub:dummy', + path: '/' + }, + cosigners: [{ + pub: 'xpub:dummy' + }, { + pub: 'xpuv:dummy' + }], + type: 'temporary', + network: 'testnet' + } + + }]; + const res = _.find(responses, function (r) { + return _.includes(params.url, r.path); + }); + if (res) { + return Promise.resolve(res.response); + } + return Promise.reject(); + }); + + return function (_x, _x2) { + return _ref.apply(this, arguments); + }; + })(); + return this; +} + +logger.debug('Using Mock HTTP Service'); +const http = new HttpServiceConstructor(); +http.request('/status').then(console.log); // eslint-disable-line +logger.debug(`HTTP Service instance ${JSON.stringify(http, null, 2)}`); + +module.exports = http; \ No newline at end of file diff --git a/dist/cjs/services/anchorService.js b/dist/cjs/services/anchorService.js new file mode 100644 index 00000000..cba30fc7 --- /dev/null +++ b/dist/cjs/services/anchorService.js @@ -0,0 +1,20 @@ +"use strict"; + +/** + * Abstract Anchor/Attestation service + * + * @param {*} impl + */ +function Anchor(impl) { + this.impl = impl; + this.anchor = (label, data, options) => this.impl.anchor(label, data, options); + this.update = tempAnchor => this.impl.update(tempAnchor); + this.verifySignature = subject => this.impl.verifySignature(subject); + this.verifySubjectSignature = subject => this.impl.verifySubjectSignature(subject); + this.verifyAttestation = signature => this.impl.verifyAttestation(signature); + this.revokeAttestation = signature => this.impl.revokeAttestation(signature); + this.isRevoked = signature => this.impl.isRevoked(signature); + return this; +} + +module.exports = Anchor; \ No newline at end of file diff --git a/dist/cjs/services/config.js b/dist/cjs/services/config.js new file mode 100644 index 00000000..06c07403 --- /dev/null +++ b/dist/cjs/services/config.js @@ -0,0 +1,50 @@ +'use strict'; + +const path = require('path'); +const os = require('os'); +const fs = require('fs'); + +const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined'; + +if (process.platform === 'win32') throw new Error(`Unsupported platform: ${process.platform}`); + +if (process.env.APP_ENV !== 'browser' && !isBrowser) { + const CONFIG_FILE = 'config'; + + const CONFIG_PATH = { + BOX: '/etc/civic', + USER: path.join(`${os.homedir()}`, '.civic') + }; + + const userConfigFile = path.join(CONFIG_PATH.USER, CONFIG_FILE); + const boxConfigFile = path.join(CONFIG_PATH.BOX, CONFIG_FILE); + + const configFile = fs.existsSync(userConfigFile) ? userConfigFile : boxConfigFile; + + /* eslint-disable global-require */ + if (fs.existsSync(userConfigFile)) { + require('dotenv').config({ + path: configFile + }); + } + /* eslint-ebable global-require */ +} + +const config = { + sipSecurityService: process.env.CIVIC_SEC_URL, + attestationService: process.env.CIVIC_ATTN_URL, + clientConfig: { + id: process.env.CIVIC_CLIENT_ID, + signingKeys: { + hexpub: process.env.CIVIC_CLIENT_XPUB, + hexsec: process.env.CIVIC_CLIENT_XPRV + } + }, + passphrase: process.env.CIVIC_PASSPHRASE, + keychain: { prv: process.env.CIVIC_KEYCHAIN }, + accessToken: process.env.CLIENT_ACCESS_TOKEN, + walletId: process.env.CLIENT_WALLET_ID, + walletPassphrase: process.env.CLIENT_WALLET_PASSPHRASE +}; + +module.exports = config; \ No newline at end of file diff --git a/dist/cjs/services/httpService.js b/dist/cjs/services/httpService.js new file mode 100644 index 00000000..12580b16 --- /dev/null +++ b/dist/cjs/services/httpService.js @@ -0,0 +1,26 @@ +'use strict'; + +function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } + +/** + * A simple node HTTP services + */ +const request = require('request-promise-native'); +// uncomment to debug requests +// require('request-debug')(request); + +function HttpServiceConstructor() { + this.request = (() => { + var _ref = _asyncToGenerator(function* (uri, options) { + const response = yield request(uri, options); + return response; + }); + + return function (_x, _x2) { + return _ref.apply(this, arguments); + }; + })(); + return this; +} + +module.exports = HttpServiceConstructor; \ No newline at end of file diff --git a/dist/cjs/services/index.js b/dist/cjs/services/index.js new file mode 100644 index 00000000..9153b3a3 --- /dev/null +++ b/dist/cjs/services/index.js @@ -0,0 +1,58 @@ +'use strict'; + +/** + * Services IoC modules + */ +const Bottle = require('bottlejs'); +const { CurrentCivicAnchor } = require('./DefaultAnchorServiceImpl.js'); +const logger = require('../logger'); +const HttpServiceConstructor = require('./httpService'); +const config = require('./config'); +const SecureRandom = require('../SecureRandom'); +const MiniCryptoManagerImpl = require('./MiniCryptoManagerImpl'); + +const services = new Bottle(); + +/** + * Init services with new values to config and http services + * @param {*} conf + * @param {*} http + * @param secureRandom + */ +const initServices = (conf, http, secureRandom, cryptoManagerImpl) => { + if (http) { + services.resetProviders(['Http']); + logger.debug('Registering custom HTTP service implementation'); + services.factory('Http', () => http); + } + if (conf) { + services.resetProviders(['Config']); + logger.debug('Registering custom Config service implementation'); + services.factory('Config', () => conf); + } + if (secureRandom) { + services.resetProviders(['SecureRandom']); + logger.debug('Registering custom SecureRandom service implementation'); + services.factory('SecureRandom', () => secureRandom); + } + if (cryptoManagerImpl) { + services.resetProviders(['CryptoManager']); + logger.debug('Registering custom CryptoManager service implementation'); + services.factory('CryptoManager', () => cryptoManagerImpl); + } + return services; +}; + +services.factory('Config', () => config); + +logger.info('Registering request-promise-native as Http service implementation.'); +services.service('Http', HttpServiceConstructor); + +services.factory('SecureRandom', () => new SecureRandom()); + +services.service('AnchorService', CurrentCivicAnchor, 'Config', 'Http'); + +// The default CryptoManager Implementation +services.service('CryptoManager', MiniCryptoManagerImpl); + +module.exports = { services, initServices }; \ No newline at end of file diff --git a/dist/cjs/timeHelper.js b/dist/cjs/timeHelper.js new file mode 100644 index 00000000..85646d00 --- /dev/null +++ b/dist/cjs/timeHelper.js @@ -0,0 +1,37 @@ +'use strict'; + +const moment = require('moment-mini'); + +const unitMapper = { + y: 'y', + m: 'M', + w: 'w', + d: 'd' +}; + +/** + * Convert a delta string like "21y" to a moment Duration object + * @param delta + * @return {moment.Duration} + */ +const timeDeltaToMomentDuration = delta => { + const matched = delta.match(/(-?\d+)(\w)/); + + if (!matched) throw new Error(`Invalid time delta ${delta}`); + + const [, amount, unit] = matched; + + return moment.duration(parseInt(amount, 10), unitMapper[unit]); +}; + +/** + * Given a time delta like "-21y", apply it to the passed in date object, or the current time + * @param delta String + * @param date Date + * @return {Date} + */ +const applyDeltaToDate = (delta, date = new Date()) => moment(date).add(timeDeltaToMomentDuration(delta)).toDate(); + +module.exports = { + applyDeltaToDate +}; \ No newline at end of file diff --git a/dist/es/AggregationHandler.js b/dist/es/AggregationHandler.js new file mode 100644 index 00000000..10f53b69 --- /dev/null +++ b/dist/es/AggregationHandler.js @@ -0,0 +1,66 @@ +const _ = require('lodash'); + +const validateEmptyParametersOperators = parameters => { + if (!_.isEmpty(parameters)) { + throw new Error('parameters should be empty'); + } + return true; +}; +const validateNotEmptyParametersOperators = parameters => { + if (!parameters && _.isEmpty(parameters)) { + throw new Error('parameters should not be empty'); + } + return true; +}; +const validatePathParametersOperators = parameters => { + if (!_.isString(parameters)) { + throw new Error('parameters should be string'); + } + return true; +}; +const validateNumberParametersOperators = parameters => { + if (!_.isNumber(parameters)) { + throw new Error('parameters should be number'); + } + return true; +}; +const validateObjectParametersOperators = parameters => { + if (!_.isObject(parameters)) { + throw new Error('parameters should be object'); + } + return true; +}; + +const sort = (colllection, params) => { + const path = _.keys(params)[0]; + const order = params[path]; + const ordered = _.sortBy(colllection, path); + return order === 'ASC' ? ordered : _.reverse(ordered); +}; + +const AGGREGATION_OPERATORS_MAP = { + none: (collection, params) => validateEmptyParametersOperators(params) ? [...collection] : null, + $limit: (collection, params) => validateNumberParametersOperators(params) ? [..._.slice(collection, 0, params)] : null, + $min: (collection, params) => validatePathParametersOperators(params) ? [_.minBy(collection, params)] : null, + $max: (collection, params) => validatePathParametersOperators(params) ? [_.maxBy(collection, params)] : null, + $first: (collection, params) => validateNotEmptyParametersOperators(params) ? [_.first(collection)] : null, + $last: (collection, params) => validateNotEmptyParametersOperators(params) ? [_.last(collection)] : null, + $sort: (collection, params) => validateObjectParametersOperators(params) ? [...sort(collection, params)] : null +}; + +function aggregate(credentials, stages) { + let filtered = [...credentials]; + _.forEach(stages, stage => { + const operator = _.keys(stage)[0]; + + if (!_.includes(_.keys(AGGREGATION_OPERATORS_MAP), operator)) { + throw new Error(`Invalid operator: ${operator}`); + } + const params = stage[operator]; + const operatorImplementation = AGGREGATION_OPERATORS_MAP[operator]; + filtered = operatorImplementation(filtered, params); + }); + return filtered; +} + +module.exports = aggregate; \ No newline at end of file diff --git a/dist/es/SecureRandom.js b/dist/es/SecureRandom.js new file mode 100644 index 00000000..7d560a04 --- /dev/null +++ b/dist/es/SecureRandom.js @@ -0,0 +1,40 @@ +const sjcl = require('sjcl'); +const logger = require('./logger'); + +class SecureRandom { + constructor(seedHexString) { + logger.debug('Init Secure Random'); + // eslint-disable-next-line new-cap + this.sjclRandom = new sjcl.prng(10); + + if (seedHexString) { + const seed = sjcl.codec.hex.toBits(seedHexString); + this.sjclRandom.addEntropy(seed, undefined, 'csprng'); + this.isSeeded = true; + } else { + try { + logger.debug('Trying crypto'); + /* eslint-disable global-require */ + const hexString = require('crypto').randomBytes(1024).toString('hex'); + /* eslint-enable global-require */ + const seed = sjcl.codec.hex.toBits(hexString); + this.sjclRandom.addEntropy(seed, undefined, 'csprng'); + this.isSeeded = true; + } catch (error) { + logger.warn(`Crypto: ${error}`); + this.isSeeded = false; + } + } + } + + wordWith(size) { + if (!this.isSeeded) { + throw new Error("Can't user SecureRandom before seeding"); + } + + const randomBytes = this.sjclRandom.randomWords(size / 8, 10); + return sjcl.codec.hex.fromBits(randomBytes); + } +} + +module.exports = SecureRandom; \ No newline at end of file diff --git a/dist/es/claim/Claim.js b/dist/es/claim/Claim.js new file mode 100644 index 00000000..c62a2e26 --- /dev/null +++ b/dist/es/claim/Claim.js @@ -0,0 +1,363 @@ +const _ = require('lodash'); +const sjcl = require('sjcl'); +const { UserCollectableAttribute } = require('@identity.com/uca'); +const definitions = require('./definitions'); +const { services } = require('../services'); + +const validIdentifiers = _.map(definitions, d => d.identifier); + +const getDefinition = (identifier, version) => version ? _.find(definitions, { identifier, version }) : _.find(definitions, { identifier }); + +const isArrayAttestableValue = aValue => aValue.indexOf('[') > -1 && aValue.indexOf(']') > -1; + +function getBaseIdentifiers(identifier) { + const claimRegex = /claim-cvc:(.*)\.(.*)-v\d*/; + let isNewIdentifier = true; + + let identifierComponents = claimRegex.exec(identifier); + if (identifierComponents === null) { + identifierComponents = _.split(identifier, ':'); + isNewIdentifier = false; + } + return { identifierComponents, isNewIdentifier }; +} + +function adaptIdentifierIfNeeded(identifier, version) { + const definition = getDefinition(identifier, version); + const resolvedIdentifier = definition && definition.alias ? definition.type : identifier; + + const { isNewIdentifier, identifierComponents } = getBaseIdentifiers(resolvedIdentifier); + + if (!isNewIdentifier && !getDefinition(resolvedIdentifier, version)) { + const newIdentifier = `claim-cvc:${identifierComponents[1]}.${identifierComponents[2]}-v1`; + const foundNewIdentifier = _.find(definitions, { identifier: newIdentifier }); + if (foundNewIdentifier) { + return newIdentifier; + } + throw new Error(`${resolvedIdentifier} is not defined`); + } + return identifier; +} + +class Claim extends UserCollectableAttribute { + constructor(identifier, value, version) { + const currentIdentifier = adaptIdentifierIfNeeded(identifier, version); + super(currentIdentifier, value, version, definitions); + this.initialize(currentIdentifier, value, version); + } + + initialize(identifier, value, version) { + super.initialize(identifier, value, version); + if (!this.salt) { + const secureRandom = services.container.SecureRandom; + this.salt = sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(secureRandom.wordWith(64))); + } + } + + initializeValuesWithArrayItems(identifier, values, version) { + const definition = getDefinition(this.identifier, this.version); + const ucaArray = []; + + if (!_.isArray(values)) throw new Error(`Value for ${identifier}-${version} should be an array`); + + _.forEach(values, value => { + const claim = new Claim(_.get(definition, 'items.type'), value); + ucaArray.push(claim); + }); + + this.value = ucaArray; + } + + initializeAttestableValue() { + const { value } = this; + const definition = getDefinition(this.identifier, this.version); + const parsedAttestableValue = Claim.parseAttestableValue(value); + + // Trying to construct UCA with a existing attestableValue + if (parsedAttestableValue.length === 1) { + // This is a simple attestableValue + this.timestamp = null; + this.salt = parsedAttestableValue[0].salt; + const ucaValue = parsedAttestableValue[0].value; + this.value = definition.type === 'Array' ? _.map(ucaValue, item => new Claim(definition.items.type, { attestableValue: item })) : this.value = _.includes(['null', 'undefined'], ucaValue) ? null : ucaValue; + } else { + const ucaValue = {}; + for (let i = 0; i < parsedAttestableValue.length; i += 1) { + const { propertyName } = parsedAttestableValue[i]; + // we have stored only the property name on the urn, so we have to find the UCA definition + + let filteredIdentifier; + let ucaPropertyName; + const ucaType = UserCollectableAttribute.resolveType(definition, definitions); + const ucaDef = ucaType.properties.find(prop => prop.name === propertyName); + if (ucaDef) { + filteredIdentifier = ucaDef.type; + ucaPropertyName = propertyName; + } else { + const splitPropertyName = propertyName.split('.'); + // this property is used to check if the recursion tree has more than an depth + const ucaNamespace = splitPropertyName[splitPropertyName.length - 2]; + const ucaNamespacePascal = ucaNamespace.substring(0, 1).toUpperCase() + ucaNamespace.substring(1); + ucaPropertyName = splitPropertyName[splitPropertyName.length - 1]; + filteredIdentifier = `cvc:${ucaNamespacePascal}:${ucaPropertyName}`; + } + + // test if definition exists + const filteredDefinition = definitions.find(def => def.identifier === filteredIdentifier); + if (!filteredDefinition) { + // this must have an claim path with no recursive definition + filteredIdentifier = this.findDefinitionByAttestableValue(ucaPropertyName, definition); + } + ucaValue[propertyName] = new Claim(filteredIdentifier, { attestableValue: parsedAttestableValue[i].stringValue }); + } + this.value = ucaValue; + } + } + + /* eslint-disable class-methods-use-this */ + getValidIdentifiers() { + return validIdentifiers; + } + + static resolveType(definition) { + return UserCollectableAttribute.resolveType(definition, definitions); + } + + static parseAttestableArrayValue(value) { + const splitDots = value.attestableValue.split(':'); + + const propertyName = splitDots[1]; + const salt = splitDots[2]; + const attestableValueItems = value.attestableValue.substring(value.attestableValue.indexOf('[') + 1, value.attestableValue.indexOf(']') - 1).split(','); + const parsedArrayItems = _.map(attestableValueItems, item => Claim.parseAttestableValue({ attestableValue: item })); + return { + propertyName, salt, value: parsedArrayItems + }; + } + + static parseAttestableValue(value) { + const values = []; + + if (_.isArray(value.attestableValue)) { + // Already parsed in a previous recursion + return value.attestableValue; + } + + if (isArrayAttestableValue(value.attestableValue)) { + const arrayValues = Claim.parseAttestableArrayValue(value); + return [arrayValues]; + } + + // If is not an ArrayValue we parse it now + const splitPipes = _.split(value.attestableValue, '|'); + const attestableValueRegex = /^urn:(\w+(?:\.\w+)*):(\w+):(.+)/; + _.each(splitPipes, stringValue => { + const match = attestableValueRegex.exec(stringValue); + if (match && match.length === 4) { + const v = { + propertyName: match[1], + salt: match[2], + value: match[3], + stringValue + }; + values.push(v); + } + }); + if (splitPipes.length !== values.length && splitPipes.length !== values.length + 1) { + throw new Error('Invalid attestableValue'); + } + return values; + } + + findDefinitionByAttestableValue(attestableValuePropertyName, rootDefinition) { + const ucaType = UserCollectableAttribute.resolveType(rootDefinition, definitions); + for (const property of ucaType.properties) { + // eslint-disable-line no-restricted-syntax + const resolvedDefinition = _.find(definitions, { identifier: property.type }); + resolvedDefinition.type = UserCollectableAttribute.resolveType(resolvedDefinition, definitions); + if (!resolvedDefinition.type.properties && property.name === attestableValuePropertyName) { + return property.type; + } + if (resolvedDefinition.type.properties) { + return this.findDefinitionByAttestableValue(attestableValuePropertyName, resolvedDefinition); + } + } + return null; + } + + getAttestableValue(path, isArrayItem = false) { + // all UCA properties they have the form of :propertyName or :something.propertyName + const { identifierComponents } = getBaseIdentifiers(this.identifier); + let propertyName = identifierComponents[2]; + + if (isArrayItem) { + // we need to supress the root path + propertyName = null; + } + + if (path) { + propertyName = `${path}.${propertyName}`; + } + + // it was defined that the attestable value would be on the URN type https://tools.ietf.org/html/rfc8141 + if (['String', 'Number', 'Boolean'].indexOf(this.type) >= 0) { + return `urn:${propertyName}:${this.salt}:${this.value}|`; + }if (this.type === 'Array') { + const itemsValues = _.reduce(this.value, (result, item) => `${result}${item.getAttestableValue(null, true)},`, ''); + return `urn:${propertyName}:${this.salt}:[${itemsValues}]`; + } + return _.reduce(_.sortBy(_.keys(this.value)), (s, k) => `${s}${this.value[k].getAttestableValue(propertyName)}`, ''); + } + + /** + * Returns the global CredentialItem of the Credential + */ + getGlobalIdentifier() { + return `claim-${this.identifier}-${this.version}`; + } + + getClaimRootPropertyName() { + const { identifierComponents } = getBaseIdentifiers(this.identifier); + return identifierComponents[1].toLowerCase() === 'type' ? '' : _.camelCase(identifierComponents[1]); + } + + getClaimPropertyName() { + const { identifierComponents } = getBaseIdentifiers(this.identifier); + return identifierComponents[2]; + } + + getClaimPath() { + return Claim.getPath(this.identifier); + } + + static getPath(identifier) { + const { identifierComponents } = getBaseIdentifiers(identifier); + const baseName = _.camelCase(identifierComponents[1]); + return baseName !== 'type' ? `${baseName}.${identifierComponents[2]}` : identifierComponents[2]; + } + + getAttestableValues(path, isItemArray = false) { + const joinPaths = (head, tail) => { + const headComponents = head ? _.split(head, '.') : []; + let tailComponents = tail ? _.split(tail, '.') : []; + tailComponents = _.last(headComponents) === _.first(tailComponents) ? tailComponents.splice(1) : tailComponents; + const newPath = _.join([...headComponents, ...tailComponents], '.'); + return newPath; + }; + + let values = []; + const def = _.find(definitions, { identifier: this.identifier, version: this.version }); + if (def.credentialItem || def.attestable) { + const claimPath = joinPaths(path, !isItemArray ? this.getClaimPath() : null); + values.push({ identifier: this.identifier, value: this.getAttestableValue(null, isItemArray), claimPath }); + if (this.type === 'Object') { + _.forEach(_.keys(this.value), k => { + const innerValues = this.value[k].getAttestableValues(claimPath); + values = _.concat(values, innerValues); + }); + } else if (this.type === 'Array') { + _.forEach(this.value, (item, idx) => { + values.push(...item.getAttestableValues(`${claimPath}.${idx}`, true)); + }); + } + } + return values; + } + + /** + * extract the expected Type name for the value when constructing an UCA + * @param {*} definition + */ + static getTypeName(definition) { + if (_.isString(definition.type)) { + if (_.includes(validIdentifiers, definition.type)) { + const innerDefinition = _.find(definitions, { identifier: definition.type }); + return this.getTypeName(innerDefinition); + } + + return definition.type; + } + return 'Object'; + } + + static getAllProperties(identifier, pathName) { + const definition = _.find(definitions, { identifier }); + const properties = []; + const type = UserCollectableAttribute.resolveType(definition, definitions); + const typeDefinition = _.isString(type) ? _.find(definitions, { identifier: type }) : definition; + + if (typeDefinition && this.getTypeName(typeDefinition) === 'Object') { + let typeDefProps; + if (typeDefinition.type.properties) { + typeDefProps = typeDefinition.type.properties; + } else { + const typeDefDefinition = _.find(definitions, { identifier: typeDefinition.type }); + typeDefProps = UserCollectableAttribute.resolveType(typeDefDefinition, definitions).properties; + } + + let basePropName; + const { identifierComponents: baseIdentifierComponents } = getBaseIdentifiers(identifier); + if (pathName) { + if (_.includes(pathName, _.lowerCase(baseIdentifierComponents[1]))) { + basePropName = `${pathName}`; + } else { + basePropName = `${pathName}.${_.lowerCase(baseIdentifierComponents[1])}.${baseIdentifierComponents[2]}`; + } + } else { + basePropName = `${_.lowerCase(baseIdentifierComponents[1])}.${baseIdentifierComponents[2]}`; + } + + if (_.includes(['String', 'Number', 'Boolean'], `${typeDefProps.type}`)) { + // Properties is not an object + properties.push(`${basePropName}.${typeDefProps.name}`); + } else { + _.forEach(typeDefProps, prop => { + const { isNewIdentifier } = getBaseIdentifiers(prop.type); + const newBasePropName = !isNewIdentifier ? basePropName : `${basePropName}.${prop.name}`; + const proProperties = this.getAllProperties(prop.type, newBasePropName); + _.forEach(proProperties, p => properties.push(p)); + }); + } + } else if (pathName) { + const { identifierComponents } = getBaseIdentifiers(definition.identifier); + let propertiesName; + if (pathName.indexOf(identifierComponents[2]) >= 0) { + propertiesName = `${pathName}`; + } else { + propertiesName = `${pathName}.${identifierComponents[2]}`; + } + properties.push(propertiesName); + } else { + const { identifierComponents } = getBaseIdentifiers(identifier); + const propertiesName = `${_.lowerCase(identifierComponents[1])}.${identifierComponents[2]}`; + properties.push(propertiesName); + } + return properties; + } +} + +function convertIdentifierToClassName(identifier) { + const { identifierComponents } = getBaseIdentifiers(identifier); + const baseName = identifierComponents[1]; + const detailName = _.upperFirst(_.camelCase(identifierComponents[2])); + return `${baseName}${detailName}`; +} + +function mixinIdentifiers(UCA) { + // Extend UCA Semantic + _.forEach(_.filter(definitions, d => d.credentialItem), def => { + const name = convertIdentifierToClassName(def.identifier); + const source = {}; + const { identifier } = def; + + function UCAConstructor(value, version) { + return new Claim(identifier, value, version); + } + + source[name] = UCAConstructor; + _.mixin(Claim, source); + }); + return UCA; +} + +module.exports = { Claim: mixinIdentifiers(Claim), definitions, getBaseIdentifiers }; \ No newline at end of file diff --git a/dist/es/claim/__mocks__/definitions.js b/dist/es/claim/__mocks__/definitions.js new file mode 100644 index 00000000..bd06f160 --- /dev/null +++ b/dist/es/claim/__mocks__/definitions.js @@ -0,0 +1,31 @@ +const definitions = [{ + identifier: 'civ:Mock:booleans', + version: '1', + type: 'Boolean', + attestable: true +}, { + identifier: 'civ:Mock:excMax', + version: '1', + type: 'Number', + exclusiveMaximum: true, + maximum: 20 +}, { + identifier: 'civ:Mock:max', + version: '1', + type: 'Number', + exclusiveMaximum: false, + maximum: 50 +}, { + identifier: 'civ:Mock:excMax', + version: '1', + type: 'Number', + value: [10, 20, 30] +}, { + identifier: 'civ:Mock:max', + version: '1', + type: 'Number', + exclusiveMinimum: false, + minimum: 5 +}]; + +module.exports = definitions; \ No newline at end of file diff --git a/dist/es/claim/definitions.js b/dist/es/claim/definitions.js new file mode 100644 index 00000000..94b50211 --- /dev/null +++ b/dist/es/claim/definitions.js @@ -0,0 +1,616 @@ +const { definitions: ucaDefinitions } = require('@identity.com/uca'); + +// ######################################### DEFINITIONS ########################################### +const definitions = [{ + identifier: 'claim-cvc:Email.domain-v1', + version: '1', + type: 'cvc:Type:domain', + credentialItem: true +}, { + identifier: 'claim-cvc:Contact.email-v1', + version: '1', + type: 'claim-cvc:Type.email-v1', + credentialItem: true +}, { + identifier: 'claim-cvc:User.id-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:User.realm-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Phone.countryCode-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Phone.number-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Phone.extension-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Phone.lineType-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:PhoneNumber.countryCode-v1', + type: 'claim-cvc:Phone.countryCode-v1', + version: '1', + credentialItem: true +}, { + identifier: 'claim-cvc:PhoneNumber.number-v1', + type: 'claim-cvc:Phone.number-v1', + version: '1', + credentialItem: true +}, { + identifier: 'claim-cvc:PhoneNumber.extension-v1', + type: 'claim-cvc:Phone.extension-v1', + version: '1', + credentialItem: true +}, { + identifier: 'claim-cvc:PhoneNumber.lineType-v1', + type: 'claim-cvc:Phone.lineType-v1', + version: '1', + credentialItem: true +}, { + identifier: 'claim-cvc:Contact.phoneNumber-v1', + version: '1', + type: 'claim-cvc:Type.phoneNumber-v1', + credentialItem: true +}, { + identifier: 'claim-cvc:Name.givenNames-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Name.familyNames-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Name.otherNames-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Type.Name-v1', + version: '1', + type: { + properties: [{ + name: 'givenNames', + type: 'claim-cvc:Name.givenNames-v1' + }, { + name: 'familyNames', + type: 'claim-cvc:Name.familyNames-v1' + }, { + name: 'otherNames', + type: 'claim-cvc:Name.otherNames-v1' + }], + required: ['givenNames'] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Document.name-v1', + version: '1', + type: 'claim-cvc:Type.Name-v1', + credentialItem: true +}, { + identifier: 'claim-cvc:Identity.name-v1', + version: '1', + type: 'claim-cvc:Type.Name-v1', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.nationality-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.number-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Identity.dateOfBirth-v1', + version: '1', + type: 'cvc:Type:date', + credentialItem: true +}, { + identifier: 'claim-cvc:Address.city-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Address.postalCode-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Address.state-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Address.county-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Address.country-v1', + version: '1', + type: 'cvc:Type:country', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.address-v1', + version: '1', + type: 'claim-cvc:Type.address-v1', + credentialItem: true +}, { + identifier: 'claim-cvc:Identity.address-v1', + version: '1', + type: 'claim-cvc:Type.address-v1', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.dateOfIssue-v1', + version: '1', + type: 'cvc:Type:date', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.dateOfExpiry-v1', + version: '1', + type: 'cvc:Type:date', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.dateOfBirth-v1', + version: '1', + type: 'cvc:Type:date', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.enum-v1', + version: '1', + type: 'String' +}, { + identifier: 'claim-cvc:Document.type-v1', + version: '1', + type: 'cvc:Type:documentType', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.gender-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.issueLocation-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.issueAuthority-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.issueCountry-v1', + version: '1', + type: 'cvc:Type:country', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.placeOfBirth-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Type.email-v1', + version: '1', + type: { + properties: [{ + name: 'username', + type: 'cvc:Email:username' + }, { + name: 'domain', + type: 'claim-cvc:Email.domain-v1' + }] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Type.phoneNumber-v1', + version: '1', + type: { + properties: [{ + name: 'country', + type: 'claim-cvc:PhoneNumber.country-v1' + }, { + name: 'countryCode', + type: 'claim-cvc:PhoneNumber.countryCode-v1' + }, { + name: 'number', + type: 'claim-cvc:PhoneNumber.number-v1' + }, { + name: 'extension', + type: 'claim-cvc:PhoneNumber.extension-v1' + }, { + name: 'lineType', + type: 'claim-cvc:PhoneNumber.lineType-v1' + }], + required: ['country', 'countryCode', 'number', 'lineType'] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:PhoneNumber.country-v1', + type: 'cvc:Type:country', + version: '1', + credentialItem: true +}, { + identifier: 'claim-cvc:Type.Name-v1', + version: '1', + type: { + properties: [{ + name: 'givenNames', + type: 'claim-cvc:Name.givenNames-v1' + }, { + name: 'familyNames', + type: 'claim-cvc:Name.familyNames-v1' + }, { + name: 'otherNames', + type: 'claim-cvc:Name.otherNames-v1' + }], + required: ['givenNames'] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Type.address-v1', + version: '1', + type: { + properties: [{ + name: 'country', + type: 'claim-cvc:Address.country-v1' + }, { + name: 'county', + type: 'claim-cvc:Address.county-v1' + }, { + name: 'state', + type: 'claim-cvc:Address.state-v1' + }, { + name: 'street', + type: 'claim-cvc:Address.street-v1' + }, { + name: 'unit', + type: 'claim-cvc:Address.unit-v1' + }, { + name: 'city', + type: 'claim-cvc:Address.city-v1' + }, { + name: 'postalCode', + type: 'claim-cvc:Address.postalCode-v1' + }], + required: ['street', 'city', 'state', 'country'] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Address.street-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Address.unit-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.properties-v1', + version: '1', + attestable: true, + type: { + properties: [{ + name: 'dateOfIssue', + type: 'claim-cvc:Document.dateOfIssue-v1' + }, { + name: 'dateOfExpiry', + type: 'claim-cvc:Document.dateOfExpiry-v1' + }], + required: ['dateOfIssue'] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:SocialSecurity.number-v1', + version: '1', + type: 'cvc:Type:socialSecurityNumber', + credentialItem: true +}, { + identifier: 'claim-cvc:Validation:evidences.idDocumentFront-v1', + version: '1', + type: 'cvc:Evidences:idDocumentFront', + credentialItem: true +}, { + identifier: 'claim-cvc:Validation:evidences.idDocumentBack-v1', + version: '1', + type: 'cvc:Evidences:idDocumentBack', + credentialItem: true +}, { + identifier: 'claim-cvc:Validation:evidences.selfie-v1', + version: '1', + type: 'cvc:Evidences:selfie', + credentialItem: true +}, { + identifier: 'claim-cvc:Document.evidences-v1', + version: '1', + attestable: true, + type: { + properties: [{ + name: 'idDocumentFront', + type: 'claim-cvc:Validation:evidences.idDocumentFront-v1' + }, { + name: 'idDocumentBack', + type: 'claim-cvc:Validation:evidences.idDocumentBack-v1' + }, { + name: 'selfie', + type: 'claim-cvc:Validation:evidences.selfie-v1' + }] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Vaccination.date-v1', + version: '1', + type: 'cvc:Type:timestamp', + credentialItem: false +}, { + identifier: 'claim-cvc:Test.date-v1', + version: '1', + type: 'cvc:Type:timestamp', + credentialItem: false +}, { + identifier: 'claim-cvc:Vaccination.name-v1', + version: '1', + type: 'String', + credentialItem: false +}, { + identifier: 'claim-cvc:Vaccination.recordDetail-v1', + version: '1', + type: { + properties: [{ + name: 'createdAt', + type: 'cvc:Type:date' + }, { + name: 'updatedAt', + type: 'cvc:Type:date' + }] + }, + required: ['createdAt'], + credentialItem: false +}, { + identifier: 'claim-cvc:Type.organizationName-v1', + version: '1', + type: 'String', + credentialItem: false +}, { + identifier: 'claim-cvc:Type.organizationId-v1', + version: '1', + type: 'String', + credentialItem: false +}, { + identifier: 'claim-cvc:Type.organization-v1', + version: '1', + type: { + properties: [{ + name: 'name', + type: 'claim-cvc:Type.organizationName-v1' + }, { + name: 'id', + type: 'claim-cvc:Type.organizationId-v1' + }] + }, + required: ['name'], + credentialItem: false +}, { + identifier: 'claim-cvc:Type.patient-v1', + version: '1', + type: { + properties: [{ + name: 'fullName', + type: 'cvc:Type:fullName' + }, { + name: 'dateOfBirth', + type: 'cvc:Type:date' + }] + }, + required: ['name'], + credentialItem: true +}, { + identifier: 'claim-cvc:Medical.code-v1', + version: '1', + type: { + properties: [{ + name: 'name', + type: 'cvc:Code:name' + }, { + name: 'code', + type: 'cvc:Code:code' + }, { + name: 'codeSystem', + type: 'cvc:Code:codeSystem' + }, { + name: 'codeSystemName', + type: 'cvc:Code:codeSystemName' + }] + }, + required: ['name', 'code'], + credentialItem: false +}, { + identifier: 'claim-cvc:Manufacturer.name-v1', + version: '1', + type: 'String', + credentialItem: false +}, { + identifier: 'claim-cvc:Vaccination.manufacturer-v1', + version: '1', + type: { + properties: [{ + name: 'name', + type: 'claim-cvc:Manufacturer.name-v1' + }, { + name: 'code', + type: 'claim-cvc:Medical.code-v1' + }], + required: ['name'] + }, + credentialItem: false +}, { + identifier: 'claim-cvc:Vaccination.id-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Medical.codes-v1', + version: '1', + type: 'Array', + items: { + type: 'claim-cvc:Medical.code-v1' + }, + credentialItem: false +}, { + identifier: 'claim-cvc:Codes.records-v1', + version: '1', + type: 'Array', + items: { + type: 'claim-cvc:Medical.code-v1' + }, + credentialItem: false +}, { + identifier: 'claim-cvc:Vaccination.record-v1', + version: '1', + type: { + properties: [{ + name: 'vaccinationId', + type: 'claim-cvc:Vaccination.id-v1' + }, { + name: 'dateOfAdministration', + type: 'claim-cvc:Vaccination.date-v1' + }, { + name: 'manufacturer', + type: 'claim-cvc:Vaccination.manufacturer-v1' + }, { + name: 'name', + type: 'claim-cvc:Vaccination.name-v1' + }, { + name: 'detail', + type: 'claim-cvc:Vaccination.recordDetail-v1' + }, { + name: 'organization', + type: 'cvc:Type:organization' + }, { + name: 'codes', + type: 'claim-cvc:Codes.records-v1' + }], + required: ['vaccinationId', 'dateOfAdministration', 'name', 'organization'] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Vaccination.records-v1', + version: '1', + type: 'Array', + items: { + type: 'claim-cvc:Vaccination.record-v1' + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Test.type-v1', + version: '1', + type: 'String', + credentialItem: false +}, { + identifier: 'claim-cvc:Test.result-v1', + version: '1', + type: 'String', + credentialItem: false +}, { + identifier: 'claim-cvc:Test.id-v1', + version: '1', + type: 'String', + credentialItem: true +}, { + identifier: 'claim-cvc:Test.record-v1', + version: '1', + type: { + properties: [{ + name: 'testId', + type: 'claim-cvc:Test.id-v1' + }, { + name: 'testDate', + type: 'claim-cvc:Test.date-v1' + }, { + name: 'resultDate', + type: 'claim-cvc:Test.date-v1' + }, { + name: 'type', + type: 'claim-cvc:Test.type-v1' + }, { + name: 'result', + type: 'claim-cvc:Test.result-v1' + }, { + name: 'organization', + type: 'claim-cvc:Type.organization-v1' + }, { + name: 'codes', + type: 'claim-cvc:Codes.records-v1' + }], + required: ['testId', 'testDate', 'type', 'result'] + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Test.records-v1', + version: '1', + type: 'Array', + items: { + type: 'claim-cvc:Test.record-v1' + }, + credentialItem: true +}, { + identifier: 'claim-cvc:Medical.covid19-v1', + version: '1', + type: { + properties: [{ + name: 'vaccinations', + type: 'claim-cvc:Vaccination.records-v1' + }, { + name: 'tests', + type: 'claim-cvc:Test.records-v1' + }, { + name: 'patient', + type: 'claim-cvc:Type.patient-v1' + }] + }, + require: ['patient'], + credentialItem: true +}]; + +function transformUcaIdToClaimId(identifier) { + const identifierComponents = identifier.split(':'); + return `claim-cvc:${identifierComponents[1]}.${identifierComponents[2]}-v1`; +} + +function isDefinitionEqual(definition, ucaDefinition) { + return definition.identifier === transformUcaIdToClaimId(ucaDefinition.identifier) || definition.identifier === ucaDefinition.identifier; +} + +ucaDefinitions.forEach(ucaDefinition => { + let found = false; + definitions.some(definition => { + if (isDefinitionEqual(definition, ucaDefinition)) { + found = true; + } + return found; + }); + if (!found) { + definitions.push(ucaDefinition); + } +}); + +module.exports = definitions; \ No newline at end of file diff --git a/dist/es/constants/headers.js b/dist/es/constants/headers.js new file mode 100644 index 00000000..10d12150 --- /dev/null +++ b/dist/es/constants/headers.js @@ -0,0 +1,8 @@ +const HeaderType = { + EXTERNAL_ID_HEADER: 'X-External-ID', + FLOW_ID_HEADER: 'X-Civic-FlowId', + IDENTITY_HEADER: 'X-Identity-Self' +}; +module.exports = { + HeaderType +}; \ No newline at end of file diff --git a/dist/es/constants/index.js b/dist/es/constants/index.js new file mode 100644 index 00000000..a1529709 --- /dev/null +++ b/dist/es/constants/index.js @@ -0,0 +1,5 @@ +const headers = require('./headers'); + +module.exports = { + headers +}; \ No newline at end of file diff --git a/dist/es/creds/ClaimModel.js b/dist/es/creds/ClaimModel.js new file mode 100644 index 00000000..e487743c --- /dev/null +++ b/dist/es/creds/ClaimModel.js @@ -0,0 +1,23 @@ +const _ = require('lodash'); + +/** + * Transforms a list of UCAs into the claim property of the verifiable cliams + */ +class ClaimModel { + constructor(ucas) { + _.forEach(ucas, uca => { + const rootPropertyName = uca.getClaimRootPropertyName(); + if (!_.isEmpty(rootPropertyName)) { + if (!this[rootPropertyName]) { + this[rootPropertyName] = {}; + } + + this[rootPropertyName][uca.getClaimPropertyName()] = uca.getPlainValue(); + } else { + this[uca.getClaimPropertyName()] = uca.getPlainValue(); + } + }); + } +} + +module.exports = { ClaimModel }; \ No newline at end of file diff --git a/dist/es/creds/CvcMerkleProof.js b/dist/es/creds/CvcMerkleProof.js new file mode 100644 index 00000000..d54f9682 --- /dev/null +++ b/dist/es/creds/CvcMerkleProof.js @@ -0,0 +1,60 @@ +const _ = require('lodash'); +const MerkleTools = require('merkle-tools'); + +const { sha256 } = require('../lib/crypto'); +const { Claim } = require('../claim/Claim'); +const { services } = require('../services'); + +/** + * Transforms a list of UCAs into the signature property of the verifiable claims + + */ +class CvcMerkleProof { + static get PADDING_INCREMENTS() { + return 16; + } + + constructor(ucas) { + const withRandomUcas = CvcMerkleProof.padTree(ucas); + this.type = 'CvcMerkleProof2018'; + this.merkleRoot = null; + this.anchor = 'TBD (Civic Blockchain Attestation)'; + this.leaves = CvcMerkleProof.getAllAttestableValue(withRandomUcas); + this.buildMerkleTree(); + } + + buildMerkleTree() { + const merkleTools = new MerkleTools(); + const hashes = _.map(this.leaves, n => sha256(n.value)); + merkleTools.addLeaves(hashes); + merkleTools.makeTree(); + _.forEach(hashes, (hash, idx) => { + this.leaves[idx].targetHash = hash; + this.leaves[idx].node = merkleTools.getProof(idx); + }); + this.leaves = _.filter(this.leaves, el => !(el.identifier === 'cvc:Random:node')); + this.merkleRoot = merkleTools.getMerkleRoot().toString('hex'); + } + + static padTree(nodes) { + const currentLength = nodes.length; + const targetLength = currentLength < CvcMerkleProof.PADDING_INCREMENTS ? CvcMerkleProof.PADDING_INCREMENTS : _.ceil(currentLength / CvcMerkleProof.PADDING_INCREMENTS) * CvcMerkleProof.PADDING_INCREMENTS; + const newNodes = _.clone(nodes); + const secureRandom = services.container.SecureRandom; + while (newNodes.length < targetLength) { + newNodes.push(new Claim('cvc:Random:node', secureRandom.wordWith(16))); + } + return newNodes; + } + + static getAllAttestableValue(ucas) { + let values = []; + _.forEach(ucas, uca => { + const innerValues = uca.getAttestableValues(); + values = _.concat(values, innerValues); + }); + return values; + } +} + +module.exports = { CvcMerkleProof }; \ No newline at end of file diff --git a/dist/es/creds/VerifiableCredential.js b/dist/es/creds/VerifiableCredential.js new file mode 100644 index 00000000..d632c208 --- /dev/null +++ b/dist/es/creds/VerifiableCredential.js @@ -0,0 +1,741 @@ +const _ = require('lodash'); +const validUrl = require('valid-url'); +const sift = require('sift').default; + +const timestamp = require('unix-timestamp'); +const flatten = require('flat'); +const uuidv4 = require('uuid/v4'); +const MerkleTools = require('merkle-tools'); + +const { sha256 } = require('../lib/crypto'); +const { Claim } = require('../claim/Claim'); + +const definitions = require('./definitions'); +const { services } = require('../services'); +const time = require('../timeHelper'); +const { CvcMerkleProof } = require('./CvcMerkleProof'); +const { ClaimModel } = require('./ClaimModel'); + +// convert a time delta to a timestamp +const convertDeltaToTimestamp = delta => time.applyDeltaToDate(delta).getTime() / 1000; + +function validIdentifiers() { + const vi = _.map(definitions, d => d.identifier); + return vi; +} + +function getClaimsWithFlatKeys(claims) { + const flattenDepth3 = flatten(claims, { maxDepth: 3 }); + const flattenDepth2 = flatten(claims, { maxDepth: 2 }); + const flattenClaim = _.merge({}, flattenDepth3, flattenDepth2); + return _(flattenClaim).toPairs().sortBy(0).fromPairs().value(); +} + +function getLeavesClaimPaths(signLeaves) { + return _.map(signLeaves, 'claimPath'); +} + +function verifyLeave(leave, merkleTools, claims, signature, invalidValues, invalidHashs, invalidProofs) { + // 1. verify valid targetHashs + // 1.1 "leave.value" should be equal claim values + const ucaValue = new Claim(leave.identifier, { attestableValue: leave.value }); + if (ucaValue.type === 'String' || ucaValue.type === 'Number') { + if (ucaValue.value !== _.get(claims, leave.claimPath)) { + invalidValues.push(leave.value); + } + } else if (ucaValue.type === 'Object') { + const ucaValueValue = ucaValue.value; + const innerClaimValue = _.get(claims, leave.claimPath); + const claimPathSufix = _.last(_.split(leave.claimPath, '.')); + + const claimValue = {}; + claimValue[claimPathSufix] = innerClaimValue; + const ucaValueKeys = _.keys(ucaValue.value); + _.each(ucaValueKeys, k => { + const expectedClaimValue = _.get(claimValue, k); + if (expectedClaimValue && `${_.get(ucaValueValue[k], 'value')}` !== `${expectedClaimValue}`) { + invalidValues.push(claimValue[k]); + } + }); + } else if (ucaValue.type === 'Array') { + const innerClaimValue = _.get(claims, leave.claimPath); + + _.forEach(ucaValue.value, (arrayItem, idx) => { + const itemInnerClaimValue = innerClaimValue[idx]; + const ucaValueKeys = _.keys(arrayItem.value); + _.each(ucaValueKeys, k => { + const expectedClaimValue = _.get(itemInnerClaimValue, k); + if (expectedClaimValue && `${_.get(arrayItem.value, [k, 'value'])}` !== `${expectedClaimValue}`) { + invalidValues.push(itemInnerClaimValue[k]); + } + }); + }); + } else { + // Invalid ucaValue.type + invalidValues.push(leave.value); + } + + // 1.2 hash(leave.value) should be equal leave.targetHash + const hash = sha256(leave.value); + if (hash !== leave.targetHash) invalidHashs.push(leave.targetHash); + + // 2. Validate targetHashs + proofs with merkleRoot + const isValidProof = merkleTools.validateProof(leave.node, leave.targetHash, signature.merkleRoot); + if (!isValidProof) invalidProofs.push(leave.targetHash); +} + +function validateEvidence(evidenceItem) { + const requiredFields = ['type', 'verifier', 'evidenceDocument', 'subjectPresence', 'documentPresence']; + _.forEach(requiredFields, field => { + if (!(field in evidenceItem)) { + throw new Error(`Evidence ${field} is required`); + } + }); + // id property is optional, but if present, SHOULD contain a URL + if ('id' in evidenceItem && !validUrl.isWebUri(evidenceItem.id)) { + throw new Error('Evidence id is not a valid URL'); + } + if (!_.isArray(evidenceItem.type)) { + throw new Error('Evidence type is not an Array object'); + } +} + +function serializeEvidence(evidence) { + const evidenceList = _.isArray(evidence) ? evidence : [evidence]; + return _.map(evidenceList, evidenceItem => { + validateEvidence(evidenceItem); + return { + id: evidenceItem.id, + type: evidenceItem.type, + verifier: evidenceItem.verifier, + evidenceDocument: evidenceItem.evidenceDocument, + subjectPresence: evidenceItem.subjectPresence, + documentPresence: evidenceItem.documentPresence + }; + }); +} + +/** + * Transform DSR constraints to sift constraits + * @param {*} constraints + */ +function transformConstraint(constraints) { + const resultConstraints = []; + + _.forEach(constraints.claims, constraint => { + if (!constraint.path) { + throw new Error('Malformed contraint: missing PATTH'); + } + if (!constraint.is) { + throw new Error('Malformed contraint: missing IS'); + } + + const siftConstraint = {}; + siftConstraint[constraint.path] = constraint.is; + resultConstraints.push(siftConstraint); + }); + + return resultConstraints; +} + +/** + * Checks if object is a Date Structure (has day, month, year properties) + * + * @param obj - Structure to test + * @return {boolean} + */ +function isDateStructure(obj) { + const objKeys = _.keys(obj); + if (objKeys.length !== 3) { + // it has more or less keys the (day, month, year) + return false; + } + return _.includes(objKeys, 'day') && _.includes(objKeys, 'month') && _.includes(objKeys, 'year'); +} + +/** + * Non cryptographically secure verify the Credential + * Performs a proofs verification only. + * @param credential - A credential object with expirationDate, claim and proof + * @return true if verified, false otherwise. + */ +function nonCryptographicallySecureVerify(credential) { + const expiry = _.clone(credential.expirationDate); + const claims = _.clone(credential.claim); + const signature = _.clone(credential.proof); + const signLeaves = _.get(signature, 'leaves'); + let valid = false; + + const merkleTools = new MerkleTools(); + const claimsWithFlatKeys = getClaimsWithFlatKeys(claims); + const leavesClaimPaths = getLeavesClaimPaths(signLeaves); + const invalidClaim = []; + const invalidExpiry = []; + const invalidValues = []; + const invalidHashs = []; + const invalidProofs = []; + _.forEach(_.keys(claimsWithFlatKeys), claimKey => { + // check if `claimKey` has a `claimPath` proof + const leaveIdx = _.indexOf(leavesClaimPaths, claimKey); + // if not found + if (leaveIdx === -1) { + // .. still test if parent key node may have a `claimPath` proof + _.findLastIndex(claimKey, '.'); + const parentClaimKey = claimKey.substring(0, _.lastIndexOf(claimKey, '.')); + if (_.indexOf(leavesClaimPaths, parentClaimKey) > -1) { + // if yes, no problem, go to next loop + return; + } + // if no, include on invalidClaim array + invalidClaim.push(claimKey); + } else { + const leave = signLeaves[leaveIdx]; + verifyLeave(leave, merkleTools, claims, signature, invalidValues, invalidHashs, invalidProofs); + } + }); + + // It has to be present Credential expiry even with null value + const expiryIdx = _.indexOf(leavesClaimPaths, 'meta.expirationDate'); + if (expiryIdx >= 0) { + const expiryLeave = signLeaves[expiryIdx]; + const metaClaim = { + meta: { + expirationDate: expiry + } + }; + const totalLengthBefore = invalidValues.length + invalidHashs.length + invalidProofs.length; + verifyLeave(expiryLeave, merkleTools, metaClaim, signature, invalidValues, invalidHashs, invalidProofs); + const totalLengthAfter = invalidValues.length + invalidHashs.length + invalidProofs.length; + if (totalLengthAfter === totalLengthBefore) { + // expiry has always to be string formatted date or null value + // if it is null it means it's indefinitely + if (expiry !== null) { + const now = new Date(); + const expiryDate = new Date(expiry); + if (now.getTime() > expiryDate.getTime()) { + invalidExpiry.push(expiry); + } + } + } + } + if (_.isEmpty(invalidClaim) && _.isEmpty(invalidValues) && _.isEmpty(invalidHashs) && _.isEmpty(invalidProofs) && _.isEmpty(invalidExpiry)) { + valid = true; + } + return valid; +} + +/** + * Cryptographically secure verify the Credential. + * Performs a non cryptographically secure verification, attestation check and signature validation. + * @param credential - A credential object with expirationDate, claim and proof + * @param verifyAttestationFunc - Async method to verify a credential attestation + * @param verifySignatureFunc - Async method to verify a credential signature + * @return true if verified, false otherwise. + */ +async function cryptographicallySecureVerify(credential, verifyAttestationFunc, verifySignatureFunc) { + if (!nonCryptographicallySecureVerify(credential)) { + return false; + } + + if (verifyAttestationFunc) { + const attestationCheck = await verifyAttestationFunc(credential.proof); + if (!attestationCheck) return false; + } + + if (verifySignatureFunc) { + const signatureCheck = await verifySignatureFunc(credential.proof); + if (!signatureCheck) return false; + } + + return true; +} + +/** + * Verify if a credential was granted for a specific requester and requestId. + * @param credential - A credential object with expirationDate, claim and proof + * @return true if verified, false otherwise. + */ +function requesterGrantVerify(credential, requesterId, requestId, keyName) { + const label = _.get(credential.proof, 'anchor.subject.label'); + const anchorPubKey = _.get(credential.proof, 'anchor.subject.pub'); + const anchorData = _.get(credential.proof, 'anchor.subject.data'); + + if (_.isEmpty(credential.granted) || _.isEmpty(label) || _.isEmpty(anchorPubKey)) { + return false; + } + + const stringToHash = `${label}${anchorData}${requesterId}${requestId}`; + const hexHash = sha256(stringToHash); + + const cryptoManager = services.container.CryptoManager; + + let verifyKey = keyName; + if (_.isEmpty(verifyKey)) { + if (!_.isFunction(cryptoManager.installKey)) { + throw new Error('CryptoManager does not support installKey, please use a `keyName` instead.'); + } + verifyKey = `TEMP_KEY_NAME_${new Date().getTime()}`; + cryptoManager.installKey(verifyKey, anchorPubKey); + } + + return cryptoManager.verify(verifyKey, hexHash, credential.granted); +} + +/** + * Trasnform {day, month, year } to Unix Date + * + * @param obj {day, month, year } + * @return {number} an unix-timestamp in seconds + */ +function transformDate(obj) { + return new Date(obj.year, obj.month - 1, obj.day).getTime() / 1000; +} + +const VERIFY_LEVELS = { + INVALID: -1, // Verifies if the VC structure and/or signature proofs is not valid, or credential is expired + PROOFS: 0, // Verifies if the VC structure and/or signature proofs are valid, including the expiry + ANCHOR: 1, // Verifies if the VC Attestation Anchor structure is valid + GRANTED: 2, // Verifies if the owner granted the VC usage for a specific request + BLOCKCHAIN: 3 // Verifies if the VC Attestation is valid on the blockchain +}; + +/** + * Throws exception if the definition has missing required claims + * @param {*} definition - the credential definition + * @param {*} ucas - the list of ucas + */ +function verifyRequiredClaims(definition, ucas) { + if (!_.isEmpty(definition.required)) { + const identifiers = ucas.map(uca => uca.identifier); + const missings = _.difference(definition.required, identifiers); + if (!_.isEmpty(missings)) { + throw new Error(`Missing required claim(s): ${_.join(missings, ', ')}`); + } + } +} + +/** + * Throws exception if the definition has missing required claims + * @param {*} definition - the credential definition + * @param {*} verifiableCredentialJSON - the verifiable credential JSON + */ +function verifyRequiredClaimsFromJSON(definition, verifiableCredentialJSON) { + const leaves = _.get(verifiableCredentialJSON, 'proof.leaves'); + + if (!_.isEmpty(definition.required) && leaves) { + const identifiers = leaves.map(leave => leave.identifier); + const missings = _.difference(definition.required, identifiers); + if (!_.isEmpty(missings)) { + throw new Error(`Missing required claim(s): ${_.join(missings, ', ')}`); + } + } +} + +/** + * Retrieves the credential definition + * @param {string} identifier - credential identifier + * @param {*} [version] - definition version + */ +function getCredentialDefinition(identifier, version) { + let definition; + if (version) { + definition = _.find(definitions, { identifier, version: `${version}` }); + } else { + definition = _.find(definitions, { identifier }); + } + if (!definition) { + throw new Error(`Credential definition for ${identifier} v${version} not found`); + } + return definition; +} + +/** + * Creates a new Verifiable Credential based on an well-known identifier and it's claims dependencies + * @param {*} identifier + * @param {*} issuer + * @param {*} ucas + * @param {*} version + * @param {*} [evidence] + */ +function VerifiableCredentialBaseConstructor(identifier, issuer, expiryIn, ucas, version, evidence) { + this.id = uuidv4(); + this.issuer = issuer; + const issuerUCA = new Claim('cvc:Meta:issuer', this.issuer); + this.issuanceDate = new Date().toISOString(); + const issuanceDateUCA = new Claim('cvc:Meta:issuanceDate', this.issuanceDate); + this.identifier = identifier; + this.expirationDate = expiryIn ? timestamp.toDate(timestamp.now(expiryIn)).toISOString() : null; + const expiryUCA = new Claim('cvc:Meta:expirationDate', this.expirationDate ? this.expirationDate : 'null'); + + const proofUCAs = expiryUCA ? _.concat(ucas, issuerUCA, issuanceDateUCA, expiryUCA) : _.concat(ucas, issuerUCA, issuanceDateUCA); + + if (!_.includes(validIdentifiers(), identifier)) { + throw new Error(`${identifier} is not defined`); + } + + const definition = getCredentialDefinition(identifier, version); + this.version = `${version}` || definition.version; + this.type = ['Credential', identifier]; + this.transient = definition.transient || false; + + if (evidence) { + this.evidence = serializeEvidence(evidence); + } + + // ucas can be empty here if it is been constructed from JSON + if (!_.isEmpty(ucas)) { + verifyRequiredClaims(definition, ucas); + this.claim = new ClaimModel(ucas); + this.proof = new CvcMerkleProof(proofUCAs); + if (!_.isEmpty(definition.excludes)) { + const removed = _.remove(this.proof.leaves, el => _.includes(definition.excludes, el.identifier)); + _.forEach(removed, r => { + _.unset(this.claim, r.claimPath); + }); + } + // The VC Grantted session (see .grantUsageFor) + this.granted = null; + } + + /** + * Returns the global identifier of the Credential + */ + this.getGlobalIdentifier = () => `credential-${this.identifier}-${this.version}`; + + /** + * Creates a filtered credential exposing only the requested claims + * @param {*} requestedClaims + */ + this.filter = requestedClaims => { + const filtered = _.cloneDeep(this); + _.remove(filtered.proof.leaves, el => !_.includes(requestedClaims, el.identifier)); + + filtered.claim = {}; + _.forEach(filtered.proof.leaves, el => { + _.set(filtered.claim, el.claimPath, _.get(this.claim, el.claimPath)); + }); + + return filtered; + }; + + /** + * Request that this credential MerkleRoot is anchored on the Blockchain. + * This will return a _temporary_ anchor meaning that the blockchain entry is still not confirmed. + * + * @param options options to be passed + * @param options.subject the local signed subject with the user private key + * @param options.subject.label a short description of the subject + * @param options.subject.data hash of the merkle root + * @param options.subject.pub xpub of the signing private key + * @param options.subject.signature the value of the signature of the private key + * @param options.network testnet for test env, bitcoin for production + * @param options.cosigner object containing private and public key for cosigning + * @param options.cosigner.xpub public key of the cosigner + * @param options.cosigner.xprv private key of the cosigner + * + * @returns the json object containing the whole anchor attestation + * + */ + this.requestAnchor = async options => { + if (this.transient) { + // If credential is transient no Blockchain attestation is issued + this.proof.anchor = { + type: 'transient', + subject: { + label: this.identifier, + data: this.proof.merkleRoot + } + }; + return this; + } + + const anchorService = services.container.AnchorService; + const updatedOption = _.merge({}, options, { + subject: { + label: this.identifier, + data: this.proof.merkleRoot + } + }); + const anchor = await anchorService.anchor(updatedOption); + this.proof.anchor = anchor; + return this; + }; + + /** + * Trys to renew the current anchor. replecinf the _temporary_ anchor for a _permanent_ one, + * already confirmed on the blockchain. + */ + this.updateAnchor = async () => { + // If credential is transient no Blockchain attestation is issued + if (this.transient) { + // If credential is transient no Blockchain attestation is issued + this.proof.anchor = { + type: 'transient', + subject: { + label: this.identifier, + data: this.proof.merkleRoot + } + }; + return this; + } + const anchorService = services.container.AnchorService; + const anchor = await anchorService.update(this.proof.anchor); + this.proof.anchor = anchor; + return this; + }; + + /** + * Iterate over all leaves and see if their proofs are valid + * @returns {boolean} + */ + this.verifyProofs = () => nonCryptographicallySecureVerify(this); + + /** + * Verify the Credential and return a verification level. + * @return Any of VC.VERIFY_LEVELS + */ + this.verify = (higherVerifyLevel, options) => { + const { requestorId, requestId, keyName } = options || {}; + const hVerifyLevel = !_.isNil(higherVerifyLevel) ? higherVerifyLevel : VERIFY_LEVELS.GRANTED; + let verifiedlevel = VERIFY_LEVELS.INVALID; + + // Test next level + if (verifiedlevel === VERIFY_LEVELS.INVALID && hVerifyLevel >= VERIFY_LEVELS.PROOFS && this.verifyProofs()) verifiedlevel = VERIFY_LEVELS.PROOFS; + + // Test next level + if (verifiedlevel === VERIFY_LEVELS.PROOFS && hVerifyLevel >= VERIFY_LEVELS.ANCHOR && this.verifyAttestation()) verifiedlevel = VERIFY_LEVELS.ANCHOR; + + // Test next level + if (verifiedlevel === VERIFY_LEVELS.ANCHOR && hVerifyLevel >= VERIFY_LEVELS.GRANTED && this.verifyGrant(requestorId, requestId, keyName)) verifiedlevel = VERIFY_LEVELS.GRANTED; + + return verifiedlevel; + }; + + /** + * This method checks if the signature matches for the root of the Merkle Tree + * @return true or false for the validation + */ + this.verifySignature = pinnedPubKey => { + if (this.proof.anchor.type === 'transient') { + return true; + } + return services.container.AnchorService.verifySignature(this.proof, pinnedPubKey); + }; + + /** + * This method checks that the attestation / anchor exists on the BC + */ + this.verifyAttestation = async () => { + // Don't check attestation for credentials that are never attested on blockchain + if (this.proof.anchor.type === 'transient' || this.proof.anchor.network === 'dummynet') { + return true; + } + + return services.container.AnchorService.verifyAttestation(this.proof); + }; + + /** + * This method will revoke the attestation on the chain + * @returns {Promise|void>} + */ + this.revokeAttestation = async () => { + if (this.proof.type === 'transient') { + return; + } + // eslint-disable-next-line consistent-return + return services.container.AnchorService.revokeAttestation(this.proof); + }; + + /** + * This method will check on the chain the balance of the transaction and if it's still unspent, than it's not revoked + * @returns {Promise|void>} + */ + this.isRevoked = async () => { + if (this.proof.type === 'transient') { + return false; + } + return services.container.AnchorService.isRevoked(this.proof); + }; + + const convertTimestampIfString = obj => _.isString(obj) ? convertDeltaToTimestamp(obj) : obj; + + this.isMatch = constraints => { + const claims = _.cloneDeep(this.claim); + const siftCompatibleConstraints = transformConstraint(constraints); + + const claimsMatchConstraint = constraint => { + const path = _.keys(constraint)[0]; + const pathValue = _.get(claims, path); + if (isDateStructure(pathValue)) { + _.set(claims, path, transformDate(pathValue)); + // transforms delta values like "-18y" to a proper timestamp + _.set(constraint, path, _.mapValues(constraint[path], convertTimestampIfString)); + } + // The Constraints are ANDed here - if one is false, the entire + return sift(constraint)([claims]); + }; + + return siftCompatibleConstraints.reduce((matchesAllConstraints, nextConstraint) => matchesAllConstraints && claimsMatchConstraint(nextConstraint), true); + }; + + /** + * Updates the credential with a "granted" token based on the requestorId and a unique requestId (a nonce) that + * can be verified later using .verify() function. + * + * @param {string} requestorId - The IDR id (DID). + * @param {string} requestId - A unique requestID. This should be a nonce for proof chanlange. + * @param {Object} option - You should provide either a keyName or a pvtKey. + * @param {string} option.keyName - A keyName - if CryptoManager is been used. + * @param {string} option.pvtKey - A pvtKey in base58 format (default impl). + */ + this.grantUsageFor = (requestorId, requestId, { keyName, pvtKey }) => { + if (_.isEmpty(_.get(this.proof, 'anchor.subject.label')) || _.isEmpty(_.get(this.proof, 'anchor.subject.data'))) { + throw new Error('Invalid credential attestation/anchor'); + } + if (!this.verifySignature()) { + throw new Error('Invalid credential attestation/anchor signature'); + } + if (!requestorId || !requestId || !(keyName || pvtKey)) { + throw new Error('Missing required parameter: requestorId, requestId or key'); + } + // eslint-disable-next-line max-len + const stringToHash = `${this.proof.anchor.subject.label}${this.proof.anchor.subject.data}${requestorId}${requestId}`; + const hexHash = sha256(stringToHash); + + const cryptoManager = services.container.CryptoManager; + + let signKey = keyName; + if (pvtKey) { + if (!_.isFunction(cryptoManager.installKey)) { + throw new Error('You provide a `pvtKey` but the CryptoManager does not support it, use a `keyName` instead.'); + } + signKey = `TEMP_KEY_NAME_${new Date().getTime()}`; + cryptoManager.installKey(signKey, pvtKey); + } + + const hexSign = cryptoManager.sign(signKey, hexHash); + this.granted = hexSign; + }; + + /** + * @param {} requestorId + * @param {} requestId + * @param {} [keyName] + */ + this.verifyGrant = (requesterId, requestId, keyName) => requesterGrantVerify(this, requesterId, requestId, keyName); + + return this; +} + +/** + * CREDENTIAL_META_FIELDS - Array with meta fields of a credential + */ +const CREDENTIAL_META_FIELDS = ['id', 'identifier', 'issuer', 'issuanceDate', 'expirationDate', 'version', 'type']; + +/** + * + * @param {*} vc + */ +const getCredentialMeta = vc => _.pick(vc, CREDENTIAL_META_FIELDS); + +/** + * Sift constraints to throw errors for constraints missing IS + * @param {*} constraintsMeta + * @param Array + */ +function transformMetaConstraint(constraintsMeta) { + const resultConstraints = []; + + // handle special field constraints.meta.credential + const constraintsMetaKeys = _.keys(constraintsMeta.meta); + _.forEach(constraintsMetaKeys, constraintKey => { + const constraint = constraintsMeta.meta[constraintKey]; + const siftConstraint = {}; + // handle special field constraints.meta.credential + if (constraintKey === 'credential') { + siftConstraint.identifier = constraint; + } else if (constraint.is) { + siftConstraint[constraintKey] = constraint.is; + } else { + throw new Error(`Malformed meta constraint "${constraintKey}": missing the IS`); + } + resultConstraints.push(siftConstraint); + }); + return resultConstraints; +} + +/** + * isMatchCredentialMeta + * @param {*} credentialMeta An Object contains only VC meta fields. Other object keys will be ignored. + * @param {*} constraintsMeta Example: + * // constraints.meta = { + * // "credential": "credential-civ:Credential:CivicBasic-1", + * // "issuer": { + * // "is": { + * // "$eq": "did:ethr:0xaf9482c84De4e2a961B98176C9f295F9b6008BfD" + * // } + * // } + * @returns boolean + */ +const isMatchCredentialMeta = (credentialMeta, constraintsMeta) => { + const siftCompatibleConstraints = transformMetaConstraint(constraintsMeta); + + if (_.isEmpty(siftCompatibleConstraints)) return false; + + const credentialMetaMatchesConstraint = constraint => sift(constraint)([credentialMeta]); + + return siftCompatibleConstraints.reduce((matchesAllConstraints, nextConstraint) => matchesAllConstraints && credentialMetaMatchesConstraint(nextConstraint), true); +}; + +VerifiableCredentialBaseConstructor.CREDENTIAL_META_FIELDS = CREDENTIAL_META_FIELDS; +VerifiableCredentialBaseConstructor.getCredentialMeta = getCredentialMeta; +VerifiableCredentialBaseConstructor.isMatchCredentialMeta = isMatchCredentialMeta; + +/** + * Factory function that creates a new Verifiable Credential based on a JSON object + * @param {*} verifiableCredentialJSON + * @returns VerifiableCredentialBaseConstructor + */ +VerifiableCredentialBaseConstructor.fromJSON = verifiableCredentialJSON => { + const definition = getCredentialDefinition(verifiableCredentialJSON.identifier, verifiableCredentialJSON.version); + + verifyRequiredClaimsFromJSON(definition, verifiableCredentialJSON); + + const newObj = new VerifiableCredentialBaseConstructor(verifiableCredentialJSON.identifier, verifiableCredentialJSON.issuer); + newObj.id = _.clone(verifiableCredentialJSON.id); + newObj.issuanceDate = _.clone(verifiableCredentialJSON.issuanceDate); + newObj.expirationDate = _.clone(verifiableCredentialJSON.expirationDate); + newObj.identifier = _.clone(verifiableCredentialJSON.identifier); + newObj.version = _.clone(verifiableCredentialJSON.version); + newObj.type = _.cloneDeep(verifiableCredentialJSON.type); + newObj.claim = _.cloneDeep(verifiableCredentialJSON.claim); + newObj.proof = _.cloneDeep(verifiableCredentialJSON.proof); + newObj.granted = _.clone(verifiableCredentialJSON.granted) || null; + return newObj; +}; + +/** + * List all properties of a Verifiable Credential + */ +VerifiableCredentialBaseConstructor.getAllProperties = identifier => { + const vcDefinition = _.find(definitions, { identifier }); + if (vcDefinition) { + const allProperties = []; + _.forEach(vcDefinition.depends, ucaIdentifier => { + allProperties.push(...Claim.getAllProperties(ucaIdentifier)); + }); + const excludesProperties = []; + _.forEach(vcDefinition.excludes, ucaIdentifier => { + excludesProperties.push(...Claim.getAllProperties(ucaIdentifier)); + }); + return _.difference(allProperties, excludesProperties); + } + return null; +}; + +VerifiableCredentialBaseConstructor.VERIFY_LEVELS = VERIFY_LEVELS; +VerifiableCredentialBaseConstructor.nonCryptographicallySecureVerify = nonCryptographicallySecureVerify; +VerifiableCredentialBaseConstructor.cryptographicallySecureVerify = cryptographicallySecureVerify; +VerifiableCredentialBaseConstructor.requesterGrantVerify = requesterGrantVerify; + +module.exports = VerifiableCredentialBaseConstructor; \ No newline at end of file diff --git a/dist/es/creds/__mocks__/definitions.js b/dist/es/creds/__mocks__/definitions.js new file mode 100644 index 00000000..7d4291e8 --- /dev/null +++ b/dist/es/creds/__mocks__/definitions.js @@ -0,0 +1,16 @@ +const definitions = [{ + identifier: 'civ:Credential:SimpleIdentity', + version: '1', + depends: ['civ:Identity:name', 'civ:Identity:DateOfBirth'] +}, { + identifier: 'civ:Credential:SimpleTest', + version: '1', + depends: ['civ:Identity:name', 'civ:Identity:DateOfBirth'] +}, { + identifier: 'civ:Credential:TestWithExcludes', + version: '1', + depends: ['civ:Identity:name', 'civ:Identity:DateOfBirth'], + excludes: ['civ:Identity:name.middle'] +}]; + +module.exports = definitions; \ No newline at end of file diff --git a/dist/es/creds/definitions.js b/dist/es/creds/definitions.js new file mode 100644 index 00000000..a618feb9 --- /dev/null +++ b/dist/es/creds/definitions.js @@ -0,0 +1,66 @@ +/** + * name: 'attgenericId', + * name: 'attBaseIdentity', + * name: 'attAddress', + * @type {*[]} + */ +const definitions = [{ + identifier: 'credential-cvc:Email-v1', + version: '1', + depends: ['claim-cvc:Contact.email-v1'] +}, { + identifier: 'credential-cvc:PhoneNumber-v1', + version: '1', + depends: ['claim-cvc:Contact.phoneNumber-v1'] +}, { + identifier: 'credential-cvc:GenericDocumentId-v1', + version: '1', + depends: ['claim-cvc:Document.type-v1', 'claim-cvc:Document.number-v1', 'claim-cvc:Document.name-v1', 'claim-cvc:Document.gender-v1', 'claim-cvc:Document.issueLocation-v1', 'claim-cvc:Document.issueAuthority-v1', 'claim-cvc:Document.issueCountry-v1', 'claim-cvc:Document.placeOfBirth-v1', 'claim-cvc:Document.dateOfBirth-v1', 'claim-cvc:Document.address-v1', 'claim-cvc:Document.properties-v1', 'cvc:Document:image'] +}, { + identifier: 'credential-cvc:IdDocument-v1', + version: '1', + depends: ['claim-cvc:Document.type-v1', 'claim-cvc:Document.number-v1', 'claim-cvc:Document.name-v1', 'claim-cvc:Document.gender-v1', 'claim-cvc:Document.issueCountry-v1', 'claim-cvc:Document.placeOfBirth-v1', 'claim-cvc:Document.dateOfBirth-v1', 'claim-cvc:Document.dateOfExpiry-v1', 'claim-cvc:Document.nationality-v1', 'claim-cvc:Document.evidences-v1'], + required: ['claim-cvc:Document.type-v1', 'claim-cvc:Document.name-v1', 'claim-cvc:Document.dateOfBirth-v1', 'claim-cvc:Document.issueCountry-v1'] +}, { + identifier: 'credential-cvc:IdDocument-v2', + version: '1', + depends: ['claim-cvc:Document.type-v1', 'claim-cvc:Document.number-v1', 'claim-cvc:Document.name-v1', 'claim-cvc:Document.gender-v1', 'claim-cvc:Document.issueCountry-v1', 'claim-cvc:Document.placeOfBirth-v1', 'claim-cvc:Document.dateOfBirth-v1', 'claim-cvc:Document.dateOfExpiry-v1', 'claim-cvc:Document.nationality-v1', 'claim-cvc:Document.evidences-v1'], + required: ['claim-cvc:Document.type-v1', 'claim-cvc:Document.name-v1', 'claim-cvc:Document.dateOfBirth-v1', 'claim-cvc:Document.issueCountry-v1', 'claim-cvc:Document.evidences-v1'] +}, { + identifier: 'credential-cvc:LiveIdDocument-v1', + version: '1', + depends: ['claim-cvc:Document.type-v1', 'claim-cvc:Document.number-v1', 'claim-cvc:Document.name-v1', 'claim-cvc:Document.gender-v1', 'claim-cvc:Document.issueCountry-v1', 'claim-cvc:Document.placeOfBirth-v1', 'claim-cvc:Document.dateOfBirth-v1', 'claim-cvc:Document.dateOfExpiry-v1', 'claim-cvc:Document.nationality-v1', 'claim-cvc:Document.evidences-v1'], + required: ['claim-cvc:Document.type-v1', 'claim-cvc:Document.name-v1', 'claim-cvc:Document.dateOfBirth-v1', 'claim-cvc:Document.issueCountry-v1', 'claim-cvc:Document.evidences-v1'] +}, { + identifier: 'credential-cvc:Address-v1', + version: '1', + depends: ['claim-cvc:Identity.address-v1'] +}, { + identifier: 'credential-cvc:Identity-v1', + version: '1', + depends: ['claim-cvc:Identity.name-v1', 'claim-cvc:Identity.dateOfBirth-v1'] +}, { + identifier: 'credential-cvc:IDVaaS-v1', + version: '1', + depends: ['claim-cvc:Identity.name-v1', 'claim-cvc:Identity.dateOfBirth-v1', 'claim-cvc:Identity.address-v1', 'claim-cvc:Contact.email-v1', 'claim-cvc:SocialSecurity.number-v1', 'claim-cvc:Contact.phoneNumber-v1'] +}, { + identifier: 'credential-cvc:UnverifiedSsn-v1', + version: '1', + transient: true, + depends: ['claim-cvc:SocialSecurity.number-v1'] +}, { + identifier: 'credential-cvc:UnverifiedAddress-v1', + version: '1', + transient: true, + depends: ['claim-cvc:Identity.address-v1'] +}, { + identifier: 'credential-cvc:Covid19-v1', + version: '1', + depends: ['claim-cvc:Medical.covid19-v1'] +}, { + identifier: 'credential-alt:Identity-v1', + version: '1', + depends: ['claim-cvc:Identity.name-v1', 'claim-cvc:Identity.dateOfBirth-v1', 'claim-cvc:Identity.address-v1'] +}]; + +module.exports = definitions; \ No newline at end of file diff --git a/dist/es/errors/definitions.js b/dist/es/errors/definitions.js new file mode 100644 index 00000000..70c46d3b --- /dev/null +++ b/dist/es/errors/definitions.js @@ -0,0 +1,444 @@ +/** + * Enum for ErrorCodes + * @readonly + * @enum { string } + */ +const ErrorCodes = { + + // IDV + // Manual Review Tool + /** + * Reason: Manual Review detected that the provided document is invalid. + * Troubleshooting: Make sure the provided document is a valid one. + */ + ERROR_IDV_MRT_INVALID_DOC: 'error.idv.mrt.invalid.doc', + + /** + * Reason: Manual Review detected that the provided document is unsupported. + * Troubleshooting: Make sure the provided document is a valid one. + */ + ERROR_IDV_MRT_UNSUPPORTED_DOC: 'error.idv.mrt.unsupported.doc', + + /** + * Reason: Manual Review detected that the provided utility is invalid. + * Troubleshooting: Make sure the provided utility is a valid one. + */ + ERROR_IDV_MRT_INVALID_UTILITY: 'error.idv.mrt.invalid.utility', + + /** + * Reason: Manual Review detected that the provided document scan has a low quality resolution. + * Troubleshooting: Make sure the provided document scan has a good resolution. + */ + ERROR_IDV_MRT_QUALITY: 'error.idv.mrt.quality', + + /** + * Reason: Manual Review detected that the provided document is expired. + * Troubleshooting: Make sure the provided document has a valid date of expiry. + */ + ERROR_IDV_MRT_EXPIRED: 'error.idv.mrt.expired', + + /** + * Reason: Manual Review detected that the provided document and photo don't have facial similiarity + * Troubleshooting: Make sure the provided document and photo have a good face similarity. + */ + ERROR_IDV_MRT_MISMATCH: 'error.idv.mrt.mismatch', + + /** + * Reason: Manual Review detected that the requirements fail. + * Troubleshooting: Make sure the provided document do fit the requirements. + */ + ERROR_IDV_MRT_REQUIREMENTS_FAIL: 'error.idv.mrt.requirements.fail', + + // Validation + /** + * Reason: The IDV detected that the provided document is invalid. + * Troubleshooting: Make sure the provided document is a valid one. + */ + ERROR_IDV_VALIDATION_INVALID_DOC: 'error.idv.validation.invalid.doc', + + /** + * Reason: The IDV detected that the provided phone is invalid. + * Troubleshooting: Make sure the provided phone is a valid one. + */ + ERROR_IDV_VALIDATION_INVALID_PHONE: 'error.idv.validation.invalid.phone', + + /** + * Reason: The IDV detected that the provided email is invalid. + * Troubleshooting: Make sure the provided email is a valid one. + */ + ERROR_IDV_VALIDATION_INVALID_EMAIL: 'error.idv.validation.invalid.email', + + /** + * Reason: The IDV detected that the provided document is unsupported. + * Troubleshooting: Make sure the provided document is a valid one. + */ + ERROR_IDV_VALIDATION_UNSUPPORTED_DOC: 'error.idv.validation.unsupported.doc', + + /** + * Reason: The IDV detected that the provided utility is invalid. + * Troubleshooting: Make sure the provided utility is a valid one. + */ + ERROR_IDV_VALIDATION_INVALID_UTILITY: 'error.idv.validation.invalid.utility', + + /** + * Reason: The IDV detected that the provided document scan has a low quality resolution. + * Troubleshooting: Make sure the provided document scan has a good resolution. + */ + ERROR_IDV_VALIDATION_QUALITY: 'error.idv.validation.quality', + + /** + * Reason: The IDV detected that the provided document is expired. + * Troubleshooting: Make sure the provided document has a valid date of expiry. + */ + ERROR_IDV_VALIDATION_EXPIRED: 'error.idv.validation.expired', + + /** + * Reason: The IDV detected that the provided document and photo don't have facial similiarity + * Troubleshooting: Make sure the provided document and photo have a good face similarity. + */ + ERROR_IDV_VALIDATION_MISMATCH: 'error.idv.validation.mismatch', + + /** + * Reason: The IDV detected that the provided document does not contain the user name. + * Troubleshooting: Make sure the provided document contains the user name. + */ + ERROR_IDV_VALIDATION_MISSING_NAME: 'error.idv.validation.missing.name', + + /** + * Reason: The IDV detected that the provided document does not contain the user date of birth. + * Troubleshooting: Make sure the provided document contains the user date of birth. + */ + ERROR_IDV_VALIDATION_MISSING_DOB: 'error.idv.validation.missing.dob', + + /** + * Reason: The IDV detected that the provided document does not contain the issuing country. + * Troubleshooting: Make sure the provided document contains the issuing country. + */ + ERROR_IDV_VALIDATION_MISSING_COUNTRY: 'error.idv.validation.missing.country', + + /** + * Reason: The IDV detected that the provided document does not contain a valid document type. + * Troubleshooting: Make sure the provided document contains a valid document type. + */ + ERROR_IDV_VALIDATION_MISSING_DOC_TYPE: 'error.idv.validation.missing.doc.type', + + /** + * Reason: The IDV detected that the requirements fail. + * Troubleshooting: Make sure the provided document do fit the requirements. + */ + ERROR_IDV_VALIDATION_REQUIREMENTS_FAIL: 'error.idv.validation.requirements.fail', + + /** + * Reason: The data provided by the user is not the same as the one that the IDV got from the document + * Troubleshooting: Make sure the provided data is equal to the data in the document. + */ + ERROR_IDV_VALIDATION_UCA_VALUE_MISMATCH: 'error.idv.validation.uca.value.mismatch', + + /** + * Reason: Missing required property when sending UCAs + * Troubleshooting: Make sure the provided UCA has all the required properties filled. + * Look at the UCA definition to make sure you provided all the values. + */ + ERROR_IDV_UCA_MISSING_PROPERTY: 'error.idv.uca.missing.property', + + /** + * Reason: UCA has no more retries remaining + * Troubleshooting: The maximum number of retries has reached. + * You must request a new credentialRequest and start over again + */ + ERROR_IDV_UCA_NO_RETRIES: 'error.idv.uca.no.retries', + + /** + * Reason: The process is in a final status "FAILED","COMPLETED" + * Troubleshooting: if you got a FINAL state error, + * you must request a new credentialRequest and start over again + */ + ERROR_IDV_PROCESS_HAS_FINAL_STATUS: 'error.idv.process.has.final.status', + + /** + * Reason: The UCA is in a final status + * Troubleshooting: Make sure to change the state of a UCA that is not in the final status. + * you must request a new credentialRequest and start over again + */ + ERROR_IDV_UCA_HAS_FINAL_STATUS: 'error.idv.uca.has.final.status', + + /** + * Reason: A UCA of the batch is in a final status + * Troubleshooting: Make sure to change the state of a UCA that is not in the final status. + */ + ERROR_IDV_UCA_BATCH_HAS_FINAL_STATUS: 'error.idv.uca.batch.has.final.status', + + /** + * Reason: The credentialItem is not valid/unknown to the IDV + * Troubleshooting: Make sure to provide the valid identifier of a credentialItem by checking the plan + */ + ERROR_IDV_CR_INVALID_CREDENTIAL_ITEM: 'error.idv.cr.invalid.credentialItem', + + /** + * Reason: The signature could not be verified + * Troubleshooting: Try to sign again a credential + */ + ERROR_IDV_CREDENTIAL_INVALID_SIGNATURE: 'error.idv.credential.invalid.signature', + + /** + * Reason: The credential has already been signed. + * Troubleshooting: The credential is already signed. You must not sign it again + */ + ERROR_IDV_CR_ALREADY_SIGNED: 'error.idv.cr.already.signed', + + /** + * Reason: The payload is missing a required property + * Troubleshooting: Make sure the payload of a credential contains all the required properties. + * In the error values will be suplied the missing properties + */ + ERROR_IDV_CR_MISSING_PROPERTY: 'error.idv.cr.missing.property', + + /** + * Reason: One of the external services required for phone number validation could not be reached (Authy, Twilio ) + * Troubleshooting: Try again later + */ + ERROR_IDV_UCA_SERVER: 'error.idv.uca.server', + + /** + * Reason: thrown if there are no UCAs in the process or if the UCA specified in the event is missing + * Troubleshooting: Make sure to provide the missing specified UCA + */ + ERROR_IDV_MISSING_UCA: 'error.idv.missing.uca', + + /** + * Reason: UCA is in a wrong version + * Troubleshooting: Make sure you're providing the UCA in the version declared on the plan + */ + ERROR_IDV_UCA_WRONG_VERSION: 'error.idv.uca.wrong.version', + + /** + * Reason: Could not find a validation plan for credential item + * Troubleshooting: Check if you're providing the right validation plan + * and credential item + */ + ERROR_IDV_MISSING_PLAN: 'error.idv.missing.plan', + + /** + * Reason: Could not find process with the provided ID + * Troubleshooting: Check if you're providing the right process id + */ + ERROR_IDV_MISSING_PROCESS: 'error.idv.missing.process', + + /** + * Reason: The value specified for a UCA isn't good for the UCA type + * Troubleshooting: Check the provided UCA value + */ + ERROR_IDV_UCA_BAD_VALUE: 'error.idv.uca.bad.value', + + /** + * Reason: The UCA doesn't have a status in the data store + * Troubleshooting: Try again + */ + ERROR_IDV_UCA_UPDATE_NO_STATUS: 'error.idv.uca.update.no.status', + + /** + * Reason: Unable to determine if the UCA can be updated, because the process it belongs to has no status + * Troubleshooting: Try again + */ + ERROR_IDV_UCA_UPDATE_NO_PROCESS_STATUS: 'error.idv.uca.update.no.process.status', + + /** + * Reason: A token is received before one is issued + * Troubleshooting: Try again + */ + ERROR_IDV_TOKEN_RECEIVED_BEFORE_ISSUE: 'error.idv.token.received.before.issue', + + /** + * Reason: Unable to send the token + * Troubleshooting: Try again + */ + ERROR_IDV_TOKEN_SENDING_FAILED: 'error.idv.token.sending.failed', + + /** + * Reason: The provided token is expired + * Troubleshooting: Request a new token + */ + ERROR_IDV_TOKEN_EXPIRED: 'error.idv.token.expired', + + /** + * Reason: The provided token does not match the generated one + * Troubleshooting: Make sure to provide the received token + */ + ERROR_IDV_TOKEN_MISMATCH: 'error.idv.token.mismatch', + + // CW ERRORS + + /** + * Reason: Thrown when CredentialWallet.validateDsr or CredentialWallet.fetch when a DSR is empty or invalid + * Troubleshooting: Check if the DSR provided is correct and it's not empty + */ + ERROR_CW_DSR_INVALID_SCOPE_REQUEST: 'error.dsr.invalid.scope.request', + + /** + * Reason: IDV has returned 'Bad request' anwser + * Troubleshooting: Check if the value of your UCA is correct or your request params + */ + ERROR_CW_IDV_INVALID_REQUEST: 'error.cw.idv.request.failed.generic.4XX', + + /** + * Reason: IDV has returned unexpected error + * Troubleshooting: Check the attached message + */ + ERROR_CW_IDV_ERROR: 'error.cw.idv.server.failed.generic.5XX', + + /** + * Reason: CW has returned unexpected error + * Troubleshooting: Check the attached message + */ + ERROR_CW_GENERIC: 'error.generic', + + /** + * Reason: DSR is missing 'eventURL' attribute + * Troubleshooting: Provide 'eventURL' attribute + */ + ERROR_CW_DSR_RESPONSE_MISSING_EVENT_URL: 'error.dsr.missing.event.url', + + /** + * Reason: eventType value is not a valid one + * Troubleshooting: Make sure you are providing one of the values: + * CANCELLED, VERIFYING', COMPLETED, + */ + ERROR_CW_DSR_RESPONSE_INVALID_EVENT_TYPE: 'error.dsr.invalid.event.type', + + /** + * Reason: No clientID found while calling LegacyService.getUploadDetails + * Troubleshooting: Make sure LegacyService.legacyDeviceRegistration is being called. + */ + ERROR_CW_CLIENT_ID_NOT_FOUND: 'client.id.not.found', + + /** + * Reason: No certificate found for UCA while calling LegacyService.getCertificatesFor + * Troubleshooting: Make sure there is a certificate saved on localStorage, key 'StorageScope.CERTIFICATE', + * for the related UCA. + */ + ERROR_CW_CERTIFICATE_NOT_FOUND: 'error.certificate.not.found', + + /** + * Reason: Unparsable certificate for UCA while calling getCertificatesFor + * Troubleshooting: Make sure there is a valid certificate saved on localStorage, key 'StorageScope.CERTIFICATE', + * for the related UCA. + */ + ERROR_CW_CERTIFICATE_UNPARSABLE: 'error.certificate.unparsable', + + /** + * Reason: Invalid operator when tried to 'constructHumanReadableForm'. + * Troubleshooting: Make sure the operator is one of the listed ones here: + * @see HumanReadableForm.convertSiftOperator + */ + ERROR_CW_WRONG_QUERY_OPERATOR_SCOPE_REQUEST: 'error.dsr.wrong.sift.operator', + + /** + * Reason: Could not verify credential during build dsr response. + * Troubleshooting: Unexpected error during verifying credential. Check logs and try again. + */ + ERROR_CW_VERIFY_CREDENTIAL: 'error.verify.credential', + + /** + * Reason: Legacy UCA identifier is not valid. + * Troubleshooting: must be one of the followings: + * 'credential-cvc:Email-v1' + * 'credential-cvc:PhoneNumber-v1' + * 'credential-cvc:GenericDocumentId-v1' + * 'credential-cvc:Address-v1' + * 'credential-cvc:Identity-v1' + */ + ERROR_CW_WRONG_UCA_IDENTIFIER: 'error.wrong.uca.identifier', + + /** + * Reason: Legacy Verifiable Credential identifier is not valid. + * Troubleshooting: must be one of the followings: + * 'credential-cvc:Email-v1' + * 'credential-cvc:PhoneNumber-v1' + * 'credential-cvc:GenericDocumentId-v1' + * 'credential-cvc:Address-v1' + * 'credential-cvc:Identity-v1' + */ + ERROR_CW_WRONG_VC_IDENTIFIER: 'error.wrong.credential.identifier', + + /** + * Reason: Verifiable Credential Request was not found. + * Troubleshooting: please check if the provided id is correct. + * Also, this happens only on 'IdvApiServiceLocal'. + * Make sure you want to use that implementation or the 'IdvApiService'. + * You can toggle implementation by setting the flag: disableLegacy = true + */ + ERROR_CW_VCR_NOT_FOUND: 'vcr.not.found', + + /** + * Reason: CredentialRequest is assigned with a wrong status. + * Troubleshooting: It must be either ACCEPTED or ISSUED. + * Also, this happens only on 'IdvApiServiceLocal'. + * Make sure you want to use that implementation or the 'IdvApiService'. + * You can toggle implementation by setting the flag: disableLegacy = true + */ + ERROR_CW_VCR_INVALID_STATE: 'vcr.invalid.state', + + /** + * Reason: Could not retrieve Credential from a Credential Request. + * Troubleshooting: Make sure the Credential Request is ready to check its status + */ + ERROR_CW_VCR_INVALID_CREDENTIAL: 'vcr.invalid.credential', + + /** + * Reason: Provided Credential Request is invalid. + * Troubleshooting: Make sure the provided Credential Request meets the following rules: + * - It's not null + * - Has a 'credentialRequest.idv' attribute + * - Has a 'credentialItem' attribute + * - 'credentialItem' attribute has an 'identifier' + */ + ERROR_CW_VCR_INVALID_REQUEST: 'vcr.invalid.request', + + /** + * Reason: idvService.patchSubjectCredentialRequest has returned null Credential Request + * Troubleshooting: Make sure the provided subject is correct + */ + ERROR_CW_VCR_ERROR_PATCH_SIGNED_SUBJECT: 'vcr.error.patch.signed.subject', + + /** + * Reason: Could not ensure DID extenal key during 'resolveMissingCredentials' + * Troubleshooting: Check the attached error + */ + ERROR_CW_KEY_MANAGER_CANT_ENSURE_KEY: 'key.manager.cant.ensure.key', + + /** + * Reason: Unexpected error during communication with CW backend + * Troubleshooting: Check the attached error + */ + ERROR_CW_NETWORK_GENERIC: 'error.network.generic', + + /** + * Reason: Unexpected error during communication with any endpoint that should be retried + * Troubleshooting: Retry the network call again + */ + ERROR_RETRYABLE_NETWORK_ERROR: 'error.retryable.network' + +}; + +/** + * Enum for ErrorContextTypes + * @readonly + * @enum { string } + */ +const ErrorContextTypes = { + MISSING_PROPERTY: 'missing_property', + UCA_STATE: 'uca_state', + UCA_VALUE: 'uca_value', + UCA_VERSION: 'uca_version', + PLAN_UCA_VERSION: 'plan_uca_version', + PROCESS_ID: 'process_id', + UCA_NAME: 'uca_name', + UCA_ID: 'uca_id', + CREDENTIAL_ITEM: 'credential_item', + UCA_ERROR: 'uca_error' +}; + +module.exports = { + ErrorCodes, + ErrorContextTypes +}; \ No newline at end of file diff --git a/dist/es/errors/idvErrors.js b/dist/es/errors/idvErrors.js new file mode 100644 index 00000000..5f3277c9 --- /dev/null +++ b/dist/es/errors/idvErrors.js @@ -0,0 +1,32 @@ +const _ = require('lodash'); +const { ErrorCodes, ErrorContextTypes } = require('./definitions'); + +// These codes are passed in the 'name' value of the error object when the IDV-toolkit +// throws an error +// @deprecated - left here for retrofit, use ErrorConstants instead for future versions +const IDVErrorCodes = _.pickBy(ErrorCodes, (v, k) => k.startsWith('ERROR_IDV')); + +/* +* IDVError parses a HTTP Error response body from the IDV-toolkit +* Usage: the IDVError can be instantiated directly from the HTTPResponse body e.g. +* const idvError = new IDVError(response.body); +* @param errorObj: parsed directly from the HTTP Response body which should contain +* message: human readable explanation of the error e.g. 'Missing required UCA fields' +* name: Error-Code, defined in IDVErrorCodes, e.g. IDVErrorCodes.ERROR_IDV_UCA_MISSING_PROPERTY +* data: an array of objects with { name: "name", value: "value" } properties e.g. +* [{ name: ErrorContextType.MISSING_PROPERTY, value: missingProperty }] +* @returns an instance of IDVError +* */ +class IDVError { + constructor(errorObj) { + this.message = errorObj.message; + this.errorCode = errorObj.name; + this.errorContext = errorObj.data; + } +} + +module.exports = { + IDVErrorCodes, + ErrorContextTypes, + IDVError +}; \ No newline at end of file diff --git a/dist/es/errors/index.js b/dist/es/errors/index.js new file mode 100644 index 00000000..585a934b --- /dev/null +++ b/dist/es/errors/index.js @@ -0,0 +1,8 @@ +const idvErrors = require('./idvErrors'); +const { ErrorCodes, ErrorContextTypes } = require('./definitions'); + +module.exports = { + ErrorCodes, + ErrorContextTypes, + idvErrors // For retrofit, will be deprecated on the future +}; \ No newline at end of file diff --git a/dist/es/index.js b/dist/es/index.js new file mode 100644 index 00000000..bcfa7c19 --- /dev/null +++ b/dist/es/index.js @@ -0,0 +1,33 @@ +const { Claim } = require('./claim/Claim'); +const VC = require('./creds/VerifiableCredential'); +const { initServices, services } = require('./services/index'); +const isValidGlobalIdentifier = require('./isValidGlobalIdentifier'); +const isClaimRelated = require('./isClaimRelated'); +const errors = require('./errors'); +const constants = require('./constants'); +const claimDefinitions = require('./claim/definitions'); +const credentialDefinitions = require('./creds/definitions'); +const aggregate = require('./AggregationHandler'); + +/** + * Entry Point for Civic Credential Commons + * @returns {CredentialCommons} + * @constructor + */ +function CredentialCommons() { + this.Claim = Claim; + this.VC = VC; + this.init = initServices; + this.isValidGlobalIdentifier = isValidGlobalIdentifier; + this.isClaimRelated = isClaimRelated; + this.services = services; + this.aggregate = aggregate; + this.errors = errors; + this.constants = constants; + this.claimDefinitions = claimDefinitions; + this.credentialDefinitions = credentialDefinitions; + return this; +} + +// to work with entry points in multi module manage the best way +module.exports = new CredentialCommons(); \ No newline at end of file diff --git a/dist/es/isClaimRelated.js b/dist/es/isClaimRelated.js new file mode 100644 index 00000000..e131c4d1 --- /dev/null +++ b/dist/es/isClaimRelated.js @@ -0,0 +1,39 @@ +const _ = require('lodash'); +const { definitions, Claim } = require('./claim/Claim'); +const vcDefinitions = require('./creds/definitions'); +/** + * Validate an claim path against it's parent UserCollectableAttribute, and the parent Claim against the + * dependencies of an Credential + * @param claim path, eg: name.first + * @param uca the global identifier for the UCA/Claim, eg: claim-civ:Identity:name-1 + * @param credential the parent identifier, eg: civ:Credential:GenericId + * @return true if the dependency exists and false if it doesn't + */ +function isClaimRelated(claim, uca, credential) { + // first get the UCA identifier + const ucaIdentifier = uca.substring(uca.indexOf('-') + 1, uca.lastIndexOf('-')); + // check on the credential commons if this identifier exists + const ucaDefinition = definitions.find(definition => definition.identifier === ucaIdentifier); + // does the UCA exist? + if (ucaDefinition) { + const ucaProperties = Claim.getAllProperties(ucaIdentifier); + + // does the claim exists in the Claim? + if (_.includes(ucaProperties, claim)) { + // we now have the composite uca, the uca for the claim property, they both are correct + // we need to check now the UCA is inside the dependencies of the credential refered as parent + const credentialDefinition = vcDefinitions.find(definition => definition.identifier === credential); + if (credentialDefinition) { + return _.includes(credentialDefinition.depends, ucaIdentifier); + } + throw new Error('Credential identifier does not exist'); + } else { + throw new Error('Claim property path does not exist on UCA definitions'); + } + } else { + // return error about wrong uca identifier + throw new Error('UCA identifier does not exist'); + } +} + +module.exports = isClaimRelated; \ No newline at end of file diff --git a/dist/es/isValidGlobalIdentifier.js b/dist/es/isValidGlobalIdentifier.js new file mode 100644 index 00000000..a8b8bad8 --- /dev/null +++ b/dist/es/isValidGlobalIdentifier.js @@ -0,0 +1,38 @@ +const _ = require('lodash'); +const { definitions } = require('@identity.com/uca'); +const vcDefinitions = require('./creds/definitions'); +const claimDefinitions = require('./claim/definitions'); + +const validUCAIdentifiers = _.map(definitions, d => d.identifier); +const validClaimIdentifiers = _.map(claimDefinitions, d => d.identifier); +const validVCIdentifiers = _.map(vcDefinitions, d => d.identifier); +const validPrefixes = ['claim', 'credential']; + +function isValidGlobalIdentifier(identifier) { + const splited = _.split(identifier, '-'); + + if (splited.length !== 3) { + throw new Error('Malformed Global Identifier'); + } + + if (!_.includes(validPrefixes, splited[0])) { + throw new Error('Invalid Global Identifier Prefix'); + } + + switch (splited[0]) { + case 'claim': + if (!_.includes(validUCAIdentifiers, splited[1]) && !_.includes(validClaimIdentifiers, identifier)) { + throw new Error(`${identifier} is not valid`); + } + return true; + case 'credential': + if (!_.includes(validVCIdentifiers, splited[1]) && !_.includes(validVCIdentifiers, identifier)) { + throw new Error(`${identifier} is not valid`); + } + return true; + default: + return false; + } +} + +module.exports = isValidGlobalIdentifier; \ No newline at end of file diff --git a/dist/es/lib/crypto.js b/dist/es/lib/crypto.js new file mode 100644 index 00000000..e2dac3e8 --- /dev/null +++ b/dist/es/lib/crypto.js @@ -0,0 +1,7 @@ +const sjcl = require('sjcl'); + +const sha256 = stringToHash => sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(stringToHash)); + +module.exports = { + sha256 +}; \ No newline at end of file diff --git a/dist/es/logger.js b/dist/es/logger.js new file mode 100644 index 00000000..5569f055 --- /dev/null +++ b/dist/es/logger.js @@ -0,0 +1,11 @@ +const { createLogger, format, transports } = require('winston'); + +// Configure the Winston logger. For the complete documentation see https://github.com/winstonjs/winston +const logger = createLogger({ + // To see more detailed errors, change this to 'debug' + level: 'info', + format: format.combine(format.splat(), format.simple()), + transports: [new transports.Console()] +}); + +module.exports = logger; \ No newline at end of file diff --git a/dist/es/schemas/generator/SchemaGenerator.js b/dist/es/schemas/generator/SchemaGenerator.js new file mode 100644 index 00000000..f6fc731f --- /dev/null +++ b/dist/es/schemas/generator/SchemaGenerator.js @@ -0,0 +1,255 @@ +/* eslint-disable no-use-before-define */ +const _ = require('lodash'); +const randomString = require('randomstring'); +const Type = require('type-of-is'); +const RandExp = require('randexp'); +const { UserCollectableAttribute: UCA, definitions: ucaDefinitions } = require('@identity.com/uca'); +const { Claim, definitions, getBaseIdentifiers } = require('../../claim/Claim'); + +const DRAFT = 'http://json-schema.org/draft-07/schema#'; + +const getPropertyNameFromDefinition = definition => getBaseIdentifiers(definition.identifier).identifierComponents[2]; + +const getPropertyType = value => Type.string(value).toLowerCase(); + +const processObject = (object, outputParam, parentKey) => { + const output = outputParam || {}; + const objectProperties = object; + const { definition } = objectProperties; + delete objectProperties.definition; + + output.type = getPropertyType(objectProperties); + output.properties = output.properties || {}; + const keys = Object.entries(objectProperties); + + // too much debate on this eslint + // https://github.com/airbnb/javascript/issues/1122 + // eslint-disable-next-line no-restricted-syntax + for (const [key, value] of keys) { + // we have to get the required array from the definitions properties + + const type = getPropertyType(value); + if (type === 'object') { + output.properties[key] = processObject(value, output.properties[key], `${parentKey}.${key}`); + } else if (type === 'array') { + // recursion + // eslint-disable-next-line + output.properties[key] = processArray(value, output.properties[key], key); + } else { + output.properties[key] = {}; + output.properties[key].type = type === 'null' ? ['null', 'string'] : type; + if (definition && definition.type.properties) { + let propType = definition.type.properties.find(prop => prop.name === key); + // simple composite, one depth level civ:Identity.name for example + if (propType && propType.type.includes(':')) { + propType = definitions.find(def => def.identifier === propType.type); + } + + output.properties[key] = addMinimumMaximum(propType, output.properties[key]); + } else { + output.properties[key] = addMinimumMaximum(definition, output.properties[key]); + } + } + } + // it must be 4 here, we start the json of the VC with root + // then it's claim, then all standardize Claim are type:name + if (parentKey.includes('claim') && parentKey.split('.').length === 4) { + // with the json key of the claim + const baseUcaName = parentKey.substring('root.claim.'.length); + let typeName = (baseUcaName.substring(0, 1).toUpperCase() + baseUcaName.substring(1)).replace('.', ':'); + // regenerate uca + let refDefinition = definitions.find(def => def.identifier.includes(typeName)); + if (refDefinition == null) { + const baseName = baseUcaName.substring(0, 1).toUpperCase() + baseUcaName.substring(1); + typeName = `claim-cvc:${baseName}-v1`; + refDefinition = definitions.find(def => def.identifier.includes(typeName)); + } + if (refDefinition == null) { + typeName = `claim-cvc:${baseUcaName}-v1`; + refDefinition = definitions.find(def => def.identifier.includes(typeName)); + } + // get it's required definitions + output.required = refDefinition.type.required; + } + output.additionalProperties = false; + return output; +}; + +const processArray = (array, outputParam) => { + const output = outputParam || {}; + output.type = getPropertyType(array); + output.items = output.items || {}; + const type = getPropertyType(array[0]); + output.items.type = type; + output.additionalProperties = false; + return output; +}; + +/** + * Entry point of this class. Use this to generate an sample json data + * then an json schema from that data. That way you do not need to + * create sample or mocks json from Credentials + * + * @param definition Claim/VC definition + * @param json generated json + * @returns {{$schema: string}} expected json schema to validate this data + */ +const process = (definition, json) => { + const object = json; + const title = definition.identifier; + let processOutput; + const output = { + $schema: DRAFT + }; + output.title = title; + // Set initial object type + output.type = Type.string(object).toLowerCase(); + + // Process object + if (output.type === 'object') { + processOutput = processObject(object, {}, 'root'); + output.type = processOutput.type; + output.properties = processOutput.properties; + } + + // never allow additionalProperties + output.additionalProperties = false; + // Output + return output; +}; + +/** + * Build a sample json from an definition identifier + * Recursively make the Claim from nested properties and Claim references + * + * @param definition receive an Claim and build an sample json from it's properties + * @returns {{$schema: string}} + */ +const buildSampleJson = (definition, includeDefinitions = false) => { + let output = {}; + output = makeJsonRecursion(definition, includeDefinitions); + return output; +}; + +/** + * Recursion to build the schema from an json value + * @param ucaDefinition + */ +const makeJsonRecursion = (ucaDefinition, includeDefinitions = false) => { + let output = {}; + const typeName = Claim.getTypeName(ucaDefinition); + if (typeof ucaDefinition.type === 'object' && ucaDefinition.type.properties !== undefined) { + // array of properties + ucaDefinition.type.properties.forEach(property => { + output[property.name] = generateRandomValueForType(property, includeDefinitions); + }); + } else if (typeName === 'Array') { + const itemType = ucaDefinition.items.type; + const itemDefinition = _.find(definitions, { identifier: itemType }); + output = [makeJsonRecursion(itemDefinition, includeDefinitions)]; + } else if (typeName !== 'Object') { + // not a reference + const propertyName = getPropertyNameFromDefinition(ucaDefinition); + if (typeof ucaDefinition.pattern !== 'undefined' && ucaDefinition.pattern !== null) { + output[propertyName] = new RandExp(ucaDefinition.pattern).gen(); + } else { + output[propertyName] = generateRandomValueForType(ucaDefinition, includeDefinitions); + } + } else { + // a direct reference to a composite type + output = generateRandomValueForType(ucaDefinition, includeDefinitions); + } + if (includeDefinitions && output.definition == null) { + output.definition = ucaDefinition; + } + return output; +}; + +/** + * This method is an auxiliary method to allow random values to easy create + * json schemas from JSON values generated from Claim/VC + * + * @param definition + * @returns {number} + */ +const generateRandomNumberValueWithRange = definition => { + let genRandomNumber = Math.random() * 100; + + if (definition !== null) { + if (typeof definition.minimum !== 'undefined' && definition.minimum !== null && genRandomNumber < definition.minimum) { + genRandomNumber = definition.minimum; + } + + if (definition.exclusiveMinimum !== 'undefined' && definition.exclusiveMinimum !== null && genRandomNumber <= definition.exclusiveMinimum) { + genRandomNumber = definition.exclusiveMinimum + 0.1; + } + + if (typeof definition.maximum !== 'undefined' && definition.maximum !== null && genRandomNumber > definition.maximum) { + genRandomNumber = definition.maximum; + } + + if (definition.exclusiveMaximum !== 'undefined' && definition.exclusiveMaximum !== null && genRandomNumber >= definition.exclusiveMaximum) { + genRandomNumber = definition.exclusiveMaximum - 0.1; + } + } + + return genRandomNumber; +}; + +const generateRandomValueForType = (definition, includeDefinitions = false) => { + const typeName = definition.type; + let refDefinition = definition; + let resolvedTypeName = typeName; + if (typeName.includes(':')) { + // simple composite, one depth level civ:Identity.name for example + refDefinition = definitions.find(def => def.identifier === typeName); + if (refDefinition != null) { + resolvedTypeName = Claim.resolveType(refDefinition); + } else { + refDefinition = ucaDefinitions.find(def => def.identifier === typeName); + if (refDefinition) { + resolvedTypeName = UCA.resolveType(refDefinition); + } + } + } + // generate sample data + // that's why the magic numbers are here + switch (resolvedTypeName) { + case 'String': + if (refDefinition.enum) { + return _.values(refDefinition.enum)[0]; + } + return refDefinition && refDefinition.pattern ? new RandExp(refDefinition.pattern).gen() : randomString.generate(10); + case 'Number': + return generateRandomNumberValueWithRange(refDefinition); + case 'Boolean': + return Math.round(Math.random()) === 1; + default: + return makeJsonRecursion(refDefinition, includeDefinitions); + } +}; + +const addMinimumMaximum = (definition, object) => { + const output = object; + // for simple Claim get json schema properties + if (typeof definition !== 'undefined' && definition !== null) { + if (definition.exclusiveMinimum != null) { + output.exclusiveMinimum = definition.exclusiveMinimum; + } + + if (definition.minimum != null) { + output.minimum = definition.minimum; + } + + if (definition.exclusiveMaximum != null) { + output.exclusiveMaximum = definition.exclusiveMaximum; + } + + if (definition.maximum != null) { + output.maximum = definition.maximum; + } + } + return output; +}; + +module.exports = { process, buildSampleJson }; \ No newline at end of file diff --git a/dist/es/services/DefaultAnchorServiceImpl.js b/dist/es/services/DefaultAnchorServiceImpl.js new file mode 100644 index 00000000..9a57575d --- /dev/null +++ b/dist/es/services/DefaultAnchorServiceImpl.js @@ -0,0 +1,124 @@ +/** + * Current Anchor/Attester service + * + */ +const uuid = require('uuid/v4'); +const { HDNode, ECSignature } = require('bitcoinjs-lib'); +const sjcl = require('sjcl'); +const logger = require('../logger'); + +/** + * An Anchor/Attester implementation + * + * @param {*} config + * @param {*} http + */ +function DummyAnchorServiceImpl(config, http) { + this.config = config; + this.http = http; + const pollService = async statusUrl => { + try { + const attestation = await this.http.request({ + url: statusUrl, + method: 'GET', + simple: true, + json: true + }); + + if (!attestation || !attestation.type) { + // eslint-disable-next-line no-unused-vars + return await pollService(statusUrl); + } + if (attestation && attestation.type !== 'permanent') { + attestation.statusUrl = statusUrl; + return attestation; + } + return attestation; + } catch (error) { + logger.error(`Error polling: ${statusUrl}`, JSON.stringify(error, null, 2)); + throw new Error(`Error polling: ${statusUrl}`); + } + }; + + this.anchor = async (options = {}) => Promise.resolve({ + subject: { + pub: 'xpub:dummy', + label: options.subject && options.subject.label ? options.subject.label : null, + data: options.subject && options.subject.data ? options.subject.data : null, + signature: 'signed:dummy' + }, + walletId: 'none', + cosigners: [{ + pub: 'xpub:dummy' + }, { + pub: 'xpub:dummy' + }], + authority: { + pub: 'xpub:dummy', + path: '/' + }, + coin: 'dummycoin', + tx: uuid(), + network: 'dummynet', + type: 'temporary', + civicAsPrimary: false, + schema: 'dummy-20180201' + }); + + this.update = async tempAnchor => { + tempAnchor.type = 'permanent'; // eslint-disable-line + tempAnchor.value = new uuid(); // eslint-disable-line + return Promise.resolve(tempAnchor); + }; + + this.verifySignature = (proof, pinnedPubKey) => { + const { subject } = proof.anchor; + const anchorSubjectValidation = this.verifySubjectSignature(subject, pinnedPubKey); + return anchorSubjectValidation && subject.data === proof.merkleRoot; + }; + + /** + * This method checks if the subject signature matches the pub key + * @param subject a json with label, data, signature, pub + * @returns {*} true or false for the validation + */ + this.verifySubjectSignature = (subject, pinnedPubKey) => { + // Do not use JS destruct on the next line, We need to predict the JSON order + const toHash = JSON.stringify({ xpub: subject.pub, label: subject.label, data: subject.data }); + const hash = sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(toHash)); + const subjectSignature = ECSignature.fromDER(Buffer.from(subject.signature, 'hex')); + return HDNode.fromBase58(pinnedPubKey || subject.pub).keyPair.verify(Buffer.from(hash, 'hex'), subjectSignature); + }; + + /** + * This method checks that the attestation / anchor exists on the BC + */ + this.verifyAttestation = async (proof, offline = true) => { + const path = '/proof'; + const endpoint = `${this.config.attestationService}${path}`; + + const requestOptions = { + url: endpoint, + body: { attestation: proof.anchor, offline }, + method: 'POST', + json: true, + simple: true // reject if not 2XX + }; + + const response = await this.http.request(requestOptions); + return response.valid; + }; + + this.revokeAttestation = async signature => { + signature.revoked = true; // eslint-disable-line + return Promise.resolve(signature); + }; + + this.isRevoked = signature => signature.revoked ? signature.revoked : false; + + return this; +} + +module.exports = { + CurrentCivicAnchor: DummyAnchorServiceImpl +}; \ No newline at end of file diff --git a/dist/es/services/DummyAnchorServiceImpl.js b/dist/es/services/DummyAnchorServiceImpl.js new file mode 100644 index 00000000..580e4e1b --- /dev/null +++ b/dist/es/services/DummyAnchorServiceImpl.js @@ -0,0 +1,100 @@ +/** + * Current Anchor/Attester service + * + */ +const uuid = require('uuid/v4'); +const logger = require('../logger'); + +/** + * An Anchor/Attester implementation + * + * @param {*} config + * @param {*} http + */ +function DummyAnchorServiceImpl(config, http) { + this.config = config; + this.http = http; + const pollService = async statusUrl => { + try { + const attestation = await this.http.request({ + url: statusUrl, + method: 'GET', + simple: true, + json: true + }); + + if (!attestation || !attestation.type) { + // eslint-disable-next-line no-unused-vars + return await pollService(statusUrl); + } + if (attestation && attestation.type !== 'permanent') { + attestation.statusUrl = statusUrl; + return attestation; + } + return attestation; + } catch (error) { + logger.error(`Error polling: ${statusUrl}`, JSON.stringify(error, null, 2)); + throw new Error(`Error polling: ${statusUrl}`); + } + }; + + this.anchor = async (options = {}) => Promise.resolve({ + subject: { + pub: 'xpub:dummy', + label: options.subject && options.subject.label ? options.subject.label : null, + data: options.subject && options.subject.data ? options.subject.data : null, + signature: 'signed:dummy' + }, + walletId: 'none', + cosigners: [{ + pub: 'xpub:dummy' + }, { + pub: 'xpub:dummy' + }], + authority: { + pub: 'xpub:dummy', + path: '/' + }, + coin: 'dummycoin', + tx: new uuid(), // eslint-disable-line + network: 'dummynet', + type: 'temporary', + civicAsPrimary: false, + schema: 'dummy-20180201' + }); + + this.update = async tempAnchor => { + // eslint-disable-next-line no-param-reassign + tempAnchor.type = 'permanent'; + // eslint-disable-next-line no-param-reassign + tempAnchor.value = uuid(); + return Promise.resolve(tempAnchor); + }; + + this.verifySignature = () => true; + + /** + * This method checks if the subject signature matches the pub key + * @returns {*} true or false for the validation + */ + this.verifySubjectSignature = () => true; + + /** + * This method checks that the attestation / anchor exists on the BC + */ + this.verifyAttestation = async () => true; + + this.revokeAttestation = async signature => { + // eslint-disable-next-line no-param-reassign + signature.revoked = true; + return Promise.resolve(signature); + }; + + this.isRevoked = signature => signature.revoked ? signature.revoked : false; + + return this; +} + +module.exports = { + CurrentCivicAnchor: DummyAnchorServiceImpl +}; \ No newline at end of file diff --git a/dist/es/services/MiniCryptoManagerImpl.js b/dist/es/services/MiniCryptoManagerImpl.js new file mode 100644 index 00000000..d1f949a0 --- /dev/null +++ b/dist/es/services/MiniCryptoManagerImpl.js @@ -0,0 +1,81 @@ +const { HDNode, ECSignature } = require('bitcoinjs-lib'); + +/** + * MiniCryptoManagerImpl - A minimal CryptoManagerImpl for the portable CryptoManagerInterface + * to provide only default sign() and verify() functions to credential-commons with minimal dependencies. + * + * Particularities of this Mini Implementation: + * + * 1. Only sign() and verify() function are available; + * + * 2. This implementation is based on HDNode key material from bitcoinjs library; + * + * 3. There is a volatile in memory only Storage Implementation to allow `installKey()`. + * You should `installKey` a PVT key or a PUB key (verify only) before call `sign()` or `verify()`. + * The installed key is removed after `sign()` or `verify()` function was called. + */ +class MiniCryptoManagerImpl { + constructor() { + this.KEY_STORAGE = {}; + } + + /** + * Install a pvt or a pub key on a keyName to be used on `sign()` or `verify()` function later. + * @param {} keyName - name of the key to be installed. + * @param {} key - a pvt or a pub key in base58 format. + */ + installKey(keyName, key) { + try { + // Test if key is a valid HDNode key + HDNode.fromBase58(key); + this.KEY_STORAGE[keyName] = key; + } catch (err) { + throw new Error(`Invalid key format: ${err.message}`); + } + } + + /** + * Return input data signed using the specified key. + * + * Signature return value will be to be a DER encoded value. + * + * @param { string } keyName - name of the key to be used to sign. + * @param { string } hexHash - hex string representation of the hash + */ + sign(keyName, hexHash) { + const privateKey = this.KEY_STORAGE[keyName]; + const keyPair = HDNode.fromBase58(privateKey); + + const hash = Buffer.from(hexHash, 'hex'); + const signature = keyPair.sign(hash); + const hexSignature = signature.toDER().toString('hex'); + + // keys are volatile in this impl, removes + delete this.KEY_STORAGE[keyName]; + + return hexSignature; + } + + /** + * Return true if signature has been verified, false otherwise. + * + * @param { string } keyName - name of the key to be used to verify signature. + * @param { string } hexHash - hex string representation of the hash + * @param { string } hexSignature - DER encoded signature. + */ + verify(keyName, hexHash, hexSignature) { + const key = this.KEY_STORAGE[keyName]; + const keyPair = HDNode.fromBase58(key); + + const hash = Buffer.from(hexHash, 'hex'); + const signature = Buffer.from(hexSignature, 'hex'); + const ecSignature = ECSignature.fromDER(signature); + + // keys are volatile in this impl, removes + delete this.KEY_STORAGE[keyName]; + + return keyPair.verify(hash, ecSignature); + } +} + +module.exports = MiniCryptoManagerImpl; \ No newline at end of file diff --git a/dist/es/services/__mocks__/httpService.js b/dist/es/services/__mocks__/httpService.js new file mode 100644 index 00000000..c47062e0 --- /dev/null +++ b/dist/es/services/__mocks__/httpService.js @@ -0,0 +1,68 @@ +/* eslint-disable max-len */ + +const _ = require('lodash'); +const logger = require('../../logger'); + +function HttpServiceConstructor() { + this.name = 'mockHttp'; + this.request = async (uri, options) => { + logger.debug(`Mocking request for: ${JSON.stringify({ uri, options }, null, 2)}`); + const params = _.isString(uri) ? { url: uri } : uri; + _.assign(params, options); + const responses = [{ + path: '/registry', + response: { + clientID: '6e0ce9b31eb13064a194c1482ed3d9d330f22df6fb4cbcc0dbebf3169dc2325b', + xpub: '0469919359510a703516503299c77ef0e00f18255a32db19a3e69636e203f25f29be24b685df9f8a70548751f53a2e4c235ec0fbdc82d0783bd30e315ebfd6bd1e', + cas: '{"iv":"TEtgZuJdyJFkgcuHoBC52w==","v":1,"iter":10000,"ks":128,"ts":64,"mode":"gcm","adata":"","cipher":"aes","salt":"SA0z5h6IlfA=","ct":"8h6ys3fD31HsWH3s5rrbF6o54ekJf6owhSJBW6FBIhkftJWSWVWVEt0u0FJFqhCqPaEl+DMM6olH9fAcB7bD7i2DRPjLYiC+"}', + sak: {} + } + }, { + path: '/jwt', + response: { jwt: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJqdGkiOiIyYzdlNjQ4YS1hNDhmLTQxNTgtOGZmMS02MTY0YzM5OWNlNDMiLCJpYXQiOjE1Mjg4MjE1ODUuNDM0LCJleHAiOjE1Mjg4MjE3NjUuNDM0LCJpc3MiOiJodHRwczovL2FwaS5jaXZpYy5jb20vand0IiwiYXVkIjoiQXR0ZXN0ZXJTZXJ2aWNlIiwic3ViIjoiYzhhNjRhODE4NWRlMzNkMTlkZTgwMjFmYmUyMjhkMmE1YTc3YzExMTdkYjc1NDJlZDE0ODM1NGNiZjdkNGVmMSIsImRhdGEiOnsibWV0aG9kIjoiUE9TVCIsInBhdGgiOiJodHRwczovL2Rldi5hcGkuY2l2aWMuY29tL3JlcXVlc3QtYXR0ZXN0YXRpb24tdGJjaC9yZXF1ZXN0QXR0ZXN0YXRpb24ifX0.2Rp8XLTLvzu51raTQRpce8kIiilsMeiPZeWAsuNv5n7hFZGl-ce-fx9DgxsZ0OTaIUgo8frbiGmHjQh0WlUG7A' } + }, { + path: '/requestAttestation', + response: { statusUrl: '/status/372091f0-6e5f-11e8-ab04-8d6f9c9b4e5a' } + }, { + path: '/requestAttestation', + response: { statusUrl: '/status/372091f0-6e5f-11e8-ab04-8d6f9c9b4e5a' } + }, { + path: '/status', + response: { + schema: 'dummy-20180201', + tx: '01000000018815822815dbd6c355ad47af5d753a00000000fc00473044022042426820da1f2fac328a408d538638143177168b575da66825bc99a3f487472baa0751b67355407b4a4e99da04a3186c520220578b820dd051c919c2fb57b26aa29667483b547f6766a23e3c821e47a5d1237b0147304402201316cc0ee8a968f4d86a616fcf710b663e0bb7021e95d7a300036b65e95ca34602204f05162db06278af2a8abdd7ab4d92e973dc4154a92bf37a4056f3298fa9ecad014c695221028f9205846d9b23dd9a17588ae13603aa3eda3599582750904716c827d02269db210340f8f56a56b2af2a9698f66574882068cf8bd8fa95a26136ac34edabfe5eb5d021029d52d336232eb3d4f37730822df9d3993a84c3edba20f14d3ee0f20141c0bdfd53aeffffffff01551500000000000017a91460312cbbb8ec560305a239d56398f0d8aa57ecf68700000000', + subject: { + label: 'teste', + pub: 'xpub:dummy', + data: 'testesdsd', + signature: '304502210089e94f11587bf7fa202817ace9664639855a146565d4e54b9f853f31f4d7ce31022077098a904e0dda7ab947db92a3e7dd7a5d52654c286151c3cc97feb0ef4a3310' + }, + authority: { + pub: 'xpub:dummy', + path: '/' + }, + cosigners: [{ + pub: 'xpub:dummy' + }, { + pub: 'xpuv:dummy' + }], + type: 'temporary', + network: 'testnet' + } + + }]; + const res = _.find(responses, r => _.includes(params.url, r.path)); + if (res) { + return Promise.resolve(res.response); + } + return Promise.reject(); + }; + return this; +} + +logger.debug('Using Mock HTTP Service'); +const http = new HttpServiceConstructor(); +http.request('/status').then(console.log); // eslint-disable-line +logger.debug(`HTTP Service instance ${JSON.stringify(http, null, 2)}`); + +module.exports = http; \ No newline at end of file diff --git a/dist/es/services/anchorService.js b/dist/es/services/anchorService.js new file mode 100644 index 00000000..49b915d1 --- /dev/null +++ b/dist/es/services/anchorService.js @@ -0,0 +1,18 @@ +/** + * Abstract Anchor/Attestation service + * + * @param {*} impl + */ +function Anchor(impl) { + this.impl = impl; + this.anchor = (label, data, options) => this.impl.anchor(label, data, options); + this.update = tempAnchor => this.impl.update(tempAnchor); + this.verifySignature = subject => this.impl.verifySignature(subject); + this.verifySubjectSignature = subject => this.impl.verifySubjectSignature(subject); + this.verifyAttestation = signature => this.impl.verifyAttestation(signature); + this.revokeAttestation = signature => this.impl.revokeAttestation(signature); + this.isRevoked = signature => this.impl.isRevoked(signature); + return this; +} + +module.exports = Anchor; \ No newline at end of file diff --git a/dist/es/services/config.js b/dist/es/services/config.js new file mode 100644 index 00000000..5a6c787a --- /dev/null +++ b/dist/es/services/config.js @@ -0,0 +1,48 @@ +const path = require('path'); +const os = require('os'); +const fs = require('fs'); + +const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined'; + +if (process.platform === 'win32') throw new Error(`Unsupported platform: ${process.platform}`); + +if (process.env.APP_ENV !== 'browser' && !isBrowser) { + const CONFIG_FILE = 'config'; + + const CONFIG_PATH = { + BOX: '/etc/civic', + USER: path.join(`${os.homedir()}`, '.civic') + }; + + const userConfigFile = path.join(CONFIG_PATH.USER, CONFIG_FILE); + const boxConfigFile = path.join(CONFIG_PATH.BOX, CONFIG_FILE); + + const configFile = fs.existsSync(userConfigFile) ? userConfigFile : boxConfigFile; + + /* eslint-disable global-require */ + if (fs.existsSync(userConfigFile)) { + require('dotenv').config({ + path: configFile + }); + } + /* eslint-ebable global-require */ +} + +const config = { + sipSecurityService: process.env.CIVIC_SEC_URL, + attestationService: process.env.CIVIC_ATTN_URL, + clientConfig: { + id: process.env.CIVIC_CLIENT_ID, + signingKeys: { + hexpub: process.env.CIVIC_CLIENT_XPUB, + hexsec: process.env.CIVIC_CLIENT_XPRV + } + }, + passphrase: process.env.CIVIC_PASSPHRASE, + keychain: { prv: process.env.CIVIC_KEYCHAIN }, + accessToken: process.env.CLIENT_ACCESS_TOKEN, + walletId: process.env.CLIENT_WALLET_ID, + walletPassphrase: process.env.CLIENT_WALLET_PASSPHRASE +}; + +module.exports = config; \ No newline at end of file diff --git a/dist/es/services/httpService.js b/dist/es/services/httpService.js new file mode 100644 index 00000000..b190f00d --- /dev/null +++ b/dist/es/services/httpService.js @@ -0,0 +1,16 @@ +/** + * A simple node HTTP services + */ +const request = require('request-promise-native'); +// uncomment to debug requests +// require('request-debug')(request); + +function HttpServiceConstructor() { + this.request = async (uri, options) => { + const response = await request(uri, options); + return response; + }; + return this; +} + +module.exports = HttpServiceConstructor; \ No newline at end of file diff --git a/dist/es/services/index.js b/dist/es/services/index.js new file mode 100644 index 00000000..e0b0b80e --- /dev/null +++ b/dist/es/services/index.js @@ -0,0 +1,56 @@ +/** + * Services IoC modules + */ +const Bottle = require('bottlejs'); +const { CurrentCivicAnchor } = require('./DefaultAnchorServiceImpl.js'); +const logger = require('../logger'); +const HttpServiceConstructor = require('./httpService'); +const config = require('./config'); +const SecureRandom = require('../SecureRandom'); +const MiniCryptoManagerImpl = require('./MiniCryptoManagerImpl'); + +const services = new Bottle(); + +/** + * Init services with new values to config and http services + * @param {*} conf + * @param {*} http + * @param secureRandom + */ +const initServices = (conf, http, secureRandom, cryptoManagerImpl) => { + if (http) { + services.resetProviders(['Http']); + logger.debug('Registering custom HTTP service implementation'); + services.factory('Http', () => http); + } + if (conf) { + services.resetProviders(['Config']); + logger.debug('Registering custom Config service implementation'); + services.factory('Config', () => conf); + } + if (secureRandom) { + services.resetProviders(['SecureRandom']); + logger.debug('Registering custom SecureRandom service implementation'); + services.factory('SecureRandom', () => secureRandom); + } + if (cryptoManagerImpl) { + services.resetProviders(['CryptoManager']); + logger.debug('Registering custom CryptoManager service implementation'); + services.factory('CryptoManager', () => cryptoManagerImpl); + } + return services; +}; + +services.factory('Config', () => config); + +logger.info('Registering request-promise-native as Http service implementation.'); +services.service('Http', HttpServiceConstructor); + +services.factory('SecureRandom', () => new SecureRandom()); + +services.service('AnchorService', CurrentCivicAnchor, 'Config', 'Http'); + +// The default CryptoManager Implementation +services.service('CryptoManager', MiniCryptoManagerImpl); + +module.exports = { services, initServices }; \ No newline at end of file diff --git a/dist/es/timeHelper.js b/dist/es/timeHelper.js new file mode 100644 index 00000000..76184995 --- /dev/null +++ b/dist/es/timeHelper.js @@ -0,0 +1,35 @@ +const moment = require('moment-mini'); + +const unitMapper = { + y: 'y', + m: 'M', + w: 'w', + d: 'd' +}; + +/** + * Convert a delta string like "21y" to a moment Duration object + * @param delta + * @return {moment.Duration} + */ +const timeDeltaToMomentDuration = delta => { + const matched = delta.match(/(-?\d+)(\w)/); + + if (!matched) throw new Error(`Invalid time delta ${delta}`); + + const [, amount, unit] = matched; + + return moment.duration(parseInt(amount, 10), unitMapper[unit]); +}; + +/** + * Given a time delta like "-21y", apply it to the passed in date object, or the current time + * @param delta String + * @param date Date + * @return {Date} + */ +const applyDeltaToDate = (delta, date = new Date()) => moment(date).add(timeDeltaToMomentDuration(delta)).toDate(); + +module.exports = { + applyDeltaToDate +}; \ No newline at end of file From 00adbefe99434f08cd36c8a78f32e17e1a2604e8 Mon Sep 17 00:00:00 2001 From: Lucas Cunha Date: Tue, 9 Mar 2021 15:11:43 -0300 Subject: [PATCH 3/6] Update UCA lib --- package-lock.json | 5 ++--- package.json | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7600fb08..3464a88f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -414,9 +414,8 @@ } }, "@identity.com/uca": { - "version": "1.0.27", - "resolved": "https://registry.npmjs.org/@identity.com/uca/-/uca-1.0.27.tgz", - "integrity": "sha512-PYAqNCxonBptyFH0X5n8c+fAtx0DKWWq+WZ6f2z77iHivCbwkUnhl8AV6HtYinnXiHSSPTWBzM3fdvb/v61luw==", + "version": "github:civicteam/uca#e0facce7da3ad952098ee373a67ef7198a0a66f6", + "from": "github:civicteam/uca", "requires": { "flat": "^4.1.0", "lodash": "^4.17.11", diff --git a/package.json b/package.json index af8f20b5..46c8ae6d 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "ajv": "^7.0.3" }, "dependencies": { - "@identity.com/uca": "^1.0.27", + "@identity.com/uca": "github:civicteam/uca", "babel-runtime": "^6.26.0", "bitcoinjs-lib": "git+https://github.com/dabura667/bitcoinjs-lib.git#bcash330", "bluebird": "^3.7.2", From db623cdb8afbfd1d7c7142c42952440edfac5f4e Mon Sep 17 00:00:00 2001 From: Lucas Cunha Date: Fri, 19 Mar 2021 15:49:48 -0300 Subject: [PATCH 4/6] Update uca lib --- package-lock.json | 1304 ++++++++++++++++++++++++++++++--------------- 1 file changed, 869 insertions(+), 435 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3464a88f..bd05526e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -414,7 +414,7 @@ } }, "@identity.com/uca": { - "version": "github:civicteam/uca#e0facce7da3ad952098ee373a67ef7198a0a66f6", + "version": "github:civicteam/uca#cad9c32ea2a91f4af8d9c5a5da9da876f7c81689", "from": "github:civicteam/uca", "requires": { "flat": "^4.1.0", @@ -9178,7 +9178,8 @@ "dependencies": { "JSONStream": { "version": "1.3.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, "requires": { "jsonparse": "^1.2.0", @@ -9187,12 +9188,14 @@ }, "abbrev": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, "agent-base": { "version": "4.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "dev": true, "requires": { "es6-promisify": "^5.0.0" @@ -9200,7 +9203,8 @@ }, "agentkeepalive": { "version": "3.5.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", "dev": true, "requires": { "humanize-ms": "^1.2.1" @@ -9208,7 +9212,8 @@ }, "ansi-align": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", "dev": true, "requires": { "string-width": "^2.0.0" @@ -9216,12 +9221,14 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "ansi-styles": { "version": "3.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" @@ -9229,27 +9236,32 @@ }, "ansicolors": { "version": "0.3.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=", "dev": true }, "ansistyles": { "version": "0.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk=", "dev": true }, "aproba": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", "dev": true }, "archy": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, "are-we-there-yet": { "version": "1.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", "dev": true, "requires": { "delegates": "^1.0.0", @@ -9258,7 +9270,8 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -9272,7 +9285,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -9282,12 +9296,14 @@ }, "asap": { "version": "2.0.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", "dev": true }, "asn1": { "version": "0.2.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "dev": true, "requires": { "safer-buffer": "~2.1.0" @@ -9295,32 +9311,38 @@ }, "assert-plus": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true }, "asynckit": { "version": "0.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, "aws-sign2": { "version": "0.7.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", "dev": true }, "aws4": { "version": "1.8.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", "dev": true }, "balanced-match": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, "bcrypt-pbkdf": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, "optional": true, "requires": { @@ -9329,7 +9351,8 @@ }, "bin-links": { "version": "1.1.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-KgmVfx+QqggqP9dA3iIc5pA4T1qEEEL+hOhOhNPaUm77OTrJoOXE/C05SJLNJe6m/2wUK7F1tDSou7n5TfCDzQ==", "dev": true, "requires": { "bluebird": "^3.5.3", @@ -9342,12 +9365,14 @@ }, "bluebird": { "version": "3.5.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==", "dev": true }, "boxen": { "version": "1.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", "dev": true, "requires": { "ansi-align": "^2.0.0", @@ -9361,7 +9386,8 @@ }, "brace-expansion": { "version": "1.1.11", - "bundled": true, + "resolved": false, + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -9370,27 +9396,32 @@ }, "buffer-from": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", "dev": true }, "builtins": { "version": "1.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", "dev": true }, "byline": { "version": "5.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=", "dev": true }, "byte-size": { "version": "5.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw==", "dev": true }, "cacache": { "version": "12.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", "dev": true, "requires": { "bluebird": "^3.5.5", @@ -9412,27 +9443,32 @@ }, "call-limit": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-5twvci5b9eRBw2wCfPtN0GmlR2/gadZqyFpPhOK6CvMFoFgA+USnZ6Jpu1lhG9h85pQ3Ouil3PfXWRD4EUaRiQ==", "dev": true }, "camelcase": { "version": "4.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, "capture-stack-trace": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", "dev": true }, "caseless": { "version": "0.12.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, "chalk": { "version": "2.4.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -9442,17 +9478,20 @@ }, "chownr": { "version": "1.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, "ci-info": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, "cidr-regex": { "version": "2.0.10", - "bundled": true, + "resolved": false, + "integrity": "sha512-sB3ogMQXWvreNPbJUZMRApxuRYd+KoIo4RGQ81VatjmMW6WJPo+IJZ2846FGItr9VzKo5w7DXzijPLGtSd0N3Q==", "dev": true, "requires": { "ip-regex": "^2.1.0" @@ -9460,12 +9499,14 @@ }, "cli-boxes": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", "dev": true }, "cli-columns": { "version": "3.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-ZzLZcpee/CrkRKHwjgj6E5yWoY4=", "dev": true, "requires": { "string-width": "^2.0.0", @@ -9474,7 +9515,8 @@ }, "cli-table3": { "version": "0.5.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", "dev": true, "requires": { "colors": "^1.1.2", @@ -9484,7 +9526,8 @@ }, "cliui": { "version": "5.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { "string-width": "^3.1.0", @@ -9494,17 +9537,20 @@ "dependencies": { "ansi-regex": { "version": "4.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, "string-width": { "version": "3.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { "emoji-regex": "^7.0.1", @@ -9514,7 +9560,8 @@ }, "strip-ansi": { "version": "5.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { "ansi-regex": "^4.1.0" @@ -9524,12 +9571,14 @@ }, "clone": { "version": "1.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, "cmd-shim": { "version": "3.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-DtGg+0xiFhQIntSBRzL2fRQBnmtAVwXIDo4Qq46HPpObYquxMaZS4sb82U9nH91qJrlosC1wa9gwr0QyL/HypA==", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -9538,12 +9587,14 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, "color-convert": { "version": "1.9.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", "dev": true, "requires": { "color-name": "^1.1.1" @@ -9551,18 +9602,21 @@ }, "color-name": { "version": "1.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "colors": { "version": "1.3.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", "dev": true, "optional": true }, "columnify": { "version": "1.5.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", "dev": true, "requires": { "strip-ansi": "^3.0.0", @@ -9571,7 +9625,8 @@ }, "combined-stream": { "version": "1.0.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "dev": true, "requires": { "delayed-stream": "~1.0.0" @@ -9579,12 +9634,14 @@ }, "concat-map": { "version": "0.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "concat-stream": { "version": "1.6.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -9595,7 +9652,8 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -9609,7 +9667,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -9619,7 +9678,8 @@ }, "config-chain": { "version": "1.1.12", - "bundled": true, + "resolved": false, + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", "dev": true, "requires": { "ini": "^1.3.4", @@ -9628,7 +9688,8 @@ }, "configstore": { "version": "3.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA==", "dev": true, "requires": { "dot-prop": "^4.2.1", @@ -9641,12 +9702,14 @@ }, "console-control-strings": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, "copy-concurrently": { "version": "1.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", "dev": true, "requires": { "aproba": "^1.1.1", @@ -9659,24 +9722,28 @@ "dependencies": { "aproba": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, "iferr": { "version": "0.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "dev": true } } }, "core-util-is": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, "create-error-class": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", "dev": true, "requires": { "capture-stack-trace": "^1.0.0" @@ -9684,7 +9751,8 @@ }, "cross-spawn": { "version": "5.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { "lru-cache": "^4.0.1", @@ -9694,7 +9762,8 @@ "dependencies": { "lru-cache": { "version": "4.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", "dev": true, "requires": { "pseudomap": "^1.0.2", @@ -9703,24 +9772,28 @@ }, "yallist": { "version": "2.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true } } }, "crypto-random-string": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", "dev": true }, "cyclist": { "version": "0.2.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", "dev": true }, "dashdash": { "version": "1.14.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { "assert-plus": "^1.0.0" @@ -9728,7 +9801,8 @@ }, "debug": { "version": "3.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -9736,34 +9810,40 @@ "dependencies": { "ms": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true } } }, "debuglog": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=", "dev": true }, "decamelize": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, "decode-uri-component": { "version": "0.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, "deep-extend": { "version": "0.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true }, "defaults": { "version": "1.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, "requires": { "clone": "^1.0.2" @@ -9771,7 +9851,8 @@ }, "define-properties": { "version": "1.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, "requires": { "object-keys": "^1.0.12" @@ -9779,27 +9860,32 @@ }, "delayed-stream": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, "delegates": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true }, "detect-indent": { "version": "5.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=", "dev": true }, "detect-newline": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", "dev": true }, "dezalgo": { "version": "1.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", "dev": true, "requires": { "asap": "^2.0.0", @@ -9808,7 +9894,8 @@ }, "dot-prop": { "version": "4.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==", "dev": true, "requires": { "is-obj": "^1.0.0" @@ -9816,17 +9903,20 @@ }, "dotenv": { "version": "5.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow==", "dev": true }, "duplexer3": { "version": "0.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, "duplexify": { "version": "3.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", "dev": true, "requires": { "end-of-stream": "^1.0.0", @@ -9837,7 +9927,8 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -9851,7 +9942,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -9861,7 +9953,8 @@ }, "ecc-jsbn": { "version": "0.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "dev": true, "optional": true, "requires": { @@ -9871,17 +9964,20 @@ }, "editor": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-YMf4e9YrzGqJT6jM1q+3gjok90I=", "dev": true }, "emoji-regex": { "version": "7.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, "encoding": { "version": "0.1.12", - "bundled": true, + "resolved": false, + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", "dev": true, "requires": { "iconv-lite": "~0.4.13" @@ -9889,7 +9985,8 @@ }, "end-of-stream": { "version": "1.4.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { "once": "^1.4.0" @@ -9897,17 +9994,20 @@ }, "env-paths": { "version": "2.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", "dev": true }, "err-code": { "version": "1.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", "dev": true }, "errno": { "version": "0.1.7", - "bundled": true, + "resolved": false, + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", "dev": true, "requires": { "prr": "~1.0.1" @@ -9915,7 +10015,8 @@ }, "es-abstract": { "version": "1.12.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", "dev": true, "requires": { "es-to-primitive": "^1.1.1", @@ -9927,7 +10028,8 @@ }, "es-to-primitive": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", "dev": true, "requires": { "is-callable": "^1.1.4", @@ -9937,12 +10039,14 @@ }, "es6-promise": { "version": "4.2.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", "dev": true }, "es6-promisify": { "version": "5.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, "requires": { "es6-promise": "^4.0.3" @@ -9950,12 +10054,14 @@ }, "escape-string-regexp": { "version": "1.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, "execa": { "version": "0.7.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { "cross-spawn": "^5.0.1", @@ -9969,39 +10075,46 @@ "dependencies": { "get-stream": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true } } }, "extend": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, "extsprintf": { "version": "1.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true }, "fast-json-stable-stringify": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", "dev": true }, "figgy-pudding": { "version": "3.5.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", "dev": true }, "find-npm-prefix": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-KEftzJ+H90x6pcKtdXZEPsQse8/y/UnvzRKrOSQFprnrGaFuJ62fVkP34Iu2IYuMvyauCyoLTNkJZgrrGA2wkA==", "dev": true }, "flush-write-stream": { "version": "1.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -10010,7 +10123,8 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -10024,7 +10138,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -10034,12 +10149,14 @@ }, "forever-agent": { "version": "0.6.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", "dev": true }, "form-data": { "version": "2.3.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "dev": true, "requires": { "asynckit": "^0.4.0", @@ -10049,7 +10166,8 @@ }, "from2": { "version": "2.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", "dev": true, "requires": { "inherits": "^2.0.1", @@ -10058,7 +10176,8 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -10072,7 +10191,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -10082,7 +10202,8 @@ }, "fs-minipass": { "version": "1.2.7", - "bundled": true, + "resolved": false, + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dev": true, "requires": { "minipass": "^2.6.0" @@ -10090,7 +10211,8 @@ "dependencies": { "minipass": { "version": "2.9.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, "requires": { "safe-buffer": "^5.1.2", @@ -10101,7 +10223,8 @@ }, "fs-vacuum": { "version": "1.2.10", - "bundled": true, + "resolved": false, + "integrity": "sha1-t2Kb7AekAxolSP35n17PHMizHjY=", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -10111,7 +10234,8 @@ }, "fs-write-stream-atomic": { "version": "1.0.10", - "bundled": true, + "resolved": false, + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -10122,12 +10246,14 @@ "dependencies": { "iferr": { "version": "0.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "dev": true }, "readable-stream": { "version": "2.3.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -10141,7 +10267,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -10151,17 +10278,20 @@ }, "fs.realpath": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, "function-bind": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "gauge": { "version": "2.7.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "requires": { "aproba": "^1.0.3", @@ -10176,12 +10306,14 @@ "dependencies": { "aproba": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, "string-width": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { "code-point-at": "^1.0.0", @@ -10193,12 +10325,14 @@ }, "genfun": { "version": "5.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==", "dev": true }, "gentle-fs": { "version": "2.3.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-OlwBBwqCFPcjm33rF2BjW+Pr6/ll2741l+xooiwTCeaX2CA1ZuclavyMBe0/KlR21/XGsgY6hzEQZ15BdNa13Q==", "dev": true, "requires": { "aproba": "^1.1.2", @@ -10216,24 +10350,28 @@ "dependencies": { "aproba": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true }, "iferr": { "version": "0.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "dev": true } } }, "get-caller-file": { "version": "2.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "get-stream": { "version": "4.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, "requires": { "pump": "^3.0.0" @@ -10241,7 +10379,8 @@ }, "getpass": { "version": "0.1.7", - "bundled": true, + "resolved": false, + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { "assert-plus": "^1.0.0" @@ -10249,7 +10388,8 @@ }, "glob": { "version": "7.1.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -10262,7 +10402,8 @@ }, "global-dirs": { "version": "0.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", "dev": true, "requires": { "ini": "^1.3.4" @@ -10270,7 +10411,8 @@ }, "got": { "version": "6.7.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", "dev": true, "requires": { "create-error-class": "^3.0.0", @@ -10288,24 +10430,28 @@ "dependencies": { "get-stream": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true } } }, "graceful-fs": { "version": "4.2.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "dev": true }, "har-schema": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", "dev": true }, "har-validator": { "version": "5.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "dev": true, "requires": { "ajv": "^6.12.3", @@ -10314,7 +10460,8 @@ "dependencies": { "ajv": { "version": "6.12.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -10325,19 +10472,22 @@ }, "fast-deep-equal": { "version": "3.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "json-schema-traverse": { "version": "0.4.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true } } }, "has": { "version": "1.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { "function-bind": "^1.1.1" @@ -10345,32 +10495,38 @@ }, "has-flag": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "has-symbols": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", "dev": true }, "has-unicode": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true }, "hosted-git-info": { "version": "2.8.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "dev": true }, "http-cache-semantics": { "version": "3.8.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", "dev": true }, "http-proxy-agent": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", "dev": true, "requires": { "agent-base": "4", @@ -10379,7 +10535,8 @@ }, "http-signature": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "requires": { "assert-plus": "^1.0.0", @@ -10389,7 +10546,8 @@ }, "https-proxy-agent": { "version": "2.2.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dev": true, "requires": { "agent-base": "^4.3.0", @@ -10398,7 +10556,8 @@ }, "humanize-ms": { "version": "1.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", "dev": true, "requires": { "ms": "^2.0.0" @@ -10406,7 +10565,8 @@ }, "iconv-lite": { "version": "0.4.23", - "bundled": true, + "resolved": false, + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" @@ -10414,12 +10574,14 @@ }, "iferr": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-9AfeLfji44r5TKInjhz3W9DyZI1zR1JAf2hVBMGhddAKPqBsupb89jGfbCTHIGZd6fGZl9WlHdn4AObygyMKwg==", "dev": true }, "ignore-walk": { "version": "3.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", "dev": true, "requires": { "minimatch": "^3.0.4" @@ -10427,22 +10589,26 @@ }, "import-lazy": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", "dev": true }, "imurmurhash": { "version": "0.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, "infer-owner": { "version": "1.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "dev": true }, "inflight": { "version": "1.0.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { "once": "^1.3.0", @@ -10451,17 +10617,20 @@ }, "inherits": { "version": "2.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "ini": { "version": "1.3.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, "init-package-json": { "version": "1.10.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw==", "dev": true, "requires": { "glob": "^7.1.1", @@ -10476,22 +10645,26 @@ }, "ip": { "version": "1.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", "dev": true }, "ip-regex": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", "dev": true }, "is-callable": { "version": "1.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", "dev": true }, "is-ci": { "version": "1.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", "dev": true, "requires": { "ci-info": "^1.5.0" @@ -10499,14 +10672,16 @@ "dependencies": { "ci-info": { "version": "1.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", "dev": true } } }, "is-cidr": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-8Xnnbjsb0x462VoYiGlhEi+drY8SFwrHiSYuzc/CEwco55vkehTaxAyIjEdpi3EMvLPPJAJi9FlzP+h+03gp0Q==", "dev": true, "requires": { "cidr-regex": "^2.0.10" @@ -10514,12 +10689,14 @@ }, "is-date-object": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", "dev": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { "number-is-nan": "^1.0.0" @@ -10527,7 +10704,8 @@ }, "is-installed-globally": { "version": "0.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", "dev": true, "requires": { "global-dirs": "^0.1.0", @@ -10536,17 +10714,20 @@ }, "is-npm": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", "dev": true }, "is-obj": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, "is-path-inside": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { "path-is-inside": "^1.0.1" @@ -10554,12 +10735,14 @@ }, "is-redirect": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", "dev": true }, "is-regex": { "version": "1.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "requires": { "has": "^1.0.1" @@ -10567,17 +10750,20 @@ }, "is-retry-allowed": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", "dev": true }, "is-stream": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, "is-symbol": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", "dev": true, "requires": { "has-symbols": "^1.0.0" @@ -10585,53 +10771,63 @@ }, "is-typedarray": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, "isarray": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "isexe": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "isstream": { "version": "0.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, "jsbn": { "version": "0.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true, "optional": true }, "json-parse-better-errors": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, "json-schema": { "version": "0.2.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "dev": true }, "json-stringify-safe": { "version": "5.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, "jsonparse": { "version": "1.3.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, "jsprim": { "version": "1.4.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "dev": true, "requires": { "assert-plus": "1.0.0", @@ -10642,7 +10838,8 @@ }, "latest-version": { "version": "3.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", "dev": true, "requires": { "package-json": "^4.0.0" @@ -10650,12 +10847,14 @@ }, "lazy-property": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-hN3Es3Bnm6i9TNz6TAa0PVcREUc=", "dev": true }, "libcipm": { "version": "4.0.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-IN3hh2yDJQtZZ5paSV4fbvJg4aHxCCg5tcZID/dSVlTuUiWktsgaldVljJv6Z5OUlYspx6xQkbR0efNodnIrOA==", "dev": true, "requires": { "bin-links": "^1.1.2", @@ -10677,7 +10876,8 @@ }, "libnpm": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-d7jU5ZcMiTfBqTUJVZ3xid44fE5ERBm9vBnmhp2ECD2Ls+FNXWxHSkO7gtvrnbLO78gwPdNPz1HpsF3W4rjkBQ==", "dev": true, "requires": { "bin-links": "^1.1.2", @@ -10704,7 +10904,8 @@ }, "libnpmaccess": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-01512AK7MqByrI2mfC7h5j8N9V4I7MHJuk9buo8Gv+5QgThpOgpjB7sQBDDkeZqRteFb1QM/6YNdHfG7cDvfAQ==", "dev": true, "requires": { "aproba": "^2.0.0", @@ -10715,7 +10916,8 @@ }, "libnpmconfig": { "version": "1.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-9esX8rTQAHqarx6qeZqmGQKBNZR5OIbl/Ayr0qQDy3oXja2iFVQQI81R6GZ2a02bSNZ9p3YOGX1O6HHCb1X7kA==", "dev": true, "requires": { "figgy-pudding": "^3.5.1", @@ -10725,7 +10927,8 @@ "dependencies": { "find-up": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { "locate-path": "^3.0.0" @@ -10733,7 +10936,8 @@ }, "locate-path": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { "p-locate": "^3.0.0", @@ -10742,7 +10946,8 @@ }, "p-limit": { "version": "2.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -10750,7 +10955,8 @@ }, "p-locate": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { "p-limit": "^2.0.0" @@ -10758,14 +10964,16 @@ }, "p-try": { "version": "2.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true } } }, "libnpmhook": { "version": "5.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-UdNLMuefVZra/wbnBXECZPefHMGsVDTq5zaM/LgKNE9Keyl5YXQTnGAzEo+nFOpdRqTWI9LYi4ApqF9uVCCtuA==", "dev": true, "requires": { "aproba": "^2.0.0", @@ -10776,7 +10984,8 @@ }, "libnpmorg": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-0sRUXLh+PLBgZmARvthhYXQAWn0fOsa6T5l3JSe2n9vKG/lCVK4nuG7pDsa7uMq+uTt2epdPK+a2g6btcY11Ww==", "dev": true, "requires": { "aproba": "^2.0.0", @@ -10787,7 +10996,8 @@ }, "libnpmpublish": { "version": "1.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-2yIwaXrhTTcF7bkJKIKmaCV9wZOALf/gsTDxVSu/Gu/6wiG3fA8ce8YKstiWKTxSFNC0R7isPUb6tXTVFZHt2g==", "dev": true, "requires": { "aproba": "^2.0.0", @@ -10803,7 +11013,8 @@ }, "libnpmsearch": { "version": "2.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-VTBbV55Q6fRzTdzziYCr64+f8AopQ1YZ+BdPOv16UegIEaE8C0Kch01wo4s3kRTFV64P121WZJwgmBwrq68zYg==", "dev": true, "requires": { "figgy-pudding": "^3.5.1", @@ -10813,7 +11024,8 @@ }, "libnpmteam": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-p420vM28Us04NAcg1rzgGW63LMM6rwe+6rtZpfDxCcXxM0zUTLl7nPFEnRF3JfFBF5skF/yuZDUthTsHgde8QA==", "dev": true, "requires": { "aproba": "^2.0.0", @@ -10824,7 +11036,8 @@ }, "libnpx": { "version": "10.2.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-BPc0D1cOjBeS8VIBKUu5F80s6njm0wbVt7CsGMrIcJ+SI7pi7V0uVPGpEMH9H5L8csOcclTxAXFE2VAsJXUhfA==", "dev": true, "requires": { "dotenv": "^5.0.1", @@ -10839,7 +11052,8 @@ }, "lock-verify": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-vcLpxnGvrqisKvLQ2C2v0/u7LVly17ak2YSgoK4PrdsYBXQIax19vhKiLfvKNFx7FRrpTnitrpzF/uuCMuorIg==", "dev": true, "requires": { "npm-package-arg": "^6.1.0", @@ -10848,7 +11062,8 @@ }, "lockfile": { "version": "1.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", "dev": true, "requires": { "signal-exit": "^3.0.2" @@ -10856,12 +11071,14 @@ }, "lodash._baseindexof": { "version": "3.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=", "dev": true }, "lodash._baseuniq": { "version": "4.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-DrtE5FaBSveQXGIS+iybLVG4Qeg=", "dev": true, "requires": { "lodash._createset": "~4.0.0", @@ -10870,17 +11087,20 @@ }, "lodash._bindcallback": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", "dev": true }, "lodash._cacheindexof": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=", "dev": true }, "lodash._createcache": { "version": "3.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=", "dev": true, "requires": { "lodash._getnative": "^3.0.0" @@ -10888,52 +11108,62 @@ }, "lodash._createset": { "version": "4.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=", "dev": true }, "lodash._getnative": { "version": "3.9.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", "dev": true }, "lodash._root": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", "dev": true }, "lodash.clonedeep": { "version": "4.5.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, "lodash.restparam": { "version": "3.6.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", "dev": true }, "lodash.union": { "version": "4.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=", "dev": true }, "lodash.uniq": { "version": "4.5.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, "lodash.without": { "version": "4.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-PNRXSgC2e643OpS3SHcmQFB7eqw=", "dev": true }, "lowercase-keys": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, "lru-cache": { "version": "5.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "requires": { "yallist": "^3.0.2" @@ -10941,7 +11171,8 @@ }, "make-dir": { "version": "1.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", "dev": true, "requires": { "pify": "^3.0.0" @@ -10949,7 +11180,8 @@ }, "make-fetch-happen": { "version": "5.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==", "dev": true, "requires": { "agentkeepalive": "^3.4.1", @@ -10967,17 +11199,20 @@ }, "meant": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-KN+1uowN/NK+sT/Lzx7WSGIj2u+3xe5n2LbwObfjOhPZiA+cCfCm6idVl0RkEfjThkw5XJ96CyRcanq6GmKtUg==", "dev": true }, "mime-db": { "version": "1.35.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==", "dev": true }, "mime-types": { "version": "2.1.19", - "bundled": true, + "resolved": false, + "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", "dev": true, "requires": { "mime-db": "~1.35.0" @@ -10985,7 +11220,8 @@ }, "minimatch": { "version": "3.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -10993,12 +11229,14 @@ }, "minimist": { "version": "1.2.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, "minizlib": { "version": "1.3.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "dev": true, "requires": { "minipass": "^2.9.0" @@ -11006,7 +11244,8 @@ "dependencies": { "minipass": { "version": "2.9.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, "requires": { "safe-buffer": "^5.1.2", @@ -11017,7 +11256,8 @@ }, "mississippi": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", "dev": true, "requires": { "concat-stream": "^1.5.0", @@ -11034,7 +11274,8 @@ }, "mkdirp": { "version": "0.5.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { "minimist": "^1.2.5" @@ -11042,14 +11283,16 @@ "dependencies": { "minimist": { "version": "1.2.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true } } }, "move-concurrently": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", "dev": true, "requires": { "aproba": "^1.1.1", @@ -11062,24 +11305,28 @@ "dependencies": { "aproba": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true } } }, "ms": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, "mute-stream": { "version": "0.0.7", - "bundled": true, + "resolved": false, + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, "node-fetch-npm": { "version": "2.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==", "dev": true, "requires": { "encoding": "^0.1.11", @@ -11089,7 +11336,8 @@ }, "node-gyp": { "version": "5.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-OUTryc5bt/P8zVgNUmC6xdXiDJxLMAW8cF5tLQOT9E5sOQj+UeQxnnPy74K3CLCa/SOjjBlbuzDLR8ANwA+wmw==", "dev": true, "requires": { "env-paths": "^2.2.0", @@ -11107,7 +11355,8 @@ }, "nopt": { "version": "4.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", "dev": true, "requires": { "abbrev": "1", @@ -11116,7 +11365,8 @@ }, "normalize-package-data": { "version": "2.5.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { "hosted-git-info": "^2.1.4", @@ -11127,7 +11377,8 @@ "dependencies": { "resolve": { "version": "1.10.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -11137,7 +11388,8 @@ }, "npm-audit-report": { "version": "1.3.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-8nH/JjsFfAWMvn474HB9mpmMjrnKb1Hx/oTAdjv4PT9iZBvBxiZ+wtDUapHCJwLqYGQVPaAfs+vL5+5k9QndXw==", "dev": true, "requires": { "cli-table3": "^0.5.0", @@ -11146,7 +11398,8 @@ }, "npm-bundled": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", "dev": true, "requires": { "npm-normalize-package-bin": "^1.0.1" @@ -11154,12 +11407,14 @@ }, "npm-cache-filename": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-3tMGxbC/yHCp6fr4I7xfKD4FrhE=", "dev": true }, "npm-install-checks": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-E4kzkyZDIWoin6uT5howP8VDvkM+E8IQDcHAycaAxMbwkqhIg5eEYALnXOl3Hq9MrkdQB/2/g1xwBINXdKSRkg==", "dev": true, "requires": { "semver": "^2.3.0 || 3.x || 4 || 5" @@ -11167,7 +11422,8 @@ }, "npm-lifecycle": { "version": "3.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-lDLVkjfZmvmfvpvBzA4vzee9cn+Me4orq0QF8glbswJVEbIcSNWib7qGOffolysc3teCqbbPZZkzbr3GQZTL1g==", "dev": true, "requires": { "byline": "^5.0.0", @@ -11182,17 +11438,20 @@ }, "npm-logical-tree": { "version": "1.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-AJI/qxDB2PWI4LG1CYN579AY1vCiNyWfkiquCsJWqntRu/WwimVrC8yXeILBFHDwxfOejxewlmnvW9XXjMlYIg==", "dev": true }, "npm-normalize-package-bin": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", "dev": true }, "npm-package-arg": { "version": "6.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", "dev": true, "requires": { "hosted-git-info": "^2.7.1", @@ -11203,7 +11462,8 @@ }, "npm-packlist": { "version": "1.4.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", "dev": true, "requires": { "ignore-walk": "^3.0.1", @@ -11213,7 +11473,8 @@ }, "npm-pick-manifest": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==", "dev": true, "requires": { "figgy-pudding": "^3.5.1", @@ -11223,7 +11484,8 @@ }, "npm-profile": { "version": "4.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-Ta8xq8TLMpqssF0H60BXS1A90iMoM6GeKwsmravJ6wYjWwSzcYBTdyWa3DZCYqPutacBMEm7cxiOkiIeCUAHDQ==", "dev": true, "requires": { "aproba": "^1.1.2 || 2", @@ -11233,7 +11495,8 @@ }, "npm-registry-fetch": { "version": "4.0.7", - "bundled": true, + "resolved": false, + "integrity": "sha512-cny9v0+Mq6Tjz+e0erFAB+RYJ/AVGzkjnISiobqP8OWj9c9FLoZZu8/SPSKJWE17F1tk4018wfjV+ZbIbqC7fQ==", "dev": true, "requires": { "JSONStream": "^1.3.4", @@ -11247,14 +11510,16 @@ "dependencies": { "safe-buffer": { "version": "5.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true } } }, "npm-run-path": { "version": "2.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { "path-key": "^2.0.0" @@ -11262,12 +11527,14 @@ }, "npm-user-validate": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-uQwcd/tY+h1jnEaze6cdX/LrhWhoBxfSknxentoqmIuStxUExxjWd3ULMLFPiFUrZKbOVMowH6Jq2FRWfmhcEw==", "dev": true }, "npmlog": { "version": "4.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "requires": { "are-we-there-yet": "~1.1.2", @@ -11278,27 +11545,32 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "oauth-sign": { "version": "0.9.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, "object-assign": { "version": "4.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, "object-keys": { "version": "1.0.12", - "bundled": true, + "resolved": false, + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", "dev": true }, "object.getownpropertydescriptors": { "version": "2.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", "dev": true, "requires": { "define-properties": "^1.1.2", @@ -11307,7 +11579,8 @@ }, "once": { "version": "1.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { "wrappy": "1" @@ -11315,22 +11588,26 @@ }, "opener": { "version": "1.5.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", "dev": true }, "os-homedir": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, "os-tmpdir": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, "osenv": { "version": "0.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "requires": { "os-homedir": "^1.0.0", @@ -11339,12 +11616,14 @@ }, "p-finally": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, "package-json": { "version": "4.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", "dev": true, "requires": { "got": "^6.7.1", @@ -11355,7 +11634,8 @@ }, "pacote": { "version": "9.5.12", - "bundled": true, + "resolved": false, + "integrity": "sha512-BUIj/4kKbwWg4RtnBncXPJd15piFSVNpTzY0rysSr3VnMowTYgkGKcaHrbReepAkjTr8lH2CVWRi58Spg2CicQ==", "dev": true, "requires": { "bluebird": "^3.5.3", @@ -11392,7 +11672,8 @@ "dependencies": { "minipass": { "version": "2.9.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, "requires": { "safe-buffer": "^5.1.2", @@ -11403,7 +11684,8 @@ }, "parallel-transform": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", "dev": true, "requires": { "cyclist": "~0.2.2", @@ -11413,7 +11695,8 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -11427,7 +11710,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -11437,57 +11721,68 @@ }, "path-exists": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, "path-is-absolute": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, "path-is-inside": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, "path-key": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "path-parse": { "version": "1.0.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, "performance-now": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, "pify": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true }, "prepend-http": { "version": "1.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, "process-nextick-args": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true }, "promise-inflight": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, "promise-retry": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", "dev": true, "requires": { "err-code": "^1.0.0", @@ -11496,14 +11791,16 @@ "dependencies": { "retry": { "version": "0.10.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", "dev": true } } }, "promzard": { "version": "0.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=", "dev": true, "requires": { "read": "1" @@ -11511,12 +11808,14 @@ }, "proto-list": { "version": "1.2.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", "dev": true }, "protoduck": { "version": "5.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==", "dev": true, "requires": { "genfun": "^5.0.0" @@ -11524,22 +11823,26 @@ }, "prr": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, "pseudomap": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, "psl": { "version": "1.1.29", - "bundled": true, + "resolved": false, + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", "dev": true }, "pump": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -11548,7 +11851,8 @@ }, "pumpify": { "version": "1.5.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "dev": true, "requires": { "duplexify": "^3.6.0", @@ -11558,7 +11862,8 @@ "dependencies": { "pump": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -11569,22 +11874,26 @@ }, "punycode": { "version": "1.4.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true }, "qrcode-terminal": { "version": "0.12.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==", "dev": true }, "qs": { "version": "6.5.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, "query-string": { "version": "6.8.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-J3Qi8XZJXh93t2FiKyd/7Ec6GNifsjKXUsVFkSBj/kjLsDylWhnCz4NT1bkPcKotttPW+QbKGqqPH8OoI2pdqw==", "dev": true, "requires": { "decode-uri-component": "^0.2.0", @@ -11594,12 +11903,14 @@ }, "qw": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-77/cdA+a0FQwRCassYNBLMi5ltQ=", "dev": true }, "rc": { "version": "1.2.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "requires": { "deep-extend": "^0.6.0", @@ -11610,7 +11921,8 @@ }, "read": { "version": "1.0.7", - "bundled": true, + "resolved": false, + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", "dev": true, "requires": { "mute-stream": "~0.0.4" @@ -11618,7 +11930,8 @@ }, "read-cmd-shim": { "version": "1.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-v5yCqQ/7okKoZZkBQUAfTsQ3sVJtXdNfbPnI5cceppoxEVLYA3k+VtV2omkeo8MS94JCy4fSiUwlRBAwCVRPUA==", "dev": true, "requires": { "graceful-fs": "^4.1.2" @@ -11626,7 +11939,8 @@ }, "read-installed": { "version": "4.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc=", "dev": true, "requires": { "debuglog": "^1.0.1", @@ -11640,7 +11954,8 @@ }, "read-package-json": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-dAiqGtVc/q5doFz6096CcnXhpYk0ZN8dEKVkGLU0CsASt8SrgF6SF7OTKAYubfvFhWaqofl+Y8HK19GR8jwW+A==", "dev": true, "requires": { "glob": "^7.1.1", @@ -11652,7 +11967,8 @@ }, "read-package-tree": { "version": "5.3.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==", "dev": true, "requires": { "read-package-json": "^2.0.0", @@ -11662,7 +11978,8 @@ }, "readable-stream": { "version": "3.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -11672,7 +11989,8 @@ }, "readdir-scoped-modules": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", "dev": true, "requires": { "debuglog": "^1.0.1", @@ -11683,7 +12001,8 @@ }, "registry-auth-token": { "version": "3.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", "dev": true, "requires": { "rc": "^1.1.6", @@ -11692,7 +12011,8 @@ }, "registry-url": { "version": "3.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", "dev": true, "requires": { "rc": "^1.0.1" @@ -11700,7 +12020,8 @@ }, "request": { "version": "2.88.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "dev": true, "requires": { "aws-sign2": "~0.7.0", @@ -11727,27 +12048,32 @@ }, "require-directory": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "require-main-filename": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, "resolve-from": { "version": "4.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "retry": { "version": "0.12.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", "dev": true }, "rimraf": { "version": "2.7.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "requires": { "glob": "^7.1.3" @@ -11755,7 +12081,8 @@ }, "run-queue": { "version": "1.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", "dev": true, "requires": { "aproba": "^1.1.1" @@ -11763,29 +12090,34 @@ "dependencies": { "aproba": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true } } }, "safe-buffer": { "version": "5.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "safer-buffer": { "version": "2.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, "semver": { "version": "5.7.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, "semver-diff": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", "dev": true, "requires": { "semver": "^5.0.3" @@ -11793,12 +12125,14 @@ }, "set-blocking": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "sha": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-DOYnM37cNsLNSGIG/zZWch5CKIRNoLdYUQTQlcgkRkoYIUwDYjqDyye16YcDZg/OPdcbUgTKMjc4SY6TB7ZAPw==", "dev": true, "requires": { "graceful-fs": "^4.1.2" @@ -11806,7 +12140,8 @@ }, "shebang-command": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { "shebang-regex": "^1.0.0" @@ -11814,27 +12149,32 @@ }, "shebang-regex": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, "signal-exit": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, "slide": { "version": "1.1.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", "dev": true }, "smart-buffer": { "version": "4.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==", "dev": true }, "socks": { "version": "2.3.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", "dev": true, "requires": { "ip": "1.1.5", @@ -11843,7 +12183,8 @@ }, "socks-proxy-agent": { "version": "4.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", "dev": true, "requires": { "agent-base": "~4.2.1", @@ -11852,7 +12193,8 @@ "dependencies": { "agent-base": { "version": "4.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", "dev": true, "requires": { "es6-promisify": "^5.0.0" @@ -11862,12 +12204,14 @@ }, "sorted-object": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-fWMfS9OnmKJK8d/8+/6DM3pd9fw=", "dev": true }, "sorted-union-stream": { "version": "2.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-x3lMfgd4gAUv9xqNSi27Sppjisc=", "dev": true, "requires": { "from2": "^1.3.0", @@ -11876,7 +12220,8 @@ "dependencies": { "from2": { "version": "1.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-iEE7qqX5pZfP3pIh2GmGzTwGHf0=", "dev": true, "requires": { "inherits": "~2.0.1", @@ -11885,12 +12230,14 @@ }, "isarray": { "version": "0.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, "readable-stream": { "version": "1.1.14", - "bundled": true, + "resolved": false, + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -11901,14 +12248,16 @@ }, "string_decoder": { "version": "0.10.31", - "bundled": true, + "resolved": false, + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "spdx-correct": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -11917,12 +12266,14 @@ }, "spdx-exceptions": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", "dev": true }, "spdx-expression-parse": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -11931,17 +12282,20 @@ }, "spdx-license-ids": { "version": "3.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, "split-on-first": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", "dev": true }, "sshpk": { "version": "1.14.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", "dev": true, "requires": { "asn1": "~0.2.3", @@ -11957,7 +12311,8 @@ }, "ssri": { "version": "6.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", "dev": true, "requires": { "figgy-pudding": "^3.5.1" @@ -11965,7 +12320,8 @@ }, "stream-each": { "version": "1.2.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -11974,7 +12330,8 @@ }, "stream-iterate": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-K9fHcpbBcCpGSIuK1B95hl7s1OE=", "dev": true, "requires": { "readable-stream": "^2.1.5", @@ -11983,7 +12340,8 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -11997,7 +12355,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -12007,17 +12366,20 @@ }, "stream-shift": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, "strict-uri-encode": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=", "dev": true }, "string-width": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", @@ -12026,17 +12388,20 @@ "dependencies": { "ansi-regex": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, "strip-ansi": { "version": "4.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { "ansi-regex": "^3.0.0" @@ -12046,7 +12411,8 @@ }, "string_decoder": { "version": "1.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "requires": { "safe-buffer": "~5.2.0" @@ -12054,19 +12420,22 @@ "dependencies": { "safe-buffer": { "version": "5.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", "dev": true } } }, "stringify-package": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", "dev": true }, "strip-ansi": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { "ansi-regex": "^2.0.0" @@ -12074,17 +12443,20 @@ }, "strip-eof": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, "strip-json-comments": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, "supports-color": { "version": "5.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -12092,7 +12464,8 @@ }, "tar": { "version": "4.4.13", - "bundled": true, + "resolved": false, + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", "dev": true, "requires": { "chownr": "^1.1.1", @@ -12106,7 +12479,8 @@ "dependencies": { "minipass": { "version": "2.9.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, "requires": { "safe-buffer": "^5.1.2", @@ -12117,7 +12491,8 @@ }, "term-size": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", "dev": true, "requires": { "execa": "^0.7.0" @@ -12125,17 +12500,20 @@ }, "text-table": { "version": "0.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, "through": { "version": "2.3.8", - "bundled": true, + "resolved": false, + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, "through2": { "version": "2.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { "readable-stream": "^2.1.5", @@ -12144,7 +12522,8 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -12158,7 +12537,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -12168,17 +12548,20 @@ }, "timed-out": { "version": "4.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", "dev": true }, "tiny-relative-date": { "version": "1.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A==", "dev": true }, "tough-cookie": { "version": "2.4.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "dev": true, "requires": { "psl": "^1.1.24", @@ -12187,7 +12570,8 @@ }, "tunnel-agent": { "version": "0.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { "safe-buffer": "^5.0.1" @@ -12195,28 +12579,33 @@ }, "tweetnacl": { "version": "0.14.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true, "optional": true }, "typedarray": { "version": "0.0.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, "uid-number": { "version": "0.0.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", "dev": true }, "umask": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=", "dev": true }, "unique-filename": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", "dev": true, "requires": { "unique-slug": "^2.0.0" @@ -12224,7 +12613,8 @@ }, "unique-slug": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", "dev": true, "requires": { "imurmurhash": "^0.1.4" @@ -12232,7 +12622,8 @@ }, "unique-string": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", "dev": true, "requires": { "crypto-random-string": "^1.0.0" @@ -12240,17 +12631,20 @@ }, "unpipe": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, "unzip-response": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", "dev": true }, "update-notifier": { "version": "2.5.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", "dev": true, "requires": { "boxen": "^1.2.1", @@ -12267,7 +12661,8 @@ }, "uri-js": { "version": "4.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", "dev": true, "requires": { "punycode": "^2.1.0" @@ -12275,14 +12670,16 @@ "dependencies": { "punycode": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true } } }, "url-parse-lax": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", "dev": true, "requires": { "prepend-http": "^1.0.1" @@ -12290,17 +12687,20 @@ }, "util-deprecate": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, "util-extend": { "version": "1.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=", "dev": true }, "util-promisify": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=", "dev": true, "requires": { "object.getownpropertydescriptors": "^2.0.3" @@ -12308,12 +12708,14 @@ }, "uuid": { "version": "3.3.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", "dev": true }, "validate-npm-package-license": { "version": "3.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { "spdx-correct": "^3.0.0", @@ -12322,7 +12724,8 @@ }, "validate-npm-package-name": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", "dev": true, "requires": { "builtins": "^1.0.3" @@ -12330,7 +12733,8 @@ }, "verror": { "version": "1.10.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { "assert-plus": "^1.0.0", @@ -12340,7 +12744,8 @@ }, "wcwidth": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", "dev": true, "requires": { "defaults": "^1.0.3" @@ -12348,7 +12753,8 @@ }, "which": { "version": "1.3.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" @@ -12356,12 +12762,14 @@ }, "which-module": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, "wide-align": { "version": "1.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", "dev": true, "requires": { "string-width": "^1.0.2" @@ -12369,7 +12777,8 @@ "dependencies": { "string-width": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { "code-point-at": "^1.0.0", @@ -12381,7 +12790,8 @@ }, "widest-line": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", "dev": true, "requires": { "string-width": "^2.1.1" @@ -12389,7 +12799,8 @@ }, "worker-farm": { "version": "1.7.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", "dev": true, "requires": { "errno": "~0.1.7" @@ -12397,7 +12808,8 @@ }, "wrap-ansi": { "version": "5.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, "requires": { "ansi-styles": "^3.2.0", @@ -12407,17 +12819,20 @@ "dependencies": { "ansi-regex": { "version": "4.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, "string-width": { "version": "3.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { "emoji-regex": "^7.0.1", @@ -12427,7 +12842,8 @@ }, "strip-ansi": { "version": "5.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { "ansi-regex": "^4.1.0" @@ -12437,12 +12853,14 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "write-file-atomic": { "version": "2.4.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", "dev": true, "requires": { "graceful-fs": "^4.1.11", @@ -12452,27 +12870,32 @@ }, "xdg-basedir": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", "dev": true }, "xtend": { "version": "4.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, "y18n": { "version": "4.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, "yallist": { "version": "3.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "dev": true }, "yargs": { "version": "14.2.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", "dev": true, "requires": { "cliui": "^5.0.0", @@ -12490,12 +12913,14 @@ "dependencies": { "ansi-regex": { "version": "4.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "find-up": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { "locate-path": "^3.0.0" @@ -12503,12 +12928,14 @@ }, "is-fullwidth-code-point": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, "locate-path": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { "p-locate": "^3.0.0", @@ -12517,7 +12944,8 @@ }, "p-limit": { "version": "2.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -12525,7 +12953,8 @@ }, "p-locate": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { "p-limit": "^2.0.0" @@ -12533,12 +12962,14 @@ }, "p-try": { "version": "2.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "string-width": { "version": "3.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { "emoji-regex": "^7.0.1", @@ -12548,7 +12979,8 @@ }, "strip-ansi": { "version": "5.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { "ansi-regex": "^4.1.0" @@ -12558,7 +12990,8 @@ }, "yargs-parser": { "version": "15.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", "dev": true, "requires": { "camelcase": "^5.0.0", @@ -12567,7 +13000,8 @@ "dependencies": { "camelcase": { "version": "5.3.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true } } From 411ce511cad2c6f3520cebdd4c4c922277352bb8 Mon Sep 17 00:00:00 2001 From: Lucas Cunha Date: Fri, 19 Mar 2021 16:17:12 -0300 Subject: [PATCH 5/6] Upgrade uca lib --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index bd05526e..dd68af3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -414,7 +414,7 @@ } }, "@identity.com/uca": { - "version": "github:civicteam/uca#cad9c32ea2a91f4af8d9c5a5da9da876f7c81689", + "version": "github:civicteam/uca#c44edc3b6d545a7e3866139081f11e18f4ddc986", "from": "github:civicteam/uca", "requires": { "flat": "^4.1.0", From 76883e2cf1ea6772a3af05b3cf2558e08545c428 Mon Sep 17 00:00:00 2001 From: Joao Santos Date: Tue, 23 Mar 2021 14:32:05 -0300 Subject: [PATCH 6/6] rollback ajv --- package-lock.json | 1171 +++++++++++++++++++-------------------------- package.json | 2 +- 2 files changed, 484 insertions(+), 689 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7600fb08..a0746ba1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,34 +5,41 @@ "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", "dev": true, "requires": { - "@babel/highlight": "^7.10.4" + "@babel/highlight": "^7.12.13" } }, + "@babel/compat-data": { + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.13.12.tgz", + "integrity": "sha512-3eJJ841uKxeV8dcN/2yGEUy+RfgQspPEgQat85umsE1rotuquQ2AbIub4S6j7c50a2d+4myc+zSlnXeIHrOnhQ==", + "dev": true + }, "@babel/core": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz", - "integrity": "sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.10", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.5", - "@babel/parser": "^7.12.10", - "@babel/template": "^7.12.7", - "@babel/traverse": "^7.12.10", - "@babel/types": "^7.12.10", + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.13.10.tgz", + "integrity": "sha512-bfIYcT0BdKeAZrovpMqX2Mx5NrgAckGbwT982AkdS5GNfn3KMGiprlBAtmBcFZRUmpaufS6WZFP8trvx8ptFDw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.9", + "@babel/helper-compilation-targets": "^7.13.10", + "@babel/helper-module-transforms": "^7.13.0", + "@babel/helpers": "^7.13.10", + "@babel/parser": "^7.13.10", + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", + "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", "lodash": "^4.17.19", - "semver": "^5.4.1", + "semver": "^6.3.0", "source-map": "^0.5.0" }, "dependencies": { @@ -61,20 +68,20 @@ "dev": true }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } }, "@babel/generator": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz", - "integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==", + "version": "7.13.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.13.9.tgz", + "integrity": "sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw==", "dev": true, "requires": { - "@babel/types": "^7.12.11", + "@babel/types": "^7.13.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -87,104 +94,123 @@ } } }, + "@babel/helper-compilation-targets": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.10.tgz", + "integrity": "sha512-/Xju7Qg1GQO4mHZ/Kcs6Au7gfafgZnwm+a7sy/ow/tV1sHeraRUHbjdat8/UvDor4Tez+siGKDk6zIKtCPKVJA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.13.8", + "@babel/helper-validator-option": "^7.12.17", + "browserslist": "^4.14.5", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "@babel/helper-function-name": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz", - "integrity": "sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", + "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.12.10", - "@babel/template": "^7.12.7", - "@babel/types": "^7.12.11" + "@babel/helper-get-function-arity": "^7.12.13", + "@babel/template": "^7.12.13", + "@babel/types": "^7.12.13" } }, "@babel/helper-get-function-arity": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz", - "integrity": "sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", + "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", "dev": true, "requires": { - "@babel/types": "^7.12.10" + "@babel/types": "^7.12.13" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz", - "integrity": "sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz", + "integrity": "sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw==", "dev": true, "requires": { - "@babel/types": "^7.12.7" + "@babel/types": "^7.13.12" } }, "@babel/helper-module-imports": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", - "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz", + "integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA==", "dev": true, "requires": { - "@babel/types": "^7.12.5" + "@babel/types": "^7.13.12" } }, "@babel/helper-module-transforms": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz", - "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.12.1", - "@babel/helper-replace-supers": "^7.12.1", - "@babel/helper-simple-access": "^7.12.1", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/helper-validator-identifier": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.1", - "@babel/types": "^7.12.1", - "lodash": "^4.17.19" + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.13.12.tgz", + "integrity": "sha512-7zVQqMO3V+K4JOOj40kxiCrMf6xlQAkewBB0eu2b03OO/Q21ZutOzjpfD79A5gtE/2OWi1nv625MrDlGlkbknQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.13.12", + "@babel/helper-replace-supers": "^7.13.12", + "@babel/helper-simple-access": "^7.13.12", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/helper-validator-identifier": "^7.12.11", + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.12" } }, "@babel/helper-optimise-call-expression": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz", - "integrity": "sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz", + "integrity": "sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA==", "dev": true, "requires": { - "@babel/types": "^7.12.10" + "@babel/types": "^7.12.13" } }, "@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", + "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", "dev": true }, "@babel/helper-replace-supers": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz", - "integrity": "sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz", + "integrity": "sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.12.7", - "@babel/helper-optimise-call-expression": "^7.12.10", - "@babel/traverse": "^7.12.10", - "@babel/types": "^7.12.11" + "@babel/helper-member-expression-to-functions": "^7.13.12", + "@babel/helper-optimise-call-expression": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.12" } }, "@babel/helper-simple-access": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz", - "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz", + "integrity": "sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA==", "dev": true, "requires": { - "@babel/types": "^7.12.1" + "@babel/types": "^7.13.12" } }, "@babel/helper-split-export-declaration": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz", - "integrity": "sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", + "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", "dev": true, "requires": { - "@babel/types": "^7.12.11" + "@babel/types": "^7.12.13" } }, "@babel/helper-validator-identifier": { @@ -193,24 +219,30 @@ "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", "dev": true }, + "@babel/helper-validator-option": { + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz", + "integrity": "sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==", + "dev": true + }, "@babel/helpers": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz", - "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==", + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.13.10.tgz", + "integrity": "sha512-4VO883+MWPDUVRF3PhiLBUFHoX/bsLTGFpFK/HqvvfBZz2D57u9XzPVNFVBTc0PW/CWR9BXTOKt8NF4DInUHcQ==", "dev": true, "requires": { - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.12.5", - "@babel/types": "^7.12.5" + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.0" } }, "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", + "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.4", + "@babel/helper-validator-identifier": "^7.12.11", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -235,21 +267,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -274,9 +291,9 @@ } }, "@babel/parser": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz", - "integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.13.12.tgz", + "integrity": "sha512-4T7Pb244rxH24yR116LAuJ+adxXXnHhZaLJjegJVKSdoNCe4x1eDBaud5YIcQFcqzsaD5BHvJw5BQ0AZapdCRw==", "dev": true }, "@babel/plugin-syntax-object-rest-spread": { @@ -289,9 +306,9 @@ } }, "@babel/runtime": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", - "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz", + "integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==", "dev": true, "requires": { "regenerator-runtime": "^0.13.4" @@ -306,9 +323,9 @@ } }, "@babel/runtime-corejs3": { - "version": "7.12.5", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.12.5.tgz", - "integrity": "sha512-roGr54CsTmNPPzZoCP1AmDXuBoNao7tnSA83TXTwt+UK5QVyh1DIJnrgYRPWKCF2flqZQXwa7Yr8v7VmLzF0YQ==", + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.13.10.tgz", + "integrity": "sha512-x/XYVQ1h684pp1mJwOV4CyvqZXqbc8CMsMGUnAbuc82ZCdv1U63w5RSUzgDSXQHG5Rps/kiksH6g2D5BuaKyXg==", "dev": true, "requires": { "core-js-pure": "^3.0.0", @@ -324,28 +341,28 @@ } }, "@babel/template": { - "version": "7.12.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz", - "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", "dev": true, "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.12.7", - "@babel/types": "^7.12.7" + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" } }, "@babel/traverse": { - "version": "7.12.12", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz", - "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.13.0.tgz", + "integrity": "sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.12.11", - "@babel/generator": "^7.12.11", - "@babel/helper-function-name": "^7.12.11", - "@babel/helper-split-export-declaration": "^7.12.11", - "@babel/parser": "^7.12.11", - "@babel/types": "^7.12.12", + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.13.0", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.13.0", + "@babel/types": "^7.13.0", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.19" @@ -375,9 +392,9 @@ } }, "@babel/types": { - "version": "7.12.12", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", - "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.13.12.tgz", + "integrity": "sha512-K4nY2xFN4QMvQwkQ+zmBDp6ANMbVNw6BbxWmYA4qNjhR9W+Lj/8ky5MEY2Me5r+B2c6/v6F53oMndG+f9s3IiA==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.12.11", @@ -414,9 +431,9 @@ } }, "@identity.com/uca": { - "version": "1.0.27", - "resolved": "https://registry.npmjs.org/@identity.com/uca/-/uca-1.0.27.tgz", - "integrity": "sha512-PYAqNCxonBptyFH0X5n8c+fAtx0DKWWq+WZ6f2z77iHivCbwkUnhl8AV6HtYinnXiHSSPTWBzM3fdvb/v61luw==", + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/@identity.com/uca/-/uca-1.0.28.tgz", + "integrity": "sha512-bHbcdqXXGQ4EZXKfl7SWn/SYgEkwb2WquHvUmBN6iQcTMerrYbJhgFob8rE0AzONxrTy4fDWAwJT5F/AjTv8Og==", "requires": { "flat": "^4.1.0", "lodash": "^4.17.11", @@ -456,21 +473,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -603,21 +605,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -784,6 +771,12 @@ "kind-of": "^6.0.0" } }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", @@ -955,21 +948,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -1126,21 +1104,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -1307,6 +1270,12 @@ "kind-of": "^6.0.0" } }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", @@ -1415,9 +1384,9 @@ } }, "@types/babel__core": { - "version": "7.1.12", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.12.tgz", - "integrity": "sha512-wMTHiiTiBAAPebqaPiPDLFA4LYPKr6Ph0Xq/6rq1Ur3v66HXyG+clfR9CNETkD7MQS8ZHvpQOtA53DLws5WAEQ==", + "version": "7.1.14", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.14.tgz", + "integrity": "sha512-zGZJzzBUVDo/eV6KgbE0f0ZI7dInEYvo12Rb70uNQDshC3SkRMb67ja0GgRHZgAX3Za6rhaWlvbDO8rrGyAb1g==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -1447,9 +1416,9 @@ } }, "@types/babel__traverse": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.11.0.tgz", - "integrity": "sha512-kSjgDMZONiIfSH1Nxcr5JIRMwUetDki63FSQfpTCz8ogF3Ulqm8+mr5f78dUYs6vMiB6gBusQqfQmBvHZj/lwg==", + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.11.1.tgz", + "integrity": "sha512-Vs0hm0vPahPMYi9tDjtP66llufgO3ST16WXaSTtDGEl9cewAl3AibmxWw6TINOqHPT9z0uABKAYjT9jNSg4npw==", "dev": true, "requires": { "@babel/types": "^7.3.0" @@ -1571,14 +1540,13 @@ "dev": true }, "ajv": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz", - "integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==", - "dev": true, + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "requires": { "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, @@ -1607,6 +1575,21 @@ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { "color-convert": "^2.0.1" + }, + "dependencies": { + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + } } }, "anymatch": { @@ -1668,15 +1651,15 @@ "dev": true }, "array-includes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.2.tgz", - "integrity": "sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "get-intrinsic": "^1.0.1", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", "is-string": "^1.0.5" } }, @@ -1800,9 +1783,9 @@ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, "axe-core": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.1.1.tgz", - "integrity": "sha512-5Kgy8Cz6LPC9DJcNb3yjAXTu3XihQgEdnIg50c//zOC/MyLP0Clg+Y8Sh9ZjjnvBrDZU4DgXS9C3T9r4/scGZQ==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.1.3.tgz", + "integrity": "sha512-vwPpH4Aj4122EW38mxO/fxhGKtwWTMLDIJfZ1He0Edbtjcfna/R3YB67yVhezUMzqc3Jr3+Ii50KRntlENL4xQ==", "dev": true }, "axobject-query": { @@ -2144,21 +2127,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -2823,6 +2791,16 @@ "semver": "^5.3.0" }, "dependencies": { + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -3159,13 +3137,16 @@ } }, "browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz", + "integrity": "sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" + "caniuse-lite": "^1.0.30001181", + "colorette": "^1.2.1", + "electron-to-chromium": "^1.3.649", + "escalade": "^3.1.1", + "node-releases": "^1.1.70" } }, "bs58": { @@ -3196,9 +3177,9 @@ } }, "bson": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/bson/-/bson-4.2.2.tgz", - "integrity": "sha512-9fX257PVHAUpiRGmY3356RVWKQxLA73BgjA/x5MGuJkTEMeG7yzjuBrsiFB67EXRJnFVKrbJY9t/M+oElKYktQ==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.2.3.tgz", + "integrity": "sha512-3ztgjpKp0itFxGqzrLMHWqyZH5oMOIRWsjeY61yNVzrDGB/KxtgD6djFlz9n3vx7lLr2r6bkHagBCgyk1ZjETA==", "requires": { "buffer": "^5.6.0" } @@ -3300,9 +3281,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001181", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001181.tgz", - "integrity": "sha512-m5ul/ARCX50JB8BSNM+oiPmQrR5UmngaQ3QThTTp5HcIIQGP/nPBs82BYLE+tigzm3VW+F4BJIhUyaVtEweelQ==", + "version": "1.0.30001204", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001204.tgz", + "integrity": "sha512-JUdjWpcxfJ9IPamy2f5JaRDCaqJOxDzOSKtbdx4rH9VivMd1vIzoPumsJa9LoMIi4Fx2BV2KZOxWhNkBjaYivQ==", "dev": true }, "capture-exit": { @@ -3458,45 +3439,36 @@ "requires": { "color-convert": "^1.9.1", "color-string": "^1.5.2" - }, - "dependencies": { - "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==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - } } }, "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "requires": { - "color-name": "~1.1.4" + "color-name": "1.1.3" } }, "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz", - "integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz", + "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==", "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -3627,9 +3599,9 @@ "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" }, "core-js-pure": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.8.3.tgz", - "integrity": "sha512-V5qQZVAr9K0xu7jXg1M7qTEwuxUgqr7dUOezGaNa7i+Xn9oXAU/d1fzqD9ObuwpVQOaorO5s70ckyi1woP9lVA==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.9.1.tgz", + "integrity": "sha512-laz3Zx0avrw9a4QEIdmIblnVuJz8W51leY9iLThatCsFawWxC3sE4guASC78JbCin+DkwMpCdp1AVAuzL/GN7A==", "dev": true }, "core-util-is": { @@ -3932,9 +3904,9 @@ } }, "electron-to-chromium": { - "version": "1.3.649", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.649.tgz", - "integrity": "sha512-ojGDupQ3UMkvPWcTICe4JYe17+o9OLiFMPoduoR72Zp2ILt1mRVeqnxBEd6s/ptekrnsFU+0A4lStfBe/wyG/A==", + "version": "1.3.695", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.695.tgz", + "integrity": "sha512-lz66RliUqLHU1Ojxx1A4QUxKydjiQ79Y4dZyPobs2Dmxj5aVL2TM3KoQ2Gs7HS703Bfny+ukI3KOxwAB0xceHQ==", "dev": true }, "emoji-regex": { @@ -3980,25 +3952,27 @@ } }, "es-abstract": { - "version": "1.18.0-next.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz", - "integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", + "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", "dev": true, "requires": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2", + "get-intrinsic": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.1", + "is-regex": "^1.1.2", + "is-string": "^1.0.5", "object-inspect": "^1.9.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.3", - "string.prototype.trimstart": "^1.0.3" + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.0" } }, "es-to-primitive": { @@ -4012,6 +3986,12 @@ "is-symbol": "^1.0.2" } }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -4150,21 +4130,6 @@ "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", "dev": true }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -4638,9 +4603,9 @@ }, "dependencies": { "emoji-regex": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.1.tgz", - "integrity": "sha512-117l1H6U4X3Krn+MrzYrL57d5H7siRHWraBs7s+LjRuFK7Fe7hJqnJ0skWlinqsycVLU5YAo6L8CsEYQ0V5prg==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true } } @@ -4652,22 +4617,35 @@ "dev": true }, "eslint-plugin-react": { - "version": "7.22.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz", - "integrity": "sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.23.0.tgz", + "integrity": "sha512-5rfsRiHKIAdhxv3NxrzE+dBC7BFsNhuErL+Fy940oD1cau55JVTnuL25sqXqD7XY0OkYCRsKEqxZVwezE5ol5w==", "dev": true, "requires": { - "array-includes": "^3.1.1", - "array.prototype.flatmap": "^1.2.3", + "array-includes": "^3.1.3", + "array.prototype.flatmap": "^1.2.4", "doctrine": "^2.1.0", "has": "^1.0.3", "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "object.entries": "^1.1.2", - "object.fromentries": "^2.0.2", - "object.values": "^1.1.1", + "minimatch": "^3.0.4", + "object.entries": "^1.1.3", + "object.fromentries": "^2.0.4", + "object.values": "^1.1.3", "prop-types": "^15.7.2", - "resolve": "^1.18.1", - "string.prototype.matchall": "^4.0.2" + "resolve": "^2.0.0-next.3", + "string.prototype.matchall": "^4.0.4" + }, + "dependencies": { + "resolve": { + "version": "2.0.0-next.3", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.3.tgz", + "integrity": "sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + } } }, "eslint-scope": { @@ -4703,9 +4681,9 @@ "dev": true }, "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -4764,9 +4742,9 @@ } }, "exec-sh": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz", - "integrity": "sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.5.tgz", + "integrity": "sha512-0hzpaUazv4mEccxdn3TXC+HWNeVXNKMCJRK6E7Xyg+LwGAYI3yFag6jTkd4injV+kChYDQS1ftqDhnDVWNhU8A==", "dev": true }, "execa": { @@ -4889,21 +4867,6 @@ "requires": { "color-convert": "^1.9.0" } - }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true } } }, @@ -5071,13 +5034,6 @@ "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", "requires": { "is-buffer": "~2.0.3" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" - } } }, "flat-cache": { @@ -5209,9 +5165,9 @@ "dev": true }, "get-intrinsic": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.0.tgz", - "integrity": "sha512-M11rgtQp5GZMZzDL7jLTNxbDfurpzuau5uqRWDPvlHjfvg3TdScAZo96GLvhMjImrmR8uAt0FS2RLoMrfWGKlg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "dev": true, "requires": { "function-bind": "^1.1.1", @@ -5289,9 +5245,9 @@ "dev": true }, "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", "dev": true }, "growly": { @@ -5312,24 +5268,6 @@ "requires": { "ajv": "^6.12.3", "har-schema": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - } } }, "has": { @@ -5357,15 +5295,21 @@ } } }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "dev": true }, "has-value": { @@ -5397,6 +5341,12 @@ "kind-of": "^4.0.0" }, "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -5739,6 +5689,12 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, + "is-bigint": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", + "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", + "dev": true + }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", @@ -5749,10 +5705,19 @@ "binary-extensions": "^1.0.0" } }, + "is-boolean-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", + "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" }, "is-callable": { "version": "1.2.3", @@ -5890,6 +5855,12 @@ "kind-of": "^3.0.2" } }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -5922,11 +5893,12 @@ "optional": true }, "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", "dev": true, "requires": { + "call-bind": "^1.0.2", "has-symbols": "^1.0.1" } }, @@ -6147,21 +6119,6 @@ "wrap-ansi": "^5.1.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -6402,21 +6359,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -6583,6 +6525,12 @@ "kind-of": "^6.0.0" } }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", @@ -6699,21 +6647,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -6773,21 +6706,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -7069,6 +6987,12 @@ "kind-of": "^6.0.0" } }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", @@ -7226,21 +7150,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -7300,21 +7209,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -7409,21 +7303,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -7590,6 +7469,12 @@ "kind-of": "^6.0.0" } }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", @@ -7734,21 +7619,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -7824,21 +7694,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -7940,21 +7795,6 @@ "wrap-ansi": "^5.1.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -8130,21 +7970,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -8208,21 +8033,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -8286,21 +8096,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -8359,21 +8154,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -8501,10 +8281,9 @@ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -8557,6 +8336,14 @@ "dev": true, "requires": { "is-buffer": "^1.1.5" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + } } }, "kleur": { @@ -8661,9 +8448,9 @@ } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash.isplainobject": { "version": "4.0.6", @@ -8782,6 +8569,13 @@ "charenc": "0.0.2", "crypt": "0.0.2", "is-buffer": "~1.1.6" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + } } }, "md5.js": { @@ -8836,16 +8630,16 @@ } }, "mime-db": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==" + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==" }, "mime-types": { - "version": "2.1.28", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", - "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "version": "2.1.29", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", + "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", "requires": { - "mime-db": "1.45.0" + "mime-db": "1.46.0" } }, "mimic-fn": { @@ -8988,9 +8782,9 @@ "dev": true }, "node-notifier": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", - "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.5.tgz", + "integrity": "sha512-tVbHs7DyTLtzOiN78izLA85zRqB9NvEXkAf014Vx3jtSvn/xBl6bR8ZYifj+dFcFrKI21huSQgJZ6ZtL3B4HfQ==", "dev": true, "requires": { "growly": "^1.3.0", @@ -9017,6 +8811,12 @@ } } }, + "node-releases": { + "version": "1.1.71", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", + "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", + "dev": true + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -12691,26 +12491,26 @@ } }, "object.fromentries": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.3.tgz", - "integrity": "sha512-IDUSMXs6LOSJBWE++L0lzIbSqHl9KDCfff2x/JSEIDtEUavUnyMYC2ZGay/04Zq4UT8lvd4xNhU4/YHKibAOlw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.4.tgz", + "integrity": "sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.18.0-next.2", "has": "^1.0.3" } }, "object.getownpropertydescriptors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz", - "integrity": "sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", + "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" + "es-abstract": "^1.18.0-next.2" } }, "object.omit": { @@ -12742,14 +12542,14 @@ } }, "object.values": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz", - "integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", + "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.18.0-next.2", "has": "^1.0.3" } }, @@ -13069,21 +12869,6 @@ "requires": { "color-convert": "^1.9.0" } - }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true } } }, @@ -13522,6 +13307,13 @@ "kind-of": "^6.0.0" } }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "optional": true + }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", @@ -13804,13 +13596,6 @@ "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" - }, - "dependencies": { - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } } }, "request-debug": { @@ -13846,12 +13631,6 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", @@ -13869,11 +13648,11 @@ } }, "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "requires": { - "is-core-module": "^2.1.0", + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } }, @@ -13971,9 +13750,9 @@ } }, "rxjs": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", - "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "version": "6.6.6", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.6.tgz", + "integrity": "sha512-/oTwee4N4iWzAMAL9xdGKjkEHmIwupR3oXbQjCKywF1BeFohswF3vZdogbmEF6pZkOsXTzWkrZszrWpQTByYVg==", "requires": { "tslib": "^1.9.0" } @@ -14233,6 +14012,12 @@ "kind-of": "^6.0.0" } }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", @@ -14315,9 +14100,9 @@ "dev": true }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -14595,9 +14380,9 @@ } }, "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", "dev": true }, "spdx-correct": { @@ -14758,9 +14543,9 @@ } }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -14768,37 +14553,37 @@ } }, "string.prototype.matchall": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz", - "integrity": "sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.4.tgz", + "integrity": "sha512-pknFIWVachNcyqRfaQSeu/FUfpvJTe4uskUSZ9Wc1RijsPuzbZ8TyYT8WCNnntCjUEqQ3vUHMAfVj2+wLAisPQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.18.0-next.2", "has-symbols": "^1.0.1", - "internal-slot": "^1.0.2", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.3" + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.3.1", + "side-channel": "^1.0.4" } }, "string.prototype.trimend": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", - "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" } }, "string.prototype.trimstart": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", - "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" } }, @@ -14908,21 +14693,6 @@ "supports-color": "^5.3.0" } }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "fast-deep-equal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", @@ -15173,6 +14943,18 @@ "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" }, + "unbox-primitive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.0.tgz", + "integrity": "sha512-P/51NX+JXyxK/aigg1/ZgyccdAxm5K1+n8+tvqSntjOivPt19gvm1VC49RWYetsiub8WViUchdxl/KWHHB0kzA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.0", + "has-symbols": "^1.0.0", + "which-boxed-primitive": "^1.0.1" + } + }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -15385,6 +15167,19 @@ "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", diff --git a/package.json b/package.json index af8f20b5..7809594a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "jest-html-reporter": "^2.3.0", "request-debug": "^0.2.0", "rimraf": "^2.6.2", - "ajv": "^7.0.3" + "ajv": "^6.5.2" }, "dependencies": { "@identity.com/uca": "^1.0.27",