@sealkeeper/schema 0.4.4 → 0.4.6

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 (54) hide show
  1. package/dist/agent-name.d.ts +1 -1
  2. package/dist/agent-name.js +4 -4
  3. package/dist/api.d.ts +625 -33
  4. package/dist/api.js +262 -57
  5. package/dist/badge.d.ts +1 -0
  6. package/dist/badge.js +7 -0
  7. package/dist/client-address.d.ts +6 -0
  8. package/dist/client-address.js +81 -0
  9. package/dist/db/agents.d.ts +155 -0
  10. package/dist/db/agents.js +38 -0
  11. package/dist/db/client.d.ts +431 -0
  12. package/dist/db/client.js +24 -1
  13. package/dist/db/events.js +7 -0
  14. package/dist/db/index.d.ts +16 -0
  15. package/dist/db/index.js +4 -0
  16. package/dist/db/migrate.js +5 -1
  17. package/dist/db/migrator.d.ts +5 -1
  18. package/dist/db/migrator.js +18 -2
  19. package/dist/db/operator-identities.d.ts +211 -0
  20. package/dist/db/operator-identities.js +49 -0
  21. package/dist/db/operator-level-grants.d.ts +109 -0
  22. package/dist/db/operator-level-grants.js +30 -0
  23. package/dist/db/operator-slugs.d.ts +92 -0
  24. package/dist/db/operator-slugs.js +25 -0
  25. package/dist/db/operators.d.ts +119 -0
  26. package/dist/db/operators.js +30 -2
  27. package/dist/db/standing.d.ts +1 -0
  28. package/dist/db/standing.js +2 -0
  29. package/dist/db/task-claim-failures.d.ts +143 -0
  30. package/dist/db/task-claim-failures.js +37 -0
  31. package/dist/db/tasks.d.ts +60 -0
  32. package/dist/db/tasks.js +19 -1
  33. package/dist/envelope.d.ts +3 -0
  34. package/dist/envelope.js +16 -11
  35. package/dist/goal.d.ts +62 -1
  36. package/dist/goal.js +70 -11
  37. package/dist/index.d.ts +7 -0
  38. package/dist/index.js +7 -0
  39. package/dist/json-shape.d.ts +9 -0
  40. package/dist/json-shape.js +70 -0
  41. package/dist/moderation.d.ts +29 -0
  42. package/dist/moderation.js +547 -0
  43. package/dist/operator-domains.d.ts +104 -0
  44. package/dist/operator-domains.js +85 -0
  45. package/dist/policy.d.ts +4 -0
  46. package/dist/policy.js +10 -0
  47. package/dist/runtime.d.ts +17 -0
  48. package/dist/runtime.js +61 -0
  49. package/dist/seal-conformance.js +2 -0
  50. package/dist/standing.d.ts +27 -8
  51. package/dist/standing.js +59 -22
  52. package/dist/tasks.d.ts +25 -1
  53. package/dist/tasks.js +43 -9
  54. package/package.json +1 -1
package/dist/goal.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { AgentId } from './agent-id.js';
3
3
  import { Version } from './events.js';
4
- import { Level } from './standing.js';
4
+ import { LADDER, Level } from './standing.js';
5
5
  // GET /v1/agents/:id/goal. What the agent's current version needs for its
6
6
  // next level, threshold by threshold, and what to do next. The API sends
7
7
  // these strictly. A client parses them loosely (packages/cli/src/responses.ts),
