@aifabrix/builder 2.33.1 → 2.33.3

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 (42) hide show
  1. package/README.md +13 -0
  2. package/lib/app/deploy-config.js +161 -0
  3. package/lib/app/deploy.js +28 -153
  4. package/lib/app/register.js +6 -5
  5. package/lib/app/run-helpers.js +23 -17
  6. package/lib/cli.js +31 -1
  7. package/lib/commands/logout.js +3 -4
  8. package/lib/commands/up-common.js +72 -0
  9. package/lib/commands/up-dataplane.js +109 -0
  10. package/lib/commands/up-miso.js +134 -0
  11. package/lib/core/config.js +32 -9
  12. package/lib/core/secrets-docker-env.js +88 -0
  13. package/lib/core/secrets.js +142 -115
  14. package/lib/infrastructure/helpers.js +82 -1
  15. package/lib/infrastructure/index.js +2 -0
  16. package/lib/schema/env-config.yaml +7 -0
  17. package/lib/utils/compose-generator.js +13 -13
  18. package/lib/utils/config-paths.js +13 -0
  19. package/lib/utils/device-code.js +2 -2
  20. package/lib/utils/env-endpoints.js +2 -5
  21. package/lib/utils/env-map.js +4 -5
  22. package/lib/utils/parse-image-ref.js +27 -0
  23. package/lib/utils/paths.js +28 -4
  24. package/lib/utils/secrets-generator.js +34 -12
  25. package/lib/utils/secrets-helpers.js +1 -2
  26. package/lib/utils/token-manager-refresh.js +5 -0
  27. package/package.json +1 -1
  28. package/templates/applications/dataplane/Dockerfile +16 -0
  29. package/templates/applications/dataplane/README.md +205 -0
  30. package/templates/applications/dataplane/env.template +143 -0
  31. package/templates/applications/dataplane/rbac.yaml +283 -0
  32. package/templates/applications/dataplane/variables.yaml +143 -0
  33. package/templates/applications/keycloak/Dockerfile +1 -1
  34. package/templates/applications/keycloak/README.md +193 -0
  35. package/templates/applications/keycloak/variables.yaml +5 -6
  36. package/templates/applications/miso-controller/Dockerfile +8 -8
  37. package/templates/applications/miso-controller/README.md +369 -0
  38. package/templates/applications/miso-controller/env.template +114 -6
  39. package/templates/applications/miso-controller/rbac.yaml +74 -0
  40. package/templates/applications/miso-controller/variables.yaml +93 -5
  41. package/templates/infra/compose.yaml.hbs +2 -1
  42. package/templates/applications/miso-controller/test.yaml +0 -1
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Parse full image reference (registry/name:tag or name:tag) into { name, tag }
3
+ *
4
+ * @fileoverview Image reference parsing for compose and run overrides
5
+ * @author AI Fabrix Team
6
+ * @version 2.0.0
7
+ */
8
+
9
+ /**
10
+ * Parses full image reference (registry/name:tag or name:tag) into { name, tag }
11
+ * @param {string} imageRef - Full image reference (e.g. myreg/keycloak:v1 or keycloak:latest)
12
+ * @returns {{ name: string, tag: string }|null} Parsed name and tag, or null if invalid
13
+ */
14
+ function parseImageOverride(imageRef) {
15
+ if (!imageRef || typeof imageRef !== 'string') {
16
+ return null;
17
+ }
18
+ const lastColon = imageRef.lastIndexOf(':');
19
+ if (lastColon <= 0) {
20
+ return { name: imageRef.trim(), tag: 'latest' };
21
+ }
22
+ const name = imageRef.substring(0, lastColon).trim();
23
+ const tag = imageRef.substring(lastColon + 1).trim() || 'latest';
24
+ return { name, tag };
25
+ }
26
+
27
+ module.exports = { parseImageOverride };
@@ -30,18 +30,33 @@ function safeHomedir() {
30
30
  return process.env.HOME || process.env.USERPROFILE || '/';
31
31
  }
