@sealkeeper/schema 0.4.3 → 0.4.5
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.
- package/dist/agent-name.d.ts +1 -1
- package/dist/agent-name.js +4 -4
- package/dist/api.d.ts +744 -27
- package/dist/api.js +232 -43
- package/dist/badge.d.ts +1 -0
- package/dist/badge.js +7 -0
- package/dist/credential.d.ts +186 -1
- package/dist/credential.js +55 -8
- package/dist/db/agents.d.ts +70 -0
- package/dist/db/agents.js +18 -0
- package/dist/db/client.d.ts +398 -0
- package/dist/db/client.js +2 -0
- package/dist/db/events.js +7 -0
- package/dist/db/index.d.ts +17 -1
- package/dist/db/index.js +5 -1
- package/dist/db/migrate.js +5 -1
- package/dist/db/migrator.d.ts +3 -1
- package/dist/db/migrator.js +8 -2
- package/dist/db/operator-identities.d.ts +211 -0
- package/dist/db/operator-identities.js +49 -0
- package/dist/db/operator-level-grants.d.ts +109 -0
- package/dist/db/operator-level-grants.js +30 -0
- package/dist/db/operator-slugs.d.ts +92 -0
- package/dist/db/operator-slugs.js +25 -0
- package/dist/db/operators.d.ts +119 -0
- package/dist/db/operators.js +30 -2
- package/dist/db/standing.d.ts +36 -0
- package/dist/db/standing.js +5 -0
- package/dist/db/task-claim-failures.d.ts +143 -0
- package/dist/db/task-claim-failures.js +37 -0
- package/dist/db/task-outcomes.d.ts +19 -0
- package/dist/db/task-outcomes.js +8 -1
- package/dist/db/tasks.d.ts +79 -0
- package/dist/db/tasks.js +19 -1
- package/dist/envelope.d.ts +3 -0
- package/dist/envelope.js +16 -11
- package/dist/goal.d.ts +149 -0
- package/dist/goal.js +171 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/moderation.d.ts +28 -0
- package/dist/moderation.js +450 -0
- package/dist/operator-domains.d.ts +104 -0
- package/dist/operator-domains.js +85 -0
- package/dist/policy.d.ts +4 -0
- package/dist/policy.js +10 -0
- package/dist/runtime.d.ts +17 -0
- package/dist/runtime.js +61 -0
- package/dist/seal-conformance.js +32 -1
- package/dist/standing.d.ts +68 -0
- package/dist/standing.js +132 -6
- package/dist/tasks.d.ts +23 -1
- package/dist/tasks.js +29 -5
- package/package.json +1 -1
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
// What an agent runs in, such as Claude Code or Codex. Declared by the
|
|
3
|
+
// operator at registration or with a signed PATCH, never inferred from
|
|
4
|
+
// events, since events do not say which adapter sent them. `other` is a
|
|
5
|
+
// runtime not on this list, `unknown` is an agent that has not said, which
|
|
6
|
+
// is every agent registered before runtimes existed and every agent a CLI
|
|
7
|
+
// without runtimes registers.
|
|
8
|
+
export const RUNTIMES = [
|
|
9
|
+
'claude-code',
|
|
10
|
+
'codex',
|
|
11
|
+
'cursor',
|
|
12
|
+
'gemini-cli',
|
|
13
|
+
'openclaw',
|
|
14
|
+
'mastra',
|
|
15
|
+
'other',
|
|
16
|
+
'unknown',
|
|
17
|
+
];
|
|
18
|
+
export const Runtime = z.enum(RUNTIMES);
|
|
19
|
+
// The runtime an agent has until it says otherwise.
|
|
20
|
+
export const DEFAULT_RUNTIME = 'unknown';
|
|
21
|
+
// How a runtime reads in prose, on the web and in the CLI.
|
|
22
|
+
export const RUNTIME_LABELS = {
|
|
23
|
+
'claude-code': 'Claude Code',
|
|
24
|
+
codex: 'Codex',
|
|
25
|
+
cursor: 'Cursor',
|
|
26
|
+
'gemini-cli': 'Gemini CLI',
|
|
27
|
+
openclaw: 'OpenClaw',
|
|
28
|
+
mastra: 'Mastra',
|
|
29
|
+
other: 'Other',
|
|
30
|
+
unknown: 'Unknown',
|
|
31
|
+
};
|
|
32
|
+
// Names that say what an agent runs in rather than which agent it is, such
|
|
33
|
+
// as claude-code or codex. A soft list. The CLI nudges once when an agent
|
|
34
|
+
// is about to be registered under one, and keeping it is allowed. The API
|
|
35
|
+
// never refuses one, so the list can grow without breaking anybody.
|
|
36
|
+
export const RUNTIME_NAMES = new Set([
|
|
37
|
+
'aider',
|
|
38
|
+
'amp',
|
|
39
|
+
'claude',
|
|
40
|
+
'claude-code',
|
|
41
|
+
'cline',
|
|
42
|
+
'codex',
|
|
43
|
+
'codex-cli',
|
|
44
|
+
'continue',
|
|
45
|
+
'copilot',
|
|
46
|
+
'cursor',
|
|
47
|
+
'cursor-agent',
|
|
48
|
+
'devin',
|
|
49
|
+
'gemini',
|
|
50
|
+
'gemini-cli',
|
|
51
|
+
'goose',
|
|
52
|
+
'mastra',
|
|
53
|
+
'openclaw',
|
|
54
|
+
'opencode',
|
|
55
|
+
'roo-code',
|
|
56
|
+
'windsurf',
|
|
57
|
+
]);
|
|
58
|
+
// True when name is on the soft list above.
|
|
59
|
+
export function isRuntimeName(name) {
|
|
60
|
+
return RUNTIME_NAMES.has(name);
|
|
61
|
+
}
|
package/dist/seal-conformance.js
CHANGED
|
@@ -9,6 +9,15 @@ const KID = 'vouched-conformance-1';
|
|
|
9
9
|
const NOW = 1_790_812_800;
|
|
10
10
|
const LEGACY_ISSUER = LEGACY_ISSUERS[0];
|
|
11
11
|
const HOUR = 3600;
|
|
12
|
+
// The counted evidence of the base SEAL's counts, for the version 2 cases.
|
|
13
|
+
// 25 seed tasks of one type count 17, one server checked task counts 0.98,
|
|
14
|
+
// rounded down to 0.
|
|
15
|
+
const COUNTED = {
|
|
16
|
+
verified_tasks: 17,
|
|
17
|
+
seed_tasks: 17,
|
|
18
|
+
server_checked_tasks: 0,
|
|
19
|
+
confirmed_tasks: 0,
|
|
20
|
+
};
|
|
12
21
|
const header = (kid) => base64urlEncode(utf8Encode(JSON.stringify({ alg: 'EdDSA', kid })));
|
|
13
22
|
// Signs payload bytes as they are, so a case can carry a payload that is not
|
|
14
23
|
// JSON. sign() in envelope.ts always writes JSON.
|
|
@@ -79,12 +88,34 @@ export async function sealConformanceCases() {
|
|
|
79
88
|
}),
|
|
80
89
|
'not_yet_valid',
|
|
81
90
|
],
|
|
82
|
-
[
|
|
91
|
+
[
|
|
92
|
+
'version 2 with counted evidence',
|
|
93
|
+
signed({ ...base, ver: 2, counted: COUNTED }),
|
|
94
|
+
'valid',
|
|
95
|
+
],
|
|
96
|
+
['version 2 without counted', signed({ ...base, ver: 2 }), 'malformed'],
|
|
97
|
+
[
|
|
98
|
+
'version 1 with counted',
|
|
99
|
+
signed({ ...base, counted: COUNTED }),
|
|
100
|
+
'malformed',
|
|
101
|
+
],
|
|
102
|
+
[
|
|
103
|
+
'version 2 with a counted value above its count',
|
|
104
|
+
signed({
|
|
105
|
+
...base,
|
|
106
|
+
ver: 2,
|
|
107
|
+
counted: { ...COUNTED, verified_tasks: 27, seed_tasks: 26 },
|
|
108
|
+
}),
|
|
109
|
+
'malformed',
|
|
110
|
+
],
|
|
111
|
+
['an unknown ver', signed({ ...base, ver: 3 }), 'unsupported_version'],
|
|
83
112
|
[
|
|
84
113
|
'no ver after the legacy cutoff',
|
|
85
114
|
signed({ ...base, ver: undefined }),
|
|
86
115
|
'unsupported_version',
|
|
87
116
|
],
|
|
117
|
+
// Intended. Platinum is reserved on LADDER and is not a Level under ver
|
|
118
|
+
// 1 or 2 (standard, section 9). It becomes valid only with a ver bump.
|
|
88
119
|
[
|
|
89
120
|
'the wrong shape, a level not in the standard',
|
|
90
121
|
signed({ ...base, level: 'platinum' }),
|
package/dist/standing.d.ts
CHANGED
|
@@ -7,6 +7,25 @@ export declare const Level: z.ZodEnum<{
|
|
|
7
7
|
}>;
|
|
8
8
|
export type Level = z.infer<typeof Level>;
|
|
9
9
|
export declare const LEVEL_RANK: Record<Level, number>;
|
|
10
|
+
export declare const LADDER: readonly [{
|
|
11
|
+
readonly level: 'none';
|
|
12
|
+
readonly state: 'issued';
|
|
13
|
+
}, {
|
|
14
|
+
readonly level: 'bronze';
|
|
15
|
+
readonly state: 'issued';
|
|
16
|
+
}, {
|
|
17
|
+
readonly level: 'silver';
|
|
18
|
+
readonly state: 'issued';
|
|
19
|
+
}, {
|
|
20
|
+
readonly level: 'gold';
|
|
21
|
+
readonly state: 'issued';
|
|
22
|
+
}, {
|
|
23
|
+
readonly level: 'platinum';
|
|
24
|
+
readonly state: 'reserved';
|
|
25
|
+
}];
|
|
26
|
+
export type LadderLevel = (typeof LADDER)[number]['level'];
|
|
27
|
+
export type LadderState = (typeof LADDER)[number]['state'];
|
|
28
|
+
export declare const ISSUED_LEVELS: readonly Level[];
|
|
10
29
|
export declare const StandingCounts: z.ZodObject<{
|
|
11
30
|
events: z.ZodInt;
|
|
12
31
|
history_days: z.ZodInt;
|
|
@@ -18,6 +37,17 @@ export declare const StandingCounts: z.ZodObject<{
|
|
|
18
37
|
safety_incidents_90d: z.ZodInt;
|
|
19
38
|
}, z.core.$strict>;
|
|
20
39
|
export type StandingCounts = z.infer<typeof StandingCounts>;
|
|
40
|
+
export declare const CountedCounts: z.ZodObject<{
|
|
41
|
+
verified_tasks: z.ZodInt;
|
|
42
|
+
seed_tasks: z.ZodInt;
|
|
43
|
+
server_checked_tasks: z.ZodInt;
|
|
44
|
+
confirmed_tasks: z.ZodInt;
|
|
45
|
+
}, z.core.$strict>;
|
|
46
|
+
export type CountedCounts = z.infer<typeof CountedCounts>;
|
|
47
|
+
export declare const COUNTED_EVIDENCE: {
|
|
48
|
+
readonly dailyCeiling: 20;
|
|
49
|
+
readonly diminishingK: 25;
|
|
50
|
+
};
|
|
21
51
|
export declare const DAY_MS = 86400000;
|
|
22
52
|
export declare const DORMANCY: {
|
|
23
53
|
readonly quietDays: 14;
|
|
@@ -25,6 +55,38 @@ export declare const DORMANCY: {
|
|
|
25
55
|
readonly dropTwoDays: 60;
|
|
26
56
|
readonly noneDays: 90;
|
|
27
57
|
};
|
|
58
|
+
export declare const LEVEL_THRESHOLDS: {
|
|
59
|
+
readonly bronze: {
|
|
60
|
+
readonly verifiedTasks: 25;
|
|
61
|
+
readonly historyDays: 3;
|
|
62
|
+
readonly reliability: 0.8;
|
|
63
|
+
readonly incidents90d: 0;
|
|
64
|
+
};
|
|
65
|
+
readonly silver: {
|
|
66
|
+
readonly verifiedTasks: 200;
|
|
67
|
+
readonly historyDays: 30;
|
|
68
|
+
readonly reliability: 0.9;
|
|
69
|
+
readonly safety: 0.9;
|
|
70
|
+
readonly incidents90d: 0;
|
|
71
|
+
readonly provenance: 0.8;
|
|
72
|
+
readonly modelDeclared: true;
|
|
73
|
+
};
|
|
74
|
+
readonly gold: {
|
|
75
|
+
readonly verifiedTasks: 200;
|
|
76
|
+
readonly confirmedTasks: 25;
|
|
77
|
+
readonly confirmedOperators: 3;
|
|
78
|
+
readonly historySpanDays: 90;
|
|
79
|
+
readonly activeDays: 60;
|
|
80
|
+
readonly reliability: 0.95;
|
|
81
|
+
readonly safety: 0.95;
|
|
82
|
+
readonly cleanDays: 180;
|
|
83
|
+
readonly operatorVerified: true;
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
export declare const OPERATOR_SILVER_CAP: {
|
|
87
|
+
readonly agents: 5;
|
|
88
|
+
readonly days: 30;
|
|
89
|
+
};
|
|
28
90
|
export declare function dormantDays(lastActive: Date | null, now: Date): number | null;
|
|
29
91
|
export declare const isQuiet: (days: number | null) => boolean;
|
|
30
92
|
export declare const Standing: z.ZodObject<{
|
|
@@ -38,6 +100,12 @@ export declare const Standing: z.ZodObject<{
|
|
|
38
100
|
distinct_operators: z.ZodInt;
|
|
39
101
|
safety_incidents_90d: z.ZodInt;
|
|
40
102
|
}, z.core.$strict>;
|
|
103
|
+
counted: z.ZodObject<{
|
|
104
|
+
verified_tasks: z.ZodInt;
|
|
105
|
+
seed_tasks: z.ZodInt;
|
|
106
|
+
server_checked_tasks: z.ZodInt;
|
|
107
|
+
confirmed_tasks: z.ZodInt;
|
|
108
|
+
}, z.core.$strict>;
|
|
41
109
|
history_days: z.ZodInt;
|
|
42
110
|
last_active: z.ZodNullable<z.ZodISODateTime>;
|
|
43
111
|
dormant_days: z.ZodNullable<z.ZodInt>;
|
package/dist/standing.js
CHANGED
|
@@ -2,13 +2,33 @@ import { z } from 'zod';
|
|
|
2
2
|
// Standing levels from the SEAL standard, section 5, lowest first. none is
|
|
3
3
|
// below bronze. Every scored agent version has one.
|
|
4
4
|
export const Level = z.enum(['none', 'bronze', 'silver', 'gold']);
|
|
5
|
-
// Higher is better. The leaderboard sorts on it before the score.
|
|
5
|
+
// Higher is better. The leaderboard sorts on it before the score. Equal to
|
|
6
|
+
// the level's index on LADDER.
|
|
6
7
|
export const LEVEL_RANK = {
|
|
7
8
|
none: 0,
|
|
8
9
|
bronze: 1,
|
|
9
10
|
silver: 2,
|
|
10
11
|
gold: 3,
|
|
11
12
|
};
|
|
13
|
+
/*
|
|
14
|
+
* Every level of the standard, lowest first. issued levels are the ones a
|
|
15
|
+
* SEAL can carry. A reserved level is named and ordered but never issued,
|
|
16
|
+
* so no code may treat the highest issued level as the top of the ladder.
|
|
17
|
+
* Platinum is reserved. Level, LEVEL_RANK and the standing.level check
|
|
18
|
+
* constraint stay at the issued four, because the payload fields of a SEAL
|
|
19
|
+
* version are closed (standard, section 9) and published CLIs and offline
|
|
20
|
+
* verifiers reject a level they do not know. Platinum enters Level with a
|
|
21
|
+
* ver bump when it is issued.
|
|
22
|
+
*/
|
|
23
|
+
export const LADDER = [
|
|
24
|
+
{ level: 'none', state: 'issued' },
|
|
25
|
+
{ level: 'bronze', state: 'issued' },
|
|
26
|
+
{ level: 'silver', state: 'issued' },
|
|
27
|
+
{ level: 'gold', state: 'issued' },
|
|
28
|
+
{ level: 'platinum', state: 'reserved' },
|
|
29
|
+
];
|
|
30
|
+
// The issued levels of LADDER in order, the same values as Level.options.
|
|
31
|
+
export const ISSUED_LEVELS = LADDER.flatMap((step) => step.state === 'issued' ? [Level.parse(step.level)] : []);
|
|
12
32
|
const Count = z.int().min(0);
|
|
13
33
|
// The evidence counts of the SEAL standard, section 4, over the scoring
|
|
14
34
|
// window (180 days) for one agent version. The names are the standard's, so
|
|
@@ -44,18 +64,121 @@ export const StandingCounts = z
|
|
|
44
64
|
message: 'verified_tasks must equal seed_tasks + server_checked_tasks + confirmed_tasks',
|
|
45
65
|
path: ['verified_tasks'],
|
|
46
66
|
});
|
|
67
|
+
// The counted evidence (VOU-139), what the levels read. The same verified
|
|
68
|
+
// tasks as the counts after the daily ceiling (at most 20 per agent per UTC
|
|
69
|
+
// day count, the most valuable first) and diminishing returns (within a
|
|
70
|
+
// seed task type, or another operator's tasks, n tasks count 25 * ln(1 +
|
|
71
|
+
// n / 25)), each kind rounded down. The counts stay the raw facts.
|
|
72
|
+
//
|
|
73
|
+
// verified_tasks seed_tasks + server_checked_tasks + confirmed_tasks
|
|
74
|
+
// seed_tasks counted seed tasks
|
|
75
|
+
// server_checked_tasks counted server checked tasks
|
|
76
|
+
// confirmed_tasks counted confirmed tasks
|
|
77
|
+
//
|
|
78
|
+
// Each is at most its raw count, and verified_tasks is always the sum.
|
|
79
|
+
export const CountedCounts = z
|
|
80
|
+
.strictObject({
|
|
81
|
+
verified_tasks: Count,
|
|
82
|
+
seed_tasks: Count,
|
|
83
|
+
server_checked_tasks: Count,
|
|
84
|
+
confirmed_tasks: Count,
|
|
85
|
+
})
|
|
86
|
+
.refine((c) => c.verified_tasks ===
|
|
87
|
+
c.seed_tasks + c.server_checked_tasks + c.confirmed_tasks, {
|
|
88
|
+
message: 'verified_tasks must equal seed_tasks + server_checked_tasks + confirmed_tasks',
|
|
89
|
+
path: ['verified_tasks'],
|
|
90
|
+
});
|
|
91
|
+
// The two numbers of counted evidence (VOU-139), starting values set on 26
|
|
92
|
+
// September 2026. At most dailyCeiling verified tasks per agent per UTC day
|
|
93
|
+
// count, and n tasks of one category count diminishingK * ln(1 + n /
|
|
94
|
+
// diminishingK). The scoring job applies them (SCORING in the API) and the
|
|
95
|
+
// CLI explains them, so they live here.
|
|
96
|
+
export const COUNTED_EVIDENCE = {
|
|
97
|
+
dailyCeiling: 20,
|
|
98
|
+
diminishingK: 25,
|
|
99
|
+
};
|
|
47
100
|
export const DAY_MS = 86_400_000;
|
|
48
101
|
// The dormancy ladder of the SEAL standard, section 5, in whole days since
|
|
49
|
-
// the agent's last accepted event. At quietDays the
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
102
|
+
// the agent's last accepted event. At quietDays the level stays and the
|
|
103
|
+
// agent is quiet, which the agent answers carry (Standing.quiet, isQuiet)
|
|
104
|
+
// and the badge and profile show. At dropOneDays and dropTwoDays the level
|
|
105
|
+
// drops one step each. At noneDays the level is none and the scoring run
|
|
106
|
+
// stores no_seal, so the SEAL routes withhold the SEAL until a run after
|
|
107
|
+
// the agent is active again. An agent at none for any other reason still gets a SEAL
|
|
108
|
+
// that says none. The scoring job applies the ladder and the CLI explains
|
|
109
|
+
// it, so it lives here.
|
|
53
110
|
export const DORMANCY = {
|
|
54
111
|
quietDays: 14,
|
|
55
112
|
dropOneDays: 30,
|
|
56
113
|
dropTwoDays: 60,
|
|
57
114
|
noneDays: 90,
|
|
58
115
|
};
|
|
116
|
+
// SEAL standard levels, version 1 thresholds, section 5. Every one is a
|
|
117
|
+
// minimum and all of a level's must hold. The scoring job applies them
|
|
118
|
+
// (SCORING.levels in the API) and the CLI explains them, so they live here.
|
|
119
|
+
// Task counts are counted evidence (CountedCounts), recalibrated on 26
|
|
120
|
+
// September 2026 (VOU-139) from the simulation in
|
|
121
|
+
// apps/api/src/scoring/simulation.ts. Seed tasks count in verifiedTasks at
|
|
122
|
+
// every level (VOU-172, 26 September 2026), so an agent that does seed
|
|
123
|
+
// tasks every day reaches silver on them alone. Silver dropped its
|
|
124
|
+
// checked or confirmed, other operator and confirmed task clauses then,
|
|
125
|
+
// and gold moved from 1000 verified and 250 confirmed from 25 operators to
|
|
126
|
+
// the step-ups below, with ratings left out until a later change.
|
|
127
|
+
export const LEVEL_THRESHOLDS = {
|
|
128
|
+
bronze: {
|
|
129
|
+
verifiedTasks: 25,
|
|
130
|
+
historyDays: 3,
|
|
131
|
+
reliability: 0.8,
|
|
132
|
+
// Confirmed incidents in the last 90 days, at most.
|
|
133
|
+
incidents90d: 0,
|
|
134
|
+
},
|
|
135
|
+
silver: {
|
|
136
|
+
verifiedTasks: 200,
|
|
137
|
+
historyDays: 30,
|
|
138
|
+
reliability: 0.9,
|
|
139
|
+
safety: 0.9,
|
|
140
|
+
incidents90d: 0,
|
|
141
|
+
// Provenance of at least this, meaning the share of the agent's events
|
|
142
|
+
// in the window, received since this version was first seen, that carry
|
|
143
|
+
// this version. Measured from first seen, so an agent that ships often
|
|
144
|
+
// and cuts over cleanly still passes.
|
|
145
|
+
provenance: 0.8,
|
|
146
|
+
// A declared model, meaning the card names one or the agent sent a
|
|
147
|
+
// usage event with a model in the window.
|
|
148
|
+
modelDeclared: true,
|
|
149
|
+
},
|
|
150
|
+
gold: {
|
|
151
|
+
verifiedTasks: 200,
|
|
152
|
+
// Confirmed tasks posted by hand with no routine report, from at least
|
|
153
|
+
// confirmedOperators other operators.
|
|
154
|
+
confirmedTasks: 25,
|
|
155
|
+
confirmedOperators: 3,
|
|
156
|
+
// Span from the first accepted event in the window, with activity on at
|
|
157
|
+
// least activeDays of those days.
|
|
158
|
+
historySpanDays: 90,
|
|
159
|
+
activeDays: 60,
|
|
160
|
+
reliability: 0.95,
|
|
161
|
+
safety: 0.95,
|
|
162
|
+
// Whole days since the later of the agent's first accepted event and
|
|
163
|
+
// its last incident, the clean_days count, which stops here.
|
|
164
|
+
cleanDays: 180,
|
|
165
|
+
operatorVerified: true,
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
// The operator silver cap (VOU-182, 26 September 2026). At most `agents`
|
|
169
|
+
// agents of one operator reach silver for the first time in any `days`
|
|
170
|
+
// days. The first time an agent earns silver it takes a grant, one of the
|
|
171
|
+
// operator's slots. An agent that finds no free slot is held at bronze
|
|
172
|
+
// until the oldest grant in the window is `days` days old. An agent keeps
|
|
173
|
+
// its grant through dormancy drops and version changes, and deleting it
|
|
174
|
+
// does not free the slot. Gold is above silver, so it needs the grant too.
|
|
175
|
+
// The scoring job applies it and the CLI explains it, so it lives here. A
|
|
176
|
+
// higher number for verified operators (20 proposed) is open. It would sit
|
|
177
|
+
// beside `agents` as its own key.
|
|
178
|
+
export const OPERATOR_SILVER_CAP = {
|
|
179
|
+
agents: 5,
|
|
180
|
+
days: 30,
|
|
181
|
+
};
|
|
59
182
|
// Whole days from lastActive to now, never below zero. null when the agent
|
|
60
183
|
// has sent no accepted event. The one place dormancy is counted.
|
|
61
184
|
export function dormantDays(lastActive, now) {
|
|
@@ -66,12 +189,15 @@ export function dormantDays(lastActive, now) {
|
|
|
66
189
|
// True at quietDays or more. Never active is not quiet.
|
|
67
190
|
export const isQuiet = (days) => days !== null && days >= DORMANCY.quietDays;
|
|
68
191
|
// What the agent answers carry beside level, read from the standing table
|
|
69
|
-
// for the current version.
|
|
192
|
+
// for the current version. counts are the raw facts and counted what the
|
|
193
|
+
// level read. last_active is the newest accepted event of the
|
|
70
194
|
// agent on any version, null when it has sent none. dormant_days is whole
|
|
71
195
|
// days since last_active at the time of the answer, null with it. quiet is
|
|
72
196
|
// true when dormant_days is at DORMANCY.quietDays or more.
|
|
73
197
|
export const Standing = z.strictObject({
|
|
74
198
|
counts: StandingCounts,
|
|
199
|
+
// The counted evidence the level stands on (VOU-139).
|
|
200
|
+
counted: CountedCounts,
|
|
75
201
|
history_days: Count,
|
|
76
202
|
last_active: z.iso.datetime().nullable(),
|
|
77
203
|
dormant_days: Count.nullable(),
|
package/dist/tasks.d.ts
CHANGED
|
@@ -22,6 +22,28 @@ export declare const VerificationSpec: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
22
22
|
kind: z.ZodLiteral<"counterparty">;
|
|
23
23
|
}, z.core.$strict>], "kind">;
|
|
24
24
|
export type VerificationSpec = z.infer<typeof VerificationSpec>;
|
|
25
|
+
export declare const PublicHashVerification: z.ZodObject<{
|
|
26
|
+
kind: z.ZodLiteral<"hash">;
|
|
27
|
+
}, z.core.$strict>;
|
|
28
|
+
export declare const PublicVerificationSpec: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
29
|
+
kind: z.ZodLiteral<"hash">;
|
|
30
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
31
|
+
kind: z.ZodLiteral<"schema">;
|
|
32
|
+
jsonSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
33
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
34
|
+
kind: z.ZodLiteral<"counterparty">;
|
|
35
|
+
}, z.core.$strict>], "kind">;
|
|
36
|
+
export type PublicVerificationSpec = z.infer<typeof PublicVerificationSpec>;
|
|
37
|
+
export declare const ShownVerificationSpec: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
38
|
+
kind: z.ZodLiteral<"hash">;
|
|
39
|
+
sha256: z.ZodOptional<z.ZodString>;
|
|
40
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
41
|
+
kind: z.ZodLiteral<"schema">;
|
|
42
|
+
jsonSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
43
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
44
|
+
kind: z.ZodLiteral<"counterparty">;
|
|
45
|
+
}, z.core.$strict>], "kind">;
|
|
46
|
+
export type ShownVerificationSpec = z.infer<typeof ShownVerificationSpec>;
|
|
25
47
|
export declare const TaskOutcome: z.ZodEnum<{
|
|
26
48
|
failure: "failure";
|
|
27
49
|
success: "success";
|
|
@@ -45,5 +67,5 @@ export type TaskTimestamps = {
|
|
|
45
67
|
export declare function taskState(task: TaskTimestamps, now?: Date): TaskState;
|
|
46
68
|
type JsonObject = Record<string, unknown>;
|
|
47
69
|
export declare function redactJsonSchema(schema: JsonObject): JsonObject;
|
|
48
|
-
export declare function publicVerification(spec: VerificationSpec):
|
|
70
|
+
export declare function publicVerification(spec: VerificationSpec): PublicVerificationSpec;
|
|
49
71
|
export {};
|
package/dist/tasks.js
CHANGED
|
@@ -20,6 +20,26 @@ export const VerificationSpec = z.discriminatedUnion('kind', [
|
|
|
20
20
|
SchemaVerification,
|
|
21
21
|
CounterpartyVerification,
|
|
22
22
|
]);
|
|
23
|
+
// A hash task as everyone but its poster sees it, without the digest. With
|
|
24
|
+
// the digest in hand a claimant could hash candidate answers offline until
|
|
25
|
+
// one matched and submit only that one (VOU-181).
|
|
26
|
+
export const PublicHashVerification = z.strictObject({
|
|
27
|
+
kind: z.literal('hash'),
|
|
28
|
+
});
|
|
29
|
+
// The spec every public read shows, from publicVerification below.
|
|
30
|
+
export const PublicVerificationSpec = z.discriminatedUnion('kind', [
|
|
31
|
+
PublicHashVerification,
|
|
32
|
+
SchemaVerification,
|
|
33
|
+
CounterpartyVerification,
|
|
34
|
+
]);
|
|
35
|
+
// The spec a task response carries. The poster's own post and its signed
|
|
36
|
+
// submission read show the full spec, every other response the public one,
|
|
37
|
+
// so the digest is optional here and required in a post.
|
|
38
|
+
export const ShownVerificationSpec = z.discriminatedUnion('kind', [
|
|
39
|
+
z.strictObject({ kind: z.literal('hash'), sha256: Sha256Hex.optional() }),
|
|
40
|
+
SchemaVerification,
|
|
41
|
+
CounterpartyVerification,
|
|
42
|
+
]);
|
|
23
43
|
export const TaskOutcome = z.enum(['success', 'failure']);
|
|
24
44
|
export const TaskState = z.enum([
|
|
25
45
|
'open',
|
|
@@ -123,10 +143,14 @@ export function redactJsonSchema(schema) {
|
|
|
123
143
|
}
|
|
124
144
|
return out;
|
|
125
145
|
}
|
|
126
|
-
// What GET /v1/tasks and GET /v1/tasks/:id show.
|
|
127
|
-
//
|
|
146
|
+
// What GET /v1/tasks and GET /v1/tasks/:id show. A hash task drops its
|
|
147
|
+
// digest, which only the poster sees (VOU-181). A schema task shows its
|
|
148
|
+
// redacted schema. A counterparty spec has nothing to hide.
|
|
128
149
|
export function publicVerification(spec) {
|
|
129
|
-
if (spec.kind
|
|
130
|
-
return
|
|
131
|
-
|
|
150
|
+
if (spec.kind === 'hash')
|
|
151
|
+
return { kind: 'hash' };
|
|
152
|
+
if (spec.kind === 'schema') {
|
|
153
|
+
return { kind: 'schema', jsonSchema: redactJsonSchema(spec.jsonSchema) };
|
|
154
|
+
}
|
|
155
|
+
return spec;
|
|
132
156
|
}
|