@checkstack/integration-backend 0.1.30 → 0.3.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 +188 -0
- package/package.json +11 -9
- package/src/connection-credentials-migration.test.ts +171 -0
- package/src/connection-credentials-migration.ts +182 -0
- package/src/connection-credentials.test.ts +180 -0
- package/src/connection-credentials.ts +165 -0
- package/src/connection-store.ts +119 -6
- package/src/index.ts +55 -181
- package/src/provider-registry.test.ts +56 -286
- package/src/provider-registry.ts +5 -20
- package/src/provider-types.ts +23 -149
- package/src/router.ts +87 -608
- package/src/schema.ts +13 -59
- package/src/test-connection-masking.test.ts +98 -0
- package/tsconfig.json +6 -0
- package/src/delivery-coordinator.ts +0 -391
- package/src/event-registry.test.ts +0 -396
- package/src/event-registry.ts +0 -99
- package/src/hook-subscriber.ts +0 -105
package/src/index.ts
CHANGED
|
@@ -13,39 +13,31 @@ import {
|
|
|
13
13
|
} from "@checkstack/integration-common";
|
|
14
14
|
import { resolveRoute } from "@checkstack/common";
|
|
15
15
|
import type { PluginMetadata } from "@checkstack/common";
|
|
16
|
-
import type {
|
|
17
|
-
IntegrationEventDefinition,
|
|
18
|
-
IntegrationProvider,
|
|
19
|
-
} from "./provider-types";
|
|
16
|
+
import type { IntegrationProvider } from "./provider-types";
|
|
20
17
|
|
|
21
18
|
import * as schema from "./schema";
|
|
22
|
-
import {
|
|
23
|
-
createIntegrationEventRegistry,
|
|
24
|
-
type IntegrationEventRegistry,
|
|
25
|
-
} from "./event-registry";
|
|
26
|
-
import {
|
|
27
|
-
createIntegrationProviderRegistry,
|
|
28
|
-
type IntegrationProviderRegistry,
|
|
29
|
-
} from "./provider-registry";
|
|
30
|
-
import { createDeliveryCoordinator } from "./delivery-coordinator";
|
|
19
|
+
import { createIntegrationProviderRegistry } from "./provider-registry";
|
|
31
20
|
import {
|
|
32
21
|
createConnectionStore,
|
|
33
22
|
type ConnectionStore,
|
|
34
23
|
} from "./connection-store";
|
|
35
|
-
import { subscribeToRegisteredEvents } from "./hook-subscriber";
|
|
36
24
|
import { createIntegrationRouter } from "./router";
|
|
37
25
|
import { registerSearchProvider } from "@checkstack/command-backend";
|
|
26
|
+
import {
|
|
27
|
+
secretResolverRef,
|
|
28
|
+
internalSecretsRef,
|
|
29
|
+
} from "@checkstack/secrets-backend";
|
|
38
30
|
|
|
39
31
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
40
32
|
// Service References
|
|
41
33
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
42
34
|
|
|
43
35
|
/**
|
|
44
|
-
* Service reference for the connection store.
|
|
45
|
-
*
|
|
36
|
+
* Service reference for the connection store. Provider plugins inject
|
|
37
|
+
* this to look up credentials when an automation action runs.
|
|
46
38
|
*/
|
|
47
39
|
export const connectionStoreRef = createServiceRef<ConnectionStore>(
|
|
48
|
-
"integration.connectionStore"
|
|
40
|
+
"integration.connectionStore",
|
|
49
41
|
);
|
|
50
42
|
|
|
51
43
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
@@ -53,83 +45,45 @@ export const connectionStoreRef = createServiceRef<ConnectionStore>(
|
|
|
53
45
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
54
46
|
|
|
55
47
|
/**
|
|
56
|
-
* Extension point for registering integration
|
|
57
|
-
*
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Register a hook as an integration event.
|
|
62
|
-
* The event will be namespaced by the plugin's ID automatically.
|
|
63
|
-
*/
|
|
64
|
-
registerEvent<T>(
|
|
65
|
-
definition: IntegrationEventDefinition<T>,
|
|
66
|
-
pluginMetadata: PluginMetadata
|
|
67
|
-
): void;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export const integrationEventExtensionPoint =
|
|
71
|
-
createExtensionPoint<IntegrationEventExtensionPoint>(
|
|
72
|
-
"integration.eventExtensionPoint"
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Extension point for registering integration providers.
|
|
77
|
-
* Plugins use this to register webhook delivery providers.
|
|
48
|
+
* Extension point for registering integration providers. After the
|
|
49
|
+
* migration to the Automation Platform a provider is just the
|
|
50
|
+
* connection metadata + dropdown resolvers + a test endpoint — the
|
|
51
|
+
* per-event delivery work moved onto automation actions.
|
|
78
52
|
*/
|
|
79
53
|
export interface IntegrationProviderExtensionPoint {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
* @template TConfig - Per-subscription configuration type
|
|
84
|
-
* @template TConnection - Site-wide connection configuration type (optional)
|
|
85
|
-
*/
|
|
86
|
-
addProvider<TConfig, TConnection = undefined>(
|
|
87
|
-
provider: IntegrationProvider<TConfig, TConnection>,
|
|
88
|
-
pluginMetadata: PluginMetadata
|
|
54
|
+
addProvider<TConnection = undefined>(
|
|
55
|
+
provider: IntegrationProvider<TConnection>,
|
|
56
|
+
pluginMetadata: PluginMetadata,
|
|
89
57
|
): void;
|
|
90
58
|
}
|
|
91
59
|
|
|
92
60
|
export const integrationProviderExtensionPoint =
|
|
93
61
|
createExtensionPoint<IntegrationProviderExtensionPoint>(
|
|
94
|
-
"integration.providerExtensionPoint"
|
|
62
|
+
"integration.providerExtensionPoint",
|
|
95
63
|
);
|
|
96
64
|
|
|
97
65
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
98
66
|
// Plugin Definition
|
|
99
67
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
100
68
|
|
|
69
|
+
interface EnvStash {
|
|
70
|
+
/** Set in `init`, used by `afterPluginsReady` for the credential migration. */
|
|
71
|
+
runCredentialMigration?: () => Promise<void>;
|
|
72
|
+
}
|
|
73
|
+
|
|
101
74
|
export default createBackendPlugin({
|
|
102
75
|
metadata: pluginMetadata,
|
|
103
76
|
|
|
104
77
|
register(env) {
|
|
105
|
-
// Create the registries
|
|
106
|
-
const eventRegistry = createIntegrationEventRegistry();
|
|
107
78
|
const providerRegistry = createIntegrationProviderRegistry();
|
|
108
79
|
|
|
109
|
-
// Register static access rules
|
|
110
80
|
env.registerAccessRules(integrationAccessRules);
|
|
111
81
|
|
|
112
|
-
// Register the event extension point
|
|
113
|
-
env.registerExtensionPoint(integrationEventExtensionPoint, {
|
|
114
|
-
registerEvent: <T>(
|
|
115
|
-
definition: IntegrationEventDefinition<T>,
|
|
116
|
-
metadata: PluginMetadata
|
|
117
|
-
) => {
|
|
118
|
-
// Type erasure: cast to unknown for storage (the registry handles this internally)
|
|
119
|
-
eventRegistry.register(
|
|
120
|
-
definition as IntegrationEventDefinition<unknown>,
|
|
121
|
-
metadata
|
|
122
|
-
);
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// Register the provider extension point
|
|
127
82
|
env.registerExtensionPoint(integrationProviderExtensionPoint, {
|
|
128
83
|
addProvider: (provider, metadata) => {
|
|
129
|
-
// Type erasure: cast to unknown for storage (the registry handles this internally)
|
|
130
84
|
providerRegistry.register(
|
|
131
85
|
provider as IntegrationProvider<unknown>,
|
|
132
|
-
metadata
|
|
86
|
+
metadata,
|
|
133
87
|
);
|
|
134
88
|
},
|
|
135
89
|
});
|
|
@@ -140,167 +94,87 @@ export default createBackendPlugin({
|
|
|
140
94
|
logger: coreServices.logger,
|
|
141
95
|
rpc: coreServices.rpc,
|
|
142
96
|
config: coreServices.config,
|
|
143
|
-
|
|
144
|
-
|
|
97
|
+
secretResolver: secretResolverRef,
|
|
98
|
+
internalSecrets: internalSecretsRef,
|
|
145
99
|
},
|
|
146
100
|
init: async ({
|
|
147
101
|
logger,
|
|
148
|
-
database,
|
|
149
102
|
rpc,
|
|
150
103
|
config,
|
|
151
|
-
|
|
152
|
-
|
|
104
|
+
database,
|
|
105
|
+
secretResolver,
|
|
106
|
+
internalSecrets,
|
|
153
107
|
}) => {
|
|
154
108
|
logger.debug("🔌 Initializing Integration Backend...");
|
|
155
109
|
|
|
156
|
-
const db = database;
|
|
157
|
-
|
|
158
|
-
// Create connection store for generic connection management
|
|
159
110
|
const connectionStore = createConnectionStore({
|
|
160
111
|
configService: config,
|
|
161
112
|
providerRegistry,
|
|
162
113
|
logger,
|
|
114
|
+
// Unified credential resolution through the ONE secrets channel.
|
|
115
|
+
credentials: { secretResolver, internalSecrets },
|
|
163
116
|
});
|
|
164
|
-
|
|
165
|
-
// Publish connection store for provider plugins to inject
|
|
166
117
|
env.registerService(connectionStoreRef, connectionStore);
|
|
118
|
+
// Stash the migration for afterPluginsReady (all providers + their
|
|
119
|
+
// connectionSchemas are registered only by then).
|
|
120
|
+
(env as unknown as EnvStash).runCredentialMigration = () =>
|
|
121
|
+
connectionStore.runCredentialMigration();
|
|
167
122
|
|
|
168
|
-
// Create delivery coordinator
|
|
169
|
-
const deliveryCoordinator = createDeliveryCoordinator({
|
|
170
|
-
db,
|
|
171
|
-
providerRegistry,
|
|
172
|
-
connectionStore,
|
|
173
|
-
queueManager,
|
|
174
|
-
signalService,
|
|
175
|
-
logger,
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
// Store for afterPluginsReady access
|
|
179
|
-
(
|
|
180
|
-
env as unknown as {
|
|
181
|
-
eventRegistry: IntegrationEventRegistry;
|
|
182
|
-
providerRegistry: IntegrationProviderRegistry;
|
|
183
|
-
deliveryCoordinator: typeof deliveryCoordinator;
|
|
184
|
-
}
|
|
185
|
-
).eventRegistry = eventRegistry;
|
|
186
|
-
(
|
|
187
|
-
env as unknown as {
|
|
188
|
-
eventRegistry: IntegrationEventRegistry;
|
|
189
|
-
providerRegistry: IntegrationProviderRegistry;
|
|
190
|
-
deliveryCoordinator: typeof deliveryCoordinator;
|
|
191
|
-
}
|
|
192
|
-
).providerRegistry = providerRegistry;
|
|
193
|
-
(
|
|
194
|
-
env as unknown as {
|
|
195
|
-
eventRegistry: IntegrationEventRegistry;
|
|
196
|
-
providerRegistry: IntegrationProviderRegistry;
|
|
197
|
-
deliveryCoordinator: typeof deliveryCoordinator;
|
|
198
|
-
}
|
|
199
|
-
).deliveryCoordinator = deliveryCoordinator;
|
|
200
|
-
|
|
201
|
-
// Create and register the router
|
|
202
123
|
const router = createIntegrationRouter({
|
|
203
|
-
db,
|
|
204
|
-
eventRegistry,
|
|
124
|
+
db: database,
|
|
205
125
|
providerRegistry,
|
|
206
|
-
deliveryCoordinator,
|
|
207
126
|
connectionStore,
|
|
208
|
-
signalService,
|
|
209
127
|
logger,
|
|
210
128
|
});
|
|
211
129
|
rpc.registerRouter(router, integrationContract);
|
|
212
130
|
|
|
213
|
-
// Register command palette commands
|
|
214
131
|
registerSearchProvider({
|
|
215
132
|
pluginMetadata,
|
|
216
133
|
commands: [
|
|
217
134
|
{
|
|
218
|
-
id: "
|
|
219
|
-
title: "
|
|
220
|
-
subtitle: "
|
|
221
|
-
iconName: "Webhook",
|
|
222
|
-
route:
|
|
223
|
-
resolveRoute(integrationRoutes.routes.list) + "?action=create",
|
|
224
|
-
requiredAccessRules: [integrationAccess.manage],
|
|
225
|
-
},
|
|
226
|
-
{
|
|
227
|
-
id: "manage",
|
|
228
|
-
title: "Manage Integrations",
|
|
229
|
-
subtitle: "Manage integration subscriptions and connections",
|
|
135
|
+
id: "connections",
|
|
136
|
+
title: "Manage Integration Connections",
|
|
137
|
+
subtitle: "Configure credentials for Jira, Teams, Webex, etc.",
|
|
230
138
|
iconName: "Webhook",
|
|
231
139
|
shortcuts: ["meta+shift+g", "ctrl+shift+g"],
|
|
232
140
|
route: resolveRoute(integrationRoutes.routes.list),
|
|
233
141
|
requiredAccessRules: [integrationAccess.manage],
|
|
234
142
|
},
|
|
235
|
-
{
|
|
236
|
-
id: "logs",
|
|
237
|
-
title: "View Integration Logs",
|
|
238
|
-
subtitle: "View integration delivery logs",
|
|
239
|
-
iconName: "FileText",
|
|
240
|
-
route: resolveRoute(integrationRoutes.routes.logs),
|
|
241
|
-
requiredAccessRules: [integrationAccess.manage],
|
|
242
|
-
},
|
|
243
143
|
],
|
|
244
144
|
});
|
|
245
145
|
|
|
246
|
-
logger.debug("✅ Integration Backend initialized.");
|
|
247
|
-
},
|
|
248
|
-
afterPluginsReady: async ({ logger, onHook }) => {
|
|
249
|
-
// Get registries from env
|
|
250
|
-
const stored = env as unknown as {
|
|
251
|
-
eventRegistry: IntegrationEventRegistry;
|
|
252
|
-
providerRegistry: IntegrationProviderRegistry;
|
|
253
|
-
deliveryCoordinator: ReturnType<typeof createDeliveryCoordinator>;
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
const events = stored.eventRegistry.getEvents();
|
|
257
|
-
const providers = stored.providerRegistry.getProviders();
|
|
258
|
-
|
|
259
|
-
logger.debug(
|
|
260
|
-
`🔌 Registered ${events.length} integration events: ${events
|
|
261
|
-
.map((e) => e.eventId)
|
|
262
|
-
.join(", ")}`
|
|
263
|
-
);
|
|
264
|
-
|
|
265
146
|
logger.debug(
|
|
266
|
-
`📡
|
|
267
|
-
.map((p) => p.qualifiedId)
|
|
268
|
-
.join(", ")}`
|
|
147
|
+
`📡 Integration Backend init complete with ${providerRegistry.getProviders().length} providers`,
|
|
269
148
|
);
|
|
149
|
+
},
|
|
270
150
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
logger.debug("✅ Integration Backend afterPluginsReady complete.");
|
|
151
|
+
// Consolidate legacy inline connection credentials onto the secrets
|
|
152
|
+
// platform once every provider (and its connectionSchema) is
|
|
153
|
+
// registered. Idempotent + parity-verified + reversible (backup).
|
|
154
|
+
afterPluginsReady: async ({ logger }) => {
|
|
155
|
+
try {
|
|
156
|
+
await (env as unknown as EnvStash).runCredentialMigration?.();
|
|
157
|
+
} catch (error) {
|
|
158
|
+
logger.error(
|
|
159
|
+
`Connection credential migration failed: ${String(error)}`,
|
|
160
|
+
);
|
|
161
|
+
}
|
|
284
162
|
},
|
|
285
163
|
});
|
|
286
164
|
},
|
|
287
165
|
});
|
|
288
166
|
|
|
289
|
-
// Re-
|
|
290
|
-
|
|
167
|
+
// ─── Re-exports ─────────────────────────────────────────────────────────
|
|
168
|
+
|
|
291
169
|
export { integrationProviderExtensionPoint as providerExtensionPoint };
|
|
292
170
|
|
|
293
|
-
// Re-export provider types for consumer plugins
|
|
294
|
-
// All backend-only types are defined here (not in integration-common)
|
|
295
171
|
export type {
|
|
296
|
-
IntegrationEventDefinition,
|
|
297
|
-
IntegrationDeliveryContext,
|
|
298
|
-
IntegrationDeliveryResult,
|
|
299
172
|
TestConnectionResult,
|
|
300
173
|
ProviderDocumentation,
|
|
301
174
|
ConnectionOption,
|
|
302
175
|
GetConnectionOptionsParams,
|
|
303
176
|
IntegrationProvider,
|
|
304
177
|
RegisteredIntegrationProvider,
|
|
305
|
-
RegisteredIntegrationEvent,
|
|
306
178
|
} from "./provider-types";
|
|
179
|
+
|
|
180
|
+
export type { ConnectionStore } from "./connection-store";
|