@secondlayer/shared 13.11.0 → 13.13.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 (41) hide show
  1. package/dist/src/archive/range-digest.d.ts +125 -0
  2. package/dist/src/archive/semantic-digest-builder.d.ts +125 -0
  3. package/dist/src/coverage/index.d.ts +125 -0
  4. package/dist/src/db/index.d.ts +146 -2
  5. package/dist/src/db/index.js +11 -1
  6. package/dist/src/db/index.js.map +3 -3
  7. package/dist/src/db/queries/chain-reorgs.d.ts +125 -0
  8. package/dist/src/db/queries/chain-reorgs.js +11 -1
  9. package/dist/src/db/queries/chain-reorgs.js.map +3 -3
  10. package/dist/src/db/queries/contracts.d.ts +125 -0
  11. package/dist/src/db/queries/instance.d.ts +125 -0
  12. package/dist/src/db/queries/integrity.d.ts +125 -0
  13. package/dist/src/db/queries/subgraph-gaps.d.ts +125 -0
  14. package/dist/src/db/queries/subgraph-operations.d.ts +125 -0
  15. package/dist/src/db/queries/subgraphs.d.ts +125 -0
  16. package/dist/src/db/queries/sync-scope.d.ts +125 -0
  17. package/dist/src/db/queries/webhook-replays.d.ts +1431 -0
  18. package/dist/src/db/queries/webhook-replays.js +156 -0
  19. package/dist/src/db/queries/webhook-replays.js.map +10 -0
  20. package/dist/src/db/queries/webhooks.d.ts +125 -0
  21. package/dist/src/db/schema.d.ts +136 -2
  22. package/dist/src/index.d.ts +146 -2
  23. package/dist/src/index.js +15 -1
  24. package/dist/src/index.js.map +4 -4
  25. package/dist/src/insights/index.d.ts +142 -3
  26. package/dist/src/insights/index.js +40 -3
  27. package/dist/src/insights/index.js.map +3 -3
  28. package/dist/src/node/local-client.d.ts +125 -0
  29. package/dist/src/queue/listener.js +11 -1
  30. package/dist/src/queue/listener.js.map +3 -3
  31. package/dist/src/schemas/index.js +5 -1
  32. package/dist/src/schemas/index.js.map +3 -3
  33. package/dist/src/schemas/webhooks.d.ts +45 -1
  34. package/dist/src/schemas/webhooks.js +6 -1
  35. package/dist/src/schemas/webhooks.js.map +3 -3
  36. package/migrations/0177_oauth_mcp.ts +122 -0
  37. package/migrations/0178_insight_snooze.ts +22 -0
  38. package/migrations/0179_webhook_replays.ts +56 -0
  39. package/migrations/0180_push.ts +54 -0
  40. package/migrations/0181_push_sent.ts +30 -0
  41. package/package.json +5 -1
