@aifabrix/builder 2.9.0 → 2.10.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.
@@ -359,7 +359,13 @@ async function handleDeviceCodeLogin(controllerUrl, environment, offline, scope)
359
359
  );
360
360
 
361
361
  } catch (deviceError) {
362
- logger.error(chalk.red(`\n❌ Device code flow failed: ${deviceError.message}`));
362
+ // Display formatted error if available (includes detailed validation info)
363
+ if (deviceError.formattedError) {
364
+ logger.error(chalk.red('\n❌ Device code flow failed:'));
365
+ logger.log(deviceError.formattedError);
366
+ } else {
367
+ logger.error(chalk.red(`\n❌ Device code flow failed: ${deviceError.message}`));
368
+ }
363
369
  process.exit(1);
364
370
  }
365
371
  }
@@ -11,6 +11,10 @@ environments:
11
11
  MISO_PORT: 3000
12
12
  KEYCLOAK_HOST: keycloak
13
13
  KEYCLOAK_PORT: 8082
14
+ NODE_ENV: production
15
+ PYTHONUNBUFFERED: 1
16
+ PYTHONDONTWRITEBYTECODE: 1
17
+ PYTHONIOENCODING: utf-8
14
18
 
15
19
  local:
16
20
  DB_HOST: localhost
@@ -20,4 +24,8 @@ environments:
20
24
  MISO_HOST: localhost
21
25
  MISO_PORT: 3010
22
26
  KEYCLOAK_HOST: localhost
