@sealkeeper/schema 0.0.1 → 0.4.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 (68) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +2 -0
  3. package/README.md +14 -1
  4. package/dist/agent-id.d.ts +13 -0
  5. package/dist/agent-id.js +29 -0
  6. package/dist/agent-name.d.ts +9 -0
  7. package/dist/agent-name.js +58 -0
  8. package/dist/api.d.ts +1212 -0
  9. package/dist/api.js +633 -0
  10. package/dist/base64url.d.ts +4 -0
  11. package/dist/base64url.js +43 -0
  12. package/dist/credential.d.ts +392 -0
  13. package/dist/credential.js +287 -0
  14. package/dist/db/agent-renames.d.ts +126 -0
  15. package/dist/db/agent-renames.js +20 -0
  16. package/dist/db/agents.d.ts +145 -0
  17. package/dist/db/agents.js +40 -0
  18. package/dist/db/client.d.ts +1896 -0
  19. package/dist/db/client.js +36 -0
  20. package/dist/db/credentials.d.ts +143 -0
  21. package/dist/db/credentials.js +16 -0
  22. package/dist/db/deleted-operators.d.ts +75 -0
  23. package/dist/db/deleted-operators.js +13 -0
  24. package/dist/db/events.d.ts +160 -0
  25. package/dist/db/events.js +34 -0
  26. package/dist/db/feed-items.d.ts +109 -0
  27. package/dist/db/feed-items.js +16 -0
  28. package/dist/db/index.d.ts +56 -0
  29. package/dist/db/index.js +23 -0
  30. package/dist/db/migrate.d.ts +1 -0
  31. package/dist/db/migrate.js +30 -0
  32. package/dist/db/migrator.d.ts +2 -0
  33. package/dist/db/migrator.js +20 -0
  34. package/dist/db/operators.d.ts +109 -0
  35. package/dist/db/operators.js +11 -0
  36. package/dist/db/quota-counters.d.ts +109 -0
  37. package/dist/db/quota-counters.js +17 -0
  38. package/dist/db/ratings.d.ts +160 -0
  39. package/dist/db/ratings.js +27 -0
  40. package/dist/db/scores.d.ts +160 -0
  41. package/dist/db/scores.js +15 -0
  42. package/dist/db/standing.d.ts +228 -0
  43. package/dist/db/standing.js +29 -0
  44. package/dist/db/task-outcomes.d.ts +126 -0
  45. package/dist/db/task-outcomes.js +18 -0
  46. package/dist/db/tasks.d.ts +251 -0
  47. package/dist/db/tasks.js +49 -0
  48. package/dist/db/timestamps.d.ts +4 -0
  49. package/dist/db/timestamps.js +24 -0
  50. package/dist/db/url.d.ts +12 -0
  51. package/dist/db/url.js +25 -0
  52. package/dist/dimensions.d.ts +21 -0
  53. package/dist/dimensions.js +15 -0
  54. package/dist/envelope.d.ts +16 -0
  55. package/dist/envelope.js +70 -0
  56. package/dist/events.d.ts +153 -0
  57. package/dist/events.js +98 -0
  58. package/dist/index.d.ts +12 -0
  59. package/dist/index.js +12 -0
  60. package/dist/seal-conformance.d.ts +14 -0
  61. package/dist/seal-conformance.js +176 -0
  62. package/dist/standing.d.ts +46 -0
  63. package/dist/standing.js +79 -0
  64. package/dist/tasks.d.ts +49 -0
  65. package/dist/tasks.js +132 -0
  66. package/dist/top-dimensions.d.ts +9 -0
  67. package/dist/top-dimensions.js +13 -0
  68. package/package.json +69 -5
