@kya-os/mcp-i-core 1.7.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.
- package/README.md +1 -1
- 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 +10 -0
- package/dist/conformance/index.js +19 -0
- package/dist/conformance/validate-level2.d.ts +203 -0
- package/dist/conformance/validate-level2.js +294 -0
- 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/delegation/outbound-proof.d.ts +3 -2
- package/dist/delegation/outbound-proof.js +3 -2
- package/dist/delegation/utils.d.ts +3 -1
- package/dist/index.d.ts +9 -63
- package/dist/index.js +22 -161
- package/dist/utils/base58.d.ts +4 -28
- package/dist/utils/base58.js +18 -98
- package/dist/utils/base64.d.ts +4 -29
- package/dist/utils/base64.js +18 -167
- package/dist/utils/did-helpers.d.ts +4 -165
- package/dist/utils/did-helpers.js +18 -217
- package/package.json +5 -7
- 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
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PolicyService - Evaluates agent access policies
|
|
3
|
-
*
|
|
4
|
-
* This service evaluates incoming requests against configured policy rules
|
|
5
|
-
* to determine the appropriate enforcement action (allow, block, challenge, redirect).
|
|
6
|
-
*
|
|
7
|
-
* Policy evaluation order:
|
|
8
|
-
* 1. Allow list (exempt agents, always allowed)
|
|
9
|
-
* 2. Deny list (blocked agents, always blocked)
|
|
10
|
-
* 3. Threshold checks (confidence, reputation)
|
|
11
|
-
* 4. Custom rules (evaluated by priority, first match wins)
|
|
12
|
-
* 5. Default action (if no rules match)
|
|
13
|
-
*
|
|
14
|
-
* @package @kya-os/mcp-i-core
|
|
15
|
-
* @since 1.7.0
|
|
16
|
-
*/
|
|
17
|
-
import type { PolicyConfig, EnforcementAction } from '@kya-os/contracts';
|
|
18
|
-
/**
|
|
19
|
-
* Context for policy evaluation
|
|
20
|
-
* Contains all attributes about the request/agent that can be matched against
|
|
21
|
-
*/
|
|
22
|
-
export interface PolicyEvaluationContext {
|
|
23
|
-
agentType?: string;
|
|
24
|
-
agentName?: string;
|
|
25
|
-
agentVendor?: string;
|
|
26
|
-
clientDid?: string;
|
|
27
|
-
agentDid?: string;
|
|
28
|
-
confidence?: number;
|
|
29
|
-
reputationScore?: number;
|
|
30
|
-
riskLevel?: 'low' | 'medium' | 'high' | 'critical';
|
|
31
|
-
path?: string;
|
|
32
|
-
method?: string;
|
|
33
|
-
origin?: string;
|
|
34
|
-
userAgent?: string;
|
|
35
|
-
signatureVerified?: boolean;
|
|
36
|
-
isAuthenticated?: boolean;
|
|
37
|
-
hasValidDelegation?: boolean;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Result of policy evaluation
|
|
41
|
-
*/
|
|
42
|
-
export interface PolicyEvaluationResult {
|
|
43
|
-
/** Enforcement action to take */
|
|
44
|
-
action: EnforcementAction;
|
|
45
|
-
/** Reason for the action */
|
|
46
|
-
reason: string;
|
|
47
|
-
/** Rule ID that matched (if any) */
|
|
48
|
-
ruleId?: string;
|
|
49
|
-
/** Rule name that matched (if any) */
|
|
50
|
-
ruleName?: string;
|
|
51
|
-
/** Redirect URL (if action is 'redirect') */
|
|
52
|
-
redirectUrl?: string;
|
|
53
|
-
/** Custom message from the matched rule */
|
|
54
|
-
message?: string;
|
|
55
|
-
/** Whether this was matched by allow/deny list */
|
|
56
|
-
matchType: 'allow-list' | 'deny-list' | 'threshold' | 'rule' | 'default';
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Service configuration
|
|
60
|
-
*/
|
|
61
|
-
export interface PolicyServiceConfig {
|
|
62
|
-
/** Enable debug logging */
|
|
63
|
-
debug?: boolean;
|
|
64
|
-
}
|
|
65
|
-
export declare class PolicyService {
|
|
66
|
-
private config;
|
|
67
|
-
private policy;
|
|
68
|
-
constructor(policy?: PolicyConfig, config?: PolicyServiceConfig);
|
|
69
|
-
/**
|
|
70
|
-
* Update the policy configuration
|
|
71
|
-
*/
|
|
72
|
-
setPolicy(policy: PolicyConfig): void;
|
|
73
|
-
/**
|
|
74
|
-
* Get the current policy configuration
|
|
75
|
-
*/
|
|
76
|
-
getPolicy(): PolicyConfig;
|
|
77
|
-
/**
|
|
78
|
-
* Check if policy enforcement is enabled
|
|
79
|
-
*/
|
|
80
|
-
isEnabled(): boolean;
|
|
81
|
-
/**
|
|
82
|
-
* Evaluate a request against the policy
|
|
83
|
-
*
|
|
84
|
-
* @param context - Request/agent context to evaluate
|
|
85
|
-
* @returns Evaluation result with action and reason
|
|
86
|
-
*/
|
|
87
|
-
evaluate(context: PolicyEvaluationContext): PolicyEvaluationResult;
|
|
88
|
-
/**
|
|
89
|
-
* Check if context matches any allow list entry
|
|
90
|
-
*/
|
|
91
|
-
private checkAllowList;
|
|
92
|
-
/**
|
|
93
|
-
* Check if context matches any deny list entry
|
|
94
|
-
*/
|
|
95
|
-
private checkDenyList;
|
|
96
|
-
/**
|
|
97
|
-
* Check if context matches a list entry (allow or deny)
|
|
98
|
-
*/
|
|
99
|
-
private matchesListEntry;
|
|
100
|
-
/**
|
|
101
|
-
* Check threshold-based enforcement
|
|
102
|
-
*/
|
|
103
|
-
private checkThresholds;
|
|
104
|
-
/**
|
|
105
|
-
* Evaluate custom policy rules
|
|
106
|
-
*/
|
|
107
|
-
private evaluateRules;
|
|
108
|
-
/**
|
|
109
|
-
* Check if context matches a rule (all conditions must match)
|
|
110
|
-
*/
|
|
111
|
-
private matchesRule;
|
|
112
|
-
/**
|
|
113
|
-
* Check if context matches a single condition
|
|
114
|
-
*/
|
|
115
|
-
private matchesCondition;
|
|
116
|
-
/**
|
|
117
|
-
* Get a value from the context by field name
|
|
118
|
-
*/
|
|
119
|
-
private getContextValue;
|
|
120
|
-
/**
|
|
121
|
-
* Compare two values for equality
|
|
122
|
-
*/
|
|
123
|
-
private compareEqual;
|
|
124
|
-
/**
|
|
125
|
-
* Sanitize context for logging (mask sensitive values)
|
|
126
|
-
*/
|
|
127
|
-
private sanitizeContext;
|
|
128
|
-
}
|
|
129
|
-
export default PolicyService;
|
|
130
|
-
//# sourceMappingURL=policy.service.d.ts.map
|
|
@@ -1,399 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* PolicyService - Evaluates agent access policies
|
|
4
|
-
*
|
|
5
|
-
* This service evaluates incoming requests against configured policy rules
|
|
6
|
-
* to determine the appropriate enforcement action (allow, block, challenge, redirect).
|
|
7
|
-
*
|
|
8
|
-
* Policy evaluation order:
|
|
9
|
-
* 1. Allow list (exempt agents, always allowed)
|
|
10
|
-
* 2. Deny list (blocked agents, always blocked)
|
|
11
|
-
* 3. Threshold checks (confidence, reputation)
|
|
12
|
-
* 4. Custom rules (evaluated by priority, first match wins)
|
|
13
|
-
* 5. Default action (if no rules match)
|
|
14
|
-
*
|
|
15
|
-
* @package @kya-os/mcp-i-core
|
|
16
|
-
* @since 1.7.0
|
|
17
|
-
*/
|
|
18
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.PolicyService = void 0;
|
|
20
|
-
const contracts_1 = require("@kya-os/contracts");
|
|
21
|
-
// ============================================================================
|
|
22
|
-
// PolicyService Implementation
|
|
23
|
-
// ============================================================================
|
|
24
|
-
class PolicyService {
|
|
25
|
-
config;
|
|
26
|
-
policy;
|
|
27
|
-
constructor(policy, config) {
|
|
28
|
-
// Clone the default config to prevent mutation of the shared default
|
|
29
|
-
this.policy = policy ?? structuredClone(contracts_1.DEFAULT_POLICY_CONFIG);
|
|
30
|
-
this.config = config ?? {};
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Update the policy configuration
|
|
34
|
-
*/
|
|
35
|
-
setPolicy(policy) {
|
|
36
|
-
this.policy = policy;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Get the current policy configuration
|
|
40
|
-
*/
|
|
41
|
-
getPolicy() {
|
|
42
|
-
return this.policy;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Check if policy enforcement is enabled
|
|
46
|
-
*/
|
|
47
|
-
isEnabled() {
|
|
48
|
-
return this.policy.enabled ?? true;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Evaluate a request against the policy
|
|
52
|
-
*
|
|
53
|
-
* @param context - Request/agent context to evaluate
|
|
54
|
-
* @returns Evaluation result with action and reason
|
|
55
|
-
*/
|
|
56
|
-
evaluate(context) {
|
|
57
|
-
// If policy is disabled, always allow
|
|
58
|
-
if (!this.isEnabled()) {
|
|
59
|
-
return {
|
|
60
|
-
action: 'allow',
|
|
61
|
-
reason: 'Policy enforcement disabled',
|
|
62
|
-
matchType: 'default',
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
// 1. Check allow list first (exempt agents)
|
|
66
|
-
const allowListMatch = this.checkAllowList(context);
|
|
67
|
-
if (allowListMatch) {
|
|
68
|
-
if (this.config.debug) {
|
|
69
|
-
console.error('[PolicyService] Allow list match', {
|
|
70
|
-
context: this.sanitizeContext(context),
|
|
71
|
-
match: allowListMatch,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
return {
|
|
75
|
-
action: 'allow',
|
|
76
|
-
reason: `Allowed: ${allowListMatch.reason ?? 'On allow list'}`,
|
|
77
|
-
matchType: 'allow-list',
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
// 2. Check deny list (blocked agents)
|
|
81
|
-
const denyListMatch = this.checkDenyList(context);
|
|
82
|
-
if (denyListMatch) {
|
|
83
|
-
if (this.config.debug) {
|
|
84
|
-
console.error('[PolicyService] Deny list match', {
|
|
85
|
-
context: this.sanitizeContext(context),
|
|
86
|
-
match: denyListMatch,
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
return {
|
|
90
|
-
action: 'block',
|
|
91
|
-
reason: denyListMatch.reason ?? 'On deny list',
|
|
92
|
-
matchType: 'deny-list',
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
// 3. Check threshold-based enforcement
|
|
96
|
-
const thresholdResult = this.checkThresholds(context);
|
|
97
|
-
if (thresholdResult) {
|
|
98
|
-
if (this.config.debug) {
|
|
99
|
-
console.error('[PolicyService] Threshold match', {
|
|
100
|
-
context: this.sanitizeContext(context),
|
|
101
|
-
result: thresholdResult,
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
return thresholdResult;
|
|
105
|
-
}
|
|
106
|
-
// 4. Evaluate custom rules (by priority)
|
|
107
|
-
const ruleResult = this.evaluateRules(context);
|
|
108
|
-
if (ruleResult) {
|
|
109
|
-
if (this.config.debug) {
|
|
110
|
-
console.error('[PolicyService] Rule match', {
|
|
111
|
-
context: this.sanitizeContext(context),
|
|
112
|
-
result: ruleResult,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
return ruleResult;
|
|
116
|
-
}
|
|
117
|
-
// 5. Default action
|
|
118
|
-
return {
|
|
119
|
-
action: this.policy.defaultAction ?? 'allow',
|
|
120
|
-
reason: 'No matching rules, using default action',
|
|
121
|
-
matchType: 'default',
|
|
122
|
-
redirectUrl: this.policy.defaultAction === 'redirect' ? this.policy.redirectUrl : undefined,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
// ============================================================================
|
|
126
|
-
// Private Methods
|
|
127
|
-
// ============================================================================
|
|
128
|
-
/**
|
|
129
|
-
* Check if context matches any allow list entry
|
|
130
|
-
*/
|
|
131
|
-
checkAllowList(context) {
|
|
132
|
-
if (!this.policy.allowList?.length) {
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
for (const entry of this.policy.allowList) {
|
|
136
|
-
if (this.matchesListEntry(context, entry)) {
|
|
137
|
-
return entry;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Check if context matches any deny list entry
|
|
144
|
-
*/
|
|
145
|
-
checkDenyList(context) {
|
|
146
|
-
if (!this.policy.denyList?.length) {
|
|
147
|
-
return null;
|
|
148
|
-
}
|
|
149
|
-
for (const entry of this.policy.denyList) {
|
|
150
|
-
// Check if entry is active and not expired
|
|
151
|
-
if (entry.active === false)
|
|
152
|
-
continue;
|
|
153
|
-
if (entry.expiresAt && new Date(entry.expiresAt) < new Date())
|
|
154
|
-
continue;
|
|
155
|
-
if (this.matchesListEntry(context, entry)) {
|
|
156
|
-
return entry;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Check if context matches a list entry (allow or deny)
|
|
163
|
-
*/
|
|
164
|
-
matchesListEntry(context, entry) {
|
|
165
|
-
// At least one identifier must match
|
|
166
|
-
if (entry.clientDid && context.clientDid === entry.clientDid)
|
|
167
|
-
return true;
|
|
168
|
-
if (entry.agentDid && context.agentDid === entry.agentDid)
|
|
169
|
-
return true;
|
|
170
|
-
if (entry.clientName && context.agentName?.toLowerCase() === entry.clientName.toLowerCase())
|
|
171
|
-
return true;
|
|
172
|
-
if (entry.agentType && context.agentType === entry.agentType)
|
|
173
|
-
return true;
|
|
174
|
-
return false;
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Check threshold-based enforcement
|
|
178
|
-
*/
|
|
179
|
-
checkThresholds(context) {
|
|
180
|
-
const thresholds = this.policy.thresholds;
|
|
181
|
-
if (!thresholds)
|
|
182
|
-
return null;
|
|
183
|
-
// If signed requests bypass thresholds and request is signed, skip threshold checks
|
|
184
|
-
if (thresholds.trustSignedRequests && context.signatureVerified) {
|
|
185
|
-
return null;
|
|
186
|
-
}
|
|
187
|
-
// Check trusted reputation threshold (bypass other checks)
|
|
188
|
-
if (context.reputationScore !== undefined &&
|
|
189
|
-
context.reputationScore >= thresholds.trustedReputationThreshold) {
|
|
190
|
-
return null; // Trusted, continue to rules
|
|
191
|
-
}
|
|
192
|
-
// Check confidence threshold
|
|
193
|
-
if (context.confidence !== undefined &&
|
|
194
|
-
context.confidence >= thresholds.confidenceThreshold) {
|
|
195
|
-
return {
|
|
196
|
-
action: thresholds.confidenceAction,
|
|
197
|
-
reason: `Detection confidence (${context.confidence}) exceeds threshold (${thresholds.confidenceThreshold})`,
|
|
198
|
-
matchType: 'threshold',
|
|
199
|
-
redirectUrl: thresholds.confidenceAction === 'redirect' ? this.policy.redirectUrl : undefined,
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
// Check minimum reputation score
|
|
203
|
-
if (thresholds.minReputationScore > 0 &&
|
|
204
|
-
context.reputationScore !== undefined &&
|
|
205
|
-
context.reputationScore < thresholds.minReputationScore) {
|
|
206
|
-
return {
|
|
207
|
-
action: thresholds.lowReputationAction,
|
|
208
|
-
reason: `Reputation score (${context.reputationScore}) below minimum (${thresholds.minReputationScore})`,
|
|
209
|
-
matchType: 'threshold',
|
|
210
|
-
redirectUrl: thresholds.lowReputationAction === 'redirect' ? this.policy.redirectUrl : undefined,
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
-
return null;
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* Evaluate custom policy rules
|
|
217
|
-
*/
|
|
218
|
-
evaluateRules(context) {
|
|
219
|
-
const rules = this.policy.rules;
|
|
220
|
-
if (!rules?.length)
|
|
221
|
-
return null;
|
|
222
|
-
// Sort rules by priority (lower = higher priority)
|
|
223
|
-
const sortedRules = [...rules]
|
|
224
|
-
.filter((r) => r.enabled !== false)
|
|
225
|
-
.sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
|
|
226
|
-
for (const rule of sortedRules) {
|
|
227
|
-
if (this.matchesRule(context, rule)) {
|
|
228
|
-
return {
|
|
229
|
-
action: rule.action,
|
|
230
|
-
reason: rule.description ?? rule.name,
|
|
231
|
-
ruleId: rule.id,
|
|
232
|
-
ruleName: rule.name,
|
|
233
|
-
redirectUrl: rule.action === 'redirect' ? rule.redirectUrl : undefined,
|
|
234
|
-
message: rule.message,
|
|
235
|
-
matchType: 'rule',
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return null;
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* Check if context matches a rule (all conditions must match)
|
|
243
|
-
*/
|
|
244
|
-
matchesRule(context, rule) {
|
|
245
|
-
// All conditions must match (AND logic)
|
|
246
|
-
return rule.conditions.every((condition) => this.matchesCondition(context, condition));
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
|
-
* Check if context matches a single condition
|
|
250
|
-
*/
|
|
251
|
-
matchesCondition(context, condition) {
|
|
252
|
-
const value = this.getContextValue(context, condition.field);
|
|
253
|
-
const targetValue = condition.value;
|
|
254
|
-
// Handle null/undefined - these operators should return true when value is missing
|
|
255
|
-
if (value === undefined || value === null) {
|
|
256
|
-
return (condition.operator === 'notEquals' ||
|
|
257
|
-
condition.operator === 'notIn' ||
|
|
258
|
-
condition.operator === 'notContains');
|
|
259
|
-
}
|
|
260
|
-
switch (condition.operator) {
|
|
261
|
-
case 'equals':
|
|
262
|
-
return this.compareEqual(value, targetValue, condition.caseInsensitive);
|
|
263
|
-
case 'notEquals':
|
|
264
|
-
return !this.compareEqual(value, targetValue, condition.caseInsensitive);
|
|
265
|
-
case 'contains':
|
|
266
|
-
return typeof value === 'string' && typeof targetValue === 'string'
|
|
267
|
-
? condition.caseInsensitive
|
|
268
|
-
? value.toLowerCase().includes(targetValue.toLowerCase())
|
|
269
|
-
: value.includes(targetValue)
|
|
270
|
-
: false;
|
|
271
|
-
case 'notContains':
|
|
272
|
-
return typeof value === 'string' && typeof targetValue === 'string'
|
|
273
|
-
? condition.caseInsensitive
|
|
274
|
-
? !value.toLowerCase().includes(targetValue.toLowerCase())
|
|
275
|
-
: !value.includes(targetValue)
|
|
276
|
-
: true;
|
|
277
|
-
case 'startsWith':
|
|
278
|
-
return typeof value === 'string' && typeof targetValue === 'string'
|
|
279
|
-
? condition.caseInsensitive
|
|
280
|
-
? value.toLowerCase().startsWith(targetValue.toLowerCase())
|
|
281
|
-
: value.startsWith(targetValue)
|
|
282
|
-
: false;
|
|
283
|
-
case 'endsWith':
|
|
284
|
-
return typeof value === 'string' && typeof targetValue === 'string'
|
|
285
|
-
? condition.caseInsensitive
|
|
286
|
-
? value.toLowerCase().endsWith(targetValue.toLowerCase())
|
|
287
|
-
: value.endsWith(targetValue)
|
|
288
|
-
: false;
|
|
289
|
-
case 'greaterThan':
|
|
290
|
-
return typeof value === 'number' && typeof targetValue === 'number'
|
|
291
|
-
? value > targetValue
|
|
292
|
-
: false;
|
|
293
|
-
case 'lessThan':
|
|
294
|
-
return typeof value === 'number' && typeof targetValue === 'number'
|
|
295
|
-
? value < targetValue
|
|
296
|
-
: false;
|
|
297
|
-
case 'greaterThanOrEquals':
|
|
298
|
-
return typeof value === 'number' && typeof targetValue === 'number'
|
|
299
|
-
? value >= targetValue
|
|
300
|
-
: false;
|
|
301
|
-
case 'lessThanOrEquals':
|
|
302
|
-
return typeof value === 'number' && typeof targetValue === 'number'
|
|
303
|
-
? value <= targetValue
|
|
304
|
-
: false;
|
|
305
|
-
case 'matches':
|
|
306
|
-
if (typeof value !== 'string' || typeof targetValue !== 'string') {
|
|
307
|
-
return false;
|
|
308
|
-
}
|
|
309
|
-
try {
|
|
310
|
-
const flags = condition.caseInsensitive ? 'i' : '';
|
|
311
|
-
return new RegExp(targetValue, flags).test(value);
|
|
312
|
-
}
|
|
313
|
-
catch {
|
|
314
|
-
return false;
|
|
315
|
-
}
|
|
316
|
-
case 'in':
|
|
317
|
-
return Array.isArray(targetValue)
|
|
318
|
-
? targetValue.some((v) => this.compareEqual(value, v, condition.caseInsensitive))
|
|
319
|
-
: false;
|
|
320
|
-
case 'notIn':
|
|
321
|
-
return Array.isArray(targetValue)
|
|
322
|
-
? !targetValue.some((v) => this.compareEqual(value, v, condition.caseInsensitive))
|
|
323
|
-
: true;
|
|
324
|
-
default:
|
|
325
|
-
return false;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* Get a value from the context by field name
|
|
330
|
-
*/
|
|
331
|
-
getContextValue(context, field) {
|
|
332
|
-
switch (field) {
|
|
333
|
-
case 'agentType':
|
|
334
|
-
return context.agentType;
|
|
335
|
-
case 'agentName':
|
|
336
|
-
return context.agentName;
|
|
337
|
-
case 'agentVendor':
|
|
338
|
-
return context.agentVendor;
|
|
339
|
-
case 'clientDid':
|
|
340
|
-
return context.clientDid;
|
|
341
|
-
case 'agentDid':
|
|
342
|
-
return context.agentDid;
|
|
343
|
-
case 'confidence':
|
|
344
|
-
return context.confidence;
|
|
345
|
-
case 'reputationScore':
|
|
346
|
-
return context.reputationScore;
|
|
347
|
-
case 'riskLevel':
|
|
348
|
-
return context.riskLevel;
|
|
349
|
-
case 'path':
|
|
350
|
-
return context.path;
|
|
351
|
-
case 'method':
|
|
352
|
-
return context.method;
|
|
353
|
-
case 'origin':
|
|
354
|
-
return context.origin;
|
|
355
|
-
case 'userAgent':
|
|
356
|
-
return context.userAgent;
|
|
357
|
-
case 'signatureVerified':
|
|
358
|
-
return context.signatureVerified;
|
|
359
|
-
case 'isAuthenticated':
|
|
360
|
-
return context.isAuthenticated;
|
|
361
|
-
case 'hasValidDelegation':
|
|
362
|
-
return context.hasValidDelegation;
|
|
363
|
-
default:
|
|
364
|
-
return undefined;
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
/**
|
|
368
|
-
* Compare two values for equality
|
|
369
|
-
*/
|
|
370
|
-
compareEqual(a, b, caseInsensitive) {
|
|
371
|
-
if (typeof a === 'string' && typeof b === 'string') {
|
|
372
|
-
return caseInsensitive ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
373
|
-
}
|
|
374
|
-
return a === b;
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* Sanitize context for logging (mask sensitive values)
|
|
378
|
-
*/
|
|
379
|
-
sanitizeContext(context) {
|
|
380
|
-
return {
|
|
381
|
-
agentType: context.agentType,
|
|
382
|
-
agentName: context.agentName,
|
|
383
|
-
agentVendor: context.agentVendor,
|
|
384
|
-
clientDid: context.clientDid ? `${context.clientDid.slice(0, 20)}...` : undefined,
|
|
385
|
-
agentDid: context.agentDid ? `${context.agentDid.slice(0, 20)}...` : undefined,
|
|
386
|
-
confidence: context.confidence,
|
|
387
|
-
reputationScore: context.reputationScore,
|
|
388
|
-
riskLevel: context.riskLevel,
|
|
389
|
-
path: context.path,
|
|
390
|
-
method: context.method,
|
|
391
|
-
signatureVerified: context.signatureVerified,
|
|
392
|
-
isAuthenticated: context.isAuthenticated,
|
|
393
|
-
hasValidDelegation: context.hasValidDelegation,
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
exports.PolicyService = PolicyService;
|
|
398
|
-
exports.default = PolicyService;
|
|
399
|
-
//# sourceMappingURL=policy.service.js.map
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ProofVerifier
|
|
3
|
-
*
|
|
4
|
-
* Centralized proof verification service that validates DetachedProof
|
|
5
|
-
* signatures, enforces nonce replay protection, and checks timestamp skew.
|
|
6
|
-
*/
|
|
7
|
-
import { type Ed25519JWK } from "./crypto.service.js";
|
|
8
|
-
import { CryptoProvider } from "../providers/base.js";
|
|
9
|
-
import { ClockProvider } from "../providers/base.js";
|
|
10
|
-
import { NonceCacheProvider } from "../providers/base.js";
|
|
11
|
-
import { FetchProvider } from "../providers/base.js";
|
|
12
|
-
import { type DetachedProof } from "@kya-os/contracts/proof";
|
|
13
|
-
import { type ProofVerificationErrorCode } from "./errors.js";
|
|
14
|
-
export interface ProofVerificationResult {
|
|
15
|
-
valid: boolean;
|
|
16
|
-
reason?: string;
|
|
17
|
-
error?: Error;
|
|
18
|
-
errorCode?: ProofVerificationErrorCode;
|
|
19
|
-
details?: Record<string, unknown>;
|
|
20
|
-
}
|
|
21
|
-
export interface ProofVerifierConfig {
|
|
22
|
-
cryptoProvider: CryptoProvider;
|
|
23
|
-
clockProvider: ClockProvider;
|
|
24
|
-
nonceCacheProvider: NonceCacheProvider;
|
|
25
|
-
fetchProvider: FetchProvider;
|
|
26
|
-
timestampSkewSeconds?: number;
|
|
27
|
-
nonceTtlSeconds?: number;
|
|
28
|
-
}
|
|
29
|
-
export declare class ProofVerifier {
|
|
30
|
-
private cryptoService;
|
|
31
|
-
private clock;
|
|
32
|
-
private nonceCache;
|
|
33
|
-
private fetch;
|
|
34
|
-
private timestampSkewSeconds;
|
|
35
|
-
private nonceTtlSeconds;
|
|
36
|
-
constructor(config: ProofVerifierConfig);
|
|
37
|
-
/**
|
|
38
|
-
* Verify a DetachedProof
|
|
39
|
-
* Automatically reconstructs canonical payload from proof.meta for signature verification
|
|
40
|
-
* @param proof - The proof to verify
|
|
41
|
-
* @param publicKeyJwk - Ed25519 public key in JWK format (from DID document)
|
|
42
|
-
* @returns Verification result
|
|
43
|
-
*/
|
|
44
|
-
verifyProof(proof: DetachedProof, publicKeyJwk: Ed25519JWK): Promise<ProofVerificationResult>;
|
|
45
|
-
/**
|
|
46
|
-
* Verify proof with detached payload (for CLI/verifier compatibility)
|
|
47
|
-
* @param proof - The proof to verify
|
|
48
|
-
* @param canonicalPayload - Canonical JSON payload (for detached JWS) as string or Uint8Array
|
|
49
|
-
* @param publicKeyJwk - Ed25519 public key in JWK format
|
|
50
|
-
* @returns Verification result
|
|
51
|
-
*/
|
|
52
|
-
verifyProofDetached(proof: DetachedProof, canonicalPayload: string | Uint8Array, publicKeyJwk: Ed25519JWK): Promise<ProofVerificationResult>;
|
|
53
|
-
/**
|
|
54
|
-
* Validate proof structure using Zod schema
|
|
55
|
-
* @private
|
|
56
|
-
*/
|
|
57
|
-
private validateProofStructure;
|
|
58
|
-
/**
|
|
59
|
-
* Validate nonce replay protection
|
|
60
|
-
* @private
|
|
61
|
-
*/
|
|
62
|
-
private validateNonce;
|
|
63
|
-
/**
|
|
64
|
-
* Validate timestamp skew
|
|
65
|
-
* @private
|
|
66
|
-
*/
|
|
67
|
-
private validateTimestamp;
|
|
68
|
-
/**
|
|
69
|
-
* Verify JWS signature
|
|
70
|
-
* @private
|
|
71
|
-
*/
|
|
72
|
-
private verifySignature;
|
|
73
|
-
/**
|
|
74
|
-
* Add nonce to cache to prevent replay (scoped to agent DID)
|
|
75
|
-
* @private
|
|
76
|
-
*/
|
|
77
|
-
private addNonceToCache;
|
|
78
|
-
/**
|
|
79
|
-
* Fetch public key from DID document
|
|
80
|
-
* @param did - DID to resolve
|
|
81
|
-
* @param kid - Key ID (optional, defaults to first verification method)
|
|
82
|
-
* @returns Ed25519 JWK or null if not found
|
|
83
|
-
* @throws {ProofVerificationError} If DID resolution fails with specific error code
|
|
84
|
-
*/
|
|
85
|
-
fetchPublicKeyFromDID(did: string, kid?: string): Promise<Ed25519JWK | null>;
|
|
86
|
-
/**
|
|
87
|
-
* Build canonical payload from proof meta
|
|
88
|
-
*
|
|
89
|
-
* CRITICAL: This must reconstruct the exact JWS payload structure that was originally signed.
|
|
90
|
-
* The original JWS payload uses standard JWT claims (aud, sub, iss) plus custom proof claims,
|
|
91
|
-
* NOT the proof.meta structure directly.
|
|
92
|
-
*
|
|
93
|
-
* @param meta - Proof metadata
|
|
94
|
-
* @returns Canonical JSON string matching the original JWS payload structure
|
|
95
|
-
*/
|
|
96
|
-
buildCanonicalPayload(meta: DetachedProof["meta"]): string;
|
|
97
|
-
}
|
|
98
|
-
//# sourceMappingURL=proof-verifier.d.ts.map
|