32
32
 
33
+ /**
34
+ * Returns the path to the config file (AIFABRIX_HOME env or ~/.aifabrix).
35
+ * Used so getAifabrixHome can read from the same location as config.js.
36
+ * @returns {string} Absolute path to config directory
37
+ */
38
+ function getConfigDirForPaths() {
39
+ if (process.env.AIFABRIX_HOME && typeof process.env.AIFABRIX_HOME === 'string') {
40
+ return path.resolve(process.env.AIFABRIX_HOME.trim());
41
+ }
42
+ return path.join(safeHomedir(), '.aifabrix');
43
+ }
44
+
33
45
  /**
34
46
  * Returns the base AI Fabrix directory.
35
- * Resolved from config.yaml `aifabrix-home` (stored under OS home).
36
- * Falls back to ~/.aifabrix when not specified.
47
+ * Priority: AIFABRIX_HOME env → config.yaml `aifabrix-home` (from AIFABRIX_HOME or ~/.aifabrix) → ~/.aifabrix.
37
48
  *
38
49
  * @returns {string} Absolute path to the AI Fabrix home directory
39
50
  */
40
51
  function getAifabrixHome() {
52
+ if (process.env.AIFABRIX_HOME && typeof process.env.AIFABRIX_HOME === 'string') {
53
+ return path.resolve(process.env.AIFABRIX_HOME.trim());
54
+ }
41
55
  const isTestEnv = process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID !== undefined;
42
56
  if (!isTestEnv) {
43
57
  try {
44
- const configPath = path.join(safeHomedir(), '.aifabrix', 'config.yaml');
58
+ const configDir = getConfigDirForPaths();
59
+ const configPath = path.join(configDir, 'config.yaml');
45
60
  if (fs.existsSync(configPath)) {
46
61
  const content = fs.readFileSync(configPath, 'utf8');
47
62
  const config = yaml.load(content) || {};
@@ -278,7 +293,9 @@ function getIntegrationPath(appName) {
278
293
  }
279
294
 
280
295
  /**
281
- * Gets the builder folder path for regular applications
296
+ * Gets the builder folder path for regular applications.
297
+ * When AIFABRIX_BUILDER_DIR is set (e.g. by up-miso/up-dataplane from config aifabrix-env-config),
298
+ * uses that as builder root instead of cwd/builder.
282
299
  * @param {string} appName - Application name
283
300
  * @returns {string} Absolute path to builder directory
284
301
  */
@@ -286,6 +303,12 @@ function getBuilderPath(appName) {
286
303
  if (!appName || typeof appName !== 'string') {
287
304
  throw new Error('App name is required and must be a string');
288
305
  }
306
+ const builderRoot = process.env.AIFABRIX_BUILDER_DIR && typeof process.env.AIFABRIX_BUILDER_DIR === 'string'
307
+ ? process.env.AIFABRIX_BUILDER_DIR.trim()
308
+ : null;
309
+ if (builderRoot) {
310
+ return path.join(builderRoot, appName);
311
+ }
289
312
  return path.join(process.cwd(), 'builder', appName);
290
313
  }
291
314
 
@@ -442,6 +465,7 @@ async function detectAppType(appName, options = {}) {
442
465
 
443
466
  module.exports = {
444
467
  getAifabrixHome,
468
+ getConfigDirForPaths,
445
469
  getApplicationsBaseDir,
446
470
  getDevDirectory,
447
471
  getAppPath,
@@ -41,6 +41,36 @@ function findMissingSecretKeys(envTemplate, existingSecrets) {
41
41
  return missingKeys;
42
42
  }
43
43
 
44
+ /**
45
+ * Generate database password value for a key (databases-*-passwordKeyVault)
46
+ * @param {string} key - Secret key name
47
+ * @returns {string|null} Password string or null if key does not match
48
+ */
49
+ function generateDbPasswordValue(key) {
50
+ const dbPasswordMatch = key.match(/^databases-([a-z0-9-_]+)-\d+-passwordKeyVault$/i);
51
+ if (!dbPasswordMatch) return null;
52
+ const appName = dbPasswordMatch[1];
53
+ if (appName === 'miso-controller') return 'miso_pass123';
54
+ const dbName = appName.replace(/-/g, '_');
55
+ return `${dbName}_pass123`;
56
+ }
57
+
58
+ /**
59
+ * Generate database URL value for a key (databases-*-urlKeyVault)
60
+ * @param {string} key - Secret key name
61
+ * @returns {string|null} URL string or null if key does not match
62
+ */
63
+ function generateDbUrlValue(key) {
64
+ const dbUrlMatch = key.match(/^databases-([a-z0-9-_]+)-\d+-urlKeyVault$/i);
65
+ if (!dbUrlMatch) return null;
66
+ const appName = dbUrlMatch[1];
67
+ if (appName === 'miso-controller') {
68
+ return 'postgresql://miso_user:miso_pass123@${DB_HOST}:${DB_PORT}/miso';
69
+ }
70
+ const dbName = appName.replace(/-/g, '_');
71
+ return `postgresql://${dbName}_user:${dbName}_pass123@\${DB_HOST}:\${DB_PORT}/${dbName}`;
72
+ }
73
+
44
74
  /**
45
75
  * Generates secret value based on key name
46
76
  * @function generateSecretValue
@@ -51,22 +81,14 @@ function generateSecretValue(key) {
51
81
  const keyLower = key.toLowerCase();
52
82
 
53
83
  if (keyLower.includes('password')) {
54
- const dbPasswordMatch = key.match(/^databases-([a-z0-9-_]+)-\d+-passwordKeyVault$/i);
55
- if (dbPasswordMatch) {
56
- const appName = dbPasswordMatch[1];
57
- const dbName = appName.replace(/-/g, '_');
58
- return `${dbName}_pass123`;
59
- }
84
+ const dbPassword = generateDbPasswordValue(key);
85
+ if (dbPassword !== null) return dbPassword;
60
86
  return crypto.randomBytes(32).toString('base64');
61
87
  }
62
88
 
63
89
  if (keyLower.includes('url') || keyLower.includes('uri')) {
64
- const dbUrlMatch = key.match(/^databases-([a-z0-9-_]+)-\d+-urlKeyVault$/i);
65
- if (dbUrlMatch) {
66
- const appName = dbUrlMatch[1];
67
- const dbName = appName.replace(/-/g, '_');
68
- return `postgresql://${dbName}_user:${dbName}_pass123@\${DB_HOST}:\${DB_PORT}/${dbName}`;
69
- }
90
+ const dbUrl = generateDbUrlValue(key);
91
+ if (dbUrl !== null) return dbUrl;
70
92
  return '';
71
93
  }
72
94
 
@@ -263,8 +263,7 @@ async function getLocalEnvWithOverrides() {
263
263
  let localEnv = await getEnvHosts('local');
264
264
 
265
265
  try {
266
- const os = require('os');
267
- const cfgPath = path.join(os.homedir(), '.aifabrix', 'config.yaml');
266
+ const cfgPath = config.CONFIG_FILE;
268
267
  if (fs.existsSync(cfgPath)) {
269
268
  const cfgContent = fs.readFileSync(cfgPath, 'utf8');
270
269
  const cfg = yaml.load(cfgContent) || {};
@@ -10,6 +10,7 @@
10
10
 
11
11
  const config = require('../core/config');
12
12
  const { refreshDeviceToken: apiRefreshDeviceToken } = require('./api');
13
+ const { isTokenEncrypted } = require('./token-encryption');
13
14
 
14
15
  /**
15
16
  * Validates refresh token parameters
@@ -138,6 +139,10 @@ async function refreshDeviceToken(controllerUrl, refreshToken) {
138
139
  if (!refreshToken || typeof refreshToken !== 'string') {
139
140
  throw new Error('Refresh token is required');
140
141
  }
142
+ // Never send encrypted token to the API (causes 401). Decryption should happen in getDeviceToken; this is a safeguard.
143
+ if (isTokenEncrypted(refreshToken)) {
144
+ throw new Error('Refresh token is still encrypted; decryption may have failed. Run "aifabrix login" to authenticate again.');
145
+ }
141
146
 
142
147
  try {
143
148
  // Call API refresh endpoint
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aifabrix/builder",
3
- "version": "2.33.1",
3
+ "version": "2.33.3",
4
4
  "description": "AI Fabrix Local Fabric & Deployment SDK",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -0,0 +1,16 @@
1
+ # AI Fabrix Dataplane - Build from base image
2
+ # This repo has no application source; use the published image as baseline.
3
+ # Build: docker build -t aifabrix/dataplane:local .
4
+ # Or use the image directly: docker run aifabrix/dataplane:latest
5
+
6
+ FROM aifabrix/dataplane:latest
7
+
8
+ # Expose port (documentation; base image may already set this)
9
+ EXPOSE 3001
10
+
11
+ # Health check (documentation; base image may already set this)
12
+ HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
13
+ CMD curl -f http://localhost:3001/health || exit 1
14
+
15
+ # CMD inherited from base image; override only if needed
16
+ # CMD inherited: uvicorn app.main:app --host 0.0.0.0 --port 3001
@@ -0,0 +1,205 @@
1
+ # Dataplane Builder
2
+
3
+ Build, run, and deploy Dataplane using `@aifabrix/builder`.
4
+
5
+ ---
6
+
7
+ ## Quick Start
8
+
9
+ ### 1. Install
10
+
11
+ ```bash
12
+ npm install -g @aifabrix/builder
13
+ ```
14
+
15
+ ### 2. First Time Setup
16
+
17
+ ```bash
18
+ # Check your environment
19
+ aifabrix doctor
20
+
21
+ # Login to controller (change your own port)
22
+ aifabrix login --method device --environment dev --controller http://localhost:3100
23
+
24
+ # Register your application (gets you credentials automatically)
25
+ aifabrix app register dataplane
26
+ ```
27
+
28
+ ### 3. Build & Run Locally
29
+
30
+ ```bash
31
+ # Build the Docker image
32
+ aifabrix build dataplane
33
+
34
+ # Run locally
35
+ aifabrix run dataplane
36
+ ```
37
+
38
+ **Access your app:** <http://localhost:3111> (host port from `build.localPort`; container uses 3001)
39
+
40
+ ---
41
+
42
+ ## Testing dataplane (use DATAPLANE_TEST_GUIDE)
43
+
44
+ **Use the builder's Dataplane Test Guide** for auth, health, wizard, external systems, and pipeline checks:
45
+
46
+ - **In aifabrix-builder:** `integration/hubspot/DATAPLANE_TEST_GUIDE.md`
47
+ - **Dataplane base URL:** `http://localhost:3111`
48
+ - **Controller:** `http://localhost:3110` (login, token)
49
+
50
+ The guide defines: token setup, `/health`, wizard API, external systems API, pipeline API, and quick checks.
51
+ Keep `build.localPort` in `variables.yaml` at **3111** so it matches that guide.
52
+
53
+ **View logs:**
54
+
55
+ ```bash
56
+ docker logs aifabrix-dataplane -f
57
+ ```
58
+
59
+ **Stop:**
60
+
61
+ ```bash
62
+ docker stop aifabrix-dataplane
63
+ ```
64
+
65
+ ### 4. Deploy to Azure
66
+
67
+ ```bash
68
+ # Build with version tag
69
+ aifabrix build dataplane --tag v1.0.0
70
+
71
+ # Push to registry
72
+ aifabrix push dataplane --registry myacr.azurecr.io --tag "v1.0.0,latest"
73
+
74
+ # Deploy to miso-controller
75
+ aifabrix deploy dataplane
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Using miso-client
81
+
82
+ > [miso-client](https://github.com/esystemsdev/aifabrix-miso-client)
83
+
84
+ After registering your app, you automatically get credentials in your secret file. Use miso-client for login, RBAC, audit logs, etc.
85
+
86
+ **Rotate credentials if needed:**
87
+
88
+ ```bash
89
+ aifabrix app rotate-secret dataplane
90
+ ```
91
+
92
+ ---
93
+
94
+ ## Reference
95
+
96
+ ### Common Commands
97
+
98
+ ```bash
99
+ # Development
100
+ aifabrix build dataplane # Build app
101
+ aifabrix run dataplane # Run locally
102
+ aifabrix dockerfile dataplane --force # Generate Dockerfile
103
+ aifabrix resolve dataplane # Generate .env file
104
+
105
+ # Deployment
106
+ aifabrix json dataplane # Preview deployment JSON
107
+ aifabrix genkey dataplane # Generate deployment key
108
+ aifabrix push dataplane --registry myacr.azurecr.io # Push to ACR
109
+ aifabrix deploy dataplane --controller <url> # Deploy to Azure
110
+
111
+ # Management
112
+ aifabrix app register dataplane
113
+ aifabrix app list
114
+ aifabrix app rotate-secret dataplane
115
+
116
+ # Utilities
117
+ aifabrix doctor # Check environment
118
+ aifabrix login --method device # Login
119
+ aifabrix --help # Get help
120
+ ```
121
+
122
+ ### Build Options
123
+
124
+ ```bash
125
+ aifabrix build dataplane --tag v1.0.0 # Custom tag
126
+ aifabrix build dataplane --force-template # Force template regeneration
127
+ aifabrix build dataplane --language typescript # Override language detection
128
+ ```
129
+
130
+ ### Run Options
131
+
132
+ ```bash
133
+ aifabrix run dataplane --port 3000 # Custom port
134
+ aifabrix run dataplane --debug # Debug output
135
+ ```
136
+
137
+ ### Push Options
138
+
139
+ ```bash
140
+ aifabrix push dataplane --registry myacr.azurecr.io --tag v1.0.0
141
+ aifabrix push dataplane --registry myacr.azurecr.io --tag "v1.0.0,latest,stable"
142
+ ```
143
+
144
+ ### Deploy Options
145
+
146
+ ```bash
147
+ aifabrix deploy dataplane
148
+ aifabrix deploy dataplane --no-poll
149
+ ```
150
+
151
+ ### Login Methods
152
+
153
+ ```bash
154
+ # Device code flow
155
+ aifabrix login --method device --environment dev
156
+
157
+ # Credentials (reads from secrets.local.yaml)
158
+ aifabrix login --method credentials --app dataplane --environment dev
159
+
160
+ # Explicit credentials
161
+ aifabrix login --method credentials --app dataplane --client-id $CLIENT_ID --client-secret $CLIENT_SECRET --environment dev
162
+ ```
163
+
164
+ ### Environment Variables
165
+
166
+ ```bash
167
+ export AIFABRIX_HOME=/custom/path
168
+ export AIFABRIX_SECRETS=/path/to/secrets.yaml
169
+ ```
170
+
171
+ ---
172
+
173
+ ## Troubleshooting
174
+
175
+ - **"Docker not running"** → Start Docker Desktop
176
+ - **"Not logged in"** → Run `aifabrix login` first
177
+ - **"Port already in use"** → Use `--port` flag or change `build.localPort` in `variables.yaml` (default: 3111, must match DATAPLANE_TEST_GUIDE)
178
+ - **"Authentication failed"** → Run `aifabrix login` again
179
+ - **"Build fails"** → Check Docker is running and `variables.yaml` → `build.secrets` path is correct
180
+ - **"Can't connect"** → Verify infrastructure is running and PostgreSQL is accessible
181
+
182
+ **Regenerate files:**
183
+
184
+ ```bash
185
+ aifabrix resolve dataplane --force
186
+ aifabrix json dataplane
187
+ aifabrix genkey dataplane
188
+ ```
189
+
190
+ ---
191
+
192
+ ## Prerequisites
193
+
194
+ - `@aifabrix/builder` installed globally
195
+ - Docker Desktop running
196
+ - Azure CLI installed (for push command)
197
+ - Authenticated with controller (for deploy command)
198
+ - PostgreSQL database (ensure infrastructure is running)
199
+ - Redis (ensure infrastructure is running)
200
+ - File storage configured
201
+ - Authentication/RBAC configured
202
+
203
+ ---
204
+
205
+ **Application**: dataplane | **Port**: 3111 (local) / 3001 (container) | **Registry**: myacr.azurecr.io | **Image**: aifabrix/dataplane:latest
@@ -0,0 +1,143 @@
1
+ # Environment Variables Template
2
+ # Use kv:// references for secrets (resolved from .aifabrix/secrets.yaml)
3
+ # Use ${VAR} for environment-specific values
4
+
5
+ # =============================================================================
6
+ # APPLICATION ENVIRONMENT
7
+ # =============================================================================
8
+
9
+ PORT=3001
10
+ ENVIRONMENT=development
11
+ DEBUG=false
12
+ LOG_LEVEL=INFO
13
+ LOG_FORMAT=json
14
+ LOG_FILE_PATH=/mnt/data/logs/app.log
15
+ LOCAL_MODE=false
16
+
17
+ # When API_KEY is set, a matching Bearer token bypasses OAuth2 validation
18
+ API_KEY=kv://miso-controller-api-key-secretKeyVault
19
+
20
+ # API Configuration
21
+ API_V1_STR=/api/v1
22
+ VERSION=1.6.0
23
+
24
+ # CORS Configuration
25
+ ALLOWED_ORIGINS=http://localhost:*
26
+ IDE_CORS_ORIGINS=
27
+
28
+ # Encryption Configuration
29
+ ENCRYPTION_KEY=kv://secrets-encryptionKeyVault
30
+
31
+ # =============================================================================
32
+ # DATABASE CONFIGURATION
33
+ # =============================================================================
34
+
35
+ DATABASE_URL=kv://databases-dataplane-0-urlKeyVault
36
+ DB_0_PASSWORD=kv://databases-dataplane-0-passwordKeyVault
37
+
38
+ # Vector and document store DB: chunks, embeddings, vector indexes (pgvector).
39
+ # Binaries path: config.processing.fileStoragePath or /data/documents.
40
+ VECTOR_DATABASE_URL=kv://databases-dataplane-1-urlKeyVault
41
+ DB_1_PASSWORD=kv://databases-dataplane-1-passwordKeyVault
42
+
43
+ # Logs Database Configuration (for execution, audit, ABAC traces)
44
+ LOGS_DATABASE_URL=kv://databases-dataplane-2-urlKeyVault
45
+ DB_2_PASSWORD=kv://databases-dataplane-2-passwordKeyVault
46
+
47
+ # Records Database Configuration (for external records storage)
48
+ RECORDS_DATABASE_URL=kv://databases-dataplane-3-urlKeyVault
49
+ DB_3_PASSWORD=kv://databases-dataplane-3-passwordKeyVault
50
+
51
+ # =============================================================================
52
+ # REDIS CONFIGURATION
53
+ # =============================================================================
54
+ # Connects to external redis from aifabrix-setup
55
+
56
+ REDIS_URL=kv://redis-url
57
+
58
+ # =============================================================================
59
+ # CACHE CONFIGURATION
60
+ # =============================================================================
61
+
62
+ CACHE_ENABLED=true
63
+ CACHE_CIP_EXECUTION_TTL=1800
64
+ CACHE_METADATA_FILTER_TTL=3600
65
+
66
+ # =============================================================================
67
+ # AUTHENTICATION CONFIGURATION
68
+ # =============================================================================
69
+
70
+ # MISO Application Client Credentials (per application)
71
+ MISO_CLIENTID=kv://dataplane-client-idKeyVault
72
+ MISO_CLIENTSECRET=kv://dataplane-client-secretKeyVault
73
+
74
+ # Keycloak Configuration (for OAuth2 endpoints)
75
+ KEYCLOAK_SERVER_URL=kv://keycloak-server-urlKeyVault
76
+ KEYCLOAK_REALM=aifabrix
77
+
78
+ # MISO Controller URL
79
+ MISO_CONTROLLER_URL=http://${MISO_HOST}:${MISO_PORT}
80
+
81
+ # =============================================================================
82
+ # AI/LLM CONFIGURATION
83
+ # =============================================================================
84
+
85
+ # OpenAI Configuration
86
+ OPENAI_API_KEY=kv://secrets-openaiApiKeyVault
87
+
88
+ # Azure OpenAI Configuration
89
+ AZURE_OPENAI_ENDPOINT=
90
+ AZURE_OPENAI_API_KEY=kv://secrets-azureOpenaiApiKeyVault
91
+ AZURE_OPENAI_API_VERSION=2024-02-15-preview
92
+ AZURE_OPENAI_DEPLOYMENT_NAME=gpt-4o
93
+
94
+ # =============================================================================
95
+ # AUDIT CONFIGURATION
96
+ # =============================================================================
97
+
98
+ # General Audit Settings
99
+ AUDIT_ENABLED=true
100
+ MISO_LOG_FORWARD_ERRORS=true
101
+ AUTH_AUDIT_ENABLED=true
102
+
103
+ # ABAC Audit Configuration
104
+ ABAC_AUDIT_ENABLED=true
105
+ ABAC_AUDIT_DETAIL_LEVEL=summary
106
+ ABAC_EXPLAIN_MODE_ENABLED=false
107
+ ABAC_PERFORMANCE_THRESHOLD_MS=1000
108
+
109
+ # RBAC Audit Configuration
110
+ RBAC_AUDIT_ENABLED=true
111
+ RBAC_AUDIT_DETAIL_LEVEL=summary
112
+ RBAC_EXPLAIN_MODE_ENABLED=false
113
+
114
+ # =============================================================================
115
+ # OBSERVABILITY CONFIGURATION
116
+ # =============================================================================
117
+
118
+ # OpenTelemetry Configuration
119
+ OPENTELEMETRY_ENABLED=false
120
+ OPENTELEMETRY_ENDPOINT=
121
+
122
+ # =============================================================================
123
+ # CIP EXECUTION CONFIGURATION
124
+ # =============================================================================
125
+ # These control CIP (Composable Integration Pipeline) execution behavior
126
+
127
+ CIP_EXECUTION_MAX_RESPONSE_SIZE_MB=100.0
128
+ CIP_EXECUTION_MAX_RECORDS=100000
129
+ CIP_EXECUTION_OPERATION_TIMEOUT=300.0
130
+ CIP_EXECUTION_HTTP_TIMEOUT=30.0
131
+ CIP_EXECUTION_MAX_RETRIES=3
132
+ CIP_EXECUTION_RETRY_BACKOFF_FACTOR=2.0
133
+ CIP_EXECUTION_RETRY_INITIAL_DELAY=1.0
134
+
135
+ # Circuit Breaker Configuration
136
+ CIP_EXECUTION_CIRCUIT_BREAKER_FAILURE_THRESHOLD=5
137
+ CIP_EXECUTION_CIRCUIT_BREAKER_TIME_WINDOW=60
138
+ CIP_EXECUTION_CIRCUIT_BREAKER_SUCCESS_THRESHOLD=2
139
+ CIP_EXECUTION_CIRCUIT_BREAKER_HALF_OPEN_TIMEOUT=30
140
+
141
+ # Rate Limiting Configuration
142
+ CIP_EXECUTION_RATE_LIMIT_REQUESTS_PER_SECOND=10.0
143
+ CIP_EXECUTION_RATE_LIMIT_BURST_SIZE=20