@checkstack/backend-api 0.10.1 → 0.11.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,65 @@
1
1
  # @checkstack/backend-api
2
2
 
3
+ ## 0.11.1
4
+
5
+ ### Patch Changes
6
+
7
+ - d1a2796: Enforce stricter code quality standards and eliminate AI slop anti-patterns.
8
+
9
+ **New utility**
10
+
11
+ - `extractErrorMessage(error, fallback?)` in `@checkstack/common` for consistent error extraction
12
+
13
+ **ESLint rules**
14
+
15
+ - `react-hooks/rules-of-hooks` and `exhaustive-deps` for hook correctness
16
+ - `no-console` in frontend packages — forces `toast` over silent `console.error`
17
+ - `no-restricted-syntax` banning `instanceof Error` — forces `extractErrorMessage`
18
+ - Custom `no-eslint-disable-any` rule preventing `@typescript-eslint/no-explicit-any` circumvention
19
+
20
+ **Refactoring**
21
+
22
+ - Replace 141 `instanceof Error` boilerplate patterns across the codebase
23
+ - Replace swallowed `console.error` with user-visible `toast.error()` feedback
24
+ - Remove 15 redundant `as` type casts in IntegrationsPage and ProviderConnectionsPage
25
+ - Consolidate 3 identical callback handlers into `handleDialogClose`
26
+ - Fix conditional React hook call in `FormField.tsx`
27
+ - Fix unstable useMemo deps in `Dashboard.tsx`
28
+ - Replace `useEffect`→`setState` with derived `useMemo` in `RegisterPage.tsx`
29
+ - Rewrite `keystore.test.ts` with typed `DrizzleMockChain` (eliminating 7 `any` suppressions)
30
+ - Delete obvious comments in `encryption.ts` and Teams `provider.ts`
31
+
32
+ - Updated dependencies [d1a2796]
33
+ - Updated dependencies [3c34b07]
34
+ - @checkstack/common@0.6.5
35
+ - @checkstack/healthcheck-common@0.10.1
36
+ - @checkstack/signal-common@0.1.9
37
+ - @checkstack/queue-api@0.2.12
38
+
39
+ ## 0.11.0
40
+
41
+ ### Minor Changes
42
+
43
+ - 54a5f80: ### Health Check Editor Redesign — IDE-Style Experience
44
+
45
+ Replaces the modal-based health check editor with a full-page, IDE-style experience:
46
+
47
+ - **Strategy Picker Page**: New `/config/create` page with categorized strategy discovery, search filtering, and grouped card grid layout
48
+ - **IDE Editor Page**: New `/config/:configId/edit` page with a split-view layout — explorer tree on the left, editor panel on the right
49
+ - **Strategy Categories**: Introduces `StrategyCategory` enum with 16 categories (Networking, Database, Infrastructure, etc.) — all 13 strategy plugins now declare their category
50
+ - **New RPC Endpoint**: Added `getConfiguration` (singular by ID) for efficient single-resource fetching on the edit page
51
+ - **Explorer Tree**: Left-hand navigation with General, Check Items (collectors), and Access Control sections, with real-time validation indicators
52
+ - **Validation Status Bar**: Bottom bar showing aggregated validation issues with clickable navigation
53
+ - **Unsaved Changes Guard**: Browser `beforeunload` protection when the form is dirty
54
+ - **Responsive Design**: Split-view on desktop, stacked layout on mobile
55
+ - **Deleted**: Legacy `HealthCheckEditor.tsx` modal component
56
+
57
+ ### Patch Changes
58
+
59
+ - Updated dependencies [54a5f80]
60
+ - @checkstack/healthcheck-common@0.10.0
61
+ - @checkstack/queue-api@0.2.11
62
+
3
63
  ## 0.10.1
4
64
 
