@aifabrix/builder 2.45.0 → 2.45.5

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 (180) hide show
  1. package/.cursor/rules/docs-rules.mdc +3 -1
  2. package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
  3. package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
  4. package/integration/hubspot-test/wizard-hubspot-e2e.yaml +1 -1
  5. package/jest.projects.js +44 -1
  6. package/lib/api/agent-metadata-validation.api.js +93 -0
  7. package/lib/api/audit-api-helpers.js +68 -0
  8. package/lib/api/audit.api.js +119 -0
  9. package/lib/api/auth-cache.api.js +44 -0
  10. package/lib/api/certificates.api.js +4 -4
  11. package/lib/api/credential.api.js +2 -2
  12. package/lib/api/dataplane-health.api.js +137 -0
  13. package/lib/api/dataplane-sync.api.js +27 -0
  14. package/lib/api/datasources-core.api.js +21 -18
  15. package/lib/api/datasources-extended.api.js +22 -22
  16. package/lib/api/dimensions.api.js +3 -0
  17. package/lib/api/external-systems.api.js +13 -13
  18. package/lib/api/governance-scenarios.api.js +39 -0
  19. package/lib/api/groups.api.js +79 -0
  20. package/lib/api/index.js +45 -2
  21. package/lib/api/pipeline.api.js +4 -4
  22. package/lib/api/protection.api.js +157 -0
  23. package/lib/api/records-bulk.api.js +30 -0
  24. package/lib/api/records-search-parse.js +49 -0
  25. package/lib/api/records-search.api.js +29 -0
  26. package/lib/api/types/agent-metadata-validation.types.js +67 -0
  27. package/lib/api/types/audit.types.js +72 -0
  28. package/lib/api/types/dataplane-health.types.js +27 -0
  29. package/lib/api/types/dimensions.types.js +2 -0
  30. package/lib/api/types/governance-scenarios.types.js +39 -0
  31. package/lib/api/types/protection.types.js +69 -0
  32. package/lib/api/types/records-bulk.types.js +35 -0
  33. package/lib/api/types/records-search.types.js +28 -0
  34. package/lib/api/user-groups.api.js +50 -0
  35. package/lib/api/users.api.js +95 -0
  36. package/lib/api/validation-run.api.js +3 -3
  37. package/lib/api/validation-runner.js +3 -3
  38. package/lib/api/wizard-platform.api.js +3 -3
  39. package/lib/api/wizard.api.js +21 -21
  40. package/lib/app/deploy.js +34 -19
  41. package/lib/cli/index.js +4 -2
  42. package/lib/cli/infra-guided.js +22 -3
  43. package/lib/cli/setup-app.help.js +50 -2
  44. package/lib/cli/setup-app.js +33 -24
  45. package/lib/cli/setup-app.test-commands.js +80 -21
  46. package/lib/cli/setup-auth.js +30 -3
  47. package/lib/cli/setup-external-system.js +37 -3
  48. package/lib/cli/setup-utility-help-after.js +45 -0
  49. package/lib/cli/setup-utility-resolve.js +2 -2
  50. package/lib/cli/setup-utility.js +99 -81
  51. package/lib/commands/auth-status-dataplane-version.js +231 -0
  52. package/lib/commands/auth-status-display.js +94 -0
  53. package/lib/commands/auth-status.js +70 -6
  54. package/lib/commands/credential-push.js +10 -5
  55. package/lib/commands/datasource-load-export-cli.js +178 -0
  56. package/lib/commands/datasource-test-trust-cli.js +114 -0
  57. package/lib/commands/datasource-unified-test-cli.js +25 -17
  58. package/lib/commands/datasource-unified-test-cli.options.js +18 -3
  59. package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +5 -5
  60. package/lib/commands/datasource-verify-audit-cli.js +96 -0
  61. package/lib/commands/datasource.js +68 -1
  62. package/lib/commands/dimension-value.js +43 -13
  63. package/lib/commands/dimension.js +38 -7
  64. package/lib/commands/identity-apply-sync.js +131 -0
  65. package/lib/commands/identity-group-cli.js +146 -0
  66. package/lib/commands/identity-membership-role-cache.js +175 -0
  67. package/lib/commands/identity-shared.js +94 -0
  68. package/lib/commands/identity-user-cli.js +158 -0
  69. package/lib/commands/identity.js +43 -0
  70. package/lib/commands/login.js +46 -16
  71. package/lib/commands/protection-cli-leaves.js +286 -0
  72. package/lib/commands/protection.js +50 -0
  73. package/lib/commands/repair.js +13 -3
  74. package/lib/commands/test-e2e-external.js +40 -9
  75. package/lib/commands/test-governance-cli-options.js +47 -0
  76. package/lib/commands/test-governance-command-action.js +55 -0
  77. package/lib/commands/test-governance-external.js +88 -0
  78. package/lib/commands/test-trust-cli-options.js +32 -0
  79. package/lib/commands/test-trust-command-action.js +118 -0
  80. package/lib/commands/test-trust-external.js +127 -0
  81. package/lib/commands/upload.js +34 -13
  82. package/lib/commands/wizard-core.js +3 -0
  83. package/lib/core/config-device-dataplane.js +185 -0
  84. package/lib/datasource/agent-trust-debug-log.js +45 -0
  85. package/lib/datasource/agent-trust-fetch.js +115 -0
  86. package/lib/datasource/agent-trust-map.js +101 -0
  87. package/lib/datasource/agent-trust-mock.js +44 -0
  88. package/lib/datasource/agent-trust-run.js +93 -0
  89. package/lib/datasource/agent-trust-timeout.js +25 -0
  90. package/lib/datasource/audit-evidence-display.js +80 -0
  91. package/lib/datasource/audit-evidence-extract-debug.js +103 -0
  92. package/lib/datasource/audit-evidence-extract.js +177 -0
  93. package/lib/datasource/audit-evidence-matrix-rows.js +158 -0
  94. package/lib/datasource/audit-evidence-operation-aliases.js +63 -0
  95. package/lib/datasource/audit-evidence-poll.js +109 -0
  96. package/lib/datasource/audit-evidence-run.js +177 -0
  97. package/lib/datasource/audit-evidence-verify-helpers.js +167 -0
  98. package/lib/datasource/audit-evidence-verify-matrix.js +177 -0
  99. package/lib/datasource/audit-evidence-verify.js +108 -0
  100. package/lib/datasource/bulk-loader-run-batches.js +88 -0
  101. package/lib/datasource/bulk-loader-service-retry.js +52 -0
  102. package/lib/datasource/bulk-loader-service.js +127 -0
  103. package/lib/datasource/capability/run-capability-dimension.js +2 -1
  104. package/lib/datasource/datasource-exporter-resolve.js +82 -0
  105. package/lib/datasource/datasource-exporter-service.js +144 -0
  106. package/lib/datasource/datasource-identifier.js +148 -0
  107. package/lib/datasource/datasource-load-export-context.js +92 -0
  108. package/lib/datasource/integration-context.js +6 -4
  109. package/lib/datasource/local-data-paths.js +145 -0
  110. package/lib/datasource/log-cleaner.js +241 -0
  111. package/lib/datasource/log-viewer.js +111 -6
  112. package/lib/datasource/record-file-parser.js +85 -0
  113. package/lib/datasource/record-mapper.js +129 -0
  114. package/lib/datasource/resolve-app.js +74 -55
  115. package/lib/datasource/test-e2e.js +26 -2
  116. package/lib/datasource/unified-validation-run-resolve.js +45 -12
  117. package/lib/datasource/unified-validation-run.js +43 -17
  118. package/lib/datasource/validate.js +37 -20
  119. package/lib/external-system/test-system-level.js +25 -4
  120. package/lib/external-system/test.js +3 -1
  121. package/lib/governance/governance-pack-loader.js +70 -0
  122. package/lib/governance/governance-run-display.js +119 -0
  123. package/lib/identity/identity-apply-core.js +108 -0
  124. package/lib/identity/identity-apply-phases.js +244 -0
  125. package/lib/identity/identity-apply-service.js +77 -0
  126. package/lib/identity/identity-csv-parser.js +114 -0
  127. package/lib/internal/fs-real-sync.js +29 -1
  128. package/lib/protection/auth-context.js +45 -0
  129. package/lib/protection/convert-batch.js +90 -0
  130. package/lib/protection/load.js +41 -0
  131. package/lib/protection/paths.js +158 -0
  132. package/lib/protection/preflight-datasource-ready.js +46 -0
  133. package/lib/protection/protection-create-probe-lines.js +142 -0
  134. package/lib/protection/protection-create-probes.js +95 -0
  135. package/lib/protection/protection-create-scaffold.js +281 -0
  136. package/lib/protection/protection-display-helpers.js +445 -0
  137. package/lib/protection/protection-display.js +215 -0
  138. package/lib/protection/protection-preset-registry.js +97 -0
  139. package/lib/protection/report-exit.js +62 -0
  140. package/lib/protection/resolve.js +202 -0
  141. package/lib/protection/run-commands-validate.js +130 -0
  142. package/lib/protection/run-commands.js +216 -0
  143. package/lib/protection/run-protection-create-helpers.js +134 -0
  144. package/lib/protection/run-protection-create-probes-flow.js +43 -0
  145. package/lib/protection/run-protection-create.js +191 -0
  146. package/lib/protection/scope.js +22 -0
  147. package/lib/protection/sync-after-upload.js +64 -0
  148. package/lib/protection/upload-batch.js +127 -0
  149. package/lib/protection/validate-batch.js +113 -0
  150. package/lib/protection/validate-local.js +65 -0
  151. package/lib/resolvers/dimension-file.js +29 -4
  152. package/lib/schema/external-datasource.schema.json +47 -13
  153. package/lib/schema/flag-map-validation-run.json +2 -2
  154. package/lib/schema/protection.schema.json +374 -0
  155. package/lib/schema/type/credential-field-registry.json +636 -0
  156. package/lib/schema/wizard-config.schema.json +1 -1
  157. package/lib/utils/agent-trust-run-display.js +231 -0
  158. package/lib/utils/agent-trust-run-exit.js +59 -0
  159. package/lib/utils/agent-trust-wait-ui.js +94 -0
  160. package/lib/utils/cli-exit-codes.js +30 -0
  161. package/lib/utils/cli-sync-options.js +33 -0
  162. package/lib/utils/credential-push-ui.js +90 -0
  163. package/lib/utils/dataplane-cli-version-gate.js +202 -0
  164. package/lib/utils/dataplane-cli-version-help.js +74 -0
  165. package/lib/utils/datasource-export-display.js +137 -0
  166. package/lib/utils/datasource-load-display.js +174 -0
  167. package/lib/utils/datasource-load-export-ui.js +120 -0
  168. package/lib/utils/datasource-test-run-capability-scope.js +3 -3
  169. package/lib/utils/datasource-test-run-display.js +3 -3
  170. package/lib/utils/datasource-test-run-tty-log.js +5 -1
  171. package/lib/utils/help-builder.js +30 -24
  172. package/lib/utils/manifest-source-emit.js +22 -0
  173. package/lib/utils/semver-compare.js +127 -0
  174. package/lib/utils/upload-pipeline-ui.js +91 -0
  175. package/lib/utils/validation-poll-ui.js +14 -7
  176. package/lib/validation/wizard-config-validator.js +58 -19
  177. package/package.json +1 -1
  178. package/templates/applications/dataplane/env.template +13 -1
  179. package/templates/applications/dataplane/rbac.yaml +4 -0
  180. package/templates/external-system/README.md.hbs +56 -8
