@aifabrix/builder 2.44.4 → 2.44.6

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 (214) hide show
  1. package/.cursor/rules/cli-layout.mdc +1 -1
  2. package/.cursor/rules/project-rules.mdc +1 -1
  3. package/.npmrc.token +1 -1
  4. package/README.md +15 -23
  5. package/integration/hubspot-test/README.md +2 -0
  6. package/integration/hubspot-test/test.js +5 -3
  7. package/jest.projects.js +68 -17
  8. package/lib/api/controller-health.api.js +49 -0
  9. package/lib/api/dimension-values.api.js +82 -0
  10. package/lib/api/dimensions.api.js +114 -0
  11. package/lib/api/external-systems.api.js +1 -0
  12. package/lib/api/integration-clients.api.js +168 -0
  13. package/lib/api/types/dimension-values.types.js +28 -0
  14. package/lib/api/types/dimensions.types.js +31 -0
  15. package/lib/api/types/integration-clients.types.js +45 -0
  16. package/lib/api/types/wizard.types.js +2 -1
  17. package/lib/api/validation-runner.js +46 -25
  18. package/lib/app/deploy-config.js +11 -1
  19. package/lib/app/deploy-status-display.js +3 -3
  20. package/lib/app/deploy.js +36 -14
  21. package/lib/app/display.js +15 -11
  22. package/lib/app/push.js +46 -23
  23. package/lib/app/register.js +1 -1
  24. package/lib/app/restart-display.js +95 -0
  25. package/lib/app/rotate-secret.js +1 -1
  26. package/lib/app/run-container-start.js +12 -6
  27. package/lib/app/run-env-compose.js +30 -1
  28. package/lib/app/run-helpers.js +44 -12
  29. package/lib/app/run-reload-sync.js +148 -0
  30. package/lib/app/run-resolve-image.js +51 -1
  31. package/lib/app/run.js +99 -73
  32. package/lib/build/index.js +75 -45
  33. package/lib/cli/doctor-check.js +117 -0
  34. package/lib/cli/index.js +8 -2
  35. package/lib/cli/infra-guided.js +445 -0
  36. package/lib/cli/setup-app.help.js +1 -1
  37. package/lib/cli/setup-app.js +20 -2
  38. package/lib/cli/setup-app.test-commands.js +9 -5
  39. package/lib/cli/setup-auth.js +26 -0
  40. package/lib/cli/setup-dev-path-commands.js +50 -3
  41. package/lib/cli/setup-infra.js +138 -61
  42. package/lib/cli/setup-integration-client.js +182 -0
  43. package/lib/cli/setup-parameters.js +21 -2
  44. package/lib/cli/setup-platform.js +102 -0
  45. package/lib/cli/setup-secrets.js +18 -6
  46. package/lib/cli/setup-utility.js +97 -33
  47. package/lib/commands/datasource-capability-dimension-cli.js +128 -0
  48. package/lib/commands/datasource-capability-output.js +29 -0
  49. package/lib/commands/datasource-capability-relate-cli.js +140 -0
  50. package/lib/commands/datasource-capability.js +411 -0
  51. package/lib/commands/datasource-unified-test-cli.options.js +1 -1
  52. package/lib/commands/datasource.js +53 -13
  53. package/lib/commands/dev-down.js +3 -3
  54. package/lib/commands/dev-infra-gate.js +32 -0
  55. package/lib/commands/dev-init.js +13 -7
  56. package/lib/commands/dimension-value.js +179 -0
  57. package/lib/commands/dimension.js +330 -0
  58. package/lib/commands/integration-client.js +430 -0
  59. package/lib/commands/login-device.js +65 -30
  60. package/lib/commands/login.js +21 -10
  61. package/lib/commands/parameters-validate.js +78 -13
  62. package/lib/commands/repair-datasource-auto-rbac.js +166 -0
  63. package/lib/commands/repair-datasource-keys.js +10 -5
  64. package/lib/commands/repair-datasource.js +19 -7
  65. package/lib/commands/repair-env-template.js +4 -1
  66. package/lib/commands/repair-openapi-sync.js +172 -0
  67. package/lib/commands/repair-persist.js +102 -0
  68. package/lib/commands/repair-rbac-extract.js +27 -0
  69. package/lib/commands/repair-rbac-migrate.js +186 -0
  70. package/lib/commands/repair-rbac.js +225 -19
  71. package/lib/commands/repair-system-alignment.js +246 -0
  72. package/lib/commands/repair-system-permissions.js +168 -0
  73. package/lib/commands/repair.js +120 -354
  74. package/lib/commands/secure.js +1 -1
  75. package/lib/commands/setup-modes.js +455 -0
  76. package/lib/commands/setup-prompts.js +388 -0
  77. package/lib/commands/setup.js +149 -0
  78. package/lib/commands/teardown.js +228 -0
  79. package/lib/commands/test-e2e-external.js +4 -3
  80. package/lib/commands/up-common.js +97 -12
  81. package/lib/commands/up-dataplane.js +33 -11
  82. package/lib/commands/up-miso.js +7 -11
  83. package/lib/commands/upload.js +109 -23
  84. package/lib/commands/wizard-core-helpers.js +14 -11
  85. package/lib/commands/wizard-core.js +58 -15
  86. package/lib/commands/wizard-dataplane.js +2 -2
  87. package/lib/commands/wizard-entity-selection.js +72 -14
  88. package/lib/commands/wizard-headless.js +7 -3
  89. package/lib/commands/wizard-helpers.js +13 -1
  90. package/lib/commands/wizard.js +210 -61
  91. package/lib/constants/infra-compose-service-names.js +40 -0
  92. package/lib/core/env-reader.js +16 -3
  93. package/lib/core/secrets-admin-env.js +101 -0
  94. package/lib/core/secrets-ensure-infra.js +34 -1
  95. package/lib/core/secrets-ensure.js +88 -66
  96. package/lib/core/secrets-env-content.js +432 -0
  97. package/lib/core/secrets-env-write.js +27 -1
  98. package/lib/core/secrets-load.js +248 -0
  99. package/lib/core/secrets-names.js +32 -0
  100. package/lib/core/secrets.js +17 -757
  101. package/lib/datasource/capability/basic-exposure.js +76 -0
  102. package/lib/datasource/capability/capability-diff-slice.js +41 -0
  103. package/lib/datasource/capability/capability-key.js +34 -0
  104. package/lib/datasource/capability/capability-resolve.js +172 -0
  105. package/lib/datasource/capability/capability-storage-keys.js +22 -0
  106. package/lib/datasource/capability/copy-operations.js +348 -0
  107. package/lib/datasource/capability/copy-test-payload.js +139 -0
  108. package/lib/datasource/capability/create-operations.js +235 -0
  109. package/lib/datasource/capability/dimension-operations.js +151 -0
  110. package/lib/datasource/capability/dimension-validate.js +219 -0
  111. package/lib/datasource/capability/json-pointer.js +31 -0
  112. package/lib/datasource/capability/reference-rewrite.js +51 -0
  113. package/lib/datasource/capability/relate-operations.js +325 -0
  114. package/lib/datasource/capability/relate-validate.js +219 -0
  115. package/lib/datasource/capability/remove-operations.js +275 -0
  116. package/lib/datasource/capability/run-capability-copy.js +152 -0
  117. package/lib/datasource/capability/run-capability-diff.js +135 -0
  118. package/lib/datasource/capability/run-capability-dimension.js +291 -0
  119. package/lib/datasource/capability/run-capability-edit.js +377 -0
  120. package/lib/datasource/capability/run-capability-relate.js +193 -0
  121. package/lib/datasource/capability/run-capability-remove.js +105 -0
  122. package/lib/datasource/capability/templates/minimal-fetch.json +18 -0
  123. package/lib/datasource/capability/validate-capability-slice.js +35 -0
  124. package/lib/datasource/list.js +136 -23
  125. package/lib/datasource/log-viewer.js +2 -4
  126. package/lib/datasource/unified-validation-run.js +51 -16
  127. package/lib/datasource/validate.js +53 -1
  128. package/lib/deployment/deploy-poll-ui.js +60 -0
  129. package/lib/deployment/deployer-status.js +29 -3
  130. package/lib/deployment/deployer.js +48 -30
  131. package/lib/deployment/environment.js +7 -2
  132. package/lib/deployment/poll-interval.js +72 -0
  133. package/lib/deployment/push.js +11 -9
  134. package/lib/external-system/deploy.js +4 -1
  135. package/lib/external-system/download.js +61 -32
  136. package/lib/external-system/sync-deploy-manifest.js +33 -0
  137. package/lib/generator/wizard-prompts.js +7 -1
  138. package/lib/generator/wizard.js +34 -0
  139. package/lib/infrastructure/index.js +49 -19
  140. package/lib/infrastructure/orphan-infra-docker-teardown.js +177 -0
  141. package/lib/parameters/infra-kv-discovery.js +29 -4
  142. package/lib/parameters/infra-parameter-catalog.js +6 -3
  143. package/lib/parameters/infra-parameter-validate.js +67 -19
  144. package/lib/resolvers/datasource-resolver.js +53 -0
  145. package/lib/resolvers/dimension-file.js +52 -0
  146. package/lib/resolvers/manifest-resolver.js +133 -0
  147. package/lib/schema/external-datasource.schema.json +183 -53
  148. package/lib/schema/external-system.schema.json +23 -10
  149. package/lib/schema/infra.parameter.yaml +26 -11
  150. package/lib/schema/wizard-config.schema.json +2 -2
  151. package/lib/utils/aifabrix-config-dir-walk.js +40 -0
  152. package/lib/utils/aifabrix-runtime-config-dir.js +26 -3
  153. package/lib/utils/app-run-containers.js +2 -2
  154. package/lib/utils/bash-secret-env.js +59 -0
  155. package/lib/utils/cli-secrets-error-format.js +78 -0
  156. package/lib/utils/cli-test-layout-chalk.js +31 -9
  157. package/lib/utils/cli-utils.js +4 -36
  158. package/lib/utils/datasource-test-run-display.js +8 -0
  159. package/lib/utils/dev-hosts-helper.js +3 -2
  160. package/lib/utils/dev-init-ssh-merge.js +2 -1
  161. package/lib/utils/docker-build.js +17 -9
  162. package/lib/utils/docker-reload-mount.js +127 -0
  163. package/lib/utils/external-readme.js +117 -4
  164. package/lib/utils/external-system-local-test-tty.js +3 -2
  165. package/lib/utils/external-system-readiness-core.js +45 -12
  166. package/lib/utils/external-system-readiness-deploy-display.js +3 -3
  167. package/lib/utils/external-system-readiness-display-internals.js +33 -3
  168. package/lib/utils/external-system-readiness-display.js +10 -1
  169. package/lib/utils/file-upload.js +40 -3
  170. package/lib/utils/health-check-db-init.js +107 -0
  171. package/lib/utils/health-check-public-warn.js +69 -0
  172. package/lib/utils/health-check-url.js +19 -4
  173. package/lib/utils/health-check.js +135 -105
  174. package/lib/utils/help-builder.js +5 -1
  175. package/lib/utils/image-name.js +34 -7
  176. package/lib/utils/integration-file-backup.js +74 -0
  177. package/lib/utils/mutagen-install.js +30 -3
  178. package/lib/utils/paths.js +108 -25
  179. package/lib/utils/postgres-wipe.js +212 -0
  180. package/lib/utils/register-aifabrix-shell-env.js +15 -0
  181. package/lib/utils/remote-dev-auth.js +21 -5
  182. package/lib/utils/remote-docker-env.js +9 -1
  183. package/lib/utils/remote-secrets-loader.js +42 -3
  184. package/lib/utils/resolve-docker-image-ref.js +9 -3
  185. package/lib/utils/secrets-ancestor-paths.js +47 -0
  186. package/lib/utils/secrets-helpers.js +17 -10
  187. package/lib/utils/secrets-kv-refs.js +42 -0
  188. package/lib/utils/secrets-kv-scope.js +19 -2
  189. package/lib/utils/secrets-materialize-local.js +134 -0
  190. package/lib/utils/secrets-path.js +24 -10
  191. package/lib/utils/secrets-utils.js +2 -2
  192. package/lib/utils/system-builder-root.js +34 -0
  193. package/lib/utils/url-declarative-resolve-build.js +6 -1
  194. package/lib/utils/url-declarative-runtime-base-path.js +32 -0
  195. package/lib/utils/url-declarative-vdir-inactive-env.js +2 -1
  196. package/lib/utils/urls-local-registry.js +73 -20
  197. package/lib/utils/validation-poll-ui.js +81 -0
  198. package/lib/utils/validation-run-poll.js +29 -5
  199. package/lib/utils/with-muted-logger.js +53 -0
  200. package/package.json +1 -1
  201. package/templates/applications/dataplane/application.yaml +1 -1
  202. package/templates/applications/dataplane/rbac.yaml +10 -10
  203. package/templates/applications/keycloak/env.template +8 -6
  204. package/templates/applications/miso-controller/application.yaml +7 -0
  205. package/templates/applications/miso-controller/env.template +7 -7
  206. package/templates/applications/miso-controller/rbac.yaml +9 -9
  207. package/templates/external-system/README.md.hbs +89 -102
  208. package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +0 -1
  209. package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +0 -1
  210. package/.nyc_output/processinfo/index.json +0 -1
  211. package/lib/api/service-users.api.js +0 -150
  212. package/lib/api/types/service-users.types.js +0 -65
  213. package/lib/cli/setup-service-user.js +0 -187
  214. package/lib/commands/service-user.js +0 -429
