@checkstack/integration-common 0.0.2

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,46 @@
1
+ # @checkstack/integration-common
2
+
3
+ ## 0.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - d20d274: Initial release of all @checkstack packages. Rebranded from Checkmate to Checkstack with new npm organization @checkstack and domain checkstack.dev.
8
+ - Updated dependencies [d20d274]
9
+ - @checkstack/common@0.0.2
10
+ - @checkstack/signal-common@0.0.2
11
+
12
+ ## 0.1.1
13
+
14
+ ### Patch Changes
15
+
16
+ - Updated dependencies [a65e002]
17
+ - @checkstack/common@0.2.0
18
+ - @checkstack/signal-common@0.1.1
19
+
20
+ ## 0.1.0
21
+
22
+ ### Minor Changes
23
+
24
+ - 4dd644d: Enable external application (API key) access to management endpoints
25
+
26
+ 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:
27
+
28
+ - **incident-common**: createIncident, updateIncident, addUpdate, resolveIncident, deleteIncident
29
+ - **maintenance-common**: createMaintenance, updateMaintenance, addUpdate, closeMaintenance, deleteMaintenance
30
+ - **catalog-common**: System CRUD, Group CRUD, addSystemToGroup, removeSystemFromGroup
31
+ - **healthcheck-common**: Configuration management, system associations, retention config, detailed history
32
+ - **integration-common**: Subscription management, connection management, event discovery, delivery logs
33
+
34
+ This enables automation use cases such as:
35
+
36
+ - Creating incidents from external monitoring systems (Prometheus, Grafana)
37
+ - Scheduling maintenances from CI/CD pipelines
38
+ - Managing catalog systems from infrastructure-as-code tools
39
+ - Configuring health checks from deployment scripts
40
+
41
+ ### Patch Changes
42
+
43
+ - Updated dependencies [ffc28f6]
44
+ - Updated dependencies [b55fae6]
45
+ - @checkstack/common@0.1.0
46
+ - @checkstack/signal-common@0.1.0
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@checkstack/integration-common",
3
+ "version": "0.0.2",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "types": "./src/index.ts",
8
+ "import": "./src/index.ts"
9
+ }
10
+ },
11
+ "dependencies": {
12
+ "@checkstack/common": "workspace:*",
13
+ "@checkstack/signal-common": "workspace:*",
14
+ "@orpc/contract": "^1.13.2",
15
+ "zod": "^4.0.0"
16
+ },
17
+ "devDependencies": {
18
+ "@checkstack/tsconfig": "workspace:*",
19
+ "typescript": "^5.7.2",
20
+ "@checkstack/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,64 @@
1
+ // Schemas - Zod validators for API contracts
2
+ export {
3
+ // Delivery status
4
+ DeliveryStatusSchema,
5
+ type DeliveryStatus,
6
+ // Webhook subscriptions
7
+ WebhookSubscriptionSchema,
8
+ type WebhookSubscription,
9
+ CreateSubscriptionInputSchema,
10
+ type CreateSubscriptionInput,
11
+ UpdateSubscriptionInputSchema,
12
+ type UpdateSubscriptionInput,
13
+ // Delivery logs
14
+ DeliveryLogSchema,
15
+ type DeliveryLog,
16
+ DeliveryLogQueryInputSchema,
17
+ type DeliveryLogQueryInput,
18
+ // Provider info
19
+ IntegrationProviderInfoSchema,
20
+ type IntegrationProviderInfo,
21
+ // Event info
22
+ IntegrationEventInfoSchema,
23
+ type IntegrationEventInfo,
24
+ // Result schemas (for API validation)
25
+ IntegrationDeliveryResultSchema,
26
+ TestConnectionResultSchema,
27
+ // Connection management
28
+ ProviderConnectionSchema,
29
+ type ProviderConnection,
30
+ ProviderConnectionRedactedSchema,
31
+ type ProviderConnectionRedacted,
32
+ CreateConnectionInputSchema,
33
+ type CreateConnectionInput,
34
+ UpdateConnectionInputSchema,
35
+ type UpdateConnectionInput,
36
+ GetConnectionOptionsInputSchema,
37
+ type GetConnectionOptionsInput,
38
+ ConnectionOptionSchema,
39
+ type ConnectionOptionOutput,
40
+ // Payload property hints
41
+ PayloadPropertySchema,
42
+ type PayloadProperty,
43
+ EventPayloadSchemaOutputSchema,
44
+ type EventPayloadSchemaOutput,
45
+ } from "./schemas";
46
+
47
+ // NOTE: All backend-only types (IntegrationProvider, IntegrationDeliveryContext, etc.)
48
+ // are defined in @checkstack/integration-backend/provider-types.
49
+ // Frontend code should only use the Zod schemas above for API contracts.
50
+
51
+ // Permissions
52
+ export * from "./permissions";
53
+
54
+ // RPC Contract
55
+ export * from "./rpc-contract";
56
+
57
+ // Signals
58
+ export * from "./signals";
59
+
60
+ // Plugin Metadata
61
+ export * from "./plugin-metadata";
62
+
63
+ // Routes
64
+ export { integrationRoutes } from "./routes";
@@ -0,0 +1,12 @@
1
+ import { createPermission } from "@checkstack/common";
2
+
3
+ export const permissions = {
4
+ /** Manage webhook integrations and view delivery logs */
5
+ integrationManage: createPermission(
6
+ "integration",
7
+ "manage",
8
+ "Manage webhook integrations and view delivery logs"
9
+ ),
10
+ };
11
+
12
+ export const permissionList = Object.values(permissions);
@@ -0,0 +1,9 @@
1
+ import { definePluginMetadata } from "@checkstack/common";
2
+
3
+ /**
4
+ * Plugin metadata for the integration plugin.
5
+ * Exported from the common package so both backend and frontend can reference it.
6
+ */
7
+ export const pluginMetadata = definePluginMetadata({
8
+ pluginId: "integration",
9
+ });
package/src/routes.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { createRoutes } from "@checkstack/common";
2
+
3
+ /**
4
+ * Route definitions for the integration plugin.
5
+ */
6
+ export const integrationRoutes = createRoutes("integration", {
7
+ /** Main integrations management page */
8
+ list: "/",
9
+ /** Delivery logs page (all logs) */
10
+ logs: "/logs",
11
+ /** Delivery logs filtered by subscription */
12
+ deliveryLogs: "/logs/:subscriptionId",
13
+ /** Provider connections management */
14
+ connections: "/connections/:providerId",
15
+ });
@@ -0,0 +1,311 @@
1
+ import { oc } from "@orpc/contract";
2
+ import { z } from "zod";
3
+ import { permissions } from "./permissions";
4
+ import { pluginMetadata } from "./plugin-metadata";
5
+ import {
6
+ createClientDefinition,
7
+ type ProcedureMetadata,
8
+ } from "@checkstack/common";
9
+ import {
10
+ WebhookSubscriptionSchema,
11
+ CreateSubscriptionInputSchema,
12
+ UpdateSubscriptionInputSchema,
13
+ DeliveryLogSchema,
14
+ DeliveryLogQueryInputSchema,
15
+ IntegrationProviderInfoSchema,
16
+ IntegrationEventInfoSchema,
17
+ TestConnectionResultSchema,
18
+ ProviderConnectionRedactedSchema,
19
+ CreateConnectionInputSchema,
20
+ UpdateConnectionInputSchema,
21
+ GetConnectionOptionsInputSchema,
22
+ ConnectionOptionSchema,
23
+ EventPayloadSchemaOutputSchema,
24
+ } from "./schemas";
25
+
26
+ // Base builder with full metadata support (userType + permissions)
27
+ const _base = oc.$meta<ProcedureMetadata>({});
28
+
29
+ // Integration RPC Contract
30
+ export const integrationContract = {
31
+ // ==========================================================================
32
+ // SUBSCRIPTION MANAGEMENT (Admin only)
33
+ // ==========================================================================
34
+
35
+ /** List all webhook subscriptions */
36
+ listSubscriptions: _base
37
+ .meta({
38
+ userType: "authenticated",
39
+ permissions: [permissions.integrationManage.id],
40
+ })
41
+ .input(
42
+ z.object({
43
+ page: z.number().min(1).default(1),
44
+ pageSize: z.number().min(1).max(100).default(20),
45
+ providerId: z.string().optional(),
46
+ eventType: z.string().optional(),
47
+ enabled: z.boolean().optional(),
48
+ })
49
+ )
50
+ .output(
51
+ z.object({
52
+ subscriptions: z.array(WebhookSubscriptionSchema),
53
+ total: z.number(),
54
+ })
55
+ ),
56
+
57
+ /** Get a single subscription by ID */
58
+ getSubscription: _base
59
+ .meta({
60
+ userType: "authenticated",
61
+ permissions: [permissions.integrationManage.id],
62
+ })
63
+ .input(z.object({ id: z.string() }))
64
+ .output(WebhookSubscriptionSchema),
65
+
66
+ /** Create a new webhook subscription */
67
+ createSubscription: _base
68
+ .meta({
69
+ userType: "authenticated",
70
+ permissions: [permissions.integrationManage.id],
71
+ })
72
+ .input(CreateSubscriptionInputSchema)
73
+ .output(WebhookSubscriptionSchema),
74
+
75
+ /** Update an existing subscription */
76
+ updateSubscription: _base
77
+ .meta({
78
+ userType: "authenticated",
79
+ permissions: [permissions.integrationManage.id],
80
+ })
81
+ .input(UpdateSubscriptionInputSchema)
82
+ .output(WebhookSubscriptionSchema),
83
+
84
+ /** Delete a subscription */
85
+ deleteSubscription: _base
86
+ .meta({
87
+ userType: "authenticated",
88
+ permissions: [permissions.integrationManage.id],
89
+ })
90
+ .input(z.object({ id: z.string() }))
91
+ .output(z.object({ success: z.boolean() })),
92
+
93
+ /** Toggle subscription enabled state */
94
+ toggleSubscription: _base
95
+ .meta({
96
+ userType: "authenticated",
97
+ permissions: [permissions.integrationManage.id],
98
+ })
99
+ .input(z.object({ id: z.string(), enabled: z.boolean() }))
100
+ .output(z.object({ success: z.boolean() })),
101
+
102
+ // ==========================================================================
103
+ // PROVIDER DISCOVERY (Admin only)
104
+ // ==========================================================================
105
+
106
+ /** List all registered integration providers */
107
+ listProviders: _base
108
+ .meta({
109
+ userType: "authenticated",
110
+ permissions: [permissions.integrationManage.id],
111
+ })
112
+ .output(z.array(IntegrationProviderInfoSchema)),
113
+
114
+ /** Test a provider connection with given config */
115
+ testProviderConnection: _base
116
+ .meta({
117
+ userType: "authenticated",
118
+ permissions: [permissions.integrationManage.id],
119
+ })
120
+ .input(
121
+ z.object({
122
+ providerId: z.string(),
123
+ config: z.record(z.string(), z.unknown()),
124
+ })
125
+ )
126
+ .output(TestConnectionResultSchema),
127
+
128
+ // ==========================================================================
129
+ // CONNECTION MANAGEMENT (Admin only)
130
+ // Generic CRUD for site-wide provider connections
131
+ // ==========================================================================
132
+
133
+ /** List all connections for a provider */
134
+ listConnections: _base
135
+ .meta({
136
+ userType: "authenticated",
137
+ permissions: [permissions.integrationManage.id],
138
+ })
139
+ .input(z.object({ providerId: z.string() }))
140
+ .output(z.array(ProviderConnectionRedactedSchema)),
141
+
142
+ /** Get a single connection (redacted) */
143
+ getConnection: _base
144
+ .meta({
145
+ userType: "authenticated",
146
+ permissions: [permissions.integrationManage.id],
147
+ })
148
+ .input(z.object({ connectionId: z.string() }))
149
+ .output(ProviderConnectionRedactedSchema),
150
+
151
+ /** Create a new provider connection */
152
+ createConnection: _base
153
+ .meta({
154
+ userType: "authenticated",
155
+ permissions: [permissions.integrationManage.id],
156
+ })
157
+ .input(CreateConnectionInputSchema)
158
+ .output(ProviderConnectionRedactedSchema),
159
+
160
+ /** Update a provider connection */
161
+ updateConnection: _base
162
+ .meta({
163
+ userType: "authenticated",
164
+ permissions: [permissions.integrationManage.id],
165
+ })
166
+ .input(UpdateConnectionInputSchema)
167
+ .output(ProviderConnectionRedactedSchema),
168
+
169
+ /** Delete a provider connection */
170
+ deleteConnection: _base
171
+ .meta({
172
+ userType: "authenticated",
173
+ permissions: [permissions.integrationManage.id],
174
+ })
175
+ .input(z.object({ connectionId: z.string() }))
176
+ .output(z.object({ success: z.boolean() })),
177
+
178
+ /** Test a saved connection */
179
+ testConnection: _base
180
+ .meta({
181
+ userType: "authenticated",
182
+ permissions: [permissions.integrationManage.id],
183
+ })
184
+ .input(z.object({ connectionId: z.string() }))
185
+ .output(TestConnectionResultSchema),
186
+
187
+ /** Get dynamic options for cascading dropdowns */
188
+ getConnectionOptions: _base
189
+ .meta({
190
+ userType: "authenticated",
191
+ permissions: [permissions.integrationManage.id],
192
+ })
193
+ .input(GetConnectionOptionsInputSchema)
194
+ .output(z.array(ConnectionOptionSchema)),
195
+
196
+ // ==========================================================================
197
+ // EVENT DISCOVERY (Admin only)
198
+ // ==========================================================================
199
+
200
+ /** List all registered integration events */
201
+ listEventTypes: _base
202
+ .meta({
203
+ userType: "authenticated",
204
+ permissions: [permissions.integrationManage.id],
205
+ })
206
+ .output(z.array(IntegrationEventInfoSchema)),
207
+
208
+ /** Get events grouped by category */
209
+ getEventsByCategory: _base
210
+ .meta({
211
+ userType: "authenticated",
212
+ permissions: [permissions.integrationManage.id],
213
+ })
214
+ .output(
215
+ z.array(
216
+ z.object({
217
+ category: z.string(),
218
+ events: z.array(IntegrationEventInfoSchema),
219
+ })
220
+ )
221
+ ),
222
+
223
+ /** Get payload schema for a specific event with flattened property list for template hints */
224
+ getEventPayloadSchema: _base
225
+ .meta({
226
+ userType: "authenticated",
227
+ permissions: [permissions.integrationManage.id],
228
+ })
229
+ .input(z.object({ eventId: z.string() }))
230
+ .output(EventPayloadSchemaOutputSchema),
231
+
232
+ // ==========================================================================
233
+ // DELIVERY LOGS (Admin only)
234
+ // ==========================================================================
235
+
236
+ /** Get delivery logs with filtering */
237
+ getDeliveryLogs: _base
238
+ .meta({
239
+ userType: "authenticated",
240
+ permissions: [permissions.integrationManage.id],
241
+ })
242
+ .input(DeliveryLogQueryInputSchema)
243
+ .output(
244
+ z.object({
245
+ logs: z.array(DeliveryLogSchema),
246
+ total: z.number(),
247
+ })
248
+ ),
249
+
250
+ /** Get a single delivery log entry */
251
+ getDeliveryLog: _base
252
+ .meta({
253
+ userType: "authenticated",
254
+ permissions: [permissions.integrationManage.id],
255
+ })
256
+ .input(z.object({ id: z.string() }))
257
+ .output(DeliveryLogSchema),
258
+
259
+ /** Retry a failed delivery */
260
+ retryDelivery: _base
261
+ .meta({
262
+ userType: "authenticated",
263
+ permissions: [permissions.integrationManage.id],
264
+ })
265
+ .input(z.object({ logId: z.string() }))
266
+ .output(z.object({ success: z.boolean(), message: z.string().optional() })),
267
+
268
+ /** Get delivery statistics for dashboard */
269
+ getDeliveryStats: _base
270
+ .meta({
271
+ userType: "authenticated",
272
+ permissions: [permissions.integrationManage.id],
273
+ })
274
+ .input(
275
+ z.object({
276
+ /** Time range in hours (default: 24) */
277
+ hours: z.number().min(1).max(720).default(24),
278
+ })
279
+ )
280
+ .output(
281
+ z.object({
282
+ total: z.number(),
283
+ successful: z.number(),
284
+ failed: z.number(),
285
+ retrying: z.number(),
286
+ pending: z.number(),
287
+ byEvent: z.array(
288
+ z.object({
289
+ eventType: z.string(),
290
+ count: z.number(),
291
+ })
292
+ ),
293
+ byProvider: z.array(
294
+ z.object({
295
+ providerId: z.string(),
296
+ count: z.number(),
297
+ })
298
+ ),
299
+ })
300
+ ),
301
+ };
302
+
303
+ // Export contract type
304
+ export type IntegrationContract = typeof integrationContract;
305
+
306
+ // Export client definition for type-safe forPlugin usage
307
+ // Use: const client = rpcApi.forPlugin(IntegrationApi);
308
+ export const IntegrationApi = createClientDefinition(
309
+ integrationContract,
310
+ pluginMetadata
311
+ );
package/src/schemas.ts ADDED
@@ -0,0 +1,306 @@
1
+ import { z } from "zod";
2
+
3
+ // =============================================================================
4
+ // Webhook Subscription Schemas
5
+ // =============================================================================
6
+
7
+ /** Status of a webhook delivery attempt */
8
+ export const DeliveryStatusSchema = z.enum([
9
+ "pending",
10
+ "success",
11
+ "failed",
12
+ "retrying",
13
+ ]);
14
+ export type DeliveryStatus = z.infer<typeof DeliveryStatusSchema>;
15
+
16
+ /** Webhook subscription configuration */
17
+ export const WebhookSubscriptionSchema = z.object({
18
+ id: z.string(),
19
+ name: z.string().min(1).max(100),
20
+ description: z.string().optional(),
21
+
22
+ /** Fully qualified provider ID: {pluginId}.{providerId} */
23
+ providerId: z.string(),
24
+
25
+ /** Provider-specific configuration (validated against provider schema) */
26
+ providerConfig: z.record(z.string(), z.unknown()),
27
+
28
+ /** Single event to subscribe to (fully qualified event ID) */
29
+ eventId: z.string(),
30
+
31
+ /** Optional: Filter by system IDs */
32
+ systemFilter: z.array(z.string()).optional(),
33
+
34
+ /** Subscription state */
35
+ enabled: z.boolean().default(true),
36
+
37
+ createdAt: z.coerce.date(),
38
+ updatedAt: z.coerce.date(),
39
+ });
40
+ export type WebhookSubscription = z.infer<typeof WebhookSubscriptionSchema>;
41
+
42
+ /** Input for creating a webhook subscription */
43
+ export const CreateSubscriptionInputSchema = z.object({
44
+ name: z.string().min(1).max(100),
45
+ description: z.string().optional(),
46
+ providerId: z.string(),
47
+ providerConfig: z.record(z.string(), z.unknown()),
48
+ /** Single event to subscribe to */
49
+ eventId: z.string(),
50
+ systemFilter: z.array(z.string()).optional(),
51
+ });
52
+ export type CreateSubscriptionInput = z.infer<
53
+ typeof CreateSubscriptionInputSchema
54
+ >;
55
+
56
+ /** Input for updating a webhook subscription */
57
+ export const UpdateSubscriptionInputSchema = z.object({
58
+ id: z.string(),
59
+ updates: z.object({
60
+ name: z.string().min(1).max(100).optional(),
61
+ description: z.string().optional(),
62
+ providerConfig: z.record(z.string(), z.unknown()).optional(),
63
+ eventId: z.string().optional(),
64
+ systemFilter: z.array(z.string()).optional(),
65
+ enabled: z.boolean().optional(),
66
+ }),
67
+ });
68
+ export type UpdateSubscriptionInput = z.infer<
69
+ typeof UpdateSubscriptionInputSchema
70
+ >;
71
+
72
+ // =============================================================================
73
+ // Delivery Log Schemas
74
+ // =============================================================================
75
+
76
+ /** Delivery log entry */
77
+ export const DeliveryLogSchema = z.object({
78
+ id: z.string(),
79
+ subscriptionId: z.string(),
80
+ subscriptionName: z.string().optional(),
81
+
82
+ eventType: z.string(),
83
+ eventPayload: z.record(z.string(), z.unknown()),
84
+
85
+ status: DeliveryStatusSchema,
86
+ attempts: z.number(),
87
+ lastAttemptAt: z.coerce.date().optional(),
88
+ nextRetryAt: z.coerce.date().optional(),
89
+
90
+ externalId: z.string().optional(),
91
+ errorMessage: z.string().optional(),
92
+
93
+ createdAt: z.coerce.date(),
94
+ });
95
+ export type DeliveryLog = z.infer<typeof DeliveryLogSchema>;
96
+
97
+ /** Input for querying delivery logs */
98
+ export const DeliveryLogQueryInputSchema = z.object({
99
+ subscriptionId: z.string().optional(),
100
+ eventType: z.string().optional(),
101
+ status: DeliveryStatusSchema.optional(),
102
+ page: z.number().min(1).default(1),
103
+ pageSize: z.number().min(1).max(100).default(20),
104
+ });
105
+ export type DeliveryLogQueryInput = z.infer<typeof DeliveryLogQueryInputSchema>;
106
+
107
+ // =============================================================================
108
+ // Integration Provider Schemas
109
+ // =============================================================================
110
+
111
+ /** Documentation schema for provider setup help */
112
+ export const ProviderDocumentationSchema = z
113
+ .object({
114
+ /** Brief setup instructions (rendered as markdown) */
115
+ setupGuide: z.string().optional(),
116
+ /** Example request body (JSON string for syntax highlighting) */
117
+ examplePayload: z.string().optional(),
118
+ /** HTTP headers that will be sent with each request */
119
+ headers: z
120
+ .array(
121
+ z.object({
122
+ name: z.string(),
123
+ description: z.string(),
124
+ })
125
+ )
126
+ .optional(),
127
+ /** Link to external documentation */
128
+ externalDocsUrl: z.string().url().optional(),
129
+ })
130
+ .optional();
131
+
132
+ /** Provider info for API responses */
133
+ export const IntegrationProviderInfoSchema = z.object({
134
+ /** Qualified ID: {pluginId}.{providerId} */
135
+ qualifiedId: z.string(),
136
+ /** Display name */
137
+ displayName: z.string(),
138
+ /** Description */
139
+ description: z.string().optional(),
140
+ /** Lucide icon name */
141
+ icon: z.string().optional(),
142
+ /** Owner plugin ID */
143
+ ownerPluginId: z.string(),
144
+ /** Events this provider can handle (undefined = all) */
145
+ supportedEvents: z.array(z.string()).optional(),
146
+ /** JSON Schema for provider config (for DynamicForm) */
147
+ configSchema: z.record(z.string(), z.unknown()),
148
+ /** Whether this provider has a connectionSchema (requires connection management) */
149
+ hasConnectionSchema: z.boolean().default(false),
150
+ /** JSON Schema for connection config (for DynamicForm in connection management) */
151
+ connectionSchema: z.record(z.string(), z.unknown()).optional(),
152
+ /** Optional documentation to help users configure their endpoints */
153
+ documentation: ProviderDocumentationSchema,
154
+ });
155
+ export type IntegrationProviderInfo = z.infer<
156
+ typeof IntegrationProviderInfoSchema
157
+ >;
158
+
159
+ // =============================================================================
160
+ // Provider Connection Schemas
161
+ // =============================================================================
162
+
163
+ /** Provider connection record (site-wide credentials) */
164
+ export const ProviderConnectionSchema = z.object({
165
+ /** Unique connection ID */
166
+ id: z.string(),
167
+ /** Qualified provider ID this connection belongs to */
168
+ providerId: z.string(),
169
+ /** Display name for this connection */
170
+ name: z.string().min(1).max(100),
171
+ /** Connection configuration (provider-specific, secrets redacted for API) */
172
+ config: z.record(z.string(), z.unknown()),
173
+ createdAt: z.coerce.date(),
174
+ updatedAt: z.coerce.date(),
175
+ });
176
+ export type ProviderConnection = z.infer<typeof ProviderConnectionSchema>;
177
+
178
+ /** Redacted connection for API responses (no secrets) */
179
+ export const ProviderConnectionRedactedSchema = z.object({
180
+ id: z.string(),
181
+ providerId: z.string(),
182
+ name: z.string(),
183
+ /** Redacted config (secret fields removed) */
184
+ configPreview: z.record(z.string(), z.unknown()),
185
+ createdAt: z.coerce.date(),
186
+ updatedAt: z.coerce.date(),
187
+ });
188
+ export type ProviderConnectionRedacted = z.infer<
189
+ typeof ProviderConnectionRedactedSchema
190
+ >;
191
+
192
+ /** Input for creating a provider connection */
193
+ export const CreateConnectionInputSchema = z.object({
194
+ /** Qualified provider ID */
195
+ providerId: z.string(),
196
+ /** Display name */
197
+ name: z.string().min(1).max(100),
198
+ /** Provider-specific connection config (validated against connectionSchema) */
199
+ config: z.record(z.string(), z.unknown()),
200
+ });
201
+ export type CreateConnectionInput = z.infer<typeof CreateConnectionInputSchema>;
202
+
203
+ /** Input for updating a provider connection */
204
+ export const UpdateConnectionInputSchema = z.object({
205
+ connectionId: z.string(),
206
+ updates: z.object({
207
+ name: z.string().min(1).max(100).optional(),
208
+ /** Partial config update (only provided fields are updated) */
209
+ config: z.record(z.string(), z.unknown()).optional(),
210
+ }),
211
+ });
212
+ export type UpdateConnectionInput = z.infer<typeof UpdateConnectionInputSchema>;
213
+
214
+ /** Input for getting connection options (cascading dropdowns) */
215
+ export const GetConnectionOptionsInputSchema = z.object({
216
+ providerId: z.string(),
217
+ connectionId: z.string(),
218
+ resolverName: z.string(),
219
+ context: z.record(z.string(), z.unknown()).default({}),
220
+ });
221
+ export type GetConnectionOptionsInput = z.infer<
222
+ typeof GetConnectionOptionsInputSchema
223
+ >;
224
+
225
+ /** Option returned from getConnectionOptions */
226
+ export const ConnectionOptionSchema = z.object({
227
+ value: z.string(),
228
+ label: z.string(),
229
+ description: z.string().optional(),
230
+ });
231
+ export type ConnectionOptionOutput = z.infer<typeof ConnectionOptionSchema>;
232
+
233
+ // =============================================================================
234
+ // Integration Event Schemas
235
+ // =============================================================================
236
+
237
+ /** Integration event info for API responses */
238
+ export const IntegrationEventInfoSchema = z.object({
239
+ /** Fully qualified event ID: {pluginId}.{hookId} */
240
+ eventId: z.string(),
241
+ /** Display name for UI */
242
+ displayName: z.string(),
243
+ /** Description of when this event fires */
244
+ description: z.string().optional(),
245
+ /** Category for UI grouping */
246
+ category: z.string().optional(),
247
+ /** Owner plugin ID */
248
+ ownerPluginId: z.string(),
249
+ /** JSON Schema for payload preview */
250
+ payloadSchema: z.record(z.string(), z.unknown()),
251
+ });
252
+ export type IntegrationEventInfo = z.infer<typeof IntegrationEventInfoSchema>;
253
+
254
+ // =============================================================================
255
+ // Delivery Result Schema
256
+ // =============================================================================
257
+
258
+ /** Result of a provider delivery attempt */
259
+ export const IntegrationDeliveryResultSchema = z.object({
260
+ success: z.boolean(),
261
+ externalId: z.string().optional(),
262
+ error: z.string().optional(),
263
+ retryAfterMs: z.number().optional(),
264
+ });
265
+ export type IntegrationDeliveryResult = z.infer<
266
+ typeof IntegrationDeliveryResultSchema
267
+ >;
268
+
269
+ // =============================================================================
270
+ // Test Connection Schema
271
+ // =============================================================================
272
+
273
+ /** Result of testing a provider connection */
274
+ export const TestConnectionResultSchema = z.object({
275
+ success: z.boolean(),
276
+ message: z.string().optional(),
277
+ });
278
+ export type TestConnectionResult = z.infer<typeof TestConnectionResultSchema>;
279
+
280
+ // =============================================================================
281
+ // Payload Property Schema (for template hints)
282
+ // =============================================================================
283
+
284
+ /** A single payload property available for templating */
285
+ export const PayloadPropertySchema = z.object({
286
+ /** Full path to the property, e.g., "payload.incident.title" */
287
+ path: z.string(),
288
+ /** Type of the property, e.g., "string", "number", "boolean" */
289
+ type: z.string(),
290
+ /** Optional description of the property */
291
+ description: z.string().optional(),
292
+ });
293
+ export type PayloadProperty = z.infer<typeof PayloadPropertySchema>;
294
+
295
+ /** Output schema for getEventPayloadSchema */
296
+ export const EventPayloadSchemaOutputSchema = z.object({
297
+ /** Event ID */
298
+ eventId: z.string(),
299
+ /** Full JSON Schema for the payload */
300
+ payloadSchema: z.record(z.string(), z.unknown()),
301
+ /** Flattened list of available properties for template hints */
302
+ availableProperties: z.array(PayloadPropertySchema),
303
+ });
304
+ export type EventPayloadSchemaOutput = z.infer<
305
+ typeof EventPayloadSchemaOutputSchema
306
+ >;
package/src/signals.ts ADDED
@@ -0,0 +1,31 @@
1
+ import { createSignal } from "@checkstack/signal-common";
2
+ import { z } from "zod";
3
+ import { DeliveryStatusSchema } from "./schemas";
4
+
5
+ /**
6
+ * Signal emitted when a delivery completes (success or failure).
7
+ * Used to update the delivery logs UI in real-time.
8
+ */
9
+ export const INTEGRATION_DELIVERY_COMPLETED = createSignal(
10
+ "INTEGRATION_DELIVERY_COMPLETED",
11
+ z.object({
12
+ logId: z.string(),
13
+ subscriptionId: z.string(),
14
+ eventType: z.string(),
15
+ status: DeliveryStatusSchema,
16
+ externalId: z.string().optional(),
17
+ errorMessage: z.string().optional(),
18
+ })
19
+ );
20
+
21
+ /**
22
+ * Signal emitted when a subscription is created, updated, or deleted.
23
+ * Used to refresh the subscriptions list in real-time.
24
+ */
25
+ export const INTEGRATION_SUBSCRIPTION_CHANGED = createSignal(
26
+ "INTEGRATION_SUBSCRIPTION_CHANGED",
27
+ z.object({
28
+ action: z.enum(["created", "updated", "deleted"]),
29
+ subscriptionId: z.string(),
30
+ })
31
+ );
package/tsconfig.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "@checkstack/tsconfig/common.json",
3
+ "include": [
4
+ "src"
5
+ ]
6
+ }