@secondlayer/shared 7.8.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.
Files changed (52) hide show
  1. package/dist/src/archive/derived-stage-report.d.ts +99 -0
  2. package/dist/src/archive/derived-stage-report.js +64 -0
  3. package/dist/src/archive/derived-stage-report.js.map +10 -0
  4. package/dist/src/archive/disk-guard.d.ts +46 -0
  5. package/dist/src/archive/disk-guard.js +69 -0
  6. package/dist/src/archive/disk-guard.js.map +10 -0
  7. package/dist/src/archive/per-height-digest.d.ts +99 -0
  8. package/dist/src/archive/per-height-digest.js +194 -0
  9. package/dist/src/archive/per-height-digest.js.map +11 -0
  10. package/dist/src/archive/range-digest.d.ts +96 -0
  11. package/dist/src/archive/semantic-digest-builder.d.ts +1183 -0
  12. package/dist/src/archive/semantic-digest-builder.js +302 -0
  13. package/dist/src/archive/semantic-digest-builder.js.map +11 -0
  14. package/dist/src/archive/semantic-digest.d.ts +131 -0
  15. package/dist/src/archive/semantic-digest.js +143 -0
  16. package/dist/src/archive/semantic-digest.js.map +10 -0
  17. package/dist/src/coverage/index.d.ts +1670 -0
  18. package/dist/src/coverage/index.js +1483 -0
  19. package/dist/src/coverage/index.js.map +23 -0
  20. package/dist/src/db/index.d.ts +105 -1
  21. package/dist/src/db/index.js +31 -1
  22. package/dist/src/db/index.js.map +6 -5
  23. package/dist/src/db/queries/chain-reorgs.d.ts +96 -0
  24. package/dist/src/db/queries/chain-reorgs.js +30 -1
  25. package/dist/src/db/queries/chain-reorgs.js.map +6 -5
  26. package/dist/src/db/queries/contracts.d.ts +96 -0
  27. package/dist/src/db/queries/instance.d.ts +1127 -0
  28. package/dist/src/db/queries/instance.js +92 -0
  29. package/dist/src/db/queries/instance.js.map +10 -0
  30. package/dist/src/db/queries/integrity.d.ts +96 -0
  31. package/dist/src/db/queries/subgraph-gaps.d.ts +96 -0
  32. package/dist/src/db/queries/subgraph-operations.d.ts +96 -0
  33. package/dist/src/db/queries/subgraphs.d.ts +99 -1
  34. package/dist/src/db/queries/subgraphs.js +52 -23
  35. package/dist/src/db/queries/subgraphs.js.map +7 -7
  36. package/dist/src/db/queries/subscriptions.d.ts +96 -0
  37. package/dist/src/db/queries/subscriptions.js +47 -31
  38. package/dist/src/db/queries/subscriptions.js.map +5 -5
  39. package/dist/src/db/schema.d.ts +97 -1
  40. package/dist/src/index.d.ts +109 -1
  41. package/dist/src/index.js +52 -1
  42. package/dist/src/index.js.map +7 -6
  43. package/dist/src/node/client.d.ts +11 -1
  44. package/dist/src/node/client.js +42 -4
  45. package/dist/src/node/client.js.map +3 -3
  46. package/dist/src/node/local-client.d.ts +96 -0
  47. package/dist/src/node/nakamoto.d.ts +22 -7
  48. package/dist/src/node/nakamoto.js +46 -5
  49. package/dist/src/node/nakamoto.js.map +3 -3
  50. package/migrations/0115_instances.ts +33 -0
  51. package/migrations/0116_coverage_schema.ts +163 -0
  52. package/package.json +29 -1
@@ -1,5 +1,23 @@
1
1
  import { Kysely } from "kysely";
2
2
  import { ColumnType, Generated, Selectable } from "kysely";
