@aifabrix/builder 2.43.0 → 2.44.1

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 (371) hide show
  1. package/.cursor/rules/anchor-docs.mdc +15 -0
  2. package/.cursor/rules/cli-layout.mdc +75 -0
  3. package/.cursor/rules/project-rules.mdc +8 -0
  4. package/.npmrc.token +1 -0
  5. package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
  6. package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
  7. package/.nyc_output/processinfo/index.json +1 -0
  8. package/README.md +1 -1
  9. package/anchor-docs/README.md +10 -0
  10. package/anchor-docs/_TEMPLATE +24 -0
  11. package/bin/aifabrix.js +13 -4
  12. package/integration/hubspot-test/README.md +31 -0
  13. package/integration/hubspot-test/create-hubspot.js +5 -5
  14. package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
  15. package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
  16. package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
  17. package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
  18. package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
  19. package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
  20. package/integration/hubspot-test/test-dataplane-down.js +3 -3
  21. package/integration/hubspot-test/test.js +35 -43
  22. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
  23. package/integration/roundtrip-test-local/README.md +144 -0
  24. package/integration/roundtrip-test-local/application.yaml +13 -0
  25. package/integration/roundtrip-test-local/env.template +15 -0
  26. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
  27. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
  28. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
  29. package/integration/roundtrip-test-local2/README.md +144 -0
  30. package/integration/roundtrip-test-local2/application.yaml +13 -0
  31. package/integration/roundtrip-test-local2/env.template +15 -0
  32. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
  33. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
  34. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
  35. package/integration/test/wizard.yaml +8 -0
  36. package/jest.config.default.js +10 -0
  37. package/jest.config.integration.fixtures.js +22 -0
  38. package/jest.config.integration.js +21 -18
  39. package/jest.config.isolated.js +10 -0
  40. package/jest.projects.js +301 -0
  41. package/lib/api/certificates.api.js +62 -0
  42. package/lib/api/datasources-core.api.js +3 -3
  43. package/lib/api/dev-mtls-request.js +110 -0
  44. package/lib/api/dev-server-https.js +145 -0
  45. package/lib/api/dev.api.js +133 -144
  46. package/lib/api/index.js +11 -3
  47. package/lib/api/pipeline.api.js +67 -20
  48. package/lib/api/types/certificates.types.js +48 -0
  49. package/lib/api/types/dev.types.js +4 -3
  50. package/lib/api/types/pipeline.types.js +8 -5
  51. package/lib/api/types/validation-run.types.js +56 -0
  52. package/lib/api/validation-run.api.js +111 -0
  53. package/lib/api/validation-runner.js +109 -0
  54. package/lib/app/certification-show-enrich.js +129 -0
  55. package/lib/app/certification-verify-rows.js +60 -0
  56. package/lib/app/config.js +1 -1
  57. package/lib/app/deploy-status-display.js +2 -2
  58. package/lib/app/deploy.js +7 -6
  59. package/lib/app/display.js +2 -1
  60. package/lib/app/dockerfile.js +3 -2
  61. package/lib/app/down.js +2 -1
  62. package/lib/app/helpers.js +6 -5
  63. package/lib/app/index.js +27 -8
  64. package/lib/app/list.js +7 -6
  65. package/lib/app/push.js +4 -3
  66. package/lib/app/register.js +16 -7
  67. package/lib/app/rotate-secret.js +14 -13
  68. package/lib/app/run-container-start.js +184 -0
  69. package/lib/app/run-docker-fallback.js +108 -0
  70. package/lib/app/run-env-compose.js +30 -42
  71. package/lib/app/run-helpers.js +49 -126
  72. package/lib/app/run-infra-requirements.js +30 -0
  73. package/lib/app/run-resolve-image.js +21 -0
  74. package/lib/app/run.js +74 -21
  75. package/lib/app/show-display.js +44 -1
  76. package/lib/app/show.js +93 -9
  77. package/lib/build/index.js +13 -10
  78. package/lib/certification/cli-cert-sync-skip.js +21 -0
  79. package/lib/certification/merge-certification-from-artifact.js +185 -0
  80. package/lib/certification/post-unified-cert-sync.js +33 -0
  81. package/lib/certification/sync-after-external-command.js +52 -0
  82. package/lib/certification/sync-system-certification.js +197 -0
  83. package/lib/cli/index.js +2 -0
  84. package/lib/cli/setup-app.help.js +67 -0
  85. package/lib/cli/setup-app.js +61 -121
  86. package/lib/cli/setup-app.test-commands.js +195 -0
  87. package/lib/cli/setup-auth.js +19 -5
  88. package/lib/cli/setup-credential-deployment.js +22 -8
  89. package/lib/cli/setup-dev-path-commands.js +124 -0
  90. package/lib/cli/setup-dev.js +170 -113
  91. package/lib/cli/setup-environment.js +7 -1
  92. package/lib/cli/setup-external-system.js +84 -23
  93. package/lib/cli/setup-infra.js +126 -47
  94. package/lib/cli/setup-parameters.js +32 -0
  95. package/lib/cli/setup-secrets.js +137 -18
  96. package/lib/cli/setup-service-user.js +1 -1
  97. package/lib/cli/setup-utility.js +54 -22
  98. package/lib/commands/app-down.js +5 -7
  99. package/lib/commands/app-install.js +14 -7
  100. package/lib/commands/app-logs.js +13 -10
  101. package/lib/commands/app-shell.js +4 -1
  102. package/lib/commands/app-test.js +25 -19
  103. package/lib/commands/app.js +32 -11
  104. package/lib/commands/auth-config.js +6 -6
  105. package/lib/commands/auth-status.js +4 -3
  106. package/lib/commands/credential-env.js +4 -3
  107. package/lib/commands/credential-list.js +5 -4
  108. package/lib/commands/credential-push.js +4 -3
  109. package/lib/commands/datasource-unified-test-cli.js +428 -0
  110. package/lib/commands/datasource-unified-test-cli.options.js +191 -0
  111. package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +106 -0
  112. package/lib/commands/datasource-validation-cli.js +143 -0
  113. package/lib/commands/datasource.js +125 -95
  114. package/lib/commands/deployment-list.js +6 -5
  115. package/lib/commands/dev-cli-handlers.js +122 -18
  116. package/lib/commands/dev-down.js +4 -3
  117. package/lib/commands/dev-init.js +231 -116
  118. package/lib/commands/dev-show-display.js +473 -0
  119. package/lib/commands/login-credentials.js +3 -2
  120. package/lib/commands/login-device.js +4 -3
  121. package/lib/commands/login.js +5 -4
  122. package/lib/commands/logout.js +8 -7
  123. package/lib/commands/parameters-validate.js +54 -0
  124. package/lib/commands/repair-datasource.js +314 -68
  125. package/lib/commands/repair-env-template.js +2 -2
  126. package/lib/commands/repair.js +21 -3
  127. package/lib/commands/secrets-list.js +23 -12
  128. package/lib/commands/secrets-remove-all.js +220 -0
  129. package/lib/commands/secrets-remove.js +21 -12
  130. package/lib/commands/secrets-set.js +21 -12
  131. package/lib/commands/secrets-validate.js +4 -4
  132. package/lib/commands/secure.js +10 -9
  133. package/lib/commands/service-user.js +26 -25
  134. package/lib/commands/test-e2e-external.js +27 -1
  135. package/lib/commands/up-common.js +3 -2
  136. package/lib/commands/up-dataplane.js +29 -16
  137. package/lib/commands/up-miso.js +19 -29
  138. package/lib/commands/upload.js +149 -39
  139. package/lib/commands/wizard-core-helpers.js +1 -1
  140. package/lib/commands/wizard-dataplane.js +4 -3
  141. package/lib/commands/wizard-helpers.js +3 -3
  142. package/lib/commands/wizard.js +2 -2
  143. package/lib/core/admin-secrets.js +14 -5
  144. package/lib/core/audit-logger.js +12 -4
  145. package/lib/core/config-attach-extensions.js +46 -0
  146. package/lib/core/config-runtime-paths.js +29 -0
  147. package/lib/core/config.js +55 -56
  148. package/lib/core/diff.js +3 -2
  149. package/lib/core/ensure-encryption-key.js +1 -1
  150. package/lib/core/secrets-ensure-infra.js +77 -0
  151. package/lib/core/secrets-ensure.js +120 -64
  152. package/lib/core/secrets-env-write.js +35 -7
  153. package/lib/core/secrets-infra-placeholder-sync.js +61 -0
  154. package/lib/core/secrets.js +200 -37
  155. package/lib/core/templates-env.js +4 -3
  156. package/lib/datasource/abac-validator.js +1 -10
  157. package/lib/datasource/deploy.js +75 -53
  158. package/lib/datasource/field-reference-validator.js +9 -6
  159. package/lib/datasource/integration-context.js +63 -0
  160. package/lib/datasource/list.js +8 -7
  161. package/lib/datasource/log-viewer.js +189 -67
  162. package/lib/datasource/resolve-app.js +4 -4
  163. package/lib/datasource/test-e2e.js +113 -146
  164. package/lib/datasource/test-integration.js +114 -122
  165. package/lib/datasource/unified-validation-run-body.js +68 -0
  166. package/lib/datasource/unified-validation-run-post.js +23 -0
  167. package/lib/datasource/unified-validation-run-resolve.js +43 -0
  168. package/lib/datasource/unified-validation-run.js +93 -0
  169. package/lib/datasource/validate.js +157 -13
  170. package/lib/deployment/deployer.js +4 -3
  171. package/lib/deployment/environment.js +7 -6
  172. package/lib/deployment/push.js +17 -8
  173. package/lib/external-system/delete.js +4 -3
  174. package/lib/external-system/deploy.js +166 -53
  175. package/lib/external-system/download-helpers.js +1 -1
  176. package/lib/external-system/download.js +7 -6
  177. package/lib/external-system/generator.js +92 -6
  178. package/lib/external-system/integration-test-dispatch.js +26 -0
  179. package/lib/external-system/test-execution.js +5 -1
  180. package/lib/external-system/test-helpers.js +0 -4
  181. package/lib/external-system/test-system-level-helpers.js +110 -0
  182. package/lib/external-system/test-system-level.js +83 -44
  183. package/lib/external-system/test.js +59 -8
  184. package/lib/generator/builders.js +23 -11
  185. package/lib/generator/deploy-manifest-azure-kv.js +81 -0
  186. package/lib/generator/external.js +16 -4
  187. package/lib/generator/helpers.js +58 -3
  188. package/lib/generator/index.js +4 -0
  189. package/lib/generator/split-readme.js +12 -7
  190. package/lib/generator/split-variables.js +2 -1
  191. package/lib/generator/split.js +1 -1
  192. package/lib/generator/wizard-readme.js +3 -3
  193. package/lib/generator/wizard.js +8 -8
  194. package/lib/infrastructure/compose.js +70 -7
  195. package/lib/infrastructure/helpers-docker-check.js +67 -0
  196. package/lib/infrastructure/helpers.js +203 -42
  197. package/lib/infrastructure/index.js +31 -18
  198. package/lib/infrastructure/services.js +21 -67
  199. package/lib/internal/fs-real-sync.js +104 -0
  200. package/lib/internal/node-fs.js +98 -0
  201. package/lib/parameters/database-secret-values.js +173 -0
  202. package/lib/parameters/infra-kv-discovery.js +121 -0
  203. package/lib/parameters/infra-parameter-catalog.js +458 -0
  204. package/lib/parameters/infra-parameter-validate.js +64 -0
  205. package/lib/schema/application-schema.json +37 -17
  206. package/lib/schema/datasource-test-run.schema.json +493 -0
  207. package/lib/schema/deployment-rules.yaml +102 -63
  208. package/lib/schema/external-datasource.schema.json +1200 -442
  209. package/lib/schema/external-system.schema.json +203 -5
  210. package/lib/schema/flag-map-validation-run.json +31 -0
  211. package/lib/schema/infra-parameter.schema.json +106 -0
  212. package/lib/schema/infra.parameter.yaml +421 -0
  213. package/lib/schema/type/credential-auth-templates.json +40 -0
  214. package/lib/schema/type/document-storage.json +226 -0
  215. package/lib/schema/type/message-service.json +123 -0
  216. package/lib/schema/type/vector-store.json +88 -0
  217. package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
  218. package/lib/utils/api-error-handler.js +2 -2
  219. package/lib/utils/api.js +77 -17
  220. package/lib/utils/app-register-api.js +3 -2
  221. package/lib/utils/app-register-auth.js +1 -1
  222. package/lib/utils/app-register-config.js +4 -4
  223. package/lib/utils/app-register-display.js +3 -2
  224. package/lib/utils/app-register-validator.js +3 -2
  225. package/lib/utils/app-run-containers.js +26 -22
  226. package/lib/utils/app-scoped-config.js +31 -0
  227. package/lib/utils/app-service-env-from-builder.js +164 -0
  228. package/lib/utils/build-copy.js +1 -1
  229. package/lib/utils/build-helpers.js +20 -20
  230. package/lib/utils/build-resolve-image.js +165 -0
  231. package/lib/utils/cli-layout-chalk.js +8 -0
  232. package/lib/utils/cli-test-layout-chalk.js +267 -0
  233. package/lib/utils/cli-utils.js +88 -11
  234. package/lib/utils/compose-db-passwords.js +138 -0
  235. package/lib/utils/compose-generate-docker-compose.js +216 -0
  236. package/lib/utils/compose-generator.js +197 -291
  237. package/lib/utils/compose-miso-env.js +18 -0
  238. package/lib/utils/compose-traefik-ingress-base.js +158 -0
  239. package/lib/utils/config-paths.js +166 -7
  240. package/lib/utils/config-scoped-resources-preference.js +41 -0
  241. package/lib/utils/configuration-env-resolver.js +11 -8
  242. package/lib/utils/controller-deployment-outcome.js +68 -0
  243. package/lib/utils/credential-display.js +2 -2
  244. package/lib/utils/credential-secrets-env.js +5 -5
  245. package/lib/utils/dataplane-pipeline-warning.js +4 -3
  246. package/lib/utils/datasource-test-run-capability-scope.js +43 -0
  247. package/lib/utils/datasource-test-run-certificate-tty.js +82 -0
  248. package/lib/utils/datasource-test-run-debug-display.js +137 -0
  249. package/lib/utils/datasource-test-run-debug-slice.js +93 -0
  250. package/lib/utils/datasource-test-run-display.js +459 -0
  251. package/lib/utils/datasource-test-run-exit.js +83 -0
  252. package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
  253. package/lib/utils/datasource-test-run-report-version.js +51 -0
  254. package/lib/utils/datasource-test-run-schema-sync.js +59 -0
  255. package/lib/utils/datasource-test-run-tty-log.js +81 -0
  256. package/lib/utils/datasource-validation-watch.js +266 -0
  257. package/lib/utils/declarative-url-ports.js +47 -0
  258. package/lib/utils/derive-env-key-from-client-id.js +41 -0
  259. package/lib/utils/dev-ca-install.js +185 -23
  260. package/lib/utils/dev-cert-helper.js +266 -17
  261. package/lib/utils/dev-hosts-helper.js +307 -0
  262. package/lib/utils/dev-init-cert-hints.js +37 -0
  263. package/lib/utils/dev-init-health-messages.js +52 -0
  264. package/lib/utils/dev-init-resolve.js +86 -0
  265. package/lib/utils/dev-init-ssh-merge.js +65 -0
  266. package/lib/utils/dev-ssh-config-helper.js +196 -0
  267. package/lib/utils/dev-user-groups.js +93 -0
  268. package/lib/utils/docker-build.js +42 -17
  269. package/lib/utils/docker-exec.js +28 -0
  270. package/lib/utils/docker-manifest-public-port.js +116 -0
  271. package/lib/utils/docker-not-running-hint.js +52 -0
  272. package/lib/utils/docker.js +98 -11
  273. package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
  274. package/lib/utils/env-config-loader.js +10 -91
  275. package/lib/utils/env-copy.js +19 -10
  276. package/lib/utils/env-map.js +35 -8
  277. package/lib/utils/env-template.js +2 -2
  278. package/lib/utils/environment-scoped-resources.js +144 -0
  279. package/lib/utils/error-formatter.js +92 -13
  280. package/lib/utils/error-formatters/http-status-errors.js +6 -5
  281. package/lib/utils/error-formatters/network-errors.js +2 -1
  282. package/lib/utils/error-formatters/permission-errors.js +2 -1
  283. package/lib/utils/error-formatters/validation-errors.js +2 -1
  284. package/lib/utils/external-readme.js +8 -1
  285. package/lib/utils/external-system-display.js +242 -136
  286. package/lib/utils/external-system-local-test-tty.js +389 -0
  287. package/lib/utils/external-system-readiness-core.js +377 -0
  288. package/lib/utils/external-system-readiness-deploy-display.js +270 -0
  289. package/lib/utils/external-system-readiness-display-internals.js +150 -0
  290. package/lib/utils/external-system-readiness-display.js +186 -0
  291. package/lib/utils/external-system-system-test-tty-overview.js +120 -0
  292. package/lib/utils/external-system-system-test-tty.js +417 -0
  293. package/lib/utils/external-system-test-helpers.js +24 -6
  294. package/lib/utils/external-system-validators.js +30 -12
  295. package/lib/utils/health-check-url.js +119 -0
  296. package/lib/utils/health-check.js +59 -25
  297. package/lib/utils/help-builder.js +11 -8
  298. package/lib/utils/image-version.js +4 -8
  299. package/lib/utils/infra-containers.js +4 -7
  300. package/lib/utils/infra-env-defaults.js +162 -0
  301. package/lib/utils/infra-status-display.js +167 -0
  302. package/lib/utils/infra-status.js +16 -8
  303. package/lib/utils/local-secrets.js +3 -4
  304. package/lib/utils/paths.js +148 -47
  305. package/lib/utils/port-resolver.js +10 -23
  306. package/lib/utils/redis-env-scope.js +62 -0
  307. package/lib/utils/register-aifabrix-shell-env.js +204 -0
  308. package/lib/utils/remote-builder-validation.js +99 -0
  309. package/lib/utils/remote-dev-auth.js +117 -21
  310. package/lib/utils/remote-docker-env.js +67 -15
  311. package/lib/utils/remote-secrets-loader.js +13 -4
  312. package/lib/utils/resolve-docker-image-ref.js +124 -0
  313. package/lib/utils/schema-loader.js +22 -9
  314. package/lib/utils/secrets-bash-kv.js +25 -0
  315. package/lib/utils/secrets-generator.js +169 -49
  316. package/lib/utils/secrets-helpers.js +70 -59
  317. package/lib/utils/secrets-kv-scope.js +60 -0
  318. package/lib/utils/secrets-utils.js +32 -38
  319. package/lib/utils/secrets-validation.js +3 -1
  320. package/lib/utils/secrets-yaml-preserve.js +109 -0
  321. package/lib/utils/ssh-key-helper.js +4 -2
  322. package/lib/utils/template-helpers.js +2 -2
  323. package/lib/utils/test-log-writer.js +3 -3
  324. package/lib/utils/token-manager.js +1 -2
  325. package/lib/utils/url-declarative-public-base.js +188 -0
  326. package/lib/utils/url-declarative-resolve-build.js +493 -0
  327. package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
  328. package/lib/utils/url-declarative-resolve.js +220 -0
  329. package/lib/utils/url-declarative-token-parse.js +74 -0
  330. package/lib/utils/url-declarative-url-flags.js +50 -0
  331. package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
  332. package/lib/utils/url-public-path-prefix.js +34 -0
  333. package/lib/utils/urls-local-registry.js +220 -0
  334. package/lib/utils/validation-report-tty-kit.js +77 -0
  335. package/lib/utils/validation-run-poll.js +112 -0
  336. package/lib/utils/validation-run-post-retry.js +85 -0
  337. package/lib/utils/validation-run-request.js +116 -0
  338. package/lib/utils/variable-transformer.js +21 -4
  339. package/lib/utils/yaml-preserve.js +33 -14
  340. package/lib/validation/datasource-warnings.js +56 -0
  341. package/lib/validation/env-template-auth.js +1 -1
  342. package/lib/validation/external-manifest-validator.js +27 -7
  343. package/lib/validation/validate-display.js +37 -31
  344. package/lib/validation/validate-external-cert-sync.js +23 -0
  345. package/lib/validation/validate.js +8 -14
  346. package/lib/validation/validator-unresolved-placeholders.js +98 -0
  347. package/lib/validation/validator.js +22 -65
  348. package/lib/validation/wizard-config-validator.js +2 -1
  349. package/package.json +9 -4
  350. package/scripts/check-datasource-test-run-schema-sync.js +34 -0
  351. package/scripts/diagnose-cli.js +150 -0
  352. package/scripts/install-local.js +307 -55
  353. package/scripts/pnpm-global-remove.js +48 -0
  354. package/templates/README.md +15 -2
  355. package/templates/applications/dataplane/application.yaml +52 -2
  356. package/templates/applications/dataplane/env.template +79 -17
  357. package/templates/applications/dataplane/rbac.yaml +8 -0
  358. package/templates/applications/keycloak/application.yaml +9 -1
  359. package/templates/applications/keycloak/env.template +15 -6
  360. package/templates/applications/miso-controller/application.yaml +10 -2
  361. package/templates/applications/miso-controller/env.template +42 -12
  362. package/templates/applications/miso-controller/rbac.yaml +5 -0
  363. package/templates/external-system/README.md.hbs +20 -7
  364. package/templates/external-system/deploy.js.hbs +5 -5
  365. package/templates/external-system/external-datasource.yaml.hbs +197 -118
  366. package/templates/infra/compose.yaml.hbs +33 -16
  367. package/templates/infra/servers.json.hbs +3 -1
  368. package/templates/python/docker-compose.hbs +16 -0
  369. package/templates/typescript/docker-compose.hbs +16 -0
  370. package/lib/api/external-test.api.js +0 -111
  371. package/lib/schema/env-config.yaml +0 -60
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Environment-scoped resource naming (shared infra: dev/tst on same Postgres/Redis/Docker).
3
+ * Effective only when user gate AND app flag AND run env is dev|tst.
4
+ *
5
+ * @fileoverview environmentScopedResources + useEnvironmentScopedResources helpers
6
+ * @author AI Fabrix Team
7
+ * @version 1.0.0
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ /**
13
+ * Run/env keys that participate in resource prefixing (not pro).
14
+ * @param {string} envKey - Normalized lowercase env key
15
+ * @returns {boolean}
16
+ */
17
+ function isScopedRunEnvironmentKey(envKey) {
18
+ if (!envKey || typeof envKey !== 'string') return false;
19
+ const k = envKey.toLowerCase();
20
+ return k === 'dev' || k === 'tst';
21
+ }
22
+
23
+ /**
24
+ * Effective local/deploy prefix behavior: user gate ∧ app flag ∧ dev|tst.
25
+ *
26
+ * @param {boolean} useEnvironmentScopedResources - ~/.aifabrix/config.yaml
27
+ * @param {boolean} appEnvironmentScopedResources - application.yaml
28
+ * @param {string} runEnvKey - dev | tst | pro | other (lowercase)
29
+ * @returns {boolean}
30
+ */
31
+ function computeEffectiveEnvironmentScopedResources(
32
+ useEnvironmentScopedResources,
33
+ appEnvironmentScopedResources,
34
+ runEnvKey
35
+ ) {
36
+ return (
37
+ Boolean(useEnvironmentScopedResources) &&
38
+ Boolean(appEnvironmentScopedResources) &&
39
+ isScopedRunEnvironmentKey(runEnvKey)
40
+ );
41
+ }
42
+
43
+ /**
44
+ * Redis logical DB index when env-scoped resources are effective.
45
+ * dev → 0, tst → 1 (single shared Redis instance).
46
+ *
47
+ * @param {string} runEnvKey - dev | tst
48
+ * @returns {number|null} Index or null if not applicable
49
+ */
50
+ function redisDbIndexForScopedRunEnv(runEnvKey) {
51
+ if (!runEnvKey || typeof runEnvKey !== 'string') return null;
52
+ const k = runEnvKey.toLowerCase();
53
+ if (k === 'dev') return 0;
54
+ if (k === 'tst') return 1;
55
+ return null;
56
+ }
57
+
58
+ /**
59
+ * Docker container name for local `aifabrix run` when env-scoping applies.
60
+ *
61
+ * @param {string} appName - Application key
62
+ * @param {string|number} devId - Developer id
63
+ * @param {number} idNum - Parsed numeric developer id
64
+ * @param {string} envKey - dev | tst
65
+ * @returns {string}
66
+ */
67
+ function buildScopedLocalContainerName(appName, devId, idNum, envKey) {
68
+ const e = String(envKey).toLowerCase();
69
+ if (idNum === 0) {
70
+ return `aifabrix-${e}-${appName}`;
71
+ }
72
+ return `aifabrix-dev${devId}-${e}-${appName}`;
73
+ }
74
+
75
+ /**
76
+ * Default local container name (no env scope).
77
+ *
78
+ * @param {string} appName - Application key
79
+ * @param {string|number} devId - Developer id
80
+ * @param {number} idNum - Parsed numeric developer id
81
+ * @returns {string}
82
+ */
83
+ function buildDefaultLocalContainerName(appName, devId, idNum) {
84
+ if (idNum === 0) {
85
+ return `aifabrix-${appName}`;
86
+ }
87
+ return `aifabrix-dev${devId}-${appName}`;
88
+ }
89
+
90
+ /**
91
+ * Resolved container name for run/stop/status.
92
+ *
93
+ * @param {string} appName - Application key
94
+ * @param {string|number} developerId - Developer id
95
+ * @param {boolean} effectiveScoped - From {@link computeEffectiveEnvironmentScopedResources}
96
+ * @param {string} [runEnvKey] - dev | tst (required when effectiveScoped)
97
+ * @returns {string}
98
+ */
99
+ function resolveRunContainerName(appName, developerId, effectiveScoped, runEnvKey) {
100
+ const idNum = typeof developerId === 'string' ? parseInt(developerId, 10) : developerId;
101
+ if (effectiveScoped && runEnvKey) {
102
+ return buildScopedLocalContainerName(appName, developerId, idNum, runEnvKey);
103
+ }
104
+ return buildDefaultLocalContainerName(appName, developerId, idNum);
105
+ }
106
+
107
+ /**
108
+ * Traefik PathPrefix: prefix /{envKey} before pattern base (e.g. /api → /dev/api).
109
+ *
110
+ * @param {string} basePath - From derivePathFromPattern
111
+ * @param {string} envKey - dev | tst
112
+ * @returns {string}
113
+ */
114
+ function buildEnvScopedTraefikPath(basePath, envKey) {
115
+ const e = String(envKey).toLowerCase();
116
+ const trimmed = (basePath || '/').trim() || '/';
117
+ if (trimmed === '/') {
118
+ return `/${e}`;
119
+ }
120
+ const withSlash = trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
121
+ return `/${e}${withSlash}`.replace(/\/{2,}/g, '/');
122
+ }
123
+
124
+ /**
125
+ * Compose service + Traefik router key when env-scoped (unique per env on shared host).
126
+ *
127
+ * @param {string} appName - Application key
128
+ * @param {string} envKey - dev | tst
129
+ * @returns {string}
130
+ */
131
+ function composeTraefikServiceKey(appName, envKey) {
132
+ return `${String(envKey).toLowerCase()}-${appName}`;
133
+ }
134
+
135
+ module.exports = {
136
+ isScopedRunEnvironmentKey,
137
+ computeEffectiveEnvironmentScopedResources,
138
+ redisDbIndexForScopedRunEnv,
139
+ buildScopedLocalContainerName,
140
+ buildDefaultLocalContainerName,
141
+ resolveRunContainerName,
142
+ buildEnvScopedTraefikPath,
143
+ composeTraefikServiceKey
144
+ };
@@ -47,15 +47,52 @@ function getFieldName(error) {
47
47
  return path ? `Field "${path}"` : 'Configuration';
48
48
  }