@@ -0,0 +1,1431 @@
1
+ import { Kysely } from "kysely";
2
+ /** Live state of one stored replay. */
3
+ interface ReplayProgress {
4
+ replayId: string;
5
+ webhookId: string;
6
+ status: "scanning" | "running" | "done" | "failed";
7
+ fromBlock: number;
8
+ toBlock: number;
9
+ /** Events the replay enqueued. */
10
+ total: number;
11
+ /** Delivered or gave up (`total - pending`). */
12
+ processed: number;
13
+ pending: number;
14
+ /** Null until the replay finishes. */
15
+ delivered: number | null;
16
+ /** Null until the replay finishes. */
17
+ gaveUp: number | null;
18
+ startedAt: string;
19
+ finishedAt: string | null;
20
+ error: string | null;
21
+ }
22
+ import { ColumnType, Generated, Selectable } from "kysely";
23
+ /**
24
+ * Coverage-kernel constraints. SQL CHECKs in migration 0116 must stay
25
+ * identical — property tests treat this file as the spec.
26
+ */
27
+ declare const STAGE_KINDS: readonly ["raw", "decode", "subgraph", "queue"];
28
+ type StageKind = (typeof STAGE_KINDS)[number];
29
+ declare const NATIVE_CLOCKS: readonly ["block", "cursor", "queue"];
30
+ type NativeClock = (typeof NATIVE_CLOCKS)[number];
31
+ declare const REPAIR_MODES: readonly ["range_safe", "full_reindex", "archive_replay", "none"];
32
+ type RepairMode = (typeof REPAIR_MODES)[number];
33
+ declare const RUN_STATUSES: readonly ["pending", "running", "complete", "syncing", "lagging", "gap", "stale", "failed", "unverified_import", "unanchored", "source_unavailable", "out_of_scope", "disabled", "halted"];
34
+ type RunStatus = (typeof RUN_STATUSES)[number];
35
+ declare const FAILURE_UNITS: readonly ["block", "range", "cursor", "queue"];
36
+ type FailureUnit = (typeof FAILURE_UNITS)[number];
37
+ declare const FAILURE_CLASSES: readonly ["omission", "version", "digest_mismatch", "crash", "reorg", "source_gap", "handler", "timeout", "unknown"];
38
+ type FailureClass = (typeof FAILURE_CLASSES)[number];
39
+ declare const RETRY_STATES: readonly ["open", "retrying", "halted", "resolved"];
40
+ type RetryState = (typeof RETRY_STATES)[number];
41
+ type BootstrapSource = "archive" | "genesis" | "import";
42
+ /**
43
+ * How far a subgraph's rows can be checked without trusting the server,
44
+ * derived from its sources and a scan of its handler. Never configured.
45
+ *
46
+ * - `state`: every input is a named state write, provable from block headers.
47
+ * Handlers run in the deterministic realm. A deployed `state` subgraph is
48
+ * verifiable: one with any reason is refused at deploy.
49
+ * - `events`: an input (events, prints, tx results, `ctx.client`) needs
50
+ * re-execution proofs, which are not served yet.
51
+ * - `none`: a source can never be proven as written (trait scope, tip-first
52
+ * backfill).
53
+ */
54
+ interface SubgraphVerification {
55
+ level: "state" | "events" | "none";
56
+ /** What stands between the subgraph and checkable rows, e.g.
57
+ * `print_event source "swaps" needs event proofs` or
58
+ * `subgraph.ts:41:12 Date: wall-clock time differs per run`. */
59
+ reasons: string[];
60
+ /** What stays unproven even at this level, e.g. tx attribution of writes. */
61
+ unproven: string[];
62
+ }
63
+ interface BlocksTable {
64
+ height: number;
65
+ hash: string;
66
+ parent_hash: string;
67
+ burn_block_height: number;
68
+ burn_block_hash: ColumnType<string | null, string | null | undefined, string | null>;
69
+ /** Nakamoto StacksBlockId. Null on rows ingested before it was persisted. */
70
+ index_block_hash: ColumnType<string | null, string | null | undefined, string | null>;
71
+ timestamp: number;
72
+ canonical: Generated<boolean>;
73
+ /** Tx count `persistBlock` was handed for this height. Null on rows
74
+ * ingested before this column existed. */
75
+ tx_count: ColumnType<number | null, number | null | undefined, number | null>;
76
+ created_at: Generated<Date>;
77
+ }
78
+ interface TransactionsTable {
79
+ tx_id: string;
80
+ block_height: number;
81
+ tx_index: Generated<number>;
82
+ type: string;
83
+ sender: string;
84
+ status: string;
85
+ contract_id: string | null;
86
+ function_name: string | null;
87
+ function_args: Generated<unknown | null>;
88
+ raw_result: Generated<string | null>;
89
+ raw_tx: string;
90
+ created_at: Generated<Date>;
91
+ }
92
+ interface EventsTable {
93
+ id: Generated<string>;
94
+ tx_id: string;
95
+ block_height: number;
96
+ event_index: number;
97
+ type: string;
98
+ data: unknown;
99
+ created_at: Generated<Date>;
100
+ }
101
+ interface TransactionsArchiveTable {
102
+ archive_id: Generated<string>;
103
+ tx_id: string;
104
+ block_height: number;
105
+ tx_index: number;
106
+ type: string;
107
+ sender: string;
108
+ status: string;
109
+ contract_id: string | null;
110
+ function_name: string | null;
111
+ function_args: unknown | null;
112
+ raw_result: string | null;
113
+ raw_tx: string;
114
+ created_at: Date;
115
+ orphaned_block_hash: string | null;
116
+ archived_at: Generated<Date>;
117
+ }
118
+ interface EventsArchiveTable {
119
+ archive_id: Generated<string>;
120
+ id: string;
121
+ tx_id: string;
122
+ block_height: number;
123
+ event_index: number;
124
+ type: string;
125
+ data: unknown;
126
+ created_at: Date;
127
+ orphaned_block_hash: string | null;
128
+ archived_at: Generated<Date>;
129
+ }
130
+ interface VmEventsTable {
131
+ tx_id: string;
132
+ block_height: number;
133
+ ordinal: number;
134
+ type: string;
135
+ data: unknown;
136
+ created_at: Generated<Date>;
137
+ }
138
+ interface VmEventsArchiveTable {
139
+ archive_id: Generated<string>;
140
+ /** `block_height:ordinal`; rows archived before migration 0153 hold the old uuid. */
141
+ id: string;
142
+ tx_id: string;
143
+ block_height: number;
144
+ ordinal: number;
145
+ type: string;
146
+ data: unknown;
147
+ created_at: Date;
148
+ orphaned_block_hash: string | null;
149
+ archived_at: Generated<Date>;
150
+ }
151
+ interface StateWritesTable {
152
+ block_height: number;
153
+ ordinal: number;
154
+ tx_index: number | null;
155
+ key: string;
156
+ value_hex: string;
157
+ }
158
+ interface StateWritesArchiveTable {
159
+ archive_id: Generated<string>;
160
+ /** `block_height:ordinal`. */
161
+ id: string;
162
+ block_height: number;
163
+ ordinal: number;
164
+ tx_index: number | null;
165
+ key: string;
166
+ value_hex: string;
167
+ orphaned_block_hash: string | null;
168
+ archived_at: Generated<Date>;
169
+ }
170
+ interface DeadLetterEventsTable {
171
+ id: Generated<string>;
172
+ block_height: number;
173
+ tx_id: string;
174
+ event_index: number;
175
+ event_type: string;
176
+ data: unknown;
177
+ reason: string;
178
+ created_at: Generated<Date>;
179
+ }
180
+ interface MempoolTransactionsTable {
181
+ seq: Generated<string>;
182
+ tx_id: string;
183
+ raw_tx: string;
184
+ type: string;
185
+ sender: string;
186
+ contract_id: string | null;
187
+ function_name: string | null;
188
+ function_args: unknown | null;
189
+ received_at: Generated<Date>;
190
+ }
191
+ interface IndexProgressTable {
192
+ network: string;
193
+ last_indexed_block: Generated<number>;
194
+ last_contiguous_block: Generated<number>;
195
+ highest_seen_block: Generated<number>;
196
+ updated_at: Generated<Date>;
197
+ }
198
+ interface SubgraphsTable {
199
+ id: Generated<string>;
200
+ name: string;
201
+ version: Generated<string>;
202
+ status: Generated<string>;
203
+ definition: Record<string, unknown>;
204
+ schema_hash: string;
205
+ handler_path: string;
206
+ schema_name: string | null;
207
+ start_block: Generated<number>;
208
+ last_processed_block: Generated<number>;
209
+ reindex_from_block: number | null;
210
+ reindex_to_block: number | null;
211
+ last_error: string | null;
212
+ last_error_at: Date | null;
213
+ total_processed: Generated<number>;
214
+ total_errors: Generated<number>;
215
+ account_id: string;
216
+ handler_code: string | null;
217
+ source_code: string | null;
218
+ project_id: string | null;
219
+ /** Paid (wallet-ghost) deploys expire unless renewed or claimed; NULL = no expiry. */
220
+ expires_at: Date | null;
221
+ /** (event type, contract) probe pairs persisted at deploy for weight classification. */
222
+ sparse_probe_targets: unknown | null;
223
+ /** sha256 over everything that shapes rows (schema, handler bundle,
224
+ * startBlock, network, runtime). NULL for unbundled or older deploys. */
225
+ pin: string | null;
226
+ /** The canonical JSON `pin` hashes, so a client can recompute it. NULL
227
+ * wherever `pin` is, and for deploys before migration 0158. */
228
+ pin_preimage: string | null;
229
+ /** Level derived at deploy. NULL (older deploys) = not verifiable. */
230
+ verification: SubgraphVerification | null;
231
+ created_at: Generated<Date>;
232
+ updated_at: Generated<Date>;
233
+ }
234
+ interface ContractsTable {
235
+ contract_id: string;
236
+ deployer: string;
237
+ block_height: number;
238
+ canonical: Generated<boolean>;
239
+ abi: unknown | null;
240
+ declared_traits: Generated<string[]>;
241
+ inferred_standards: Generated<string[]>;
242
+ abi_status: Generated<string>;
243
+ abi_fetched_at: Date | null;
244
+ created_at: Generated<Date>;
245
+ }
246
+ interface SubgraphGapsTable {
247
+ id: Generated<string>;
248
+ subgraph_id: string;
249
+ subgraph_name: string;
250
+ gap_start: number;
251
+ gap_end: number;
252
+ reason: string;
253
+ detected_at: Generated<Date>;
254
+ resolved_at: Date | null;
255
+ }
256
+ /** Print-validate skips persisted for the authed violations GET. Cap 100/subgraph. */
257
+ interface SubgraphViolationsTable {
258
+ id: Generated<string>;
259
+ subgraph_name: string;
260
+ source_name: string;
261
+ block_height: number;
262
+ tx_id: string;
263
+ reason: string;
264
+ sample_payload: Record<string, unknown>;
265
+ seen_at: Generated<Date>;
266
+ }
267
+ type SubgraphOperationKind = "reindex" | "backfill";
268
+ type SubgraphOperationStatus = "queued" | "running" | "completed" | "failed" | "cancelled";
269
+ interface SubgraphOperationsTable {
270
+ id: Generated<string>;
271
+ subgraph_id: string;
272
+ subgraph_name: string;
273
+ account_id: string | null;
274
+ kind: ColumnType<SubgraphOperationKind, SubgraphOperationKind, SubgraphOperationKind>;
275
+ status: ColumnType<SubgraphOperationStatus, SubgraphOperationStatus | undefined, SubgraphOperationStatus>;
276
+ from_block: number | null;
277
+ to_block: number | null;
278
+ cancel_requested: Generated<boolean>;
279
+ locked_by: string | null;
280
+ locked_until: Date | null;
281
+ started_at: Date | null;
282
+ finished_at: Date | null;
283
+ processed_blocks: number | null;
284
+ error: string | null;
285
+ created_at: Generated<Date>;
286
+ updated_at: Generated<Date>;
287
+ /** 'light' (contract-scoped sparse) | 'heavy' (broad). Claim budgets heavy. */
288
+ weight: Generated<string>;
289
+ /** Candidate-event denominator computed at enqueue (sparse ops only). */
290
+ estimated_events: string | number | bigint | null;
291
+ /** Events processed so far — written by the progress flush. */
292
+ processed_events: string | number | bigint | null;
293
+ /** Backfill ops' own crash checkpoint — advanced conditionally in-tx with
294
+ * each written block; replays skip at/below it. NULL for reindex ops
295
+ * (those checkpoint on subgraphs.last_processed_block). */
296
+ cursor_block: string | number | bigint | null;
297
+ }
298
+ interface ApiKeysTable {
299
+ id: Generated<string>;
300
+ key_hash: string;
301
+ key_prefix: string;
302
+ name: string | null;
303
+ status: Generated<string>;
304
+ rate_limit: Generated<number>;
305
+ ip_address: string;
306
+ account_id: string;
307
+ product: Generated<"account" | "streams" | "index" | "sentinel" | "docs" | "tenant">;
308
+ /** Sentinel permission areas; set only on `product = 'sentinel'` keys. */
309
+ areas: unknown | null;
310
+ tier: "free" | "build" | "scale" | "enterprise" | "internal" | null;
311
+ last_used_at: Date | null;
312
+ revoked_at: Date | null;
313
+ /** Set only on `docs` keys (24h). A key past this instant never authenticates. */
314
+ expires_at: Date | null;
315
+ created_at: Generated<Date>;
316
+ }
317
+ /** Singleton self-host / publisher identity. Network is immutable. */
318
+ interface InstancesTable {
319
+ id: Generated<string>;
320
+ network: string;
321
+ created_at: Generated<Date>;
322
+ }
323
+ interface AccountsTable {
324
+ id: Generated<string>;
325
+ /** NULL for unclaimed ghost accounts (anonymous self-serve keys). */
326
+ email: string | null;
327
+ /** True for anonymous self-serve accounts until claimed via magic link. */
328
+ ghost: Generated<boolean>;
329
+ /** First-party service account: usage priced at $0, never gated on
330
+ * credits. Set by ops only. */
331
+ internal: Generated<boolean>;
332
+ /** Stacks principal owning a wallet-ghost account. */
333
+ wallet_principal: string | null;
334
+ display_name: string | null;
335
+ bio: string | null;
336
+ avatar_url: string | null;
337
+ stripe_customer_id: string | null;
338
+ /** Opt-out toggle for the subgraph reindex-completion email. Defaults true. */
339
+ notify_reindex_complete: Generated<boolean>;
340
+ created_at: Generated<Date>;
341
+ }
342
+ interface SessionsTable {
343
+ id: Generated<string>;
344
+ token_hash: string;
345
+ token_prefix: string;
346
+ account_id: string;
347
+ ip_address: string;
348
+ expires_at: Generated<Date>;
349
+ revoked_at: Date | null;
350
+ last_used_at: Date | null;
351
+ created_at: Generated<Date>;
352
+ }
353
+ interface MagicLinksTable {
354
+ id: Generated<string>;
355
+ email: string;
356
+ token: string;
357
+ code: string | null;
358
+ expires_at: Date;
359
+ used_at: Date | null;
360
+ failed_attempts: Generated<number>;
361
+ created_at: Generated<Date>;
362
+ }
363
+ interface SubgraphProcessingStatsTable {
364
+ id: Generated<string>;
365
+ subgraph_name: string;
366
+ api_key_id: string | null;
367
+ bucket_start: Date | null;
368
+ bucket_end: Date | null;
369
+ blocks_processed: number | null;
370
+ total_time_ms: number | null;
371
+ handler_time_ms: number | null;
372
+ flush_time_ms: number | null;
373
+ max_block_time_ms: number | null;
374
+ max_handler_time_ms: number | null;
375
+ avg_ops_per_block: number | null;
376
+ is_catchup: Generated<boolean>;
377
+ created_at: Generated<Date>;
378
+ }
379
+ interface SubgraphHealthSnapshotsTable {
380
+ id: Generated<string>;
381
+ subgraph_id: string;
382
+ total_processed: number;
383
+ total_errors: number;
384
+ last_processed_block: number | null;
385
+ chain_tip: string | number | null;
386
+ rows_written_total: string | number | null;
387
+ storage_bytes: string | number | null;
388
+ captured_at: Generated<Date>;
389
+ }
390
+ /** Handler errors grouped by fingerprint. Cap 50/subgraph. */
391
+ interface SubgraphErrorGroupsTable {
392
+ id: Generated<string>;
393
+ subgraph_name: string;
394
+ fingerprint: string;
395
+ source_name: string;
396
+ event_type: string | null;
397
+ message: string;
398
+ frame: string | null;
399
+ count: Generated<string | number>;
400
+ sample_tx_id: string | null;
401
+ sample_block_height: string | number | null;
402
+ first_seen: Generated<Date>;
403
+ last_seen: Generated<Date>;
404
+ }
405
+ /**
406
+ * One ranked dashboard insight. `account_id` is NULL on tenant and self-host
407
+ * databases. `severity` is never "recovered": that is derived on read from
408
+ * `resolved_at`.
409
+ */
410
+ interface InsightsTable {
411
+ id: Generated<string>;
412
+ account_id: string | null;
413
+ resource_kind: string;
414
+ resource_id: string;
415
+ rule: string;
416
+ severity: string;
417
+ impact: Generated<number>;
418
+ /** resource, line, meta, lead, body, evidence, handoff, how. */
419
+ payload: unknown;
420
+ first_seen_at: Generated<Date>;
421
+ last_seen_at: Generated<Date>;
422
+ clear_streak: Generated<number>;
423
+ resolved_at: Date | null;
424
+ dismissed_at: Date | null;
425
+ snoozed_until: Date | null;
426
+ }
427
+ /** "Expected": mutes one rule for one resource until removed. */
428
+ interface InsightMutesTable {
429
+ account_id: string | null;
430
+ resource_kind: string;
431
+ resource_id: string;
432
+ rule: string;
433
+ created_at: Generated<Date>;
434
+ }
435
+ interface ProcessedStripeEventsTable {
436
+ event_id: string;
437
+ event_type: string;
438
+ processed_at: Generated<Date>;
439
+ }
440
+ interface DecodedEventsTable {
441
+ cursor: string;
442
+ block_height: number;
443
+ tx_id: string;
444
+ tx_index: number;
445
+ event_index: number;
446
+ event_type: string;
447
+ microblock_hash: string | null;
448
+ canonical: Generated<boolean>;
449
+ contract_id: string | null;
450
+ sender: string | null;
451
+ recipient: string | null;
452
+ amount: string | null;
453
+ asset_identifier: string | null;
454
+ value: string | null;
455
+ memo: string | null;
456
+ /** Decoded payload for event types that don't fit the flat columns
457
+ * (e.g. `print`: { topic, value, raw_value }). Null for transfer types. */
458
+ payload: unknown | null;
459
+ source_cursor: string;
460
+ created_at: Generated<Date>;
461
+ }
462
+ interface DecoderCheckpointsTable {
463
+ decoder_name: string;
464
+ last_cursor: string | null;
465
+ updated_at: Generated<Date>;
466
+ }
467
+ interface ChainReorgsTable {
468
+ id: Generated<string>;
469
+ detected_at: Generated<Date>;
470
+ fork_point_height: number;
471
+ old_index_block_hash: string | null;
472
+ new_index_block_hash: string | null;
473
+ orphaned_from_height: number;
474
+ orphaned_from_event_index: number;
475
+ orphaned_to_height: number;
476
+ orphaned_to_event_index: number;
477
+ new_canonical_height: number;
478
+ new_canonical_event_index: number;
479
+ created_at: Generated<Date>;
480
+ }
481
+ type Pox4FunctionName = "stack-stx" | "delegate-stx" | "stack-extend" | "stack-increase" | "revoke-delegate-stx" | "delegate-stack-stx" | "delegate-stack-extend" | "delegate-stack-increase" | "stack-aggregation-commit" | "stack-aggregation-commit-indexed" | "stack-aggregation-increase" | "set-signer-key-authorization";
482
+ interface Pox4CallsTable {
483
+ cursor: string;
484
+ block_height: number;
485
+ block_time: Date;
486
+ burn_block_height: number;
487
+ tx_id: string;
488
+ tx_index: number;
489
+ function_name: Pox4FunctionName;
490
+ caller: string;
491
+ stacker: string | null;
492
+ delegate_to: string | null;
493
+ amount_ustx: string | null;
494
+ lock_period: number | null;
495
+ pox_addr_version: number | null;
496
+ pox_addr_hashbytes: string | null;
497
+ pox_addr_btc: string | null;
498
+ start_cycle: number | null;
499
+ end_cycle: number | null;
500
+ signer_key: string | null;
501
+ signer_signature: string | null;
502
+ auth_id: string | null;
503
+ max_amount: string | null;
504
+ reward_cycle: number | null;
505
+ aggregated_amount_ustx: string | null;
506
+ aggregated_signer_index: number | null;
507
+ auth_period: number | null;
508
+ auth_topic: string | null;
509
+ auth_allowed: boolean | null;
510
+ result_ok: boolean;
511
+ result_raw: string;
512
+ canonical: Generated<boolean>;
513
+ source_cursor: string;
514
+ created_at: Generated<Date>;
515
+ }
516
+ type Pox5EventTopic = "set-bond-admin" | "set-pause-admin" | "pause-rewards" | "setup-bond" | "add-to-allowlist" | "register-for-bond" | "update-bond-registration" | "register-signer" | "stake" | "stake-update" | "announce-l1-early-exit" | "unstake-sbtc" | "unstake" | "calculate-rewards" | "bond-distribution" | "claim-rewards" | "claim-staker-rewards-for-signer" | "grant-signer-key" | "revoke-signer-grant";
517
+ interface Pox5EventsTable {
518
+ cursor: string;
519
+ block_height: number;
520
+ block_time: Date;
521
+ tx_id: string;
522
+ tx_index: number;
523
+ event_index: number;
524
+ topic: Pox5EventTopic;
525
+ staker: string | null;
526
+ signer: string | null;
527
+ signer_manager: string | null;
528
+ bond_index: number | null;
529
+ amount_ustx: string | null;
530
+ amount_sats: string | null;
531
+ reward_cycle: number | null;
532
+ first_reward_cycle: number | null;
533
+ unlock_cycle: number | null;
534
+ unlock_burn_height: number | null;
535
+ is_l1_lock: boolean | null;
536
+ signer_key: string | null;
537
+ data: unknown;
538
+ canonical: Generated<boolean>;
539
+ source_cursor: string;
540
+ created_at: Generated<Date>;
541
+ }
542
+ interface Pox5CyclesTable {
543
+ reward_cycle: number;
544
+ start_burn_height: number;
545
+ prepare_start_burn_height: number;
546
+ end_burn_height: number;
547
+ total_stacked_ustx: string;
548
+ reward_eligible_ustx: string;
549
+ stakers: number;
550
+ signers_in_set: number;
551
+ /** bond index (as string) -> sats staked for this cycle. */
552
+ bond_sats: unknown;
553
+ bond_total_sats: string;
554
+ sbtc_custodied_sats: string;
555
+ rewards_allocated_stx: string;
556
+ rewards_allocated_bond: string;
557
+ reserve_deposit: string;
558
+ rewards_per_token_stx: string | null;
559
+ /** bond index (as string) -> cumulative rewards-per-sat for this cycle. */
560
+ rewards_per_token_bond: unknown;
561
+ distributions: number;
562
+ rewards_claimed: string;
563
+ computed_through_height: number;
564
+ updated_at: Generated<Date>;
565
+ }
566
+ interface Pox5CycleSignersTable {
567
+ reward_cycle: number;
568
+ signer: string;
569
+ delegated_ustx: string;
570
+ stx_only_ustx: string;
571
+ reward_shares_ustx: string;
572
+ in_set: boolean;
573
+ rewards_claimed: string;
574
+ }
575
+ interface BurnBlockRewardsTable {
576
+ cursor: string;
577
+ burn_block_height: number;
578
+ burn_block_hash: string;
579
+ reward_index: number;
580
+ recipient_btc: string;
581
+ amount_sats: string;
582
+ burn_amount: Generated<string>;
583
+ created_at: Generated<Date>;
584
+ }
585
+ interface BurnBlockRewardSlotsTable {
586
+ cursor: string;
587
+ burn_block_height: number;
588
+ burn_block_hash: string;
589
+ slot_index: number;
590
+ holder_btc: string;
591
+ created_at: Generated<Date>;
592
+ }
593
+ type SbtcEventTopic = "completed-deposit" | "withdrawal-create" | "withdrawal-accept" | "withdrawal-reject" | "key-rotation" | "update-protocol-contract";
594
+ interface SbtcEventsTable {
595
+ cursor: string;
596
+ block_height: number;
597
+ block_time: Date;
598
+ tx_id: string;
599
+ tx_index: number;
600
+ event_index: number;
601
+ topic: SbtcEventTopic;
602
+ request_id: number | null;
603
+ amount: string | null;
604
+ sender: string | null;
605
+ recipient_btc_version: number | null;
606
+ recipient_btc_hashbytes: string | null;
607
+ bitcoin_txid: string | null;
608
+ output_index: number | null;
609
+ sweep_txid: string | null;
610
+ burn_hash: string | null;
611
+ burn_height: number | null;
612
+ signer_bitmap: string | null;
613
+ max_fee: string | null;
614
+ fee: string | null;
615
+ block_height_at_request: number | null;
616
+ governance_contract_type: number | null;
617
+ governance_new_contract: string | null;
618
+ signer_aggregate_pubkey: string | null;
619
+ signer_threshold: number | null;
620
+ signer_address: string | null;
621
+ signer_keys_count: number | null;
622
+ canonical: Generated<boolean>;
623
+ source_cursor: string;
624
+ created_at: Generated<Date>;
625
+ }
626
+ type SbtcTokenEventType = "transfer" | "mint" | "burn";
627
+ interface SbtcTokenEventsTable {
628
+ cursor: string;
629
+ block_height: number;
630
+ block_time: Date;
631
+ tx_id: string;
632
+ tx_index: number;
633
+ event_index: number;
634
+ event_type: SbtcTokenEventType;
635
+ sender: string | null;
636
+ recipient: string | null;
637
+ amount: string;
638
+ memo: string | null;
639
+ canonical: Generated<boolean>;
640
+ source_cursor: string;
641
+ created_at: Generated<Date>;
642
+ }
643
+ /**
644
+ * BTC L1 settlement status for sBTC withdrawal sweeps. Filled by the indexer's
645
+ * settlement-confirmer worker, which polls our own bitcoind for confirmations of
646
+ * each `withdrawal-accept`'s `sweep_txid` and surfaces real settlement on the
647
+ * withdrawal lifecycle (the API's `settlement.{btc_confirmations,
648
+ * settlement_confirmed}` placeholder). Keyed on `sweep_txid` (not `request_id`):
649
+ * a request can produce more than one sweep over its life (RBF/rebroadcast), so
650
+ * each broadcast keeps its own confirmation history.
651
+ */
652
+ interface SbtcSettlementsTable {
653
+ sweep_txid: string;
654
+ request_id: number;
655
+ btc_confirmations: Generated<number>;
656
+ settlement_confirmed: Generated<boolean>;
657
+ /** Confirming Bitcoin block — null while the sweep is unconfirmed. */
658
+ block_hash: string | null;
659
+ block_height: number | null;
660
+ first_seen_at: Generated<Date>;
661
+ last_checked_at: Generated<Date>;
662
+ /** Set once, when `settlement_confirmed` first flips true. */
663
+ confirmed_at: Date | null;
664
+ updated_at: Generated<Date>;
665
+ }
666
+ type BnsNameEventTopic = "new-name" | "transfer-name" | "renew-name" | "burn-name" | "new-airdrop";
667
+ interface BnsNameEventsTable {
668
+ cursor: string;
669
+ block_height: number;
670
+ block_time: Date;
671
+ tx_id: string;
672
+ tx_index: number;
673
+ event_index: number;
674
+ topic: BnsNameEventTopic;
675
+ namespace: string;
676
+ name: string;
677
+ fqn: string;
678
+ owner: string | null;
679
+ bns_id: string;
680
+ registered_at: number | null;
681
+ imported_at: number | null;
682
+ renewal_height: number | null;
683
+ stx_burn: string | null;
684
+ preordered_by: string | null;
685
+ hashed_salted_fqn_preorder: string | null;
686
+ canonical: Generated<boolean>;
687
+ source_cursor: string;
688
+ created_at: Generated<Date>;
689
+ }
690
+ type BnsNamespaceEventStatus = "launch" | "transfer-manager" | "freeze-manager" | "update-price-manager" | "freeze-price-manager" | "turn-off-manager-transfers";
691
+ interface BnsNamespaceEventsTable {
692
+ cursor: string;
693
+ block_height: number;
694
+ block_time: Date;
695
+ tx_id: string;
696
+ tx_index: number;
697
+ event_index: number;
698
+ status: BnsNamespaceEventStatus;
699
+ namespace: string;
700
+ manager: string | null;
701
+ manager_frozen: boolean | null;
702
+ manager_transfers_disabled: boolean | null;
703
+ price_function: string | null;
704
+ price_frozen: boolean | null;
705
+ lifetime: number | null;
706
+ revealed_at: number | null;
707
+ launched_at: number | null;
708
+ canonical: Generated<boolean>;
709
+ source_cursor: string;
710
+ created_at: Generated<Date>;
711
+ }
712
+ type BnsMarketplaceAction = "list-in-ustx" | "unlist-in-ustx" | "buy-in-ustx";
713
+ interface BnsMarketplaceEventsTable {
714
+ cursor: string;
715
+ block_height: number;
716
+ block_time: Date;
717
+ tx_id: string;
718
+ tx_index: number;
719
+ event_index: number;
720
+ action: BnsMarketplaceAction;
721
+ bns_id: string;
722
+ price_ustx: string | null;
723
+ commission: string | null;
724
+ canonical: Generated<boolean>;
725
+ source_cursor: string;
726
+ created_at: Generated<Date>;
727
+ }
728
+ interface BnsNamesTable {
729
+ fqn: string;
730
+ namespace: string;
731
+ name: string;
732
+ owner: string;
733
+ bns_id: string;
734
+ registered_at: number | null;
735
+ renewal_height: number | null;
736
+ last_event_cursor: string;
737
+ last_event_at: Date;
738
+ updated_at: Generated<Date>;
739
+ }
740
+ interface BnsNamespacesTable {
741
+ namespace: string;
742
+ manager: string | null;
743
+ manager_frozen: Generated<boolean>;
744
+ price_frozen: Generated<boolean>;
745
+ lifetime: number | null;
746
+ launched_at: number | null;
747
+ last_event_cursor: string;
748
+ last_event_at: Date;
749
+ name_count: Generated<number>;
750
+ updated_at: Generated<Date>;
751
+ }
752
+ /**
753
+ * Memoized `ctx.client.readOnly()` results. Keyed on `index_block_hash` so a
754
+ * reorg-replaced block never inherits the orphaned fork's answer; a NULL
755
+ * `index_block_hash` marks a caller-declared contract-constant value, cached
756
+ * once per contract+args instead of once per block.
757
+ */
758
+ interface ChainReadCacheTable {
759
+ id: Generated<number>;
760
+ contract_id: string;
761
+ function_name: string;
762
+ args_hash: string;
763
+ index_block_hash: string | null;
764
+ block_height: ColumnType<number | null, number | null | undefined, number | null>;
765
+ result_hex: string;
766
+ created_at: Generated<Date>;
767
+ }
768
+ /**
769
+ * A block that arrived for a height we already hold, staged until a later
770
+ * block's `parent_hash` says which of the two the chain kept. See migration
771
+ * 0112 — adopting on first sight picked the losing fork twice.
772
+ */
773
+ interface PendingForkBlocksTable {
774
+ height: number;
775
+ block_hash: string;
776
+ parent_hash: string;
777
+ /** The canonical hash we held at this height when the contender arrived. */
778
+ incumbent_hash: string;
779
+ /** The raw observer payload, replayed verbatim if this fork wins. */
780
+ payload: ColumnType<unknown, unknown, unknown>;
781
+ received_at: Generated<Date>;
782
+ }
783
+ type ObserverJournalStatus = "received" | "processed" | "failed" | "retried";
784
+ /**
785
+ * Exact observer callback receipt. `raw_body` is immutable evidence; the
786
+ * processing columns are updated only after the current derived-state write
787
+ * succeeds or fails.
788
+ */
789
+ interface ObserverJournalTable {
790
+ sequence: Generated<string>;
791
+ network: string;
792
+ path: string;
793
+ source: string | null;
794
+ received_at: Generated<Date>;
795
+ raw_body: ColumnType<Buffer, Buffer, Buffer>;
796
+ raw_body_sha256: string;
797
+ status: ColumnType<ObserverJournalStatus, ObserverJournalStatus | undefined, ObserverJournalStatus>;
798
+ semantic_sha256: string | null;
799
+ block_height: number | null;
800
+ block_hash: string | null;
801
+ burn_block_height: number | null;
802
+ burn_block_hash: string | null;
803
+ result: unknown | null;
804
+ error: string | null;
805
+ processed_at: Date | null;
806
+ }
807
+ /** Declared coverage stage. Identity is the `id` string (`raw`, `decode:stx`, …). */
808
+ interface StageRegistryTable {
809
+ id: string;
810
+ kind: StageKind;
811
+ depends_on: string | null;
812
+ native_clock: NativeClock;
813
+ producer_version: string;
814
+ repair_mode: RepairMode;
815
+ enabled: Generated<boolean>;
816
+ created_at: Generated<Date>;
817
+ }
818
+ /** One versioned sweep of a stage. */
819
+ interface StageRunsTable {
820
+ id: Generated<string>;
821
+ stage_id: string;
822
+ code_hash: string;
823
+ config_hash: string;
824
+ handler_hash: string | null;
825
+ target_height: number | null;
826
+ target_cursor: string | null;
827
+ status: RunStatus;
828
+ complete_through: number | null;
829
+ started_at: Generated<Date>;
830
+ finished_at: Date | null;
831
+ }
832
+ /** Per-block acknowledgement. Unique on (stage, height, hash). */
833
+ interface StageBlockReceiptsTable {
834
+ id: Generated<string>;
835
+ stage_id: string;
836
+ run_id: string | null;
837
+ block_height: number;
838
+ block_hash: string;
839
+ input_count: number;
840
+ input_digest: string;
841
+ effect_digest: string;
842
+ finalized: Generated<boolean>;
843
+ compacted_at: Date | null;
844
+ created_at: Generated<Date>;
845
+ }
846
+ /** Compacted finalized range. Only sealed after receipts in the range finalize. */
847
+ interface CoverageSegmentsTable {
848
+ id: Generated<string>;
849
+ stage_id: string;
850
+ from_height: number;
851
+ to_height: number;
852
+ chain_digest: string;
853
+ input_digest: string;
854
+ output_digest: string;
855
+ sealed_at: Generated<Date>;
856
+ }
857
+ /** Exact unit or range that failed, plus retry/retention state. */
858
+ interface StageFailuresTable {
859
+ id: Generated<string>;
860
+ stage_id: string;
861
+ run_id: string | null;
862
+ unit_kind: FailureUnit;
863
+ from_height: number | null;
864
+ to_height: number | null;
865
+ class: FailureClass;
866
+ retry_state: RetryState;
867
+ retry_count: Generated<number>;
868
+ last_error: string | null;
869
+ created_at: Generated<Date>;
870
+ resolved_at: Date | null;
871
+ retain_until: Generated<Date>;
872
+ }
873
+ /**
874
+ * The instance's declared scope — one row per network. `start_height` is what
875
+ * makes missing history below it deliberate rather than a gap.
876
+ */
877
+ interface SyncScopesTable {
878
+ network: string;
879
+ start_height: number;
880
+ target_height: number | null;
881
+ bootstrap_source: BootstrapSource;
882
+ bootstrap_manifest_digest: string | null;
883
+ genesis_hash: string | null;
884
+ created_at: Generated<Date>;
885
+ updated_at: Generated<Date>;
886
+ }
887
+ interface Database {
888
+ blocks: BlocksTable;
889
+ transactions: TransactionsTable;
890
+ events: EventsTable;
891
+ vm_events: VmEventsTable;
892
+ state_writes: StateWritesTable;
893
+ transactions_archive: TransactionsArchiveTable;
894
+ events_archive: EventsArchiveTable;
895
+ vm_events_archive: VmEventsArchiveTable;
896
+ state_writes_archive: StateWritesArchiveTable;
897
+ dead_letter_events: DeadLetterEventsTable;
898
+ mempool_transactions: MempoolTransactionsTable;
899
+ index_progress: IndexProgressTable;
900
+ contracts: ContractsTable;
901
+ subgraphs: SubgraphsTable;
902
+ api_keys: ApiKeysTable;
903
+ instances: InstancesTable;
904
+ accounts: AccountsTable;
905
+ sessions: SessionsTable;
906
+ magic_links: MagicLinksTable;
907
+ subgraph_health_snapshots: SubgraphHealthSnapshotsTable;
908
+ subgraph_processing_stats: SubgraphProcessingStatsTable;
909
+ subgraph_gaps: SubgraphGapsTable;
910
+ subgraph_violations: SubgraphViolationsTable;
911
+ subgraph_error_groups: SubgraphErrorGroupsTable;
912
+ subgraph_operations: SubgraphOperationsTable;
913
+ processed_stripe_events: ProcessedStripeEventsTable;
914
+ account_spend_caps: AccountSpendCapsTable;
915
+ account_credits: AccountCreditsTable;
916
+ webhooks: WebhooksTable;
917
+ webhook_outbox: WebhookOutboxTable;
918
+ webhook_deliveries: WebhookDeliveriesTable;
919
+ webhook_replays: WebhookReplaysTable;
920
+ trigger_evaluator_state: TriggerEvaluatorStateTable;
921
+ decoded_events: DecodedEventsTable;
922
+ decoder_checkpoints: DecoderCheckpointsTable;
923
+ chain_reorgs: ChainReorgsTable;
924
+ pox4_calls: Pox4CallsTable;
925
+ pox5_events: Pox5EventsTable;
926
+ pox5_cycles: Pox5CyclesTable;
927
+ pox5_cycle_signers: Pox5CycleSignersTable;
928
+ burn_block_rewards: BurnBlockRewardsTable;
929
+ burn_block_reward_slots: BurnBlockRewardSlotsTable;
930
+ sbtc_events: SbtcEventsTable;
931
+ sbtc_token_events: SbtcTokenEventsTable;
932
+ sbtc_settlements: SbtcSettlementsTable;
933
+ bns_name_events: BnsNameEventsTable;
934
+ bns_namespace_events: BnsNamespaceEventsTable;
935
+ bns_marketplace_events: BnsMarketplaceEventsTable;
936
+ bns_names: BnsNamesTable;
937
+ bns_namespaces: BnsNamespacesTable;
938
+ service_heartbeats: ServiceHeartbeatsTable;
939
+ chain_read_cache: ChainReadCacheTable;
940
+ pending_fork_blocks: PendingForkBlocksTable;
941
+ observer_journal: ObserverJournalTable;
942
+ sync_scopes: SyncScopesTable;
943
+ stage_registry: StageRegistryTable;
944
+ stage_runs: StageRunsTable;
945
+ stage_block_receipts: StageBlockReceiptsTable;
946
+ coverage_segments: CoverageSegmentsTable;
947
+ stage_failures: StageFailuresTable;
948
+ archive_fetches: ArchiveFetchesTable;
949
+ usage_ledger: UsageLedgerTable;
950
+ account_balance_alerts: AccountBalanceAlertsTable;
951
+ webhook_incident_alerts: WebhookIncidentAlertsTable;
952
+ cli_device_logins: CliDeviceLoginsTable;
953
+ oauth_clients: OauthClientsTable;
954
+ oauth_requests: OauthRequestsTable;
955
+ oauth_codes: OauthCodesTable;
956
+ oauth_grants: OauthGrantsTable;
957
+ oauth_tokens: OauthTokensTable;
958
+ oauth_refresh_retired: OauthRefreshRetiredTable;
959
+ sentinel_accounts: SentinelAccountsTable;
960
+ waitlists: WaitlistsTable;
961
+ waitlist_signups: WaitlistSignupsTable;
962
+ contact_requests: ContactRequestsTable;
963
+ api_failed_requests: ApiFailedRequestsTable;
964
+ api_request_log: ApiRequestLogTable;
965
+ insights: InsightsTable;
966
+ insight_mutes: InsightMutesTable;
967
+ feedback_tickets: FeedbackTicketsTable;
968
+ push_subscriptions: PushSubscriptionsTable;
969
+ push_prefs: PushPrefsTable;
970
+ push_sent: PushSentTable;
971
+ }
972
+ interface ServiceHeartbeatsTable {
973
+ name: string;
974
+ updated_at: Generated<Date>;
975
+ }
976
+ interface AccountSpendCapsTable {
977
+ account_id: string;
978
+ monthly_cap_cents: number | null;
979
+ compute_cap_cents: number | null;
980
+ storage_cap_cents: number | null;
981
+ alert_threshold_pct: Generated<number>;
982
+ alert_sent_at: Date | null;
983
+ frozen_at: Date | null;
984
+ updated_at: Generated<Date>;
985
+ }
986
+ /** Prepaid dev credits — card-funded balance per account. */
987
+ interface AccountCreditsTable {
988
+ account_id: string;
989
+ balance_usd_micros: Generated<string | number | bigint>;
990
+ /** Month bucket ("YYYY-MM") the spend counter applies to. */
991
+ spent_month: string | null;
992
+ spent_month_usd_micros: Generated<string | number | bigint>;
993
+ /** Null = auto-refill off. */
994
+ refill_below_usd_micros: string | number | bigint | null;
995
+ refill_pack_usd: number | null;
996
+ refill_last_at: Date | null;
997
+ updated_at: Generated<Date>;
998
+ }
999
+ /**
1000
+ * Archive fetch charge log. Append-only: one row per
1001
+ * priced attempt to fetch a partition object. `usd_micros` is 0 for
1002
+ * free rows (24h re-issue, monthly repair allowance).
1003
+ */
1004
+ interface ArchiveFetchesTable {
1005
+ id: Generated<string>;
1006
+ account_id: string;
1007
+ path: string;
1008
+ dataset: string;
1009
+ usd_micros: string | number | bigint;
1010
+ via_allowance: Generated<boolean>;
1011
+ charged_at: Generated<Date>;
1012
+ }
1013
+ /**
1014
+ * One metered ledger for every billable unit (archive partitions, hosted
1015
+ * Index/Streams rows, and future hosted-stack meters). Append-only, written
1016
+ * only by `meter()`. `idempotency_key` is UNIQUE so a retried submission
1017
+ * no-ops instead of double-charging. `debited` is false when the balance
1018
+ * (or a spend cap) refused the charge — the row still exists so the gap is
1019
+ * visible, never silently dropped. `usd_micros` is negative for a Stripe
1020
+ * top-up (`unit: "topup"`).
1021
+ */
1022
+ interface UsageLedgerTable {
1023
+ id: Generated<string>;
1024
+ account_id: string;
1025
+ unit: string;
1026
+ quantity: string | number | bigint;
1027
+ /** Raw sampled quantity before any floor (e.g. `memory.gb_hour`'s actual
1028
+ * RAM, before the 0.5 GB minimum). NULL for every unit that has no
1029
+ * floor to observe past. */
1030
+ observed_quantity: string | number | null;
1031
+ usd_micros: string | number | bigint;
1032
+ debited: Generated<boolean>;
1033
+ source: string;
1034
+ /** API key behind a metered read; null for non-read units and older rows. */
1035
+ api_key_id: string | null;
1036
+ idempotency_key: string;
1037
+ occurred_at: Generated<Date>;
1038
+ recorded_at: Generated<Date>;
1039
+ }
1040
+ /** Preferences + debounce state for the balance-runway email alerts. One
1041
+ * row per account; a missing row means both alerts are on (defaults). */
1042
+ interface AccountBalanceAlertsTable {
1043
+ account_id: string;
1044
+ notify_7d: Generated<boolean>;
1045
+ notify_2d: Generated<boolean>;
1046
+ sent_7d_at: Date | null;
1047
+ sent_2d_at: Date | null;
1048
+ sent_stopped_at: Date | null;
1049
+ }
1050
+ /** Debounce state for the webhook-down email: one row per incident, open
1051
+ * while `resolved_at` is null. No preference columns by design. */
1052
+ interface WebhookIncidentAlertsTable {
1053
+ id: Generated<string>;
1054
+ account_id: string;
1055
+ webhook_id: string;
1056
+ webhook_name: string;
1057
+ failing_since: Date;
1058
+ opened_at: Generated<Date>;
1059
+ emailed_at: Date | null;
1060
+ email_attempts: Generated<number>;
1061
+ resolved_at: Date | null;
1062
+ }
1063
+ /** One browser/device push subscription; the endpoint is unique. */
1064
+ interface PushSubscriptionsTable {
1065
+ id: Generated<string>;
1066
+ account_id: string;
1067
+ endpoint: string;
1068
+ p256dh: string;
1069
+ auth: string;
1070
+ user_agent: string | null;
1071
+ created_at: Generated<Date>;
1072
+ last_success_at: Date | null;
1073
+ failed_count: Generated<number>;
1074
+ }
1075
+ /** Per-account push toggles. A missing row means the column defaults. */
1076
+ interface PushPrefsTable {
1077
+ account_id: string;
1078
+ webhook_failing: Generated<boolean>;
1079
+ subgraph_stopped: Generated<boolean>;
1080
+ subgraph_not_serving: Generated<boolean>;
1081
+ replay_done: Generated<boolean>;
1082
+ spend_cap: Generated<boolean>;
1083
+ key_repeat: Generated<boolean>;
1084
+ updated_at: Generated<Date>;
1085
+ }
1086
+ /** A push already sent, keyed by what it was about; debounces repeat signals. */
1087
+ interface PushSentTable {
1088
+ account_id: string;
1089
+ key: string;
1090
+ kind: string;
1091
+ sent_at: Generated<Date>;
1092
+ }
1093
+ type CliDeviceLoginStatus = "pending" | "approved" | "denied" | "consumed";
1094
+ /** The product that started a CLI sign-in; null is `sl login`. */
1095
+ type CliDeviceProduct = "sentinel";
1096
+ /** One browser sign-in attempt from `sl login` (or `sentinel login`). Only the
1097
+ * hash of the CLI's device code is stored; the session is opened when the CLI
1098
+ * polls after approval. */
1099
+ interface CliDeviceLoginsTable {
1100
+ id: Generated<string>;
1101
+ device_code_hash: string;
1102
+ user_code: string;
1103
+ client_name: string;
1104
+ product: CliDeviceProduct | null;
1105
+ status: Generated<CliDeviceLoginStatus>;
1106
+ account_id: string | null;
1107
+ key_name: string | null;
1108
+ created_at: Generated<Date>;
1109
+ expires_at: Date;
1110
+ approved_at: Date | null;
1111
+ consumed_at: Date | null;
1112
+ }
1113
+ /** An app that registered itself (RFC 7591). Public clients only: no secret. */
1114
+ interface OauthClientsTable {
1115
+ id: string;
1116
+ /** The app's own claim, validated at registration; shown quoted. */
1117
+ name: string;
1118
+ redirect_uris: string[];
1119
+ created_ip: string | null;
1120
+ created_at: Generated<Date>;
1121
+ /** Set when it first gets tokens; never-used clients are purged. */
1122
+ last_used_at: Date | null;
1123
+ }
1124
+ type OauthRequestStatus = "pending" | "approved" | "denied";
1125
+ /** One authorize request waiting for (or answered on) the consent page. */
1126
+ interface OauthRequestsTable {
1127
+ id: string;
1128
+ client_id: string;
1129
+ redirect_uri: string;
1130
+ state: string | null;
1131
+ code_challenge: string;
1132
+ resource: string;
1133
+ status: Generated<OauthRequestStatus>;
1134
+ account_id: string | null;
1135
+ created_at: Generated<Date>;
1136
+ expires_at: Date;
1137
+ answered_at: Date | null;
1138
+ }
1139
+ /** A one-time authorization code, bound to its client, redirect, PKCE
1140
+ * challenge, resource and account. */
1141
+ interface OauthCodesTable {
1142
+ code_hash: string;
1143
+ client_id: string;
1144
+ account_id: string;
1145
+ redirect_uri: string;
1146
+ code_challenge: string;
1147
+ resource: string;
1148
+ /** The grant its one use made, so a replay can revoke it. */
1149
+ grant_id: string | null;
1150
+ created_at: Generated<Date>;
1151
+ expires_at: Date;
1152
+ used_at: Date | null;
1153
+ }
1154
+ /** What a person allowed one app to do: use the hosted MCP as them. */
1155
+ interface OauthGrantsTable {
1156
+ id: Generated<string>;
1157
+ account_id: string;
1158
+ client_id: string;
1159
+ scope: Generated<string>;
1160
+ resource: string;
1161
+ created_at: Generated<Date>;
1162
+ last_used_at: Date | null;
1163
+ revoked_at: Date | null;
1164
+ }
1165
+ type OauthTokenKind = "access" | "refresh";
1166
+ interface OauthTokensTable {
1167
+ token_hash: string;
1168
+ grant_id: string;
1169
+ kind: OauthTokenKind;
1170
+ created_at: Generated<Date>;
1171
+ expires_at: Date;
1172
+ }
1173
+ /** A refresh token a rotation replaced: presented again, it revokes the grant. */
1174
+ interface OauthRefreshRetiredTable {
1175
+ token_hash: string;
1176
+ grant_id: string;
1177
+ retired_at: Generated<Date>;
1178
+ }
1179
+ /** Accounts Sentinel's service key may touch: created by Sentinel, or the
1180
+ * owner opted in. */
1181
+ interface SentinelAccountsTable {
1182
+ account_id: string;
1183
+ linked_at: Generated<Date>;
1184
+ via: "created" | "consent";
1185
+ }
1186
+ type WebhookStatus2 = "active" | "paused" | "error";
1187
+ /** Webhooks react to raw chain events matched directly off the Index/Streams
1188
+ * clock. `chain` is the only kind since migration 0159 removed subgraph-row
1189
+ * webhooks; the column stays as the discriminator. */
1190
+ type WebhookKind2 = "chain";
1191
+ type WebhookFormat2 = "standard-webhooks" | "inngest" | "trigger" | "cloudflare" | "cloudevents" | "raw";
1192
+ interface WebhooksTable {
1193
+ id: Generated<string>;
1194
+ account_id: string;
1195
+ project_id: string | null;
1196
+ name: string;
1197
+ status: ColumnType<WebhookStatus2, WebhookStatus2 | undefined, WebhookStatus2>;
1198
+ kind: ColumnType<WebhookKind2, WebhookKind2 | undefined, WebhookKind2>;
1199
+ /** Chain-trigger filter array (the `SubgraphFilter` shape, JSON). Typed
1200
+ * loosely here to avoid a shared→subgraphs import cycle; the Zod schema in
1201
+ * schemas/webhooks.ts owns the shape. */
1202
+ triggers: unknown;
1203
+ format: ColumnType<WebhookFormat2, WebhookFormat2 | undefined, WebhookFormat2>;
1204
+ url: string;
1205
+ signing_secret_enc: Buffer;
1206
+ auth_config: Generated<unknown>;
1207
+ max_retries: Generated<number>;
1208
+ timeout_ms: Generated<number>;
1209
+ concurrency: Generated<number>;
1210
+ circuit_failures: Generated<number>;
1211
+ circuit_opened_at: Date | null;
1212
+ last_delivery_at: Date | null;
1213
+ last_success_at: Date | null;
1214
+ last_error: string | null;
1215
+ /** Receiver TLS leaf certificate expiry, from the emitter's periodic probe. */
1216
+ receiver_cert_expires_at: Date | null;
1217
+ receiver_cert_checked_at: Date | null;
1218
+ created_at: Generated<Date>;
1219
+ updated_at: Generated<Date>;
1220
+ }
1221
+ type OutboxStatus = "pending" | "delivered" | "dead";
1222
+ interface WebhookOutboxTable {
1223
+ id: Generated<string>;
1224
+ webhook_id: string;
1225
+ kind: ColumnType<WebhookKind2, WebhookKind2 | undefined, WebhookKind2>;
1226
+ block_height: number | bigint;
1227
+ tx_id: string | null;
1228
+ row_pk: unknown;
1229
+ event_type: string;
1230
+ payload: unknown;
1231
+ dedup_key: string;
1232
+ attempt: Generated<number>;
1233
+ next_attempt_at: Generated<Date>;
1234
+ status: ColumnType<OutboxStatus, OutboxStatus | undefined, OutboxStatus>;
1235
+ is_replay: Generated<boolean>;
1236
+ /** The replay that created this row; null for live rows. */
1237
+ replay_id: string | null;
1238
+ /** The chain block_time of the matched event/tx. Null for rows written
1239
+ * before this column existed, and for the settlement scan path (not yet
1240
+ * wired). Lets `delivered_at - block_time` measure end-to-end webhook
1241
+ * latency without a join to SOURCE-plane `blocks`. */
1242
+ block_time: Date | null;
1243
+ delivered_at: Date | null;
1244
+ failed_at: Date | null;
1245
+ locked_by: string | null;
1246
+ locked_until: Date | null;
1247
+ /** Set when a reorg marks an in-flight row `dead` instead of retrying it
1248
+ * into an orphaned fork. Null otherwise — delivery failures track their
1249
+ * history on `webhooks.last_error`, not per-row. */
1250
+ last_error: string | null;
1251
+ created_at: Generated<Date>;
1252
+ }
1253
+ type WebhookReplayStatus = "scanning" | "running" | "done" | "failed";
1254
+ interface WebhookReplaysTable {
1255
+ id: string;
1256
+ webhook_id: string;
1257
+ from_block: number | bigint;
1258
+ to_block: number | bigint;
1259
+ status: WebhookReplayStatus;
1260
+ scanned_count: Generated<number>;
1261
+ enqueued_count: Generated<number>;
1262
+ total: number | null;
1263
+ delivered: number | null;
1264
+ gave_up: number | null;
1265
+ error: string | null;
1266
+ started_at: Generated<Date>;
1267
+ finished_at: Date | null;
1268
+ }
1269
+ type WebhookReplay = Selectable<WebhookReplaysTable>;
1270
+ interface WebhookDeliveriesTable {
1271
+ id: Generated<string>;
1272
+ /** Nullable after migration 0077 — outbox row may be cleaned up while
1273
+ * delivery telemetry is retained. */
1274
+ outbox_id: string | null;
1275
+ webhook_id: string;
1276
+ attempt: number;
1277
+ status_code: number | null;
1278
+ response_headers: unknown | null;
1279
+ response_body: string | null;
1280
+ error_message: string | null;
1281
+ duration_ms: number | null;
1282
+ dispatched_at: Generated<Date>;
1283
+ }
1284
+ /** Single-row (id always TRUE) high-water mark for the chain-trigger evaluator.
1285
+ * One loop serves all chain webhooks, so the cursor is global. */
1286
+ interface TriggerEvaluatorStateTable {
1287
+ id: Generated<boolean>;
1288
+ last_processed_block: ColumnType<bigint, bigint | number | undefined, bigint | number>;
1289
+ /** Watermark for the async sBTC settlement-confirmed webhook scan; null until
1290
+ * the evaluator fast-forwards it on first run. */
1291
+ last_settlement_scan_at: ColumnType<Date | null, Date | null | undefined, Date | null>;
1292
+ /** Streams cursor (`<block_height>:<event_index>`) for the Bitcoin (Runes)
1293
+ * chain-trigger evaluator (plan 060) — a separate clock from
1294
+ * `last_processed_block` (Stacks). Null until the evaluator fast-forwards
1295
+ * it to the Bitcoin Streams tip on first run. */
1296
+ bitcoin_last_cursor: ColumnType<string | null, string | null | undefined, string | null>;
1297
+ updated_at: Generated<Date>;
1298
+ }
1299
+ /** A public waitlist page: what it is for and whether it takes signups. */
1300
+ interface WaitlistsTable {
1301
+ slug: string;
1302
+ title: string;
1303
+ description: string;
1304
+ url: string;
1305
+ opened_at: Generated<Date>;
1306
+ /** Null while the list is open. */
1307
+ closed_at: Date | null;
1308
+ }
1309
+ /**
1310
+ * One signup per (list, contact, token). `answers` holds the list's own
1311
+ * questions, validated per list by the API before insert.
1312
+ */
1313
+ interface WaitlistSignupsTable {
1314
+ id: Generated<string>;
1315
+ list: string;
1316
+ contact: string;
1317
+ answers: Record<string, unknown>;
1318
+ created_at: Generated<Date>;
1319
+ }
1320
+ /**
1321
+ * A "Talk to us" message. Stored before the operator is emailed;
1322
+ * `notified_at` stays null until the email goes out.
1323
+ */
1324
+ interface ContactRequestsTable {
1325
+ id: Generated<string>;
1326
+ name: string;
1327
+ email: string;
1328
+ company: string | null;
1329
+ volume: "lt10m" | "10m-100m" | "100m-1b" | "gt1b" | "unsure" | null;
1330
+ message: string;
1331
+ source_page: string | null;
1332
+ account_id: string | null;
1333
+ /** Hex sha256 of the client IP, never the address. */
1334
+ ip_hash: string | null;
1335
+ notified_at: Date | null;
1336
+ created_at: Generated<Date>;
1337
+ }
1338
+ /**
1339
+ * 24h hosted record of a failed API request, keyed by `request_id` and
1340
+ * scoped to the account that made it. `query` is redacted before insert.
1341
+ */
1342
+ interface ApiFailedRequestsTable {
1343
+ request_id: string;
1344
+ account_id: string;
1345
+ method: string;
1346
+ path: string;
1347
+ status: number;
1348
+ code: string;
1349
+ message: Generated<string>;
1350
+ query: Record<string, unknown>;
1351
+ origin: string | null;
1352
+ /** Revoked account key the request presented (`KEY_REVOKED` only). */
1353
+ api_key_id: string | null;
1354
+ created_at: Generated<Date>;
1355
+ }
1356
+ /**
1357
+ * 7-day hosted log of account-attributed Index/Streams reads. Query values
1358
+ * are stored only as hashes; never bodies, headers or tokens.
1359
+ */
1360
+ interface ApiRequestLogTable {
1361
+ id: Generated<string>;
1362
+ request_id: string | null;
1363
+ account_id: string;
1364
+ api_key_id: string | null;
1365
+ method: string;
1366
+ path: string;
1367
+ path_template: string;
1368
+ params_hash: string | null;
1369
+ cursor_hash: string | null;
1370
+ page_size: number | null;
1371
+ rows: number | null;
1372
+ status: number;
1373
+ duration_ms: number;
1374
+ created_at: Generated<Date>;
1375
+ }
1376
+ /**
1377
+ * Hosted problem report. `attempted` is the server's own copy of the failed
1378
+ * request (never caller-supplied); `status` starts `new` until classified.
1379
+ */
1380
+ interface FeedbackTicketsTable {
1381
+ id: Generated<string>;
1382
+ account_id: string;
1383
+ idempotency_key: string | null;
1384
+ request_id: string | null;
1385
+ intent: string;
1386
+ expected: Record<string, unknown> | null;
1387
+ kind_hint: string | null;
1388
+ evidence: Record<string, unknown> | null;
1389
+ attempted: Record<string, unknown> | null;
1390
+ origin: string;
1391
+ status: Generated<"new" | "classified">;
1392
+ route: string | null;
1393
+ classification: Record<string, unknown> | null;
1394
+ classified_at: Date | null;
1395
+ created_at: Generated<Date>;
1396
+ }
1397
+ /** Thrown by {@link beginReplay} when a replay is still scanning for the
1398
+ * webhook. The route maps this to 409; `force` does not bypass it. */
1399
+ declare class ReplayInProgressError extends Error {
1400
+ constructor();
1401
+ }
1402
+ declare function beginReplay(db: Kysely<Database>, input: {
1403
+ id: string
1404
+ webhookId: string
1405
+ fromBlock: number
1406
+ toBlock: number
1407
+ }): Promise<void>;
1408
+ declare function finishScan(db: Kysely<Database>, id: string, counts: {
1409
+ scanned: number
1410
+ enqueued: number
1411
+ }): Promise<void>;
1412
+ declare function failScan(db: Kysely<Database>, id: string, error: string): Promise<void>;
1413
+ /** Outbox rows of this replay still waiting to be delivered or to give up. */
1414
+ declare function pendingCount(db: Kysely<Database>, id: string): Promise<number>;
1415
+ /** Outbox rows of this replay that gave up. Finalize only; never on a poll. */
1416
+ declare function deadCount(db: Kysely<Database>, webhookId: string, id: string): Promise<number>;
1417
+ declare function progressOf(record: WebhookReplay, pending: number): ReplayProgress;
1418
+ declare function readReplay(db: Kysely<Database>, webhookId: string, id: string): Promise<ReplayProgress | null>;
1419
+ /** Replays in progress or started within `sinceHours`, newest first. */
1420
+ declare function listReplays(db: Kysely<Database>, input: {
1421
+ webhookIds: string[]
1422
+ sinceHours: number
1423
+ limit: number
1424
+ }): Promise<ReplayProgress[]>;
1425
+ /** Newest replays of one webhook, finalizing any that have drained. */
1426
+ declare function listWebhookReplays(db: Kysely<Database>, webhookId: string, limit: number): Promise<ReplayProgress[]>;
1427
+ /** Retention backstop: finalize every running replay that has drained. */
1428
+ declare function finalizeReplays(db: Kysely<Database>): Promise<void>;
1429
+ declare function deadSince(db: Kysely<Database>, webhookId: string, since: Date | null): Promise<number>;
1430
+ declare function knownEventsInRange(db: Kysely<Database>, webhookId: string, from: number, to: number): Promise<number>;
1431
+ export { ReplayInProgressError, beginReplay, deadCount, deadSince, failScan, finalizeReplays, finishScan, knownEventsInRange, listReplays, listWebhookReplays, pendingCount, progressOf, readReplay };