@bluefields/db 0.2.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 (76) hide show
  1. package/LICENSE +202 -0
  2. package/dist/client.d.ts +6 -0
  3. package/dist/client.js +13 -0
  4. package/dist/client.js.map +1 -0
  5. package/dist/index.d.ts +19 -0
  6. package/dist/index.js +20 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/migrate.d.ts +11 -0
  9. package/dist/migrate.js +48 -0
  10. package/dist/migrate.js.map +1 -0
  11. package/dist/schema/api-keys.d.ts +145 -0
  12. package/dist/schema/api-keys.js +18 -0
  13. package/dist/schema/api-keys.js.map +1 -0
  14. package/dist/schema/audit-log.d.ts +228 -0
  15. package/dist/schema/audit-log.js +49 -0
  16. package/dist/schema/audit-log.js.map +1 -0
  17. package/dist/schema/cost-records.d.ts +190 -0
  18. package/dist/schema/cost-records.js +55 -0
  19. package/dist/schema/cost-records.js.map +1 -0
  20. package/dist/schema/crawl-job-pages.d.ts +186 -0
  21. package/dist/schema/crawl-job-pages.js +31 -0
  22. package/dist/schema/crawl-job-pages.js.map +1 -0
  23. package/dist/schema/crawl-jobs.d.ts +271 -0
  24. package/dist/schema/crawl-jobs.js +40 -0
  25. package/dist/schema/crawl-jobs.js.map +1 -0
  26. package/dist/schema/customers.d.ts +145 -0
  27. package/dist/schema/customers.js +19 -0
  28. package/dist/schema/customers.js.map +1 -0
  29. package/dist/schema/event-feedback.d.ts +170 -0
  30. package/dist/schema/event-feedback.js +35 -0
  31. package/dist/schema/event-feedback.js.map +1 -0
  32. package/dist/schema/events.d.ts +291 -0
  33. package/dist/schema/events.js +58 -0
  34. package/dist/schema/events.js.map +1 -0
  35. package/dist/schema/extractions.d.ts +327 -0
  36. package/dist/schema/extractions.js +56 -0
  37. package/dist/schema/extractions.js.map +1 -0
  38. package/dist/schema/host-extractors.d.ts +131 -0
  39. package/dist/schema/host-extractors.js +18 -0
  40. package/dist/schema/host-extractors.js.map +1 -0
  41. package/dist/schema/host-records.d.ts +237 -0
  42. package/dist/schema/host-records.js +42 -0
  43. package/dist/schema/host-records.js.map +1 -0
  44. package/dist/schema/notification-preferences.d.ts +195 -0
  45. package/dist/schema/notification-preferences.js +49 -0
  46. package/dist/schema/notification-preferences.js.map +1 -0
  47. package/dist/schema/scrape-cache.d.ts +136 -0
  48. package/dist/schema/scrape-cache.js +23 -0
  49. package/dist/schema/scrape-cache.js.map +1 -0
  50. package/dist/schema/sessions.d.ts +153 -0
  51. package/dist/schema/sessions.js +27 -0
  52. package/dist/schema/sessions.js.map +1 -0
  53. package/dist/schema/snapshots.d.ts +382 -0
  54. package/dist/schema/snapshots.js +60 -0
  55. package/dist/schema/snapshots.js.map +1 -0
  56. package/dist/schema/subscriptions.d.ts +604 -0
  57. package/dist/schema/subscriptions.js +79 -0
  58. package/dist/schema/subscriptions.js.map +1 -0
  59. package/dist/schema/usage-periods.d.ts +446 -0
  60. package/dist/schema/usage-periods.js +71 -0
  61. package/dist/schema/usage-periods.js.map +1 -0
  62. package/dist/tsconfig.tsbuildinfo +1 -0
  63. package/package.json +54 -0
  64. package/src/migrations/0001_initial.sql +398 -0
  65. package/src/migrations/0002_pg_cron.sql +109 -0
  66. package/src/migrations/0003_webhook_secret_cleanup.sql +55 -0
  67. package/src/migrations/0004_events_pg_notify.sql +39 -0
  68. package/src/migrations/0005_subscription_consecutive_failures.sql +19 -0
  69. package/src/migrations/0006_notification_preferences.sql +27 -0
  70. package/src/migrations/0007_crawl_jobs.sql +65 -0
  71. package/src/migrations/0008_sessions.sql +38 -0
  72. package/src/migrations/0009_scrape_cache.sql +34 -0
  73. package/src/migrations/0010_neon_defaults.sql +99 -0
  74. package/src/migrations/0011_credits_consumed_numeric.sql +12 -0
  75. package/src/migrations/0012_crawl_page_attestation.sql +10 -0
  76. package/src/migrations/0013_customer_deleted_at.sql +5 -0
