@sealkeeper/schema 0.4.6 → 0.4.7

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 (66) hide show
  1. package/README.md +2 -2
  2. package/dist/api.d.ts +9 -32
  3. package/dist/api.js +32 -28
  4. package/dist/credential.d.ts +1 -66
  5. package/dist/credential.js +25 -63
  6. package/dist/events.d.ts +1 -0
  7. package/dist/events.js +13 -1
  8. package/dist/goal.js +2 -2
  9. package/dist/hidden.d.ts +1 -0
  10. package/dist/hidden.js +5 -0
  11. package/dist/index.d.ts +1 -1
  12. package/dist/index.js +1 -1
  13. package/dist/moderation.js +1 -4
  14. package/dist/seal-conformance.js +2 -2
  15. package/dist/seal-verify.d.ts +21 -0
  16. package/dist/seal-verify.js +63 -0
  17. package/dist/standing.js +1 -1
  18. package/package.json +2 -6
  19. package/dist/db/agent-milestones.d.ts +0 -75
  20. package/dist/db/agent-milestones.js +0 -16
  21. package/dist/db/agent-renames.d.ts +0 -126
  22. package/dist/db/agent-renames.js +0 -20
  23. package/dist/db/agents.d.ts +0 -351
  24. package/dist/db/agents.js +0 -99
  25. package/dist/db/client.d.ts +0 -2561
  26. package/dist/db/client.js +0 -61
  27. package/dist/db/credentials.d.ts +0 -143
  28. package/dist/db/credentials.js +0 -16
  29. package/dist/db/deleted-operators.d.ts +0 -75
  30. package/dist/db/deleted-operators.js +0 -13
  31. package/dist/db/events.d.ts +0 -160
  32. package/dist/db/events.js +0 -41
  33. package/dist/db/feed-items.d.ts +0 -109
  34. package/dist/db/feed-items.js +0 -21
  35. package/dist/db/index.d.ts +0 -76
  36. package/dist/db/index.js +0 -28
  37. package/dist/db/migrate.d.ts +0 -1
  38. package/dist/db/migrate.js +0 -34
  39. package/dist/db/migrator.d.ts +0 -6
  40. package/dist/db/migrator.js +0 -36
  41. package/dist/db/operator-identities.d.ts +0 -211
  42. package/dist/db/operator-identities.js +0 -49
  43. package/dist/db/operator-level-grants.d.ts +0 -109
  44. package/dist/db/operator-level-grants.js +0 -30
  45. package/dist/db/operator-slugs.d.ts +0 -92
  46. package/dist/db/operator-slugs.js +0 -25
  47. package/dist/db/operators.d.ts +0 -228
  48. package/dist/db/operators.js +0 -39
  49. package/dist/db/quota-counters.d.ts +0 -109
  50. package/dist/db/quota-counters.js +0 -17
  51. package/dist/db/ratings.d.ts +0 -160
  52. package/dist/db/ratings.js +0 -27
  53. package/dist/db/scores.d.ts +0 -160
  54. package/dist/db/scores.js +0 -15
  55. package/dist/db/standing.d.ts +0 -264
  56. package/dist/db/standing.js +0 -34
  57. package/dist/db/task-claim-failures.d.ts +0 -143
  58. package/dist/db/task-claim-failures.js +0 -37
  59. package/dist/db/task-outcomes.d.ts +0 -145
  60. package/dist/db/task-outcomes.js +0 -25
  61. package/dist/db/tasks.d.ts +0 -381
  62. package/dist/db/tasks.js +0 -106
  63. package/dist/db/timestamps.d.ts +0 -4
  64. package/dist/db/timestamps.js +0 -24
  65. package/dist/db/url.d.ts +0 -12
  66. package/dist/db/url.js +0 -25
