@checkstack/automation-common 0.2.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.
@@ -0,0 +1,246 @@
1
+ import { z } from "zod";
2
+ import {
3
+ createClientDefinition,
4
+ PaginatedResult,
5
+ PaginationInput,
6
+ proc,
7
+ } from "@checkstack/common";
8
+ import { automationAccess } from "./access";
9
+ import { pluginMetadata } from "./plugin-metadata";
10
+ import {
11
+ ActionInfoSchema,
12
+ ArtifactTypeInfoSchema,
13
+ AutomationArtifactSchema,
14
+ AutomationRunSchema,
15
+ AutomationRunStepSchema,
16
+ AutomationSchema,
17
+ AutomationStatusSchema,
18
+ CreateAutomationInputSchema,
19
+ ListRunsInputSchema,
20
+ ManualRunInputSchema,
21
+ TriggerInfoSchema,
22
+ UpdateAutomationInputSchema,
23
+ ValidateDefinitionInputSchema,
24
+ ValidateDefinitionResultSchema,
25
+ } from "./schemas";
26
+
27
+ /**
28
+ * Automation RPC contract. Mirrors the integration-common pattern: each
29
+ * procedure is built via `proc()` with `userType`, `operationType`, and
30
+ * `access` metadata so `autoAuthMiddleware` enforces auth + access checks
31
+ * automatically.
32
+ *
33
+ * Read operations require `automationAccess.read`. Anything that mutates
34
+ * state, runs an automation, or returns potentially sensitive registry
35
+ * metadata that gates editor UIs requires `automationAccess.manage`.
36
+ */
37
+ export const automationContract = {
38
+ // ─── Automations CRUD ──────────────────────────────────────────────────
39
+
40
+ listAutomations: proc({
41
+ operationType: "query",
42
+ userType: "authenticated",
43
+ access: [automationAccess.read],
44
+ })
45
+ .input(
46
+ PaginationInput.extend({
47
+ status: AutomationStatusSchema.optional(),
48
+ }),
49
+ )
50
+ .output(PaginatedResult(AutomationSchema)),
51
+
52
+ getAutomation: proc({
53
+ operationType: "query",
54
+ userType: "authenticated",
55
+ access: [automationAccess.read],
56
+ })
57
+ .input(z.object({ id: z.string() }))
58
+ .output(AutomationSchema),
59
+
60
+ createAutomation: proc({
61
+ operationType: "mutation",
62
+ userType: "authenticated",
63
+ access: [automationAccess.manage],
64
+ })
65
+ .input(CreateAutomationInputSchema)
66
+ .output(AutomationSchema),
67
+
68
+ updateAutomation: proc({
69
+ operationType: "mutation",
70
+ userType: "authenticated",
71
+ access: [automationAccess.manage],
72
+ })
73
+ .route({ method: "PATCH" })
74
+ .input(UpdateAutomationInputSchema)
75
+ .output(AutomationSchema),
76
+
77
+ deleteAutomation: proc({
78
+ operationType: "mutation",
79
+ userType: "authenticated",
80
+ access: [automationAccess.manage],
81
+ })
82
+ .route({ method: "DELETE" })
83
+ .input(z.object({ id: z.string() }))
84
+ .output(z.object({ success: z.boolean() })),
85
+
86
+ toggleAutomation: proc({
87
+ operationType: "mutation",
88
+ userType: "authenticated",
89
+ access: [automationAccess.manage],
90
+ })
91
+ .input(z.object({ id: z.string(), enabled: z.boolean() }))
92
+ .output(AutomationSchema),
93
+
94
+ // ─── Definition validation ─────────────────────────────────────────────
95
+
96
+ validateDefinition: proc({
97
+ operationType: "mutation",
98
+ userType: "authenticated",
99
+ access: [automationAccess.read],
100
+ })
101
+ .input(ValidateDefinitionInputSchema)
102
+ .output(ValidateDefinitionResultSchema),
103
+
104
+ // ─── Manual run ────────────────────────────────────────────────────────
105
+
106
+ manualRun: proc({
107
+ operationType: "mutation",
108
+ userType: "authenticated",
109
+ access: [automationAccess.manage],
110
+ })
111
+ .input(ManualRunInputSchema)
112
+ .output(z.object({ runId: z.string() })),
113
+
114
+ // ─── Runs / history ────────────────────────────────────────────────────
115
+
116
+ listRuns: proc({
117
+ operationType: "query",
118
+ userType: "authenticated",
119
+ access: [automationAccess.read],
120
+ })
121
+ .input(ListRunsInputSchema)
122
+ .output(PaginatedResult(AutomationRunSchema)),
123
+
124
+ getRun: proc({
125
+ operationType: "query",
126
+ userType: "authenticated",
127
+ access: [automationAccess.read],
128
+ })
129
+ .input(z.object({ id: z.string() }))
130
+ .output(
131
+ z.object({
132
+ run: AutomationRunSchema,
133
+ steps: z.array(AutomationRunStepSchema),
134
+ artifacts: z.array(AutomationArtifactSchema),
135
+ }),
136
+ ),
137
+
138
+ cancelRun: proc({
139
+ operationType: "mutation",
140
+ userType: "authenticated",
141
+ access: [automationAccess.manage],
142
+ })
143
+ .input(z.object({ id: z.string() }))
144
+ .output(z.object({ success: z.boolean() })),
145
+
146
+ // ─── Registry introspection ────────────────────────────────────────────
147
+
148
+ listTriggers: proc({
149
+ operationType: "query",
150
+ userType: "authenticated",
151
+ access: [automationAccess.read],
152
+ }).output(z.object({ items: z.array(TriggerInfoSchema) })),
153
+
154
+ listActions: proc({
155
+ operationType: "query",
156
+ userType: "authenticated",
157
+ access: [automationAccess.read],
158
+ }).output(z.object({ items: z.array(ActionInfoSchema) })),
159
+
160
+ listArtifactTypes: proc({
161
+ operationType: "query",
162
+ userType: "authenticated",
163
+ access: [automationAccess.read],
164
+ }).output(z.object({ items: z.array(ArtifactTypeInfoSchema) })),
165
+
166
+ // ─── Subscription-migration failures ──────────────────────────────────
167
+ //
168
+ // Surfaces every legacy `webhook_subscriptions` row the one-time
169
+ // migration couldn't translate into an automation. Admins see the
170
+ // list on boot, fix each one by hand (recreating it as an
171
+ // automation), then acknowledge it to clear the entry.
172
+
173
+ listMigrationFailures: proc({
174
+ operationType: "query",
175
+ userType: "authenticated",
176
+ access: [automationAccess.manage],
177
+ }).output(
178
+ z.object({
179
+ items: z.array(
180
+ z.object({
181
+ id: z.string(),
182
+ subscriptionId: z.string(),
183
+ subscriptionName: z.string(),
184
+ providerId: z.string(),
185
+ eventId: z.string(),
186
+ reason: z.string(),
187
+ detail: z.string().optional(),
188
+ providerConfig: z.record(z.string(), z.unknown()),
189
+ createdAt: z.coerce.date(),
190
+ }),
191
+ ),
192
+ }),
193
+ ),
194
+
195
+ acknowledgeMigrationFailure: proc({
196
+ operationType: "mutation",
197
+ userType: "authenticated",
198
+ access: [automationAccess.manage],
199
+ })
200
+ .input(z.object({ id: z.string() }))
201
+ .output(z.object({ success: z.boolean() })),
202
+
203
+ // ─── Template playground ───────────────────────────────────────────────
204
+
205
+ /**
206
+ * Render a template (or evaluate a condition) against a sample context.
207
+ * Used by the playground page and the inline preview in the editor.
208
+ */
209
+ renderTemplate: proc({
210
+ operationType: "mutation",
211
+ userType: "authenticated",
212
+ access: [automationAccess.read],
213
+ })
214
+ .input(
215
+ z.object({
216
+ template: z.string(),
217
+ context: z.record(z.string(), z.unknown()).default({}),
218
+ mode: z.enum(["template", "condition"]).default("template"),
219
+ }),
220
+ )
221
+ .output(
222
+ z.object({
223
+ success: z.boolean(),
224
+ output: z.string().optional(),
225
+ booleanResult: z.boolean().optional(),
226
+ error: z
227
+ .object({
228
+ message: z.string(),
229
+ line: z.number(),
230
+ column: z.number(),
231
+ })
232
+ .optional(),
233
+ }),
234
+ ),
235
+ };
236
+
237
+ export type AutomationContract = typeof automationContract;
238
+
239
+ /**
240
+ * Client definition for typed `rpcApi.forPlugin(AutomationApi)` calls
241
+ * from the frontend.
242
+ */
243
+ export const AutomationApi = createClientDefinition(
244
+ automationContract,
245
+ pluginMetadata,
246
+ );