@aifabrix/builder 2.52.0 → 2.53.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 (310) hide show
  1. package/lib/api/datasources-extended.api.js +8 -8
  2. package/lib/api/keycloak.api.js +92 -0
  3. package/lib/api/token-providers.api.js +77 -0
  4. package/lib/api/types/keycloak.types.js +23 -0
  5. package/lib/api/types/token-providers.types.js +65 -0
  6. package/lib/app/deploy-config.js +3 -2
  7. package/lib/app/down.js +16 -1
  8. package/lib/channels/add-channel.js +134 -57
  9. package/lib/channels/approval-guides/chatgpt.js +1 -1
  10. package/lib/channels/approval-guides/index.js +3 -0
  11. package/lib/channels/approval-guides/microsoft-copilot.js +27 -14
  12. package/lib/channels/channel-add-ensure.js +128 -0
  13. package/lib/channels/channel-add-existing.js +72 -0
  14. package/lib/channels/channel-artifact-generator.js +11 -1
  15. package/lib/channels/channel-branding.js +94 -0
  16. package/lib/channels/channel-credential.js +8 -0
  17. package/lib/channels/channel-discovery.js +330 -0
  18. package/lib/channels/channel-external-system.js +1 -1
  19. package/lib/channels/channel-runtime-resolver.js +107 -14
  20. package/lib/channels/channel-status-display.js +36 -3
  21. package/lib/channels/microsoft-copilot-channel-add.js +138 -0
  22. package/lib/channels/microsoft-copilot-entra-sso-form.js +251 -0
  23. package/lib/channels/microsoft-copilot-entra-sso.js +285 -0
  24. package/lib/channels/microsoft-copilot-icons.js +74 -0
  25. package/lib/channels/microsoft-copilot-limits.js +103 -0
  26. package/lib/channels/microsoft-copilot-package.js +178 -52
  27. package/lib/channels/microsoft-copilot-validate.js +227 -0
  28. package/lib/cli/attach-default-help-examples.js +102 -0
  29. package/lib/cli/index.js +4 -0
  30. package/lib/cli/infra-guided.js +13 -6
  31. package/lib/cli/setup-credential-deployment.js +7 -5
  32. package/lib/cli/setup-infra.js +31 -4
  33. package/lib/cli/setup-utility-validate.js +1 -0
  34. package/lib/commands/channel-add-setup.js +28 -9
  35. package/lib/commands/channel.js +14 -10
  36. package/lib/commands/credential-push.js +37 -5
  37. package/lib/commands/integration-definition.js +158 -0
  38. package/lib/commands/package-score.js +72 -0
  39. package/lib/commands/repair-auth-apply.js +19 -5
  40. package/lib/commands/repair-datasource-sync-operations.js +4 -1
  41. package/lib/commands/role-assistant-test-output.js +200 -0
  42. package/lib/commands/role-assistant.js +163 -166
  43. package/lib/datasource/capability/capability-resolve.js +15 -5
  44. package/lib/datasource/capability/copy-operations.js +14 -4
  45. package/lib/deployment/deployer-poll-run.js +2 -2
  46. package/lib/deployment/deployer.js +1 -1
  47. package/lib/deployment/environment.js +2 -2
  48. package/lib/external-system/deploy.js +11 -21
  49. package/lib/infrastructure/index.js +19 -4
  50. package/lib/integration-definition/apply.js +476 -0
  51. package/lib/integration-definition/canonical-json.js +51 -0
  52. package/lib/integration-definition/emit-suite-bid.js +94 -0
  53. package/lib/integration-definition/enrich-crm-field-mappings.js +240 -0
  54. package/lib/integration-definition/enrich-openapi-operations.js +433 -0
  55. package/lib/integration-definition/from-discovery.js +339 -0
  56. package/lib/integration-definition/hash.js +37 -0
  57. package/lib/integration-definition/index.js +37 -0
  58. package/lib/integration-definition/resource-type-catalog.js +59 -0
  59. package/lib/integration-definition/system-kind-enum.js +40 -0
  60. package/lib/integration-definition/validate.js +148 -0
  61. package/lib/lab/package-parity-score.js +417 -0
  62. package/lib/programmatic/builder-api-request.js +5 -1
  63. package/lib/programmatic/builder-help-governance.js +3 -2
  64. package/lib/programmatic/capability-registry.js +20 -0
  65. package/lib/programmatic/help-content/channel-onboarding.md +35 -0
  66. package/lib/programmatic/help-content/cip-overview.md +27 -0
  67. package/lib/programmatic/help-content/connected-system-ui.md +70 -0
  68. package/lib/programmatic/help-content/dimensions-guide.md +23 -0
  69. package/lib/programmatic/help-content/enterprise-sync-fabrix.md +123 -0
  70. package/lib/programmatic/help-content/overview.md +25 -0
  71. package/lib/programmatic/help-content/subscription-guide.md +27 -0
  72. package/lib/programmatic/help-content/workflow.md +50 -0
  73. package/lib/programmatic/openapi-component-schemas.js +7 -1
  74. package/lib/programmatic/openapi-descriptions.js +46 -0
  75. package/lib/programmatic/openapi-envelope-examples.js +280 -0
  76. package/lib/programmatic/openapi-operation-bindings.js +50 -0
  77. package/lib/programmatic/openapi-request-schemas.js +40 -0
  78. package/lib/programmatic/openapi-result-schemas-overflow.js +101 -0
  79. package/lib/programmatic/openapi-result-schemas.js +76 -99
  80. package/lib/programmatic/openapi-schema-descriptions-core.js +25 -4
  81. package/lib/programmatic/openapi-schema-descriptions-help.js +1 -1
  82. package/lib/programmatic/openapi-schema-descriptions-operations.js +43 -0
  83. package/lib/programmatic/openapi-schema-helpers.js +9 -9
  84. package/lib/programmatic/openapi-spec.js +11 -1
  85. package/lib/programmatic/orchestration-openapi-meta.js +10 -0
  86. package/lib/programmatic/persist-supplied-openapi.js +180 -0
  87. package/lib/programmatic/route-handler-map.js +35 -1
  88. package/lib/programmatic/run-channel-package.js +236 -0
  89. package/lib/programmatic/run-integration-definition.js +77 -0
  90. package/lib/role-assistant/evidence-sync.js +55 -7
  91. package/lib/role-assistant/knowledge-sync-logging.js +58 -0
  92. package/lib/role-assistant/knowledge-sync.js +88 -93
  93. package/lib/role-assistant/test-cases-bid.js +155 -0
  94. package/lib/role-assistant/test-cases-evaluate.js +9 -1
  95. package/lib/role-assistant/test-cases-honesty.js +24 -10
  96. package/lib/role-assistant/test-cases.js +28 -0
  97. package/lib/role-assistant/test-runner-attachments.js +118 -0
  98. package/lib/role-assistant/test-runner-bid-apply.js +201 -0
  99. package/lib/role-assistant/test-runner-bid-document.js +278 -0
  100. package/lib/role-assistant/test-runner-start-payload.js +96 -0
  101. package/lib/role-assistant/test-runner-workhub-answers.js +249 -20
  102. package/lib/role-assistant/test-runner-workhub-helpers.js +100 -0
  103. package/lib/role-assistant/test-runner-workhub-soft.js +86 -0
  104. package/lib/role-assistant/test-runner-workhub.js +152 -107
  105. package/lib/role-assistant/test-runner.js +5 -63
  106. package/lib/role-assistant/test-suite.js +112 -0
  107. package/lib/schema/application-schema.json +56 -6
  108. package/lib/schema/external-datasource.schema.json +103 -17
  109. package/lib/schema/external-system.schema.json +54 -3
  110. package/lib/schema/integration-definition.schema.json +195 -0
  111. package/lib/utils/authentication-shape.js +6 -0
  112. package/lib/utils/compose-generator.js +10 -1
  113. package/lib/utils/compose-traefik-extra-routes.js +107 -0
  114. package/lib/utils/docker-build.js +2 -2
  115. package/lib/utils/help-builder.js +3 -1
  116. package/lib/utils/promote-dev-docker-image.js +102 -18
  117. package/lib/utils/transient-developer-id.js +28 -0
  118. package/package.json +14 -16
  119. package/templates/README.md +12 -1
  120. package/templates/applications/dataplane/application.yaml +10 -2
  121. package/templates/applications/dataplane/env.template +7 -6
  122. package/templates/applications/miso-controller/application.yaml +23 -8
  123. package/templates/applications/miso-controller/env.template +8 -2
  124. package/templates/applications/miso-controller/rbac.yaml +1 -0
  125. package/templates/channels/README.md +11 -1
  126. package/templates/channels/brand/color-192.png +0 -0
  127. package/templates/channels/brand/dark/128.png +0 -0
  128. package/templates/channels/brand/dark/192.png +0 -0
  129. package/templates/channels/brand/dark/256.png +0 -0
  130. package/templates/channels/brand/dark/32.png +0 -0
  131. package/templates/channels/brand/dark/512.png +0 -0
  132. package/templates/channels/brand/dark/64.png +0 -0
  133. package/templates/channels/brand/light/128.png +0 -0
  134. package/templates/channels/brand/light/192.png +0 -0
  135. package/templates/channels/brand/light/256.png +0 -0
  136. package/templates/channels/brand/light/32.png +0 -0
  137. package/templates/channels/brand/light/512.png +0 -0
  138. package/templates/channels/brand/light/64.png +0 -0
  139. package/templates/channels/brand/mono-white/128.png +0 -0
  140. package/templates/channels/brand/mono-white/192.png +0 -0
  141. package/templates/channels/brand/mono-white/256.png +0 -0
  142. package/templates/channels/brand/mono-white/32.png +0 -0
  143. package/templates/channels/brand/mono-white/512.png +0 -0
  144. package/templates/channels/brand/mono-white/64.png +0 -0
  145. package/templates/channels/brand/outline-32.png +0 -0
  146. package/templates/channels/chatgpt/install.template.md.hbs +6 -4
  147. package/templates/channels/chatgpt/integration/README.md +4 -5
  148. package/templates/channels/chatgpt/integration/chatgpt-system.json +1 -16
  149. package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +14 -16
  150. package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +5 -3
  151. package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +30 -0
  152. package/templates/channels/microsoft-copilot/fi-fi.template.json.hbs +7 -0
  153. package/templates/channels/microsoft-copilot/install.template.md.hbs +93 -22
  154. package/templates/channels/microsoft-copilot/integration/README.md +2 -3
  155. package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +1 -22
  156. package/templates/channels/microsoft-copilot/manifest.template.json.hbs +34 -19
  157. package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +15 -0
  158. package/templates/channels/slack/integration/README.md +2 -4
  159. package/templates/channels/teams-bot/install.template.md.hbs +4 -0
  160. package/templates/channels/teams-bot/integration/README.md +3 -5
  161. package/templates/channels/web-embed/integration/web-embed-system.json +1 -16
  162. package/templates/python/docker-compose.hbs +36 -0
  163. package/templates/typescript/docker-compose.hbs +36 -0
  164. package/.cursor/plans/Done/157.1-security-quality-violations-by-type.csv +0 -374
  165. package/.cursor/process/README.md +0 -9
  166. package/.cursor/rules/anchor-docs.mdc +0 -15
  167. package/.cursor/rules/assistant-driven-integration-build.mdc +0 -40
  168. package/.cursor/rules/cli-layout.mdc +0 -81
  169. package/.cursor/rules/cli-product-neutral.mdc +0 -43
  170. package/.cursor/rules/deploy-rules/docker-image-ip-policy.mdc +0 -49
  171. package/.cursor/rules/docs-rules.mdc +0 -32
  172. package/.cursor/rules/plan-rules/application-lifecycle.mdc +0 -30
  173. package/.cursor/rules/plan-rules/plan-frontmatter.mdc +0 -35
  174. package/.cursor/rules/plan-rules/plan-lifecycle.mdc +0 -31
  175. package/.cursor/rules/plan-rules/plan-validation-gate.mdc +0 -34
  176. package/.cursor/rules/project-rules.mdc +0 -913
  177. package/.cursor/skills/README.md +0 -15
  178. package/.dockerignore +0 -52
  179. package/.eslintignore +0 -22
  180. package/.markdownlint.json +0 -14
  181. package/anchor-docs/README.md +0 -10
  182. package/anchor-docs/_TEMPLATE +0 -24
  183. package/babel.config.js +0 -6
  184. package/bin/builder-api-cleanup.js +0 -26
  185. package/bin/builder-api-nest.js +0 -10
  186. package/bin/builder-api-spike.js +0 -19
  187. package/enterprise-knowledge/README.md +0 -50
  188. package/enterprise-knowledge/enterprise-integration-lifecycle/README.md +0 -22
  189. package/enterprise-knowledge/enterprise-integration-lifecycle/application.json +0 -15
  190. package/enterprise-knowledge/enterprise-integration-lifecycle/deploy.js +0 -69
  191. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-deploy.json +0 -52
  192. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-system.json +0 -29
  193. package/enterprise-knowledge/enterprise-integration-lifecycle/env.template +0 -2
  194. package/integration/README.md +0 -81
  195. package/integration/github/README.md +0 -53
  196. package/integration/github/application.json +0 -21
  197. package/integration/github/deploy.js +0 -72
  198. package/integration/github/env.template +0 -11
  199. package/integration/github/github-datasource-issue-comments.json +0 -239
  200. package/integration/github/github-datasource-issues.json +0 -399
  201. package/integration/github/github-datasource-repository.json +0 -354
  202. package/integration/github/github-deploy.json +0 -1202
  203. package/integration/github/github-system.json +0 -82
  204. package/integration/hubspot-test/README.md +0 -159
  205. package/integration/hubspot-test/application.json +0 -54
  206. package/integration/hubspot-test/companies.json +0 -2048
  207. package/integration/hubspot-test/create-hubspot.js +0 -523
  208. package/integration/hubspot-test/env.template +0 -4
  209. package/integration/hubspot-test/hubspot-test-datasource-company.json +0 -138
  210. package/integration/hubspot-test/hubspot-test-datasource-contact.json +0 -146
  211. package/integration/hubspot-test/hubspot-test-datasource-deal.json +0 -146
  212. package/integration/hubspot-test/hubspot-test-datasource-users.json +0 -76
  213. package/integration/hubspot-test/hubspot-test-deploy.json +0 -2160
  214. package/integration/hubspot-test/hubspot-test-system.json +0 -74
  215. package/integration/hubspot-test/rbac.json +0 -166
  216. package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +0 -20
  217. package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +0 -9
  218. package/integration/hubspot-test/test-artifacts/wizard-invalid-add-datasource.yaml +0 -5
  219. package/integration/hubspot-test/test-artifacts/wizard-invalid-app-name.yaml +0 -5
  220. package/integration/hubspot-test/test-artifacts/wizard-invalid-credential-create.yaml +0 -7
  221. package/integration/hubspot-test/test-artifacts/wizard-invalid-credential-select.yaml +0 -7
  222. package/integration/hubspot-test/test-artifacts/wizard-invalid-known-platform.yaml +0 -4
  223. package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-app.yaml +0 -4
  224. package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-source.yaml +0 -2
  225. package/integration/hubspot-test/test-artifacts/wizard-invalid-mode.yaml +0 -5
  226. package/integration/hubspot-test/test-artifacts/wizard-invalid-openapi-file.yaml +0 -5
  227. package/integration/hubspot-test/test-artifacts/wizard-invalid-openapi-url.yaml +0 -4
  228. package/integration/hubspot-test/test-artifacts/wizard-invalid-source.yaml +0 -4
  229. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-array-test.yaml +0 -5
  230. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-key-test.yaml +0 -5
  231. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-path-test.yaml +0 -5
  232. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-test.yaml +0 -5
  233. package/integration/hubspot-test/test-artifacts/wizard-valid-for-rbac-test.yaml +0 -5
  234. package/integration/hubspot-test/test-artifacts/wizard-valid-for-rbac-yaml-test.yaml +0 -5
  235. package/integration/hubspot-test/test-dataplane-down-helpers.js +0 -249
  236. package/integration/hubspot-test/test-dataplane-down-tests.js +0 -386
  237. package/integration/hubspot-test/test-dataplane-down.js +0 -209
  238. package/integration/hubspot-test/test.js +0 -1588
  239. package/integration/hubspot-test/wizard-hubspot-e2e.yaml +0 -16
  240. package/integration/hubspot-test/wizard-hubspot-platform.yaml +0 -8
  241. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +0 -23
  242. package/integration/roundtrip-test-local/README.md +0 -143
  243. package/integration/roundtrip-test-local/application.yaml +0 -13
  244. package/integration/roundtrip-test-local/env.template +0 -15
  245. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +0 -14
  246. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +0 -61
  247. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +0 -25
  248. package/integration/roundtrip-test-local2/README.md +0 -143
  249. package/integration/roundtrip-test-local2/application.yaml +0 -13
  250. package/integration/roundtrip-test-local2/env.template +0 -15
  251. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +0 -31
  252. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +0 -86
  253. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +0 -25
  254. package/integration/test/wizard.yaml +0 -8
  255. package/jest.config.coverage.js +0 -37
  256. package/jest.config.default.js +0 -11
  257. package/jest.config.integration.fixtures.js +0 -22
  258. package/jest.config.integration.js +0 -33
  259. package/jest.config.isolated.js +0 -11
  260. package/jest.config.manual.js +0 -30
  261. package/jest.global-live-fabrix-hooks.js +0 -36
  262. package/jest.isolated-projects.js +0 -260
  263. package/jest.projects.js +0 -76
  264. package/packages/builder-api/README.md +0 -120
  265. package/packages/builder-api/package.json +0 -30
  266. package/packages/builder-api/src/app.module.ts +0 -7
  267. package/packages/builder-api/src/auth/auth.module.ts +0 -5
  268. package/packages/builder-api/src/external-system/external-system.module.ts +0 -5
  269. package/packages/builder-api/src/main.ts +0 -16
  270. package/packages/builder-api/tsconfig.json +0 -15
  271. package/scripts/check-builder-api-architecture-grep.js +0 -79
  272. package/scripts/check-datasource-test-run-schema-sync.js +0 -34
  273. package/scripts/ci-fix.sh +0 -19
  274. package/scripts/ci-simulate.sh +0 -19
  275. package/scripts/diagnose-cli.js +0 -150
  276. package/scripts/docker_image_content_gate.js +0 -47
  277. package/scripts/docker_image_content_gate.sh +0 -5
  278. package/scripts/export-builder-api-evidence.js +0 -262
  279. package/scripts/install-local.js +0 -490
  280. package/scripts/lib/builder-api-docker-staging-copy.js +0 -60
  281. package/scripts/lib/builder-api-docker-staging-core.js +0 -183
  282. package/scripts/lib/docker-image-content-gate-core.js +0 -166
  283. package/scripts/lib/plan-actor.js +0 -109
  284. package/scripts/lib/plan-config.js +0 -20
  285. package/scripts/lib/plan-gates.js +0 -154
  286. package/scripts/lib/plan-meta.js +0 -104
  287. package/scripts/lib/plan-parse.js +0 -162
  288. package/scripts/lib/plan-prevalidate-gates.js +0 -337
  289. package/scripts/lib/plan-run-core.js +0 -125
  290. package/scripts/lib/plan-run-report.js +0 -119
  291. package/scripts/plan-approve.js +0 -24
  292. package/scripts/plan-archive.js +0 -49
  293. package/scripts/plan-run.js +0 -13
  294. package/scripts/plan-set-actor.js +0 -21
  295. package/scripts/plan-validate.js +0 -80
  296. package/scripts/pnpm/af.mjs +0 -110
  297. package/scripts/pnpm/check-quiet.mjs +0 -32
  298. package/scripts/pnpm/dev-install.mjs +0 -29
  299. package/scripts/pnpm/dev-reload.mjs +0 -18
  300. package/scripts/pnpm/help.mjs +0 -55
  301. package/scripts/pnpm/lib/dev-reload-core.mjs +0 -189
  302. package/scripts/pnpm/lib/dev-reload-log-capture.mjs +0 -67
  303. package/scripts/pnpm/lib/dev-reload-log-utils.mjs +0 -32
  304. package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +0 -124
  305. package/scripts/pnpm/lib/resolve-app-url.mjs +0 -183
  306. package/scripts/pnpm/lib/spinner.mjs +0 -42
  307. package/scripts/pnpm-global-remove.js +0 -48
  308. package/scripts/stage_builder_api_for_docker.js +0 -65
  309. package/scripts/sync-builder-api-template.js +0 -44
  310. package/scripts/test-dataplane-bootstrap.js +0 -331
