@aifabrix/builder 2.45.5 → 2.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/.cursor/rules/cli-layout.mdc +2 -0
  2. package/.cursor/rules/cli-product-neutral.mdc +43 -0
  3. package/.cursor/rules/project-rules.mdc +1 -0
  4. package/README.md +43 -17
  5. package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
  6. package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
  7. package/jest.config.default.js +2 -1
  8. package/jest.config.isolated.js +2 -1
  9. package/jest.global-live-fabrix-hooks.js +36 -0
  10. package/jest.isolated-projects.js +130 -0
  11. package/jest.projects.js +41 -136
  12. package/lib/api/api-response-errors.js +124 -0
  13. package/lib/api/governance-scenario-pack.api.js +159 -0
  14. package/lib/api/index.js +43 -3
  15. package/lib/api/lifecycle.api.js +77 -0
  16. package/lib/api/pipeline.api.js +3 -1
  17. package/lib/api/records-bulk.api.js +14 -1
  18. package/lib/api/validation-runner.js +3 -1
  19. package/lib/app/deploy-config.js +4 -1
  20. package/lib/app/down.js +20 -1
  21. package/lib/app/push.js +4 -5
  22. package/lib/app/register.js +7 -4
  23. package/lib/app/run-env-compose.js +84 -30
  24. package/lib/build/index.js +5 -0
  25. package/lib/certification/sync-system-certification.js +13 -6
  26. package/lib/cli/index.js +4 -0
  27. package/lib/cli/infra-guided-auth.js +109 -0
  28. package/lib/cli/infra-guided.js +84 -81
  29. package/lib/cli/setup-app.help.js +0 -31
  30. package/lib/cli/setup-app.js +28 -2
  31. package/lib/cli/setup-app.test-commands.js +5 -57
  32. package/lib/cli/setup-auth.js +25 -0
  33. package/lib/cli/setup-certification-commands.js +147 -0
  34. package/lib/cli/setup-certification.help.js +141 -0
  35. package/lib/cli/setup-environment.js +19 -2
  36. package/lib/cli/setup-external-system-help.js +62 -0
  37. package/lib/cli/setup-external-system.js +25 -3
  38. package/lib/cli/setup-infra.js +9 -1
  39. package/lib/cli/setup-platform.js +6 -1
  40. package/lib/cli/setup-secrets.js +33 -1
  41. package/lib/cli/setup-utility-help-after.js +22 -2
  42. package/lib/cli/setup-utility-repair.js +198 -0
  43. package/lib/cli/setup-utility-resolve.js +40 -4
  44. package/lib/cli/setup-utility-validate.js +197 -0
  45. package/lib/cli/setup-utility.js +4 -239
  46. package/lib/commands/auth-status-client-tokens.js +214 -0
  47. package/lib/commands/auth-status-dataplane-version.js +58 -20
  48. package/lib/commands/auth-status.js +41 -47
  49. package/lib/commands/datasource-test-trust-cli.js +27 -23
  50. package/lib/commands/datasource-unified-test-cli.js +6 -3
  51. package/lib/commands/datasource-unified-test-cli.options.js +5 -1
  52. package/lib/commands/datasource.js +7 -7
  53. package/lib/commands/dev-show-display.js +8 -1
  54. package/lib/commands/governance-cli-shared.js +94 -0
  55. package/lib/commands/governance-command-action.js +132 -0
  56. package/lib/commands/governance-download-external.js +34 -0
  57. package/lib/commands/governance-generate-external.js +71 -0
  58. package/lib/commands/governance-upload-external.js +36 -0
  59. package/lib/commands/governance-verify-external.js +64 -0
  60. package/lib/commands/governance.js +144 -0
  61. package/lib/commands/lifecycle-command-action.js +123 -0
  62. package/lib/commands/lifecycle-external.js +268 -0
  63. package/lib/commands/login.js +11 -2
  64. package/lib/commands/repair-auth-apply.js +127 -0
  65. package/lib/commands/repair-changed-files.js +41 -0
  66. package/lib/commands/repair-datasource-keys.js +4 -1
  67. package/lib/commands/repair-datasource-run.js +59 -0
  68. package/lib/commands/repair-datasource-test-payload.js +259 -0
  69. package/lib/commands/repair-datasource.js +1 -51
  70. package/lib/commands/repair-env-template.js +64 -13
  71. package/lib/commands/repair-external-run.js +216 -0
  72. package/lib/commands/repair-openapi-sync.js +23 -0
  73. package/lib/commands/repair-persist.js +4 -0
  74. package/lib/commands/repair-rbac.js +52 -1
  75. package/lib/commands/repair-steps.js +145 -0
  76. package/lib/commands/repair.js +29 -296
  77. package/lib/commands/secrets-get.js +184 -0
  78. package/lib/commands/secrets-remove-all.js +3 -1
  79. package/lib/commands/setup-image-refresh.js +146 -0
  80. package/lib/commands/setup-modes.js +158 -162
  81. package/lib/commands/setup-platform-auth.js +76 -0
  82. package/lib/commands/setup-prompts-admin.js +244 -0
  83. package/lib/commands/setup-prompts-platform-mode.js +67 -0
  84. package/lib/commands/setup-prompts-validators.js +36 -0
  85. package/lib/commands/setup-prompts.js +24 -76
  86. package/lib/commands/setup-run-context.js +45 -0
  87. package/lib/commands/setup-spinners.js +39 -0
  88. package/lib/commands/setup.js +27 -5
  89. package/lib/commands/teardown.js +39 -0
  90. package/lib/commands/test-e2e-external.js +24 -8
  91. package/lib/commands/test-governance-external.js +3 -24
  92. package/lib/commands/test-trust-external.js +20 -21
  93. package/lib/commands/up-common.js +25 -13
  94. package/lib/commands/up-dataplane.js +50 -13
  95. package/lib/commands/upload-publish-context.js +75 -0
  96. package/lib/commands/upload-sidecar-followups.js +89 -0
  97. package/lib/commands/upload.js +90 -108
  98. package/lib/commands/verify-governance-combined-external.js +61 -0
  99. package/lib/commands/verify-governance-command-action.js +64 -0
  100. package/lib/commands/verify-governance-db.js +102 -0
  101. package/lib/commands/verify-governance-external.js +77 -0
  102. package/lib/commands/verify-governance-result-builders.js +71 -0
  103. package/lib/commands/verify-operations-command-action.js +68 -0
  104. package/lib/commands/verify-operations-external.js +268 -0
  105. package/lib/commands/verify-operations-persist.js +75 -0
  106. package/lib/commands/verify-operations-step-plan.js +68 -0
  107. package/lib/commands/verify-operations-steps.js +111 -0
  108. package/lib/commands/verify-trust-command-action.js +70 -0
  109. package/lib/commands/verify-trust-external.js +67 -0
  110. package/lib/commands/wizard-config-normalizer.js +43 -23
  111. package/lib/commands/wizard-core.js +2 -0
  112. package/lib/core/admin-password-generator.js +38 -0
  113. package/lib/core/admin-secrets-bundle.js +111 -0
  114. package/lib/core/admin-secrets-env-overlay.js +62 -0
  115. package/lib/core/admin-secrets.js +32 -4
  116. package/lib/core/config-attach-extensions.js +3 -0
  117. package/lib/core/config-platform-controller.js +44 -0
  118. package/lib/core/config-setup-installation-profile.js +42 -0
  119. package/lib/core/config-setup-platform-mode.js +46 -0
  120. package/lib/core/config.js +46 -36
  121. package/lib/core/secrets-admin-env.js +6 -2
  122. package/lib/core/secrets-ensure.js +4 -0
  123. package/lib/core/secrets-env-content.js +54 -48
  124. package/lib/core/secrets-env-write.js +10 -1
  125. package/lib/core/secrets-infra-placeholder-sync.js +2 -0
  126. package/lib/core/setup-installation-profile.js +43 -0
  127. package/lib/core/setup-platform-mode.js +55 -0
  128. package/lib/datasource/agent-trust-debug-log.js +1 -1
  129. package/lib/datasource/agent-trust-run.js +5 -3
  130. package/lib/datasource/audit-evidence-extract-debug.js +30 -18
  131. package/lib/datasource/audit-evidence-extract.js +7 -4
  132. package/lib/datasource/audit-evidence-verify-matrix.js +54 -26
  133. package/lib/datasource/bulk-loader-run-batches.js +15 -3
  134. package/lib/datasource/datasource-load-export-context.js +3 -0
  135. package/lib/datasource/log-cleaner.js +2 -2
  136. package/lib/datasource/log-viewer.js +8 -8
  137. package/lib/datasource/test-e2e.js +4 -1
  138. package/lib/datasource/unified-validation-run-body.js +3 -1
  139. package/lib/datasource/unified-validation-run.js +5 -2
  140. package/lib/deployment/environment-poll-status.js +138 -0
  141. package/lib/deployment/environment.js +42 -34
  142. package/lib/external-system/download.js +21 -20
  143. package/lib/external-system/generator.js +5 -1
  144. package/lib/external-system/integration-auth-context.js +45 -0
  145. package/lib/external-system/test-auth.js +12 -5
  146. package/lib/external-system/test.js +6 -6
  147. package/lib/generator/external-controller-manifest.js +15 -0
  148. package/lib/governance/governance-cli-errors.js +96 -0
  149. package/lib/governance/governance-download-display.js +38 -0
  150. package/lib/governance/governance-run-display.js +215 -25
  151. package/lib/infrastructure/admin-secrets-apply.js +84 -0
  152. package/lib/infrastructure/admin-secrets-ensure.js +130 -0
  153. package/lib/infrastructure/admin-secrets-resolve.js +95 -0
  154. package/lib/infrastructure/admin-secrets-sync.js +91 -0
  155. package/lib/infrastructure/helpers.js +23 -129
  156. package/lib/infrastructure/index.js +5 -6
  157. package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
  158. package/lib/lifecycle/certification-progress.js +231 -0
  159. package/lib/lifecycle/dataplane-ui-url.js +145 -0
  160. package/lib/lifecycle/exit-codes.js +24 -0
  161. package/lib/lifecycle/json-envelope.js +25 -0
  162. package/lib/lifecycle/lifecycle-governance-options.js +51 -0
  163. package/lib/lifecycle/logger-quiet.js +29 -0
  164. package/lib/lifecycle/open-api-published.js +59 -0
  165. package/lib/lifecycle/operations-readiness-metrics.js +101 -0
  166. package/lib/lifecycle/product-model.js +196 -0
  167. package/lib/lifecycle/report-display.js +471 -0
  168. package/lib/lifecycle/scenario-upload.js +191 -0
  169. package/lib/lifecycle/verify-step-progress.js +87 -0
  170. package/lib/parameters/infra-kv-discovery.js +27 -2
  171. package/lib/protection/auth-context.js +10 -4
  172. package/lib/schema/application-schema.json +1 -1
  173. package/lib/schema/datasource-test-run.schema.json +89 -6
  174. package/lib/schema/external-datasource.schema.json +2636 -2622
  175. package/lib/schema/external-system.schema.json +1089 -761
  176. package/lib/schema/infra.parameter.yaml +45 -0
  177. package/lib/schema/type/credential-field-registry.json +103 -97
  178. package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
  179. package/lib/utils/api.js +55 -31
  180. package/lib/utils/app-relative-path-env.js +112 -0
  181. package/lib/utils/cli-secrets-error-format.js +83 -21
  182. package/lib/utils/cli-utils.js +16 -4
  183. package/lib/utils/compose-generate-docker-compose.js +4 -0
  184. package/lib/utils/compose-traefik-ingress-base.js +16 -1
  185. package/lib/utils/config-secrets-path.js +46 -0
  186. package/lib/utils/controller-url.js +88 -1
  187. package/lib/utils/credential-secrets-env.js +137 -9
  188. package/lib/utils/dataplane-resolver.js +129 -2
  189. package/lib/utils/declarative-url-ports.js +3 -3
  190. package/lib/utils/deployment-auth-mode.js +41 -0
  191. package/lib/utils/developer-volume-id.js +33 -0
  192. package/lib/utils/env-copy.js +14 -9
  193. package/lib/utils/env-kv-orphan-lines.js +43 -0
  194. package/lib/utils/error-formatters/network-errors.js +13 -4
  195. package/lib/utils/external-env-template.js +1 -0
  196. package/lib/utils/external-system-readiness-core.js +10 -0
  197. package/lib/utils/external-system-readiness-display.js +80 -23
  198. package/lib/utils/health-check.js +4 -1
  199. package/lib/utils/help-builder.js +11 -8
  200. package/lib/utils/keycloak-realm-ready.js +101 -0
  201. package/lib/utils/load-cip-capacity-display-config.js +61 -15
  202. package/lib/utils/manifest-source-emit.js +2 -0
  203. package/lib/utils/pipeline-upload-auth-retry.js +82 -0
  204. package/lib/utils/platform-controller-url.js +156 -0
  205. package/lib/utils/postgres-platform-bootstrap.js +199 -0
  206. package/lib/utils/postgres-wipe.js +9 -2
  207. package/lib/utils/resolve-env-mode.js +47 -0
  208. package/lib/utils/secrets-generator.js +31 -25
  209. package/lib/utils/secrets-missing-error.js +164 -0
  210. package/lib/utils/service-url-label.js +81 -0
  211. package/lib/utils/setup-quiet-output.js +25 -0
  212. package/lib/utils/template-helpers.js +15 -0
  213. package/lib/utils/token-manager-client-credentials.js +201 -0
  214. package/lib/utils/token-manager-messages.js +8 -0
  215. package/lib/utils/token-manager-refresh.js +12 -2
  216. package/lib/utils/token-manager.js +86 -105
  217. package/lib/utils/upload-pipeline-ui.js +12 -5
  218. package/lib/utils/upload-sync-options.js +42 -0
  219. package/lib/utils/url-declarative-public-base.js +21 -3
  220. package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
  221. package/lib/utils/validation-poll-ui.js +8 -0
  222. package/lib/utils/validation-run-stage.js +45 -0
  223. package/package.json +1 -1
  224. package/templates/applications/dataplane/application.yaml +2 -1
  225. package/templates/applications/dataplane/env.template +24 -1
  226. package/templates/applications/miso-controller/env.template +16 -0
  227. package/templates/external-system/README.md.hbs +74 -17
  228. package/templates/python/docker-compose.hbs +19 -18
  229. package/templates/typescript/docker-compose.hbs +18 -17
  230. package/lib/commands/test-governance-command-action.js +0 -55
  231. package/lib/commands/test-trust-command-action.js +0 -118
