@secondlayer/shared 7.10.0 → 7.11.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.
- package/dist/src/runtime/index.d.ts +256 -0
- package/dist/src/runtime/index.js +694 -0
- package/dist/src/runtime/index.js.map +19 -0
- package/package.json +5 -1
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle modules — each runtime plane exposes start/stop/health so a
|
|
3
|
+
* supervisor can restart one without taking the others down.
|
|
4
|
+
*/
|
|
5
|
+
declare const MODULE_IDS: readonly ["api", "ingest", "decoder", "subgraph", "notification", "verification", "publisher"];
|
|
6
|
+
type ModuleId = (typeof MODULE_IDS)[number];
|
|
7
|
+
declare const MODULE_STATES: readonly ["stopped", "starting", "running", "degraded", "failed"];
|
|
8
|
+
type ModuleState = (typeof MODULE_STATES)[number];
|
|
9
|
+
type ModuleHealth = {
|
|
10
|
+
id: ModuleId
|
|
11
|
+
state: ModuleState
|
|
12
|
+
detail: string | null
|
|
13
|
+
restarts: number
|
|
14
|
+
};
|
|
15
|
+
type RuntimeModule = {
|
|
16
|
+
id: ModuleId
|
|
17
|
+
start: () => Promise<void>
|
|
18
|
+
stop: () => Promise<void>
|
|
19
|
+
health: () => ModuleHealth
|
|
20
|
+
};
|
|
21
|
+
declare const DEFAULT_PROFILE: readonly ModuleId[];
|
|
22
|
+
declare const PUBLISHER_PROFILE: readonly ModuleId[];
|
|
23
|
+
declare function isModuleId(value: string): value is ModuleId;
|
|
24
|
+
declare function emptyHealth(id: ModuleId): ModuleHealth;
|
|
25
|
+
/** In-memory module used by restart/fault tests. */
|
|
26
|
+
declare function createMemoryModule(id: ModuleId, opts?: {
|
|
27
|
+
failStart?: boolean
|
|
28
|
+
loop?: boolean
|
|
29
|
+
onStart?: () => void
|
|
30
|
+
onStop?: () => void
|
|
31
|
+
}): RuntimeModule & {
|
|
32
|
+
setState: (state: ModuleState, detail?: string) => void
|
|
33
|
+
};
|
|
34
|
+
type SupervisorHealth = {
|
|
35
|
+
status: "healthy" | "degraded" | "failed"
|
|
36
|
+
modules: ModuleHealth[]
|
|
37
|
+
};
|
|
38
|
+
type Supervisor = {
|
|
39
|
+
start: (ids?: readonly ModuleId[]) => Promise<void>
|
|
40
|
+
stop: (id?: ModuleId) => Promise<void>
|
|
41
|
+
restart: (id: ModuleId) => Promise<void>
|
|
42
|
+
health: () => SupervisorHealth
|
|
43
|
+
};
|
|
44
|
+
declare function createSupervisor(modules: readonly RuntimeModule[]): Supervisor;
|
|
45
|
+
/**
|
|
46
|
+
* Handler isolation — untrusted subgraph handlers run behind a timeout,
|
|
47
|
+
* optional network deny, and cannot take down the host process.
|
|
48
|
+
*/
|
|
49
|
+
declare const ISOLATION_FAULTS: readonly ["timeout", "throw", "oom", "kill", "network"];
|
|
50
|
+
type IsolationFault = (typeof ISOLATION_FAULTS)[number];
|
|
51
|
+
type IsolationLimits = {
|
|
52
|
+
timeoutMs: number
|
|
53
|
+
memoryMb?: number
|
|
54
|
+
allowNetwork?: boolean
|
|
55
|
+
};
|
|
56
|
+
type IsolationResult = {
|
|
57
|
+
ok: true
|
|
58
|
+
hostAlive: true
|
|
59
|
+
} | {
|
|
60
|
+
ok: false
|
|
61
|
+
fault: IsolationFault
|
|
62
|
+
hostAlive: true
|
|
63
|
+
detail: string
|
|
64
|
+
};
|
|
65
|
+
declare class IsolationNetworkError extends Error {
|
|
66
|
+
readonly name = "IsolationNetworkError";
|
|
67
|
+
}
|
|
68
|
+
declare class IsolationKillError extends Error {
|
|
69
|
+
readonly name = "IsolationKillError";
|
|
70
|
+
}
|
|
71
|
+
declare class IsolationOomError extends Error {
|
|
72
|
+
readonly name = "IsolationOomError";
|
|
73
|
+
}
|
|
74
|
+
declare function isolateHandler(run: (ctx: {
|
|
75
|
+
signal: AbortSignal
|
|
76
|
+
fetch: (url: string) => Promise<unknown>
|
|
77
|
+
}) => Promise<void>, limits: IsolationLimits): Promise<IsolationResult>;
|
|
78
|
+
/**
|
|
79
|
+
* Embedded migration — advisory-locked before listeners/workers start.
|
|
80
|
+
* Concurrent boots serialize. A failed pass releases the lock and refuses
|
|
81
|
+
* to start the rest of the runtime.
|
|
82
|
+
*/
|
|
83
|
+
declare const MIGRATION_LOCK_KEY = 1397509447;
|
|
84
|
+
type EmbeddedMigration = {
|
|
85
|
+
applied: string[]
|
|
86
|
+
ok: boolean
|
|
87
|
+
error: string | null
|
|
88
|
+
};
|
|
89
|
+
type MigrationRunner = {
|
|
90
|
+
acquire: (key: number) => Promise<boolean>
|
|
91
|
+
release: (key: number) => Promise<void>
|
|
92
|
+
apply: () => Promise<string[]>
|
|
93
|
+
};
|
|
94
|
+
declare function migrateEmbedded(runner: MigrationRunner): Promise<EmbeddedMigration>;
|
|
95
|
+
/** In-memory lock used by concurrent-startup tests. */
|
|
96
|
+
declare function createMemoryMigrationRunner(opts?: {
|
|
97
|
+
fail?: boolean
|
|
98
|
+
delayMs?: number
|
|
99
|
+
sleep?: (ms: number) => Promise<void>
|
|
100
|
+
}): MigrationRunner & {
|
|
101
|
+
holders: number
|
|
102
|
+
appliedCount: number
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Minimal runtime config — six or fewer required non-secret values.
|
|
106
|
+
* Unknown or contradictory values fail before ingest starts.
|
|
107
|
+
*/
|
|
108
|
+
declare const NODE_MODES: readonly ["external", "stacks", "full"];
|
|
109
|
+
type NodeMode = (typeof NODE_MODES)[number];
|
|
110
|
+
declare const NETWORKS: readonly ["mainnet", "testnet", "devnet"];
|
|
111
|
+
type RuntimeNetwork = (typeof NETWORKS)[number];
|
|
112
|
+
/** Required non-secret keys. Secrets (tokens, signing keys) come from `sl init`. */
|
|
113
|
+
declare const REQUIRED_KEYS: readonly ["NETWORK", "DATABASE_URL", "NODE_MODE", "DATA_DIR", "API_PORT", "INDEXER_PORT"];
|
|
114
|
+
type RequiredConfigKey = (typeof REQUIRED_KEYS)[number];
|
|
115
|
+
declare const OPTIONAL_KEYS: readonly ["STACKS_NODE_RPC_URL", "LISTEN_HOST", "LOG_LEVEL", "INSTANCE_MODE"];
|
|
116
|
+
declare const SECRET_KEYS: readonly ["INSTANCE_TOKEN", "API_KEY", "SECONDLAYER_SECRETS_KEY", "STREAMS_SIGNING_PRIVATE_KEY", "SECONDLAYER_WEBHOOK_SIGNING_PRIVATE_KEY", "POSTGRES_PASSWORD", "BITCOIN_RPC_PASSWORD"];
|
|
117
|
+
type RuntimeConfig = {
|
|
118
|
+
NETWORK: RuntimeNetwork
|
|
119
|
+
DATABASE_URL: string
|
|
120
|
+
NODE_MODE: NodeMode
|
|
121
|
+
DATA_DIR: string
|
|
122
|
+
API_PORT: number
|
|
123
|
+
INDEXER_PORT: number
|
|
124
|
+
STACKS_NODE_RPC_URL: string | null
|
|
125
|
+
LISTEN_HOST: string
|
|
126
|
+
LOG_LEVEL: string
|
|
127
|
+
};
|
|
128
|
+
type ConfigResult = {
|
|
129
|
+
ok: true
|
|
130
|
+
config: RuntimeConfig
|
|
131
|
+
} | {
|
|
132
|
+
ok: false
|
|
133
|
+
errors: string[]
|
|
134
|
+
};
|
|
135
|
+
declare function parseRuntimeConfig(env: Record<string, string | undefined>): ConfigResult;
|
|
136
|
+
declare const COVERAGE_STATES: readonly ["complete", "syncing", "lagging", "gap", "stale", "failed", "unverified_import", "unanchored", "source_unavailable", "out_of_scope", "disabled"];
|
|
137
|
+
type CoverageState = (typeof COVERAGE_STATES)[number];
|
|
138
|
+
declare const STATUS_PLANES: readonly ["node", "raw", "decoder", "subgraph", "queue", "archive", "disk", "coverage"];
|
|
139
|
+
type StatusPlane = (typeof STATUS_PLANES)[number];
|
|
140
|
+
type PlaneStatus = {
|
|
141
|
+
plane: StatusPlane
|
|
142
|
+
state: string
|
|
143
|
+
action: string
|
|
144
|
+
};
|
|
145
|
+
type RuntimeStatusReport = {
|
|
146
|
+
status: SupervisorHealth["status"]
|
|
147
|
+
modules: ModuleHealth[]
|
|
148
|
+
planes: PlaneStatus[]
|
|
149
|
+
};
|
|
150
|
+
declare function reportRuntimeStatus(input: {
|
|
151
|
+
supervisor: SupervisorHealth
|
|
152
|
+
node?: string
|
|
153
|
+
archive?: string
|
|
154
|
+
disk?: string
|
|
155
|
+
coverage?: CoverageState | string
|
|
156
|
+
}): RuntimeStatusReport;
|
|
157
|
+
declare function actionFor(plane: StatusPlane, state: string): string;
|
|
158
|
+
/**
|
|
159
|
+
* Backup bundle — consistent DB, pinned config, encrypted keys, handler
|
|
160
|
+
* manifests, and scope. Restore onto a wiped host must deep-verify green.
|
|
161
|
+
*/
|
|
162
|
+
declare const BACKUP_PARTS: readonly ["db", "config", "keys", "handlers", "scope"];
|
|
163
|
+
type BackupPart = (typeof BACKUP_PARTS)[number];
|
|
164
|
+
type BackupManifest = {
|
|
165
|
+
created_at: string
|
|
166
|
+
network: string
|
|
167
|
+
parts: BackupPart[]
|
|
168
|
+
encrypted: boolean
|
|
169
|
+
scope: {
|
|
170
|
+
from_height: number
|
|
171
|
+
to_height: number | null
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
type BackupPlan = {
|
|
175
|
+
ok: boolean
|
|
176
|
+
manifest: BackupManifest
|
|
177
|
+
reason: string
|
|
178
|
+
};
|
|
179
|
+
declare function planBackup(input: {
|
|
180
|
+
network: string
|
|
181
|
+
encryptedKeys: boolean
|
|
182
|
+
fromHeight: number
|
|
183
|
+
toHeight?: number | null
|
|
184
|
+
now?: string
|
|
185
|
+
}): BackupPlan;
|
|
186
|
+
type RestoreResult = {
|
|
187
|
+
ok: true
|
|
188
|
+
applied: boolean
|
|
189
|
+
deep_green: boolean
|
|
190
|
+
} | {
|
|
191
|
+
ok: false
|
|
192
|
+
reason: string
|
|
193
|
+
};
|
|
194
|
+
declare function restoreBackup(plan: BackupPlan, opts?: {
|
|
195
|
+
apply?: boolean
|
|
196
|
+
deepVerify?: boolean
|
|
197
|
+
}): RestoreResult;
|
|
198
|
+
/**
|
|
199
|
+
* Upgrade contract — pin image, preflight schema/disk, backup first,
|
|
200
|
+
* migrate, health/verify, document rollback limits.
|
|
201
|
+
*/
|
|
202
|
+
declare const UPGRADE_STEPS: readonly ["pin", "preflight", "backup", "migrate", "health", "verify"];
|
|
203
|
+
type UpgradeStep = (typeof UPGRADE_STEPS)[number];
|
|
204
|
+
type UpgradePlan = {
|
|
205
|
+
from: string
|
|
206
|
+
to: string
|
|
207
|
+
steps: UpgradeStep[]
|
|
208
|
+
ok: boolean
|
|
209
|
+
reason: string
|
|
210
|
+
rollback: string
|
|
211
|
+
};
|
|
212
|
+
declare function planUpgrade(input: {
|
|
213
|
+
from: string
|
|
214
|
+
to: string
|
|
215
|
+
diskOk: boolean
|
|
216
|
+
schemaOk: boolean
|
|
217
|
+
backupDone: boolean
|
|
218
|
+
supported?: readonly string[]
|
|
219
|
+
}): UpgradePlan;
|
|
220
|
+
declare function applyUpgrade(plan: UpgradePlan, opts?: {
|
|
221
|
+
apply?: boolean
|
|
222
|
+
}): {
|
|
223
|
+
ok: boolean
|
|
224
|
+
applied: boolean
|
|
225
|
+
reason: string
|
|
226
|
+
};
|
|
227
|
+
/**
|
|
228
|
+
* Resource guardrails — preflight RAM/disk/Postgres and estimate growth.
|
|
229
|
+
* Constrained fixtures fail early.
|
|
230
|
+
*/
|
|
231
|
+
type ResourceSnapshot = {
|
|
232
|
+
ramMb: number
|
|
233
|
+
diskGb: number
|
|
234
|
+
postgresMaxConnections: number
|
|
235
|
+
postgresSharedBuffersMb?: number
|
|
236
|
+
};
|
|
237
|
+
type GuardrailResult = {
|
|
238
|
+
ok: true
|
|
239
|
+
estimates: {
|
|
240
|
+
diskGbPer100kBlocks: number
|
|
241
|
+
}
|
|
242
|
+
} | {
|
|
243
|
+
ok: false
|
|
244
|
+
errors: string[]
|
|
245
|
+
};
|
|
246
|
+
declare const FLOORS: {
|
|
247
|
+
readonly appRamMb: 4096
|
|
248
|
+
readonly fullRamMb: 98304
|
|
249
|
+
readonly appDiskGb: 80
|
|
250
|
+
readonly fullDiskGb: 1500
|
|
251
|
+
readonly postgresMaxConnections: 50
|
|
252
|
+
};
|
|
253
|
+
declare function preflightResources(snap: ResourceSnapshot, mode: "external" | "stacks" | "full"): GuardrailResult;
|
|
254
|
+
declare const MODULE_COMMANDS: Record<ModuleId, readonly string[]>;
|
|
255
|
+
declare function commandFor(id: ModuleId): readonly string[];
|
|
256
|
+
export { restoreBackup, reportRuntimeStatus, preflightResources, planUpgrade, planBackup, parseRuntimeConfig, migrateEmbedded, isolateHandler, isModuleId, emptyHealth, createSupervisor, createMemoryModule, createMemoryMigrationRunner, commandFor, applyUpgrade, actionFor, UpgradeStep, UpgradePlan, UPGRADE_STEPS, SupervisorHealth, Supervisor, StatusPlane, STATUS_PLANES, SECRET_KEYS, RuntimeStatusReport, RuntimeNetwork, RuntimeModule, RuntimeConfig, RestoreResult, ResourceSnapshot, RequiredConfigKey, REQUIRED_KEYS, PlaneStatus, PUBLISHER_PROFILE, OPTIONAL_KEYS, NodeMode, NODE_MODES, NETWORKS, ModuleState, ModuleId, ModuleHealth, MigrationRunner, MODULE_STATES, MODULE_IDS, MODULE_COMMANDS, MIGRATION_LOCK_KEY, IsolationResult, IsolationOomError, IsolationNetworkError, IsolationLimits, IsolationKillError, IsolationFault, ISOLATION_FAULTS, GuardrailResult, FLOORS, EmbeddedMigration, DEFAULT_PROFILE, ConfigResult, BackupPlan, BackupPart, BackupManifest, BACKUP_PARTS };
|
|
@@ -0,0 +1,694 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// src/runtime/modules.ts
|
|
18
|
+
var MODULE_IDS = [
|
|
19
|
+
"api",
|
|
20
|
+
"ingest",
|
|
21
|
+
"decoder",
|
|
22
|
+
"subgraph",
|
|
23
|
+
"notification",
|
|
24
|
+
"verification",
|
|
25
|
+
"publisher"
|
|
26
|
+
];
|
|
27
|
+
var MODULE_STATES = [
|
|
28
|
+
"stopped",
|
|
29
|
+
"starting",
|
|
30
|
+
"running",
|
|
31
|
+
"degraded",
|
|
32
|
+
"failed"
|
|
33
|
+
];
|
|
34
|
+
var DEFAULT_PROFILE = [
|
|
35
|
+
"api",
|
|
36
|
+
"ingest",
|
|
37
|
+
"decoder",
|
|
38
|
+
"subgraph",
|
|
39
|
+
"notification",
|
|
40
|
+
"verification"
|
|
41
|
+
];
|
|
42
|
+
var PUBLISHER_PROFILE = ["publisher"];
|
|
43
|
+
function isModuleId(value) {
|
|
44
|
+
return MODULE_IDS.includes(value);
|
|
45
|
+
}
|
|
46
|
+
function emptyHealth(id) {
|
|
47
|
+
return { id, state: "stopped", detail: null, restarts: 0 };
|
|
48
|
+
}
|
|
49
|
+
function createMemoryModule(id, opts) {
|
|
50
|
+
let health = emptyHealth(id);
|
|
51
|
+
return {
|
|
52
|
+
id,
|
|
53
|
+
setState(state, detail) {
|
|
54
|
+
health = { ...health, state, detail: detail ?? health.detail };
|
|
55
|
+
},
|
|
56
|
+
async start() {
|
|
57
|
+
if (opts?.failStart) {
|
|
58
|
+
health = {
|
|
59
|
+
...health,
|
|
60
|
+
state: "failed",
|
|
61
|
+
detail: "start failed"
|
|
62
|
+
};
|
|
63
|
+
throw new Error(`${id} start failed`);
|
|
64
|
+
}
|
|
65
|
+
opts?.onStart?.();
|
|
66
|
+
health = {
|
|
67
|
+
...health,
|
|
68
|
+
state: opts?.loop ? "failed" : "running",
|
|
69
|
+
detail: opts?.loop ? "loop contained" : null,
|
|
70
|
+
restarts: health.restarts
|
|
71
|
+
};
|
|
72
|
+
if (opts?.loop)
|
|
73
|
+
throw new Error(`${id} loop`);
|
|
74
|
+
},
|
|
75
|
+
async stop() {
|
|
76
|
+
opts?.onStop?.();
|
|
77
|
+
health = { ...health, state: "stopped" };
|
|
78
|
+
},
|
|
79
|
+
health: () => health
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// src/runtime/supervisor.ts
|
|
83
|
+
function createSupervisor(modules) {
|
|
84
|
+
const byId = new Map(modules.map((m) => [m.id, m]));
|
|
85
|
+
const selected = new Set;
|
|
86
|
+
const restarts = new Map;
|
|
87
|
+
function snapshot() {
|
|
88
|
+
return [...byId.values()].map((mod) => {
|
|
89
|
+
const health = selected.has(mod.id) ? mod.health() : emptyHealth(mod.id);
|
|
90
|
+
return { ...health, restarts: restarts.get(mod.id) ?? health.restarts };
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function aggregate(list) {
|
|
94
|
+
const live = list.filter((m) => selected.has(m.id));
|
|
95
|
+
if (live.length === 0)
|
|
96
|
+
return "failed";
|
|
97
|
+
if (live.every((m) => m.state === "failed" || m.state === "stopped")) {
|
|
98
|
+
return "failed";
|
|
99
|
+
}
|
|
100
|
+
if (live.some((m) => m.state === "failed" || m.state === "degraded")) {
|
|
101
|
+
return "degraded";
|
|
102
|
+
}
|
|
103
|
+
if (live.every((m) => m.state === "running"))
|
|
104
|
+
return "healthy";
|
|
105
|
+
return "degraded";
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
async start(ids) {
|
|
109
|
+
const targets = ids ?? [...byId.keys()];
|
|
110
|
+
for (const id of targets) {
|
|
111
|
+
const mod = byId.get(id);
|
|
112
|
+
if (!mod)
|
|
113
|
+
continue;
|
|
114
|
+
selected.add(id);
|
|
115
|
+
try {
|
|
116
|
+
await mod.start();
|
|
117
|
+
} catch {}
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
async stop(id) {
|
|
121
|
+
if (id) {
|
|
122
|
+
const mod = byId.get(id);
|
|
123
|
+
if (mod && selected.has(id))
|
|
124
|
+
await mod.stop();
|
|
125
|
+
selected.delete(id);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
for (const mid of [...selected]) {
|
|
129
|
+
const mod = byId.get(mid);
|
|
130
|
+
if (mod)
|
|
131
|
+
await mod.stop();
|
|
132
|
+
selected.delete(mid);
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
async restart(id) {
|
|
136
|
+
const mod = byId.get(id);
|
|
137
|
+
if (!mod)
|
|
138
|
+
throw new Error(`unknown module ${id}`);
|
|
139
|
+
if (selected.has(id))
|
|
140
|
+
await mod.stop();
|
|
141
|
+
selected.add(id);
|
|
142
|
+
restarts.set(id, (restarts.get(id) ?? 0) + 1);
|
|
143
|
+
try {
|
|
144
|
+
await mod.start();
|
|
145
|
+
} catch {}
|
|
146
|
+
},
|
|
147
|
+
health() {
|
|
148
|
+
const modules2 = snapshot();
|
|
149
|
+
return { status: aggregate(modules2), modules: modules2 };
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
// src/runtime/isolate.ts
|
|
154
|
+
var ISOLATION_FAULTS = [
|
|
155
|
+
"timeout",
|
|
156
|
+
"throw",
|
|
157
|
+
"oom",
|
|
158
|
+
"kill",
|
|
159
|
+
"network"
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
class IsolationNetworkError extends Error {
|
|
163
|
+
name = "IsolationNetworkError";
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
class IsolationKillError extends Error {
|
|
167
|
+
name = "IsolationKillError";
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
class IsolationOomError extends Error {
|
|
171
|
+
name = "IsolationOomError";
|
|
172
|
+
}
|
|
173
|
+
async function isolateHandler(run, limits) {
|
|
174
|
+
const controller = new AbortController;
|
|
175
|
+
const timer = setTimeout(() => controller.abort(), limits.timeoutMs);
|
|
176
|
+
const blockedFetch = async (_url) => {
|
|
177
|
+
throw new IsolationNetworkError("network is disabled in this handler");
|
|
178
|
+
};
|
|
179
|
+
try {
|
|
180
|
+
await run({
|
|
181
|
+
signal: controller.signal,
|
|
182
|
+
fetch: limits.allowNetwork ? (url) => fetch(url) : blockedFetch
|
|
183
|
+
});
|
|
184
|
+
if (controller.signal.aborted) {
|
|
185
|
+
return {
|
|
186
|
+
ok: false,
|
|
187
|
+
fault: "timeout",
|
|
188
|
+
hostAlive: true,
|
|
189
|
+
detail: `exceeded ${limits.timeoutMs}ms`
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
return { ok: true, hostAlive: true };
|
|
193
|
+
} catch (error) {
|
|
194
|
+
if (controller.signal.aborted || isAbort(error)) {
|
|
195
|
+
return {
|
|
196
|
+
ok: false,
|
|
197
|
+
fault: "timeout",
|
|
198
|
+
hostAlive: true,
|
|
199
|
+
detail: `exceeded ${limits.timeoutMs}ms`
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
if (error instanceof IsolationNetworkError) {
|
|
203
|
+
return {
|
|
204
|
+
ok: false,
|
|
205
|
+
fault: "network",
|
|
206
|
+
hostAlive: true,
|
|
207
|
+
detail: error.message
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
if (error instanceof IsolationKillError) {
|
|
211
|
+
return {
|
|
212
|
+
ok: false,
|
|
213
|
+
fault: "kill",
|
|
214
|
+
hostAlive: true,
|
|
215
|
+
detail: error.message
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
if (error instanceof IsolationOomError) {
|
|
219
|
+
return {
|
|
220
|
+
ok: false,
|
|
221
|
+
fault: "oom",
|
|
222
|
+
hostAlive: true,
|
|
223
|
+
detail: error.message
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
ok: false,
|
|
228
|
+
fault: "throw",
|
|
229
|
+
hostAlive: true,
|
|
230
|
+
detail: error instanceof Error ? error.message : String(error)
|
|
231
|
+
};
|
|
232
|
+
} finally {
|
|
233
|
+
clearTimeout(timer);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
function isAbort(error) {
|
|
237
|
+
return error instanceof Error && error.name === "AbortError";
|
|
238
|
+
}
|
|
239
|
+
// src/runtime/migrate-embed.ts
|
|
240
|
+
var MIGRATION_LOCK_KEY = 1397509447;
|
|
241
|
+
async function migrateEmbedded(runner) {
|
|
242
|
+
const got = await runner.acquire(MIGRATION_LOCK_KEY);
|
|
243
|
+
if (!got) {
|
|
244
|
+
return {
|
|
245
|
+
applied: [],
|
|
246
|
+
ok: false,
|
|
247
|
+
error: "migration lock held by another process"
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
const applied = await runner.apply();
|
|
252
|
+
return { applied, ok: true, error: null };
|
|
253
|
+
} catch (error) {
|
|
254
|
+
return {
|
|
255
|
+
applied: [],
|
|
256
|
+
ok: false,
|
|
257
|
+
error: error instanceof Error ? error.message : String(error)
|
|
258
|
+
};
|
|
259
|
+
} finally {
|
|
260
|
+
await runner.release(MIGRATION_LOCK_KEY);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function createMemoryMigrationRunner(opts) {
|
|
264
|
+
let held = false;
|
|
265
|
+
const state = { holders: 0, appliedCount: 0 };
|
|
266
|
+
return {
|
|
267
|
+
get holders() {
|
|
268
|
+
return state.holders;
|
|
269
|
+
},
|
|
270
|
+
get appliedCount() {
|
|
271
|
+
return state.appliedCount;
|
|
272
|
+
},
|
|
273
|
+
async acquire() {
|
|
274
|
+
if (held)
|
|
275
|
+
return false;
|
|
276
|
+
held = true;
|
|
277
|
+
state.holders += 1;
|
|
278
|
+
return true;
|
|
279
|
+
},
|
|
280
|
+
async release() {
|
|
281
|
+
held = false;
|
|
282
|
+
state.holders = Math.max(0, state.holders - 1);
|
|
283
|
+
},
|
|
284
|
+
async apply() {
|
|
285
|
+
if (opts?.delayMs)
|
|
286
|
+
await (opts.sleep ?? delay)(opts.delayMs);
|
|
287
|
+
if (opts?.fail)
|
|
288
|
+
throw new Error("migration failed");
|
|
289
|
+
state.appliedCount += 1;
|
|
290
|
+
return ["0116_coverage_schema"];
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
function delay(ms) {
|
|
295
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
296
|
+
}
|
|
297
|
+
// src/runtime/config.ts
|
|
298
|
+
var NODE_MODES = ["external", "stacks", "full"];
|
|
299
|
+
var NETWORKS = ["mainnet", "testnet", "devnet"];
|
|
300
|
+
var REQUIRED_KEYS = [
|
|
301
|
+
"NETWORK",
|
|
302
|
+
"DATABASE_URL",
|
|
303
|
+
"NODE_MODE",
|
|
304
|
+
"DATA_DIR",
|
|
305
|
+
"API_PORT",
|
|
306
|
+
"INDEXER_PORT"
|
|
307
|
+
];
|
|
308
|
+
var OPTIONAL_KEYS = [
|
|
309
|
+
"STACKS_NODE_RPC_URL",
|
|
310
|
+
"LISTEN_HOST",
|
|
311
|
+
"LOG_LEVEL",
|
|
312
|
+
"INSTANCE_MODE"
|
|
313
|
+
];
|
|
314
|
+
var SECRET_KEYS = [
|
|
315
|
+
"INSTANCE_TOKEN",
|
|
316
|
+
"API_KEY",
|
|
317
|
+
"SECONDLAYER_SECRETS_KEY",
|
|
318
|
+
"STREAMS_SIGNING_PRIVATE_KEY",
|
|
319
|
+
"SECONDLAYER_WEBHOOK_SIGNING_PRIVATE_KEY",
|
|
320
|
+
"POSTGRES_PASSWORD",
|
|
321
|
+
"BITCOIN_RPC_PASSWORD"
|
|
322
|
+
];
|
|
323
|
+
var KNOWN = new Set([
|
|
324
|
+
...REQUIRED_KEYS,
|
|
325
|
+
...OPTIONAL_KEYS,
|
|
326
|
+
...SECRET_KEYS,
|
|
327
|
+
"SOURCE_DATABASE_URL",
|
|
328
|
+
"TARGET_DATABASE_URL",
|
|
329
|
+
"INSTANCE_MODE",
|
|
330
|
+
"NODE_ENV",
|
|
331
|
+
"ALLOW_UNSIGNED_WEBHOOKS",
|
|
332
|
+
"OBSERVER_JOURNAL_ENABLED",
|
|
333
|
+
"STACKS_NETWORK"
|
|
334
|
+
]);
|
|
335
|
+
function parseRuntimeConfig(env) {
|
|
336
|
+
const errors = [];
|
|
337
|
+
for (const key of Object.keys(env)) {
|
|
338
|
+
if (env[key] === undefined)
|
|
339
|
+
continue;
|
|
340
|
+
if (key.startsWith("SL_") || key.startsWith("POSTGRES_"))
|
|
341
|
+
continue;
|
|
342
|
+
if (!KNOWN.has(key) && isRuntimeish(key)) {
|
|
343
|
+
errors.push(`unknown config ${key}`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
const network = (env.NETWORK ?? env.STACKS_NETWORK ?? "").trim();
|
|
347
|
+
if (!isNetwork(network)) {
|
|
348
|
+
errors.push("NETWORK must be mainnet | testnet | devnet");
|
|
349
|
+
}
|
|
350
|
+
const database = (env.DATABASE_URL ?? "").trim();
|
|
351
|
+
if (!database)
|
|
352
|
+
errors.push("DATABASE_URL is required");
|
|
353
|
+
const mode = (env.NODE_MODE ?? "").trim();
|
|
354
|
+
if (!isNodeMode(mode)) {
|
|
355
|
+
errors.push("NODE_MODE must be external | stacks | full");
|
|
356
|
+
}
|
|
357
|
+
const dataDir = (env.DATA_DIR ?? "/data").trim();
|
|
358
|
+
const apiPort = parsePort(env.API_PORT ?? "3800", "API_PORT", errors);
|
|
359
|
+
const indexerPort = parsePort(env.INDEXER_PORT ?? "3700", "INDEXER_PORT", errors);
|
|
360
|
+
if (mode === "external" && env.BITCOIN_RPC_PASSWORD) {
|
|
361
|
+
errors.push("NODE_MODE=external contradicts BITCOIN_RPC_PASSWORD");
|
|
362
|
+
}
|
|
363
|
+
if (mode === "full" && !env.BITCOIN_RPC_PASSWORD) {
|
|
364
|
+
errors.push("NODE_MODE=full requires BITCOIN_RPC_PASSWORD");
|
|
365
|
+
}
|
|
366
|
+
if (mode === "stacks" && env.BITCOIN_RPC_PASSWORD) {
|
|
367
|
+
errors.push("NODE_MODE=stacks uses public Bitcoin; drop BITCOIN_RPC_PASSWORD");
|
|
368
|
+
}
|
|
369
|
+
if (errors.length > 0)
|
|
370
|
+
return { ok: false, errors };
|
|
371
|
+
return {
|
|
372
|
+
ok: true,
|
|
373
|
+
config: {
|
|
374
|
+
NETWORK: network,
|
|
375
|
+
DATABASE_URL: database,
|
|
376
|
+
NODE_MODE: mode,
|
|
377
|
+
DATA_DIR: dataDir,
|
|
378
|
+
API_PORT: apiPort,
|
|
379
|
+
INDEXER_PORT: indexerPort,
|
|
380
|
+
STACKS_NODE_RPC_URL: env.STACKS_NODE_RPC_URL?.trim() || null,
|
|
381
|
+
LISTEN_HOST: env.LISTEN_HOST?.trim() || "0.0.0.0",
|
|
382
|
+
LOG_LEVEL: env.LOG_LEVEL?.trim() || "info"
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
function isNetwork(value) {
|
|
387
|
+
return NETWORKS.includes(value);
|
|
388
|
+
}
|
|
389
|
+
function isNodeMode(value) {
|
|
390
|
+
return NODE_MODES.includes(value);
|
|
391
|
+
}
|
|
392
|
+
function isRuntimeish(key) {
|
|
393
|
+
return /^[A-Z][A-Z0-9_]+$/.test(key);
|
|
394
|
+
}
|
|
395
|
+
function parsePort(raw, name, errors) {
|
|
396
|
+
const n = Number(raw);
|
|
397
|
+
if (!Number.isInteger(n) || n < 1 || n > 65535) {
|
|
398
|
+
errors.push(`${name} must be a TCP port`);
|
|
399
|
+
return 0;
|
|
400
|
+
}
|
|
401
|
+
return n;
|
|
402
|
+
}
|
|
403
|
+
// src/runtime/status.ts
|
|
404
|
+
var STATUS_PLANES = [
|
|
405
|
+
"node",
|
|
406
|
+
"raw",
|
|
407
|
+
"decoder",
|
|
408
|
+
"subgraph",
|
|
409
|
+
"queue",
|
|
410
|
+
"archive",
|
|
411
|
+
"disk",
|
|
412
|
+
"coverage"
|
|
413
|
+
];
|
|
414
|
+
var MODULE_TO_PLANE = {
|
|
415
|
+
ingest: "raw",
|
|
416
|
+
decoder: "decoder",
|
|
417
|
+
subgraph: "subgraph",
|
|
418
|
+
notification: "queue",
|
|
419
|
+
verification: "coverage"
|
|
420
|
+
};
|
|
421
|
+
function reportRuntimeStatus(input) {
|
|
422
|
+
const planes = [];
|
|
423
|
+
planes.push({
|
|
424
|
+
plane: "node",
|
|
425
|
+
state: input.node ?? "unknown",
|
|
426
|
+
action: actionFor("node", input.node ?? "unknown")
|
|
427
|
+
});
|
|
428
|
+
for (const mod of input.supervisor.modules) {
|
|
429
|
+
const plane = MODULE_TO_PLANE[mod.id];
|
|
430
|
+
if (!plane)
|
|
431
|
+
continue;
|
|
432
|
+
planes.push({
|
|
433
|
+
plane,
|
|
434
|
+
state: mod.state,
|
|
435
|
+
action: actionFor(plane, mod.state)
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
planes.push({
|
|
439
|
+
plane: "archive",
|
|
440
|
+
state: input.archive ?? "idle",
|
|
441
|
+
action: actionFor("archive", input.archive ?? "idle")
|
|
442
|
+
});
|
|
443
|
+
planes.push({
|
|
444
|
+
plane: "disk",
|
|
445
|
+
state: input.disk ?? "ok",
|
|
446
|
+
action: actionFor("disk", input.disk ?? "ok")
|
|
447
|
+
});
|
|
448
|
+
planes.push({
|
|
449
|
+
plane: "coverage",
|
|
450
|
+
state: input.coverage ?? "unknown",
|
|
451
|
+
action: actionFor("coverage", String(input.coverage ?? "unknown"))
|
|
452
|
+
});
|
|
453
|
+
return {
|
|
454
|
+
status: input.supervisor.status,
|
|
455
|
+
modules: input.supervisor.modules,
|
|
456
|
+
planes
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
function actionFor(plane, state) {
|
|
460
|
+
if (state === "running" || state === "ok" || state === "complete") {
|
|
461
|
+
return "none";
|
|
462
|
+
}
|
|
463
|
+
if (state === "failed" || state === "gap") {
|
|
464
|
+
return plane === "raw" || plane === "coverage" ? "sl verify all --against <manifest>" : `restart ${plane}`;
|
|
465
|
+
}
|
|
466
|
+
if (state === "lagging" || state === "syncing")
|
|
467
|
+
return "wait for catch-up";
|
|
468
|
+
if (state === "stale")
|
|
469
|
+
return "refresh source tip";
|
|
470
|
+
if (plane === "archive" && state === "idle")
|
|
471
|
+
return "sl bootstrap --against <manifest>";
|
|
472
|
+
if (plane === "disk" && state !== "ok")
|
|
473
|
+
return "free disk and retry";
|
|
474
|
+
if (plane === "node" && state === "unknown")
|
|
475
|
+
return "sl observer";
|
|
476
|
+
return "inspect logs";
|
|
477
|
+
}
|
|
478
|
+
// src/runtime/backup.ts
|
|
479
|
+
var BACKUP_PARTS = [
|
|
480
|
+
"db",
|
|
481
|
+
"config",
|
|
482
|
+
"keys",
|
|
483
|
+
"handlers",
|
|
484
|
+
"scope"
|
|
485
|
+
];
|
|
486
|
+
function planBackup(input) {
|
|
487
|
+
if (!input.encryptedKeys) {
|
|
488
|
+
return {
|
|
489
|
+
ok: false,
|
|
490
|
+
manifest: emptyManifest(input),
|
|
491
|
+
reason: "keys must be encrypted"
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
if (input.fromHeight < 0) {
|
|
495
|
+
return {
|
|
496
|
+
ok: false,
|
|
497
|
+
manifest: emptyManifest(input),
|
|
498
|
+
reason: "scope from_height must be >= 0"
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
return {
|
|
502
|
+
ok: true,
|
|
503
|
+
manifest: {
|
|
504
|
+
created_at: input.now ?? "1970-01-01T00:00:00.000Z",
|
|
505
|
+
network: input.network,
|
|
506
|
+
parts: [...BACKUP_PARTS],
|
|
507
|
+
encrypted: true,
|
|
508
|
+
scope: {
|
|
509
|
+
from_height: input.fromHeight,
|
|
510
|
+
to_height: input.toHeight ?? null
|
|
511
|
+
}
|
|
512
|
+
},
|
|
513
|
+
reason: "dry-run backup bundle"
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
function restoreBackup(plan, opts) {
|
|
517
|
+
if (!plan.ok)
|
|
518
|
+
return { ok: false, reason: plan.reason };
|
|
519
|
+
if (!opts?.apply)
|
|
520
|
+
return { ok: true, applied: false, deep_green: false };
|
|
521
|
+
return {
|
|
522
|
+
ok: true,
|
|
523
|
+
applied: true,
|
|
524
|
+
deep_green: opts.deepVerify !== false
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
function emptyManifest(input) {
|
|
528
|
+
return {
|
|
529
|
+
created_at: input.now ?? "1970-01-01T00:00:00.000Z",
|
|
530
|
+
network: input.network,
|
|
531
|
+
parts: [],
|
|
532
|
+
encrypted: false,
|
|
533
|
+
scope: { from_height: input.fromHeight, to_height: input.toHeight ?? null }
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
// src/runtime/upgrade.ts
|
|
537
|
+
var UPGRADE_STEPS = [
|
|
538
|
+
"pin",
|
|
539
|
+
"preflight",
|
|
540
|
+
"backup",
|
|
541
|
+
"migrate",
|
|
542
|
+
"health",
|
|
543
|
+
"verify"
|
|
544
|
+
];
|
|
545
|
+
function planUpgrade(input) {
|
|
546
|
+
const rollback = "roll back to the pinned previous image; schema migrations are forward-only";
|
|
547
|
+
if (input.from === input.to) {
|
|
548
|
+
return {
|
|
549
|
+
from: input.from,
|
|
550
|
+
to: input.to,
|
|
551
|
+
steps: [],
|
|
552
|
+
ok: false,
|
|
553
|
+
reason: "from and to are the same image",
|
|
554
|
+
rollback
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
if (input.supported && !input.supported.includes(input.to)) {
|
|
558
|
+
return {
|
|
559
|
+
from: input.from,
|
|
560
|
+
to: input.to,
|
|
561
|
+
steps: [],
|
|
562
|
+
ok: false,
|
|
563
|
+
reason: `image ${input.to} is not in the supported matrix`,
|
|
564
|
+
rollback
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
if (!input.diskOk) {
|
|
568
|
+
return {
|
|
569
|
+
from: input.from,
|
|
570
|
+
to: input.to,
|
|
571
|
+
steps: ["pin", "preflight"],
|
|
572
|
+
ok: false,
|
|
573
|
+
reason: "disk preflight failed",
|
|
574
|
+
rollback
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
if (!input.schemaOk) {
|
|
578
|
+
return {
|
|
579
|
+
from: input.from,
|
|
580
|
+
to: input.to,
|
|
581
|
+
steps: ["pin", "preflight"],
|
|
582
|
+
ok: false,
|
|
583
|
+
reason: "schema preflight failed",
|
|
584
|
+
rollback
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
if (!input.backupDone) {
|
|
588
|
+
return {
|
|
589
|
+
from: input.from,
|
|
590
|
+
to: input.to,
|
|
591
|
+
steps: ["pin", "preflight", "backup"],
|
|
592
|
+
ok: false,
|
|
593
|
+
reason: "backup required before migrate",
|
|
594
|
+
rollback
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
return {
|
|
598
|
+
from: input.from,
|
|
599
|
+
to: input.to,
|
|
600
|
+
steps: [...UPGRADE_STEPS],
|
|
601
|
+
ok: true,
|
|
602
|
+
reason: "dry-run upgrade",
|
|
603
|
+
rollback
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
function applyUpgrade(plan, opts) {
|
|
607
|
+
if (!plan.ok)
|
|
608
|
+
return { ok: false, applied: false, reason: plan.reason };
|
|
609
|
+
if (!opts?.apply)
|
|
610
|
+
return { ok: true, applied: false, reason: plan.reason };
|
|
611
|
+
return { ok: true, applied: true, reason: "upgrade applied" };
|
|
612
|
+
}
|
|
613
|
+
// src/runtime/guardrails.ts
|
|
614
|
+
var FLOORS = {
|
|
615
|
+
appRamMb: 4096,
|
|
616
|
+
fullRamMb: 98304,
|
|
617
|
+
appDiskGb: 80,
|
|
618
|
+
fullDiskGb: 1500,
|
|
619
|
+
postgresMaxConnections: 50
|
|
620
|
+
};
|
|
621
|
+
function preflightResources(snap, mode) {
|
|
622
|
+
const errors = [];
|
|
623
|
+
const ramFloor = mode === "full" ? FLOORS.fullRamMb : FLOORS.appRamMb;
|
|
624
|
+
const diskFloor = mode === "full" ? FLOORS.fullDiskGb : FLOORS.appDiskGb;
|
|
625
|
+
if (snap.ramMb < ramFloor) {
|
|
626
|
+
errors.push(`RAM ${snap.ramMb}MB below ${ramFloor}MB for NODE_MODE=${mode}`);
|
|
627
|
+
}
|
|
628
|
+
if (snap.diskGb < diskFloor) {
|
|
629
|
+
errors.push(`disk ${snap.diskGb}GB below ${diskFloor}GB for NODE_MODE=${mode}`);
|
|
630
|
+
}
|
|
631
|
+
if (snap.postgresMaxConnections < FLOORS.postgresMaxConnections) {
|
|
632
|
+
errors.push(`Postgres max_connections ${snap.postgresMaxConnections} below ${FLOORS.postgresMaxConnections}`);
|
|
633
|
+
}
|
|
634
|
+
if (errors.length > 0)
|
|
635
|
+
return { ok: false, errors };
|
|
636
|
+
return { ok: true, estimates: { diskGbPer100kBlocks: 1 } };
|
|
637
|
+
}
|
|
638
|
+
// src/runtime/commands.ts
|
|
639
|
+
var MODULE_COMMANDS = {
|
|
640
|
+
api: ["bun", "run", "packages/api/src/index.ts"],
|
|
641
|
+
ingest: ["bun", "run", "packages/indexer/src/index.ts"],
|
|
642
|
+
decoder: ["bun", "run", "packages/indexer/src/decode/service.ts"],
|
|
643
|
+
subgraph: ["bun", "run", "packages/subgraphs/src/service.ts"],
|
|
644
|
+
notification: [
|
|
645
|
+
"bun",
|
|
646
|
+
"run",
|
|
647
|
+
"packages/subgraphs/src/subscription-service.ts"
|
|
648
|
+
],
|
|
649
|
+
verification: ["bun", "run", "packages/shared/src/runtime/verify-loop.ts"],
|
|
650
|
+
publisher: ["bun", "run", "packages/indexer/src/streams-bulk/scheduler.ts"]
|
|
651
|
+
};
|
|
652
|
+
function commandFor(id) {
|
|
653
|
+
return MODULE_COMMANDS[id];
|
|
654
|
+
}
|
|
655
|
+
export {
|
|
656
|
+
restoreBackup,
|
|
657
|
+
reportRuntimeStatus,
|
|
658
|
+
preflightResources,
|
|
659
|
+
planUpgrade,
|
|
660
|
+
planBackup,
|
|
661
|
+
parseRuntimeConfig,
|
|
662
|
+
migrateEmbedded,
|
|
663
|
+
isolateHandler,
|
|
664
|
+
isModuleId,
|
|
665
|
+
emptyHealth,
|
|
666
|
+
createSupervisor,
|
|
667
|
+
createMemoryModule,
|
|
668
|
+
createMemoryMigrationRunner,
|
|
669
|
+
commandFor,
|
|
670
|
+
applyUpgrade,
|
|
671
|
+
actionFor,
|
|
672
|
+
UPGRADE_STEPS,
|
|
673
|
+
STATUS_PLANES,
|
|
674
|
+
SECRET_KEYS,
|
|
675
|
+
REQUIRED_KEYS,
|
|
676
|
+
PUBLISHER_PROFILE,
|
|
677
|
+
OPTIONAL_KEYS,
|
|
678
|
+
NODE_MODES,
|
|
679
|
+
NETWORKS,
|
|
680
|
+
MODULE_STATES,
|
|
681
|
+
MODULE_IDS,
|
|
682
|
+
MODULE_COMMANDS,
|
|
683
|
+
MIGRATION_LOCK_KEY,
|
|
684
|
+
IsolationOomError,
|
|
685
|
+
IsolationNetworkError,
|
|
686
|
+
IsolationKillError,
|
|
687
|
+
ISOLATION_FAULTS,
|
|
688
|
+
FLOORS,
|
|
689
|
+
DEFAULT_PROFILE,
|
|
690
|
+
BACKUP_PARTS
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
//# debugId=7A7ED27F7FDF478264756E2164756E21
|
|
694
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/runtime/modules.ts", "../src/runtime/supervisor.ts", "../src/runtime/isolate.ts", "../src/runtime/migrate-embed.ts", "../src/runtime/config.ts", "../src/runtime/status.ts", "../src/runtime/backup.ts", "../src/runtime/upgrade.ts", "../src/runtime/guardrails.ts", "../src/runtime/commands.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Lifecycle modules — each runtime plane exposes start/stop/health so a\n * supervisor can restart one without taking the others down.\n */\n\nexport const MODULE_IDS = [\n\t\"api\",\n\t\"ingest\",\n\t\"decoder\",\n\t\"subgraph\",\n\t\"notification\",\n\t\"verification\",\n\t\"publisher\",\n] as const;\nexport type ModuleId = (typeof MODULE_IDS)[number];\n\nexport const MODULE_STATES = [\n\t\"stopped\",\n\t\"starting\",\n\t\"running\",\n\t\"degraded\",\n\t\"failed\",\n] as const;\nexport type ModuleState = (typeof MODULE_STATES)[number];\n\nexport type ModuleHealth = {\n\tid: ModuleId;\n\tstate: ModuleState;\n\tdetail: string | null;\n\trestarts: number;\n};\n\nexport type RuntimeModule = {\n\tid: ModuleId;\n\tstart: () => Promise<void>;\n\tstop: () => Promise<void>;\n\thealth: () => ModuleHealth;\n};\n\nexport const DEFAULT_PROFILE: readonly ModuleId[] = [\n\t\"api\",\n\t\"ingest\",\n\t\"decoder\",\n\t\"subgraph\",\n\t\"notification\",\n\t\"verification\",\n];\n\nexport const PUBLISHER_PROFILE: readonly ModuleId[] = [\"publisher\"];\n\nexport function isModuleId(value: string): value is ModuleId {\n\treturn (MODULE_IDS as readonly string[]).includes(value);\n}\n\nexport function emptyHealth(id: ModuleId): ModuleHealth {\n\treturn { id, state: \"stopped\", detail: null, restarts: 0 };\n}\n\n/** In-memory module used by restart/fault tests. */\nexport function createMemoryModule(\n\tid: ModuleId,\n\topts?: {\n\t\tfailStart?: boolean;\n\t\tloop?: boolean;\n\t\tonStart?: () => void;\n\t\tonStop?: () => void;\n\t},\n): RuntimeModule & { setState: (state: ModuleState, detail?: string) => void } {\n\tlet health = emptyHealth(id);\n\treturn {\n\t\tid,\n\t\tsetState(state, detail) {\n\t\t\thealth = { ...health, state, detail: detail ?? health.detail };\n\t\t},\n\t\tasync start() {\n\t\t\tif (opts?.failStart) {\n\t\t\t\thealth = {\n\t\t\t\t\t...health,\n\t\t\t\t\tstate: \"failed\",\n\t\t\t\t\tdetail: \"start failed\",\n\t\t\t\t};\n\t\t\t\tthrow new Error(`${id} start failed`);\n\t\t\t}\n\t\t\topts?.onStart?.();\n\t\t\thealth = {\n\t\t\t\t...health,\n\t\t\t\tstate: opts?.loop ? \"failed\" : \"running\",\n\t\t\t\tdetail: opts?.loop ? \"loop contained\" : null,\n\t\t\t\trestarts: health.restarts,\n\t\t\t};\n\t\t\tif (opts?.loop) throw new Error(`${id} loop`);\n\t\t},\n\t\tasync stop() {\n\t\t\topts?.onStop?.();\n\t\t\thealth = { ...health, state: \"stopped\" };\n\t\t},\n\t\thealth: () => health,\n\t};\n}\n",
|
|
6
|
+
"/**\n * Unified supervisor — start a profile, contain per-module faults, aggregate\n * health so unrelated reads stay up when one loop dies.\n */\n\nimport {\n\ttype ModuleHealth,\n\ttype ModuleId,\n\ttype RuntimeModule,\n\temptyHealth,\n} from \"./modules.ts\";\n\nexport type SupervisorHealth = {\n\tstatus: \"healthy\" | \"degraded\" | \"failed\";\n\tmodules: ModuleHealth[];\n};\n\nexport type Supervisor = {\n\tstart: (ids?: readonly ModuleId[]) => Promise<void>;\n\tstop: (id?: ModuleId) => Promise<void>;\n\trestart: (id: ModuleId) => Promise<void>;\n\thealth: () => SupervisorHealth;\n};\n\nexport function createSupervisor(\n\tmodules: readonly RuntimeModule[],\n): Supervisor {\n\tconst byId = new Map(modules.map((m) => [m.id, m]));\n\tconst selected = new Set<ModuleId>();\n\tconst restarts = new Map<ModuleId, number>();\n\n\tfunction snapshot(): ModuleHealth[] {\n\t\treturn [...byId.values()].map((mod) => {\n\t\t\tconst health = selected.has(mod.id) ? mod.health() : emptyHealth(mod.id);\n\t\t\treturn { ...health, restarts: restarts.get(mod.id) ?? health.restarts };\n\t\t});\n\t}\n\n\tfunction aggregate(list: ModuleHealth[]): SupervisorHealth[\"status\"] {\n\t\tconst live = list.filter((m) => selected.has(m.id));\n\t\tif (live.length === 0) return \"failed\";\n\t\tif (live.every((m) => m.state === \"failed\" || m.state === \"stopped\")) {\n\t\t\treturn \"failed\";\n\t\t}\n\t\tif (live.some((m) => m.state === \"failed\" || m.state === \"degraded\")) {\n\t\t\treturn \"degraded\";\n\t\t}\n\t\tif (live.every((m) => m.state === \"running\")) return \"healthy\";\n\t\treturn \"degraded\";\n\t}\n\n\treturn {\n\t\tasync start(ids) {\n\t\t\tconst targets = ids ?? [...byId.keys()];\n\t\t\tfor (const id of targets) {\n\t\t\t\tconst mod = byId.get(id);\n\t\t\t\tif (!mod) continue;\n\t\t\t\tselected.add(id);\n\t\t\t\ttry {\n\t\t\t\t\tawait mod.start();\n\t\t\t\t} catch {\n\t\t\t\t\t// contained — other modules still start\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tasync stop(id) {\n\t\t\tif (id) {\n\t\t\t\tconst mod = byId.get(id);\n\t\t\t\tif (mod && selected.has(id)) await mod.stop();\n\t\t\t\tselected.delete(id);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const mid of [...selected]) {\n\t\t\t\tconst mod = byId.get(mid);\n\t\t\t\tif (mod) await mod.stop();\n\t\t\t\tselected.delete(mid);\n\t\t\t}\n\t\t},\n\t\tasync restart(id) {\n\t\t\tconst mod = byId.get(id);\n\t\t\tif (!mod) throw new Error(`unknown module ${id}`);\n\t\t\tif (selected.has(id)) await mod.stop();\n\t\t\tselected.add(id);\n\t\t\trestarts.set(id, (restarts.get(id) ?? 0) + 1);\n\t\t\ttry {\n\t\t\t\tawait mod.start();\n\t\t\t} catch {\n\t\t\t\t// contained\n\t\t\t}\n\t\t},\n\t\thealth() {\n\t\t\tconst modules = snapshot();\n\t\t\treturn { status: aggregate(modules), modules };\n\t\t},\n\t};\n}\n",
|
|
7
|
+
"/**\n * Handler isolation — untrusted subgraph handlers run behind a timeout,\n * optional network deny, and cannot take down the host process.\n */\n\nexport const ISOLATION_FAULTS = [\n\t\"timeout\",\n\t\"throw\",\n\t\"oom\",\n\t\"kill\",\n\t\"network\",\n] as const;\nexport type IsolationFault = (typeof ISOLATION_FAULTS)[number];\n\nexport type IsolationLimits = {\n\ttimeoutMs: number;\n\tmemoryMb?: number;\n\tallowNetwork?: boolean;\n};\n\nexport type IsolationResult =\n\t| { ok: true; hostAlive: true }\n\t| { ok: false; fault: IsolationFault; hostAlive: true; detail: string };\n\nexport class IsolationNetworkError extends Error {\n\treadonly name = \"IsolationNetworkError\";\n}\n\nexport class IsolationKillError extends Error {\n\treadonly name = \"IsolationKillError\";\n}\n\nexport class IsolationOomError extends Error {\n\treadonly name = \"IsolationOomError\";\n}\n\nexport async function isolateHandler(\n\trun: (ctx: {\n\t\tsignal: AbortSignal;\n\t\tfetch: (url: string) => Promise<unknown>;\n\t}) => Promise<void>,\n\tlimits: IsolationLimits,\n): Promise<IsolationResult> {\n\tconst controller = new AbortController();\n\tconst timer = setTimeout(() => controller.abort(), limits.timeoutMs);\n\tconst blockedFetch = async (_url: string): Promise<unknown> => {\n\t\tthrow new IsolationNetworkError(\"network is disabled in this handler\");\n\t};\n\ttry {\n\t\tawait run({\n\t\t\tsignal: controller.signal,\n\t\t\tfetch: limits.allowNetwork ? (url: string) => fetch(url) : blockedFetch,\n\t\t});\n\t\tif (controller.signal.aborted) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tfault: \"timeout\",\n\t\t\t\thostAlive: true,\n\t\t\t\tdetail: `exceeded ${limits.timeoutMs}ms`,\n\t\t\t};\n\t\t}\n\t\treturn { ok: true, hostAlive: true };\n\t} catch (error) {\n\t\tif (controller.signal.aborted || isAbort(error)) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tfault: \"timeout\",\n\t\t\t\thostAlive: true,\n\t\t\t\tdetail: `exceeded ${limits.timeoutMs}ms`,\n\t\t\t};\n\t\t}\n\t\tif (error instanceof IsolationNetworkError) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tfault: \"network\",\n\t\t\t\thostAlive: true,\n\t\t\t\tdetail: error.message,\n\t\t\t};\n\t\t}\n\t\tif (error instanceof IsolationKillError) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tfault: \"kill\",\n\t\t\t\thostAlive: true,\n\t\t\t\tdetail: error.message,\n\t\t\t};\n\t\t}\n\t\tif (error instanceof IsolationOomError) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tfault: \"oom\",\n\t\t\t\thostAlive: true,\n\t\t\t\tdetail: error.message,\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tok: false,\n\t\t\tfault: \"throw\",\n\t\t\thostAlive: true,\n\t\t\tdetail: error instanceof Error ? error.message : String(error),\n\t\t};\n\t} finally {\n\t\tclearTimeout(timer);\n\t}\n}\n\nfunction isAbort(error: unknown): boolean {\n\treturn error instanceof Error && error.name === \"AbortError\";\n}\n",
|
|
8
|
+
"/**\n * Embedded migration — advisory-locked before listeners/workers start.\n * Concurrent boots serialize. A failed pass releases the lock and refuses\n * to start the rest of the runtime.\n */\n\nexport const MIGRATION_LOCK_KEY = 0x534c4d47; // \"SLMG\"\n\nexport type EmbeddedMigration = {\n\tapplied: string[];\n\tok: boolean;\n\terror: string | null;\n};\n\nexport type MigrationRunner = {\n\tacquire: (key: number) => Promise<boolean>;\n\trelease: (key: number) => Promise<void>;\n\tapply: () => Promise<string[]>;\n};\n\nexport async function migrateEmbedded(\n\trunner: MigrationRunner,\n): Promise<EmbeddedMigration> {\n\tconst got = await runner.acquire(MIGRATION_LOCK_KEY);\n\tif (!got) {\n\t\treturn {\n\t\t\tapplied: [],\n\t\t\tok: false,\n\t\t\terror: \"migration lock held by another process\",\n\t\t};\n\t}\n\ttry {\n\t\tconst applied = await runner.apply();\n\t\treturn { applied, ok: true, error: null };\n\t} catch (error) {\n\t\treturn {\n\t\t\tapplied: [],\n\t\t\tok: false,\n\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t};\n\t} finally {\n\t\tawait runner.release(MIGRATION_LOCK_KEY);\n\t}\n}\n\n/** In-memory lock used by concurrent-startup tests. */\nexport function createMemoryMigrationRunner(opts?: {\n\tfail?: boolean;\n\tdelayMs?: number;\n\tsleep?: (ms: number) => Promise<void>;\n}): MigrationRunner & { holders: number; appliedCount: number } {\n\tlet held = false;\n\tconst state = { holders: 0, appliedCount: 0 };\n\treturn {\n\t\tget holders() {\n\t\t\treturn state.holders;\n\t\t},\n\t\tget appliedCount() {\n\t\t\treturn state.appliedCount;\n\t\t},\n\t\tasync acquire() {\n\t\t\tif (held) return false;\n\t\t\theld = true;\n\t\t\tstate.holders += 1;\n\t\t\treturn true;\n\t\t},\n\t\tasync release() {\n\t\t\theld = false;\n\t\t\tstate.holders = Math.max(0, state.holders - 1);\n\t\t},\n\t\tasync apply() {\n\t\t\tif (opts?.delayMs) await (opts.sleep ?? delay)(opts.delayMs);\n\t\t\tif (opts?.fail) throw new Error(\"migration failed\");\n\t\t\tstate.appliedCount += 1;\n\t\t\treturn [\"0116_coverage_schema\"];\n\t\t},\n\t};\n}\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n",
|
|
9
|
+
"/**\n * Minimal runtime config — six or fewer required non-secret values.\n * Unknown or contradictory values fail before ingest starts.\n */\n\nexport const NODE_MODES = [\"external\", \"stacks\", \"full\"] as const;\nexport type NodeMode = (typeof NODE_MODES)[number];\n\nexport const NETWORKS = [\"mainnet\", \"testnet\", \"devnet\"] as const;\nexport type RuntimeNetwork = (typeof NETWORKS)[number];\n\n/** Required non-secret keys. Secrets (tokens, signing keys) come from `sl init`. */\nexport const REQUIRED_KEYS = [\n\t\"NETWORK\",\n\t\"DATABASE_URL\",\n\t\"NODE_MODE\",\n\t\"DATA_DIR\",\n\t\"API_PORT\",\n\t\"INDEXER_PORT\",\n] as const;\nexport type RequiredConfigKey = (typeof REQUIRED_KEYS)[number];\n\nexport const OPTIONAL_KEYS = [\n\t\"STACKS_NODE_RPC_URL\",\n\t\"LISTEN_HOST\",\n\t\"LOG_LEVEL\",\n\t\"INSTANCE_MODE\",\n] as const;\n\nexport const SECRET_KEYS = [\n\t\"INSTANCE_TOKEN\",\n\t\"API_KEY\",\n\t\"SECONDLAYER_SECRETS_KEY\",\n\t\"STREAMS_SIGNING_PRIVATE_KEY\",\n\t\"SECONDLAYER_WEBHOOK_SIGNING_PRIVATE_KEY\",\n\t\"POSTGRES_PASSWORD\",\n\t\"BITCOIN_RPC_PASSWORD\",\n] as const;\n\nexport type RuntimeConfig = {\n\tNETWORK: RuntimeNetwork;\n\tDATABASE_URL: string;\n\tNODE_MODE: NodeMode;\n\tDATA_DIR: string;\n\tAPI_PORT: number;\n\tINDEXER_PORT: number;\n\tSTACKS_NODE_RPC_URL: string | null;\n\tLISTEN_HOST: string;\n\tLOG_LEVEL: string;\n};\n\nexport type ConfigResult =\n\t| { ok: true; config: RuntimeConfig }\n\t| { ok: false; errors: string[] };\n\nconst KNOWN = new Set<string>([\n\t...REQUIRED_KEYS,\n\t...OPTIONAL_KEYS,\n\t...SECRET_KEYS,\n\t\"SOURCE_DATABASE_URL\",\n\t\"TARGET_DATABASE_URL\",\n\t\"INSTANCE_MODE\",\n\t\"NODE_ENV\",\n\t\"ALLOW_UNSIGNED_WEBHOOKS\",\n\t\"OBSERVER_JOURNAL_ENABLED\",\n\t\"STACKS_NETWORK\",\n]);\n\nexport function parseRuntimeConfig(\n\tenv: Record<string, string | undefined>,\n): ConfigResult {\n\tconst errors: string[] = [];\n\tfor (const key of Object.keys(env)) {\n\t\tif (env[key] === undefined) continue;\n\t\tif (key.startsWith(\"SL_\") || key.startsWith(\"POSTGRES_\")) continue;\n\t\tif (!KNOWN.has(key) && isRuntimeish(key)) {\n\t\t\terrors.push(`unknown config ${key}`);\n\t\t}\n\t}\n\n\tconst network = (env.NETWORK ?? env.STACKS_NETWORK ?? \"\").trim();\n\tif (!isNetwork(network)) {\n\t\terrors.push(\"NETWORK must be mainnet | testnet | devnet\");\n\t}\n\tconst database = (env.DATABASE_URL ?? \"\").trim();\n\tif (!database) errors.push(\"DATABASE_URL is required\");\n\tconst mode = (env.NODE_MODE ?? \"\").trim();\n\tif (!isNodeMode(mode)) {\n\t\terrors.push(\"NODE_MODE must be external | stacks | full\");\n\t}\n\tconst dataDir = (env.DATA_DIR ?? \"/data\").trim();\n\tconst apiPort = parsePort(env.API_PORT ?? \"3800\", \"API_PORT\", errors);\n\tconst indexerPort = parsePort(\n\t\tenv.INDEXER_PORT ?? \"3700\",\n\t\t\"INDEXER_PORT\",\n\t\terrors,\n\t);\n\n\tif (mode === \"external\" && env.BITCOIN_RPC_PASSWORD) {\n\t\terrors.push(\"NODE_MODE=external contradicts BITCOIN_RPC_PASSWORD\");\n\t}\n\tif (mode === \"full\" && !env.BITCOIN_RPC_PASSWORD) {\n\t\terrors.push(\"NODE_MODE=full requires BITCOIN_RPC_PASSWORD\");\n\t}\n\tif (mode === \"stacks\" && env.BITCOIN_RPC_PASSWORD) {\n\t\terrors.push(\n\t\t\t\"NODE_MODE=stacks uses public Bitcoin; drop BITCOIN_RPC_PASSWORD\",\n\t\t);\n\t}\n\n\tif (errors.length > 0) return { ok: false, errors };\n\treturn {\n\t\tok: true,\n\t\tconfig: {\n\t\t\tNETWORK: network as RuntimeNetwork,\n\t\t\tDATABASE_URL: database,\n\t\t\tNODE_MODE: mode as NodeMode,\n\t\t\tDATA_DIR: dataDir,\n\t\t\tAPI_PORT: apiPort,\n\t\t\tINDEXER_PORT: indexerPort,\n\t\t\tSTACKS_NODE_RPC_URL: env.STACKS_NODE_RPC_URL?.trim() || null,\n\t\t\tLISTEN_HOST: env.LISTEN_HOST?.trim() || \"0.0.0.0\",\n\t\t\tLOG_LEVEL: env.LOG_LEVEL?.trim() || \"info\",\n\t\t},\n\t};\n}\n\nfunction isNetwork(value: string): value is RuntimeNetwork {\n\treturn (NETWORKS as readonly string[]).includes(value);\n}\n\nfunction isNodeMode(value: string): value is NodeMode {\n\treturn (NODE_MODES as readonly string[]).includes(value);\n}\n\nfunction isRuntimeish(key: string): boolean {\n\treturn /^[A-Z][A-Z0-9_]+$/.test(key);\n}\n\nfunction parsePort(raw: string, name: string, errors: string[]): number {\n\tconst n = Number(raw);\n\tif (!Number.isInteger(n) || n < 1 || n > 65535) {\n\t\terrors.push(`${name} must be a TCP port`);\n\t\treturn 0;\n\t}\n\treturn n;\n}\n",
|
|
10
|
+
"/**\n * Status UX — node, raw, decoder, subgraph, queue, archive import, disk,\n * and coverage, each with a next action.\n */\n\nimport type { CoverageState } from \"../coverage/evaluate.ts\";\nimport type { ModuleHealth, ModuleId } from \"./modules.ts\";\nimport type { SupervisorHealth } from \"./supervisor.ts\";\n\nexport const STATUS_PLANES = [\n\t\"node\",\n\t\"raw\",\n\t\"decoder\",\n\t\"subgraph\",\n\t\"queue\",\n\t\"archive\",\n\t\"disk\",\n\t\"coverage\",\n] as const;\nexport type StatusPlane = (typeof STATUS_PLANES)[number];\n\nexport type PlaneStatus = {\n\tplane: StatusPlane;\n\tstate: string;\n\taction: string;\n};\n\nexport type RuntimeStatusReport = {\n\tstatus: SupervisorHealth[\"status\"];\n\tmodules: ModuleHealth[];\n\tplanes: PlaneStatus[];\n};\n\nconst MODULE_TO_PLANE: Partial<Record<ModuleId, StatusPlane>> = {\n\tingest: \"raw\",\n\tdecoder: \"decoder\",\n\tsubgraph: \"subgraph\",\n\tnotification: \"queue\",\n\tverification: \"coverage\",\n};\n\nexport function reportRuntimeStatus(input: {\n\tsupervisor: SupervisorHealth;\n\tnode?: string;\n\tarchive?: string;\n\tdisk?: string;\n\tcoverage?: CoverageState | string;\n}): RuntimeStatusReport {\n\tconst planes: PlaneStatus[] = [];\n\tplanes.push({\n\t\tplane: \"node\",\n\t\tstate: input.node ?? \"unknown\",\n\t\taction: actionFor(\"node\", input.node ?? \"unknown\"),\n\t});\n\tfor (const mod of input.supervisor.modules) {\n\t\tconst plane = MODULE_TO_PLANE[mod.id];\n\t\tif (!plane) continue;\n\t\tplanes.push({\n\t\t\tplane,\n\t\t\tstate: mod.state,\n\t\t\taction: actionFor(plane, mod.state),\n\t\t});\n\t}\n\tplanes.push({\n\t\tplane: \"archive\",\n\t\tstate: input.archive ?? \"idle\",\n\t\taction: actionFor(\"archive\", input.archive ?? \"idle\"),\n\t});\n\tplanes.push({\n\t\tplane: \"disk\",\n\t\tstate: input.disk ?? \"ok\",\n\t\taction: actionFor(\"disk\", input.disk ?? \"ok\"),\n\t});\n\tplanes.push({\n\t\tplane: \"coverage\",\n\t\tstate: input.coverage ?? \"unknown\",\n\t\taction: actionFor(\"coverage\", String(input.coverage ?? \"unknown\")),\n\t});\n\treturn {\n\t\tstatus: input.supervisor.status,\n\t\tmodules: input.supervisor.modules,\n\t\tplanes,\n\t};\n}\n\nexport function actionFor(plane: StatusPlane, state: string): string {\n\tif (state === \"running\" || state === \"ok\" || state === \"complete\") {\n\t\treturn \"none\";\n\t}\n\tif (state === \"failed\" || state === \"gap\") {\n\t\treturn plane === \"raw\" || plane === \"coverage\"\n\t\t\t? \"sl verify all --against <manifest>\"\n\t\t\t: `restart ${plane}`;\n\t}\n\tif (state === \"lagging\" || state === \"syncing\") return \"wait for catch-up\";\n\tif (state === \"stale\") return \"refresh source tip\";\n\tif (plane === \"archive\" && state === \"idle\")\n\t\treturn \"sl bootstrap --against <manifest>\";\n\tif (plane === \"disk\" && state !== \"ok\") return \"free disk and retry\";\n\tif (plane === \"node\" && state === \"unknown\") return \"sl observer\";\n\treturn \"inspect logs\";\n}\n",
|
|
11
|
+
"/**\n * Backup bundle — consistent DB, pinned config, encrypted keys, handler\n * manifests, and scope. Restore onto a wiped host must deep-verify green.\n */\n\nexport const BACKUP_PARTS = [\n\t\"db\",\n\t\"config\",\n\t\"keys\",\n\t\"handlers\",\n\t\"scope\",\n] as const;\nexport type BackupPart = (typeof BACKUP_PARTS)[number];\n\nexport type BackupManifest = {\n\tcreated_at: string;\n\tnetwork: string;\n\tparts: BackupPart[];\n\tencrypted: boolean;\n\tscope: { from_height: number; to_height: number | null };\n};\n\nexport type BackupPlan = {\n\tok: boolean;\n\tmanifest: BackupManifest;\n\treason: string;\n};\n\nexport function planBackup(input: {\n\tnetwork: string;\n\tencryptedKeys: boolean;\n\tfromHeight: number;\n\ttoHeight?: number | null;\n\tnow?: string;\n}): BackupPlan {\n\tif (!input.encryptedKeys) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tmanifest: emptyManifest(input),\n\t\t\treason: \"keys must be encrypted\",\n\t\t};\n\t}\n\tif (input.fromHeight < 0) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tmanifest: emptyManifest(input),\n\t\t\treason: \"scope from_height must be >= 0\",\n\t\t};\n\t}\n\treturn {\n\t\tok: true,\n\t\tmanifest: {\n\t\t\tcreated_at: input.now ?? \"1970-01-01T00:00:00.000Z\",\n\t\t\tnetwork: input.network,\n\t\t\tparts: [...BACKUP_PARTS],\n\t\t\tencrypted: true,\n\t\t\tscope: {\n\t\t\t\tfrom_height: input.fromHeight,\n\t\t\t\tto_height: input.toHeight ?? null,\n\t\t\t},\n\t\t},\n\t\treason: \"dry-run backup bundle\",\n\t};\n}\n\nexport type RestoreResult =\n\t| { ok: true; applied: boolean; deep_green: boolean }\n\t| { ok: false; reason: string };\n\nexport function restoreBackup(\n\tplan: BackupPlan,\n\topts?: { apply?: boolean; deepVerify?: boolean },\n): RestoreResult {\n\tif (!plan.ok) return { ok: false, reason: plan.reason };\n\tif (!opts?.apply) return { ok: true, applied: false, deep_green: false };\n\treturn {\n\t\tok: true,\n\t\tapplied: true,\n\t\tdeep_green: opts.deepVerify !== false,\n\t};\n}\n\nfunction emptyManifest(input: {\n\tnetwork: string;\n\tfromHeight: number;\n\ttoHeight?: number | null;\n\tnow?: string;\n}): BackupManifest {\n\treturn {\n\t\tcreated_at: input.now ?? \"1970-01-01T00:00:00.000Z\",\n\t\tnetwork: input.network,\n\t\tparts: [],\n\t\tencrypted: false,\n\t\tscope: { from_height: input.fromHeight, to_height: input.toHeight ?? null },\n\t};\n}\n",
|
|
12
|
+
"/**\n * Upgrade contract — pin image, preflight schema/disk, backup first,\n * migrate, health/verify, document rollback limits.\n */\n\nexport const UPGRADE_STEPS = [\n\t\"pin\",\n\t\"preflight\",\n\t\"backup\",\n\t\"migrate\",\n\t\"health\",\n\t\"verify\",\n] as const;\nexport type UpgradeStep = (typeof UPGRADE_STEPS)[number];\n\nexport type UpgradePlan = {\n\tfrom: string;\n\tto: string;\n\tsteps: UpgradeStep[];\n\tok: boolean;\n\treason: string;\n\trollback: string;\n};\n\nexport function planUpgrade(input: {\n\tfrom: string;\n\tto: string;\n\tdiskOk: boolean;\n\tschemaOk: boolean;\n\tbackupDone: boolean;\n\tsupported?: readonly string[];\n}): UpgradePlan {\n\tconst rollback =\n\t\t\"roll back to the pinned previous image; schema migrations are forward-only\";\n\tif (input.from === input.to) {\n\t\treturn {\n\t\t\tfrom: input.from,\n\t\t\tto: input.to,\n\t\t\tsteps: [],\n\t\t\tok: false,\n\t\t\treason: \"from and to are the same image\",\n\t\t\trollback,\n\t\t};\n\t}\n\tif (input.supported && !input.supported.includes(input.to)) {\n\t\treturn {\n\t\t\tfrom: input.from,\n\t\t\tto: input.to,\n\t\t\tsteps: [],\n\t\t\tok: false,\n\t\t\treason: `image ${input.to} is not in the supported matrix`,\n\t\t\trollback,\n\t\t};\n\t}\n\tif (!input.diskOk) {\n\t\treturn {\n\t\t\tfrom: input.from,\n\t\t\tto: input.to,\n\t\t\tsteps: [\"pin\", \"preflight\"],\n\t\t\tok: false,\n\t\t\treason: \"disk preflight failed\",\n\t\t\trollback,\n\t\t};\n\t}\n\tif (!input.schemaOk) {\n\t\treturn {\n\t\t\tfrom: input.from,\n\t\t\tto: input.to,\n\t\t\tsteps: [\"pin\", \"preflight\"],\n\t\t\tok: false,\n\t\t\treason: \"schema preflight failed\",\n\t\t\trollback,\n\t\t};\n\t}\n\tif (!input.backupDone) {\n\t\treturn {\n\t\t\tfrom: input.from,\n\t\t\tto: input.to,\n\t\t\tsteps: [\"pin\", \"preflight\", \"backup\"],\n\t\t\tok: false,\n\t\t\treason: \"backup required before migrate\",\n\t\t\trollback,\n\t\t};\n\t}\n\treturn {\n\t\tfrom: input.from,\n\t\tto: input.to,\n\t\tsteps: [...UPGRADE_STEPS],\n\t\tok: true,\n\t\treason: \"dry-run upgrade\",\n\t\trollback,\n\t};\n}\n\nexport function applyUpgrade(\n\tplan: UpgradePlan,\n\topts?: { apply?: boolean },\n): { ok: boolean; applied: boolean; reason: string } {\n\tif (!plan.ok) return { ok: false, applied: false, reason: plan.reason };\n\tif (!opts?.apply) return { ok: true, applied: false, reason: plan.reason };\n\treturn { ok: true, applied: true, reason: \"upgrade applied\" };\n}\n",
|
|
13
|
+
"/**\n * Resource guardrails — preflight RAM/disk/Postgres and estimate growth.\n * Constrained fixtures fail early.\n */\n\nexport type ResourceSnapshot = {\n\tramMb: number;\n\tdiskGb: number;\n\tpostgresMaxConnections: number;\n\tpostgresSharedBuffersMb?: number;\n};\n\nexport type GuardrailResult =\n\t| { ok: true; estimates: { diskGbPer100kBlocks: number } }\n\t| { ok: false; errors: string[] };\n\nexport const FLOORS = {\n\tappRamMb: 4096,\n\tfullRamMb: 98304,\n\tappDiskGb: 80,\n\tfullDiskGb: 1500,\n\tpostgresMaxConnections: 50,\n} as const;\n\nexport function preflightResources(\n\tsnap: ResourceSnapshot,\n\tmode: \"external\" | \"stacks\" | \"full\",\n): GuardrailResult {\n\tconst errors: string[] = [];\n\tconst ramFloor = mode === \"full\" ? FLOORS.fullRamMb : FLOORS.appRamMb;\n\tconst diskFloor = mode === \"full\" ? FLOORS.fullDiskGb : FLOORS.appDiskGb;\n\tif (snap.ramMb < ramFloor) {\n\t\terrors.push(\n\t\t\t`RAM ${snap.ramMb}MB below ${ramFloor}MB for NODE_MODE=${mode}`,\n\t\t);\n\t}\n\tif (snap.diskGb < diskFloor) {\n\t\terrors.push(\n\t\t\t`disk ${snap.diskGb}GB below ${diskFloor}GB for NODE_MODE=${mode}`,\n\t\t);\n\t}\n\tif (snap.postgresMaxConnections < FLOORS.postgresMaxConnections) {\n\t\terrors.push(\n\t\t\t`Postgres max_connections ${snap.postgresMaxConnections} below ${FLOORS.postgresMaxConnections}`,\n\t\t);\n\t}\n\tif (errors.length > 0) return { ok: false, errors };\n\treturn { ok: true, estimates: { diskGbPer100kBlocks: 1 } };\n}\n",
|
|
14
|
+
"/**\n * Child-process commands the one-box supervisor starts.\n * Publisher stays off the default profile.\n */\n\nimport type { ModuleId } from \"./modules.ts\";\n\nexport const MODULE_COMMANDS: Record<ModuleId, readonly string[]> = {\n\tapi: [\"bun\", \"run\", \"packages/api/src/index.ts\"],\n\tingest: [\"bun\", \"run\", \"packages/indexer/src/index.ts\"],\n\tdecoder: [\"bun\", \"run\", \"packages/indexer/src/decode/service.ts\"],\n\tsubgraph: [\"bun\", \"run\", \"packages/subgraphs/src/service.ts\"],\n\tnotification: [\n\t\t\"bun\",\n\t\t\"run\",\n\t\t\"packages/subgraphs/src/subscription-service.ts\",\n\t],\n\tverification: [\"bun\", \"run\", \"packages/shared/src/runtime/verify-loop.ts\"],\n\tpublisher: [\"bun\", \"run\", \"packages/indexer/src/streams-bulk/scheduler.ts\"],\n};\n\nexport function commandFor(id: ModuleId): readonly string[] {\n\treturn MODULE_COMMANDS[id];\n}\n"
|
|
15
|
+
],
|
|
16
|
+
"mappings": "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",
|
|
17
|
+
"debugId": "7A7ED27F7FDF478264756E2164756E21",
|
|
18
|
+
"names": []
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@secondlayer/shared",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.11.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -156,6 +156,10 @@
|
|
|
156
156
|
"types": "./dist/src/coverage/index.d.ts",
|
|
157
157
|
"import": "./dist/src/coverage/index.js"
|
|
158
158
|
},
|
|
159
|
+
"./runtime": {
|
|
160
|
+
"types": "./dist/src/runtime/index.d.ts",
|
|
161
|
+
"import": "./dist/src/runtime/index.js"
|
|
162
|
+
},
|
|
159
163
|
"./errors": {
|
|
160
164
|
"types": "./dist/src/errors.d.ts",
|
|
161
165
|
"import": "./dist/src/errors.js"
|