@secondlayer/shared 7.9.0 → 7.10.0

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.
@@ -0,0 +1,163 @@
1
+ import { type Kysely, sql } from "kysely";
2
+ import { onChainPlane } from "../src/db/migration-role.ts";
3
+
4
+ /**
5
+ * Coverage kernel — registry, runs, per-block receipts, compacted segments,
6
+ * and failures. Lives on the source plane with the chain it attests.
7
+ *
8
+ * Constraints here must match `src/coverage/constraints.ts`.
9
+ */
10
+ export async function up(db: Kysely<unknown>): Promise<void> {
11
+ await onChainPlane(async () => {
12
+ await sql`SET lock_timeout = '30s'`.execute(db);
13
+
14
+ await sql`
15
+ CREATE TABLE stage_registry (
16
+ id TEXT PRIMARY KEY,
17
+ kind TEXT NOT NULL
18
+ CHECK (kind IN ('raw', 'decode', 'subgraph', 'queue')),
19
+ depends_on TEXT REFERENCES stage_registry (id),
20
+ native_clock TEXT NOT NULL
21
+ CHECK (native_clock IN ('block', 'cursor', 'queue')),
22
+ producer_version TEXT NOT NULL,
23
+ repair_mode TEXT NOT NULL
24
+ CHECK (repair_mode IN (
25
+ 'range_safe', 'full_reindex', 'archive_replay', 'none'
26
+ )),
27
+ enabled BOOLEAN NOT NULL DEFAULT true,
28
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now()
29
+ )
30
+ `.execute(db);
31
+
32
+ await sql`
33
+ CREATE TABLE stage_runs (
34
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
35
+ stage_id TEXT NOT NULL REFERENCES stage_registry (id),
36
+ code_hash TEXT NOT NULL,
37
+ config_hash TEXT NOT NULL,
38
+ handler_hash TEXT,
39
+ target_height BIGINT CHECK (target_height IS NULL OR target_height >= 0),
40
+ target_cursor TEXT,
41
+ status TEXT NOT NULL
42
+ CHECK (status IN (
43
+ 'pending', 'running', 'complete', 'syncing', 'lagging',
44
+ 'gap', 'stale', 'failed', 'unverified_import', 'unanchored',
45
+ 'source_unavailable', 'out_of_scope', 'disabled', 'halted'
46
+ )),
47
+ complete_through BIGINT
48
+ CHECK (complete_through IS NULL OR complete_through >= 0),
49
+ started_at TIMESTAMPTZ NOT NULL DEFAULT now(),
50
+ finished_at TIMESTAMPTZ
51
+ )
52
+ `.execute(db);
53
+
54
+ await sql`
55
+ CREATE INDEX stage_runs_stage_started_idx
56
+ ON stage_runs (stage_id, started_at DESC)
57
+ `.execute(db);
58
+
59
+ await sql`
60
+ CREATE TABLE stage_block_receipts (
61
+ id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
62
+ stage_id TEXT NOT NULL REFERENCES stage_registry (id),
63
+ run_id UUID REFERENCES stage_runs (id) ON DELETE SET NULL,
64
+ block_height BIGINT NOT NULL CHECK (block_height >= 0),
65
+ block_hash TEXT NOT NULL,
66
+ input_count INTEGER NOT NULL CHECK (input_count >= 0),
67
+ input_digest TEXT NOT NULL,
68
+ effect_digest TEXT NOT NULL,
69
+ finalized BOOLEAN NOT NULL DEFAULT false,
70
+ compacted_at TIMESTAMPTZ,
71
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
72
+ CONSTRAINT stage_block_receipts_compacted_finalized
73
+ CHECK (compacted_at IS NULL OR finalized),
74
+ CONSTRAINT stage_block_receipts_stage_height_hash_key
75
+ UNIQUE (stage_id, block_height, block_hash)
76
+ )
77
+ `.execute(db);
78
+
79
+ await sql`
80
+ CREATE INDEX stage_block_receipts_open_idx
81
+ ON stage_block_receipts (stage_id, block_height)
82
+ WHERE compacted_at IS NULL
83
+ `.execute(db);
84
+
85
+ await sql`
86
+ CREATE TABLE coverage_segments (
87
+ id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
88
+ stage_id TEXT NOT NULL REFERENCES stage_registry (id),
89
+ from_height BIGINT NOT NULL CHECK (from_height >= 0),
90
+ to_height BIGINT NOT NULL,
91
+ chain_digest TEXT NOT NULL,
92
+ input_digest TEXT NOT NULL,
93
+ output_digest TEXT NOT NULL,
94
+ sealed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
95
+ CONSTRAINT coverage_segments_range_ordered
96
+ CHECK (from_height <= to_height),
97
+ CONSTRAINT coverage_segments_stage_range_key
98
+ UNIQUE (stage_id, from_height, to_height)
99
+ )
100
+ `.execute(db);
101
+
102
+ await sql`
103
+ CREATE INDEX coverage_segments_stage_from_idx
104
+ ON coverage_segments (stage_id, from_height, to_height)
105
+ `.execute(db);
106
+
107
+ await sql`
108
+ CREATE TABLE stage_failures (
109
+ id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
110
+ stage_id TEXT NOT NULL REFERENCES stage_registry (id),
111
+ run_id UUID REFERENCES stage_runs (id) ON DELETE SET NULL,
112
+ unit_kind TEXT NOT NULL
113
+ CHECK (unit_kind IN ('block', 'range', 'cursor', 'queue')),
114
+ from_height BIGINT CHECK (from_height IS NULL OR from_height >= 0),
115
+ to_height BIGINT CHECK (to_height IS NULL OR to_height >= 0),
116
+ class TEXT NOT NULL
117
+ CHECK (class IN (
118
+ 'omission', 'version', 'digest_mismatch', 'crash',
119
+ 'reorg', 'source_gap', 'handler', 'timeout', 'unknown'
120
+ )),
121
+ retry_state TEXT NOT NULL
122
+ CHECK (retry_state IN ('open', 'retrying', 'halted', 'resolved')),
123
+ retry_count INTEGER NOT NULL DEFAULT 0 CHECK (retry_count >= 0),
124
+ last_error TEXT,
125
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
126
+ resolved_at TIMESTAMPTZ,
127
+ retain_until TIMESTAMPTZ NOT NULL
128
+ DEFAULT (now() + interval '30 days'),
129
+ CONSTRAINT stage_failures_range_ordered
130
+ CHECK (
131
+ from_height IS NULL
132
+ OR to_height IS NULL
133
+ OR from_height <= to_height
134
+ ),
135
+ CONSTRAINT stage_failures_retain_until
136
+ CHECK (retain_until >= created_at),
137
+ CONSTRAINT stage_failures_resolved_at
138
+ CHECK (retry_state <> 'resolved' OR resolved_at IS NOT NULL)
139
+ )
140
+ `.execute(db);
141
+
142
+ await sql`
143
+ CREATE INDEX stage_failures_open_idx
144
+ ON stage_failures (stage_id, retry_state, created_at)
145
+ WHERE retry_state <> 'resolved'
146
+ `.execute(db);
147
+
148
+ await sql`
149
+ CREATE INDEX stage_failures_retain_until_idx
150
+ ON stage_failures (retain_until)
151
+ `.execute(db);
152
+ });
153
+ }
154
+
155
+ export async function down(db: Kysely<unknown>): Promise<void> {
156
+ await onChainPlane(async () => {
157
+ await sql`DROP TABLE IF EXISTS stage_failures`.execute(db);
158
+ await sql`DROP TABLE IF EXISTS coverage_segments`.execute(db);
159
+ await sql`DROP TABLE IF EXISTS stage_block_receipts`.execute(db);
160
+ await sql`DROP TABLE IF EXISTS stage_runs`.execute(db);
161
+ await sql`DROP TABLE IF EXISTS stage_registry`.execute(db);
162
+ });
163
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@secondlayer/shared",
3
- "version": "7.9.0",
3
+ "version": "7.10.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -152,6 +152,10 @@
152
152
  "types": "./dist/src/archive/derived-stage-report.d.ts",
153
153
  "import": "./dist/src/archive/derived-stage-report.js"
154
154
  },
155
+ "./coverage": {
156
+ "types": "./dist/src/coverage/index.d.ts",
157
+ "import": "./dist/src/coverage/index.js"
158
+ },
155
159
  "./errors": {
156
160
  "types": "./dist/src/errors.d.ts",
157
161
  "import": "./dist/src/errors.js"