@@ -0,0 +1,191 @@
1
+ /**
2
+ * @fileoverview Upload local governance scenario YAML packs to dataplane (419.0).
3
+ * @author AI Fabrix Team
4
+ * @version 1.0.0
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const path = require('path');
10
+ const {
11
+ existsSync,
12
+ readFileSync,
13
+ readdirSync,
14
+ mkdirSync,
15
+ writeFileSync
16
+ } = require('../internal/fs-real-sync');
17
+ const yaml = require('js-yaml');
18
+ const logger = require('../utils/logger');
19
+ const { getIntegrationPath } = require('../utils/paths');
20
+ const { upsertDatasourceGovernancePack } = require('../api/governance-scenario-pack.api');
21
+ const { formatSuccessLine, formatWarningLine } = require('../utils/cli-test-layout-chalk');
22
+ const { shortGovernanceApiError } = require('../governance/governance-cli-errors');
23
+ const { printGovernanceDownloadMisses } = require('../governance/governance-download-display');
24
+
25
+ /**
26
+ * @param {string} scenariosDir
27
+ * @returns {string[]}
28
+ */
29
+ function listScenarioYamlFiles(scenariosDir) {
30
+ if (!existsSync(scenariosDir)) return [];
31
+ return readdirSync(scenariosDir)
32
+ .filter(name => name.endsWith('.yaml') || name.endsWith('.yml'))
33
+ .map(name => path.join(scenariosDir, name));
34
+ }
35
+
36
+ /**
37
+ * Extract datasource keys referenced in a pack document.
38
+ * @param {Object} pack
39
+ * @returns {string[]}
40
+ */
41
+ function datasourceKeysFromPack(pack) {
42
+ const keys = new Set();
43
+ const scenarios = pack?.spec?.scenarios || [];
44
+ for (const scenario of scenarios) {
45
+ const dsKeys = scenario?.search?.datasourceKeys || [];
46
+ for (const k of dsKeys) {
47
+ if (k && typeof k === 'string') keys.add(k.trim());
48
+ }
49
+ }
50
+ return [...keys];
51
+ }
52
+
53
+ /**
54
+ * @param {string} filePath
55
+ * @returns {Object}
56
+ */
57
+ function loadPackFromFile(filePath) {
58
+ const raw = readFileSync(filePath, 'utf8');
59
+ const doc = yaml.load(raw);
60
+ if (!doc || typeof doc !== 'object') {
61
+ throw new Error(`Invalid scenario pack YAML: ${filePath}`);
62
+ }
63
+ return doc;
64
+ }
65
+
66
+ /**
67
+ * Upload scenario packs under integration/<systemKey>/scenarios/ to dataplane.
68
+ * @async
69
+ * @param {string} systemKey
70
+ * @param {string} dataplaneUrl
71
+ * @param {Object} authConfig
72
+ * @param {{ silent?: boolean }} [opts]
73
+ * @returns {Promise<number>} count of packs uploaded
74
+ */
75
+ async function uploadGovernanceScenarioPacks(systemKey, dataplaneUrl, authConfig, opts = {}) {
76
+ const scenariosDir = path.join(getIntegrationPath(systemKey), 'scenarios');
77
+ const files = listScenarioYamlFiles(scenariosDir);
78
+ if (files.length === 0) return 0;
79
+
80
+ let uploaded = 0;
81
+ for (const filePath of files) {
82
+ const pack = loadPackFromFile(filePath);
83
+ const dsKeys = datasourceKeysFromPack(pack);
84
+ if (dsKeys.length === 0) {
85
+ if (!opts.silent) {
86
+ logger.log(
87
+ formatWarningLine(
88
+ `Skipping ${path.basename(filePath)} — no datasourceKeys in scenarios`
89
+ )
90
+ );
91
+ }
92
+ continue;
93
+ }
94
+ for (const dsKey of dsKeys) {
95
+ await upsertDatasourceGovernancePack(dataplaneUrl, authConfig, dsKey, pack);
96
+ uploaded += 1;
97
+ if (!opts.silent) {
98
+ logger.log(
99
+ formatSuccessLine(
100
+ `Governance scenario pack uploaded for ${dsKey} (${path.basename(filePath)})`
101
+ )
102
+ );
103
+ }
104
+ }
105
+ }
106
+ return uploaded;
107
+ }
108
+
109
+ /**
110
+ * Write governance scenario packs from dataplane to integration/<systemKey>/scenarios/.
111
+ * @async
112
+ * @param {string} systemKey
113
+ * @param {string[]} datasourceKeys
114
+ * @param {string} dataplaneUrl
115
+ * @param {Object} authConfig
116
+ * @returns {Promise<number>}
117
+ */
118
+ async function downloadGovernanceScenarioPacks(
119
+ systemKey,
120
+ datasourceKeys,
121
+ dataplaneUrl,
122
+ authConfig
123
+ ) {
124
+ const { getDatasourceGovernancePack } = require('../api/governance-scenario-pack.api');
125
+ const scenariosDir = path.join(getIntegrationPath(systemKey), 'scenarios');
126
+ if (!existsSync(scenariosDir)) {
127
+ mkdirSync(scenariosDir, { recursive: true });
128
+ }
129
+
130
+ let written = 0;
131
+ const missing = [];
132
+ for (const dsKey of datasourceKeys) {
133
+ try {
134
+ const row = await getDatasourceGovernancePack(dataplaneUrl, authConfig, dsKey);
135
+ if (!row || !row.pack) {
136
+ missing.push({
137
+ datasourceKey: dsKey,
138
+ reason: 'No active pack on dataplane'
139
+ });
140
+ continue;
141
+ }
142
+ const outPath = path.join(scenariosDir, `${dsKey}.yaml`);
143
+ writeFileSync(outPath, yaml.dump(row.pack, { lineWidth: 120 }), 'utf8');
144
+ written += 1;
145
+ logger.log(formatSuccessLine(`Scenario pack saved: ${outPath}`));
146
+ } catch (err) {
147
+ missing.push({
148
+ datasourceKey: dsKey,
149
+ reason: shortGovernanceApiError(err)
150
+ });
151
+ }
152
+ }
153
+ printGovernanceDownloadMisses(missing);
154
+ return written;
155
+ }
156
+
157
+ /**
158
+ * Download governance packs for all datasource keys on a running manifest.
159
+ * @async
160
+ * @param {string} systemKey
161
+ * @param {Object} manifest
162
+ * @param {string} dataplaneUrl
163
+ * @param {Object} authConfig
164
+ * @returns {Promise<number>}
165
+ */
166
+ async function downloadGovernanceScenarioPacksFromManifest(
167
+ systemKey,
168
+ manifest,
169
+ dataplaneUrl,
170
+ authConfig
171
+ ) {
172
+ const dsKeys = (manifest.dataSources || []).map((ds) => ds && ds.key).filter(Boolean);
173
+ if (dsKeys.length === 0) {
174
+ return 0;
175
+ }
176
+ try {
177
+ return await downloadGovernanceScenarioPacks(systemKey, dsKeys, dataplaneUrl, authConfig);
178
+ } catch (err) {
179
+ logger.log(formatWarningLine(`Governance scenario download skipped: ${err.message}`));
180
+ return 0;
181
+ }
182
+ }
183
+
184
+ module.exports = {
185
+ listScenarioYamlFiles,
186
+ datasourceKeysFromPack,
187
+ loadPackFromFile,
188
+ uploadGovernanceScenarioPacks,
189
+ downloadGovernanceScenarioPacks,
190
+ downloadGovernanceScenarioPacksFromManifest
191
+ };
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Active progress (ora spinner or single ⏳ line) for verify-* orchestration steps.
3
+ *
4
+ * @fileoverview Verify step progress UI
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('../utils/logger');
13
+ const { formatProgress } = require('../utils/cli-test-layout-chalk');
14
+ const { withQuietLogs } = require('./logger-quiet');
15
+
16
+ /**
17
+ * @param {Object} [options]
18
+ * @returns {boolean}
19
+ */
20
+ function shouldShowVerifyStepProgress(options = {}) {
21
+ return options.json !== true;
22
+ }
23
+
24
+ /**
25
+ * @param {Object} [options]
26
+ * @returns {boolean}
27
+ */
28
+ function shouldUseVerifyStepSpinner(options = {}) {
29
+ if (!shouldShowVerifyStepProgress(options)) {
30
+ return false;
31
+ }
32
+ return Boolean(process && process.stdout && process.stdout.isTTY);
33
+ }
34
+
35
+ /**
36
+ * @param {string} label
37
+ * @returns {string}
38
+ */
39
+ function formatVerifyStepLabel(label) {
40
+ const text = label && String(label).trim() ? String(label).trim() : 'Processing';
41
+ return text.endsWith('…') ? text : `${text}…`;
42
+ }
43
+
44
+ /**
45
+ * Run a verify step with one active progress indicator (spinner on TTY).
46
+ *
47
+ * @template T
48
+ * @async
49
+ * @param {string} label - Plain label without trailing ellipsis
50
+ * @param {(progress: { setLabel: (next: string) => void }) => Promise<T>} work
51
+ * @param {Object} [options]
52
+ * @param {boolean} [options.json]
53
+ * @returns {Promise<T>}
54
+ */
55
+ async function runWithVerifyStepProgress(label, work, options = {}) {
56
+ if (!shouldShowVerifyStepProgress(options)) {
57
+ return withQuietLogs(() => work({ setLabel: () => {} }));
58
+ }
59
+
60
+ if (!shouldUseVerifyStepSpinner(options)) {
61
+ logger.log(formatProgress(formatVerifyStepLabel(label)));
62
+ return withQuietLogs(() => work({ setLabel: () => {} }));
63
+ }
64
+
65
+ const ora = require('ora');
66
+ const spinner = ora({
67
+ text: chalk.white(formatVerifyStepLabel(label)),
68
+ spinner: 'dots'
69
+ }).start();
70
+
71
+ const setLabel = (next) => {
72
+ spinner.text = chalk.white(formatVerifyStepLabel(next));
73
+ };
74
+
75
+ try {
76
+ return await withQuietLogs(() => work({ setLabel }));
77
+ } finally {
78
+ spinner.stop();
79
+ }
80
+ }
81
+
82
+ module.exports = {
83
+ shouldShowVerifyStepProgress,
84
+ shouldUseVerifyStepSpinner,
85
+ formatVerifyStepLabel,
86
+ runWithVerifyStepProgress
87
+ };
@@ -6,7 +6,10 @@
6
6
 
