@aifabrix/builder 2.53.1 → 2.54.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 (321) hide show
  1. package/bin/aifabrix.js +2 -2
  2. package/lib/api/assistants.api.js +8 -5
  3. package/lib/api/channel-identity.api.js +41 -0
  4. package/lib/api/evidence-authoring.api.js +5 -1
  5. package/lib/api/evidence.api.js +2 -0
  6. package/lib/api/types/evidence.types.js +2 -0
  7. package/lib/api/work-search.api.js +136 -0
  8. package/lib/channels/add-channel.js +163 -126
  9. package/lib/channels/approval-guides/chatgpt.js +14 -18
  10. package/lib/channels/approval-guides/claude.js +29 -0
  11. package/lib/channels/approval-guides/index.js +88 -22
  12. package/lib/channels/approval-guides/mcp-client.js +27 -0
  13. package/lib/channels/approval-guides/microsoft-copilot.js +52 -3
  14. package/lib/channels/approval-guides/slack.js +10 -10
  15. package/lib/channels/approval-guides/teams-bot.js +8 -12
  16. package/lib/channels/channel-add-continuations.js +91 -0
  17. package/lib/channels/channel-add-ensure.js +124 -27
  18. package/lib/channels/channel-add-existing.js +160 -28
  19. package/lib/channels/channel-add-failure.js +60 -0
  20. package/lib/channels/channel-add-remaining.js +486 -0
  21. package/lib/channels/channel-add-tty.js +190 -0
  22. package/lib/channels/channel-add-wizard-config.js +138 -0
  23. package/lib/channels/channel-add-wizard.js +250 -0
  24. package/lib/channels/channel-artifact-generator.js +27 -13
  25. package/lib/channels/channel-cardinality.js +83 -0
  26. package/lib/channels/channel-catalog-icon.js +45 -0
  27. package/lib/channels/channel-cli-instructions.js +75 -0
  28. package/lib/channels/channel-configuration-map.js +213 -0
  29. package/lib/channels/channel-credential.js +11 -14
  30. package/lib/channels/channel-definition-project.js +101 -0
  31. package/lib/channels/channel-definition-registry.js +154 -0
  32. package/lib/channels/channel-description.js +59 -2
  33. package/lib/channels/channel-discovery.js +16 -2
  34. package/lib/channels/channel-external-system.js +86 -9
  35. package/lib/channels/channel-install-envelope-actions.js +88 -0
  36. package/lib/channels/channel-install-envelope-microsoft.js +155 -0
  37. package/lib/channels/channel-install-envelope.js +356 -0
  38. package/lib/channels/channel-install-help-md.js +172 -0
  39. package/lib/channels/channel-install-http-payload.js +62 -0
  40. package/lib/channels/channel-install-inventory.js +115 -0
  41. package/lib/channels/channel-install-profiles.js +90 -0
  42. package/lib/channels/channel-instance-collision.js +118 -0
  43. package/lib/channels/channel-instance-key.js +100 -0
  44. package/lib/channels/channel-instance-materialize.js +240 -0
  45. package/lib/channels/channel-integration-generator.js +16 -9
  46. package/lib/channels/channel-integration-template.js +101 -22
  47. package/lib/channels/channel-inventory-fetch.js +79 -0
  48. package/lib/channels/channel-oauth-preflight.js +104 -0
  49. package/lib/channels/channel-package-version.js +76 -0
  50. package/lib/channels/channel-predefined-client.js +154 -0
  51. package/lib/channels/channel-probe.js +7 -2
  52. package/lib/channels/channel-runtime-resolver.js +180 -72
  53. package/lib/channels/channel-status-display.js +86 -16
  54. package/lib/channels/channel-targets.js +106 -92
  55. package/lib/channels/chatgpt-callback.js +318 -0
  56. package/lib/channels/chatgpt-channel-add.js +229 -0
  57. package/lib/channels/chatgpt-preflight.js +396 -0
  58. package/lib/channels/chatgpt-runtime-contract.js +17 -0
  59. package/lib/channels/chatgpt-setup-values.js +124 -0
  60. package/lib/channels/claude-callback.js +67 -0
  61. package/lib/channels/claude-channel-add.js +254 -0
  62. package/lib/channels/claude-runtime-contract.js +40 -0
  63. package/lib/channels/claude-runtime.js +58 -0
  64. package/lib/channels/claude-setup-values.js +89 -0
  65. package/lib/channels/mcp-client/config-merge.js +148 -0
  66. package/lib/channels/mcp-client/ensure-client.js +231 -0
  67. package/lib/channels/mcp-client/paths.js +53 -0
  68. package/lib/channels/mcp-client/profiles.js +122 -0
  69. package/lib/channels/mcp-client/redirect-uris.js +99 -0
  70. package/lib/channels/mcp-client/runtime.js +59 -0
  71. package/lib/channels/mcp-client-channel-add.js +186 -0
  72. package/lib/channels/microsoft-copilot-channel-add.js +117 -7
  73. package/lib/channels/microsoft-copilot-entra-identifier-uris.js +187 -0
  74. package/lib/channels/microsoft-copilot-entra-sso-form.js +106 -18
  75. package/lib/channels/microsoft-copilot-entra-sso.js +31 -2
  76. package/lib/channels/microsoft-copilot-package-prior.js +107 -0
  77. package/lib/channels/microsoft-copilot-package.js +29 -28
  78. package/lib/channels/microsoft-provisioning/a365.js +80 -0
  79. package/lib/channels/microsoft-provisioning/auth-config.js +240 -0
  80. package/lib/channels/microsoft-provisioning/auth.js +179 -0
  81. package/lib/channels/microsoft-provisioning/cli.js +71 -0
  82. package/lib/channels/microsoft-provisioning/constants.js +75 -0
  83. package/lib/channels/microsoft-provisioning/errors.js +117 -0
  84. package/lib/channels/microsoft-provisioning/index.js +55 -0
  85. package/lib/channels/microsoft-provisioning/install-atk.js +158 -0
  86. package/lib/channels/microsoft-provisioning/install-teams.js +115 -0
  87. package/lib/channels/microsoft-provisioning/login-portal-device.js +236 -0
  88. package/lib/channels/microsoft-provisioning/login-portal-parse.js +71 -0
  89. package/lib/channels/microsoft-provisioning/login-portal-teams.js +193 -0
  90. package/lib/channels/microsoft-provisioning/login-portal.js +230 -0
  91. package/lib/channels/microsoft-provisioning/persist.js +110 -0
  92. package/lib/channels/microsoft-provisioning/teams-bot-args.js +119 -0
  93. package/lib/channels/microsoft-provisioning/teams-bot-controller.js +123 -0
  94. package/lib/channels/microsoft-provisioning/teams-bot-parse.js +134 -0
  95. package/lib/channels/microsoft-provisioning/teams-bot-persist.js +113 -0
  96. package/lib/channels/microsoft-provisioning/teams-bot-provision.js +234 -0
  97. package/lib/channels/microsoft-provisioning/teams-bot-secrets.js +45 -0
  98. package/lib/channels/microsoft-provisioning/teams-cli.js +82 -0
  99. package/lib/channels/runtime-tool-catalog.js +5 -2
  100. package/lib/channels/slack-channel-add-portal.js +130 -0
  101. package/lib/channels/slack-channel-add-tty-auth.js +95 -0
  102. package/lib/channels/slack-channel-add.js +258 -0
  103. package/lib/channels/slack-provisioning/apps.js +181 -0
  104. package/lib/channels/slack-provisioning/auth-store.js +110 -0
  105. package/lib/channels/slack-provisioning/auth-ticket.js +185 -0
  106. package/lib/channels/slack-provisioning/auth.js +115 -0
  107. package/lib/channels/slack-provisioning/callbacks.js +41 -0
  108. package/lib/channels/slack-provisioning/cli.js +226 -0
  109. package/lib/channels/slack-provisioning/constants.js +37 -0
  110. package/lib/channels/slack-provisioning/credentials.js +169 -0
  111. package/lib/channels/slack-provisioning/curl-shim.js +132 -0
  112. package/lib/channels/slack-provisioning/developer-install.js +118 -0
  113. package/lib/channels/slack-provisioning/env-file.js +120 -0
  114. package/lib/channels/slack-provisioning/errors.js +47 -0
  115. package/lib/channels/slack-provisioning/go-ca-bundle.js +137 -0
  116. package/lib/channels/slack-provisioning/index.js +250 -0
  117. package/lib/channels/slack-provisioning/install-cli.js +323 -0
  118. package/lib/channels/slack-provisioning/manifest.js +89 -0
  119. package/lib/channels/slack-provisioning/oauth-lock.js +33 -0
  120. package/lib/channels/slack-provisioning/offer-cli.js +113 -0
  121. package/lib/channels/slack-provisioning/onboard-members.js +122 -0
  122. package/lib/channels/slack-provisioning/onboard.js +89 -0
  123. package/lib/channels/slack-provisioning/persist.js +95 -0
  124. package/lib/channels/slack-provisioning/remaining-urls.js +158 -0
  125. package/lib/channels/slack-provisioning/with-curl-on-path.js +48 -0
  126. package/lib/channels/teams-bot-channel-add.js +94 -0
  127. package/lib/channels/vendor-dataplane-url.js +249 -0
  128. package/lib/cli/setup-certification.help.js +2 -0
  129. package/lib/cli/setup-external-system-help.js +2 -0
  130. package/lib/cli/setup-external-system.js +1 -1
  131. package/lib/commands/channel-add-help.js +366 -0
  132. package/lib/commands/channel-add-setup.js +162 -80
  133. package/lib/commands/channel-configure.js +118 -0
  134. package/lib/commands/channel.js +10 -1
  135. package/lib/commands/governance-upload-external.js +6 -3
  136. package/lib/commands/lifecycle-command-action.js +2 -5
  137. package/lib/commands/lifecycle-external.js +93 -21
  138. package/lib/commands/repair-datasource-test-payload.js +4 -2
  139. package/lib/commands/repair-datasource-webhooks-sync-bridge.js +23 -2
  140. package/lib/commands/repair-datasource.js +3 -0
  141. package/lib/commands/repair-external-run.js +59 -25
  142. package/lib/commands/repair-openapi-rest-runtime.js +127 -0
  143. package/lib/commands/repair-orchestration-tag-merge.js +339 -0
  144. package/lib/commands/repair-rbac-catalog-defaults.js +96 -0
  145. package/lib/commands/repair-rbac-platform-preset.js +26 -15
  146. package/lib/commands/repair-rbac-reader-roles.js +8 -21
  147. package/lib/commands/repair-rbac.js +10 -34
  148. package/lib/commands/repair-system-permissions.js +24 -22
  149. package/lib/commands/role-assistant-test-output.js +14 -0
  150. package/lib/commands/role-assistant.js +59 -21
  151. package/lib/commands/test-e2e-external.js +148 -21
  152. package/lib/commands/upload-credential-push-log.js +2 -1
  153. package/lib/commands/upload-publish-context.js +1 -1
  154. package/lib/commands/upload-role-assistant-shell.js +124 -0
  155. package/lib/commands/upload-sidecar-followups.js +6 -3
  156. package/lib/commands/upload.js +18 -3
  157. package/lib/core/secrets-docker-env.js +4 -1
  158. package/lib/core/secrets-env-content.js +17 -3
  159. package/lib/datasource/capability/capability-manifest.js +0 -3
  160. package/lib/datasource/capability/copy-test-payload.js +3 -0
  161. package/lib/external-system/deploy-helpers.js +26 -1
  162. package/lib/external-system/deploy.js +10 -6
  163. package/lib/external-system/download-helpers.js +29 -2
  164. package/lib/external-system/download-role-assistant.js +83 -4
  165. package/lib/external-system/download.js +40 -30
  166. package/lib/external-system/sync-deploy-manifest.js +3 -2
  167. package/lib/external-system/upload-identity.js +42 -0
  168. package/lib/generator/index.js +19 -15
  169. package/lib/generator/split.js +13 -2
  170. package/lib/lifecycle/role-assistant-governance.js +146 -0
  171. package/lib/lifecycle/scenario-upload.js +181 -30
  172. package/lib/programmatic/builder-api-cors.js +143 -0
  173. package/lib/programmatic/builder-api-request.js +6 -0
  174. package/lib/programmatic/builder-api-route-dispatch.js +56 -42
  175. package/lib/programmatic/builder-api-server.js +8 -1
  176. package/lib/programmatic/capability-registry.js +54 -0
  177. package/lib/programmatic/channel-install-help-resolve.js +359 -0
  178. package/lib/programmatic/channel-install-session.js +218 -0
  179. package/lib/programmatic/help-content/channel-onboarding.md +2 -0
  180. package/lib/programmatic/help-content/cip-overview.md +3 -1
  181. package/lib/programmatic/http-raw-response.js +62 -0
  182. package/lib/programmatic/openapi-channel-install-bindings.js +179 -0
  183. package/lib/programmatic/openapi-channel-install-schemas.js +286 -0
  184. package/lib/programmatic/openapi-component-schemas.js +18 -1
  185. package/lib/programmatic/openapi-description-enricher.js +3 -1
  186. package/lib/programmatic/openapi-descriptions.js +74 -3
  187. package/lib/programmatic/openapi-envelope-examples.js +117 -0
  188. package/lib/programmatic/openapi-operation-bindings.js +4 -1
  189. package/lib/programmatic/openapi-schema-descriptions-channel.js +316 -0
  190. package/lib/programmatic/openapi-spec.js +12 -8
  191. package/lib/programmatic/platform-rbac-catalog.js +36 -18
  192. package/lib/programmatic/route-handler-map.js +51 -1
  193. package/lib/programmatic/route-handlers-context.js +2 -1
  194. package/lib/programmatic/run-auth-permissions.js +54 -0
  195. package/lib/programmatic/run-channel-catalog.js +196 -0
  196. package/lib/programmatic/run-channel-install-artifacts.js +137 -0
  197. package/lib/programmatic/run-channel-install-copilot.js +353 -0
  198. package/lib/programmatic/run-channel-install-options.js +232 -0
  199. package/lib/programmatic/run-channel-install-teams-bot.js +204 -0
  200. package/lib/programmatic/run-channel-install.js +346 -0
  201. package/lib/programmatic/run-channel-package.js +87 -7
  202. package/lib/programmatic/workspace-context.js +2 -0
  203. package/lib/role-assistant/evidence-sync.js +4 -2
  204. package/lib/role-assistant/evidence-validation-issues.js +51 -0
  205. package/lib/role-assistant/knowledge-sync.js +10 -4
  206. package/lib/role-assistant/settings.js +49 -2
  207. package/lib/role-assistant/test-cases-evaluate.js +30 -2
  208. package/lib/role-assistant/test-cases-evidence.js +175 -0
  209. package/lib/role-assistant/test-cases-search.js +229 -0
  210. package/lib/role-assistant/test-cases.js +37 -4
  211. package/lib/role-assistant/test-runner-search.js +149 -0
  212. package/lib/role-assistant/test-runner-workhub-helpers.js +40 -2
  213. package/lib/role-assistant/test-runner-workhub-soft.js +9 -3
  214. package/lib/role-assistant/test-runner-workhub.js +29 -11
  215. package/lib/role-assistant/test-runner.js +16 -1
  216. package/lib/schema/external-datasource.schema.json +112 -18
  217. package/lib/schema/external-system.schema.json +159 -2
  218. package/lib/schema/mcp-client-profile.schema.json +103 -0
  219. package/lib/utils/app-path-resolve.js +4 -0
  220. package/lib/utils/authentication-env-template.js +44 -6
  221. package/lib/utils/credential-secrets-env.js +6 -1
  222. package/lib/utils/env-copy.js +19 -7
  223. package/lib/utils/external-env-template.js +20 -2
  224. package/lib/utils/paths.js +18 -1
  225. package/lib/utils/platform-shell-package.js +69 -0
  226. package/lib/utils/port-resolver.js +50 -1
  227. package/lib/utils/rewrite-name-flag.js +20 -0
  228. package/lib/utils/role-assistant-paths.js +13 -10
  229. package/lib/utils/schema-resolver.js +11 -1
  230. package/lib/utils/secrets-helpers.js +12 -21
  231. package/lib/utils/token-manager.js +10 -5
  232. package/lib/validation/validate.js +40 -0
  233. package/package.json +1 -1
  234. package/templates/README.md +1 -1
  235. package/templates/applications/builder-api/Dockerfile +1 -1
  236. package/templates/applications/builder-api/env.template +7 -0
  237. package/templates/applications/dataplane/application.yaml +6 -5
  238. package/templates/applications/dataplane/env.template +2 -2
  239. package/templates/applications/dataplane/rbac.yaml +7 -2
  240. package/templates/applications/keycloak/Dockerfile +30 -4
  241. package/templates/applications/keycloak/application.yaml +2 -2
  242. package/templates/applications/keycloak/cimd-lenient-parse/AbstractClientIdMetadataDocumentExecutor.java +896 -0
  243. package/templates/applications/keycloak/cimd-lenient-parse/SOURCE.md +19 -0
  244. package/templates/applications/keycloak/env.template +3 -0
  245. package/templates/applications/miso-controller/application.yaml +1 -2
  246. package/templates/applications/miso-controller/env.template +2 -0
  247. package/templates/channels/README.md +5 -5
  248. package/templates/channels/chatgpt/TROUBLESHOOTING.md +51 -0
  249. package/templates/channels/chatgpt/channel.json +59 -0
  250. package/templates/channels/chatgpt/icon.svg +1 -0
  251. package/templates/channels/chatgpt/install.template.md.hbs +20 -95
  252. package/templates/channels/chatgpt/integration/README.md +1 -1
  253. package/templates/channels/chatgpt/integration/application.json +2 -2
  254. package/templates/channels/chatgpt/integration/chatgpt-system.json +49 -4
  255. package/templates/channels/chatgpt/integration/env.template +2 -4
  256. package/templates/channels/chatgpt/integration/rbac.json +13 -0
  257. package/templates/channels/claude/TROUBLESHOOTING.md +41 -0
  258. package/templates/channels/claude/channel.json +59 -0
  259. package/templates/channels/claude/icon.svg +1 -0
  260. package/templates/channels/claude/install.template.md.hbs +21 -0
  261. package/templates/channels/claude/integration/README.md +14 -0
  262. package/templates/channels/claude/integration/application.json +15 -0
  263. package/templates/channels/claude/integration/claude-system.json +59 -0
  264. package/templates/channels/claude/integration/env.template +2 -0
  265. package/templates/channels/claude/integration/rbac.json +13 -0
  266. package/templates/channels/claude/manifest.template.json.hbs +40 -0
  267. package/templates/channels/mcp-client/channel.json +72 -0
  268. package/templates/channels/mcp-client/icon.svg +1 -0
  269. package/templates/channels/mcp-client/install.template.md.hbs +24 -0
  270. package/templates/channels/mcp-client/integration/README.md +13 -0
  271. package/templates/channels/mcp-client/integration/application.json +15 -0
  272. package/templates/channels/mcp-client/integration/env.template +2 -0
  273. package/templates/channels/mcp-client/integration/mcp-client-system.json +72 -0
  274. package/templates/channels/mcp-client/integration/rbac.json +13 -0
  275. package/templates/channels/mcp-client/manifest.template.json.hbs +41 -0
  276. package/templates/channels/mcp-client/profiles/cursor.json +26 -0
  277. package/templates/channels/mcp-client/profiles/github-copilot.json +29 -0
  278. package/templates/channels/mcp-client/profiles/vscode.json +29 -0
  279. package/templates/channels/microsoft-copilot/channel.json +73 -0
  280. package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +8 -4
  281. package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +65 -5
  282. package/templates/channels/microsoft-copilot/icon.svg +1 -0
  283. package/templates/channels/microsoft-copilot/install.template.md.hbs +9 -9
  284. package/templates/channels/microsoft-copilot/integration/README.md +1 -1
  285. package/templates/channels/microsoft-copilot/integration/application.json +2 -2
  286. package/templates/channels/microsoft-copilot/integration/env.template +3 -6
  287. package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +63 -4
  288. package/templates/channels/microsoft-copilot/integration/rbac.json +13 -0
  289. package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +5 -5
  290. package/templates/channels/slack/channel.json +223 -0
  291. package/templates/channels/slack/icon.svg +1 -0
  292. package/templates/channels/slack/install.template.md.hbs +36 -28
  293. package/templates/channels/slack/integration/README.md +245 -22
  294. package/templates/channels/slack/integration/application.json +44 -7
  295. package/templates/channels/slack/integration/env.template +15 -6
  296. package/templates/channels/slack/integration/openapi/openapi.json +126 -0
  297. package/templates/channels/slack/integration/rbac.json +84 -0
  298. package/templates/channels/slack/integration/slack-datasource-commands.json +154 -0
  299. package/templates/channels/slack/integration/slack-datasource-conversations.json +28 -3
  300. package/templates/channels/slack/integration/slack-datasource-events.json +154 -0
  301. package/templates/channels/slack/integration/slack-datasource-interactive.json +154 -0
  302. package/templates/channels/slack/integration/slack-datasource-messages.json +40 -2
  303. package/templates/channels/slack/integration/slack-system.json +155 -77
  304. package/templates/channels/slack/manifest.template.json.hbs +5 -2
  305. package/templates/channels/teams-bot/channel.json +161 -0
  306. package/templates/channels/teams-bot/icon.svg +1 -0
  307. package/templates/channels/teams-bot/install.template.md.hbs +12 -13
  308. package/templates/channels/teams-bot/integration/README.md +5 -4
  309. package/templates/channels/teams-bot/integration/application.json +6 -4
  310. package/templates/channels/teams-bot/integration/env.template +5 -4
  311. package/templates/channels/teams-bot/integration/openapi/openapi.json +68 -0
  312. package/templates/channels/teams-bot/integration/rbac.json +21 -0
  313. package/templates/channels/teams-bot/integration/teams-bot-datasource-activities.json +154 -0
  314. package/templates/channels/teams-bot/integration/teams-bot-system.json +128 -23
  315. package/templates/channels/web-embed/channel.json +60 -0
  316. package/templates/channels/web-embed/install.template.md.hbs +1 -1
  317. package/templates/channels/web-embed/integration/README.md +2 -2
  318. package/templates/channels/web-embed/integration/application.json +2 -2
  319. package/templates/channels/web-embed/integration/env.template +1 -1
  320. package/templates/channels/web-embed/integration/rbac.json +13 -0
  321. package/templates/channels/web-embed/integration/web-embed-system.json +50 -4