23
- KEYCLOAK_PORT: 8082
27
+ KEYCLOAK_PORT: 8082
28
+ NODE_ENV: development
29
+ PYTHONUNBUFFERED: 1
30
+ PYTHONDONTWRITEBYTECODE: 1
31
+ PYTHONIOENCODING: utf-8
package/lib/templates.js CHANGED
@@ -134,13 +134,31 @@ function generateVariablesYaml(appName, config) {
134
134
  */
135
135
  function buildCoreEnv(config) {
136
136
  return {
137
- 'NODE_ENV': 'development',
137
+ 'NODE_ENV': '${NODE_ENV}',
138
138
  'PORT': config.port || 3000,
139
139
  'APP_NAME': config.appName || 'myapp',
140
140
  'LOG_LEVEL': 'info'
141
141
  };
142
142
  }
143
143
 
144
+ /**
145
+ * Builds Python-specific environment variables
146
+ * @param {Object} config - Configuration options
147
+ * @returns {Object} Python environment variables
148
+ */
149
+ function buildPythonEnv(config) {
150
+ const language = config.language || 'typescript';
151
+ if (language !== 'python') {
152
+ return {};
153
+ }
154
+
155
+ return {
156
+ 'PYTHONUNBUFFERED': '${PYTHONUNBUFFERED}',
157
+ 'PYTHONDONTWRITEBYTECODE': '${PYTHONDONTWRITEBYTECODE}',
158
+ 'PYTHONIOENCODING': '${PYTHONIOENCODING}'
159
+ };
160
+ }
161
+
144
162
  function buildDatabaseEnv(config) {
145
163
  if (!config.database) {
146
164
  return {};
@@ -207,8 +225,9 @@ function buildMonitoringEnv(config) {
207
225
  return {
208
226
  'MISO_CONTROLLER_URL': config.controllerUrl || 'https://controller.aifabrix.ai',
209
227
  'MISO_ENVIRONMENT': 'dev',
210
- 'MISO_CLIENTID': 'kv://miso-clientid',
211
- 'MISO_CLIENTSECRET': 'kv://miso-clientsecret'
228
+ 'MISO_CLIENTID': 'kv://miso-controller-client-idKeyVault',
229
+ 'MISO_CLIENTSECRET': 'kv://miso-controller-client-secretKeyVault',
230
+ 'MISO_WEB_SERVER_URL': 'kv://miso-controller-web-server-url'
212
231
  };
213
232
  }
214
233
 
@@ -220,10 +239,17 @@ function buildMonitoringEnv(config) {
220
239
  function addCoreVariables(lines, envVars) {
221
240
  Object.entries(envVars).forEach(([key, value]) => {
222
241
  if (key.startsWith('NODE_ENV') || key.startsWith('PORT') ||
223
- key.startsWith('APP_NAME') || key.startsWith('LOG_LEVEL')) {
242
+ key.startsWith('APP_NAME') || key.startsWith('LOG_LEVEL') ||
243
+ key.startsWith('PYTHON')) {
224
244
  lines.push(`${key}=${value}`);
225
245
  }
226
246
  });
247
+
248
+ // Add ALLOWED_ORIGINS and WEB_SERVER_URL after PORT variable
249
+ // ALLOWED_ORIGINS: My application public address
250
+ lines.push('ALLOWED_ORIGINS=http://localhost:*,');
251
+ // WEB_SERVER_URL: Miso public address (uses ${PORT} template variable)
252
+ lines.push('WEB_SERVER_URL=http://localhost:${PORT},');
227
253
  }
228
254
 
229
255
  function addMonitoringSection(lines, envVars) {
@@ -232,6 +258,10 @@ function addMonitoringSection(lines, envVars) {
232
258
  lines.push(`MISO_ENVIRONMENT=${envVars['MISO_ENVIRONMENT']}`);
233
259
  lines.push(`MISO_CLIENTID=${envVars['MISO_CLIENTID']}`);
234
260
  lines.push(`MISO_CLIENTSECRET=${envVars['MISO_CLIENTSECRET']}`);
261
+ // MISO_WEB_SERVER_URL: Miso public address
262
+ if (envVars['MISO_WEB_SERVER_URL']) {
263
+ lines.push(`MISO_WEB_SERVER_URL=${envVars['MISO_WEB_SERVER_URL']}`);
264
+ }
235
265
  }
236
266
 
237
267
  function addDatabaseSection(lines, envVars) {
@@ -316,6 +346,7 @@ function addAuthenticationSection(lines, envVars) {
316
346
  function generateEnvTemplate(config, existingEnv = {}) {
317
347
  const envVars = {
318
348
  ...buildCoreEnv(config),
349
+ ...buildPythonEnv(config),
319
350
  ...buildDatabaseEnv(config),
320
351
  ...buildRedisEnv(config),
321
352
  ...buildStorageEnv(config),
@@ -73,13 +73,11 @@ function formatPermissionError(errorData) {
73
73
 
74
74
  const requiredPerms = extractRequiredPermissions(errorData);
75
75
  addPermissionList(lines, requiredPerms, 'Required permissions');
76
-
77
76
  const requestUrl = errorData.instance || errorData.url;
78
77
  const method = errorData.method || 'POST';
79
78
  if (requestUrl) {
80
79
  lines.push(chalk.gray(`Request: ${method} ${requestUrl}`));
81
80
  }
82
-
83
81
  if (errorData.correlationId) {
84
82
  lines.push(chalk.gray(`Correlation ID: ${errorData.correlationId}`));
85
83
  }
@@ -97,18 +95,27 @@ function formatValidationError(errorData) {
97
95
  lines.push(chalk.red('❌ Validation Error\n'));
98
96
 
99
97
  // Handle RFC 7807 Problem Details format
100
- // Priority: detail > title > message
98
+ // Priority: detail > title > errorDescription > message > error
101
99
  if (errorData.detail) {
102
100
  lines.push(chalk.yellow(errorData.detail));
103
101
  lines.push('');
104
102
  } else if (errorData.title) {
105
103
  lines.push(chalk.yellow(errorData.title));
106
104
  lines.push('');
105
+ } else if (errorData.errorDescription) {
106
+ // Handle Keycloak-style error format
107
+ lines.push(chalk.yellow(errorData.errorDescription));
108
+ if (errorData.error) {
109
+ lines.push(chalk.gray(`Error code: ${errorData.error}`));
110
+ }
111
+ lines.push('');
107
112
  } else if (errorData.message) {
108
113
  lines.push(chalk.yellow(errorData.message));
109
114
  lines.push('');
115
+ } else if (errorData.error) {
116
+ lines.push(chalk.yellow(errorData.error));
117
+ lines.push('');
110
118
  }
111
-
112
119
  // Handle errors array - this is the most important part
113
120
  if (errorData.errors && Array.isArray(errorData.errors) && errorData.errors.length > 0) {
114
121
  lines.push(chalk.yellow('Validation errors:'));
@@ -124,17 +131,14 @@ function formatValidationError(errorData) {
124
131
  });
125
132
  lines.push('');
126
133
  }
127
-
128
134
  // Show instance (endpoint) if available (RFC 7807)
129
135
  if (errorData.instance) {
130
136
  lines.push(chalk.gray(`Endpoint: ${errorData.instance}`));
131
137
  }
132
-
133
138
  // Show correlation ID if available
134
139
  if (errorData.correlationId) {
135
140
  lines.push(chalk.gray(`Correlation ID: ${errorData.correlationId}`));
136
141
  }
137
-
138
142
  return lines.join('\n');
139
143
  }
140
144
  /**
@@ -145,7 +149,6 @@ function formatValidationError(errorData) {
145
149
  function formatAuthenticationError(errorData) {
146
150
  const lines = [];
147
151
  lines.push(chalk.red('❌ Authentication Failed\n'));
148
-
149
152
  if (errorData.message) {
150
153
  lines.push(chalk.yellow(errorData.message));
151
154
  } else {
@@ -153,11 +156,9 @@ function formatAuthenticationError(errorData) {
153
156
  }
154
157
  lines.push('');
155
158
  lines.push(chalk.gray('Run: aifabrix login'));
156
-
157
159
  if (errorData.correlationId) {
158
160
  lines.push(chalk.gray(`Correlation ID: ${errorData.correlationId}`));
159
161
  }
160
-
161
162
  return lines.join('\n');
162
163
  }
163
164
  /**
@@ -379,7 +380,7 @@ function createErrorResult(type, message, formatted, data) {
379
380
  * @returns {string} Error message
380
381
  */
381
382
  function getErrorMessage(errorData, defaultMessage) {
382
- return errorData.detail || errorData.title || errorData.message || defaultMessage;
383
+ return errorData.detail || errorData.title || errorData.errorDescription || errorData.message || errorData.error || defaultMessage;
383
384
  }
384
385
 
385
386
  /**
@@ -486,7 +487,6 @@ function formatApiError(apiResponse) {
486
487
  const parsed = parseErrorResponse(errorResponse, statusCode, isNetworkError);
487
488
  return parsed.formatted;
488
489
  }
489
-
490
490
  module.exports = {
491
491
  parseErrorResponse,
492
492
  formatApiError,
@@ -140,15 +140,61 @@ function parseTokenResponse(response) {
140
140
  };
141
141
  }
142
142
 
143
+ /**
144
+ * Creates a validation error with detailed information
145
+ * @function createValidationError
146
+ * @param {Object} response - Full API response object
147
+ * @returns {Error} Validation error with formattedError and errorData attached
148
+ */
149
+ function createValidationError(response) {
150
+ const validationError = new Error('Token polling failed: Validation error');
151
+
152
+ // Attach formatted error if available (includes detailed validation info with ANSI colors)
153
+ if (response && response.formattedError) {
154
+ validationError.formattedError = response.formattedError;
155
+ validationError.message = `Token polling failed:\n${response.formattedError}`;
156
+ }
157
+
158
+ // Attach error data for programmatic access
159
+ if (response && response.errorData) {
160
+ validationError.errorData = response.errorData;
161
+ validationError.errorType = response.errorType || 'validation';
162
+
163
+ // Build detailed message if formattedError not available
164
+ if (!validationError.formattedError) {
165
+ const errorData = response.errorData;
166
+ const detail = errorData.detail || errorData.title || errorData.message || 'Validation error';
167
+ let errorMsg = `Token polling failed: ${detail}`;
168
+ // Add validation errors if available
169
+ if (errorData.errors && Array.isArray(errorData.errors) && errorData.errors.length > 0) {
170
+ errorMsg += '\n\nValidation errors:';
171
+ errorData.errors.forEach(err => {
172
+ const field = err.field || err.path || 'validation';
173
+ const message = err.message || 'Invalid value';
174
+ if (field === 'validation' || field === 'unknown') {
175
+ errorMsg += `\n • ${message}`;
176
+ } else {
177
+ errorMsg += `\n • ${field}: ${message}`;
178
+ }
179
+ });
180
+ }
181
+ validationError.message = errorMsg;
182
+ }
183
+ }
184
+
185
+ return validationError;
186
+ }
187
+
143
188
  /**
144
189
  * Handles polling errors
145
190
  * @function handlePollingErrors
146
191
  * @param {string} error - Error code
147
192
  * @param {number} status - HTTP status code
193
+ * @param {Object} response - Full API response object (for accessing formattedError and errorData)
148
194
  * @throws {Error} For fatal errors
149
195
  * @returns {boolean} True if should continue polling
150
196
  */
151
- function handlePollingErrors(error, status) {
197
+ function handlePollingErrors(error, status, response) {
152
198
  if (error === 'authorization_pending' || status === 202) {
153
199
  return true;
154
200
  }
@@ -166,6 +212,11 @@ function handlePollingErrors(error, status) {
166
212
  return true;
167
213
  }
168
214
 
215
+ // Handle validation errors with detailed message
216
+ if (error === 'validation_error' || status === 400) {
217
+ throw createValidationError(response);
218
+ }
219
+
169
220
  throw new Error(`Token polling failed: ${error}`);
170
221
  }
171
222
 
@@ -187,6 +238,18 @@ async function waitForNextPoll(interval, slowDown) {
187
238
  * @returns {string} Error code or 'Unknown error'
188
239
  */
189
240
  function extractPollingError(response) {
241
+ // Check for structured error data first (from api-error-handler)
242
+ if (response.errorData) {
243
+ const errorData = response.errorData;
244
+ // For validation errors, return the error type so we can handle it specially
245
+ if (response.errorType === 'validation') {
246
+ return 'validation_error';
247
+ }
248
+ // Return the error message from structured error
249
+ return errorData.detail || errorData.title || errorData.message || errorData.error || response.error || 'Unknown error';
250
+ }
251
+
252
+ // Fallback to original extraction logic
190
253
  const apiResponse = response.data || {};
191
254
  const errorData = typeof apiResponse === 'object' ? apiResponse : {};
192
255
  return errorData.error || response.error || 'Unknown error';
@@ -229,7 +292,7 @@ async function processPollingResponse(response, interval) {
229
292
  }
230
293
 
231
294
  const error = extractPollingError(response);
232
- const shouldContinue = handlePollingErrors(error, response.status);
295
+ const shouldContinue = handlePollingErrors(error, response.status, response);
233
296
 
234
297
  if (shouldContinue) {
235
298
  const slowDown = error === 'slow_down';
@@ -20,10 +20,11 @@ const logger = require('../utils/logger');
20
20
  * @param {string} appKey - Application key
21
21
  * @param {string} clientIdKey - Secret key for client ID (e.g., 'myapp-client-idKeyVault')
22
22
  * @param {string} clientSecretKey - Secret key for client secret (e.g., 'myapp-client-secretKeyVault')
23
- * @param {string} controllerUrl - Controller URL (e.g., 'http://localhost:3010' or 'https://controller.aifabrix.ai')
23
+ * @param {string} _controllerUrl - Controller URL (e.g., 'http://localhost:3010' or 'https://controller.aifabrix.ai')
24
+ * Note: This parameter is accepted for compatibility but the template format http://${MISO_HOST}:${MISO_PORT} is used instead
24
25
  * @returns {Promise<void>} Resolves when template is updated
25
26
  */
26
- async function updateEnvTemplate(appKey, clientIdKey, clientSecretKey, controllerUrl) {
27
+ async function updateEnvTemplate(appKey, clientIdKey, clientSecretKey, _controllerUrl) {
27
28
  const envTemplatePath = path.join(process.cwd(), 'builder', appKey, 'env.template');
28
29
 
29
30
  if (!fsSync.existsSync(envTemplatePath)) {
@@ -49,7 +50,7 @@ async function updateEnvTemplate(appKey, clientIdKey, clientSecretKey, controlle
49
50
  }
50
51
 
51
52
  if (hasControllerUrl) {
52
- content = content.replace(/^MISO_CONTROLLER_URL\s*=.*$/m, `MISO_CONTROLLER_URL=${controllerUrl}`);
53
+ content = content.replace(/^MISO_CONTROLLER_URL\s*=.*$/m, 'MISO_CONTROLLER_URL=http://${MISO_HOST}:${MISO_PORT}');
53
54
  }
54
55
 
55
56
  // Add missing entries
@@ -62,7 +63,7 @@ async function updateEnvTemplate(appKey, clientIdKey, clientSecretKey, controlle
62
63
  missingEntries.push(`MISO_CLIENTSECRET=kv://${clientSecretKey}`);
63
64
  }
64
65
  if (!hasControllerUrl) {
65
- missingEntries.push(`MISO_CONTROLLER_URL=${controllerUrl}`);
66
+ missingEntries.push('MISO_CONTROLLER_URL=http://${MISO_HOST}:${MISO_PORT}');
66
67
  }
67
68
 
68
69
  const misoSection = `# MISO Application Client Credentials (per application)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aifabrix/builder",
3
- "version": "2.9.0",
3
+ "version": "2.10.0",
4
4
  "description": "AI Fabrix Local Fabric & Deployment SDK",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -26,13 +26,19 @@ KC_HTTP_MANAGEMENT_HEALTH_ENABLED=false
26
26
  # =============================================================================
27
27
  # DATABASE CONFIGURATION
28
28
  # =============================================================================
29
+
30
+ # MISO Application Client Credentials (per application)
31
+ MISO_CLIENTID=kv://keycloak-client-idKeyVault
32
+ MISO_CLIENTSECRET=kv://keycloak-client-secretKeyVault
33
+ MISO_CONTROLLER_URL=http://${MISO_HOST}:${MISO_PORT}
34
+ MISO_WEB_SERVER_URL=kv://miso-controller-web-server-url
35
+
29
36
  # Connects to postgres service in Docker network (postgres) or localhost (local)
30
37
 
31
38
  KC_DB=postgres
32
39
  KC_DB_URL_HOST=${DB_HOST}
33
- KC_DB_URL_PORT=5432
40
+ KC_DB_URL_PORT=${DB_PORT}
34
41
  KC_DB_URL_DATABASE=keycloak
35
42
  KC_DB_USERNAME=keycloak_user
36
43
  KC_DB_PASSWORD=kv://databases-keycloak-0-passwordKeyVault
37
44
  DB_0_PASSWORD=kv://databases-keycloak-0-passwordKeyVault
38
-
@@ -1,14 +1,14 @@
1
1
  # Application Metadata
2
2
  app:
3
3
  key: keycloak
4
- displayName: "AI Fabrix Keycloak"
5
- description: "Identity and Access Management"
4
+ displayName: 'AI Fabrix Keycloak'
5
+ description: 'Identity and Access Management'
6
6
  type: webapp
7
7
 
8
8
  # Image Configuration
9
9
  image:
10
10
  name: aifabrix/keycloak
11
- tag: "latest"
11
+ tag: 'latest'
12
12
  registry: devflowiseacr.azurecr.io
13
13
  registryMode: acr
14
14
 
@@ -28,13 +28,21 @@ ONBOARDING_ADMIN_EMAIL=kv://miso-controller-admin-emailKeyVault
28
28
  # APPLICATION ENVIRONMENT
29
29
  # =============================================================================
30
30
 
31
- NODE_ENV=development
32
- PORT=3000
31
+ # NODE_ENV: production for Docker (serves pre-built static files), development for local dev
32
+ # In Docker, this should be production to prevent Vite dev server initialization
33
+ NODE_ENV=${NODE_ENV}
34
+ PORT=${MISO_PORT}
33
35
  AUTO_CREATE_TABLES=true
34
36
  FAST_STARTUP=false
35
- ALLOWED_ORIGINS=http://localhost:3000,http://localhost:5173
37
+ ALLOWED_ORIGINS=http://localhost:*
36
38
  ENABLE_API_DOCS=true
37
39
 
40
+ # Rate Limiting Configuration (for local development)
41
+ # Set DISABLE_RATE_LIMIT=true to disable rate limiting entirely (local development only)
42
+ DISABLE_RATE_LIMIT=true
43
+ # RATE_LIMIT_WINDOW_MS=900000 # 15 minutes in milliseconds (default: 900000)
44
+ # RATE_LIMIT_MAX=100 # Max requests per window (default: 100)
45
+
38
46
  # Package Version (auto-set by npm/pnpm, optional override)
39
47
  # npm_package_version=1.0.0
40
48
 
@@ -72,6 +80,7 @@ REDIS_PERMISSIONS_TTL=900
72
80
 
73
81
  KEYCLOAK_REALM=aifabrix
74
82
  KEYCLOAK_SERVER_URL=kv://keycloak-server-urlKeyVault
83
+ KEYCLOAK_PUBLIC_SERVER_URL=kv://keycloak-public-server-urlKeyVault
75
84
  KEYCLOAK_CLIENT_ID=miso-controller
76
85
  KEYCLOAK_CLIENT_SECRET=kv://keycloak-client-secretKeyVault
77
86
  KEYCLOAK_ADMIN_USERNAME=admin
@@ -96,8 +105,9 @@ AZURE_SERVICE_NAME=kv://azure-service-nameKeyVault
96
105
  AZURE_CLIENT_ID=kv://azure-client-idKeyVault
97
106
  AZURE_CLIENT_SECRET=kv://azure-client-secretKeyVault
98
107
 
99
- # Mock Mode (set to false for production)
100
- MOCK=true
108
+ # Mock Mode (defaults to false - set to true only for testing/development)
109
+ # Set MOCK=true to prevent actual Azure resource creation (for testing)
110
+ MOCK=false
101
111
 
102
112
  # =============================================================================
103
113
  # SECURITY & ENCRYPTION
@@ -117,11 +127,14 @@ API_KEY=kv://miso-controller-api-key-secretKeyVault
117
127
  # =============================================================================
118
128
 
119
129
  # MISO Controller URL
120
- MISO_CONTROLLER_URL=kv://miso-controller-url
121
-
122
- # Web Server URL (for OpenAPI documentation server URLs)
123
- # Used to generate correct server URLs in OpenAPI spec
124
- WEB_SERVER_URL=kv://miso-controller-web-server-url
130
+ MISO_CONTROLLER_URL=http://${MISO_HOST}:${MISO_PORT}
131
+
132
+ # Web Server URL (for OpenAPI documentation server URLs and Keycloak callbacks)
133
+ # This is the PUBLIC-FACING URL that browsers/users access (e.g., http://localhost:3100)
134
+ # Used to generate correct server URLs in OpenAPI spec and Keycloak callback URLs
135
+ # For Docker: use localhost with mapped port (e.g., localhost:3100)
136
+ # For production: use public domain (e.g., https://miso.example.com)
137
+ MISO_WEB_SERVER_URL=kv://miso-controller-web-server-url
125
138
 
126
139
  # MISO Environment Configuration (miso, dev, tst, pro)
127
140
  MISO_ENVIRONMENT=miso
@@ -1,230 +1,280 @@
1
1
  roles:
2
- - name: "AI Fabrix Platform Admin"
3
- value: "aifabrix-platform-admin"
4
- description: "Full platform infrastructure management and enterprise controller access"
5
- Groups: ["AI-Fabrix-Platform-Admins"]
6
-
7
- - name: "AI Fabrix Security Admin"
8
- value: "aifabrix-security-admin"
9
- description: "Security and compliance management for enterprise controller"
10
- Groups: ["AI-Fabrix-Security-Admins"]
11
-
12
- - name: "AI Fabrix Infrastructure Admin"
13
- value: "aifabrix-infrastructure-admin"
14
- description: "Infrastructure deployment and management across environments"
15
- Groups: ["AI-Fabrix-Infrastructure-Admins"]
16
-
17
- - name: "AI Fabrix Deployment Admin"
18
- value: "aifabrix-deployment-admin"
19
- description: "Application deployment orchestration and environment management"
20
- Groups: ["AI-Fabrix-Deployment-Admins"]
21
-
22
- - name: "AI Fabrix Compliance Admin"
23
- value: "aifabrix-compliance-admin"
24
- description: "ISO 27001 compliance monitoring and audit management"
25
- Groups: ["AI-Fabrix-Compliance-Admins"]
26
-
27
- - name: "AI Fabrix Developer"
28
- value: "aifabrix-developer"
29
- description: "Developer access to deploy applications via GitHub Actions"
30
- Groups: ["AI-Fabrix-Developers"]
31
-
32
- - name: "AI Fabrix Observer"
33
- value: "aifabrix-observer"
34
- description: "Read-only access to monitoring, logs, and compliance reports"
35
- Groups: ["AI-Fabrix-Observers"]
2
+ - name: 'AI Fabrix Platform Admin'
3
+ value: 'aifabrix-platform-admin'
4
+ description: 'Full platform infrastructure management and enterprise controller access'
5
+ Groups: ['AI-Fabrix-Platform-Admins']
6
+
7
+ - name: 'AI Fabrix Security Admin'
8
+ value: 'aifabrix-security-admin'
9
+ description: 'Security and compliance management for enterprise controller'
10
+ Groups: ['AI-Fabrix-Security-Admins']
11
+
12
+ - name: 'AI Fabrix Infrastructure Admin'
13
+ value: 'aifabrix-infrastructure-admin'
14
+ description: 'Infrastructure deployment and management across environments'
15
+ Groups: ['AI-Fabrix-Infrastructure-Admins']
16
+
17
+ - name: 'AI Fabrix Deployment Admin'
18
+ value: 'aifabrix-deployment-admin'
19
+ description: 'Application deployment orchestration and environment management'
20
+ Groups: ['AI-Fabrix-Deployment-Admins']
21
+
22
+ - name: 'AI Fabrix Compliance Admin'
23
+ value: 'aifabrix-compliance-admin'
24
+ description: 'ISO 27001 compliance monitoring and audit management'
25
+ Groups: ['AI-Fabrix-Compliance-Admins']
26
+
27
+ - name: 'AI Fabrix Developer'
28
+ value: 'aifabrix-developer'
29
+ description: 'Developer access to deploy applications via GitHub Actions'
30
+ Groups: ['AI-Fabrix-Developers']
31
+
32
+ - name: 'AI Fabrix Observer'
33
+ value: 'aifabrix-observer'
34
+ description: 'Read-only access to monitoring, logs, and compliance reports'
35
+ Groups: ['AI-Fabrix-Observers']
36
36
 
37
37
  permissions:
38
38
  # Service User Management
39
- - name: "service-user:create"
40
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin"]
41
- description: "Create service users and API clients"
42
-
43
- - name: "service-user:read"
44
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin", "aifabrix-observer"]
45
- description: "View service users and their configurations"
46
-
47
- - name: "service-user:update"
48
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin"]
49
- description: "Update service user configurations and regenerate secrets"
50
-
51
- - name: "service-user:delete"
52
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin"]
53
- description: "Deactivate service users"
54
-
39
+ - name: 'service-user:create'
40
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin']
41
+ description: 'Create service users and API clients'
42
+
43
+ - name: 'service-user:read'
44
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin', 'aifabrix-observer']
45
+ description: 'View service users and their configurations'
46
+
47
+ - name: 'service-user:update'
48
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin']
49
+ description: 'Update service user configurations and regenerate secrets'
50
+
51
+ - name: 'service-user:delete'
52
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin']
53
+ description: 'Deactivate service users'
54
+
55
55
  # User Management
56
- - name: "users:create"
57
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin"]
58
- description: "Create new users"
59
-
60
- - name: "users:read"
61
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin", "aifabrix-observer"]
62
- description: "View user information and profiles"
63
-
64
- - name: "users:update"
65
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin"]
66
- description: "Update user information and manage group memberships"
67
-
68
- - name: "users:delete"
69
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin"]
70
- description: "Delete users"
71
-
56
+ - name: 'users:create'
57
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin']
58
+ description: 'Create new users'
59
+
60
+ - name: 'users:read'
61
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin', 'aifabrix-observer']
62
+ description: 'View user information and profiles'
63
+
64
+ - name: 'users:update'
65
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin']
66
+ description: 'Update user information and manage group memberships'
67
+
68
+ - name: 'users:delete'
69
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin']
70
+ description: 'Delete users'
71
+
72
72
  # Group Management
73
- - name: "groups:create"
74
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin"]
75
- description: "Create new groups"
76
-
77
- - name: "groups:read"
78
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin", "aifabrix-observer"]
79
- description: "View group information and members"
80
-
81
- - name: "groups:update"
82
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin"]
83
- description: "Update group information"
84
-
85
- - name: "groups:delete"
86
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin"]
87
- description: "Delete groups"
88
-
73
+ - name: 'groups:create'
74
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin']
75
+ description: 'Create new groups'
76
+
77
+ - name: 'groups:read'
78
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin', 'aifabrix-observer']
79
+ description: 'View group information and members'
80
+
81
+ - name: 'groups:update'
82
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin']
83
+ description: 'Update group information'
84
+
85
+ - name: 'groups:delete'
86
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin']
87
+ description: 'Delete groups'
88
+
89
89
  # Administrative Permissions
90
- - name: "admin:read"
91
- roles: ["aifabrix-platform-admin"]
92
- description: "Administrative read access to all resources"
93
-
94
- - name: "admin:write"
95
- roles: ["aifabrix-platform-admin"]
96
- description: "Administrative write access to all resources"
97
-
98
- - name: "admin:delete"
99
- roles: ["aifabrix-platform-admin"]
100
- description: "Administrative delete access to all resources"
101
-
90
+ - name: 'admin:read'
91
+ roles: ['aifabrix-platform-admin']
92
+ description: 'Administrative read access to all resources'
93
+
94
+ - name: 'admin:write'
95
+ roles: ['aifabrix-platform-admin']
96
+ description: 'Administrative write access to all resources'
97
+
98
+ - name: 'admin:delete'
99
+ roles: ['aifabrix-platform-admin']
100
+ description: 'Administrative delete access to all resources'
101
+
102
102
  # Template Applications (environment = null)
103
- - name: "applications:create"
104
- roles: ["aifabrix-platform-admin", "aifabrix-infrastructure-admin", "aifabrix-deployment-admin"]
105
- description: "Register new application templates"
106
-
107
- - name: "applications:read"
108
- roles: ["aifabrix-platform-admin", "aifabrix-infrastructure-admin", "aifabrix-deployment-admin", "aifabrix-developer", "aifabrix-observer"]
109
- description: "View application templates"
110
-
111
- - name: "applications:update"
112
- roles: ["aifabrix-platform-admin", "aifabrix-infrastructure-admin", "aifabrix-deployment-admin"]
113
- description: "Update application templates"
114
-
115
- - name: "applications:delete"
116
- roles: ["aifabrix-platform-admin", "aifabrix-infrastructure-admin"]
117
- description: "Remove application templates"
118
-
103
+ - name: 'applications:create'
104
+ roles: ['aifabrix-platform-admin', 'aifabrix-infrastructure-admin', 'aifabrix-deployment-admin']
105
+ description: 'Register new application templates'
106
+
107
+ - name: 'applications:read'
108
+ roles:
109
+ [
110
+ 'aifabrix-platform-admin',
111
+ 'aifabrix-infrastructure-admin',
112
+ 'aifabrix-deployment-admin',
113
+ 'aifabrix-developer',
114
+ 'aifabrix-observer'
115
+ ]
116
+ description: 'View application templates'
117
+
118
+ - name: 'applications:update'
119
+ roles: ['aifabrix-platform-admin', 'aifabrix-infrastructure-admin', 'aifabrix-deployment-admin']
120
+ description: 'Update application templates'
121
+
122
+ - name: 'applications:delete'
123
+ roles: ['aifabrix-platform-admin', 'aifabrix-infrastructure-admin']
124
+ description: 'Remove application templates'
125
+
119
126
  # Environments
120
- - name: "environments:create"
121
- roles: ["aifabrix-platform-admin", "aifabrix-infrastructure-admin"]
122
- description: "Create new environments (dev, tst, pro, miso)"
123
-
124
- - name: "environments:read"
125
- roles: ["aifabrix-platform-admin", "aifabrix-infrastructure-admin", "aifabrix-deployment-admin", "aifabrix-developer", "aifabrix-observer"]
126
- description: "View environments and their status"
127
-
128
- - name: "environments:update"
129
- roles: ["aifabrix-platform-admin", "aifabrix-infrastructure-admin"]
130
- description: "Update environment configuration"
131
-
132
- - name: "environments:delete"
133
- roles: ["aifabrix-platform-admin", "aifabrix-infrastructure-admin"]
134
- description: "Delete environments"
135
-
127
+ - name: 'environments:create'
128
+ roles: ['aifabrix-platform-admin', 'aifabrix-infrastructure-admin']
129
+ description: 'Create new environments (dev, tst, pro, miso)'
130
+
131
+ - name: 'environments:read'
132
+ roles:
133
+ [
134
+ 'aifabrix-platform-admin',
135
+ 'aifabrix-infrastructure-admin',
136
+ 'aifabrix-deployment-admin',
137
+ 'aifabrix-developer',
138
+ 'aifabrix-observer'
139
+ ]
140
+ description: 'View environments and their status'
141
+
142
+ - name: 'environments:update'
143
+ roles: ['aifabrix-platform-admin', 'aifabrix-infrastructure-admin']
144
+ description: 'Update environment configuration'
145
+
146
+ - name: 'environments:delete'
147
+ roles: ['aifabrix-platform-admin', 'aifabrix-infrastructure-admin']
148
+ description: 'Delete environments'
149
+
136
150
  # Environment Applications
137
- - name: "environments-applications:create"
138
- roles: ["aifabrix-platform-admin", "aifabrix-deployment-admin", "aifabrix-developer"]
139
- description: "Create applications within environments"
140
-
141
- - name: "environments-applications:read"
142
- roles: ["aifabrix-platform-admin", "aifabrix-deployment-admin", "aifabrix-developer", "aifabrix-observer"]
143
- description: "View applications within environments"
144
-
145
- - name: "environments-applications:update"
146
- roles: ["aifabrix-platform-admin", "aifabrix-deployment-admin", "aifabrix-developer"]
147
- description: "Update applications within environments"
148
-
149
- - name: "environments-applications:delete"
150
- roles: ["aifabrix-platform-admin", "aifabrix-deployment-admin"]
151
- description: "Remove applications from environments"
152
-
151
+ - name: 'environments-applications:create'
152
+ roles: ['aifabrix-platform-admin', 'aifabrix-deployment-admin', 'aifabrix-developer']
153
+ description: 'Create applications within environments'
154
+
155
+ - name: 'environments-applications:read'
156
+ roles:
157
+ [
158
+ 'aifabrix-platform-admin',
159
+ 'aifabrix-deployment-admin',
160
+ 'aifabrix-developer',
161
+ 'aifabrix-observer'
162
+ ]
163
+ description: 'View applications within environments'
164
+
165
+ - name: 'environments-applications:update'
166
+ roles: ['aifabrix-platform-admin', 'aifabrix-deployment-admin', 'aifabrix-developer']
167
+ description: 'Update applications within environments'
168
+
169
+ - name: 'environments-applications:delete'
170
+ roles: ['aifabrix-platform-admin', 'aifabrix-deployment-admin']
171
+ description: 'Remove applications from environments'
172
+
153
173
  # Pipeline & Deployment
154
- - name: "applications:deploy"
155
- roles: ["aifabrix-platform-admin", "aifabrix-deployment-admin", "aifabrix-developer"]
156
- description: "Deploy applications to environments"
157
-
158
- - name: "deployments:read"
159
- roles: ["aifabrix-platform-admin", "aifabrix-deployment-admin", "aifabrix-developer", "aifabrix-observer"]
160
- description: "View deployment history and status"
161
-
174
+ - name: 'applications:deploy'
175
+ roles: ['aifabrix-platform-admin', 'aifabrix-deployment-admin', 'aifabrix-developer']
176
+ description: 'Deploy applications to environments'
177
+
178
+ - name: 'deployments:read'
179
+ roles:
180
+ [
181
+ 'aifabrix-platform-admin',
182
+ 'aifabrix-deployment-admin',
183
+ 'aifabrix-developer',
184
+ 'aifabrix-observer'
185
+ ]
186
+ description: 'View deployment history and status'
187
+
162
188
  # Controller Operations
163
- - name: "controller:admin"
164
- roles: ["aifabrix-platform-admin"]
165
- description: "Full administrative access to controller operations"
166
-
167
- - name: "controller:deploy"
168
- roles: ["aifabrix-platform-admin", "aifabrix-infrastructure-admin", "aifabrix-deployment-admin"]
169
- description: "Deploy infrastructure and manage environments"
170
-
171
- - name: "controller:monitor"
172
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin", "aifabrix-observer"]
173
- description: "Monitor system health and view logs"
174
-
175
- - name: "controller:compliance"
176
- roles: ["aifabrix-platform-admin", "aifabrix-compliance-admin"]
177
- description: "Access compliance reports and audit logs"
178
-
189
+ - name: 'controller:admin'
190
+ roles: ['aifabrix-platform-admin']
191
+ description: 'Full administrative access to controller operations'
192
+
193
+ - name: 'controller:deploy'
194
+ roles: ['aifabrix-platform-admin', 'aifabrix-infrastructure-admin', 'aifabrix-deployment-admin']
195
+ description: 'Deploy infrastructure and manage environments'
196
+
197
+ - name: 'controller:monitor'
198
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin', 'aifabrix-observer']
199
+ description: 'Monitor system health and view logs'
200
+
201
+ - name: 'controller:compliance'
202
+ roles: ['aifabrix-platform-admin', 'aifabrix-compliance-admin']
203
+ description: 'Access compliance reports and audit logs'
204
+
179
205
  # Authentication & Authorization
180
- - name: "auth:read"
181
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin", "aifabrix-developer", "aifabrix-observer"]
182
- description: "View user roles and permissions"
183
-
206
+ - name: 'auth:read'
207
+ roles:
208
+ [
209
+ 'aifabrix-platform-admin',
210
+ 'aifabrix-security-admin',
211
+ 'aifabrix-developer',
212
+ 'aifabrix-observer'
213
+ ]
214
+ description: 'View user roles and permissions'
215
+
184
216
  # Logs
185
- - name: "logs:read"
186
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin", "aifabrix-compliance-admin", "aifabrix-observer"]
187
- description: "View application and audit logs"
188
-
189
- - name: "logs:write"
190
- roles: ["aifabrix-platform-admin", "aifabrix-developer"]
191
- description: "Write audit and error logs"
192
-
193
- - name: "logs:export"
194
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin", "aifabrix-compliance-admin"]
195
- description: "Export logs for archival and compliance"
196
-
197
- - name: "audit:read"
198
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin", "aifabrix-compliance-admin"]
199
- description: "View audit trail logs"
200
-
201
- - name: "jobs:read"
202
- roles: ["aifabrix-platform-admin", "aifabrix-infrastructure-admin", "aifabrix-deployment-admin", "aifabrix-observer"]
203
- description: "View job and performance logs"
204
-
205
- - name: "admin:export"
206
- roles: ["aifabrix-platform-admin"]
207
- description: "Administrative export access to all data"
208
-
217
+ - name: 'logs:read'
218
+ roles:
219
+ [
220
+ 'aifabrix-platform-admin',
221
+ 'aifabrix-security-admin',
222
+ 'aifabrix-compliance-admin',
223
+ 'aifabrix-observer'
224
+ ]
225
+ description: 'View application and audit logs'
226
+
227
+ - name: 'logs:write'
228
+ roles: ['aifabrix-platform-admin', 'aifabrix-developer']
229
+ description: 'Write audit and error logs'
230
+
231
+ - name: 'logs:export'
232
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin', 'aifabrix-compliance-admin']
233
+ description: 'Export logs for archival and compliance'
234
+
235
+ - name: 'audit:read'
236
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin', 'aifabrix-compliance-admin']
237
+ description: 'View audit trail logs'
238
+
239
+ - name: 'jobs:read'
240
+ roles:
241
+ [
242
+ 'aifabrix-platform-admin',
243
+ 'aifabrix-infrastructure-admin',
244
+ 'aifabrix-deployment-admin',
245
+ 'aifabrix-observer'
246
+ ]
247
+ description: 'View job and performance logs'
248
+
249
+ - name: 'admin:export'
250
+ roles: ['aifabrix-platform-admin']
251
+ description: 'Administrative export access to all data'
252
+
209
253
  # Admin Operations
210
- - name: "admin:sync"
211
- roles: ["aifabrix-platform-admin", "aifabrix-infrastructure-admin"]
212
- description: "Full system synchronization operations"
213
-
214
- - name: "admin:keycloak"
215
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin"]
216
- description: "Keycloak administration and configuration"
217
-
254
+ - name: 'admin:sync'
255
+ roles: ['aifabrix-platform-admin', 'aifabrix-infrastructure-admin']
256
+ description: 'Full system synchronization operations'
257
+
258
+ - name: 'admin:keycloak'
259
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin']
260
+ description: 'Keycloak administration and configuration'
261
+
218
262
  # Cache Management
219
- - name: "cache:read"
220
- roles: ["aifabrix-platform-admin", "aifabrix-security-admin", "aifabrix-observer"]
221
- description: "View cache statistics and performance metrics"
222
-
223
- - name: "cache:admin"
224
- roles: ["aifabrix-platform-admin"]
225
- description: "Manage cache (clear, invalidate patterns)"
226
-
263
+ - name: 'cache:read'
264
+ roles: ['aifabrix-platform-admin', 'aifabrix-security-admin', 'aifabrix-observer']
265
+ description: 'View cache statistics and performance metrics'
266
+
267
+ - name: 'cache:admin'
268
+ roles: ['aifabrix-platform-admin']
269
+ description: 'Manage cache (clear, invalidate patterns)'
270
+
227
271
  # Dashboard
228
- - name: "dashboard:read"
229
- roles: ["aifabrix-platform-admin", "aifabrix-deployment-admin", "aifabrix-developer", "aifabrix-observer"]
230
- description: "View dashboard summaries and aggregates"
272
+ - name: 'dashboard:read'
273
+ roles:
274
+ [
275
+ 'aifabrix-platform-admin',
276
+ 'aifabrix-deployment-admin',
277
+ 'aifabrix-developer',
278
+ 'aifabrix-observer'
279
+ ]
280
+ description: 'View dashboard summaries and aggregates'
@@ -1,8 +1,8 @@
1
1
  # Application Metadata
2
2
  app:
3
3
  key: miso-controller
4
- displayName: "Miso Controller"
5
- description: "AI Fabrix Miso Controller - Backend API and orchestration service"
4
+ displayName: 'Miso Controller'
5
+ description: 'AI Fabrix Miso Controller - Backend API and orchestration service'
6
6
  type: webapp
7
7
 
8
8
  # Image Configuration
@@ -34,7 +34,7 @@ healthCheck:
34
34
 
35
35
  # Authentication
36
36
  authentication:
37
- type: local
37
+ type: keycloak
38
38
  enableSSO: true
39
39
  requiredRoles:
40
40
  - aifabrix-user