@@ -16,14 +16,23 @@ const { setupInstallTestE2eLintCommands } = require('./setup-app.test-commands')
16
16
 
17
17
  const CREATE_HELP_AFTER = `
18
18
  Examples:
19
+ # Builder app → builder/<appKey>/
19
20
  $ aifabrix create myapi --type webapp -l typescript
20
- $ aifabrix create mycrm --wizard
21
+ $ aifabrix create mysvc --type api -l python
22
+
23
+ # External system → integration/<systemKey>/ (default --type external)
24
+ $ aifabrix create hubspot --wizard
25
+ $ aifabrix create mycrm --type external --display-name "My CRM" --description "..." \\
26
+ --system-type openapi --auth-type oauth2 --entity-type recordStorage --datasources 1
27
+
28
+ Positional: appKey for builder types; systemKey for --type external (folder under integration/).
29
+ Prefer aifabrix wizard [systemKey] for guided external setup.
21
30
  `;
22
31
 
23
32
  const DEPLOY_HELP_AFTER = `
24
33
  Examples:
25
- $ aifabrix deploy myapp
26
- $ aifabrix deploy myext --local
34
+ $ aifabrix deploy myapp # builder appKey → builder/myapp/
35
+ $ aifabrix deploy hubspot --local # systemKey → integration/hubspot/
27
36
  `;