@@ -0,0 +1,81 @@
1
+ /**
2
+ * TTY ora spinner + throttled non-TTY lines for unified validation run polling (aligned with deploy-poll-ui).
3
+ *
4
+ * @fileoverview Validation run poll presentation helpers
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const chalk = require('chalk');
12
+ const logger = require('./logger');
13
+
14
+ function shouldUseValidationPollSpinner() {
15
+ return Boolean(process && process.stdout && process.stdout.isTTY);
16
+ }
17
+
18
+ /**
19
+ * Single-line ora text / log line for validation polling.
20
+ *
21
+ * @param {Object|null|undefined} envelope - Latest GET envelope (optional before first poll tick)
22
+ * @param {number} attemptIndex - Zero-based poll index after initial POST
23
+ * @param {number} deadlineMs - Wall-clock deadline (Date.now() + remaining budget)
24
+ * @returns {string}
25
+ */
26
+ function buildValidationPollSpinnerText(envelope, attemptIndex, deadlineMs) {
27
+ const remainingSec = Math.max(0, Math.ceil((deadlineMs - Date.now()) / 1000));
28
+ if (!envelope || typeof envelope !== 'object') {
29
+ return `Waiting for validation run… starting (budget ~${remainingSec}s)`;
30
+ }
31
+ const c =
32
+ envelope.reportCompleteness !== undefined && envelope.reportCompleteness !== null
33
+ ? String(envelope.reportCompleteness)
34
+ : '?';
35
+ const st =
36
+ envelope.status !== undefined && envelope.status !== null ? String(envelope.status) : '?';
37
+ return `Waiting for validation run… completeness=${c} status=${st} (poll ${attemptIndex + 1} · ~${remainingSec}s left)`;
38
+ }
39
+
40
+ const NON_TTY_THROTTLE_MS = 5000;
41
+
42
+ /**
43
+ * @param {number} deadlineMs - Absolute deadline for poll budget display
44
+ * @returns {{ usesSpinner: boolean, onPollProgress: Function, finish: () => void }}
45
+ */
46
+ function createValidationPollHandlers(deadlineMs) {
47
+ if (shouldUseValidationPollSpinner()) {
48
+ const ora = require('ora');
49
+ const spinner = ora({
50
+ text: buildValidationPollSpinnerText(null, 0, deadlineMs),
51
+ spinner: 'dots'
52
+ }).start();
53
+ return {
54
+ usesSpinner: true,
55
+ onPollProgress: (envelope, attemptIndex, _meta) => {
56
+ spinner.text = buildValidationPollSpinnerText(envelope, attemptIndex, deadlineMs);
57
+ },
58
+ finish: () => {
59
+ spinner.stop();
60
+ }
61
+ };
62
+ }
63
+
64
+ let lastNonTtyLogAt = 0;
65
+ return {
66
+ usesSpinner: false,
67
+ onPollProgress: (envelope, attemptIndex, _meta) => {
68
+ const now = Date.now();
69
+ if (now - lastNonTtyLogAt < NON_TTY_THROTTLE_MS) return;
70
+ lastNonTtyLogAt = now;
71
+ logger.log(chalk.gray(buildValidationPollSpinnerText(envelope, attemptIndex, deadlineMs)));
72
+ },
73
+ finish: () => {}
74
+ };
75
+ }
76
+
77
+ module.exports = {
78
+ createValidationPollHandlers,
79
+ shouldUseValidationPollSpinner,
80
+ buildValidationPollSpinnerText
81
+ };
@@ -34,8 +34,8 @@ function sleep(ms) {
34
34
  return new Promise(resolve => setTimeout(resolve, ms));
35
35
  }
