@svsprotocol/solana 0.1.0

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 (38) hide show
  1. package/LICENSE +158 -0
  2. package/README.md +365 -0
  3. package/dist/action-production-proof-evidence.js +553 -0
  4. package/dist/adapter-catalog.d.ts +29 -0
  5. package/dist/adapter-catalog.js +146 -0
  6. package/dist/adapter-core.d.ts +48 -0
  7. package/dist/adapter-core.js +249 -0
  8. package/dist/approval-signature.js +197 -0
  9. package/dist/base58.js +69 -0
  10. package/dist/bot-auth.js +50 -0
  11. package/dist/bot-certification-evidence.js +342 -0
  12. package/dist/bot-first-action-runbook.js +299 -0
  13. package/dist/bot-integration-contract.js +41 -0
  14. package/dist/certified-submit-status.js +176 -0
  15. package/dist/common.d.ts +1135 -0
  16. package/dist/elizaos.d.ts +43 -0
  17. package/dist/elizaos.js +227 -0
  18. package/dist/goat.d.ts +47 -0
  19. package/dist/goat.js +261 -0
  20. package/dist/index.d.ts +330 -0
  21. package/dist/index.js +128 -0
  22. package/dist/protocol.d.ts +205 -0
  23. package/dist/protocol.js +900 -0
  24. package/dist/receipt.js +51 -0
  25. package/dist/signed-proof-read-protection.js +495 -0
  26. package/dist/solana-agent-kit.d.ts +35 -0
  27. package/dist/solana-agent-kit.js +151 -0
  28. package/dist/svs-client.js +1232 -0
  29. package/dist/vercel-ai.d.ts +47 -0
  30. package/dist/vercel-ai.js +266 -0
  31. package/dist/verified-agent-adoption-kit.js +471 -0
  32. package/dist/verified-agent-profile.js +329 -0
  33. package/dist/verified-agent-registry-consumer.js +421 -0
  34. package/dist/verified-agent-registry.d.ts +36 -0
  35. package/dist/verified-agent-registry.js +826 -0
  36. package/dist/verified-agent-trust-score.js +335 -0
  37. package/dist/webhooks.js +834 -0
  38. package/package.json +72 -0