5
65
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkstack/backend-api",
3
- "version": "0.10.1",
3
+ "version": "0.11.1",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "scripts": {
@@ -10,8 +10,8 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "@checkstack/common": "0.6.4",
13
- "@checkstack/healthcheck-common": "0.8.4",
14
- "@checkstack/queue-api": "0.2.9",
13
+ "@checkstack/healthcheck-common": "0.10.0",
14
+ "@checkstack/queue-api": "0.2.11",
15
15
  "@checkstack/signal-common": "0.1.8",
16
16
  "@orpc/client": "^1.13.14",
17
17
  "@orpc/contract": "^1.13.14",
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/bun": "latest",
28
- "@checkstack/tsconfig": "0.0.4",
28
+ "@checkstack/tsconfig": "0.0.5",
29
29
  "@checkstack/scripts": "0.1.2"
30
30
  },
31
31
  "peerDependencies": {
@@ -66,8 +66,7 @@ export class MigrationBuilder<TCurrent> {
66
66
  migration: Migration<TCurrent, TNext>
67
67
  ): MigrationBuilder<TNext> {
68
68
  this.migrations.push(migration);
69
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
70
- return this as any as MigrationBuilder<TNext>;
69
+ return this as unknown as MigrationBuilder<TNext>;
71
70
  }
72
71
 
73
72
  /**
package/src/encryption.ts CHANGED
@@ -30,22 +30,18 @@ const getMasterKey = (): Buffer => {
30
30
  export const encrypt = (plaintext: string): string => {
31
31
  const key = getMasterKey();
32
32
 
33
- // Generate random IV (12 bytes for GCM)
34
33
  const iv = crypto.randomBytes(12);
35
34
 
36
- // Create cipher
37
35
  const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);
38
36
 
39
- // Encrypt
40
37
  const encrypted = Buffer.concat([
41
38
  cipher.update(plaintext, "utf8"),
42
39
  cipher.final(),
43
40
  ]);
44
41
 
45
- // Get auth tag
46
42
  const authTag = cipher.getAuthTag();
47
43
 
48
- // Return base64-encoded iv:authTag:ciphertext
44
+
49
45
  return `${iv.toString("base64")}:${authTag.toString(
50
46
  "base64"
51
47
  )}:${encrypted.toString("base64")}`;
@@ -58,7 +54,6 @@ export const encrypt = (plaintext: string): string => {
58
54
  export const decrypt = (encrypted: string): string => {
59
55
  const key = getMasterKey();
60
56
 
61
- // Parse the encrypted string
62
57
  const parts = encrypted.split(":");
63
58
  if (parts.length !== 3) {
64
59
  throw new Error("Invalid encrypted format");
@@ -68,11 +63,9 @@ export const decrypt = (encrypted: string): string => {
68
63
  const authTag = Buffer.from(parts[1], "base64");
69
64
  const ciphertext = Buffer.from(parts[2], "base64");
70
65
 
71
- // Create decipher
72
66
  const decipher = crypto.createDecipheriv("aes-256-gcm", key, iv);
73
67
  decipher.setAuthTag(authTag);
74
68
 
75
- // Decrypt
76
69
  const decrypted = Buffer.concat([
77
70
  decipher.update(ciphertext),
78
71
  decipher.final(),
@@ -64,6 +64,8 @@ export interface HealthCheckStrategy<
64
64
  id: string;
65
65
  displayName: string;
66
66
  description?: string;
67
+ /** Strategy category for UI grouping in the strategy picker */
68
+ category?: string;
67
69
 
68
70
  /** Configuration schema with versioning and migrations */
69
71
  config: Versioned<TConfig>;
@@ -7,6 +7,8 @@
7
7
  * @module @checkstack/backend-api/oauth-handler
8
8
  */
9
9
 
10
+ import { extractErrorMessage } from "@checkstack/common";
11
+
10
12
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
11
13
  // OAuth Configuration Interface
12
14
  // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -416,7 +418,7 @@ export function createOAuthHandler(
416
418
  return Response.json(result);
417
419
  } catch (error) {
418
420
  return Response.json(
419
- { error: error instanceof Error ? error.message : "Refresh failed" },
421
+ { error: extractErrorMessage(error, "Refresh failed") },
420
422
  { status: 500 }
421
423
  );
422
424
  }