@kya-os/mcp-i-core 1.8.0 → 1.8.2
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/dist/conformance/capability-verifier-adapter.d.ts +66 -0
- package/dist/conformance/capability-verifier-adapter.js +61 -0
- package/dist/conformance/index.d.ts +3 -1
- package/dist/conformance/index.js +7 -1
- package/dist/conformance/validate-level2.d.ts +13 -3
- package/dist/conformance/validate-level2.js +15 -5
- package/dist/conformance/vc-jwt-verifier.d.ts +55 -0
- package/dist/conformance/vc-jwt-verifier.js +147 -0
- package/dist/delegation/did-web-resolver.d.ts +60 -0
- package/dist/delegation/did-web-resolver.js +129 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +9 -1
- package/package.json +3 -3
- package/dist/auth/handshake.d.ts +0 -119
- package/dist/auth/handshake.js +0 -250
- package/dist/auth/index.d.ts +0 -6
- package/dist/auth/index.js +0 -11
- package/dist/auth/types.d.ts +0 -46
- package/dist/auth/types.js +0 -10
- package/dist/cache/oauth-config-cache.d.ts +0 -69
- package/dist/cache/oauth-config-cache.js +0 -76
- package/dist/cache/tool-protection-cache.d.ts +0 -89
- package/dist/cache/tool-protection-cache.js +0 -118
- package/dist/compliance/index.d.ts +0 -8
- package/dist/compliance/index.js +0 -24
- package/dist/compliance/schema-registry.d.ts +0 -50
- package/dist/compliance/schema-registry.js +0 -438
- package/dist/compliance/schema-verifier.d.ts +0 -110
- package/dist/compliance/schema-verifier.js +0 -518
- package/dist/config/remote-config.d.ts +0 -173
- package/dist/config/remote-config.js +0 -253
- package/dist/config.d.ts +0 -182
- package/dist/config.js +0 -148
- package/dist/identity/idp-token-resolver.d.ts +0 -69
- package/dist/identity/idp-token-resolver.js +0 -136
- package/dist/identity/idp-token-storage.interface.d.ts +0 -80
- package/dist/identity/idp-token-storage.interface.js +0 -14
- package/dist/identity/user-did-manager.d.ts +0 -228
- package/dist/identity/user-did-manager.js +0 -356
- package/dist/logging/index.d.ts +0 -5
- package/dist/logging/index.js +0 -10
- package/dist/logging/logger.d.ts +0 -33
- package/dist/logging/logger.js +0 -104
- package/dist/proof/generator.d.ts +0 -109
- package/dist/proof/generator.js +0 -236
- package/dist/proof/index.d.ts +0 -5
- package/dist/proof/index.js +0 -11
- package/dist/providers/base.d.ts +0 -95
- package/dist/providers/base.js +0 -47
- package/dist/providers/memory.d.ts +0 -42
- package/dist/providers/memory.js +0 -121
- package/dist/runtime/audit-logger.d.ts +0 -37
- package/dist/runtime/audit-logger.js +0 -9
- package/dist/runtime/base.d.ts +0 -375
- package/dist/runtime/base.js +0 -1491
- package/dist/runtime/ext-apps-constants.d.ts +0 -14
- package/dist/runtime/ext-apps-constants.js +0 -17
- package/dist/services/access-control.service.d.ts +0 -138
- package/dist/services/access-control.service.js +0 -721
- package/dist/services/authorization/authorization-registry.d.ts +0 -29
- package/dist/services/authorization/authorization-registry.js +0 -58
- package/dist/services/authorization/types.d.ts +0 -53
- package/dist/services/authorization/types.js +0 -10
- package/dist/services/batch-delegation.service.d.ts +0 -53
- package/dist/services/batch-delegation.service.js +0 -95
- package/dist/services/crypto.service.d.ts +0 -69
- package/dist/services/crypto.service.js +0 -225
- package/dist/services/delegation-error-formatter.d.ts +0 -124
- package/dist/services/delegation-error-formatter.js +0 -214
- package/dist/services/errors.d.ts +0 -49
- package/dist/services/errors.js +0 -66
- package/dist/services/index.d.ts +0 -9
- package/dist/services/index.js +0 -15
- package/dist/services/oauth-config.service.d.ts +0 -53
- package/dist/services/oauth-config.service.js +0 -141
- package/dist/services/oauth-provider-registry.d.ts +0 -88
- package/dist/services/oauth-provider-registry.js +0 -128
- package/dist/services/oauth-service.d.ts +0 -122
- package/dist/services/oauth-service.js +0 -442
- package/dist/services/oauth-token-retrieval.service.d.ts +0 -49
- package/dist/services/oauth-token-retrieval.service.js +0 -150
- package/dist/services/policy.service.d.ts +0 -130
- package/dist/services/policy.service.js +0 -399
- package/dist/services/proof-verifier.d.ts +0 -98
- package/dist/services/proof-verifier.js +0 -319
- package/dist/services/provider-resolver.d.ts +0 -89
- package/dist/services/provider-resolver.js +0 -196
- package/dist/services/provider-validator.d.ts +0 -55
- package/dist/services/provider-validator.js +0 -135
- package/dist/services/session-registration.service.d.ts +0 -80
- package/dist/services/session-registration.service.js +0 -174
- package/dist/services/storage.service.d.ts +0 -116
- package/dist/services/storage.service.js +0 -411
- package/dist/services/tool-context-builder.d.ts +0 -74
- package/dist/services/tool-context-builder.js +0 -215
- package/dist/services/tool-protection.service.d.ts +0 -193
- package/dist/services/tool-protection.service.js +0 -736
- package/dist/session/index.d.ts +0 -5
- package/dist/session/index.js +0 -11
- package/dist/session/manager.d.ts +0 -113
- package/dist/session/manager.js +0 -273
- package/dist/types/oauth-required-error.d.ts +0 -46
- package/dist/types/oauth-required-error.js +0 -42
- package/dist/types/tool-protection.d.ts +0 -144
- package/dist/types/tool-protection.js +0 -48
- package/dist/utils/cors.d.ts +0 -44
- package/dist/utils/cors.js +0 -71
- package/dist/utils/index.d.ts +0 -8
- package/dist/utils/index.js +0 -24
- package/dist/utils/storage-keys.d.ts +0 -120
- package/dist/utils/storage-keys.js +0 -217
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CapabilityVerifier Adapter
|
|
3
|
+
*
|
|
4
|
+
* Adapts {@link verifyCapabilities} into the small, duck-typed verifier shape an
|
|
5
|
+
* entity-card consumer expects: given a list of capabilities and a verification
|
|
6
|
+
* context, return which capability names are `verified` (backed by a verified
|
|
7
|
+
* attestation) and which are `unverified` (self-declared or failed).
|
|
8
|
+
*
|
|
9
|
+
* The capability and verifier types are defined locally rather than imported
|
|
10
|
+
* from `@kya-os/mcp`: mcp-i-core pins `@kya-os/mcp@1.6.1`, which predates the
|
|
11
|
+
* entity-card export, so importing it would not resolve.
|
|
12
|
+
*
|
|
13
|
+
* Mapping:
|
|
14
|
+
* - bare-string capability → `unverified` (Level 1, self-declared)
|
|
15
|
+
* - L2 object capability → checked via {@link verifyCapabilities}; its
|
|
16
|
+
* `valid` names become `verified`, its `invalid` names become `unverified`.
|
|
17
|
+
*/
|
|
18
|
+
import { type CapabilityVCSignatureVerifier } from './validate-level2.js';
|
|
19
|
+
import type { DIDResolver } from '../delegation/vc-verifier.js';
|
|
20
|
+
/**
|
|
21
|
+
* Duck-typed capability. A bare string is a Level 1 self-declared capability;
|
|
22
|
+
* an object with a `name` (and optional `attestations`) is a Level 2 attested
|
|
23
|
+
* capability.
|
|
24
|
+
*/
|
|
25
|
+
export type DuckTypedCapability = string | {
|
|
26
|
+
name: string;
|
|
27
|
+
attestations?: readonly unknown[];
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
};
|
|
30
|
+
/** Context describing whose capabilities are being checked, and against whom. */
|
|
31
|
+
export interface CapabilityVerificationContext {
|
|
32
|
+
/** The subject (agent) DID the capabilities are claimed for. */
|
|
33
|
+
subjectDid: string;
|
|
34
|
+
/** Issuer DIDs trusted to attest capabilities. */
|
|
35
|
+
trustedIssuers: readonly string[];
|
|
36
|
+
}
|
|
37
|
+
/** Partition of capability names by verification outcome. */
|
|
38
|
+
export interface CapabilityVerificationResult {
|
|
39
|
+
/** Capability names backed by a verified attestation. */
|
|
40
|
+
verified: string[];
|
|
41
|
+
/** Capability names that are self-declared or failed verification. */
|
|
42
|
+
unverified: string[];
|
|
43
|
+
}
|
|
44
|
+
/** The duck-typed verifier returned by {@link createCapabilityVerifier}. */
|
|
45
|
+
export type CapabilityVerifier = (capabilities: readonly DuckTypedCapability[], ctx: CapabilityVerificationContext) => Promise<CapabilityVerificationResult>;
|
|
46
|
+
/** Options for {@link createCapabilityVerifier}. */
|
|
47
|
+
export interface CreateCapabilityVerifierOptions {
|
|
48
|
+
/**
|
|
49
|
+
* Signature verifier for Level 2 attestations. Defaults to a VC-JWT verifier
|
|
50
|
+
* (see {@link createVcJwtSignatureVerifier}).
|
|
51
|
+
*/
|
|
52
|
+
signatureVerifier?: CapabilityVCSignatureVerifier;
|
|
53
|
+
/**
|
|
54
|
+
* DID resolver for the default signature verifier. Ignored when a
|
|
55
|
+
* `signatureVerifier` is supplied.
|
|
56
|
+
*/
|
|
57
|
+
didResolver?: DIDResolver;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Create a capability verifier.
|
|
61
|
+
*
|
|
62
|
+
* @param options - Optional signature-verifier / DID-resolver overrides.
|
|
63
|
+
* @returns A verifier mapping capabilities to `{ verified, unverified }`.
|
|
64
|
+
*/
|
|
65
|
+
export declare function createCapabilityVerifier(options?: CreateCapabilityVerifierOptions): CapabilityVerifier;
|
|
66
|
+
//# sourceMappingURL=capability-verifier-adapter.d.ts.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CapabilityVerifier Adapter
|
|
4
|
+
*
|
|
5
|
+
* Adapts {@link verifyCapabilities} into the small, duck-typed verifier shape an
|
|
6
|
+
* entity-card consumer expects: given a list of capabilities and a verification
|
|
7
|
+
* context, return which capability names are `verified` (backed by a verified
|
|
8
|
+
* attestation) and which are `unverified` (self-declared or failed).
|
|
9
|
+
*
|
|
10
|
+
* The capability and verifier types are defined locally rather than imported
|
|
11
|
+
* from `@kya-os/mcp`: mcp-i-core pins `@kya-os/mcp@1.6.1`, which predates the
|
|
12
|
+
* entity-card export, so importing it would not resolve.
|
|
13
|
+
*
|
|
14
|
+
* Mapping:
|
|
15
|
+
* - bare-string capability → `unverified` (Level 1, self-declared)
|
|
16
|
+
* - L2 object capability → checked via {@link verifyCapabilities}; its
|
|
17
|
+
* `valid` names become `verified`, its `invalid` names become `unverified`.
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.createCapabilityVerifier = createCapabilityVerifier;
|
|
21
|
+
const validate_level2_js_1 = require("./validate-level2.js");
|
|
22
|
+
const vc_jwt_verifier_js_1 = require("./vc-jwt-verifier.js");
|
|
23
|
+
/**
|
|
24
|
+
* Create a capability verifier.
|
|
25
|
+
*
|
|
26
|
+
* @param options - Optional signature-verifier / DID-resolver overrides.
|
|
27
|
+
* @returns A verifier mapping capabilities to `{ verified, unverified }`.
|
|
28
|
+
*/
|
|
29
|
+
function createCapabilityVerifier(options = {}) {
|
|
30
|
+
const signatureVerifier = options.signatureVerifier ??
|
|
31
|
+
(0, vc_jwt_verifier_js_1.createVcJwtSignatureVerifier)({ didResolver: options.didResolver });
|
|
32
|
+
return async (capabilities, ctx) => {
|
|
33
|
+
const list = Array.isArray(capabilities) ? capabilities : [];
|
|
34
|
+
const bareStrings = [];
|
|
35
|
+
const attested = [];
|
|
36
|
+
for (const capability of list) {
|
|
37
|
+
if (typeof capability === 'string') {
|
|
38
|
+
bareStrings.push(capability);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
attested.push(capability);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const result = await (0, validate_level2_js_1.verifyCapabilities)(attested, {
|
|
45
|
+
agentDid: ctx.subjectDid,
|
|
46
|
+
trustedIssuers: [...ctx.trustedIssuers],
|
|
47
|
+
signatureVerifier,
|
|
48
|
+
});
|
|
49
|
+
const verified = result.valid;
|
|
50
|
+
const verifiedSet = new Set(verified);
|
|
51
|
+
// A capability verified via its L2 attestation must not also appear as
|
|
52
|
+
// unverified — e.g. when the input mixes a bare-string and an attested
|
|
53
|
+
// object for the same name. Exclude already-verified names, and dedupe.
|
|
54
|
+
const unverified = Array.from(new Set([
|
|
55
|
+
...bareStrings,
|
|
56
|
+
...result.invalid.map((entry) => entry.capability),
|
|
57
|
+
])).filter((name) => !verifiedSet.has(name));
|
|
58
|
+
return { verified, unverified };
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=capability-verifier-adapter.js.map
|
|
@@ -4,5 +4,7 @@
|
|
|
4
4
|
* See docs/conformance-levels for the spec page (introduced in
|
|
5
5
|
* modelcontextprotocol-identity#46).
|
|
6
6
|
*/
|
|
7
|
-
export { validateLevel2, DEFAULT_TRUSTED_ISSUERS, type CapabilityName, type CapabilityAttestation, type CapabilityAttestationCredential, type Level2Capability, type ManifestCapabilities, type CapabilityVCSignatureVerifier, type CapabilityStatusListResolver, type ValidateLevel2Options, type ValidateLevel2Result, type InvalidCapability, } from './validate-level2.js';
|
|
7
|
+
export { verifyCapabilities, validateLevel2, DEFAULT_TRUSTED_ISSUERS, type CapabilityName, type CapabilityAttestation, type CapabilityAttestationCredential, type Level2Capability, type ManifestCapabilities, type CapabilityVCSignatureVerifier, type CapabilityStatusListResolver, type ValidateLevel2Options, type ValidateLevel2Result, type InvalidCapability, } from './validate-level2.js';
|
|
8
|
+
export { createVcJwtSignatureVerifier, createCombinedDidResolver, type VcJwtVerifierOptions, } from './vc-jwt-verifier.js';
|
|
9
|
+
export { createCapabilityVerifier, type DuckTypedCapability, type CapabilityVerificationContext, type CapabilityVerificationResult, type CapabilityVerifier, type CreateCapabilityVerifierOptions, } from './capability-verifier-adapter.js';
|
|
8
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -6,8 +6,14 @@
|
|
|
6
6
|
* modelcontextprotocol-identity#46).
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.DEFAULT_TRUSTED_ISSUERS = exports.validateLevel2 = void 0;
|
|
9
|
+
exports.createCapabilityVerifier = exports.createCombinedDidResolver = exports.createVcJwtSignatureVerifier = exports.DEFAULT_TRUSTED_ISSUERS = exports.validateLevel2 = exports.verifyCapabilities = void 0;
|
|
10
10
|
var validate_level2_js_1 = require("./validate-level2.js");
|
|
11
|
+
Object.defineProperty(exports, "verifyCapabilities", { enumerable: true, get: function () { return validate_level2_js_1.verifyCapabilities; } });
|
|
11
12
|
Object.defineProperty(exports, "validateLevel2", { enumerable: true, get: function () { return validate_level2_js_1.validateLevel2; } });
|
|
12
13
|
Object.defineProperty(exports, "DEFAULT_TRUSTED_ISSUERS", { enumerable: true, get: function () { return validate_level2_js_1.DEFAULT_TRUSTED_ISSUERS; } });
|
|
14
|
+
var vc_jwt_verifier_js_1 = require("./vc-jwt-verifier.js");
|
|
15
|
+
Object.defineProperty(exports, "createVcJwtSignatureVerifier", { enumerable: true, get: function () { return vc_jwt_verifier_js_1.createVcJwtSignatureVerifier; } });
|
|
16
|
+
Object.defineProperty(exports, "createCombinedDidResolver", { enumerable: true, get: function () { return vc_jwt_verifier_js_1.createCombinedDidResolver; } });
|
|
17
|
+
var capability_verifier_adapter_js_1 = require("./capability-verifier-adapter.js");
|
|
18
|
+
Object.defineProperty(exports, "createCapabilityVerifier", { enumerable: true, get: function () { return capability_verifier_adapter_js_1.createCapabilityVerifier; } });
|
|
13
19
|
//# sourceMappingURL=index.js.map
|
|
@@ -174,11 +174,15 @@ export interface ValidateLevel2Result {
|
|
|
174
174
|
warnings: string[];
|
|
175
175
|
}
|
|
176
176
|
/**
|
|
177
|
-
*
|
|
177
|
+
* Verify an MCP-I agent's declared capability attestations (Level 2).
|
|
178
|
+
*
|
|
179
|
+
* Named for the action it performs — verifying capability ATTESTATIONS — rather
|
|
180
|
+
* than the conformance level. {@link validateLevel2} remains exported as a
|
|
181
|
+
* non-breaking `@deprecated` alias.
|
|
178
182
|
*
|
|
179
183
|
* @example
|
|
180
184
|
* ```ts
|
|
181
|
-
* const result = await
|
|
185
|
+
* const result = await verifyCapabilities(manifest.capabilities, {
|
|
182
186
|
* agentDid: 'did:web:securebank.example',
|
|
183
187
|
* trustedIssuers: ['did:web:knowthat.ai'],
|
|
184
188
|
* signatureVerifier: myEd25519Verifier,
|
|
@@ -189,5 +193,11 @@ export interface ValidateLevel2Result {
|
|
|
189
193
|
* console.log(result.warnings); // []
|
|
190
194
|
* ```
|
|
191
195
|
*/
|
|
192
|
-
export declare function
|
|
196
|
+
export declare function verifyCapabilities(capabilities: unknown, options: ValidateLevel2Options): Promise<ValidateLevel2Result>;
|
|
197
|
+
/**
|
|
198
|
+
* @deprecated Renamed to {@link verifyCapabilities}. Retained as a non-breaking
|
|
199
|
+
* alias — the two are referentially identical. Prefer `verifyCapabilities` in
|
|
200
|
+
* new code; this alias will be removed in a future major.
|
|
201
|
+
*/
|
|
202
|
+
export declare const validateLevel2: typeof verifyCapabilities;
|
|
193
203
|
//# sourceMappingURL=validate-level2.d.ts.map
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
* the missing attestation context.
|
|
25
25
|
*/
|
|
26
26
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
-
exports.DEFAULT_TRUSTED_ISSUERS = void 0;
|
|
28
|
-
exports.
|
|
27
|
+
exports.validateLevel2 = exports.DEFAULT_TRUSTED_ISSUERS = void 0;
|
|
28
|
+
exports.verifyCapabilities = verifyCapabilities;
|
|
29
29
|
const utils_js_1 = require("../delegation/utils.js");
|
|
30
30
|
/**
|
|
31
31
|
* Default trusted issuer registry.
|
|
@@ -37,11 +37,15 @@ exports.DEFAULT_TRUSTED_ISSUERS = [
|
|
|
37
37
|
'did:web:knowthat.ai',
|
|
38
38
|
];
|
|
39
39
|
/**
|
|
40
|
-
*
|
|
40
|
+
* Verify an MCP-I agent's declared capability attestations (Level 2).
|
|
41
|
+
*
|
|
42
|
+
* Named for the action it performs — verifying capability ATTESTATIONS — rather
|
|
43
|
+
* than the conformance level. {@link validateLevel2} remains exported as a
|
|
44
|
+
* non-breaking `@deprecated` alias.
|
|
41
45
|
*
|
|
42
46
|
* @example
|
|
43
47
|
* ```ts
|
|
44
|
-
* const result = await
|
|
48
|
+
* const result = await verifyCapabilities(manifest.capabilities, {
|
|
45
49
|
* agentDid: 'did:web:securebank.example',
|
|
46
50
|
* trustedIssuers: ['did:web:knowthat.ai'],
|
|
47
51
|
* signatureVerifier: myEd25519Verifier,
|
|
@@ -52,7 +56,7 @@ exports.DEFAULT_TRUSTED_ISSUERS = [
|
|
|
52
56
|
* console.log(result.warnings); // []
|
|
53
57
|
* ```
|
|
54
58
|
*/
|
|
55
|
-
async function
|
|
59
|
+
async function verifyCapabilities(capabilities, options) {
|
|
56
60
|
const result = {
|
|
57
61
|
valid: [],
|
|
58
62
|
invalid: [],
|
|
@@ -118,6 +122,12 @@ async function validateLevel2(capabilities, options) {
|
|
|
118
122
|
}
|
|
119
123
|
return result;
|
|
120
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* @deprecated Renamed to {@link verifyCapabilities}. Retained as a non-breaking
|
|
127
|
+
* alias — the two are referentially identical. Prefer `verifyCapabilities` in
|
|
128
|
+
* new code; this alias will be removed in a future major.
|
|
129
|
+
*/
|
|
130
|
+
exports.validateLevel2 = verifyCapabilities;
|
|
121
131
|
async function validateCapability(capability, ctx) {
|
|
122
132
|
const reasons = [];
|
|
123
133
|
if (!Array.isArray(capability.attestations) || capability.attestations.length === 0) {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VC-JWT Signature Verifier
|
|
3
|
+
*
|
|
4
|
+
* A {@link CapabilityVCSignatureVerifier} (the pluggable signature hook accepted
|
|
5
|
+
* by {@link verifyCapabilities}) that cryptographically verifies a capability
|
|
6
|
+
* attestation presented as a compact VC-JWT (JWS).
|
|
7
|
+
*
|
|
8
|
+
* Flow:
|
|
9
|
+
* 1. If no compact JWS was supplied (object-form VC) → reject. There is
|
|
10
|
+
* nothing to verify cryptographically.
|
|
11
|
+
* 2. Resolve the credential's `issuer` DID via a combined, pluggable resolver
|
|
12
|
+
* (did:key built in, plus the did:web resolver).
|
|
13
|
+
* 3. Select the verification method whose id matches the JWS header `kid`.
|
|
14
|
+
* 4. Import its `publicKeyJwk` as an EdDSA key and verify the compact JWS.
|
|
15
|
+
*
|
|
16
|
+
* The verifier never throws — every failure path returns
|
|
17
|
+
* `{ valid: false, reason }` so it composes cleanly inside the validator's
|
|
18
|
+
* per-attestation loop.
|
|
19
|
+
*
|
|
20
|
+
* @see ./validate-level2.ts — the validator this plugs into.
|
|
21
|
+
*/
|
|
22
|
+
import { type DidWebFetch } from '../delegation/did-web-resolver.js';
|
|
23
|
+
import type { DIDResolver } from '../delegation/vc-verifier.js';
|
|
24
|
+
import type { CapabilityVCSignatureVerifier } from './validate-level2.js';
|
|
25
|
+
/** Options for {@link createVcJwtSignatureVerifier}. */
|
|
26
|
+
export interface VcJwtVerifierOptions {
|
|
27
|
+
/**
|
|
28
|
+
* DID resolver used to fetch the issuer's verification keys. Defaults to a
|
|
29
|
+
* combined did:key + did:web resolver (see {@link createCombinedDidResolver}).
|
|
30
|
+
*/
|
|
31
|
+
didResolver?: DIDResolver;
|
|
32
|
+
/**
|
|
33
|
+
* Pluggable fetch passed to the default did:web resolver. Ignored when a
|
|
34
|
+
* `didResolver` is supplied. Defaults to the global `fetch`.
|
|
35
|
+
*/
|
|
36
|
+
fetch?: DidWebFetch;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Create a DID resolver that dispatches by method: did:key is resolved locally,
|
|
40
|
+
* did:web is fetched over HTTPS, and every other method resolves to `null`.
|
|
41
|
+
*
|
|
42
|
+
* @param options - Optional pluggable fetch for the did:web branch.
|
|
43
|
+
*/
|
|
44
|
+
export declare function createCombinedDidResolver(options?: {
|
|
45
|
+
fetch?: DidWebFetch;
|
|
46
|
+
}): DIDResolver;
|
|
47
|
+
/**
|
|
48
|
+
* Create a VC-JWT signature verifier suitable for
|
|
49
|
+
* {@link verifyCapabilities}'s `signatureVerifier` option.
|
|
50
|
+
*
|
|
51
|
+
* @param options - DID resolver / fetch overrides.
|
|
52
|
+
* @returns A `(vc, rawJwt) => Promise<{ valid; reason? }>` function.
|
|
53
|
+
*/
|
|
54
|
+
export declare function createVcJwtSignatureVerifier(options?: VcJwtVerifierOptions): CapabilityVCSignatureVerifier;
|
|
55
|
+
//# sourceMappingURL=vc-jwt-verifier.d.ts.map
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* VC-JWT Signature Verifier
|
|
4
|
+
*
|
|
5
|
+
* A {@link CapabilityVCSignatureVerifier} (the pluggable signature hook accepted
|
|
6
|
+
* by {@link verifyCapabilities}) that cryptographically verifies a capability
|
|
7
|
+
* attestation presented as a compact VC-JWT (JWS).
|
|
8
|
+
*
|
|
9
|
+
* Flow:
|
|
10
|
+
* 1. If no compact JWS was supplied (object-form VC) → reject. There is
|
|
11
|
+
* nothing to verify cryptographically.
|
|
12
|
+
* 2. Resolve the credential's `issuer` DID via a combined, pluggable resolver
|
|
13
|
+
* (did:key built in, plus the did:web resolver).
|
|
14
|
+
* 3. Select the verification method whose id matches the JWS header `kid`.
|
|
15
|
+
* 4. Import its `publicKeyJwk` as an EdDSA key and verify the compact JWS.
|
|
16
|
+
*
|
|
17
|
+
* The verifier never throws — every failure path returns
|
|
18
|
+
* `{ valid: false, reason }` so it composes cleanly inside the validator's
|
|
19
|
+
* per-attestation loop.
|
|
20
|
+
*
|
|
21
|
+
* @see ./validate-level2.ts — the validator this plugs into.
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.createCombinedDidResolver = createCombinedDidResolver;
|
|
25
|
+
exports.createVcJwtSignatureVerifier = createVcJwtSignatureVerifier;
|
|
26
|
+
const jose_1 = require("jose");
|
|
27
|
+
const did_key_resolver_js_1 = require("../delegation/did-key-resolver.js");
|
|
28
|
+
const did_web_resolver_js_1 = require("../delegation/did-web-resolver.js");
|
|
29
|
+
/**
|
|
30
|
+
* Create a DID resolver that dispatches by method: did:key is resolved locally,
|
|
31
|
+
* did:web is fetched over HTTPS, and every other method resolves to `null`.
|
|
32
|
+
*
|
|
33
|
+
* @param options - Optional pluggable fetch for the did:web branch.
|
|
34
|
+
*/
|
|
35
|
+
function createCombinedDidResolver(options = {}) {
|
|
36
|
+
const didKey = (0, did_key_resolver_js_1.createDidKeyResolver)();
|
|
37
|
+
const didWeb = (0, did_web_resolver_js_1.createDidWebResolver)({ fetch: options.fetch });
|
|
38
|
+
return {
|
|
39
|
+
resolve: async (did) => {
|
|
40
|
+
if (did.startsWith('did:key:'))
|
|
41
|
+
return didKey.resolve(did);
|
|
42
|
+
if (did.startsWith('did:web:'))
|
|
43
|
+
return didWeb.resolve(did);
|
|
44
|
+
return null;
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Create a VC-JWT signature verifier suitable for
|
|
50
|
+
* {@link verifyCapabilities}'s `signatureVerifier` option.
|
|
51
|
+
*
|
|
52
|
+
* @param options - DID resolver / fetch overrides.
|
|
53
|
+
* @returns A `(vc, rawJwt) => Promise<{ valid; reason? }>` function.
|
|
54
|
+
*/
|
|
55
|
+
function createVcJwtSignatureVerifier(options = {}) {
|
|
56
|
+
const resolver = options.didResolver ?? createCombinedDidResolver({ fetch: options.fetch });
|
|
57
|
+
return async (vc, rawJwt) => {
|
|
58
|
+
if (rawJwt === undefined) {
|
|
59
|
+
return { valid: false, reason: 'no compact JWS' };
|
|
60
|
+
}
|
|
61
|
+
const issuerDid = extractIssuerDid(vc);
|
|
62
|
+
if (!issuerDid) {
|
|
63
|
+
return { valid: false, reason: 'VC missing issuer' };
|
|
64
|
+
}
|
|
65
|
+
let kid;
|
|
66
|
+
try {
|
|
67
|
+
kid = (0, jose_1.decodeProtectedHeader)(rawJwt).kid;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return { valid: false, reason: 'malformed JWS protected header' };
|
|
71
|
+
}
|
|
72
|
+
let didDoc;
|
|
73
|
+
try {
|
|
74
|
+
didDoc = await resolver.resolve(issuerDid);
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
return {
|
|
78
|
+
valid: false,
|
|
79
|
+
reason: `issuer resolution failed: ${errorMessage(err)}`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (!didDoc) {
|
|
83
|
+
return { valid: false, reason: `could not resolve issuer ${issuerDid}` };
|
|
84
|
+
}
|
|
85
|
+
const method = selectVerificationMethod(didDoc, kid);
|
|
86
|
+
if (!method?.publicKeyJwk) {
|
|
87
|
+
return {
|
|
88
|
+
valid: false,
|
|
89
|
+
reason: kid
|
|
90
|
+
? `no verification method matching kid ${kid}`
|
|
91
|
+
: 'no verification method with a publicKeyJwk',
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
const key = await (0, jose_1.importJWK)(method.publicKeyJwk, 'EdDSA');
|
|
96
|
+
await (0, jose_1.compactVerify)(rawJwt, key);
|
|
97
|
+
return { valid: true };
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
return {
|
|
101
|
+
valid: false,
|
|
102
|
+
reason: `signature verification failed: ${errorMessage(err)}`,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Select the verification method to verify against.
|
|
109
|
+
*
|
|
110
|
+
* When the JWS carries a `kid`, prefer an exact id match; only when none exists
|
|
111
|
+
* fall back to matching by fragment — so a fragment-only kid (`#key-1`) and a
|
|
112
|
+
* fully-qualified id (`did:web:example#key-1`), both common across did:web
|
|
113
|
+
* documents and JWTs, still resolve to the same key, while a later exact match
|
|
114
|
+
* is never shadowed by an earlier fragment-only one. Stays fail-closed: a kid
|
|
115
|
+
* that matches no method is rejected, and a wrongly-matched key fails the
|
|
116
|
+
* subsequent signature check. Without a `kid`, fall back to the first method
|
|
117
|
+
* with a `publicKeyJwk`.
|
|
118
|
+
*/
|
|
119
|
+
function selectVerificationMethod(didDoc, kid) {
|
|
120
|
+
const methods = didDoc.verificationMethod ?? [];
|
|
121
|
+
if (kid) {
|
|
122
|
+
const exact = methods.find((method) => method.id === kid);
|
|
123
|
+
if (exact)
|
|
124
|
+
return exact;
|
|
125
|
+
const kidFragment = fragmentOf(kid);
|
|
126
|
+
return methods.find((method) => fragmentOf(method.id) === kidFragment);
|
|
127
|
+
}
|
|
128
|
+
return methods.find((method) => method.publicKeyJwk);
|
|
129
|
+
}
|
|
130
|
+
/** The fragment of a DID-URL reference (the part after `#`), or the whole ref if none. */
|
|
131
|
+
function fragmentOf(ref) {
|
|
132
|
+
const hash = ref.indexOf('#');
|
|
133
|
+
return hash >= 0 ? ref.slice(hash + 1) : ref;
|
|
134
|
+
}
|
|
135
|
+
function extractIssuerDid(vc) {
|
|
136
|
+
const issuer = vc.issuer;
|
|
137
|
+
if (typeof issuer === 'string')
|
|
138
|
+
return issuer;
|
|
139
|
+
if (issuer && typeof issuer === 'object' && typeof issuer.id === 'string') {
|
|
140
|
+
return issuer.id;
|
|
141
|
+
}
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
function errorMessage(err) {
|
|
145
|
+
return err instanceof Error ? err.message : String(err);
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=vc-jwt-verifier.js.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* did:web Resolver
|
|
3
|
+
*
|
|
4
|
+
* Resolves did:web DIDs to DID Documents by fetching the well-known document
|
|
5
|
+
* over HTTPS, per the did:web method spec.
|
|
6
|
+
*
|
|
7
|
+
* URL mapping (did:web method spec §3.2):
|
|
8
|
+
* did:web:example.com → https://example.com/.well-known/did.json
|
|
9
|
+
* did:web:example.com:a:b → https://example.com/a/b/did.json
|
|
10
|
+
* did:web:example.com%3A3000 → https://example.com:3000/.well-known/did.json
|
|
11
|
+
*
|
|
12
|
+
* Percent-encoded characters in each colon-separated segment are decoded
|
|
13
|
+
* (notably `%3A` for a host:port colon).
|
|
14
|
+
*
|
|
15
|
+
* The fetch implementation is pluggable so callers — and tests — can supply
|
|
16
|
+
* their own transport; it defaults to the global `fetch`. The resolver never
|
|
17
|
+
* throws: a non-did:web input, non-OK response, malformed document, or
|
|
18
|
+
* transport error all resolve to `null`.
|
|
19
|
+
*
|
|
20
|
+
* Mirrors the shape of {@link createDidKeyResolver}.
|
|
21
|
+
*
|
|
22
|
+
* @see https://w3c-ccg.github.io/did-method-web/
|
|
23
|
+
*/
|
|
24
|
+
import type { DIDResolver } from './vc-verifier';
|
|
25
|
+
/** Minimal subset of a fetch `Response` consumed by the resolver. */
|
|
26
|
+
export interface DidWebFetchResponse {
|
|
27
|
+
ok: boolean;
|
|
28
|
+
json(): Promise<unknown>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Pluggable fetch signature. The global `fetch` satisfies this structurally,
|
|
32
|
+
* so it is the default.
|
|
33
|
+
*/
|
|
34
|
+
export type DidWebFetch = (url: string) => Promise<DidWebFetchResponse>;
|
|
35
|
+
/** Options for {@link createDidWebResolver}. */
|
|
36
|
+
export interface DidWebResolverOptions {
|
|
37
|
+
/** Transport used to retrieve the DID document. Defaults to global `fetch`. */
|
|
38
|
+
fetch?: DidWebFetch;
|
|
39
|
+
/**
|
|
40
|
+
* Max time (ms) to wait for the DID document before failing closed (returning
|
|
41
|
+
* `null`). Guards against a stalled issuer endpoint hanging verification.
|
|
42
|
+
* Defaults to {@link DEFAULT_TIMEOUT_MS}.
|
|
43
|
+
*/
|
|
44
|
+
timeoutMs?: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Convert a did:web DID into the HTTPS URL of its DID document.
|
|
48
|
+
*
|
|
49
|
+
* @param did - The did:web DID to map.
|
|
50
|
+
* @returns The document URL, or `null` if the DID is not a well-formed did:web.
|
|
51
|
+
*/
|
|
52
|
+
export declare function didWebToUrl(did: string): string | null;
|
|
53
|
+
/**
|
|
54
|
+
* Create a did:web resolver.
|
|
55
|
+
*
|
|
56
|
+
* @param options - Optional pluggable fetch transport.
|
|
57
|
+
* @returns A {@link DIDResolver} for did:web DIDs.
|
|
58
|
+
*/
|
|
59
|
+
export declare function createDidWebResolver(options?: DidWebResolverOptions): DIDResolver;
|
|
60
|
+
//# sourceMappingURL=did-web-resolver.d.ts.map
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* did:web Resolver
|
|
4
|
+
*
|
|
5
|
+
* Resolves did:web DIDs to DID Documents by fetching the well-known document
|
|
6
|
+
* over HTTPS, per the did:web method spec.
|
|
7
|
+
*
|
|
8
|
+
* URL mapping (did:web method spec §3.2):
|
|
9
|
+
* did:web:example.com → https://example.com/.well-known/did.json
|
|
10
|
+
* did:web:example.com:a:b → https://example.com/a/b/did.json
|
|
11
|
+
* did:web:example.com%3A3000 → https://example.com:3000/.well-known/did.json
|
|
12
|
+
*
|
|
13
|
+
* Percent-encoded characters in each colon-separated segment are decoded
|
|
14
|
+
* (notably `%3A` for a host:port colon).
|
|
15
|
+
*
|
|
16
|
+
* The fetch implementation is pluggable so callers — and tests — can supply
|
|
17
|
+
* their own transport; it defaults to the global `fetch`. The resolver never
|
|
18
|
+
* throws: a non-did:web input, non-OK response, malformed document, or
|
|
19
|
+
* transport error all resolve to `null`.
|
|
20
|
+
*
|
|
21
|
+
* Mirrors the shape of {@link createDidKeyResolver}.
|
|
22
|
+
*
|
|
23
|
+
* @see https://w3c-ccg.github.io/did-method-web/
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.didWebToUrl = didWebToUrl;
|
|
27
|
+
exports.createDidWebResolver = createDidWebResolver;
|
|
28
|
+
/** did:web method prefix. */
|
|
29
|
+
const DID_WEB_PREFIX = 'did:web:';
|
|
30
|
+
/** Default time budget (ms) for retrieving a DID document before failing closed. */
|
|
31
|
+
const DEFAULT_TIMEOUT_MS = 5000;
|
|
32
|
+
/**
|
|
33
|
+
* Convert a did:web DID into the HTTPS URL of its DID document.
|
|
34
|
+
*
|
|
35
|
+
* @param did - The did:web DID to map.
|
|
36
|
+
* @returns The document URL, or `null` if the DID is not a well-formed did:web.
|
|
37
|
+
*/
|
|
38
|
+
function didWebToUrl(did) {
|
|
39
|
+
if (!did.startsWith(DID_WEB_PREFIX)) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
const identifier = did.slice(DID_WEB_PREFIX.length);
|
|
43
|
+
if (identifier.length === 0) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const segments = identifier.split(':');
|
|
47
|
+
let host;
|
|
48
|
+
let path;
|
|
49
|
+
try {
|
|
50
|
+
host = decodeURIComponent(segments[0]);
|
|
51
|
+
path = segments.slice(1).map((segment) => decodeURIComponent(segment));
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// Malformed percent-encoding (decodeURIComponent throws URIError).
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
if (host.length === 0 || path.some((segment) => segment.length === 0)) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
const suffix = path.length === 0
|
|
61
|
+
? '/.well-known/did.json'
|
|
62
|
+
: `/${path.join('/')}/did.json`;
|
|
63
|
+
return `https://${host}${suffix}`;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Create a did:web resolver.
|
|
67
|
+
*
|
|
68
|
+
* @param options - Optional pluggable fetch transport.
|
|
69
|
+
* @returns A {@link DIDResolver} for did:web DIDs.
|
|
70
|
+
*/
|
|
71
|
+
function createDidWebResolver(options = {}) {
|
|
72
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
73
|
+
const doFetch = options.fetch ?? ((url) => fetch(url, { signal: AbortSignal.timeout(timeoutMs) }));
|
|
74
|
+
return {
|
|
75
|
+
resolve: async (did) => {
|
|
76
|
+
const url = didWebToUrl(did);
|
|
77
|
+
if (!url) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
let response;
|
|
81
|
+
try {
|
|
82
|
+
response = await withTimeout(doFetch(url), timeoutMs);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Transport error, abort, or timeout → fail closed.
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
if (!response.ok) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
let doc;
|
|
92
|
+
try {
|
|
93
|
+
doc = await response.json();
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
return isDidDocument(doc) ? doc : null;
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Minimal structural check: a DID Document is an object with a string `id`.
|
|
104
|
+
*/
|
|
105
|
+
function isDidDocument(value) {
|
|
106
|
+
return (typeof value === 'object' &&
|
|
107
|
+
value !== null &&
|
|
108
|
+
typeof value.id === 'string');
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Reject if `promise` does not settle within `ms`, so a stalled fetch fails
|
|
112
|
+
* closed (the resolver returns `null`) instead of hanging verification
|
|
113
|
+
* indefinitely. The default transport additionally aborts the underlying request
|
|
114
|
+
* via `AbortSignal.timeout`; this race also bounds a custom transport.
|
|
115
|
+
*/
|
|
116
|
+
async function withTimeout(promise, ms) {
|
|
117
|
+
let timer;
|
|
118
|
+
const timeout = new Promise((_, reject) => {
|
|
119
|
+
timer = setTimeout(() => reject(new Error(`did:web fetch timed out after ${ms}ms`)), ms);
|
|
120
|
+
});
|
|
121
|
+
try {
|
|
122
|
+
return await Promise.race([promise, timeout]);
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
if (timer)
|
|
126
|
+
clearTimeout(timer);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=did-web-resolver.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export { MemoryStatusListStorage } from "./delegation/storage/memory-statuslist-
|
|
|
19
19
|
export { MemoryDelegationGraphStorage } from "./delegation/storage/memory-graph-storage";
|
|
20
20
|
export { buildDelegationProofJWT, buildChainString, type DelegationProofOptions, type Ed25519PrivateJWK, } from "./delegation/outbound-proof";
|
|
21
21
|
export { createDidKeyResolver, isEd25519DidKey, extractPublicKeyFromDidKey, publicKeyToJwk, resolveDidKeySync, } from "./delegation/did-key-resolver";
|
|
22
|
+
export { createDidWebResolver, didWebToUrl, type DidWebFetch, type DidWebFetchResponse, type DidWebResolverOptions, } from "./delegation/did-web-resolver";
|
|
22
23
|
export { canonicalizeJSON, createUnsignedVCJWT, completeVCJWT, parseVCJWT, type VCJWTHeader, type VCJWTPayload, type EncodeVCAsJWTOptions, } from "./delegation/utils";
|
|
23
|
-
export { validateLevel2, DEFAULT_TRUSTED_ISSUERS, type CapabilityName, type CapabilityAttestation, type CapabilityAttestationCredential, type Level2Capability, type ManifestCapabilities, type CapabilityVCSignatureVerifier, type CapabilityStatusListResolver, type ValidateLevel2Options, type ValidateLevel2Result, type InvalidCapability, } from "./conformance/index.js";
|
|
24
|
+
export { verifyCapabilities, validateLevel2, DEFAULT_TRUSTED_ISSUERS, type CapabilityName, type CapabilityAttestation, type CapabilityAttestationCredential, type Level2Capability, type ManifestCapabilities, type CapabilityVCSignatureVerifier, type CapabilityStatusListResolver, type ValidateLevel2Options, type ValidateLevel2Result, type InvalidCapability, createVcJwtSignatureVerifier, createCombinedDidResolver, type VcJwtVerifierOptions, createCapabilityVerifier, type DuckTypedCapability, type CapabilityVerificationContext, type CapabilityVerificationResult, type CapabilityVerifier, type CreateCapabilityVerifierOptions, } from "./conformance/index.js";
|
|
24
25
|
//# sourceMappingURL=index.d.ts.map
|