49
49
 
50
+ /**
51
+ * Resolves a value from root using an AJV instancePath (JSON Pointer, e.g. /roles/0/value).
52
+ * @param {*} root - Object or array validated at root
53
+ * @param {string} instancePath - AJV instancePath (leading slash or empty)
54
+ * @returns {*|undefined}
55
+ */
56
+ function getValueAtInstancePath(root, instancePath) {
57
+ if (root === undefined || root === null) return undefined;
58
+ if (!instancePath || instancePath === '' || instancePath === '/') return root;
59
+ const parts = instancePath.split('/').filter(Boolean);
60
+ let cur = root;
61
+ for (const p of parts) {
62
+ if (cur === undefined || cur === null) return undefined;
63
+ const key = /^\d+$/.test(p) ? parseInt(p, 10) : p;
64
+ cur = cur[key];
65
+ }
66
+ return cur;
67
+ }
68
+
69
+ /**
70
+ * Resolves the failing value for display (AJV may omit `data` depending on compile options).
71
+ * @param {Object} error - AJV error
72
+ * @param {Object} [options] - rootData or deploymentManifest (same shape as validated root)
73
+ * @returns {*|undefined}
74
+ */
75
+ function resolveErrorDataValue(error, options = {}) {
76
+ if (error && error.data !== undefined) return error.data;
77
+ const root = options.rootData !== undefined ? options.rootData : options.deploymentManifest;
78
+ if (!root) return undefined;
79
+ return getValueAtInstancePath(root, error.instancePath || '');
80
+ }
81
+
50
82
  /**
51
83
  * Formats a pattern validation error with the actual invalid value
52
84
  * @function formatPatternError
53
85
  * @param {string} field - Field name
54
86
  * @param {Object} error - Validation error object
87
+ * @param {Object} [options] - Pass rootData or deploymentManifest to show value when error.data is missing
55
88
  * @returns {string} Formatted error message
56
89
  */
