@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,665 @@
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
+
10
+ import { z } from 'zod';
11
+ import { TrustTier, TIER_THRESHOLDS } from './trust-factors';
12
+ import { hasCapability, getCapabilitiesForTier, type Capability } from './trust-capabilities';
13
+
14
+ // =============================================================================
15
+ // VALIDATION GATE TYPES
16
+ // =============================================================================
17
+
18
+ /**
19
+ * Gate decision - determines whether agent can proceed
20
+ */
21
+ export enum GateDecision {
22
+ /** Agent passes validation, proceed to Layer 2 */
23
+ PASS = 'PASS',
24
+ /** Agent fails validation, block execution */
25
+ REJECT = 'REJECT',
26
+ /** Agent requires human review before proceeding */
27
+ ESCALATE = 'ESCALATE',
28
+ }
29
+
30
+ /**
31
+ * Validation error severity levels
32
+ */
33
+ export enum ValidationSeverity {
34
+ /** Informational - does not affect decision */
35
+ INFO = 'info',
36
+ /** Warning - may affect future decisions */
37
+ WARNING = 'warning',
38
+ /** Error - causes rejection */
39
+ ERROR = 'error',
40
+ /** Critical - immediate rejection with logging */
41
+ CRITICAL = 'critical',
42
+ }
43
+
44
+ /**
45
+ * A single validation issue
46
+ */
47
+ export interface ValidationIssue {
48
+ /** Unique code for this issue type */
49
+ code: string;
50
+ /** Human-readable message */
51
+ message: string;
52
+ /** Severity level */
53
+ severity: ValidationSeverity;
54
+ /** Field path that caused the issue */
55
+ path?: string;
56
+ /** Expected value or format */
57
+ expected?: string;
58
+ /** Actual value received */
59
+ actual?: string;
60
+ }
61
+
62
+ /**
63
+ * Result of validation gate check
64
+ */
65
+ export interface ValidationGateResult {
66
+ /** Gate decision: PASS, REJECT, or ESCALATE */
67
+ decision: GateDecision;
68
+ /** Whether validation passed */
69
+ valid: boolean;
70
+ /** Agent identifier (CAR string or ID) */
71
+ agentId: string;
72
+ /** Agent's current trust tier */
73
+ trustTier?: TrustTier;
74
+ /** Agent's trust score (0-1000) */
75
+ trustScore?: number;
76
+ /** List of validation issues found */
77
+ issues: ValidationIssue[];
78
+ /** Summary of errors (severity=error or critical) */
79
+ errors: ValidationIssue[];
80
+ /** Summary of warnings */
81
+ warnings: ValidationIssue[];
82
+ /** Timestamp of validation */
83
+ validatedAt: Date;
84
+ /** Duration of validation in milliseconds */
85
+ durationMs: number;
86
+ /** Capabilities the agent is allowed to use */
87
+ allowedCapabilities?: string[];
88
+ /** Capabilities that were requested but denied */
89
+ deniedCapabilities?: string[];
90
+ /** Recommendations for improving validation result */
91
+ recommendations?: string[];
92
+ }
93
+
94
+ /**
95
+ * Agent manifest for validation
96
+ */
97
+ export interface AgentManifest {
98
+ /** Agent identifier (CAR string format preferred) */
99
+ agentId: string;
100
+ /** Organization/owner of the agent */
101
+ organization?: string;
102
+ /** Agent classification/type */
103
+ agentClass?: string;
104
+ /** Capability domains the agent claims */
105
+ domains?: string[];
106
+ /** Capability level claimed (L0-L7) */
107
+ capabilityLevel?: number;
108
+ /** Version string */
109
+ version?: string;
110
+ /** Current trust score (0-1000) */
111
+ trustScore?: number;
112
+ /** Capabilities the agent claims to need */
113
+ requestedCapabilities?: string[];
114
+ /** Additional metadata */
115
+ metadata?: Record<string, unknown>;
116
+ }
117
+
118
+ /**
119
+ * Registered agent profile (from registry)
120
+ */
121
+ export interface RegisteredProfile {
122
+ /** Agent ID */
123
+ agentId: string;
124
+ /** Organization */
125
+ organization: string;
126
+ /** Agent class */
127
+ agentClass: string;
128
+ /** Approved domains */
129
+ approvedDomains: string[];
130
+ /** Maximum capability level */
131
+ maxCapabilityLevel: number;
132
+ /** Approved capabilities */
133
+ approvedCapabilities: string[];
134
+ /** Current trust score */
135
+ trustScore: number;
136
+ /** Registration date */
137
+ registeredAt: Date;
138
+ /** Last verification date */
139
+ lastVerifiedAt?: Date;
140
+ }
141
+
142
+ /**
143
+ * Options for validation gate
144
+ */
145
+ export interface ValidationGateOptions {
146
+ /** Strict mode - treat warnings as errors */
147
+ strict?: boolean;
148
+ /** Require registered profile match */
149
+ requireRegisteredProfile?: boolean;
150
+ /** Allow capability escalation request */
151
+ allowCapabilityEscalation?: boolean;
152
+ /** Custom domain requirements */
153
+ requiredDomains?: string[];
154
+ /** Minimum trust tier required */
155
+ minimumTrustTier?: TrustTier;
156
+ /** Custom validators to run */
157
+ customValidators?: CustomValidator[];
158
+ }
159
+
160
+ /**
161
+ * Custom validator function
162
+ */
163
+ export type CustomValidator = (
164
+ manifest: AgentManifest,
165
+ profile?: RegisteredProfile
166
+ ) => ValidationIssue[];
167
+
168
+ // =============================================================================
169
+ // ZOD SCHEMAS
170
+ // =============================================================================
171
+
172
+ export const validationIssueSchema = z.object({
173
+ code: z.string(),
174
+ message: z.string(),
175
+ severity: z.nativeEnum(ValidationSeverity),
176
+ path: z.string().optional(),
177
+ expected: z.string().optional(),
178
+ actual: z.string().optional(),
179
+ });
180
+
181
+ export const agentManifestSchema = z.object({
182
+ agentId: z.string().min(1),
183
+ organization: z.string().optional(),
184
+ agentClass: z.string().optional(),
185
+ domains: z.array(z.string()).optional(),
186
+ capabilityLevel: z.number().int().min(0).max(7).optional(),
187
+ version: z.string().optional(),
188
+ trustScore: z.number().min(0).max(1000).optional(),
189
+ requestedCapabilities: z.array(z.string()).optional(),
190
+ metadata: z.record(z.unknown()).optional(),
191
+ });
192
+
193
+ export const registeredProfileSchema = z.object({
194
+ agentId: z.string(),
195
+ organization: z.string(),
196
+ agentClass: z.string(),
197
+ approvedDomains: z.array(z.string()),
198
+ maxCapabilityLevel: z.number().int().min(0).max(7),
199
+ approvedCapabilities: z.array(z.string()),
200
+ trustScore: z.number().min(0).max(1000),
201
+ registeredAt: z.date(),
202
+ lastVerifiedAt: z.date().optional(),
203
+ });
204
+
205
+ export const validationGateResultSchema = z.object({
206
+ decision: z.nativeEnum(GateDecision),
207
+ valid: z.boolean(),
208
+ agentId: z.string(),
209
+ trustTier: z.nativeEnum(TrustTier).optional(),
210
+ trustScore: z.number().optional(),
211
+ issues: z.array(validationIssueSchema),
212
+ errors: z.array(validationIssueSchema),
213
+ warnings: z.array(validationIssueSchema),
214
+ validatedAt: z.date(),
215
+ durationMs: z.number(),
216
+ allowedCapabilities: z.array(z.string()).optional(),
217
+ deniedCapabilities: z.array(z.string()).optional(),
218
+ recommendations: z.array(z.string()).optional(),
219
+ });
220
+
221
+ // =============================================================================
222
+ // HELPER FUNCTIONS
223
+ // =============================================================================
224
+
225
+ /**
226
+ * Convert trust score to trust tier
227
+ */
228
+ export function scoreToTier(score: number): TrustTier {
229
+ // Iterate through tiers in reverse order (highest first)
230
+ const tiers = [
231
+ TrustTier.T7_AUTONOMOUS,
232
+ TrustTier.T6_CERTIFIED,
233
+ TrustTier.T5_TRUSTED,
234
+ TrustTier.T4_OPERATIONAL,
235
+ TrustTier.T3_VERIFIED,
236
+ TrustTier.T2_PROVISIONAL,
237
+ TrustTier.T1_OBSERVED,
238
+ TrustTier.T0_SANDBOX,
239
+ ];
240
+
241
+ for (const tier of tiers) {
242
+ const thresholds = TIER_THRESHOLDS[tier];
243
+ if (score >= thresholds.min && score <= thresholds.max) {
244
+ return tier;
245
+ }
246
+ }
247
+ return TrustTier.T0_SANDBOX;
248
+ }
249
+
250
+ /**
251
+ * Validate CAR string format
252
+ */
253
+ function validateCARFormat(agentId: string | undefined): ValidationIssue[] {
254
+ const issues: ValidationIssue[] = [];
255
+
256
+ // Handle undefined/empty agentId
257
+ if (!agentId) {
258
+ issues.push({
259
+ code: 'MISSING_AGENT_ID',
260
+ message: 'Agent ID is required',
261
+ severity: ValidationSeverity.ERROR,
262
+ path: 'agentId',
263
+ });
264
+ return issues;
265
+ }
266
+
267
+ // Basic CAR format: registry.org.class:DOMAINS-Ln@version
268
+ const carRegex = /^([a-z0-9]+)\.([a-z0-9-]+)\.([a-z0-9-]+):([A-Z]+)-L([0-7])@(\d+\.\d+\.\d+)(?:#[a-z0-9,_-]+)?$/;
269
+
270
+ if (!carRegex.test(agentId)) {
271
+ // Check if it looks like a legacy format or just an ID
272
+ if (agentId.includes(':') && agentId.includes('@')) {
273
+ issues.push({
274
+ code: 'INVALID_CAR_FORMAT',
275
+ message: 'CAR string format is invalid',
276
+ severity: ValidationSeverity.ERROR,
277
+ path: 'agentId',
278
+ expected: 'registry.org.class:DOMAINS-Ln@x.y.z',
279
+ actual: agentId,
280
+ });
281
+ } else if (!agentId.includes('.')) {
282
+ // Simple ID format - acceptable but noted
283
+ issues.push({
284
+ code: 'SIMPLE_ID_FORMAT',
285
+ message: 'Agent uses simple ID format instead of full CAR string',
286
+ severity: ValidationSeverity.INFO,
287
+ path: 'agentId',
288
+ });
289
+ }
290
+ }
291
+
292
+ return issues;
293
+ }
294
+
295
+ /**
296
+ * Validate manifest against registered profile
297
+ */
298
+ function validateAgainstProfile(
299
+ manifest: AgentManifest,
300
+ profile: RegisteredProfile
301
+ ): ValidationIssue[] {
302
+ const issues: ValidationIssue[] = [];
303
+
304
+ // Check organization match
305
+ if (manifest.organization && manifest.organization !== profile.organization) {
306
+ issues.push({
307
+ code: 'ORG_MISMATCH',
308
+ message: 'Organization does not match registered profile',
309
+ severity: ValidationSeverity.ERROR,
310
+ path: 'organization',
311
+ expected: profile.organization,
312
+ actual: manifest.organization,
313
+ });
314
+ }
315
+
316
+ // Check agent class match
317
+ if (manifest.agentClass && manifest.agentClass !== profile.agentClass) {
318
+ issues.push({
319
+ code: 'CLASS_MISMATCH',
320
+ message: 'Agent class does not match registered profile',
321
+ severity: ValidationSeverity.ERROR,
322
+ path: 'agentClass',
323
+ expected: profile.agentClass,
324
+ actual: manifest.agentClass,
325
+ });
326
+ }
327
+
328
+ // Check capability level
329
+ if (manifest.capabilityLevel !== undefined) {
330
+ if (manifest.capabilityLevel > profile.maxCapabilityLevel) {
331
+ issues.push({
332
+ code: 'CAPABILITY_LEVEL_EXCEEDED',
333
+ message: 'Claimed capability level exceeds registered maximum',
334
+ severity: ValidationSeverity.ERROR,
335
+ path: 'capabilityLevel',
336
+ expected: `<= ${profile.maxCapabilityLevel}`,
337
+ actual: String(manifest.capabilityLevel),
338
+ });
339
+ }
340
+ }
341
+
342
+ // Check domains
343
+ if (manifest.domains) {
344
+ const unauthorizedDomains = manifest.domains.filter(
345
+ (d) => !profile.approvedDomains.includes(d)
346
+ );
347
+ if (unauthorizedDomains.length > 0) {
348
+ issues.push({
349
+ code: 'UNAUTHORIZED_DOMAINS',
350
+ message: `Agent claims unauthorized domains: ${unauthorizedDomains.join(', ')}`,
351
+ severity: ValidationSeverity.ERROR,
352
+ path: 'domains',
353
+ expected: profile.approvedDomains.join(', '),
354
+ actual: manifest.domains.join(', '),
355
+ });
356
+ }
357
+ }
358
+
359
+ // Check requested capabilities
360
+ if (manifest.requestedCapabilities) {
361
+ const unauthorizedCaps = manifest.requestedCapabilities.filter(
362
+ (c) => !profile.approvedCapabilities.includes(c)
363
+ );
364
+ if (unauthorizedCaps.length > 0) {
365
+ issues.push({
366
+ code: 'UNAUTHORIZED_CAPABILITIES',
367
+ message: `Agent requests unauthorized capabilities: ${unauthorizedCaps.join(', ')}`,
368
+ severity: ValidationSeverity.WARNING,
369
+ path: 'requestedCapabilities',
370
+ });
371
+ }
372
+ }
373
+
374
+ return issues;
375
+ }
376
+
377
+ /**
378
+ * Validate trust tier requirements
379
+ */
380
+ function validateTrustTier(
381
+ manifest: AgentManifest,
382
+ minimumTier?: TrustTier
383
+ ): ValidationIssue[] {
384
+ const issues: ValidationIssue[] = [];
385
+
386
+ if (manifest.trustScore === undefined) {
387
+ issues.push({
388
+ code: 'MISSING_TRUST_SCORE',
389
+ message: 'Agent manifest does not include trust score',
390
+ severity: ValidationSeverity.WARNING,
391
+ path: 'trustScore',
392
+ });
393
+ return issues;
394
+ }
395
+
396
+ const agentTier = scoreToTier(manifest.trustScore);
397
+
398
+ if (minimumTier !== undefined) {
399
+ // Compare numeric tier values directly (TrustTier is a numeric enum 0-7)
400
+ if (agentTier < minimumTier) {
401
+ issues.push({
402
+ code: 'INSUFFICIENT_TRUST_TIER',
403
+ message: `Agent trust tier T${agentTier} is below minimum required T${minimumTier}`,
404
+ severity: ValidationSeverity.ERROR,
405
+ path: 'trustScore',
406
+ expected: `>= T${minimumTier}`,
407
+ actual: `T${agentTier}`,
408
+ });
409
+ }
410
+ }
411
+
412
+ return issues;
413
+ }
414
+
415
+ /**
416
+ * Validate requested capabilities against trust tier
417
+ */
418
+ function validateCapabilitiesAgainstTier(
419
+ manifest: AgentManifest
420
+ ): { issues: ValidationIssue[]; allowed: string[]; denied: string[] } {
421
+ const issues: ValidationIssue[] = [];
422
+ const allowed: string[] = [];
423
+ const denied: string[] = [];
424
+
425
+ if (!manifest.requestedCapabilities || manifest.requestedCapabilities.length === 0) {
426
+ return { issues, allowed, denied };
427
+ }
428
+
429
+ const trustScore = manifest.trustScore ?? 0;
430
+ const agentTier = scoreToTier(trustScore);
431
+
432
+ for (const capability of manifest.requestedCapabilities) {
433
+ if (hasCapability(agentTier, capability)) {
434
+ allowed.push(capability);
435
+ } else {
436
+ denied.push(capability);
437
+ issues.push({
438
+ code: 'CAPABILITY_TIER_INSUFFICIENT',
439
+ message: `Capability ${capability} requires higher trust tier than ${agentTier}`,
440
+ severity: ValidationSeverity.WARNING,
441
+ path: 'requestedCapabilities',
442
+ actual: capability,
443
+ });
444
+ }
445
+ }
446
+
447
+ return { issues, allowed, denied };
448
+ }
449
+
450
+ // =============================================================================
451
+ // MAIN VALIDATION GATE
452
+ // =============================================================================
453
+
454
+ /**
455
+ * BASIS Validation Gate
456
+ *
457
+ * Validates an agent manifest and returns a PASS/REJECT/ESCALATE decision.
458
+ *
459
+ * @param manifest - Agent manifest to validate
460
+ * @param profile - Optional registered profile for comparison
461
+ * @param options - Validation options
462
+ * @returns Validation result with decision
463
+ *
464
+ * @example
465
+ * ```typescript
466
+ * const result = validateAgent({
467
+ * agentId: 'a3i.acme-corp.invoice-bot:ABF-L3@1.0.0',
468
+ * trustScore: 450,
469
+ * requestedCapabilities: ['CAP-DB-READ', 'CAP-WRITE-APPROVED'],
470
+ * });
471
+ *
472
+ * if (result.decision === GateDecision.PASS) {
473
+ * // Proceed to Layer 2 (INTENT)
474
+ * } else if (result.decision === GateDecision.REJECT) {
475
+ * // Block execution, log reasons
476
+ * console.log('Rejected:', result.errors);
477
+ * }
478
+ * ```
479
+ */
480
+ export function validateAgent(
481
+ manifest: AgentManifest,
482
+ profile?: RegisteredProfile,
483
+ options: ValidationGateOptions = {}
484
+ ): ValidationGateResult {
485
+ const startTime = Date.now();
486
+ const issues: ValidationIssue[] = [];
487
+
488
+ // 1. Validate manifest schema
489
+ const schemaResult = agentManifestSchema.safeParse(manifest);
490
+ if (!schemaResult.success) {
491
+ for (const error of schemaResult.error.errors) {
492
+ issues.push({
493
+ code: 'SCHEMA_VALIDATION_FAILED',
494
+ message: error.message,
495
+ severity: ValidationSeverity.ERROR,
496
+ path: error.path.join('.'),
497
+ });
498
+ }
499
+ }
500
+
501
+ // 2. Validate CAR format (handles undefined agentId)
502
+ const carIssues = validateCARFormat(manifest.agentId);
503
+ issues.push(...carIssues);
504
+
505
+ // If agentId is missing, short-circuit with early rejection
506
+ if (carIssues.some(i => i.code === 'MISSING_AGENT_ID')) {
507
+ return {
508
+ decision: GateDecision.REJECT,
509
+ valid: false,
510
+ agentId: manifest.agentId ?? 'unknown',
511
+ issues,
512
+ errors: issues.filter(i => i.severity === ValidationSeverity.ERROR || i.severity === ValidationSeverity.CRITICAL),
513
+ warnings: issues.filter(i => i.severity === ValidationSeverity.WARNING),
514
+ validatedAt: new Date(),
515
+ durationMs: Date.now() - startTime,
516
+ };
517
+ }
518
+
519
+ // 3. Validate against registered profile
520
+ if (profile) {
521
+ issues.push(...validateAgainstProfile(manifest, profile));
522
+ } else if (options.requireRegisteredProfile) {
523
+ issues.push({
524
+ code: 'PROFILE_NOT_FOUND',
525
+ message: 'Agent must have a registered profile',
526
+ severity: ValidationSeverity.ERROR,
527
+ path: 'agentId',
528
+ });
529
+ }
530
+
531
+ // 4. Validate trust tier requirements
532
+ issues.push(...validateTrustTier(manifest, options.minimumTrustTier));
533
+
534
+ // 5. Validate required domains
535
+ if (options.requiredDomains && options.requiredDomains.length > 0) {
536
+ const agentDomains = manifest.domains || [];
537
+ const missingDomains = options.requiredDomains.filter(
538
+ (d) => !agentDomains.includes(d)
539
+ );
540
+ if (missingDomains.length > 0) {
541
+ issues.push({
542
+ code: 'MISSING_REQUIRED_DOMAINS',
543
+ message: `Agent missing required domains: ${missingDomains.join(', ')}`,
544
+ severity: ValidationSeverity.ERROR,
545
+ path: 'domains',
546
+ expected: options.requiredDomains.join(', '),
547
+ actual: agentDomains.join(', ') || 'none',
548
+ });
549
+ }
550
+ }
551
+
552
+ // 6. Validate capabilities against trust tier
553
+ const capValidation = validateCapabilitiesAgainstTier(manifest);
554
+ issues.push(...capValidation.issues);
555
+
556
+ // 7. Run custom validators
557
+ if (options.customValidators) {
558
+ for (const validator of options.customValidators) {
559
+ try {
560
+ issues.push(...validator(manifest, profile));
561
+ } catch (e) {
562
+ issues.push({
563
+ code: 'CUSTOM_VALIDATOR_ERROR',
564
+ message: `Custom validator failed: ${e instanceof Error ? e.message : String(e)}`,
565
+ severity: ValidationSeverity.WARNING,
566
+ });
567
+ }
568
+ }
569
+ }
570
+
571
+ // Separate errors and warnings
572
+ const errors = issues.filter(
573
+ (i) => i.severity === ValidationSeverity.ERROR || i.severity === ValidationSeverity.CRITICAL
574
+ );
575
+ const warnings = issues.filter((i) => i.severity === ValidationSeverity.WARNING);
576
+
577
+ // Determine decision
578
+ let decision: GateDecision;
579
+ let valid: boolean;
580
+
581
+ const hasCritical = issues.some((i) => i.severity === ValidationSeverity.CRITICAL);
582
+ const hasErrors = errors.length > 0;
583
+ const hasWarnings = warnings.length > 0;
584
+
585
+ if (hasCritical || hasErrors) {
586
+ decision = GateDecision.REJECT;
587
+ valid = false;
588
+ } else if (options.strict && hasWarnings) {
589
+ decision = GateDecision.REJECT;
590
+ valid = false;
591
+ } else if (!options.strict && hasWarnings && capValidation.denied.length > 0) {
592
+ // Agent wants capabilities they can't have - escalate for review
593
+ decision = options.allowCapabilityEscalation ? GateDecision.ESCALATE : GateDecision.REJECT;
594
+ valid = decision === GateDecision.ESCALATE;
595
+ } else {
596
+ decision = GateDecision.PASS;
597
+ valid = true;
598
+ }
599
+
600
+ // Build recommendations
601
+ const recommendations: string[] = [];
602
+ if (capValidation.denied.length > 0) {
603
+ recommendations.push(
604
+ `Increase trust score to access denied capabilities: ${capValidation.denied.join(', ')}`
605
+ );
606
+ }
607
+ if (!profile && !options.requireRegisteredProfile) {
608
+ recommendations.push('Consider registering agent profile for enhanced validation');
609
+ }
610
+
611
+ // Calculate trust tier
612
+ const trustTier = manifest.trustScore !== undefined ? scoreToTier(manifest.trustScore) : undefined;
613
+
614
+ return {
615
+ decision,
616
+ valid,
617
+ agentId: manifest.agentId,
618
+ trustTier,
619
+ trustScore: manifest.trustScore,
620
+ issues,
621
+ errors,
622
+ warnings,
623
+ validatedAt: new Date(),
624
+ durationMs: Date.now() - startTime,
625
+ allowedCapabilities: capValidation.allowed.length > 0 ? capValidation.allowed : undefined,
626
+ deniedCapabilities: capValidation.denied.length > 0 ? capValidation.denied : undefined,
627
+ recommendations: recommendations.length > 0 ? recommendations : undefined,
628
+ };
629
+ }
630
+
631
+ /**
632
+ * Quick validation check - returns boolean
633
+ */
634
+ export function isValidAgent(
635
+ manifest: AgentManifest,
636
+ profile?: RegisteredProfile,
637
+ options?: ValidationGateOptions
638
+ ): boolean {
639
+ return validateAgent(manifest, profile, options).valid;
640
+ }
641
+
642
+ /**
643
+ * Create a validation gate with preset options
644
+ */
645
+ export function createValidationGate(defaultOptions: ValidationGateOptions) {
646
+ return {
647
+ validate: (manifest: AgentManifest, profile?: RegisteredProfile, options?: ValidationGateOptions) =>
648
+ validateAgent(manifest, profile, { ...defaultOptions, ...options }),
649
+ isValid: (manifest: AgentManifest, profile?: RegisteredProfile, options?: ValidationGateOptions) =>
650
+ isValidAgent(manifest, profile, { ...defaultOptions, ...options }),
651
+ };
652
+ }
653
+
654
+ /**
655
+ * Strict validation gate - treats warnings as errors
656
+ */
657
+ export const strictValidationGate = createValidationGate({ strict: true });
658
+
659
+ /**
660
+ * Production validation gate - requires registered profile
661
+ */
662
+ export const productionValidationGate = createValidationGate({
663
+ requireRegisteredProfile: true,
664
+ minimumTrustTier: TrustTier.T2_PROVISIONAL,
665
+ });