7
7
  const fsRealSync = require('../internal/fs-real-sync');
8
8
  const path = require('path');
9
- const { loadRequiresDatabasesArray } = require('./database-secret-values');
9
+ const { loadRequiresDatabasesArray, loadShippedRequiresDatabases } = require('./database-secret-values');
10
+
11
+ /** Platform apps from shipped templates (setup/up-infra before builder/ is copied). */
12
+ const SHIPPED_PLATFORM_APP_KEYS = ['keycloak', 'miso-controller', 'dataplane'];
10
13
 
11
14
  /**
12
15
  * Extract kv:// secret key names from env template content (active lines only).
@@ -90,6 +93,25 @@ function deriveDatabaseKvKeysFromWorkspace(pathsUtil) {
90
93
  return [...keys];
91
94
  }
92
95
 
96
+ /**
97
+ * Database kv keys from shipped platform templates when builder/ apps are not copied yet
98
+ * (e.g. `aifabrix setup` fresh install before `up-platform`).
99
+ *
100
+ * @returns {string[]}
101
+ */
102
+ function deriveDatabaseKvKeysFromShippedPlatformTemplates() {
103
+ const keys = new Set();
104
+ for (const appKey of SHIPPED_PLATFORM_APP_KEYS) {
105
+ const dbs = loadShippedRequiresDatabases(appKey);
106
+ if (!Array.isArray(dbs) || dbs.length === 0) continue;
107
+ for (let i = 0; i < dbs.length; i++) {
108
+ keys.add(`databases-${appKey}-${i}-urlKeyVault`);
109
+ keys.add(`databases-${appKey}-${i}-passwordKeyVault`);
110
+ }
111
+ }
112
+ return [...keys];
113
+ }
114
+
93
115
  /**
94
116
  * Keys from env.template files whose catalog entry includes the given hook (e.g. upInfra).
95
117
  * @param {object} pathsUtil - paths module
@@ -132,6 +154,7 @@ function getAllInfraEnsureKeys(catalog, pathsUtil) {
132
154
  const set = new Set();
133
155
  for (const k of catalog.getStandardUpInfraBootstrapKeys()) set.add(k);
134
156
  for (const k of deriveDatabaseKvKeysFromWorkspace(pathsUtil)) set.add(k);
157
+ for (const k of deriveDatabaseKvKeysFromShippedPlatformTemplates()) set.add(k);
135
158
  for (const k of discoverKvKeysFromEnvTemplatesForHook(pathsUtil, 'upInfra', catalog)) set.add(k);
136
159
  return [...set].sort();
137
160
  }
@@ -139,8 +162,10 @@ function getAllInfraEnsureKeys(catalog, pathsUtil) {
139
162
  module.exports = {
140
163
  extractKvKeysFromEnvContent,
141
164
  deriveDatabaseKvKeysFromWorkspace,
165
+ deriveDatabaseKvKeysFromShippedPlatformTemplates,
142
166
  discoverKvKeysFromEnvTemplatesForHook,
143
167
  getAllInfraEnsureKeys,
144
168
  listAppDirsForDiscovery,
145
- listBuilderAppDirsForDiscovery
169
+ listBuilderAppDirsForDiscovery,
170
+ SHIPPED_PLATFORM_APP_KEYS
146
171
  };
@@ -9,6 +9,7 @@
9
9
  const { resolveControllerUrl } = require('../utils/controller-url');
10
10
  const { resolveEnvironment } = require('../core/config');
11
11
  const { getDeviceOnlyAuth, getDeploymentAuth } = require('../utils/token-manager');
12
+ const { getDeploymentAuthMode } = require('../utils/deployment-auth-mode');
12
13
  const { resolveDataplaneUrl } = require('../utils/dataplane-resolver');
13
14
 
14
15
  /**
@@ -23,11 +24,16 @@ async function resolveProtectionDataplaneContext(options = {}) {
23
24
  throw new Error('Controller URL is required. Run "aifabrix login" first.');
24
25
  }
25
26
 
27
+ const authMode = getDeploymentAuthMode(options);
26
28
  let authConfig;
27
- try {
28
- authConfig = await getDeviceOnlyAuth(controllerUrl);
29
- } catch {
30
- authConfig = await getDeploymentAuth(controllerUrl, environment, 'dataplane');
29
+ if (authMode === 'client-credentials') {
30
+ authConfig = await getDeploymentAuth(controllerUrl, environment, 'dataplane', options);
31
+ } else {
32
+ try {
33
+ authConfig = await getDeviceOnlyAuth(controllerUrl);
34
+ } catch {
35
+ authConfig = await getDeploymentAuth(controllerUrl, environment, 'dataplane', options);
36
+ }
31
37
  }
32
38
 
33
39
  if (!authConfig?.token) {
@@ -34,7 +34,7 @@
34
34
  "version": "1.4.0",
35
35
  "date": "2026-04-06T00:00:00Z",
36
36
  "changes": [
37
- "Removed build.localPort: local workstation PORT and localhost URL rewriting use the root-level manifest port only, with local host port = port + 10 + developerId*100 (developer id 0 → port+10). Docker published host port remains port + developerId*100.",
37
+ "Removed build.localPort: local workstation PORT and localhost URL rewriting use the root-level manifest port only, with host port = port + developerId*100 (developer id 0 → port). Same formula for Docker publish and aifabrix run.",
38
38
  "Migration: delete build.localPort from application.yaml; set or keep port as the single listen/container port. Use url://public, url://internal, or url://<app>-public|internal in env.template for declarative URLs (resolved after kv://)."
39
39
  ],
40
40
  "breaking": true
@@ -2,20 +2,25 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "aifabrix://schema/datasource-test-run.schema.json",
4
4
  "title": "DatasourceTestRun",
5
- "description": "Canonical datasource-root test report (plans 362/365). Public success shape for POST /api/v1/validation/run (and async poll GET /validation/run/{testRunId}). runType=test|integration|e2e; CLI/docs may say test | test-integration | test-e2e; public JSON uses runType only. Includes validation layer (machine/explain), certificate snapshot, optional integration pipeline results, capability E2Es, debug by reference, plural audit refs, developer summaries. Forward-compatible: minor reportVersion bumps may add fields.",
5
+ "description": "Canonical datasource-root test report (plans 362/365, 370.06, 370.07 stage). Public success shape for POST /api/v1/validation/run (and async poll GET /validation/run/{testRunId}). runType=test|integration|e2e; stage=readiness|simulation|integration|e2e. reportVersion 1.5.0 adds required stage (minor bump). Older clients must tolerate absent stage when reportVersion < 1.5.0.",
6
6
  "type": "object",
7
- "required": ["reportVersion", "datasourceKey", "systemKey", "runType", "status"],
7
+ "required": ["reportVersion", "datasourceKey", "systemKey", "runType", "stage", "status"],
8
8
  "properties": {
9
9
  "reportVersion": {
10
10
  "type": "string",
11
11
  "description": "Semver-style contract version for this envelope. Policy: additive fields => minor bump within same major; removed/renamed fields => major bump. Route migrations must cite target reportVersion.",
12
- "example": "1.3.0"
12
+ "example": "1.5.0"
13
13
  },
14
14
  "runType": {
15
15
  "type": "string",
16
- "description": "Kind of run. Maps to CLI/commands: test=test, test-integration=integration, test-e2e=e2e. Do not use kebab strings inside runType.",
16
+ "description": "Legacy kind of run. Maps to CLI: test, test-integration, test-e2e. Prefer stage for new clients.",
17
17
  "enum": ["test", "integration", "e2e"]
18
18
  },
19
+ "stage": {
20
+ "type": "string",
21
+ "description": "Contract validation stage aligned with contracts/rules stage and concept appliesTo.",
22
+ "enum": ["readiness", "simulation", "integration", "e2e"]
23
+ },
19
24
  "status": {
20
25
  "type": "string",
21
26
  "description": "Root rollup across validation, integration, certificate, and capabilities for this datasource run: ok | warn | fail | skipped.",
@@ -252,7 +257,7 @@
252
257
  "level": {
253
258
  "type": "string",
254
259
  "description": "Achieved certification tier when applicable.",
255
- "enum": ["bronze", "silver", "gold"]
260
+ "enum": ["bronze", "silver", "gold", "platinum"]
256
261
  },
257
262
  "summary": {
258
263
  "type": "string",
@@ -388,6 +393,61 @@
388
393
  }
389
394
  }
390
395
  },
396
+ "FixInstruction": {
397
+ "type": "object",
398
+ "additionalProperties": false,
399
+ "required": ["step"],
400
+ "description": "One deterministic repair step (370.03 fixInstruction vocabulary).",
401
+ "properties": {
402
+ "step": {
403
+ "type": "string",
404
+ "enum": [
405
+ "locate_file",
406
+ "update_path",
407
+ "add_mapping",
408
+ "set_value",
409
+ "remove_value",
410
+ "add_item",
411
+ "remove_item",
412
+ "explain"
413
+ ]
414
+ },
415
+ "value": {
416
+ "type": "string",
417
+ "description": "Brace tokens only in authored YAML: {datasource}, {systemKey}, {field}, {raw.*}."
418
+ },
419
+ "path": { "type": "string" },
420
+ "template": { "type": "string" },
421
+ "note": { "type": "string" }
422
+ }
423
+ },
424
+ "IssueFix": {
425
+ "type": "object",
426
+ "additionalProperties": false,
427
+ "required": ["type", "instructions"],
428
+ "description": "Structured remediation on Issue (370.06; aligned with rule YAML fix).",
429
+ "properties": {
430
+ "type": {
431
+ "type": "string",
432
+ "enum": [
433
+ "add_mapping",
434
+ "edit_schema",
435
+ "edit_exposure",
436
+ "edit_governance",
437
+ "edit_execution",
438
+ "generic"
439
+ ]
440
+ },
441
+ "instructions": {
442
+ "type": "array",
443
+ "minItems": 1,
444
+ "items": { "$ref": "#/$defs/FixInstruction" }
445
+ },
446
+ "example": {
447
+ "description": "Optional structured or scalar example for authors/tooling."
448
+ }
449
+ }
450
+ },
391
451
  "Issue": {
392
452
  "type": "object",
393
453
  "required": ["message"],
@@ -395,7 +455,7 @@
395
455
  "properties": {
396
456
  "code": {
397
457
  "type": "string",
398
- "description": "Stable code: DP-VAL-* (structural/config), DP-CIP-* (execution/CIP), DP-SEC-* (auth/RBAC/exposure), DP-CONN-* (REST/MCP/connectivity), DP-E2E-* (end-to-end live); warnings DP-*-Wnn. Mapped from engine errorCode in DatasourceTestRun builders.",
458
+ "description": "Stable code: DP-VAL-* (structural/config), DP-CIP-* (execution/CIP), DP-SEC-* (auth/RBAC/exposure), DP-CONN-* (REST/MCP/connectivity), DP-E2E-* (end-to-end live); warnings DP-*-Wnn. Prefer stableCode when present; otherwise mapped from engine errorCode.",
399
459
  "example": "DP-CIP-010"
400
460
  },
401
461
  "message": {
@@ -410,6 +470,29 @@
410
470
  "hint": {
411
471
  "type": "string",
412
472
  "description": "Remediation or next-step hint."
473
+ },
474
+ "conceptId": {
475
+ "type": "string",
476
+ "description": "Concept catalog id (370.02) for concept-first organization."
477
+ },
478
+ "ruleId": {
479
+ "type": "string",
480
+ "description": "YAML rule id when the finding came from the contract rule set.",
481
+ "example": "VAL-PIL-001"
482
+ },
483
+ "stableCode": {
484
+ "type": "string",
485
+ "description": "Frozen DP-* stable code from rule YAML.",
486
+ "example": "DP-VAL-097"
487
+ },
488
+ "ruleRefs": {
489
+ "type": "array",
490
+ "items": { "type": "string" },
491
+ "description": "Legacy or supplemental rule references; prefer ruleId + stableCode for YAML rules."
492
+ },
493
+ "fix": {
494
+ "$ref": "#/$defs/IssueFix",
495
+ "description": "Structured fix instructions when the emitting rule supplies them."
413
496
  }
414
497
  }
415
498
  },