57
- function formatPatternError(field, error) {
58
- const invalidValue = error.data !== undefined ? `"${error.data}"` : 'value';
90
+ function formatPatternError(field, error, options = {}) {
91
+ const actual = resolveErrorDataValue(error, options);
92
+ const invalidValue =
93
+ actual === undefined
94
+ ? '(unavailable — pass rootData/deploymentManifest to formatValidationErrors to show it)'
95
+ : JSON.stringify(actual);
59
96
  const patternDesc = getPatternDescription(error.params?.pattern);
60
97
  return `${field}: Invalid value ${invalidValue} - ${patternDesc}`;
61
98
  }
@@ -121,19 +158,16 @@ function createKeywordFormatters(field, error) {
121
158
  ? `${field}: Must be at most ${params.limit} characters`
122
159
  : `${field}: Too long`,
123
160
 
161
+ minItems: params.limit !== undefined
162
+ ? `${field}: must have at least ${params.limit} item(s)`
163
+ : `${field}: too few items`,
164
+
124
165
  enum: params.allowedValues && params.allowedValues.length > 0
125
166
  ? `${field}: Must be one of: ${params.allowedValues.join(', ')}`
126
167
  : `${field}: Must be one of: unknown`
127
168
  };
128
169
  }
129
170
 
130
- /**
131
- * Formats a single validation error into a developer-friendly message
132
- *
133
- * @function formatSingleError
134
- * @param {Object} error - Raw validation error from Ajv
135
- * @returns {string} Formatted error message
136
- */
137
171
  /**
138
172
  * Formats oneOf/anyOf validation errors with actionable message
139
173
  * @param {string} field - Field name
@@ -163,12 +197,55 @@ function formatConstError(field, error) {
163
197
  return `${field}: invalid value (constraint violation)`;
164
198
  }
165
199
 
166
- function formatSingleError(error) {
200
+ /** JSON Pointer: /permissions/<index>/roles */
201
+ const PERMISSION_ROLES_INSTANCE_PATH = /^\/permissions\/(\d+)\/roles$/;
202
+
203
+ /**
204
+ * Clear message when permissions[i].roles is [] (schema minItems: 1).
205
+ * @param {Object} error - AJV error
206
+ * @param {Object} [options] - Optional context
207
+ * @param {Object} [options.deploymentManifest] - Deploy JSON being validated (for permission name)
208
+ * @returns {string|null}
209
+ */
210
+ function tryFormatPermissionRolesMinItemsError(error, options) {
211
+ if (error.keyword !== 'minItems') {
212
+ return null;
213
+ }
214
+ const m = (error.instancePath || '').match(PERMISSION_ROLES_INSTANCE_PATH);
215
+ if (!m) {
216
+ return null;
217
+ }
218
+ const idx = parseInt(m[1], 10);
219
+ const perms = options?.deploymentManifest?.permissions;
220
+ const perm = Array.isArray(perms) ? perms[idx] : null;
221
+ const named =
222
+ perm && typeof perm.name === 'string' && perm.name.trim()
223
+ ? ` "${perm.name.trim()}"`
224
+ : ` at permissions[${idx}]`;
225
+ return (
226
+ `RBAC: permission${named} has an empty "roles" array. ` +
227
+ 'Each permission must list at least one role, and each string must match a role "value" from your "roles" list ' +
228
+ '(in application.yaml or rbac.yaml under the app folder). ' +
229
+ 'Add roles, e.g. roles: ["admin"], or remove the permission if it is unused.'
230
+ );
231
+ }
232
+
233
+ /**
234
+ * @param {Object} error - Raw validation error from Ajv
235
+ * @param {Object} [options] - Optional; use deploymentManifest for richer RBAC messages
236
+ * @returns {string} Formatted error message
237
+ */
238
+ function formatSingleError(error, options) {
167
239
  const field = getFieldName(error);
168
240
 
241
+ const rbacRolesMsg = tryFormatPermissionRolesMinItemsError(error, options);
242
+ if (rbacRolesMsg) {
243
+ return rbacRolesMsg;
244
+ }
245
+
169
246
  // Handle pattern errors with special formatting
170
247
  if (error.keyword === 'pattern') {
171
- return formatPatternError(field, error);
248
+ return formatPatternError(field, error, options);
172
249
  }
173
250
  if (error.keyword === 'additionalProperties') {
174
251
  return formatAdditionalPropertiesError(field, error);
@@ -194,18 +271,19 @@ function formatSingleError(error) {
194
271
  *
195
272
  * @function formatValidationErrors
196
273
  * @param {Array} errors - Raw validation errors from Ajv
274
+ * @param {Object} [options] - Optional; pass `{ deploymentManifest }` or `{ rootData }` for RBAC/pattern detail
197
275
  * @returns {Array} Formatted error messages
198
276
  *
199
277
  * @example
200
278
  * const messages = formatValidationErrors(ajvErrors);
201
279
  * // Returns: ['Port must be between 1 and 65535', 'Missing required field: displayName']
202
280
  */
203
- function formatValidationErrors(errors) {
281
+ function formatValidationErrors(errors, options) {
204
282
  if (!Array.isArray(errors)) {
205
283
  return ['Unknown validation error'];
206
284
  }
207
285
 
208
- return errors.map(formatSingleError);
286
+ return errors.map((e) => formatSingleError(e, options));
209
287
  }
210
288
 
211
289
  /**
@@ -232,5 +310,6 @@ module.exports = {
232
310
  formatValidationErrors,
233
311
  formatMissingDbPasswordError,
234
312
  getPatternDescription,
313
+ getValueAtInstancePath,
235
314
  PATTERN_DESCRIPTIONS
236
315
  };
@@ -1,3 +1,4 @@
1
+ const { formatBlockingError } = require('../cli-test-layout-chalk');
1
2
  /**
2
3
  * HTTP Status Error Formatters
3
4
  *
@@ -123,7 +124,7 @@ function addAuthenticationGuidance(lines, errorData) {
123
124
 
124
125
  function formatAuthenticationError(errorData) {
125
126
  const lines = [];
126
- lines.push(chalk.red('Authentication Failed\n'));
127
+ lines.push(formatBlockingError('Authentication Failed\n'));
127
128
 
128
129
  addControllerUrlInfo(lines, errorData);
129
130
  addAttemptedUrlsInfo(lines, errorData);
@@ -148,7 +149,7 @@ function formatAuthenticationError(errorData) {
148
149
  */
149
150
  function formatServerError(errorData) {
150
151
  const lines = [];
151
- lines.push(chalk.red('Server Error\n'));
152
+ lines.push(formatBlockingError('Server Error\n'));
152
153
 
153
154
  // Show controller URL if available
154
155
  if (errorData.controllerUrl) {
@@ -183,7 +184,7 @@ function formatServerError(errorData) {
183
184
  */
184
185
  function formatConflictError(errorData) {
185
186
  const lines = [];
186
- lines.push(chalk.red('Conflict\n'));
187
+ lines.push(formatBlockingError('Conflict\n'));
187
188
 
188
189
  // Show controller URL if available
189
190
  if (errorData.controllerUrl) {
@@ -252,7 +253,7 @@ function getNotFoundGuidance(detail) {
252
253
  */
253
254
  function formatNotFoundError(errorData) {
254
255
  const lines = [];
255
- lines.push(chalk.red('Not Found\n'));
256
+ lines.push(formatBlockingError('Not Found\n'));
256
257
 
257
258
  // Show controller URL if available
258
259
  if (errorData.controllerUrl) {
@@ -289,7 +290,7 @@ function formatNotFoundError(errorData) {
289
290
  */
290
291
  function formatGenericError(errorData, statusCode) {
291
292
  const lines = [];
292
- lines.push(chalk.red(`❌ Error (HTTP ${statusCode})\n`));
293
+ lines.push(chalk.red(`✖ Error (HTTP ${statusCode})\n`));
293
294
 
294
295
  // Show controller URL if available
295
296
  if (errorData.controllerUrl) {
@@ -1,3 +1,4 @@
1
+ const { formatBlockingError } = require('../cli-test-layout-chalk');
1
2
  /**
2
3
  * Network Error Formatters
3
4
  *
@@ -135,7 +136,7 @@ function addCorrelationId(lines, errorData) {
135
136
  */
136
137
  function formatNetworkError(errorMessage, errorData) {
137
138
  const lines = [];
138
- lines.push(chalk.red('Network Error\n'));
139
+ lines.push(formatBlockingError('Network Error\n'));
139
140
 
140
141
  addControllerUrlHeader(lines, errorData);
141
142
 
@@ -1,3 +1,4 @@
1
+ const { formatBlockingError } = require('../cli-test-layout-chalk');
1
2
  /**
2
3
  * Permission Error Formatters
3
4
  *
@@ -103,7 +104,7 @@ function getPermissionDetailLines(errorData) {
103
104
  */
104
105
  function formatPermissionError(errorData) {
105
106
  const lines = [];
106
- lines.push(chalk.red('Permission Denied\n'));
107
+ lines.push(formatBlockingError('Permission Denied\n'));
107
108
 
108
109
  if (errorData.detail) {
109
110
  lines.push(chalk.yellow(errorData.detail));
@@ -1,3 +1,4 @@
1
+ const { formatBlockingError } = require('../cli-test-layout-chalk');
1
2
  /**
2
3
  * Validation Error Formatters
3
4
  *
@@ -111,7 +112,7 @@ function addValidationGuidance(lines, hasErrors) {
111
112
  */
112
113
  function formatValidationError(errorData) {
113
114
  const lines = [];
114
- lines.push(chalk.red('Validation Error\n'));
115
+ lines.push(formatBlockingError('Validation Error\n'));
115
116
 
116
117
  addValidationErrorMessage(lines, errorData);
117
118
  addValidationErrorsList(lines, errorData.errors);
@@ -133,6 +133,10 @@ function buildSecretPaths(systemKey, authType) {
133
133
  * @param {Object} [params.authentication] - Full authentication object (authType used if authType not set)
134
134
  * @returns {Object} Template context
135
135
  */
136
+ function rbacOptionalFilename(normalizedExt) {
137
+ return normalizedExt === '.yaml' || normalizedExt === '.yml' ? 'rbac.yaml' : 'rbac.json';
138
+ }
139
+
136
140
  function buildExternalReadmeContext(params = {}) {
137
141
  const appName = params.appName || params.systemKey || 'external-system';
138
142
  const systemKey = params.systemKey || appName;
@@ -140,9 +144,11 @@ function buildExternalReadmeContext(params = {}) {
140
144
  const description = params.description || `External system integration for ${systemKey}`;
141
145
  const systemType = params.systemType || 'openapi';
142
146
  const fileExt = params.fileExt !== undefined ? params.fileExt : '.json';
147
+ const normalizedExt = fileExt && fileExt.startsWith('.') ? fileExt : `.${fileExt || 'json'}`;
143
148
  const datasources = normalizeDatasources(params.datasources, systemKey, fileExt);
144
149
  const authType = params.authType || params.authentication?.type || params.authentication?.method || params.authentication?.authType;
145
150
  const secretPaths = buildSecretPaths(systemKey, authType);
151
+ const rbacOptionalFile = rbacOptionalFilename(normalizedExt);
146
152
 
147
153
  return {
148
154
  appName,
@@ -150,7 +156,8 @@ function buildExternalReadmeContext(params = {}) {
150
156
  displayName,
151
157
  description,
152
158
  systemType,
153
- fileExt: fileExt && fileExt.startsWith('.') ? fileExt : `.${fileExt || 'json'}`,
159
+ fileExt: normalizedExt,
160
+ rbacOptionalFile,
154
161
  datasourceCount: datasources.length,
155
162
  hasDatasources: datasources.length > 0,
156
163
  datasources,