@@ -110,6 +110,9 @@ function buildAuthenticationFromMethod(systemKey, authType) {
110
110
  if (method === 'none') {
111
111
  return { authType: 'none' };
112
112
  }
113
+ if (method === 'system') {
114
+ return { authType: 'system' };
115
+ }
113
116
  const flat = buildFlatCredentialTemplate(systemKey, method);
114
117
  return {
115
118
  authType: 'credential',
@@ -174,6 +177,9 @@ function migrateAuthenticationToNestedSchema(authentication, systemKey) {
174
177
  if (authentication.authType === 'none') {
175
178
  return { authentication: { authType: 'none' }, changed: false };
176
179
  }
180
+ if (authentication.authType === 'system') {
181
+ return { authentication: { authType: 'system' }, changed: false };
182
+ }
177
183
  if (authentication.authType === 'apiProvider' && authentication.apiProvider) {
178
184
  return { authentication, changed: false };
179
185
  }
@@ -31,6 +31,7 @@ const {
31
31
  buildTraefikIngressBase,
32
32
  computeTraefikStripPathPrefix
33
33
  } = require('./compose-traefik-ingress-base');
34
+ const { buildTraefikExtraRouters } = require('./compose-traefik-extra-routes');
34
35
  const { parseDeveloperIdNum } = require('./declarative-url-ports');
35
36
 
36
37
  registerComposeHelpers();
@@ -250,13 +251,20 @@ function buildTraefikConfig(config, devId, scopeOpts = null, remoteServer = null
250
251
  // Traefik must only attach routers to `web` for developer-id > 0; `websecure`+tls labels without
251
252
  // matching certs break routing on Traefik 3.6+ for HTTP traffic (404 on PathPrefix).
252
253
  const terminateTlsAtTraefik = base.tls === true && devNum === 0;
254
+ const stripPathPrefix = computeTraefikStripPathPrefix(base.path, resolvedHealth);
255
+ const extra = buildTraefikExtraRouters(config.frontDoorRouting, base.path);
253
256
  return {
254
257
  enabled: true,
255
258
  host: base.host,
256
259
  path: base.path,
257
260
  tls: terminateTlsAtTraefik,
258
261
  certStore: terminateTlsAtTraefik ? base.certStore || null : null,
259
- stripPathPrefix: computeTraefikStripPathPrefix(base.path, resolvedHealth)
262
+ stripPathPrefix,
263
+ passThroughRouters: extra.passThroughRouters,
264
+ aliasRouters: extra.aliasRouters.map((r) => ({
265
+ ...r,
266
+ stripPrimary: stripPathPrefix === true && base.path !== '/'
267
+ }))
260
268
  };
261
269
  }
262
270
 
@@ -424,6 +432,7 @@ module.exports = {
424
432
  getImageName,
425
433
  derivePathFromPattern,
426
434
  buildTraefikConfig,
435
+ buildTraefikExtraRouters,
427
436
  computeAlignedHealthCheckPath,
428
437
  resolveHealthCheckPathWithFrontDoorVdir,
429
438
  buildDevUsername,
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Extra Traefik routers from frontDoorRouting.requiresRuleSet + ruleSetConditions.
3
+ *
4
+ * @fileoverview Schema-legal pass-through routes (plan 171.0). No invented keys.
5
+ * @author AI Fabrix Team
6
+ * @version 1.1.0
7
+ */
8
+
9
+ /**
10
+ * Normalize a route pattern to a PathPrefix value (no trailing slash / wildcards).
11
+ * @param {unknown} pattern
12
+ * @returns {string|null}
13
+ */
14
+ function normalizeRoutePrefix(pattern) {
15
+ if (!pattern || typeof pattern !== 'string') {
16
+ return null;
17
+ }
18
+ const trimmed = pattern.trim();
19
+ if (!trimmed.startsWith('/')) {
20
+ return null;
21
+ }
22
+ if (trimmed === '/' || trimmed === '/*') {
23
+ return '/';
24
+ }
25
+ const withoutWildcards = trimmed.replace(/\/\*+$/g, '').replace(/\*+$/g, '');
26
+ const withoutTrailing = withoutWildcards.replace(/\/+$/g, '');
27
+ return withoutTrailing || '/';
28
+ }
29
+
30
+ /**
31
+ * Safe Traefik label id fragment from a path prefix.
32
+ * @param {string} prefix
33
+ * @param {number} index
34
+ * @returns {string}
35
+ */
36
+ function routeIdFromPrefix(prefix, index) {
37
+ const slug = String(prefix || 'x')
38
+ .replace(/^\//, '')
39
+ .replace(/[^a-zA-Z0-9]+/g, '-')
40
+ .replace(/^-+|-+$/g, '')
41
+ .slice(0, 40);
42
+ return `${slug || 'route'}-${index}`;
43
+ }
44
+
45
+ /**
46
+ * Collect PathPrefix values from ruleSetConditions matchValues.
47
+ * @param {Object} frontDoor
48
+ * @returns {string[]}
49
+ */
50
+ function matchValuesFromRuleSetConditions(frontDoor) {
51
+ if (frontDoor.requiresRuleSet !== true) {
52
+ return [];
53
+ }
54
+ const conditions = Array.isArray(frontDoor.ruleSetConditions)
55
+ ? frontDoor.ruleSetConditions
56
+ : [];
57
+ const prefixes = [];
58
+ conditions.forEach((condition) => {
59
+ if (!condition || typeof condition !== 'object') {
60
+ return;
61
+ }
62
+ const values = Array.isArray(condition.matchValues) ? condition.matchValues : [];
63
+ values.forEach((raw) => {
64
+ const pathPrefix = normalizeRoutePrefix(raw);
65
+ if (pathPrefix && pathPrefix !== '/') {
66
+ prefixes.push(pathPrefix);
67
+ }
68
+ });
69
+ });
70
+ return prefixes;
71
+ }
72
+
73
+ /**
74
+ * Build Traefik extra-route descriptors from frontDoorRouting (schema fields only).
75
+ * @param {Object|null|undefined} frontDoor
76
+ * @param {string} _primaryPath - Resolved primary PathPrefix (unused; reserved for callers)
77
+ * @returns {{ passThroughRouters: object[], aliasRouters: object[] }}
78
+ */
79
+ function buildTraefikExtraRouters(frontDoor, _primaryPath) {
80
+ const passThroughRouters = [];
81
+ const aliasRouters = [];
82
+ if (!frontDoor || typeof frontDoor !== 'object') {
83
+ return { passThroughRouters, aliasRouters };
84
+ }
85
+
86
+ const prefixes = matchValuesFromRuleSetConditions(frontDoor);
87
+ const seen = new Set();
88
+ prefixes.forEach((pathPrefix, index) => {
89
+ if (seen.has(pathPrefix)) {
90
+ return;
91
+ }
92
+ seen.add(pathPrefix);
93
+ passThroughRouters.push({
94
+ id: routeIdFromPrefix(pathPrefix, index),
95
+ pathPrefix
96
+ });
97
+ });
98
+
99
+ return { passThroughRouters, aliasRouters };
100
+ }
101
+
102
+ module.exports = {
103
+ normalizeRoutePrefix,
104
+ routeIdFromPrefix,
105
+ matchValuesFromRuleSetConditions,
106
+ buildTraefikExtraRouters
107
+ };
@@ -253,8 +253,8 @@ async function executeBuild(imageName, dockerfilePath, contextPath, tag, options
253
253
  );
254
254
  await executeDockerBuild(imageName, dockerfilePath, contextPath, tag, buildArgs, noCache);
255
255
 
256
- // Tag image if additional tag provided
257
- if (options && options.tag && options.tag !== 'latest') {
256
+ // Also apply floating `latest` when building a version tag (matches dev-promote dual tags).
257
+ if (options && options.tag && options.tag !== 'latest' && options.tag !== 'main') {
258
258
  const { execFileWithDockerEnv } = require('./docker-exec');
259
259
  const { getDockerExecEnv } = require('./remote-docker-env');
260
260
  const env = await getDockerExecEnv();
@@ -98,7 +98,8 @@ const CATEGORIES = [
98
98
  { name: 'validate', term: 'validate [appKey|systemKey|file]' },
99
99
  { name: 'validate-json', term: 'validate-json [appKey|systemKey]' },
100
100
  { name: 'parameters', term: 'parameters validate' },
101
- { name: 'diff', term: 'diff <file1> <file2>' }
101
+ { name: 'diff', term: 'diff <file1> <file2>' },
102
+ { name: 'package-score', term: 'package-score --reference <dir> --candidate <dir>' }
102
103
  ]
103
104
  },
104
105
  {
@@ -111,6 +112,7 @@ const CATEGORIES = [
111
112
  { name: 'delete', term: 'delete <systemKey>' },
112
113
  { name: 'repair', term: 'repair <systemKey>' },
113
114
  { name: 'manifest', term: 'manifest get-section <systemKey> <sectionKey>' },
115
+ { name: 'integration-definition', term: 'integration-definition apply <file>' },
114
116
  { name: 'channel', term: 'channel scaffold <channelTarget>' },
115
117
  { name: 'datasource' },
116
118
  { name: 'datasource load', term: 'datasource load <datasourceKey>' },
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * Promote a developer-scoped local Docker image to the manifest base repository (tag only).
3
3
  *
4
- * @fileoverview Used by `aifabrix build --base --from-dev` and dev-promote workflows
4
+ * @fileoverview Used by `aifabrix build --base --from-dev` and dev-promote workflows.
5
+ * Promote always applies two base tags: `latest` (floating) and the version tag (TAG / package version).
5
6
  * @author AI Fabrix Team
6
- * @version 1.0.0
7
+ * @version 1.2.0
7
8
  */
8
9
 
9
10
  'use strict';
@@ -15,6 +16,12 @@ const { execWithDockerEnv } = require('./docker-exec');
15
16
  const logger = require('./logger');
16
17
  const { formatSuccessLine } = require('./cli-test-layout-chalk');
17
18
 
19
+ /** Floating base tag applied on every promote alongside the version tag (matches setup manifests). */
20
+ const PROMOTE_FLOATING_TAG = 'latest';
21
+
22
+ /** @deprecated Use {@link PROMOTE_FLOATING_TAG}. Kept for callers that imported the old name. */
23
+ const PROMOTE_MAIN_TAG = PROMOTE_FLOATING_TAG;
24
+
18
25
  /**
19
26
  * @param {string} value
20
27
  * @returns {string}
@@ -61,6 +68,34 @@ async function dockerTagImageRef(sourceRef, targetRef) {
61
68
  await execWithDockerEnv(`docker tag ${shellQuote(sourceRef)} ${shellQuote(targetRef)}`);
62
69
  }
63
70
 
71
+ /**
72
+ * Version tag for promote (not floating aliases).
73
+ * @param {Object} options
74
+ * @returns {string}
75
+ */
76
+ function resolvePromoteVersionTag(options = {}) {
77
+ const raw = String(options.tag || '').trim();
78
+ // `main` accepted as legacy alias for the floating tag.
79
+ if (!raw || raw === PROMOTE_FLOATING_TAG || raw === 'main') {
80
+ return PROMOTE_FLOATING_TAG;
81
+ }
82
+ return raw;
83
+ }
84
+
85
+ /**
86
+ * Base tags to apply on promote: version first, then `latest` when distinct.
87
+ * @param {Object} options
88
+ * @returns {string[]}
89
+ */
90
+ function resolvePromoteBaseTags(options = {}) {
91
+ const versionTag = resolvePromoteVersionTag(options);
92
+ const tags = [versionTag];
93
+ if (versionTag !== PROMOTE_FLOATING_TAG) {
94
+ tags.push(PROMOTE_FLOATING_TAG);
95
+ }
96
+ return tags;
97
+ }
98
+
64
99
  /**
65
100
  * @param {string} appName
66
101
  * @param {Object} variables
@@ -69,7 +104,7 @@ async function dockerTagImageRef(sourceRef, targetRef) {
69
104
  * @returns {Promise<{ devRef: string, baseRef: string, devTag: string, baseTag: string }>}
70
105
  */
71
106
  async function resolveDevAndBaseImageRefs(appName, variables, developerId, options) {
72
- const baseTag = options.tag || 'latest';
107
+ const baseTag = resolvePromoteVersionTag(options);
73
108
  const devTag = options.fromDevTag || 'latest';
74
109
  const { buildImageName: baseName } = await resolveBuildDockerTagNames(appName, variables, developerId, {
75
110
  ...options,
@@ -93,31 +128,68 @@ async function resolveDevAndBaseImageRefs(appName, variables, developerId, optio
93
128
  * @param {Object} appConfig
94
129
  * @param {string|number} developerId
95
130
  * @param {Object} options
96
- * @returns {Promise<{ devRef: string, baseRef: string }|null>}
131
+ * @returns {Promise<{
132
+ * devRef: string,
133
+ * baseRef: string,
134
+ * baseName: string,
135
+ * baseTags: string[]
136
+ * }|null>}
97
137
  */
98
138
  async function resolvePromoteSourceAndTargetRefs(appName, appConfig, developerId, options) {
99
- const baseTag = options.tag || 'latest';
139
+ const baseTags = resolvePromoteBaseTags(options);
140
+ const versionTag = baseTags[0];
100
141
  const devTagCandidates = ['latest'];
101
- if (baseTag !== 'latest' && !devTagCandidates.includes(baseTag)) {
102
- devTagCandidates.push(baseTag);
142
+ if (versionTag !== 'latest' && !devTagCandidates.includes(versionTag)) {
143
+ devTagCandidates.push(versionTag);
103
144
  }
104
145
  for (const fromDevTag of devTagCandidates) {
105
146
  const refs = await resolveDevAndBaseImageRefs(appName, appConfig, developerId, {
106
147
  ...options,
148
+ tag: versionTag,
107
149
  fromDevTag
108
150
  });
109
151
  if (await dockerImageRefExists(refs.devRef)) {
110
- return { devRef: refs.devRef, baseRef: refs.baseRef };
152
+ const baseName = refs.baseRef.slice(0, refs.baseRef.lastIndexOf(':'));
153
+ return {
154
+ devRef: refs.devRef,
155
+ baseRef: refs.baseRef,
156
+ baseName,
157
+ baseTags
158
+ };
111
159
  }
112
160
  }
113
161
  return null;
114
162
  }
115
163
 
164
+ /**
165
+ * @param {string} baseName
166
+ * @param {string[]} baseTags
167
+ * @param {string|null} devId
168
+ * @returns {Promise<boolean>} true when every target already matches dev image id
169
+ */
170
+ async function allBaseTagsMatchDev(baseName, baseTags, devId) {
171
+ if (!devId) {
172
+ return false;
173
+ }
174
+ for (const tag of baseTags) {
175
+ const ref = `${baseName}:${tag}`;
176
+ if (!(await dockerImageRefExists(ref))) {
177
+ return false;
178
+ }
179
+ const baseId = await readDockerImageId(ref);
180
+ if (!baseId || baseId !== devId) {
181
+ return false;
182
+ }
183
+ }
184
+ return true;
185
+ }
186
+
116
187
  /**
117
188
  * Tag developer-scoped image as manifest base when present locally.
189
+ * Always applies the version tag and `latest`.
118
190
  * @param {string} appName
119
191
  * @param {Object} options - build options (`base`, `tag`, `registry`, `fromDev`)
120
- * @returns {Promise<string|null>} base image ref when promoted/skipped; null when dev image missing
192
+ * @returns {Promise<string|null>} primary base image ref (version) when promoted; null when missing
121
193
  */
122
194
  async function tryPromoteDevImageToBase(appName, options = {}) {
123
195
  if (options.base !== true) {
@@ -135,19 +207,27 @@ async function tryPromoteDevImageToBase(appName, options = {}) {
135
207
  if (!resolved) {
136
208
  return null;
137
209
  }
138
- const { devRef, baseRef } = resolved;
210
+ const { devRef, baseRef, baseName, baseTags } = resolved;
139
211
 
140
212
  const devId = await readDockerImageId(devRef);
141
- if (await dockerImageRefExists(baseRef)) {
142
- const baseId = await readDockerImageId(baseRef);
143
- if (devId && baseId && devId === baseId) {
144
- logger.log(formatSuccessLine(`Base image already matches dev build: ${baseRef}`));
145
- return baseRef;
146
- }
213
+ if (await allBaseTagsMatchDev(baseName, baseTags, devId)) {
214
+ logger.log(
215
+ formatSuccessLine(
216
+ `Base image already matches dev build: ${baseTags.map((t) => `${baseName}:${t}`).join(', ')}`
217
+ )
218
+ );
219
+ return baseRef;
147
220
  }
148
221
 
149
- await dockerTagImageRef(devRef, baseRef);
150
- logger.log(formatSuccessLine(`Promoted dev image to base (tag only): ${baseRef}`));
222
+ for (const tag of baseTags) {
223
+ const targetRef = `${baseName}:${tag}`;
224
+ await dockerTagImageRef(devRef, targetRef);
225
+ }
226
+ logger.log(
227
+ formatSuccessLine(
228
+ `Promoted dev image to base (tag only): ${baseTags.map((t) => `${baseName}:${t}`).join(', ')}`
229
+ )
230
+ );
151
231
  return baseRef;
152
232
  }
153
233
 
@@ -160,10 +240,14 @@ function shouldAttemptDevPromote(options) {
160
240
  }
161
241
 
162
242
  module.exports = {
243
+ PROMOTE_FLOATING_TAG,
244
+ PROMOTE_MAIN_TAG,
163
245
  tryPromoteDevImageToBase,
164
246
  shouldAttemptDevPromote,
165
247
  resolveDevAndBaseImageRefs,
166
248
  resolvePromoteSourceAndTargetRefs,
249
+ resolvePromoteBaseTags,
250
+ resolvePromoteVersionTag,
167
251
  dockerImageRefExists,
168
252
  readDockerImageId,
169
253
  dockerTagImageRef
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Transient developer-id override for CLI commands (does not persist config).
3
+ *
4
+ * @fileoverview Resolve optional --developer-id / --developer without setDeveloperId
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const { validateAndNormalizeDeveloperId } = require('../core/config-normalize');
10
+
11
+ /**
12
+ * Resolve optional CLI developer override (transient — does not persist).
13
+ * Prefers developerId (--developer-id) over developer (-d/--developer).
14
+ *
15
+ * @param {Object} [options] - Commander options
16
+ * @returns {string|undefined} Normalized digit string, or undefined to use config
17
+ */
18
+ function resolveTransientDeveloperIdFromOptions(options) {
19
+ const raw = options && (options.developerId ?? options.developer);
20
+ if (raw === undefined || raw === null || raw === '') {
21
+ return undefined;
22
+ }
23
+ return validateAndNormalizeDeveloperId(raw);
24
+ }
25
+
26
+ module.exports = {
27
+ resolveTransientDeveloperIdFromOptions
28
+ };
package/package.json CHANGED
@@ -1,12 +1,19 @@
1
1
  {
2
2
  "name": "@aifabrix/builder",
3
- "version": "2.52.0",
3
+ "version": "2.53.0",
4
4
  "description": "AI Fabrix Builder — CLI and developer scripts (pnpm + af)",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
7
7
  "aifabrix": "bin/aifabrix.js",
8
8
  "af": "bin/aifabrix.js"
9
9
  },
10
+ "files": [
11
+ "bin/aifabrix.js",
12
+ "lib/",
13
+ "templates/",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
10
17
  "scripts": {
11
18
  "help": "node scripts/pnpm/help.mjs",
12
19
  "dev-install": "node scripts/pnpm/dev-install.mjs",
@@ -21,32 +28,23 @@
21
28
  "lint:fix": "eslint . --ext .js --fix",
22
29
  "test": "node tests/scripts/test-wrapper.js",
23
30
  "build": "npm run lint && npm run test",
24
- "build:ci": "npm run lint && npm run check:schema-sync && npm run check:flags && npm run test:ci",
31
+ "build:ci": "npm run lint && npm run check:schema-sync && npm run check:flags && npm run check:cli-help && npm run test:ci",
25
32
  "test:ci": "bash tests/scripts/ci-simulate.sh",
26
- "install:local": "node scripts/install-local.js && which aifabrix && which af",
27
- "uninstall:local": "node scripts/install-local.js uninstall && which aifabrix && which af",
28
- "sync-json": "node scripts/sync-builder-api-template.js",
29
- "builder-api:build": "tsc -p packages/builder-api/tsconfig.json",
30
- "builder-api:nest": "node bin/builder-api-nest.js",
31
- "builder-api:cleanup": "node bin/builder-api-cleanup.js",
32
- "check:builder-api-arch": "node scripts/check-builder-api-architecture-grep.js",
33
33
  "check:schema-sync": "node scripts/check-datasource-test-run-schema-sync.js",
34
34
  "check:flags": "jest tests/lib/schema/flag-map-validation-run.test.js --runInBand --config jest.config.default.js",
35
- "test:154": "npm run check:builder-api-arch && jest --runInBand tests/lib/programmatic/ tests/packages/builder-api/ tests/lib/commands/up-builder-api.test.js tests/lib/commands/up-common.test.js tests/lib/commands/repair-deploy-script.test.js tests/lib/generator/deploy-script.test.js tests/lib/generator/wizard-generator.test.js tests/lib/scripts/sync-builder-api-template.test.js tests/lib/platform-integrations-manifest.test.js",
36
- "test:154-docker-ip": "jest --runInBand tests/scripts/stage_builder_api_for_docker.test.js tests/scripts/docker_image_content_gate.test.js",
37
- "stage-builder-api-docker": "node scripts/stage_builder_api_for_docker.js",
38
- "docker-image-build-builder-api": "npm run stage-builder-api-docker && docker build -f builder/builder-api/Dockerfile -t builder-api:gate .",
39
- "docker-image-gate-builder-api": "npm run docker-image-build-builder-api && node scripts/docker_image_content_gate.js builder-api:gate builder-api",
35
+ "check:cli-help": "node scripts/check-cli-help-examples.js",
40
36
  "test:manual": "jest --config jest.config.manual.js --runInBand",
41
37
  "test:integration": "jest --config jest.config.integration.js --runInBand",
42
38
  "test:integration:fixtures": "jest --config jest.config.integration.fixtures.js --runInBand",
43
39
  "test:hubspot-wizard": "node integration/hubspot-test/test.js",
44
40
  "test:hubspot-dataplane-down": "node integration/hubspot-test/test-dataplane-down.js",
45
41
  "test:coverage": "cross-env RUN_COVERAGE=1 node tests/scripts/test-wrapper.js",
46
- "test:watch": "jest --watch",
47
- "diagnose:cli": "node scripts/diagnose-cli.js",
42
+ "docker-image-gate-builder-api": "node scripts/stage_builder_api_for_docker.js && docker build -f builder/builder-api/Dockerfile -t builder-api:gate . && node scripts/docker_image_content_gate.js builder-api:gate builder-api",
43
+ "install:local": "node scripts/install-local.js && which aifabrix && which af",
44
+ "uninstall:local": "node scripts/install-local.js uninstall && which aifabrix && which af",
48
45
  "install:global": "npm install -g . --force && which aifabrix && which af && aifabrix --version",
49
46
  "uninstall:global": "npm uninstall -g @aifabrix/builder",
47
+ "sync-json": "node scripts/sync-builder-api-template.js",
50
48
  "pack": "npm run build && npm pack",
51
49
  "validate": "npm run build",
52
50
  "prepublishOnly": "npm run validate"
@@ -15,7 +15,18 @@ Application templates are folder-based and located under `templates/applications
15
15
  - `templates/applications/keycloak/` - Keycloak application template
16
16
  - `templates/applications/builder-api/` - Builder API platform webapp (published from `builder/builder-api/` via `npm run sync-json`)
17
17
 
18
- **Platform SSOT (builder-api, plan 154.2):** Edit `builder/builder-api/` in the aifabrix-builder repo, then run `npm run sync-json` to publish `application.yaml`, `Dockerfile`, and `env.template` into `templates/applications/builder-api/`. Install with `aifabrix up-platform` or `aifabrix up-builder-api` — not hand-editing the template copy.
18
+ **Platform template sync (`pnpm run sync-json`):** Publishes local `builder/builder-api/` (`application.yaml`, `Dockerfile`, `env.template`) and, when sibling checkouts exist, pulls the same file sets as miso/dataplane sync-json:
19
+
20
+ | SSOT | → template |
21
+ | --- | --- |
22
+ | `aifabrix-builder/builder/builder-api/` | `templates/applications/builder-api/` |
23
+ | `aifabrix-miso/builder/miso-controller/` (`env.template`, `rbac.yaml`, `application.yaml`) | `templates/applications/miso-controller/` |
24
+ | `aifabrix-miso/builder/keycloak/` (`env.template`, `application.yaml`) | `templates/applications/keycloak/` |
25
+ | `aifabrix-dataplane/builder/dataplane/` (`env.template`, `rbac.yaml`, `application.yaml`) | `templates/applications/dataplane/` |
26
+
27
+ **Schema master (dataplane):** Also copies dataplane `app/schemas/json/` core integration schemas + `type/*` and `configs/deployment-rules.yaml` into `lib/schema/` (same contract as dataplane `make sync-json`). Do not hand-edit those mirrors — edit dataplane SSOT, then sync. Builder-owned schemas in `lib/schema/` (wizard, infra, etc.) are left alone.
28
+
29
+ Overrides: `AIFABRIX_MISO_SRC`, `AIFABRIX_DATAPLANE_SRC` / `AIFABRIX_DATAPLANE_ROOT` (repo roots). Install with `aifabrix up-platform` / `up-builder-api` — do not hand-edit the template copies as primary.
19
30
 
20
31
  **Template Validation:**
21
32
  - Template folder must exist in `templates/applications/<name>/`
@@ -5,7 +5,7 @@ app:
5
5
  description: "AI Fabrix Dataplane is a secure, in-tenant integration and automation layer that supplies governed, normalized, and explainable enterprise data to AI agents. Using CIP as a declarative standard, it enforces RBAC and ABAC, executes integrations, and exposes trusted data via MCP and OpenAPI."
6
6
  type: webapp
7
7
  language: python # Explicitly specify Python language
8
- version: 2.0.20
8
+ version: 2.0.31
9
9
  # Image Configuration
10
10
  # Set tag to match your build (example: aifabrix build dataplane -t 1.0.0).
11
11
  # Registry is required so the controller can pull the image (avoids docker-not-found on the controller host).
@@ -29,6 +29,13 @@ frontDoorRouting:
29
29
  internalDockerUseOriginOnly: false
30
30
  host: ${DEV_USERNAME}.${REMOTE_HOST}
31
31
  tls: ${TLS_ENABLED}
32
+ # Origin RFC 9728 PRM (outside /data PathPrefix) — Builder Traefik pass-through (plan 171.0).
33
+ requiresRuleSet: true
34
+ ruleSetConditions:
35
+ - type: UrlPath
36
+ operator: BeginsWith
37
+ matchValues:
38
+ - /.well-known/oauth-protected-resource/data
32
39
 
33
40
  # Azure Requirements
34
41
  requires:
@@ -88,7 +95,8 @@ build:
88
95
  # - MISO_*, KEYCLOAK_* → auto-generated during Azure install
89
96
  # - AI params / provider secrets → LLM external systems + secret store
90
97
  # (never product OPENAI_* / AZURE_OPENAI_*). ≥2 providers →
91
- # ENTERPRISE_LLM_DEFAULT_SELECTOR (portal LLM category).
98
+ # ENTERPRISE_LLM_DEFAULT_SELECTOR (portal/env deploy default); Environment
99
+ # Settings ai.llmProvider overrides without redeploy.
92
100
  # - ENVIRONMENT → set by deployment target
93
101
 
94
102
  configuration:
@@ -44,7 +44,7 @@ API_KEY_BYPASS_ROLES=full-access
44
44
 
45
45
  # API Configuration
46
46
  API_V1_STR=/api/v1
47
- VERSION=2.0.20
47
+ VERSION=2.0.31
48
48
  # Minimum supported aifabrix-builder CLI semver (advertised on /health and /api/v1/health; empty = no gate)
49
49
  # MIN_BUILDER_CLI_VERSION=2.45.0
50
50
  MIN_BUILDER_CLI_VERSION=2.45.5
@@ -155,11 +155,10 @@ MISO_PIPELINE_ENV_KEY=
155
155
 
156
156
  # LLM: chat/embed route through governed enterprise-llm only. Provider credentials
157
157
  # live on LLM provider external systems + dataplane secret store (not product .env).
158
- # When ≥2 LLM providers are published under enterprise-llm, set selectorKey
159
- # (system key), e.g. openai | azure-openai | ollama. Ignored when only one.
160
- # Prefer portal Configuration category LLM after deploy; this env is the resolve target.
161
- # Default LLM provider systemKey when ≥2 LLM providers are published under
162
- # enterprise-llm (fail-closed if empty). Portal category LLM can override.
158
+ # Deploy-time default provider (systemKey) when Environment Settings ai.llmProvider
159
+ # is empty. Operators can override in Environment Settings without redeploying.
160
+ # When ≥2 LLM providers are published and both settings and this env are empty,
161
+ # resolve fails closed. Ignored when only one provider is published.
163
162
  # Lab default: openai (catalog also ships azure-openai).
164
163
  ENTERPRISE_LLM_DEFAULT_SELECTOR=openai
165
164
 
@@ -180,6 +179,8 @@ ABAC_EXPLAIN_MODE_ENABLED=false
180
179
  ABAC_PERFORMANCE_THRESHOLD_MS=1000
181
180
 
182
181
  # RBAC Audit Configuration
182
+ # When true, audit denials (rbac.permission.check.failure) and decision traces.
183
+ # Successful allow checks are not audited (no forensic value; floods every request).
183
184
  RBAC_AUDIT_ENABLED=true
184
185
  # RBAC audit detail: summary | detailed | explain
185
186
  RBAC_AUDIT_DETAIL_LEVEL=summary
@@ -4,7 +4,7 @@ app:
4
4
  displayName: 'Miso Controller'
5
5
  description: 'Miso is the AI Fabrix in-tenant controller and portal layer for securely operating enterprise AI apps inside a customer’s Azure tenant. It provides Entra ID SSO, RBAC, audit logs, environment/app configuration via schemas, and safe secret handling via Key Vault references—ensuring governance, traceability, and predictable UX across portal, SDK, and CLI.'
6
6
  type: webapp
7
- version: '2.0.20'
7
+ version: '2.0.34'
8
8
 
9
9
  # Image Configuration
10
10
  # Set tag to match your build (e.g. aifabrix build miso-controller -t 1.0.0 then tag: 1.0.0)
@@ -81,7 +81,7 @@ configuration:
81
81
  # Operations & Debugging
82
82
  # -------------------------------------------------------------------------
83
83
  - name: LOG_LEVEL
84
- category: General
84
+ category: Operations & Debugging
85
85
  portalInput:
86
86
  field: select
87
87
  label: 'Log Level'
@@ -92,7 +92,7 @@ configuration:
92
92
  - error
93
93
 
94
94
  - name: ENABLE_API_DOCS
95
- category: General
95
+ category: Operations & Debugging
96
96
  portalInput:
97
97
  field: select
98
98
  label: 'Enable API Documentation (Swagger/ReDoc)'
@@ -101,7 +101,7 @@ configuration:
101
101
  - 'false'
102
102
 
103
103
  - name: FAST_STARTUP
104
- category: General
104
+ category: Operations & Debugging
105
105
  portalInput:
106
106
  field: select
107
107
  label: 'Fast Startup (skip non-critical init)'
@@ -110,7 +110,7 @@ configuration:
110
110
  - 'false'
111
111
 
112
112
  - name: LOG_TO_FILE
113
- category: General
113
+ category: Operations & Debugging
114
114
  portalInput:
115
115
  field: select
116
116
  label: 'Log to File'
@@ -122,7 +122,7 @@ configuration:
122
122
  # Keycloak Events (feature flag)
123
123
  # -------------------------------------------------------------------------
124
124
  - name: KEYCLOAK_EVENTS_ENABLED
125
- category: General
125
+ category: Keycloak Events
126
126
  portalInput:
127
127
  field: select
128
128
  label: 'Keycloak Events (sync users/groups)'
@@ -130,18 +130,33 @@ configuration:
130
130
  - 'true'
131
131
  - 'false'
132
132
 
133
+ # -------------------------------------------------------------------------
134
+ # Identity — local user password / invitation
135
+ # -------------------------------------------------------------------------
136
+ - name: IDENTITY_LOCAL_PASSWORD_MODE
137
+ category: Identity
138
+ portalInput:
139
+ field: select
140
+ label: 'Password setup for new local users'
141
+ placeholder: 'Choose how new users set their password'
142
+ options:
143
+ - label: 'Send invitation email (user sets their own password)'
144
+ value: email
145
+ - label: 'Show a one-time temporary password to the admin'
146
+ value: admin-reveal
147
+
133
148
  # -------------------------------------------------------------------------
134
149
  # Rate Limiting (tune for environment)
135
150
  # -------------------------------------------------------------------------
136
151
  - name: RATE_LIMIT_WINDOW_MS
137
- category: General
152
+ category: Rate Limiting
138
153
  portalInput:
139
154
  field: text
140
155
  label: 'Rate Limit Window (milliseconds)'
141
156
  placeholder: '900000'
142
157
 
143
158
  - name: RATE_LIMIT_MAX
144
- category: General
159
+ category: Rate Limiting
145
160
  portalInput:
146
161
  field: text
147
162
  label: 'Rate Limit Max Requests per Window'