@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,329 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { dirname } from "node:path";
3
+ import { hashObject } from "./receipt.js";
4
+ import {
5
+ verifyBotCertificationEvidence
6
+ } from "./bot-certification-evidence.js";
7
+
8
+ export const VERIFIED_AGENT_PROFILE_VERSION = "svs.verified-agent-profile.v1";
9
+ export const VERIFIED_AGENT_PROFILE_VERIFICATION_VERSION = "svs.verified-agent-profile-verification.v1";
10
+ export const VERIFIED_AGENT_BADGE_VERSION = "svs.verified-agent-badge.v1";
11
+ export const DEFAULT_VERIFIED_AGENT_PROFILE_PATH = "./data/security/verified-agent-profile.json";
12
+ export const DEFAULT_VERIFIED_AGENT_BADGE_PATH = "./data/security/verified-agent-badge.svg";
13
+
14
+ export function createVerifiedAgentProfile({
15
+ certificationEvidence,
16
+ agentName = null,
17
+ agentUrl = null,
18
+ profileUrl = null,
19
+ badgeUrl = null,
20
+ generatedAt = new Date(),
21
+ staleAfterMs = null,
22
+ now = generatedAt
23
+ } = {}) {
24
+ if (!certificationEvidence || typeof certificationEvidence !== "object") {
25
+ throw new Error("certificationEvidence is required.");
26
+ }
27
+
28
+ const verification = verifyBotCertificationEvidence(certificationEvidence, {
29
+ requireOk: true,
30
+ staleAfterMs,
31
+ now
32
+ });
33
+ const status = verification.ok ? "verified" : verification.stale ? "stale" : "not_verified";
34
+ const botId = verification.botId ??
35
+ certificationEvidence.certificationCheck?.botId ??
36
+ certificationEvidence.certification?.botId ??
37
+ null;
38
+ const unsigned = {
39
+ version: VERIFIED_AGENT_PROFILE_VERSION,
40
+ generatedAt: generatedAt instanceof Date ? generatedAt.toISOString() : new Date(generatedAt).toISOString(),
41
+ agent: {
42
+ botId,
43
+ name: agentName ?? botId,
44
+ url: agentUrl,
45
+ profileUrl,
46
+ badgeUrl
47
+ },
48
+ status: {
49
+ ok: verification.ok === true,
50
+ value: status,
51
+ label: verification.ok ? "SVS Verified" : verification.stale ? "SVS Stale" : "SVS Not Verified",
52
+ nextAction: verification.ok
53
+ ? {
54
+ code: "none",
55
+ message: "Agent has current SVS production certification."
56
+ }
57
+ : certificationEvidence.nextAction ?? certificationEvidence.certificationCheck?.nextAction ?? null
58
+ },
59
+ certification: {
60
+ evidenceHash: verification.evidenceHash,
61
+ computedEvidenceHash: verification.computedEvidenceHash,
62
+ certificationHash: verification.certificationHash,
63
+ recordId: verification.recordId,
64
+ generatedAt: verification.generatedAt,
65
+ stale: verification.stale,
66
+ ageMs: verification.ageMs,
67
+ staleAfterMs: verification.staleAfterMs
68
+ },
69
+ qualityTarget: verification.qualityTarget
70
+ ? {
71
+ ready: verification.qualityTarget.ready === true,
72
+ score: Number.isInteger(verification.qualityTarget.score) ? verification.qualityTarget.score : null,
73
+ targetScore: Number.isInteger(verification.qualityTarget.targetScore) ? verification.qualityTarget.targetScore : null,
74
+ status: verification.qualityTarget.status ?? null
75
+ }
76
+ : null,
77
+ proofs: {
78
+ actionRecordVerificationOk: certificationEvidence.proofs?.actionRecordVerificationOk === true,
79
+ receiptRegistrySubmissionVerificationOk: certificationEvidence.proofs?.receiptRegistrySubmissionVerificationOk === true,
80
+ portableSetVerified: certificationEvidence.proofs?.portableSetVerified === true,
81
+ integrationContractCurrent: certificationEvidence.proofs?.integrationContractCurrent === true,
82
+ verificationSetHash: certificationEvidence.proofs?.verificationSetHash ?? null,
83
+ botIntegrationReportHash: certificationEvidence.proofs?.botIntegrationReportHash ?? null,
84
+ integrationContractHash: certificationEvidence.proofs?.integrationContractHash ?? null,
85
+ currentIntegrationContractHash: certificationEvidence.proofs?.currentIntegrationContractHash ?? null
86
+ },
87
+ display: {
88
+ badgeText: verification.ok ? "SVS Verified" : verification.stale ? "SVS Stale" : "SVS Not Verified",
89
+ badgeColor: verification.ok ? "#14f195" : verification.stale ? "#f59e0b" : "#ef4444",
90
+ badgeTextColor: "#08111f"
91
+ },
92
+ reportSafety: {
93
+ secretsIncluded: false,
94
+ sourceEvidenceSecretsIncluded: certificationEvidence.reportSafety?.secretsIncluded === true ||
95
+ certificationEvidence.proofs?.secretsIncluded === true,
96
+ redactedFields: [
97
+ "SVS_BOT_API_KEY",
98
+ "SVS_BOT_REQUEST_SIGNING_SECRET",
99
+ "SVS_BOT_PENDING_REQUEST_SIGNING_SECRET",
100
+ "apiKey",
101
+ "requestSigningSecret",
102
+ "pendingRequestSigningSecret",
103
+ "webhookSecret",
104
+ "svs-request-signature"
105
+ ]
106
+ }
107
+ };
108
+
109
+ return {
110
+ ...unsigned,
111
+ profileHash: hashVerifiedAgentProfile(unsigned)
112
+ };
113
+ }
114
+
115
+ export async function persistVerifiedAgentProfile({
116
+ certificationEvidence,
117
+ outputPath = DEFAULT_VERIFIED_AGENT_PROFILE_PATH,
118
+ badgeOutputPath = null,
119
+ ...options
120
+ } = {}) {
121
+ const profile = createVerifiedAgentProfile({
122
+ certificationEvidence,
123
+ ...options
124
+ });
125
+ const text = `${JSON.stringify(profile, null, 2)}\n`;
126
+
127
+ await mkdir(dirname(outputPath), { recursive: true });
128
+ await writeFile(outputPath, text);
129
+
130
+ const result = {
131
+ path: outputPath,
132
+ bytes: Buffer.byteLength(text, "utf8"),
133
+ profile
134
+ };
135
+
136
+ if (badgeOutputPath) {
137
+ const badge = createVerifiedAgentBadgeSvg(profile);
138
+
139
+ await mkdir(dirname(badgeOutputPath), { recursive: true });
140
+ await writeFile(badgeOutputPath, badge);
141
+ result.badge = {
142
+ path: badgeOutputPath,
143
+ bytes: Buffer.byteLength(badge, "utf8"),
144
+ badgeHash: hashObject({
145
+ version: VERIFIED_AGENT_BADGE_VERSION,
146
+ profileHash: profile.profileHash,
147
+ svg: badge
148
+ })
149
+ };
150
+ }
151
+
152
+ return result;
153
+ }
154
+
155
+ export function verifyVerifiedAgentProfile(profile, {
156
+ requireVerified = true,
157
+ expectedBotId = null,
158
+ staleAfterMs = null,
159
+ now = new Date()
160
+ } = {}) {
161
+ const freshness = checkProfileFreshness({
162
+ generatedAt: profile?.generatedAt,
163
+ staleAfterMs,
164
+ now
165
+ });
166
+ const recomputedHash = hashVerifiedAgentProfile(profile);
167
+ const checks = [
168
+ check(
169
+ "Verified agent profile version is supported",
170
+ profile?.version === VERIFIED_AGENT_PROFILE_VERSION,
171
+ profile?.version ?? "missing"
172
+ ),
173
+ check(
174
+ "Verified agent profile hash is valid",
175
+ profile?.profileHash === recomputedHash,
176
+ `declared=${profile?.profileHash ?? "missing"} recomputed=${recomputedHash ?? "missing"}`
177
+ ),
178
+ check(
179
+ "Verified agent profile excludes secrets",
180
+ profile?.reportSafety?.secretsIncluded === false &&
181
+ profile?.reportSafety?.sourceEvidenceSecretsIncluded !== true,
182
+ `profile=${profile?.reportSafety?.secretsIncluded ?? "missing"} source=${profile?.reportSafety?.sourceEvidenceSecretsIncluded ?? "missing"}`
183
+ ),
184
+ check(
185
+ "Verified agent profile has a bot id",
186
+ Boolean(profile?.agent?.botId),
187
+ profile?.agent?.botId ?? "missing"
188
+ ),
189
+ check(
190
+ "Verified agent profile matches expected bot id",
191
+ !expectedBotId || profile?.agent?.botId === expectedBotId,
192
+ `expected=${expectedBotId ?? "none"} actual=${profile?.agent?.botId ?? "missing"}`
193
+ ),
194
+ check(
195
+ "Verified agent profile is verified",
196
+ !requireVerified || profile?.status?.ok === true && profile?.status?.value === "verified",
197
+ `status=${profile?.status?.value ?? "missing"}`
198
+ ),
199
+ check(
200
+ "Verified agent profile includes custom registry proof",
201
+ !requireVerified || profile?.proofs?.receiptRegistrySubmissionVerificationOk === true,
202
+ `ok=${profile?.proofs?.receiptRegistrySubmissionVerificationOk ?? "missing"}`
203
+ ),
204
+ check(
205
+ "Verified agent profile includes action record proof",
206
+ !requireVerified || profile?.proofs?.actionRecordVerificationOk === true,
207
+ `ok=${profile?.proofs?.actionRecordVerificationOk ?? "missing"}`
208
+ ),
209
+ check(
210
+ "Verified agent profile includes portable set proof",
211
+ !requireVerified || profile?.proofs?.portableSetVerified === true,
212
+ `ok=${profile?.proofs?.portableSetVerified ?? "missing"}`
213
+ )
214
+ ];
215
+
216
+ if (staleAfterMs !== null && staleAfterMs !== undefined) {
217
+ checks.push(check(
218
+ "Verified agent profile is fresh",
219
+ !freshness.stale,
220
+ freshness.ageMs === null
221
+ ? `generatedAt=${profile?.generatedAt ?? "missing"}`
222
+ : `ageMs=${freshness.ageMs} staleAfterMs=${staleAfterMs}`
223
+ ));
224
+ }
225
+
226
+ const failedChecks = checks.filter((item) => !item.ok);
227
+
228
+ return {
229
+ version: VERIFIED_AGENT_PROFILE_VERIFICATION_VERSION,
230
+ ok: failedChecks.length === 0,
231
+ status: failedChecks.length === 0 ? "verified" : freshness.stale ? "stale" : "failed",
232
+ checkedAt: now instanceof Date ? now.toISOString() : new Date(now).toISOString(),
233
+ found: Boolean(profile),
234
+ profileHash: profile?.profileHash ?? null,
235
+ computedProfileHash: recomputedHash,
236
+ botId: profile?.agent?.botId ?? null,
237
+ badgeText: profile?.display?.badgeText ?? null,
238
+ stale: freshness.stale,
239
+ ageMs: freshness.ageMs,
240
+ staleAfterMs,
241
+ failedCheckCount: failedChecks.length,
242
+ failedChecks,
243
+ checks
244
+ };
245
+ }
246
+
247
+ export function createVerifiedAgentBadgeSvg(profile, {
248
+ width = 188,
249
+ height = 28
250
+ } = {}) {
251
+ const label = profile?.display?.badgeText ?? "SVS Not Verified";
252
+ const botId = profile?.agent?.botId ?? "agent";
253
+ const color = profile?.display?.badgeColor ?? "#ef4444";
254
+ const textColor = profile?.display?.badgeTextColor ?? "#08111f";
255
+ const leftWidth = 56;
256
+ const rightWidth = width - leftWidth;
257
+
258
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" role="img" aria-label="${escapeXml(label)}">
259
+ <title>${escapeXml(label)}: ${escapeXml(botId)}</title>
260
+ <linearGradient id="svs-gradient" x1="0%" x2="100%" y1="0%" y2="0%">
261
+ <stop offset="0%" stop-color="#9945ff"/>
262
+ <stop offset="52%" stop-color="#14f195"/>
263
+ <stop offset="100%" stop-color="#00c2ff"/>
264
+ </linearGradient>
265
+ <rect width="${width}" height="${height}" rx="6" fill="#08111f"/>
266
+ <rect width="${leftWidth}" height="${height}" rx="6" fill="url(#svs-gradient)"/>
267
+ <rect x="${leftWidth - 6}" width="6" height="${height}" fill="url(#svs-gradient)"/>
268
+ <rect x="${leftWidth}" width="${rightWidth}" height="${height}" fill="${escapeXml(color)}"/>
269
+ <text x="28" y="18" text-anchor="middle" font-family="Inter, ui-sans-serif, system-ui, sans-serif" font-size="11" font-weight="800" fill="#08111f">SVS</text>
270
+ <text x="${leftWidth + Math.floor(rightWidth / 2)}" y="18" text-anchor="middle" font-family="Inter, ui-sans-serif, system-ui, sans-serif" font-size="11" font-weight="800" fill="${escapeXml(textColor)}">${escapeXml(label.replace(/^SVS\\s+/, ""))}</text>
271
+ </svg>
272
+ `;
273
+ }
274
+
275
+ export function hashVerifiedAgentProfile(profile) {
276
+ if (!profile || typeof profile !== "object") {
277
+ return null;
278
+ }
279
+
280
+ const { profileHash: _profileHash, ...unsigned } = profile;
281
+
282
+ return hashObject(unsigned);
283
+ }
284
+
285
+ function checkProfileFreshness({
286
+ generatedAt,
287
+ staleAfterMs,
288
+ now = new Date()
289
+ } = {}) {
290
+ if (staleAfterMs === null || staleAfterMs === undefined) {
291
+ return {
292
+ stale: false,
293
+ ageMs: null
294
+ };
295
+ }
296
+
297
+ const generatedTime = Date.parse(generatedAt);
298
+ const nowTime = now instanceof Date ? now.getTime() : Date.parse(now);
299
+
300
+ if (!Number.isFinite(generatedTime) || !Number.isFinite(nowTime)) {
301
+ return {
302
+ stale: true,
303
+ ageMs: null
304
+ };
305
+ }
306
+
307
+ const ageMs = Math.max(0, nowTime - generatedTime);
308
+
309
+ return {
310
+ stale: ageMs > staleAfterMs,
311
+ ageMs
312
+ };
313
+ }
314
+
315
+ function check(name, ok, detail) {
316
+ return {
317
+ name,
318
+ ok: Boolean(ok),
319
+ detail
320
+ };
321
+ }
322
+
323
+ function escapeXml(value) {
324
+ return String(value ?? "")
325
+ .replaceAll("&", "&amp;")
326
+ .replaceAll("<", "&lt;")
327
+ .replaceAll(">", "&gt;")
328
+ .replaceAll("\"", "&quot;");
329
+ }