@@ -0,0 +1,446 @@
1
+ /**
2
+ * Per-customer per-billing-period usage counters (Review #8).
3
+ *
4
+ * Updated by triggers on events + cost_records (deferred to a later chunk per
5
+ * Chunk 1 spec); read by quota checks, alerts, dashboard.
6
+ *
7
+ * Not partitioned (one row per customer per period — small table even at scale).
8
+ *
9
+ * Grandfathering: plan snapshot captured at period start; mid-period plan
10
+ * changes don't break invariants. Same row holds both events-based quotas
11
+ * (Review #8) and credits-based quotas for the MCP agent path (Review #10).
12
+ */
13
+ export declare const usagePeriods: import("drizzle-orm/pg-core").PgTableWithColumns<{
14
+ name: "usage_periods";
15
+ schema: undefined;
16
+ columns: {
17
+ customerId: import("drizzle-orm/pg-core").PgColumn<{
18
+ name: "customer_id";
19
+ tableName: "usage_periods";
20
+ dataType: "string";
21
+ columnType: "PgUUID";
22
+ data: string;
23
+ driverParam: string;
24
+ notNull: true;
25
+ hasDefault: false;
26
+ isPrimaryKey: false;
27
+ isAutoincrement: false;
28
+ hasRuntimeDefault: false;
29
+ enumValues: undefined;
30
+ baseColumn: never;
31
+ identity: undefined;
32
+ generated: undefined;
33
+ }, {}, {}>;
34
+ periodStart: import("drizzle-orm/pg-core").PgColumn<{
35
+ name: "period_start";
36
+ tableName: "usage_periods";
37
+ dataType: "string";
38
+ columnType: "PgDateString";
39
+ data: string;
40
+ driverParam: string;
41
+ notNull: true;
42
+ hasDefault: false;
43
+ isPrimaryKey: false;
44
+ isAutoincrement: false;
45
+ hasRuntimeDefault: false;
46
+ enumValues: undefined;
47
+ baseColumn: never;
48
+ identity: undefined;
49
+ generated: undefined;
50
+ }, {}, {}>;
51
+ periodEnd: import("drizzle-orm/pg-core").PgColumn<{
52
+ name: "period_end";
53
+ tableName: "usage_periods";
54
+ dataType: "string";
55
+ columnType: "PgDateString";
56
+ data: string;
57
+ driverParam: string;
58
+ notNull: true;
59
+ hasDefault: false;
60
+ isPrimaryKey: false;
61
+ isAutoincrement: false;
62
+ hasRuntimeDefault: false;
63
+ enumValues: undefined;
64
+ baseColumn: never;
65
+ identity: undefined;
66
+ generated: undefined;
67
+ }, {}, {}>;
68
+ plan: import("drizzle-orm/pg-core").PgColumn<{
69
+ name: "plan";
70
+ tableName: "usage_periods";
71
+ dataType: "string";
72
+ columnType: "PgText";
73
+ data: string;
74
+ driverParam: string;
75
+ notNull: true;
76
+ hasDefault: false;
77
+ isPrimaryKey: false;
78
+ isAutoincrement: false;
79
+ hasRuntimeDefault: false;
80
+ enumValues: [string, ...string[]];
81
+ baseColumn: never;
82
+ identity: undefined;
83
+ generated: undefined;
84
+ }, {}, {}>;
85
+ eventsQuota: import("drizzle-orm/pg-core").PgColumn<{
86
+ name: "events_quota";
87
+ tableName: "usage_periods";
88
+ dataType: "number";
89
+ columnType: "PgInteger";
90
+ data: number;
91
+ driverParam: string | number;
92
+ notNull: true;
93
+ hasDefault: false;
94
+ isPrimaryKey: false;
95
+ isAutoincrement: false;
96
+ hasRuntimeDefault: false;
97
+ enumValues: undefined;
98
+ baseColumn: never;
99
+ identity: undefined;
100
+ generated: undefined;
101
+ }, {}, {}>;
102
+ scrapesQuota: import("drizzle-orm/pg-core").PgColumn<{
103
+ name: "scrapes_quota";
104
+ tableName: "usage_periods";
105
+ dataType: "number";
106
+ columnType: "PgInteger";
107
+ data: number;
108
+ driverParam: string | number;
109
+ notNull: true;
110
+ hasDefault: false;
111
+ isPrimaryKey: false;
112
+ isAutoincrement: false;
113
+ hasRuntimeDefault: false;
114
+ enumValues: undefined;
115
+ baseColumn: never;
116
+ identity: undefined;
117
+ generated: undefined;
118
+ }, {}, {}>;
119
+ activeSubsQuota: import("drizzle-orm/pg-core").PgColumn<{
120
+ name: "active_subs_quota";
121
+ tableName: "usage_periods";
122
+ dataType: "number";
123
+ columnType: "PgInteger";
124
+ data: number;
125
+ driverParam: string | number;
126
+ notNull: true;
127
+ hasDefault: false;
128
+ isPrimaryKey: false;
129
+ isAutoincrement: false;
130
+ hasRuntimeDefault: false;
131
+ enumValues: undefined;
132
+ baseColumn: never;
133
+ identity: undefined;
134
+ generated: undefined;
135
+ }, {}, {}>;
136
+ overageCapEvents: import("drizzle-orm/pg-core").PgColumn<{
137
+ name: "overage_cap_events";
138
+ tableName: "usage_periods";
139
+ dataType: "number";
140
+ columnType: "PgInteger";
141
+ data: number;
142
+ driverParam: string | number;
143
+ notNull: true;
144
+ hasDefault: false;
145
+ isPrimaryKey: false;
146
+ isAutoincrement: false;
147
+ hasRuntimeDefault: false;
148
+ enumValues: undefined;
149
+ baseColumn: never;
150
+ identity: undefined;
151
+ generated: undefined;
152
+ }, {}, {}>;
153
+ eventsBillable: import("drizzle-orm/pg-core").PgColumn<{
154
+ name: "events_billable";
155
+ tableName: "usage_periods";
156
+ dataType: "number";
157
+ columnType: "PgInteger";
158
+ data: number;
159
+ driverParam: string | number;
160
+ notNull: true;
161
+ hasDefault: true;
162
+ isPrimaryKey: false;
163
+ isAutoincrement: false;
164
+ hasRuntimeDefault: false;
165
+ enumValues: undefined;
166
+ baseColumn: never;
167
+ identity: undefined;
168
+ generated: undefined;
169
+ }, {}, {}>;
170
+ eventsNonbillable: import("drizzle-orm/pg-core").PgColumn<{
171
+ name: "events_nonbillable";
172
+ tableName: "usage_periods";
173
+ dataType: "number";
174
+ columnType: "PgInteger";
175
+ data: number;
176
+ driverParam: string | number;
177
+ notNull: true;
178
+ hasDefault: true;
179
+ isPrimaryKey: false;
180
+ isAutoincrement: false;
181
+ hasRuntimeDefault: false;
182
+ enumValues: undefined;
183
+ baseColumn: never;
184
+ identity: undefined;
185
+ generated: undefined;
186
+ }, {}, {}>;
187
+ scrapesConsumed: import("drizzle-orm/pg-core").PgColumn<{
188
+ name: "scrapes_consumed";
189
+ tableName: "usage_periods";
190
+ dataType: "number";
191
+ columnType: "PgInteger";
192
+ data: number;
193
+ driverParam: string | number;
194
+ notNull: true;
195
+ hasDefault: true;
196
+ isPrimaryKey: false;
197
+ isAutoincrement: false;
198
+ hasRuntimeDefault: false;
199
+ enumValues: undefined;
200
+ baseColumn: never;
201
+ identity: undefined;
202
+ generated: undefined;
203
+ }, {}, {}>;
204
+ activeSubsMax: import("drizzle-orm/pg-core").PgColumn<{
205
+ name: "active_subs_max";
206
+ tableName: "usage_periods";
207
+ dataType: "number";
208
+ columnType: "PgInteger";
209
+ data: number;
210
+ driverParam: string | number;
211
+ notNull: true;
212
+ hasDefault: true;
213
+ isPrimaryKey: false;
214
+ isAutoincrement: false;
215
+ hasRuntimeDefault: false;
216
+ enumValues: undefined;
217
+ baseColumn: never;
218
+ identity: undefined;
219
+ generated: undefined;
220
+ }, {}, {}>;
221
+ creditsQuota: import("drizzle-orm/pg-core").PgColumn<{
222
+ name: "credits_quota";
223
+ tableName: "usage_periods";
224
+ dataType: "number";
225
+ columnType: "PgInteger";
226
+ data: number;
227
+ driverParam: string | number;
228
+ notNull: true;
229
+ hasDefault: true;
230
+ isPrimaryKey: false;
231
+ isAutoincrement: false;
232
+ hasRuntimeDefault: false;
233
+ enumValues: undefined;
234
+ baseColumn: never;
235
+ identity: undefined;
236
+ generated: undefined;
237
+ }, {}, {}>;
238
+ creditsConsumed: import("drizzle-orm/pg-core").PgColumn<{
239
+ name: "credits_consumed";
240
+ tableName: "usage_periods";
241
+ dataType: "string";
242
+ columnType: "PgNumeric";
243
+ data: string;
244
+ driverParam: string;
245
+ notNull: true;
246
+ hasDefault: true;
247
+ isPrimaryKey: false;
248
+ isAutoincrement: false;
249
+ hasRuntimeDefault: false;
250
+ enumValues: undefined;
251
+ baseColumn: never;
252
+ identity: undefined;
253
+ generated: undefined;
254
+ }, {}, {}>;
255
+ quotaAlert50Sent: import("drizzle-orm/pg-core").PgColumn<{
256
+ name: "quota_alert_50_sent";
257
+ tableName: "usage_periods";
258
+ dataType: "boolean";
259
+ columnType: "PgBoolean";
260
+ data: boolean;
261
+ driverParam: boolean;
262
+ notNull: true;
263
+ hasDefault: true;
264
+ isPrimaryKey: false;
265
+ isAutoincrement: false;
266
+ hasRuntimeDefault: false;
267
+ enumValues: undefined;
268
+ baseColumn: never;
269
+ identity: undefined;
270
+ generated: undefined;
271
+ }, {}, {}>;
272
+ quotaAlert75Sent: import("drizzle-orm/pg-core").PgColumn<{
273
+ name: "quota_alert_75_sent";
274
+ tableName: "usage_periods";
275
+ dataType: "boolean";
276
+ columnType: "PgBoolean";
277
+ data: boolean;
278
+ driverParam: boolean;
279
+ notNull: true;
280
+ hasDefault: true;
281
+ isPrimaryKey: false;
282
+ isAutoincrement: false;
283
+ hasRuntimeDefault: false;
284
+ enumValues: undefined;
285
+ baseColumn: never;
286
+ identity: undefined;
287
+ generated: undefined;
288
+ }, {}, {}>;
289
+ quotaAlert90Sent: import("drizzle-orm/pg-core").PgColumn<{
290
+ name: "quota_alert_90_sent";
291
+ tableName: "usage_periods";
292
+ dataType: "boolean";
293
+ columnType: "PgBoolean";
294
+ data: boolean;
295
+ driverParam: boolean;
296
+ notNull: true;
297
+ hasDefault: true;
298
+ isPrimaryKey: false;
299
+ isAutoincrement: false;
300
+ hasRuntimeDefault: false;
301
+ enumValues: undefined;
302
+ baseColumn: never;
303
+ identity: undefined;
304
+ generated: undefined;
305
+ }, {}, {}>;
306
+ quotaAlert100Sent: import("drizzle-orm/pg-core").PgColumn<{
307
+ name: "quota_alert_100_sent";
308
+ tableName: "usage_periods";
309
+ dataType: "boolean";
310
+ columnType: "PgBoolean";
311
+ data: boolean;
312
+ driverParam: boolean;
313
+ notNull: true;
314
+ hasDefault: true;
315
+ isPrimaryKey: false;
316
+ isAutoincrement: false;
317
+ hasRuntimeDefault: false;
318
+ enumValues: undefined;
319
+ baseColumn: never;
320
+ identity: undefined;
321
+ generated: undefined;
322
+ }, {}, {}>;
323
+ creditsAlert50Sent: import("drizzle-orm/pg-core").PgColumn<{
324
+ name: "credits_alert_50_sent";
325
+ tableName: "usage_periods";
326
+ dataType: "boolean";
327
+ columnType: "PgBoolean";
328
+ data: boolean;
329
+ driverParam: boolean;
330
+ notNull: true;
331
+ hasDefault: true;
332
+ isPrimaryKey: false;
333
+ isAutoincrement: false;
334
+ hasRuntimeDefault: false;
335
+ enumValues: undefined;
336
+ baseColumn: never;
337
+ identity: undefined;
338
+ generated: undefined;
339
+ }, {}, {}>;
340
+ creditsAlert75Sent: import("drizzle-orm/pg-core").PgColumn<{
341
+ name: "credits_alert_75_sent";
342
+ tableName: "usage_periods";
343
+ dataType: "boolean";
344
+ columnType: "PgBoolean";
345
+ data: boolean;
346
+ driverParam: boolean;
347
+ notNull: true;
348
+ hasDefault: true;
349
+ isPrimaryKey: false;
350
+ isAutoincrement: false;
351
+ hasRuntimeDefault: false;
352
+ enumValues: undefined;
353
+ baseColumn: never;
354
+ identity: undefined;
355
+ generated: undefined;
356
+ }, {}, {}>;
357
+ creditsAlert90Sent: import("drizzle-orm/pg-core").PgColumn<{
358
+ name: "credits_alert_90_sent";
359
+ tableName: "usage_periods";
360
+ dataType: "boolean";
361
+ columnType: "PgBoolean";
362
+ data: boolean;
363
+ driverParam: boolean;
364
+ notNull: true;
365
+ hasDefault: true;
366
+ isPrimaryKey: false;
367
+ isAutoincrement: false;
368
+ hasRuntimeDefault: false;
369
+ enumValues: undefined;
370
+ baseColumn: never;
371
+ identity: undefined;
372
+ generated: undefined;
373
+ }, {}, {}>;
374
+ creditsAlert100Sent: import("drizzle-orm/pg-core").PgColumn<{
375
+ name: "credits_alert_100_sent";
376
+ tableName: "usage_periods";
377
+ dataType: "boolean";
378
+ columnType: "PgBoolean";
379
+ data: boolean;
380
+ driverParam: boolean;
381
+ notNull: true;
382
+ hasDefault: true;
383
+ isPrimaryKey: false;
384
+ isAutoincrement: false;
385
+ hasRuntimeDefault: false;
386
+ enumValues: undefined;
387
+ baseColumn: never;
388
+ identity: undefined;
389
+ generated: undefined;
390
+ }, {}, {}>;
391
+ pollingPausedAt: import("drizzle-orm/pg-core").PgColumn<{
392
+ name: "polling_paused_at";
393
+ tableName: "usage_periods";
394
+ dataType: "date";
395
+ columnType: "PgTimestamp";
396
+ data: Date;
397
+ driverParam: string;
398
+ notNull: false;
399
+ hasDefault: false;
400
+ isPrimaryKey: false;
401
+ isAutoincrement: false;
402
+ hasRuntimeDefault: false;
403
+ enumValues: undefined;
404
+ baseColumn: never;
405
+ identity: undefined;
406
+ generated: undefined;
407
+ }, {}, {}>;
408
+ mcpPausedAt: import("drizzle-orm/pg-core").PgColumn<{
409
+ name: "mcp_paused_at";
410
+ tableName: "usage_periods";
411
+ dataType: "date";
412
+ columnType: "PgTimestamp";
413
+ data: Date;
414
+ driverParam: string;
415
+ notNull: false;
416
+ hasDefault: false;
417
+ isPrimaryKey: false;
418
+ isAutoincrement: false;
419
+ hasRuntimeDefault: false;
420
+ enumValues: undefined;
421
+ baseColumn: never;
422
+ identity: undefined;
423
+ generated: undefined;
424
+ }, {}, {}>;
425
+ spendCapMicroUsd: import("drizzle-orm/pg-core").PgColumn<{
426
+ name: "spend_cap_micro_usd";
427
+ tableName: "usage_periods";
428
+ dataType: "number";
429
+ columnType: "PgBigInt53";
430
+ data: number;
431
+ driverParam: string | number;
432
+ notNull: false;
433
+ hasDefault: false;
434
+ isPrimaryKey: false;
435
+ isAutoincrement: false;
436
+ hasRuntimeDefault: false;
437
+ enumValues: undefined;
438
+ baseColumn: never;
439
+ identity: undefined;
440
+ generated: undefined;
441
+ }, {}, {}>;
442
+ };
443
+ dialect: "pg";
444
+ }>;
445
+ export type UsagePeriod = typeof usagePeriods.$inferSelect;
446
+ export type NewUsagePeriod = typeof usagePeriods.$inferInsert;
@@ -0,0 +1,71 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ import { sql } from 'drizzle-orm';
3
+ import { bigint, boolean, date, index, integer, numeric, pgTable, primaryKey, text, timestamp, uuid, } from 'drizzle-orm/pg-core';
4
+ import { customers } from './customers.js';
5
+ /**
6
+ * Per-customer per-billing-period usage counters (Review #8).
7
+ *
8
+ * Updated by triggers on events + cost_records (deferred to a later chunk per
9
+ * Chunk 1 spec); read by quota checks, alerts, dashboard.
10
+ *
11
+ * Not partitioned (one row per customer per period — small table even at scale).
12
+ *
13
+ * Grandfathering: plan snapshot captured at period start; mid-period plan
14
+ * changes don't break invariants. Same row holds both events-based quotas
15
+ * (Review #8) and credits-based quotas for the MCP agent path (Review #10).
16
+ */
17
+ export const usagePeriods = pgTable('usage_periods', {
18
+ customerId: uuid('customer_id')
19
+ .notNull()
20
+ .references(() => customers.id),
21
+ // first day of the billing period (typically 1st of month)
22
+ periodStart: date('period_start').notNull(),
23
+ periodEnd: date('period_end').notNull(),
24
+ // snapshot of plan at period start; grandfathering-safe
25
+ plan: text('plan').notNull(),
26
+ // Quotas (Review #8) — snapshot from plan at period start
27
+ eventsQuota: integer('events_quota').notNull(),
28
+ scrapesQuota: integer('scrapes_quota').notNull(),
29
+ activeSubsQuota: integer('active_subs_quota').notNull(),
30
+ // 50% above included quota by default
31
+ overageCapEvents: integer('overage_cap_events').notNull(),
32
+ // Counters
33
+ // count of subscription.change + subscription.first_observation
34
+ eventsBillable: integer('events_billable').notNull().default(0),
35
+ // subscription.error, ping, housekeeping (for transparency)
36
+ eventsNonbillable: integer('events_nonbillable').notNull().default(0),
37
+ scrapesConsumed: integer('scrapes_consumed').notNull().default(0),
38
+ // high-water mark this period
39
+ activeSubsMax: integer('active_subs_max').notNull().default(0),
40
+ // MCP credits (Review #10): agent path bills on credits, not events
41
+ // 0 for customers without MCP access; per-plan otherwise
42
+ creditsQuota: integer('credits_quota').notNull().default(0),
43
+ // consumed by scrape_url, watch_url, watch polls, etc. NUMERIC (not integer)
44
+ // so a fractional charge — e.g. the 0.2-credit cache hit — is storable.
45
+ // Drizzle maps numeric → string; readers coerce with Number(...).
46
+ creditsConsumed: numeric('credits_consumed', { precision: 14, scale: 4 })
47
+ .notNull()
48
+ .default('0'),
49
+ // Alert state (Review #8) — prevents re-alerting on same threshold within a period
50
+ quotaAlert50Sent: boolean('quota_alert_50_sent').notNull().default(false),
51
+ quotaAlert75Sent: boolean('quota_alert_75_sent').notNull().default(false),
52
+ quotaAlert90Sent: boolean('quota_alert_90_sent').notNull().default(false),
53
+ quotaAlert100Sent: boolean('quota_alert_100_sent').notNull().default(false),
54
+ // separate alert track for credits (Review #10)
55
+ creditsAlert50Sent: boolean('credits_alert_50_sent').notNull().default(false),
56
+ creditsAlert75Sent: boolean('credits_alert_75_sent').notNull().default(false),
57
+ creditsAlert90Sent: boolean('credits_alert_90_sent').notNull().default(false),
58
+ creditsAlert100Sent: boolean('credits_alert_100_sent').notNull().default(false),
59
+ // non-null when overage cap reached and polling paused (Review #8)
60
+ pollingPausedAt: timestamp('polling_paused_at', { withTimezone: true }),
61
+ // non-null when credit cap reached and MCP tool calls rejected (Review #10)
62
+ mcpPausedAt: timestamp('mcp_paused_at', { withTimezone: true }),
63
+ // opt-in customer spend cap (Review #8); null = no cap
64
+ spendCapMicroUsd: bigint('spend_cap_micro_usd', { mode: 'number' }),
65
+ }, (table) => [
66
+ primaryKey({ columns: [table.customerId, table.periodStart] }),
67
+ index('idx_usage_unalerted')
68
+ .on(table.customerId)
69
+ .where(sql `${table.quotaAlert100Sent} = false`),
70
+ ]);
71
+ //# sourceMappingURL=usage-periods.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage-periods.js","sourceRoot":"","sources":["../../src/schema/usage-periods.ts"],"names":[],"mappings":"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"}