@@ -29,7 +29,13 @@ const {
29
29
  applyDockerEnvOverride,
30
30
  getContainerPortFromDockerEnv
31
31
  } = require('./secrets-docker-env');
32
- const { getContainerPortFromPath, loadVariablesFromPath } = require('../utils/port-resolver');
32
+ const {
33
+ getContainerPortFromPath,
34
+ loadVariablesFromPath,
35
+ isExternalAppDoc,
36
+ isExternalAppPath,
37
+ stripListenPortEnvLines
38
+ } = require('../utils/port-resolver');
33
39
  const secretsEnsure = require('./secrets-ensure');
34
40
  const { resolveSecretsPath, getActualSecretsPath } = require('../utils/secrets-path');
35
41
  const pathsUtil = require('../utils/paths');
@@ -163,9 +169,14 @@ async function applyDockerTransformations(resolved, variablesPath) {
163
169
  envVars.REDIS_PORT = String(redisPort);
164
170
  envVars.DB_HOST = dbHost;
165
171
  envVars.DB_PORT = String(dbPort);
166
- envVars.PORT = String(containerPort);
172
+ if (!isExternalAppDoc(appDoc)) {
173
+ envVars.PORT = String(containerPort);
174
+ }
167
175
  resolved = interpolateEnvVars(resolved, envVars);
168
176
  resolved = rewriteDockerManifestPublicPortEnvLine(resolved, envVars, appDoc);
177
+ if (isExternalAppDoc(appDoc)) {
178
+ return resolved;
179
+ }
169
180
  return updatePortForDocker(resolved, variablesPath);
170
181
  }
