@checkstack/healthcheck-backend 1.2.0 → 1.3.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/src/service.ts CHANGED
@@ -11,6 +11,8 @@ import {
11
11
  DEFAULT_NOTIFICATION_POLICY,
12
12
  } from "@checkstack/healthcheck-common";
13
13
  import type { ConfigService } from "@checkstack/backend-api";
14
+ import type { InferClient } from "@checkstack/common";
15
+ import type { CatalogApi } from "@checkstack/catalog-common";
14
16
  import {
15
17
  notificationDefaultsConfigV1,
16
18
  NOTIFICATION_DEFAULTS_CONFIG_ID,
@@ -56,6 +58,10 @@ import {
56
58
  // Drizzle type helper - uses SafeDatabase to prevent relational query API usage
57
59
  type Db = SafeDatabase<typeof schema>;
58
60
 
61
+ // Catalog client type used to resolve human-readable system names for
62
+ // satellite assignment run-context. Optional on the service.
63
+ type CatalogClient = InferClient<typeof CatalogApi>;
64
+
59
65
  interface SystemCheckStatus {
60
66
  configurationId: string;
61
67
  configurationName: string;
@@ -83,6 +89,12 @@ export class HealthCheckService {
83
89
  * have to plumb it through.
84
90
  */
85
91
  private configService?: ConfigService,
92
+ /**
93
+ * Optional — used to resolve human-readable system names when building
94
+ * satellite assignment run-context. When absent (e.g. GitOps-only /
95
+ * test constructions), `systemName` falls back to the `systemId`.
96
+ */
97
+ private catalogClient?: CatalogClient,
86
98
  ) {}
87
99
 
88
100
  /**
@@ -242,6 +254,35 @@ export class HealthCheckService {
242
254
  });
243
255
  }
244
256
 
257
+ /**
258
+ * Flip the `enabled` flag on an existing `systemHealthChecks` row
259
+ * without touching any of the other configuration (thresholds,
260
+ * satellite assignment, notification policy). Returns `true` when a
261
+ * row was updated, `false` when the assignment doesn't exist.
262
+ *
263
+ * Carved out so the automation actions `enable_assignment` /
264
+ * `disable_assignment` don't have to round-trip through
265
+ * `associateSystem` (which would otherwise wipe operator-managed
266
+ * fields when invoked with a sparse partial).
267
+ */
268
+ async setAssignmentEnabled(
269
+ systemId: string,
270
+ configurationId: string,
271
+ enabled: boolean,
272
+ ): Promise<boolean> {
273
+ const result = await this.db
274
+ .update(systemHealthChecks)
275
+ .set({ enabled, updatedAt: new Date() })
276
+ .where(
277
+ and(
278
+ eq(systemHealthChecks.systemId, systemId),
279
+ eq(systemHealthChecks.configurationId, configurationId),
280
+ ),
281
+ )
282
+ .returning({ systemId: systemHealthChecks.systemId });
283
+ return result.length > 0;
284
+ }
285
+
245
286
  async disassociateSystem(systemId: string, configurationId: string) {
246
287
  await this.db
247
288
  .delete(systemHealthChecks)
@@ -1197,6 +1238,27 @@ export class HealthCheckService {
1197
1238
 
1198
1239
  if (matchingAssociations.length === 0) return [];
1199
1240
 
1241
+ // Resolve human-readable system names once per distinct systemId.
1242
+ // Falls back to the systemId when no catalog client is wired or the
1243
+ // lookup fails, mirroring the queue-executor's resolution behaviour.
1244
+ const systemNameCache = new Map<string, string>();
1245
+ const resolveSystemName = async (systemId: string): Promise<string> => {
1246
+ const cached = systemNameCache.get(systemId);
1247
+ if (cached !== undefined) return cached;
1248
+
1249
+ let systemName = systemId;
1250
+ if (this.catalogClient) {
1251
+ try {
1252
+ const system = await this.catalogClient.getSystem({ systemId });
1253
+ if (system) systemName = system.name;
1254
+ } catch {
1255
+ // Fall back to systemId if catalog lookup fails.
1256
+ }
1257
+ }
1258
+ systemNameCache.set(systemId, systemName);
1259
+ return systemName;
1260
+ };
1261
+
1200
1262
  // Get configurations for each matching association
1201
1263
  const assignments = [];
1202
1264
  for (const assoc of matchingAssociations) {
@@ -1214,6 +1276,9 @@ export class HealthCheckService {
1214
1276
  config: config.config,
1215
1277
  collectors: config.collectors ?? undefined,
1216
1278
  intervalSeconds: config.intervalSeconds,
1279
+ // Curated run-context metadata exposed to satellite collectors.
1280
+ configName: config.name,
1281
+ systemName: await resolveSystemName(assoc.systemId),
1217
1282
  });
1218
1283
  }
1219
1284
 
package/tsconfig.json CHANGED
@@ -4,6 +4,9 @@
4
4
  "src"
5
5
  ],
6
6
  "references": [
7
+ {
8
+ "path": "../automation-backend"
9
+ },
7
10
  {
8
11
  "path": "../backend-api"
9
12
  },
@@ -43,9 +46,6 @@
43
46
  {
44
47
  "path": "../incident-common"
45
48
  },
46
- {
47
- "path": "../integration-backend"
48
- },
49
49
  {
50
50
  "path": "../maintenance-common"
51
51
  },