@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.
- package/dist/src/archive/range-digest.d.ts +125 -0
- package/dist/src/archive/semantic-digest-builder.d.ts +125 -0
- package/dist/src/coverage/index.d.ts +125 -0
- package/dist/src/db/index.d.ts +146 -2
- package/dist/src/db/index.js +11 -1
- package/dist/src/db/index.js.map +3 -3
- package/dist/src/db/queries/chain-reorgs.d.ts +125 -0
- package/dist/src/db/queries/chain-reorgs.js +11 -1
- package/dist/src/db/queries/chain-reorgs.js.map +3 -3
- package/dist/src/db/queries/contracts.d.ts +125 -0
- package/dist/src/db/queries/instance.d.ts +125 -0
- package/dist/src/db/queries/integrity.d.ts +125 -0
- package/dist/src/db/queries/subgraph-gaps.d.ts +125 -0
- package/dist/src/db/queries/subgraph-operations.d.ts +125 -0
- package/dist/src/db/queries/subgraphs.d.ts +125 -0
- package/dist/src/db/queries/sync-scope.d.ts +125 -0
- package/dist/src/db/queries/webhook-replays.d.ts +1431 -0
- package/dist/src/db/queries/webhook-replays.js +156 -0
- package/dist/src/db/queries/webhook-replays.js.map +10 -0
- package/dist/src/db/queries/webhooks.d.ts +125 -0
- package/dist/src/db/schema.d.ts +136 -2
- package/dist/src/index.d.ts +146 -2
- package/dist/src/index.js +15 -1
- package/dist/src/index.js.map +4 -4
- package/dist/src/insights/index.d.ts +142 -3
- package/dist/src/insights/index.js +40 -3
- package/dist/src/insights/index.js.map +3 -3
- package/dist/src/node/local-client.d.ts +125 -0
- package/dist/src/queue/listener.js +11 -1
- package/dist/src/queue/listener.js.map +3 -3
- package/dist/src/schemas/index.js +5 -1
- package/dist/src/schemas/index.js.map +3 -3
- package/dist/src/schemas/webhooks.d.ts +45 -1
- package/dist/src/schemas/webhooks.js +6 -1
- package/dist/src/schemas/webhooks.js.map +3 -3
- package/migrations/0177_oauth_mcp.ts +122 -0
- package/migrations/0178_insight_snooze.ts +22 -0
- package/migrations/0179_webhook_replays.ts +56 -0
- package/migrations/0180_push.ts +54 -0
- package/migrations/0181_push_sent.ts +30 -0
- package/package.json +5 -1
|
@@ -597,6 +597,7 @@ interface InsightsTable {
|
|
|
597
597
|
clear_streak: Generated<number>;
|
|
598
598
|
resolved_at: Date | null;
|
|
599
599
|
dismissed_at: Date | null;
|
|
600
|
+
snoozed_until: Date | null;
|
|
600
601
|
}
|
|
601
602
|
/** "Expected": mutes one rule for one resource until removed. */
|
|
602
603
|
interface InsightMutesTable {
|
|
@@ -1090,6 +1091,7 @@ interface Database {
|
|
|
1090
1091
|
webhooks: WebhooksTable;
|
|
1091
1092
|
webhook_outbox: WebhookOutboxTable;
|
|
1092
1093
|
webhook_deliveries: WebhookDeliveriesTable;
|
|
1094
|
+
webhook_replays: WebhookReplaysTable;
|
|
1093
1095
|
trigger_evaluator_state: TriggerEvaluatorStateTable;
|
|
1094
1096
|
decoded_events: DecodedEventsTable;
|
|
1095
1097
|
decoder_checkpoints: DecoderCheckpointsTable;
|
|
@@ -1123,6 +1125,12 @@ interface Database {
|
|
|
1123
1125
|
account_balance_alerts: AccountBalanceAlertsTable;
|
|
1124
1126
|
webhook_incident_alerts: WebhookIncidentAlertsTable;
|
|
1125
1127
|
cli_device_logins: CliDeviceLoginsTable;
|
|
1128
|
+
oauth_clients: OauthClientsTable;
|
|
1129
|
+
oauth_requests: OauthRequestsTable;
|
|
1130
|
+
oauth_codes: OauthCodesTable;
|
|
1131
|
+
oauth_grants: OauthGrantsTable;
|
|
1132
|
+
oauth_tokens: OauthTokensTable;
|
|
1133
|
+
oauth_refresh_retired: OauthRefreshRetiredTable;
|
|
1126
1134
|
sentinel_accounts: SentinelAccountsTable;
|
|
1127
1135
|
waitlists: WaitlistsTable;
|
|
1128
1136
|
waitlist_signups: WaitlistSignupsTable;
|
|
@@ -1132,6 +1140,9 @@ interface Database {
|
|
|
1132
1140
|
insights: InsightsTable;
|
|
1133
1141
|
insight_mutes: InsightMutesTable;
|
|
1134
1142
|
feedback_tickets: FeedbackTicketsTable;
|
|
1143
|
+
push_subscriptions: PushSubscriptionsTable;
|
|
1144
|
+
push_prefs: PushPrefsTable;
|
|
1145
|
+
push_sent: PushSentTable;
|
|
1135
1146
|
}
|
|
1136
1147
|
interface ServiceHeartbeatsTable {
|
|
1137
1148
|
name: string;
|
|
@@ -1224,6 +1235,36 @@ interface WebhookIncidentAlertsTable {
|
|
|
1224
1235
|
email_attempts: Generated<number>;
|
|
1225
1236
|
resolved_at: Date | null;
|
|
1226
1237
|
}
|
|
1238
|
+
/** One browser/device push subscription; the endpoint is unique. */
|
|
1239
|
+
interface PushSubscriptionsTable {
|
|
1240
|
+
id: Generated<string>;
|
|
1241
|
+
account_id: string;
|
|
1242
|
+
endpoint: string;
|
|
1243
|
+
p256dh: string;
|
|
1244
|
+
auth: string;
|
|
1245
|
+
user_agent: string | null;
|
|
1246
|
+
created_at: Generated<Date>;
|
|
1247
|
+
last_success_at: Date | null;
|
|
1248
|
+
failed_count: Generated<number>;
|
|
1249
|
+
}
|
|
1250
|
+
/** Per-account push toggles. A missing row means the column defaults. */
|
|
1251
|
+
interface PushPrefsTable {
|
|
1252
|
+
account_id: string;
|
|
1253
|
+
webhook_failing: Generated<boolean>;
|
|
1254
|
+
subgraph_stopped: Generated<boolean>;
|
|
1255
|
+
subgraph_not_serving: Generated<boolean>;
|
|
1256
|
+
replay_done: Generated<boolean>;
|
|
1257
|
+
spend_cap: Generated<boolean>;
|
|
1258
|
+
key_repeat: Generated<boolean>;
|
|
1259
|
+
updated_at: Generated<Date>;
|
|
1260
|
+
}
|
|
1261
|
+
/** A push already sent, keyed by what it was about; debounces repeat signals. */
|
|
1262
|
+
interface PushSentTable {
|
|
1263
|
+
account_id: string;
|
|
1264
|
+
key: string;
|
|
1265
|
+
kind: string;
|
|
1266
|
+
sent_at: Generated<Date>;
|
|
1267
|
+
}
|
|
1227
1268
|
type CliDeviceLoginStatus = "pending" | "approved" | "denied" | "consumed";
|
|
1228
1269
|
/** The product that started a CLI sign-in; null is `sl login`. */
|
|
1229
1270
|
type CliDeviceProduct = "sentinel";
|
|
@@ -1244,6 +1285,72 @@ interface CliDeviceLoginsTable {
|
|
|
1244
1285
|
approved_at: Date | null;
|
|
1245
1286
|
consumed_at: Date | null;
|
|
1246
1287
|
}
|
|
1288
|
+
/** An app that registered itself (RFC 7591). Public clients only: no secret. */
|
|
1289
|
+
interface OauthClientsTable {
|
|
1290
|
+
id: string;
|
|
1291
|
+
/** The app's own claim, validated at registration; shown quoted. */
|
|
1292
|
+
name: string;
|
|
1293
|
+
redirect_uris: string[];
|
|
1294
|
+
created_ip: string | null;
|
|
1295
|
+
created_at: Generated<Date>;
|
|
1296
|
+
/** Set when it first gets tokens; never-used clients are purged. */
|
|
1297
|
+
last_used_at: Date | null;
|
|
1298
|
+
}
|
|
1299
|
+
type OauthRequestStatus = "pending" | "approved" | "denied";
|
|
1300
|
+
/** One authorize request waiting for (or answered on) the consent page. */
|
|
1301
|
+
interface OauthRequestsTable {
|
|
1302
|
+
id: string;
|
|
1303
|
+
client_id: string;
|
|
1304
|
+
redirect_uri: string;
|
|
1305
|
+
state: string | null;
|
|
1306
|
+
code_challenge: string;
|
|
1307
|
+
resource: string;
|
|
1308
|
+
status: Generated<OauthRequestStatus>;
|
|
1309
|
+
account_id: string | null;
|
|
1310
|
+
created_at: Generated<Date>;
|
|
1311
|
+
expires_at: Date;
|
|
1312
|
+
answered_at: Date | null;
|
|
1313
|
+
}
|
|
1314
|
+
/** A one-time authorization code, bound to its client, redirect, PKCE
|
|
1315
|
+
* challenge, resource and account. */
|
|
1316
|
+
interface OauthCodesTable {
|
|
1317
|
+
code_hash: string;
|
|
1318
|
+
client_id: string;
|
|
1319
|
+
account_id: string;
|
|
1320
|
+
redirect_uri: string;
|
|
1321
|
+
code_challenge: string;
|
|
1322
|
+
resource: string;
|
|
1323
|
+
/** The grant its one use made, so a replay can revoke it. */
|
|
1324
|
+
grant_id: string | null;
|
|
1325
|
+
created_at: Generated<Date>;
|
|
1326
|
+
expires_at: Date;
|
|
1327
|
+
used_at: Date | null;
|
|
1328
|
+
}
|
|
1329
|
+
/** What a person allowed one app to do: use the hosted MCP as them. */
|
|
1330
|
+
interface OauthGrantsTable {
|
|
1331
|
+
id: Generated<string>;
|
|
1332
|
+
account_id: string;
|
|
1333
|
+
client_id: string;
|
|
1334
|
+
scope: Generated<string>;
|
|
1335
|
+
resource: string;
|
|
1336
|
+
created_at: Generated<Date>;
|
|
1337
|
+
last_used_at: Date | null;
|
|
1338
|
+
revoked_at: Date | null;
|
|
1339
|
+
}
|
|
1340
|
+
type OauthTokenKind = "access" | "refresh";
|
|
1341
|
+
interface OauthTokensTable {
|
|
1342
|
+
token_hash: string;
|
|
1343
|
+
grant_id: string;
|
|
1344
|
+
kind: OauthTokenKind;
|
|
1345
|
+
created_at: Generated<Date>;
|
|
1346
|
+
expires_at: Date;
|
|
1347
|
+
}
|
|
1348
|
+
/** A refresh token a rotation replaced: presented again, it revokes the grant. */
|
|
1349
|
+
interface OauthRefreshRetiredTable {
|
|
1350
|
+
token_hash: string;
|
|
1351
|
+
grant_id: string;
|
|
1352
|
+
retired_at: Generated<Date>;
|
|
1353
|
+
}
|
|
1247
1354
|
/** Accounts Sentinel's service key may touch: created by Sentinel, or the
|
|
1248
1355
|
* owner opted in. */
|
|
1249
1356
|
interface SentinelAccountsTable {
|
|
@@ -1301,6 +1408,8 @@ interface WebhookOutboxTable {
|
|
|
1301
1408
|
next_attempt_at: Generated<Date>;
|
|
1302
1409
|
status: ColumnType<OutboxStatus, OutboxStatus | undefined, OutboxStatus>;
|
|
1303
1410
|
is_replay: Generated<boolean>;
|
|
1411
|
+
/** The replay that created this row; null for live rows. */
|
|
1412
|
+
replay_id: string | null;
|
|
1304
1413
|
/** The chain block_time of the matched event/tx. Null for rows written
|
|
1305
1414
|
* before this column existed, and for the settlement scan path (not yet
|
|
1306
1415
|
* wired). Lets `delivered_at - block_time` measure end-to-end webhook
|
|
@@ -1316,6 +1425,22 @@ interface WebhookOutboxTable {
|
|
|
1316
1425
|
last_error: string | null;
|
|
1317
1426
|
created_at: Generated<Date>;
|
|
1318
1427
|
}
|
|
1428
|
+
type WebhookReplayStatus = "scanning" | "running" | "done" | "failed";
|
|
1429
|
+
interface WebhookReplaysTable {
|
|
1430
|
+
id: string;
|
|
1431
|
+
webhook_id: string;
|
|
1432
|
+
from_block: number | bigint;
|
|
1433
|
+
to_block: number | bigint;
|
|
1434
|
+
status: WebhookReplayStatus;
|
|
1435
|
+
scanned_count: Generated<number>;
|
|
1436
|
+
enqueued_count: Generated<number>;
|
|
1437
|
+
total: number | null;
|
|
1438
|
+
delivered: number | null;
|
|
1439
|
+
gave_up: number | null;
|
|
1440
|
+
error: string | null;
|
|
1441
|
+
started_at: Generated<Date>;
|
|
1442
|
+
finished_at: Date | null;
|
|
1443
|
+
}
|
|
1319
1444
|
interface WebhookDeliveriesTable {
|
|
1320
1445
|
id: Generated<string>;
|
|
1321
1446
|
/** Nullable after migration 0077 — outbox row may be cleaned up while
|
|
@@ -1474,8 +1599,16 @@ interface InsightRule<Input> {
|
|
|
1474
1599
|
* and resolves once the streak reaches `CLEAR_STREAK_TO_RESOLVE`. A rule that
|
|
1475
1600
|
* was skipped (missing data) must stay out of `evaluatedKeys` so it never
|
|
1476
1601
|
* counts toward clearing.
|
|
1602
|
+
*
|
|
1603
|
+
* Returns the insights this pass newly opened (inserted, not updated). A
|
|
1604
|
+
* re-fire after a resolve is a fresh insert and counts. Nothing stored or
|
|
1605
|
+
* listed depends on the return value.
|
|
1477
1606
|
*/
|
|
1478
|
-
declare function recordEvaluation(db: Kysely<Database>, scope: InsightScope, fired: DetectedInsight[], evaluatedKeys: EvaluatedKey[], now?: Date): Promise<
|
|
1607
|
+
declare function recordEvaluation(db: Kysely<Database>, scope: InsightScope, fired: DetectedInsight[], evaluatedKeys: EvaluatedKey[], now?: Date): Promise<{
|
|
1608
|
+
opened: Array<DetectedInsight & {
|
|
1609
|
+
id: string
|
|
1610
|
+
}>
|
|
1611
|
+
}>;
|
|
1479
1612
|
/** (kind, id) pairs that have an open insight in this scope. */
|
|
1480
1613
|
declare function listOpenResources(db: Kysely<Database>, scope: InsightScope): Promise<{
|
|
1481
1614
|
kind: Insight["resource"]["kind"]
|
|
@@ -1484,7 +1617,7 @@ declare function listOpenResources(db: Kysely<Database>, scope: InsightScope): P
|
|
|
1484
1617
|
}[]>;
|
|
1485
1618
|
/**
|
|
1486
1619
|
* Open rows plus rows resolved within `RECOVERED_VISIBLE_MS`, minus dismissed
|
|
1487
|
-
* and muted ones. Resolved rows come back as `recovered`. One row per
|
|
1620
|
+
* snoozed and muted ones. Resolved rows come back as `recovered`. One row per
|
|
1488
1621
|
* (resource, rule): the open incident, else the latest recovered one. Ranked.
|
|
1489
1622
|
*/
|
|
1490
1623
|
declare function listInsights(db: Kysely<Database>, scope: InsightScope, now?: Date, filter?: {
|
|
@@ -1493,6 +1626,12 @@ declare function listInsights(db: Kysely<Database>, scope: InsightScope, now?: D
|
|
|
1493
1626
|
}): Promise<Insight[]>;
|
|
1494
1627
|
/** Hide the current incident. Returns false when the id is not in scope. */
|
|
1495
1628
|
declare function dismissInsight(db: Kysely<Database>, scope: InsightScope, id: string, now?: Date): Promise<boolean>;
|
|
1629
|
+
/** Hide the current incident until `until`. Returns false when the id is not in scope. */
|
|
1630
|
+
declare function snoozeInsight(db: Kysely<Database>, scope: InsightScope, id: string, until: Date): Promise<boolean>;
|
|
1631
|
+
/** Show a snoozed insight again now. Returns false when the id is not in scope. */
|
|
1632
|
+
declare function unsnoozeInsight(db: Kysely<Database>, scope: InsightScope, id: string): Promise<boolean>;
|
|
1633
|
+
/** Show a dismissed insight again. Returns false when the id is not in scope. */
|
|
1634
|
+
declare function undismissInsight(db: Kysely<Database>, scope: InsightScope, id: string): Promise<boolean>;
|
|
1496
1635
|
/** Mute the insight's rule for its resource until un-muted. */
|
|
1497
1636
|
declare function muteRule(db: Kysely<Database>, scope: InsightScope, id: string): Promise<boolean>;
|
|
1498
1637
|
declare function unmuteRule(db: Kysely<Database>, scope: InsightScope, id: string): Promise<boolean>;
|
|
@@ -1607,4 +1746,4 @@ interface TenantEvaluateDeps extends Omit<LabelDeps, "now"> {
|
|
|
1607
1746
|
* exist resolve through the normal two-pass clear.
|
|
1608
1747
|
*/
|
|
1609
1748
|
declare function evaluateTenantInsights(db: Kysely3<Database>, deps?: TenantEvaluateDeps): Promise<void>;
|
|
1610
|
-
export { BACKFILL_DAY_SHARE, BACKFILL_FULL_PAGE_RATIO, BACKFILL_MIN_DAY_ROWS, CLEAR_STREAK_TO_RESOLVE, CREDITS_RUNWAY_WARN_DAYS, DEAD_LETTER_DELETE_AGE_DAYS, DEAD_LETTER_WARN_AGE_DAYS, DOWN_MIN_CONSECUTIVE, DUPLICATE_READS_LOOKBACK_MS, DUPLICATE_READS_MIN_PAGES, DUPLICATE_READS_WINDOW_MS, DetectedInsight, EvaluatedKey, HANDLER_ERRORS_MIN_24H, InsightRule, InsightScope, KEY_UNUSED_DAYS, LAG_MIN_SAMPLES, LAG_THRESHOLD_MS, LAG_WINDOW, LOGIN_WALL_MIN_CONSECUTIVE, LOGIN_WALL_MIN_PRIOR, LOGIN_WALL_PRIOR_JSON_RATIO, PAGE_CAP_ROWS, POLLING_FOLLOW_GAP_MS, POLLING_LOOKBACK_MS, POLLING_MAX_STDDEV_RATIO, POLLING_MIN_DURATION_MS, POLLING_MIN_EMPTY_RATIO, POLLING_MIN_REQUESTS, POLLING_STALE_INTERVALS, RATE_LIMITED_MIN_ATTEMPTS, RATE_LIMITED_MIN_RATIO, RECOVERED_VISIBLE_MS, REJECTS_MIN_CONSECUTIVE, REVOKED_KEY_ACTIVE_MS, SERVER_ERRORS_MIN_5XX, SLOWING_DAYS, SLOWING_MIN_R2, SLOWING_MIN_RISING_DAYS, SLOW_MIN_SAMPLES, SLOW_TIMEOUT_RATIO, SLOW_WINDOW, STACK_UNREACHABLE_ACTIVE_MS, STACK_UNREACHABLE_MIN_FAILURES, SUBGRAPH_LAG_BLOCKS, SUBGRAPH_LAG_LOSING_BLOCKS, SUBGRAPH_LAG_SNAPSHOTS, TEST_ENDPOINT_MIN_AGE_DAYS, TLS_WARN_DAYS, TenantEvaluateDeps, dismissInsight, evaluateTenantInsights, handoffPrompt, hostOf, listInsights, listOpenResources, maybeLabel, muteRule, plainSnippet, plural, purgeResolved, rankInsights, recordEvaluation, runRules, unmuteRule, utcDateTime, utcDay, utcTime };
|
|
1749
|
+
export { BACKFILL_DAY_SHARE, BACKFILL_FULL_PAGE_RATIO, BACKFILL_MIN_DAY_ROWS, CLEAR_STREAK_TO_RESOLVE, CREDITS_RUNWAY_WARN_DAYS, DEAD_LETTER_DELETE_AGE_DAYS, DEAD_LETTER_WARN_AGE_DAYS, DOWN_MIN_CONSECUTIVE, DUPLICATE_READS_LOOKBACK_MS, DUPLICATE_READS_MIN_PAGES, DUPLICATE_READS_WINDOW_MS, DetectedInsight, EvaluatedKey, HANDLER_ERRORS_MIN_24H, InsightRule, InsightScope, KEY_UNUSED_DAYS, LAG_MIN_SAMPLES, LAG_THRESHOLD_MS, LAG_WINDOW, LOGIN_WALL_MIN_CONSECUTIVE, LOGIN_WALL_MIN_PRIOR, LOGIN_WALL_PRIOR_JSON_RATIO, PAGE_CAP_ROWS, POLLING_FOLLOW_GAP_MS, POLLING_LOOKBACK_MS, POLLING_MAX_STDDEV_RATIO, POLLING_MIN_DURATION_MS, POLLING_MIN_EMPTY_RATIO, POLLING_MIN_REQUESTS, POLLING_STALE_INTERVALS, RATE_LIMITED_MIN_ATTEMPTS, RATE_LIMITED_MIN_RATIO, RECOVERED_VISIBLE_MS, REJECTS_MIN_CONSECUTIVE, REVOKED_KEY_ACTIVE_MS, SERVER_ERRORS_MIN_5XX, SLOWING_DAYS, SLOWING_MIN_R2, SLOWING_MIN_RISING_DAYS, SLOW_MIN_SAMPLES, SLOW_TIMEOUT_RATIO, SLOW_WINDOW, STACK_UNREACHABLE_ACTIVE_MS, STACK_UNREACHABLE_MIN_FAILURES, SUBGRAPH_LAG_BLOCKS, SUBGRAPH_LAG_LOSING_BLOCKS, SUBGRAPH_LAG_SNAPSHOTS, TEST_ENDPOINT_MIN_AGE_DAYS, TLS_WARN_DAYS, TenantEvaluateDeps, dismissInsight, evaluateTenantInsights, handoffPrompt, hostOf, listInsights, listOpenResources, maybeLabel, muteRule, plainSnippet, plural, purgeResolved, rankInsights, recordEvaluation, runRules, snoozeInsight, undismissInsight, unmuteRule, unsnoozeInsight, utcDateTime, utcDay, utcTime };
|
|
@@ -234,9 +234,10 @@ function toPayload(insight) {
|
|
|
234
234
|
};
|
|
235
235
|
}
|
|
236
236
|
async function recordEvaluation(db, scope, fired, evaluatedKeys, now = new Date) {
|
|
237
|
-
|
|
237
|
+
return db.transaction().execute(async (trx) => {
|
|
238
|
+
const opened = [];
|
|
238
239
|
for (const insight of fired) {
|
|
239
|
-
await sql2`
|
|
240
|
+
const { rows } = await sql2`
|
|
240
241
|
INSERT INTO insights
|
|
241
242
|
(account_id, resource_kind, resource_id, rule, severity, impact,
|
|
242
243
|
payload, first_seen_at, last_seen_at)
|
|
@@ -253,7 +254,11 @@ async function recordEvaluation(db, scope, fired, evaluatedKeys, now = new Date)
|
|
|
253
254
|
impact = EXCLUDED.impact,
|
|
254
255
|
last_seen_at = EXCLUDED.last_seen_at,
|
|
255
256
|
clear_streak = 0
|
|
257
|
+
RETURNING id, (xmax = 0) AS inserted
|
|
256
258
|
`.execute(trx);
|
|
259
|
+
const row = rows[0];
|
|
260
|
+
if (row?.inserted)
|
|
261
|
+
opened.push({ ...insight, id: row.id });
|
|
257
262
|
}
|
|
258
263
|
const firedKeys = new Set(fired.map((i) => `${i.resource.kind}\x00${i.resource.id}\x00${i.rule}`));
|
|
259
264
|
for (const key of evaluatedKeys) {
|
|
@@ -274,6 +279,7 @@ async function recordEvaluation(db, scope, fired, evaluatedKeys, now = new Date)
|
|
|
274
279
|
AND resolved_at IS NULL
|
|
275
280
|
`.execute(trx);
|
|
276
281
|
}
|
|
282
|
+
return { opened };
|
|
277
283
|
});
|
|
278
284
|
}
|
|
279
285
|
async function listOpenResources(db, scope) {
|
|
@@ -301,6 +307,7 @@ async function listInsights(db, scope, now = new Date, filter = {}) {
|
|
|
301
307
|
ORDER BY resource_kind, resource_id, rule, resolved_at DESC NULLS FIRST
|
|
302
308
|
) i
|
|
303
309
|
WHERE i.dismissed_at IS NULL
|
|
310
|
+
AND (i.snoozed_until IS NULL OR i.snoozed_until <= ${now})
|
|
304
311
|
AND NOT EXISTS (
|
|
305
312
|
SELECT 1 FROM insight_mutes m
|
|
306
313
|
WHERE ${scopeWhere(scope, sql2.ref("m.account_id"))}
|
|
@@ -331,6 +338,33 @@ async function dismissInsight(db, scope, id, now = new Date) {
|
|
|
331
338
|
`.execute(db);
|
|
332
339
|
return Number(result.numAffectedRows ?? 0) > 0;
|
|
333
340
|
}
|
|
341
|
+
async function snoozeInsight(db, scope, id, until) {
|
|
342
|
+
if (!UUID_RE.test(id))
|
|
343
|
+
return false;
|
|
344
|
+
const result = await sql2`
|
|
345
|
+
UPDATE insights SET snoozed_until = ${until}
|
|
346
|
+
WHERE id = ${id}::uuid AND ${scopeWhere(scope)}
|
|
347
|
+
`.execute(db);
|
|
348
|
+
return Number(result.numAffectedRows ?? 0) > 0;
|
|
349
|
+
}
|
|
350
|
+
async function unsnoozeInsight(db, scope, id) {
|
|
351
|
+
if (!UUID_RE.test(id))
|
|
352
|
+
return false;
|
|
353
|
+
const result = await sql2`
|
|
354
|
+
UPDATE insights SET snoozed_until = NULL
|
|
355
|
+
WHERE id = ${id}::uuid AND ${scopeWhere(scope)}
|
|
356
|
+
`.execute(db);
|
|
357
|
+
return Number(result.numAffectedRows ?? 0) > 0;
|
|
358
|
+
}
|
|
359
|
+
async function undismissInsight(db, scope, id) {
|
|
360
|
+
if (!UUID_RE.test(id))
|
|
361
|
+
return false;
|
|
362
|
+
const result = await sql2`
|
|
363
|
+
UPDATE insights SET dismissed_at = NULL
|
|
364
|
+
WHERE id = ${id}::uuid AND ${scopeWhere(scope)}
|
|
365
|
+
`.execute(db);
|
|
366
|
+
return Number(result.numAffectedRows ?? 0) > 0;
|
|
367
|
+
}
|
|
334
368
|
async function muteRule(db, scope, id) {
|
|
335
369
|
if (!UUID_RE.test(id))
|
|
336
370
|
return false;
|
|
@@ -2301,11 +2335,14 @@ export {
|
|
|
2301
2335
|
rankInsights,
|
|
2302
2336
|
recordEvaluation,
|
|
2303
2337
|
runRules2 as runRules,
|
|
2338
|
+
snoozeInsight,
|
|
2339
|
+
undismissInsight,
|
|
2304
2340
|
unmuteRule,
|
|
2341
|
+
unsnoozeInsight,
|
|
2305
2342
|
utcDateTime,
|
|
2306
2343
|
utcDay,
|
|
2307
2344
|
utcTime
|
|
2308
2345
|
};
|
|
2309
2346
|
|
|
2310
|
-
//# debugId=
|
|
2347
|
+
//# debugId=43EF1744AA425D2F64756E2164756E21
|
|
2311
2348
|
//# sourceMappingURL=index.js.map
|