@aifabrix/builder 2.8.0 → 2.9.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.
Files changed (36) hide show
  1. package/integration/hubspot/README.md +136 -0
  2. package/integration/hubspot/env.template +9 -0
  3. package/integration/hubspot/hubspot-deploy-company.json +200 -0
  4. package/integration/hubspot/hubspot-deploy-contact.json +228 -0
  5. package/integration/hubspot/hubspot-deploy-deal.json +248 -0
  6. package/integration/hubspot/hubspot-deploy.json +91 -0
  7. package/integration/hubspot/variables.yaml +17 -0
  8. package/lib/app-config.js +4 -3
  9. package/lib/app-deploy.js +8 -20
  10. package/lib/app-dockerfile.js +7 -9
  11. package/lib/app-prompts.js +6 -5
  12. package/lib/app-push.js +9 -9
  13. package/lib/app-register.js +23 -5
  14. package/lib/app-rotate-secret.js +10 -0
  15. package/lib/app-run.js +5 -11
  16. package/lib/app.js +42 -14
  17. package/lib/build.js +20 -16
  18. package/lib/cli.js +61 -2
  19. package/lib/datasource-deploy.js +14 -20
  20. package/lib/external-system-deploy.js +123 -40
  21. package/lib/external-system-download.js +431 -0
  22. package/lib/external-system-generator.js +13 -10
  23. package/lib/external-system-test.js +446 -0
  24. package/lib/generator-builders.js +323 -0
  25. package/lib/generator.js +200 -292
  26. package/lib/schema/application-schema.json +853 -852
  27. package/lib/schema/external-datasource.schema.json +823 -49
  28. package/lib/schema/external-system.schema.json +96 -78
  29. package/lib/templates.js +1 -1
  30. package/lib/utils/cli-utils.js +4 -4
  31. package/lib/utils/external-system-display.js +159 -0
  32. package/lib/utils/external-system-validators.js +245 -0
  33. package/lib/utils/paths.js +151 -1
  34. package/lib/utils/schema-resolver.js +7 -2
  35. package/lib/validator.js +5 -2
  36. package/package.json +1 -1
