@kya-os/mcp-i-core 1.3.13 → 1.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/remote-config.js +9 -12
- package/dist/runtime/base.d.ts +2 -1
- package/dist/runtime/base.js +34 -6
- package/dist/services/access-control.service.js +5 -0
- package/dist/services/tool-protection.service.js +17 -8
- package/package.json +2 -2
- package/.turbo/turbo-build.log +0 -4
- package/.turbo/turbo-test$colon$coverage.log +0 -4586
- package/.turbo/turbo-test.log +0 -4631
- package/COMPLIANCE_IMPROVEMENT_REPORT.md +0 -483
- package/Composer 3.md +0 -615
- package/GPT-5.md +0 -1169
- package/OPUS-plan.md +0 -352
- package/PHASE_3_AND_4.1_SUMMARY.md +0 -585
- package/PHASE_3_SUMMARY.md +0 -317
- package/PHASE_4.1.3_SUMMARY.md +0 -428
- package/PHASE_4.1_COMPLETE.md +0 -525
- package/PHASE_4_USER_DID_IDENTITY_LINKING_PLAN.md +0 -1240
- package/SCHEMA_COMPLIANCE_REPORT.md +0 -275
- package/TEST_PLAN.md +0 -571
- package/coverage/coverage-final.json +0 -60
- package/dist/cache/oauth-config-cache.d.ts.map +0 -1
- package/dist/cache/oauth-config-cache.js.map +0 -1
- package/dist/cache/tool-protection-cache.d.ts.map +0 -1
- package/dist/cache/tool-protection-cache.js.map +0 -1
- package/dist/compliance/index.d.ts.map +0 -1
- package/dist/compliance/index.js.map +0 -1
- package/dist/compliance/schema-registry.d.ts.map +0 -1
- package/dist/compliance/schema-registry.js.map +0 -1
- package/dist/compliance/schema-verifier.d.ts.map +0 -1
- package/dist/compliance/schema-verifier.js.map +0 -1
- package/dist/config/remote-config.d.ts.map +0 -1
- package/dist/config/remote-config.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/delegation/audience-validator.d.ts.map +0 -1
- package/dist/delegation/audience-validator.js.map +0 -1
- package/dist/delegation/bitstring.d.ts.map +0 -1
- package/dist/delegation/bitstring.js.map +0 -1
- package/dist/delegation/cascading-revocation.d.ts.map +0 -1
- package/dist/delegation/cascading-revocation.js.map +0 -1
- package/dist/delegation/delegation-graph.d.ts.map +0 -1
- package/dist/delegation/delegation-graph.js.map +0 -1
- package/dist/delegation/did-key-resolver.d.ts.map +0 -1
- package/dist/delegation/did-key-resolver.js.map +0 -1
- package/dist/delegation/index.d.ts.map +0 -1
- package/dist/delegation/index.js.map +0 -1
- package/dist/delegation/statuslist-manager.d.ts.map +0 -1
- package/dist/delegation/statuslist-manager.js.map +0 -1
- package/dist/delegation/storage/index.d.ts.map +0 -1
- package/dist/delegation/storage/index.js.map +0 -1
- package/dist/delegation/storage/memory-graph-storage.d.ts.map +0 -1
- package/dist/delegation/storage/memory-graph-storage.js.map +0 -1
- package/dist/delegation/storage/memory-statuslist-storage.d.ts.map +0 -1
- package/dist/delegation/storage/memory-statuslist-storage.js.map +0 -1
- package/dist/delegation/utils.d.ts.map +0 -1
- package/dist/delegation/utils.js.map +0 -1
- package/dist/delegation/vc-issuer.d.ts.map +0 -1
- package/dist/delegation/vc-issuer.js.map +0 -1
- package/dist/delegation/vc-verifier.d.ts.map +0 -1
- package/dist/delegation/vc-verifier.js.map +0 -1
- package/dist/identity/idp-token-resolver.d.ts.map +0 -1
- package/dist/identity/idp-token-resolver.js.map +0 -1
- package/dist/identity/idp-token-storage.interface.d.ts.map +0 -1
- package/dist/identity/idp-token-storage.interface.js.map +0 -1
- package/dist/identity/user-did-manager.d.ts.map +0 -1
- package/dist/identity/user-did-manager.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/providers/base.d.ts.map +0 -1
- package/dist/providers/base.js.map +0 -1
- package/dist/providers/memory.d.ts.map +0 -1
- package/dist/providers/memory.js.map +0 -1
- package/dist/runtime/audit-logger.d.ts.map +0 -1
- package/dist/runtime/audit-logger.js.map +0 -1
- package/dist/runtime/base.d.ts.map +0 -1
- package/dist/runtime/base.js.map +0 -1
- package/dist/services/access-control.service.d.ts.map +0 -1
- package/dist/services/access-control.service.js.map +0 -1
- package/dist/services/authorization/authorization-registry.d.ts.map +0 -1
- package/dist/services/authorization/authorization-registry.js.map +0 -1
- package/dist/services/authorization/types.d.ts.map +0 -1
- package/dist/services/authorization/types.js.map +0 -1
- package/dist/services/batch-delegation.service.d.ts.map +0 -1
- package/dist/services/batch-delegation.service.js.map +0 -1
- package/dist/services/crypto.service.d.ts.map +0 -1
- package/dist/services/crypto.service.js.map +0 -1
- package/dist/services/errors.d.ts.map +0 -1
- package/dist/services/errors.js.map +0 -1
- package/dist/services/index.d.ts.map +0 -1
- package/dist/services/index.js.map +0 -1
- package/dist/services/oauth-config.service.d.ts.map +0 -1
- package/dist/services/oauth-config.service.js.map +0 -1
- package/dist/services/oauth-provider-registry.d.ts.map +0 -1
- package/dist/services/oauth-provider-registry.js.map +0 -1
- package/dist/services/oauth-service.d.ts.map +0 -1
- package/dist/services/oauth-service.js.map +0 -1
- package/dist/services/oauth-token-retrieval.service.d.ts.map +0 -1
- package/dist/services/oauth-token-retrieval.service.js.map +0 -1
- package/dist/services/proof-verifier.d.ts.map +0 -1
- package/dist/services/proof-verifier.js.map +0 -1
- package/dist/services/provider-resolver.d.ts.map +0 -1
- package/dist/services/provider-resolver.js.map +0 -1
- package/dist/services/provider-validator.d.ts.map +0 -1
- package/dist/services/provider-validator.js.map +0 -1
- package/dist/services/session-registration.service.d.ts.map +0 -1
- package/dist/services/session-registration.service.js.map +0 -1
- package/dist/services/storage.service.d.ts.map +0 -1
- package/dist/services/storage.service.js.map +0 -1
- package/dist/services/tool-context-builder.d.ts.map +0 -1
- package/dist/services/tool-context-builder.js.map +0 -1
- package/dist/services/tool-protection.service.d.ts.map +0 -1
- package/dist/services/tool-protection.service.js.map +0 -1
- package/dist/types/oauth-required-error.d.ts.map +0 -1
- package/dist/types/oauth-required-error.js.map +0 -1
- package/dist/types/tool-protection.d.ts.map +0 -1
- package/dist/types/tool-protection.js.map +0 -1
- package/dist/utils/base58.d.ts.map +0 -1
- package/dist/utils/base58.js.map +0 -1
- package/dist/utils/base64.d.ts.map +0 -1
- package/dist/utils/base64.js.map +0 -1
- package/dist/utils/cors.d.ts.map +0 -1
- package/dist/utils/cors.js.map +0 -1
- package/dist/utils/did-helpers.d.ts.map +0 -1
- package/dist/utils/did-helpers.js.map +0 -1
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/storage-keys.d.ts.map +0 -1
- package/dist/utils/storage-keys.js.map +0 -1
- package/docs/API_REFERENCE.md +0 -1362
- package/docs/COMPLIANCE_MATRIX.md +0 -691
- package/docs/STATUSLIST2021_GUIDE.md +0 -696
- package/docs/W3C_VC_DELEGATION_GUIDE.md +0 -710
- package/src/__tests__/cache/tool-protection-cache.test.ts +0 -640
- package/src/__tests__/config/provider-runtime-config.test.ts +0 -309
- package/src/__tests__/delegation-e2e.test.ts +0 -690
- package/src/__tests__/identity/user-did-manager.test.ts +0 -232
- package/src/__tests__/index.test.ts +0 -56
- package/src/__tests__/integration/full-flow.test.ts +0 -789
- package/src/__tests__/integration.test.ts +0 -281
- package/src/__tests__/providers/base.test.ts +0 -173
- package/src/__tests__/providers/memory.test.ts +0 -319
- package/src/__tests__/regression/phase2-regression.test.ts +0 -429
- package/src/__tests__/runtime/audit-logger.test.ts +0 -154
- package/src/__tests__/runtime/base-extensions.test.ts +0 -595
- package/src/__tests__/runtime/base.test.ts +0 -869
- package/src/__tests__/runtime/delegation-flow.test.ts +0 -164
- package/src/__tests__/runtime/proof-client-did.test.ts +0 -376
- package/src/__tests__/runtime/route-interception.test.ts +0 -686
- package/src/__tests__/runtime/tool-protection-enforcement.test.ts +0 -908
- package/src/__tests__/services/agentshield-integration.test.ts +0 -791
- package/src/__tests__/services/cache-busting.test.ts +0 -125
- package/src/__tests__/services/oauth-service-pkce.test.ts +0 -556
- package/src/__tests__/services/provider-resolver-edge-cases.test.ts +0 -591
- package/src/__tests__/services/tool-protection-merged-config.test.ts +0 -485
- package/src/__tests__/services/tool-protection-oauth-provider.test.ts +0 -480
- package/src/__tests__/services/tool-protection.service.test.ts +0 -1373
- package/src/__tests__/utils/mock-providers.ts +0 -340
- package/src/cache/oauth-config-cache.d.ts +0 -69
- package/src/cache/oauth-config-cache.d.ts.map +0 -1
- package/src/cache/oauth-config-cache.js.map +0 -1
- package/src/cache/oauth-config-cache.ts +0 -123
- package/src/cache/tool-protection-cache.ts +0 -171
- package/src/compliance/EXAMPLE.md +0 -412
- package/src/compliance/__tests__/schema-verifier.test.ts +0 -797
- package/src/compliance/index.ts +0 -8
- package/src/compliance/schema-registry.ts +0 -460
- package/src/compliance/schema-verifier.ts +0 -708
- package/src/config/__tests__/merged-config.spec.ts +0 -445
- package/src/config/__tests__/remote-config.spec.ts +0 -268
- package/src/config/remote-config.ts +0 -264
- package/src/config.ts +0 -312
- package/src/delegation/__tests__/audience-validator.test.ts +0 -112
- package/src/delegation/__tests__/bitstring.test.ts +0 -346
- package/src/delegation/__tests__/cascading-revocation.test.ts +0 -628
- package/src/delegation/__tests__/delegation-graph.test.ts +0 -584
- package/src/delegation/__tests__/did-key-resolver.test.ts +0 -265
- package/src/delegation/__tests__/utils.test.ts +0 -152
- package/src/delegation/__tests__/vc-issuer.test.ts +0 -442
- package/src/delegation/__tests__/vc-verifier.test.ts +0 -922
- package/src/delegation/audience-validator.ts +0 -52
- package/src/delegation/bitstring.ts +0 -278
- package/src/delegation/cascading-revocation.ts +0 -370
- package/src/delegation/delegation-graph.ts +0 -299
- package/src/delegation/did-key-resolver.ts +0 -179
- package/src/delegation/index.ts +0 -14
- package/src/delegation/statuslist-manager.ts +0 -353
- package/src/delegation/storage/__tests__/memory-graph-storage.test.ts +0 -366
- package/src/delegation/storage/__tests__/memory-statuslist-storage.test.ts +0 -228
- package/src/delegation/storage/index.ts +0 -9
- package/src/delegation/storage/memory-graph-storage.ts +0 -178
- package/src/delegation/storage/memory-statuslist-storage.ts +0 -77
- package/src/delegation/utils.ts +0 -221
- package/src/delegation/vc-issuer.ts +0 -232
- package/src/delegation/vc-verifier.ts +0 -568
- package/src/identity/idp-token-resolver.ts +0 -181
- package/src/identity/idp-token-storage.interface.ts +0 -94
- package/src/identity/user-did-manager.ts +0 -526
- package/src/index.ts +0 -310
- package/src/providers/base.d.ts +0 -91
- package/src/providers/base.d.ts.map +0 -1
- package/src/providers/base.js.map +0 -1
- package/src/providers/base.ts +0 -96
- package/src/providers/memory.ts +0 -142
- package/src/runtime/audit-logger.ts +0 -39
- package/src/runtime/base.ts +0 -1392
- package/src/services/__tests__/access-control.integration.test.ts +0 -443
- package/src/services/__tests__/access-control.proof-response-validation.test.ts +0 -578
- package/src/services/__tests__/access-control.service.test.ts +0 -970
- package/src/services/__tests__/batch-delegation.service.test.ts +0 -351
- package/src/services/__tests__/crypto.service.test.ts +0 -531
- package/src/services/__tests__/oauth-provider-registry.test.ts +0 -142
- package/src/services/__tests__/proof-verifier.integration.test.ts +0 -485
- package/src/services/__tests__/proof-verifier.test.ts +0 -489
- package/src/services/__tests__/provider-resolution.integration.test.ts +0 -202
- package/src/services/__tests__/provider-resolver.test.ts +0 -213
- package/src/services/__tests__/storage.service.test.ts +0 -358
- package/src/services/access-control.service.ts +0 -990
- package/src/services/authorization/authorization-registry.ts +0 -66
- package/src/services/authorization/types.ts +0 -71
- package/src/services/batch-delegation.service.ts +0 -137
- package/src/services/crypto.service.ts +0 -302
- package/src/services/errors.ts +0 -76
- package/src/services/index.ts +0 -18
- package/src/services/oauth-config.service.d.ts +0 -53
- package/src/services/oauth-config.service.d.ts.map +0 -1
- package/src/services/oauth-config.service.js.map +0 -1
- package/src/services/oauth-config.service.ts +0 -192
- package/src/services/oauth-provider-registry.d.ts +0 -57
- package/src/services/oauth-provider-registry.d.ts.map +0 -1
- package/src/services/oauth-provider-registry.js.map +0 -1
- package/src/services/oauth-provider-registry.ts +0 -141
- package/src/services/oauth-service.ts +0 -544
- package/src/services/oauth-token-retrieval.service.ts +0 -245
- package/src/services/proof-verifier.ts +0 -478
- package/src/services/provider-resolver.d.ts +0 -48
- package/src/services/provider-resolver.d.ts.map +0 -1
- package/src/services/provider-resolver.js.map +0 -1
- package/src/services/provider-resolver.ts +0 -146
- package/src/services/provider-validator.ts +0 -170
- package/src/services/session-registration.service.ts +0 -251
- package/src/services/storage.service.ts +0 -566
- package/src/services/tool-context-builder.ts +0 -237
- package/src/services/tool-protection.service.ts +0 -1070
- package/src/types/oauth-required-error.ts +0 -63
- package/src/types/tool-protection.ts +0 -155
- package/src/utils/__tests__/did-helpers.test.ts +0 -156
- package/src/utils/base58.ts +0 -109
- package/src/utils/base64.ts +0 -148
- package/src/utils/cors.ts +0 -83
- package/src/utils/did-helpers.ts +0 -210
- package/src/utils/index.ts +0 -8
- package/src/utils/storage-keys.ts +0 -278
- package/tsconfig.json +0 -21
- package/vitest.config.ts +0 -56
|
@@ -1,485 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ToolProtectionService Tests - Merged Config Format
|
|
3
|
-
*
|
|
4
|
-
* TDD tests for ToolProtectionService consuming the new merged config API
|
|
5
|
-
* where tool protections are embedded at config.toolProtection.tools.
|
|
6
|
-
*
|
|
7
|
-
* These tests document the expected behavior BEFORE implementation.
|
|
8
|
-
* The service should fetch from /config endpoint and extract tool protections
|
|
9
|
-
* from the embedded tools field.
|
|
10
|
-
*
|
|
11
|
-
* @since 1.6.0
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { describe, test, expect, beforeEach, vi, afterEach } from 'vitest';
|
|
15
|
-
import { ToolProtectionService } from '../../services/tool-protection.service';
|
|
16
|
-
import {
|
|
17
|
-
InMemoryToolProtectionCache,
|
|
18
|
-
type ToolProtectionCache,
|
|
19
|
-
} from '../../cache/tool-protection-cache';
|
|
20
|
-
import type {
|
|
21
|
-
ToolProtectionServiceConfig,
|
|
22
|
-
ToolProtectionConfig,
|
|
23
|
-
} from '../../types/tool-protection';
|
|
24
|
-
|
|
25
|
-
// Mock global fetch
|
|
26
|
-
global.fetch = vi.fn();
|
|
27
|
-
|
|
28
|
-
describe('ToolProtectionService - Merged Config API', () => {
|
|
29
|
-
let service: ToolProtectionService;
|
|
30
|
-
let cache: ToolProtectionCache;
|
|
31
|
-
let config: ToolProtectionServiceConfig;
|
|
32
|
-
const mockAgentDid = 'did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK';
|
|
33
|
-
|
|
34
|
-
beforeEach(() => {
|
|
35
|
-
vi.clearAllMocks();
|
|
36
|
-
cache = new InMemoryToolProtectionCache();
|
|
37
|
-
config = {
|
|
38
|
-
apiUrl: 'https://kya.vouched.id',
|
|
39
|
-
apiKey: 'test-api-key-12345',
|
|
40
|
-
projectId: 'test-project-123',
|
|
41
|
-
cacheTtl: 300000,
|
|
42
|
-
debug: false,
|
|
43
|
-
};
|
|
44
|
-
service = new ToolProtectionService(config, cache);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
afterEach(() => {
|
|
48
|
-
vi.restoreAllMocks();
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
describe('Fetching from /config endpoint with embedded tools', () => {
|
|
52
|
-
test('should fetch from /config endpoint and extract toolProtection.tools', async () => {
|
|
53
|
-
// New merged config API response format
|
|
54
|
-
const mergedConfigResponse = {
|
|
55
|
-
success: true,
|
|
56
|
-
data: {
|
|
57
|
-
config: {
|
|
58
|
-
identity: {
|
|
59
|
-
serverDid: 'did:key:test',
|
|
60
|
-
environment: 'production',
|
|
61
|
-
storageLocation: 'cloudflare-kv'
|
|
62
|
-
},
|
|
63
|
-
proofing: {
|
|
64
|
-
enabled: true,
|
|
65
|
-
destinations: [],
|
|
66
|
-
batchQueue: { maxBatchSize: 10, flushIntervalMs: 5000, maxRetries: 3 }
|
|
67
|
-
},
|
|
68
|
-
delegation: {
|
|
69
|
-
enabled: true,
|
|
70
|
-
enforceStrictly: true,
|
|
71
|
-
verifier: { type: 'agentshield' },
|
|
72
|
-
authorization: {}
|
|
73
|
-
},
|
|
74
|
-
toolProtection: {
|
|
75
|
-
source: 'agentshield',
|
|
76
|
-
tools: {
|
|
77
|
-
checkout: {
|
|
78
|
-
requiresDelegation: true,
|
|
79
|
-
requiredScopes: ['cart:write', 'payment:execute'],
|
|
80
|
-
riskLevel: 'high'
|
|
81
|
-
},
|
|
82
|
-
greet: {
|
|
83
|
-
requiresDelegation: false,
|
|
84
|
-
requiredScopes: []
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
audit: { enabled: true, includeProofHashes: true, includePayloads: false },
|
|
89
|
-
session: { timestampSkewSeconds: 120, ttlMinutes: 30 },
|
|
90
|
-
platform: { type: 'cloudflare' },
|
|
91
|
-
metadata: { version: '1.6.0', lastUpdated: new Date().toISOString(), source: 'dashboard' }
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
metadata: {
|
|
95
|
-
timestamp: new Date().toISOString(),
|
|
96
|
-
cachedUntil: new Date(Date.now() + 60000).toISOString()
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
(global.fetch as any).mockResolvedValueOnce({
|
|
101
|
-
ok: true,
|
|
102
|
-
text: async () => JSON.stringify(mergedConfigResponse),
|
|
103
|
-
json: async () => mergedConfigResponse,
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
const result = await service.getToolProtectionConfig(mockAgentDid);
|
|
107
|
-
|
|
108
|
-
// Should extract tool protections from embedded field
|
|
109
|
-
expect(result.toolProtections).toEqual({
|
|
110
|
-
checkout: {
|
|
111
|
-
requiresDelegation: true,
|
|
112
|
-
requiredScopes: ['cart:write', 'payment:execute'],
|
|
113
|
-
riskLevel: 'high'
|
|
114
|
-
},
|
|
115
|
-
greet: {
|
|
116
|
-
requiresDelegation: false,
|
|
117
|
-
requiredScopes: []
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
// Should have called the /config endpoint (not /tool-protections)
|
|
122
|
-
expect(global.fetch).toHaveBeenCalledWith(
|
|
123
|
-
expect.stringContaining('/config'),
|
|
124
|
-
expect.any(Object)
|
|
125
|
-
);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
test('should use projectId-based /config endpoint when projectId is set', async () => {
|
|
129
|
-
const projectId = 'my-project-id';
|
|
130
|
-
config.projectId = projectId;
|
|
131
|
-
service = new ToolProtectionService(config, cache);
|
|
132
|
-
|
|
133
|
-
const mergedConfigResponse = {
|
|
134
|
-
success: true,
|
|
135
|
-
data: {
|
|
136
|
-
config: {
|
|
137
|
-
identity: { serverDid: 'did:key:test', environment: 'production', storageLocation: 'cloudflare-kv' },
|
|
138
|
-
proofing: { enabled: false, destinations: [], batchQueue: { maxBatchSize: 10, flushIntervalMs: 5000, maxRetries: 3 } },
|
|
139
|
-
delegation: { enabled: false, enforceStrictly: false, verifier: { type: 'memory' }, authorization: {} },
|
|
140
|
-
toolProtection: {
|
|
141
|
-
source: 'agentshield',
|
|
142
|
-
tools: {
|
|
143
|
-
greet: { requiresDelegation: true, requiredScopes: ['greeting:write'] }
|
|
144
|
-
}
|
|
145
|
-
},
|
|
146
|
-
audit: { enabled: false, includeProofHashes: false, includePayloads: false },
|
|
147
|
-
session: { timestampSkewSeconds: 120, ttlMinutes: 30 },
|
|
148
|
-
platform: { type: 'node' },
|
|
149
|
-
metadata: { version: '1.6.0', lastUpdated: new Date().toISOString(), source: 'dashboard' }
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
(global.fetch as any).mockResolvedValueOnce({
|
|
155
|
-
ok: true,
|
|
156
|
-
text: async () => JSON.stringify(mergedConfigResponse),
|
|
157
|
-
json: async () => mergedConfigResponse,
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
await service.getToolProtectionConfig(mockAgentDid);
|
|
161
|
-
|
|
162
|
-
// Should call /api/v1/bouncer/projects/{projectId}/config
|
|
163
|
-
expect(global.fetch).toHaveBeenCalledWith(
|
|
164
|
-
`https://kya.vouched.id/api/v1/bouncer/projects/${encodeURIComponent(projectId)}/config`,
|
|
165
|
-
expect.any(Object)
|
|
166
|
-
);
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
test('should handle empty tools object from merged config', async () => {
|
|
170
|
-
const mergedConfigResponse = {
|
|
171
|
-
success: true,
|
|
172
|
-
data: {
|
|
173
|
-
config: {
|
|
174
|
-
identity: { serverDid: 'did:key:test', environment: 'production', storageLocation: 'cloudflare-kv' },
|
|
175
|
-
proofing: { enabled: false, destinations: [], batchQueue: { maxBatchSize: 10, flushIntervalMs: 5000, maxRetries: 3 } },
|
|
176
|
-
delegation: { enabled: false, enforceStrictly: false, verifier: { type: 'memory' }, authorization: {} },
|
|
177
|
-
toolProtection: {
|
|
178
|
-
source: 'agentshield',
|
|
179
|
-
tools: {} // No tools discovered yet
|
|
180
|
-
},
|
|
181
|
-
audit: { enabled: false, includeProofHashes: false, includePayloads: false },
|
|
182
|
-
session: { timestampSkewSeconds: 120, ttlMinutes: 30 },
|
|
183
|
-
platform: { type: 'node' },
|
|
184
|
-
metadata: { version: '1.6.0', lastUpdated: new Date().toISOString(), source: 'dashboard' }
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
(global.fetch as any).mockResolvedValueOnce({
|
|
190
|
-
ok: true,
|
|
191
|
-
text: async () => JSON.stringify(mergedConfigResponse),
|
|
192
|
-
json: async () => mergedConfigResponse,
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
const result = await service.getToolProtectionConfig(mockAgentDid);
|
|
196
|
-
|
|
197
|
-
expect(result.toolProtections).toEqual({});
|
|
198
|
-
});
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
describe('checkToolProtection with merged config', () => {
|
|
202
|
-
test('should correctly identify protected tool from merged config', async () => {
|
|
203
|
-
const mergedConfigResponse = {
|
|
204
|
-
success: true,
|
|
205
|
-
data: {
|
|
206
|
-
config: {
|
|
207
|
-
identity: { serverDid: 'did:key:test', environment: 'production', storageLocation: 'cloudflare-kv' },
|
|
208
|
-
proofing: { enabled: false, destinations: [], batchQueue: { maxBatchSize: 10, flushIntervalMs: 5000, maxRetries: 3 } },
|
|
209
|
-
delegation: { enabled: true, enforceStrictly: true, verifier: { type: 'agentshield' }, authorization: {} },
|
|
210
|
-
toolProtection: {
|
|
211
|
-
source: 'agentshield',
|
|
212
|
-
tools: {
|
|
213
|
-
checkout: {
|
|
214
|
-
requiresDelegation: true,
|
|
215
|
-
requiredScopes: ['checkout:execute'],
|
|
216
|
-
riskLevel: 'high'
|
|
217
|
-
},
|
|
218
|
-
greet: {
|
|
219
|
-
requiresDelegation: false,
|
|
220
|
-
requiredScopes: []
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
},
|
|
224
|
-
audit: { enabled: false, includeProofHashes: false, includePayloads: false },
|
|
225
|
-
session: { timestampSkewSeconds: 120, ttlMinutes: 30 },
|
|
226
|
-
platform: { type: 'cloudflare' },
|
|
227
|
-
metadata: { version: '1.6.0', lastUpdated: new Date().toISOString(), source: 'dashboard' }
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
(global.fetch as any).mockResolvedValueOnce({
|
|
233
|
-
ok: true,
|
|
234
|
-
text: async () => JSON.stringify(mergedConfigResponse),
|
|
235
|
-
json: async () => mergedConfigResponse,
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
// Protected tool should return protection details
|
|
239
|
-
const checkoutProtection = await service.checkToolProtection('checkout', mockAgentDid);
|
|
240
|
-
expect(checkoutProtection).toEqual({
|
|
241
|
-
requiresDelegation: true,
|
|
242
|
-
requiredScopes: ['checkout:execute'],
|
|
243
|
-
riskLevel: 'high'
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
// Unprotected tool should return null
|
|
247
|
-
const greetProtection = await service.checkToolProtection('greet', mockAgentDid);
|
|
248
|
-
expect(greetProtection).toBeNull();
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
test('should return null for unknown tool', async () => {
|
|
252
|
-
const mergedConfigResponse = {
|
|
253
|
-
success: true,
|
|
254
|
-
data: {
|
|
255
|
-
config: {
|
|
256
|
-
identity: { serverDid: 'did:key:test', environment: 'production', storageLocation: 'cloudflare-kv' },
|
|
257
|
-
proofing: { enabled: false, destinations: [], batchQueue: { maxBatchSize: 10, flushIntervalMs: 5000, maxRetries: 3 } },
|
|
258
|
-
delegation: { enabled: false, enforceStrictly: false, verifier: { type: 'memory' }, authorization: {} },
|
|
259
|
-
toolProtection: {
|
|
260
|
-
source: 'agentshield',
|
|
261
|
-
tools: {
|
|
262
|
-
greet: { requiresDelegation: false, requiredScopes: [] }
|
|
263
|
-
}
|
|
264
|
-
},
|
|
265
|
-
audit: { enabled: false, includeProofHashes: false, includePayloads: false },
|
|
266
|
-
session: { timestampSkewSeconds: 120, ttlMinutes: 30 },
|
|
267
|
-
platform: { type: 'node' },
|
|
268
|
-
metadata: { version: '1.6.0', lastUpdated: new Date().toISOString(), source: 'dashboard' }
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
(global.fetch as any).mockResolvedValueOnce({
|
|
274
|
-
ok: true,
|
|
275
|
-
text: async () => JSON.stringify(mergedConfigResponse),
|
|
276
|
-
json: async () => mergedConfigResponse,
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
const unknownProtection = await service.checkToolProtection('unknown-tool', mockAgentDid);
|
|
280
|
-
expect(unknownProtection).toBeNull();
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
describe('Fallback behavior with merged config', () => {
|
|
285
|
-
test('should use fallback config when network error occurs', async () => {
|
|
286
|
-
const fallbackConfig: ToolProtectionConfig = {
|
|
287
|
-
toolProtections: {
|
|
288
|
-
greet: {
|
|
289
|
-
requiresDelegation: true,
|
|
290
|
-
requiredScopes: ['fallback:scope']
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
config.fallbackConfig = fallbackConfig;
|
|
296
|
-
service = new ToolProtectionService(config, cache);
|
|
297
|
-
|
|
298
|
-
// Network error (not HTTP error) triggers fallback
|
|
299
|
-
(global.fetch as any).mockRejectedValueOnce(new Error('Network error'));
|
|
300
|
-
|
|
301
|
-
const result = await service.getToolProtectionConfig(mockAgentDid);
|
|
302
|
-
|
|
303
|
-
expect(result.toolProtections.greet).toEqual({
|
|
304
|
-
requiresDelegation: true,
|
|
305
|
-
requiredScopes: ['fallback:scope']
|
|
306
|
-
});
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
test('should throw error when API returns HTTP error (500)', async () => {
|
|
310
|
-
// HTTP errors (4xx, 5xx) are intentionally propagated, not fallback
|
|
311
|
-
(global.fetch as any).mockResolvedValueOnce({
|
|
312
|
-
ok: false,
|
|
313
|
-
status: 500,
|
|
314
|
-
statusText: 'Internal Server Error',
|
|
315
|
-
text: async () => 'Server error',
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
await expect(service.getToolProtectionConfig(mockAgentDid))
|
|
319
|
-
.rejects.toThrow('Failed to fetch bouncer config: 500');
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
test('should handle API returning config without tools field', async () => {
|
|
323
|
-
// Simulate old API format without tools field
|
|
324
|
-
const oldFormatResponse = {
|
|
325
|
-
success: true,
|
|
326
|
-
data: {
|
|
327
|
-
config: {
|
|
328
|
-
identity: { serverDid: 'did:key:test', environment: 'production', storageLocation: 'cloudflare-kv' },
|
|
329
|
-
proofing: { enabled: false, destinations: [], batchQueue: { maxBatchSize: 10, flushIntervalMs: 5000, maxRetries: 3 } },
|
|
330
|
-
delegation: { enabled: false, enforceStrictly: false, verifier: { type: 'memory' }, authorization: {} },
|
|
331
|
-
toolProtection: {
|
|
332
|
-
source: 'agentshield'
|
|
333
|
-
// No tools field - old format
|
|
334
|
-
},
|
|
335
|
-
audit: { enabled: false, includeProofHashes: false, includePayloads: false },
|
|
336
|
-
session: { timestampSkewSeconds: 120, ttlMinutes: 30 },
|
|
337
|
-
platform: { type: 'node' },
|
|
338
|
-
metadata: { version: '1.5.0', lastUpdated: new Date().toISOString(), source: 'dashboard' }
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
};
|
|
342
|
-
|
|
343
|
-
const fallbackConfig: ToolProtectionConfig = {
|
|
344
|
-
toolProtections: {
|
|
345
|
-
greet: {
|
|
346
|
-
requiresDelegation: true,
|
|
347
|
-
requiredScopes: ['fallback:scope']
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
config.fallbackConfig = fallbackConfig;
|
|
353
|
-
service = new ToolProtectionService(config, cache);
|
|
354
|
-
|
|
355
|
-
(global.fetch as any).mockResolvedValueOnce({
|
|
356
|
-
ok: true,
|
|
357
|
-
text: async () => JSON.stringify(oldFormatResponse),
|
|
358
|
-
json: async () => oldFormatResponse,
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
const result = await service.getToolProtectionConfig(mockAgentDid);
|
|
362
|
-
|
|
363
|
-
// Should fallback to empty or use fallback config
|
|
364
|
-
// After implementation: should return empty tools or use fallback
|
|
365
|
-
expect(result.toolProtections).toBeDefined();
|
|
366
|
-
});
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
describe('Caching with merged config', () => {
|
|
370
|
-
test('should cache tool protections extracted from merged config', async () => {
|
|
371
|
-
const mergedConfigResponse = {
|
|
372
|
-
success: true,
|
|
373
|
-
data: {
|
|
374
|
-
config: {
|
|
375
|
-
identity: { serverDid: 'did:key:test', environment: 'production', storageLocation: 'cloudflare-kv' },
|
|
376
|
-
proofing: { enabled: false, destinations: [], batchQueue: { maxBatchSize: 10, flushIntervalMs: 5000, maxRetries: 3 } },
|
|
377
|
-
delegation: { enabled: false, enforceStrictly: false, verifier: { type: 'memory' }, authorization: {} },
|
|
378
|
-
toolProtection: {
|
|
379
|
-
source: 'agentshield',
|
|
380
|
-
tools: {
|
|
381
|
-
greet: { requiresDelegation: true, requiredScopes: ['greeting:write'] }
|
|
382
|
-
}
|
|
383
|
-
},
|
|
384
|
-
audit: { enabled: false, includeProofHashes: false, includePayloads: false },
|
|
385
|
-
session: { timestampSkewSeconds: 120, ttlMinutes: 30 },
|
|
386
|
-
platform: { type: 'node' },
|
|
387
|
-
metadata: { version: '1.6.0', lastUpdated: new Date().toISOString(), source: 'dashboard' }
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
};
|
|
391
|
-
|
|
392
|
-
(global.fetch as any).mockResolvedValueOnce({
|
|
393
|
-
ok: true,
|
|
394
|
-
text: async () => JSON.stringify(mergedConfigResponse),
|
|
395
|
-
json: async () => mergedConfigResponse,
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
// First call - should fetch from API
|
|
399
|
-
await service.getToolProtectionConfig(mockAgentDid);
|
|
400
|
-
expect(global.fetch).toHaveBeenCalledTimes(1);
|
|
401
|
-
|
|
402
|
-
// Second call - should use cache
|
|
403
|
-
await service.getToolProtectionConfig(mockAgentDid);
|
|
404
|
-
expect(global.fetch).toHaveBeenCalledTimes(1); // No additional fetch
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
test('should respect cache TTL for merged config', async () => {
|
|
408
|
-
const mergedConfigResponse = {
|
|
409
|
-
success: true,
|
|
410
|
-
data: {
|
|
411
|
-
config: {
|
|
412
|
-
identity: { serverDid: 'did:key:test', environment: 'production', storageLocation: 'cloudflare-kv' },
|
|
413
|
-
proofing: { enabled: false, destinations: [], batchQueue: { maxBatchSize: 10, flushIntervalMs: 5000, maxRetries: 3 } },
|
|
414
|
-
delegation: { enabled: false, enforceStrictly: false, verifier: { type: 'memory' }, authorization: {} },
|
|
415
|
-
toolProtection: {
|
|
416
|
-
source: 'agentshield',
|
|
417
|
-
tools: {
|
|
418
|
-
greet: { requiresDelegation: true, requiredScopes: ['greeting:write'] }
|
|
419
|
-
}
|
|
420
|
-
},
|
|
421
|
-
audit: { enabled: false, includeProofHashes: false, includePayloads: false },
|
|
422
|
-
session: { timestampSkewSeconds: 120, ttlMinutes: 30 },
|
|
423
|
-
platform: { type: 'node' },
|
|
424
|
-
metadata: { version: '1.6.0', lastUpdated: new Date().toISOString(), source: 'dashboard' }
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
};
|
|
428
|
-
|
|
429
|
-
// Use short TTL
|
|
430
|
-
config.cacheTtl = 100; // 100ms
|
|
431
|
-
service = new ToolProtectionService(config, cache);
|
|
432
|
-
|
|
433
|
-
(global.fetch as any).mockResolvedValue({
|
|
434
|
-
ok: true,
|
|
435
|
-
text: async () => JSON.stringify(mergedConfigResponse),
|
|
436
|
-
json: async () => mergedConfigResponse,
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
// First call
|
|
440
|
-
await service.getToolProtectionConfig(mockAgentDid);
|
|
441
|
-
expect(global.fetch).toHaveBeenCalledTimes(1);
|
|
442
|
-
|
|
443
|
-
// Wait for cache to expire
|
|
444
|
-
await new Promise(resolve => setTimeout(resolve, 150));
|
|
445
|
-
|
|
446
|
-
// Second call - should fetch again (cache expired)
|
|
447
|
-
await service.getToolProtectionConfig(mockAgentDid);
|
|
448
|
-
expect(global.fetch).toHaveBeenCalledTimes(2);
|
|
449
|
-
});
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
describe('Backward compatibility - /tool-protections response format', () => {
|
|
453
|
-
test('should still handle legacy /tool-protections response format if encountered', async () => {
|
|
454
|
-
// This tests backward compatibility during transition period
|
|
455
|
-
// The service might encounter the old response format
|
|
456
|
-
const legacyResponse = {
|
|
457
|
-
success: true,
|
|
458
|
-
data: {
|
|
459
|
-
toolProtections: {
|
|
460
|
-
greet: { requiresDelegation: true, requiredScopes: ['greeting:write'] }
|
|
461
|
-
}
|
|
462
|
-
},
|
|
463
|
-
metadata: {
|
|
464
|
-
timestamp: new Date().toISOString(),
|
|
465
|
-
cachedUntil: new Date(Date.now() + 60000).toISOString()
|
|
466
|
-
}
|
|
467
|
-
};
|
|
468
|
-
|
|
469
|
-
(global.fetch as any).mockResolvedValueOnce({
|
|
470
|
-
ok: true,
|
|
471
|
-
text: async () => JSON.stringify(legacyResponse),
|
|
472
|
-
json: async () => legacyResponse,
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
const result = await service.getToolProtectionConfig(mockAgentDid);
|
|
476
|
-
|
|
477
|
-
// Should still work with legacy format
|
|
478
|
-
expect(result.toolProtections.greet).toEqual({
|
|
479
|
-
requiresDelegation: true,
|
|
480
|
-
requiredScopes: ['greeting:write']
|
|
481
|
-
});
|
|
482
|
-
});
|
|
483
|
-
});
|
|
484
|
-
});
|
|
485
|
-
|