28
37
 
29
38
  const PUSH_HELP_AFTER = `
@@ -133,8 +142,8 @@ async function handleCreateCommand(appName, options) {
133
142
  }
134
143
 
135
144
  function setupCreateCommand(program) {
136
- program.command('create <app>')
137
- .description('Scaffold builder or external app (flags or --wizard)')
145
+ program.command('create <appKey|systemKey>')
146
+ .description('Create builder app (builder/<appKey>/) or external system (integration/<systemKey>/; --type, flags, or --wizard)')
138
147
  .addHelpText('after', CREATE_HELP_AFTER)
139
148
  .option('-p, --port <port>', 'Application port', '3000')
140
149
  .option('-d, --database', 'Requires database')
@@ -148,7 +157,7 @@ function setupCreateCommand(program) {
148
157
  .option('-g, --github', 'Generate GitHub Actions workflows')
149
158
  .option('--github-steps <steps>', 'Extra GitHub workflow steps (comma-separated, e.g., npm,test)')
150
159
  .option('--main-branch <branch>', 'Main branch name for workflows', 'main')
151
- .option('--wizard', 'Use interactive wizard for external system creation')
160
+ .option('--wizard', 'Run wizard for external system (systemKey → integration/<systemKey>/; same as aifabrix wizard)')
152
161
  .option('--display-name <name>', 'External system display name')
153
162
  .option('--description <desc>', 'External system description')
154
163
  .option('--system-type <type>', 'External system type (openapi, mcp, custom)')
@@ -209,8 +218,8 @@ Examples:
209
218
  $ aifabrix run myapp --base
210
219
  $ aifabrix run myapp --reload
211
220
  $ aifabrix run myapp --no-proxy # same as --proxy false: localhost for Docker declarative public URLs; saves applications.<app>.proxy: false`;
