@vorionsys/basis 1.0.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 (174) hide show
  1. package/.env.example +22 -0
  2. package/AMOY-MIGRATION.md +188 -0
  3. package/DEPLOY-AMOY.md +368 -0
  4. package/DEPLOY-NOW.md +216 -0
  5. package/DEPLOYMENT.md +239 -0
  6. package/GET-WALLET.md +286 -0
  7. package/QUICK-WALLET-SETUP.md +268 -0
  8. package/README.md +195 -0
  9. package/artifacts/@openzeppelin/contracts/access/AccessControl.sol/AccessControl.dbg.json +4 -0
  10. package/artifacts/@openzeppelin/contracts/access/AccessControl.sol/AccessControl.json +236 -0
  11. package/artifacts/@openzeppelin/contracts/access/IAccessControl.sol/IAccessControl.dbg.json +4 -0
  12. package/artifacts/@openzeppelin/contracts/access/IAccessControl.sol/IAccessControl.json +204 -0
  13. package/artifacts/@openzeppelin/contracts/interfaces/IERC4906.sol/IERC4906.dbg.json +4 -0
  14. package/artifacts/@openzeppelin/contracts/interfaces/IERC4906.sol/IERC4906.json +328 -0
  15. package/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors.dbg.json +4 -0
  16. package/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors.json +113 -0
  17. package/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors.dbg.json +4 -0
  18. package/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors.json +97 -0
  19. package/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors.dbg.json +4 -0
  20. package/artifacts/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors.json +114 -0
  21. package/artifacts/@openzeppelin/contracts/token/ERC721/ERC721.sol/ERC721.dbg.json +4 -0
  22. package/artifacts/@openzeppelin/contracts/token/ERC721/ERC721.sol/ERC721.json +444 -0
  23. package/artifacts/@openzeppelin/contracts/token/ERC721/IERC721.sol/IERC721.dbg.json +4 -0
  24. package/artifacts/@openzeppelin/contracts/token/ERC721/IERC721.sol/IERC721.json +296 -0
  25. package/artifacts/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol/IERC721Receiver.dbg.json +4 -0
  26. package/artifacts/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol/IERC721Receiver.json +45 -0
  27. package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol/ERC721Enumerable.dbg.json +4 -0
  28. package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol/ERC721Enumerable.json +521 -0
  29. package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol/ERC721URIStorage.dbg.json +4 -0
  30. package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol/ERC721URIStorage.json +476 -0
  31. package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol/IERC721Enumerable.dbg.json +4 -0
  32. package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol/IERC721Enumerable.json +352 -0
  33. package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol/IERC721Metadata.dbg.json +4 -0
  34. package/artifacts/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol/IERC721Metadata.json +341 -0
  35. package/artifacts/@openzeppelin/contracts/token/ERC721/utils/ERC721Utils.sol/ERC721Utils.dbg.json +4 -0
  36. package/artifacts/@openzeppelin/contracts/token/ERC721/utils/ERC721Utils.sol/ERC721Utils.json +10 -0
  37. package/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.dbg.json +4 -0
  38. package/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.json +10 -0
  39. package/artifacts/@openzeppelin/contracts/utils/Panic.sol/Panic.dbg.json +4 -0
  40. package/artifacts/@openzeppelin/contracts/utils/Panic.sol/Panic.json +10 -0
  41. package/artifacts/@openzeppelin/contracts/utils/Strings.sol/Strings.dbg.json +4 -0
  42. package/artifacts/@openzeppelin/contracts/utils/Strings.sol/Strings.json +37 -0
  43. package/artifacts/@openzeppelin/contracts/utils/introspection/ERC165.sol/ERC165.dbg.json +4 -0
  44. package/artifacts/@openzeppelin/contracts/utils/introspection/ERC165.sol/ERC165.json +30 -0
  45. package/artifacts/@openzeppelin/contracts/utils/introspection/IERC165.sol/IERC165.dbg.json +4 -0
  46. package/artifacts/@openzeppelin/contracts/utils/introspection/IERC165.sol/IERC165.json +30 -0
  47. package/artifacts/@openzeppelin/contracts/utils/math/Math.sol/Math.dbg.json +4 -0
  48. package/artifacts/@openzeppelin/contracts/utils/math/Math.sol/Math.json +10 -0
  49. package/artifacts/@openzeppelin/contracts/utils/math/SafeCast.sol/SafeCast.dbg.json +4 -0
  50. package/artifacts/@openzeppelin/contracts/utils/math/SafeCast.sol/SafeCast.json +65 -0
  51. package/artifacts/@openzeppelin/contracts/utils/math/SignedMath.sol/SignedMath.dbg.json +4 -0
  52. package/artifacts/@openzeppelin/contracts/utils/math/SignedMath.sol/SignedMath.json +10 -0
  53. package/artifacts/build-info/357d1bba4062d461f497f221490811a3.json +1 -0
  54. package/artifacts/contracts/AgentCard.sol/AgentCard.dbg.json +4 -0
  55. package/artifacts/contracts/AgentCard.sol/AgentCard.json +1430 -0
  56. package/build_errors.txt +0 -0
  57. package/build_output.txt +0 -0
  58. package/cache/solidity-files-cache.json +885 -0
  59. package/contracts/AgentCard.sol +478 -0
  60. package/contracts/deploy/01-deploy-agentcard.ts +66 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +12 -0
  63. package/dist/kya/accountability.d.ts.map +1 -0
  64. package/dist/kya/accountability.js +100 -0
  65. package/dist/kya/authorization.d.ts.map +1 -0
  66. package/dist/kya/authorization.js +258 -0
  67. package/dist/kya/behavior.d.ts.map +1 -0
  68. package/dist/kya/behavior.js +142 -0
  69. package/dist/kya/identity.d.ts.map +1 -0
  70. package/dist/kya/identity.js +187 -0
  71. package/dist/kya/index.d.ts.map +1 -0
  72. package/dist/kya/index.js +99 -0
  73. package/dist/kya/types.d.ts.map +1 -0
  74. package/dist/kya/types.js +5 -0
  75. package/dist/trust-1000-agents.test.d.ts.map +1 -0
  76. package/dist/trust-1000-agents.test.js +608 -0
  77. package/dist/trust-capabilities.d.ts.map +1 -0
  78. package/dist/trust-capabilities.js +478 -0
  79. package/dist/trust-factors.d.ts.map +1 -0
  80. package/dist/trust-factors.js +588 -0
  81. package/dist/trust-factors.test.d.ts.map +1 -0
  82. package/dist/trust-factors.test.js +179 -0
  83. package/dist/validation-gate.d.ts.map +1 -0
  84. package/dist/validation-gate.js +468 -0
  85. package/dist/validation-gate.test.d.ts.map +1 -0
  86. package/dist/validation-gate.test.js +419 -0
  87. package/hardhat.config.ts +55 -0
  88. package/package.json +57 -0
  89. package/scripts/certify-agent.ts +91 -0
  90. package/scripts/deploy-agentcard.ts +63 -0
  91. package/scripts/mint-agentcard.ts +87 -0
  92. package/specs/adversarial-sandbox-test-suite.md +1055 -0
  93. package/specs/kya-framework.md +910 -0
  94. package/specs/trust-factors-v2.md +437 -0
  95. package/src/index.ts +14 -0
  96. package/src/kya/accountability.ts +132 -0
  97. package/src/kya/authorization.ts +325 -0
  98. package/src/kya/behavior.ts +169 -0
  99. package/src/kya/identity.ts +224 -0
  100. package/src/kya/index.ts +125 -0
  101. package/src/kya/types.ts +242 -0
  102. package/src/trust-1000-agents.test.ts +745 -0
  103. package/src/trust-capabilities.ts +517 -0
  104. package/src/trust-factors.test.ts +241 -0
  105. package/src/trust-factors.ts +666 -0
  106. package/src/validation-gate.test.ts +531 -0
  107. package/src/validation-gate.ts +665 -0
  108. package/test-kya-simple.ts +258 -0
  109. package/test-kya.ts +245 -0
  110. package/tsconfig.json +14 -0
  111. package/typechain-types/@openzeppelin/contracts/access/AccessControl.ts +324 -0
  112. package/typechain-types/@openzeppelin/contracts/access/IAccessControl.ts +292 -0
  113. package/typechain-types/@openzeppelin/contracts/access/index.ts +5 -0
  114. package/typechain-types/@openzeppelin/contracts/index.ts +11 -0
  115. package/typechain-types/@openzeppelin/contracts/interfaces/IERC4906.ts +462 -0
  116. package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors.ts +69 -0
  117. package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors.ts +69 -0
  118. package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors.ts +69 -0
  119. package/typechain-types/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/index.ts +6 -0
  120. package/typechain-types/@openzeppelin/contracts/interfaces/index.ts +6 -0
  121. package/typechain-types/@openzeppelin/contracts/token/ERC721/ERC721.ts +420 -0
  122. package/typechain-types/@openzeppelin/contracts/token/ERC721/IERC721.ts +393 -0
  123. package/typechain-types/@openzeppelin/contracts/token/ERC721/IERC721Receiver.ts +110 -0
  124. package/typechain-types/@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.ts +470 -0
  125. package/typechain-types/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.ts +489 -0
  126. package/typechain-types/@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.ts +443 -0
  127. package/typechain-types/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.ts +420 -0
  128. package/typechain-types/@openzeppelin/contracts/token/ERC721/extensions/index.ts +7 -0
  129. package/typechain-types/@openzeppelin/contracts/token/ERC721/index.ts +8 -0
  130. package/typechain-types/@openzeppelin/contracts/token/index.ts +5 -0
  131. package/typechain-types/@openzeppelin/contracts/utils/Strings.ts +69 -0
  132. package/typechain-types/@openzeppelin/contracts/utils/index.ts +8 -0
  133. package/typechain-types/@openzeppelin/contracts/utils/introspection/ERC165.ts +94 -0
  134. package/typechain-types/@openzeppelin/contracts/utils/introspection/IERC165.ts +94 -0
  135. package/typechain-types/@openzeppelin/contracts/utils/introspection/index.ts +5 -0
  136. package/typechain-types/@openzeppelin/contracts/utils/math/SafeCast.ts +69 -0
  137. package/typechain-types/@openzeppelin/contracts/utils/math/index.ts +4 -0
  138. package/typechain-types/@openzeppelin/index.ts +5 -0
  139. package/typechain-types/common.ts +131 -0
  140. package/typechain-types/contracts/AgentCard.ts +1415 -0
  141. package/typechain-types/contracts/index.ts +4 -0
  142. package/typechain-types/factories/@openzeppelin/contracts/access/AccessControl__factory.ts +250 -0
  143. package/typechain-types/factories/@openzeppelin/contracts/access/IAccessControl__factory.ts +218 -0
  144. package/typechain-types/factories/@openzeppelin/contracts/access/index.ts +5 -0
  145. package/typechain-types/factories/@openzeppelin/contracts/index.ts +7 -0
  146. package/typechain-types/factories/@openzeppelin/contracts/interfaces/IERC4906__factory.ts +339 -0
  147. package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC1155Errors__factory.ts +127 -0
  148. package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC20Errors__factory.ts +111 -0
  149. package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/IERC721Errors__factory.ts +128 -0
  150. package/typechain-types/factories/@openzeppelin/contracts/interfaces/draft-IERC6093.sol/index.ts +6 -0
  151. package/typechain-types/factories/@openzeppelin/contracts/interfaces/index.ts +5 -0
  152. package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/ERC721__factory.ts +455 -0
  153. package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/IERC721Receiver__factory.ts +59 -0
  154. package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/IERC721__factory.ts +307 -0
  155. package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable__factory.ts +535 -0
  156. package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage__factory.ts +490 -0
  157. package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable__factory.ts +366 -0
  158. package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata__factory.ts +355 -0
  159. package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/extensions/index.ts +7 -0
  160. package/typechain-types/factories/@openzeppelin/contracts/token/ERC721/index.ts +7 -0
  161. package/typechain-types/factories/@openzeppelin/contracts/token/index.ts +4 -0
  162. package/typechain-types/factories/@openzeppelin/contracts/utils/Strings__factory.ts +90 -0
  163. package/typechain-types/factories/@openzeppelin/contracts/utils/index.ts +6 -0
  164. package/typechain-types/factories/@openzeppelin/contracts/utils/introspection/ERC165__factory.ts +41 -0
  165. package/typechain-types/factories/@openzeppelin/contracts/utils/introspection/IERC165__factory.ts +41 -0
  166. package/typechain-types/factories/@openzeppelin/contracts/utils/introspection/index.ts +5 -0
  167. package/typechain-types/factories/@openzeppelin/contracts/utils/math/SafeCast__factory.ts +118 -0
  168. package/typechain-types/factories/@openzeppelin/contracts/utils/math/index.ts +4 -0
  169. package/typechain-types/factories/@openzeppelin/index.ts +4 -0
  170. package/typechain-types/factories/contracts/AgentCard__factory.ts +1480 -0
  171. package/typechain-types/factories/contracts/index.ts +4 -0
  172. package/typechain-types/factories/index.ts +5 -0
  173. package/typechain-types/index.ts +44 -0
  174. package/vitest.config.ts +8 -0
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Trust Factors Test Suite
3
+ *
4
+ * Tests 100 simulated agents through the trust scoring system
5
+ * to validate tier placement is correct.
6
+ */
7
+ import { TrustTier, TIER_THRESHOLDS, getTrustTierFromScore, getTierName, calculateTrustScore, } from './trust-factors';
8
+ // All 23 factor codes
9
+ const ALL_FACTOR_CODES = [
10
+ 'CT-COMP', 'CT-REL', 'CT-OBS', 'CT-TRANS', 'CT-ACCT', 'CT-SAFE',
11
+ 'CT-SEC', 'CT-PRIV', 'CT-ID', 'OP-HUMAN', 'OP-ALIGN', 'OP-STEW',
12
+ 'SF-HUM', 'SF-ADAPT', 'SF-LEARN', 'LC-UNCERT', 'LC-HANDOFF',
13
+ 'LC-EMPHUM', 'LC-CAUSAL', 'LC-PATIENT', 'LC-EMP', 'LC-MORAL', 'LC-TRACK'
14
+ ];
15
+ // Generate agent with scores targeting a specific score range
16
+ function generateAgentForScoreRange(agentId, targetTier) {
17
+ const tierRange = TIER_THRESHOLDS[targetTier];
18
+ // Target the middle of the tier's score range
19
+ const targetScore = (tierRange.min + tierRange.max) / 2 / 1000; // Convert to 0-1 scale
20
+ // Generate uniform scores around the target
21
+ const factorScores = ALL_FACTOR_CODES.map(code => {
22
+ // Add some variance but stay near target
23
+ const variance = (Math.random() - 0.5) * 0.1;
24
+ const score = Math.min(1.0, Math.max(0, targetScore + variance));
25
+ return {
26
+ code: code,
27
+ score,
28
+ timestamp: new Date(),
29
+ source: 'measured',
30
+ confidence: 0.9,
31
+ };
32
+ });
33
+ return {
34
+ id: agentId,
35
+ targetTier,
36
+ factorScores,
37
+ expectedScoreRange: tierRange,
38
+ };
39
+ }
40
+ // Generate edge case agent at boundary of tier
41
+ function generateBoundaryAgent(agentId, targetTier, position) {
42
+ const tierRange = TIER_THRESHOLDS[targetTier];
43
+ // Target specific boundary score
44
+ const targetScore = position === 'low'
45
+ ? (tierRange.min + 10) / 1000 // Just inside lower bound
46
+ : (tierRange.max - 10) / 1000; // Just inside upper bound
47
+ const factorScores = ALL_FACTOR_CODES.map(code => {
48
+ // Very small variance to stay near boundary
49
+ const variance = (Math.random() - 0.5) * 0.02;
50
+ const score = Math.min(1.0, Math.max(0, targetScore + variance));
51
+ return {
52
+ code: code,
53
+ score,
54
+ timestamp: new Date(),
55
+ source: 'measured',
56
+ confidence: 0.9,
57
+ };
58
+ });
59
+ return {
60
+ id: agentId,
61
+ targetTier,
62
+ factorScores,
63
+ expectedScoreRange: tierRange,
64
+ };
65
+ }
66
+ function runTests() {
67
+ console.log('='.repeat(80));
68
+ console.log('BASIS TRUST FACTORS TEST SUITE');
69
+ console.log('Testing 100 agents across all trust tiers');
70
+ console.log('='.repeat(80));
71
+ console.log('');
72
+ // Print tier thresholds
73
+ console.log('TIER THRESHOLDS:');
74
+ console.log('-'.repeat(50));
75
+ Object.entries(TIER_THRESHOLDS).forEach(([tier, range]) => {
76
+ const tierNum = parseInt(tier);
77
+ console.log(` T${tierNum} ${getTierName(tierNum)}: ${range.min} - ${range.max}`);
78
+ });
79
+ console.log('');
80
+ const results = [];
81
+ let agentCounter = 0;
82
+ // Generate 100 test agents distributed across tiers
83
+ // T0: 12 agents, T1-T6: 13 agents each, T7: 10 agents
84
+ const tiersToTest = [
85
+ { tier: TrustTier.T0_SANDBOX, count: 12 },
86
+ { tier: TrustTier.T1_OBSERVED, count: 13 },
87
+ { tier: TrustTier.T2_PROVISIONAL, count: 13 },
88
+ { tier: TrustTier.T3_VERIFIED, count: 13 },
89
+ { tier: TrustTier.T4_OPERATIONAL, count: 13 },
90
+ { tier: TrustTier.T5_TRUSTED, count: 13 },
91
+ { tier: TrustTier.T6_CERTIFIED, count: 13 },
92
+ { tier: TrustTier.T7_AUTONOMOUS, count: 10 },
93
+ ];
94
+ for (const { tier, count } of tiersToTest) {
95
+ console.log(`\nTesting T${tier} ${getTierName(tier)} (${count} agents):`);
96
+ console.log('-'.repeat(60));
97
+ for (let i = 0; i < count; i++) {
98
+ agentCounter++;
99
+ const agentId = `AGENT-${agentCounter.toString().padStart(3, '0')}`;
100
+ // Mix of regular and boundary agents
101
+ const agent = i < 2
102
+ ? generateBoundaryAgent(agentId, tier, i === 0 ? 'low' : 'high')
103
+ : generateAgentForScoreRange(agentId, tier);
104
+ // Calculate trust score
105
+ const evaluation = calculateTrustScore(agent.factorScores, tier);
106
+ const actualTier = getTrustTierFromScore(evaluation.totalScore);
107
+ const passed = evaluation.totalScore >= agent.expectedScoreRange.min &&
108
+ evaluation.totalScore <= agent.expectedScoreRange.max;
109
+ const result = {
110
+ agentId,
111
+ targetTier: `T${tier} ${getTierName(tier)}`,
112
+ actualTier: `T${actualTier} ${getTierName(actualTier)}`,
113
+ score: evaluation.totalScore,
114
+ expectedRange: `${agent.expectedScoreRange.min}-${agent.expectedScoreRange.max}`,
115
+ passed,
116
+ compliant: evaluation.compliant,
117
+ criticalFailures: evaluation.belowThreshold.length,
118
+ };
119
+ results.push(result);
120
+ // Print result
121
+ const status = passed ? '✓' : '✗';
122
+ const complianceStatus = evaluation.compliant ? 'COMPLIANT' : `FAILED(${evaluation.belowThreshold.length})`;
123
+ console.log(` ${status} ${agentId}: Score=${evaluation.totalScore.toString().padStart(4)} ` +
124
+ `Target=${result.targetTier.padEnd(15)} Actual=${result.actualTier.padEnd(15)} ` +
125
+ `[${complianceStatus}]`);
126
+ }
127
+ }
128
+ // Summary
129
+ console.log('\n' + '='.repeat(80));
130
+ console.log('TEST SUMMARY');
131
+ console.log('='.repeat(80));
132
+ const passed = results.filter(r => r.passed).length;
133
+ const failed = results.filter(r => !r.passed).length;
134
+ const compliant = results.filter(r => r.compliant).length;
135
+ console.log(`\nTotal Agents Tested: ${results.length}`);
136
+ console.log(`Passed (in expected range): ${passed} (${((passed / results.length) * 100).toFixed(1)}%)`);
137
+ console.log(`Failed (outside range): ${failed} (${((failed / results.length) * 100).toFixed(1)}%)`);
138
+ console.log(`Compliant (met all critical factors): ${compliant} (${((compliant / results.length) * 100).toFixed(1)}%)`);
139
+ // Distribution by tier
140
+ console.log('\nDISTRIBUTION BY ACTUAL TIER:');
141
+ console.log('-'.repeat(40));
142
+ for (let t = 0; t <= 7; t++) {
143
+ const inTier = results.filter(r => r.actualTier.startsWith(`T${t}`)).length;
144
+ const bar = '█'.repeat(Math.round(inTier / 2));
145
+ console.log(` T${t} ${getTierName(t).padEnd(12)}: ${inTier.toString().padStart(3)} ${bar}`);
146
+ }
147
+ // Score distribution
148
+ console.log('\nSCORE DISTRIBUTION:');
149
+ console.log('-'.repeat(40));
150
+ const scoreRanges = [
151
+ { label: '0-199', min: 0, max: 199 },
152
+ { label: '200-349', min: 200, max: 349 },
153
+ { label: '350-499', min: 350, max: 499 },
154
+ { label: '500-649', min: 500, max: 649 },
155
+ { label: '650-799', min: 650, max: 799 },
156
+ { label: '800-875', min: 800, max: 875 },
157
+ { label: '876-949', min: 876, max: 949 },
158
+ { label: '950-1000', min: 950, max: 1000 },
159
+ ];
160
+ for (const range of scoreRanges) {
161
+ const count = results.filter(r => r.score >= range.min && r.score <= range.max).length;
162
+ const bar = '█'.repeat(Math.round(count / 2));
163
+ console.log(` ${range.label.padEnd(10)}: ${count.toString().padStart(3)} ${bar}`);
164
+ }
165
+ // Failed agents detail
166
+ if (failed > 0) {
167
+ console.log('\nFAILED AGENTS:');
168
+ console.log('-'.repeat(60));
169
+ results.filter(r => !r.passed).forEach(r => {
170
+ console.log(` ${r.agentId}: Score=${r.score} Expected=${r.expectedRange} Got=${r.actualTier}`);
171
+ });
172
+ }
173
+ console.log('\n' + '='.repeat(80));
174
+ console.log(failed === 0 ? 'ALL TESTS PASSED!' : `${failed} TESTS FAILED`);
175
+ console.log('='.repeat(80));
176
+ }
177
+ // Run tests
178
+ runTests();
179
+ //# sourceMappingURL=trust-factors.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-gate.d.ts","sourceRoot":"","sources":["../src/validation-gate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,468 @@
1
+ /**
2
+ * BASIS Validation Gate
3
+ *
4
+ * Central validation gate that verifies agent manifests before execution.
5
+ * Combines CAR parsing, schema validation, and capability matching.
6
+ *
7
+ * This gate returns PASS/REJECT decisions for the Kaizen pipeline.
8
+ */
9
+ import { z } from 'zod';
10
+ import { TrustTier, TIER_THRESHOLDS } from './trust-factors';
11
+ import { hasCapability } from './trust-capabilities';
12
+ // =============================================================================
13
+ // VALIDATION GATE TYPES
14
+ // =============================================================================
15
+ /**
16
+ * Gate decision - determines whether agent can proceed
17
+ */
18
+ export var GateDecision;
19
+ (function (GateDecision) {
20
+ /** Agent passes validation, proceed to Layer 2 */
21
+ GateDecision["PASS"] = "PASS";
22
+ /** Agent fails validation, block execution */
23
+ GateDecision["REJECT"] = "REJECT";
24
+ /** Agent requires human review before proceeding */
25
+ GateDecision["ESCALATE"] = "ESCALATE";
26
+ })(GateDecision || (GateDecision = {}));
27
+ /**
28
+ * Validation error severity levels
29
+ */
30
+ export var ValidationSeverity;
31
+ (function (ValidationSeverity) {
32
+ /** Informational - does not affect decision */
33
+ ValidationSeverity["INFO"] = "info";
34
+ /** Warning - may affect future decisions */
35
+ ValidationSeverity["WARNING"] = "warning";
36
+ /** Error - causes rejection */
37
+ ValidationSeverity["ERROR"] = "error";
38
+ /** Critical - immediate rejection with logging */
39
+ ValidationSeverity["CRITICAL"] = "critical";
40
+ })(ValidationSeverity || (ValidationSeverity = {}));
41
+ // =============================================================================
42
+ // ZOD SCHEMAS
43
+ // =============================================================================
44
+ export const validationIssueSchema = z.object({
45
+ code: z.string(),
46
+ message: z.string(),
47
+ severity: z.nativeEnum(ValidationSeverity),
48
+ path: z.string().optional(),
49
+ expected: z.string().optional(),
50
+ actual: z.string().optional(),
51
+ });
52
+ export const agentManifestSchema = z.object({
53
+ agentId: z.string().min(1),
54
+ organization: z.string().optional(),
55
+ agentClass: z.string().optional(),
56
+ domains: z.array(z.string()).optional(),
57
+ capabilityLevel: z.number().int().min(0).max(7).optional(),
58
+ version: z.string().optional(),
59
+ trustScore: z.number().min(0).max(1000).optional(),
60
+ requestedCapabilities: z.array(z.string()).optional(),
61
+ metadata: z.record(z.unknown()).optional(),
62
+ });
63
+ export const registeredProfileSchema = z.object({
64
+ agentId: z.string(),
65
+ organization: z.string(),
66
+ agentClass: z.string(),
67
+ approvedDomains: z.array(z.string()),
68
+ maxCapabilityLevel: z.number().int().min(0).max(7),
69
+ approvedCapabilities: z.array(z.string()),
70
+ trustScore: z.number().min(0).max(1000),
71
+ registeredAt: z.date(),
72
+ lastVerifiedAt: z.date().optional(),
73
+ });
74
+ export const validationGateResultSchema = z.object({
75
+ decision: z.nativeEnum(GateDecision),
76
+ valid: z.boolean(),
77
+ agentId: z.string(),
78
+ trustTier: z.nativeEnum(TrustTier).optional(),
79
+ trustScore: z.number().optional(),
80
+ issues: z.array(validationIssueSchema),
81
+ errors: z.array(validationIssueSchema),
82
+ warnings: z.array(validationIssueSchema),
83
+ validatedAt: z.date(),
84
+ durationMs: z.number(),
85
+ allowedCapabilities: z.array(z.string()).optional(),
86
+ deniedCapabilities: z.array(z.string()).optional(),
87
+ recommendations: z.array(z.string()).optional(),
88
+ });
89
+ // =============================================================================
90
+ // HELPER FUNCTIONS
91
+ // =============================================================================
92
+ /**
93
+ * Convert trust score to trust tier
94
+ */
95
+ export function scoreToTier(score) {
96
+ // Iterate through tiers in reverse order (highest first)
97
+ const tiers = [
98
+ TrustTier.T7_AUTONOMOUS,
99
+ TrustTier.T6_CERTIFIED,
100
+ TrustTier.T5_TRUSTED,
101
+ TrustTier.T4_OPERATIONAL,
102
+ TrustTier.T3_VERIFIED,
103
+ TrustTier.T2_PROVISIONAL,
104
+ TrustTier.T1_OBSERVED,
105
+ TrustTier.T0_SANDBOX,
106
+ ];
107
+ for (const tier of tiers) {
108
+ const thresholds = TIER_THRESHOLDS[tier];
109
+ if (score >= thresholds.min && score <= thresholds.max) {
110
+ return tier;
111
+ }
112
+ }
113
+ return TrustTier.T0_SANDBOX;
114
+ }
115
+ /**
116
+ * Validate CAR string format
117
+ */
118
+ function validateCARFormat(agentId) {
119
+ const issues = [];
120
+ // Handle undefined/empty agentId
121
+ if (!agentId) {
122
+ issues.push({
123
+ code: 'MISSING_AGENT_ID',
124
+ message: 'Agent ID is required',
125
+ severity: ValidationSeverity.ERROR,
126
+ path: 'agentId',
127
+ });
128
+ return issues;
129
+ }
130
+ // Basic CAR format: registry.org.class:DOMAINS-Ln@version
131
+ const carRegex = /^([a-z0-9]+)\.([a-z0-9-]+)\.([a-z0-9-]+):([A-Z]+)-L([0-7])@(\d+\.\d+\.\d+)(?:#[a-z0-9,_-]+)?$/;
132
+ if (!carRegex.test(agentId)) {
133
+ // Check if it looks like a legacy format or just an ID
134
+ if (agentId.includes(':') && agentId.includes('@')) {
135
+ issues.push({
136
+ code: 'INVALID_CAR_FORMAT',
137
+ message: 'CAR string format is invalid',
138
+ severity: ValidationSeverity.ERROR,
139
+ path: 'agentId',
140
+ expected: 'registry.org.class:DOMAINS-Ln@x.y.z',
141
+ actual: agentId,
142
+ });
143
+ }
144
+ else if (!agentId.includes('.')) {
145
+ // Simple ID format - acceptable but noted
146
+ issues.push({
147
+ code: 'SIMPLE_ID_FORMAT',
148
+ message: 'Agent uses simple ID format instead of full CAR string',
149
+ severity: ValidationSeverity.INFO,
150
+ path: 'agentId',
151
+ });
152
+ }
153
+ }
154
+ return issues;
155
+ }
156
+ /**
157
+ * Validate manifest against registered profile
158
+ */
159
+ function validateAgainstProfile(manifest, profile) {
160
+ const issues = [];
161
+ // Check organization match
162
+ if (manifest.organization && manifest.organization !== profile.organization) {
163
+ issues.push({
164
+ code: 'ORG_MISMATCH',
165
+ message: 'Organization does not match registered profile',
166
+ severity: ValidationSeverity.ERROR,
167
+ path: 'organization',
168
+ expected: profile.organization,
169
+ actual: manifest.organization,
170
+ });
171
+ }
172
+ // Check agent class match
173
+ if (manifest.agentClass && manifest.agentClass !== profile.agentClass) {
174
+ issues.push({
175
+ code: 'CLASS_MISMATCH',
176
+ message: 'Agent class does not match registered profile',
177
+ severity: ValidationSeverity.ERROR,
178
+ path: 'agentClass',
179
+ expected: profile.agentClass,
180
+ actual: manifest.agentClass,
181
+ });
182
+ }
183
+ // Check capability level
184
+ if (manifest.capabilityLevel !== undefined) {
185
+ if (manifest.capabilityLevel > profile.maxCapabilityLevel) {
186
+ issues.push({
187
+ code: 'CAPABILITY_LEVEL_EXCEEDED',
188
+ message: 'Claimed capability level exceeds registered maximum',
189
+ severity: ValidationSeverity.ERROR,
190
+ path: 'capabilityLevel',
191
+ expected: `<= ${profile.maxCapabilityLevel}`,
192
+ actual: String(manifest.capabilityLevel),
193
+ });
194
+ }
195
+ }
196
+ // Check domains
197
+ if (manifest.domains) {
198
+ const unauthorizedDomains = manifest.domains.filter((d) => !profile.approvedDomains.includes(d));
199
+ if (unauthorizedDomains.length > 0) {
200
+ issues.push({
201
+ code: 'UNAUTHORIZED_DOMAINS',
202
+ message: `Agent claims unauthorized domains: ${unauthorizedDomains.join(', ')}`,
203
+ severity: ValidationSeverity.ERROR,
204
+ path: 'domains',
205
+ expected: profile.approvedDomains.join(', '),
206
+ actual: manifest.domains.join(', '),
207
+ });
208
+ }
209
+ }
210
+ // Check requested capabilities
211
+ if (manifest.requestedCapabilities) {
212
+ const unauthorizedCaps = manifest.requestedCapabilities.filter((c) => !profile.approvedCapabilities.includes(c));
213
+ if (unauthorizedCaps.length > 0) {
214
+ issues.push({
215
+ code: 'UNAUTHORIZED_CAPABILITIES',
216
+ message: `Agent requests unauthorized capabilities: ${unauthorizedCaps.join(', ')}`,
217
+ severity: ValidationSeverity.WARNING,
218
+ path: 'requestedCapabilities',
219
+ });
220
+ }
221
+ }
222
+ return issues;
223
+ }
224
+ /**
225
+ * Validate trust tier requirements
226
+ */
227
+ function validateTrustTier(manifest, minimumTier) {
228
+ const issues = [];
229
+ if (manifest.trustScore === undefined) {
230
+ issues.push({
231
+ code: 'MISSING_TRUST_SCORE',
232
+ message: 'Agent manifest does not include trust score',
233
+ severity: ValidationSeverity.WARNING,
234
+ path: 'trustScore',
235
+ });
236
+ return issues;
237
+ }
238
+ const agentTier = scoreToTier(manifest.trustScore);
239
+ if (minimumTier !== undefined) {
240
+ // Compare numeric tier values directly (TrustTier is a numeric enum 0-7)
241
+ if (agentTier < minimumTier) {
242
+ issues.push({
243
+ code: 'INSUFFICIENT_TRUST_TIER',
244
+ message: `Agent trust tier T${agentTier} is below minimum required T${minimumTier}`,
245
+ severity: ValidationSeverity.ERROR,
246
+ path: 'trustScore',
247
+ expected: `>= T${minimumTier}`,
248
+ actual: `T${agentTier}`,
249
+ });
250
+ }
251
+ }
252
+ return issues;
253
+ }
254
+ /**
255
+ * Validate requested capabilities against trust tier
256
+ */
257
+ function validateCapabilitiesAgainstTier(manifest) {
258
+ const issues = [];
259
+ const allowed = [];
260
+ const denied = [];
261
+ if (!manifest.requestedCapabilities || manifest.requestedCapabilities.length === 0) {
262
+ return { issues, allowed, denied };
263
+ }
264
+ const trustScore = manifest.trustScore ?? 0;
265
+ const agentTier = scoreToTier(trustScore);
266
+ for (const capability of manifest.requestedCapabilities) {
267
+ if (hasCapability(agentTier, capability)) {
268
+ allowed.push(capability);
269
+ }
270
+ else {
271
+ denied.push(capability);
272
+ issues.push({
273
+ code: 'CAPABILITY_TIER_INSUFFICIENT',
274
+ message: `Capability ${capability} requires higher trust tier than ${agentTier}`,
275
+ severity: ValidationSeverity.WARNING,
276
+ path: 'requestedCapabilities',
277
+ actual: capability,
278
+ });
279
+ }
280
+ }
281
+ return { issues, allowed, denied };
282
+ }
283
+ // =============================================================================
284
+ // MAIN VALIDATION GATE
285
+ // =============================================================================
286
+ /**
287
+ * BASIS Validation Gate
288
+ *
289
+ * Validates an agent manifest and returns a PASS/REJECT/ESCALATE decision.
290
+ *
291
+ * @param manifest - Agent manifest to validate
292
+ * @param profile - Optional registered profile for comparison
293
+ * @param options - Validation options
294
+ * @returns Validation result with decision
295
+ *
296
+ * @example
297
+ * ```typescript
298
+ * const result = validateAgent({
299
+ * agentId: 'a3i.acme-corp.invoice-bot:ABF-L3@1.0.0',
300
+ * trustScore: 450,
301
+ * requestedCapabilities: ['CAP-DB-READ', 'CAP-WRITE-APPROVED'],
302
+ * });
303
+ *
304
+ * if (result.decision === GateDecision.PASS) {
305
+ * // Proceed to Layer 2 (INTENT)
306
+ * } else if (result.decision === GateDecision.REJECT) {
307
+ * // Block execution, log reasons
308
+ * console.log('Rejected:', result.errors);
309
+ * }
310
+ * ```
311
+ */
312
+ export function validateAgent(manifest, profile, options = {}) {
313
+ const startTime = Date.now();
314
+ const issues = [];
315
+ // 1. Validate manifest schema
316
+ const schemaResult = agentManifestSchema.safeParse(manifest);
317
+ if (!schemaResult.success) {
318
+ for (const error of schemaResult.error.errors) {
319
+ issues.push({
320
+ code: 'SCHEMA_VALIDATION_FAILED',
321
+ message: error.message,
322
+ severity: ValidationSeverity.ERROR,
323
+ path: error.path.join('.'),
324
+ });
325
+ }
326
+ }
327
+ // 2. Validate CAR format (handles undefined agentId)
328
+ const carIssues = validateCARFormat(manifest.agentId);
329
+ issues.push(...carIssues);
330
+ // If agentId is missing, short-circuit with early rejection
331
+ if (carIssues.some(i => i.code === 'MISSING_AGENT_ID')) {
332
+ return {
333
+ decision: GateDecision.REJECT,
334
+ valid: false,
335
+ agentId: manifest.agentId ?? 'unknown',
336
+ issues,
337
+ errors: issues.filter(i => i.severity === ValidationSeverity.ERROR || i.severity === ValidationSeverity.CRITICAL),
338
+ warnings: issues.filter(i => i.severity === ValidationSeverity.WARNING),
339
+ validatedAt: new Date(),
340
+ durationMs: Date.now() - startTime,
341
+ };
342
+ }
343
+ // 3. Validate against registered profile
344
+ if (profile) {
345
+ issues.push(...validateAgainstProfile(manifest, profile));
346
+ }
347
+ else if (options.requireRegisteredProfile) {
348
+ issues.push({
349
+ code: 'PROFILE_NOT_FOUND',
350
+ message: 'Agent must have a registered profile',
351
+ severity: ValidationSeverity.ERROR,
352
+ path: 'agentId',
353
+ });
354
+ }
355
+ // 4. Validate trust tier requirements
356
+ issues.push(...validateTrustTier(manifest, options.minimumTrustTier));
357
+ // 5. Validate required domains
358
+ if (options.requiredDomains && options.requiredDomains.length > 0) {
359
+ const agentDomains = manifest.domains || [];
360
+ const missingDomains = options.requiredDomains.filter((d) => !agentDomains.includes(d));
361
+ if (missingDomains.length > 0) {
362
+ issues.push({
363
+ code: 'MISSING_REQUIRED_DOMAINS',
364
+ message: `Agent missing required domains: ${missingDomains.join(', ')}`,
365
+ severity: ValidationSeverity.ERROR,
366
+ path: 'domains',
367
+ expected: options.requiredDomains.join(', '),
368
+ actual: agentDomains.join(', ') || 'none',
369
+ });
370
+ }
371
+ }
372
+ // 6. Validate capabilities against trust tier
373
+ const capValidation = validateCapabilitiesAgainstTier(manifest);
374
+ issues.push(...capValidation.issues);
375
+ // 7. Run custom validators
376
+ if (options.customValidators) {
377
+ for (const validator of options.customValidators) {
378
+ try {
379
+ issues.push(...validator(manifest, profile));
380
+ }
381
+ catch (e) {
382
+ issues.push({
383
+ code: 'CUSTOM_VALIDATOR_ERROR',
384
+ message: `Custom validator failed: ${e instanceof Error ? e.message : String(e)}`,
385
+ severity: ValidationSeverity.WARNING,
386
+ });
387
+ }
388
+ }
389
+ }
390
+ // Separate errors and warnings
391
+ const errors = issues.filter((i) => i.severity === ValidationSeverity.ERROR || i.severity === ValidationSeverity.CRITICAL);
392
+ const warnings = issues.filter((i) => i.severity === ValidationSeverity.WARNING);
393
+ // Determine decision
394
+ let decision;
395
+ let valid;
396
+ const hasCritical = issues.some((i) => i.severity === ValidationSeverity.CRITICAL);
397
+ const hasErrors = errors.length > 0;
398
+ const hasWarnings = warnings.length > 0;
399
+ if (hasCritical || hasErrors) {
400
+ decision = GateDecision.REJECT;
401
+ valid = false;
402
+ }
403
+ else if (options.strict && hasWarnings) {
404
+ decision = GateDecision.REJECT;
405
+ valid = false;
406
+ }
407
+ else if (!options.strict && hasWarnings && capValidation.denied.length > 0) {
408
+ // Agent wants capabilities they can't have - escalate for review
409
+ decision = options.allowCapabilityEscalation ? GateDecision.ESCALATE : GateDecision.REJECT;
410
+ valid = decision === GateDecision.ESCALATE;
411
+ }
412
+ else {
413
+ decision = GateDecision.PASS;
414
+ valid = true;
415
+ }
416
+ // Build recommendations
417
+ const recommendations = [];
418
+ if (capValidation.denied.length > 0) {
419
+ recommendations.push(`Increase trust score to access denied capabilities: ${capValidation.denied.join(', ')}`);
420
+ }
421
+ if (!profile && !options.requireRegisteredProfile) {
422
+ recommendations.push('Consider registering agent profile for enhanced validation');
423
+ }
424
+ // Calculate trust tier
425
+ const trustTier = manifest.trustScore !== undefined ? scoreToTier(manifest.trustScore) : undefined;
426
+ return {
427
+ decision,
428
+ valid,
429
+ agentId: manifest.agentId,
430
+ trustTier,
431
+ trustScore: manifest.trustScore,
432
+ issues,
433
+ errors,
434
+ warnings,
435
+ validatedAt: new Date(),
436
+ durationMs: Date.now() - startTime,
437
+ allowedCapabilities: capValidation.allowed.length > 0 ? capValidation.allowed : undefined,
438
+ deniedCapabilities: capValidation.denied.length > 0 ? capValidation.denied : undefined,
439
+ recommendations: recommendations.length > 0 ? recommendations : undefined,
440
+ };
441
+ }
442
+ /**
443
+ * Quick validation check - returns boolean
444
+ */
445
+ export function isValidAgent(manifest, profile, options) {
446
+ return validateAgent(manifest, profile, options).valid;
447
+ }
448
+ /**
449
+ * Create a validation gate with preset options
450
+ */
451
+ export function createValidationGate(defaultOptions) {
452
+ return {
453
+ validate: (manifest, profile, options) => validateAgent(manifest, profile, { ...defaultOptions, ...options }),
454
+ isValid: (manifest, profile, options) => isValidAgent(manifest, profile, { ...defaultOptions, ...options }),
455
+ };
456
+ }
457
+ /**
458
+ * Strict validation gate - treats warnings as errors
459
+ */
460
+ export const strictValidationGate = createValidationGate({ strict: true });
461
+ /**
462
+ * Production validation gate - requires registered profile
463
+ */
464
+ export const productionValidationGate = createValidationGate({
465
+ requireRegisteredProfile: true,
466
+ minimumTrustTier: TrustTier.T2_PROVISIONAL,
467
+ });
468
+ //# sourceMappingURL=validation-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-gate.test.d.ts","sourceRoot":"","sources":["../src/validation-gate.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}