171
182
 
@@ -389,10 +400,13 @@ function resolveEnvContentToWrite(resolved, pathToPreserve, options = {}) {
389
400
  async function writeResolvedEnv({ appName, envPath, resolved, variablesPath, secretsPath, opts }) {
390
401
  const preservePath = opts.preserveFromPath !== undefined && opts.preserveFromPath !== null ? opts.preserveFromPath : null;
391
402
  const pathToPreserve = preservePath !== null ? preservePath : envPath;
392
- const toWrite = resolveEnvContentToWrite(resolved, pathToPreserve, {
403
+ let toWrite = resolveEnvContentToWrite(resolved, pathToPreserve, {
393
404
  freshEnv: opts.freshEnv === true,
394
405
  pruneOrphanKv: opts.envOnly === true && opts.freshEnv !== true
395
406
  });
407
+ if (isExternalAppPath(variablesPath) && !/^PORT\s*=/m.test(resolved || '')) {
408
+ toWrite = stripListenPortEnvLines(toWrite);
409
+ }
396
410
  fs.writeFileSync(envPath, toWrite, { mode: 0o600 });
397
411
 
398
412
  if (!opts.skipOutputPath) {
@@ -27,11 +27,8 @@ const DEFAULT_RISK_BY_KEY = {
27
27
  };
28
28
 
29
29
  const RESOURCE_TYPE_MAP = {
30
- conversation: 'message',
31
30
  user: 'employee',
32
31
  person: 'employee',
33
- record: 'document',
34
- folder: 'document',
35
32
  country: 'organization',
36
33
  report: 'document',
37
34
  calendar: 'event',
@@ -1,5 +1,8 @@
1
1
  /**
2
2
  * Clone testPayload.scenarios rows when copying a capability.
3
+ * Deep-clones whole scenario objects and rewrites operation only. Nested row gold
4
+ * (expectedRows and related keys) is copied as-is; it may be wrong for --as —
5
+ * the author must edit after copy. Does not invent gold.
3
6
  *
4
7
  * @fileoverview Used by applyCapabilityCopy when includeTestPayload is true
5
8
  * @author AI Fabrix Team
@@ -170,6 +170,30 @@ async function uploadDigitalWorkerIfNeeded(appName, options, _compact, manifest)
170
170
  });
171
171
  }
172
172
 
173
+ async function deployRoleAssistantShellIfNeeded(appName, options, baseDir) {
174
+ const { isRoleAssistantWorkspace } = require('../utils/platform-shell-package');
175
+ if (!isRoleAssistantWorkspace(baseDir)) {
176
+ return null;
177
+ }
178
+ const { formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
179
+ const logger = require('../utils/logger');
180
+ if (options.json !== true) {
181
+ logger.log(
182
+ formatSuccessParagraph(
183
+ 'Role Assistant deployment uses settings and Evidence upload (no Connected System publish).'
184
+ )
185
+ );
186
+ }
187
+ const { uploadExternalSystem } = require('../commands/upload');
188
+ return uploadExternalSystem(appName, {
189
+ ...options,
190
+ uploadStatus: 'published',
191
+ silentResolve: false,
192
+ suppressPipelineSpinner: false,
193
+ syncMode: false
194
+ });
195
+ }
196
+
173
197
  module.exports = {
174
198
  loadVariablesYaml,
175
199
  validateSingleSystemFile,
@@ -177,6 +201,7 @@ module.exports = {
177
201
  validateSingleDatasourceFile,
178
202
  validateDatasourceFiles,
179
203
  extractSystemKey,
180
- uploadDigitalWorkerIfNeeded
204
+ uploadDigitalWorkerIfNeeded,
205
+ deployRoleAssistantShellIfNeeded
181
206
  };
182
207
 
@@ -30,7 +30,7 @@ const { displayValidationResults } = require('../validation/validate-display');
30
30
  const { syncDeployJsonFromSources } = require('./sync-deploy-manifest');
31
31
  const { runDeployGateOrchestrator } = require('../commands/deploy-gate-orchestrator');
32
32
  const { runPostPublishDataSync } = require('../commands/run-post-publish-data-sync');
33
- const { uploadDigitalWorkerIfNeeded } = require('./deploy-helpers');
33
+ const { uploadDigitalWorkerIfNeeded, deployRoleAssistantShellIfNeeded } = require('./deploy-helpers');
34
34
 
35
35
  /**
36
36
  * Validates manifest on dataplane (dry-run) before controller deploy.
@@ -412,17 +412,13 @@ async function validateDataplaneManifestForDeploy(manifest, authConfig, dataplan
412
412
  }
413
413
  }
414
414
 
415
- async function runExternalSystemDeployFlow(appName, options) {
416
- const compact = options.verbose !== true;
417
- const { appPath } = await detectAppType(appName);
418
- logOfflinePathWhenType(appPath);
415
+ async function runConnectedSystemDeployAfterDetect(appName, options, compact) {
419
416
  if (!compact) {
420
417
  logger.log(chalk.blue(`\n🚀 Deploying external system: ${appName}`));
421
418
  }
422
419
  await validateExternalSystemForDeploy(appName, options, compact);
423
420
  const gateOutcomes = await runDeployGateOrchestrator(appName, {
424
421
  ...options,
425
- // Compact deploy still shows step progress; only JSON mode stays fully quiet.
426
422
  quietDeployUi: options.json === true
427
423
  });
428
424
  await syncDeployJsonFromSources(appName);
@@ -453,6 +449,14 @@ async function runExternalSystemDeployFlow(appName, options) {
453
449
  });
454
450
  }
455
451
 
452
+ async function runExternalSystemDeployFlow(appName, options) {
453
+ const compact = options.verbose !== true;
454
+ const { appPath, baseDir } = await detectAppType(appName);
455
+ logOfflinePathWhenType(appPath);
456
+ const shellResult = await deployRoleAssistantShellIfNeeded(appName, options, baseDir);
457
+ return shellResult || runConnectedSystemDeployAfterDetect(appName, options, compact);
458
+ }
459
+
456
460
  /**
457
461
  * Deploys external system via controller pipeline (same as regular apps)
458
462
  *
@@ -36,7 +36,30 @@ const {
36
36
  const path = require('path');
37
37
 
38
38
  /** Runtime/API fields that must not appear on external-system manifests. */
39
- const NON_MANIFEST_SYSTEM_KEYS = ['showOpenApiDocs'];
39
+ const NON_MANIFEST_SYSTEM_KEYS = ['showOpenApiDocs', 'rbac'];
40
+
41
+ /**
42
+ * Coerce system dataSources to unique string keys (dataplane may return objects).
43
+ * @param {*} dataSources
44
+ * @returns {string[]}
45
+ */
46
+ function normalizeManifestDataSourceKeys(dataSources) {
47
+ if (!Array.isArray(dataSources)) {
48
+ return [];
49
+ }
50
+ const keys = [];
51
+ const seen = new Set();
52
+ for (const item of dataSources) {
53
+ const raw = typeof item === 'string' ? item : item && item.key;
54
+ const key = typeof raw === 'string' ? raw.trim() : '';
55
+ if (!key || seen.has(key)) {
56
+ continue;
57
+ }
58
+ seen.add(key);
59
+ keys.push(key);
60
+ }
61
+ return keys;
62
+ }
40
63
 
41
64
  /**
42
65
  * True when cwd looks like a product/workspace repo (integration, builder, or EK tree).
@@ -114,6 +137,9 @@ function sanitizeDownloadedApplication(application) {
114
137
  for (const key of NON_MANIFEST_SYSTEM_KEYS) {
115
138
  delete cleaned[key];
116
139
  }
140
+ if (Array.isArray(cleaned.dataSources)) {
141
+ cleaned.dataSources = normalizeManifestDataSourceKeys(cleaned.dataSources);
142
+ }
117
143
  return cleaned;
118
144
  }
119
145
 
@@ -296,6 +322,7 @@ module.exports = {
296
322
  runConvertToJsonIfRequested,
297
323
  generateVariablesYaml,
298
324
  generateReadme,
299
- NON_MANIFEST_SYSTEM_KEYS
325
+ NON_MANIFEST_SYSTEM_KEYS,
326
+ normalizeManifestDataSourceKeys
300
327
  };
301
328
 
@@ -1,17 +1,36 @@
1
1
  /**
2
2
  * Role Assistant sidecar handling during external-system download.
3
3
  *
4
- * @fileoverview Post-download evidence/knowledge/workflow actions for digitalWorker systems
4
+ * @fileoverview Platform-shell download (digitalWorker / enterpriseKnowledge) plus RA sidecars
5
5
  * @author AI Fabrix Team
6
- * @version 1.0.0
6
+ * @version 1.1.0
7
7
  */
8
8
 
9
9
  'use strict';
10
10
 
11
+ const path = require('path');
11
12
  const logger = require('../utils/logger');
12
- const { formatWarningLine } = require('../utils/cli-test-layout-chalk');
13
+ const {
14
+ formatWarningLine,
15
+ formatSuccessLine,
16
+ metadata
17
+ } = require('../utils/cli-test-layout-chalk');
13
18
  const { exportRoleAssistantKnowledge, logKnowledgeExportSummary } = require('../role-assistant/knowledge-sync');
14
19
  const { exportRoleAssistantEvidence, logRoleAssistantEvidenceExportSummary } = require('../role-assistant/evidence-sync');
20
+ const { writeOrMergeRoleAssistantSettings } = require('../role-assistant/settings');
21
+ const {
22
+ isDigitalWorkerKind,
23
+ isEnterpriseKnowledgeKind,
24
+ isPlatformShellKind
25
+ } = require('../utils/platform-shell-package');
26
+
27
+ const CONNECTED_SYSTEM_DRY_RUN_FILES = [
28
+ 'deploy.json',
29
+ 'application.yaml',
30
+ 'system.yaml',
31
+ 'env.template',
32
+ 'README.md'
33
+ ];
15
34
 
16
35
  async function maybeExportRoleAssistantEvidenceArtifacts(systemKey, manifest, dataplaneUrl, authConfig, options) {
17
36
  try {
@@ -50,6 +69,66 @@ async function runRoleAssistantDownloadSidecars(params) {
50
69
  await maybeExportRoleAssistantKnowledgeArtifacts(systemKey, manifest, dataplaneUrl, authConfig, options);
51
70
  }
52
71
 
72
+ function logConnectedSystemDryRunFiles(systemKey) {
73
+ logger.log(metadata('Would create:'));
74
+ CONNECTED_SYSTEM_DRY_RUN_FILES.forEach((name) => {
75
+ const fileName = name === 'deploy.json' || name === 'system.yaml'
76
+ ? `${systemKey}-${name}`
77
+ : name;
78
+ logger.log(metadata(` - integration/${systemKey}/${fileName}`));
79
+ });
80
+ }
81
+
82
+ function handleDownloadDryRun(systemKey, dataplaneUrl, application) {
83
+ logger.log(formatWarningLine('Dry run mode: no files written.'));
84
+ logger.log(metadata(`Would fetch: ${dataplaneUrl}/api/v1/external/systems/${systemKey}/config`));
85
+ if (isEnterpriseKnowledgeKind(application)) {
86
+ logger.log(metadata('Would not write local package files.'));
87
+ return;
88
+ }
89
+ if (isDigitalWorkerKind(application)) {
90
+ logger.log(metadata('Would create:'));
91
+ logger.log(metadata(` - role-assistant/${systemKey}/role-assistant.yaml`));
92
+ return;
93
+ }
94
+ logConnectedSystemDryRunFiles(systemKey);
95
+ }
96
+
97
+ async function downloadDigitalWorkerPackage(params) {
98
+ const { systemKey, manifest, dataplaneUrl, authConfig, options = {} } = params;
99
+ const yamlPath = writeOrMergeRoleAssistantSettings(systemKey, {
100
+ force: options.force === true,
101
+ pathOptions: options.pathOptions || {}
102
+ });
103
+ logger.log(formatSuccessLine(`Wrote ${path.relative(process.cwd(), yamlPath)}`));
104
+ await runRoleAssistantDownloadSidecars({
105
+ systemKey,
106
+ manifest,
107
+ dataplaneUrl,
108
+ authConfig,
109
+ options
110
+ });
111
+ return true;
112
+ }
113
+
114
+ async function downloadPlatformShellIfNeeded(params) {
115
+ const application = params.manifest && params.manifest.application;
116
+ if (!isPlatformShellKind(application)) {
117
+ return false;
118
+ }
119
+ if (isEnterpriseKnowledgeKind(application)) {
120
+ logger.log(
121
+ formatSuccessLine(
122
+ `Enterprise Knowledge '${params.systemKey}' stays on the platform; no local package files written.`
123
+ )
124
+ );
125
+ return true;
126
+ }
127
+ return downloadDigitalWorkerPackage(params);
128
+ }
129
+
53
130
  module.exports = {
54
- runRoleAssistantDownloadSidecars
131
+ runRoleAssistantDownloadSidecars,
132
+ downloadPlatformShellIfNeeded,
133
+ handleDownloadDryRun
55
134
  };
@@ -31,7 +31,7 @@ const readline = require('readline');
31
31
  const yaml = require('js-yaml');
32
32
  const { getExternalSystemConfig } = require('../api/external-systems.api');
33
33
  const { getDeploymentAuth, requireBearerForDataplanePipeline } = require('../utils/token-manager');
34
- const { getConfig } = require('../core/config');
34
+ const { getConfig, getFormat } = require('../core/config');
35
35
  const { retemplateConfigurationForDownload, retemplateAllVariableDefinitions } = require('../utils/configuration-env-resolver');
36
36
  const { syncRuntimeConfigurationFromDataplane } = require('../utils/runtime-configuration-download');
37
37
  const logger = require('../utils/logger');
@@ -41,12 +41,17 @@ const {
41
41
  validateSystemType,
42
42
  validateDownloadedData,
43
43
  sanitizeDownloadedApplication,
44
+ normalizeManifestDataSourceKeys,
44
45
  resolveDownloadDestinationPath,
45
46
  logDownloadCommandHeader,
46
47
  displayDownloadSuccess,
47
48
  runConvertToJsonIfRequested
48
49
  } = require('./download-helpers');
49
- const { runRoleAssistantDownloadSidecars } = require('./download-role-assistant');
50
+ const {
51
+ runRoleAssistantDownloadSidecars,
52
+ downloadPlatformShellIfNeeded,
53
+ handleDownloadDryRun
54
+ } = require('./download-role-assistant');
50
55
 
51
56
  /**
52
57
  * Setup authentication and get dataplane URL
@@ -187,10 +192,14 @@ function augmentConfigurationWithAuthSecrets(system) {
187
192
  * @returns {Object} Deploy JSON object for splitDeployJson
188
193
  */
189
194
  function buildDeployJsonFromManifest(application, dataSources, version) {
190
- const dataSourcesKeys = Array.isArray(dataSources)
191
- ? dataSources.map(ds => (ds && ds.key) ? ds.key : ds)
192
- : [];
193
- const system = { ...application, dataSources: application.dataSources || dataSourcesKeys };
195
+ const fromApp = normalizeManifestDataSourceKeys(application.dataSources);
196
+ const fromInline = normalizeManifestDataSourceKeys(
197
+ Array.isArray(dataSources) ? dataSources.map(ds => (ds && ds.key) ? ds.key : ds) : []
198
+ );
199
+ const system = {
200
+ ...application,
201
+ dataSources: fromApp.length ? fromApp : fromInline
202
+ };
194
203
  augmentConfigurationWithAuthSecrets(system);
195
204
  const deploy = { system, dataSources };
196
205
  if (version) deploy.version = version;
@@ -211,26 +220,6 @@ function validateSystemKeyFormat(systemKey) {
211
220
  }
212
221
  }
213
222
 
214
- /**
215
- * Handle dry run mode
216
- * @param {string} systemKey - System key
217
- * @param {string} dataplaneUrl - Dataplane URL
218
- */
219
- function handleDryRun(systemKey, dataplaneUrl) {
220
- logger.log(formatWarningLine('Dry run mode: no files written.'));
221
- logger.log(metadata(`Would fetch: ${dataplaneUrl}/api/v1/external/systems/${systemKey}/config`));
222
- logger.log(metadata('Would create:'));
223
- [
224
- `integration/${systemKey}/${systemKey}-deploy.json`,
225
- `integration/${systemKey}/application.yaml`,
226
- `integration/${systemKey}/${systemKey}-system.yaml`,
227
- `integration/${systemKey}/env.template`,
228
- `integration/${systemKey}/README.md`
229
- ].forEach(rel => {
230
- logger.log(metadata(` - ${rel}`));
231
- });
232
- }
233
-
234
223
  /**
235
224
  * Validate and log downloaded data
236
225
  * @param {Object} application - Application configuration
@@ -406,9 +395,21 @@ async function finalizeDownloadArtifacts({
406
395
  * @param {Object} [options]
407
396
  * @returns {Promise<void>}
408
397
  */
398
+ async function resolveDownloadFormat(requested) {
399
+ const raw = typeof requested === 'string' ? requested.trim().toLowerCase() : '';
400
+ if (raw === 'json' || raw === 'yaml') {
401
+ return raw;
402
+ }
403
+ const fromConfig = await getFormat();
404
+ if (fromConfig === 'json' || fromConfig === 'yaml') {
405
+ return fromConfig;
406
+ }
407
+ return 'yaml';
408
+ }
409
+
409
410
  async function downloadExternalSystem(systemKey, options = {}) {
410
411
  validateSystemKeyFormat(systemKey);
411
- const format = (options.format || 'yaml').toLowerCase();
412
+ const format = await resolveDownloadFormat(options.format);
412
413
 
413
414
  try {
414
415
  logDownloadCommandHeader(systemKey);
@@ -418,12 +419,21 @@ async function downloadExternalSystem(systemKey, options = {}) {
418
419
  options,
419
420
  config
420
421
  );
422
+ const manifest = await downloadFullManifest(dataplaneUrl, systemKey, authConfig, options);
421
423
  if (options.dryRun) {
422
- handleDryRun(systemKey, dataplaneUrl);
424
+ handleDownloadDryRun(systemKey, dataplaneUrl, manifest.application);
425
+ return;
426
+ }
427
+ const platformHandled = await downloadPlatformShellIfNeeded({
428
+ systemKey,
429
+ manifest,
430
+ dataplaneUrl,
431
+ authConfig,
432
+ options
433
+ });
434
+ if (platformHandled) {
423
435
  return;
424
436
  }
425
-
426
- const manifest = await downloadFullManifest(dataplaneUrl, systemKey, authConfig, options);
427
437
  validateAndLogDownloadedData(manifest.application, manifest.dataSources);
428
438
  const finalPath = resolveDownloadDestinationPath(systemKey, manifest.application);
429
439
  await processDownloadedSystem(
@@ -21,8 +21,9 @@ const logger = require('../utils/logger');
21
21
  * @returns {Promise<string>} Absolute path to the written deploy JSON file
22
22
  */
23
23
  async function syncDeployJsonFromSources(systemKey, opts = {}) {
24
- const deployPath = await generator.generateDeployJson(systemKey, {});
25
- if (!opts.quiet) {
24
+ const { quiet, ...generateOpts } = opts;
25
+ const deployPath = await generator.generateDeployJson(systemKey, generateOpts);
26
+ if (!quiet) {
26
27
  logger.log(formatSuccessLine(`Updated deployment manifest: ${deployPath}`));
27
28
  }
28
29
  return deployPath;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Fail closed when an upload payload's keys do not match the target system.
3
+ *
4
+ * @fileoverview Same contract as dataplane system_key_mismatch
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ /**
12
+ * @param {Object} payload
13
+ * @param {string} systemKey
14
+ * @returns {void}
15
+ */
16
+ function assertUploadPackageIdentity(payload, systemKey) {
17
+ if (!payload || typeof payload !== 'object') {
18
+ throw new Error('Upload payload is required.');
19
+ }
20
+ const applicationKey =
21
+ payload.application && typeof payload.application.key === 'string'
22
+ ? payload.application.key
23
+ : '';
24
+ if (applicationKey !== systemKey) {
25
+ throw new Error(
26
+ `systemKey '${applicationKey}' does not match expected system key '${systemKey}'`
27
+ );
28
+ }
29
+ const dataSources = Array.isArray(payload.dataSources) ? payload.dataSources : [];
30
+ for (const ds of dataSources) {
31
+ if (!ds || ds.systemKey === systemKey) {
32
+ continue;
33
+ }
34
+ throw new Error(
35
+ `systemKey '${ds.systemKey}' does not match expected system key '${systemKey}'`
36
+ );
37
+ }
38
+ }
39
+
40
+ module.exports = {
41
+ assertUploadPackageIdentity
42
+ };
@@ -298,26 +298,30 @@ async function writeRegularDeployJson(appName, appPath, appType) {
298
298
  return jsonPath;
299
299
  }
300
300
 
301
- async function generateDeployJson(appName, options = {}) {
302
- if (!appName || typeof appName !== 'string') {
303
- throw new Error('App name is required and must be a string');
304
- }
305
- let appPath;
306
- let isExternal;
307
- let appType;
301
+ async function resolveDeployJsonAppContext(appName, options) {
308
302
  if (options.appPath) {
309
- appPath = path.resolve(options.appPath);
303
+ const appPath = path.resolve(options.appPath);
310
304
  const configPath = resolveApplicationConfigPath(appPath);
311
305
  const { loadConfigFile } = require('../utils/config-format');
312
306
  const variables = loadConfigFile(configPath);
313
- appType = variables?.app?.type || 'external';
314
- isExternal = appType === 'external';
315
- } else {
316
- const detected = await detectAppType(appName, options);
317
- appPath = detected.appPath;
318
- isExternal = detected.isExternal;
319
- appType = detected.appType;
307
+ const appType = variables?.app?.type || 'external';
308
+ return { appPath, appType, isExternal: appType === 'external' };
309
+ }
310
+ const detected = await detectAppType(appName, options);
311
+ const { throwIfPlatformShellHasNoDeployJson } = require('../utils/platform-shell-package');
312
+ throwIfPlatformShellHasNoDeployJson(appName, detected.baseDir);
313
+ return {
314
+ appPath: detected.appPath,
315
+ isExternal: detected.isExternal,
316
+ appType: detected.appType
317
+ };
318
+ }
319
+
320
+ async function generateDeployJson(appName, options = {}) {
321
+ if (!appName || typeof appName !== 'string') {
322
+ throw new Error('App name is required and must be a string');
320
323
  }
324
+ const { appPath, isExternal, appType } = await resolveDeployJsonAppContext(appName, options);
321
325
  logOfflinePathWhenType(appPath);
322
326
  if (isExternal) {
323
327
  return writeExternalDeployJson(appName, appPath, options);
@@ -15,6 +15,18 @@ const { parseImageReference } = require('./parse-image');
15
15
  const { generateReadmeFromDeployJson } = require('./split-readme');
16
16
  const { extractVariablesYaml, getExternalDatasourceFileName } = require('./split-variables');
17
17
  const { generateExternalEnvTemplateContent } = require('../utils/external-env-template');
18
+ const { normalizeManifestDataSourceKeys } = require('../external-system/download-helpers');
19
+
20
+ /**
21
+ * System YAML payload: omit runtime RBAC fields and coerce dataSources to keys.
22
+ * @param {Object} system
23
+ * @returns {Object}
24
+ */
25
+ function systemYamlPayload(system) {
26
+ const { roles: _roles, permissions: _permissions, rbac: _rbac, ...rest } = system;
27
+ rest.dataSources = normalizeManifestDataSourceKeys(rest.dataSources);
28
+ return rest;
29
+ }
18
30
 
19
31
  /**
20
32
  * Converts configuration array back to env.template format
@@ -339,9 +351,8 @@ async function writeExternalSystemAndDatasourceFiles(outputDir, deployment) {
339
351
  const system = deployment.system;
340
352
  const systemKey = system.key || 'external-system';
341
353
  const dataSourcesList = deployment.dataSources || deployment.datasources || [];
342
- const { roles: _roles, permissions: _permissions, ...systemWithoutRbac } = system;
343
354
  const systemPath = path.join(outputDir, `${systemKey}-system.yaml`);
344
- await writeComponentFile(systemPath, yaml.dump(systemWithoutRbac, { indent: 2, lineWidth: -1 }));
355
+ await writeComponentFile(systemPath, yaml.dump(systemYamlPayload(system), { indent: 2, lineWidth: -1 }));
345
356
  const datasourcePaths = await writeDatasourceFiles(outputDir, systemKey, dataSourcesList);
346
357
  return { systemFile: systemPath, datasourceFiles: datasourcePaths };
347
358
  }