212
- program.command('run <app>')
213
- .description('Run app locally or on remote Docker host')
221
+ program.command('run <appKey>')
222
+ .description('Run builder app by appKey locally or on remote Docker host')
214
223
  .option('-p, --port <port>', 'Override local port')
215
224
  .option('-d, --debug', 'Enable debug output with detailed container information')
216
225
  .option('-t, --tag <tag>', 'Image tag to run (e.g. v1.0.0); overrides application.yaml image.tag')
@@ -238,8 +247,8 @@ Examples:
238
247
  }
239
248
 
240
249
  function setupBuildRunLogsDownCommands(program) {
241
- program.command('build <app>')
242
- .description('Build Docker image (auto-detect runtime)')
250
+ program.command('build <appKey>')
251
+ .description('Build Docker image for builder appKey (auto-detect runtime)')
243
252
  .option('-l, --language <lang>', 'Override language detection')
244
253
  .option('-f, --force-template', 'Force rebuild from template')
245
254
  .option('--no-cache', 'Full Docker rebuild (disable layer cache); use after Dockerfile or context fixes')
@@ -257,8 +266,8 @@ function setupBuildRunLogsDownCommands(program) {
257
266
 
258
267
  registerRunCommand(program);
259
268
 
260
- program.command('logs <app>')
261
- .description('Tail app container logs (optional env summary; secrets masked)')
269
+ program.command('logs <appKey>')
270
+ .description('Tail container logs for appKey (optional env summary; secrets masked)')
262
271
  .option('-f', 'Follow log stream')
263
272
  .option('-t, --tail <lines>', 'Number of lines (default: 100); 0 = full list', '100')
264
273
  .option('-l, --level <level>', 'Show only logs at this level or above (debug|info|warn|error)')
@@ -275,8 +284,8 @@ function setupBuildRunLogsDownCommands(program) {
275
284
  }
276
285
  });
277
286
 
278
- program.command('down-app <app>')
279
- .description('Stop and remove app container (--volumes removes data volume)')
287
+ program.command('down-app <appKey>')
288
+ .description('Stop and remove container for appKey (--volumes removes data volume)')
280
289
  .option('--volumes', 'Remove application Docker volume')
