@secondlayer/shared 0.12.3 → 1.1.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 (70) hide show
  1. package/README.md +5 -7
  2. package/dist/src/constants.d.ts +1 -1
  3. package/dist/src/constants.js.map +2 -2
  4. package/dist/src/crypto/secrets.d.ts +5 -0
  5. package/dist/src/crypto/secrets.js +69 -0
  6. package/dist/src/crypto/secrets.js.map +10 -0
  7. package/dist/src/db/index.d.ts +37 -64
  8. package/dist/src/db/index.js +2 -2
  9. package/dist/src/db/index.js.map +2 -2
  10. package/dist/src/db/queries/accounts.d.ts +30 -51
  11. package/dist/src/db/queries/integrity.d.ts +30 -51
  12. package/dist/src/db/queries/marketplace.d.ts +30 -51
  13. package/dist/src/db/queries/projects.d.ts +30 -51
  14. package/dist/src/db/queries/subgraph-gaps.d.ts +30 -51
  15. package/dist/src/db/queries/subgraphs.d.ts +31 -51
  16. package/dist/src/db/queries/subgraphs.js +3 -1
  17. package/dist/src/db/queries/subgraphs.js.map +3 -3
  18. package/dist/src/db/queries/usage.d.ts +31 -56
  19. package/dist/src/db/queries/usage.js +1 -19
  20. package/dist/src/db/queries/usage.js.map +4 -4
  21. package/dist/src/db/queries/workflows.d.ts +35 -53
  22. package/dist/src/db/queries/workflows.js +130 -13
  23. package/dist/src/db/queries/workflows.js.map +5 -4
  24. package/dist/src/db/schema.d.ts +37 -64
  25. package/dist/src/errors.d.ts +19 -50
  26. package/dist/src/errors.js +28 -45
  27. package/dist/src/errors.js.map +3 -3
  28. package/dist/src/index.d.ts +59 -256
  29. package/dist/src/index.js +32 -234
  30. package/dist/src/index.js.map +7 -9
  31. package/dist/src/lib/plans.d.ts +0 -1
  32. package/dist/src/lib/plans.js +1 -2
  33. package/dist/src/lib/plans.js.map +3 -3
  34. package/dist/src/node/local-client.d.ts +30 -51
  35. package/dist/src/pricing.d.ts +28 -0
  36. package/dist/src/pricing.js +47 -0
  37. package/dist/src/pricing.js.map +10 -0
  38. package/dist/src/queue/listener.d.ts +1 -18
  39. package/dist/src/queue/listener.js +2 -12
  40. package/dist/src/queue/listener.js.map +3 -3
  41. package/dist/src/schemas/filters.d.ts +3 -3
  42. package/dist/src/schemas/filters.js +3 -3
  43. package/dist/src/schemas/filters.js.map +3 -3
  44. package/dist/src/schemas/index.d.ts +5 -100
  45. package/dist/src/schemas/index.js +4 -88
  46. package/dist/src/schemas/index.js.map +5 -6
  47. package/dist/src/schemas/subgraphs.d.ts +2 -0
  48. package/dist/src/schemas/subgraphs.js +2 -1
  49. package/dist/src/schemas/subgraphs.js.map +3 -3
  50. package/dist/src/schemas/workflows.d.ts +4 -0
  51. package/dist/src/schemas/workflows.js +5 -1
  52. package/dist/src/schemas/workflows.js.map +3 -3
  53. package/dist/src/types.d.ts +1 -53
  54. package/migrations/0030_workflow_source_code.ts +21 -0
  55. package/migrations/0031_subgraph_source_code.ts +18 -0
  56. package/migrations/0032_drop_streams_tables.ts +43 -0
  57. package/migrations/0033_workflow_steps_memo_key.ts +54 -0
  58. package/migrations/0034_workflow_signer_secrets.ts +42 -0
  59. package/migrations/0035_workflow_budgets.ts +53 -0
  60. package/migrations/0036_tx_confirmed_notify.ts +36 -0
  61. package/package.json +11 -15
  62. package/dist/src/db/queries/metrics.d.ts +0 -419
  63. package/dist/src/db/queries/metrics.js +0 -55
  64. package/dist/src/db/queries/metrics.js.map +0 -10
  65. package/dist/src/queue/index.d.ts +0 -50
  66. package/dist/src/queue/index.js +0 -184
  67. package/dist/src/queue/index.js.map +0 -12
  68. package/dist/src/queue/recovery.d.ts +0 -14
  69. package/dist/src/queue/recovery.js +0 -108
  70. package/dist/src/queue/recovery.js.map +0 -12
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @secondlayer/shared
2
2
 
3
- Foundational utilities for Second Layer services: DB layer (Kysely+Postgres), job queue, Zod schemas, HMAC signing, Stacks node clients.
3
+ Foundational utilities for Second Layer services: DB layer (Kysely+Postgres), Zod schemas, HMAC signing, Stacks node clients.
4
4
 
5
5
  ## Testing
6
6
 
@@ -9,7 +9,7 @@ Foundational utilities for Second Layer services: DB layer (Kysely+Postgres), jo
9
9
  bun test
10
10
 
11
11
  # Run with database