@@ -1,896 +1,897 @@
1
1
  {
2
- "$schema":"http://json-schema.org/draft-07/schema#",
3
- "$id":"https://raw.githubusercontent.com/esystemsdev/aifabrix-builder/refs/heads/main/lib/schema/application-schema.json",
4
- "title":"AI Fabrix Application Configuration Schema",
5
- "description":"Schema for AI Fabrix applications deployed via the API-Driven Deployment System",
6
- "metadata":{
7
- "key":"application-schema",
8
- "name":"Application Configuration Schema",
9
- "description":"JSON schema for validating AI Fabrix application configuration files",
10
- "version":"1.2.0",
11
- "type":"schema",
12
- "category":"infrastructure",
13
- "author":"AI Fabrix Team",
14
- "createdAt":"2024-01-01T00:00:00Z",
15
- "updatedAt":"2025-12-01T00:00:00Z",
16
- "compatibility":{
17
- "minVersion":"1.0.0",
18
- "maxVersion":"2.0.0",
19
- "deprecated":false
20
- },
21
- "tags":[
22
- "schema",
23
- "application",
24
- "validation",
25
- "configuration",
26
- "external-integration"
27
- ],
28
- "dependencies":[
29
- "external-system.schema.json",
30
- "external-datasource.schema.json"
31
- ],
32
- "changelog":[
33
- {
34
- "version":"1.2.0",
35
- "date":"2025-12-01T00:00:00Z",
36
- "changes":[
37
- "Added schema references to external-system.schema.json and external-datasource.schema.json",
38
- "Added optional inline system and dataSources properties using $ref for atomic deployment",
39
- "Replaces application-deployment.schema.json functionality",
40
- "Supports both file-based and inline external integration definitions"
41
- ],
42
- "breaking":false
43
- },
44
- {
45
- "version":"1.1.0",
46
- "date":"2025-11-26T00:00:00Z",
47
- "changes":[
48
- "Added externalIntegration block for ExternalSystem + ExternalDataSource pipeline deployments",
49
- "Added schemaBasePath, systems, dataSources and autopublish fields"
50
- ],
51
- "breaking":false
52
- }
53
- ]
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://raw.githubusercontent.com/esystemsdev/aifabrix-builder/refs/heads/main/lib/schema/application-schema.json",
4
+ "title": "AI Fabrix Application Configuration Schema",
5
+ "description": "Schema for AI Fabrix applications deployed via the API-Driven Deployment System",
6
+ "metadata": {
7
+ "key": "application-schema",
8
+ "name": "Application Configuration Schema",
9
+ "description": "JSON schema for validating AI Fabrix application configuration files",
10
+ "version": "1.2.0",
11
+ "type": "schema",
12
+ "category": "infrastructure",
13
+ "author": "AI Fabrix Team",
14
+ "createdAt": "2024-01-01T00:00:00Z",
15
+ "updatedAt": "2025-12-01T00:00:00Z",
16
+ "compatibility": {
17
+ "minVersion": "1.0.0",
18
+ "maxVersion": "2.0.0",
19
+ "deprecated": false
20
+ },
21
+ "tags": [
22
+ "schema",
23
+ "application",
24
+ "validation",
25
+ "configuration",
26
+ "external-integration"
27
+ ],
28
+ "dependencies": [
29
+ "external-system.schema.json",
30
+ "external-datasource.schema.json"
31
+ ],
32
+ "changelog": [
33
+ {
34
+ "version": "1.2.0",
35
+ "date": "2025-12-01T00:00:00Z",
36
+ "changes": [
37
+ "Added schema references to external-system.schema.json and external-datasource.schema.json",
38
+ "Added optional inline system and dataSources properties using $ref for atomic deployment",
39
+ "Replaces application-deployment.schema.json functionality",
40
+ "Supports both file-based and inline external integration definitions"
41
+ ],
42
+ "breaking": false
43
+ },
44
+ {
45
+ "version": "1.1.0",
46
+ "date": "2025-11-26T00:00:00Z",
47
+ "changes": [
48
+ "Added externalIntegration block for ExternalSystem + ExternalDataSource pipeline deployments",
49
+ "Added schemaBasePath, systems, dataSources and autopublish fields"
50
+ ],
51
+ "breaking": false
52
+ }
53
+ ]
54
54
  },
55
- "type":"object",
56
- "required":[
57
- "key",
58
- "displayName",
59
- "description",
60
- "type",
61
- "deploymentKey"
55
+ "type": "object",
56
+ "required": [
57
+ "key",
58
+ "displayName",
59
+ "description",
60
+ "type",
61
+ "deploymentKey"
62
62
  ],
63
- "properties":{
64
- "key":{
65
- "type":"string",
66
- "description":"Unique application identifier (cannot be changed after registration)",
67
- "pattern":"^[a-z0-9-]+$",
68
- "minLength":3,
69
- "maxLength":40
70
- },
71
- "displayName":{
72
- "type":"string",
73
- "description":"Human-readable application name",
74
- "minLength":1,
75
- "maxLength":100
76
- },
77
- "description":{
78
- "type":"string",
79
- "description":"Application description",
80
- "minLength":1,
81
- "maxLength":500
82
- },
83
- "type":{
84
- "type":"string",
85
- "description":"Azure application type",
86
- "enum":[
87
- "webapp",
88
- "functionapp",
89
- "api",
90
- "service",
91
- "external"
92
- ]
93
- },
94
- "image":{
95
- "type":"string",
96
- "description":"Container image reference",
97
- "pattern":"^[a-zA-Z0-9._/-]+:[a-zA-Z0-9._-]+$"
98
- },
99
- "registryMode":{
100
- "type":"string",
101
- "description":"Registry mode for image authentication",
102
- "enum":[
103
- "acr",
104
- "external",
105
- "public"
106
- ]
107
- },
108
- "port":{
109
- "type":"integer",
110
- "description":"Application port number",
111
- "minimum":1,
112
- "maximum":65535
113
- },
114
- "deploymentKey":{
115
- "type":"string",
116
- "description":"SHA256 hash of deployment manifest (excluding deploymentKey field)",
117
- "pattern":"^[a-f0-9]{64}$"
118
- },
119
- "requiresDatabase":{
120
- "type":"boolean",
121
- "description":"Whether application requires database"
122
- },
123
- "databases":{
124
- "type":"array",
125
- "description":"Database configurations",
126
- "items":{
127
- "type":"object",
128
- "required":[
129
- "name"
130
- ],
131
- "properties":{
132
- "name":{
133
- "type":"string",
134
- "description":"Database name",
135
- "pattern":"^[a-z0-9_-]+$"
136
- }
137
- },
138
- "additionalProperties":false
139
- }
140
- },
141
- "requiresRedis":{
142
- "type":"boolean",
143
- "description":"Whether application requires Redis"
144
- },
145
- "requiresStorage":{
146
- "type":"boolean",
147
- "description":"Whether application requires storage.Physical storage is mapped to /mnt/data/. Blob storage is mapped to SMB File share /data/{app-key}/."
148
- },
149
- "configuration":{
150
- "type":"array",
151
- "description":"Core application configuration",
152
- "items":{
153
- "type":"object",
154
- "required":[
155
- "name",
156
- "value",
157
- "location",
158
- "required"
159
- ],
160
- "properties":{
161
- "name":{
162
- "type":"string",
163
- "description":"Configuration variable name",
164
- "pattern":"^[A-Z_][A-Z0-9_]*$"
63
+ "properties": {
64
+ "key": {
65
+ "type": "string",
66
+ "description": "Unique application identifier (cannot be changed after registration)",
67
+ "pattern": "^[a-z0-9-]+$",
68
+ "minLength": 3,
69
+ "maxLength": 40
70
+ },
71
+ "displayName": {
72
+ "type": "string",
73
+ "description": "Human-readable application name",
74
+ "minLength": 1,
75
+ "maxLength": 100
76
+ },
77
+ "description": {
78
+ "type": "string",
79
+ "description": "Application description",
80
+ "minLength": 1,
81
+ "maxLength": 500
82
+ },
83
+ "type": {
84
+ "type": "string",
85
+ "description": "Azure application type",
86
+ "enum": [
87
+ "webapp",
88
+ "functionapp",
89
+ "api",
90
+ "service",
91
+ "external"
92
+ ]
93
+ },
94
+ "image": {
95
+ "type": "string",
96
+ "description": "Container image reference",
97
+ "pattern": "^[a-zA-Z0-9._/-]+:[a-zA-Z0-9._-]+$"
98
+ },
99
+ "registryMode": {
100
+ "type": "string",
101
+ "description": "Registry mode for image authentication",
102
+ "enum": [
103
+ "acr",
104
+ "external",
105
+ "public"
106
+ ]
107
+ },
108
+ "port": {
109
+ "type": "integer",
110
+ "description": "Application port number",
111
+ "minimum": 1,
112
+ "maximum": 65535
113
+ },
114
+ "deploymentKey": {
115
+ "type": "string",
116
+ "description": "SHA256 hash of deployment manifest (excluding deploymentKey field)",
117
+ "pattern": "^[a-f0-9]{64}$"
118
+ },
119
+ "requiresDatabase": {
120
+ "type": "boolean",
121
+ "description": "Whether application requires database"
122
+ },
123
+ "databases": {
124
+ "type": "array",
125
+ "description": "Database configurations",
126
+ "items": {
127
+ "type": "object",
128
+ "required": [
129
+ "name"
130
+ ],
131
+ "properties": {
132
+ "name": {
133
+ "type": "string",
134
+ "description": "Database name",
135
+ "pattern": "^[a-z0-9_-]+$"
136
+ }
137
+ },
138
+ "additionalProperties": false
139
+ }
140
+ },
141
+ "requiresRedis": {
142
+ "type": "boolean",
143
+ "description": "Whether application requires Redis"
144
+ },
145
+ "requiresStorage": {
146
+ "type": "boolean",
147
+ "description": "Whether application requires storage.Physical storage is mapped to /mnt/data/. Blob storage is mapped to SMB File share /data/{app-key}/."
148
+ },
149
+ "configuration": {
150
+ "type": "array",
151
+ "description": "Core application configuration",
152
+ "items": {
153
+ "type": "object",
154
+ "required": [
155
+ "name",
156
+ "value",
157
+ "location",
158
+ "required"
159
+ ],
160
+ "properties": {
161
+ "name": {
162
+ "type": "string",
163
+ "description": "Configuration variable name",
164
+ "pattern": "^[A-Z_][A-Z0-9_]*$"
165
+ },
166
+ "value": {
167
+ "type": "string",
168
+ "description": "Configuration value (literal or ready-made parameter reference)"
169
+ },
170
+ "location": {
171
+ "type": "string",
172
+ "description": "Where the value is stored",
173
+ "enum": [
174
+ "variable",
175
+ "keyvault"
176
+ ]
177
+ },
178
+ "required": {
179
+ "type": "boolean",
180
+ "description": "Whether this configuration is required"
181
+ },
182
+ "portalInput": {
183
+ "type": "object",
184
+ "description": "Portal input configuration for user-provided values",
185
+ "properties": {
186
+ "field": {
187
+ "type": "string",
188
+ "enum": [
189
+ "password",
190
+ "text",
191
+ "textarea",
192
+ "select"
193
+ ]
165
194
  },
166
- "value":{
167
- "type":"string",
168
- "description":"Configuration value (literal or ready-made parameter reference)"
195
+ "label": {
196
+ "type": "string",
197
+ "description": "Display label for the input field"
169
198
  },
170
- "location":{
171
- "type":"string",
172
- "description":"Where the value is stored",
173
- "enum":[
174
- "variable",
175
- "keyvault"
176
- ]
199
+ "placeholder": {
200
+ "type": "string",
201
+ "description": "Placeholder text for the input field"
202
+ },
203
+ "masked": {
204
+ "type": "boolean",
205
+ "description": "Whether to mask the input (for passwords)"
177
206
  },
178
- "required":{
179
- "type":"boolean",
180
- "description":"Whether this configuration is required"
207
+ "validation": {
208
+ "type": "object",
209
+ "properties": {
210
+ "minLength": {
211
+ "type": "integer",
212
+ "minimum": 1
213
+ },
214
+ "maxLength": {
215
+ "type": "integer",
216
+ "minimum": 1
217
+ },
218
+ "pattern": {
219
+ "type": "string",
220
+ "description": "Regex pattern for validation"
221
+ },
222
+ "required": {
223
+ "type": "boolean"
224
+ }
225
+ },
226
+ "additionalProperties": false
181
227
  },
182
- "portalInput":{
183
- "type":"object",
184
- "description":"Portal input configuration for user-provided values",
185
- "properties":{
186
- "field":{
187
- "type":"string",
188
- "enum":[
189
- "password",
190
- "text",
191
- "textarea",
192
- "select"
193
- ]
228
+ "options": {
229
+ "type": "array",
230
+ "description": "Options for select fields",
231
+ "items": {
232
+ "type": "string"
233
+ }
234
+ }
235
+ },
236
+ "required": [
237
+ "field",
238
+ "label"
239
+ ],
240
+ "additionalProperties": false
241
+ }
242
+ },
243
+ "additionalProperties": false
244
+ }
245
+ },
246
+ "conditionalConfiguration": {
247
+ "type": "array",
248
+ "description": "Conditional configuration based on service requirements",
249
+ "items": {
250
+ "type": "object",
251
+ "required": [
252
+ "condition",
253
+ "configuration"
254
+ ],
255
+ "properties": {
256
+ "condition": {
257
+ "type": "string",
258
+ "description": "Condition for including this configuration",
259
+ "pattern": "^\\{\\{.*\\}\\}$"
260
+ },
261
+ "configuration": {
262
+ "type": "array",
263
+ "description": "Configuration items to include when condition is true",
264
+ "items": {
265
+ "type": "object",
266
+ "required": [
267
+ "name",
268
+ "value",
269
+ "location",
270
+ "required"
271
+ ],
272
+ "properties": {
273
+ "name": {
274
+ "type": "string",
275
+ "description": "Configuration variable name",
276
+ "pattern": "^[A-Z_][A-Z0-9_]*$"
277
+ },
278
+ "value": {
279
+ "type": "string",
280
+ "description": "Configuration value (literal or ready-made parameter reference)"
281
+ },
282
+ "location": {
283
+ "type": "string",
284
+ "description": "Where the value is stored",
285
+ "enum": [
286
+ "variable",
287
+ "keyvault"
288
+ ]
289
+ },
290
+ "required": {
291
+ "type": "boolean",
292
+ "description": "Whether this configuration is required"
293
+ },
294
+ "portalInput": {
295
+ "type": "object",
296
+ "description": "Portal input configuration for user-provided values",
297
+ "properties": {
298
+ "field": {
299
+ "type": "string",
300
+ "enum": [
301
+ "password",
302
+ "text",
303
+ "textarea",
304
+ "select"
305
+ ]
194
306
  },
195
- "label":{
196
- "type":"string",
197
- "description":"Display label for the input field"
307
+ "label": {
308
+ "type": "string",
309
+ "description": "Display label for the input field"
198
310
  },
199
- "placeholder":{
200
- "type":"string",
201
- "description":"Placeholder text for the input field"
311
+ "placeholder": {
312
+ "type": "string",
313
+ "description": "Placeholder text for the input field"
202
314
  },
203
- "masked":{
204
- "type":"boolean",
205
- "description":"Whether to mask the input (for passwords)"
315
+ "masked": {
316
+ "type": "boolean",
317
+ "description": "Whether to mask the input (for passwords)"
206
318
  },
207
- "validation":{
208
- "type":"object",
209
- "properties":{
210
- "minLength":{
211
- "type":"integer",
212
- "minimum":1
213
- },
214
- "maxLength":{
215
- "type":"integer",
216
- "minimum":1
217
- },
218
- "pattern":{
219
- "type":"string",
220
- "description":"Regex pattern for validation"
221
- },
222
- "required":{
223
- "type":"boolean"
224
- }
225
- },
226
- "additionalProperties":false
319
+ "validation": {
320
+ "type": "object",
321
+ "properties": {
322
+ "minLength": {
323
+ "type": "integer",
324
+ "minimum": 1
325
+ },
326
+ "maxLength": {
327
+ "type": "integer",
328
+ "minimum": 1
329
+ },
330
+ "pattern": {
331
+ "type": "string",
332
+ "description": "Regex pattern for validation"
333
+ },
334
+ "required": {
335
+ "type": "boolean"
336
+ }
337
+ },
338
+ "additionalProperties": false
227
339
  },
228
- "options":{
229
- "type":"array",
230
- "description":"Options for select fields",
231
- "items":{
232
- "type":"string"
233
- }
340
+ "options": {
341
+ "type": "array",
342
+ "description": "Options for select fields",
343
+ "items": {
344
+ "type": "string"
345
+ }
234
346
  }
235
- },
236
- "required":[
347
+ },
348
+ "required": [
237
349
  "field",
238
350
  "label"
239
- ],
240
- "additionalProperties":false
241
- }
242
- },
243
- "additionalProperties":false
244
- }
245
- },
246
- "conditionalConfiguration":{
247
- "type":"array",
248
- "description":"Conditional configuration based on service requirements",
249
- "items":{
250
- "type":"object",
251
- "required":[
252
- "condition",
253
- "configuration"
254
- ],
255
- "properties":{
256
- "condition":{
257
- "type":"string",
258
- "description":"Condition for including this configuration",
259
- "pattern":"^\\{\\{.*\\}\\}$"
351
+ ],
352
+ "additionalProperties": false
353
+ }
260
354
  },
261
- "configuration":{
262
- "type":"array",
263
- "description":"Configuration items to include when condition is true",
264
- "items":{
265
- "type":"object",
266
- "required":[
267
- "name",
268
- "value",
269
- "location",
270
- "required"
271
- ],
272
- "properties":{
273
- "name":{
274
- "type":"string",
275
- "description":"Configuration variable name",
276
- "pattern":"^[A-Z_][A-Z0-9_]*$"
277
- },
278
- "value":{
279
- "type":"string",
280
- "description":"Configuration value (literal or ready-made parameter reference)"
281
- },
282
- "location":{
283
- "type":"string",
284
- "description":"Where the value is stored",
285
- "enum":[
286
- "variable",
287
- "keyvault"
288
- ]
289
- },
290
- "required":{
291
- "type":"boolean",
292
- "description":"Whether this configuration is required"
293
- },
294
- "portalInput":{
295
- "type":"object",
296
- "description":"Portal input configuration for user-provided values",
297
- "properties":{
298
- "field":{
299
- "type":"string",
300
- "enum":[
301
- "password",
302
- "text",
303
- "textarea",
304
- "select"
305
- ]
306
- },
307
- "label":{
308
- "type":"string",
309
- "description":"Display label for the input field"
310
- },
311
- "placeholder":{
312
- "type":"string",
313
- "description":"Placeholder text for the input field"
314
- },
315
- "masked":{
316
- "type":"boolean",
317
- "description":"Whether to mask the input (for passwords)"
318
- },
319
- "validation":{
320
- "type":"object",
321
- "properties":{
322
- "minLength":{
323
- "type":"integer",
324
- "minimum":1
325
- },
326
- "maxLength":{
327
- "type":"integer",
328
- "minimum":1
329
- },
330
- "pattern":{
331
- "type":"string",
332
- "description":"Regex pattern for validation"
333
- },
334
- "required":{
335
- "type":"boolean"
336
- }
337
- },
338
- "additionalProperties":false
339
- },
340
- "options":{
341
- "type":"array",
342
- "description":"Options for select fields",
343
- "items":{
344
- "type":"string"
345
- }
346
- }
347
- },
348
- "required":[
349
- "field",
350
- "label"
351
- ],
352
- "additionalProperties":false
353
- }
354
- },
355
- "additionalProperties":false
356
- }
357
- }
358
- },
359
- "additionalProperties":false
355
+ "additionalProperties": false
356
+ }
357
+ }
358
+ },
359
+ "additionalProperties": false
360
+ }
361
+ },
362
+ "healthCheck": {
363
+ "type": "object",
364
+ "description": "Health check configuration. The health check endpoint must return HTTP 200 and a JSON response with one of the following formats: {\"status\": \"UP\"} (Keycloak format), {\"status\": \"ok\"} (standard format, optionally with {\"database\": \"connected\"}), {\"status\": \"healthy\"} (alternative format), or {\"success\": true} (success-based format). For non-JSON responses, HTTP 200 status code is sufficient.",
365
+ "required": [
366
+ "path",
367
+ "interval"
368
+ ],
369
+ "properties": {
370
+ "path": {
371
+ "type": "string",
372
+ "description": "Health check endpoint path",
373
+ "pattern": "^/"
374
+ },
375
+ "interval": {
376
+ "type": "integer",
377
+ "description": "Health check interval in seconds",
378
+ "minimum": 10,
379
+ "maximum": 300
380
+ },
381
+ "probePath": {
382
+ "type": "string",
383
+ "description": "Front Door health probe path (defaults to path if not specified)",
384
+ "pattern": "^/"
385
+ },
386
+ "probeRequestType": {
387
+ "type": "string",
388
+ "description": "HTTP method for Front Door probe",
389
+ "enum": [
390
+ "GET",
391
+ "POST",
392
+ "HEAD",
393
+ "PUT",
394
+ "DELETE"
395
+ ]
396
+ },
397
+ "probeProtocol": {
398
+ "type": "string",
399
+ "description": "Protocol for Front Door probe",
400
+ "enum": [
401
+ "Http",
402
+ "Https"
403
+ ]
404
+ },
405
+ "probeIntervalInSeconds": {
406
+ "type": "integer",
407
+ "description": "Front Door probe interval in seconds (default 120)",
408
+ "minimum": 60,
409
+ "maximum": 600
360
410
  }
361
- },
362
- "healthCheck":{
363
- "type":"object",
364
- "description":"Health check configuration. The health check endpoint must return HTTP 200 and a JSON response with one of the following formats: {\"status\": \"UP\"} (Keycloak format), {\"status\": \"ok\"} (standard format, optionally with {\"database\": \"connected\"}), {\"status\": \"healthy\"} (alternative format), or {\"success\": true} (success-based format). For non-JSON responses, HTTP 200 status code is sufficient.",
365
- "required":[
366
- "path",
367
- "interval"
368
- ],
369
- "properties":{
370
- "path":{
371
- "type":"string",
372
- "description":"Health check endpoint path",
373
- "pattern":"^/"
374
- },
375
- "interval":{
376
- "type":"integer",
377
- "description":"Health check interval in seconds",
378
- "minimum":10,
379
- "maximum":300
380
- },
381
- "probePath":{
382
- "type":"string",
383
- "description":"Front Door health probe path (defaults to path if not specified)",
384
- "pattern":"^/"
385
- },
386
- "probeRequestType":{
387
- "type":"string",
388
- "description":"HTTP method for Front Door probe",
389
- "enum":[
390
- "GET",
391
- "POST",
392
- "HEAD",
393
- "PUT",
394
- "DELETE"
395
- ]
396
- },
397
- "probeProtocol":{
398
- "type":"string",
399
- "description":"Protocol for Front Door probe",
400
- "enum":[
401
- "Http",
402
- "Https"
403
- ]
404
- },
405
- "probeIntervalInSeconds":{
406
- "type":"integer",
407
- "description":"Front Door probe interval in seconds (default 120)",
408
- "minimum":60,
409
- "maximum":600
410
- }
411
+ },
412
+ "additionalProperties": false,
413
+ "examples": [
414
+ {
415
+ "path": "/health",
416
+ "interval": 30
411
417
  },
412
- "additionalProperties":false,
413
- "examples":[
414
- {
415
- "path":"/health",
416
- "interval":30
417
- },
418
- {
419
- "path":"/api/health",
420
- "interval":60,
421
- "probePath":"/api/health",
422
- "probeRequestType":"GET",
423
- "probeProtocol":"Http",
424
- "probeIntervalInSeconds":120
425
- }
426
- ],
427
- "responseFormats":{
428
- "description":"Valid health check response formats",
429
- "formats":[
430
- {
431
- "format":"Keycloak",
432
- "example":"{\"status\": \"UP\", \"checks\": []}",
433
- "validation":"status === 'UP'"
434
- },
435
- {
436
- "format":"Standard",
437
- "example":"{\"status\": \"ok\", \"database\": \"connected\"}",
438
- "validation":"status === 'ok' && (database === 'connected' || !database)"
439
- },
440
- {
441
- "format":"Alternative",
442
- "example":"{\"status\": \"healthy\", \"service\": \"dataplane\"}",
443
- "validation":"status === 'healthy'"
418
+ {
419
+ "path": "/api/health",
420
+ "interval": 60,
421
+ "probePath": "/api/health",
422
+ "probeRequestType": "GET",
423
+ "probeProtocol": "Http",
424
+ "probeIntervalInSeconds": 120
425
+ }
426
+ ],
427
+ "responseFormats": {
428
+ "description": "Valid health check response formats",
429
+ "formats": [
430
+ {
431
+ "format": "Keycloak",
432
+ "example": "{\"status\": \"UP\", \"checks\": []}",
433
+ "validation": "status === 'UP'"
434
+ },
435
+ {
436
+ "format": "Standard",
437
+ "example": "{\"status\": \"ok\", \"database\": \"connected\"}",
438
+ "validation": "status === 'ok' && (database === 'connected' || !database)"
439
+ },
440
+ {
441
+ "format": "Alternative",
442
+ "example": "{\"status\": \"healthy\", \"service\": \"dataplane\"}",
443
+ "validation": "status === 'healthy'"
444
+ },
445
+ {
446
+ "format": "Success-based",
447
+ "example": "{\"success\": true, \"message\": \"Service is running\"}",
448
+ "validation": "success === true"
449
+ },
450
+ {
451
+ "format": "Non-JSON",
452
+ "example": "OK",
453
+ "validation": "HTTP status code === 200"
454
+ }
455
+ ]
456
+ }
457
+ },
458
+ "frontDoorRouting": {
459
+ "type": "object",
460
+ "description": "Front Door routing configuration",
461
+ "properties": {
462
+ "pattern": {
463
+ "type": "string",
464
+ "description": "URL pattern for routing (e.g., '/app/*')",
465
+ "pattern": "^/.+"
466
+ },
467
+ "requiresRuleSet": {
468
+ "type": "boolean",
469
+ "description": "Whether URL rewriting rule set is required"
470
+ },
471
+ "ruleSetConditions": {
472
+ "type": "array",
473
+ "description": "Rule set conditions for URL rewriting",
474
+ "items": {
475
+ "type": "object",
476
+ "properties": {
477
+ "type": {
478
+ "type": "string",
479
+ "description": "Condition type (e.g., 'UrlPath')"
444
480
  },
445
- {
446
- "format":"Success-based",
447
- "example":"{\"success\": true, \"message\": \"Service is running\"}",
448
- "validation":"success === true"
481
+ "operator": {
482
+ "type": "string",
483
+ "description": "Condition operator (e.g., 'BeginsWith')"
449
484
  },
450
- {
451
- "format":"Non-JSON",
452
- "example":"OK",
453
- "validation":"HTTP status code === 200"
485
+ "matchValues": {
486
+ "type": "array",
487
+ "items": {
488
+ "type": "string"
489
+ }
454
490
  }
455
- ]
491
+ }
492
+ }
456
493
  }
457
- },
458
- "frontDoorRouting":{
459
- "type":"object",
460
- "description":"Front Door routing configuration",
461
- "properties":{
462
- "pattern":{
463
- "type":"string",
464
- "description":"URL pattern for routing (e.g., '/app/*')",
465
- "pattern":"^/.+"
466
- },
467
- "requiresRuleSet":{
468
- "type":"boolean",
469
- "description":"Whether URL rewriting rule set is required"
470
- },
471
- "ruleSetConditions":{
472
- "type":"array",
473
- "description":"Rule set conditions for URL rewriting",
474
- "items":{
475
- "type":"object",
476
- "properties":{
477
- "type":{
478
- "type":"string",
479
- "description":"Condition type (e.g., 'UrlPath')"
480
- },
481
- "operator":{
482
- "type":"string",
483
- "description":"Condition operator (e.g., 'BeginsWith')"
484
- },
485
- "matchValues":{
486
- "type":"array",
487
- "items":{
488
- "type":"string"
489
- }
490
- }
491
- }
492
- }
493
- }
494
+ },
495
+ "additionalProperties": false
496
+ },
497
+ "authentication": {
498
+ "type": "object",
499
+ "description": "Authentication configuration. When enableSSO is true, type and requiredRoles are required. When enableSSO is false, type and requiredRoles are optional.",
500
+ "required": [
501
+ "enableSSO"
502
+ ],
503
+ "properties": {
504
+ "type": {
505
+ "type": "string",
506
+ "description": "Authentication type",
507
+ "enum": [
508
+ "azure",
509
+ "local",
510
+ "none"
511
+ ]
494
512
  },
495
- "additionalProperties":false
496
- },
497
- "authentication":{
498
- "type":"object",
499
- "description":"Authentication configuration. When enableSSO is true, type and requiredRoles are required. When enableSSO is false, type and requiredRoles are optional.",
500
- "required":[
501
- "enableSSO"
502
- ],
503
- "properties":{
504
- "type":{
505
- "type":"string",
506
- "description":"Authentication type",
507
- "enum":[
508
- "azure",
509
- "local",
510
- "none"
511
- ]
512
- },
513
- "enableSSO":{
514
- "type":"boolean",
515
- "description":"Whether to enable SSO"
516
- },
517
- "requiredRoles":{
518
- "type":"array",
519
- "description":"Required roles for access",
520
- "items":{
521
- "type":"string",
522
- "pattern":"^[a-z-]+$"
523
- }
524
- },
525
- "endpoints":{
526
- "type":"object",
527
- "description":"Authentication endpoints",
528
- "properties":{
529
- "local":{
530
- "type":"string",
531
- "description":"Local authentication endpoint",
532
- "pattern":"^(http|https)://.*$"
533
- },
534
- "custom":{
535
- "type":"string",
536
- "description":"Custom authentication endpoint",
537
- "pattern":"^(http|https)://.*$"
538
- }
539
- },
540
- "additionalProperties":false
541
- }
513
+ "enableSSO": {
514
+ "type": "boolean",
515
+ "description": "Whether to enable SSO"
542
516
  },
543
- "if":{
544
- "properties":{
545
- "enableSSO":{
546
- "const":true
547
- }
548
- }
517
+ "requiredRoles": {
518
+ "type": "array",
519
+ "description": "Required roles for access",
520
+ "items": {
521
+ "type": "string",
522
+ "pattern": "^[a-z-]+$"
523
+ }
549
524
  },
550
- "then":{
551
- "required":[
552
- "type",
553
- "requiredRoles"
554
- ]
555
- },
556
- "additionalProperties":false
557
- },
558
- "roles":{
559
- "type":"array",
560
- "description":"Application roles for Azure AD group mapping",
561
- "items":{
562
- "type":"object",
563
- "required":[
564
- "name",
565
- "value",
566
- "description"
567
- ],
568
- "properties":{
569
- "name":{
570
- "type":"string",
571
- "description":"Human-readable role name",
572
- "minLength":1,
573
- "maxLength":100
574
- },
575
- "value":{
576
- "type":"string",
577
- "description":"Role identifier (used in JWT and ACL)",
578
- "pattern":"^[a-z-]+$"
579
- },
580
- "description":{
581
- "type":"string",
582
- "description":"Role description",
583
- "minLength":1,
584
- "maxLength":500
585
- },
586
- "Groups":{
587
- "type":"array",
588
- "description":"Azure AD groups mapped to this role",
589
- "items":{
590
- "type":"string",
591
- "minLength":1,
592
- "maxLength":100
593
- }
594
- }
595
- },
596
- "additionalProperties":false
525
+ "endpoints": {
526
+ "type": "object",
527
+ "description": "Authentication endpoints",
528
+ "properties": {
529
+ "local": {
530
+ "type": "string",
531
+ "description": "Local authentication endpoint",
532
+ "pattern": "^(http|https)://.*$"
533
+ },
534
+ "custom": {
535
+ "type": "string",
536
+ "description": "Custom authentication endpoint",
537
+ "pattern": "^(http|https)://.*$"
538
+ }
539
+ },
540
+ "additionalProperties": false
597
541
  }
598
- },
599
- "permissions":{
600
- "type":"array",
601
- "description":"Application permissions with role mappings for access control",
602
- "items":{
603
- "type":"object",
604
- "required":[
605
- "name",
606
- "roles",
607
- "description"
608
- ],
609
- "properties":{
610
- "name":{
611
- "type":"string",
612
- "description":"Permission identifier (e.g., 'documentstore:read', 'flowise:dev:access')",
613
- "pattern":"^[a-z0-9-:]+$",
614
- "minLength":1,
615
- "maxLength":100
616
- },
617
- "roles":{
618
- "type":"array",
619
- "description":"Roles that have this permission",
620
- "items":{
621
- "type":"string",
622
- "pattern":"^[a-z-]+$",
623
- "minLength":1,
624
- "maxLength":50
625
- },
626
- "minItems":1
627
- },
628
- "description":{
629
- "type":"string",
630
- "description":"Permission description",
631
- "minLength":1,
632
- "maxLength":500
633
- }
634
- },
635
- "additionalProperties":false
542
+ },
543
+ "if": {
544
+ "properties": {
545
+ "enableSSO": {
546
+ "const": true
547
+ }
636
548
  }
637
- },
638
- "repository":{
639
- "type":"object",
640
- "description":"Repository deployment configuration",
641
- "properties":{
642
- "enabled":{
643
- "type":"boolean",
644
- "description":"Whether repository deployment is enabled"
645
- },
646
- "repositoryUrl":{
647
- "type":"string",
648
- "description":"Full repository URL for pipeline validation (same as OAuth callback)",
649
- "pattern":"^(https://github.com/[^/]+/[^/]+|https://gitlab.com/[^/]+/[^/]+|https://dev.azure.com/[^/]+/[^/]+/[^/]+)$"
650
- }
549
+ },
550
+ "then": {
551
+ "required": [
552
+ "type",
553
+ "requiredRoles"
554
+ ]
555
+ },
556
+ "additionalProperties": false
557
+ },
558
+ "roles": {
559
+ "type": "array",
560
+ "description": "Application roles for Azure AD group mapping",
561
+ "items": {
562
+ "type": "object",
563
+ "required": [
564
+ "name",
565
+ "value",
566
+ "description"
567
+ ],
568
+ "properties": {
569
+ "name": {
570
+ "type": "string",
571
+ "description": "Human-readable role name",
572
+ "minLength": 1,
573
+ "maxLength": 100
574
+ },
575
+ "value": {
576
+ "type": "string",
577
+ "description": "Role identifier (used in JWT and ACL)",
578
+ "pattern": "^[a-z-]+$"
579
+ },
580
+ "description": {
581
+ "type": "string",
582
+ "description": "Role description",
583
+ "minLength": 1,
584
+ "maxLength": 500
585
+ },
586
+ "Groups": {
587
+ "type": "array",
588
+ "description": "Azure AD groups mapped to this role",
589
+ "items": {
590
+ "type": "string",
591
+ "minLength": 1,
592
+ "maxLength": 100
593
+ }
594
+ }
651
595
  },
652
- "required":[
653
- "enabled"
596
+ "additionalProperties": false
597
+ }
598
+ },
599
+ "permissions": {
600
+ "type": "array",
601
+ "description": "Application permissions with role mappings for access control",
602
+ "items": {
603
+ "type": "object",
604
+ "required": [
605
+ "name",
606
+ "roles",
607
+ "description"
654
608
  ],
655
- "additionalProperties":false
656
- },
657
- "startupCommand":{
658
- "type":"string",
659
- "description":"Application startup command (e.g., 'pnpm start', 'python app.py')",
660
- "minLength":1,
661
- "maxLength":200
662
- },
663
- "runtimeVersion":{
664
- "type":"object",
665
- "description":"Runtime version configuration",
666
- "properties":{
667
- "node":{
668
- "type":"string",
669
- "description":"Node.js version (e.g., '18.17.0')",
670
- "pattern":"^[0-9]+\\.[0-9]+\\.[0-9]+$"
671
- },
672
- "python":{
673
- "type":"string",
674
- "description":"Python version (e.g., '3.11')",
675
- "pattern":"^[0-9]+\\.[0-9]+$"
676
- },
677
- "dotnet":{
678
- "type":"string",
679
- "description":".NET version (e.g., '8.0')",
680
- "pattern":"^[0-9]+\\.[0-9]+$"
681
- }
609
+ "properties": {
610
+ "name": {
611
+ "type": "string",
612
+ "description": "Permission identifier (e.g., 'documentstore:read', 'flowise:dev:access')",
613
+ "pattern": "^[a-z0-9-:]+$",
614
+ "minLength": 1,
615
+ "maxLength": 100
616
+ },
617
+ "roles": {
618
+ "type": "array",
619
+ "description": "Roles that have this permission",
620
+ "items": {
621
+ "type": "string",
622
+ "pattern": "^[a-z-]+$",
623
+ "minLength": 1,
624
+ "maxLength": 50
625
+ },
626
+ "minItems": 1
627
+ },
628
+ "description": {
629
+ "type": "string",
630
+ "description": "Permission description",
631
+ "minLength": 1,
632
+ "maxLength": 500
633
+ }
682
634
  },
683
- "additionalProperties":false
684
- },
685
- "scaling":{
686
- "type":"object",
687
- "description":"Application scaling configuration",
688
- "properties":{
689
- "minInstances":{
690
- "type":"integer",
691
- "description":"Minimum number of instances",
692
- "minimum":1,
693
- "maximum":20
694
- },
695
- "maxInstances":{
696
- "type":"integer",
697
- "description":"Maximum number of instances",
698
- "minimum":1,
699
- "maximum":20
700
- },
701
- "cpuThreshold":{
702
- "type":"number",
703
- "description":"CPU threshold for scaling (percentage)",
704
- "minimum":10,
705
- "maximum":90
706
- }
635
+ "additionalProperties": false
636
+ }
637
+ },
638
+ "repository": {
639
+ "type": "object",
640
+ "description": "Repository deployment configuration",
641
+ "properties": {
642
+ "enabled": {
643
+ "type": "boolean",
644
+ "description": "Whether repository deployment is enabled"
707
645
  },
708
- "additionalProperties":false
709
- },
710
- "build":{
711
- "type":"object",
712
- "description":"Build and local development configuration",
713
- "properties":{
714
- "envOutputPath":{
715
- "type":"string",
716
- "description":"Path where .env file is copied for local development (relative to builder/)",
717
- "pattern":"^[^/].*"
718
- },
719
- "localPort":{
720
- "type":"integer",
721
- "description":"Port for local development (different from Docker port)",
722
- "minimum":1000,
723
- "maximum":65535
724
- },
725
- "containerPort":{
726
- "type":"integer",
727
- "description":"Container internal port (defaults to port if not specified)",
728
- "minimum":1,
729
- "maximum":65535
730
- },
731
- "language":{
732
- "type":"string",
733
- "description":"Runtime language for template selection",
734
- "enum":[
735
- "typescript",
736
- "python"
737
- ]
738
- },
739
- "context":{
740
- "type":"string",
741
- "description":"Docker build context path (relative to builder/)",
742
- "pattern":"^[^/].*"
743
- },
744
- "dockerfile":{
745
- "type":"string",
746
- "description":"Dockerfile name (empty or missing = use auto-generated template)",
747
- "pattern":"^[^/].*"
748
- }
646
+ "repositoryUrl": {
647
+ "type": "string",
648
+ "description": "Full repository URL for pipeline validation (same as OAuth callback)",
649
+ "pattern": "^(https://github.com/[^/]+/[^/]+|https://gitlab.com/[^/]+/[^/]+|https://dev.azure.com/[^/]+/[^/]+/[^/]+)$"
650
+ }
651
+ },
652
+ "required": [
653
+ "enabled"
654
+ ],
655
+ "additionalProperties": false
656
+ },
657
+ "startupCommand": {
658
+ "type": "string",
659
+ "description": "Application startup command (e.g., 'pnpm start', 'python app.py')",
660
+ "minLength": 1,
661
+ "maxLength": 200
662
+ },
663
+ "runtimeVersion": {
664
+ "type": "object",
665
+ "description": "Runtime version configuration",
666
+ "properties": {
667
+ "node": {
668
+ "type": "string",
669
+ "description": "Node.js version (e.g., '18.17.0')",
670
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
749
671
  },
750
- "additionalProperties":false
751
- },
752
- "deployment":{
753
- "type":"object",
754
- "description":"Deployment configuration for pipeline API",
755
- "properties":{
756
- "controllerUrl":{
757
- "type":"string",
758
- "description":"Controller API URL for deployment",
759
- "pattern":"^https://.*$"
760
- }
672
+ "python": {
673
+ "type": "string",
674
+ "description": "Python version (e.g., '3.11')",
675
+ "pattern": "^[0-9]+\\.[0-9]+$"
761
676
  },
762
- "additionalProperties":false
763
- },
764
- "system":{
765
- "type":"object",
766
- "description":"Optional: Inline external system configuration for atomic deployment. Uses external-system.schema.json structure via $ref. Alternative to externalIntegration.systems file-based approach.",
767
- "$ref":"https://raw.githubusercontent.com/esystemsdev/aifabrix-builder/refs/heads/main/lib/schema/external-system.schema.json"
768
- },
769
- "dataSources":{
770
- "type":"array",
771
- "description":"Optional: Inline external data source configurations for atomic deployment. Uses external-datasource.schema.json structure via $ref. Alternative to externalIntegration.dataSources file-based approach.",
772
- "minItems":0,
773
- "items":{
774
- "$ref":"https://raw.githubusercontent.com/esystemsdev/aifabrix-builder/refs/heads/main/lib/schema/external-datasource.schema.json"
677
+ "dotnet": {
678
+ "type": "string",
679
+ "description": ".NET version (e.g., '8.0')",
680
+ "pattern": "^[0-9]+\\.[0-9]+$"
775
681
  }
776
- },
777
- "externalIntegration":{
778
- "type":"object",
779
- "description":"Defines External Systems & External Data Sources shipped with this application. Pipeline registers these in Miso-Controller and publishes schemas to Dataplane. Supports both file-based references and inline definitions.",
780
- "required":[
781
- "schemaBasePath"
782
- ],
783
- "properties":{
784
- "schemaBasePath":{
785
- "type":"string",
786
- "description":"Base folder path containing external-system.json and external-datasource.json files (used when systems/dataSources are file references).",
787
- "pattern":"^[^ ].*$"
788
- },
789
- "systems":{
790
- "type":"array",
791
- "description":"List of external-system JSON files to deploy via pipeline.",
792
- "items":{
793
- "type":"string",
794
- "pattern":"^[^ ].+\\.json$"
795
- },
796
- "uniqueItems":true
797
- },
798
- "dataSources":{
799
- "type":"array",
800
- "description":"List of external-datasource JSON files belonging to this app.",
801
- "items":{
802
- "type":"string",
803
- "pattern":"^[^ ].+\\.json$"
804
- },
805
- "uniqueItems":true
806
- },
807
- "autopublish":{
808
- "type":"boolean",
809
- "default":true,
810
- "description":"If true, pipeline automatically publishes ExternalSystems + ExternalDataSources to Dataplane after deployment."
811
- },
812
- "version":{
813
- "type":"string",
814
- "description":"Version of the integration set (used for schema diffing & migrations).",
815
- "pattern":"^[0-9]+\\.[0-9]+\\.[0-9]+$"
816
- }
682
+ },
683
+ "additionalProperties": false
684
+ },
685
+ "scaling": {
686
+ "type": "object",
687
+ "description": "Application scaling configuration",
688
+ "properties": {
689
+ "minInstances": {
690
+ "type": "integer",
691
+ "description": "Minimum number of instances",
692
+ "minimum": 1,
693
+ "maximum": 20
817
694
  },
818
- "additionalProperties":false
819
- }
820
- },
821
- "additionalProperties":false,
822
- "allOf":[
823
- {
824
- "if":{
825
- "properties":{
826
- "type":{
827
- "const":"external"
828
- }
829
- }
695
+ "maxInstances": {
696
+ "type": "integer",
697
+ "description": "Maximum number of instances",
698
+ "minimum": 1,
699
+ "maximum": 20
830
700
  },
831
- "then":{
832
- "required":[
833
- "externalIntegration"
834
- ]
701
+ "cpuThreshold": {
702
+ "type": "number",
703
+ "description": "CPU threshold for scaling (percentage)",
704
+ "minimum": 10,
705
+ "maximum": 90
835
706
  }
836
- },
837
- {
838
- "if":{
839
- "properties":{
840
- "type":{
841
- "not":{
842
- "const":"external"
843
- }
844
- }
845
- }
707
+ },
708
+ "additionalProperties": false
709
+ },
710
+ "build": {
711
+ "type": "object",
712
+ "description": "Build and local development configuration",
713
+ "properties": {
714
+ "envOutputPath": {
715
+ "type": "string",
716
+ "description": "Path where .env file is copied for local development (relative to builder/)",
717
+ "pattern": "^[^/].*"
846
718
  },
847
- "then":{
848
- "required":[
849
- "image",
850
- "registryMode",
851
- "port"
852
- ]
853
- }
854
- },
855
- {
856
- "if":{
857
- "properties":{
858
- "requiresDatabase":{
859
- "const":true
860
- }
861
- }
719
+ "localPort": {
720
+ "type": "integer",
721
+ "description": "Port for local development (different from Docker port)",
722
+ "minimum": 1000,
723
+ "maximum": 65535
724
+ },
725
+ "containerPort": {
726
+ "type": "integer",
727
+ "description": "Container internal port (defaults to port if not specified)",
728
+ "minimum": 1,
729
+ "maximum": 65535
730
+ },
731
+ "language": {
732
+ "type": "string",
733
+ "description": "Runtime language for template selection",
734
+ "enum": [
735
+ "typescript",
736
+ "python"
737
+ ]
738
+ },
739
+ "context": {
740
+ "type": "string",
741
+ "description": "Docker build context path (relative to builder/)",
742
+ "pattern": "^[^/].*"
862
743
  },
863
- "then":{
864
- "required":[
865
- "databases"
866
- ]
744
+ "dockerfile": {
745
+ "type": "string",
746
+ "description": "Dockerfile name (empty or missing = use auto-generated template)",
747
+ "pattern": "^[^/].*"
867
748
  }
868
- },
869
- {
870
- "if":{
871
- "properties":{
872
- "registryMode":{
873
- "const":"external"
874
- }
875
- }
749
+ },
750
+ "additionalProperties": false
751
+ },
752
+ "deployment": {
753
+ "type": "object",
754
+ "description": "Deployment configuration for pipeline API",
755
+ "properties": {
756
+ "controllerUrl": {
757
+ "type": "string",
758
+ "description": "Controller API URL for deployment",
759
+ "pattern": "^https://.*$"
760
+ }
761
+ },
762
+ "additionalProperties": false
763
+ },
764
+ "system": {
765
+ "type": "object",
766
+ "description": "Optional: Inline external system configuration for atomic deployment. Uses external-system.schema.json structure via $ref. Alternative to externalIntegration.systems file-based approach.",
767
+ "$ref": "https://raw.githubusercontent.com/esystemsdev/aifabrix-builder/refs/heads/main/lib/schema/external-system.schema.json"
768
+ },
769
+ "dataSources": {
770
+ "type": "array",
771
+ "description": "Optional: Inline external data source configurations for atomic deployment. Uses external-datasource.schema.json structure via $ref. Alternative to externalIntegration.dataSources file-based approach.",
772
+ "minItems": 0,
773
+ "items": {
774
+ "$ref": "https://raw.githubusercontent.com/esystemsdev/aifabrix-builder/refs/heads/main/lib/schema/external-datasource.schema.json"
775
+ }
776
+ },
777
+ "externalIntegration": {
778
+ "type": "object",
779
+ "description": "Defines External Systems & External Data Sources shipped with this application. Pipeline registers these in Miso-Controller and publishes schemas to Dataplane. Supports both file-based references and inline definitions.",
780
+ "required": [
781
+ "schemaBasePath"
782
+ ],
783
+ "properties": {
784
+ "schemaBasePath": {
785
+ "type": "string",
786
+ "description": "Base folder path containing external-system.json and external-datasource.json files (used when systems/dataSources are file references).",
787
+ "pattern": "^[^ ].*$"
876
788
  },
877
- "then":{
878
- "properties":{
879
- "configuration":{
880
- "items":{
881
- "properties":{
882
- "name":{
883
- "enum":[
884
- "DOCKER_REGISTRY_SERVER_URL",
885
- "DOCKER_REGISTRY_SERVER_USERNAME",
886
- "DOCKER_REGISTRY_SERVER_PASSWORD"
887
- ]
888
- }
889
- }
890
- }
789
+ "systems": {
790
+ "type": "array",
791
+ "description": "List of external-system JSON files to deploy via pipeline.",
792
+ "items": {
793
+ "type": "string",
794
+ "pattern": "^[^ ].+\\.json$"
795
+ },
796
+ "uniqueItems": true
797
+ },
798
+ "dataSources": {
799
+ "type": "array",
800
+ "description": "List of external-datasource JSON files belonging to this app.",
801
+ "items": {
802
+ "type": "string",
803
+ "pattern": "^[^ ].+\\.json$"
804
+ },
805
+ "uniqueItems": true
806
+ },
807
+ "autopublish": {
808
+ "type": "boolean",
809
+ "default": true,
810
+ "description": "If true, pipeline automatically publishes ExternalSystems + ExternalDataSources to Dataplane after deployment."
811
+ },
812
+ "version": {
813
+ "type": "string",
814
+ "description": "Version of the integration set (used for schema diffing & migrations).",
815
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
816
+ }
817
+ },
818
+ "additionalProperties": false
819
+ }
820
+ },
821
+ "additionalProperties": false,
822
+ "allOf": [
823
+ {
824
+ "if": {
825
+ "properties": {
826
+ "type": {
827
+ "const": "external"
828
+ }
829
+ }
830
+ },
831
+ "then": {
832
+ "required": [
833
+ "externalIntegration"
834
+ ]
835
+ }
836
+ },
837
+ {
838
+ "if": {
839
+ "properties": {
840
+ "type": {
841
+ "not": {
842
+ "const": "external"
843
+ }
844
+ }
845
+ }
846
+ },
847
+ "then": {
848
+ "required": [
849
+ "image",
850
+ "registryMode",
851
+ "port"
852
+ ]
853
+ }
854
+ },
855
+ {
856
+ "if": {
857
+ "properties": {
858
+ "requiresDatabase": {
859
+ "const": true
860
+ }
861
+ }
862
+ },
863
+ "then": {
864
+ "required": [
865
+ "databases"
866
+ ]
867
+ }
868
+ },
869
+ {
870
+ "if": {
871
+ "properties": {
872
+ "registryMode": {
873
+ "const": "external"
874
+ }
875
+ }
876
+ },
877
+ "then": {
878
+ "properties": {
879
+ "configuration": {
880
+ "items": {
881
+ "properties": {
882
+ "name": {
883
+ "enum": [
884
+ "DOCKER_REGISTRY_SERVER_URL",
885
+ "DOCKER_REGISTRY_SERVER_USERNAME",
886
+ "DOCKER_REGISTRY_SERVER_PASSWORD"
887
+ ]
888
+ }
891
889
  }
892
- }
890
+ }
891
+ }
893
892
  }
894
- }
893
+ }
894
+ }
895
895
  ]
896
- }
896
+ }
897
+