281
290
  .action(async(appName, options) => {
282
291
  try {
@@ -290,8 +299,8 @@ function setupBuildRunLogsDownCommands(program) {
290
299
  }
291
300
 
292
301
  function setupShellTestStopCommands(program) {
293
- program.command('stop <app>')
294
- .description('Alias for down-app: stop and remove container')
302
+ program.command('stop <appKey>')
303
+ .description('Alias for down-app: stop and remove container for appKey')
295
304
  .option('--volumes', 'Remove application Docker volume')
296
305
  .action(async(appName, options) => {
297
306
  try {
@@ -303,8 +312,8 @@ function setupShellTestStopCommands(program) {
303
312
  }
304
313
  });
305
314
 
306
- program.command('shell <app>')
307
- .description('Interactive shell in running or ephemeral container')
315
+ program.command('shell <appKey>')
316
+ .description('Interactive shell in container for builder appKey')
308
317
  .option('--env <env>', 'Environment (dev|tst); dev uses running container', 'dev')
309
318
  .action(async(appName, options) => {
310
319
  try {
@@ -318,8 +327,8 @@ function setupShellTestStopCommands(program) {
318
327
  }
319
328
 
320
329
  function setupDockerfileGenerateCommand(program) {
321
- program.command('dockerfile <app>')
322
- .description('Generate Dockerfile from detected runtime')
330
+ program.command('dockerfile <appKey>')
331
+ .description('Generate Dockerfile for builder appKey from detected runtime')
323
332
  .option('-l, --language <lang>', 'Override language detection')
324
333
  .option('-f, --force', 'Overwrite existing Dockerfile')
325
334
  .action(async(appName, options) => {
@@ -335,8 +344,8 @@ function setupDockerfileGenerateCommand(program) {
335
344
  }
336
345
 
337
346
  function setupPushDeployDockerfileCommands(program) {
338
- program.command('push <app>')
339
- .description('Push image to Azure Container Registry')
347
+ program.command('push <appKey>')
348
+ .description('Push builder appKey image to Azure Container Registry')
340
349
  .addHelpText('after', PUSH_HELP_AFTER)
341
350
  .option('-r, --registry <registry>', 'ACR registry URL (overrides application.yaml)')
342
351
  .option('-t, --tag <tag>', 'Image tag(s) - comma-separated for multiple (default: latest)')
@@ -349,8 +358,8 @@ function setupPushDeployDockerfileCommands(program) {
349
358
  }
350
359
  });
351
360
 
352
- program.command('deploy <app>')
353
- .description('Deploy via Miso Controller (Azure or --local)')
361
+ program.command('deploy <appKey|systemKey>')
362
+ .description('Deploy builder app or external system via Miso Controller (Azure or --local)')
354
363
  .addHelpText('after', DEPLOY_HELP_AFTER)
355
364
  .option('--local', 'Send manifest to controller then run app locally (app: same as aifabrix run <app>; external: restart dataplane)')
356
365
  .option('--client-id <id>', 'Client ID (overrides config)')
@@ -8,11 +8,16 @@ const chalk = require('chalk');
8
8
  const logger = require('../utils/logger');
9
9
  const { handleCommandError } = require('../utils/cli-utils');
10
10
  const { cliOptsSkipCertSync } = require('../certification/cli-cert-sync-skip');
11
- const { TEST_HELP_AFTER, TEST_E2E_HELP_AFTER } = require('./setup-app.help');
11
+ const {
12
+ TEST_HELP_AFTER,
13
+ TEST_E2E_HELP_AFTER,
14
+ TEST_TRUST_HELP_AFTER,
15
+ TEST_GOVERNANCE_HELP_AFTER
16
+ } = require('./setup-app.help');
12
17
 
13
18
  function setupTestCommand(program) {
14
- program.command('test <app>')
15
- .description('Tests: builder in container; external = local validation')
19
+ program.command('test <appKey|systemKey>')
20
+ .description('Tests: builder appKey in container; external systemKey = local validation')
16
21
  .option('-e, --env <env>', 'For builder app: dev (running container) or tst (ephemeral)', 'dev')
17
22
  .option('-v, --verbose', 'Verbose output')
18
23
  .option('-d, --debug', 'Write debug log to integration/<systemKey>/logs/ (external only)')
@@ -84,14 +89,16 @@ function firstIssuanceFailureHintFromE2eResults(results) {
84
89
  * @param {Object} options
85
90
  * @returns {Promise<void>}
86
91
  */
87
- async function runExternalIntegrationE2EAndCertSync(appName, options) {
92
+ async function runExternalIntegrationE2EAndCertSync(appName, options, cmd) {
93
+ const { cliOptsSkipSync } = require('../utils/cli-sync-options');
88
94
  const { runTestE2EForExternalSystem } = require('../commands/test-e2e-external');
95
+ const noSync = cliOptsSkipSync(options, cmd);
89
96
  const { success, results } = await runTestE2EForExternalSystem(appName, {
90
97
  env: options.env,
91
98
  debug: options.debug,
92
99
  verbose: options.verbose,
93
100
  async: options.async !== false,
94
- noSync: options.noSync === true
101
+ noSync
95
102
  });
96
103
  const { displayIntegrationTestResults } = require('../utils/external-system-display');
97
104
  const datasourceResults = results.map(r => ({
@@ -118,17 +125,19 @@ async function runExternalIntegrationE2EAndCertSync(appName, options) {
118
125
  await trySyncCertificationFromDataplaneForExternalApp(appName, 'test-e2e', { issuanceFailureHint });
119
126
  }
120
127
 
121
- async function runTestE2ECommand(appName, options) {
128
+ async function runTestE2ECommand(appName, options, cmd) {
129
+ const { cliOptsSkipSync } = require('../utils/cli-sync-options');
130
+ const noSync = cliOptsSkipSync(options, cmd);
122
131
  const pathsUtil = require('../utils/paths');
123
132
  const appType = await pathsUtil.detectAppType(appName).catch(() => null);
124
- if (options.noSync === true && appType && appType.baseDir === 'builder') {
133
+ if (noSync && appType && appType.baseDir === 'builder') {
125
134
  throw new Error(
126
135
  'Option --no-sync applies only to external integration E2E (integration/<systemKey>/). ' +
127
136
  'Remove --no-sync for builder app E2E.'
128
137
  );
129
138
  }
130
139
  if (appType && appType.baseDir === 'integration') {
131
- await runExternalIntegrationE2EAndCertSync(appName, options);
140
+ await runExternalIntegrationE2EAndCertSync(appName, options, cmd);
132
141
  return;
133
142
  }
134
143
  const { runAppTestE2e } = require('../commands/app-test');
@@ -136,8 +145,8 @@ async function runTestE2ECommand(appName, options) {
136
145
  }
137
146
 
138
147
  function setupInstallCommand(program) {
139
- program.command('install <app>')
140
- .description('Install deps in container (builder apps only)')
148
+ program.command('install <appKey>')
149
+ .description('Install deps in container (builder appKey only)')
141
150
  .option('--env <env>', 'dev (running container) or tst (ephemeral with .env)', 'dev')
142
151
  .action(async(appName, options) => {
143
152
  try {
@@ -145,7 +154,7 @@ function setupInstallCommand(program) {
145
154
  const appType = await pathsUtil.detectAppType(appName).catch(() => null);
146
155
  if (appType && appType.baseDir === 'integration') {
147
156
  logger.log(
148
- chalk.gray('Install is for builder applications only. Use aifabrix shell <app> to run commands in external setups.')
157
+ chalk.gray('Install is for builder appKey only. Use aifabrix shell <appKey> for builder apps or External Systems commands for integrations.')
149
158
  );
150
159
  return;
151
160
  }
@@ -159,15 +168,11 @@ function setupInstallCommand(program) {
159
168
  }
160
169
 
161
170
  function setupTestE2eCommand(program) {
162
- program.command('test-e2e <app>')
163
- .description('E2E: builder in container; external = all datasources via dataplane')
171
+ program.command('test-e2e <appKey|systemKey>')
172
+ .description('E2E: builder appKey in container; external systemKey = all datasources via dataplane')
164
173
  .option('-e, --env <env>', 'Environment: dev, tst, or pro (builder: dev/tst for container)', 'dev')
165
174
  .option('-v, --verbose', 'Show detailed step output and poll progress')
166
175
  .option('-d, --debug', 'Include debug output and write log to integration/<systemKey>/logs/')
167
- .option(
168
- '--sync',
169
- '(Deprecated; no-op.) Local integration files are published before E2E by default; use --no-sync to skip.'
170
- )
171
176
  .option(
172
177
  '--no-sync',
173
178
  'Skip publishing local integration files; E2E uses the system config already on the dataplane (external integration only)'
@@ -188,7 +193,7 @@ function setupTestE2eCommand(program) {
188
193
  env: envExplicit ? options.env : undefined,
189
194
  async: true // system-level command surface omits --no-async; always poll for completeness
190
195
  };
191
- await runTestE2ECommand(appName, externalOpts);
196
+ await runTestE2ECommand(appName, externalOpts, cmd);
192
197
  } catch (error) {
193
198
  handleCommandError(error, 'test-e2e');
194
199
  process.exit(1);
@@ -197,15 +202,15 @@ function setupTestE2eCommand(program) {
197
202
  }
198
203
 
199
204
  function setupLintCommand(program) {
200
- program.command('lint <app>')
201
- .description('Lint in container (builder apps only)')
205
+ program.command('lint <appKey>')
206
+ .description('Lint in container (builder appKey only)')
202
207
  .option('--env <env>', 'dev (running container) or tst (ephemeral with .env)', 'dev')
203
208
  .action(async(appName, options) => {
204
209
  try {
205
210
  const pathsUtil = require('../utils/paths');
206
211
  const appType = await pathsUtil.detectAppType(appName).catch(() => null);
207
212
  if (appType && appType.baseDir === 'integration') {
208
- logger.log(chalk.gray('lint is for builder applications only. Use aifabrix shell <app> then make lint or pnpm lint.'));
213
+ logger.log(chalk.gray('lint is for builder appKey only. Use aifabrix shell <appKey> then make lint or pnpm lint.'));
209
214
  return;
210
215
  }
211
216
  const { runAppLint } = require('../commands/app-test');
@@ -217,10 +222,64 @@ function setupLintCommand(program) {
217
222
  });
218
223
  }
219
224
 
225
+ function collectScenarioId(value, previous) {
226
+ return previous.concat([value]);
227
+ }
228
+
229
+ function setupTestGovernanceCommand(program) {
230
+ const { testGovernanceCommandHandler } = require('../commands/test-governance-command-action');
231
+ program
232
+ .command('test-governance <appKey|systemKey>')
233
+ .description(
234
+ 'Governance scenario acceptance: ABAC visibility via governed search (key sets only)'
235
+ )
236
+ .option('-e, --env <env>', 'Environment: dev, tst, or pro', 'dev')
237
+ .option('--pack <path>', 'Scenario pack YAML (default: scenarios/default.yaml or <systemKey>-v1.yaml)')
238
+ .option('-a, --app <path>', 'Integration folder override')
239
+ .option(
240
+ '--scenario <id>',
241
+ 'Run subset of scenario ids (repeatable)',
242
+ collectScenarioId,
243
+ []
244
+ )
245
+ .option('--no-sync', 'Skip publishing local integration files before run')
246
+ .option('-v, --verbose', 'Per-scenario verdict lines with subject and counts')
247
+ .option('--json', 'Machine-readable redacted result (same allowlist as API)')
248
+ .addHelpText('after', TEST_GOVERNANCE_HELP_AFTER)
249
+ .action((appName, options, cmd) => testGovernanceCommandHandler(appName, options, cmd));
250
+ }
251
+
252
+ function setupTestTrustCommand(program) {
253
+ const { testTrustCommandHandler } = require('../commands/test-trust-command-action');
254
+ program
255
+ .command('test-trust <appKey|systemKey>')
256
+ .description(
257
+ 'Semantic agent metadata validation for external system (all datasources via dataplane 404.5)'
258
+ )
259
+ .option('-e, --env <env>', 'Environment: dev, tst, or pro', 'dev')
260
+ .option('-v, --verbose', 'Show findings and observed business model')
261
+ .option('-d, --debug', 'Write debug log under integration/<systemKey>/logs/')
262
+ .option('--no-sync', 'Skip publishing local integration files before validate')
263
+ .option('--revalidate', 'Force new validation for each datasource')
264
+ .option(
265
+ '--timeout <ms>',
266
+ 'HTTP timeout for validate/latest requests (ms)',
267
+ '120000'
268
+ )
269
+ .option('--strict', 'Exit 1 unless every datasource is trusted')
270
+ .option('--warnings-as-errors', 'Exit 1 when any datasource is usableWithWarnings')
271
+ .option('--json', 'Print JSON array of trust runs')
272
+ .option('--summary', 'One line per datasource')
273
+ .addHelpText('after', TEST_TRUST_HELP_AFTER)
274
+ .action((appName, options, cmd) => testTrustCommandHandler(appName, options, cmd));
275
+ }
276
+
220
277
  function setupInstallTestE2eLintCommands(program) {
221
278
  setupInstallCommand(program);
222
279
  setupTestCommand(program);
223
280
  setupTestE2eCommand(program);
281
+ setupTestGovernanceCommand(program);
282
+ setupTestTrustCommand(program);
224
283
  setupLintCommand(program);
225
284
  }
226
285
 
@@ -28,7 +28,33 @@ For details on omitting the URL: aifabrix auth set-controller -h
28
28
  Aliases:
29
29
  aifabrix auth set-controller [url]
30
30
  aifabrix auth set-environment <env>
31
- Subcommand: auth status [--validate] for CI/scripts.
31
+ Subcommand: auth status [--validate] for CI/scripts (exit codes 0/1/3).
32
+ `;
33
+
34
+ const AUTH_STATUS_HELP_AFTER = `
35
+ Examples:
36
+ $ aifabrix auth status
37
+ $ aifabrix auth status --validate
38
+
39
+ Exit codes (--validate only):
40
+ 0 Authenticated and Builder CLI meets dataplane minimum (or no minimum configured)
41
+ 1 Not authenticated — run aifabrix login
42
+ 3 Authenticated but Builder CLI is older than dataplane minimum
43
+
44
+ Config cache (written on status when dataplane is reachable):
45
+ ~/.aifabrix/config.yaml → device.<controllerUrl>:
46
+ dataplane-version — last dataplane version from health
47
+ dataplane-min-cli-version — minimum Builder CLI required (when enforced)
48
+
49
+ What is blocked when CLI is too old:
50
+ Dataplane commands (upload, wizard, datasource upload, deploy to dataplane, …)
51
+ What still works:
52
+ Local validate, aifabrix run, up-infra, file generation without dataplane API calls
53
+
54
+ Troubleshooting:
55
+ • "Upgrade required" but you upgraded — run auth status again to refresh cache
56
+ • No min version shown — dataplane MIN_BUILDER_CLI_VERSION not set (ops)
57
+ • CI exit 3 — pin @aifabrix/builder version in pipeline to ≥ dataplane-min-cli-version
32
58
  `;
33
59
 
34
60
  const AUTH_SET_CONTROLLER_HELP_AFTER = `
@@ -168,7 +194,8 @@ function setupAuthSubcommands(program) {
168
194
 
169
195
  auth.command('status')
170
196
  .description('Show tokens/session for current controller and environment')
171
- .option('--validate', 'Exit with code 1 when not authenticated (for scripted use, e.g. manual test setup)')
197
+ .addHelpText('after', AUTH_STATUS_HELP_AFTER)
198
+ .option('--validate', 'Exit 1 when not authenticated, 3 when Builder CLI < dataplane minimum, 0 otherwise (for CI/scripts)')
172
199
  .action(createAuthStatusAction());
173
200
  }
174
201
 
@@ -182,4 +209,4 @@ function setupAuthCommands(program) {
182
209
  setupAuthSubcommands(program);
183
210
  }
184
211
 
185
- module.exports = { setupAuthCommands };
212
+ module.exports = { setupAuthCommands, AUTH_STATUS_HELP_AFTER };
@@ -42,8 +42,11 @@ function setupDownloadCommand(program) {
42
42
 
43
43
  function setupUploadCommand(program) {
44
44
  program.command('upload <systemKey>')
45
- .description('Validate, publish to dataplane, and register with controller (draft application)')
45
+ .description('Validate, publish to dataplane, and register with controller (draft application); or upload .protection batch')
46
46
  .option('--dry-run', 'Validate and build payload only; no API calls')
47
+ .option('--no-sync', 'For .protection: skip datasource sync after upload')
48
+ .option('--json', 'For .protection: JSON output')
49
+ .option('--warnings-as-errors', 'For .protection: pass strict=true to dataplane validate')
47
50
  .option('-v, --verbose', 'Run server-side pipeline validate and print warnings before publish')
48
51
  .option('--probe', 'After publish, run dataplane runtime checks (validation/run); slower')
49
52
  .option('--minimal', 'Print only a short readiness summary after upload')
@@ -54,6 +57,26 @@ function setupUploadCommand(program) {
54
57
  )
55
58
  .action(async(systemKey, options) => {
56
59
  try {
60
+ const { isProtectionScope } = require('../protection/scope');
61
+ if (isProtectionScope(systemKey)) {
62
+ const { uploadProtectionBatchCommand } = require('../protection/upload-batch');
63
+ const logger = require('../utils/logger');
64
+ const code = await uploadProtectionBatchCommand(
65
+ {
66
+ env: options.env,
67
+ dryRun: options.dryRun === true,
68
+ noSync: options.noSync === true,
69
+ json: options.json === true,
70
+ verbose: options.verbose === true,
71
+ warningsAsErrors: options.warningsAsErrors === true
72
+ },
73
+ logger
74
+ );
75
+ if (code !== 0) {
76
+ process.exit(code);
77
+ }
78
+ return;
79
+ }
57
80
  const upload = require('../commands/upload');
58
81
  const probeTimeout =
59
82
  options.probeTimeout === undefined || options.probeTimeout === null
@@ -79,6 +102,17 @@ function setupDeleteCommand(program) {
79
102
  .option('--force', 'Skip confirmation prompt (alias for --yes)')
80
103
  .action(async(systemKey, options) => {
81
104
  try {
105
+ const { isProtectionScope } = require('../protection/scope');
106
+ if (isProtectionScope(systemKey)) {
107
+ const logger = require('../utils/logger');
108
+ const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
109
+ logger.error(
110
+ formatBlockingError(
111
+ 'delete .protection is not supported. Use: aifabrix protection delete <datasourceKey>'
112
+ )
113
+ );
114
+ process.exit(1);
115
+ }
82
116
  const externalDelete = require('../external-system/delete');
83
117
  await externalDelete.deleteExternalSystem(systemKey, options);
84
118
  } catch (error) {
@@ -186,8 +220,8 @@ async function runTestIntegrationCommand(appName, options) {
186
220
 
187
221
  function setupExternalSystemTestCommands(program) {
188
222
  // 'test <app>' is registered in setup-app.js and dispatches by app type (builder vs external)
189
- program.command('test-integration <app>')
190
- .description('Integration tests: builder in container; external via dataplane')
223
+ program.command('test-integration <appKey|systemKey>')
224
+ .description('Integration tests: builder appKey in container; external systemKey via dataplane')
191
225
  .option('-e, --env <env>', 'Environment: dev, tst, or pro (builder: dev/tst for container)', 'dev')
192
226
  .option('-v, --verbose', 'Show detailed test output')
193
227
  .option('-d, --debug', 'Include debug output and write log to integration/<systemKey>/logs/')
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @fileoverview Help-after strings for setup-utility CLI commands.
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ const JSON_HELP_AFTER = `
8
+ Example:
9
+ $ aifabrix json myapp
10
+ Generates *-deploy.json (or application-schema.json) for commit before deploy.
11
+ `;
12
+
13
+ const VALIDATE_HELP_AFTER = `
14
+ Examples:
15
+ $ aifabrix validate myapp
16
+ $ aifabrix validate myapp --cert-sync
17
+ $ aifabrix validate --integration
18
+ $ aifabrix validate --builder
19
+ `;
20
+
21
+ const REPAIR_HELP_AFTER = `
22
+ Examples:
23
+ $ aifabrix repair hubspot-demo
24
+ Align manifest, system/datasource files, RBAC extract, env.template, and deploy JSON under integration/<systemKey>/.
25
+
26
+ $ aifabrix repair hubspot-demo --dry-run
27
+ Show what would change without writing files.
28
+
29
+ $ aifabrix repair hubspot-demo --auth oauth2
30
+ Set authentication method; updates the system file and env.template (oauth2, aad, apikey, basic, …).
31
+
32
+ $ aifabrix repair hubspot-demo --rbac --expose --sync --test
33
+ Optional datasource fixes: RBAC roles/permissions, exposed.schema from attributes, default sync block, testPayload stubs.
34
+
35
+ $ aifabrix repair hubspot-demo --doc
36
+ Regenerate README.md from the current deployment manifest only (other drift fixes unchanged).
37
+
38
+ Before overwriting files, repair writes timestamped backups under integration/<systemKey>/backup/ (same as datasource capability copy). Use --no-backup to skip.
39
+ `;
40
+
41
+ module.exports = {
42
+ JSON_HELP_AFTER,
43
+ VALIDATE_HELP_AFTER,
44
+ REPAIR_HELP_AFTER
45
+ };
@@ -114,8 +114,8 @@ async function runResolveAppAction(appName, options) {
114
114
  * @returns {void}
115
115
  */
116
116
  function setupResolveCommand(program) {
117
- program.command('resolve <app>')
118
- .description('Generate .env from template; optional validate after')
117
+ program.command('resolve <appKey|systemKey>')
118
+ .description('Generate .env from template (builder/<appKey>/ or integration/<systemKey>/); optional validate after')
119
119
  .option('-f, --force', 'Generate missing secret keys in secrets file')
120
120
  .option('--skip-validation', 'Skip file validation after generating .env')
121
121
  .option('--json', 'Print JSON summary (envPath, manifestSource, optional validation)')