@@ -15,6 +15,11 @@ export const GOAL_ACTION_CODES = [
15
15
  // The agent has sent nothing accepted for a while and its level drops.
16
16
  // count is the dormant days.
17
17
  'dormant',
18
+ // The operator's verified domain was missing at its last check and the
19
+ // grace is running (VOU-185). operator_verified, which gold needs, goes
20
+ // false when it ends. count is the whole days left and until the moment
21
+ // it ends. Sent at any level.
22
+ 'operator_verification_lapsing',
18
23
  // Counterparty tasks this agent claimed wait for its outcome report. A
19
24
  // confirmed task counts for its claimant, so this counts toward the
20
25
  // agent's own level. count is how many.
@@ -22,10 +27,12 @@ export const GOAL_ACTION_CODES = [
22
27
  // Tasks addressed to this agent are waiting to be claimed. count is how
23
28
  // many.
24
29
  'addressed_waiting',
25
- // Verified seed tasks still needed for bronze. Only ever toward bronze.
30
+ // Verified tasks still needed. Seed tasks count toward it at every level
31
+ // (VOU-172). count is how many.
26
32
  'claim_seed_tasks',
27
- // Verified tasks from other operators' agents still needed. count is the
28
- // larger gap of the task thresholds it covers.
33
+ // Verified tasks from other operators' agents still needed. No threshold
34
+ // sends it since VOU-172, where seed tasks count at every level. Kept so
35
+ // a client that knows it keeps working.
29
36
  'claim_tasks',
30
37
  // Confirmed counterparty tasks with other operators still needed.
31
38
  'counterparty_tasks',
@@ -38,11 +45,15 @@ export const GOAL_ACTION_CODES = [
38
45
  'safety_below',
39
46
  // An incident in the window. count is the incidents counted.
40
47
  'safety_incident_window',
48
+ // Gold's clean record, days since the later of the first accepted event
49
+ // and the last incident, is short. count is the days still to go.
50
+ 'clean_days',
41
51
  // The version's share of the agent's events is under the threshold.
42
52
  'provenance_below',
43
53
  // No model declared on the card or in a usage event.
44
54
  'declare_model',
45
- // Operator identity not verified beyond a GitHub login.
55
+ // Operator identity not verified beyond a GitHub login. The operator
56
+ // verifies a domain on the account page (VOU-185).
46
57
  'operator_unverified',
47
58
  // Ratings from silver or gold agents still needed.
48
59
  'need_ratings',
@@ -50,6 +61,10 @@ export const GOAL_ACTION_CODES = [
50
61
  // version, and the new version's level is capped one below that
51
62
  // version's until its own record earns it.
52
63
  'version_cap',
64
+ // Every silver threshold holds, and the operator's silver slots are all
65
+ // taken (OPERATOR_SILVER_CAP), so the agent is held at bronze. count is
66
+ // the whole days until the next slot frees and until the moment it does.
67
+ 'operator_silver_cap',
53
68
  // Counterparty tasks this agent posted wait for its outcome report. It
54
69
  // helps the claimant, the other agent, and adds nothing to this agent's
55
70
  // level, so it comes after every step that does. count is how many.
@@ -71,17 +86,59 @@ export const GoalThreshold = z.strictObject({
71
86
  raw: z.number().nullable(),
72
87
  });
73
88
  // One next step. code is machine readable, count what is left where a
74
- // number says it, else null.
89
+ // number says it, else null. until is when the step clears by itself, sent
90
+ // only with operator_silver_cap. Clients parse actions loosely, so one
91
+ // that does not know until ignores it.
75
92
  export const GoalAction = z.strictObject({
76
93
  code: z.string().min(1).max(64),
77
94
  count: Count.nullable(),
95
+ until: z.iso.datetime().optional(),
96
+ });
97
+ // Where one level of LADDER stands for the agent. reached is the stored
98
+ // level and every level below it. next is the issued level above it, the
99
+ // same as nextLevel. locked is an issued level above next. reserved is a
100
+ // level the standard names and does not issue yet (platinum), whatever the
101
+ // agent has, so a client shows it as coming later.
102
+ export const GOAL_LADDER_STATES = [
103
+ 'reached',
104
+ 'next',
105
+ 'locked',
106
+ 'reserved',
107
+ ];
108
+ export const GoalLadderState = z.enum(GOAL_LADDER_STATES);
109
+ // One entry per LADDER level, lowest first.
110
+ export const GoalLadderStep = z.strictObject({
111
+ level: z.enum(LADDER.map((s) => s.level)),
112
+ state: GoalLadderState,
113
+ });
114
+ // One item of gold's checklist. code is the name of the gold threshold it
115
+ // stands for (GoalThreshold.name), done whether it holds. progress is
116
+ // current of required where the rule has a number, null for a flag such as
117
+ // operator_verified. For clean_days that reads as "Safety record, 72 of 180
118
+ // days", for history_days as "Active on 41 of 60 days".
119
+ export const GoalStep = z.strictObject({
120
+ code: z.string().min(1).max(64),
121
+ done: z.boolean(),
122
+ progress: z
123
+ .strictObject({
124
+ current: z.number(),
125
+ required: z.number(),
126
+ })
127
+ .nullable(),
78
128
  });
79
129
  // level and the thresholds come from the standing row of the current
80
- // version, so they match the SEAL. nextLevel is null at gold, with no
81
- // thresholds. pending is live (GoalPending). asOf is the scoring run the numbers come from, null before
82
- // the first. today is live too, the agent's verified tasks of the current
83
- // UTC day that count toward its level, at most ceiling, and what is left.
84
- // A task past the ceiling still verifies and shows, and counts for nothing.
130
+ // version, so they match the SEAL. nextLevel is the issued level above
131
+ // level. null means no issued level is above it, not that level is the top
132
+ // of the ladder, since a reserved level (platinum) can sit above. A client
133
+ // from before the ladder (CLI 0.4.x) reads null as nothing left to do, so
134
+ // null stays at gold. thresholds are every rule of nextLevel, none when it
135
+ // is null. ladder is every LADDER level with its state. steps is gold's
136
+ // checklist, sent when nextLevel is gold and empty otherwise, the step-ups
137
+ // first. pending is live (GoalPending). asOf is the scoring run the numbers
138
+ // come from, null before the first. today is live too, the agent's verified
139
+ // tasks of the current UTC day that count toward its level, at most
140
+ // ceiling, and what is left. A task past the ceiling still verifies and
141
+ // shows, and counts for nothing.
85
142
  export const GoalToday = z.strictObject({
86
143
  // The UTC day, YYYY-MM-DD, so a cached answer from another day is known.
87
144
  day: z.iso.date(),
@@ -104,7 +161,9 @@ export const GoalResponse = z.strictObject({
104
161
  version: Version,
105
162
  level: Level,
106
163
  nextLevel: Level.nullable(),
164
+ ladder: z.array(GoalLadderStep),
107
165
  thresholds: z.array(GoalThreshold),
166
+ steps: z.array(GoalStep),
108
167
  actions: z.array(GoalAction),
109
168
  pending: GoalPending,
110
169
  today: GoalToday,
package/dist/index.d.ts CHANGED
@@ -1,12 +1,19 @@
1
1
  export * from './agent-id.js';
2
2
  export * from './agent-name.js';
3
3
  export * from './api.js';
4
+ export * from './badge.js';
4
5
  export * from './base64url.js';
6
+ export * from './client-address.js';
5
7
  export * from './credential.js';
6
8
  export * from './dimensions.js';
7
9
  export * from './envelope.js';
8
10
  export * from './events.js';
9
11
  export * from './goal.js';
12
+ export * from './json-shape.js';
13
+ export * from './moderation.js';
14
+ export * from './operator-domains.js';
15
+ export * from './policy.js';
16
+ export * from './runtime.js';
10
17
  export * from './standing.js';
11
18
  export * from './tasks.js';
12
19
  export * from './top-dimensions.js';
package/dist/index.js CHANGED
@@ -1,12 +1,19 @@
1
1
  export * from './agent-id.js';
2
2
  export * from './agent-name.js';
3
3
  export * from './api.js';
4
+ export * from './badge.js';
4
5
  export * from './base64url.js';
6
+ export * from './client-address.js';
5
7
  export * from './credential.js';
6
8
  export * from './dimensions.js';
7
9
  export * from './envelope.js';
8
10
  export * from './events.js';
9
11
  export * from './goal.js';
12
+ export * from './json-shape.js';
13
+ export * from './moderation.js';
14
+ export * from './operator-domains.js';
15
+ export * from './policy.js';
16
+ export * from './runtime.js';
10
17
  export * from './standing.js';
11
18
  export * from './tasks.js';
12
19
  export * from './top-dimensions.js';
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ export type JsonShapeLimits = {
3
+ readonly maxDepth: number;
4
+ readonly maxKeys: number;
5
+ readonly maxBytes: number;
6
+ };
7
+ export type JsonShapeIssue = 'too_deep' | 'too_many_keys';
8
+ export declare function jsonShapeIssue(value: unknown, limits: Pick<JsonShapeLimits, 'maxDepth' | 'maxKeys'>): JsonShapeIssue | null;
9
+ export declare function boundedJsonObject(name: string, limits: JsonShapeLimits): z.ZodRecord<z.ZodString, z.ZodUnknown>;
@@ -0,0 +1,70 @@
1
+ import { z } from 'zod';
2
+ import { utf8Encode } from './base64url.js';
3
+ /*
4
+ * The first depth or key count limit a JSON value breaks, or null when it
5
+ * keeps to both.
6
+ *
7
+ * Walks with its own stack rather than recursing, so a value nested
8
+ * thousands deep cannot overflow the call stack, and stops at the first
9
+ * breach. Run it before JSON.stringify on anything a caller sent.
10
+ * stringify recurses and throws RangeError past about 7,700 levels, and
11
+ * indented output grows with the square of the depth (VOU-214).
12
+ */
13
+ export function jsonShapeIssue(value, limits) {
14
+ const stack = [];
15
+ const push = (v, depth) => {
16
+ if (typeof v === 'object' && v !== null)
17
+ stack.push({ node: v, depth });
18
+ };
19
+ push(value, 1);
20
+ let keys = 0;
21
+ for (let top = stack.pop(); top !== undefined; top = stack.pop()) {
22
+ if (top.depth > limits.maxDepth)
23
+ return 'too_deep';
24
+ let children;
25
+ if (Array.isArray(top.node)) {
26
+ children = top.node;
27
+ }
28
+ else {
29
+ children = Object.values(top.node);
30
+ keys += children.length;
31
+ if (keys > limits.maxKeys)
32
+ return 'too_many_keys';
33
+ }
34
+ for (const child of children)
35
+ push(child, top.depth + 1);
36
+ }
37
+ return null;
38
+ }
39
+ /*
40
+ * A JSON object held to the limits. The depth and key checks run first, so
41
+ * the byte check only ever stringifies a value that cannot throw, and a
42
+ * breach is a Zod issue (a 400 at the API), never a RangeError (a 500).
43
+ * superRefine is used rather than refine so each breach gets its own
44
+ * message and the byte check can be skipped once one is found.
45
+ */
46
+ export function boundedJsonObject(name, limits) {
47
+ return z.record(z.string(), z.unknown()).superRefine((value, ctx) => {
48
+ const issue = jsonShapeIssue(value, limits);
49
+ if (issue === 'too_deep') {
50
+ ctx.addIssue({
51
+ code: 'custom',
52
+ message: `${name} must nest at most ${limits.maxDepth} levels deep`,
53
+ });
54
+ return;
55
+ }
56
+ if (issue === 'too_many_keys') {
57
+ ctx.addIssue({
58
+ code: 'custom',
59
+ message: `${name} must have at most ${limits.maxKeys} keys`,
60
+ });
61
+ return;
62
+ }
63
+ if (utf8Encode(JSON.stringify(value)).length > limits.maxBytes) {
64
+ ctx.addIssue({
65
+ code: 'custom',
66
+ message: `${name} must be at most ${limits.maxBytes} bytes`,
67
+ });
68
+ }
69
+ });
70
+ }
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ export declare const OPERATOR_SLUG_MIN = 1;
3
+ export declare const OPERATOR_SLUG_MAX = 39;
4
+ export declare const OPERATOR_DISPLAY_NAME_MIN = 1;
5
+ export declare const OPERATOR_DISPLAY_NAME_MAX = 64;
6
+ export declare const OperatorSlug: z.ZodString;
7
+ export type OperatorSlug = z.infer<typeof OperatorSlug>;
8
+ export declare const OperatorDisplayName: z.ZodString;
9
+ export type OperatorDisplayName = z.infer<typeof OperatorDisplayName>;
10
+ export declare function normaliseName(text: string): string;
11
+ export declare const displayNameKey: typeof normaliseName;
12
+ export declare const PROTECTED_NAMES: readonly string[];
13
+ export declare const PROTECTED_SUFFIXES: readonly string[];
14
+ export declare const PROTECTED_PREFIXES: readonly string[];
15
+ export declare function protectedNameOf(text: string): string | null;
16
+ export declare const RESERVED_WORDS: readonly string[];
17
+ export declare function isReservedWord(text: string): boolean;
18
+ export type NameRefusalCode = 'name_protected' | 'name_reserved' | 'name_mixed_script';
19
+ export type NameRefusal = {
20
+ code: NameRefusalCode;
21
+ message: string;
22
+ };
23
+ export declare function moderateSlug(slug: string): NameRefusal | null;
24
+ export declare function mixedScriptOf(text: string): string | null;
25
+ export declare function moderateDisplayName(name: string): NameRefusal | null;
26
+ export declare function slugBase(login: string): string;
27
+ export declare const suffixedSlug: (base: string, n: number) => string;
28
+ export type SlugSuffixReason = 'reserved' | 'protected' | 'taken';
29
+ export declare function slugSuffixReason(login: string, slug: string): SlugSuffixReason | null;