@secondlayer/shared 2.1.0 → 3.0.0-alpha.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 (62) hide show
  1. package/README.md +2 -2
  2. package/dist/src/db/index.d.ts +39 -137
  3. package/dist/src/db/index.js.map +2 -2
  4. package/dist/src/db/jsonb.d.ts +5 -1
  5. package/dist/src/db/jsonb.js.map +2 -2
  6. package/dist/src/db/queries/account-spend-caps.d.ts +379 -0
  7. package/dist/src/db/queries/account-spend-caps.js +60 -0
  8. package/dist/src/db/queries/account-spend-caps.js.map +10 -0
  9. package/dist/src/db/queries/account-usage.d.ts +403 -0
  10. package/dist/src/db/queries/account-usage.js +222 -0
  11. package/dist/src/db/queries/account-usage.js.map +11 -0
  12. package/dist/src/db/queries/accounts.d.ts +41 -115
  13. package/dist/src/db/queries/accounts.js +15 -1
  14. package/dist/src/db/queries/accounts.js.map +3 -3
  15. package/dist/src/db/queries/integrity.d.ts +27 -114
  16. package/dist/src/db/queries/projects.d.ts +27 -114
  17. package/dist/src/db/queries/provisioning-audit.d.ts +27 -114
  18. package/dist/src/db/queries/subgraph-gaps.d.ts +27 -114
  19. package/dist/src/db/queries/subgraphs.d.ts +27 -115
  20. package/dist/src/db/queries/subgraphs.js +2 -3
  21. package/dist/src/db/queries/subgraphs.js.map +4 -4
  22. package/dist/src/db/queries/{workflows.d.ts → tenant-compute-addons.d.ts} +50 -149
  23. package/dist/src/db/queries/tenant-compute-addons.js +47 -0
  24. package/dist/src/db/queries/tenant-compute-addons.js.map +10 -0
  25. package/dist/src/db/queries/tenants.d.ts +40 -117
  26. package/dist/src/db/queries/tenants.js +9 -6
  27. package/dist/src/db/queries/tenants.js.map +3 -3
  28. package/dist/src/db/queries/usage.d.ts +28 -139
  29. package/dist/src/db/queries/usage.js +5 -64
  30. package/dist/src/db/queries/usage.js.map +4 -5
  31. package/dist/src/db/schema.d.ts +34 -136
  32. package/dist/src/errors.d.ts +8 -7
  33. package/dist/src/errors.js +11 -12
  34. package/dist/src/errors.js.map +3 -3
  35. package/dist/src/index.d.ts +46 -143
  36. package/dist/src/index.js +11 -12
  37. package/dist/src/index.js.map +4 -4
  38. package/dist/src/node/local-client.d.ts +27 -114
  39. package/dist/src/pricing.d.ts +20 -1
  40. package/dist/src/pricing.js +58 -1
  41. package/dist/src/pricing.js.map +3 -3
  42. package/migrations/0045_drop_marketplace_columns.ts +47 -0
  43. package/migrations/0046_tenant_activity_signal.ts +47 -0
  44. package/migrations/0047_usage_daily_tenant_id.ts +73 -0
  45. package/migrations/0048_tenant_compute_addons.ts +49 -0
  46. package/migrations/0049_accounts_stripe_customer_id.ts +30 -0
  47. package/migrations/0050_account_spend_caps.ts +45 -0
  48. package/migrations/0051_workflow_ai_usage_daily.ts +40 -0
  49. package/migrations/0052_sentries.ts +61 -0
  50. package/migrations/0053_workflow_runtime.ts +88 -0
  51. package/migrations/0054_accounts_plan_hobby.ts +32 -0
  52. package/migrations/0055_ai_usage_account_scope.ts +108 -0
  53. package/migrations/0056_drop_workflow_sentry_residuals.ts +23 -0
  54. package/package.json +26 -14
  55. package/dist/src/db/queries/workflows.js +0 -260
  56. package/dist/src/db/queries/workflows.js.map +0 -12
  57. package/dist/src/lib/plans.d.ts +0 -9
  58. package/dist/src/lib/plans.js +0 -37
  59. package/dist/src/lib/plans.js.map +0 -10
  60. package/dist/src/schemas/workflows.d.ts +0 -70
  61. package/dist/src/schemas/workflows.js +0 -43
  62. package/dist/src/schemas/workflows.js.map +0 -10
@@ -60,10 +60,6 @@ interface SubgraphsTable {
60
60
  handler_code: string | null;
61
61
  source_code: string | null;
62
62
  project_id: string | null;
63
- is_public: Generated<boolean>;
64
- tags: Generated<string[]>;
65
- description: string | null;
66
- forked_from_id: string | null;
67
63
  created_at: Generated<Date>;
68
64
  updated_at: Generated<Date>;
69
65
  }
@@ -98,6 +94,7 @@ interface AccountsTable {
98
94
  bio: string | null;
99
95
  avatar_url: string | null;
100
96
  slug: string | null;
97
+ stripe_customer_id: string | null;
101
98
  created_at: Generated<Date>;
102
99
  }
