@checkmate-monitor/incident-common 0.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,30 @@
1
+ # @checkmate-monitor/incident-common
2
+
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 4dd644d: Enable external application (API key) access to management endpoints
8
+
9
+ Changed `userType: "user"` to `userType: "authenticated"` for 52 endpoints across 5 packages, allowing external applications (service accounts with API keys) to call these endpoints programmatically while maintaining RBAC permission checks:
10
+
11
+ - **incident-common**: createIncident, updateIncident, addUpdate, resolveIncident, deleteIncident
12
+ - **maintenance-common**: createMaintenance, updateMaintenance, addUpdate, closeMaintenance, deleteMaintenance
13
+ - **catalog-common**: System CRUD, Group CRUD, addSystemToGroup, removeSystemFromGroup
14
+ - **healthcheck-common**: Configuration management, system associations, retention config, detailed history
15
+ - **integration-common**: Subscription management, connection management, event discovery, delivery logs
16
+
17
+ This enables automation use cases such as:
18
+
19
+ - Creating incidents from external monitoring systems (Prometheus, Grafana)
20
+ - Scheduling maintenances from CI/CD pipelines
21
+ - Managing catalog systems from infrastructure-as-code tools
22
+ - Configuring health checks from deployment scripts
23
+
24
+ ### Patch Changes
25
+
26
+ - Updated dependencies [ffc28f6]
27
+ - Updated dependencies [b55fae6]
28
+ - @checkmate-monitor/common@0.1.0
29
+ - @checkmate-monitor/signal-common@0.1.0
30
+ - @checkmate-monitor/frontend-api@0.0.2
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@checkmate-monitor/incident-common",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "import": "./src/index.ts"
8
+ }
9
+ },
10
+ "dependencies": {
11
+ "@checkmate-monitor/common": "workspace:*",
12
+ "@checkmate-monitor/frontend-api": "workspace:*",
13
+ "@checkmate-monitor/signal-common": "workspace:*",
14
+ "@orpc/contract": "^1.13.2",
15
+ "zod": "^4.2.1"
16
+ },
17
+ "devDependencies": {
18
+ "typescript": "^5.7.2",
19
+ "@checkmate-monitor/tsconfig": "workspace:*",
20
+ "@checkmate-monitor/scripts": "workspace:*"
21
+ },
22
+ "scripts": {
23
+ "typecheck": "tsc --noEmit",
24
+ "lint": "bun run lint:code",
25
+ "lint:code": "eslint . --max-warnings 0"
26
+ }
27
+ }
package/src/index.ts ADDED
@@ -0,0 +1,49 @@
1
+ export { permissions, permissionList } from "./permissions";
2
+ export {
3
+ incidentContract,
4
+ IncidentApi,
5
+ type IncidentContract,
6
+ } from "./rpc-contract";
7
+ export {
8
+ IncidentStatusEnum,
9
+ IncidentSeverityEnum,
10
+ IncidentSchema,
11
+ IncidentWithSystemsSchema,
12
+ IncidentUpdateSchema,
13
+ IncidentDetailSchema,
14
+ CreateIncidentInputSchema,
15
+ UpdateIncidentInputSchema,
16
+ AddIncidentUpdateInputSchema,
17
+ type IncidentStatus,
18
+ type IncidentSeverity,
19
+ type Incident,
20
+ type IncidentWithSystems,
21
+ type IncidentUpdate,
22
+ type IncidentDetail,
23
+ type CreateIncidentInput,
24
+ type UpdateIncidentInput,
25
+ type AddIncidentUpdateInput,
26
+ } from "./schemas";
27
+ export { IncidentDetailsSlot, IncidentStatusSlot } from "./slots";
28
+ export * from "./plugin-metadata";
29
+ export { incidentRoutes } from "./routes";
30
+
31
+ // =============================================================================
32
+ // REALTIME SIGNALS
33
+ // =============================================================================
34
+
35
+ import { createSignal } from "@checkmate-monitor/signal-common";
36
+ import { z } from "zod";
37
+
38
+ /**
39
+ * Broadcast when an incident is created, updated, or resolved.
40
+ * Frontend components listening to this signal can refetch state for affected systems.
41
+ */
42
+ export const INCIDENT_UPDATED = createSignal(
43
+ "incident.updated",
44
+ z.object({
45
+ incidentId: z.string(),
46
+ systemIds: z.array(z.string()),
47
+ action: z.enum(["created", "updated", "resolved", "deleted"]),
48
+ })
49
+ );
@@ -0,0 +1,13 @@
1
+ import { createPermission, type Permission } from "@checkmate-monitor/common";
2
+
3
+ export const permissions = {
4
+ /** Read access to incidents - granted to all users by default */
5
+ incidentRead: createPermission("incident", "read", "View incidents", {
6
+ isAuthenticatedDefault: true,
7
+ isPublicDefault: true,
8
+ }),
9
+ /** Manage incidents - create, edit, resolve, and delete */
10
+ incidentManage: createPermission("incident", "manage", "Manage incidents"),
11
+ } as const satisfies Record<string, Permission>;
12
+
13
+ export const permissionList = Object.values(permissions);
@@ -0,0 +1,9 @@
1
+ import { definePluginMetadata } from "@checkmate-monitor/common";
2
+
3
+ /**
4
+ * Plugin metadata for the incident plugin.
5
+ * Exported from the common package so both backend and frontend can reference it.
6
+ */
7
+ export const pluginMetadata = definePluginMetadata({
8
+ pluginId: "incident",
9
+ });
package/src/routes.ts ADDED
@@ -0,0 +1,30 @@
1
+ import { createRoutes } from "@checkmate-monitor/common";
2
+
3
+ /**
4
+ * Route definitions for the incident plugin.
5
+ * Import and use these routes in both frontend plugins and for link generation.
6
+ *
7
+ * @example Frontend plugin usage
8
+ * ```tsx
9
+ * import { incidentRoutes } from "@checkmate-monitor/incident-common";
10
+ *
11
+ * createFrontendPlugin({
12
+ * routes: [
13
+ * { route: incidentRoutes.routes.config, element: <ConfigPage /> },
14
+ * ],
15
+ * });
16
+ * ```
17
+ *
18
+ * @example Link generation
19
+ * ```tsx
20
+ * import { incidentRoutes } from "@checkmate-monitor/incident-common";
21
+ * import { resolveRoute } from "@checkmate-monitor/common";
22
+ *
23
+ * const detailPath = resolveRoute(incidentRoutes.routes.detail, { incidentId });
24
+ * ```
25
+ */
26
+ export const incidentRoutes = createRoutes("incident", {
27
+ config: "/config",
28
+ detail: "/:incidentId",
29
+ systemHistory: "/system/:systemId/incidents",
30
+ });
@@ -0,0 +1,111 @@
1
+ import { oc } from "@orpc/contract";
2
+ import { z } from "zod";
3
+ import {
4
+ createClientDefinition,
5
+ type ProcedureMetadata,
6
+ } from "@checkmate-monitor/common";
7
+ import { permissions } from "./permissions";
8
+ import { pluginMetadata } from "./plugin-metadata";
9
+ import {
10
+ IncidentWithSystemsSchema,
11
+ IncidentDetailSchema,
12
+ IncidentUpdateSchema,
13
+ CreateIncidentInputSchema,
14
+ UpdateIncidentInputSchema,
15
+ AddIncidentUpdateInputSchema,
16
+ IncidentStatusEnum,
17
+ } from "./schemas";
18
+
19
+ const _base = oc.$meta<ProcedureMetadata>({});
20
+
21
+ export const incidentContract = {
22
+ /** List all incidents with optional filters */
23
+ listIncidents: _base
24
+ .meta({
25
+ userType: "public",
26
+ permissions: [permissions.incidentRead.id],
27
+ })
28
+ .input(
29
+ z
30
+ .object({
31
+ status: IncidentStatusEnum.optional(),
32
+ systemId: z.string().optional(),
33
+ includeResolved: z.boolean().optional().default(false),
34
+ })
35
+ .optional()
36
+ )
37
+ .output(z.array(IncidentWithSystemsSchema)),
38
+
39
+ /** Get a single incident with all details */
40
+ getIncident: _base
41
+ .meta({
42
+ userType: "public",
43
+ permissions: [permissions.incidentRead.id],
44
+ })
45
+ .input(z.object({ id: z.string() }))
46
+ .output(IncidentDetailSchema.nullable()),
47
+
48
+ /** Get active incidents for a specific system */
49
+ getIncidentsForSystem: _base
50
+ .meta({
51
+ userType: "public",
52
+ permissions: [permissions.incidentRead.id],
53
+ })
54
+ .input(z.object({ systemId: z.string() }))
55
+ .output(z.array(IncidentWithSystemsSchema)),
56
+
57
+ /** Create a new incident */
58
+ createIncident: _base
59
+ .meta({
60
+ userType: "authenticated",
61
+ permissions: [permissions.incidentManage.id],
62
+ })
63
+ .input(CreateIncidentInputSchema)
64
+ .output(IncidentWithSystemsSchema),
65
+
66
+ /** Update an existing incident */
67
+ updateIncident: _base
68
+ .meta({
69
+ userType: "authenticated",
70
+ permissions: [permissions.incidentManage.id],
71
+ })
72
+ .input(UpdateIncidentInputSchema)
73
+ .output(IncidentWithSystemsSchema),
74
+
75
+ /** Add a status update to an incident */
76
+ addUpdate: _base
77
+ .meta({
78
+ userType: "authenticated",
79
+ permissions: [permissions.incidentManage.id],
80
+ })
81
+ .input(AddIncidentUpdateInputSchema)
82
+ .output(IncidentUpdateSchema),
83
+
84
+ /** Resolve an incident (sets status to resolved) */
85
+ resolveIncident: _base
86
+ .meta({
87
+ userType: "authenticated",
88
+ permissions: [permissions.incidentManage.id],
89
+ })
90
+ .input(z.object({ id: z.string(), message: z.string().optional() }))
91
+ .output(IncidentWithSystemsSchema),
92
+
93
+ /** Delete an incident */
94
+ deleteIncident: _base
95
+ .meta({
96
+ userType: "authenticated",
97
+ permissions: [permissions.incidentManage.id],
98
+ })
99
+ .input(z.object({ id: z.string() }))
100
+ .output(z.object({ success: z.boolean() })),
101
+ };
102
+
103
+ // Export contract type
104
+ export type IncidentContract = typeof incidentContract;
105
+
106
+ // Export client definition for type-safe forPlugin usage
107
+ // Use: const client = rpcApi.forPlugin(IncidentApi);
108
+ export const IncidentApi = createClientDefinition(
109
+ incidentContract,
110
+ pluginMetadata
111
+ );
package/src/schemas.ts ADDED
@@ -0,0 +1,95 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * Incident status enum values.
5
+ * Represents the lifecycle stages of an incident.
6
+ */
7
+ export const IncidentStatusEnum = z.enum([
8
+ "investigating",
9
+ "identified",
10
+ "fixing",
11
+ "monitoring",
12
+ "resolved",
13
+ ]);
14
+ export type IncidentStatus = z.infer<typeof IncidentStatusEnum>;
15
+
16
+ /**
17
+ * Incident severity enum values.
18
+ * Represents the impact level of an incident.
19
+ */
20
+ export const IncidentSeverityEnum = z.enum(["minor", "major", "critical"]);
21
+ export type IncidentSeverity = z.infer<typeof IncidentSeverityEnum>;
22
+
23
+ /**
24
+ * Core incident entity schema
25
+ */
26
+ export const IncidentSchema = z.object({
27
+ id: z.string(),
28
+ title: z.string(),
29
+ description: z.string().optional(),
30
+ status: IncidentStatusEnum,
31
+ severity: IncidentSeverityEnum,
32
+ createdAt: z.date(),
33
+ updatedAt: z.date(),
34
+ });
35
+ export type Incident = z.infer<typeof IncidentSchema>;
36
+
37
+ /**
38
+ * Incident with related systems
39
+ */
40
+ export const IncidentWithSystemsSchema = IncidentSchema.extend({
41
+ systemIds: z.array(z.string()),
42
+ });
43
+ export type IncidentWithSystems = z.infer<typeof IncidentWithSystemsSchema>;
44
+
45
+ /**
46
+ * Incident update schema - status updates posted to an incident
47
+ */
48
+ export const IncidentUpdateSchema = z.object({
49
+ id: z.string(),
50
+ incidentId: z.string(),
51
+ message: z.string(),
52
+ statusChange: IncidentStatusEnum.optional(),
53
+ createdAt: z.date(),
54
+ createdBy: z.string().optional(),
55
+ });
56
+ export type IncidentUpdate = z.infer<typeof IncidentUpdateSchema>;
57
+
58
+ /**
59
+ * Full incident detail with systems and updates
60
+ */
61
+ export const IncidentDetailSchema = IncidentWithSystemsSchema.extend({
62
+ updates: z.array(IncidentUpdateSchema),
63
+ });
64
+ export type IncidentDetail = z.infer<typeof IncidentDetailSchema>;
65
+
66
+ // Input schemas for mutations
67
+ export const CreateIncidentInputSchema = z.object({
68
+ title: z.string().min(1, "Title is required"),
69
+ description: z.string().optional(),
70
+ severity: IncidentSeverityEnum,
71
+ systemIds: z.array(z.string()).min(1, "At least one system is required"),
72
+ initialMessage: z
73
+ .string()
74
+ .optional()
75
+ .describe("Optional initial status update message"),
76
+ });
77
+ export type CreateIncidentInput = z.infer<typeof CreateIncidentInputSchema>;
78
+
79
+ export const UpdateIncidentInputSchema = z.object({
80
+ id: z.string(),
81
+ title: z.string().min(1).optional(),
82
+ description: z.string().nullable().optional(),
83
+ severity: IncidentSeverityEnum.optional(),
84
+ systemIds: z.array(z.string()).min(1).optional(),
85
+ });
86
+ export type UpdateIncidentInput = z.infer<typeof UpdateIncidentInputSchema>;
87
+
88
+ export const AddIncidentUpdateInputSchema = z.object({
89
+ incidentId: z.string(),
90
+ message: z.string().min(1, "Message is required"),
91
+ statusChange: IncidentStatusEnum.optional(),
92
+ });
93
+ export type AddIncidentUpdateInput = z.infer<
94
+ typeof AddIncidentUpdateInputSchema
95
+ >;
package/src/slots.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { createSlot } from "@checkmate-monitor/frontend-api";
2
+ import type { IncidentWithSystems } from "./schemas";
3
+
4
+ /**
5
+ * Slot for extending incident detail views.
6
+ * Plugins can add additional content or actions to incident details.
7
+ */
8
+ export const IncidentDetailsSlot = createSlot<{
9
+ incident: IncidentWithSystems;
10
+ }>("plugin.incident.details");
11
+
12
+ /**
13
+ * Slot for adding custom status indicators to incidents.
14
+ * Can be used to show external integrations, alerts, etc.
15
+ */
16
+ export const IncidentStatusSlot = createSlot<{
17
+ incident: IncidentWithSystems;
18
+ }>("plugin.incident.status");
package/tsconfig.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "@checkmate-monitor/tsconfig/common.json",
3
+ "include": [
4
+ "src"
5
+ ]
6
+ }