@@ -0,0 +1,21 @@
1
+ import type { SealBrokenReason } from './api.js';
2
+ import { type SealPayload } from './credential.js';
3
+ export type SealKey = {
4
+ kid: string;
5
+ x: string;
6
+ };
7
+ export type SealVerified = {
8
+ ok: true;
9
+ kid: string;
10
+ payload: SealPayload;
11
+ expiresIn: number;
12
+ };
13
+ export type SealProblem = {
14
+ ok: false;
15
+ reason: SealBrokenReason;
16
+ kid: string | null;
17
+ signed?: unknown;
18
+ payload?: SealPayload;
19
+ };
20
+ export type SealVerification = SealVerified | SealProblem;
21
+ export declare function verifySeal(keys: readonly SealKey[], compact: string, nowSeconds: number): Promise<SealVerification>;
@@ -0,0 +1,63 @@
1
+ import { base64urlDecode } from './base64url.js';
2
+ import { parseSealPayload, sealIatProblem, } from './credential.js';
3
+ import { decodeHeader, EnvelopeError, verify } from './envelope.js';
4
+ /*
5
+ * Verifies a SEAL against the issuer's published keys, the steps of the
6
+ * standard (section 3) in order. The API's POST /v1/seal/verify, the web's
7
+ * verify tool and badge and `sealkeeper seal verify` all call this, and the
8
+ * SEAL conformance cases hold it to the standard's answers.
9
+ *
10
+ * 1. The header, which names the kid. Surrounding whitespace is dropped
11
+ * first, as a pasted SEAL often has it.
12
+ * 2. The key the kid names, among keys.
13
+ * 3. The signature over the exact header.payload bytes, and only then the
14
+ * payload as JSON. A signature that checks out over a payload that is
15
+ * not JSON is malformed, not bad_signature.
16
+ * 4. The issuer, then ver, then the shape for that ver, through
17
+ * parseSealPayload. So a SEAL from another issuer is wrong_issuer
18
+ * whatever its ver or shape.
19
+ * 5. exp, then iat, as the standard reads "Check exp is in the future and
20
+ * iat is not". An iat more than SEAL_CLOCK_SKEW_SECONDS ahead is
21
+ * not_yet_valid.
22
+ *
23
+ * nowSeconds is the verifier's clock in Unix seconds, passed in so tests
24
+ * can pin it.
25
+ */
26
+ export async function verifySeal(keys, compact, nowSeconds) {
27
+ const jws = compact.trim();
28
+ let kid;
29
+ try {
30
+ kid = decodeHeader(jws).kid;
31
+ }
32
+ catch {
33
+ return { ok: false, reason: 'malformed', kid: null };
34
+ }
35
+ const key = keys.find((k) => k.kid === kid);
36
+ if (!key)
37
+ return { ok: false, reason: 'unknown_kid', kid };
38
+ let signed;
39
+ try {
40
+ signed = (await verify(jws, base64urlDecode(key.x))).payload;
41
+ }
42
+ catch (error) {
43
+ return {
44
+ ok: false,
45
+ reason: error instanceof EnvelopeError && error.code === 'bad_signature'
46
+ ? 'bad_signature'
47
+ : 'malformed',
48
+ kid,
49
+ };
50
+ }
51
+ const parsed = parseSealPayload(signed, nowSeconds);
52
+ if (!parsed.ok)
53
+ return { ok: false, reason: parsed.reason, kid, signed };
54
+ const payload = parsed.payload;
55
+ const expiresIn = Math.floor(payload.exp - nowSeconds);
56
+ if (expiresIn <= 0) {
57
+ return { ok: false, reason: 'expired', kid, signed, payload };
58
+ }
59
+ const early = sealIatProblem(payload.iat, nowSeconds);
60
+ if (early)
61
+ return { ok: false, reason: early, kid, signed, payload };
62
+ return { ok: true, kid, payload, expiresIn };
63
+ }
package/dist/standing.js CHANGED
@@ -118,7 +118,7 @@ export const DORMANCY = {
118
118
  // (SCORING.levels in the API) and the CLI explains them, so they live here.
119
119
  // Task counts are counted evidence (CountedCounts), recalibrated on 26
120
120
  // September 2026 (VOU-139) from the simulation in
121
- // apps/api/src/scoring/simulation.ts. Seed tasks count in verifiedTasks at
121
+ // apps/api/src/test/simulation.ts. Seed tasks count in verifiedTasks at
122
122
  // every level (VOU-172, 26 September 2026), so an agent that does seed
123
123
  // tasks every day reaches silver on them alone. Silver dropped its
124
124
  // checked or confirmed, other operator and confirmed task clauses then,
package/package.json CHANGED
@@ -1,15 +1,10 @@
1
1
  {
2
2
  "name": "@sealkeeper/schema",
3
- "version": "0.4.6",
3
+ "version": "0.4.7",
4
4
  "private": false,
5
5
  "description": "Zod schemas, event taxonomy and signing helpers for SealKeeper.",
6
6
  "license": "Apache-2.0",
7
7
  "homepage": "https://sealkeeper.run/seal/standard",
8
- "repository": {
9
- "type": "git",
10
- "url": "git+https://github.com/sealkeeper-dev/sealkeeper.git",
11
- "directory": "packages/schema"
12
- },
13
8
  "bugs": {
14
9
  "url": "https://github.com/sealkeeper-dev/cli/issues"
15
10
  },
@@ -33,6 +28,7 @@
33
28
  },
34
29
  "files": [
35
30
  "dist",
31
+ "!dist/db",
36
32
  "README.md",
37
33
  "LICENSE",
38
34
  "NOTICE"
@@ -1,75 +0,0 @@
1
- export declare const agentMilestones: import("drizzle-orm/pg-core").PgTableWithColumns<{
2
- name: "agent_milestones";
3
- schema: undefined;
4
- columns: {
5
- createdAt: import("drizzle-orm/pg-core").PgColumn<{
6
- name: "created_at";
7
- tableName: "agent_milestones";
8
- dataType: "date";
9
- columnType: "PgTimestamp";
10
- data: Date;
11
- driverParam: string;
12
- notNull: true;
13
- hasDefault: true;
14
- isPrimaryKey: false;
15
- isAutoincrement: false;
16
- hasRuntimeDefault: false;
17
- enumValues: undefined;
18
- baseColumn: never;
19
- identity: undefined;
20
- generated: undefined;
21
- }, {}, {}>;
22
- updatedAt: import("drizzle-orm/pg-core").PgColumn<{
23
- name: "updated_at";
24
- tableName: "agent_milestones";
25
- dataType: "date";
26
- columnType: "PgTimestamp";
27
- data: Date;
28
- driverParam: string;
29
- notNull: true;
30
- hasDefault: true;
31
- isPrimaryKey: false;
32
- isAutoincrement: false;
33
- hasRuntimeDefault: false;
34
- enumValues: undefined;
35
- baseColumn: never;
36
- identity: undefined;
37
- generated: undefined;
38
- }, {}, {}>;
39
- agentId: import("drizzle-orm/pg-core").PgColumn<{
40
- name: "agent_id";
41
- tableName: "agent_milestones";
42
- dataType: "string";
43
- columnType: "PgText";
44
- data: string;
45
- driverParam: string;
46
- notNull: true;
47
- hasDefault: false;
48
- isPrimaryKey: false;
49
- isAutoincrement: false;
50
- hasRuntimeDefault: false;
51
- enumValues: [string, ...string[]];
52
- baseColumn: never;
53
- identity: undefined;
54
- generated: undefined;
55
- }, {}, {}>;
56
- milestone: import("drizzle-orm/pg-core").PgColumn<{
57
- name: "milestone";
58
- tableName: "agent_milestones";
59
- dataType: "string";
60
- columnType: "PgText";
61
- data: string;
62
- driverParam: string;
63
- notNull: true;
64
- hasDefault: false;
65
- isPrimaryKey: false;
66
- isAutoincrement: false;
67
- hasRuntimeDefault: false;
68
- enumValues: [string, ...string[]];
69
- baseColumn: never;
70
- identity: undefined;
71
- generated: undefined;
72
- }, {}, {}>;
73
- };
74
- dialect: 'pg';
75
- }>;
@@ -1,16 +0,0 @@
1
- import { pgTable, primaryKey, text } from 'drizzle-orm/pg-core';
2
- import { agents } from './agents.js';
3
- import { timestamps } from './timestamps.js';
4
- // The feed milestones an agent has reached, one row per (agent, milestone).
5
- // The scoring run writes a milestone to the feed only when it has no row
6
- // here, so each is written once per agent, ever. Migration 0019 seeded it
7
- // from standing, so an agent that already stood above none, or already
8
- // passed a verified task count, before milestones existed is not told it
9
- // did so for the first time.
10
- export const agentMilestones = pgTable('agent_milestones', {
11
- agentId: text('agent_id')
12
- .notNull()
13
- .references(() => agents.id),
14
- milestone: text('milestone').notNull(),
15
- ...timestamps,
16
- }, (t) => [primaryKey({ columns: [t.agentId, t.milestone] })]);
@@ -1,126 +0,0 @@
1
- export declare const agentRenames: import("drizzle-orm/pg-core").PgTableWithColumns<{
2
- name: "agent_renames";
3
- schema: undefined;
4
- columns: {
5
- createdAt: import("drizzle-orm/pg-core").PgColumn<{
6
- name: "created_at";
7
- tableName: "agent_renames";
8
- dataType: "date";
9
- columnType: "PgTimestamp";
10
- data: Date;
11
- driverParam: string;
12
- notNull: true;
13
- hasDefault: true;
14
- isPrimaryKey: false;
15
- isAutoincrement: false;
16
- hasRuntimeDefault: false;
17
- enumValues: undefined;
18
- baseColumn: never;
19
- identity: undefined;
20
- generated: undefined;
21
- }, {}, {}>;
22
- updatedAt: import("drizzle-orm/pg-core").PgColumn<{
23
- name: "updated_at";
24
- tableName: "agent_renames";
25
- dataType: "date";
26
- columnType: "PgTimestamp";
27
- data: Date;
28
- driverParam: string;
29
- notNull: true;
30
- hasDefault: true;
31
- isPrimaryKey: false;
32
- isAutoincrement: false;
33
- hasRuntimeDefault: false;
34
- enumValues: undefined;
35
- baseColumn: never;
36
- identity: undefined;
37
- generated: undefined;
38
- }, {}, {}>;
39
- id: import("drizzle-orm/pg-core").PgColumn<{
40
- name: "id";
41
- tableName: "agent_renames";
42
- dataType: "number";
43
- columnType: "PgBigSerial53";
44
- data: number;
45
- driverParam: number;
46
- notNull: true;
47
- hasDefault: true;
48
- isPrimaryKey: true;
49
- isAutoincrement: false;
50
- hasRuntimeDefault: false;
51
- enumValues: undefined;
52
- baseColumn: never;
53
- identity: undefined;
54
- generated: undefined;
55
- }, {}, {}>;
56
- agentId: import("drizzle-orm/pg-core").PgColumn<{
57
- name: "agent_id";
58
- tableName: "agent_renames";
59
- dataType: "string";
60
- columnType: "PgText";
61
- data: string;
62
- driverParam: string;
63
- notNull: true;
64
- hasDefault: false;
65
- isPrimaryKey: false;
66
- isAutoincrement: false;
67
- hasRuntimeDefault: false;
68
- enumValues: [string, ...string[]];
69
- baseColumn: never;
70
- identity: undefined;
71
- generated: undefined;
72
- }, {}, {}>;
73
- oldName: import("drizzle-orm/pg-core").PgColumn<{
74
- name: "old_name";
75
- tableName: "agent_renames";
76
- dataType: "string";
77
- columnType: "PgText";
78
- data: string;
79
- driverParam: string;
80
- notNull: true;
81
- hasDefault: false;
82
- isPrimaryKey: false;
83
- isAutoincrement: false;
84
- hasRuntimeDefault: false;
85
- enumValues: [string, ...string[]];
86
- baseColumn: never;
87
- identity: undefined;
88
- generated: undefined;
89
- }, {}, {}>;
90
- newName: import("drizzle-orm/pg-core").PgColumn<{
91
- name: "new_name";
92
- tableName: "agent_renames";
93
- dataType: "string";
94
- columnType: "PgText";
95
- data: string;
96
- driverParam: string;
97
- notNull: true;
98
- hasDefault: false;
99
- isPrimaryKey: false;
100
- isAutoincrement: false;
101
- hasRuntimeDefault: false;
102
- enumValues: [string, ...string[]];
103
- baseColumn: never;
104
- identity: undefined;
105
- generated: undefined;
106
- }, {}, {}>;
107
- issuedAt: import("drizzle-orm/pg-core").PgColumn<{
108
- name: "issued_at";
109
- tableName: "agent_renames";
110
- dataType: "date";
111
- columnType: "PgTimestamp";
112
- data: Date;
113
- driverParam: string;
114
- notNull: true;
115
- hasDefault: false;
116
- isPrimaryKey: false;
117
- isAutoincrement: false;
118
- hasRuntimeDefault: false;
119
- enumValues: undefined;
120
- baseColumn: never;
121
- identity: undefined;
122
- generated: undefined;
123
- }, {}, {}>;
124
- };
125
- dialect: 'pg';
126
- }>;
@@ -1,20 +0,0 @@
1
- import { bigserial, index, pgTable, text, timestamp, } from 'drizzle-orm/pg-core';
2
- import { agents } from './agents.js';
3
- import { timestamps } from './timestamps.js';
4
- // One row per rename. An old handle keeps resolving, as a redirect, for
5
- // RENAME_REDIRECT_DAYS after the rename, and the profile shows the old name
6
- // for as long. issued_at is the signed issuedAt of the rename, so an older
7
- // envelope sent again is refused.
8
- //
9
- // bigserial is a bigint filled from its own sequence. mode 'number' reads it
10
- // as a JS number, which is safe well past any count of renames.
11
- export const agentRenames = pgTable('agent_renames', {
12
- id: bigserial('id', { mode: 'number' }).primaryKey(),
13
- agentId: text('agent_id')
14
- .notNull()
15
- .references(() => agents.id),
16
- oldName: text('old_name').notNull(),
17
- newName: text('new_name').notNull(),
18
- issuedAt: timestamp('issued_at', { withTimezone: true }).notNull(),
19
- ...timestamps,
20
- }, (t) => [index('agent_renames_agent_created_idx').on(t.agentId, t.createdAt)]);