103
100
  interface SessionsTable {
@@ -123,6 +120,7 @@ interface MagicLinksTable {
123
120
  }
124
121
  interface UsageDailyTable {
125
122
  account_id: string;
123
+ tenant_id: string | null;
126
124
  date: string;
127
125
  api_requests: Generated<number>;
128
126
  deliveries: Generated<number>;
@@ -249,83 +247,6 @@ interface ChatMessagesTable {
249
247
  metadata: unknown | null;
250
248
  created_at: Generated<Date>;
251
249
  }
252
- interface WorkflowDefinitionsTable {
253
- id: Generated<string>;
254
- name: string;
255
- version: Generated<string>;
256
- status: Generated<string>;
257
- trigger_type: string;
258
- trigger_config: unknown;
259
- handler_path: string;
260
- source_code: string | null;
261
- retries_config: unknown | null;
262
- timeout_ms: number | null;
263
- api_key_id: string;
264
- project_id: string | null;
265
- created_at: Generated<Date>;
266
- updated_at: Generated<Date>;
267
- }
268
- interface WorkflowRunsTable {
269
- id: Generated<string>;
270
- definition_id: string;
271
- status: Generated<string>;
272
- trigger_type: string;
273
- trigger_data: unknown | null;
274
- dedup_key: string | null;
275
- error: string | null;
276
- started_at: Date | null;
277
- completed_at: Date | null;
278
- duration_ms: number | null;
279
- total_ai_tokens: Generated<number>;
280
- created_at: Generated<Date>;
281
- }
282
- interface WorkflowStepsTable {
283
- id: Generated<string>;
284
- run_id: string;
285
- step_index: number;
286
- step_id: string;
287
- step_type: string;
288
- status: Generated<string>;
289
- input: unknown | null;
290
- output: unknown | null;
291
- error: string | null;
292
- retry_count: Generated<number>;
293
- ai_tokens_used: Generated<number>;
294
- started_at: Date | null;
295
- completed_at: Date | null;
296
- duration_ms: number | null;
297
- memo_key: string | null;
298
- parent_step_id: string | null;
299
- created_at: Generated<Date>;
300
- }
301
- interface WorkflowQueueTable {
302
- id: Generated<string>;
303
- run_id: string;
304
- status: Generated<string>;
305
- attempts: Generated<number>;
306
- max_attempts: Generated<number>;
307
- scheduled_for: Generated<Date>;
308
- locked_at: Date | null;
309
- locked_by: string | null;
310
- error: string | null;
311
- created_at: Generated<Date>;
312
- completed_at: Date | null;
313
- }
314
- interface WorkflowSchedulesTable {
315
- id: Generated<string>;
316
- definition_id: string;
317
- cron_expr: string;
318
- timezone: Generated<string>;
319
- next_run_at: Date;
320
- last_run_at: Date | null;
321
- enabled: Generated<boolean>;
322
- created_at: Generated<Date>;
323
- }
324
- interface WorkflowCursorsTable {
325
- name: string;
326
- block_height: Generated<number>;
327
- updated_at: Generated<Date>;
328
- }
329
250
  interface Database {
330
251
  blocks: BlocksTable;
331
252
  transactions: TransactionsTable;
@@ -351,16 +272,10 @@ interface Database {
351
272
  team_invitations: TeamInvitationsTable;
352
273
  chat_sessions: ChatSessionsTable;
353
274
  chat_messages: ChatMessagesTable;
354
- workflow_definitions: WorkflowDefinitionsTable;
355
- workflow_runs: WorkflowRunsTable;
356
- workflow_steps: WorkflowStepsTable;
357
- workflow_queue: WorkflowQueueTable;
358
- workflow_schedules: WorkflowSchedulesTable;
359
- workflow_cursors: WorkflowCursorsTable;
360
- workflow_signer_secrets: WorkflowSignerSecretsTable;
361
- workflow_budgets: WorkflowBudgetsTable;
362
275
  tenants: TenantsTable;
363
276
  tenant_usage_monthly: TenantUsageMonthlyTable;
277
+ tenant_compute_addons: TenantComputeAddonsTable;
278
+ account_spend_caps: AccountSpendCapsTable;
364
279
  provisioning_audit_log: ProvisioningAuditLogTable;
365
280
  }
366
281
  type TenantStatus = "provisioning" | "active" | "suspended" | "error" | "deleted";
@@ -383,9 +298,9 @@ interface TenantsTable {
383
298
  service_key_enc: Buffer;
384
299
  api_url_internal: string;
385
300
  api_url_public: string;
386
- trial_ends_at: Date;
387
301
  suspended_at: Date | null;
388
302
  last_health_check_at: Date | null;
303
+ last_active_at: Generated<Date>;
389
304
  service_gen: Generated<number>;
390
305
  anon_gen: Generated<number>;
391
306
  project_id: string | null;
@@ -403,6 +318,28 @@ interface TenantUsageMonthlyTable {
403
318
  first_at: Generated<Date>;
404
319
  last_at: Generated<Date>;
405
320
  }
321
+ interface TenantComputeAddonsTable {
322
+ id: Generated<string>;
323
+ tenant_id: string;
324
+ memory_mb_delta: Generated<number>;
325
+ cpu_delta: Generated<number | string>;
326
+ storage_mb_delta: Generated<number>;
327
+ effective_from: Generated<Date>;
328
+ effective_until: Date | null;
329
+ stripe_subscription_item_id: string | null;
330
+ created_at: Generated<Date>;
331
+ }
332
+ interface AccountSpendCapsTable {
333
+ account_id: string;
334
+ monthly_cap_cents: number | null;
335
+ compute_cap_cents: number | null;
336
+ storage_cap_cents: number | null;
337
+ ai_cap_cents: number | null;
338
+ alert_threshold_pct: Generated<number>;
339
+ alert_sent_at: Date | null;
340
+ frozen_at: Date | null;
341
+ updated_at: Generated<Date>;
342
+ }
406
343
  type ProvisioningAuditEvent = "provision.start" | "provision.success" | "provision.failure" | "suspend" | "resume" | "resize" | "keys.rotate" | "bastion.key.upload" | "bastion.key.revoke" | "teardown";
407
344
  type ProvisioningAuditStatus = "ok" | "error";
408
345
  interface ProvisioningAuditLogTable {
@@ -417,30 +354,6 @@ interface ProvisioningAuditLogTable {
417
354
  error: string | null;
418
355
  created_at: Generated<Date>;
419
356
  }
420
- interface WorkflowBudgetsTable {
421
- id: Generated<string>;
422
- workflow_definition_id: string;
423
- /** Period key: "daily:YYYY-MM-DD" | "weekly:YYYY-Www" | "per-run:<uuid>". */
424
- period: string;
425
- ai_usd_used: Generated<string>;
426
- ai_tokens_used: Generated<string>;
427
- chain_microstx_used: Generated<string>;
428
- chain_tx_count: Generated<number>;
429
- run_count: Generated<number>;
430
- step_count: Generated<number>;
431
- reset_at: Date;
432
- created_at: Generated<Date>;
433
- updated_at: Generated<Date>;
434
- }
435
- interface WorkflowSignerSecretsTable {
436
- id: Generated<string>;
437
- account_id: string;
438
- name: string;
439
- /** AES-GCM ciphertext bytes produced by the runner's KMS on write. */
440
- encrypted_value: Buffer;
441
- created_at: Generated<Date>;
442
- updated_at: Generated<Date>;
443
- }
444
357
  type Subgraph = Selectable<SubgraphsTable>;
445
358
  /**
446
359
  * Convert a subgraph name to its PostgreSQL schema name.
@@ -459,7 +372,6 @@ declare function registerSubgraph(db: Kysely<Database>, data: {
459
372
  accountId?: string
460
373
  schemaName?: string
461
374
  startBlock?: number
462
- forkedFromId?: string
463
375
  handlerCode?: string
464
376
  sourceCode?: string
465
377
  }): Promise<Subgraph>;
@@ -48,8 +48,7 @@ async function registerSubgraph(db, data) {
48
48
  handler_code: data.handlerCode ?? null,
49
49
  source_code: data.sourceCode ?? null,
50
50
  schema_name: data.schemaName ?? null,
51
- start_block: data.startBlock ?? 0,
52
- forked_from_id: data.forkedFromId ?? null
51
+ start_block: data.startBlock ?? 0
53
52
  }).onConflict((oc) => oc.columns(["name", "account_id"]).doUpdateSet({
54
53
  version: data.version,
55
54
  definition: jsonb(data.definition),
@@ -114,5 +113,5 @@ export {
114
113
  deleteSubgraph
115
114
  };
116
115
 
117
- //# debugId=AE963057007E387C64756E2164756E21
116
+ //# debugId=D8D245F7C02FE78964756E2164756E21
118
117
  //# sourceMappingURL=subgraphs.js.map
@@ -2,10 +2,10 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/db/jsonb.ts", "../src/db/queries/subgraphs.ts"],
4
4
  "sourcesContent": [
5
- "import { type RawBuilder, sql } from \"kysely\";\n\n/**\n * Safely encode a JS value as a JSONB literal for Kysely inserts/updates.\n * Kysely + postgres.js double-encodes JSON when using parameterized queries\n * with ::jsonb casts. This uses sql.raw to inline a properly escaped literal.\n */\nexport function jsonb(value: unknown): RawBuilder<unknown> {\n\tconst escaped = JSON.stringify(value, (_k, v) =>\n\t\ttypeof v === \"bigint\" ? v.toString() : v,\n\t).replace(/'/g, \"''\");\n\treturn sql`${sql.raw(`'${escaped}'::jsonb`)}`;\n}\n\n/**\n * Safely parse a JSONB value from the database.\n * Handles double-encoded strings where postgres.js returns a JSON string\n * instead of a parsed object.\n */\nexport function parseJsonb<T = unknown>(value: unknown): T {\n\tif (typeof value === \"string\") {\n\t\ttry {\n\t\t\treturn JSON.parse(value) as T;\n\t\t} catch {\n\t\t\treturn value as T;\n\t\t}\n\t}\n\treturn (value ?? {}) as T;\n}\n",
6
- "import { type Kysely, sql } from \"kysely\";\nimport { jsonb } from \"../jsonb.ts\";\nimport type { Database, Subgraph } from \"../types.ts\";\n\n/**\n * Convert a subgraph name to its PostgreSQL schema name.\n * Every tenant DB has its own isolated schema namespace, so there's no\n * account-prefix disambiguation needed — every subgraph within a tenant\n * just maps to `subgraph_{safeName}`.\n */\nexport function pgSchemaName(subgraphName: string): string {\n\tconst safeName = subgraphName.replace(/-/g, \"_\");\n\treturn `subgraph_${safeName}`;\n}\n\nexport async function registerSubgraph(\n\tdb: Kysely<Database>,\n\tdata: {\n\t\tname: string;\n\t\tversion: string;\n\t\tdefinition: Record<string, unknown>;\n\t\tschemaHash: string;\n\t\thandlerPath: string;\n\t\tapiKeyId?: string;\n\t\taccountId?: string;\n\t\tschemaName?: string;\n\t\tstartBlock?: number;\n\t\tforkedFromId?: string;\n\t\thandlerCode?: string;\n\t\tsourceCode?: string;\n\t},\n): Promise<Subgraph> {\n\treturn await db\n\t\t.insertInto(\"subgraphs\")\n\t\t.values({\n\t\t\tname: data.name,\n\t\t\tversion: data.version,\n\t\t\tdefinition: jsonb(data.definition) as any,\n\t\t\tschema_hash: data.schemaHash,\n\t\t\thandler_path: data.handlerPath,\n\t\t\taccount_id: data.accountId ?? \"\",\n\t\t\thandler_code: data.handlerCode ?? null,\n\t\t\tsource_code: data.sourceCode ?? null,\n\t\t\tschema_name: data.schemaName ?? null,\n\t\t\tstart_block: data.startBlock ?? 0,\n\t\t\tforked_from_id: data.forkedFromId ?? null,\n\t\t})\n\t\t.onConflict((oc) =>\n\t\t\toc.columns([\"name\", \"account_id\"]).doUpdateSet({\n\t\t\t\tversion: data.version,\n\t\t\t\tdefinition: jsonb(data.definition) as any,\n\t\t\t\tschema_hash: data.schemaHash,\n\t\t\t\thandler_path: data.handlerPath,\n\t\t\t\thandler_code: data.handlerCode ?? null,\n\t\t\t\tsource_code: data.sourceCode ?? null,\n\t\t\t\tschema_name: data.schemaName ?? null,\n\t\t\t\tstart_block: data.startBlock ?? 0,\n\t\t\t\tupdated_at: new Date(),\n\t\t\t}),\n\t\t)\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n}\n\nexport async function getSubgraph(\n\tdb: Kysely<Database>,\n\tname: string,\n\taccountId?: string,\n): Promise<Subgraph | null> {\n\tlet query = db.selectFrom(\"subgraphs\").selectAll().where(\"name\", \"=\", name);\n\n\tif (accountId) {\n\t\tquery = query.where(\"account_id\", \"=\", accountId);\n\t}\n\n\treturn (await query.executeTakeFirst()) ?? null;\n}\n\nexport async function listSubgraphs(\n\tdb: Kysely<Database>,\n\taccountId?: string,\n): Promise<Subgraph[]> {\n\tlet query = db.selectFrom(\"subgraphs\").selectAll();\n\tif (accountId) {\n\t\tquery = query.where(\"account_id\", \"=\", accountId);\n\t}\n\treturn query.execute();\n}\n\nexport async function updateSubgraphStatus(\n\tdb: Kysely<Database>,\n\tname: string,\n\tstatus: string,\n\tlastProcessedBlock?: number,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\tstatus,\n\t\t\t...(lastProcessedBlock !== undefined\n\t\t\t\t? { last_processed_block: lastProcessedBlock }\n\t\t\t\t: {}),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function recordSubgraphProcessed(\n\tdb: Kysely<Database>,\n\tname: string,\n\tprocessed: number,\n\terrors: number,\n\tlastError?: string,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\ttotal_processed: sql`total_processed + ${processed}`,\n\t\t\ttotal_errors: sql`total_errors + ${errors}`,\n\t\t\t...(lastError\n\t\t\t\t? { last_error: lastError, last_error_at: new Date() }\n\t\t\t\t: {}),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function updateSubgraphHandlerPath(\n\tdb: Kysely<Database>,\n\tname: string,\n\thandlerPath: string,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({ handler_path: handlerPath, updated_at: new Date() })\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function deleteSubgraph(\n\tdb: Kysely<Database>,\n\tname: string,\n\taccountId?: string,\n): Promise<Subgraph | null> {\n\tconst subgraph = await getSubgraph(db, name, accountId);\n\tif (!subgraph) return null;\n\n\t// Use stored schema_name if available, otherwise compute\n\tconst schemaName = subgraph.schema_name ?? pgSchemaName(name);\n\n\t// Drop the subgraph's schema (CASCADE drops all tables within)\n\tawait sql`DROP SCHEMA IF EXISTS ${sql.raw(`\"${schemaName}\"`)} CASCADE`.execute(\n\t\tdb,\n\t);\n\n\t// Remove from registry\n\tawait db.deleteFrom(\"subgraphs\").where(\"id\", \"=\", subgraph.id).execute();\n\n\treturn subgraph;\n}\n"
5
+ "import { type RawBuilder, sql } from \"kysely\";\n\n/**\n * Safely encode a JS value as a JSONB literal for Kysely inserts/updates.\n * Kysely + postgres.js double-encodes JSON when using parameterized queries\n * with ::jsonb casts. This uses sql.raw to inline a properly escaped literal.\n *\n * Generic parameter lets callers set the RawBuilder's output type so they\n * don't need to cast at the insert site. Default is `unknown` — widen at\n * the call site when the column type is narrower, e.g. `jsonb<MyShape>(...)`.\n */\nexport function jsonb<T = unknown>(value: T): RawBuilder<T> {\n\tconst escaped = JSON.stringify(value, (_k, v) =>\n\t\ttypeof v === \"bigint\" ? v.toString() : v,\n\t).replace(/'/g, \"''\");\n\treturn sql`${sql.raw(`'${escaped}'::jsonb`)}`;\n}\n\n/**\n * Safely parse a JSONB value from the database.\n * Handles double-encoded strings where postgres.js returns a JSON string\n * instead of a parsed object.\n */\nexport function parseJsonb<T = unknown>(value: unknown): T {\n\tif (typeof value === \"string\") {\n\t\ttry {\n\t\t\treturn JSON.parse(value) as T;\n\t\t} catch {\n\t\t\treturn value as T;\n\t\t}\n\t}\n\treturn (value ?? {}) as T;\n}\n",
6
+ "import { type Kysely, sql } from \"kysely\";\nimport { jsonb } from \"../jsonb.ts\";\nimport type { Database, Subgraph } from \"../types.ts\";\n\n/**\n * Convert a subgraph name to its PostgreSQL schema name.\n * Every tenant DB has its own isolated schema namespace, so there's no\n * account-prefix disambiguation needed — every subgraph within a tenant\n * just maps to `subgraph_{safeName}`.\n */\nexport function pgSchemaName(subgraphName: string): string {\n\tconst safeName = subgraphName.replace(/-/g, \"_\");\n\treturn `subgraph_${safeName}`;\n}\n\nexport async function registerSubgraph(\n\tdb: Kysely<Database>,\n\tdata: {\n\t\tname: string;\n\t\tversion: string;\n\t\tdefinition: Record<string, unknown>;\n\t\tschemaHash: string;\n\t\thandlerPath: string;\n\t\tapiKeyId?: string;\n\t\taccountId?: string;\n\t\tschemaName?: string;\n\t\tstartBlock?: number;\n\t\thandlerCode?: string;\n\t\tsourceCode?: string;\n\t},\n): Promise<Subgraph> {\n\treturn await db\n\t\t.insertInto(\"subgraphs\")\n\t\t.values({\n\t\t\tname: data.name,\n\t\t\tversion: data.version,\n\t\t\tdefinition: jsonb<Record<string, unknown>>(data.definition),\n\t\t\tschema_hash: data.schemaHash,\n\t\t\thandler_path: data.handlerPath,\n\t\t\taccount_id: data.accountId ?? \"\",\n\t\t\thandler_code: data.handlerCode ?? null,\n\t\t\tsource_code: data.sourceCode ?? null,\n\t\t\tschema_name: data.schemaName ?? null,\n\t\t\tstart_block: data.startBlock ?? 0,\n\t\t})\n\t\t.onConflict((oc) =>\n\t\t\toc.columns([\"name\", \"account_id\"]).doUpdateSet({\n\t\t\t\tversion: data.version,\n\t\t\t\tdefinition: jsonb<Record<string, unknown>>(data.definition),\n\t\t\t\tschema_hash: data.schemaHash,\n\t\t\t\thandler_path: data.handlerPath,\n\t\t\t\thandler_code: data.handlerCode ?? null,\n\t\t\t\tsource_code: data.sourceCode ?? null,\n\t\t\t\tschema_name: data.schemaName ?? null,\n\t\t\t\tstart_block: data.startBlock ?? 0,\n\t\t\t\tupdated_at: new Date(),\n\t\t\t}),\n\t\t)\n\t\t.returningAll()\n\t\t.executeTakeFirstOrThrow();\n}\n\nexport async function getSubgraph(\n\tdb: Kysely<Database>,\n\tname: string,\n\taccountId?: string,\n): Promise<Subgraph | null> {\n\tlet query = db.selectFrom(\"subgraphs\").selectAll().where(\"name\", \"=\", name);\n\n\tif (accountId) {\n\t\tquery = query.where(\"account_id\", \"=\", accountId);\n\t}\n\n\treturn (await query.executeTakeFirst()) ?? null;\n}\n\nexport async function listSubgraphs(\n\tdb: Kysely<Database>,\n\taccountId?: string,\n): Promise<Subgraph[]> {\n\tlet query = db.selectFrom(\"subgraphs\").selectAll();\n\tif (accountId) {\n\t\tquery = query.where(\"account_id\", \"=\", accountId);\n\t}\n\treturn query.execute();\n}\n\nexport async function updateSubgraphStatus(\n\tdb: Kysely<Database>,\n\tname: string,\n\tstatus: string,\n\tlastProcessedBlock?: number,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\tstatus,\n\t\t\t...(lastProcessedBlock !== undefined\n\t\t\t\t? { last_processed_block: lastProcessedBlock }\n\t\t\t\t: {}),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function recordSubgraphProcessed(\n\tdb: Kysely<Database>,\n\tname: string,\n\tprocessed: number,\n\terrors: number,\n\tlastError?: string,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({\n\t\t\ttotal_processed: sql`total_processed + ${processed}`,\n\t\t\ttotal_errors: sql`total_errors + ${errors}`,\n\t\t\t...(lastError\n\t\t\t\t? { last_error: lastError, last_error_at: new Date() }\n\t\t\t\t: {}),\n\t\t\tupdated_at: new Date(),\n\t\t})\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function updateSubgraphHandlerPath(\n\tdb: Kysely<Database>,\n\tname: string,\n\thandlerPath: string,\n): Promise<void> {\n\tawait db\n\t\t.updateTable(\"subgraphs\")\n\t\t.set({ handler_path: handlerPath, updated_at: new Date() })\n\t\t.where(\"name\", \"=\", name)\n\t\t.execute();\n}\n\nexport async function deleteSubgraph(\n\tdb: Kysely<Database>,\n\tname: string,\n\taccountId?: string,\n): Promise<Subgraph | null> {\n\tconst subgraph = await getSubgraph(db, name, accountId);\n\tif (!subgraph) return null;\n\n\t// Use stored schema_name if available, otherwise compute\n\tconst schemaName = subgraph.schema_name ?? pgSchemaName(name);\n\n\t// Drop the subgraph's schema (CASCADE drops all tables within)\n\tawait sql`DROP SCHEMA IF EXISTS ${sql.raw(`\"${schemaName}\"`)} CASCADE`.execute(\n\t\tdb,\n\t);\n\n\t// Remove from registry\n\tawait db.deleteFrom(\"subgraphs\").where(\"id\", \"=\", subgraph.id).execute();\n\n\treturn subgraph;\n}\n"
7
7
  ],
8
- "mappings": "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",
9
- "debugId": "AE963057007E387C64756E2164756E21",
8
+ "mappings": "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",
9
+ "debugId": "D8D245F7C02FE78964756E2164756E21",
10
10
  "names": []
11
11
  }
@@ -60,10 +60,6 @@ interface SubgraphsTable {
60
60
  handler_code: string | null;
61
61
  source_code: string | null;
62
62
  project_id: string | null;
63
- is_public: Generated<boolean>;
64
- tags: Generated<string[]>;
65
- description: string | null;
66
- forked_from_id: string | null;
67
63
  created_at: Generated<Date>;
68
64
  updated_at: Generated<Date>;
69
65
  }
@@ -98,6 +94,7 @@ interface AccountsTable {
98
94
  bio: string | null;
99
95
  avatar_url: string | null;
100
96
  slug: string | null;
97
+ stripe_customer_id: string | null;
101
98
  created_at: Generated<Date>;
102
99
  }
103
100
  interface SessionsTable {
@@ -123,6 +120,7 @@ interface MagicLinksTable {
123
120
  }
124
121
  interface UsageDailyTable {
125
122
  account_id: string;
123
+ tenant_id: string | null;
126
124
  date: string;
127
125
  api_requests: Generated<number>;
128
126
  deliveries: Generated<number>;
@@ -249,83 +247,6 @@ interface ChatMessagesTable {
249
247
  metadata: unknown | null;
250
248
  created_at: Generated<Date>;
251
249
  }
252
- interface WorkflowDefinitionsTable {
253
- id: Generated<string>;
254
- name: string;
255
- version: Generated<string>;
256
- status: Generated<string>;
257
- trigger_type: string;
258
- trigger_config: unknown;
259
- handler_path: string;
260
- source_code: string | null;
261
- retries_config: unknown | null;
262
- timeout_ms: number | null;
263
- api_key_id: string;
264
- project_id: string | null;
265
- created_at: Generated<Date>;
266
- updated_at: Generated<Date>;
267
- }
268
- interface WorkflowRunsTable {
269
- id: Generated<string>;
270
- definition_id: string;
271
- status: Generated<string>;
272
- trigger_type: string;
273
- trigger_data: unknown | null;
274
- dedup_key: string | null;
275
- error: string | null;
276
- started_at: Date | null;
277
- completed_at: Date | null;
278
- duration_ms: number | null;
279
- total_ai_tokens: Generated<number>;
280
- created_at: Generated<Date>;
281
- }
282
- interface WorkflowStepsTable {
283
- id: Generated<string>;
284
- run_id: string;
285
- step_index: number;
286
- step_id: string;
287
- step_type: string;
288
- status: Generated<string>;
289
- input: unknown | null;
290
- output: unknown | null;
291
- error: string | null;
292
- retry_count: Generated<number>;
293
- ai_tokens_used: Generated<number>;
294
- started_at: Date | null;
295
- completed_at: Date | null;
296
- duration_ms: number | null;
297
- memo_key: string | null;
298
- parent_step_id: string | null;
299
- created_at: Generated<Date>;
300
- }
301
- interface WorkflowQueueTable {
302
- id: Generated<string>;
303
- run_id: string;
304
- status: Generated<string>;
305
- attempts: Generated<number>;
306
- max_attempts: Generated<number>;
307
- scheduled_for: Generated<Date>;
308
- locked_at: Date | null;
309
- locked_by: string | null;
310
- error: string | null;
311
- created_at: Generated<Date>;
312
- completed_at: Date | null;
313
- }
314
- interface WorkflowSchedulesTable {
315
- id: Generated<string>;
316
- definition_id: string;
317
- cron_expr: string;
318
- timezone: Generated<string>;
319
- next_run_at: Date;
320
- last_run_at: Date | null;
321
- enabled: Generated<boolean>;
322
- created_at: Generated<Date>;
323
- }
324
- interface WorkflowCursorsTable {
325
- name: string;
326
- block_height: Generated<number>;
327
- updated_at: Generated<Date>;
328
- }
329
250
  interface Database {
330
251
  blocks: BlocksTable;
331
252
  transactions: TransactionsTable;
@@ -351,16 +272,10 @@ interface Database {
351
272
  team_invitations: TeamInvitationsTable;
352
273
  chat_sessions: ChatSessionsTable;
353
274
  chat_messages: ChatMessagesTable;
354
- workflow_definitions: WorkflowDefinitionsTable;
355
- workflow_runs: WorkflowRunsTable;
356
- workflow_steps: WorkflowStepsTable;
357
- workflow_queue: WorkflowQueueTable;
358
- workflow_schedules: WorkflowSchedulesTable;
359
- workflow_cursors: WorkflowCursorsTable;
360
- workflow_signer_secrets: WorkflowSignerSecretsTable;
361
- workflow_budgets: WorkflowBudgetsTable;
362
275
  tenants: TenantsTable;
363
276
  tenant_usage_monthly: TenantUsageMonthlyTable;
277
+ tenant_compute_addons: TenantComputeAddonsTable;
278
+ account_spend_caps: AccountSpendCapsTable;
364
279
  provisioning_audit_log: ProvisioningAuditLogTable;
365
280
  }
366
281
  type TenantStatus = "provisioning" | "active" | "suspended" | "error" | "deleted";
@@ -383,9 +298,9 @@ interface TenantsTable {
383
298
  service_key_enc: Buffer;
384
299
  api_url_internal: string;
385
300
  api_url_public: string;
386
- trial_ends_at: Date;
387
301
  suspended_at: Date | null;
388
302
  last_health_check_at: Date | null;
303
+ last_active_at: Generated<Date>;
389
304
  service_gen: Generated<number>;
390
305
  anon_gen: Generated<number>;
391
306
  project_id: string | null;
@@ -403,6 +318,29 @@ interface TenantUsageMonthlyTable {
403
318
  first_at: Generated<Date>;
404
319
  last_at: Generated<Date>;
405
320
  }
321
+ interface TenantComputeAddonsTable {
322
+ id: Generated<string>;
323
+ tenant_id: string;
324
+ memory_mb_delta: Generated<number>;
325
+ cpu_delta: Generated<number | string>;
326
+ storage_mb_delta: Generated<number>;
327
+ effective_from: Generated<Date>;
328
+ effective_until: Date | null;
329
+ stripe_subscription_item_id: string | null;
330
+ created_at: Generated<Date>;
331
+ }
332
+ type TenantComputeAddon = Selectable<TenantComputeAddonsTable>;
333
+ interface AccountSpendCapsTable {
334
+ account_id: string;
335
+ monthly_cap_cents: number | null;
336
+ compute_cap_cents: number | null;
337
+ storage_cap_cents: number | null;
338
+ ai_cap_cents: number | null;
339
+ alert_threshold_pct: Generated<number>;
340
+ alert_sent_at: Date | null;
341
+ frozen_at: Date | null;
342
+ updated_at: Generated<Date>;
343
+ }
406
344
  type ProvisioningAuditEvent = "provision.start" | "provision.success" | "provision.failure" | "suspend" | "resume" | "resize" | "keys.rotate" | "bastion.key.upload" | "bastion.key.revoke" | "teardown";
407
345
  type ProvisioningAuditStatus = "ok" | "error";
408
346
  interface ProvisioningAuditLogTable {
@@ -417,62 +355,25 @@ interface ProvisioningAuditLogTable {
417
355
  error: string | null;
418
356
  created_at: Generated<Date>;
419
357
  }
420
- interface WorkflowBudgetsTable {
421
- id: Generated<string>;
422
- workflow_definition_id: string;
423
- /** Period key: "daily:YYYY-MM-DD" | "weekly:YYYY-Www" | "per-run:<uuid>". */
424
- period: string;
425
- ai_usd_used: Generated<string>;
426
- ai_tokens_used: Generated<string>;
427
- chain_microstx_used: Generated<string>;
428
- chain_tx_count: Generated<number>;
429
- run_count: Generated<number>;
430
- step_count: Generated<number>;
431
- reset_at: Date;
432
- created_at: Generated<Date>;
433
- updated_at: Generated<Date>;
434
- }
435
- interface WorkflowSignerSecretsTable {
436
- id: Generated<string>;
437
- account_id: string;
438
- name: string;
439
- /** AES-GCM ciphertext bytes produced by the runner's KMS on write. */
440
- encrypted_value: Buffer;
441
- created_at: Generated<Date>;
442
- updated_at: Generated<Date>;
443
- }
444
- type WorkflowDefinition = Selectable<WorkflowDefinitionsTable>;
445
- type WorkflowRun = Selectable<WorkflowRunsTable>;
446
- type WorkflowStep = Selectable<WorkflowStepsTable>;
447
- /** Bump the patch digit of a semver string. Falls back to "1.0.1" on malformed input. */
448
- declare function bumpPatch(version: string): string;
449
- declare function listWorkflowDefinitions(db: Kysely<Database>, apiKeyIds?: string[]): Promise<WorkflowDefinition[]>;
450
- declare function getWorkflowDefinition(db: Kysely<Database>, name: string, apiKeyIds?: string[]): Promise<WorkflowDefinition | null>;
451
- declare function upsertWorkflowDefinition(db: Kysely<Database>, data: {
452
- name: string
453
- triggerType: string
454
- triggerConfig: Record<string, unknown>
455
- handlerPath: string
456
- apiKeyId: string
457
- projectId?: string
458
- retriesConfig?: Record<string, unknown>
459
- timeoutMs?: number
460
- sourceCode?: string
461
- expectedVersion?: string
462
- }): Promise<WorkflowDefinition>;
463
- declare function updateWorkflowStatus(db: Kysely<Database>, name: string, apiKeyId: string, status: string): Promise<void>;
464
- declare function deleteWorkflowDefinition(db: Kysely<Database>, name: string, apiKeyId: string): Promise<void>;
465
- declare function createWorkflowRun(db: Kysely<Database>, data: {
466
- definitionId: string
467
- triggerType: string
468
- triggerData?: Record<string, unknown>
469
- dedupKey?: string
470
- }): Promise<WorkflowRun>;
471
- declare function getWorkflowRun(db: Kysely<Database>, runId: string): Promise<WorkflowRun | null>;
472
- declare function listWorkflowRuns(db: Kysely<Database>, definitionId: string, params?: {
473
- status?: string
474
- limit?: number
475
- offset?: number
476
- }): Promise<WorkflowRun[]>;
477
- declare function getWorkflowSteps(db: Kysely<Database>, runId: string): Promise<WorkflowStep[]>;
478
- export { upsertWorkflowDefinition, updateWorkflowStatus, listWorkflowRuns, listWorkflowDefinitions, getWorkflowSteps, getWorkflowRun, getWorkflowDefinition, deleteWorkflowDefinition, createWorkflowRun, bumpPatch };
358
+ /**
359
+ * Compute add-ons — extras on top of a plan's base spec.
360
+ *
361
+ * Effective compute is NEVER derived from just the `tenants.plan`
362
+ * column — always run `computeEffectiveCompute(tenantId, planBase)`
363
+ * to fold in active add-ons. Provisioning, resize, and Stripe metering
364
+ * all share this source of truth.
365
+ */
366
+ /** Active = open-ended (effective_until IS NULL) OR not yet expired. */
367
+ declare function listActiveAddonsForTenant(db: Kysely<Database>, tenantId: string, now?: Date): Promise<TenantComputeAddon[]>;
368
+ interface ComputeSpec {
369
+ cpus: number;
370
+ memoryMb: number;
371
+ storageLimitMb: number;
372
+ }
373
+ /**
374
+ * Apply active add-ons on top of a base spec. `storageLimitMb` of -1
375
+ * (enterprise unlimited) passes through unchanged — add-ons don't
376
+ * further modify unlimited storage.
377
+ */
378
+ declare function computeEffectiveCompute(db: Kysely<Database>, tenantId: string, base: ComputeSpec, now?: Date): Promise<ComputeSpec>;
379
+ export { listActiveAddonsForTenant, computeEffectiveCompute, ComputeSpec };
@@ -0,0 +1,47 @@
1
+ import { createRequire } from "node:module";
2
+ var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true,
12
+ configurable: true,
13
+ set: __exportSetter.bind(all, name)
14
+ });
15
+ };
16
+
17
+ // src/db/queries/tenant-compute-addons.ts
18
+ import { sql } from "kysely";
19
+ async function listActiveAddonsForTenant(db, tenantId, now = new Date) {
20
+ return db.selectFrom("tenant_compute_addons").selectAll().where("tenant_id", "=", tenantId).where("effective_from", "<=", now).where((eb) => eb.or([
21
+ eb("effective_until", "is", null),
22
+ eb("effective_until", ">", now)
23
+ ])).execute();
24
+ }
25
+ async function computeEffectiveCompute(db, tenantId, base, now = new Date) {
26
+ const row = await db.selectFrom("tenant_compute_addons").select([
27
+ sql`coalesce(sum(memory_mb_delta), 0)`.as("mem_delta"),
28
+ sql`coalesce(sum(cpu_delta), 0)`.as("cpu_delta"),
29
+ sql`coalesce(sum(storage_mb_delta), 0)`.as("stor_delta")
30
+ ]).where("tenant_id", "=", tenantId).where("effective_from", "<=", now).where((eb) => eb.or([
31
+ eb("effective_until", "is", null),
32
+ eb("effective_until", ">", now)
33
+ ])).executeTakeFirst();
34
+ if (!row)
35
+ return base;
36
+ const cpus = base.cpus + Number(row.cpu_delta ?? 0);
37
+ const memoryMb = base.memoryMb + Number(row.mem_delta ?? 0);
38
+ const storageLimitMb = base.storageLimitMb === -1 ? -1 : base.storageLimitMb + Number(row.stor_delta ?? 0);
39
+ return { cpus, memoryMb, storageLimitMb };
40
+ }
41
+ export {
42
+ listActiveAddonsForTenant,
43
+ computeEffectiveCompute
44
+ };
45
+
46
+ //# debugId=70D8508BE398EADC64756E2164756E21
47
+ //# sourceMappingURL=tenant-compute-addons.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/db/queries/tenant-compute-addons.ts"],
4
+ "sourcesContent": [
5
+ "import { type Kysely, sql } from \"kysely\";\nimport type { Database, TenantComputeAddon } from \"../types.ts\";\n\n/**\n * Compute add-ons — extras on top of a plan's base spec.\n *\n * Effective compute is NEVER derived from just the `tenants.plan`\n * column — always run `computeEffectiveCompute(tenantId, planBase)`\n * to fold in active add-ons. Provisioning, resize, and Stripe metering\n * all share this source of truth.\n */\n\n/** Active = open-ended (effective_until IS NULL) OR not yet expired. */\nexport async function listActiveAddonsForTenant(\n\tdb: Kysely<Database>,\n\ttenantId: string,\n\tnow: Date = new Date(),\n): Promise<TenantComputeAddon[]> {\n\treturn db\n\t\t.selectFrom(\"tenant_compute_addons\")\n\t\t.selectAll()\n\t\t.where(\"tenant_id\", \"=\", tenantId)\n\t\t.where(\"effective_from\", \"<=\", now)\n\t\t.where((eb) =>\n\t\t\teb.or([\n\t\t\t\teb(\"effective_until\", \"is\", null),\n\t\t\t\teb(\"effective_until\", \">\", now),\n\t\t\t]),\n\t\t)\n\t\t.execute();\n}\n\nexport interface ComputeSpec {\n\tcpus: number;\n\tmemoryMb: number;\n\tstorageLimitMb: number;\n}\n\n/**\n * Apply active add-ons on top of a base spec. `storageLimitMb` of -1\n * (enterprise unlimited) passes through unchanged — add-ons don't\n * further modify unlimited storage.\n */\nexport async function computeEffectiveCompute(\n\tdb: Kysely<Database>,\n\ttenantId: string,\n\tbase: ComputeSpec,\n\tnow: Date = new Date(),\n): Promise<ComputeSpec> {\n\tconst row = await db\n\t\t.selectFrom(\"tenant_compute_addons\")\n\t\t.select([\n\t\t\tsql<number>`coalesce(sum(memory_mb_delta), 0)`.as(\"mem_delta\"),\n\t\t\tsql<string>`coalesce(sum(cpu_delta), 0)`.as(\"cpu_delta\"),\n\t\t\tsql<number>`coalesce(sum(storage_mb_delta), 0)`.as(\"stor_delta\"),\n\t\t])\n\t\t.where(\"tenant_id\", \"=\", tenantId)\n\t\t.where(\"effective_from\", \"<=\", now)\n\t\t.where((eb) =>\n\t\t\teb.or([\n\t\t\t\teb(\"effective_until\", \"is\", null),\n\t\t\t\teb(\"effective_until\", \">\", now),\n\t\t\t]),\n\t\t)\n\t\t.executeTakeFirst();\n\n\tif (!row) return base;\n\n\tconst cpus = base.cpus + Number(row.cpu_delta ?? 0);\n\tconst memoryMb = base.memoryMb + Number(row.mem_delta ?? 0);\n\tconst storageLimitMb =\n\t\tbase.storageLimitMb === -1\n\t\t\t? -1\n\t\t\t: base.storageLimitMb + Number(row.stor_delta ?? 0);\n\n\treturn { cpus, memoryMb, storageLimitMb };\n}\n"
6
+ ],
7
+ "mappings": ";;;;;;;;;;;;;;;;;AAAA;AAaA,eAAsB,yBAAyB,CAC9C,IACA,UACA,MAAY,IAAI,MACgB;AAAA,EAChC,OAAO,GACL,WAAW,uBAAuB,EAClC,UAAU,EACV,MAAM,aAAa,KAAK,QAAQ,EAChC,MAAM,kBAAkB,MAAM,GAAG,EACjC,MAAM,CAAC,OACP,GAAG,GAAG;AAAA,IACL,GAAG,mBAAmB,MAAM,IAAI;AAAA,IAChC,GAAG,mBAAmB,KAAK,GAAG;AAAA,EAC/B,CAAC,CACF,EACC,QAAQ;AAAA;AAcX,eAAsB,uBAAuB,CAC5C,IACA,UACA,MACA,MAAY,IAAI,MACO;AAAA,EACvB,MAAM,MAAM,MAAM,GAChB,WAAW,uBAAuB,EAClC,OAAO;AAAA,IACP,uCAA+C,GAAG,WAAW;AAAA,IAC7D,iCAAyC,GAAG,WAAW;AAAA,IACvD,wCAAgD,GAAG,YAAY;AAAA,EAChE,CAAC,EACA,MAAM,aAAa,KAAK,QAAQ,EAChC,MAAM,kBAAkB,MAAM,GAAG,EACjC,MAAM,CAAC,OACP,GAAG,GAAG;AAAA,IACL,GAAG,mBAAmB,MAAM,IAAI;AAAA,IAChC,GAAG,mBAAmB,KAAK,GAAG;AAAA,EAC/B,CAAC,CACF,EACC,iBAAiB;AAAA,EAEnB,IAAI,CAAC;AAAA,IAAK,OAAO;AAAA,EAEjB,MAAM,OAAO,KAAK,OAAO,OAAO,IAAI,aAAa,CAAC;AAAA,EAClD,MAAM,WAAW,KAAK,WAAW,OAAO,IAAI,aAAa,CAAC;AAAA,EAC1D,MAAM,iBACL,KAAK,mBAAmB,KACrB,KACA,KAAK,iBAAiB,OAAO,IAAI,cAAc,CAAC;AAAA,EAEpD,OAAO,EAAE,MAAM,UAAU,eAAe;AAAA;",
8
+ "debugId": "70D8508BE398EADC64756E2164756E21",
9
+ "names": []
10
+ }