@kya-os/mcp-i-core 1.8.0 → 1.8.1

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
@@ -1,29 +0,0 @@
1
- /**
2
- * Authorization Registry
3
- *
4
- * Registry for managing available authorization services.
5
- * Allows looking up the appropriate service for a given authorization type.
6
- *
7
- * @package @kya-os/mcp-i-core
8
- */
9
- import type { AuthorizationService } from "./types.js";
10
- import type { ToolProtection, AuthorizationRequirement } from "@kya-os/contracts/tool-protection";
11
- export declare class AuthorizationRegistry {
12
- private services;
13
- /**
14
- * Register an authorization service
15
- */
16
- register(service: AuthorizationService): void;
17
- /**
18
- * Get an authorization service by type
19
- */
20
- getService(type: string): AuthorizationService | null;
21
- /**
22
- * Resolve authorization requirement for a tool
23
- *
24
- * Determines the authorization requirement based on the tool protection config.
25
- * Handles backward compatibility with legacy `oauthProvider` field.
26
- */
27
- resolveRequirement(toolProtection: ToolProtection): AuthorizationRequirement | null;
28
- }
29
- //# sourceMappingURL=authorization-registry.d.ts.map
@@ -1,58 +0,0 @@
1
- "use strict";
2
- /**
3
- * Authorization Registry
4
- *
5
- * Registry for managing available authorization services.
6
- * Allows looking up the appropriate service for a given authorization type.
7
- *
8
- * @package @kya-os/mcp-i-core
9
- */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.AuthorizationRegistry = void 0;
12
- class AuthorizationRegistry {
13
- services = new Map();
14
- /**
15
- * Register an authorization service
16
- */
17
- register(service) {
18
- this.services.set(service.type, service);
19
- }
20
- /**
21
- * Get an authorization service by type
22
- */
23
- getService(type) {
24
- return this.services.get(type) || null;
25
- }
26
- /**
27
- * Resolve authorization requirement for a tool
28
- *
29
- * Determines the authorization requirement based on the tool protection config.
30
- * Handles backward compatibility with legacy `oauthProvider` field.
31
- */
32
- resolveRequirement(toolProtection) {
33
- if (!toolProtection.requiresDelegation) {
34
- return null;
35
- }
36
- // Use the explicit authorization field if present
37
- if (toolProtection.authorization) {
38
- return toolProtection.authorization;
39
- }
40
- // Legacy fallback: oauthProvider field
41
- // Note: Returns 'oauth' for backward compat; consumers should normalize to 'oauth2'
42
- if (toolProtection.oauthProvider) {
43
- return {
44
- type: 'oauth',
45
- provider: toolProtection.oauthProvider,
46
- };
47
- }
48
- // If requiresDelegation is true but no auth specified, default to 'none' (consent only)
49
- // UNLESS we are in a transition period where ProviderResolver might infer scopes.
50
- // This logic will be refined as we move logic from ProviderResolver to here.
51
- // For now, return null to let downstream logic handle fallbacks if needed,
52
- // or return 'none' if we want to enforce explicit config.
53
- // Returning null allows the legacy ProviderResolver to attempt scope inference
54
- return null;
55
- }
56
- }
57
- exports.AuthorizationRegistry = AuthorizationRegistry;
58
- //# sourceMappingURL=authorization-registry.js.map
@@ -1,53 +0,0 @@
1
- /**
2
- * Authorization Service Types
3
- *
4
- * Shared types for authorization services and flows.
5
- *
6
- * @package @kya-os/mcp-i-core
7
- */
8
- import type { ToolProtection } from "@kya-os/contracts/tool-protection";
9
- /**
10
- * Authorization Flow Result
11
- */
12
- export interface AuthorizationResult {
13
- success: boolean;
14
- credential?: unknown;
15
- userDid?: string;
16
- metadata?: Record<string, unknown>;
17
- error?: Error;
18
- }
19
- /**
20
- * Authorization Flow
21
- * Represents an initiated authorization flow
22
- */
23
- export interface AuthorizationFlow {
24
- /** URL to redirect the user to */
25
- url: string;
26
- /** Unique identifier for this flow */
27
- flowId?: string;
28
- /** Metadata about the flow */
29
- metadata?: Record<string, unknown>;
30
- }
31
- /**
32
- * Authorization Service Interface
33
- * Each authorization type implements this
34
- */
35
- export interface AuthorizationService {
36
- /** Unique type identifier (e.g., 'oauth', 'mdl', 'idv') */
37
- type: string;
38
- /**
39
- * Check if authorization is required for the given tool protection
40
- */
41
- isRequired(toolProtection: ToolProtection): boolean;
42
- /**
43
- * Initiate authorization flow
44
- * Returns URL or flow identifier
45
- */
46
- initiateFlow(toolProtection: ToolProtection, sessionId: string, projectId: string, agentDid: string, serverUrl: string): Promise<AuthorizationFlow>;
47
- /**
48
- * Verify authorization result
49
- * Called after user completes flow
50
- */
51
- verifyAuthorization(flowId: string, result: unknown): Promise<AuthorizationResult>;
52
- }
53
- //# sourceMappingURL=types.d.ts.map
@@ -1,10 +0,0 @@
1
- "use strict";
2
- /**
3
- * Authorization Service Types
4
- *
5
- * Shared types for authorization services and flows.
6
- *
7
- * @package @kya-os/mcp-i-core
8
- */
9
- Object.defineProperty(exports, "__esModule", { value: true });
10
- //# sourceMappingURL=types.js.map
@@ -1,53 +0,0 @@
1
- /**
2
- * Batch Delegation Service
3
- *
4
- * Groups tools by OAuth provider for batch delegation flows.
5
- * Enables single OAuth flow for multiple tools requiring the same provider.
6
- *
7
- * @package @kya-os/mcp-i-core
8
- */
9
- import type { ProviderResolver } from "./provider-resolver.js";
10
- import type { ToolProtectionService } from "./tool-protection.service.js";
11
- /**
12
- * Tool group by provider
13
- */
14
- export interface ToolGroup {
15
- /** OAuth provider name */
16
- provider: string;
17
- /** Tool names in this group */
18
- tools: string[];
19
- /** Merged scopes from all tools in group */
20
- scopes: string[];
21
- /** Highest risk level in group */
22
- riskLevel: "low" | "medium" | "high";
23
- }
24
- /**
25
- * Service for grouping tools by OAuth provider
26
- */
27
- export declare class BatchDelegationService {
28
- private providerResolver;
29
- private toolProtectionService;
30
- constructor(providerResolver: ProviderResolver, toolProtectionService: ToolProtectionService);
31
- /**
32
- * Group tools by OAuth provider
33
- *
34
- * Returns a map of provider → tools that require that provider.
35
- * Tools that don't require delegation are skipped.
36
- *
37
- * @param toolNames - Array of tool names to group
38
- * @param projectId - Project ID for provider resolution
39
- * @param agentDid - Agent DID for fetching tool protections
40
- * @returns Map of provider name to ToolGroup
41
- */
42
- groupToolsByProvider(toolNames: string[], projectId: string, agentDid: string): Promise<Map<string, ToolGroup>>;
43
- /**
44
- * Get all tools that require a specific provider
45
- *
46
- * @param provider - Provider name to filter by
47
- * @param projectId - Project ID for provider resolution
48
- * @param agentDid - Agent DID for fetching tool protections
49
- * @returns Array of tool names requiring the specified provider
50
- */
51
- getToolsForProvider(_provider: string, _projectId: string, _agentDid: string): Promise<string[]>;
52
- }
53
- //# sourceMappingURL=batch-delegation.service.d.ts.map
@@ -1,95 +0,0 @@
1
- "use strict";
2
- /**
3
- * Batch Delegation Service
4
- *
5
- * Groups tools by OAuth provider for batch delegation flows.
6
- * Enables single OAuth flow for multiple tools requiring the same provider.
7
- *
8
- * @package @kya-os/mcp-i-core
9
- */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.BatchDelegationService = void 0;
12
- /**
13
- * Service for grouping tools by OAuth provider
14
- */
15
- class BatchDelegationService {
16
- providerResolver;
17
- toolProtectionService;
18
- constructor(providerResolver, toolProtectionService) {
19
- this.providerResolver = providerResolver;
20
- this.toolProtectionService = toolProtectionService;
21
- }
22
- /**
23
- * Group tools by OAuth provider
24
- *
25
- * Returns a map of provider → tools that require that provider.
26
- * Tools that don't require delegation are skipped.
27
- *
28
- * @param toolNames - Array of tool names to group
29
- * @param projectId - Project ID for provider resolution
30
- * @param agentDid - Agent DID for fetching tool protections
31
- * @returns Map of provider name to ToolGroup
32
- */
33
- async groupToolsByProvider(toolNames, projectId, agentDid) {
34
- const groups = new Map();
35
- for (const toolName of toolNames) {
36
- const protection = await this.toolProtectionService.checkToolProtection(toolName, agentDid);
37
- if (!protection?.requiresDelegation) {
38
- continue; // Skip tools that don't require delegation
39
- }
40
- // Resolve provider for this tool
41
- let provider;
42
- try {
43
- provider = await this.providerResolver.resolveProvider(protection, projectId);
44
- }
45
- catch (error) {
46
- console.warn(`[BatchDelegation] Could not resolve provider for tool "${toolName}", skipping`, error instanceof Error ? error.message : String(error));
47
- continue;
48
- }
49
- // Get or create group for this provider
50
- if (!groups.has(provider)) {
51
- groups.set(provider, {
52
- provider,
53
- tools: [],
54
- scopes: [],
55
- riskLevel: "medium", // Default
56
- });
57
- }
58
- const group = groups.get(provider);
59
- group.tools.push(toolName);
60
- // Merge scopes (deduplicate)
61
- const allScopes = new Set([
62
- ...group.scopes,
63
- ...(protection.requiredScopes || []),
64
- ]);
65
- group.scopes = Array.from(allScopes);
66
- // Use highest risk level
67
- if (protection.riskLevel) {
68
- const riskOrder = { low: 1, medium: 2, high: 3, critical: 4 };
69
- const currentRisk = riskOrder[group.riskLevel] || 1;
70
- const toolRisk = riskOrder[protection.riskLevel] || 1;
71
- if (toolRisk > currentRisk) {
72
- // Map critical to high for ToolGroup interface
73
- group.riskLevel = protection.riskLevel === "critical" ? "high" : protection.riskLevel;
74
- }
75
- }
76
- }
77
- return groups;
78
- }
79
- /**
80
- * Get all tools that require a specific provider
81
- *
82
- * @param provider - Provider name to filter by
83
- * @param projectId - Project ID for provider resolution
84
- * @param agentDid - Agent DID for fetching tool protections
85
- * @returns Array of tool names requiring the specified provider
86
- */
87
- async getToolsForProvider(_provider, _projectId, _agentDid) {
88
- // Stub implementation: Returns empty array.
89
- // Full implementation would fetch all tool protections and filter by provider.
90
- // TODO(feature): Implement when batch delegation UI requires provider-based tool grouping.
91
- return [];
92
- }
93
- }
94
- exports.BatchDelegationService = BatchDelegationService;
95
- //# sourceMappingURL=batch-delegation.service.js.map
@@ -1,69 +0,0 @@
1
- /**
2
- * CryptoService
3
- *
4
- * Centralized cryptographic operations service that provides consistent
5
- * signature verification across all platforms (Cloudflare, Node.js, etc.).
6
- *
7
- * This service eliminates code duplication and ensures cryptographic operations
8
- * behave identically everywhere.
9
- */
10
- import { CryptoProvider } from "../providers/base.js";
11
- /**
12
- * Minimal JWK interface to avoid external dependencies
13
- */
14
- export interface Ed25519JWK {
15
- kty: "OKP";
16
- crv: "Ed25519";
17
- x: string;
18
- kid?: string;
19
- use?: string;
20
- }
21
- /**
22
- * JWS parsing result
23
- */
24
- export interface ParsedJWS {
25
- header: Record<string, unknown>;
26
- payload?: Record<string, unknown>;
27
- signatureBytes: Uint8Array;
28
- signingInput: string;
29
- }
30
- export declare class CryptoService {
31
- private cryptoProvider;
32
- constructor(cryptoProvider: CryptoProvider);
33
- /**
34
- * Verify raw Ed25519 signature
35
- * @param data - Data that was signed
36
- * @param signature - Signature bytes
37
- * @param publicKey - Base64 encoded Ed25519 public key (32 bytes)
38
- */
39
- verifyEd25519(data: Uint8Array, signature: Uint8Array, publicKey: string): Promise<boolean>;
40
- /**
41
- * Parse JWS into components
42
- * @param jws - Full compact JWS string (header.payload.signature)
43
- * @returns Parsed JWS components
44
- */
45
- parseJWS(jws: string): ParsedJWS;
46
- /**
47
- * Verify JWS signature (full compact format: header.payload.signature)
48
- * @param jws - Full compact JWS string (or detached format: header..signature)
49
- * @param publicKeyJwk - Ed25519 public key in JWK format
50
- * @param options - Verification options
51
- * @param options.detachedPayload - Optional detached payload (Uint8Array or string) for detached JWS format
52
- * @param options.expectedKid - Optional expected key ID to validate
53
- * @param options.alg - Optional expected algorithm (defaults to 'EdDSA')
54
- */
55
- verifyJWS(jws: string, publicKeyJwk: Ed25519JWK, options?: {
56
- detachedPayload?: Uint8Array | string;
57
- expectedKid?: string;
58
- alg?: "EdDSA";
59
- }): Promise<boolean>;
60
- /**
61
- * Validate Ed25519 JWK format
62
- */
63
- private isValidEd25519JWK;
64
- /**
65
- * Convert Ed25519 JWK to base64 encoded public key
66
- */
67
- private jwkToBase64PublicKey;
68
- }
69
- //# sourceMappingURL=crypto.service.d.ts.map
@@ -1,225 +0,0 @@
1
- "use strict";
2
- /**
3
- * CryptoService
4
- *
5
- * Centralized cryptographic operations service that provides consistent
6
- * signature verification across all platforms (Cloudflare, Node.js, etc.).
7
- *
8
- * This service eliminates code duplication and ensures cryptographic operations
9
- * behave identically everywhere.
10
- */
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.CryptoService = void 0;
13
- const base64_js_1 = require("../utils/base64.js");
14
- class CryptoService {
15
- cryptoProvider;
16
- constructor(cryptoProvider) {
17
- this.cryptoProvider = cryptoProvider;
18
- }
19
- /**
20
- * Verify raw Ed25519 signature
21
- * @param data - Data that was signed
22
- * @param signature - Signature bytes
23
- * @param publicKey - Base64 encoded Ed25519 public key (32 bytes)
24
- */
25
- async verifyEd25519(data, signature, publicKey) {
26
- try {
27
- const result = await this.cryptoProvider.verify(data, signature, publicKey);
28
- // Ensure we always return a boolean (handle undefined from unmocked providers)
29
- return result === true;
30
- }
31
- catch (error) {
32
- // Log error for debugging but return false for invalid signatures
33
- console.error("[CryptoService] Ed25519 verification error:", error);
34
- return false;
35
- }
36
- }
37
- /**
38
- * Parse JWS into components
39
- * @param jws - Full compact JWS string (header.payload.signature)
40
- * @returns Parsed JWS components
41
- */
42
- parseJWS(jws) {
43
- const parts = jws.split(".");
44
- if (parts.length !== 3) {
45
- throw new Error("Invalid JWS format: expected header.payload.signature");
46
- }
47
- const [headerB64, payloadB64, signatureB64] = parts;
48
- // Decode header
49
- let header;
50
- try {
51
- header = JSON.parse((0, base64_js_1.base64urlDecodeToString)(headerB64));
52
- }
53
- catch (error) {
54
- throw new Error(`Invalid header base64: ${error instanceof Error ? error.message : String(error)}`);
55
- }
56
- // Decode payload (optional, may be detached)
57
- let payload;
58
- if (payloadB64) {
59
- try {
60
- payload = JSON.parse((0, base64_js_1.base64urlDecodeToString)(payloadB64));
61
- }
62
- catch (error) {
63
- // Payload decoding failed - this is an error for non-detached JWS
64
- // Re-throw to let caller handle it (they can check if it's detached format)
65
- throw new Error(`Invalid payload base64: ${error instanceof Error ? error.message : String(error)}`);
66
- }
67
- }
68
- // Decode signature bytes
69
- let signatureBytes;
70
- try {
71
- signatureBytes = (0, base64_js_1.base64urlDecodeToBytes)(signatureB64);
72
- }
73
- catch (error) {
74
- // Invalid signature base64 - this is a fatal error
75
- throw new Error(`Invalid signature base64: ${error instanceof Error ? error.message : String(error)}`);
76
- }
77
- // Create signing input (header.payload)
78
- const signingInput = `${headerB64}.${payloadB64}`;
79
- return {
80
- header,
81
- payload,
82
- signatureBytes,
83
- signingInput,
84
- };
85
- }
86
- /**
87
- * Verify JWS signature (full compact format: header.payload.signature)
88
- * @param jws - Full compact JWS string (or detached format: header..signature)
89
- * @param publicKeyJwk - Ed25519 public key in JWK format
90
- * @param options - Verification options
91
- * @param options.detachedPayload - Optional detached payload (Uint8Array or string) for detached JWS format
92
- * @param options.expectedKid - Optional expected key ID to validate
93
- * @param options.alg - Optional expected algorithm (defaults to 'EdDSA')
94
- */
95
- async verifyJWS(jws, publicKeyJwk, options) {
96
- try {
97
- // Validate JWK format
98
- if (!this.isValidEd25519JWK(publicKeyJwk)) {
99
- console.error("[CryptoService] Invalid Ed25519 JWK format");
100
- return false;
101
- }
102
- // Validate expected kid if provided
103
- if (options?.expectedKid && publicKeyJwk.kid !== options.expectedKid) {
104
- console.error("[CryptoService] Key ID mismatch");
105
- return false;
106
- }
107
- // Parse JWS components - handle malformed JWS gracefully
108
- let parsed;
109
- try {
110
- parsed = this.parseJWS(jws);
111
- }
112
- catch (error) {
113
- // Malformed JWS - check if it's detached format with provided payload
114
- if (options?.detachedPayload !== undefined) {
115
- const parts = jws.split(".");
116
- if (parts.length === 3 && parts[1] === "") {
117
- // Detached format: header..signature
118
- try {
119
- const headerB64 = parts[0];
120
- const signatureB64 = parts[2];
121
- const header = JSON.parse((0, base64_js_1.base64urlDecodeToString)(headerB64));
122
- const signatureBytes = (0, base64_js_1.base64urlDecodeToBytes)(signatureB64);
123
- parsed = {
124
- header,
125
- payload: undefined,
126
- signatureBytes,
127
- signingInput: "", // Will be reconstructed below
128
- };
129
- }
130
- catch {
131
- console.error("[CryptoService] Invalid detached JWS format");
132
- return false;
133
- }
134
- }
135
- else {
136
- console.error("[CryptoService] Invalid JWS format:", error);
137
- return false;
138
- }
139
- }
140
- else {
141
- console.error("[CryptoService] Invalid JWS format:", error);
142
- return false;
143
- }
144
- }
145
- // Validate algorithm
146
- const expectedAlg = options?.alg || "EdDSA";
147
- if (parsed.header.alg !== expectedAlg) {
148
- console.error(`[CryptoService] Unsupported algorithm: ${parsed.header.alg}, expected ${expectedAlg}`);
149
- return false;
150
- }
151
- // Handle detached payload if provided
152
- let signingInput;
153
- let signingInputBytes;
154
- if (options?.detachedPayload !== undefined) {
155
- // Detached format: reconstruct signing input from header + detached payload
156
- const headerB64 = jws.split(".")[0];
157
- let payloadB64;
158
- if (options.detachedPayload instanceof Uint8Array) {
159
- // Uint8Array payload
160
- payloadB64 = (0, base64_js_1.base64urlEncodeFromBytes)(options.detachedPayload);
161
- }
162
- else {
163
- // String payload (backward compatibility)
164
- payloadB64 = (0, base64_js_1.base64urlEncodeFromBytes)(new TextEncoder().encode(options.detachedPayload));
165
- }
166
- signingInput = `${headerB64}.${payloadB64}`;
167
- signingInputBytes = new TextEncoder().encode(signingInput);
168
- }
169
- else {
170
- // Full compact format: use parsed signing input
171
- if (!parsed.signingInput) {
172
- console.error("[CryptoService] Missing signing input for compact JWS");
173
- return false;
174
- }
175
- signingInput = parsed.signingInput;
176
- signingInputBytes = new TextEncoder().encode(signingInput);
177
- }
178
- // Extract raw public key from JWK
179
- let publicKeyBase64;
180
- try {
181
- publicKeyBase64 = this.jwkToBase64PublicKey(publicKeyJwk);
182
- }
183
- catch (error) {
184
- console.error("[CryptoService] Failed to extract public key:", error);
185
- return false;
186
- }
187
- // Verify signature
188
- return await this.verifyEd25519(signingInputBytes, parsed.signatureBytes, publicKeyBase64);
189
- }
190
- catch (error) {
191
- // Security-safe failure: never throw, always return false
192
- console.error("[CryptoService] JWS verification error:", error);
193
- return false;
194
- }
195
- }
196
- /**
197
- * Validate Ed25519 JWK format
198
- */
199
- isValidEd25519JWK(jwk) {
200
- return (typeof jwk === "object" &&
201
- jwk !== null &&
202
- "kty" in jwk &&
203
- jwk.kty === "OKP" &&
204
- "crv" in jwk &&
205
- jwk.crv === "Ed25519" &&
206
- "x" in jwk &&
207
- typeof jwk.x === "string" &&
208
- jwk.x.length > 0);
209
- }
210
- /**
211
- * Convert Ed25519 JWK to base64 encoded public key
212
- */
213
- jwkToBase64PublicKey(jwk) {
214
- // The 'x' field contains the base64url encoded public key
215
- // Convert from base64url to standard base64
216
- const publicKeyBytes = (0, base64_js_1.base64urlDecodeToBytes)(jwk.x);
217
- // Verify key length (Ed25519 public keys are 32 bytes)
218
- if (publicKeyBytes.length !== 32) {
219
- throw new Error(`Invalid Ed25519 public key length: ${publicKeyBytes.length}`);
220
- }
221
- return (0, base64_js_1.bytesToBase64)(publicKeyBytes);
222
- }
223
- }
224
- exports.CryptoService = CryptoService;
225
- //# sourceMappingURL=crypto.service.js.map