@sealkeeper/schema 0.4.2 → 0.4.4

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.
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { CountedCounts } from './standing.js';
2
3
  export declare const CREDENTIAL_ISSUER = "sealkeeper.run";
3
4
  export declare const LEGACY_ISSUERS: readonly ['vouched.run'];
4
5
  export declare const LEGACY_ISSUER_UNTIL: number;
@@ -13,6 +14,7 @@ export declare const CREDENTIAL_EXTENSION_URI = "https://vouched.run/ext/credent
13
14
  export declare const LEGACY_SEAL_EXTENSION_URIS: readonly string[];
14
15
  export declare const SEAL_EXTENSION_URIS: readonly string[];
15
16
  export declare const SEAL_VERSION = 1;
17
+ export declare const SEAL_VERSIONS: readonly [1, 2];
16
18
  export declare const LEGACY_UNTIL: number;
17
19
  export declare const IdentityKind: z.ZodUnion<readonly [z.ZodEnum<{
18
20
  kya: "kya";
@@ -94,6 +96,65 @@ export declare const CredentialPayload: z.ZodObject<{
94
96
  dormant_days: z.ZodNullable<z.ZodInt>;
95
97
  }, z.core.$strict>;
96
98
  export type CredentialPayload = z.infer<typeof CredentialPayload>;
99
+ export declare const CredentialPayloadV2: z.ZodObject<{
100
+ iss: z.ZodLiteral<"sealkeeper.run">;
101
+ sub: z.ZodString;
102
+ ver: z.ZodLiteral<2>;
103
+ iat: z.ZodInt;
104
+ exp: z.ZodInt;
105
+ agent_version: z.ZodString;
106
+ version: z.ZodString;
107
+ level: z.ZodEnum<{
108
+ bronze: "bronze";
109
+ gold: "gold";
110
+ none: "none";
111
+ silver: "silver";
112
+ }>;
113
+ scores: z.ZodRecord<z.ZodUnion<readonly [z.ZodEnum<{
114
+ cost_latency: "cost_latency";
115
+ provenance: "provenance";
116
+ reliability: "reliability";
117
+ safety: "safety";
118
+ }>, z.ZodTemplateLiteral<`competence:${string}`>]> & z.core.$partial, z.ZodNullable<z.ZodNumber>>;
119
+ counts: z.ZodObject<{
120
+ events: z.ZodInt;
121
+ history_days: z.ZodInt;
122
+ verified_tasks: z.ZodInt;
123
+ seed_tasks: z.ZodInt;
124
+ server_checked_tasks: z.ZodInt;
125
+ confirmed_tasks: z.ZodInt;
126
+ distinct_operators: z.ZodInt;
127
+ safety_incidents_90d: z.ZodInt;
128
+ }, z.core.$strict>;
129
+ counted: z.ZodObject<{
130
+ verified_tasks: z.ZodInt;
131
+ seed_tasks: z.ZodInt;
132
+ server_checked_tasks: z.ZodInt;
133
+ confirmed_tasks: z.ZodInt;
134
+ }, z.core.$strict>;
135
+ operator: z.ZodObject<{
136
+ verified: z.ZodBoolean;
137
+ }, z.core.$strict>;
138
+ identity: z.ZodArray<z.ZodObject<{
139
+ provider: z.ZodURL;
140
+ kind: z.ZodUnion<readonly [z.ZodEnum<{
141
+ kya: "kya";
142
+ oidc: "oidc";
143
+ saml: "saml";
144
+ verifiable_credential: "verifiable_credential";
145
+ }>, z.ZodURL]>;
146
+ ref: z.ZodString;
147
+ subject_hash: z.ZodString;
148
+ attested_at: z.ZodInt;
149
+ scope: z.ZodEnum<{
150
+ agent: "agent";
151
+ operator: "operator";
152
+ }>;
153
+ }, z.core.$strict>>;
154
+ last_active: z.ZodNullable<z.ZodInt>;
155
+ dormant_days: z.ZodNullable<z.ZodInt>;
156
+ }, z.core.$strict>;
157
+ export type CredentialPayloadV2 = z.infer<typeof CredentialPayloadV2>;
97
158
  export declare const LegacyCredentialPayload: z.ZodObject<{
98
159
  iss: z.ZodLiteral<"sealkeeper.run">;
99
160
  sub: z.ZodString;
@@ -169,6 +230,68 @@ export declare const VerifiedCredentialPayload: z.ZodObject<{
169
230
  dormant_days: z.ZodNullable<z.ZodInt>;
170
231
  }, z.core.$strict>;
171
232
  export type VerifiedCredentialPayload = z.infer<typeof VerifiedCredentialPayload>;
233
+ export declare const VerifiedCredentialPayloadV2: z.ZodObject<{
234
+ iss: z.ZodEnum<{
235
+ "sealkeeper.run": "sealkeeper.run";
236
+ "vouched.run": "vouched.run";
237
+ }>;
238
+ sub: z.ZodString;
239
+ ver: z.ZodLiteral<2>;
240
+ iat: z.ZodInt;
241
+ exp: z.ZodInt;
242
+ agent_version: z.ZodString;
243
+ version: z.ZodString;
244
+ level: z.ZodEnum<{
245
+ bronze: "bronze";
246
+ gold: "gold";
247
+ none: "none";
248
+ silver: "silver";
249
+ }>;
250
+ scores: z.ZodRecord<z.ZodUnion<readonly [z.ZodEnum<{
251
+ cost_latency: "cost_latency";
252
+ provenance: "provenance";
253
+ reliability: "reliability";
254
+ safety: "safety";
255
+ }>, z.ZodTemplateLiteral<`competence:${string}`>]> & z.core.$partial, z.ZodNullable<z.ZodNumber>>;
256
+ counts: z.ZodObject<{
257
+ events: z.ZodInt;
258
+ history_days: z.ZodInt;
259
+ verified_tasks: z.ZodInt;
260
+ seed_tasks: z.ZodInt;
261
+ server_checked_tasks: z.ZodInt;
262
+ confirmed_tasks: z.ZodInt;
263
+ distinct_operators: z.ZodInt;
264
+ safety_incidents_90d: z.ZodInt;
265
+ }, z.core.$strict>;
266
+ counted: z.ZodObject<{
267
+ verified_tasks: z.ZodInt;
268
+ seed_tasks: z.ZodInt;
269
+ server_checked_tasks: z.ZodInt;
270
+ confirmed_tasks: z.ZodInt;
271
+ }, z.core.$strict>;
272
+ operator: z.ZodObject<{
273
+ verified: z.ZodBoolean;
274
+ }, z.core.$strict>;
275
+ identity: z.ZodArray<z.ZodObject<{
276
+ provider: z.ZodURL;
277
+ kind: z.ZodUnion<readonly [z.ZodEnum<{
278
+ kya: "kya";
279
+ oidc: "oidc";
280
+ saml: "saml";
281
+ verifiable_credential: "verifiable_credential";
282
+ }>, z.ZodURL]>;
283
+ ref: z.ZodString;
284
+ subject_hash: z.ZodString;
285
+ attested_at: z.ZodInt;
286
+ scope: z.ZodEnum<{
287
+ agent: "agent";
288
+ operator: "operator";
289
+ }>;
290
+ }, z.core.$strict>>;
291
+ last_active: z.ZodNullable<z.ZodInt>;
292
+ dormant_days: z.ZodNullable<z.ZodInt>;
293
+ }, z.core.$strict>;
294
+ export type VerifiedCredentialPayloadV2 = z.infer<typeof VerifiedCredentialPayloadV2>;
172
295
  export declare const VerifiedLegacyCredentialPayload: z.ZodObject<{
173
296
  iss: z.ZodEnum<{
174
297
  "sealkeeper.run": "sealkeeper.run";
@@ -245,6 +368,66 @@ export declare const SealPayload: z.ZodUnion<readonly [z.ZodObject<{
245
368
  }, z.core.$strict>>;
246
369
  last_active: z.ZodNullable<z.ZodInt>;
247
370
  dormant_days: z.ZodNullable<z.ZodInt>;
371
+ }, z.core.$strict>, z.ZodObject<{
372
+ iss: z.ZodEnum<{
373
+ "sealkeeper.run": "sealkeeper.run";
374
+ "vouched.run": "vouched.run";
375
+ }>;
376
+ sub: z.ZodString;
377
+ ver: z.ZodLiteral<2>;
378
+ iat: z.ZodInt;
379
+ exp: z.ZodInt;
380
+ agent_version: z.ZodString;
381
+ version: z.ZodString;
382
+ level: z.ZodEnum<{
383
+ bronze: "bronze";
384
+ gold: "gold";
385
+ none: "none";
386
+ silver: "silver";
387
+ }>;
388
+ scores: z.ZodRecord<z.ZodUnion<readonly [z.ZodEnum<{
389
+ cost_latency: "cost_latency";
390
+ provenance: "provenance";
391
+ reliability: "reliability";
392
+ safety: "safety";
393
+ }>, z.ZodTemplateLiteral<`competence:${string}`>]> & z.core.$partial, z.ZodNullable<z.ZodNumber>>;
394
+ counts: z.ZodObject<{
395
+ events: z.ZodInt;
396
+ history_days: z.ZodInt;
397
+ verified_tasks: z.ZodInt;
398
+ seed_tasks: z.ZodInt;
399
+ server_checked_tasks: z.ZodInt;
400
+ confirmed_tasks: z.ZodInt;
401
+ distinct_operators: z.ZodInt;
402
+ safety_incidents_90d: z.ZodInt;
403
+ }, z.core.$strict>;
404
+ counted: z.ZodObject<{
405
+ verified_tasks: z.ZodInt;
406
+ seed_tasks: z.ZodInt;
407
+ server_checked_tasks: z.ZodInt;
408
+ confirmed_tasks: z.ZodInt;
409
+ }, z.core.$strict>;
410
+ operator: z.ZodObject<{
411
+ verified: z.ZodBoolean;
412
+ }, z.core.$strict>;
413
+ identity: z.ZodArray<z.ZodObject<{
414
+ provider: z.ZodURL;
415
+ kind: z.ZodUnion<readonly [z.ZodEnum<{
416
+ kya: "kya";
417
+ oidc: "oidc";
418
+ saml: "saml";
419
+ verifiable_credential: "verifiable_credential";
420
+ }>, z.ZodURL]>;
421
+ ref: z.ZodString;
422
+ subject_hash: z.ZodString;
423
+ attested_at: z.ZodInt;
424
+ scope: z.ZodEnum<{
425
+ agent: "agent";
426
+ operator: "operator";
427
+ }>;
428
+ }, z.core.$strict>>;
429
+ last_active: z.ZodNullable<z.ZodInt>;
430
+ dormant_days: z.ZodNullable<z.ZodInt>;
248
431
  }, z.core.$strict>, z.ZodObject<{
249
432
  iss: z.ZodEnum<{
250
433
  "sealkeeper.run": "sealkeeper.run";
@@ -267,7 +450,9 @@ export declare const SealPayload: z.ZodUnion<readonly [z.ZodObject<{
267
450
  }, z.core.$strict>;
268
451
  }, z.core.$strict>]>;
269
452
  export type SealPayload = z.infer<typeof SealPayload>;
270
- export declare const isSealV1: (p: SealPayload) => p is VerifiedCredentialPayload;
453
+ export type VersionedSealPayload = VerifiedCredentialPayload | VerifiedCredentialPayloadV2;
454
+ export declare const isSealV1: (p: SealPayload) => p is VersionedSealPayload;
455
+ export declare const sealCounted: (p: SealPayload) => CountedCounts | null;
271
456
  export declare function sealVersionProblem(raw: unknown, nowSeconds: number): 'unsupported_version' | null;
272
457
  export declare function sealIatProblem(iat: number, nowSeconds: number): 'not_yet_valid' | null;
273
458
  export type SealPayloadResult = {
@@ -3,7 +3,7 @@ import { AgentId, Ed25519PublicKey } from './agent-id.js';
3
3
  import { Dimension } from './dimensions.js';
4
4
  import { Jws } from './envelope.js';
5
5
  import { Version } from './events.js';
6
- import { Level, StandingCounts } from './standing.js';
6
+ import { CountedCounts, Level, StandingCounts } from './standing.js';
7
7
  // The issuer every SEAL carries as iss from the SealKeeper cutover on.
8
8
  export const CREDENTIAL_ISSUER = 'sealkeeper.run';
9
9
  // Issuers a verifier still accepts for a while after the cutover. A SEAL
@@ -50,6 +50,12 @@ const Seconds = z.int().min(0);
50
50
  const Count = z.int().min(0);
51
51
  // The version of the SEAL standard this issuer writes, carried as ver.
52
52
  export const SEAL_VERSION = 1;
53
+ // Every version a verifier understands. Version 2 is version 1 plus
54
+ // `counted`, the counted evidence the level read (VOU-139). CLIs 0.4.x
55
+ // understand version 1 only and refuse any other ver, so the issuer keeps
56
+ // writing version 1 until they are gone, and verifiers from this release
57
+ // on accept both. SEAL standard section 9.
58
+ export const SEAL_VERSIONS = [1, 2];
53
59
  // SEALs issued before version 1 carry no ver. Verifiers accept them as
54
60
  // legacy until the end of 25 September 2026 UTC, which is past the 24 hour
55
61
  // life of any SEAL issued before the deploy. From then on a SEAL without
@@ -125,6 +131,35 @@ const v1Payload = (iss) => z
125
131
  .refine((c) => c.exp > c.iat, 'exp must be after iat')
126
132
  .refine(withinMaxTtl, MAX_TTL_MESSAGE)
127
133
  .refine((c) => c.version === c.agent_version, 'version must equal agent_version');
134
+ /*
135
+ * Version 2. Every version 1 field with the same meaning, plus counted, the
136
+ * counted evidence the level read (CountedCounts). counts stay the raw
137
+ * facts. Each counted value is at most its raw count.
138
+ */
139
+ const v2Payload = (iss) => z
140
+ .strictObject({
141
+ iss,
142
+ sub: AgentId,
143
+ ver: z.literal(2),
144
+ iat: Seconds,
145
+ exp: Seconds,
146
+ agent_version: Version,
147
+ version: Version,
148
+ level: Level,
149
+ scores: Scores,
150
+ counts: StandingCounts,
151
+ counted: CountedCounts,
152
+ operator: z.strictObject({ verified: z.boolean() }),
153
+ identity: z.array(IdentityReference).max(16),
154
+ last_active: Seconds.nullable(),
155
+ dormant_days: Count.nullable(),
156
+ })
157
+ .refine((c) => c.exp > c.iat, 'exp must be after iat')
158
+ .refine(withinMaxTtl, MAX_TTL_MESSAGE)
159
+ .refine((c) => c.version === c.agent_version, 'version must equal agent_version')
160
+ .refine((c) => c.counted.seed_tasks <= c.counts.seed_tasks &&
161
+ c.counted.server_checked_tasks <= c.counts.server_checked_tasks &&
162
+ c.counted.confirmed_tasks <= c.counts.confirmed_tasks, 'counted must not exceed counts');
128
163
  // The payload issued before version 1, with no ver. Accepted by verifiers
129
164
  // until LEGACY_UNTIL, never issued again. seed_tasks is optional because a
130
165
  // SEAL issued before it was added has none.
@@ -146,25 +181,31 @@ const legacyPayload = (iss) => z
146
181
  .refine(withinMaxTtl, MAX_TTL_MESSAGE);
147
182
  // The issuer side. iss is CREDENTIAL_ISSUER only.
148
183
  export const CredentialPayload = v1Payload(IssuedIssuer);
184
+ export const CredentialPayloadV2 = v2Payload(IssuedIssuer);
149
185
  export const LegacyCredentialPayload = legacyPayload(IssuedIssuer);
150
186
  // The verifier side. iss may also be a LEGACY_ISSUERS entry. The shape has
151
187
  // no clock, so read these through parseSealPayload, never on their own.
152
188
  export const VerifiedCredentialPayload = v1Payload(VerifiedIssuer);
189
+ export const VerifiedCredentialPayloadV2 = v2Payload(VerifiedIssuer);
153
190
  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.
191
+ // Any payload a verifier accepts today, version 1, version 2 or legacy,
192
+ // from the current issuer or a legacy one.
156
193
  export const SealPayload = z.union([
157
194
  VerifiedCredentialPayload,
195
+ VerifiedCredentialPayloadV2,
158
196
  VerifiedLegacyCredentialPayload,
159
197
  ]);
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.
198
+ // A versioned payload carries every legacy field too, so the guard is on
199
+ // ver, the narrower of the two. Its false branch is the legacy shape. The
200
+ // name is kept from when version 1 was the only one.
162
201
  export const isSealV1 = (p) => 'ver' in p;
202
+ // The counted evidence a SEAL carries, version 2 on, null before.
203
+ export const sealCounted = (p) => 'counted' in p ? p.counted : null;
163
204
  const hasVer = (raw) => typeof raw === 'object' && raw !== null && 'ver' in raw;
164
205
  /*
165
206
  * Whether a verifier understands the version of a signed payload. Read
166
207
  * 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
208
+ * and 2 (SEAL_VERSIONS) are understood. Any other ver is unsupported_version, as section 9 of the
168
209
  * standard says, never valid with an unknown meaning. No ver at all is a
169
210
  * legacy SEAL, accepted before LEGACY_UNTIL and unsupported_version from
170
211
  * then on. Anything that is not an object is left to the shape check.
@@ -173,7 +214,9 @@ export function sealVersionProblem(raw, nowSeconds) {
173
214
  if (typeof raw !== 'object' || raw === null)
174
215
  return null;
175
216
  if (hasVer(raw)) {
176
- return raw.ver === SEAL_VERSION ? null : 'unsupported_version';
217
+ return SEAL_VERSIONS.includes(raw.ver)
218
+ ? null
219
+ : 'unsupported_version';
177
220
  }
178
221
  return nowSeconds < LEGACY_UNTIL ? null : 'unsupported_version';
179
222
  }
@@ -202,7 +245,11 @@ export function parseSealPayload(raw, nowSeconds) {
202
245
  const problem = sealVersionProblem(raw, nowSeconds);
203
246
  if (problem)
204
247
  return { ok: false, reason: problem };
205
- const parsed = (hasVer(raw) ? VerifiedCredentialPayload : VerifiedLegacyCredentialPayload).safeParse(raw);
248
+ const parsed = (!hasVer(raw)
249
+ ? VerifiedLegacyCredentialPayload
250
+ : raw.ver === 2
251
+ ? VerifiedCredentialPayloadV2
252
+ : VerifiedCredentialPayload).safeParse(raw);
206
253
  return parsed.success
207
254
  ? { ok: true, payload: parsed.data }
208
255
  : { ok: false, reason: 'malformed' };
@@ -555,6 +555,76 @@ export declare function createDb(url: string, options?: DbOptions): import("driz
555
555
  identity: undefined;
556
556
  generated: undefined;
557
557
  }, {}, {}>;
558
+ assigneeAgentId: import("drizzle-orm/pg-core").PgColumn<{
559
+ name: "assignee_agent_id";
560
+ tableName: "tasks";
561
+ dataType: "string";
562
+ columnType: "PgText";
563
+ data: string;
564
+ driverParam: string;
565
+ notNull: false;
566
+ hasDefault: false;
567
+ isPrimaryKey: false;
568
+ isAutoincrement: false;
569
+ hasRuntimeDefault: false;
570
+ enumValues: [string, ...string[]];
571
+ baseColumn: never;
572
+ identity: undefined;
573
+ generated: undefined;
574
+ }, {}, {}>;
575
+ pairSettledAt: import("drizzle-orm/pg-core").PgColumn<{
576
+ name: "pair_settled_at";
577
+ tableName: "tasks";
578
+ dataType: "date";
579
+ columnType: "PgTimestamp";
580
+ data: Date;
581
+ driverParam: string;
582
+ notNull: false;
583
+ hasDefault: false;
584
+ isPrimaryKey: false;
585
+ isAutoincrement: false;
586
+ hasRuntimeDefault: false;
587
+ enumValues: undefined;
588
+ baseColumn: never;
589
+ identity: undefined;
590
+ generated: undefined;
591
+ }, {}, {}>;
592
+ overPairCap: import("drizzle-orm/pg-core").PgColumn<{
593
+ name: "over_pair_cap";
594
+ tableName: "tasks";
595
+ dataType: "boolean";
596
+ columnType: "PgBoolean";
597
+ data: boolean;
598
+ driverParam: boolean;
599
+ notNull: true;
600
+ hasDefault: true;
601
+ isPrimaryKey: false;
602
+ isAutoincrement: false;
603
+ hasRuntimeDefault: false;
604
+ enumValues: undefined;
605
+ baseColumn: never;
606
+ identity: undefined;
607
+ generated: undefined;
608
+ }, {}, {}>;
609
+ origin: import("drizzle-orm/pg-core").PgColumn<{
610
+ name: "origin";
611
+ tableName: "tasks";
612
+ dataType: "string";
613
+ columnType: "PgText";
614
+ data: "manual" | "routine" | "template";
615
+ driverParam: string;
616
+ notNull: true;
617
+ hasDefault: true;
618
+ isPrimaryKey: false;
619
+ isAutoincrement: false;
620
+ hasRuntimeDefault: false;
621
+ enumValues: [string, ...string[]];
622
+ baseColumn: never;
623
+ identity: undefined;
624
+ generated: undefined;
625
+ }, {}, {
626
+ $type: "manual" | "routine" | "template";
627
+ }>;
558
628
  taskType: import("drizzle-orm/pg-core").PgColumn<{
559
629
  name: "task_type";
560
630
  tableName: "tasks";
@@ -840,6 +910,25 @@ export declare function createDb(url: string, options?: DbOptions): import("driz
840
910
  identity: undefined;
841
911
  generated: undefined;
842
912
  }, {}, {}>;
913
+ origin: import("drizzle-orm/pg-core").PgColumn<{
914
+ name: "origin";
915
+ tableName: "task_outcomes";
916
+ dataType: "string";
917
+ columnType: "PgText";
918
+ data: "manual" | "routine" | "template";
919
+ driverParam: string;
920
+ notNull: true;
921
+ hasDefault: true;
922
+ isPrimaryKey: false;
923
+ isAutoincrement: false;
924
+ hasRuntimeDefault: false;
925
+ enumValues: [string, ...string[]];
926
+ baseColumn: never;
927
+ identity: undefined;
928
+ generated: undefined;
929
+ }, {}, {
930
+ $type: "manual" | "routine" | "template";
931
+ }>;
843
932
  };
844
933
  dialect: 'pg';
845
934
  }>;
@@ -1416,6 +1505,25 @@ export declare function createDb(url: string, options?: DbOptions): import("driz
1416
1505
  }, {}, {
1417
1506
  $type: import("./standing.js").StoredCounts;
1418
1507
  }>;
1508
+ levelInputs: import("drizzle-orm/pg-core").PgColumn<{
1509
+ name: "level_inputs";
1510
+ tableName: "standing";
1511
+ dataType: "json";
1512
+ columnType: "PgJsonb";
1513
+ data: import("./standing.js").StoredLevelInputs;
1514
+ driverParam: unknown;
1515
+ notNull: false;
1516
+ hasDefault: false;
1517
+ isPrimaryKey: false;
1518
+ isAutoincrement: false;
1519
+ hasRuntimeDefault: false;
1520
+ enumValues: undefined;
1521
+ baseColumn: never;
1522
+ identity: undefined;
1523
+ generated: undefined;
1524
+ }, {}, {
1525
+ $type: import("./standing.js").StoredLevelInputs;
1526
+ }>;
1419
1527
  historyDays: import("drizzle-orm/pg-core").PgColumn<{
1420
1528
  name: "history_days";
1421
1529
  tableName: "standing";
@@ -27,7 +27,7 @@ export { operators } from './operators.js';
27
27
  export { quotaCounters } from './quota-counters.js';
28
28
  export { ratings } from './ratings.js';
29
29
  export { scores } from './scores.js';
30
- export { type StoredCounts, standing } from './standing.js';
30
+ export { type StoredCounts, type StoredLevelInputs, standing, } from './standing.js';
31
31
  export { taskOutcomes } from './task-outcomes.js';
32
32
  export { tasks } from './tasks.js';
33
33
  export { timestamps } from './timestamps.js';
package/dist/db/index.js CHANGED
@@ -17,7 +17,7 @@ export { operators } from './operators.js';
17
17
  export { quotaCounters } from './quota-counters.js';
18
18
  export { ratings } from './ratings.js';
19
19
  export { scores } from './scores.js';
20
- export { standing } from './standing.js';
20
+ export { standing, } from './standing.js';
21
21
  export { taskOutcomes } from './task-outcomes.js';
22
22
  export { tasks } from './tasks.js';
23
23
  export { timestamps } from './timestamps.js';
@@ -10,6 +10,22 @@ export type StoredCounts = {
10
10
  confirmed_operators: number;
11
11
  history_span_days: number;
12
12
  safety_incidents_180d: number;
13
+ gold_confirmed_tasks: number;
14
+ gold_confirmed_operators: number;
15
+ counted_verified_tasks: number;
16
+ counted_seed_tasks: number;
17
+ counted_server_checked_tasks: number;
18
+ counted_confirmed_tasks: number;
19
+ counted_gold_confirmed_tasks: number;
20
+ };
21
+ export type StoredLevelInputs = {
22
+ reliability: number | null;
23
+ safety: number | null;
24
+ provenance: number | null;
25
+ model_declared: boolean;
26
+ operator_verified: boolean;
27
+ ratings: number;
28
+ ratings_net_positive: boolean;
13
29
  };
14
30
  export declare const standing: import("drizzle-orm/pg-core").PgTableWithColumns<{
15
31
  name: "standing";
@@ -121,6 +137,25 @@ export declare const standing: import("drizzle-orm/pg-core").PgTableWithColumns<
121
137
  }, {}, {
122
138
  $type: StoredCounts;
123
139
  }>;
140
+ levelInputs: import("drizzle-orm/pg-core").PgColumn<{
141
+ name: "level_inputs";
142
+ tableName: "standing";
143
+ dataType: "json";
144
+ columnType: "PgJsonb";
145
+ data: StoredLevelInputs;
146
+ driverParam: unknown;
147
+ notNull: false;
148
+ hasDefault: false;
149
+ isPrimaryKey: false;
150
+ isAutoincrement: false;
151
+ hasRuntimeDefault: false;
152
+ enumValues: undefined;
153
+ baseColumn: never;
154
+ identity: undefined;
155
+ generated: undefined;
156
+ }, {}, {
157
+ $type: StoredLevelInputs;
158
+ }>;
124
159
  historyDays: import("drizzle-orm/pg-core").PgColumn<{
125
160
  name: "history_days";
126
161
  tableName: "standing";
@@ -9,6 +9,8 @@ import { timestamps } from './timestamps.js';
9
9
  // true at 90 or more, when the level is none and no SEAL is issued until
10
10
  // activity resumes. counts are the ones the level stands on, which for a
11
11
  // new version include what it inherited from the previous one.
12
+ // level_inputs are the scores and flags the level read, null on a row
13
+ // written before they were stored, until the agent's next run.
12
14
  export const standing = pgTable('standing', {
13
15
  agentId: text('agent_id')
14
16
  .notNull()
@@ -16,6 +18,7 @@ export const standing = pgTable('standing', {
16
18
  version: text('version').notNull(),
17
19
  level: text('level').$type().notNull(),
18
20
  counts: jsonb('counts').$type().notNull(),
21
+ levelInputs: jsonb('level_inputs').$type(),
19
22
  historyDays: integer('history_days').notNull(),
20
23
  lastActive: timestamp('last_active', { withTimezone: true }),
21
24
  dormantDays: integer('dormant_days'),
@@ -121,6 +121,25 @@ export declare const taskOutcomes: import("drizzle-orm/pg-core").PgTableWithColu
121
121
  identity: undefined;
122
122
  generated: undefined;
123
123
  }, {}, {}>;
124
+ origin: import("drizzle-orm/pg-core").PgColumn<{
125
+ name: "origin";
126
+ tableName: "task_outcomes";
127
+ dataType: "string";
128
+ columnType: "PgText";
129
+ data: "manual" | "routine" | "template";
130
+ driverParam: string;
131
+ notNull: true;
132
+ hasDefault: true;
133
+ isPrimaryKey: false;
134
+ isAutoincrement: false;
135
+ hasRuntimeDefault: false;
136
+ enumValues: [string, ...string[]];
137
+ baseColumn: never;
138
+ identity: undefined;
139
+ generated: undefined;
140
+ }, {}, {
141
+ $type: "manual" | "routine" | "template";
142
+ }>;
124
143
  };
125
144
  dialect: 'pg';
126
145
  }>;
@@ -1,4 +1,5 @@
1
- import { jsonb, pgTable, text, unique, uuid } from 'drizzle-orm/pg-core';
1
+ import { sql } from 'drizzle-orm';
2
+ import { check, jsonb, pgTable, text, unique, uuid } from 'drizzle-orm/pg-core';
2
3
  import { agents } from './agents.js';
3
4
  import { tasks } from './tasks.js';
4
5
  import { timestamps } from './timestamps.js';
@@ -12,7 +13,13 @@ export const taskOutcomes = pgTable('task_outcomes', {
12
13
  .references(() => agents.id),
13
14
  outcome: text('outcome').notNull(),
14
15
  evidence: jsonb('evidence'),
16
+ // Where this report came from, TaskOrigin in ../api.ts, from the signed
17
+ // outcome payload. manual when the payload has none. A new report
18
+ // replaces it with the rest. Gold leaves out a confirmed task either of
19
+ // whose reports is routine.
20
+ origin: text('origin').$type().notNull().default('manual'),
15
21
  ...timestamps,
16
22
  }, (t) => [
23
+ check('task_outcomes_origin', sql `${t.origin} in ('manual', 'template', 'routine')`),
17
24
  unique('task_outcomes_task_id_reporting_agent_id_unique').on(t.taskId, t.reportingAgentId),
18
25
  ]);