@veltrixsecops/app-sdk 1.0.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,286 @@
1
+ import * as react from 'react';
2
+
3
+ type AppSource = 'BUILT_IN' | 'MARKETPLACE' | 'CUSTOM';
4
+ type AppStatusType = 'AVAILABLE' | 'DEPRECATED' | 'REMOVED';
5
+ type AppInstallationStatus = 'INSTALLING' | 'INSTALLED' | 'ENABLED' | 'DISABLED' | 'FAILED' | 'UNINSTALLING';
6
+ interface AppManifest {
7
+ id: string;
8
+ name: string;
9
+ version: string;
10
+ vendor: string;
11
+ description: string;
12
+ category: string;
13
+ license?: string;
14
+ homepage?: string;
15
+ icon?: string;
16
+ logo?: string;
17
+ platform: {
18
+ minVersion: string;
19
+ };
20
+ permissions: {
21
+ platform: string[];
22
+ app: AppPermissionDeclaration[];
23
+ };
24
+ database?: {
25
+ migrations: string;
26
+ tablePrefix: string;
27
+ };
28
+ pipeline: {
29
+ configurationTypes: AppConfigurationTypeManifest[];
30
+ pipelineEvents?: string[];
31
+ };
32
+ server: {
33
+ entry: string;
34
+ routes?: {
35
+ prefix: string;
36
+ };
37
+ };
38
+ client?: {
39
+ entry: string;
40
+ pages?: AppPageDeclaration[];
41
+ };
42
+ hooks?: {
43
+ onInstall?: string;
44
+ onUninstall?: string;
45
+ onEnable?: string;
46
+ onDisable?: string;
47
+ onUpgrade?: string;
48
+ };
49
+ events?: string[];
50
+ settings?: AppSettingDeclaration[];
51
+ }
52
+ interface AppConfigurationTypeManifest {
53
+ id: string;
54
+ name: string;
55
+ description?: string;
56
+ canvasTemplate: string;
57
+ defaultConfig?: string;
58
+ handlers: {
59
+ validate: string;
60
+ deploy: string;
61
+ rollback: string;
62
+ healthCheck: string;
63
+ driftDetect?: string | null;
64
+ getStatus: string;
65
+ };
66
+ targets: {
67
+ componentTypes: string[];
68
+ requiresCredential: boolean;
69
+ requiresConnectivity: boolean;
70
+ };
71
+ }
72
+ interface AppPermissionDeclaration {
73
+ resource: string;
74
+ actions: string[];
75
+ description?: string;
76
+ }
77
+ interface AppPageDeclaration {
78
+ path: string;
79
+ component: string;
80
+ label: string;
81
+ icon?: string;
82
+ sidebar?: boolean;
83
+ parent?: string;
84
+ }
85
+ interface AppSettingDeclaration {
86
+ key: string;
87
+ type: 'string' | 'number' | 'boolean' | 'select';
88
+ label: string;
89
+ description?: string;
90
+ default?: string | number | boolean;
91
+ required?: boolean;
92
+ options?: Array<{
93
+ label: string;
94
+ value: string;
95
+ }>;
96
+ }
97
+ interface AppListItem {
98
+ id: string;
99
+ appId: string;
100
+ name: string;
101
+ version: string;
102
+ vendor: string;
103
+ description: string;
104
+ category: string;
105
+ icon?: string;
106
+ logo?: string;
107
+ source: AppSource;
108
+ isDefault: boolean;
109
+ status: AppStatusType;
110
+ installed?: boolean;
111
+ enabled?: boolean;
112
+ }
113
+ interface AppDetail extends AppListItem {
114
+ license?: string;
115
+ homepage?: string;
116
+ repository?: string;
117
+ configurationTypes: Array<{
118
+ id: string;
119
+ name: string;
120
+ description?: string;
121
+ componentTypes: string[];
122
+ }>;
123
+ permissions: AppPermissionDeclaration[];
124
+ settings: AppSettingDeclaration[];
125
+ }
126
+ interface AppInstallationDetail {
127
+ id: string;
128
+ appId: string;
129
+ customerId: string;
130
+ version: string;
131
+ enabled: boolean;
132
+ installedBy: string;
133
+ installedAt: string;
134
+ settings: Record<string, unknown>;
135
+ status: AppInstallationStatus;
136
+ app: AppListItem;
137
+ }
138
+
139
+ interface Component {
140
+ id: string;
141
+ hostname: string;
142
+ port: string;
143
+ type: string[];
144
+ toolId: string;
145
+ customerId: string;
146
+ }
147
+ interface Credential {
148
+ id: string;
149
+ name: string;
150
+ username: string;
151
+ password: string;
152
+ apiToken: string | null;
153
+ certificate: string | null;
154
+ toolId: string;
155
+ customerId: string;
156
+ }
157
+ interface Connectivity {
158
+ id: string;
159
+ componentId: string;
160
+ status: string;
161
+ sshCommand: string | null;
162
+ httpsUrl: string | null;
163
+ tailscaleDeviceIP: string | null;
164
+ }
165
+ interface Tag {
166
+ id: string;
167
+ name: string;
168
+ customerId: string;
169
+ }
170
+ interface User {
171
+ id: string;
172
+ email: string;
173
+ name: string | null;
174
+ customerId: string;
175
+ roleId: string;
176
+ }
177
+ interface Customer {
178
+ id: string;
179
+ name: string;
180
+ domain: string | null;
181
+ isActive: boolean;
182
+ }
183
+ /**
184
+ * Loosely-typed handle to the platform database, passed to lifecycle hooks.
185
+ * At runtime this is the platform's Prisma client; model delegates are
186
+ * accessed by name (e.g. `db.splunkVersion.upsert(...)` for an app table).
187
+ * Apps should only touch their own prefixed tables and the raw-query
188
+ * escape hatches — anything else is unsupported and may break between
189
+ * platform versions.
190
+ */
191
+ interface PlatformDatabaseClient {
192
+ $queryRawUnsafe<T = unknown>(query: string, ...values: unknown[]): Promise<T>;
193
+ $executeRawUnsafe(query: string, ...values: unknown[]): Promise<number>;
194
+ [modelDelegate: string]: any;
195
+ }
196
+ /**
197
+ * Context passed to app lifecycle hooks
198
+ * (onInstall / onUninstall / onEnable / onDisable / onUpgrade).
199
+ * `customerId` is present only for customer-scoped hooks (onEnable/onDisable).
200
+ */
201
+ interface AppHookContext {
202
+ db: PlatformDatabaseClient;
203
+ appId: string;
204
+ customerId?: string;
205
+ }
206
+ /**
207
+ * Context passed to an app's server route module (the `server.entry`
208
+ * declared in manifest.yaml). The platform mounts the module as a Fastify
209
+ * plugin under `/api/apps/<appId>` with auth + app-enabled checks applied;
210
+ * `hasPermission` returns a preHandler enforcing an app-scoped permission.
211
+ */
212
+ interface AppRouteContext {
213
+ appId: string;
214
+ appDir: string;
215
+ manifest: AppManifest;
216
+ db: PlatformDatabaseClient;
217
+ /**
218
+ * Returns a Fastify preHandler enforcing an app-scoped permission.
219
+ * Typed `any` so the SDK does not depend on Fastify's hook types —
220
+ * pass it straight into a route's `preHandler` array.
221
+ */
222
+ hasPermission: (resource: string, action: string) => any;
223
+ }
224
+
225
+ interface AppContextValue {
226
+ appId: string;
227
+ customerId: string;
228
+ user: User | null;
229
+ customer: Customer | null;
230
+ getComponents: () => Promise<Component[]>;
231
+ getCredentials: () => Promise<Credential[]>;
232
+ getTags: () => Promise<Tag[]>;
233
+ settings: Record<string, unknown>;
234
+ }
235
+ declare const AppContext: react.Context<AppContextValue | null>;
236
+ /**
237
+ * Access the app context in any app component.
238
+ *
239
+ * @example
240
+ * ```tsx
241
+ * import { useAppContext } from '@veltrixsecops/app-sdk/hooks'
242
+ *
243
+ * function MyComponent() {
244
+ * const { appId, settings, getComponents } = useAppContext()
245
+ * // ...
246
+ * }
247
+ * ```
248
+ */
249
+ declare function useAppContext(): AppContextValue;
250
+
251
+ interface PipelineStatusData {
252
+ pendingApprovals: number;
253
+ activeDeployments: number;
254
+ failedDeployments: number;
255
+ unresolvedDrifts: number;
256
+ recentDeployments: Array<{
257
+ id: string;
258
+ canvasName: string;
259
+ environment: string;
260
+ status: string;
261
+ startedAt: string;
262
+ completedAt?: string;
263
+ }>;
264
+ }
265
+ /**
266
+ * Hook to access pipeline status for the current app/customer.
267
+ *
268
+ * @example
269
+ * ```tsx
270
+ * import { usePipelineStatus } from '@veltrixsecops/app-sdk/hooks'
271
+ *
272
+ * function Dashboard() {
273
+ * const { data, isLoading } = usePipelineStatus('my-app')
274
+ * if (isLoading) return <Spinner />
275
+ * return <div>{data.activeDeployments} active deployments</div>
276
+ * }
277
+ * ```
278
+ */
279
+ declare function usePipelineStatus(appId: string): {
280
+ data: PipelineStatusData | null;
281
+ isLoading: boolean;
282
+ error: Error | null;
283
+ refresh: () => Promise<void>;
284
+ };
285
+
286
+ export { type AppConfigurationTypeManifest as A, type Component as C, type PipelineStatusData as P, type Tag as T, type User as U, AppContext as a, type AppContextValue as b, type AppDetail as c, type AppHookContext as d, type AppInstallationDetail as e, type AppInstallationStatus as f, type AppListItem as g, type AppManifest as h, type AppPageDeclaration as i, type AppPermissionDeclaration as j, type AppRouteContext as k, type AppSettingDeclaration as l, type AppSource as m, type AppStatusType as n, type Connectivity as o, type Credential as p, type Customer as q, type PlatformDatabaseClient as r, usePipelineStatus as s, useAppContext as u };
@@ -0,0 +1,239 @@
1
+ interface ValidationError {
2
+ field: string;
3
+ message: string;
4
+ code: string;
5
+ }
6
+ interface ValidationWarning {
7
+ field: string;
8
+ message: string;
9
+ code: string;
10
+ }
11
+ interface ValidationResult {
12
+ valid: boolean;
13
+ errors: ValidationError[];
14
+ warnings: ValidationWarning[];
15
+ }
16
+ interface DeployResult {
17
+ success: boolean;
18
+ message: string;
19
+ artifacts?: Record<string, unknown>;
20
+ rollbackData?: unknown;
21
+ }
22
+ interface RollbackResult {
23
+ success: boolean;
24
+ message: string;
25
+ }
26
+ interface HealthCheck {
27
+ name: string;
28
+ passed: boolean;
29
+ message: string;
30
+ latencyMs?: number;
31
+ }
32
+ interface HealthCheckResult {
33
+ healthy: boolean;
34
+ score: number;
35
+ checks: HealthCheck[];
36
+ }
37
+ interface DriftDiff {
38
+ field: string;
39
+ expected: unknown;
40
+ actual: unknown;
41
+ severity: 'info' | 'warning' | 'critical';
42
+ }
43
+ interface DriftResult {
44
+ hasDrift: boolean;
45
+ diffs: DriftDiff[];
46
+ }
47
+ interface ComponentConfigStatus {
48
+ componentId: string;
49
+ hostname: string;
50
+ deployed: boolean;
51
+ version?: string;
52
+ lastDeployedAt?: string;
53
+ healthy?: boolean;
54
+ healthScore?: number;
55
+ }
56
+ interface ConfigStatus {
57
+ deployed: boolean;
58
+ version: string;
59
+ lastDeployedAt: string;
60
+ componentStatuses: ComponentConfigStatus[];
61
+ }
62
+ interface CanvasSectionSnapshot {
63
+ name: string;
64
+ fields: Record<string, unknown>;
65
+ }
66
+ interface CanvasSnapshot {
67
+ id: string;
68
+ canvasId: string;
69
+ version: number;
70
+ name: string;
71
+ toolType: string;
72
+ entityType: string;
73
+ sections: CanvasSectionSnapshot[];
74
+ snapshot: Record<string, unknown>;
75
+ }
76
+ type DeploymentStrategy = 'DIRECT' | 'CANARY' | 'BLUE_GREEN' | 'ROLLING';
77
+ interface EnvironmentRef {
78
+ id: string;
79
+ name: string;
80
+ }
81
+ interface UserRef {
82
+ id: string;
83
+ email: string;
84
+ name: string | null;
85
+ }
86
+ interface ComponentRef {
87
+ id: string;
88
+ hostname: string;
89
+ port: string;
90
+ type: string[];
91
+ toolId: string;
92
+ }
93
+ interface CredentialRef {
94
+ id: string;
95
+ name: string;
96
+ username: string;
97
+ password: string;
98
+ apiToken: string | null;
99
+ certificate: string | null;
100
+ }
101
+ interface ConnectivityRef {
102
+ id: string;
103
+ status: string;
104
+ sshCommand: string | null;
105
+ httpsUrl: string | null;
106
+ tailscaleDeviceIP: string | null;
107
+ }
108
+ /** Provider-aware connectivity passed to handlers when a ConnectivityProvider is configured */
109
+ interface ConnectivityProviderRef {
110
+ id: string;
111
+ providerType: string;
112
+ name: string;
113
+ status: string;
114
+ config: Record<string, unknown>;
115
+ }
116
+ /** Summary of a deployment record, returned by PlatformDataApi */
117
+ interface DeploymentSummary {
118
+ id: string;
119
+ canvasId: string;
120
+ status: string;
121
+ healthScore: number | null;
122
+ startedAt: string;
123
+ completedAt: string | null;
124
+ environment: EnvironmentRef;
125
+ }
126
+ /**
127
+ * Tenant-scoped, read-only access to platform data, provided on every
128
+ * handler context as `ctx.platform`. Apps must use this instead of
129
+ * querying the platform database directly — it is the only supported
130
+ * way to read platform records from an app.
131
+ */
132
+ interface PlatformDataApi {
133
+ /** Latest deployment for a canvas, optionally filtered by status (e.g. 'SUCCEEDED'). */
134
+ getLatestDeployment(canvasId: string, opts?: {
135
+ status?: string;
136
+ }): Promise<DeploymentSummary | null>;
137
+ /** Components for the current customer, optionally filtered by component types. */
138
+ listComponents(filter?: {
139
+ types?: string[];
140
+ }): Promise<ComponentRef[]>;
141
+ }
142
+ interface PipelineContext {
143
+ appId: string;
144
+ customerId: string;
145
+ configTypeId: string;
146
+ canvas: CanvasSnapshot;
147
+ environment: EnvironmentRef;
148
+ user: UserRef;
149
+ settings: Record<string, unknown>;
150
+ platform: PlatformDataApi;
151
+ }
152
+ interface DeployContext extends PipelineContext {
153
+ component: ComponentRef;
154
+ credential: CredentialRef | null;
155
+ connectivity: ConnectivityRef | null;
156
+ connectivityProvider: ConnectivityProviderRef | null;
157
+ previousConfig: CanvasSnapshot | null;
158
+ strategy: DeploymentStrategy;
159
+ canaryPercent?: number;
160
+ }
161
+ interface RollbackContext extends PipelineContext {
162
+ component: ComponentRef;
163
+ credential: CredentialRef | null;
164
+ connectivity: ConnectivityRef | null;
165
+ connectivityProvider: ConnectivityProviderRef | null;
166
+ rollbackData: unknown;
167
+ targetVersion: CanvasSnapshot;
168
+ }
169
+ interface HealthCheckContext extends PipelineContext {
170
+ component: ComponentRef;
171
+ credential: CredentialRef | null;
172
+ connectivity: ConnectivityRef | null;
173
+ connectivityProvider: ConnectivityProviderRef | null;
174
+ }
175
+ interface DriftContext extends PipelineContext {
176
+ component: ComponentRef;
177
+ credential: CredentialRef | null;
178
+ connectivity: ConnectivityRef | null;
179
+ connectivityProvider: ConnectivityProviderRef | null;
180
+ deployedConfig: CanvasSnapshot;
181
+ }
182
+ type ValidateHandler = (ctx: PipelineContext) => Promise<ValidationResult>;
183
+ type DeployHandler = (ctx: DeployContext) => Promise<DeployResult>;
184
+ type RollbackHandler = (ctx: RollbackContext) => Promise<RollbackResult>;
185
+ type HealthCheckHandler = (ctx: HealthCheckContext) => Promise<HealthCheckResult>;
186
+ type DriftDetectHandler = (ctx: DriftContext) => Promise<DriftResult>;
187
+ type GetStatusHandler = (ctx: PipelineContext) => Promise<ConfigStatus>;
188
+
189
+ /**
190
+ * Define a validation handler for a configuration type.
191
+ *
192
+ * @example
193
+ * ```ts
194
+ * import { defineValidator } from '@veltrixsecops/app-sdk/pipeline'
195
+ *
196
+ * export default defineValidator(async (ctx) => {
197
+ * const errors = []
198
+ * const name = ctx.canvas.sections[0]?.fields['name']
199
+ * if (!name) {
200
+ * errors.push({ field: 'name', message: 'Name is required', code: 'REQUIRED' })
201
+ * }
202
+ * return { valid: errors.length === 0, errors, warnings: [] }
203
+ * })
204
+ * ```
205
+ */
206
+ declare function defineValidator(handler: (ctx: PipelineContext) => Promise<ValidationResult>): (ctx: PipelineContext) => Promise<ValidationResult>;
207
+
208
+ /**
209
+ * Define a deploy handler for a configuration type.
210
+ *
211
+ * @example
212
+ * ```ts
213
+ * import { defineDeployer } from '@veltrixsecops/app-sdk/pipeline'
214
+ *
215
+ * export default defineDeployer(async (ctx) => {
216
+ * const { component, credential, connectivity, canvas } = ctx
217
+ * // Push configuration to the tool
218
+ * return { success: true, message: 'Deployed', rollbackData: previousState }
219
+ * })
220
+ * ```
221
+ */
222
+ declare function defineDeployer(handler: (ctx: DeployContext) => Promise<DeployResult>): (ctx: DeployContext) => Promise<DeployResult>;
223
+
224
+ /**
225
+ * Define a rollback handler for a configuration type.
226
+ */
227
+ declare function defineRollbackHandler(handler: (ctx: RollbackContext) => Promise<RollbackResult>): (ctx: RollbackContext) => Promise<RollbackResult>;
228
+
229
+ /**
230
+ * Define a health check handler for a configuration type.
231
+ */
232
+ declare function defineHealthChecker(handler: (ctx: HealthCheckContext) => Promise<HealthCheckResult>): (ctx: HealthCheckContext) => Promise<HealthCheckResult>;
233
+
234
+ /**
235
+ * Define a drift detection handler for a configuration type.
236
+ */
237
+ declare function defineDriftDetector(handler: (ctx: DriftContext) => Promise<DriftResult>): (ctx: DriftContext) => Promise<DriftResult>;
238
+
239
+ export { defineHealthChecker as A, defineRollbackHandler as B, type CanvasSectionSnapshot as C, type DeployContext as D, type EnvironmentRef as E, defineValidator as F, type GetStatusHandler as G, type HealthCheck as H, type PipelineContext as P, type RollbackContext as R, type UserRef as U, type ValidateHandler as V, type CanvasSnapshot as a, type ComponentConfigStatus as b, type ComponentRef as c, type ConfigStatus as d, type ConnectivityProviderRef as e, type ConnectivityRef as f, type CredentialRef as g, type DeployHandler as h, type DeployResult as i, type DeploymentStrategy as j, type DeploymentSummary as k, type DriftContext as l, type DriftDetectHandler as m, type DriftDiff as n, type DriftResult as o, type HealthCheckContext as p, type HealthCheckHandler as q, type HealthCheckResult as r, type PlatformDataApi as s, type RollbackHandler as t, type RollbackResult as u, type ValidationError as v, type ValidationResult as w, type ValidationWarning as x, defineDeployer as y, defineDriftDetector as z };