@secondlayer/subgraphs 3.24.2 → 3.25.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.
@@ -366,6 +366,17 @@ type EventRecord = {
366
366
  };
367
367
  import { Database as Database2 } from "@secondlayer/shared/db";
368
368
  import { Kysely as Kysely2, Transaction } from "kysely";
369
+ /** f072: thrown by `resolveRoute` when a BYO subgraph needs its user-DB
370
+ * connection decrypted but this process holds no `SECONDLAYER_SECRETS_KEY`
371
+ * — the subgraph processor deliberately does not hold the master key (it
372
+ * runs untrusted handler code in-process, every block; see f049 site 3 /
373
+ * the sandbox spike doc's D3). Deny by default, fail loud: this must NEVER
374
+ * be caught and silently rerouted to the managed target DB, since that
375
+ * would write a tenant's rows into ours — far worse than halting the
376
+ * block. */
377
+ declare class ByoKeyUnavailableError extends Error {
378
+ constructor(subgraphName: string);
379
+ }
369
380
  /** Drop a subgraph's cached route — call on redeploy/delete (conn may
370
381
  * change). Also evicts any warm sandbox subprocess for this subgraph
371
382
  * (f071 Stage A `host.ts`) on the same edge: a redeploy can change
@@ -480,4 +491,4 @@ declare const BLOCK_RETRY_DELAYS_MS: number[];
480
491
  */
481
492
  declare function processBlockWithRetry(subgraph: SubgraphDefinition, subgraphName: string, blockHeight: number, opts?: ProcessBlockOptions, retryDelaysMs?: number[]): Promise<ProcessBlockResult>;
482
493
  declare function processBlock(subgraph: SubgraphDefinition, subgraphName: string, blockHeight: number, opts?: ProcessBlockOptions): Promise<ProcessBlockResult>;
483
- export { resolveFactoryContracts, processBlockWithRetry, processBlock, invalidateSubgraphRoute, ProcessBlockTiming, ProcessBlockResult, ProcessBlockOptions, PreloadedBlockData, BLOCK_RETRY_DELAYS_MS };
494
+ export { resolveFactoryContracts, processBlockWithRetry, processBlock, invalidateSubgraphRoute, ProcessBlockTiming, ProcessBlockResult, ProcessBlockOptions, PreloadedBlockData, ByoKeyUnavailableError, BLOCK_RETRY_DELAYS_MS };
@@ -27,6 +27,13 @@ var TYPE_MAP = {
27
27
  timestamp: "TIMESTAMPTZ",
28
28
  jsonb: "JSONB"
29
29
  };
30
+ var MAX_IDENT_BYTES = 63;
31
+ function safeIndexName(name) {
32
+ if (name.length <= MAX_IDENT_BYTES)
33
+ return name;
34
+ const hash = createHash("sha256").update(name).digest("hex").slice(0, 8);
35
+ return `${name.slice(0, MAX_IDENT_BYTES - hash.length - 1)}_${hash}`;
36
+ }
30
37
  function escapeLiteralDefault(value) {
31
38
  if (value === null || value === undefined)
32
39
  return "NULL";
@@ -69,6 +76,7 @@ function emitTableDDL(schemaName, tableName, tableDef) {
69
76
  for (const [colName, col] of Object.entries(tableDef.columns)) {
70
77
  if (col.indexed) {
71
78
  statements.push(`CREATE INDEX IF NOT EXISTS ${quotePgIdent(`idx_${schemaName}_${tableName}_${colName}`)} ON ${qualifiedName} (${quotePgIdent(colName)})`);
79
+ statements.push(`CREATE INDEX IF NOT EXISTS ${quotePgIdent(safeIndexName(`idx_${schemaName}_${tableName}_${colName}_id`))} ON ${qualifiedName} (${quotePgIdent(colName)}, ${quotePgIdent("_id")})`);
72
80
  }
73
81
  }
74
82
  for (const [colName, col] of Object.entries(tableDef.columns)) {
@@ -1627,6 +1635,7 @@ function matchSources(sources, transactions, events, traitContracts = new Map, f
1627
1635
  }
1628
1636
 
1629
1637
  // src/runtime/block-processor.ts
1638
+ import { secretsKeyAvailable } from "@secondlayer/shared/crypto/secrets";
1630
1639
  import { getTargetDb } from "@secondlayer/shared/db";
1631
1640
  import { resolveTraitContractIds } from "@secondlayer/shared/db/queries/contracts";
1632
1641
  import { advanceOperationCursor } from "@secondlayer/shared/db/queries/subgraph-operations";
@@ -2564,12 +2573,22 @@ async function refreshMatcher(db) {
2564
2573
 
2565
2574
  // src/runtime/block-processor.ts
2566
2575
  var routeCache = new Map;
2576
+
2577
+ class ByoKeyUnavailableError extends Error {
2578
+ constructor(subgraphName) {
2579
+ super(`subgraph ${subgraphName} is BYO (database_url_enc set) but this process has no SECONDLAYER_SECRETS_KEY — the subgraph processor deliberately does not hold it (f072). Route BYO subgraphs to a process that does, or unset BYO.`);
2580
+ this.name = "ByoKeyUnavailableError";
2581
+ }
2582
+ }
2567
2583
  async function resolveRoute(subgraphName, targetDb) {
2568
2584
  const cached = routeCache.get(subgraphName);
2569
2585
  if (cached)
2570
2586
  return cached;
2571
2587
  const row = await targetDb.selectFrom("subgraphs").selectAll().where("name", "=", subgraphName).executeTakeFirst();
2572
2588
  const byo = row ? isByoSubgraph(row) : false;
2589
+ if (row && byo && !secretsKeyAvailable()) {
2590
+ throw new ByoKeyUnavailableError(subgraphName);
2591
+ }
2573
2592
  const route = {
2574
2593
  schemaName: row?.schema_name ?? pgSchemaName(subgraphName),
2575
2594
  dataDb: row && byo ? resolveSubgraphDb(row) : targetDb,
@@ -2942,8 +2961,9 @@ export {
2942
2961
  processBlockWithRetry,
2943
2962
  processBlock,
2944
2963
  invalidateSubgraphRoute,
2964
+ ByoKeyUnavailableError,
2945
2965
  BLOCK_RETRY_DELAYS_MS
2946
2966
  };
2947
2967
 
2948
- //# debugId=7DCA5B46BE5FE59C64756E2164756E21
2968
+ //# debugId=A128B38411DC574B64756E2164756E21
2949
2969
  //# sourceMappingURL=block-processor.js.map