@@ -0,0 +1,392 @@
1
+ import { z } from 'zod';
2
+ export declare const CREDENTIAL_ISSUER = "sealkeeper.run";
3
+ export declare const LEGACY_ISSUERS: readonly ['vouched.run'];
4
+ export declare const LEGACY_ISSUER_UNTIL: number;
5
+ export declare function acceptedIssuer(iss: unknown, nowSeconds: number): boolean;
6
+ export declare const WELL_KNOWN_PATH = "/.well-known/seal.json";
7
+ export declare const LEGACY_WELL_KNOWN_PATH = "/.well-known/vouched.json";
8
+ export declare const WELL_KNOWN_URL = "https://sealkeeper.run/.well-known/seal.json";
9
+ export declare const LEGACY_WELL_KNOWN_URL = "https://vouched.run/.well-known/vouched.json";
10
+ export declare const SEAL_EXTENSION_URI = "https://sealkeeper.run/ext/seal/v1";
11
+ export declare const LEGACY_SEAL_EXTENSION_URI = "https://vouched.run/ext/seal/v1";
12
+ export declare const CREDENTIAL_EXTENSION_URI = "https://vouched.run/ext/credential/v1";
13
+ export declare const LEGACY_SEAL_EXTENSION_URIS: readonly string[];
14
+ export declare const SEAL_EXTENSION_URIS: readonly string[];
15
+ export declare const SEAL_VERSION = 1;
16
+ export declare const LEGACY_UNTIL: number;
17
+ export declare const IdentityKind: z.ZodUnion<readonly [z.ZodEnum<{
18
+ kya: "kya";
19
+ oidc: "oidc";
20
+ saml: "saml";
21
+ verifiable_credential: "verifiable_credential";
22
+ }>, z.ZodURL]>;
23
+ export type IdentityKind = z.infer<typeof IdentityKind>;
24
+ export declare const IdentityReference: z.ZodObject<{
25
+ provider: z.ZodURL;
26
+ kind: z.ZodUnion<readonly [z.ZodEnum<{
27
+ kya: "kya";
28
+ oidc: "oidc";
29
+ saml: "saml";
30
+ verifiable_credential: "verifiable_credential";
31
+ }>, z.ZodURL]>;
32
+ ref: z.ZodString;
33
+ subject_hash: z.ZodString;
34
+ attested_at: z.ZodInt;
35
+ scope: z.ZodEnum<{
36
+ agent: "agent";
37
+ operator: "operator";
38
+ }>;
39
+ }, z.core.$strict>;
40
+ export type IdentityReference = z.infer<typeof IdentityReference>;
41
+ export declare const operatorVerified: (identity: readonly IdentityReference[]) => boolean;
42
+ export declare const SEAL_MAX_TTL_SECONDS: number;
43
+ export declare const SEAL_CLOCK_SKEW_SECONDS = 300;
44
+ export declare const CredentialPayload: z.ZodObject<{
45
+ iss: z.ZodLiteral<"sealkeeper.run">;
46
+ sub: z.ZodString;
47
+ ver: z.ZodLiteral<1>;
48
+ iat: z.ZodInt;
49
+ exp: z.ZodInt;
50
+ agent_version: z.ZodString;
51
+ version: z.ZodString;
52
+ level: z.ZodEnum<{
53
+ bronze: "bronze";
54
+ gold: "gold";
55
+ none: "none";
56
+ silver: "silver";
57
+ }>;
58
+ scores: z.ZodRecord<z.ZodUnion<readonly [z.ZodEnum<{
59
+ cost_latency: "cost_latency";
60
+ provenance: "provenance";
61
+ reliability: "reliability";
62
+ safety: "safety";
63
+ }>, z.ZodTemplateLiteral<`competence:${string}`>]> & z.core.$partial, z.ZodNullable<z.ZodNumber>>;
64
+ counts: z.ZodObject<{
65
+ events: z.ZodInt;
66
+ history_days: z.ZodInt;
67
+ verified_tasks: z.ZodInt;
68
+ seed_tasks: z.ZodInt;
69
+ server_checked_tasks: z.ZodInt;
70
+ confirmed_tasks: z.ZodInt;
71
+ distinct_operators: z.ZodInt;
72
+ safety_incidents_90d: z.ZodInt;
73
+ }, z.core.$strict>;
74
+ operator: z.ZodObject<{
75
+ verified: z.ZodBoolean;
76
+ }, z.core.$strict>;
77
+ identity: z.ZodArray<z.ZodObject<{
78
+ provider: z.ZodURL;
79
+ kind: z.ZodUnion<readonly [z.ZodEnum<{
80
+ kya: "kya";
81
+ oidc: "oidc";
82
+ saml: "saml";
83
+ verifiable_credential: "verifiable_credential";
84
+ }>, z.ZodURL]>;
85
+ ref: z.ZodString;
86
+ subject_hash: z.ZodString;
87
+ attested_at: z.ZodInt;
88
+ scope: z.ZodEnum<{
89
+ agent: "agent";
90
+ operator: "operator";
91
+ }>;
92
+ }, z.core.$strict>>;
93
+ last_active: z.ZodNullable<z.ZodInt>;
94
+ dormant_days: z.ZodNullable<z.ZodInt>;
95
+ }, z.core.$strict>;
96
+ export type CredentialPayload = z.infer<typeof CredentialPayload>;
97
+ export declare const LegacyCredentialPayload: z.ZodObject<{
98
+ iss: z.ZodLiteral<"sealkeeper.run">;
99
+ sub: z.ZodString;
100
+ iat: z.ZodInt;
101
+ exp: z.ZodInt;
102
+ version: z.ZodString;
103
+ scores: z.ZodRecord<z.ZodUnion<readonly [z.ZodEnum<{
104
+ cost_latency: "cost_latency";
105
+ provenance: "provenance";
106
+ reliability: "reliability";
107
+ safety: "safety";
108
+ }>, z.ZodTemplateLiteral<`competence:${string}`>]> & z.core.$partial, z.ZodNullable<z.ZodNumber>>;
109
+ counts: z.ZodObject<{
110
+ events: z.ZodInt;
111
+ verified_tasks: z.ZodInt;
112
+ seed_tasks: z.ZodOptional<z.ZodInt>;
113
+ }, z.core.$strict>;
114
+ }, z.core.$strict>;
115
+ export type LegacyCredentialPayload = z.infer<typeof LegacyCredentialPayload>;
116
+ export declare const VerifiedCredentialPayload: z.ZodObject<{
117
+ iss: z.ZodEnum<{
118
+ "sealkeeper.run": "sealkeeper.run";
119
+ "vouched.run": "vouched.run";
120
+ }>;
121
+ sub: z.ZodString;
122
+ ver: z.ZodLiteral<1>;
123
+ iat: z.ZodInt;
124
+ exp: z.ZodInt;
125
+ agent_version: z.ZodString;
126
+ version: z.ZodString;
127
+ level: z.ZodEnum<{
128
+ bronze: "bronze";
129
+ gold: "gold";
130
+ none: "none";
131
+ silver: "silver";
132
+ }>;
133
+ scores: z.ZodRecord<z.ZodUnion<readonly [z.ZodEnum<{
134
+ cost_latency: "cost_latency";
135
+ provenance: "provenance";
136
+ reliability: "reliability";
137
+ safety: "safety";
138
+ }>, z.ZodTemplateLiteral<`competence:${string}`>]> & z.core.$partial, z.ZodNullable<z.ZodNumber>>;
139
+ counts: z.ZodObject<{
140
+ events: z.ZodInt;
141
+ history_days: z.ZodInt;
142
+ verified_tasks: z.ZodInt;
143
+ seed_tasks: z.ZodInt;
144
+ server_checked_tasks: z.ZodInt;
145
+ confirmed_tasks: z.ZodInt;
146
+ distinct_operators: z.ZodInt;
147
+ safety_incidents_90d: z.ZodInt;
148
+ }, z.core.$strict>;
149
+ operator: z.ZodObject<{
150
+ verified: z.ZodBoolean;
151
+ }, z.core.$strict>;
152
+ identity: z.ZodArray<z.ZodObject<{
153
+ provider: z.ZodURL;
154
+ kind: z.ZodUnion<readonly [z.ZodEnum<{
155
+ kya: "kya";
156
+ oidc: "oidc";
157
+ saml: "saml";
158
+ verifiable_credential: "verifiable_credential";
159
+ }>, z.ZodURL]>;
160
+ ref: z.ZodString;
161
+ subject_hash: z.ZodString;
162
+ attested_at: z.ZodInt;
163
+ scope: z.ZodEnum<{
164
+ agent: "agent";
165
+ operator: "operator";
166
+ }>;
167
+ }, z.core.$strict>>;
168
+ last_active: z.ZodNullable<z.ZodInt>;
169
+ dormant_days: z.ZodNullable<z.ZodInt>;
170
+ }, z.core.$strict>;
171
+ export type VerifiedCredentialPayload = z.infer<typeof VerifiedCredentialPayload>;
172
+ export declare const VerifiedLegacyCredentialPayload: z.ZodObject<{
173
+ iss: z.ZodEnum<{
174
+ "sealkeeper.run": "sealkeeper.run";
175
+ "vouched.run": "vouched.run";
176
+ }>;
177
+ sub: z.ZodString;
178
+ iat: z.ZodInt;
179
+ exp: z.ZodInt;
180
+ version: z.ZodString;
181
+ scores: z.ZodRecord<z.ZodUnion<readonly [z.ZodEnum<{
182
+ cost_latency: "cost_latency";
183
+ provenance: "provenance";
184
+ reliability: "reliability";
185
+ safety: "safety";
186
+ }>, z.ZodTemplateLiteral<`competence:${string}`>]> & z.core.$partial, z.ZodNullable<z.ZodNumber>>;
187
+ counts: z.ZodObject<{
188
+ events: z.ZodInt;
189
+ verified_tasks: z.ZodInt;
190
+ seed_tasks: z.ZodOptional<z.ZodInt>;
191
+ }, z.core.$strict>;
192
+ }, z.core.$strict>;
193
+ export type VerifiedLegacyCredentialPayload = z.infer<typeof VerifiedLegacyCredentialPayload>;
194
+ export declare const SealPayload: z.ZodUnion<readonly [z.ZodObject<{
195
+ iss: z.ZodEnum<{
196
+ "sealkeeper.run": "sealkeeper.run";
197
+ "vouched.run": "vouched.run";
198
+ }>;
199
+ sub: z.ZodString;
200
+ ver: z.ZodLiteral<1>;
201
+ iat: z.ZodInt;
202
+ exp: z.ZodInt;
203
+ agent_version: z.ZodString;
204
+ version: z.ZodString;
205
+ level: z.ZodEnum<{
206
+ bronze: "bronze";
207
+ gold: "gold";
208
+ none: "none";
209
+ silver: "silver";
210
+ }>;
211
+ scores: z.ZodRecord<z.ZodUnion<readonly [z.ZodEnum<{
212
+ cost_latency: "cost_latency";
213
+ provenance: "provenance";
214
+ reliability: "reliability";
215
+ safety: "safety";
216
+ }>, z.ZodTemplateLiteral<`competence:${string}`>]> & z.core.$partial, z.ZodNullable<z.ZodNumber>>;
217
+ counts: z.ZodObject<{
218
+ events: z.ZodInt;
219
+ history_days: z.ZodInt;
220
+ verified_tasks: z.ZodInt;
221
+ seed_tasks: z.ZodInt;
222
+ server_checked_tasks: z.ZodInt;
223
+ confirmed_tasks: z.ZodInt;
224
+ distinct_operators: z.ZodInt;
225
+ safety_incidents_90d: z.ZodInt;
226
+ }, z.core.$strict>;
227
+ operator: z.ZodObject<{
228
+ verified: z.ZodBoolean;
229
+ }, z.core.$strict>;
230
+ identity: z.ZodArray<z.ZodObject<{
231
+ provider: z.ZodURL;
232
+ kind: z.ZodUnion<readonly [z.ZodEnum<{
233
+ kya: "kya";
234
+ oidc: "oidc";
235
+ saml: "saml";
236
+ verifiable_credential: "verifiable_credential";
237
+ }>, z.ZodURL]>;
238
+ ref: z.ZodString;
239
+ subject_hash: z.ZodString;
240
+ attested_at: z.ZodInt;
241
+ scope: z.ZodEnum<{
242
+ agent: "agent";
243
+ operator: "operator";
244
+ }>;
245
+ }, z.core.$strict>>;
246
+ last_active: z.ZodNullable<z.ZodInt>;
247
+ dormant_days: z.ZodNullable<z.ZodInt>;
248
+ }, z.core.$strict>, z.ZodObject<{
249
+ iss: z.ZodEnum<{
250
+ "sealkeeper.run": "sealkeeper.run";
251
+ "vouched.run": "vouched.run";
252
+ }>;
253
+ sub: z.ZodString;
254
+ iat: z.ZodInt;
255
+ exp: z.ZodInt;
256
+ version: z.ZodString;
257
+ scores: z.ZodRecord<z.ZodUnion<readonly [z.ZodEnum<{
258
+ cost_latency: "cost_latency";
259
+ provenance: "provenance";
260
+ reliability: "reliability";
261
+ safety: "safety";
262
+ }>, z.ZodTemplateLiteral<`competence:${string}`>]> & z.core.$partial, z.ZodNullable<z.ZodNumber>>;
263
+ counts: z.ZodObject<{
264
+ events: z.ZodInt;
265
+ verified_tasks: z.ZodInt;
266
+ seed_tasks: z.ZodOptional<z.ZodInt>;
267
+ }, z.core.$strict>;
268
+ }, z.core.$strict>]>;
269
+ export type SealPayload = z.infer<typeof SealPayload>;
270
+ export declare const isSealV1: (p: SealPayload) => p is VerifiedCredentialPayload;
271
+ export declare function sealVersionProblem(raw: unknown, nowSeconds: number): 'unsupported_version' | null;
272
+ export declare function sealIatProblem(iat: number, nowSeconds: number): 'not_yet_valid' | null;
273
+ export type SealPayloadResult = {
274
+ ok: true;
275
+ payload: SealPayload;
276
+ } | {
277
+ ok: false;
278
+ reason: 'wrong_issuer' | 'unsupported_version' | 'malformed';
279
+ };
280
+ export declare function parseSealPayload(raw: unknown, nowSeconds: number): SealPayloadResult;
281
+ export declare const WellKnownKey: z.ZodObject<{
282
+ kid: z.ZodString;
283
+ kty: z.ZodLiteral<"OKP">;
284
+ crv: z.ZodLiteral<"Ed25519">;
285
+ alg: z.ZodLiteral<"EdDSA">;
286
+ x: z.ZodString;
287
+ }, z.core.$strict>;
288
+ export type WellKnownKey = z.infer<typeof WellKnownKey>;
289
+ export declare const WellKnown: z.ZodObject<{
290
+ keys: z.ZodArray<z.ZodObject<{
291
+ kid: z.ZodString;
292
+ kty: z.ZodLiteral<"OKP">;
293
+ crv: z.ZodLiteral<"Ed25519">;
294
+ alg: z.ZodLiteral<"EdDSA">;
295
+ x: z.ZodString;
296
+ }, z.core.$strict>>;
297
+ }, z.core.$strict>;
298
+ export type WellKnown = z.infer<typeof WellKnown>;
299
+ export declare const CredentialExtension: z.ZodObject<{
300
+ uri: z.ZodLiteral<"https://vouched.run/ext/credential/v1">;
301
+ description: z.ZodString;
302
+ params: z.ZodObject<{
303
+ credential: z.ZodString;
304
+ }, z.core.$strict>;
305
+ }, z.core.$strict>;
306
+ export type CredentialExtension = z.infer<typeof CredentialExtension>;
307
+ export declare const LegacySealExtension: z.ZodObject<{
308
+ uri: z.ZodLiteral<"https://vouched.run/ext/seal/v1">;
309
+ description: z.ZodString;
310
+ params: z.ZodObject<{
311
+ credential: z.ZodString;
312
+ }, z.core.$strict>;
313
+ }, z.core.$strict>;
314
+ export type LegacySealExtension = z.infer<typeof LegacySealExtension>;
315
+ export declare const SealExtension: z.ZodObject<{
316
+ uri: z.ZodLiteral<"https://sealkeeper.run/ext/seal/v1">;
317
+ description: z.ZodString;
318
+ params: z.ZodObject<{
319
+ credential: z.ZodString;
320
+ }, z.core.$strict>;
321
+ }, z.core.$strict>;
322
+ export type SealExtension = z.infer<typeof SealExtension>;
323
+ export declare const credentialExtension: (jws: string) => CredentialExtension;
324
+ export declare const legacySealExtension: (jws: string) => LegacySealExtension;
325
+ export declare const sealExtension: (jws: string) => SealExtension;
326
+ export declare const sealExtensions: (jws: string) => ({
327
+ uri: "https://vouched.run/ext/credential/v1";
328
+ description: string;
329
+ params: {
330
+ credential: string;
331
+ };
332
+ } | {
333
+ uri: "https://vouched.run/ext/seal/v1";
334
+ description: string;
335
+ params: {
336
+ credential: string;
337
+ };
338
+ } | {
339
+ uri: "https://sealkeeper.run/ext/seal/v1";
340
+ description: string;
341
+ params: {
342
+ credential: string;
343
+ };
344
+ })[];
345
+ export declare const A2A_PROTOCOL_VERSION = "0.3.0";
346
+ export declare const AgentSkill: z.ZodObject<{
347
+ id: z.ZodString;
348
+ name: z.ZodString;
349
+ description: z.ZodString;
350
+ tags: z.ZodArray<z.ZodString>;
351
+ examples: z.ZodOptional<z.ZodArray<z.ZodString>>;
352
+ }, z.core.$strict>;
353
+ export type AgentSkill = z.infer<typeof AgentSkill>;
354
+ export declare const AgentCard: z.ZodObject<{
355
+ protocolVersion: z.ZodLiteral<"0.3.0">;
356
+ name: z.ZodString;
357
+ description: z.ZodString;
358
+ url: z.ZodOptional<z.ZodURL>;
359
+ version: z.ZodString;
360
+ capabilities: z.ZodObject<{
361
+ extensions: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
362
+ uri: z.ZodLiteral<"https://sealkeeper.run/ext/seal/v1">;
363
+ description: z.ZodString;
364
+ params: z.ZodObject<{
365
+ credential: z.ZodString;
366
+ }, z.core.$strict>;
367
+ }, z.core.$strict>, z.ZodObject<{
368
+ uri: z.ZodLiteral<"https://vouched.run/ext/seal/v1">;
369
+ description: z.ZodString;
370
+ params: z.ZodObject<{
371
+ credential: z.ZodString;
372
+ }, z.core.$strict>;
373
+ }, z.core.$strict>, z.ZodObject<{
374
+ uri: z.ZodLiteral<"https://vouched.run/ext/credential/v1">;
375
+ description: z.ZodString;
376
+ params: z.ZodObject<{
377
+ credential: z.ZodString;
378
+ }, z.core.$strict>;
379
+ }, z.core.$strict>]>>;
380
+ }, z.core.$strict>;
381
+ skills: z.ZodArray<z.ZodObject<{
382
+ id: z.ZodString;
383
+ name: z.ZodString;
384
+ description: z.ZodString;
385
+ tags: z.ZodArray<z.ZodString>;
386
+ examples: z.ZodOptional<z.ZodArray<z.ZodString>>;
387
+ }, z.core.$strict>>;
388
+ defaultInputModes: z.ZodDefault<z.ZodArray<z.ZodString>>;
389
+ defaultOutputModes: z.ZodDefault<z.ZodArray<z.ZodString>>;
390
+ }, z.core.$strict>;
391
+ export type AgentCard = z.infer<typeof AgentCard>;
392
+ export type AgentCardInput = z.input<typeof AgentCard>;
@@ -0,0 +1,287 @@
1
+ import { z } from 'zod';
2
+ import { AgentId, Ed25519PublicKey } from './agent-id.js';
3
+ import { Dimension } from './dimensions.js';
4
+ import { Jws } from './envelope.js';
5
+ import { Version } from './events.js';
6
+ import { Level, StandingCounts } from './standing.js';
7
+ // The issuer every SEAL carries as iss from the SealKeeper cutover on.
8
+ export const CREDENTIAL_ISSUER = 'sealkeeper.run';
9
+ // Issuers a verifier still accepts for a while after the cutover. A SEAL
10
+ // lives at most 24 hours, so one issued as vouched.run just before the
11
+ // cutover has expired well before LEGACY_ISSUER_UNTIL. From then on only
12
+ // CREDENTIAL_ISSUER is accepted.
13
+ export const LEGACY_ISSUERS = ['vouched.run'];
14
+ // Unix seconds, the first second a LEGACY_ISSUERS entry is no longer
15
+ // accepted. 2 October 2026 00:00 UTC.
16
+ export const LEGACY_ISSUER_UNTIL = Date.UTC(2026, 9, 2) / 1000;
17
+ // Whether a verifier accepts iss at nowSeconds. CREDENTIAL_ISSUER always, a
18
+ // legacy issuer only before LEGACY_ISSUER_UNTIL, anything else never.
19
+ export function acceptedIssuer(iss, nowSeconds) {
20
+ if (iss === CREDENTIAL_ISSUER)
21
+ return true;
22
+ return (typeof iss === 'string' &&
23
+ LEGACY_ISSUERS.includes(iss) &&
24
+ nowSeconds < LEGACY_ISSUER_UNTIL);
25
+ }
26
+ // The path of the keys document, on the issuer's own domain. It is product
27
+ // neutral so another issuer can serve the same path. The old path is served
28
+ // beside it for one release.
29
+ export const WELL_KNOWN_PATH = '/.well-known/seal.json';
30
+ export const LEGACY_WELL_KNOWN_PATH = '/.well-known/vouched.json';
31
+ export const WELL_KNOWN_URL = `https://${CREDENTIAL_ISSUER}${WELL_KNOWN_PATH}`;
32
+ export const LEGACY_WELL_KNOWN_URL = `https://vouched.run${LEGACY_WELL_KNOWN_PATH}`;
33
+ // The card extension a SEAL travels under. The two old URIs are kept beside
34
+ // it for one release, VOU-77 drops them.
35
+ export const SEAL_EXTENSION_URI = 'https://sealkeeper.run/ext/seal/v1';
36
+ export const LEGACY_SEAL_EXTENSION_URI = 'https://vouched.run/ext/seal/v1';
37
+ // The first card extension URI, kept under its old name so callers compile.
38
+ export const CREDENTIAL_EXTENSION_URI = 'https://vouched.run/ext/credential/v1';
39
+ export const LEGACY_SEAL_EXTENSION_URIS = [
40
+ LEGACY_SEAL_EXTENSION_URI,
41
+ CREDENTIAL_EXTENSION_URI,
42
+ ];
43
+ // Every URI a SEAL extension may carry, the current one first. A card
44
+ // rebuilt with a fresh SEAL drops extensions with any of these first.
45
+ export const SEAL_EXTENSION_URIS = [
46
+ SEAL_EXTENSION_URI,
47
+ ...LEGACY_SEAL_EXTENSION_URIS,
48
+ ];
49
+ const Seconds = z.int().min(0);
50
+ const Count = z.int().min(0);
51
+ // The version of the SEAL standard this issuer writes, carried as ver.
52
+ export const SEAL_VERSION = 1;
53
+ // SEALs issued before version 1 carry no ver. Verifiers accept them as
54
+ // legacy until the end of 25 September 2026 UTC, which is past the 24 hour
55
+ // life of any SEAL issued before the deploy. From then on a SEAL without
56
+ // ver is broken, unsupported_version. Unix seconds, the first second no
57
+ // longer accepted.
58
+ export const LEGACY_UNTIL = Date.UTC(2026, 8, 26) / 1000;
59
+ // One identity attestation reference, SEAL standard section 4a. A pointer
60
+ // to an attestation an external provider made, never the attestation, a
61
+ // name or a tenant id. kind is one of the four names or a URL for anything
62
+ // else. subject_hash is SHA-256 of the provider's subject id, base64url.
63
+ export const IdentityKind = z.union([
64
+ z.enum(['oidc', 'saml', 'verifiable_credential', 'kya']),
65
+ z.url().max(512),
66
+ ]);
67
+ export const IdentityReference = z.strictObject({
68
+ provider: z.url().max(512),
69
+ kind: IdentityKind,
70
+ ref: z.string().min(1).max(512),
71
+ subject_hash: z.string().regex(/^[A-Za-z0-9_-]{43}$/, 'SHA-256, base64url'),
72
+ attested_at: Seconds,
73
+ scope: z.enum(['operator', 'agent']),
74
+ });
75
+ // operator.verified in the SEAL. True when an operator scoped reference is
76
+ // held. The issuer drops a reference when its attestation expires or is
77
+ // revoked, so every reference it still holds is current.
78
+ export const operatorVerified = (identity) => identity.some((r) => r.scope === 'operator');
79
+ // Each score is 0 to 1, or null when unearned (standard section 2). A
80
+ // payload with a score outside that is malformed.
81
+ const Scores = z.partialRecord(Dimension, z.number().min(0).max(1).nullable());
82
+ // A SEAL lives at most 24 hours from issue, standard section 2. The issuer's
83
+ // CREDENTIAL_TTL_HOURS may not go above it, and a payload whose exp is
84
+ // further from its iat is malformed.
85
+ export const SEAL_MAX_TTL_SECONDS = 24 * 3600;
86
+ // How far ahead of the verifier's clock iat may be before a SEAL is not yet
87
+ // valid. Five minutes covers clock drift between issuer and verifier.
88
+ export const SEAL_CLOCK_SKEW_SECONDS = 300;
89
+ // iss on the issuer side is CREDENTIAL_ISSUER and nothing else. The API
90
+ // writes it and reads its stored SEALs back with CredentialPayload, so a
91
+ // stored SEAL with a legacy issuer fails that parse and is reissued. Only
92
+ // a verifier accepts a legacy issuer, through the Verified shapes below,
93
+ // and parseSealPayload checks the clock with acceptedIssuer first.
94
+ const IssuedIssuer = z.literal(CREDENTIAL_ISSUER);
95
+ const VerifiedIssuer = z.enum([CREDENTIAL_ISSUER, ...LEGACY_ISSUERS]);
96
+ const withinMaxTtl = (c) => c.exp - c.iat <= SEAL_MAX_TTL_SECONDS;
97
+ const MAX_TTL_MESSAGE = 'exp must be at most 24 hours after iat';
98
+ /*
99
+ * The SEAL payload, version 1 of the SEAL standard (section 2). Strict, it
100
+ * is what the API issues. version is agent_version under its old name, sent
101
+ * for one release so a verifier written against the old shape keeps
102
+ * working. VOU-77 drops it.
103
+ *
104
+ * counts are the standard's eight, over the 180 day window. last_active is
105
+ * Unix seconds of the agent's newest accepted event, null when it has sent
106
+ * none, and dormant_days whole days since then at issue, null with it.
107
+ */
108
+ const v1Payload = (iss) => z
109
+ .strictObject({
110
+ iss,
111
+ sub: AgentId,
112
+ ver: z.literal(SEAL_VERSION),
113
+ iat: Seconds,
114
+ exp: Seconds,
115
+ agent_version: Version,
116
+ version: Version,
117
+ level: Level,
118
+ scores: Scores,
119
+ counts: StandingCounts,
120
+ operator: z.strictObject({ verified: z.boolean() }),
121
+ identity: z.array(IdentityReference).max(16),
122
+ last_active: Seconds.nullable(),
123
+ dormant_days: Count.nullable(),
124
+ })
125
+ .refine((c) => c.exp > c.iat, 'exp must be after iat')
126
+ .refine(withinMaxTtl, MAX_TTL_MESSAGE)
127
+ .refine((c) => c.version === c.agent_version, 'version must equal agent_version');
128
+ // The payload issued before version 1, with no ver. Accepted by verifiers
129
+ // until LEGACY_UNTIL, never issued again. seed_tasks is optional because a
130
+ // SEAL issued before it was added has none.
131
+ const legacyPayload = (iss) => z
132
+ .strictObject({
133
+ iss,
134
+ sub: AgentId,
135
+ iat: Seconds,
136
+ exp: Seconds,
137
+ version: Version,
138
+ scores: Scores,
139
+ counts: z.strictObject({
140
+ events: Count,
141
+ verified_tasks: Count,
142
+ seed_tasks: Count.optional(),
143
+ }),
144
+ })
145
+ .refine((c) => c.exp > c.iat, 'exp must be after iat')
146
+ .refine(withinMaxTtl, MAX_TTL_MESSAGE);
147
+ // The issuer side. iss is CREDENTIAL_ISSUER only.
148
+ export const CredentialPayload = v1Payload(IssuedIssuer);
149
+ export const LegacyCredentialPayload = legacyPayload(IssuedIssuer);
150
+ // The verifier side. iss may also be a LEGACY_ISSUERS entry. The shape has
151
+ // no clock, so read these through parseSealPayload, never on their own.
152
+ export const VerifiedCredentialPayload = v1Payload(VerifiedIssuer);
153
+ export const VerifiedLegacyCredentialPayload = legacyPayload(VerifiedIssuer);
154
+ // Any payload a verifier accepts today, version 1 or legacy, from the
155
+ // current issuer or a legacy one.
156
+ export const SealPayload = z.union([
157
+ VerifiedCredentialPayload,
158
+ VerifiedLegacyCredentialPayload,
159
+ ]);
160
+ // A version 1 payload carries every legacy field too, so the guard is on
161
+ // version 1, the narrower of the two. Its false branch is the legacy shape.
162
+ export const isSealV1 = (p) => 'ver' in p;
163
+ const hasVer = (raw) => typeof raw === 'object' && raw !== null && 'ver' in raw;
164
+ /*
165
+ * Whether a verifier understands the version of a signed payload. Read
166
+ * after the signature and the issuer check out and before the shape. ver 1
167
+ * is understood. Any other ver is unsupported_version, as section 9 of the
168
+ * standard says, never valid with an unknown meaning. No ver at all is a
169
+ * legacy SEAL, accepted before LEGACY_UNTIL and unsupported_version from
170
+ * then on. Anything that is not an object is left to the shape check.
171
+ */
172
+ export function sealVersionProblem(raw, nowSeconds) {
173
+ if (typeof raw !== 'object' || raw === null)
174
+ return null;
175
+ if (hasVer(raw)) {
176
+ return raw.ver === SEAL_VERSION ? null : 'unsupported_version';
177
+ }
178
+ return nowSeconds < LEGACY_UNTIL ? null : 'unsupported_version';
179
+ }
180
+ /*
181
+ * The iat half of step 4 of the standard, section 3. "Check exp is in the
182
+ * future and iat is not." Every verifier calls this after the shape parse
183
+ * and right after its expiry check, in the standard's order, exp first and
184
+ * then iat. A SEAL whose iat is more than SEAL_CLOCK_SKEW_SECONDS ahead of
185
+ * the verifier's clock is not_yet_valid. Within the skew it is accepted, so
186
+ * a verifier whose clock runs a little slow does not break fresh SEALs.
187
+ */
188
+ export function sealIatProblem(iat, nowSeconds) {
189
+ return iat - nowSeconds > SEAL_CLOCK_SKEW_SECONDS ? 'not_yet_valid' : null;
190
+ }
191
+ // The issuer, then the version check above, then the shape for that
192
+ // version, in the standard's order. The API and the web read a verified
193
+ // payload through this. The CLI, which reads payloads loosely, calls
194
+ // acceptedIssuer and sealVersionProblem itself.
195
+ export function parseSealPayload(raw, nowSeconds) {
196
+ const iss = typeof raw === 'object' && raw !== null && 'iss' in raw
197
+ ? raw.iss
198
+ : undefined;
199
+ if (!acceptedIssuer(iss, nowSeconds)) {
200
+ return { ok: false, reason: 'wrong_issuer' };
201
+ }
202
+ const problem = sealVersionProblem(raw, nowSeconds);
203
+ if (problem)
204
+ return { ok: false, reason: problem };
205
+ const parsed = (hasVer(raw) ? VerifiedCredentialPayload : VerifiedLegacyCredentialPayload).safeParse(raw);
206
+ return parsed.success
207
+ ? { ok: true, payload: parsed.data }
208
+ : { ok: false, reason: 'malformed' };
209
+ }
210
+ export const WellKnownKey = z.strictObject({
211
+ kid: z.string().min(1).max(128),
212
+ kty: z.literal('OKP'),
213
+ crv: z.literal('Ed25519'),
214
+ alg: z.literal('EdDSA'),
215
+ x: Ed25519PublicKey,
216
+ });
217
+ export const WellKnown = z.strictObject({
218
+ keys: z.array(WellKnownKey).min(1).max(16),
219
+ });
220
+ const EXTENSION_DESCRIPTION = `SealKeeper SEAL, Signed Evidence of Agent Legitimacy. JWS compact, EdDSA, verify offline with the keys at ${WELL_KNOWN_URL}`;
221
+ // Every extension carries the same SEAL under the same params key. A card
222
+ // has the current one and the two old ones for one release, then only the
223
+ // current one (VOU-77).
224
+ export const CredentialExtension = z.strictObject({
225
+ uri: z.literal(CREDENTIAL_EXTENSION_URI),
226
+ description: z.string().min(1).max(512),
227
+ params: z.strictObject({ credential: Jws }),
228
+ });
229
+ export const LegacySealExtension = z.strictObject({
230
+ uri: z.literal(LEGACY_SEAL_EXTENSION_URI),
231
+ description: z.string().min(1).max(512),
232
+ params: z.strictObject({ credential: Jws }),
233
+ });
234
+ export const SealExtension = z.strictObject({
235
+ uri: z.literal(SEAL_EXTENSION_URI),
236
+ description: z.string().min(1).max(512),
237
+ params: z.strictObject({ credential: Jws }),
238
+ });
239
+ export const credentialExtension = (jws) => ({
240
+ uri: CREDENTIAL_EXTENSION_URI,
241
+ description: EXTENSION_DESCRIPTION,
242
+ params: { credential: jws },
243
+ });
244
+ export const legacySealExtension = (jws) => ({
245
+ uri: LEGACY_SEAL_EXTENSION_URI,
246
+ description: EXTENSION_DESCRIPTION,
247
+ params: { credential: jws },
248
+ });
249
+ export const sealExtension = (jws) => ({
250
+ uri: SEAL_EXTENSION_URI,
251
+ description: EXTENSION_DESCRIPTION,
252
+ params: { credential: jws },
253
+ });
254
+ // The extensions a card carries for one SEAL, in SEAL_EXTENSION_URIS order,
255
+ // the current URI first.
256
+ export const sealExtensions = (jws) => [
257
+ sealExtension(jws),
258
+ legacySealExtension(jws),
259
+ credentialExtension(jws),
260
+ ];
261
+ export const A2A_PROTOCOL_VERSION = '0.3.0';
262
+ export const AgentSkill = z.strictObject({
263
+ id: z.string().min(1).max(128),
264
+ name: z.string().min(1).max(128),
265
+ description: z.string().min(1).max(1024),
266
+ tags: z.array(z.string().min(1).max(64)).max(32),
267
+ examples: z.array(z.string().min(1).max(1024)).max(32).optional(),
268
+ });
269
+ const Modes = z.array(z.string().min(1).max(128)).max(32).default(['text']);
270
+ // The subset of the A2A agent card that Vouched emits, strict so the CLI
271
+ // never writes a field it did not mean to. Reading someone else's card uses
272
+ // the loose AgentCardResponse instead.
273
+ export const AgentCard = z.strictObject({
274
+ protocolVersion: z.literal(A2A_PROTOCOL_VERSION),
275
+ name: z.string().min(1).max(128),
276
+ description: z.string().min(1).max(1024),
277
+ url: z.url({ protocol: /^https$/ }).optional(),
278
+ version: z.string().min(1).max(64),
279
+ capabilities: z.strictObject({
280
+ extensions: z
281
+ .array(z.union([SealExtension, LegacySealExtension, CredentialExtension]))
282
+ .max(8),
283
+ }),
284
+ skills: z.array(AgentSkill).max(64),
285
+ defaultInputModes: Modes,
286
+ defaultOutputModes: Modes,
287
+ });