@@ -0,0 +1,900 @@
1
+ import {
2
+ ACTION_PRODUCTION_PROOF_EVIDENCE_VERSION,
3
+ APPROVAL_MESSAGE_DOMAIN,
4
+ LEGACY_APPROVAL_MESSAGE_DOMAIN,
5
+ VERIFIED_AGENT_TRUST_SCORE_HIGH_TRUST_MIN,
6
+ productionCertificationIsReady,
7
+ summarizeApprovalDomain,
8
+ SolanaVerificationClient,
9
+ verifyActionProductionProofEvidence,
10
+ verifyVerifiedAgentRegistryUrl
11
+ } from "./index.js";
12
+ import { hashObject } from "./receipt.js";
13
+
14
+ export const VERIFIED_AGENT_REQUIREMENT_VERSION = "svs.verified-agent-requirement.v1";
15
+ export const CURRENT_APPROVAL_DOMAIN_REQUIREMENT_VERSION = "svs.current-approval-domain-requirement.v1";
16
+ export const HOSTED_VERIFIED_AGENT_REGISTRY_REQUIREMENT_VERSION = "svs.hosted-verified-agent-registry-requirement.v1";
17
+ export const VERIFIED_AGENT_STANDARD_CONFORMANCE_FIXTURES_VERSION = "svs.verified-agent-standard-conformance-fixtures.v1";
18
+ export const VERIFIED_AGENT_STANDARD_CONFORMANCE_VERSION = "svs.verified-agent-standard-conformance.v1";
19
+ export const HOSTED_VERIFIED_AGENT_TRUST_POLICY_STANDARD = "standard";
20
+ export const HOSTED_VERIFIED_AGENT_TRUST_POLICY_HIGH_TRUST = "high-trust";
21
+ export const HOSTED_VERIFIED_AGENT_TRUST_POLICY_CUSTOM = "custom";
22
+ export const HOSTED_VERIFIED_AGENT_TRUST_POLICY_VALUES = [
23
+ HOSTED_VERIFIED_AGENT_TRUST_POLICY_STANDARD,
24
+ HOSTED_VERIFIED_AGENT_TRUST_POLICY_HIGH_TRUST,
25
+ HOSTED_VERIFIED_AGENT_TRUST_POLICY_CUSTOM
26
+ ];
27
+
28
+ export async function requireVerifiedAgent({
29
+ client = null,
30
+ baseUrl,
31
+ apiKey,
32
+ requestSigningSecret,
33
+ botId,
34
+ agentWallet = null,
35
+ action = null,
36
+ minCertification = "production_verified",
37
+ staleAfterMs = undefined,
38
+ requireCurrentIntegrationContract = true
39
+ } = {}) {
40
+ if (!botId) {
41
+ throw new Error("botId is required.");
42
+ }
43
+
44
+ const svs = client ?? new SolanaVerificationClient({
45
+ baseUrl,
46
+ apiKey,
47
+ requestSigningSecret
48
+ });
49
+ const certification = await svs.requireProductionCertification({
50
+ botId,
51
+ staleAfterMs,
52
+ requireCurrentIntegrationContract
53
+ });
54
+ const ok = productionCertificationIsReady(certification);
55
+
56
+ if (!ok) {
57
+ throw new Error(`SVS verified agent requirement failed for ${botId}.`);
58
+ }
59
+
60
+ return {
61
+ version: VERIFIED_AGENT_REQUIREMENT_VERSION,
62
+ ok: true,
63
+ status: "verified",
64
+ minCertification,
65
+ botId,
66
+ agentWallet,
67
+ action,
68
+ certificationHash: certification.certification?.certificationHash ?? null,
69
+ recordId: certification.certification?.recordId ?? null,
70
+ qualityTarget: certification.qualityTarget ?? null,
71
+ integrationContract: certification.integrationContract ?? null,
72
+ proofs: certification.proofs ?? null,
73
+ nextAction: {
74
+ code: "none",
75
+ message: "Agent satisfies SVS production certification requirements."
76
+ }
77
+ };
78
+ }
79
+
80
+ export function requireCurrentApprovalDomain(proofEvidenceOrHumanApproval, {
81
+ action = null
82
+ } = {}) {
83
+ const humanApproval = proofEvidenceOrHumanApproval?.humanApproval ?? proofEvidenceOrHumanApproval;
84
+ const domain = summarizeApprovalDomain(humanApproval);
85
+ const status = humanApproval?.domainStatus ?? domain.status;
86
+ const current = domain.domain === APPROVAL_MESSAGE_DOMAIN && status === "current";
87
+
88
+ if (!current) {
89
+ const error = new Error(`SVS approval domain is not current: ${status}.`);
90
+ error.name = "SvsCurrentApprovalDomainError";
91
+ error.details = {
92
+ version: CURRENT_APPROVAL_DOMAIN_REQUIREMENT_VERSION,
93
+ ok: false,
94
+ status,
95
+ domain: domain.domain,
96
+ expectedDomain: APPROVAL_MESSAGE_DOMAIN,
97
+ action,
98
+ nextAction: {
99
+ code: status === "legacy_compatible"
100
+ ? "approval_domain_legacy_compatible"
101
+ : "approval_domain_not_current",
102
+ message: status === "legacy_compatible"
103
+ ? "This proof uses the legacy approval domain. Keep it for historical audit compatibility, but require current-domain proofs for new production bot actions."
104
+ : "Require a current SVS approval-domain proof before accepting this bot action."
105
+ }
106
+ };
107
+ throw error;
108
+ }
109
+
110
+ return {
111
+ version: CURRENT_APPROVAL_DOMAIN_REQUIREMENT_VERSION,
112
+ ok: true,
113
+ status: "current",
114
+ domain: domain.domain,
115
+ expectedDomain: APPROVAL_MESSAGE_DOMAIN,
116
+ action,
117
+ nextAction: {
118
+ code: "none",
119
+ message: "SVS approval domain is current."
120
+ }
121
+ };
122
+ }
123
+
124
+ export async function requireHostedVerifiedAgentRegistry({
125
+ registryUrl,
126
+ trustManifestUrl = null,
127
+ expectedRegistryHash,
128
+ botId,
129
+ requireVerified = true,
130
+ trustPolicy = null,
131
+ requireHighTrustScore = false,
132
+ minimumTrustScore = null,
133
+ requireTrustScoreEvidenceComplete = null,
134
+ maxTrustScoreBlockingSignals = null,
135
+ staleAfterMs = null,
136
+ now = new Date(),
137
+ fetchImpl = globalThis.fetch
138
+ } = {}) {
139
+ if (!botId) {
140
+ throw new Error("botId is required.");
141
+ }
142
+
143
+ const resolvedTrustPolicy = resolveHostedTrustScorePolicyOptions({
144
+ trustPolicy,
145
+ requireHighTrustScore,
146
+ minimumTrustScore,
147
+ requireTrustScoreEvidenceComplete,
148
+ maxTrustScoreBlockingSignals
149
+ });
150
+ const verification = await verifyVerifiedAgentRegistryUrl({
151
+ registryUrl,
152
+ trustManifestUrl,
153
+ expectedRegistryHash,
154
+ requireVerified,
155
+ staleAfterMs,
156
+ now,
157
+ fetchImpl
158
+ });
159
+ const agent = verification.agents?.find((item) => item.botId === botId) ?? null;
160
+ const trustScorePolicy = evaluateHostedTrustScorePolicy(agent?.trustScore, resolvedTrustPolicy);
161
+ const ok = verification.ok === true && agent?.ok === true && trustScorePolicy.ok === true;
162
+
163
+ if (!ok) {
164
+ const firstFailure = trustScorePolicy.ok === false
165
+ ? {
166
+ name: "Hosted registry trust score policy satisfied",
167
+ ok: false,
168
+ detail: trustScorePolicy.detail
169
+ }
170
+ : agent?.failedChecks?.[0] ?? verification.failedChecks?.[0];
171
+ const error = new Error(
172
+ `SVS hosted verified-agent registry requirement failed for ${botId}: ${firstFailure?.name ?? verification.status ?? "failed"}.`
173
+ );
174
+ error.name = "SvsHostedVerifiedAgentRegistryError";
175
+ error.details = {
176
+ version: HOSTED_VERIFIED_AGENT_REGISTRY_REQUIREMENT_VERSION,
177
+ ok: false,
178
+ status: trustScorePolicy.ok === false
179
+ ? "trust_score_policy_failed"
180
+ : verification.status === "verified"
181
+ ? "agent_not_verified"
182
+ : verification.status,
183
+ botId,
184
+ registryUrl,
185
+ trustManifestUrl: verification.trustManifestUrl ?? trustManifestUrl ?? null,
186
+ expectedRegistryHash,
187
+ registryHash: verification.registryHash ?? null,
188
+ trustManifest: verification.trustManifest ?? null,
189
+ trustScorePolicy,
190
+ failedCheckCount: verification.failedCheckCount ?? null,
191
+ firstFailure: firstFailure ?? null,
192
+ agent: agent ? summarizeRegistryAgentForRequirement(agent) : null,
193
+ nextAction: {
194
+ code: trustScorePolicy.ok === false
195
+ ? "raise_hosted_verified_agent_trust_score"
196
+ : agent
197
+ ? "fix_hosted_verified_agent_registry"
198
+ : "publish_verified_agent_to_registry",
199
+ message: trustScorePolicy.ok === false
200
+ ? "Refresh or strengthen SVS proof evidence until the hosted registry trust-score policy passes."
201
+ : agent
202
+ ? "Fix the hosted SVS registry, trust manifest, or linked profile before accepting this agent."
203
+ : "Publish this bot to the hosted SVS verified-agent registry before accepting it."
204
+ }
205
+ };
206
+ throw error;
207
+ }
208
+
209
+ return {
210
+ version: HOSTED_VERIFIED_AGENT_REGISTRY_REQUIREMENT_VERSION,
211
+ ok: true,
212
+ status: "verified",
213
+ botId,
214
+ registryUrl,
215
+ trustManifestUrl: verification.trustManifestUrl ?? trustManifestUrl ?? null,
216
+ expectedRegistryHash,
217
+ registryHash: verification.registryHash ?? null,
218
+ trustManifest: verification.trustManifest ?? null,
219
+ trustScorePolicy,
220
+ agent: summarizeRegistryAgentForRequirement(agent),
221
+ profileCount: verification.profileCount ?? null,
222
+ verifiedAgentCount: verification.verifiedAgentCount ?? null,
223
+ nextAction: {
224
+ code: "none",
225
+ message: "Hosted SVS registry, trust manifest, and linked profile checks passed for this agent."
226
+ }
227
+ };
228
+ }
229
+
230
+ export function createHostedVerifiedAgentRegistryMiddleware({
231
+ registryUrl,
232
+ trustManifestUrl = null,
233
+ expectedRegistryHash,
234
+ requireVerified = true,
235
+ trustPolicy = null,
236
+ requireHighTrustScore = false,
237
+ minimumTrustScore = null,
238
+ requireTrustScoreEvidenceComplete = null,
239
+ maxTrustScoreBlockingSignals = null,
240
+ staleAfterMs = null,
241
+ now = new Date(),
242
+ fetchImpl = globalThis.fetch
243
+ } = {}) {
244
+ return async function svsHostedVerifiedAgentRegistryMiddleware(request = {}) {
245
+ const botId = request.botId ?? request.agent?.botId ?? request.body?.botId;
246
+
247
+ return requireHostedVerifiedAgentRegistry({
248
+ registryUrl,
249
+ trustManifestUrl,
250
+ expectedRegistryHash,
251
+ botId,
252
+ requireVerified,
253
+ trustPolicy,
254
+ requireHighTrustScore,
255
+ minimumTrustScore,
256
+ requireTrustScoreEvidenceComplete,
257
+ maxTrustScoreBlockingSignals,
258
+ staleAfterMs,
259
+ now,
260
+ fetchImpl
261
+ });
262
+ };
263
+ }
264
+
265
+ function summarizeRegistryAgentForRequirement(agent) {
266
+ return {
267
+ index: agent.index ?? null,
268
+ botId: agent.botId ?? null,
269
+ profilePath: agent.profilePath ?? null,
270
+ profileUrl: agent.profileUrl ?? null,
271
+ profileHash: agent.profileHash ?? null,
272
+ trustScore: agent.trustScore
273
+ ? {
274
+ version: agent.trustScore.version ?? null,
275
+ status: agent.trustScore.status ?? null,
276
+ score: agent.trustScore.score ?? null,
277
+ maxScore: agent.trustScore.maxScore ?? null,
278
+ evidenceComplete: agent.trustScore.evidenceComplete === true,
279
+ blockingSignalCount: agent.trustScore.blockingSignalCount ?? null,
280
+ trustScoreHash: agent.trustScore.trustScoreHash ?? null,
281
+ computedTrustScoreHash: agent.trustScore.computedTrustScoreHash ?? null,
282
+ hashValid: agent.trustScore.hashValid === true,
283
+ highTrustMinimumScore: agent.trustScore.highTrustMinimumScore ?? null,
284
+ nextAction: agent.trustScore.nextAction ?? null
285
+ }
286
+ : null,
287
+ ok: agent.ok === true,
288
+ failedCheckCount: agent.failedCheckCount ?? 0
289
+ };
290
+ }
291
+
292
+ function evaluateHostedTrustScorePolicy(trustScore, {
293
+ trustPolicy = HOSTED_VERIFIED_AGENT_TRUST_POLICY_STANDARD,
294
+ requireHighTrustScore = false,
295
+ minimumTrustScore = null,
296
+ requireTrustScoreEvidenceComplete = null,
297
+ maxTrustScoreBlockingSignals = null
298
+ } = {}) {
299
+ const effectiveMinimum = normalizeOptionalNumber(minimumTrustScore);
300
+ const effectiveBlockingMax = normalizeOptionalNumber(maxTrustScoreBlockingSignals);
301
+ const policyEnabled = requireHighTrustScore ||
302
+ effectiveMinimum !== null ||
303
+ requireTrustScoreEvidenceComplete === true ||
304
+ effectiveBlockingMax !== null;
305
+
306
+ if (!policyEnabled) {
307
+ return {
308
+ ok: true,
309
+ status: "not_required",
310
+ required: false,
311
+ trustPolicy,
312
+ detail: "No hosted registry trust-score policy was requested."
313
+ };
314
+ }
315
+
316
+ const minScore = requireHighTrustScore
317
+ ? effectiveMinimum ?? trustScore?.highTrustMinimumScore ?? VERIFIED_AGENT_TRUST_SCORE_HIGH_TRUST_MIN
318
+ : effectiveMinimum;
319
+ const mustComplete = requireHighTrustScore || requireTrustScoreEvidenceComplete === true;
320
+ const maxBlocking = requireHighTrustScore ? 0 : effectiveBlockingMax;
321
+ const failures = [];
322
+
323
+ if (!trustScore) {
324
+ failures.push("trust score missing");
325
+ } else {
326
+ if (trustScore.hashValid !== true) {
327
+ failures.push("trust score hash invalid");
328
+ }
329
+
330
+ if (minScore !== null && Number(trustScore.score ?? -1) < minScore) {
331
+ failures.push(`score ${trustScore.score ?? "missing"} below ${minScore}`);
332
+ }
333
+
334
+ if (mustComplete && trustScore.evidenceComplete !== true) {
335
+ failures.push("required evidence incomplete");
336
+ }
337
+
338
+ if (maxBlocking !== null && Number(trustScore.blockingSignalCount ?? Number.POSITIVE_INFINITY) > maxBlocking) {
339
+ failures.push(`blocking signals ${trustScore.blockingSignalCount ?? "missing"} above ${maxBlocking}`);
340
+ }
341
+ }
342
+
343
+ const ok = failures.length === 0;
344
+
345
+ return {
346
+ ok,
347
+ status: ok ? "passed" : "failed",
348
+ required: true,
349
+ trustPolicy,
350
+ requireHighTrustScore: Boolean(requireHighTrustScore),
351
+ minimumTrustScore: minScore,
352
+ requireTrustScoreEvidenceComplete: mustComplete,
353
+ maxTrustScoreBlockingSignals: maxBlocking,
354
+ detail: ok
355
+ ? `score=${trustScore?.score ?? "missing"} min=${minScore ?? "not_required"} blocking=${trustScore?.blockingSignalCount ?? "missing"} maxBlocking=${maxBlocking ?? "not_required"}`
356
+ : failures.join("; ")
357
+ };
358
+ }
359
+
360
+ function resolveHostedTrustScorePolicyOptions({
361
+ trustPolicy = null,
362
+ requireHighTrustScore = false,
363
+ minimumTrustScore = null,
364
+ requireTrustScoreEvidenceComplete = null,
365
+ maxTrustScoreBlockingSignals = null
366
+ } = {}) {
367
+ const explicitPolicy = normalizeHostedTrustPolicy(trustPolicy);
368
+ const hasCustomScoreOptions = normalizeOptionalNumber(minimumTrustScore) !== null ||
369
+ requireTrustScoreEvidenceComplete === true ||
370
+ normalizeOptionalNumber(maxTrustScoreBlockingSignals) !== null;
371
+
372
+ if (explicitPolicy === HOSTED_VERIFIED_AGENT_TRUST_POLICY_CUSTOM && !hasCustomScoreOptions) {
373
+ throw new Error(
374
+ 'trustPolicy "custom" requires minimumTrustScore, requireTrustScoreEvidenceComplete, or maxTrustScoreBlockingSignals.'
375
+ );
376
+ }
377
+
378
+ let resolvedPolicy = explicitPolicy ??
379
+ (requireHighTrustScore
380
+ ? HOSTED_VERIFIED_AGENT_TRUST_POLICY_HIGH_TRUST
381
+ : hasCustomScoreOptions
382
+ ? HOSTED_VERIFIED_AGENT_TRUST_POLICY_CUSTOM
383
+ : HOSTED_VERIFIED_AGENT_TRUST_POLICY_STANDARD);
384
+
385
+ if (resolvedPolicy === HOSTED_VERIFIED_AGENT_TRUST_POLICY_STANDARD && hasCustomScoreOptions) {
386
+ resolvedPolicy = HOSTED_VERIFIED_AGENT_TRUST_POLICY_CUSTOM;
387
+ }
388
+
389
+ return {
390
+ trustPolicy: resolvedPolicy,
391
+ requireHighTrustScore: requireHighTrustScore ||
392
+ resolvedPolicy === HOSTED_VERIFIED_AGENT_TRUST_POLICY_HIGH_TRUST,
393
+ minimumTrustScore,
394
+ requireTrustScoreEvidenceComplete,
395
+ maxTrustScoreBlockingSignals
396
+ };
397
+ }
398
+
399
+ function normalizeHostedTrustPolicy(value) {
400
+ if (value === null || value === undefined || value === "") {
401
+ return null;
402
+ }
403
+
404
+ const normalized = String(value).trim().toLowerCase().replaceAll("_", "-");
405
+
406
+ if (["standard", "baseline", "default"].includes(normalized)) {
407
+ return HOSTED_VERIFIED_AGENT_TRUST_POLICY_STANDARD;
408
+ }
409
+
410
+ if (["high-trust", "hightrust", "strict"].includes(normalized)) {
411
+ return HOSTED_VERIFIED_AGENT_TRUST_POLICY_HIGH_TRUST;
412
+ }
413
+
414
+ if (normalized === "custom") {
415
+ return HOSTED_VERIFIED_AGENT_TRUST_POLICY_CUSTOM;
416
+ }
417
+
418
+ throw new Error(
419
+ `Unsupported hosted registry trustPolicy "${value}". Use one of: ${HOSTED_VERIFIED_AGENT_TRUST_POLICY_VALUES.join(", ")}.`
420
+ );
421
+ }
422
+
423
+ function normalizeOptionalNumber(value) {
424
+ if (value === null || value === undefined || value === "") {
425
+ return null;
426
+ }
427
+
428
+ const number = Number(value);
429
+
430
+ return Number.isFinite(number) ? number : null;
431
+ }
432
+
433
+ export function createVerifiedAgentStandardConformanceFixtures({
434
+ now = new Date(),
435
+ botId = "svs-conformance-agent",
436
+ agentWallet = "ConformanceController111111111111111111111111",
437
+ action = "treasury_transfer",
438
+ recordId = "svs-conformance-record-1"
439
+ } = {}) {
440
+ const generatedAt = normalizeDate(now).toISOString();
441
+ const baseCertification = createConformanceCertification({ recordId });
442
+ const baseEvidence = createConformanceActionProofEvidence({
443
+ generatedAt,
444
+ botId,
445
+ recordId,
446
+ approvalDomain: APPROVAL_MESSAGE_DOMAIN,
447
+ approvalDomainStatus: "current"
448
+ });
449
+ const scenarios = [
450
+ {
451
+ id: "accept_current_verified_agent_action",
452
+ label: "Accept current verified agent action",
453
+ expectedAccepted: true,
454
+ requirement: "Protocol accepts only when certification, action proof, current approval domain, signed bot request, human approval, broadcast, custom registry, and action-record verification pass.",
455
+ botId,
456
+ agentWallet,
457
+ action,
458
+ recordId,
459
+ certification: baseCertification,
460
+ actionProductionProofEvidence: baseEvidence
461
+ },
462
+ {
463
+ id: "reject_legacy_approval_domain",
464
+ label: "Reject legacy approval domain for new protocol acceptance",
465
+ expectedAccepted: false,
466
+ expectedFailureCode: "approval_domain_legacy_compatible",
467
+ requirement: "Protocol must fail closed when a new action proof uses the legacy approval domain.",
468
+ botId,
469
+ agentWallet,
470
+ action,
471
+ recordId,
472
+ certification: baseCertification,
473
+ actionProductionProofEvidence: createConformanceActionProofEvidence({
474
+ generatedAt,
475
+ botId,
476
+ recordId,
477
+ approvalDomain: LEGACY_APPROVAL_MESSAGE_DOMAIN,
478
+ approvalDomainStatus: "legacy_compatible"
479
+ })
480
+ },
481
+ {
482
+ id: "reject_stale_action_proof",
483
+ label: "Reject stale action production proof",
484
+ expectedAccepted: false,
485
+ expectedFailureCode: "action_proof_verification_failed",
486
+ requirement: "Protocol must fail closed when the action production proof is older than the configured freshness window.",
487
+ botId,
488
+ agentWallet,
489
+ action,
490
+ recordId,
491
+ certification: baseCertification,
492
+ actionProductionProofEvidence: createConformanceActionProofEvidence({
493
+ generatedAt: new Date(normalizeDate(now).getTime() - 3_600_000).toISOString(),
494
+ botId,
495
+ recordId,
496
+ approvalDomain: APPROVAL_MESSAGE_DOMAIN,
497
+ approvalDomainStatus: "current"
498
+ }),
499
+ staleAfterMs: 1_000
500
+ },
501
+ {
502
+ id: "reject_missing_custom_registry_proof",
503
+ label: "Reject missing custom receipt-registry proof",
504
+ expectedAccepted: false,
505
+ expectedFailureCode: "action_proof_verification_failed",
506
+ requirement: "Protocol must fail closed when production rules require the custom receipt registry and the proof does not show a confirmed registry write.",
507
+ botId,
508
+ agentWallet,
509
+ action,
510
+ recordId,
511
+ certification: baseCertification,
512
+ actionProductionProofEvidence: createConformanceActionProofEvidence({
513
+ generatedAt,
514
+ botId,
515
+ recordId,
516
+ receiptRegistryConfirmed: false,
517
+ approvalDomain: APPROVAL_MESSAGE_DOMAIN,
518
+ approvalDomainStatus: "current"
519
+ })
520
+ },
521
+ {
522
+ id: "reject_unauthenticated_bot_request",
523
+ label: "Reject unauthenticated bot request",
524
+ expectedAccepted: false,
525
+ expectedFailureCode: "action_proof_verification_failed",
526
+ requirement: "Protocol must fail closed when the action proof is not tied to an authenticated signed bot request.",
527
+ botId,
528
+ agentWallet,
529
+ action,
530
+ recordId,
531
+ certification: baseCertification,
532
+ actionProductionProofEvidence: createConformanceActionProofEvidence({
533
+ generatedAt,
534
+ botId,
535
+ recordId,
536
+ requestSignatureVerified: false,
537
+ approvalDomain: APPROVAL_MESSAGE_DOMAIN,
538
+ approvalDomainStatus: "current"
539
+ })
540
+ },
541
+ {
542
+ id: "reject_record_mismatch",
543
+ label: "Reject action proof for another record",
544
+ expectedAccepted: false,
545
+ expectedFailureCode: "action_proof_verification_failed",
546
+ requirement: "Protocol must fail closed when the action production proof does not match the record being accepted.",
547
+ botId,
548
+ agentWallet,
549
+ action,
550
+ recordId,
551
+ certification: baseCertification,
552
+ expectedRecordId: "svs-conformance-record-2",
553
+ actionProductionProofEvidence: baseEvidence
554
+ },
555
+ {
556
+ id: "reject_uncertified_agent",
557
+ label: "Reject uncertified agent",
558
+ expectedAccepted: false,
559
+ expectedFailureCode: "verified_agent_requirement_failed",
560
+ requirement: "Protocol must fail closed when SVS production certification is missing, stale, incomplete, or below policy.",
561
+ botId,
562
+ agentWallet,
563
+ action,
564
+ recordId,
565
+ certification: createConformanceCertification({
566
+ recordId,
567
+ ok: false,
568
+ qualityReady: false,
569
+ score: 70,
570
+ status: "incomplete"
571
+ }),
572
+ actionProductionProofEvidence: baseEvidence
573
+ }
574
+ ];
575
+
576
+ return {
577
+ version: VERIFIED_AGENT_STANDARD_CONFORMANCE_FIXTURES_VERSION,
578
+ generatedAt,
579
+ standard: "Verified Agent Standard",
580
+ botId,
581
+ agentWallet,
582
+ action,
583
+ recordId,
584
+ scenarioCount: scenarios.length,
585
+ scenarios
586
+ };
587
+ }
588
+
589
+ export async function runVerifiedAgentStandardConformance({
590
+ fixtures = null,
591
+ now = new Date(),
592
+ staleAfterMs = 86_400_000
593
+ } = {}) {
594
+ const checkedAt = normalizeDate(now).toISOString();
595
+ const resolvedFixtures = fixtures ?? createVerifiedAgentStandardConformanceFixtures({ now });
596
+ const scenarios = [];
597
+
598
+ for (const fixture of resolvedFixtures.scenarios ?? []) {
599
+ scenarios.push(await evaluateVerifiedAgentStandardScenario(fixture, {
600
+ now: normalizeDate(now),
601
+ staleAfterMs
602
+ }));
603
+ }
604
+
605
+ const failedScenarios = scenarios.filter((scenario) => scenario.ok !== true);
606
+ const unsigned = {
607
+ version: VERIFIED_AGENT_STANDARD_CONFORMANCE_VERSION,
608
+ ok: failedScenarios.length === 0,
609
+ status: failedScenarios.length === 0 ? "verified" : "failed",
610
+ checkedAt,
611
+ fixtureVersion: resolvedFixtures.version ?? null,
612
+ scenarioCount: scenarios.length,
613
+ passedScenarioCount: scenarios.filter((scenario) => scenario.ok === true).length,
614
+ failedScenarioCount: failedScenarios.length,
615
+ scenarios,
616
+ nextAction: failedScenarios[0]
617
+ ? {
618
+ code: failedScenarios[0].id,
619
+ message: `Fix Verified Agent Standard conformance scenario ${failedScenarios[0].id}: ${failedScenarios[0].detail}.`
620
+ }
621
+ : {
622
+ code: "none",
623
+ message: "Verified Agent Standard pass/fail conformance fixtures match SDK verifier behavior."
624
+ }
625
+ };
626
+
627
+ return {
628
+ ...unsigned,
629
+ conformanceHash: hashObject(unsigned)
630
+ };
631
+ }
632
+
633
+ async function evaluateVerifiedAgentStandardScenario(fixture, {
634
+ now,
635
+ staleAfterMs
636
+ }) {
637
+ const expectedAccepted = fixture.expectedAccepted === true;
638
+ const expectedRecordId = fixture.expectedRecordId ?? fixture.recordId ?? null;
639
+ const scenarioStaleAfterMs = fixture.staleAfterMs ?? staleAfterMs;
640
+
641
+ try {
642
+ const verifiedAgent = await requireVerifiedAgent({
643
+ client: {
644
+ async requireProductionCertification(options) {
645
+ return {
646
+ ...(fixture.certification ?? {}),
647
+ requestedOptions: options
648
+ };
649
+ }
650
+ },
651
+ botId: fixture.botId,
652
+ agentWallet: fixture.agentWallet ?? null,
653
+ action: fixture.action ?? null,
654
+ staleAfterMs: fixture.certificationStaleAfterMs,
655
+ requireCurrentIntegrationContract: true
656
+ });
657
+ const actionProof = verifyActionProductionProofEvidence(fixture.actionProductionProofEvidence, {
658
+ expectedRecordId,
659
+ staleAfterMs: scenarioStaleAfterMs,
660
+ now
661
+ });
662
+
663
+ if (actionProof.ok !== true) {
664
+ return createConformanceScenarioResult({
665
+ fixture,
666
+ expectedAccepted,
667
+ accepted: false,
668
+ failureCode: "action_proof_verification_failed",
669
+ detail: actionProof.failedChecks?.[0]?.name ?? actionProof.status,
670
+ verifiedAgent,
671
+ actionProof
672
+ });
673
+ }
674
+
675
+ const approvalDomain = requireCurrentApprovalDomain(fixture.actionProductionProofEvidence, {
676
+ action: fixture.action ?? null
677
+ });
678
+
679
+ return createConformanceScenarioResult({
680
+ fixture,
681
+ expectedAccepted,
682
+ accepted: true,
683
+ failureCode: null,
684
+ detail: "accepted",
685
+ verifiedAgent,
686
+ actionProof,
687
+ approvalDomain
688
+ });
689
+ } catch (error) {
690
+ return createConformanceScenarioResult({
691
+ fixture,
692
+ expectedAccepted,
693
+ accepted: false,
694
+ failureCode: classifyConformanceError(error),
695
+ detail: error.message,
696
+ errorName: error.name
697
+ });
698
+ }
699
+ }
700
+
701
+ function createConformanceScenarioResult({
702
+ fixture,
703
+ expectedAccepted,
704
+ accepted,
705
+ failureCode,
706
+ detail,
707
+ errorName = null,
708
+ verifiedAgent = null,
709
+ actionProof = null,
710
+ approvalDomain = null
711
+ }) {
712
+ const expectedFailureCode = expectedAccepted ? null : fixture.expectedFailureCode ?? null;
713
+ const ok = accepted === expectedAccepted &&
714
+ (expectedAccepted || !expectedFailureCode || failureCode === expectedFailureCode);
715
+
716
+ return {
717
+ id: fixture.id,
718
+ label: fixture.label,
719
+ ok,
720
+ expectedAccepted,
721
+ accepted,
722
+ expectedFailureCode,
723
+ failureCode,
724
+ errorName,
725
+ detail,
726
+ requirement: fixture.requirement,
727
+ verification: verifiedAgent
728
+ ? {
729
+ ok: verifiedAgent.ok,
730
+ status: verifiedAgent.status,
731
+ certificationHash: verifiedAgent.certificationHash,
732
+ recordId: verifiedAgent.recordId
733
+ }
734
+ : null,
735
+ actionProductionProof: actionProof
736
+ ? {
737
+ ok: actionProof.ok,
738
+ status: actionProof.status,
739
+ recordId: actionProof.recordId,
740
+ evidenceHash: actionProof.evidenceHash,
741
+ failedCheckCount: actionProof.failedCheckCount,
742
+ failedChecks: actionProof.failedChecks?.slice(0, 3) ?? []
743
+ }
744
+ : null,
745
+ approvalDomain: approvalDomain
746
+ ? {
747
+ ok: approvalDomain.ok,
748
+ status: approvalDomain.status,
749
+ domain: approvalDomain.domain,
750
+ expectedDomain: approvalDomain.expectedDomain
751
+ }
752
+ : null
753
+ };
754
+ }
755
+
756
+ function classifyConformanceError(error) {
757
+ if (error?.name === "SvsCurrentApprovalDomainError") {
758
+ return error.details?.nextAction?.code ?? "approval_domain_not_current";
759
+ }
760
+
761
+ if (/SVS verified agent requirement failed/.test(error?.message ?? "")) {
762
+ return "verified_agent_requirement_failed";
763
+ }
764
+
765
+ return "unexpected_error";
766
+ }
767
+
768
+ function createConformanceCertification({
769
+ recordId,
770
+ ok = true,
771
+ qualityReady = true,
772
+ score = 100,
773
+ status = "excellent"
774
+ } = {}) {
775
+ return {
776
+ ok,
777
+ certification: {
778
+ certificationHash: ok ? "a".repeat(64) : null,
779
+ recordId
780
+ },
781
+ qualityTarget: {
782
+ ready: qualityReady,
783
+ score,
784
+ targetScore: 100,
785
+ status
786
+ },
787
+ integrationContract: {
788
+ ok,
789
+ status: ok ? "current" : "missing"
790
+ },
791
+ proofs: {
792
+ actionRecordVerificationOk: ok
793
+ },
794
+ nextAction: ok
795
+ ? { code: "none", message: "Production certification is current." }
796
+ : { code: "complete_certification", message: "Complete SVS production certification before protocol acceptance." }
797
+ };
798
+ }
799
+
800
+ function createConformanceActionProofEvidence({
801
+ generatedAt,
802
+ botId,
803
+ recordId,
804
+ approvalDomain,
805
+ approvalDomainStatus,
806
+ requestSignatureVerified = true,
807
+ receiptRegistryConfirmed = true
808
+ } = {}) {
809
+ const unsigned = {
810
+ version: ACTION_PRODUCTION_PROOF_EVIDENCE_VERSION,
811
+ generatedAt,
812
+ source: {
813
+ recordPath: `data/actions/${recordId}.json`,
814
+ statusVersion: "svs.action-production-proof-status.v1"
815
+ },
816
+ productionProof: {
817
+ ready: true,
818
+ status: "ready",
819
+ recordId,
820
+ botId,
821
+ receiptId: "svs-conformance-receipt-1",
822
+ nextAction: { code: "none", message: "Production proof is ready." },
823
+ checks: []
824
+ },
825
+ request: {
826
+ authenticatedBotId: requestSignatureVerified ? botId : null,
827
+ requestSignatureVerified,
828
+ requestSignatureSlot: requestSignatureVerified ? "primary" : null,
829
+ requestSignatureVersion: requestSignatureVerified ? "v1" : null,
830
+ requestNonce: requestSignatureVerified ? "svs-conformance-nonce-1" : null,
831
+ requestId: "svs-conformance-request-1",
832
+ idempotencyKey: "svs-conformance-request-1",
833
+ requestTimestamp: generatedAt
834
+ },
835
+ humanApproval: {
836
+ approved: true,
837
+ reviewer: "operator",
838
+ signer: "ConformanceController111111111111111111111111",
839
+ verified: true,
840
+ messageHash: "c".repeat(64),
841
+ domain: approvalDomain,
842
+ domainStatus: approvalDomainStatus,
843
+ currentDomain: approvalDomainStatus === "current",
844
+ legacyDomainCompatible: approvalDomainStatus === "legacy_compatible"
845
+ },
846
+ broadcast: {
847
+ confirmed: true,
848
+ signature: "svs-conformance-broadcast-signature",
849
+ confirmationStatus: "confirmed",
850
+ slot: 100,
851
+ rpcUrl: "https://api.devnet.solana.com"
852
+ },
853
+ receiptRegistry: {
854
+ confirmed: receiptRegistryConfirmed,
855
+ signature: receiptRegistryConfirmed ? "svs-conformance-registry-signature" : null,
856
+ confirmationStatus: receiptRegistryConfirmed ? "confirmed" : null,
857
+ slot: receiptRegistryConfirmed ? 101 : null,
858
+ programId: "ReceiptRegistry111111111111111111111111111111",
859
+ receiptAccount: receiptRegistryConfirmed ? "ReceiptAccount111111111111111111111111111111" : null,
860
+ planHash: receiptRegistryConfirmed ? "d".repeat(64) : null,
861
+ transactionPlanHash: receiptRegistryConfirmed ? "e".repeat(64) : null
862
+ },
863
+ actionRecordVerification: {
864
+ ok: true,
865
+ version: "svs.action-record-verification.v1",
866
+ checkedAt: generatedAt,
867
+ receiptId: "svs-conformance-receipt-1",
868
+ receiptAccount: receiptRegistryConfirmed ? "ReceiptAccount111111111111111111111111111111" : null,
869
+ registryTransactionSignature: receiptRegistryConfirmed ? "svs-conformance-registry-signature" : null,
870
+ failedCheckCount: 0
871
+ },
872
+ policy: {
873
+ controllerWallet: "ConformanceController111111111111111111111111",
874
+ policyHash: "f".repeat(64),
875
+ intentHash: "1".repeat(64),
876
+ simulationHash: "2".repeat(64)
877
+ },
878
+ reportSafety: {
879
+ secretsIncluded: false,
880
+ redactedFields: [
881
+ "SVS_BOT_API_KEY",
882
+ "SVS_BOT_REQUEST_SIGNING_SECRET",
883
+ "SVS_BOT_PENDING_REQUEST_SIGNING_SECRET",
884
+ "apiKey",
885
+ "requestSigningSecret",
886
+ "pendingRequestSigningSecret",
887
+ "webhookSecret"
888
+ ]
889
+ }
890
+ };
891
+
892
+ return {
893
+ ...unsigned,
894
+ evidenceHash: hashObject(unsigned)
895
+ };
896
+ }
897
+
898
+ function normalizeDate(value) {
899
+ return value instanceof Date ? value : new Date(value);
900
+ }