3
+ /**
4
+ * Coverage-kernel constraints. SQL CHECKs in migration 0116 must stay
5
+ * identical — property tests treat this file as the spec.
6
+ */
7
+ declare const STAGE_KINDS: readonly ["raw", "decode", "subgraph", "queue"];
8
+ type StageKind = (typeof STAGE_KINDS)[number];
9
+ declare const NATIVE_CLOCKS: readonly ["block", "cursor", "queue"];
10
+ type NativeClock = (typeof NATIVE_CLOCKS)[number];
11
+ declare const REPAIR_MODES: readonly ["range_safe", "full_reindex", "archive_replay", "none"];
12
+ type RepairMode = (typeof REPAIR_MODES)[number];
13
+ declare const RUN_STATUSES: readonly ["pending", "running", "complete", "syncing", "lagging", "gap", "stale", "failed", "unverified_import", "unanchored", "source_unavailable", "out_of_scope", "disabled", "halted"];
14
+ type RunStatus = (typeof RUN_STATUSES)[number];
15
+ declare const FAILURE_UNITS: readonly ["block", "range", "cursor", "queue"];
16
+ type FailureUnit = (typeof FAILURE_UNITS)[number];
17
+ declare const FAILURE_CLASSES: readonly ["omission", "version", "digest_mismatch", "crash", "reorg", "source_gap", "handler", "timeout", "unknown"];
18
+ type FailureClass = (typeof FAILURE_CLASSES)[number];
19
+ declare const RETRY_STATES: readonly ["open", "retrying", "halted", "resolved"];
20
+ type RetryState = (typeof RETRY_STATES)[number];
3
21
  interface BlocksTable {
4
22
  height: number;
5
23
  hash: string;
@@ -191,6 +209,12 @@ interface ApiKeysTable {
191
209
  revoked_at: Date | null;
192
210
  created_at: Generated<Date>;
193
211
  }
212
+ /** Singleton self-host / publisher identity. Network is immutable. */
213
+ interface InstancesTable {
214
+ id: Generated<string>;
215
+ network: string;
216
+ created_at: Generated<Date>;
217
+ }
194
218
  interface AccountsTable {
195
219
  id: Generated<string>;
196
220
  /** NULL for unclaimed ghost accounts (anonymous self-serve keys). */
@@ -721,6 +745,72 @@ interface ObserverJournalTable {
721
745
  error: string | null;
722
746
  processed_at: Date | null;
723
747
  }
748
+ /** Declared coverage stage. Identity is the `id` string (`raw`, `decode:stx`, …). */
749
+ interface StageRegistryTable {
750
+ id: string;
751
+ kind: StageKind;
752
+ depends_on: string | null;
753
+ native_clock: NativeClock;
754
+ producer_version: string;
755
+ repair_mode: RepairMode;
756
+ enabled: Generated<boolean>;
757
+ created_at: Generated<Date>;
758
+ }
759
+ /** One versioned sweep of a stage. */
760
+ interface StageRunsTable {
761
+ id: Generated<string>;
762
+ stage_id: string;
763
+ code_hash: string;
764
+ config_hash: string;
765
+ handler_hash: string | null;
766
+ target_height: number | null;
767
+ target_cursor: string | null;
768
+ status: RunStatus;
769
+ complete_through: number | null;
770
+ started_at: Generated<Date>;
771
+ finished_at: Date | null;
772
+ }
773
+ /** Per-block acknowledgement. Unique on (stage, height, hash). */
774
+ interface StageBlockReceiptsTable {
775
+ id: Generated<string>;
776
+ stage_id: string;
777
+ run_id: string | null;
778
+ block_height: number;
779
+ block_hash: string;
780
+ input_count: number;
781
+ input_digest: string;
782
+ effect_digest: string;
783
+ finalized: Generated<boolean>;
784
+ compacted_at: Date | null;
785
+ created_at: Generated<Date>;
786
+ }
787
+ /** Compacted finalized range. Only sealed after receipts in the range finalize. */
788
+ interface CoverageSegmentsTable {
789
+ id: Generated<string>;
790
+ stage_id: string;
791
+ from_height: number;
792
+ to_height: number;
793
+ chain_digest: string;
794
+ input_digest: string;
795
+ output_digest: string;
796
+ sealed_at: Generated<Date>;
797
+ }
798
+ /** Exact unit or range that failed, plus retry/retention state. */
799
+ interface StageFailuresTable {
800
+ id: Generated<string>;
801
+ stage_id: string;
802
+ run_id: string | null;
803
+ unit_kind: FailureUnit;
804
+ from_height: number | null;
805
+ to_height: number | null;
806
+ class: FailureClass;
807
+ retry_state: RetryState;
808
+ retry_count: Generated<number>;
809
+ last_error: string | null;
810
+ created_at: Generated<Date>;
811
+ resolved_at: Date | null;
812
+ retain_until: Generated<Date>;
813
+ }
724
814
  interface Database {
725
815
  blocks: BlocksTable;
726
816
  transactions: TransactionsTable;
@@ -733,6 +823,7 @@ interface Database {
733
823
  contracts: ContractsTable;
734
824
  subgraphs: SubgraphsTable;
735
825
  api_keys: ApiKeysTable;
826
+ instances: InstancesTable;
736
827
  accounts: AccountsTable;
737
828
  sessions: SessionsTable;
738
829
  magic_links: MagicLinksTable;
@@ -785,6 +876,11 @@ interface Database {
785
876
  chain_read_cache: ChainReadCacheTable;
786
877
  pending_fork_blocks: PendingForkBlocksTable;
787
878
  observer_journal: ObserverJournalTable;
879
+ stage_registry: StageRegistryTable;
880
+ stage_runs: StageRunsTable;
881
+ stage_block_receipts: StageBlockReceiptsTable;
882
+ coverage_segments: CoverageSegmentsTable;
883
+ stage_failures: StageFailuresTable;
788
884
  }
789
885
  /** Prepaid x402 credit — one running USD-micros balance per payer principal. */
790
886
  interface X402BalancesTable {
@@ -14,6 +14,22 @@ var __export = (target, all) => {
14
14
  });
15
15
  };
16
16
 
17
+ // src/mode.ts
18
+ var VALID_MODES = ["oss", "platform"];
19
+ function getInstanceMode() {
20
+ const raw = process.env.INSTANCE_MODE?.trim().toLowerCase();
21
+ if (raw && VALID_MODES.includes(raw)) {
22
+ return raw;
23
+ }
24
+ return "oss";
25
+ }
26
+ function isPlatformMode() {
27
+ return getInstanceMode() === "platform";
28
+ }
29
+ function isOssMode() {
30
+ return getInstanceMode() === "oss";
31
+ }
32
+
17
33
  // src/crypto/hmac.ts
18
34
  var exports_hmac = {};
19
35
  __export(exports_hmac, {
@@ -68,22 +84,6 @@ function verifySignatureHeader(payload, header, secret, toleranceSeconds = 300)
68
84
  return verifySignature(signedPayload, signature, secret);
69
85
  }
70
86
 
71
- // src/mode.ts
72
- var VALID_MODES = ["oss", "platform"];
73
- function getInstanceMode() {
74
- const raw = process.env.INSTANCE_MODE?.trim().toLowerCase();
75
- if (raw && VALID_MODES.includes(raw)) {
76
- return raw;
77
- }
78
- return "oss";
79
- }
80
- function isPlatformMode() {
81
- return getInstanceMode() === "platform";
82
- }
83
- function isOssMode() {
84
- return getInstanceMode() === "oss";
85
- }
86
-
87
87
  // src/crypto/secrets.ts
88
88
  import { createCipheriv, createDecipheriv, randomBytes as randomBytes2 } from "node:crypto";
89
89
  import {
@@ -214,7 +214,7 @@ async function createSubscription(db, input) {
214
214
  const signingSecret = generateSecret();
215
215
  const kind = input.kind ?? "subgraph";
216
216
  const row = {
217
- account_id: input.accountId,
217
+ account_id: isPlatformMode() ? input.accountId : "",
218
218
  project_id: input.projectId ?? null,
219
219
  name: input.name,
220
220
  status: "active",
@@ -236,7 +236,9 @@ async function createSubscription(db, input) {
236
236
  return { subscription, signingSecret };
237
237
  }
238
238
  async function listSubscriptions(db, accountId, opts) {
239
- let q = db.selectFrom("subscriptions").selectAll().where("account_id", "=", accountId).orderBy("created_at", "desc");
239
+ let q = db.selectFrom("subscriptions").selectAll().orderBy("created_at", "desc");
240
+ if (isPlatformMode())
241
+ q = q.where("account_id", "=", accountId);
240
242
  if (opts?.limit !== undefined)
241
243
  q = q.limit(opts.limit);
242
244
  if (opts?.offset !== undefined)
@@ -247,12 +249,16 @@ async function listActiveChainSubscriptions(db) {
247
249
  return db.selectFrom("subscriptions").selectAll().where("kind", "=", "chain").where("status", "=", "active").execute();
248
250
  }
249
251
  async function getSubscription(db, accountId, id) {
250
- const row = await db.selectFrom("subscriptions").selectAll().where("account_id", "=", accountId).where("id", "=", id).executeTakeFirst();
251
- return row ?? null;
252
+ let q = db.selectFrom("subscriptions").selectAll().where("id", "=", id);
253
+ if (isPlatformMode())
254
+ q = q.where("account_id", "=", accountId);
255
+ return await q.executeTakeFirst() ?? null;
252
256
  }
253
257
  async function getSubscriptionByName(db, accountId, name) {
254
- const row = await db.selectFrom("subscriptions").selectAll().where("account_id", "=", accountId).where("name", "=", name).executeTakeFirst();
255
- return row ?? null;
258
+ let q = db.selectFrom("subscriptions").selectAll().where("name", "=", name);
259
+ if (isPlatformMode())
260
+ q = q.where("account_id", "=", accountId);
261
+ return await q.executeTakeFirst() ?? null;
256
262
  }
257
263
  async function updateSubscription(db, accountId, id, patch) {
258
264
  const update = { updated_at: new Date };
@@ -274,30 +280,40 @@ async function updateSubscription(db, accountId, id, patch) {
274
280
  update.timeout_ms = patch.timeoutMs;
275
281
  if (patch.concurrency !== undefined)
276
282
  update.concurrency = patch.concurrency;
277
- const row = await db.updateTable("subscriptions").set(update).where("account_id", "=", accountId).where("id", "=", id).returningAll().executeTakeFirst();
278
- return row ?? null;
283
+ let q = db.updateTable("subscriptions").set(update).where("id", "=", id);
284
+ if (isPlatformMode())
285
+ q = q.where("account_id", "=", accountId);
286
+ return await q.returningAll().executeTakeFirst() ?? null;
279
287
  }
280
288
  async function toggleSubscriptionStatus(db, accountId, id, status) {
281
- const row = await db.updateTable("subscriptions").set({
289
+ let q = db.updateTable("subscriptions").set({
282
290
  status,
283
291
  updated_at: new Date,
284
292
  ...status === "active" ? {
285
293
  circuit_failures: 0,
286
294
  circuit_opened_at: null
287
295
  } : {}
288
- }).where("account_id", "=", accountId).where("id", "=", id).returningAll().executeTakeFirst();
289
- return row ?? null;
296
+ }).where("id", "=", id);
297
+ if (isPlatformMode())
298
+ q = q.where("account_id", "=", accountId);
299
+ return await q.returningAll().executeTakeFirst() ?? null;
290
300
  }
291
301
  async function deleteSubscription(db, accountId, id) {
292
- const res = await db.deleteFrom("subscriptions").where("account_id", "=", accountId).where("id", "=", id).executeTakeFirst();
302
+ let q = db.deleteFrom("subscriptions").where("id", "=", id);
303
+ if (isPlatformMode())
304
+ q = q.where("account_id", "=", accountId);
305
+ const res = await q.executeTakeFirst();
293
306
  return Number(res.numDeletedRows ?? 0) > 0;
294
307
  }
295
308
  async function rotateSubscriptionSecret(db, accountId, id) {
296
309
  const signingSecret = generateSecret();
297
- const row = await db.updateTable("subscriptions").set({
310
+ let q = db.updateTable("subscriptions").set({
298
311
  signing_secret_enc: encryptSecret(signingSecret),
299
312
  updated_at: new Date
300
- }).where("account_id", "=", accountId).where("id", "=", id).returningAll().executeTakeFirst();
313
+ }).where("id", "=", id);
314
+ if (isPlatformMode())
315
+ q = q.where("account_id", "=", accountId);
316
+ const row = await q.returningAll().executeTakeFirst();
301
317
  if (!row)
302
318
  return null;
303
319
  return { subscription: row, signingSecret };
@@ -322,5 +338,5 @@ export {
322
338
  createSubscription
323
339
  };
324
340
 
325
- //# debugId=82CE895808FBD66564756E2164756E21
341
+ //# debugId=AC6E9EB29680C9A564756E2164756E21
326
342
  //# sourceMappingURL=subscriptions.js.map
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/crypto/hmac.ts", "../src/mode.ts", "../src/crypto/secrets.ts", "../src/db/queries/subscriptions.ts"],
3
+ "sources": ["../src/mode.ts", "../src/crypto/hmac.ts", "../src/crypto/secrets.ts", "../src/db/queries/subscriptions.ts"],
4
4
  "sourcesContent": [
5
- "import { createHmac, randomBytes } from \"node:crypto\";\n\n/**\n * Generate a random secret for delivery signing\n * Returns 32 bytes as a 64-character hex string\n */\nexport function generateSecret(): string {\n\treturn randomBytes(32).toString(\"hex\");\n}\n\n/**\n * Sign a payload with HMAC-SHA256\n * Returns the signature as a hex string\n */\nexport function signPayload(payload: string, secret: string): string {\n\tconst hmac = createHmac(\"sha256\", secret);\n\thmac.update(payload);\n\treturn hmac.digest(\"hex\");\n}\n\n/**\n * Verify an HMAC signature\n * Uses constant-time comparison to prevent timing attacks\n */\nexport function verifySignature(\n\tpayload: string,\n\tsignature: string,\n\tsecret: string,\n): boolean {\n\tconst expectedSignature = signPayload(payload, secret);\n\n\t// Constant-time comparison\n\tif (signature.length !== expectedSignature.length) {\n\t\treturn false;\n\t}\n\n\tlet result = 0;\n\tfor (let i = 0; i < signature.length; i++) {\n\t\tresult |= signature.charCodeAt(i) ^ expectedSignature.charCodeAt(i);\n\t}\n\n\treturn result === 0;\n}\n\n/**\n * Create a Stripe-style signature header\n * Format: t=timestamp,v1=signature\n */\nexport function createSignatureHeader(\n\tpayload: string,\n\tsecret: string,\n\ttimestamp?: number,\n): string {\n\tconst ts = timestamp ?? Math.floor(Date.now() / 1000);\n\tconst signedPayload = `${ts}.${payload}`;\n\tconst signature = signPayload(signedPayload, secret);\n\n\treturn `t=${ts},v1=${signature}`;\n}\n\n/**\n * Parse and verify a Stripe-style signature header\n * Returns true if valid, false otherwise\n */\nexport function verifySignatureHeader(\n\tpayload: string,\n\theader: string,\n\tsecret: string,\n\ttoleranceSeconds = 300, // 5 minutes\n): boolean {\n\t// Parse header\n\tconst parts = header.split(\",\");\n\tconst timestamp = parts.find((p) => p.startsWith(\"t=\"))?.slice(2);\n\tconst signature = parts.find((p) => p.startsWith(\"v1=\"))?.slice(3);\n\n\tif (!timestamp || !signature) {\n\t\treturn false;\n\t}\n\n\tconst ts = Number.parseInt(timestamp, 10);\n\tif (Number.isNaN(ts)) {\n\t\treturn false;\n\t}\n\n\t// Check timestamp is within tolerance\n\tconst now = Math.floor(Date.now() / 1000);\n\tif (Math.abs(now - ts) > toleranceSeconds) {\n\t\treturn false;\n\t}\n\n\t// Verify signature\n\tconst signedPayload = `${ts}.${payload}`;\n\treturn verifySignature(signedPayload, signature, secret);\n}\n",
6
5
  "/**\n * Instance modes for the Secondlayer platform.\n *\n * - `oss`: self-hosted, single-tenant. No auth middleware, no platform routes\n * (projects, admin). Everything runs against a single `DATABASE_URL`.\n * Intended for `docker compose up`.\n *\n * - `platform`: control-plane mode. Magic-link auth, API keys, projects,\n * admin. Serves the dashboard + CLI against a single shared DB. Post\n * 2026-05-14 shared-rip this also serves subgraphs + subscriptions.\n */\n\nexport type InstanceMode = \"oss\" | \"platform\";\n\nconst VALID_MODES: readonly InstanceMode[] = [\"oss\", \"platform\"];\n\n/**\n * Resolve the active instance mode from `process.env.INSTANCE_MODE`.\n * Defaults to `\"oss\"` — the safest default for self-hosters who deploy\n * without setting the variable.\n */\nexport function getInstanceMode(): InstanceMode {\n\tconst raw = process.env.INSTANCE_MODE?.trim().toLowerCase();\n\tif (raw && (VALID_MODES as readonly string[]).includes(raw)) {\n\t\treturn raw as InstanceMode;\n\t}\n\treturn \"oss\";\n}\n\n/** True when the active mode is `\"platform\"` (shared multi-tenant). */\nexport function isPlatformMode(): boolean {\n\treturn getInstanceMode() === \"platform\";\n}\n\n/** True when the active mode is `\"oss\"` (self-hosted). */\nexport function isOssMode(): boolean {\n\treturn getInstanceMode() === \"oss\";\n}\n",
6
+ "import { createHmac, randomBytes } from \"node:crypto\";\n\n/**\n * Generate a random secret for delivery signing\n * Returns 32 bytes as a 64-character hex string\n */\nexport function generateSecret(): string {\n\treturn randomBytes(32).toString(\"hex\");\n}\n\n/**\n * Sign a payload with HMAC-SHA256\n * Returns the signature as a hex string\n */\nexport function signPayload(payload: string, secret: string): string {\n\tconst hmac = createHmac(\"sha256\", secret);\n\thmac.update(payload);\n\treturn hmac.digest(\"hex\");\n}\n\n/**\n * Verify an HMAC signature\n * Uses constant-time comparison to prevent timing attacks\n */\nexport function verifySignature(\n\tpayload: string,\n\tsignature: string,\n\tsecret: string,\n): boolean {\n\tconst expectedSignature = signPayload(payload, secret);\n\n\t// Constant-time comparison\n\tif (signature.length !== expectedSignature.length) {\n\t\treturn false;\n\t}\n\n\tlet result = 0;\n\tfor (let i = 0; i < signature.length; i++) {\n\t\tresult |= signature.charCodeAt(i) ^ expectedSignature.charCodeAt(i);\n\t}\n\n\treturn result === 0;\n}\n\n/**\n * Create a Stripe-style signature header\n * Format: t=timestamp,v1=signature\n */\nexport function createSignatureHeader(\n\tpayload: string,\n\tsecret: string,\n\ttimestamp?: number,\n): string {\n\tconst ts = timestamp ?? Math.floor(Date.now() / 1000);\n\tconst signedPayload = `${ts}.${payload}`;\n\tconst signature = signPayload(signedPayload, secret);\n\n\treturn `t=${ts},v1=${signature}`;\n}\n\n/**\n * Parse and verify a Stripe-style signature header\n * Returns true if valid, false otherwise\n */\nexport function verifySignatureHeader(\n\tpayload: string,\n\theader: string,\n\tsecret: string,\n\ttoleranceSeconds = 300, // 5 minutes\n): boolean {\n\t// Parse header\n\tconst parts = header.split(\",\");\n\tconst timestamp = parts.find((p) => p.startsWith(\"t=\"))?.slice(2);\n\tconst signature = parts.find((p) => p.startsWith(\"v1=\"))?.slice(3);\n\n\tif (!timestamp || !signature) {\n\t\treturn false;\n\t}\n\n\tconst ts = Number.parseInt(timestamp, 10);\n\tif (Number.isNaN(ts)) {\n\t\treturn false;\n\t}\n\n\t// Check timestamp is within tolerance\n\tconst now = Math.floor(Date.now() / 1000);\n\tif (Math.abs(now - ts) > toleranceSeconds) {\n\t\treturn false;\n\t}\n\n\t// Verify signature\n\tconst signedPayload = `${ts}.${payload}`;\n\treturn verifySignature(signedPayload, signature, secret);\n}\n",
7
7
  "import { createCipheriv, createDecipheriv, randomBytes } from \"node:crypto\";\nimport {\n\tappendFileSync,\n\tcloseSync,\n\texistsSync,\n\topenSync,\n\treadFileSync,\n\tunlinkSync,\n} from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { getInstanceMode } from \"../mode.ts\";\n\n/**\n * AES-256-GCM symmetric envelope for encrypted secrets at rest (tenant keys,\n * subscription signing secrets, etc.).\n *\n * Ciphertext layout: `iv (12 bytes) || authTag (16 bytes) || ciphertext`\n *\n * The key comes from `SECONDLAYER_SECRETS_KEY` — 32 bytes hex. In OSS mode,\n * if the env var is unset on first use we autogenerate a key and persist it\n * to `.env.local` in the current working directory so subsequent restarts\n * pick it up without user intervention. Dedicated/platform modes throw —\n * those runtimes must provision the key explicitly.\n *\n * Rotation strategy: re-encrypt all rows with the new key and swap the env\n * var. Not zero-downtime, but acceptable at v2 scale. For real KMS (AWS\n * KMS, Vault, GCP KMS), wrap the same byte layout behind an\n * `EncryptSecret`/`DecryptSecret` interface and swap at startup.\n */\n\nconst KEY_ENV = \"SECONDLAYER_SECRETS_KEY\";\nconst IV_LEN = 12;\nconst TAG_LEN = 16;\n\nfunction readExistingKey(envPath: string): string | null {\n\tif (!existsSync(envPath)) return null;\n\tconst contents = readFileSync(envPath, \"utf8\");\n\tconst match = contents.match(/^SECONDLAYER_SECRETS_KEY=([a-fA-F0-9]{64})/m);\n\t// biome-ignore lint/style/noNonNullAssertion: value is non-null after preceding check or by construction; TS narrowing limitation\n\treturn match ? match[1]! : null;\n}\n\n/**\n * Atomic file lock via `openSync(..., \"wx\")` — O_CREAT | O_EXCL. If two\n * processes race on cold-compose start, exactly one creates the lock\n * file; the loser polls until the winner finishes writing `.env.local`,\n * then reads the winner's key. Stale locks (process crashed mid-write)\n * are cleaned after `STALE_LOCK_MS`.\n */\nconst STALE_LOCK_MS = 10_000;\nconst POLL_MS = 25;\n\nfunction bootstrapOssKey(): string {\n\tconst envPath = resolve(process.cwd(), \".env.local\");\n\n\t// Fast path — key already on disk from a prior run.\n\tconst existing = readExistingKey(envPath);\n\tif (existing) {\n\t\tprocess.env[KEY_ENV] = existing;\n\t\treturn existing;\n\t}\n\n\tconst lockPath = `${envPath}.secret-bootstrap.lock`;\n\tlet lockFd: number | null = null;\n\ttry {\n\t\tlockFd = openSync(lockPath, \"wx\", 0o600);\n\t} catch (err) {\n\t\tconst e = err as NodeJS.ErrnoException;\n\t\tif (e.code !== \"EEXIST\") throw err;\n\t}\n\n\tif (lockFd === null) {\n\t\t// Another process is bootstrapping. Poll for its result.\n\t\tconst deadline = Date.now() + STALE_LOCK_MS;\n\t\twhile (Date.now() < deadline) {\n\t\t\tconst key = readExistingKey(envPath);\n\t\t\tif (key) {\n\t\t\t\tprocess.env[KEY_ENV] = key;\n\t\t\t\treturn key;\n\t\t\t}\n\t\t\tBun.sleepSync(POLL_MS);\n\t\t}\n\t\t// Lock holder died mid-write — force-clean and retry once.\n\t\ttry {\n\t\t\tunlinkSync(lockPath);\n\t\t} catch {}\n\t\treturn bootstrapOssKey();\n\t}\n\n\ttry {\n\t\tconst hex = randomBytes(32).toString(\"hex\");\n\t\tconst line = `${existsSync(envPath) ? \"\\n\" : \"\"}${KEY_ENV}=${hex}\\n`;\n\t\tappendFileSync(envPath, line, { mode: 0o600 });\n\t\tprocess.env[KEY_ENV] = hex;\n\t\tconsole.log(\n\t\t\t`[secondlayer] generated ${KEY_ENV}; saved to ${envPath} (mode 0600)`,\n\t\t);\n\t\treturn hex;\n\t} finally {\n\t\tcloseSync(lockFd);\n\t\ttry {\n\t\t\tunlinkSync(lockPath);\n\t\t} catch {}\n\t}\n}\n\nfunction loadKey(): Buffer {\n\tlet hex = process.env[KEY_ENV];\n\tif (!hex) {\n\t\tif (getInstanceMode() === \"oss\") {\n\t\t\thex = bootstrapOssKey();\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t`${KEY_ENV} not set. Generate one with: openssl rand -hex 32`,\n\t\t\t);\n\t\t}\n\t}\n\tconst key = Buffer.from(hex, \"hex\");\n\tif (key.length !== 32) {\n\t\tthrow new Error(`${KEY_ENV} must be 32 bytes hex (got ${key.length})`);\n\t}\n\treturn key;\n}\n\nlet _cachedKey: Buffer | null = null;\nfunction getKey(): Buffer {\n\tif (!_cachedKey) _cachedKey = loadKey();\n\treturn _cachedKey;\n}\n\n/**\n * Non-throwing check for whether a secrets key is currently resolvable —\n * same resolution order as {@link loadKey} (env var, then the OSS\n * `.env.local` fallback), but never bootstraps a new key (that would\n * generate+persist a key as a side effect of a mere existence check), never\n * throws, and never returns or logs the key itself. Used by callers that\n * need to fail loud on a missing key BEFORE attempting a decrypt (f072).\n */\nexport function secretsKeyAvailable(): boolean {\n\tif (process.env[KEY_ENV]) return true;\n\tif (getInstanceMode() === \"oss\") {\n\t\tconst envPath = resolve(process.cwd(), \".env.local\");\n\t\treturn readExistingKey(envPath) !== null;\n\t}\n\treturn false;\n}\n\nexport function encryptSecret(plaintext: string): Buffer {\n\tconst key = getKey();\n\tconst iv = randomBytes(IV_LEN);\n\tconst cipher = createCipheriv(\"aes-256-gcm\", key, iv);\n\tconst ciphertext = Buffer.concat([\n\t\tcipher.update(plaintext, \"utf8\"),\n\t\tcipher.final(),\n\t]);\n\tconst tag = cipher.getAuthTag();\n\treturn Buffer.concat([iv, tag, ciphertext]);\n}\n\nexport function decryptSecret(envelope: Buffer): string {\n\tconst key = getKey();\n\tconst iv = envelope.subarray(0, IV_LEN);\n\tconst tag = envelope.subarray(IV_LEN, IV_LEN + TAG_LEN);\n\tconst ciphertext = envelope.subarray(IV_LEN + TAG_LEN);\n\tconst decipher = createDecipheriv(\"aes-256-gcm\", key, iv);\n\tdecipher.setAuthTag(tag);\n\treturn decipher.update(ciphertext).toString(\"utf8\") + decipher.final(\"utf8\");\n}\n\n/** Generate a fresh 32-byte hex key suitable for `SECONDLAYER_SECRETS_KEY`. */\nexport function generateSecretsKey(): string {\n\treturn randomBytes(32).toString(\"hex\");\n}\n",
8
- "import { type Kysely, sql } from \"kysely\";\nimport { generateSecret } from \"../../crypto/hmac.ts\";\nimport { decryptSecret, encryptSecret } from \"../../crypto/secrets.ts\";\nimport type {\n\tDatabase,\n\tInsertSubscription,\n\tSubscription,\n\tSubscriptionFormat,\n\tSubscriptionKind,\n\tSubscriptionRuntime,\n\tSubscriptionStatus,\n\tUpdateSubscription,\n} from \"../types.ts\";\n\n/**\n * Subscription CRUD. `signing_secret_enc` is transparently encrypted via\n * `encryptSecret`/`decryptSecret`. Plaintext secrets only leave via the\n * return value of `create` (one-time display) and `rotateSecret`.\n */\n\nexport interface CreateSubscriptionInput {\n\taccountId: string;\n\tprojectId?: string | null;\n\tname: string;\n\t/** Defaults to \"subgraph\". Chain subscriptions set kind=\"chain\" + triggers. */\n\tkind?: SubscriptionKind;\n\t/** Required for subgraph subscriptions; omitted for chain. */\n\tsubgraphName?: string | null;\n\t/** Required for subgraph subscriptions; omitted for chain. */\n\ttableName?: string | null;\n\t/** Chain-trigger filter array. Required for chain subscriptions. */\n\ttriggers?: unknown;\n\tfilter?: unknown;\n\tformat?: SubscriptionFormat;\n\truntime?: SubscriptionRuntime | null;\n\turl: string;\n\tauthConfig?: unknown;\n\tmaxRetries?: number;\n\ttimeoutMs?: number;\n\tconcurrency?: number;\n}\n\nexport interface CreateSubscriptionResult {\n\tsubscription: Subscription;\n\t/** Plaintext signing secret — surfaced once, never stored decrypted. */\n\tsigningSecret: string;\n}\n\nexport async function createSubscription(\n\tdb: Kysely<Database>,\n\tinput: CreateSubscriptionInput,\n): Promise<CreateSubscriptionResult> {\n\tconst signingSecret = generateSecret();\n\tconst kind: SubscriptionKind = input.kind ?? \"subgraph\";\n\tconst row: InsertSubscription = {\n\t\taccount_id: input.accountId,\n\t\tproject_id: input.projectId ?? null,\n\t\tname: input.name,\n\t\tstatus: \"active\",\n\t\tkind,\n\t\tsubgraph_name: input.subgraphName ?? null,\n\t\ttable_name: input.tableName ?? null,\n\t\ttriggers: kind === \"chain\" ? ((input.triggers ?? []) as unknown) : null,\n\t\tfilter: input.filter ?? {},\n\t\tformat: input.format ?? \"standard-webhooks\",\n\t\truntime: input.runtime ?? null,\n\t\turl: input.url,\n\t\tsigning_secret_enc: encryptSecret(signingSecret),\n\t\tauth_config: input.authConfig ?? {},\n\t\t...(input.maxRetries !== undefined\n\t\t\t? { max_retries: input.maxRetries }\n\t\t\t: {}),\n\t\t...(input.timeoutMs !== undefined ? { timeout_ms: input.timeoutMs } : {}),\n\t\t...(input.concurrency !== undefined\n\t\t\t? { concurrency: input.concurrency }\n\t\t\t: {}),\n\t};\n\tconst subscription = await db\n\t\t.insertInto(\"subscriptions\")\n\t\t.values(row)\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n\treturn { subscription, signingSecret };\n}\n\nexport async function listSubscriptions(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\topts?: { limit?: number; offset?: number },\n): Promise<Subscription[]> {\n\tlet q = db\n\t\t.selectFrom(\"subscriptions\")\n\t\t.selectAll()\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.orderBy(\"created_at\", \"desc\");\n\tif (opts?.limit !== undefined) q = q.limit(opts.limit);\n\tif (opts?.offset !== undefined) q = q.offset(opts.offset);\n\treturn q.execute();\n}\n\n/**\n * All active chain subscriptions across every account — the input to the global\n * trigger evaluator (one loop serves them all). Subgraph subscriptions are\n * excluded; they emit via the subgraph flush path.\n */\nexport async function listActiveChainSubscriptions(\n\tdb: Kysely<Database>,\n): Promise<Subscription[]> {\n\treturn db\n\t\t.selectFrom(\"subscriptions\")\n\t\t.selectAll()\n\t\t.where(\"kind\", \"=\", \"chain\")\n\t\t.where(\"status\", \"=\", \"active\")\n\t\t.execute();\n}\n\nexport async function getSubscription(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tid: string,\n): Promise<Subscription | null> {\n\tconst row = await db\n\t\t.selectFrom(\"subscriptions\")\n\t\t.selectAll()\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"id\", \"=\", id)\n\t\t.executeTakeFirst();\n\treturn row ?? null;\n}\n\nexport async function getSubscriptionByName(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tname: string,\n): Promise<Subscription | null> {\n\tconst row = await db\n\t\t.selectFrom(\"subscriptions\")\n\t\t.selectAll()\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"name\", \"=\", name)\n\t\t.executeTakeFirst();\n\treturn row ?? null;\n}\n\nexport interface UpdateSubscriptionInput {\n\tname?: string;\n\tfilter?: unknown;\n\tformat?: SubscriptionFormat;\n\truntime?: SubscriptionRuntime | null;\n\turl?: string;\n\tauthConfig?: unknown;\n\tmaxRetries?: number;\n\ttimeoutMs?: number;\n\tconcurrency?: number;\n}\n\nexport async function updateSubscription(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tid: string,\n\tpatch: UpdateSubscriptionInput,\n): Promise<Subscription | null> {\n\tconst update: UpdateSubscription = { updated_at: new Date() };\n\tif (patch.name !== undefined) update.name = patch.name;\n\tif (patch.filter !== undefined) update.filter = patch.filter;\n\tif (patch.format !== undefined) update.format = patch.format;\n\tif (patch.runtime !== undefined) update.runtime = patch.runtime;\n\tif (patch.url !== undefined) update.url = patch.url;\n\tif (patch.authConfig !== undefined) update.auth_config = patch.authConfig;\n\tif (patch.maxRetries !== undefined) update.max_retries = patch.maxRetries;\n\tif (patch.timeoutMs !== undefined) update.timeout_ms = patch.timeoutMs;\n\tif (patch.concurrency !== undefined) update.concurrency = patch.concurrency;\n\n\tconst row = await db\n\t\t.updateTable(\"subscriptions\")\n\t\t.set(update)\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"id\", \"=\", id)\n\t\t.returningAll()\n\t\t.executeTakeFirst();\n\treturn row ?? null;\n}\n\nexport async function toggleSubscriptionStatus(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tid: string,\n\tstatus: SubscriptionStatus,\n): Promise<Subscription | null> {\n\tconst row = await db\n\t\t.updateTable(\"subscriptions\")\n\t\t.set({\n\t\t\tstatus,\n\t\t\tupdated_at: new Date(),\n\t\t\t...(status === \"active\"\n\t\t\t\t? {\n\t\t\t\t\t\tcircuit_failures: 0,\n\t\t\t\t\t\tcircuit_opened_at: null,\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t})\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"id\", \"=\", id)\n\t\t.returningAll()\n\t\t.executeTakeFirst();\n\treturn row ?? null;\n}\n\nexport async function deleteSubscription(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tid: string,\n): Promise<boolean> {\n\tconst res = await db\n\t\t.deleteFrom(\"subscriptions\")\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"id\", \"=\", id)\n\t\t.executeTakeFirst();\n\treturn Number(res.numDeletedRows ?? 0) > 0;\n}\n\nexport interface RotateSecretResult {\n\tsubscription: Subscription;\n\tsigningSecret: string;\n}\n\nexport async function rotateSubscriptionSecret(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tid: string,\n): Promise<RotateSecretResult | null> {\n\tconst signingSecret = generateSecret();\n\tconst row = await db\n\t\t.updateTable(\"subscriptions\")\n\t\t.set({\n\t\t\tsigning_secret_enc: encryptSecret(signingSecret),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"account_id\", \"=\", accountId)\n\t\t.where(\"id\", \"=\", id)\n\t\t.returningAll()\n\t\t.executeTakeFirst();\n\tif (!row) return null;\n\treturn { subscription: row, signingSecret };\n}\n\n/** Decrypt a subscription's signing secret for HMAC signing at emit time. */\nexport function getSubscriptionSigningSecret(sub: Subscription): string {\n\treturn decryptSecret(sub.signing_secret_enc);\n}\n\n/** Fire `subscriptions:changed` notify so the emitter hot-reloads its cache. */\nexport async function notifySubscriptionsChanged(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<void> {\n\tawait sql`SELECT pg_notify('subscriptions:changed', ${accountId})`.execute(\n\t\tdb,\n\t);\n}\n"
8
+ "import { type Kysely, sql } from \"kysely\";\nimport { generateSecret } from \"../../crypto/hmac.ts\";\nimport { decryptSecret, encryptSecret } from \"../../crypto/secrets.ts\";\nimport { isPlatformMode } from \"../../mode.ts\";\nimport type {\n\tDatabase,\n\tInsertSubscription,\n\tSubscription,\n\tSubscriptionFormat,\n\tSubscriptionKind,\n\tSubscriptionRuntime,\n\tSubscriptionStatus,\n\tUpdateSubscription,\n} from \"../types.ts\";\n\n/**\n * Subscription CRUD. `signing_secret_enc` is transparently encrypted via\n * `encryptSecret`/`decryptSecret`. Plaintext secrets only leave via the\n * return value of `create` (one-time display) and `rotateSecret`.\n */\n\nexport interface CreateSubscriptionInput {\n\taccountId: string;\n\tprojectId?: string | null;\n\tname: string;\n\t/** Defaults to \"subgraph\". Chain subscriptions set kind=\"chain\" + triggers. */\n\tkind?: SubscriptionKind;\n\t/** Required for subgraph subscriptions; omitted for chain. */\n\tsubgraphName?: string | null;\n\t/** Required for subgraph subscriptions; omitted for chain. */\n\ttableName?: string | null;\n\t/** Chain-trigger filter array. Required for chain subscriptions. */\n\ttriggers?: unknown;\n\tfilter?: unknown;\n\tformat?: SubscriptionFormat;\n\truntime?: SubscriptionRuntime | null;\n\turl: string;\n\tauthConfig?: unknown;\n\tmaxRetries?: number;\n\ttimeoutMs?: number;\n\tconcurrency?: number;\n}\n\nexport interface CreateSubscriptionResult {\n\tsubscription: Subscription;\n\t/** Plaintext signing secret — surfaced once, never stored decrypted. */\n\tsigningSecret: string;\n}\n\nexport async function createSubscription(\n\tdb: Kysely<Database>,\n\tinput: CreateSubscriptionInput,\n): Promise<CreateSubscriptionResult> {\n\tconst signingSecret = generateSecret();\n\tconst kind: SubscriptionKind = input.kind ?? \"subgraph\";\n\tconst row: InsertSubscription = {\n\t\taccount_id: isPlatformMode() ? input.accountId : \"\",\n\t\tproject_id: input.projectId ?? null,\n\t\tname: input.name,\n\t\tstatus: \"active\",\n\t\tkind,\n\t\tsubgraph_name: input.subgraphName ?? null,\n\t\ttable_name: input.tableName ?? null,\n\t\ttriggers: kind === \"chain\" ? ((input.triggers ?? []) as unknown) : null,\n\t\tfilter: input.filter ?? {},\n\t\tformat: input.format ?? \"standard-webhooks\",\n\t\truntime: input.runtime ?? null,\n\t\turl: input.url,\n\t\tsigning_secret_enc: encryptSecret(signingSecret),\n\t\tauth_config: input.authConfig ?? {},\n\t\t...(input.maxRetries !== undefined\n\t\t\t? { max_retries: input.maxRetries }\n\t\t\t: {}),\n\t\t...(input.timeoutMs !== undefined ? { timeout_ms: input.timeoutMs } : {}),\n\t\t...(input.concurrency !== undefined\n\t\t\t? { concurrency: input.concurrency }\n\t\t\t: {}),\n\t};\n\tconst subscription = await db\n\t\t.insertInto(\"subscriptions\")\n\t\t.values(row)\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n\treturn { subscription, signingSecret };\n}\n\nexport async function listSubscriptions(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\topts?: { limit?: number; offset?: number },\n): Promise<Subscription[]> {\n\tlet q = db\n\t\t.selectFrom(\"subscriptions\")\n\t\t.selectAll()\n\t\t.orderBy(\"created_at\", \"desc\");\n\tif (isPlatformMode()) q = q.where(\"account_id\", \"=\", accountId);\n\tif (opts?.limit !== undefined) q = q.limit(opts.limit);\n\tif (opts?.offset !== undefined) q = q.offset(opts.offset);\n\treturn q.execute();\n}\n\n/**\n * All active chain subscriptions across every account — the input to the global\n * trigger evaluator (one loop serves them all). Subgraph subscriptions are\n * excluded; they emit via the subgraph flush path.\n */\nexport async function listActiveChainSubscriptions(\n\tdb: Kysely<Database>,\n): Promise<Subscription[]> {\n\treturn db\n\t\t.selectFrom(\"subscriptions\")\n\t\t.selectAll()\n\t\t.where(\"kind\", \"=\", \"chain\")\n\t\t.where(\"status\", \"=\", \"active\")\n\t\t.execute();\n}\n\nexport async function getSubscription(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tid: string,\n): Promise<Subscription | null> {\n\tlet q = db.selectFrom(\"subscriptions\").selectAll().where(\"id\", \"=\", id);\n\tif (isPlatformMode()) q = q.where(\"account_id\", \"=\", accountId);\n\treturn (await q.executeTakeFirst()) ?? null;\n}\n\nexport async function getSubscriptionByName(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tname: string,\n): Promise<Subscription | null> {\n\tlet q = db.selectFrom(\"subscriptions\").selectAll().where(\"name\", \"=\", name);\n\tif (isPlatformMode()) q = q.where(\"account_id\", \"=\", accountId);\n\treturn (await q.executeTakeFirst()) ?? null;\n}\n\nexport interface UpdateSubscriptionInput {\n\tname?: string;\n\tfilter?: unknown;\n\tformat?: SubscriptionFormat;\n\truntime?: SubscriptionRuntime | null;\n\turl?: string;\n\tauthConfig?: unknown;\n\tmaxRetries?: number;\n\ttimeoutMs?: number;\n\tconcurrency?: number;\n}\n\nexport async function updateSubscription(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tid: string,\n\tpatch: UpdateSubscriptionInput,\n): Promise<Subscription | null> {\n\tconst update: UpdateSubscription = { updated_at: new Date() };\n\tif (patch.name !== undefined) update.name = patch.name;\n\tif (patch.filter !== undefined) update.filter = patch.filter;\n\tif (patch.format !== undefined) update.format = patch.format;\n\tif (patch.runtime !== undefined) update.runtime = patch.runtime;\n\tif (patch.url !== undefined) update.url = patch.url;\n\tif (patch.authConfig !== undefined) update.auth_config = patch.authConfig;\n\tif (patch.maxRetries !== undefined) update.max_retries = patch.maxRetries;\n\tif (patch.timeoutMs !== undefined) update.timeout_ms = patch.timeoutMs;\n\tif (patch.concurrency !== undefined) update.concurrency = patch.concurrency;\n\n\tlet q = db.updateTable(\"subscriptions\").set(update).where(\"id\", \"=\", id);\n\tif (isPlatformMode()) q = q.where(\"account_id\", \"=\", accountId);\n\treturn (await q.returningAll().executeTakeFirst()) ?? null;\n}\n\nexport async function toggleSubscriptionStatus(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tid: string,\n\tstatus: SubscriptionStatus,\n): Promise<Subscription | null> {\n\tlet q = db\n\t\t.updateTable(\"subscriptions\")\n\t\t.set({\n\t\t\tstatus,\n\t\t\tupdated_at: new Date(),\n\t\t\t...(status === \"active\"\n\t\t\t\t? {\n\t\t\t\t\t\tcircuit_failures: 0,\n\t\t\t\t\t\tcircuit_opened_at: null,\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t})\n\t\t.where(\"id\", \"=\", id);\n\tif (isPlatformMode()) q = q.where(\"account_id\", \"=\", accountId);\n\treturn (await q.returningAll().executeTakeFirst()) ?? null;\n}\n\nexport async function deleteSubscription(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tid: string,\n): Promise<boolean> {\n\tlet q = db.deleteFrom(\"subscriptions\").where(\"id\", \"=\", id);\n\tif (isPlatformMode()) q = q.where(\"account_id\", \"=\", accountId);\n\tconst res = await q.executeTakeFirst();\n\treturn Number(res.numDeletedRows ?? 0) > 0;\n}\n\nexport interface RotateSecretResult {\n\tsubscription: Subscription;\n\tsigningSecret: string;\n}\n\nexport async function rotateSubscriptionSecret(\n\tdb: Kysely<Database>,\n\taccountId: string,\n\tid: string,\n): Promise<RotateSecretResult | null> {\n\tconst signingSecret = generateSecret();\n\tlet q = db\n\t\t.updateTable(\"subscriptions\")\n\t\t.set({\n\t\t\tsigning_secret_enc: encryptSecret(signingSecret),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"id\", \"=\", id);\n\tif (isPlatformMode()) q = q.where(\"account_id\", \"=\", accountId);\n\tconst row = await q.returningAll().executeTakeFirst();\n\tif (!row) return null;\n\treturn { subscription: row, signingSecret };\n}\n\n/** Decrypt a subscription's signing secret for HMAC signing at emit time. */\nexport function getSubscriptionSigningSecret(sub: Subscription): string {\n\treturn decryptSecret(sub.signing_secret_enc);\n}\n\n/** Fire `subscriptions:changed` notify so the emitter hot-reloads its cache. */\nexport async function notifySubscriptionsChanged(\n\tdb: Kysely<Database>,\n\taccountId: string,\n): Promise<void> {\n\tawait sql`SELECT pg_notify('subscriptions:changed', ${accountId})`.execute(\n\t\tdb,\n\t);\n}\n"
9
9
  ],
10
- "mappings": "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",
11
- "debugId": "82CE895808FBD66564756E2164756E21",
10
+ "mappings": ";;;;;;;;;;;;;;;;;AAcA,IAAM,cAAuC,CAAC,OAAO,UAAU;AAOxD,SAAS,eAAe,GAAiB;AAAA,EAC/C,MAAM,MAAM,QAAQ,IAAI,eAAe,KAAK,EAAE,YAAY;AAAA,EAC1D,IAAI,OAAQ,YAAkC,SAAS,GAAG,GAAG;AAAA,IAC5D,OAAO;AAAA,EACR;AAAA,EACA,OAAO;AAAA;AAID,SAAS,cAAc,GAAY;AAAA,EACzC,OAAO,gBAAgB,MAAM;AAAA;AAIvB,SAAS,SAAS,GAAY;AAAA,EACpC,OAAO,gBAAgB,MAAM;AAAA;;;;;;;;;;;ACpC9B;AAMO,SAAS,cAAc,GAAW;AAAA,EACxC,OAAO,YAAY,EAAE,EAAE,SAAS,KAAK;AAAA;AAO/B,SAAS,WAAW,CAAC,SAAiB,QAAwB;AAAA,EACpE,MAAM,OAAO,WAAW,UAAU,MAAM;AAAA,EACxC,KAAK,OAAO,OAAO;AAAA,EACnB,OAAO,KAAK,OAAO,KAAK;AAAA;AAOlB,SAAS,eAAe,CAC9B,SACA,WACA,QACU;AAAA,EACV,MAAM,oBAAoB,YAAY,SAAS,MAAM;AAAA,EAGrD,IAAI,UAAU,WAAW,kBAAkB,QAAQ;AAAA,IAClD,OAAO;AAAA,EACR;AAAA,EAEA,IAAI,SAAS;AAAA,EACb,SAAS,IAAI,EAAG,IAAI,UAAU,QAAQ,KAAK;AAAA,IAC1C,UAAU,UAAU,WAAW,CAAC,IAAI,kBAAkB,WAAW,CAAC;AAAA,EACnE;AAAA,EAEA,OAAO,WAAW;AAAA;AAOZ,SAAS,qBAAqB,CACpC,SACA,QACA,WACS;AAAA,EACT,MAAM,KAAK,aAAa,KAAK,MAAM,KAAK,IAAI,IAAI,IAAI;AAAA,EACpD,MAAM,gBAAgB,GAAG,MAAM;AAAA,EAC/B,MAAM,YAAY,YAAY,eAAe,MAAM;AAAA,EAEnD,OAAO,KAAK,SAAS;AAAA;AAOf,SAAS,qBAAqB,CACpC,SACA,QACA,QACA,mBAAmB,KACT;AAAA,EAEV,MAAM,QAAQ,OAAO,MAAM,GAAG;AAAA,EAC9B,MAAM,YAAY,MAAM,KAAK,CAAC,MAAM,EAAE,WAAW,IAAI,CAAC,GAAG,MAAM,CAAC;AAAA,EAChE,MAAM,YAAY,MAAM,KAAK,CAAC,MAAM,EAAE,WAAW,KAAK,CAAC,GAAG,MAAM,CAAC;AAAA,EAEjE,IAAI,CAAC,aAAa,CAAC,WAAW;AAAA,IAC7B,OAAO;AAAA,EACR;AAAA,EAEA,MAAM,KAAK,OAAO,SAAS,WAAW,EAAE;AAAA,EACxC,IAAI,OAAO,MAAM,EAAE,GAAG;AAAA,IACrB,OAAO;AAAA,EACR;AAAA,EAGA,MAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,IAAI;AAAA,EACxC,IAAI,KAAK,IAAI,MAAM,EAAE,IAAI,kBAAkB;AAAA,IAC1C,OAAO;AAAA,EACR;AAAA,EAGA,MAAM,gBAAgB,GAAG,MAAM;AAAA,EAC/B,OAAO,gBAAgB,eAAe,WAAW,MAAM;AAAA;;;AC5FxD,0DAA2C;AAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA;AAqBA,IAAM,UAAU;AAChB,IAAM,SAAS;AACf,IAAM,UAAU;AAEhB,SAAS,eAAe,CAAC,SAAgC;AAAA,EACxD,IAAI,CAAC,WAAW,OAAO;AAAA,IAAG,OAAO;AAAA,EACjC,MAAM,WAAW,aAAa,SAAS,MAAM;AAAA,EAC7C,MAAM,QAAQ,SAAS,MAAM,6CAA6C;AAAA,EAE1E,OAAO,QAAQ,MAAM,KAAM;AAAA;AAU5B,IAAM,gBAAgB;AACtB,IAAM,UAAU;AAEhB,SAAS,eAAe,GAAW;AAAA,EAClC,MAAM,UAAU,QAAQ,QAAQ,IAAI,GAAG,YAAY;AAAA,EAGnD,MAAM,WAAW,gBAAgB,OAAO;AAAA,EACxC,IAAI,UAAU;AAAA,IACb,QAAQ,IAAI,WAAW;AAAA,IACvB,OAAO;AAAA,EACR;AAAA,EAEA,MAAM,WAAW,GAAG;AAAA,EACpB,IAAI,SAAwB;AAAA,EAC5B,IAAI;AAAA,IACH,SAAS,SAAS,UAAU,MAAM,GAAK;AAAA,IACtC,OAAO,KAAK;AAAA,IACb,MAAM,IAAI;AAAA,IACV,IAAI,EAAE,SAAS;AAAA,MAAU,MAAM;AAAA;AAAA,EAGhC,IAAI,WAAW,MAAM;AAAA,IAEpB,MAAM,WAAW,KAAK,IAAI,IAAI;AAAA,IAC9B,OAAO,KAAK,IAAI,IAAI,UAAU;AAAA,MAC7B,MAAM,MAAM,gBAAgB,OAAO;AAAA,MACnC,IAAI,KAAK;AAAA,QACR,QAAQ,IAAI,WAAW;AAAA,QACvB,OAAO;AAAA,MACR;AAAA,MACA,IAAI,UAAU,OAAO;AAAA,IACtB;AAAA,IAEA,IAAI;AAAA,MACH,WAAW,QAAQ;AAAA,MAClB,MAAM;AAAA,IACR,OAAO,gBAAgB;AAAA,EACxB;AAAA,EAEA,IAAI;AAAA,IACH,MAAM,MAAM,aAAY,EAAE,EAAE,SAAS,KAAK;AAAA,IAC1C,MAAM,OAAO,GAAG,WAAW,OAAO,IAAI;AAAA,IAAO,KAAK,WAAW;AAAA;AAAA,IAC7D,eAAe,SAAS,MAAM,EAAE,MAAM,IAAM,CAAC;AAAA,IAC7C,QAAQ,IAAI,WAAW;AAAA,IACvB,QAAQ,IACP,2BAA2B,qBAAqB,qBACjD;AAAA,IACA,OAAO;AAAA,YACN;AAAA,IACD,UAAU,MAAM;AAAA,IAChB,IAAI;AAAA,MACH,WAAW,QAAQ;AAAA,MAClB,MAAM;AAAA;AAAA;AAIV,SAAS,OAAO,GAAW;AAAA,EAC1B,IAAI,MAAM,QAAQ,IAAI;AAAA,EACtB,IAAI,CAAC,KAAK;AAAA,IACT,IAAI,gBAAgB,MAAM,OAAO;AAAA,MAChC,MAAM,gBAAgB;AAAA,IACvB,EAAO;AAAA,MACN,MAAM,IAAI,MACT,GAAG,0DACJ;AAAA;AAAA,EAEF;AAAA,EACA,MAAM,MAAM,OAAO,KAAK,KAAK,KAAK;AAAA,EAClC,IAAI,IAAI,WAAW,IAAI;AAAA,IACtB,MAAM,IAAI,MAAM,GAAG,qCAAqC,IAAI,SAAS;AAAA,EACtE;AAAA,EACA,OAAO;AAAA;AAGR,IAAI,aAA4B;AAChC,SAAS,MAAM,GAAW;AAAA,EACzB,IAAI,CAAC;AAAA,IAAY,aAAa,QAAQ;AAAA,EACtC,OAAO;AAAA;AAWD,SAAS,mBAAmB,GAAY;AAAA,EAC9C,IAAI,QAAQ,IAAI;AAAA,IAAU,OAAO;AAAA,EACjC,IAAI,gBAAgB,MAAM,OAAO;AAAA,IAChC,MAAM,UAAU,QAAQ,QAAQ,IAAI,GAAG,YAAY;AAAA,IACnD,OAAO,gBAAgB,OAAO,MAAM;AAAA,EACrC;AAAA,EACA,OAAO;AAAA;AAGD,SAAS,aAAa,CAAC,WAA2B;AAAA,EACxD,MAAM,MAAM,OAAO;AAAA,EACnB,MAAM,KAAK,aAAY,MAAM;AAAA,EAC7B,MAAM,SAAS,eAAe,eAAe,KAAK,EAAE;AAAA,EACpD,MAAM,aAAa,OAAO,OAAO;AAAA,IAChC,OAAO,OAAO,WAAW,MAAM;AAAA,IAC/B,OAAO,MAAM;AAAA,EACd,CAAC;AAAA,EACD,MAAM,MAAM,OAAO,WAAW;AAAA,EAC9B,OAAO,OAAO,OAAO,CAAC,IAAI,KAAK,UAAU,CAAC;AAAA;AAGpC,SAAS,aAAa,CAAC,UAA0B;AAAA,EACvD,MAAM,MAAM,OAAO;AAAA,EACnB,MAAM,KAAK,SAAS,SAAS,GAAG,MAAM;AAAA,EACtC,MAAM,MAAM,SAAS,SAAS,QAAQ,SAAS,OAAO;AAAA,EACtD,MAAM,aAAa,SAAS,SAAS,SAAS,OAAO;AAAA,EACrD,MAAM,WAAW,iBAAiB,eAAe,KAAK,EAAE;AAAA,EACxD,SAAS,WAAW,GAAG;AAAA,EACvB,OAAO,SAAS,OAAO,UAAU,EAAE,SAAS,MAAM,IAAI,SAAS,MAAM,MAAM;AAAA;AAIrE,SAAS,kBAAkB,GAAW;AAAA,EAC5C,OAAO,aAAY,EAAE,EAAE,SAAS,KAAK;AAAA;;;AC3KtC;AAiDA,eAAsB,kBAAkB,CACvC,IACA,OACoC;AAAA,EACpC,MAAM,gBAAgB,eAAe;AAAA,EACrC,MAAM,OAAyB,MAAM,QAAQ;AAAA,EAC7C,MAAM,MAA0B;AAAA,IAC/B,YAAY,eAAe,IAAI,MAAM,YAAY;AAAA,IACjD,YAAY,MAAM,aAAa;AAAA,IAC/B,MAAM,MAAM;AAAA,IACZ,QAAQ;AAAA,IACR;AAAA,IACA,eAAe,MAAM,gBAAgB;AAAA,IACrC,YAAY,MAAM,aAAa;AAAA,IAC/B,UAAU,SAAS,UAAY,MAAM,YAAY,CAAC,IAAiB;AAAA,IACnE,QAAQ,MAAM,UAAU,CAAC;AAAA,IACzB,QAAQ,MAAM,UAAU;AAAA,IACxB,SAAS,MAAM,WAAW;AAAA,IAC1B,KAAK,MAAM;AAAA,IACX,oBAAoB,cAAc,aAAa;AAAA,IAC/C,aAAa,MAAM,cAAc,CAAC;AAAA,OAC9B,MAAM,eAAe,YACtB,EAAE,aAAa,MAAM,WAAW,IAChC,CAAC;AAAA,OACA,MAAM,cAAc,YAAY,EAAE,YAAY,MAAM,UAAU,IAAI,CAAC;AAAA,OACnE,MAAM,gBAAgB,YACvB,EAAE,aAAa,MAAM,YAAY,IACjC,CAAC;AAAA,EACL;AAAA,EACA,MAAM,eAAe,MAAM,GACzB,WAAW,eAAe,EAC1B,OAAO,GAAG,EACV,aAAa,EACb,wBAAwB;AAAA,EAC1B,OAAO,EAAE,cAAc,cAAc;AAAA;AAGtC,eAAsB,iBAAiB,CACtC,IACA,WACA,MAC0B;AAAA,EAC1B,IAAI,IAAI,GACN,WAAW,eAAe,EAC1B,UAAU,EACV,QAAQ,cAAc,MAAM;AAAA,EAC9B,IAAI,eAAe;AAAA,IAAG,IAAI,EAAE,MAAM,cAAc,KAAK,SAAS;AAAA,EAC9D,IAAI,MAAM,UAAU;AAAA,IAAW,IAAI,EAAE,MAAM,KAAK,KAAK;AAAA,EACrD,IAAI,MAAM,WAAW;AAAA,IAAW,IAAI,EAAE,OAAO,KAAK,MAAM;AAAA,EACxD,OAAO,EAAE,QAAQ;AAAA;AAQlB,eAAsB,4BAA4B,CACjD,IAC0B;AAAA,EAC1B,OAAO,GACL,WAAW,eAAe,EAC1B,UAAU,EACV,MAAM,QAAQ,KAAK,OAAO,EAC1B,MAAM,UAAU,KAAK,QAAQ,EAC7B,QAAQ;AAAA;AAGX,eAAsB,eAAe,CACpC,IACA,WACA,IAC+B;AAAA,EAC/B,IAAI,IAAI,GAAG,WAAW,eAAe,EAAE,UAAU,EAAE,MAAM,MAAM,KAAK,EAAE;AAAA,EACtE,IAAI,eAAe;AAAA,IAAG,IAAI,EAAE,MAAM,cAAc,KAAK,SAAS;AAAA,EAC9D,OAAQ,MAAM,EAAE,iBAAiB,KAAM;AAAA;AAGxC,eAAsB,qBAAqB,CAC1C,IACA,WACA,MAC+B;AAAA,EAC/B,IAAI,IAAI,GAAG,WAAW,eAAe,EAAE,UAAU,EAAE,MAAM,QAAQ,KAAK,IAAI;AAAA,EAC1E,IAAI,eAAe;AAAA,IAAG,IAAI,EAAE,MAAM,cAAc,KAAK,SAAS;AAAA,EAC9D,OAAQ,MAAM,EAAE,iBAAiB,KAAM;AAAA;AAexC,eAAsB,kBAAkB,CACvC,IACA,WACA,IACA,OAC+B;AAAA,EAC/B,MAAM,SAA6B,EAAE,YAAY,IAAI,KAAO;AAAA,EAC5D,IAAI,MAAM,SAAS;AAAA,IAAW,OAAO,OAAO,MAAM;AAAA,EAClD,IAAI,MAAM,WAAW;AAAA,IAAW,OAAO,SAAS,MAAM;AAAA,EACtD,IAAI,MAAM,WAAW;AAAA,IAAW,OAAO,SAAS,MAAM;AAAA,EACtD,IAAI,MAAM,YAAY;AAAA,IAAW,OAAO,UAAU,MAAM;AAAA,EACxD,IAAI,MAAM,QAAQ;AAAA,IAAW,OAAO,MAAM,MAAM;AAAA,EAChD,IAAI,MAAM,eAAe;AAAA,IAAW,OAAO,cAAc,MAAM;AAAA,EAC/D,IAAI,MAAM,eAAe;AAAA,IAAW,OAAO,cAAc,MAAM;AAAA,EAC/D,IAAI,MAAM,cAAc;AAAA,IAAW,OAAO,aAAa,MAAM;AAAA,EAC7D,IAAI,MAAM,gBAAgB;AAAA,IAAW,OAAO,cAAc,MAAM;AAAA,EAEhE,IAAI,IAAI,GAAG,YAAY,eAAe,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,KAAK,EAAE;AAAA,EACvE,IAAI,eAAe;AAAA,IAAG,IAAI,EAAE,MAAM,cAAc,KAAK,SAAS;AAAA,EAC9D,OAAQ,MAAM,EAAE,aAAa,EAAE,iBAAiB,KAAM;AAAA;AAGvD,eAAsB,wBAAwB,CAC7C,IACA,WACA,IACA,QAC+B;AAAA,EAC/B,IAAI,IAAI,GACN,YAAY,eAAe,EAC3B,IAAI;AAAA,IACJ;AAAA,IACA,YAAY,IAAI;AAAA,OACZ,WAAW,WACZ;AAAA,MACA,kBAAkB;AAAA,MAClB,mBAAmB;AAAA,IACpB,IACC,CAAC;AAAA,EACL,CAAC,EACA,MAAM,MAAM,KAAK,EAAE;AAAA,EACrB,IAAI,eAAe;AAAA,IAAG,IAAI,EAAE,MAAM,cAAc,KAAK,SAAS;AAAA,EAC9D,OAAQ,MAAM,EAAE,aAAa,EAAE,iBAAiB,KAAM;AAAA;AAGvD,eAAsB,kBAAkB,CACvC,IACA,WACA,IACmB;AAAA,EACnB,IAAI,IAAI,GAAG,WAAW,eAAe,EAAE,MAAM,MAAM,KAAK,EAAE;AAAA,EAC1D,IAAI,eAAe;AAAA,IAAG,IAAI,EAAE,MAAM,cAAc,KAAK,SAAS;AAAA,EAC9D,MAAM,MAAM,MAAM,EAAE,iBAAiB;AAAA,EACrC,OAAO,OAAO,IAAI,kBAAkB,CAAC,IAAI;AAAA;AAQ1C,eAAsB,wBAAwB,CAC7C,IACA,WACA,IACqC;AAAA,EACrC,MAAM,gBAAgB,eAAe;AAAA,EACrC,IAAI,IAAI,GACN,YAAY,eAAe,EAC3B,IAAI;AAAA,IACJ,oBAAoB,cAAc,aAAa;AAAA,IAC/C,YAAY,IAAI;AAAA,EACjB,CAAC,EACA,MAAM,MAAM,KAAK,EAAE;AAAA,EACrB,IAAI,eAAe;AAAA,IAAG,IAAI,EAAE,MAAM,cAAc,KAAK,SAAS;AAAA,EAC9D,MAAM,MAAM,MAAM,EAAE,aAAa,EAAE,iBAAiB;AAAA,EACpD,IAAI,CAAC;AAAA,IAAK,OAAO;AAAA,EACjB,OAAO,EAAE,cAAc,KAAK,cAAc;AAAA;AAIpC,SAAS,4BAA4B,CAAC,KAA2B;AAAA,EACvE,OAAO,cAAc,IAAI,kBAAkB;AAAA;AAI5C,eAAsB,0BAA0B,CAC/C,IACA,WACgB;AAAA,EAChB,MAAM,gDAAgD,aAAa,QAClE,EACD;AAAA;",
11
+ "debugId": "AC6E9EB29680C9A564756E2164756E21",
12
12
  "names": []
13
13
  }
@@ -1,4 +1,22 @@
1
1
  import { ColumnType, Generated, Insertable, Selectable, Updateable } from "kysely";
2
+ /**
3
+ * Coverage-kernel constraints. SQL CHECKs in migration 0116 must stay
4
+ * identical — property tests treat this file as the spec.
5
+ */
6
+ declare const STAGE_KINDS: readonly ["raw", "decode", "subgraph", "queue"];
7
+ type StageKind = (typeof STAGE_KINDS)[number];
8
+ declare const NATIVE_CLOCKS: readonly ["block", "cursor", "queue"];
9
+ type NativeClock = (typeof NATIVE_CLOCKS)[number];
10
+ declare const REPAIR_MODES: readonly ["range_safe", "full_reindex", "archive_replay", "none"];
11
+ type RepairMode = (typeof REPAIR_MODES)[number];
12
+ declare const RUN_STATUSES: readonly ["pending", "running", "complete", "syncing", "lagging", "gap", "stale", "failed", "unverified_import", "unanchored", "source_unavailable", "out_of_scope", "disabled", "halted"];
13
+ type RunStatus = (typeof RUN_STATUSES)[number];
14
+ declare const FAILURE_UNITS: readonly ["block", "range", "cursor", "queue"];
15
+ type FailureUnit = (typeof FAILURE_UNITS)[number];
16
+ declare const FAILURE_CLASSES: readonly ["omission", "version", "digest_mismatch", "crash", "reorg", "source_gap", "handler", "timeout", "unknown"];
17
+ type FailureClass = (typeof FAILURE_CLASSES)[number];
18
+ declare const RETRY_STATES: readonly ["open", "retrying", "halted", "resolved"];
19
+ type RetryState = (typeof RETRY_STATES)[number];
2
20
  interface BlocksTable {
3
21
  height: number;
4
22
  hash: string;
@@ -190,6 +208,12 @@ interface ApiKeysTable {
190
208
  revoked_at: Date | null;
191
209
  created_at: Generated<Date>;
192
210
  }
211
+ /** Singleton self-host / publisher identity. Network is immutable. */
212
+ interface InstancesTable {
213
+ id: Generated<string>;
214
+ network: string;
215
+ created_at: Generated<Date>;
216
+ }
193
217
  interface AccountsTable {
194
218
  id: Generated<string>;
195
219
  /** NULL for unclaimed ghost accounts (anonymous self-serve keys). */
@@ -720,6 +744,72 @@ interface ObserverJournalTable {
720
744
  error: string | null;
721
745
  processed_at: Date | null;
722
746
  }
747
+ /** Declared coverage stage. Identity is the `id` string (`raw`, `decode:stx`, …). */
748
+ interface StageRegistryTable {
749
+ id: string;
750
+ kind: StageKind;
751
+ depends_on: string | null;
752
+ native_clock: NativeClock;
753
+ producer_version: string;
754
+ repair_mode: RepairMode;
755
+ enabled: Generated<boolean>;
756
+ created_at: Generated<Date>;
757
+ }
758
+ /** One versioned sweep of a stage. */
759
+ interface StageRunsTable {
760
+ id: Generated<string>;
761
+ stage_id: string;
762
+ code_hash: string;
763
+ config_hash: string;
764
+ handler_hash: string | null;
765
+ target_height: number | null;
766
+ target_cursor: string | null;
767
+ status: RunStatus;
768
+ complete_through: number | null;
769
+ started_at: Generated<Date>;
770
+ finished_at: Date | null;
771
+ }
772
+ /** Per-block acknowledgement. Unique on (stage, height, hash). */
773
+ interface StageBlockReceiptsTable {
774
+ id: Generated<string>;
775
+ stage_id: string;
776
+ run_id: string | null;
777
+ block_height: number;
778
+ block_hash: string;
779
+ input_count: number;
780
+ input_digest: string;
781
+ effect_digest: string;
782
+ finalized: Generated<boolean>;
783
+ compacted_at: Date | null;
784
+ created_at: Generated<Date>;
785
+ }
786
+ /** Compacted finalized range. Only sealed after receipts in the range finalize. */
787
+ interface CoverageSegmentsTable {
788
+ id: Generated<string>;
789
+ stage_id: string;
790
+ from_height: number;
791
+ to_height: number;
792
+ chain_digest: string;
793
+ input_digest: string;
794
+ output_digest: string;
795
+ sealed_at: Generated<Date>;
796
+ }
797
+ /** Exact unit or range that failed, plus retry/retention state. */
798
+ interface StageFailuresTable {
799
+ id: Generated<string>;
800
+ stage_id: string;
801
+ run_id: string | null;
802
+ unit_kind: FailureUnit;
803
+ from_height: number | null;
804
+ to_height: number | null;
805
+ class: FailureClass;
806
+ retry_state: RetryState;
807
+ retry_count: Generated<number>;
808
+ last_error: string | null;
809
+ created_at: Generated<Date>;
810
+ resolved_at: Date | null;
811
+ retain_until: Generated<Date>;
812
+ }
723
813
  interface Database {
724
814
  blocks: BlocksTable;
725
815
  transactions: TransactionsTable;
@@ -732,6 +822,7 @@ interface Database {
732
822
  contracts: ContractsTable;
733
823
  subgraphs: SubgraphsTable;
734
824
  api_keys: ApiKeysTable;
825
+ instances: InstancesTable;
735
826
  accounts: AccountsTable;
736
827
  sessions: SessionsTable;
737
828
  magic_links: MagicLinksTable;
@@ -784,6 +875,11 @@ interface Database {
784
875
  chain_read_cache: ChainReadCacheTable;
785
876
  pending_fork_blocks: PendingForkBlocksTable;
786
877
  observer_journal: ObserverJournalTable;
878
+ stage_registry: StageRegistryTable;
879
+ stage_runs: StageRunsTable;
880
+ stage_block_receipts: StageBlockReceiptsTable;
881
+ coverage_segments: CoverageSegmentsTable;
882
+ stage_failures: StageFailuresTable;
787
883
  }
788
884
  /** Prepaid x402 credit — one running USD-micros balance per payer principal. */
789
885
  interface X402BalancesTable {
@@ -1076,4 +1172,4 @@ interface TriggerEvaluatorStateTable {
1076
1172
  updated_at: Generated<Date>;
1077
1173
  }
1078
1174
  type TriggerEvaluatorState = Selectable<TriggerEvaluatorStateTable>;
1079
- export { X402PaymentsTable, X402BalancesTable, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateTenantUsageMonthly, UpdateTenantComputeAddon, UpdateTenant, UpdateSubscriptionOutbox, UpdateSubscription, UpdateSubgraphOperation, UpdateSubgraph, UpdateProject, UpdateIndexProgress, UpdateEvent, UpdateContract, UpdateBlock, UpdateApiKey, UpdateAccountSpendCap, UpdateAccountCredits, TriggerEvaluatorStateTable, TriggerEvaluatorState, TransactionsTable, TransactionsArchiveTable, Transaction, TenantsTable, TenantUsageMonthlyTable, TenantUsageMonthly, TenantStatus, TenantComputeAddonsTable, TenantComputeAddon, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, SubscriptionsTable, SubscriptionStatus, SubscriptionRuntime, SubscriptionOutboxTable, SubscriptionOutbox, SubscriptionKind, SubscriptionFormat, SubscriptionDelivery, SubscriptionDeliveriesTable, Subscription, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphProcessingStatsTable, SubgraphOperationsTable, SubgraphOperationStatus, SubgraphOperationKind, SubgraphOperation, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGap, Subgraph, SessionsTable, Session, ServiceHeartbeatsTable, SbtcTokenEventsTable, SbtcTokenEventType, SbtcSupplySnapshotsTable, SbtcSettlementsTable, SbtcEventsTable, SbtcEventTopic, ProvisioningAuditStatus, ProvisioningAuditLogTable, ProvisioningAuditLog, ProvisioningAuditEvent, ProjectsTable, Project, ProcessedStripeEventsTable, Pox5EventsTable, Pox5EventTopic, Pox4SignersDailyTable, Pox4FunctionName, Pox4CyclesDailyTable, Pox4CallsTable, PendingForkBlocksTable, OutboxStatus, ObserverJournalTable, ObserverJournalStatus, MempoolTransactionsTable, MempoolTransaction, MagicLinksTable, MagicLink, InsertTransaction, InsertTenantUsageMonthly, InsertTenantComputeAddon, InsertTenant, InsertTeamMember, InsertTeamInvitation, InsertSubscriptionOutbox, InsertSubscriptionDelivery, InsertSubscription, InsertSubgraphUsageDaily, InsertSubgraphOperation, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProvisioningAuditLog, InsertProject, InsertMempoolTransaction, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertContract, InsertClaimToken, InsertBlock, InsertApiKey, InsertAccountSpendCap, InsertAccountInsight, InsertAccountCredits, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, EventsTable, EventsArchiveTable, Event, DecoderCheckpointsTable, DecodedEventsTable, DeadLetterEventsTable, Database, ContractsTable, Contract, ClaimTokensTable, ClaimToken, ChainReorgsTable, ChainReadCacheTable, BurnBlockRewardsTable, BurnBlockRewardSlotsTable, BnsNamespacesTable, BnsNamespaceEventsTable, BnsNamespaceEventStatus, BnsNamesTable, BnsNameEventsTable, BnsNameEventTopic, BnsMarketplaceEventsTable, BnsMarketplaceAction, BlocksTable, Block, ApiKeysTable, ApiKey, AccountsTable, AccountSpendCapsTable, AccountSpendCap, AccountInsightsTable, AccountInsight, AccountCreditsTable, AccountCredits, AccountAgentRunsTable, AccountAgentRun, Account };
1175
+ export { X402PaymentsTable, X402BalancesTable, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateTransaction, UpdateTenantUsageMonthly, UpdateTenantComputeAddon, UpdateTenant, UpdateSubscriptionOutbox, UpdateSubscription, UpdateSubgraphOperation, UpdateSubgraph, UpdateProject, UpdateIndexProgress, UpdateEvent, UpdateContract, UpdateBlock, UpdateApiKey, UpdateAccountSpendCap, UpdateAccountCredits, TriggerEvaluatorStateTable, TriggerEvaluatorState, TransactionsTable, TransactionsArchiveTable, Transaction, TenantsTable, TenantUsageMonthlyTable, TenantUsageMonthly, TenantStatus, TenantComputeAddonsTable, TenantComputeAddon, Tenant, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, SubscriptionsTable, SubscriptionStatus, SubscriptionRuntime, SubscriptionOutboxTable, SubscriptionOutbox, SubscriptionKind, SubscriptionFormat, SubscriptionDelivery, SubscriptionDeliveriesTable, Subscription, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphProcessingStatsTable, SubgraphOperationsTable, SubgraphOperationStatus, SubgraphOperationKind, SubgraphOperation, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGap, Subgraph, StageRunsTable, StageRegistryTable, StageKind, StageFailuresTable, StageBlockReceiptsTable, SessionsTable, Session, ServiceHeartbeatsTable, SbtcTokenEventsTable, SbtcTokenEventType, SbtcSupplySnapshotsTable, SbtcSettlementsTable, SbtcEventsTable, SbtcEventTopic, RunStatus, RetryState, RepairMode, ProvisioningAuditStatus, ProvisioningAuditLogTable, ProvisioningAuditLog, ProvisioningAuditEvent, ProjectsTable, Project, ProcessedStripeEventsTable, Pox5EventsTable, Pox5EventTopic, Pox4SignersDailyTable, Pox4FunctionName, Pox4CyclesDailyTable, Pox4CallsTable, PendingForkBlocksTable, OutboxStatus, ObserverJournalTable, ObserverJournalStatus, NativeClock, MempoolTransactionsTable, MempoolTransaction, MagicLinksTable, MagicLink, InstancesTable, InsertTransaction, InsertTenantUsageMonthly, InsertTenantComputeAddon, InsertTenant, InsertTeamMember, InsertTeamInvitation, InsertSubscriptionOutbox, InsertSubscriptionDelivery, InsertSubscription, InsertSubgraphUsageDaily, InsertSubgraphOperation, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProvisioningAuditLog, InsertProject, InsertMempoolTransaction, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertContract, InsertClaimToken, InsertBlock, InsertApiKey, InsertAccountSpendCap, InsertAccountInsight, InsertAccountCredits, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, FailureUnit, FailureClass, EventsTable, EventsArchiveTable, Event, DecoderCheckpointsTable, DecodedEventsTable, DeadLetterEventsTable, Database, CoverageSegmentsTable, ContractsTable, Contract, ClaimTokensTable, ClaimToken, ChainReorgsTable, ChainReadCacheTable, BurnBlockRewardsTable, BurnBlockRewardSlotsTable, BnsNamespacesTable, BnsNamespaceEventsTable, BnsNamespaceEventStatus, BnsNamesTable, BnsNameEventsTable, BnsNameEventTopic, BnsMarketplaceEventsTable, BnsMarketplaceAction, BlocksTable, Block, ApiKeysTable, ApiKey, AccountsTable, AccountSpendCapsTable, AccountSpendCap, AccountInsightsTable, AccountInsight, AccountCreditsTable, AccountCredits, AccountAgentRunsTable, AccountAgentRun, Account };