36
36
 
37
- function maybeLogPollProgress(envelope, verbosePoll, lastProgressLogAtRef) {
38
- if (!verbosePoll || !envelope || typeof envelope !== 'object') return;
37
+ function maybeLogPollProgress(envelope, verbosePoll, lastProgressLogAtRef, skipBecauseUi) {
38
+ if (skipBecauseUi || !verbosePoll || !envelope || typeof envelope !== 'object') return;
39
39
  const now = Date.now();
40
40
  if (now - lastProgressLogAtRef[0] < 5000) return;
41
41
  lastProgressLogAtRef[0] = now;
@@ -57,6 +57,21 @@ function isTerminalReportCompleteness(envelope) {
57
57
  return envelope.reportCompleteness === 'full';
58
58
  }
59
59
 
60
+ function emitPollProgressLine(
61
+ envelope,
62
+ verbosePoll,
63
+ lastProgressLogAtRef,
64
+ onPollProgress,
65
+ attempt,
66
+ deadline
67
+ ) {
68
+ const hasPollUi = typeof onPollProgress === 'function';
69
+ maybeLogPollProgress(envelope, verbosePoll, lastProgressLogAtRef, hasPollUi);
70
+ if (hasPollUi) {
71
+ onPollProgress(envelope, attempt, { deadlineMs: deadline });
72
+ }
73
+ }
74
+
60
75
  /**
61
76
  * Poll until reportCompleteness === 'full' or budget exhausted.
62
77
  * @async
@@ -66,7 +81,8 @@ function isTerminalReportCompleteness(envelope) {
66
81
  * @param {string} opts.testRunId
67
82
  * @param {number} opts.budgetMs - Remaining wall-clock budget for polls only (POST excluded)
68
83
  * @param {typeof getValidationRunWithTransportRetry} [opts.fetchRun] - Inject for tests (default: GET with transport retry)
69
- * @param {boolean} [opts.verbosePoll] - Log throttled progress (plan §3.13)
84
+ * @param {boolean} [opts.verbosePoll] - Log throttled progress (plan §3.13); skipped when `onPollProgress` is set
85
+ * @param {Function|null} [opts.onPollProgress] - `(envelope, attemptIndex, { deadlineMs })` each non-terminal poll
70
86
  * @param {number} [opts.pollRequestTimeoutMs] - Per-GET HTTP timeout (match validation aggregate budget)
71
87
  * @returns {Promise<{ envelope: Object|null, timedOut: boolean, lastApiResult: Object|null }>}
72
88
  */
@@ -78,7 +94,8 @@ async function pollValidationRunUntilComplete(opts) {
78
94
  budgetMs,
79
95
  fetchRun = getValidationRunWithTransportRetry,
80
96
  verbosePoll = false,
81
- pollRequestTimeoutMs
97
+ pollRequestTimeoutMs,
98
+ onPollProgress = null
82
99
  } = opts;
83
100
  const pollTransportOpts =
84
101
  Number.isFinite(pollRequestTimeoutMs) && pollRequestTimeoutMs > 0
@@ -100,7 +117,14 @@ async function pollValidationRunUntilComplete(opts) {
100
117
  return { envelope, timedOut: false, lastApiResult };
101
118
  }
102
119
 
103
- maybeLogPollProgress(envelope, verbosePoll, lastProgressLogAtRef);
120
+ emitPollProgressLine(
121
+ envelope,
122
+ verbosePoll,
123
+ lastProgressLogAtRef,
124
+ onPollProgress,
125
+ attempt,
126
+ deadline
127
+ );
104
128
 
105
129
  const delay = Math.min(nextPollDelayMs(attempt), Math.max(0, deadline - Date.now()));
106
130
  attempt += 1;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @fileoverview Temporarily mute logger.log output for guided UX flows.
3
+ *
4
+ * Used by guided installer-style commands (e.g. up-platform default mode) to avoid
5
+ * streaming orchestration mechanics while preserving errors and warnings.
6
+ */
7
+
8
+ 'use strict';
9
+
10
+ const logger = require('./logger');
11
+
12
+ /**
13
+ * Run a function while muting logger.log/info.
14
+ *
15
+ * - logger.error and logger.warn are preserved.
16
+ * - An optional allowlist can let specific messages through (rare).
17
+ *
18
+ * @template T
19
+ * @param {() => Promise<T>} fn
20
+ * @param {{ allow?: ((...args: any[]) => boolean) }} [opts]
21
+ * @returns {Promise<T>}
22
+ */
23
+ async function withMutedLogger(fn, opts = {}) {
24
+ const original = {
25
+ log: logger.log,
26
+ info: logger.info
27
+ };
28
+
29
+ const allow = typeof opts.allow === 'function' ? opts.allow : null;
30
+
31
+ const muted = (...args) => {
32
+ try {
33
+ if (allow && allow(...args)) {
34
+ return original.log(...args);
35
+ }
36
+ } catch {
37
+ // ignore allow errors; treat as muted
38
+ }
39
+ return undefined;
40
+ };
41
+
42
+ logger.log = muted;
43
+ logger.info = muted;
44
+ try {
45
+ return await fn();
46
+ } finally {
47
+ logger.log = original.log;
48
+ logger.info = original.info;
49
+ }
50
+ }
51
+
52
+ module.exports = { withMutedLogger };
53
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aifabrix/builder",
3
- "version": "2.44.4",
3
+ "version": "2.44.6",
4
4
  "description": "AI Fabrix Local Fabric & Deployment SDK",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -8,7 +8,7 @@ app:
8
8
  version: 1.9.5
9
9
 
10
10
  # Image Configuration
11
- # Set tag to match your build (e.g. aifabrix build dataplane -t v1.0.0 then tag: v1.0.0)
11
+ # Set tag to match your build (e.g. aifabrix build dataplane -t 1.0.0 then tag: 1.0.0)
12
12
  # Registry is required so the controller can pull the image (avoids "docker: not found" on the controller host).
13
13
  image:
14
14
  name: aifabrix/dataplane
@@ -232,19 +232,19 @@ permissions:
232
232
  roles: ["aifabrix-platform-admin", "aifabrix-security-admin", "aifabrix-compliance-admin", "aifabrix-observer"]
233
233
  description: "Read group information"
234
234
 
235
- # OpenAPI file management
236
- - name: "openapi-file:read"
235
+ # OpenAPI / MCP spec bundle (mounted specs under /api/v1/specs)
236
+ - name: "spec:read"
237
237
  roles: ["aifabrix-platform-admin", "aifabrix-security-admin", "aifabrix-deployment-admin", "aifabrix-compliance-admin", "aifabrix-developer", "aifabrix-observer"]
238
- description: "Read OpenAPI files"
239
-
240
- - name: "openapi-file:update"
238
+ description: "Read OpenAPI/MCP spec bundles"
239
+
240
+ - name: "spec:update"
241
241
  roles: ["aifabrix-platform-admin", "aifabrix-developer"]
242
- description: "Update OpenAPI files"
243
-
244
- - name: "openapi-file:delete"
242
+ description: "Update OpenAPI/MCP spec bundles (uploaded or user-owned)"
243
+
244
+ - name: "spec:delete"
245
245
  roles: ["aifabrix-platform-admin", "aifabrix-developer"]
246
- description: "Delete OpenAPI files"
247
-
246
+ description: "Delete OpenAPI/MCP spec bundles (user-owned only; internal specs are not deletable via API)"
247
+
248
248
  # External data source write operations
249
249
  - name: "external-data-source:write"
250
250
  roles: ["aifabrix-platform-admin", "aifabrix-developer"]
@@ -23,15 +23,17 @@ KC_HTTP_RELATIVE_PATH=url://vdir-public
23
23
  # must use the PUBLIC URL as issuer in all tokens so they match what the
24
24
  # controller expects (KEYCLOAK_SERVER_URL).
25
25
  # - Users log in via http://localhost:${KEYCLOAK_PUBLIC_PORT} (browser/CLI)
26
- # - Server calls Keycloak at http://keycloak:8080 for token exchange and refresh
26
+ # - Server calls Keycloak at url://keycloak-internal for token exchange and refresh
27
27
  # - Controller sends Host: localhost:${KEYCLOAK_PUBLIC_PORT} so Keycloak validates issuer
28
28
  # against public URL (requires KC_HOSTNAME_BACKCHANNEL_DYNAMIC=true)
29
29
  # When KC_HOSTNAME_BACKCHANNEL_DYNAMIC=true, hostname must be a full URL.
30
- # Use host-only origin (no /auth); KC_HTTP_RELATIVE_PATH carries the front-door path (url://vdir-public).
31
- # Hostname v2: port belongs in KC_HOSTNAME (url://host-public expands to e.g. http://localhost:8182 or
32
- # https://devNN.example.com). Do not set KC_HOSTNAME_PORT (deprecated v1; triggers Quarkus warnings).
33
- # KEYCLOAK_PUBLIC_PORT = application.yaml `port` (host-published) + dev×100; used by other apps / docs.
34
- KC_HOSTNAME=url://host-public
30
+ # KC_HTTP_RELATIVE_PATH carries the runtime base path (url://vdir-public), and application.yaml
31
+ # frontDoorRouting exposes the same path for internal server-to-server URLs when enabled.
32
+ # Hostname v2: use a full public URL so Keycloak generates redirects that preserve the /auth base path.
33
+ # `url://public` expands to the full front-door URL (including /auth when Traefik + frontDoorRouting.enabled are on).
34
+ # NOTE: Prefer KC_HOSTNAME (not KC_HOSTNAME_URL). hostname-url triggers legacy hostname v1 warnings and, depending on
35
+ # runtime, may not be treated as an active hostname for hostname-backchannel-dynamic.
36
+ KC_HOSTNAME=url://public
35
37
  # nginx / Traefik send X-Forwarded-*; required when using an edge proxy (Keycloak 26+).
36
38
  KC_PROXY_HEADERS=xforwarded
37
39
  # Required for Host header to work: Keycloak resolves backchannel URL from request headers
@@ -7,6 +7,8 @@ app:
7
7
  version: '1.9.5'
8
8
 
9
9
  # Image Configuration
10
+ # Set tag to match your build (e.g. aifabrix build miso-controller -t 1.0.0 then tag: 1.0.0)
11
+ # Registry is required so the controller can pull the image (avoids "docker: not found" on the controller host).
10
12
  image:
11
13
  name: aifabrix/miso-controller
12
14
  tag: latest
@@ -57,6 +59,11 @@ build:
57
59
  language: typescript # Runtime language for template selection (typescript or python)
58
60
  reloadStart: pnpm run start:reload # When running with --reload
59
61
 
62
+ # Repository Configuration (pipeline validate: REPOSITORY_URL_MISMATCH)
63
+ repository:
64
+ enabled: true
65
+ repositoryUrl: https://github.com/aifabrix/aifabrix-miso
66
+
60
67
  # =============================================================================
61
68
  # Portal Input Configuration (Deployment Wizard)
62
69
  # =============================================================================
@@ -28,8 +28,12 @@ SKIP_FIRST_TIME_SETUP=false
28
28
  # Optional custom controller key for onboarding (default: miso-controller)
29
29
  ONBOARDING_CONTROLLER_KEY=miso-controller
30
30
 
31
- # Optional infrastructure name override for onboarding (default: from INFRASTRUCTURE_NAME or aifabrix)
32
- ONBOARDING_INFRASTRUCTURE_NAME=
31
+ # Infrastructure/service name used by controller/onboarding flows
32
+ INFRASTRUCTURE_NAME=aifabrix
33
+
34
+ # Azure region (required for first-time onboarding: controller record / provisioning metadata).
35
+ # Use the region you deploy to (e.g. westeurope, eastus, northeurope). Single env name: LOCATION.
36
+ LOCATION=westeurope
33
37
 
34
38
  # Required for admin user creation during onboarding
35
39
  # Password for the initial administrator user (username: admin)
@@ -311,7 +315,7 @@ NPM_TOKEN=kv://BASH_NPM_TOKEN
311
315
  # url://public includes front-door path from application.yaml (e.g. /controller).
312
316
  MISO_WEB_SERVER_URL=url://public
313
317
  MISO_CONTROLLER_URL=url://internal
314
-
318
+ MISO_RELATIVE_PATH=url://vdir-public
315
319
  # MISO Environment Configuration (miso, dev, tst, pro)
316
320
  MISO_ENVIRONMENT=miso
317
321
 
@@ -319,10 +323,6 @@ MISO_ENVIRONMENT=miso
319
323
  MISO_CLIENTID=kv://miso-controller-client-idKeyVault
320
324
  MISO_CLIENTSECRET=kv://miso-controller-client-secretKeyVault
321
325
 
322
- # Allowed origins for CORS validation (comma-separated)
323
- # Use wildcards for ports: http://localhost:*
324
- MISO_ALLOWED_ORIGINS=http://localhost:*,url://host-public,url://host-private,url://dataplane-host-public,url://dataplane-host-private
325
-
326
326
  # Evaluation mode (optional .env override of DB controller.configuration.evaluation):
327
327
  # When true (default if DB omits flag), infra deploy may coerce :envKey to `miso` — e2e poll on `dev` can 404.
328
328
  # Set false locally to force path envKey to match deploy + GET .../deployments/:id.
@@ -35,22 +35,22 @@ roles:
35
35
  groups: ['AI-Fabrix-Observers']
36
36
 
37
37
  permissions:
38
- # Service User Management
39
- - name: 'service-user:create'
38
+ # Integration clients (Keycloak OIDC clients + control-plane metadata)
39
+ - name: 'integration-client:create'
40
40
  roles: ['aifabrix-platform-admin', 'aifabrix-security-admin']
41
- description: 'Create service users and API clients'
41
+ description: 'Create integration clients and Keycloak OIDC clients'
42
42
 
43
- - name: 'service-user:read'
43
+ - name: 'integration-client:read'
44
44
  roles: ['aifabrix-platform-admin', 'aifabrix-security-admin', 'aifabrix-observer']
45
- description: 'View service users and their configurations'
45
+ description: 'View integration clients and their configurations'
46
46
 
47
- - name: 'service-user:update'
47
+ - name: 'integration-client:update'
48
48
  roles: ['aifabrix-platform-admin', 'aifabrix-security-admin']
49
- description: 'Update service user configurations and regenerate secrets'
49
+ description: 'Update integration client configuration and regenerate secrets'
50
50
 
51
- - name: 'service-user:delete'
51
+ - name: 'integration-client:delete'
52
52
  roles: ['aifabrix-platform-admin', 'aifabrix-security-admin']
53
- description: 'Deactivate service users'
53
+ description: 'Deactivate integration clients'
54
54
 
55
55
  # User Management
56
56
  - name: 'users:create'
@@ -2,132 +2,119 @@
2
2
 
3
3
  {{description}}
4
4
 
5
- ## System Information
5
+ ## At a glance
6
6
 
7
- - **System Key**: `{{systemKey}}`
8
- - **System Type**: `{{systemType}}`
9
- - **Datasources**: {{datasourceCount}}
7
+ | | |
8
+ | --- | --- |
9
+ | **System key** | `{{systemKey}}` |
10
+ | **Type** | `{{systemType}}` |
11
+ | **Datasources** | {{datasourceCount}} |
10
12
 
11
13
  ## Files
12
14
 
13
- - `application{{fileExt}}` Application configuration with `app` and `externalIntegration` blocks
14
- - `{{systemKey}}-system{{fileExt}}` External system definition (authentication, OpenAPI/MCP, RBAC)
15
+ | File | Purpose |
16
+ | --- | --- |
17
+ | `application{{fileExt}}` | App manifest and `externalIntegration` |
18
+ | `{{systemKey}}-system{{fileExt}}` | Auth, API definition, roles |
15
19
  {{#each datasources}}
16
- - `{{fileName}}` Datasource: {{displayName}}
20
+ | `{{fileName}}` | Datasource: {{displayName}} (**capabilities** here) |
17
21
  {{/each}}
18
- - `env.template` Environment variables template (secrets, API keys)
19
- - `{{systemKey}}-deploy.json` Deployment manifest (generated by `aifabrix json {{appName}}`)
20
- - `deploy.js` Deploy script for the integration
21
- - `wizard.yaml` Wizard configuration (if created via wizard)
22
+ | `env.template` | Secrets and env placeholders |
23
+ | `{{systemKey}}-deploy.json` | Deploy manifest (`aifabrix json {{appName}}`) |
24
+ | `deploy.js` | Deploy helper |
25
+ | `wizard.yaml` | Wizard input |
26
+ | `{{rbacOptionalFile}}` | Roles and permissions |
22
27
 
23
- Optional: `{{rbacOptionalFile}}` – Roles and permissions merged into the system when present.
28
+ ## Typical workflow
24
29
 
25
- ## Quick Start
30
+ 1. **Login** — `aifabrix login` (controller URL set via `aifabrix auth config` if needed).
31
+ 2. **Change config** — edit JSON/YAML under `integration/{{appName}}/`, or extend with `aifabrix wizard --app {{appName}}`.
32
+ 3. **Adjust operations** — use `aifabrix datasource capability …` to copy, add, or remove **capabilities** (see below).
33
+ 4. **Check locally** — `aifabrix validate {{appName}}` and `aifabrix datasource validate` on files you touched.
34
+ 5. **Align manifest** — `aifabrix repair {{appName}}` after bigger edits.
35
+ 6. **Publish** — `aifabrix upload {{appName}}` or `aifabrix deploy {{appName}}`.
26
36
 
27
- Login to your controller
28
- ```bash
29
- aifabrix auth config --set-controller <url> --set-environment dev
30
- aifabrix login
31
- ```
32
-
33
- ### 1. Extend External System
37
+ Rollback an experiment: `datasource capability remove …` → validate → upload/deploy again.
34
38
 
35
- Use the interactive wizard to extend your existing system:
36
-
37
- ```bash
38
- aifabrix wizard --app {{appName}}
39
- ```
39
+ ## Capabilities (per datasource)
40
40
 
41
- ### 2. Configure Authentication and Datasources
41
+ Each `*-datasource-*` file lists **capabilities**: named slices that tie together HTTP/API definitions and execution steps. Use the CLI to clone or drop them safely instead of editing huge JSON by hand.
42
42
 
43
- Edit files in `integration/{{appName}}/`:
43
+ **After any change:** run `aifabrix datasource validate <file-or-key>` (or `aifabrix validate {{appName}}` for the whole app).
44
44
 
45
- - **Authentication**: `{{systemKey}}-system{{fileExt}}` (auth type, credentials placeholders)
46
- - **Field mappings**: `{{systemKey}}-datasource-*{{fileExt}}` (dimensions, attributes, operations)
47
- - **Credential and configuration**: `env.template` (security settings and configuration variables)
45
+ | Command | What it does |
46
+ | --- | --- |
47
+ | `datasource capability copy` | Clone one capability to a new name (`--from` / `--as`). Supports `--dry-run`, `--overwrite`, backups. If `exposed.profiles.<from>` exists, it’s copied to `exposed.profiles.<as>`. |
48
+ | `datasource capability create` (or `add`) | New capability from `--from`, `--template`, or `--openapi-operation`. |
49
+ | `datasource capability remove` | Remove one capability (`--capability`; optional `--profile`). Use `--dry-run` first. |
50
+ | `datasource capability validate` | Schema check for the file or one `--capability`. |
51
+ | `datasource capability diff` | Compare two files for one capability. |
52
+ | `datasource capability edit` | Edit one capability’s API definition, runtime steps, or exposure profile in your editor (TTY). |
53
+ | `datasource capability relate` | Link this datasource to another (foreign-key style metadata). See `--help` for flags. |
48
54
 
49
- {{#if secretPaths}}{{#if secretPaths.length}}
50
- ### Secrets
55
+ Short alias (recommended): `af ds cap <command> …`
56
+ Full command: `aifabrix datasource capability <command> …`
51
57
 
52
- Secrets are resolved from `.aifabrix` or key vault. Set them with:
58
+ Examples (use the first datasource from the Files table):
53
59
 
54
60
  ```bash
55
- {{#each secretPaths}}
56
- aifabrix secret set {{path}} <your value> # {{description}}
57
- {{/each}}
58
- ```
59
- {{/if}}{{/if}}
60
-
61
- ### 3. Validate configuration (local only)
61
+ # Preview cloning "create" to "createBasic" (no write)
62
+ af ds cap copy {{#if hasDatasources}}{{datasources.[0].datasourceKey}}{{else}}<datasource-key>{{/if}} --from create --as createBasic --dry-run
62
63
 
63
- `aifabrix validate` runs **on your machine**: it loads files under `integration/{{appName}}/`, checks them against the application and external-system / external-datasource JSON schemas, and runs related manifest rules. It does **not** call the dataplane or any other remote API.
64
+ # Apply the copy, then validate
65
+ af ds cap copy {{#if hasDatasources}}{{datasources.[0].datasourceKey}}{{else}}<datasource-key>{{/if}} --from create --as createBasic
66
+ af ds validate {{#if hasDatasources}}{{datasources.[0].datasourceKey}}{{else}}<datasource-key>{{/if}}
64
67
 
65
- ```bash
66
- aifabrix validate {{appName}}
68
+ # Remove a capability you no longer need
69
+ af ds cap remove {{#if hasDatasources}}{{datasources.[0].datasourceKey}}{{else}}<datasource-key>{{/if}} --capability createBasic --dry-run
67
70
  ```
68
71
 
69
- Use this before upload or deploy to catch structural and policy errors early.
70
-
71
- ### 4. Repair Deployment Manifest
72
-
73
- **Run repair regularly.** It keeps naming conventions, filenames, and the deployment manifest aligned with AI Fabrix platform best practices. Use it after editing datasources, env.template, or system config—and run it often to catch drift early.
74
-
75
- ```bash
76
- aifabrix repair {{appName}}
77
- ```
72
+ For flags, run `af ds cap <command> --help`.
78
73
 
79
- Options:
80
- --auth <method> Set authentication method (oauth2, aad, apikey, basic, queryParam, oidc, hmac, none); updates system file and env.template
81
- --dry-run Report changes only; do not write
82
- --rbac Ensure RBAC permissions per datasource and add default Admin/Reader roles if none exist
83
- --expose Set exposed.attributes on each datasource to all fieldMappings.attributes keys
84
- --sync Add default sync section to datasources that lack it
85
- --test Generate testPayload.payloadTemplate and testPayload.expectedResult from attributes
74
+ ## Single datasource lifecycle (production-ready)
86
75
 
87
- ### 5. Upload to dataplane
76
+ Start with one datasource and iterate until it’s stable.
88
77
 
89
78
  ```bash
90
- aifabrix upload {{appName}}
79
+ af ds validate {{#if hasDatasources}}{{datasources.[0].datasourceKey}}{{else}}<datasource-key>{{/if}}
80
+ af ds test {{#if hasDatasources}}{{datasources.[0].datasourceKey}}{{else}}<datasource-key>{{/if}} --debug --sync
81
+ af ds test-integration {{#if hasDatasources}}{{datasources.[0].datasourceKey}}{{else}}<datasource-key>{{/if}} --sync
82
+ af ds test-e2e {{#if hasDatasources}}{{datasources.[0].datasourceKey}}{{else}}<datasource-key>{{/if}} --debug --sync
91
83
  ```
92
84
 
93
- ## Testing
94
-
95
- | Command | Where it runs | Calls dataplane? |
96
- |--------|----------------|------------------|
97
- | `aifabrix validate {{appName}}` | Local (schemas / files) | No |
98
- | `aifabrix test {{appName}}` | Local (manifest / payload checks) | No |
99
- | `aifabrix test-integration {{appName}}`, `aifabrix test-e2e {{appName}}`, `aifabrix datasource test …`, `aifabrix datasource test-integration …`, `aifabrix datasource test-e2e …` | Through configured auth | Yes — unified validation / pipeline API |
85
+ {{#if secretPaths}}{{#if secretPaths.length}}
100
86
 
101
- So: **validate** (and **`test`**) stay offline; **all integration and E2E test commands** exercise the system **via the API** (after login and a reachable dataplane).
87
+ ## Secrets
102
88
 
103
- ### Local checks (no API)
89
+ Store values the CLI expects (no secrets in Git):
104
90
 
105
91
  ```bash
106
- aifabrix validate {{appName}}
107
- aifabrix test {{appName}}
92
+ {{#each secretPaths}}
93
+ aifabrix secret set {{path}} <your value> # {{description}}
94
+ {{/each}}
108
95
  ```
96
+ {{/if}}{{/if}}
109
97
 
110
- ### Integration tests (dataplane API)
111
-
112
- ```bash
113
- aifabrix test-integration {{appName}}
114
- ```
98
+ ## Repair
115
99
 
116
- ### End-to-end tests (dataplane API)
100
+ Keeps filenames, lists, and deploy manifest in sync after manual edits.
117
101
 
118
102
  ```bash
119
- aifabrix test-e2e {{appName}}
103
+ aifabrix repair {{appName}}
120
104
  ```
121
105
 
122
- Options:
123
- -e, --env <env> Environment: dev, tst, or pro (builder: dev/tst for container)
124
- -v, --verbose Show detailed step output and poll progress
125
- --debug Include debug output and write log to integration/{{appName}}/logs/
126
- --no-async Use sync mode (no polling); single POST per datasource
106
+ Useful flags: `--dry-run`, `--auth <method>`, `--rbac`, `--expose`, `--sync`, `--test`.
107
+
108
+ ## Validate and test
127
109
 
128
- ### E2E tests per datasource
110
+ | Command | Network |
111
+ | --- | --- |
112
+ | `aifabrix validate {{appName}}` | Off — schemas and files only |
113
+ | `aifabrix test {{appName}}` | Off — local checks |
114
+ | `aifabrix test-integration {{appName}}` | On — needs login + dataplane |
115
+ | `aifabrix test-e2e {{appName}}` | On — full pipeline per datasource |
129
116
 
130
- To run a full E2E test for a single datasource (config, credential, sync, data, CIP), use `aifabrix datasource test-e2e` with the datasource key and app:
117
+ Single datasource E2E:
131
118
 
132
119
  {{#if hasDatasources}}
133
120
  ```bash
@@ -137,28 +124,28 @@ aifabrix datasource test-e2e {{datasourceKey}} --app {{../appName}}
137
124
 
138
125
  {{/each}}
139
126
  ```
127
+ {{else}}
128
+ ```bash
129
+ aifabrix datasource test-e2e <datasource-key> --app {{appName}}
130
+ ```
140
131
  {{/if}}
141
132
 
142
- Options:
143
- -a, --app {{appName}} App key (default: resolve from cwd if inside integration/{{appName}}/)
144
- -e, --env <env> Environment: dev, tst, or pro
145
- -v, --verbose Show detailed step output and poll progress
146
- --debug Include debug output and write log to integration/{{appName}}/logs/
147
- --no-run-scenarios Skip expanding testPayload.scenarios in capacity step
148
- --no-cleanup Disable cleanup after test (body cleanup: false)
149
- --primary-key-value <value|@path> Primary key value or path to JSON file (e.g. @pk.json) for body primaryKeyValue
150
- --no-async Use sync mode (no polling); single POST, no asyncRun
151
-
152
- ## Deployment
133
+ Common E2E flags: `-v` / `--verbose`, `-d` / `--debug`, `--no-async`.
153
134
 
154
- Deploy via miso-controller pipeline (same as regular apps). Auth and controller come from `aifabrix login` and `aifabrix auth config`:
135
+ ## Deploy
155
136
 
156
137
  ```bash
157
138
  aifabrix deploy {{appName}}
158
139
  ```
159
140
 
160
- ## Troubleshooting
141
+ ## Remove app
142
+
143
+ ```bash
144
+ aifabrix delete {{appName}}
145
+ ```
146
+
147
+ ## When something fails
161
148
 
162
- - **Local validation errors**: Run `aifabrix validate {{appName}}` (and `aifabrix test {{appName}}`) — these only inspect files on disk, not the dataplane.
163
- - **Deployment / auth**: Run `aifabrix auth config --set-controller <url> --set-environment <env>` and `aifabrix login` before `aifabrix deploy`.
164
- - **File not found**: Run commands from the project root (where `package.json` and `integration/` live).
149
+ - **Validation errors** Fix JSON/schema issues; run `aifabrix validate {{appName}}` and `aifabrix datasource validate` on the file you changed.
150
+ - **Auth** `aifabrix auth config` + `aifabrix login` before upload, deploy, or remote tests.
151
+ - **Wrong folder** Run CLI from the project root (where `integration/{{appName}}/` lives).