12
- DATABASE_URL=postgresql://postgres:postgres@localhost:5432/streams_test bun test
12
+ DATABASE_URL=postgresql://postgres:postgres@localhost:5432/secondlayer_test bun test
13
13
  ```
14
14
 
15
15
  ## Migrations
@@ -24,16 +24,14 @@ DATABASE_URL=... bun run migrate
24
24
  |------|-------------|
25
25
  | `@secondlayer/shared` | Core utilities |
26
26
  | `@secondlayer/shared/db` | Kysely database layer |
27
- | `@secondlayer/shared/db/queries/*` | Query helpers (integrity, metrics, accounts, usage, subgraphs) |
27
+ | `@secondlayer/shared/db/queries/*` | Query helpers (integrity, accounts, usage, subgraphs, marketplace, projects, subgraph-gaps, workflows) |
28
28
  | `@secondlayer/shared/db/schema` | Database schema |
29
29
  | `@secondlayer/shared/db/jsonb` | JSONB helpers |
30
30
  | `@secondlayer/shared/schemas` | Zod schemas |
31
- | `@secondlayer/shared/schemas/filters` | Stream filter schemas |
31
+ | `@secondlayer/shared/schemas/filters` | Event filter schemas |
32
32
  | `@secondlayer/shared/schemas/subgraphs` | Subgraph schemas |
33
33
  | `@secondlayer/shared/types` | Shared TypeScript types |
34
- | `@secondlayer/shared/queue` | Job queue |
35
- | `@secondlayer/shared/queue/listener` | Queue listener |
36
- | `@secondlayer/shared/queue/recovery` | Queue recovery |
34
+ | `@secondlayer/shared/queue/listener` | Postgres LISTEN/NOTIFY helper (used for block notifications) |
37
35
  | `@secondlayer/shared/env` | Environment config |
38
36
  | `@secondlayer/shared/logger` | Logger |
39
37
  | `@secondlayer/shared/errors` | Error types |
@@ -1,2 +1,2 @@
1
- declare const ADMIN_EMAILS: unknown;
1
+ declare const ADMIN_EMAILS: string[];
2
2
  export { ADMIN_EMAILS };
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/constants.ts"],
4
4
  "sourcesContent": [
5
- "export const ADMIN_EMAILS = [\"ryan.waits@gmail.com\"];\n"
5
+ "export const ADMIN_EMAILS: string[] = [\"ryan.waits@gmail.com\"];\n"
6
6
  ],
7
- "mappings": ";;;;;;;;;;;;;;;;;AAAO,IAAM,eAAe,CAAC,sBAAsB;",
7
+ "mappings": ";;;;;;;;;;;;;;;;;AAAO,IAAM,eAAyB,CAAC,sBAAsB;",
8
8
  "debugId": "171573A31D5D2E7964756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -0,0 +1,5 @@
1
+ declare function encryptSecret(plaintext: string): Buffer;
2
+ declare function decryptSecret(envelope: Buffer): string;
3
+ /** Generate a fresh 32-byte hex key suitable for `SECONDLAYER_SECRETS_KEY`. */
4
+ declare function generateSecretsKey(): string;
5
+ export { generateSecretsKey, encryptSecret, decryptSecret };
@@ -0,0 +1,69 @@
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/crypto/secrets.ts
18
+ import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
19
+ var KEY_ENV = "SECONDLAYER_SECRETS_KEY";
20
+ var IV_LEN = 12;
21
+ var TAG_LEN = 16;
22
+ function loadKey() {
23
+ const hex = process.env[KEY_ENV];
24
+ if (!hex) {
25
+ throw new Error(`${KEY_ENV} not set. Generate one with: openssl rand -hex 32`);
26
+ }
27
+ const key = Buffer.from(hex, "hex");
28
+ if (key.length !== 32) {
29
+ throw new Error(`${KEY_ENV} must be 32 bytes hex (got ${key.length})`);
30
+ }
31
+ return key;
32
+ }
33
+ var _cachedKey = null;
34
+ function getKey() {
35
+ if (!_cachedKey)
36
+ _cachedKey = loadKey();
37
+ return _cachedKey;
38
+ }
39
+ function encryptSecret(plaintext) {
40
+ const key = getKey();
41
+ const iv = randomBytes(IV_LEN);
42
+ const cipher = createCipheriv("aes-256-gcm", key, iv);
43
+ const ciphertext = Buffer.concat([
44
+ cipher.update(plaintext, "utf8"),
45
+ cipher.final()
46
+ ]);
47
+ const tag = cipher.getAuthTag();
48
+ return Buffer.concat([iv, tag, ciphertext]);
49
+ }
50
+ function decryptSecret(envelope) {
51
+ const key = getKey();
52
+ const iv = envelope.subarray(0, IV_LEN);
53
+ const tag = envelope.subarray(IV_LEN, IV_LEN + TAG_LEN);
54
+ const ciphertext = envelope.subarray(IV_LEN + TAG_LEN);
55
+ const decipher = createDecipheriv("aes-256-gcm", key, iv);
56
+ decipher.setAuthTag(tag);
57
+ return decipher.update(ciphertext).toString("utf8") + decipher.final("utf8");
58
+ }
59
+ function generateSecretsKey() {
60
+ return randomBytes(32).toString("hex");
61
+ }
62
+ export {
63
+ generateSecretsKey,
64
+ encryptSecret,
65
+ decryptSecret
66
+ };
67
+
68
+ //# debugId=0FD7F496A1099A3864756E2164756E21
69
+ //# sourceMappingURL=secrets.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/crypto/secrets.ts"],
4
+ "sourcesContent": [
5
+ "import { createCipheriv, createDecipheriv, randomBytes } from \"node:crypto\";\n\n/**\n * AES-256-GCM symmetric envelope for workflow signer secrets.\n *\n * Ciphertext layout: `iv (12 bytes) || authTag (16 bytes) || ciphertext`\n *\n * The key comes from `SECONDLAYER_SECRETS_KEY` — 32 bytes hex. Callers must\n * load + cache the key once per process. Rotation strategy: when a customer\n * wants to rotate keys, re-encrypt all rows with the new key and swap the\n * env var. Not zero-downtime, but acceptable at v2 scale.\n *\n * For real KMS (AWS KMS, HashiCorp Vault, GCP KMS), wrap the same byte\n * layout behind an `EncryptSecret` / `DecryptSecret` interface in the\n * runner and swap the implementation at startup.\n */\n\nconst KEY_ENV = \"SECONDLAYER_SECRETS_KEY\";\nconst IV_LEN = 12;\nconst TAG_LEN = 16;\n\nfunction loadKey(): Buffer {\n\tconst hex = process.env[KEY_ENV];\n\tif (!hex) {\n\t\tthrow new Error(\n\t\t\t`${KEY_ENV} not set. Generate one with: openssl rand -hex 32`,\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\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"
6
+ ],
7
+ "mappings": ";;;;;;;;;;;;;;;;;AAAA;AAiBA,IAAM,UAAU;AAChB,IAAM,SAAS;AACf,IAAM,UAAU;AAEhB,SAAS,OAAO,GAAW;AAAA,EAC1B,MAAM,MAAM,QAAQ,IAAI;AAAA,EACxB,IAAI,CAAC,KAAK;AAAA,IACT,MAAM,IAAI,MACT,GAAG,0DACJ;AAAA,EACD;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;AAGD,SAAS,aAAa,CAAC,WAA2B;AAAA,EACxD,MAAM,MAAM,OAAO;AAAA,EACnB,MAAM,KAAK,YAAY,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,YAAY,EAAE,EAAE,SAAS,KAAK;AAAA;",
8
+ "debugId": "0FD7F496A1099A3864756E2164756E21",
9
+ "names": []
10
+ }
@@ -46,40 +46,6 @@ interface EventsTable {
46
46
  data: unknown;
47
47
  created_at: Generated<Date>;
48
48
  }
