@interop/did-cli 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +341 -0
- package/LICENSE.md +21 -0
- package/README.md +1307 -0
- package/dist/commands/did.d.ts +3 -0
- package/dist/commands/did.d.ts.map +1 -0
- package/dist/commands/did.js +605 -0
- package/dist/commands/did.js.map +1 -0
- package/dist/commands/key.d.ts +3 -0
- package/dist/commands/key.d.ts.map +1 -0
- package/dist/commands/key.js +430 -0
- package/dist/commands/key.js.map +1 -0
- package/dist/commands/vc.d.ts +79 -0
- package/dist/commands/vc.d.ts.map +1 -0
- package/dist/commands/vc.js +528 -0
- package/dist/commands/vc.js.map +1 -0
- package/dist/commands/wallet.d.ts +14 -0
- package/dist/commands/wallet.d.ts.map +1 -0
- package/dist/commands/wallet.js +48 -0
- package/dist/commands/wallet.js.map +1 -0
- package/dist/commands/was.d.ts +500 -0
- package/dist/commands/was.d.ts.map +1 -0
- package/dist/commands/was.js +1833 -0
- package/dist/commands/was.js.map +1 -0
- package/dist/commands/zcap.d.ts +85 -0
- package/dist/commands/zcap.d.ts.map +1 -0
- package/dist/commands/zcap.js +447 -0
- package/dist/commands/zcap.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/keys/ecdsa.d.ts +40 -0
- package/dist/keys/ecdsa.d.ts.map +1 -0
- package/dist/keys/ecdsa.js +73 -0
- package/dist/keys/ecdsa.js.map +1 -0
- package/dist/meta.d.ts +164 -0
- package/dist/meta.d.ts.map +1 -0
- package/dist/meta.js +286 -0
- package/dist/meta.js.map +1 -0
- package/dist/storage.d.ts +191 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +307 -0
- package/dist/storage.js.map +1 -0
- package/dist/table.d.ts +43 -0
- package/dist/table.d.ts.map +1 -0
- package/dist/table.js +61 -0
- package/dist/table.js.map +1 -0
- package/dist/vc/fixtures/welcomeCredential.d.ts +22 -0
- package/dist/vc/fixtures/welcomeCredential.d.ts.map +1 -0
- package/dist/vc/fixtures/welcomeCredential.js +25 -0
- package/dist/vc/fixtures/welcomeCredential.js.map +1 -0
- package/dist/vc/issue.d.ts +24 -0
- package/dist/vc/issue.d.ts.map +1 -0
- package/dist/vc/issue.js +211 -0
- package/dist/vc/issue.js.map +1 -0
- package/dist/vc/registries.d.ts +30 -0
- package/dist/vc/registries.d.ts.map +1 -0
- package/dist/vc/registries.js +53 -0
- package/dist/vc/registries.js.map +1 -0
- package/dist/vc/registryManager.d.ts +25 -0
- package/dist/vc/registryManager.d.ts.map +1 -0
- package/dist/vc/registryManager.js +29 -0
- package/dist/vc/registryManager.js.map +1 -0
- package/dist/vc/suites/expirationSuite.d.ts +23 -0
- package/dist/vc/suites/expirationSuite.d.ts.map +1 -0
- package/dist/vc/suites/expirationSuite.js +84 -0
- package/dist/vc/suites/expirationSuite.js.map +1 -0
- package/dist/vc/suites/issuerDetailsSuite.d.ts +22 -0
- package/dist/vc/suites/issuerDetailsSuite.d.ts.map +1 -0
- package/dist/vc/suites/issuerDetailsSuite.js +69 -0
- package/dist/vc/suites/issuerDetailsSuite.js.map +1 -0
- package/dist/vc/verify.d.ts +46 -0
- package/dist/vc/verify.d.ts.map +1 -0
- package/dist/vc/verify.js +147 -0
- package/dist/vc/verify.js.map +1 -0
- package/dist/was/address.d.ts +44 -0
- package/dist/was/address.d.ts.map +1 -0
- package/dist/was/address.js +98 -0
- package/dist/was/address.js.map +1 -0
- package/dist/was/capability.d.ts +65 -0
- package/dist/was/capability.d.ts.map +1 -0
- package/dist/was/capability.js +108 -0
- package/dist/was/capability.js.map +1 -0
- package/dist/was/client.d.ts +108 -0
- package/dist/was/client.d.ts.map +1 -0
- package/dist/was/client.js +142 -0
- package/dist/was/client.js.map +1 -0
- package/dist/was/io.d.ts +71 -0
- package/dist/was/io.d.ts.map +1 -0
- package/dist/was/io.js +146 -0
- package/dist/was/io.js.map +1 -0
- package/dist/was/registry.d.ts +79 -0
- package/dist/was/registry.d.ts.map +1 -0
- package/dist/was/registry.js +99 -0
- package/dist/was/registry.js.map +1 -0
- package/dist/zcap/create.d.ts +20 -0
- package/dist/zcap/create.d.ts.map +1 -0
- package/dist/zcap/create.js +29 -0
- package/dist/zcap/create.js.map +1 -0
- package/dist/zcap/delegate.d.ts +44 -0
- package/dist/zcap/delegate.d.ts.map +1 -0
- package/dist/zcap/delegate.js +77 -0
- package/dist/zcap/delegate.js.map +1 -0
- package/dist/zcap/encoding.d.ts +17 -0
- package/dist/zcap/encoding.d.ts.map +1 -0
- package/dist/zcap/encoding.js +37 -0
- package/dist/zcap/encoding.js.map +1 -0
- package/dist/zcap/signer.d.ts +20 -0
- package/dist/zcap/signer.d.ts.map +1 -0
- package/dist/zcap/signer.js +62 -0
- package/dist/zcap/signer.js.map +1 -0
- package/dist/zcap/ttl.d.ts +19 -0
- package/dist/zcap/ttl.d.ts.map +1 -0
- package/dist/zcap/ttl.js +40 -0
- package/dist/zcap/ttl.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A sample Verifiable Credential used as test input. Copied from freewallet's
|
|
3
|
+
* `welcomeCredential` fixture. The `proof` block is retained for reference but
|
|
4
|
+
* sign tests strip it and override `issuer` with a freshly generated test DID.
|
|
5
|
+
*/
|
|
6
|
+
export const welcomeCredential = {
|
|
7
|
+
'@context': [
|
|
8
|
+
'https://www.w3.org/ns/credentials/v2',
|
|
9
|
+
'https://w3id.org/security/suites/ed25519-2020/v1'
|
|
10
|
+
],
|
|
11
|
+
type: ['VerifiableCredential'],
|
|
12
|
+
issuer: 'did:key:z6MkhVTX9BF3NGYX6cc7jWpbNnR7cAjH8LUffabZP8Qu4ysC',
|
|
13
|
+
name: 'Your First Credential',
|
|
14
|
+
credentialSubject: {
|
|
15
|
+
description: 'You have successfully set up your credentials wallet!'
|
|
16
|
+
},
|
|
17
|
+
proof: {
|
|
18
|
+
type: 'Ed25519Signature2020',
|
|
19
|
+
created: '2025-08-19T06:55:17Z',
|
|
20
|
+
verificationMethod: 'did:key:z6MkhVTX9BF3NGYX6cc7jWpbNnR7cAjH8LUffabZP8Qu4ysC#z6MkhVTX9BF3NGYX6cc7jWpbNnR7cAjH8LUffabZP8Qu4ysC',
|
|
21
|
+
proofPurpose: 'assertionMethod',
|
|
22
|
+
proofValue: 'z4EiTbmC79r4dRaqLQZr2yxQASoMKneHVNHVaWh1xcDoPG2eTwYjKoYaku1Canb7a6Xp5fSogKJyEhkZCaqQ6Y5nw'
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=welcomeCredential.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"welcomeCredential.js","sourceRoot":"","sources":["../../../src/vc/fixtures/welcomeCredential.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,UAAU,EAAE;QACV,sCAAsC;QACtC,kDAAkD;KACnD;IACD,IAAI,EAAE,CAAC,sBAAsB,CAAC;IAC9B,MAAM,EAAE,0DAA0D;IAClE,IAAI,EAAE,uBAAuB;IAC7B,iBAAiB,EAAE;QACjB,WAAW,EAAE,uDAAuD;KACrE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,sBAAsB;QAC5B,OAAO,EAAE,sBAAsB;QAC/B,kBAAkB,EAChB,2GAA2G;QAC7G,YAAY,EAAE,iBAAiB;QAC/B,UAAU,EACR,2FAA2F;KAC9F;CACF,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Issues (signs) a credential with a locally-stored DID's assertionMethod key.
|
|
3
|
+
*
|
|
4
|
+
* When `keyId` is given it must be authorized by the DID's `assertionMethod`
|
|
5
|
+
* relationship; otherwise the first `assertionMethod` key is used. The matching
|
|
6
|
+
* secret key is loaded from the DID's `<did>.keys.json` file. The credential's
|
|
7
|
+
* `issuer` is set to the signing DID when absent, and must match it when present.
|
|
8
|
+
*
|
|
9
|
+
* @param options {object}
|
|
10
|
+
* @param options.credential {object} The unsigned credential to issue.
|
|
11
|
+
* @param options.did {string} The id of the stored DID to issue (sign) with.
|
|
12
|
+
* @param [options.keyId] {string} The verification method id to use.
|
|
13
|
+
* @param [options.suite] {string} The signature suite. Defaults to the signing
|
|
14
|
+
* key type's default (`eddsa-rdfc-2022` for ed25519, `ecdsa-rdfc-2019` for
|
|
15
|
+
* ecdsa).
|
|
16
|
+
* @returns {Promise<object>} The issued credential.
|
|
17
|
+
*/
|
|
18
|
+
export declare function issueCredential({ credential, did, keyId, suite }: {
|
|
19
|
+
credential: object;
|
|
20
|
+
did: string;
|
|
21
|
+
keyId?: string;
|
|
22
|
+
suite?: string;
|
|
23
|
+
}): Promise<object>;
|
|
24
|
+
//# sourceMappingURL=issue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue.d.ts","sourceRoot":"","sources":["../../src/vc/issue.ts"],"names":[],"mappings":"AAoPA;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,EACpC,UAAU,EACV,GAAG,EACH,KAAK,EACL,KAAK,EACN,EAAE;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,GAAG,OAAO,CAAC,MAAM,CAAC,CAuClB"}
|
package/dist/vc/issue.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential issuance (signing) adapter over @interop/vc.
|
|
3
|
+
*
|
|
4
|
+
* `issueCredential` loads a locally-stored DID and one of its assertionMethod
|
|
5
|
+
* keys, builds a signature suite, and hands an unsigned credential to
|
|
6
|
+
* @interop/vc's `issue()`, which returns the credential with a proof attached.
|
|
7
|
+
* If the input already carries a proof, `issue()` appends an additional one.
|
|
8
|
+
* The credential's `issuer` is set to the signing DID when absent, and must
|
|
9
|
+
* match the signing DID when present (otherwise issuance is aborted) -- a
|
|
10
|
+
* credential cannot be issued by a DID other than the one named as its issuer.
|
|
11
|
+
* The signing key is read from the DID's `<did>.keys.json` file (the secret key
|
|
12
|
+
* store written by `id create --save`). All knowledge of the @interop/vc and
|
|
13
|
+
* suite contracts is isolated to this file.
|
|
14
|
+
*/
|
|
15
|
+
import { driver } from '@interop/did-method-key';
|
|
16
|
+
import { Ed25519VerificationKey } from '@interop/ed25519-verification-key';
|
|
17
|
+
import { Ed25519Signature2020, createSigner, eddsaRdfc2022 } from '@interop/ed25519-signature';
|
|
18
|
+
import * as EcdsaMultikey from '@interop/ecdsa-multikey';
|
|
19
|
+
import { ecdsaRdfc2019 } from '@interop/ecdsa-signature';
|
|
20
|
+
import { DataIntegrityProof } from '@interop/data-integrity-proof';
|
|
21
|
+
import { issue } from '@interop/vc';
|
|
22
|
+
import { securityLoader } from '@interop/security-document-loader';
|
|
23
|
+
import { loadDidDocument, loadDidKeys } from '../storage.js';
|
|
24
|
+
import { isEcdsaPublicKeyMultibase } from '../keys/ecdsa.js';
|
|
25
|
+
/**
|
|
26
|
+
* Offline document loader for signing: bundles the VC / Data Integrity / suite
|
|
27
|
+
* contexts (including the `ed25519-2020` suite context) and a did:key resolver.
|
|
28
|
+
* Built once and reused across calls.
|
|
29
|
+
*/
|
|
30
|
+
const documentLoader = securityLoader().build();
|
|
31
|
+
/**
|
|
32
|
+
* The supported `--suite` values per key type. The signing key's type (read
|
|
33
|
+
* from its multibase header) determines which suites are usable; an ed25519 key
|
|
34
|
+
* cannot sign with an ecdsa cryptosuite and vice versa.
|
|
35
|
+
*/
|
|
36
|
+
const SUPPORTED_SUITES = {
|
|
37
|
+
ed25519: ['eddsa-rdfc-2022', 'Ed25519Signature2020'],
|
|
38
|
+
ecdsa: ['ecdsa-rdfc-2019']
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* The default `--suite` for each key type, used when no `--suite` is given.
|
|
42
|
+
*/
|
|
43
|
+
const DEFAULT_SUITE = {
|
|
44
|
+
ed25519: 'eddsa-rdfc-2022',
|
|
45
|
+
ecdsa: 'ecdsa-rdfc-2019'
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Reconciles a credential's existing `issuer` property with the signing DID.
|
|
49
|
+
* When the credential has no `issuer`, the signing DID is set as the issuer.
|
|
50
|
+
* When it already has one, it must match the signing DID, otherwise issuance is
|
|
51
|
+
* aborted -- a credential must be issued by the DID named as its issuer.
|
|
52
|
+
*
|
|
53
|
+
* @param options {object}
|
|
54
|
+
* @param options.credential {object} The credential being issued (mutated in
|
|
55
|
+
* place when the issuer is absent).
|
|
56
|
+
* @param options.did {string} The id of the DID issuing (signing) the
|
|
57
|
+
* credential.
|
|
58
|
+
*/
|
|
59
|
+
function reconcileIssuer({ credential, did }) {
|
|
60
|
+
const issuer = credential.issuer;
|
|
61
|
+
if (issuer === undefined) {
|
|
62
|
+
credential.issuer = did;
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const issuerId = typeof issuer === 'string' ? issuer : issuer?.id;
|
|
66
|
+
if (issuerId !== did) {
|
|
67
|
+
throw new Error("Signing DID does not match the existing 'issuer' property. " +
|
|
68
|
+
'Remove existing issuer, or pass in a matching DID.');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Resolves the exported key pair for `keyId` out of a loaded `<did>.keys.json`,
|
|
73
|
+
* accommodating both the single-key (did:key) and the keyed-map (did:web)
|
|
74
|
+
* storage shapes.
|
|
75
|
+
*
|
|
76
|
+
* @param options {object}
|
|
77
|
+
* @param options.keysData {StoredKeys} The parsed key file contents.
|
|
78
|
+
* @param options.keyId {string} The verification method id to find.
|
|
79
|
+
* @returns {StoredKeyPair | undefined} The matching key pair, or undefined.
|
|
80
|
+
*/
|
|
81
|
+
function selectStoredKey({ keysData, keyId }) {
|
|
82
|
+
if (keysData.id === keyId) {
|
|
83
|
+
return keysData;
|
|
84
|
+
}
|
|
85
|
+
const entry = keysData[keyId];
|
|
86
|
+
return entry?.id === keyId ? entry : undefined;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Returns whether the given key id appears in the DID document's
|
|
90
|
+
* `assertionMethod` relationship, matching either a string reference or the
|
|
91
|
+
* `id` of an embedded verification method object.
|
|
92
|
+
*
|
|
93
|
+
* @param options {object}
|
|
94
|
+
* @param options.didDocument {DidDocument}
|
|
95
|
+
* @param options.keyId {string}
|
|
96
|
+
* @returns {boolean}
|
|
97
|
+
*/
|
|
98
|
+
function isAuthorizedForAssertion({ didDocument, keyId }) {
|
|
99
|
+
const assertionMethod = didDocument.assertionMethod;
|
|
100
|
+
const entries = Array.isArray(assertionMethod)
|
|
101
|
+
? assertionMethod
|
|
102
|
+
: assertionMethod
|
|
103
|
+
? [assertionMethod]
|
|
104
|
+
: [];
|
|
105
|
+
return entries.some(entry => typeof entry === 'string' ? entry === keyId : entry.id === keyId);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Detects a stored key's type from its `publicKeyMultibase` header. Both
|
|
109
|
+
* ed25519 and ecdsa keys export with `type: "Multikey"`, so the multibase
|
|
110
|
+
* prefix is what distinguishes them: ecdsa P-256/P-384/P-521 keys carry the
|
|
111
|
+
* ecdsa-multikey headers, and everything else is treated as ed25519.
|
|
112
|
+
*
|
|
113
|
+
* @param options {object}
|
|
114
|
+
* @param options.storedKey {StoredKeyPair} The exported key pair.
|
|
115
|
+
* @returns {KeyType}
|
|
116
|
+
*/
|
|
117
|
+
function detectKeyType({ storedKey }) {
|
|
118
|
+
return isEcdsaPublicKeyMultibase({
|
|
119
|
+
publicKeyMultibase: storedKey.publicKeyMultibase
|
|
120
|
+
})
|
|
121
|
+
? 'ecdsa'
|
|
122
|
+
: 'ed25519';
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Builds the @interop/vc signature suite for a stored key, loading the matching
|
|
126
|
+
* key pair, deriving a signer, and wiring the requested (or default) cryptosuite.
|
|
127
|
+
* The signing key's type selects the available suites: ed25519 keys sign with
|
|
128
|
+
* `eddsa-rdfc-2022` (default) or `Ed25519Signature2020`, and ecdsa keys sign
|
|
129
|
+
* with `ecdsa-rdfc-2019`.
|
|
130
|
+
*
|
|
131
|
+
* @param options {object}
|
|
132
|
+
* @param options.storedKey {StoredKeyPair} The exported signing key pair.
|
|
133
|
+
* @param [options.suite] {string} The requested suite, or undefined to use
|
|
134
|
+
* the key type's default.
|
|
135
|
+
* @returns {Promise<DataIntegrityProof | Ed25519Signature2020>}
|
|
136
|
+
*/
|
|
137
|
+
async function buildSuite({ storedKey, suite }) {
|
|
138
|
+
const keyType = detectKeyType({ storedKey });
|
|
139
|
+
const resolvedSuite = suite ?? DEFAULT_SUITE[keyType];
|
|
140
|
+
const supported = SUPPORTED_SUITES[keyType];
|
|
141
|
+
if (!supported.includes(resolvedSuite)) {
|
|
142
|
+
throw new Error(`Suite ${resolvedSuite} is not supported for ${keyType} keys. ` +
|
|
143
|
+
`Supported: ${supported.join(', ')}`);
|
|
144
|
+
}
|
|
145
|
+
if (keyType === 'ecdsa') {
|
|
146
|
+
const keyPair = await EcdsaMultikey.from(storedKey);
|
|
147
|
+
const signer = keyPair.signer();
|
|
148
|
+
return new DataIntegrityProof({ signer, cryptosuite: ecdsaRdfc2019 });
|
|
149
|
+
}
|
|
150
|
+
const keyPair = await Ed25519VerificationKey.from(storedKey);
|
|
151
|
+
const signer = createSigner(keyPair);
|
|
152
|
+
switch (resolvedSuite) {
|
|
153
|
+
case 'eddsa-rdfc-2022':
|
|
154
|
+
return new DataIntegrityProof({ signer, cryptosuite: eddsaRdfc2022 });
|
|
155
|
+
case 'Ed25519Signature2020':
|
|
156
|
+
return new Ed25519Signature2020({ signer });
|
|
157
|
+
default:
|
|
158
|
+
// Unreachable: resolvedSuite was validated against SUPPORTED_SUITES above.
|
|
159
|
+
throw new Error(`Unknown suite: ${resolvedSuite}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Issues (signs) a credential with a locally-stored DID's assertionMethod key.
|
|
164
|
+
*
|
|
165
|
+
* When `keyId` is given it must be authorized by the DID's `assertionMethod`
|
|
166
|
+
* relationship; otherwise the first `assertionMethod` key is used. The matching
|
|
167
|
+
* secret key is loaded from the DID's `<did>.keys.json` file. The credential's
|
|
168
|
+
* `issuer` is set to the signing DID when absent, and must match it when present.
|
|
169
|
+
*
|
|
170
|
+
* @param options {object}
|
|
171
|
+
* @param options.credential {object} The unsigned credential to issue.
|
|
172
|
+
* @param options.did {string} The id of the stored DID to issue (sign) with.
|
|
173
|
+
* @param [options.keyId] {string} The verification method id to use.
|
|
174
|
+
* @param [options.suite] {string} The signature suite. Defaults to the signing
|
|
175
|
+
* key type's default (`eddsa-rdfc-2022` for ed25519, `ecdsa-rdfc-2019` for
|
|
176
|
+
* ecdsa).
|
|
177
|
+
* @returns {Promise<object>} The issued credential.
|
|
178
|
+
*/
|
|
179
|
+
export async function issueCredential({ credential, did, keyId, suite }) {
|
|
180
|
+
const didDocument = await loadDidDocument(did);
|
|
181
|
+
reconcileIssuer({
|
|
182
|
+
credential: credential,
|
|
183
|
+
did: didDocument.id
|
|
184
|
+
});
|
|
185
|
+
let selectedKeyId;
|
|
186
|
+
if (keyId) {
|
|
187
|
+
if (!isAuthorizedForAssertion({ didDocument, keyId })) {
|
|
188
|
+
throw new Error("Specified key is not authorized by the DID's assertionMethod array");
|
|
189
|
+
}
|
|
190
|
+
selectedKeyId = keyId;
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
const method = driver().publicMethodFor({
|
|
194
|
+
didDocument: didDocument,
|
|
195
|
+
purpose: 'assertionMethod'
|
|
196
|
+
});
|
|
197
|
+
selectedKeyId = method.id;
|
|
198
|
+
}
|
|
199
|
+
const keysData = await loadDidKeys(did);
|
|
200
|
+
const storedKey = selectStoredKey({ keysData, keyId: selectedKeyId });
|
|
201
|
+
if (!storedKey) {
|
|
202
|
+
throw new Error(`No stored secret key found for key id ${selectedKeyId} in DID ${did}`);
|
|
203
|
+
}
|
|
204
|
+
const signatureSuite = await buildSuite({ storedKey, suite });
|
|
205
|
+
return issue({
|
|
206
|
+
credential: credential,
|
|
207
|
+
suite: signatureSuite,
|
|
208
|
+
documentLoader: documentLoader
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=issue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue.js","sourceRoot":"","sources":["../../src/vc/issue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trusted DID registry configuration for credential verification.
|
|
3
|
+
*
|
|
4
|
+
* Provides the DCC "known registries" list consumed by both
|
|
5
|
+
* @interop/verifier-core (the `registries` option) and
|
|
6
|
+
* @digitalcredentials/issuer-registry-client. `loadKnownRegistries` fetches
|
|
7
|
+
* the canonical remote list at runtime and falls back to a bundled set of
|
|
8
|
+
* `dcc-legacy` entries when the network is unavailable.
|
|
9
|
+
*/
|
|
10
|
+
import type { EntityIdentityRegistry } from '@interop/verifier-core';
|
|
11
|
+
/**
|
|
12
|
+
* Canonical DCC known-did-registries list. An array of EntityIdentityRegistry
|
|
13
|
+
* entries published by the Digital Credentials Consortium.
|
|
14
|
+
*/
|
|
15
|
+
export declare const KNOWN_REGISTRIES_URL = "https://digitalcredentials.github.io/dcc-known-registries/known-did-registries.json";
|
|
16
|
+
/**
|
|
17
|
+
* Legacy DID registry URLs, used as a fallback when KNOWN_REGISTRIES_URL
|
|
18
|
+
* cannot be fetched. Each entry is tagged `type: 'dcc-legacy'` so it satisfies
|
|
19
|
+
* the EntityIdentityRegistry contract consumed by @interop/verifier-core and
|
|
20
|
+
* @digitalcredentials/issuer-registry-client.
|
|
21
|
+
*/
|
|
22
|
+
export declare const KnownDidRegistries: EntityIdentityRegistry[];
|
|
23
|
+
/**
|
|
24
|
+
* Fetches the remote DCC known registries list, falling back to the bundled
|
|
25
|
+
* KnownDidRegistries const on any failure (logged to stderr).
|
|
26
|
+
*
|
|
27
|
+
* @returns {Promise<EntityIdentityRegistry[]>}
|
|
28
|
+
*/
|
|
29
|
+
export declare function loadKnownRegistries(): Promise<EntityIdentityRegistry[]>;
|
|
30
|
+
//# sourceMappingURL=registries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registries.d.ts","sourceRoot":"","sources":["../../src/vc/registries.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAA;AAEpE;;;GAGG;AACH,eAAO,MAAM,oBAAoB,wFACsD,CAAA;AAEvF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,sBAAsB,EAqBtD,CAAA;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAW7E"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical DCC known-did-registries list. An array of EntityIdentityRegistry
|
|
3
|
+
* entries published by the Digital Credentials Consortium.
|
|
4
|
+
*/
|
|
5
|
+
export const KNOWN_REGISTRIES_URL = 'https://digitalcredentials.github.io/dcc-known-registries/known-did-registries.json';
|
|
6
|
+
/**
|
|
7
|
+
* Legacy DID registry URLs, used as a fallback when KNOWN_REGISTRIES_URL
|
|
8
|
+
* cannot be fetched. Each entry is tagged `type: 'dcc-legacy'` so it satisfies
|
|
9
|
+
* the EntityIdentityRegistry contract consumed by @interop/verifier-core and
|
|
10
|
+
* @digitalcredentials/issuer-registry-client.
|
|
11
|
+
*/
|
|
12
|
+
export const KnownDidRegistries = [
|
|
13
|
+
{
|
|
14
|
+
type: 'dcc-legacy',
|
|
15
|
+
name: 'DCC Pilot Registry',
|
|
16
|
+
url: 'https://digitalcredentials.github.io/issuer-registry/registry.json'
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
type: 'dcc-legacy',
|
|
20
|
+
name: 'DCC Sandbox Registry',
|
|
21
|
+
url: 'https://digitalcredentials.github.io/sandbox-registry/registry.json'
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
type: 'dcc-legacy',
|
|
25
|
+
name: 'DCC Community Registry',
|
|
26
|
+
url: 'https://digitalcredentials.github.io/community-registry/registry.json'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
type: 'dcc-legacy',
|
|
30
|
+
name: 'DCC Registry',
|
|
31
|
+
url: 'https://digitalcredentials.github.io/dcc-registry/registry.json'
|
|
32
|
+
}
|
|
33
|
+
];
|
|
34
|
+
/**
|
|
35
|
+
* Fetches the remote DCC known registries list, falling back to the bundled
|
|
36
|
+
* KnownDidRegistries const on any failure (logged to stderr).
|
|
37
|
+
*
|
|
38
|
+
* @returns {Promise<EntityIdentityRegistry[]>}
|
|
39
|
+
*/
|
|
40
|
+
export async function loadKnownRegistries() {
|
|
41
|
+
try {
|
|
42
|
+
const response = await fetch(KNOWN_REGISTRIES_URL);
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
throw new Error(`Registry fetch failed: ${response.status}`);
|
|
45
|
+
}
|
|
46
|
+
return (await response.json());
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
console.error('Using fallback KnownDidRegistries:', err);
|
|
50
|
+
return KnownDidRegistries;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=registries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registries.js","sourceRoot":"","sources":["../../src/vc/registries.ts"],"names":[],"mappings":"AAWA;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAC/B,qFAAqF,CAAA;AAEvF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAA6B;IAC1D;QACE,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,oBAAoB;QAC1B,GAAG,EAAE,oEAAoE;KAC1E;IACD;QACE,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,sBAAsB;QAC5B,GAAG,EAAE,qEAAqE;KAC3E;IACD;QACE,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,wBAAwB;QAC9B,GAAG,EAAE,uEAAuE;KAC7E;IACD;QACE,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,cAAc;QACpB,GAAG,EAAE,iEAAiE;KACvE;CACF,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,oBAAoB,CAAC,CAAA;QAClD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;QAC9D,CAAC;QACD,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA6B,CAAA;IAC5D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,GAAG,CAAC,CAAA;QACxD,OAAO,kBAAkB,CAAA;IAC3B,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared issuer registry client. Holds a module-level singleton
|
|
3
|
+
* `RegistryClient` (from @digitalcredentials/issuer-registry-client) loaded
|
|
4
|
+
* once with the configured registries, so the issuer-details verification
|
|
5
|
+
* suite can look up rich issuer metadata without re-parsing the registry
|
|
6
|
+
* config on every credential. Keeps registry fetch/caching out of the hot
|
|
7
|
+
* path. Used by `issuerDetailsSuite`.
|
|
8
|
+
*/
|
|
9
|
+
import { RegistryClient } from '@digitalcredentials/issuer-registry-client';
|
|
10
|
+
import type { EntityIdentityRegistry } from '@interop/verifier-core';
|
|
11
|
+
/**
|
|
12
|
+
* Returns a process-wide singleton RegistryClient, loading it with the given
|
|
13
|
+
* registries on first call. Subsequent calls return the same instance and
|
|
14
|
+
* ignore their `registries` argument (the first caller wins) -- the registry
|
|
15
|
+
* config is app-wide and stable for the lifetime of the session.
|
|
16
|
+
*
|
|
17
|
+
* @param options {object}
|
|
18
|
+
* @param options.registries {EntityIdentityRegistry[]} Registries to load on
|
|
19
|
+
* first initialization.
|
|
20
|
+
* @returns {RegistryClient}
|
|
21
|
+
*/
|
|
22
|
+
export declare function getCachedRegistryClient({ registries }: {
|
|
23
|
+
registries: EntityIdentityRegistry[];
|
|
24
|
+
}): RegistryClient;
|
|
25
|
+
//# sourceMappingURL=registryManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registryManager.d.ts","sourceRoot":"","sources":["../../src/vc/registryManager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAA;AAC3E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAA;AAIpE;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,UAAU,EACX,EAAE;IACD,UAAU,EAAE,sBAAsB,EAAE,CAAA;CACrC,GAAG,cAAc,CAMjB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared issuer registry client. Holds a module-level singleton
|
|
3
|
+
* `RegistryClient` (from @digitalcredentials/issuer-registry-client) loaded
|
|
4
|
+
* once with the configured registries, so the issuer-details verification
|
|
5
|
+
* suite can look up rich issuer metadata without re-parsing the registry
|
|
6
|
+
* config on every credential. Keeps registry fetch/caching out of the hot
|
|
7
|
+
* path. Used by `issuerDetailsSuite`.
|
|
8
|
+
*/
|
|
9
|
+
import { RegistryClient } from '@digitalcredentials/issuer-registry-client';
|
|
10
|
+
let cachedClient;
|
|
11
|
+
/**
|
|
12
|
+
* Returns a process-wide singleton RegistryClient, loading it with the given
|
|
13
|
+
* registries on first call. Subsequent calls return the same instance and
|
|
14
|
+
* ignore their `registries` argument (the first caller wins) -- the registry
|
|
15
|
+
* config is app-wide and stable for the lifetime of the session.
|
|
16
|
+
*
|
|
17
|
+
* @param options {object}
|
|
18
|
+
* @param options.registries {EntityIdentityRegistry[]} Registries to load on
|
|
19
|
+
* first initialization.
|
|
20
|
+
* @returns {RegistryClient}
|
|
21
|
+
*/
|
|
22
|
+
export function getCachedRegistryClient({ registries }) {
|
|
23
|
+
if (!cachedClient) {
|
|
24
|
+
cachedClient = new RegistryClient();
|
|
25
|
+
cachedClient.use({ registries });
|
|
26
|
+
}
|
|
27
|
+
return cachedClient;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=registryManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registryManager.js","sourceRoot":"","sources":["../../src/vc/registryManager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAA;AAG3E,IAAI,YAAwC,CAAA;AAE5C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CAAC,EACtC,UAAU,EAGX;IACC,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,YAAY,GAAG,IAAI,cAAc,EAAE,CAAA;QACnC,YAAY,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,CAAC,CAAA;IAClC,CAAC;IACD,OAAO,YAAY,CAAA;AACrB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom verification suite that re-adds the credential expiration check the
|
|
3
|
+
* un-bundled @interop/verifier-core removed ("to be added in future"). It is
|
|
4
|
+
* appended to the pipeline via `additionalSuites` and reads the credential's
|
|
5
|
+
* expiry off the verification subject, comparing it against the injected
|
|
6
|
+
* `timeService`. Kept deliberately small so it can be deleted in favor of the
|
|
7
|
+
* built-in check once expiration returns upstream.
|
|
8
|
+
*
|
|
9
|
+
* Severity: non-fatal (a warning), matching the model where expiration is a
|
|
10
|
+
* soft check rather than a hard cryptographic failure.
|
|
11
|
+
*/
|
|
12
|
+
import type { VerificationSuite } from '@interop/verifier-core';
|
|
13
|
+
/**
|
|
14
|
+
* Own problem `type` URI for an expired credential. The fork has no built-in
|
|
15
|
+
* EXPIRED problem type, so we mint one in the did-cli namespace.
|
|
16
|
+
*/
|
|
17
|
+
export declare const EXPIRED_PROBLEM_TYPE = "urn:did-cli:problem:EXPIRED";
|
|
18
|
+
/**
|
|
19
|
+
* The expiration suite, appended to the verifier pipeline via
|
|
20
|
+
* `additionalSuites`.
|
|
21
|
+
*/
|
|
22
|
+
export declare const expirationSuite: VerificationSuite;
|
|
23
|
+
//# sourceMappingURL=expirationSuite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expirationSuite.d.ts","sourceRoot":"","sources":["../../../src/vc/suites/expirationSuite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAKV,iBAAiB,EAClB,MAAM,wBAAwB,CAAA;AAE/B;;;GAGG;AACH,eAAO,MAAM,oBAAoB,gCAAgC,CAAA;AAqFjE;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,iBAM7B,CAAA"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Own problem `type` URI for an expired credential. The fork has no built-in
|
|
3
|
+
* EXPIRED problem type, so we mint one in the did-cli namespace.
|
|
4
|
+
*/
|
|
5
|
+
export const EXPIRED_PROBLEM_TYPE = 'urn:did-cli:problem:EXPIRED';
|
|
6
|
+
/**
|
|
7
|
+
* Reads the credential's expiry instant, preferring the VC 2.0 `validUntil`
|
|
8
|
+
* property and falling back to the VC 1.x `expirationDate`.
|
|
9
|
+
*
|
|
10
|
+
* @param credential {Record<string, unknown>}
|
|
11
|
+
* @returns {string | undefined} The ISO date string, or undefined when none.
|
|
12
|
+
*/
|
|
13
|
+
function getExpirationIso(credential) {
|
|
14
|
+
const validUntil = credential.validUntil;
|
|
15
|
+
if (typeof validUntil === 'string' && validUntil) {
|
|
16
|
+
return validUntil;
|
|
17
|
+
}
|
|
18
|
+
const expirationDate = credential.expirationDate;
|
|
19
|
+
if (typeof expirationDate === 'string' && expirationDate) {
|
|
20
|
+
return expirationDate;
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
const expirationCheck = {
|
|
25
|
+
id: 'validity.expiration',
|
|
26
|
+
name: 'Credential Expiration Check',
|
|
27
|
+
description: 'Verifies the credential is within its validity period (validUntil / expirationDate).',
|
|
28
|
+
fatal: false,
|
|
29
|
+
appliesTo: ['verifiableCredential'],
|
|
30
|
+
execute: async (subject, context) => {
|
|
31
|
+
const credential = subject.verifiableCredential;
|
|
32
|
+
if (!credential) {
|
|
33
|
+
return {
|
|
34
|
+
status: 'skipped',
|
|
35
|
+
reason: 'No verifiable credential found in subject.'
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const expirationIso = getExpirationIso(credential);
|
|
39
|
+
if (!expirationIso) {
|
|
40
|
+
return {
|
|
41
|
+
status: 'skipped',
|
|
42
|
+
reason: 'Credential has no expiration date.'
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const expiresMs = new Date(expirationIso).getTime();
|
|
46
|
+
if (Number.isNaN(expiresMs)) {
|
|
47
|
+
return {
|
|
48
|
+
status: 'skipped',
|
|
49
|
+
reason: 'Credential expiration date is not a valid date.'
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const nowMs = context.timeService
|
|
53
|
+
? context.timeService.dateNowMs()
|
|
54
|
+
: Date.now();
|
|
55
|
+
if (expiresMs >= nowMs) {
|
|
56
|
+
return {
|
|
57
|
+
status: 'success',
|
|
58
|
+
message: `Credential is within its validity period (expires ${expirationIso}).`
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
status: 'failure',
|
|
63
|
+
problems: [
|
|
64
|
+
{
|
|
65
|
+
type: EXPIRED_PROBLEM_TYPE,
|
|
66
|
+
title: 'Credential Expired',
|
|
67
|
+
detail: `Credential expired on ${expirationIso}.`
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* The expiration suite, appended to the verifier pipeline via
|
|
75
|
+
* `additionalSuites`.
|
|
76
|
+
*/
|
|
77
|
+
export const expirationSuite = {
|
|
78
|
+
id: 'validity',
|
|
79
|
+
name: 'Validity Period',
|
|
80
|
+
description: 'Checks the credential expiration / validity period.',
|
|
81
|
+
phase: 'cryptographic',
|
|
82
|
+
checks: [expirationCheck]
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=expirationSuite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expirationSuite.js","sourceRoot":"","sources":["../../../src/vc/suites/expirationSuite.ts"],"names":[],"mappings":"AAmBA;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,6BAA6B,CAAA;AAEjE;;;;;;GAMG;AACH,SAAS,gBAAgB,CACvB,UAAmC;IAEnC,MAAM,UAAU,GAAG,UAAU,CAAC,UAAU,CAAA;IACxC,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,EAAE,CAAC;QACjD,OAAO,UAAU,CAAA;IACnB,CAAC;IACD,MAAM,cAAc,GAAG,UAAU,CAAC,cAAc,CAAA;IAChD,IAAI,OAAO,cAAc,KAAK,QAAQ,IAAI,cAAc,EAAE,CAAC;QACzD,OAAO,cAAc,CAAA;IACvB,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,MAAM,eAAe,GAAsB;IACzC,EAAE,EAAE,qBAAqB;IACzB,IAAI,EAAE,6BAA6B;IACnC,WAAW,EACT,sFAAsF;IACxF,KAAK,EAAE,KAAK;IACZ,SAAS,EAAE,CAAC,sBAAsB,CAAC;IACnC,OAAO,EAAE,KAAK,EACZ,OAA4B,EAC5B,OAA4B,EACL,EAAE;QACzB,MAAM,UAAU,GAAG,OAAO,CAAC,oBAEd,CAAA;QAEb,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO;gBACL,MAAM,EAAE,SAAS;gBACjB,MAAM,EAAE,4CAA4C;aACrD,CAAA;QACH,CAAC;QAED,MAAM,aAAa,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAA;QAClD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO;gBACL,MAAM,EAAE,SAAS;gBACjB,MAAM,EAAE,oCAAoC;aAC7C,CAAA;QACH,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE,CAAA;QACnD,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5B,OAAO;gBACL,MAAM,EAAE,SAAS;gBACjB,MAAM,EAAE,iDAAiD;aAC1D,CAAA;QACH,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW;YAC/B,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,EAAE;YACjC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAA;QAEd,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;YACvB,OAAO;gBACL,MAAM,EAAE,SAAS;gBACjB,OAAO,EAAE,qDAAqD,aAAa,IAAI;aAChF,CAAA;QACH,CAAC;QAED,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,oBAAoB;oBAC1B,KAAK,EAAE,oBAAoB;oBAC3B,MAAM,EAAE,yBAAyB,aAAa,GAAG;iBAClD;aACF;SACF,CAAA;IACH,CAAC;CACF,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAsB;IAChD,EAAE,EAAE,UAAU;IACd,IAAI,EAAE,iBAAiB;IACvB,WAAW,EAAE,qDAAqD;IAClE,KAAK,EAAE,eAAe;IACtB,MAAM,EAAE,CAAC,eAAe,CAAC;CAC1B,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom verification suite that surfaces rich issuer registry metadata.
|
|
3
|
+
*
|
|
4
|
+
* The un-bundled @interop/verifier-core gutted the registry check down to a
|
|
5
|
+
* boolean `{ found, matchingRegistries }` and discards the rich issuer
|
|
6
|
+
* payload (logo, legal name, homepage, registry org). This suite restores it:
|
|
7
|
+
* it calls @digitalcredentials/issuer-registry-client's `lookupIssuersFor`
|
|
8
|
+
* via the shared singleton client and returns the full `matchingIssuers`
|
|
9
|
+
* entries on the check `outcome.payload` -- the same channel the verifier's
|
|
10
|
+
* own `recognition.profile` uses. `verify.ts` reads this payload back into the
|
|
11
|
+
* `--summary` output's `matchingIssuers`.
|
|
12
|
+
*
|
|
13
|
+
* Severity: non-fatal (a warning) -- an unrecognized issuer is informational,
|
|
14
|
+
* not a hard cryptographic failure.
|
|
15
|
+
*/
|
|
16
|
+
import type { VerificationSuite } from '@interop/verifier-core';
|
|
17
|
+
/**
|
|
18
|
+
* The issuer-details suite, appended to the verifier pipeline via
|
|
19
|
+
* `additionalSuites`. This is the authoritative source of rich issuer data.
|
|
20
|
+
*/
|
|
21
|
+
export declare const issuerDetailsSuite: VerificationSuite;
|
|
22
|
+
//# sourceMappingURL=issuerDetailsSuite.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issuerDetailsSuite.d.ts","sourceRoot":"","sources":["../../../src/vc/suites/issuerDetailsSuite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAKV,iBAAiB,EAClB,MAAM,wBAAwB,CAAA;AAyE/B;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,iBAMhC,CAAA"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { getCachedRegistryClient } from '../registryManager.js';
|
|
2
|
+
/**
|
|
3
|
+
* Extracts the issuer DID from a credential, handling both the string and
|
|
4
|
+
* `{ id }` object forms of the `issuer` property.
|
|
5
|
+
*
|
|
6
|
+
* @param credential {Record<string, unknown>}
|
|
7
|
+
* @returns {string | undefined}
|
|
8
|
+
*/
|
|
9
|
+
function getIssuerDid(credential) {
|
|
10
|
+
const issuer = credential.issuer;
|
|
11
|
+
if (typeof issuer === 'string') {
|
|
12
|
+
return issuer;
|
|
13
|
+
}
|
|
14
|
+
if (issuer && typeof issuer === 'object' && typeof issuer.id === 'string') {
|
|
15
|
+
return issuer.id;
|
|
16
|
+
}
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
const issuerDetailsCheck = {
|
|
20
|
+
id: 'trust.issuer-details',
|
|
21
|
+
name: 'Issuer Registry Details',
|
|
22
|
+
description: 'Looks up rich issuer metadata for the credential issuer in the configured registries.',
|
|
23
|
+
fatal: false,
|
|
24
|
+
appliesTo: ['verifiableCredential'],
|
|
25
|
+
execute: async (subject, context) => {
|
|
26
|
+
const credential = subject.verifiableCredential;
|
|
27
|
+
if (!credential) {
|
|
28
|
+
return {
|
|
29
|
+
status: 'skipped',
|
|
30
|
+
reason: 'No verifiable credential found in subject.'
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (!context.registries || context.registries.length === 0) {
|
|
34
|
+
return {
|
|
35
|
+
status: 'skipped',
|
|
36
|
+
reason: 'No registries configured in verification context.'
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const issuerDid = getIssuerDid(credential);
|
|
40
|
+
if (!issuerDid) {
|
|
41
|
+
return {
|
|
42
|
+
status: 'skipped',
|
|
43
|
+
reason: 'Credential has no issuer DID.'
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const client = getCachedRegistryClient({ registries: context.registries });
|
|
47
|
+
const { matchingIssuers } = await client.lookupIssuersFor(issuerDid);
|
|
48
|
+
const count = matchingIssuers.length;
|
|
49
|
+
return {
|
|
50
|
+
status: 'success',
|
|
51
|
+
message: count > 0
|
|
52
|
+
? `Issuer found in ${count} registr${count === 1 ? 'y' : 'ies'}.`
|
|
53
|
+
: 'Issuer not found in any configured registry.',
|
|
54
|
+
payload: { matchingIssuers }
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* The issuer-details suite, appended to the verifier pipeline via
|
|
60
|
+
* `additionalSuites`. This is the authoritative source of rich issuer data.
|
|
61
|
+
*/
|
|
62
|
+
export const issuerDetailsSuite = {
|
|
63
|
+
id: 'trust',
|
|
64
|
+
name: 'Issuer Trust',
|
|
65
|
+
description: 'Surfaces rich issuer registry metadata.',
|
|
66
|
+
phase: 'trust',
|
|
67
|
+
checks: [issuerDetailsCheck]
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=issuerDetailsSuite.js.map
|