@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 +30 -0
- package/package.json +27 -0
- package/src/index.ts +49 -0
- package/src/permissions.ts +13 -0
- package/src/plugin-metadata.ts +9 -0
- package/src/routes.ts +30 -0
- package/src/rpc-contract.ts +111 -0
- package/src/schemas.ts +95 -0
- package/src/slots.ts +18 -0
- package/tsconfig.json +6 -0
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");
|