@secondlayer/shared 7.11.2 → 9.0.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 (60) hide show
  1. package/dist/src/archive/range-digest.d.ts +16 -169
  2. package/dist/src/archive/semantic-digest-builder.d.ts +16 -169
  3. package/dist/src/archive/status.js +11 -3
  4. package/dist/src/archive/status.js.map +3 -3
  5. package/dist/src/coverage/index.d.ts +15 -169
  6. package/dist/src/crypto/secrets.js +22 -3
  7. package/dist/src/crypto/secrets.js.map +3 -3
  8. package/dist/src/db/index.d.ts +18 -211
  9. package/dist/src/db/index.js +23 -16
  10. package/dist/src/db/index.js.map +4 -4
  11. package/dist/src/db/queries/chain-reorgs.d.ts +16 -169
  12. package/dist/src/db/queries/chain-reorgs.js +23 -16
  13. package/dist/src/db/queries/chain-reorgs.js.map +4 -4
  14. package/dist/src/db/queries/contracts.d.ts +16 -169
  15. package/dist/src/db/queries/instance.d.ts +16 -169
  16. package/dist/src/db/queries/integrity.d.ts +16 -169
  17. package/dist/src/db/queries/subgraph-gaps.d.ts +16 -169
  18. package/dist/src/db/queries/subgraph-operations.d.ts +17 -170
  19. package/dist/src/db/queries/subgraph-operations.js +1 -15
  20. package/dist/src/db/queries/subgraph-operations.js.map +3 -3
  21. package/dist/src/db/queries/subgraphs.d.ts +17 -191
  22. package/dist/src/db/queries/subgraphs.js +30 -1068
  23. package/dist/src/db/queries/subgraphs.js.map +5 -12
  24. package/dist/src/db/queries/subscriptions.d.ts +16 -169
  25. package/dist/src/db/queries/subscriptions.js +22 -3
  26. package/dist/src/db/queries/subscriptions.js.map +3 -3
  27. package/dist/src/db/queries/sync-scope.d.ts +1006 -0
  28. package/dist/src/db/queries/sync-scope.js +116 -0
  29. package/dist/src/db/queries/sync-scope.js.map +10 -0
  30. package/dist/src/db/schema.d.ts +17 -198
  31. package/dist/src/errors.d.ts +1 -22
  32. package/dist/src/errors.js +2 -4
  33. package/dist/src/errors.js.map +3 -3
  34. package/dist/src/index.d.ts +22 -256
  35. package/dist/src/index.js +24 -20
  36. package/dist/src/index.js.map +6 -6
  37. package/dist/src/mode.d.ts +16 -2
  38. package/dist/src/mode.js +25 -4
  39. package/dist/src/mode.js.map +3 -3
  40. package/dist/src/node/local-client.d.ts +16 -169
  41. package/dist/src/runtime/index.d.ts +137 -18
  42. package/dist/src/runtime/index.js +261 -41
  43. package/dist/src/runtime/index.js.map +9 -7
  44. package/dist/src/schemas/index.d.ts +5 -25
  45. package/dist/src/schemas/index.js +1 -2
  46. package/dist/src/schemas/index.js.map +3 -3
  47. package/dist/src/schemas/subgraphs.d.ts +5 -25
  48. package/dist/src/schemas/subgraphs.js +1 -2
  49. package/dist/src/schemas/subgraphs.js.map +3 -3
  50. package/dist/src/streams-rows/index.d.ts +399 -0
  51. package/dist/src/streams-rows/index.js +336 -0
  52. package/dist/src/streams-rows/index.js.map +17 -0
  53. package/dist/src/subgraphs/spec.d.ts +0 -9
  54. package/migrations/0118_drop_retired_control_tables.ts +53 -0
  55. package/migrations/0119_drop_accounts_plan.ts +29 -0
  56. package/migrations/0120_sync_scopes.ts +42 -0
  57. package/package.json +10 -6
  58. package/dist/src/x402.d.ts +0 -47
  59. package/dist/src/x402.js +0 -79
  60. package/dist/src/x402.js.map +0 -10
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/db/queries/subgraph-operations.ts"],
4
4
  "sourcesContent": [
5
- "import { type Kysely, sql } from \"kysely\";\nimport type {\n\tDatabase,\n\tSubgraphOperation,\n\tSubgraphOperationKind,\n\tSubgraphOperationStatus,\n} from \"../types.ts\";\n\nconst ACTIVE_STATUSES: SubgraphOperationStatus[] = [\"queued\", \"running\"];\n\nexport function isActiveSubgraphOperationConflict(err: unknown): boolean {\n\tif (!(err instanceof Error)) return false;\n\tconst candidate = err as Error & {\n\t\tcode?: string;\n\t\tconstraint?: string;\n\t\tconstraint_name?: string;\n\t};\n\treturn (\n\t\tcandidate.code === \"23505\" &&\n\t\t(candidate.constraint === \"subgraph_operations_active_unique\" ||\n\t\t\tcandidate.constraint_name === \"subgraph_operations_active_unique\")\n\t);\n}\n\nexport async function createSubgraphOperation(\n\tdb: Kysely<Database>,\n\tdata: {\n\t\tsubgraphId: string;\n\t\tsubgraphName: string;\n\t\taccountId?: string | null;\n\t\tkind: SubgraphOperationKind;\n\t\tfromBlock?: number;\n\t\ttoBlock?: number;\n\t\t/** 'light' | 'heavy' — claim budgets heavy ops. DB default 'heavy'. */\n\t\tweight?: \"light\" | \"heavy\";\n\t\testimatedEvents?: number | null;\n\t},\n): Promise<SubgraphOperation> {\n\t// Requeued backfills inherit the committed prefix of prior attempts over an\n\t// overlapping range — cancel/fail + requeue can't replay applied deltas.\n\tlet seededCursor: string | number | bigint | null = null;\n\tif (\n\t\tdata.kind === \"backfill\" &&\n\t\tdata.fromBlock != null &&\n\t\tdata.toBlock != null\n\t) {\n\t\tconst prior = await db\n\t\t\t.selectFrom(\"subgraph_operations\")\n\t\t\t.select((eb) => eb.fn.max(\"cursor_block\").as(\"max_cursor\"))\n\t\t\t.where(\"subgraph_id\", \"=\", data.subgraphId)\n\t\t\t.where(\"kind\", \"=\", \"backfill\")\n\t\t\t.where(\"status\", \"in\", [\"failed\", \"cancelled\"])\n\t\t\t.where(\"from_block\", \"<=\", data.toBlock)\n\t\t\t.where(\"to_block\", \">=\", data.fromBlock)\n\t\t\t.executeTakeFirst();\n\t\tseededCursor = prior?.max_cursor ?? null;\n\t}\n\treturn await db\n\t\t.insertInto(\"subgraph_operations\")\n\t\t.values({\n\t\t\tsubgraph_id: data.subgraphId,\n\t\t\tsubgraph_name: data.subgraphName,\n\t\t\taccount_id: data.accountId ?? null,\n\t\t\tkind: data.kind,\n\t\t\tfrom_block: data.fromBlock ?? null,\n\t\t\tto_block: data.toBlock ?? null,\n\t\t\t...(data.weight ? { weight: data.weight } : {}),\n\t\t\testimated_events: data.estimatedEvents ?? null,\n\t\t\tcursor_block: seededCursor,\n\t\t})\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n}\n\nexport async function findActiveSubgraphOperation(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n): Promise<SubgraphOperation | null> {\n\treturn (\n\t\t(await db\n\t\t\t.selectFrom(\"subgraph_operations\")\n\t\t\t.selectAll()\n\t\t\t.where(\"subgraph_id\", \"=\", subgraphId)\n\t\t\t.where(\"status\", \"in\", ACTIVE_STATUSES)\n\t\t\t.orderBy(\"created_at\", \"asc\")\n\t\t\t.executeTakeFirst()) ?? null\n\t);\n}\n\nexport async function requestSubgraphOperationCancel(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n): Promise<SubgraphOperation | null> {\n\treturn (\n\t\t(await db\n\t\t\t.updateTable(\"subgraph_operations\")\n\t\t\t.set({ cancel_requested: true, updated_at: new Date() })\n\t\t\t.where(\"subgraph_id\", \"=\", subgraphId)\n\t\t\t.where(\"status\", \"in\", ACTIVE_STATUSES)\n\t\t\t.returningAll()\n\t\t\t.executeTakeFirst()) ?? null\n\t);\n}\n\nexport async function requestSubgraphOperationsCancelForDelete(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n): Promise<SubgraphOperation[]> {\n\treturn await db\n\t\t.updateTable(\"subgraph_operations\")\n\t\t.set({ cancel_requested: true, updated_at: new Date() })\n\t\t.where(\"subgraph_id\", \"=\", subgraphId)\n\t\t.where(\"status\", \"in\", ACTIVE_STATUSES)\n\t\t.returningAll()\n\t\t.execute();\n}\n\n/**\n * Poll until no active subgraph operations remain for the subgraph or until\n * `timeoutMs` elapses. Returns true if all active operations cleared, false\n * if we timed out. Callers should use this before `DROP SCHEMA` so the active\n * processor has a chance to observe `cancel_requested` and release its row /\n * advisory locks. Without this, the DROP blocks behind the live transaction\n * and the API socket times out before the lock releases.\n */\nexport async function waitForSubgraphOperationsClear(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n\topts?: { timeoutMs?: number; pollMs?: number },\n): Promise<boolean> {\n\tconst timeoutMs = opts?.timeoutMs ?? 30_000;\n\tconst pollMs = opts?.pollMs ?? 500;\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() < deadline) {\n\t\tconst active = await db\n\t\t\t.selectFrom(\"subgraph_operations\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"subgraph_id\", \"=\", subgraphId)\n\t\t\t.where(\"status\", \"in\", ACTIVE_STATUSES)\n\t\t\t.limit(1)\n\t\t\t.executeTakeFirst();\n\t\tif (!active) return true;\n\t\tawait new Promise((r) => setTimeout(r, pollMs));\n\t}\n\treturn false;\n}\n\n/** Max concurrently-running 'heavy' ops (broad/non-sparse syncs). */\nfunction resolveHeavyOpBudget(): number {\n\tconst parsed = Number.parseInt(\n\t\tprocess.env.SUBGRAPH_HEAVY_OP_BUDGET ?? \"2\",\n\t\t10,\n\t);\n\treturn Number.isFinite(parsed) && parsed > 0 ? parsed : 2;\n}\n\nexport async function claimSubgraphOperation(\n\tdb: Kysely<Database>,\n\tlockedBy: string,\n): Promise<SubgraphOperation | null> {\n\t// Fair queue: accounts with fewer currently-running operations are served first,\n\t// breaking ties by creation time. Prevents one user's long reindex from\n\t// starving other accounts when SUBGRAPH_OPERATION_CONCURRENCY > 1.\n\tconst heavyBudget = resolveHeavyOpBudget();\n\tconst result = await sql<SubgraphOperation>`\n\t\tUPDATE subgraph_operations\n\t\tSET\n\t\t\tstatus = 'running',\n\t\t\tlocked_by = ${lockedBy},\n\t\t\tlocked_until = now() + interval '60 seconds',\n\t\t\tstarted_at = COALESCE(started_at, now()),\n\t\t\tupdated_at = now()\n\t\tWHERE id = (\n\t\t\tSELECT so.id\n\t\t\tFROM subgraph_operations so\n\t\t\tLEFT JOIN (\n\t\t\t\tSELECT account_id, COUNT(*) AS cnt\n\t\t\t\tFROM subgraph_operations\n\t\t\t\tWHERE status = 'running'\n\t\t\t\tGROUP BY account_id\n\t\t\t) rc ON so.account_id = rc.account_id\n\t\t\tLEFT JOIN accounts a ON a.id::text = so.account_id\n\t\t\tWHERE\n\t\t\t\t(\n\t\t\t\t\tso.status = 'queued'\n\t\t\t\t\tOR (\n\t\t\t\t\t\tso.status = 'running'\n\t\t\t\t\t\tAND (so.locked_until IS NULL OR so.locked_until < now())\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t\t-- Heavy budget as an eligibility FILTER (not a post-claim refusal):\n\t\t\t\t-- a budget-blocked heavy op at the head must not starve the light\n\t\t\t\t-- ops behind it. Live-lock condition (locked_until > now()) keeps a\n\t\t\t\t-- STALE heavy op from blocking its own reclaim. Soft across\n\t\t\t\t-- concurrent claimers (can overshoot by one with multiple runners) —\n\t\t\t\t-- acceptable for the single-runner deployment.\n\t\t\t\tAND (\n\t\t\t\t\tso.weight = 'light'\n\t\t\t\t\tOR (\n\t\t\t\t\t\tSELECT COUNT(*)\n\t\t\t\t\t\tFROM subgraph_operations h\n\t\t\t\t\t\tWHERE h.status = 'running'\n\t\t\t\t\t\t\tAND h.weight = 'heavy'\n\t\t\t\t\t\t\tAND h.locked_until > now()\n\t\t\t\t\t\t\tAND h.id != so.id\n\t\t\t\t\t) < ${heavyBudget}\n\t\t\t\t)\n\t\t\tORDER BY\n\t\t\t\tCOALESCE(rc.cnt, 0) ASC,\n\t\t\t\tCASE COALESCE(a.plan, 'none')\n\t\t\t\t\tWHEN 'enterprise' THEN 0\n\t\t\t\t\tWHEN 'scale' THEN 1\n\t\t\t\t\tWHEN 'launch' THEN 2\n\t\t\t\t\tELSE 3\n\t\t\t\tEND,\n\t\t\t\tCASE WHEN so.status = 'queued' THEN 0 ELSE 1 END,\n\t\t\t\tso.created_at ASC\n\t\t\tFOR UPDATE OF so SKIP LOCKED\n\t\t\tLIMIT 1\n\t\t)\n\t\tRETURNING *\n\t`.execute(db);\n\treturn result.rows[0] ?? null;\n}\n\nexport async function heartbeatSubgraphOperation(\n\tdb: Kysely<Database>,\n\toperationId: string,\n\tlockedBy: string,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraph_operations\")\n\t\t.set({\n\t\t\tlocked_until: sql<Date>`now() + interval '60 seconds'`,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"id\", \"=\", operationId)\n\t\t.where(\"status\", \"=\", \"running\")\n\t\t.where(\"locked_by\", \"=\", lockedBy)\n\t\t.execute();\n}\n\nexport async function getSubgraphOperation(\n\tdb: Kysely<Database>,\n\toperationId: string,\n): Promise<SubgraphOperation | null> {\n\treturn (\n\t\t(await db\n\t\t\t.selectFrom(\"subgraph_operations\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"=\", operationId)\n\t\t\t.executeTakeFirst()) ?? null\n\t);\n}\n\n/** Recent operations for a subgraph, newest first (for the status read API). */\nexport async function listSubgraphOperations(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n\tlimit = 20,\n): Promise<SubgraphOperation[]> {\n\treturn db\n\t\t.selectFrom(\"subgraph_operations\")\n\t\t.selectAll()\n\t\t.where(\"subgraph_id\", \"=\", subgraphId)\n\t\t.orderBy(\"created_at\", \"desc\")\n\t\t.limit(limit)\n\t\t.execute();\n}\n\nexport async function completeSubgraphOperation(\n\tdb: Kysely<Database>,\n\toperationId: string,\n\tlockedBy: string,\n\tprocessedBlocks: number,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraph_operations\")\n\t\t.set({\n\t\t\tstatus: \"completed\",\n\t\t\tfinished_at: new Date(),\n\t\t\tprocessed_blocks: processedBlocks,\n\t\t\tlocked_by: null,\n\t\t\tlocked_until: null,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"id\", \"=\", operationId)\n\t\t.where(\"locked_by\", \"=\", lockedBy)\n\t\t.execute();\n}\n\nexport async function cancelSubgraphOperation(\n\tdb: Kysely<Database>,\n\toperationId: string,\n\tlockedBy: string,\n\tprocessedBlocks: number,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraph_operations\")\n\t\t.set({\n\t\t\tstatus: \"cancelled\",\n\t\t\tfinished_at: new Date(),\n\t\t\tprocessed_blocks: processedBlocks,\n\t\t\tlocked_by: null,\n\t\t\tlocked_until: null,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"id\", \"=\", operationId)\n\t\t.where(\"locked_by\", \"=\", lockedBy)\n\t\t.execute();\n}\n\nexport async function failSubgraphOperation(\n\tdb: Kysely<Database>,\n\toperationId: string,\n\tlockedBy: string,\n\terror: string,\n\tprocessedBlocks?: number,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraph_operations\")\n\t\t.set({\n\t\t\tstatus: \"failed\",\n\t\t\tfinished_at: new Date(),\n\t\t\tprocessed_blocks: processedBlocks ?? null,\n\t\t\terror,\n\t\t\tlocked_by: null,\n\t\t\tlocked_until: null,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"id\", \"=\", operationId)\n\t\t.where(\"locked_by\", \"=\", lockedBy)\n\t\t.execute();\n}\n\n/**\n * 1-based position of a queued operation under the claim ordering (fairness →\n * plan rank → queued-first → FIFO). The heavy-budget admission filter is NOT\n * applied — a heavy op's eligibility depends on runtime budget state — so the\n * position is approximate; render it as \"~N\". Returns null unless queued.\n */\nexport async function getOperationQueuePosition(\n\tdb: Kysely<Database>,\n\toperationId: string,\n): Promise<number | null> {\n\tconst result = await sql<{ rn: string | number }>`\n\t\tWITH candidates AS (\n\t\t\tSELECT\n\t\t\t\tso.id,\n\t\t\t\tROW_NUMBER() OVER (\n\t\t\t\t\tORDER BY\n\t\t\t\t\t\tCOALESCE(rc.cnt, 0) ASC,\n\t\t\t\t\t\tCASE COALESCE(a.plan, 'none')\n\t\t\t\t\t\t\tWHEN 'enterprise' THEN 0\n\t\t\t\t\t\t\tWHEN 'scale' THEN 1\n\t\t\t\t\t\t\tWHEN 'launch' THEN 2\n\t\t\t\t\t\t\tELSE 3\n\t\t\t\t\t\tEND,\n\t\t\t\t\t\tCASE WHEN so.status = 'queued' THEN 0 ELSE 1 END,\n\t\t\t\t\t\tso.created_at ASC\n\t\t\t\t) AS rn\n\t\t\tFROM subgraph_operations so\n\t\t\tLEFT JOIN (\n\t\t\t\tSELECT account_id, COUNT(*) AS cnt\n\t\t\t\tFROM subgraph_operations\n\t\t\t\tWHERE status = 'running'\n\t\t\t\tGROUP BY account_id\n\t\t\t) rc ON so.account_id = rc.account_id\n\t\t\tLEFT JOIN accounts a ON a.id::text = so.account_id\n\t\t\tWHERE so.status = 'queued'\n\t\t)\n\t\tSELECT rn FROM candidates WHERE id = ${operationId}\n\t`.execute(db);\n\tconst rn = result.rows[0]?.rn;\n\treturn rn == null ? null : Number(rn);\n}\n\n/** Median duration (seconds) of the last 20 completed ops of a weight class —\n * the \"est. start\" multiplier for queued positions. Null with no history. */\nexport async function getRecentOperationMedianDuration(\n\tdb: Kysely<Database>,\n\tweight: \"light\" | \"heavy\",\n): Promise<number | null> {\n\tconst result = await sql<{ median: string | number | null }>`\n\t\tSELECT percentile_cont(0.5) WITHIN GROUP (\n\t\t\tORDER BY EXTRACT(EPOCH FROM (finished_at - started_at))\n\t\t) AS median\n\t\tFROM (\n\t\t\tSELECT started_at, finished_at\n\t\t\tFROM subgraph_operations\n\t\t\tWHERE status = 'completed'\n\t\t\t\tAND weight = ${weight}\n\t\t\t\tAND started_at IS NOT NULL\n\t\t\t\tAND finished_at IS NOT NULL\n\t\t\tORDER BY finished_at DESC\n\t\t\tLIMIT 20\n\t\t) recent\n\t`.execute(db);\n\tconst median = result.rows[0]?.median;\n\treturn median == null ? null : Number(median);\n}\n\n/** Progress-flush hook: events processed so far on a running operation. */\nexport async function updateOperationProcessedEvents(\n\tdb: Kysely<Database>,\n\toperationId: string,\n\tprocessedEvents: number,\n): Promise<void> {\n\t// Monotonic: a crash-resumed run restarts its in-memory counter from 0 —\n\t// never let that regress the op's ETA surfaces.\n\tawait db\n\t\t.updateTable(\"subgraph_operations\")\n\t\t.set({\n\t\t\tprocessed_events: sql`GREATEST(COALESCE(processed_events, 0), ${processedEvents})`,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"id\", \"=\", operationId)\n\t\t.execute();\n}\n\n/**\n * Conditionally advance a backfill operation's crash checkpoint. Monotonic by\n * construction: the WHERE clause makes concurrent writers serialize — exactly\n * one advance wins per height, regardless of lease/zombie timing. Returns\n * whether THIS caller advanced (false = a racing writer already covered h).\n */\nexport async function advanceOperationCursor(\n\tdb: Kysely<Database>,\n\toperationId: string,\n\theight: number,\n): Promise<boolean> {\n\tconst result = await db\n\t\t.updateTable(\"subgraph_operations\")\n\t\t.set({ cursor_block: height, updated_at: new Date() })\n\t\t.where(\"id\", \"=\", operationId)\n\t\t.where((eb) =>\n\t\t\teb.or([\n\t\t\t\teb(\"cursor_block\", \"is\", null),\n\t\t\t\teb(\"cursor_block\", \"<\", String(height)),\n\t\t\t]),\n\t\t)\n\t\t.executeTakeFirst();\n\treturn Number(result.numUpdatedRows ?? 0n) > 0;\n}\n"
5
+ "import { type Kysely, sql } from \"kysely\";\nimport type {\n\tDatabase,\n\tSubgraphOperation,\n\tSubgraphOperationKind,\n\tSubgraphOperationStatus,\n} from \"../types.ts\";\n\nconst ACTIVE_STATUSES: SubgraphOperationStatus[] = [\"queued\", \"running\"];\n\nexport function isActiveSubgraphOperationConflict(err: unknown): boolean {\n\tif (!(err instanceof Error)) return false;\n\tconst candidate = err as Error & {\n\t\tcode?: string;\n\t\tconstraint?: string;\n\t\tconstraint_name?: string;\n\t};\n\treturn (\n\t\tcandidate.code === \"23505\" &&\n\t\t(candidate.constraint === \"subgraph_operations_active_unique\" ||\n\t\t\tcandidate.constraint_name === \"subgraph_operations_active_unique\")\n\t);\n}\n\nexport async function createSubgraphOperation(\n\tdb: Kysely<Database>,\n\tdata: {\n\t\tsubgraphId: string;\n\t\tsubgraphName: string;\n\t\taccountId?: string | null;\n\t\tkind: SubgraphOperationKind;\n\t\tfromBlock?: number;\n\t\ttoBlock?: number;\n\t\t/** 'light' | 'heavy' — claim budgets heavy ops. DB default 'heavy'. */\n\t\tweight?: \"light\" | \"heavy\";\n\t\testimatedEvents?: number | null;\n\t},\n): Promise<SubgraphOperation> {\n\t// Requeued backfills inherit the committed prefix of prior attempts over an\n\t// overlapping range — cancel/fail + requeue can't replay applied deltas.\n\tlet seededCursor: string | number | bigint | null = null;\n\tif (\n\t\tdata.kind === \"backfill\" &&\n\t\tdata.fromBlock != null &&\n\t\tdata.toBlock != null\n\t) {\n\t\tconst prior = await db\n\t\t\t.selectFrom(\"subgraph_operations\")\n\t\t\t.select((eb) => eb.fn.max(\"cursor_block\").as(\"max_cursor\"))\n\t\t\t.where(\"subgraph_id\", \"=\", data.subgraphId)\n\t\t\t.where(\"kind\", \"=\", \"backfill\")\n\t\t\t.where(\"status\", \"in\", [\"failed\", \"cancelled\"])\n\t\t\t.where(\"from_block\", \"<=\", data.toBlock)\n\t\t\t.where(\"to_block\", \">=\", data.fromBlock)\n\t\t\t.executeTakeFirst();\n\t\tseededCursor = prior?.max_cursor ?? null;\n\t}\n\treturn await db\n\t\t.insertInto(\"subgraph_operations\")\n\t\t.values({\n\t\t\tsubgraph_id: data.subgraphId,\n\t\t\tsubgraph_name: data.subgraphName,\n\t\t\taccount_id: data.accountId ?? null,\n\t\t\tkind: data.kind,\n\t\t\tfrom_block: data.fromBlock ?? null,\n\t\t\tto_block: data.toBlock ?? null,\n\t\t\t...(data.weight ? { weight: data.weight } : {}),\n\t\t\testimated_events: data.estimatedEvents ?? null,\n\t\t\tcursor_block: seededCursor,\n\t\t})\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n}\n\nexport async function findActiveSubgraphOperation(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n): Promise<SubgraphOperation | null> {\n\treturn (\n\t\t(await db\n\t\t\t.selectFrom(\"subgraph_operations\")\n\t\t\t.selectAll()\n\t\t\t.where(\"subgraph_id\", \"=\", subgraphId)\n\t\t\t.where(\"status\", \"in\", ACTIVE_STATUSES)\n\t\t\t.orderBy(\"created_at\", \"asc\")\n\t\t\t.executeTakeFirst()) ?? null\n\t);\n}\n\nexport async function requestSubgraphOperationCancel(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n): Promise<SubgraphOperation | null> {\n\treturn (\n\t\t(await db\n\t\t\t.updateTable(\"subgraph_operations\")\n\t\t\t.set({ cancel_requested: true, updated_at: new Date() })\n\t\t\t.where(\"subgraph_id\", \"=\", subgraphId)\n\t\t\t.where(\"status\", \"in\", ACTIVE_STATUSES)\n\t\t\t.returningAll()\n\t\t\t.executeTakeFirst()) ?? null\n\t);\n}\n\nexport async function requestSubgraphOperationsCancelForDelete(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n): Promise<SubgraphOperation[]> {\n\treturn await db\n\t\t.updateTable(\"subgraph_operations\")\n\t\t.set({ cancel_requested: true, updated_at: new Date() })\n\t\t.where(\"subgraph_id\", \"=\", subgraphId)\n\t\t.where(\"status\", \"in\", ACTIVE_STATUSES)\n\t\t.returningAll()\n\t\t.execute();\n}\n\n/**\n * Poll until no active subgraph operations remain for the subgraph or until\n * `timeoutMs` elapses. Returns true if all active operations cleared, false\n * if we timed out. Callers should use this before `DROP SCHEMA` so the active\n * processor has a chance to observe `cancel_requested` and release its row /\n * advisory locks. Without this, the DROP blocks behind the live transaction\n * and the API socket times out before the lock releases.\n */\nexport async function waitForSubgraphOperationsClear(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n\topts?: { timeoutMs?: number; pollMs?: number },\n): Promise<boolean> {\n\tconst timeoutMs = opts?.timeoutMs ?? 30_000;\n\tconst pollMs = opts?.pollMs ?? 500;\n\tconst deadline = Date.now() + timeoutMs;\n\twhile (Date.now() < deadline) {\n\t\tconst active = await db\n\t\t\t.selectFrom(\"subgraph_operations\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"subgraph_id\", \"=\", subgraphId)\n\t\t\t.where(\"status\", \"in\", ACTIVE_STATUSES)\n\t\t\t.limit(1)\n\t\t\t.executeTakeFirst();\n\t\tif (!active) return true;\n\t\tawait new Promise((r) => setTimeout(r, pollMs));\n\t}\n\treturn false;\n}\n\n/** Max concurrently-running 'heavy' ops (broad/non-sparse syncs). */\nfunction resolveHeavyOpBudget(): number {\n\tconst parsed = Number.parseInt(\n\t\tprocess.env.SUBGRAPH_HEAVY_OP_BUDGET ?? \"2\",\n\t\t10,\n\t);\n\treturn Number.isFinite(parsed) && parsed > 0 ? parsed : 2;\n}\n\nexport async function claimSubgraphOperation(\n\tdb: Kysely<Database>,\n\tlockedBy: string,\n): Promise<SubgraphOperation | null> {\n\t// Fair queue: accounts with fewer currently-running operations are served first,\n\t// breaking ties by creation time. Prevents one user's long reindex from\n\t// starving other accounts when SUBGRAPH_OPERATION_CONCURRENCY > 1.\n\tconst heavyBudget = resolveHeavyOpBudget();\n\tconst result = await sql<SubgraphOperation>`\n\t\tUPDATE subgraph_operations\n\t\tSET\n\t\t\tstatus = 'running',\n\t\t\tlocked_by = ${lockedBy},\n\t\t\tlocked_until = now() + interval '60 seconds',\n\t\t\tstarted_at = COALESCE(started_at, now()),\n\t\t\tupdated_at = now()\n\t\tWHERE id = (\n\t\t\tSELECT so.id\n\t\t\tFROM subgraph_operations so\n\t\t\tLEFT JOIN (\n\t\t\t\tSELECT account_id, COUNT(*) AS cnt\n\t\t\t\tFROM subgraph_operations\n\t\t\t\tWHERE status = 'running'\n\t\t\t\tGROUP BY account_id\n\t\t\t) rc ON so.account_id = rc.account_id\n\t\t\tWHERE\n\t\t\t\t(\n\t\t\t\t\tso.status = 'queued'\n\t\t\t\t\tOR (\n\t\t\t\t\t\tso.status = 'running'\n\t\t\t\t\t\tAND (so.locked_until IS NULL OR so.locked_until < now())\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t\t-- Heavy budget as an eligibility FILTER (not a post-claim refusal):\n\t\t\t\t-- a budget-blocked heavy op at the head must not starve the light\n\t\t\t\t-- ops behind it. Live-lock condition (locked_until > now()) keeps a\n\t\t\t\t-- STALE heavy op from blocking its own reclaim. Soft across\n\t\t\t\t-- concurrent claimers (can overshoot by one with multiple runners) —\n\t\t\t\t-- acceptable for the single-runner deployment.\n\t\t\t\tAND (\n\t\t\t\t\tso.weight = 'light'\n\t\t\t\t\tOR (\n\t\t\t\t\t\tSELECT COUNT(*)\n\t\t\t\t\t\tFROM subgraph_operations h\n\t\t\t\t\t\tWHERE h.status = 'running'\n\t\t\t\t\t\t\tAND h.weight = 'heavy'\n\t\t\t\t\t\t\tAND h.locked_until > now()\n\t\t\t\t\t\t\tAND h.id != so.id\n\t\t\t\t\t) < ${heavyBudget}\n\t\t\t\t)\n\t\t\tORDER BY\n\t\t\t\tCOALESCE(rc.cnt, 0) ASC,\n\t\t\t\tCASE WHEN so.status = 'queued' THEN 0 ELSE 1 END,\n\t\t\t\tso.created_at ASC\n\t\t\tFOR UPDATE OF so SKIP LOCKED\n\t\t\tLIMIT 1\n\t\t)\n\t\tRETURNING *\n\t`.execute(db);\n\treturn result.rows[0] ?? null;\n}\n\nexport async function heartbeatSubgraphOperation(\n\tdb: Kysely<Database>,\n\toperationId: string,\n\tlockedBy: string,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraph_operations\")\n\t\t.set({\n\t\t\tlocked_until: sql<Date>`now() + interval '60 seconds'`,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"id\", \"=\", operationId)\n\t\t.where(\"status\", \"=\", \"running\")\n\t\t.where(\"locked_by\", \"=\", lockedBy)\n\t\t.execute();\n}\n\nexport async function getSubgraphOperation(\n\tdb: Kysely<Database>,\n\toperationId: string,\n): Promise<SubgraphOperation | null> {\n\treturn (\n\t\t(await db\n\t\t\t.selectFrom(\"subgraph_operations\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"=\", operationId)\n\t\t\t.executeTakeFirst()) ?? null\n\t);\n}\n\n/** Recent operations for a subgraph, newest first (for the status read API). */\nexport async function listSubgraphOperations(\n\tdb: Kysely<Database>,\n\tsubgraphId: string,\n\tlimit = 20,\n): Promise<SubgraphOperation[]> {\n\treturn db\n\t\t.selectFrom(\"subgraph_operations\")\n\t\t.selectAll()\n\t\t.where(\"subgraph_id\", \"=\", subgraphId)\n\t\t.orderBy(\"created_at\", \"desc\")\n\t\t.limit(limit)\n\t\t.execute();\n}\n\nexport async function completeSubgraphOperation(\n\tdb: Kysely<Database>,\n\toperationId: string,\n\tlockedBy: string,\n\tprocessedBlocks: number,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraph_operations\")\n\t\t.set({\n\t\t\tstatus: \"completed\",\n\t\t\tfinished_at: new Date(),\n\t\t\tprocessed_blocks: processedBlocks,\n\t\t\tlocked_by: null,\n\t\t\tlocked_until: null,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"id\", \"=\", operationId)\n\t\t.where(\"locked_by\", \"=\", lockedBy)\n\t\t.execute();\n}\n\nexport async function cancelSubgraphOperation(\n\tdb: Kysely<Database>,\n\toperationId: string,\n\tlockedBy: string,\n\tprocessedBlocks: number,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraph_operations\")\n\t\t.set({\n\t\t\tstatus: \"cancelled\",\n\t\t\tfinished_at: new Date(),\n\t\t\tprocessed_blocks: processedBlocks,\n\t\t\tlocked_by: null,\n\t\t\tlocked_until: null,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"id\", \"=\", operationId)\n\t\t.where(\"locked_by\", \"=\", lockedBy)\n\t\t.execute();\n}\n\nexport async function failSubgraphOperation(\n\tdb: Kysely<Database>,\n\toperationId: string,\n\tlockedBy: string,\n\terror: string,\n\tprocessedBlocks?: number,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraph_operations\")\n\t\t.set({\n\t\t\tstatus: \"failed\",\n\t\t\tfinished_at: new Date(),\n\t\t\tprocessed_blocks: processedBlocks ?? null,\n\t\t\terror,\n\t\t\tlocked_by: null,\n\t\t\tlocked_until: null,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"id\", \"=\", operationId)\n\t\t.where(\"locked_by\", \"=\", lockedBy)\n\t\t.execute();\n}\n\n/**\n * 1-based position of a queued operation under the claim ordering (fairness →\n * queued-first → FIFO). The heavy-budget admission filter is NOT applied — a\n * heavy op's eligibility depends on runtime budget state — so the position is\n * approximate; render it as \"~N\". Returns null unless queued.\n */\nexport async function getOperationQueuePosition(\n\tdb: Kysely<Database>,\n\toperationId: string,\n): Promise<number | null> {\n\tconst result = await sql<{ rn: string | number }>`\n\t\tWITH candidates AS (\n\t\t\tSELECT\n\t\t\t\tso.id,\n\t\t\t\tROW_NUMBER() OVER (\n\t\t\t\t\tORDER BY\n\t\t\t\t\t\tCOALESCE(rc.cnt, 0) ASC,\n\t\t\t\t\t\tCASE WHEN so.status = 'queued' THEN 0 ELSE 1 END,\n\t\t\t\t\t\tso.created_at ASC\n\t\t\t\t) AS rn\n\t\t\tFROM subgraph_operations so\n\t\t\tLEFT JOIN (\n\t\t\t\tSELECT account_id, COUNT(*) AS cnt\n\t\t\t\tFROM subgraph_operations\n\t\t\t\tWHERE status = 'running'\n\t\t\t\tGROUP BY account_id\n\t\t\t) rc ON so.account_id = rc.account_id\n\t\t\tWHERE so.status = 'queued'\n\t\t)\n\t\tSELECT rn FROM candidates WHERE id = ${operationId}\n\t`.execute(db);\n\tconst rn = result.rows[0]?.rn;\n\treturn rn == null ? null : Number(rn);\n}\n\n/** Median duration (seconds) of the last 20 completed ops of a weight class —\n * the \"est. start\" multiplier for queued positions. Null with no history. */\nexport async function getRecentOperationMedianDuration(\n\tdb: Kysely<Database>,\n\tweight: \"light\" | \"heavy\",\n): Promise<number | null> {\n\tconst result = await sql<{ median: string | number | null }>`\n\t\tSELECT percentile_cont(0.5) WITHIN GROUP (\n\t\t\tORDER BY EXTRACT(EPOCH FROM (finished_at - started_at))\n\t\t) AS median\n\t\tFROM (\n\t\t\tSELECT started_at, finished_at\n\t\t\tFROM subgraph_operations\n\t\t\tWHERE status = 'completed'\n\t\t\t\tAND weight = ${weight}\n\t\t\t\tAND started_at IS NOT NULL\n\t\t\t\tAND finished_at IS NOT NULL\n\t\t\tORDER BY finished_at DESC\n\t\t\tLIMIT 20\n\t\t) recent\n\t`.execute(db);\n\tconst median = result.rows[0]?.median;\n\treturn median == null ? null : Number(median);\n}\n\n/** Progress-flush hook: events processed so far on a running operation. */\nexport async function updateOperationProcessedEvents(\n\tdb: Kysely<Database>,\n\toperationId: string,\n\tprocessedEvents: number,\n): Promise<void> {\n\t// Monotonic: a crash-resumed run restarts its in-memory counter from 0 —\n\t// never let that regress the op's ETA surfaces.\n\tawait db\n\t\t.updateTable(\"subgraph_operations\")\n\t\t.set({\n\t\t\tprocessed_events: sql`GREATEST(COALESCE(processed_events, 0), ${processedEvents})`,\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"id\", \"=\", operationId)\n\t\t.execute();\n}\n\n/**\n * Conditionally advance a backfill operation's crash checkpoint. Monotonic by\n * construction: the WHERE clause makes concurrent writers serialize — exactly\n * one advance wins per height, regardless of lease/zombie timing. Returns\n * whether THIS caller advanced (false = a racing writer already covered h).\n */\nexport async function advanceOperationCursor(\n\tdb: Kysely<Database>,\n\toperationId: string,\n\theight: number,\n): Promise<boolean> {\n\tconst result = await db\n\t\t.updateTable(\"subgraph_operations\")\n\t\t.set({ cursor_block: height, updated_at: new Date() })\n\t\t.where(\"id\", \"=\", operationId)\n\t\t.where((eb) =>\n\t\t\teb.or([\n\t\t\t\teb(\"cursor_block\", \"is\", null),\n\t\t\t\teb(\"cursor_block\", \"<\", String(height)),\n\t\t\t]),\n\t\t)\n\t\t.executeTakeFirst();\n\treturn Number(result.numUpdatedRows ?? 0n) > 0;\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "7C6D7169EDA84D0F64756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "774B93C0E098748E64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,5 +1,4 @@
1
1
  import { Kysely } from "kysely";
2
- import postgres from "postgres";
3
2
  import { ColumnType, Generated, Selectable } from "kysely";
4
3
  /**
5
4
  * Coverage-kernel constraints. SQL CHECKs in migration 0116 must stay
@@ -19,6 +18,7 @@ declare const FAILURE_CLASSES: readonly ["omission", "version", "digest_mismatch
19
18
  type FailureClass = (typeof FAILURE_CLASSES)[number];
20
19
  declare const RETRY_STATES: readonly ["open", "retrying", "halted", "resolved"];
21
20
  type RetryState = (typeof RETRY_STATES)[number];
21
+ type BootstrapSource = "archive" | "genesis" | "import";
22
22
  interface BlocksTable {
23
23
  height: number;
24
24
  hash: string;
@@ -224,11 +224,9 @@ interface AccountsTable {
224
224
  ghost: Generated<boolean>;
225
225
  /** Stacks principal owning a wallet-ghost account (x402-paid deploys). */
226
226
  wallet_principal: string | null;
227
- plan: Generated<string>;
228
227
  display_name: string | null;
229
228
  bio: string | null;
230
229
  avatar_url: string | null;
231
- slug: string | null;
232
230
  stripe_customer_id: string | null;
233
231
  /** Opt-out toggle for the subgraph reindex-completion email. Defaults true. */
234
232
  notify_reindex_complete: Generated<boolean>;
@@ -245,19 +243,6 @@ interface SessionsTable {
245
243
  last_used_at: Date | null;
246
244
  created_at: Generated<Date>;
247
245
  }
248
- /**
249
- * One-time claim tokens for ghost accounts. The raw token only ever appears in
250
- * the claim URL returned at mint time; we store its sha256. A used token marks
251
- * the account as claimed (or merged into an existing account).
252
- */
253
- interface ClaimTokensTable {
254
- id: Generated<string>;
255
- account_id: string;
256
- token_hash: string;
257
- created_at: Generated<Date>;
258
- expires_at: Date;
259
- used_at: Date | null;
260
- }
261
246
  interface MagicLinksTable {
262
247
  id: Generated<string>;
263
248
  email: string;
@@ -268,47 +253,6 @@ interface MagicLinksTable {
268
253
  failed_attempts: Generated<number>;
269
254
  created_at: Generated<Date>;
270
255
  }
271
- interface UsageDailyTable {
272
- account_id: string;
273
- tenant_id: string | null;
274
- date: string;
275
- api_requests: Generated<number>;
276
- deliveries: Generated<number>;
277
- streams_events_returned: Generated<number>;
278
- index_decoded_events_returned: Generated<number>;
279
- }
280
- interface UsageSnapshotsTable {
281
- id: Generated<string>;
282
- account_id: string;
283
- measured_at: Generated<Date>;
284
- storage_bytes: Generated<number>;
285
- }
286
- interface AccountInsightsTable {
287
- id: Generated<string>;
288
- account_id: string;
289
- category: string;
290
- insight_type: string;
291
- resource_id: string | null;
292
- severity: string;
293
- title: string;
294
- body: string;
295
- data: unknown;
296
- dismissed_at: Date | null;
297
- expires_at: Date | null;
298
- created_at: Generated<Date>;
299
- }
300
- interface AccountAgentRunsTable {
301
- id: Generated<string>;
302
- account_id: string;
303
- started_at: Generated<Date>;
304
- completed_at: Date | null;
305
- status: Generated<string>;
306
- input_tokens: Generated<number>;
307
- output_tokens: Generated<number>;
308
- cost_usd: Generated<number>;
309
- insights_created: Generated<number>;
310
- error: string | null;
311
- }
312
256
  interface SubgraphProcessingStatsTable {
313
257
  id: Generated<string>;
314
258
  subgraph_name: string;
@@ -341,41 +285,6 @@ interface SubgraphHealthSnapshotsTable {
341
285
  last_processed_block: number | null;
342
286
  captured_at: Generated<Date>;
343
287
  }
344
- interface SubgraphUsageDailyTable {
345
- subgraph_id: string;
346
- date: string;
347
- query_count: Generated<number>;
348
- }
349
- interface ProjectsTable {
350
- id: Generated<string>;
351
- name: string;
352
- slug: string;
353
- account_id: string;
354
- settings: Generated<Record<string, unknown>>;
355
- network: Generated<string>;
356
- node_rpc: string | null;
357
- created_at: Generated<Date>;
358
- updated_at: Generated<Date>;
359
- }
360
- interface TeamMembersTable {
361
- id: Generated<string>;
362
- project_id: string;
363
- account_id: string;
364
- role: Generated<string>;
365
- invited_by: string | null;
366
- created_at: Generated<Date>;
367
- }
368
- interface TeamInvitationsTable {
369
- id: Generated<string>;
370
- project_id: string;
371
- email: string;
372
- role: Generated<string>;
373
- token: string;
374
- invited_by: string | null;
375
- expires_at: Date;
376
- accepted_at: Date | null;
377
- created_at: Generated<Date>;
378
- }
379
288
  interface ProcessedStripeEventsTable {
380
289
  event_id: string;
381
290
  event_type: string;
@@ -812,6 +721,20 @@ interface StageFailuresTable {
812
721
  resolved_at: Date | null;
813
722
  retain_until: Generated<Date>;
814
723
  }
724
+ /**
725
+ * The instance's declared scope — one row per network. `start_height` is what
726
+ * makes missing history below it deliberate rather than a gap.
727
+ */
728
+ interface SyncScopesTable {
729
+ network: string;
730
+ start_height: number;
731
+ target_height: number | null;
732
+ bootstrap_source: BootstrapSource;
733
+ bootstrap_manifest_digest: string | null;
734
+ genesis_hash: string | null;
735
+ created_at: Generated<Date>;
736
+ updated_at: Generated<Date>;
737
+ }
815
738
  interface Database {
816
739
  blocks: BlocksTable;
817
740
  transactions: TransactionsTable;
@@ -828,27 +751,14 @@ interface Database {
828
751
  accounts: AccountsTable;
829
752
  sessions: SessionsTable;
830
753
  magic_links: MagicLinksTable;
831
- claim_tokens: ClaimTokensTable;
832
- usage_daily: UsageDailyTable;
833
- usage_snapshots: UsageSnapshotsTable;
834
- account_insights: AccountInsightsTable;
835
- account_agent_runs: AccountAgentRunsTable;
836
754
  subgraph_health_snapshots: SubgraphHealthSnapshotsTable;
837
755
  subgraph_processing_stats: SubgraphProcessingStatsTable;
838
756
  subgraph_table_snapshots: SubgraphTableSnapshotsTable;
839
757
  subgraph_gaps: SubgraphGapsTable;
840
758
  subgraph_operations: SubgraphOperationsTable;
841
- subgraph_usage_daily: SubgraphUsageDailyTable;
842
- projects: ProjectsTable;
843
- team_members: TeamMembersTable;
844
- team_invitations: TeamInvitationsTable;
845
759
  processed_stripe_events: ProcessedStripeEventsTable;
846
- tenants: TenantsTable;
847
- tenant_usage_monthly: TenantUsageMonthlyTable;
848
- tenant_compute_addons: TenantComputeAddonsTable;
849
760
  account_spend_caps: AccountSpendCapsTable;
850
761
  account_credits: AccountCreditsTable;
851
- provisioning_audit_log: ProvisioningAuditLogTable;
852
762
  subscriptions: SubscriptionsTable;
853
763
  subscription_outbox: SubscriptionOutboxTable;
854
764
  subscription_deliveries: SubscriptionDeliveriesTable;
@@ -877,6 +787,7 @@ interface Database {
877
787
  chain_read_cache: ChainReadCacheTable;
878
788
  pending_fork_blocks: PendingForkBlocksTable;
879
789
  observer_journal: ObserverJournalTable;
790
+ sync_scopes: SyncScopesTable;
880
791
  stage_registry: StageRegistryTable;
881
792
  stage_runs: StageRunsTable;
882
793
  stage_block_receipts: StageBlockReceiptsTable;
@@ -923,57 +834,6 @@ interface X402PaymentsTable {
923
834
  * reconciler's heal path can never double-credit them. */
924
835
  credited_at: Generated<Date> | null;
925
836
  }
926
- type TenantStatus = "provisioning" | "active" | "limit_warning" | "paused_limit" | "suspended" | "error" | "deleted";
927
- interface TenantsTable {
928
- id: Generated<string>;
929
- account_id: string;
930
- slug: string;
931
- status: ColumnType<TenantStatus, TenantStatus | undefined, TenantStatus>;
932
- plan: string;
933
- cpus: ColumnType<number, number | string, number | string>;
934
- memory_mb: number;
935
- storage_limit_mb: number;
936
- storage_used_mb: number | null;
937
- pg_container_id: string | null;
938
- api_container_id: string | null;
939
- processor_container_id: string | null;
940
- target_database_url_enc: Buffer;
941
- tenant_jwt_secret_enc: Buffer;
942
- anon_key_enc: Buffer;
943
- service_key_enc: Buffer;
944
- api_url_internal: string;
945
- api_url_public: string;
946
- suspended_at: Date | null;
947
- last_health_check_at: Date | null;
948
- last_active_at: Generated<Date>;
949
- service_gen: Generated<number>;
950
- anon_gen: Generated<number>;
951
- project_id: string | null;
952
- created_at: Generated<Date>;
953
- updated_at: Generated<Date>;
954
- }
955
- interface TenantUsageMonthlyTable {
956
- id: Generated<string>;
957
- tenant_id: string;
958
- period_month: Date;
959
- storage_peak_mb: Generated<number>;
960
- storage_avg_mb: Generated<number>;
961
- storage_last_mb: Generated<number>;
962
- measurements: Generated<number>;
963
- first_at: Generated<Date>;
964
- last_at: Generated<Date>;
965
- }
966
- interface TenantComputeAddonsTable {
967
- id: Generated<string>;
968
- tenant_id: string;
969
- memory_mb_delta: Generated<number>;
970
- cpu_delta: Generated<number | string>;
971
- storage_mb_delta: Generated<number>;
972
- effective_from: Generated<Date>;
973
- effective_until: Date | null;
974
- stripe_subscription_item_id: string | null;
975
- created_at: Generated<Date>;
976
- }
977
837
  interface AccountSpendCapsTable {
978
838
  account_id: string;
979
839
  monthly_cap_cents: number | null;
@@ -997,20 +857,6 @@ interface AccountCreditsTable {
997
857
  refill_last_at: Date | null;
998
858
  updated_at: Generated<Date>;
999
859
  }
1000
- type ProvisioningAuditEvent = "provision.start" | "provision.success" | "provision.failure" | "suspend" | "resume" | "resize" | "keys.rotate" | "bastion.key.upload" | "bastion.key.revoke" | "teardown";
1001
- type ProvisioningAuditStatus = "ok" | "error";
1002
- interface ProvisioningAuditLogTable {
1003
- id: Generated<string>;
1004
- tenant_id: string | null;
1005
- tenant_slug: string | null;
1006
- account_id: string | null;
1007
- actor: string;
1008
- event: ProvisioningAuditEvent;
1009
- status: ProvisioningAuditStatus;
1010
- detail: unknown | null;
1011
- error: string | null;
1012
- created_at: Generated<Date>;
1013
- }
1014
860
  type Subgraph = Selectable<SubgraphsTable>;
1015
861
  type SubscriptionStatus = "active" | "paused" | "error";
1016
862
  /** Polymorphic subscription mode: `subgraph` reacts to processed table rows;
@@ -1101,24 +947,6 @@ interface TriggerEvaluatorStateTable {
1101
947
  updated_at: Generated<Date>;
1102
948
  }
1103
949
  /**
1104
- * BYO data plane helpers. A subgraph's user-owned Postgres connection string is
1105
- * stored encrypted at rest in `database_url_enc` (AES-GCM envelope). Plaintext
1106
- * only exists transiently — at deploy (to encrypt) and at pool construction (to
1107
- * connect). Never serialize it into API responses.
1108
- */
1109
- declare function encryptDatabaseUrl(url: string): Buffer;
1110
- /** Decrypt a subgraph's BYO connection string, or null when managed. */
1111
- declare function subgraphDatabaseUrl(subgraph: Subgraph): string | null;
1112
- /** True when the subgraph writes/serves from a user-owned DB. */
1113
- declare function isByoSubgraph(subgraph: Subgraph): boolean;
1114
- /**
1115
- * Resolve the Kysely instance a subgraph's data plane lives on: the user's DB
1116
- * when BYO, else the managed target DB. Pools are cached by URL in db/index.ts.
1117
- */
1118
- declare function resolveSubgraphDb(subgraph: Subgraph): Kysely<Database>;
1119
- /** Raw postgres.js client for a subgraph's data plane (DDL / serving queries). */
1120
- declare function resolveSubgraphRawClient(subgraph: Subgraph): ReturnType<typeof postgres>;
1121
- /**
1122
950
  * Convert a subgraph name to its PostgreSQL schema name (legacy form).
1123
951
  * Pre shared-rip every tenant DB had its own schema namespace so disambiguation
1124
952
  * was implicit. Kept for oss mode (single-tenant) and legacy-row fallback.
@@ -1145,8 +973,6 @@ declare function registerSubgraph(db: Kysely<Database>, data: {
1145
973
  startBlock?: number
1146
974
  handlerCode?: string
1147
975
  sourceCode?: string
1148
- /** BYO data plane: encrypted user-DB connection string, or null = managed. */
1149
- databaseUrlEnc?: Buffer | null
1150
976
  }): Promise<Subgraph>;
1151
977
  declare function getSubgraph(db: Kysely<Database>, name: string, accountId?: string): Promise<Subgraph | null>;
1152
978
  declare function listSubgraphs(db: Kysely<Database>, accountId?: string): Promise<Subgraph[]>;
@@ -1233,4 +1059,4 @@ declare function recordLiveProgress(db: Kysely<Database>, name: string, lastProc
1233
1059
  * forward write between the rewind and the fork block's reprocess. Do not
1234
1060
  * call this from the live catch-up path. */
1235
1061
  declare function rewindLiveProgress(db: Kysely<Database>, name: string, lastProcessedBlock: number): Promise<void>;
1236
- export { updateSubgraphVisibility, updateSubgraphStatus, updateSubgraphHandlerPath, updateSubgraphExpiry, subgraphDatabaseUrl, rewindLiveProgress, resolveSubgraphRawClient, resolveSubgraphDb, registerSubgraph, recordSubgraphProcessed, recordLiveProgress, recordLiveError, pgSchemaNameFor, pgSchemaName, localSubgraphAccountId, listSubgraphs, isByoSubgraph, getSubgraph, findPublicSubgraphByName, encryptDatabaseUrl, deleteSubgraph };
1062
+ export { updateSubgraphVisibility, updateSubgraphStatus, updateSubgraphHandlerPath, updateSubgraphExpiry, rewindLiveProgress, registerSubgraph, recordSubgraphProcessed, recordLiveProgress, recordLiveError, pgSchemaNameFor, pgSchemaName, localSubgraphAccountId, listSubgraphs, getSubgraph, findPublicSubgraphByName, deleteSubgraph };