@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.
Files changed (111) hide show
  1. package/dist/conformance/capability-verifier-adapter.d.ts +66 -0
  2. package/dist/conformance/capability-verifier-adapter.js +61 -0
  3. package/dist/conformance/index.d.ts +3 -1
  4. package/dist/conformance/index.js +7 -1
  5. package/dist/conformance/validate-level2.d.ts +13 -3
  6. package/dist/conformance/validate-level2.js +15 -5
  7. package/dist/conformance/vc-jwt-verifier.d.ts +55 -0
  8. package/dist/conformance/vc-jwt-verifier.js +147 -0
  9. package/dist/delegation/did-web-resolver.d.ts +60 -0
  10. package/dist/delegation/did-web-resolver.js +129 -0
  11. package/dist/index.d.ts +2 -1
  12. package/dist/index.js +9 -1
  13. package/package.json +3 -3
  14. package/dist/auth/handshake.d.ts +0 -119
  15. package/dist/auth/handshake.js +0 -250
  16. package/dist/auth/index.d.ts +0 -6
  17. package/dist/auth/index.js +0 -11
  18. package/dist/auth/types.d.ts +0 -46
  19. package/dist/auth/types.js +0 -10
  20. package/dist/cache/oauth-config-cache.d.ts +0 -69
  21. package/dist/cache/oauth-config-cache.js +0 -76
  22. package/dist/cache/tool-protection-cache.d.ts +0 -89
  23. package/dist/cache/tool-protection-cache.js +0 -118
  24. package/dist/compliance/index.d.ts +0 -8
  25. package/dist/compliance/index.js +0 -24
  26. package/dist/compliance/schema-registry.d.ts +0 -50
  27. package/dist/compliance/schema-registry.js +0 -438
  28. package/dist/compliance/schema-verifier.d.ts +0 -110
  29. package/dist/compliance/schema-verifier.js +0 -518
  30. package/dist/config/remote-config.d.ts +0 -173
  31. package/dist/config/remote-config.js +0 -253
  32. package/dist/config.d.ts +0 -182
  33. package/dist/config.js +0 -148
  34. package/dist/identity/idp-token-resolver.d.ts +0 -69
  35. package/dist/identity/idp-token-resolver.js +0 -136
  36. package/dist/identity/idp-token-storage.interface.d.ts +0 -80
  37. package/dist/identity/idp-token-storage.interface.js +0 -14
  38. package/dist/identity/user-did-manager.d.ts +0 -228
  39. package/dist/identity/user-did-manager.js +0 -356
  40. package/dist/logging/index.d.ts +0 -5
  41. package/dist/logging/index.js +0 -10
  42. package/dist/logging/logger.d.ts +0 -33
  43. package/dist/logging/logger.js +0 -104
  44. package/dist/proof/generator.d.ts +0 -109
  45. package/dist/proof/generator.js +0 -236
  46. package/dist/proof/index.d.ts +0 -5
  47. package/dist/proof/index.js +0 -11
  48. package/dist/providers/base.d.ts +0 -95
  49. package/dist/providers/base.js +0 -47
  50. package/dist/providers/memory.d.ts +0 -42
  51. package/dist/providers/memory.js +0 -121
  52. package/dist/runtime/audit-logger.d.ts +0 -37
  53. package/dist/runtime/audit-logger.js +0 -9
  54. package/dist/runtime/base.d.ts +0 -375
  55. package/dist/runtime/base.js +0 -1491
  56. package/dist/runtime/ext-apps-constants.d.ts +0 -14
  57. package/dist/runtime/ext-apps-constants.js +0 -17
  58. package/dist/services/access-control.service.d.ts +0 -138
  59. package/dist/services/access-control.service.js +0 -721
  60. package/dist/services/authorization/authorization-registry.d.ts +0 -29
  61. package/dist/services/authorization/authorization-registry.js +0 -58
  62. package/dist/services/authorization/types.d.ts +0 -53
  63. package/dist/services/authorization/types.js +0 -10
  64. package/dist/services/batch-delegation.service.d.ts +0 -53
  65. package/dist/services/batch-delegation.service.js +0 -95
  66. package/dist/services/crypto.service.d.ts +0 -69
  67. package/dist/services/crypto.service.js +0 -225
  68. package/dist/services/delegation-error-formatter.d.ts +0 -124
  69. package/dist/services/delegation-error-formatter.js +0 -214
  70. package/dist/services/errors.d.ts +0 -49
  71. package/dist/services/errors.js +0 -66
  72. package/dist/services/index.d.ts +0 -9
  73. package/dist/services/index.js +0 -15
  74. package/dist/services/oauth-config.service.d.ts +0 -53
  75. package/dist/services/oauth-config.service.js +0 -141
  76. package/dist/services/oauth-provider-registry.d.ts +0 -88
  77. package/dist/services/oauth-provider-registry.js +0 -128
  78. package/dist/services/oauth-service.d.ts +0 -122
  79. package/dist/services/oauth-service.js +0 -442
  80. package/dist/services/oauth-token-retrieval.service.d.ts +0 -49
  81. package/dist/services/oauth-token-retrieval.service.js +0 -150
  82. package/dist/services/policy.service.d.ts +0 -130
  83. package/dist/services/policy.service.js +0 -399
  84. package/dist/services/proof-verifier.d.ts +0 -98
  85. package/dist/services/proof-verifier.js +0 -319
  86. package/dist/services/provider-resolver.d.ts +0 -89
  87. package/dist/services/provider-resolver.js +0 -196
  88. package/dist/services/provider-validator.d.ts +0 -55
  89. package/dist/services/provider-validator.js +0 -135
  90. package/dist/services/session-registration.service.d.ts +0 -80
  91. package/dist/services/session-registration.service.js +0 -174
  92. package/dist/services/storage.service.d.ts +0 -116
  93. package/dist/services/storage.service.js +0 -411
  94. package/dist/services/tool-context-builder.d.ts +0 -74
  95. package/dist/services/tool-context-builder.js +0 -215
  96. package/dist/services/tool-protection.service.d.ts +0 -193
  97. package/dist/services/tool-protection.service.js +0 -736
  98. package/dist/session/index.d.ts +0 -5
  99. package/dist/session/index.js +0 -11
  100. package/dist/session/manager.d.ts +0 -113
  101. package/dist/session/manager.js +0 -273
  102. package/dist/types/oauth-required-error.d.ts +0 -46
  103. package/dist/types/oauth-required-error.js +0 -42
  104. package/dist/types/tool-protection.d.ts +0 -144
  105. package/dist/types/tool-protection.js +0 -48
  106. package/dist/utils/cors.d.ts +0 -44
  107. package/dist/utils/cors.js +0 -71
  108. package/dist/utils/index.d.ts +0 -8
  109. package/dist/utils/index.js +0 -24
  110. package/dist/utils/storage-keys.d.ts +0 -120
  111. 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
- * Validate an MCP-I agent's declared capabilities at Level 2.
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 validateLevel2(manifest.capabilities, {
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 validateLevel2(capabilities: unknown, options: ValidateLevel2Options): Promise<ValidateLevel2Result>;
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.validateLevel2 = validateLevel2;
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
- * Validate an MCP-I agent's declared capabilities at Level 2.
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 validateLevel2(manifest.capabilities, {
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 validateLevel2(capabilities, options) {
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