49
- interface StreamsTable {
50
- id: Generated<string>;
51
- name: string;
52
- status: Generated<string>;
53
- filters: unknown;
54
- options: Generated<unknown>;
55
- endpoint_url: string;
56
- signing_secret: string | null;
57
- api_key_id: string;
58
- project_id: string | null;
59
- created_at: Generated<Date>;
60
- updated_at: Generated<Date>;
61
- }
62
- interface StreamMetricsTable {
63
- stream_id: string;
64
- last_triggered_at: Date | null;
65
- last_triggered_block: number | null;
66
- total_deliveries: Generated<number>;
67
- failed_deliveries: Generated<number>;
68
- error_message: string | null;
69
- }
70
- interface JobsTable {
71
- id: Generated<string>;
72
- stream_id: string;
73
- block_height: number;
74
- status: Generated<string>;
75
- attempts: Generated<number>;
76
- locked_at: Date | null;
77
- locked_by: string | null;
78
- error: string | null;
79
- backfill: Generated<boolean>;
80
- created_at: Generated<Date>;
81
- completed_at: Date | null;
82
- }
83
49
  interface IndexProgressTable {
84
50
  network: string;
85
51
  last_indexed_block: Generated<number>;
@@ -87,19 +53,6 @@ interface IndexProgressTable {
87
53
  highest_seen_block: Generated<number>;
88
54
  updated_at: Generated<Date>;
89
55
  }
90
- interface DeliveriesTable {
91
- id: Generated<string>;
92
- stream_id: string;
93
- job_id: string | null;
94
- block_height: number;
95
- status: string;
96
- status_code: number | null;
97
- response_time_ms: number | null;
98
- attempts: Generated<number>;
99
- error: string | null;
100
- payload: unknown;
101
- created_at: Generated<Date>;
102
- }
103
56
  interface SubgraphsTable {
104
57
  id: Generated<string>;
105
58
  name: string;
@@ -120,6 +73,7 @@ interface SubgraphsTable {
120
73
  api_key_id: string | null;
121
74
  account_id: string;
122
75
  handler_code: string | null;
76
+ source_code: string | null;
123
77
  project_id: string | null;
124
78
  is_public: Generated<boolean>;
125
79
  tags: Generated<string[]>;
@@ -318,6 +272,7 @@ interface WorkflowDefinitionsTable {
318
272
  trigger_type: string;
319
273
  trigger_config: unknown;
320
274
  handler_path: string;
275
+ source_code: string | null;
321
276
  retries_config: unknown | null;
322
277
  timeout_ms: number | null;
323
278
  api_key_id: string;
@@ -354,6 +309,8 @@ interface WorkflowStepsTable {
354
309
  started_at: Date | null;
355
310
  completed_at: Date | null;
356
311
  duration_ms: number | null;
312
+ memo_key: string | null;
313
+ parent_step_id: string | null;
357
314
  created_at: Generated<Date>;
358
315
  }
359
316
  interface WorkflowQueueTable {
@@ -388,11 +345,7 @@ interface Database {
388
345
  blocks: BlocksTable;
389
346
  transactions: TransactionsTable;
390
347
  events: EventsTable;
391
- streams: StreamsTable;
392
- stream_metrics: StreamMetricsTable;
393
- jobs: JobsTable;
394
348
  index_progress: IndexProgressTable;
395
- deliveries: DeliveriesTable;
396
349
  subgraphs: SubgraphsTable;
397
350
  api_keys: ApiKeysTable;
398
351
  accounts: AccountsTable;
@@ -419,6 +372,32 @@ interface Database {
419
372
  workflow_queue: WorkflowQueueTable;
420
373
  workflow_schedules: WorkflowSchedulesTable;
421
374
  workflow_cursors: WorkflowCursorsTable;
375
+ workflow_signer_secrets: WorkflowSignerSecretsTable;
376
+ workflow_budgets: WorkflowBudgetsTable;
377
+ }
378
+ interface WorkflowBudgetsTable {
379
+ id: Generated<string>;
380
+ workflow_definition_id: string;
381
+ /** Period key: "daily:YYYY-MM-DD" | "weekly:YYYY-Www" | "per-run:<uuid>". */
382
+ period: string;
383
+ ai_usd_used: Generated<string>;
384
+ ai_tokens_used: Generated<string>;
385
+ chain_microstx_used: Generated<string>;
386
+ chain_tx_count: Generated<number>;
387
+ run_count: Generated<number>;
388
+ step_count: Generated<number>;
389
+ reset_at: Date;
390
+ created_at: Generated<Date>;
391
+ updated_at: Generated<Date>;
392
+ }
393
+ interface WorkflowSignerSecretsTable {
394
+ id: Generated<string>;
395
+ account_id: string;
396
+ name: string;
397
+ /** AES-GCM ciphertext bytes produced by the runner's KMS on write. */
398
+ encrypted_value: Buffer;
399
+ created_at: Generated<Date>;
400
+ updated_at: Generated<Date>;
422
401
  }
423
402
  type Block = Selectable<BlocksTable>;
424
403
  type InsertBlock = Insertable<BlocksTable>;
@@ -429,21 +408,9 @@ type UpdateTransaction = Updateable<TransactionsTable>;
429
408
  type Event = Selectable<EventsTable>;
430
409
  type InsertEvent = Insertable<EventsTable>;
431
410
  type UpdateEvent = Updateable<EventsTable>;
432
- type Stream = Selectable<StreamsTable>;
433
- type InsertStream = Insertable<StreamsTable>;
434
- type UpdateStreamRow = Updateable<StreamsTable>;
435
- type StreamMetrics = Selectable<StreamMetricsTable>;
436
- type InsertStreamMetrics = Insertable<StreamMetricsTable>;
437
- type UpdateStreamMetrics = Updateable<StreamMetricsTable>;
438
- type Job = Selectable<JobsTable>;
439
- type InsertJob = Insertable<JobsTable>;
440
- type UpdateJob = Updateable<JobsTable>;
441
411
  type IndexProgress = Selectable<IndexProgressTable>;
442
412
  type InsertIndexProgress = Insertable<IndexProgressTable>;
443
413
  type UpdateIndexProgress = Updateable<IndexProgressTable>;
444
- type Delivery = Selectable<DeliveriesTable>;
445
- type InsertDelivery = Insertable<DeliveriesTable>;
446
- type UpdateDelivery = Updateable<DeliveriesTable>;
447
414
  type Subgraph = Selectable<SubgraphsTable>;
448
415
  type InsertSubgraph = Insertable<SubgraphsTable>;
449
416
  type UpdateSubgraph = Updateable<SubgraphsTable>;
@@ -483,6 +450,12 @@ type WorkflowSchedule = Selectable<WorkflowSchedulesTable>;
483
450
  type InsertWorkflowSchedule = Insertable<WorkflowSchedulesTable>;
484
451
  type UpdateWorkflowSchedule = Updateable<WorkflowSchedulesTable>;
485
452
  type WorkflowCursor = Selectable<WorkflowCursorsTable>;
453
+ type WorkflowSignerSecret = Selectable<WorkflowSignerSecretsTable>;
454
+ type InsertWorkflowSignerSecret = Insertable<WorkflowSignerSecretsTable>;
455
+ type UpdateWorkflowSignerSecret = Updateable<WorkflowSignerSecretsTable>;
456
+ type WorkflowBudget = Selectable<WorkflowBudgetsTable>;
457
+ type InsertWorkflowBudget = Insertable<WorkflowBudgetsTable>;
458
+ type UpdateWorkflowBudget = Updateable<WorkflowBudgetsTable>;
486
459
  type Project = Selectable<ProjectsTable>;
487
460
  type InsertProject = Insertable<ProjectsTable>;
488
461
  type UpdateProject = Updateable<ProjectsTable>;
@@ -501,4 +474,4 @@ declare function getDb(connectionString?: string): Kysely<Database>;
501
474
  declare function getRawClient(): ReturnType<typeof postgres>;
502
475
  /** Close the DB connection pool. Call in CLI commands to allow process exit. */
503
476
  declare function closeDb(): Promise<void>;
504
- export { sql, parseJsonb, jsonb, getRawClient, getDb, closeDb, WorkflowStepsTable, WorkflowStep, WorkflowSchedulesTable, WorkflowSchedule, WorkflowRunsTable, WorkflowRun, WorkflowQueueTable, WorkflowQueueItem, WorkflowDefinitionsTable, WorkflowDefinition, WorkflowCursorsTable, WorkflowCursor, WaitlistTable, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateWorkflowStep, UpdateWorkflowSchedule, UpdateWorkflowRun, UpdateWorkflowDefinition, UpdateTransaction, UpdateSubgraph, UpdateStreamRow, UpdateStreamMetrics, UpdateProject, UpdateJob, UpdateIndexProgress, UpdateEvent, UpdateDelivery, UpdateChatSession, UpdateBlock, UpdateApiKey, TransactionsTable, Transaction, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphProcessingStatsTable, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGap, Subgraph, StreamsTable, StreamMetricsTable, StreamMetrics, Stream, SessionsTable, Session, ProjectsTable, Project, MagicLinksTable, MagicLink, JobsTable, Job, InsertWorkflowStep, InsertWorkflowSchedule, InsertWorkflowRun, InsertWorkflowQueueItem, InsertWorkflowDefinition, InsertTransaction, InsertTeamMember, InsertTeamInvitation, InsertSubgraphUsageDaily, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertStreamMetrics, InsertStream, InsertSession, InsertProject, InsertMagicLink, InsertJob, InsertIndexProgress, InsertEvent, InsertDelivery, InsertChatSession, InsertChatMessage, InsertBlock, InsertApiKey, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, EventsTable, Event, Delivery, DeliveriesTable, Database, ChatSessionsTable, ChatSession, ChatMessagesTable, ChatMessage, BlocksTable, Block, ApiKeysTable, ApiKey, AccountsTable, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
477
+ export { sql, parseJsonb, jsonb, getRawClient, getDb, closeDb, WorkflowStepsTable, WorkflowStep, WorkflowSignerSecretsTable, WorkflowSignerSecret, WorkflowSchedulesTable, WorkflowSchedule, WorkflowRunsTable, WorkflowRun, WorkflowQueueTable, WorkflowQueueItem, WorkflowDefinitionsTable, WorkflowDefinition, WorkflowCursorsTable, WorkflowCursor, WorkflowBudgetsTable, WorkflowBudget, WaitlistTable, UsageSnapshotsTable, UsageSnapshot, UsageDailyTable, UsageDaily, UpdateWorkflowStep, UpdateWorkflowSignerSecret, UpdateWorkflowSchedule, UpdateWorkflowRun, UpdateWorkflowDefinition, UpdateWorkflowBudget, UpdateTransaction, UpdateSubgraph, UpdateProject, UpdateIndexProgress, UpdateEvent, UpdateChatSession, UpdateBlock, UpdateApiKey, TransactionsTable, Transaction, TeamMembersTable, TeamMember, TeamInvitationsTable, TeamInvitation, SubgraphsTable, SubgraphUsageDailyTable, SubgraphUsageDaily, SubgraphTableSnapshotsTable, SubgraphProcessingStatsTable, SubgraphHealthSnapshotsTable, SubgraphHealthSnapshot, SubgraphGapsTable, SubgraphGap, Subgraph, SessionsTable, Session, ProjectsTable, Project, MagicLinksTable, MagicLink, InsertWorkflowStep, InsertWorkflowSignerSecret, InsertWorkflowSchedule, InsertWorkflowRun, InsertWorkflowQueueItem, InsertWorkflowDefinition, InsertWorkflowBudget, InsertTransaction, InsertTeamMember, InsertTeamInvitation, InsertSubgraphUsageDaily, InsertSubgraphHealthSnapshot, InsertSubgraphGap, InsertSubgraph, InsertSession, InsertProject, InsertMagicLink, InsertIndexProgress, InsertEvent, InsertChatSession, InsertChatMessage, InsertBlock, InsertApiKey, InsertAccountInsight, InsertAccountAgentRun, InsertAccount, IndexProgressTable, IndexProgress, EventsTable, Event, Database, ChatSessionsTable, ChatSession, ChatMessagesTable, ChatMessage, BlocksTable, Block, ApiKeysTable, ApiKey, AccountsTable, AccountInsightsTable, AccountInsight, AccountAgentRunsTable, AccountAgentRun, Account };
@@ -40,7 +40,7 @@ var db = null;
40
40
  var rawClient = null;
41
41
  function getDb(connectionString) {
42
42
  if (!db) {
43
- const url = connectionString || process.env.DATABASE_URL || "postgres://postgres:postgres@localhost:5432/streams_dev";
43
+ const url = connectionString || process.env.DATABASE_URL || "postgres://postgres:postgres@localhost:5432/secondlayer_dev";
44
44
  const isLocal = url.includes("localhost") || url.includes("127.0.0.1") || url.includes("@postgres:");
45
45
  const poolMax = Number.parseInt(process.env.DATABASE_POOL_MAX ?? "20", 10);
46
46
  rawClient = postgres(url, {
@@ -79,5 +79,5 @@ export {
79
79
  closeDb
80
80
  };
81
81
 
82
- //# debugId=FB849504D2C96D2864756E2164756E21
82
+ //# debugId=E1023FA2C43975A264756E2164756E21
83
83
  //# sourceMappingURL=index.js.map
@@ -3,9 +3,9 @@
3
3
  "sources": ["../src/db/jsonb.ts", "../src/db/index.ts"],
4
4
  "sourcesContent": [
5
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) => (typeof v === \"bigint\" ? v.toString() : v)).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 { Kysely } from \"kysely\";\nimport { PostgresJSDialect } from \"kysely-postgres-js\";\nimport postgres from \"postgres\";\nimport type { Database } from \"./types.ts\";\n\nlet db: Kysely<Database> | null = null;\nlet rawClient: ReturnType<typeof postgres> | null = null;\n\nexport function getDb(connectionString?: string): Kysely<Database> {\n\tif (!db) {\n\t\tconst url =\n\t\t\tconnectionString ||\n\t\t\tprocess.env.DATABASE_URL ||\n\t\t\t\"postgres://postgres:postgres@localhost:5432/streams_dev\";\n\n\t\t// Always use SSL for remote databases, just disable cert verification if needed\n\t\tconst isLocal =\n\t\t\turl.includes(\"localhost\") ||\n\t\t\turl.includes(\"127.0.0.1\") ||\n\t\t\turl.includes(\"@postgres:\");\n\t\tconst poolMax = Number.parseInt(process.env.DATABASE_POOL_MAX ?? \"20\", 10);\n\t\trawClient = postgres(url, {\n\t\t\tmax: poolMax,\n\t\t\tssl: isLocal\n\t\t\t\t? undefined\n\t\t\t\t: {\n\t\t\t\t\t\trejectUnauthorized:\n\t\t\t\t\t\t\tprocess.env.NODE_TLS_REJECT_UNAUTHORIZED !== \"0\",\n\t\t\t\t\t},\n\t\t});\n\t\tdb = new Kysely<Database>({\n\t\t\tdialect: new PostgresJSDialect({ postgres: rawClient }),\n\t\t});\n\t}\n\treturn db;\n}\n\n/** Raw postgres.js client for dynamic schema DDL (CREATE SCHEMA, DROP, etc.) */\nexport function getRawClient(): ReturnType<typeof postgres> {\n\tif (!rawClient) getDb();\n\treturn rawClient!;\n}\n\n/** Close the DB connection pool. Call in CLI commands to allow process exit. */\nexport async function closeDb(): Promise<void> {\n\tif (db) {\n\t\tawait db.destroy();\n\t\tdb = null;\n\t}\n\tif (rawClient) {\n\t\tawait rawClient.end();\n\t\trawClient = null;\n\t}\n}\n\nimport { sql } from \"kysely\";\nexport { sql };\nexport * from \"./types.ts\";\nexport { jsonb, parseJsonb } from \"./jsonb.ts\";\n"
6
+ "import { Kysely } from \"kysely\";\nimport { PostgresJSDialect } from \"kysely-postgres-js\";\nimport postgres from \"postgres\";\nimport type { Database } from \"./types.ts\";\n\nlet db: Kysely<Database> | null = null;\nlet rawClient: ReturnType<typeof postgres> | null = null;\n\nexport function getDb(connectionString?: string): Kysely<Database> {\n\tif (!db) {\n\t\tconst url =\n\t\t\tconnectionString ||\n\t\t\tprocess.env.DATABASE_URL ||\n\t\t\t\"postgres://postgres:postgres@localhost:5432/secondlayer_dev\";\n\n\t\t// Always use SSL for remote databases, just disable cert verification if needed\n\t\tconst isLocal =\n\t\t\turl.includes(\"localhost\") ||\n\t\t\turl.includes(\"127.0.0.1\") ||\n\t\t\turl.includes(\"@postgres:\");\n\t\tconst poolMax = Number.parseInt(process.env.DATABASE_POOL_MAX ?? \"20\", 10);\n\t\trawClient = postgres(url, {\n\t\t\tmax: poolMax,\n\t\t\tssl: isLocal\n\t\t\t\t? undefined\n\t\t\t\t: {\n\t\t\t\t\t\trejectUnauthorized:\n\t\t\t\t\t\t\tprocess.env.NODE_TLS_REJECT_UNAUTHORIZED !== \"0\",\n\t\t\t\t\t},\n\t\t});\n\t\tdb = new Kysely<Database>({\n\t\t\tdialect: new PostgresJSDialect({ postgres: rawClient }),\n\t\t});\n\t}\n\treturn db;\n}\n\n/** Raw postgres.js client for dynamic schema DDL (CREATE SCHEMA, DROP, etc.) */\nexport function getRawClient(): ReturnType<typeof postgres> {\n\tif (!rawClient) getDb();\n\treturn rawClient!;\n}\n\n/** Close the DB connection pool. Call in CLI commands to allow process exit. */\nexport async function closeDb(): Promise<void> {\n\tif (db) {\n\t\tawait db.destroy();\n\t\tdb = null;\n\t}\n\tif (rawClient) {\n\t\tawait rawClient.end();\n\t\trawClient = null;\n\t}\n}\n\nimport { sql } from \"kysely\";\nexport { sql };\nexport * from \"./types.ts\";\nexport { jsonb, parseJsonb } from \"./jsonb.ts\";\n"
7
7
  ],
8
8
  "mappings": ";;;;;;;;;;;;;;;;;AAAA;AAOO,SAAS,KAAK,CAAC,OAAqC;AAAA,EAC1D,MAAM,UAAU,KAAK,UAAU,OAAO,CAAC,IAAI,MAAO,OAAO,MAAM,WAAW,EAAE,SAAS,IAAI,CAAE,EAAE,QAAQ,MAAM,IAAI;AAAA,EAC/G,OAAO,MAAM,IAAI,IAAI,IAAI,iBAAiB;AAAA;AAQpC,SAAS,UAAuB,CAAC,OAAmB;AAAA,EAC1D,IAAI,OAAO,UAAU,UAAU;AAAA,IAC9B,IAAI;AAAA,MACH,OAAO,KAAK,MAAM,KAAK;AAAA,MACtB,MAAM;AAAA,MACP,OAAO;AAAA;AAAA,EAET;AAAA,EACA,OAAQ,SAAS,CAAC;AAAA;;;ACzBnB;AACA;AACA;AAqDA,gBAAS;AAlDT,IAAI,KAA8B;AAClC,IAAI,YAAgD;AAE7C,SAAS,KAAK,CAAC,kBAA6C;AAAA,EAClE,IAAI,CAAC,IAAI;AAAA,IACR,MAAM,MACL,oBACA,QAAQ,IAAI,gBACZ;AAAA,IAGD,MAAM,UACL,IAAI,SAAS,WAAW,KACxB,IAAI,SAAS,WAAW,KACxB,IAAI,SAAS,YAAY;AAAA,IAC1B,MAAM,UAAU,OAAO,SAAS,QAAQ,IAAI,qBAAqB,MAAM,EAAE;AAAA,IACzE,YAAY,SAAS,KAAK;AAAA,MACzB,KAAK;AAAA,MACL,KAAK,UACF,YACA;AAAA,QACA,oBACC,QAAQ,IAAI,iCAAiC;AAAA,MAC/C;AAAA,IACH,CAAC;AAAA,IACD,KAAK,IAAI,OAAiB;AAAA,MACzB,SAAS,IAAI,kBAAkB,EAAE,UAAU,UAAU,CAAC;AAAA,IACvD,CAAC;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAID,SAAS,YAAY,GAAgC;AAAA,EAC3D,IAAI,CAAC;AAAA,IAAW,MAAM;AAAA,EACtB,OAAO;AAAA;AAIR,eAAsB,OAAO,GAAkB;AAAA,EAC9C,IAAI,IAAI;AAAA,IACP,MAAM,GAAG,QAAQ;AAAA,IACjB,KAAK;AAAA,EACN;AAAA,EACA,IAAI,WAAW;AAAA,IACd,MAAM,UAAU,IAAI;AAAA,IACpB,YAAY;AAAA,EACb;AAAA;",
9
- "debugId": "FB849504D2C96D2864756E2164756E21",
9
+ "debugId": "E1023FA2C43975A264756E2164756E21",
10
10
  "names": []
11
11
  }
@@ -33,40 +33,6 @@ interface EventsTable {
33
33
  data: unknown;
34
34
  created_at: Generated<Date>;
35
35
  }
36
- interface StreamsTable {
37
- id: Generated<string>;
38
- name: string;
39
- status: Generated<string>;
40
- filters: unknown;
41
- options: Generated<unknown>;
42
- endpoint_url: string;
43
- signing_secret: string | null;
44
- api_key_id: string;
45
- project_id: string | null;
46
- created_at: Generated<Date>;
47
- updated_at: Generated<Date>;
48
- }
49
- interface StreamMetricsTable {
50
- stream_id: string;
51
- last_triggered_at: Date | null;
52
- last_triggered_block: number | null;
53
- total_deliveries: Generated<number>;
54
- failed_deliveries: Generated<number>;
55
- error_message: string | null;
56
- }
57
- interface JobsTable {
58
- id: Generated<string>;
59
- stream_id: string;
60
- block_height: number;
61
- status: Generated<string>;
62
- attempts: Generated<number>;
63
- locked_at: Date | null;
64
- locked_by: string | null;
65
- error: string | null;
66
- backfill: Generated<boolean>;
67
- created_at: Generated<Date>;
68
- completed_at: Date | null;
69
- }
70
36
  interface IndexProgressTable {
71
37
  network: string;
72
38
  last_indexed_block: Generated<number>;
@@ -74,19 +40,6 @@ interface IndexProgressTable {
74
40
  highest_seen_block: Generated<number>;
75
41
  updated_at: Generated<Date>;
76
42
  }
77
- interface DeliveriesTable {
78
- id: Generated<string>;
79
- stream_id: string;
80
- job_id: string | null;
81
- block_height: number;
82
- status: string;
83
- status_code: number | null;
84
- response_time_ms: number | null;
85
- attempts: Generated<number>;
86
- error: string | null;
87
- payload: unknown;
88
- created_at: Generated<Date>;
89
- }
90
43
  interface SubgraphsTable {
91
44
  id: Generated<string>;
92
45
  name: string;
@@ -107,6 +60,7 @@ interface SubgraphsTable {
107
60
  api_key_id: string | null;
108
61
  account_id: string;
109
62
  handler_code: string | null;
63
+ source_code: string | null;
110
64
  project_id: string | null;
111
65
  is_public: Generated<boolean>;
112
66
  tags: Generated<string[]>;
@@ -305,6 +259,7 @@ interface WorkflowDefinitionsTable {
305
259
  trigger_type: string;
306
260
  trigger_config: unknown;
307
261
  handler_path: string;
262
+ source_code: string | null;
308
263
  retries_config: unknown | null;
309
264
  timeout_ms: number | null;
310
265
  api_key_id: string;
@@ -341,6 +296,8 @@ interface WorkflowStepsTable {
341
296
  started_at: Date | null;
342
297
  completed_at: Date | null;
343
298
  duration_ms: number | null;
299
+ memo_key: string | null;
300
+ parent_step_id: string | null;
344
301
  created_at: Generated<Date>;
345
302
  }
346
303
  interface WorkflowQueueTable {
@@ -375,11 +332,7 @@ interface Database {
375
332
  blocks: BlocksTable;
376
333
  transactions: TransactionsTable;
377
334
  events: EventsTable;
378
- streams: StreamsTable;
379
- stream_metrics: StreamMetricsTable;
380
- jobs: JobsTable;
381
335
  index_progress: IndexProgressTable;
382
- deliveries: DeliveriesTable;
383
336
  subgraphs: SubgraphsTable;
384
337
  api_keys: ApiKeysTable;
385
338
  accounts: AccountsTable;
@@ -406,6 +359,32 @@ interface Database {
406
359
  workflow_queue: WorkflowQueueTable;
407
360
  workflow_schedules: WorkflowSchedulesTable;
408
361
  workflow_cursors: WorkflowCursorsTable;
362
+ workflow_signer_secrets: WorkflowSignerSecretsTable;
363
+ workflow_budgets: WorkflowBudgetsTable;
364
+ }
365
+ interface WorkflowBudgetsTable {
366
+ id: Generated<string>;
367
+ workflow_definition_id: string;
368
+ /** Period key: "daily:YYYY-MM-DD" | "weekly:YYYY-Www" | "per-run:<uuid>". */
369
+ period: string;
370
+ ai_usd_used: Generated<string>;
371
+ ai_tokens_used: Generated<string>;
372
+ chain_microstx_used: Generated<string>;
373
+ chain_tx_count: Generated<number>;
374
+ run_count: Generated<number>;
375
+ step_count: Generated<number>;
376
+ reset_at: Date;
377
+ created_at: Generated<Date>;
378
+ updated_at: Generated<Date>;
379
+ }
380
+ interface WorkflowSignerSecretsTable {
381
+ id: Generated<string>;
382
+ account_id: string;
383
+ name: string;
384
+ /** AES-GCM ciphertext bytes produced by the runner's KMS on write. */
385
+ encrypted_value: Buffer;
386
+ created_at: Generated<Date>;
387
+ updated_at: Generated<Date>;
409
388
  }
410
389
  type Account = Selectable<AccountsTable>;
411
390
  declare function upsertAccount(db: Kysely<Database>, email: string): Promise<Account>;
@@ -32,40 +32,6 @@ interface EventsTable {
32
32
  data: unknown;
33
33
  created_at: Generated<Date>;
34
34
  }
35
- interface StreamsTable {
36
- id: Generated<string>;
37
- name: string;
38
- status: Generated<string>;
39
- filters: unknown;
40
- options: Generated<unknown>;
41
- endpoint_url: string;
42
- signing_secret: string | null;
43
- api_key_id: string;
44
- project_id: string | null;
45
- created_at: Generated<Date>;
46
- updated_at: Generated<Date>;
47
- }
48
- interface StreamMetricsTable {
49
- stream_id: string;
50
- last_triggered_at: Date | null;
51
- last_triggered_block: number | null;
52
- total_deliveries: Generated<number>;
53
- failed_deliveries: Generated<number>;
54
- error_message: string | null;
55
- }
56
- interface JobsTable {
57
- id: Generated<string>;
58
- stream_id: string;
59
- block_height: number;
60
- status: Generated<string>;
61
- attempts: Generated<number>;
62
- locked_at: Date | null;
63
- locked_by: string | null;
64
- error: string | null;
65
- backfill: Generated<boolean>;
66
- created_at: Generated<Date>;
67
- completed_at: Date | null;
68
- }
69
35
  interface IndexProgressTable {
70
36
  network: string;
71
37
  last_indexed_block: Generated<number>;
@@ -73,19 +39,6 @@ interface IndexProgressTable {
73
39
  highest_seen_block: Generated<number>;
74
40
  updated_at: Generated<Date>;
75
41
  }
76
- interface DeliveriesTable {
77
- id: Generated<string>;
78
- stream_id: string;
79
- job_id: string | null;
80
- block_height: number;
81
- status: string;
82
- status_code: number | null;
83
- response_time_ms: number | null;
84
- attempts: Generated<number>;
85
- error: string | null;
86
- payload: unknown;
87
- created_at: Generated<Date>;
88
- }
89
42
  interface SubgraphsTable {
90
43
  id: Generated<string>;
91
44
  name: string;
@@ -106,6 +59,7 @@ interface SubgraphsTable {
106
59
  api_key_id: string | null;
107
60
  account_id: string;
108
61
  handler_code: string | null;
62
+ source_code: string | null;
109
63
  project_id: string | null;
110
64
  is_public: Generated<boolean>;
111
65
  tags: Generated<string[]>;
@@ -304,6 +258,7 @@ interface WorkflowDefinitionsTable {
304
258
  trigger_type: string;
305
259
  trigger_config: unknown;
306
260
  handler_path: string;
261
+ source_code: string | null;
307
262
  retries_config: unknown | null;
308
263
  timeout_ms: number | null;
309
264
  api_key_id: string;
@@ -340,6 +295,8 @@ interface WorkflowStepsTable {
340
295
  started_at: Date | null;
341
296
  completed_at: Date | null;
342
297
  duration_ms: number | null;
298
+ memo_key: string | null;
299
+ parent_step_id: string | null;
343
300
  created_at: Generated<Date>;
344
301
  }
345
302
  interface WorkflowQueueTable {
@@ -374,11 +331,7 @@ interface Database {
374
331
  blocks: BlocksTable;
375
332
  transactions: TransactionsTable;
376
333
  events: EventsTable;
377
- streams: StreamsTable;
378
- stream_metrics: StreamMetricsTable;
379
- jobs: JobsTable;
380
334
  index_progress: IndexProgressTable;
381
- deliveries: DeliveriesTable;
382
335
  subgraphs: SubgraphsTable;
383
336
  api_keys: ApiKeysTable;
384
337
  accounts: AccountsTable;
@@ -405,6 +358,32 @@ interface Database {
405
358
  workflow_queue: WorkflowQueueTable;
406
359
  workflow_schedules: WorkflowSchedulesTable;
407
360
  workflow_cursors: WorkflowCursorsTable;
361
+ workflow_signer_secrets: WorkflowSignerSecretsTable;
362
+ workflow_budgets: WorkflowBudgetsTable;
363
+ }
364
+ interface WorkflowBudgetsTable {
365
+ id: Generated<string>;
366
+ workflow_definition_id: string;
367
+ /** Period key: "daily:YYYY-MM-DD" | "weekly:YYYY-Www" | "per-run:<uuid>". */
368
+ period: string;
369
+ ai_usd_used: Generated<string>;
370
+ ai_tokens_used: Generated<string>;
371
+ chain_microstx_used: Generated<string>;
372
+ chain_tx_count: Generated<number>;
373
+ run_count: Generated<number>;
374
+ step_count: Generated<number>;
375
+ reset_at: Date;
376
+ created_at: Generated<Date>;
377
+ updated_at: Generated<Date>;
378
+ }
379
+ interface WorkflowSignerSecretsTable {
380
+ id: Generated<string>;
381
+ account_id: string;
382
+ name: string;
383
+ /** AES-GCM ciphertext bytes produced by the runner's KMS on write. */
384
+ encrypted_value: Buffer;
385
+ created_at: Generated<Date>;
386
+ updated_at: Generated<Date>;
408
387
  }
409
388
  interface Gap {
410
389
  gapStart: number;