@aifabrix/builder 2.53.0 → 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 +119 -16
  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
@@ -81,6 +81,19 @@ function mapCaseEnvelopeRow(row) {
81
81
  };
82
82
  }
83
83
 
84
+ function attachEnvelopeIsolation(envelope, opts) {
85
+ const emails = Array.isArray(opts.subjectEmail)
86
+ ? opts.subjectEmail.map((value) => String(value || '').trim()).filter(Boolean)
87
+ : [];
88
+ const userIds = Array.isArray(opts.subjectUserId)
89
+ ? opts.subjectUserId.map((value) => String(value || '').trim()).filter(Boolean)
90
+ : [];
91
+ if (emails.length === 0 && userIds.length === 0) {
92
+ return;
93
+ }
94
+ envelope.isolation = { subjectEmails: emails, subjectUserIds: userIds };
95
+ }
96
+
84
97
  function attachEnvelopeCases(envelope, caseResult) {
85
98
  if (Array.isArray(caseResult)) {
86
99
  envelope.cases = caseResult.map(mapCaseEnvelopeRow);
@@ -118,6 +131,7 @@ function buildRoleAssistantTestEnvelope(roleKey, verdict, portalUrl, result, opt
118
131
  summary: null
119
132
  };
120
133
  attachEnvelopeCases(envelope, caseResult);
134
+ attachEnvelopeIsolation(envelope, opts);
121
135
  if (opts.verbose || opts.debug) {
122
136
  envelope.report = report;
123
137
  }
@@ -34,6 +34,7 @@ const {
34
34
  mergeCaseExecutionIntoLifecycleResult,
35
35
  lifecycleVerdictFromCaseExecution
36
36
  } = require('../role-assistant/test-runner');
37
+ const { assertRoleAssistantEvidencePreflight } = require('../role-assistant/test-cases-evidence');
37
38
  const { collectString } = require('./governance');
38
39
  const {
39
40
  sectionTitle,
@@ -91,8 +92,12 @@ Notes:
91
92
  - Use \`aifabrix upload <roleKey> --env …\` (or \`--publish\`) when you intentionally refresh the package.
92
93
  - Runs lifecycle checks, then prints a portal deep link for full step-by-step status.
93
94
  - Case files with input.message/input.content execute Work Hub plan→accept (or work.start when executionPath: intent).
95
+ - Cases with executionPath: search|skills (input.executionPath or case-root executionPath) run work.skills / work.search instead of Work Hub.
96
+ - Role Assistant packages do not need application.yaml; test uses device login and the published dataplane worker.
97
+ - Cases with preflight.evidence.requiredKeys read live Evidence from the dataplane before start and hard-stop if those keys are missing or not active.
94
98
  - answers[] and approvals[] are matched to runtime wait payloads (questionKey/requestKey/waitReason).
95
99
  - --suite runs YAML under role-assistant/ra-<roleKey>/tests/<suite>/ (preferred), or tests/ra-<roleKey>/<roleKey>/<suite>/, or legacy tests/role-assistant/ra-<roleKey>/<suite>/ (override with --cases-root).
100
+ - --subject-email / --subject-user-id isolate Work Hub cases (repeatable). They do not generate Connected System governance packs and do not require application.yaml.
96
101
  - Use the portal URL for detailed human review while automation reads CLI/JSON output.
97
102
  `;
98
103
  }
@@ -254,38 +259,71 @@ async function runRoleAssistantTestAction(roleKey, options, cmd) {
254
259
  return exitCode;
255
260
  }
256
261
 
257
- async function resolveRoleAssistantCaseResult(roleKey, opts, result, verdict, portalUrl) {
258
- if (!opts.case) {
259
- return null;
260
- }
261
- const roleCase = loadRoleAssistantTestCase(roleKey, opts.case, {
262
- testsDir: opts.testsDir || null
263
- });
264
- if (!isExecutableRoleAssistantCase(roleCase)) {
265
- return evaluateRoleAssistantTestCase(roleCase, result, verdict, portalUrl);
266
- }
262
+ function attachCaseExecution(evaluation, executionResult, error) {
263
+ const errMsg = error && (error.message || String(error));
264
+ evaluation.execution = {
265
+ processExecutionId: executionResult?.processExecutionId || error?.planId || null,
266
+ finalStatus: executionResult?.finalStatus?.status || (error ? 'failed' : null),
267
+ waitReason: executionResult?.finalStatus?.wait?.waitReason || null,
268
+ interactions: executionResult?.interactions || [],
269
+ workResultError: executionResult?.workResultError || errMsg || null
270
+ };
271
+ return evaluation;
272
+ }
273
+
274
+ async function resolveExecutableCaseResult(roleKey, roleCase, opts, result, verdict, portalUrl) {
267
275
  const authContext = await resolveLifecycleAuth(roleKey, {
268
276
  ...opts,
269
277
  run: false,
270
278
  noPublish: true
271
279
  });
280
+ const evidencePreflight = await assertRoleAssistantEvidencePreflight(roleCase, authContext);
272
281
  const executionResult = await runRoleAssistantCaseLifecycle(roleKey, roleCase, authContext, opts);
273
282
  const executionVerdict = lifecycleVerdictFromCaseExecution(executionResult, verdict);
274
283
  const evaluationInput = mergeCaseExecutionIntoLifecycleResult(result, executionResult);
284
+ evaluationInput.evidencePreflight = evidencePreflight;
275
285
  const evaluation = evaluateRoleAssistantTestCase(
276
286
  roleCase,
277
287
  evaluationInput,
278
288
  executionVerdict,
279
289
  portalUrl
280
290
  );
281
- evaluation.execution = {
282
- processExecutionId: executionResult.processExecutionId || null,
283
- finalStatus: executionResult.finalStatus?.status || null,
284
- waitReason: executionResult.finalStatus?.wait?.waitReason || null,
285
- interactions: executionResult.interactions || [],
286
- workResultError: executionResult.workResultError || null
287
- };
288
- return evaluation;
291
+ return attachCaseExecution(evaluation, executionResult);
292
+ }
293
+
294
+ async function resolveRoleAssistantCaseResult(roleKey, opts, result, verdict, portalUrl) {
295
+ if (!opts.case) {
296
+ return null;
297
+ }
298
+ const roleCase = loadRoleAssistantTestCase(roleKey, opts.case, {
299
+ testsDir: opts.testsDir || null
300
+ });
301
+ if (!isExecutableRoleAssistantCase(roleCase)) {
302
+ return evaluateRoleAssistantTestCase(roleCase, result, verdict, portalUrl);
303
+ }
304
+ try {
305
+ return await resolveExecutableCaseResult(
306
+ roleKey,
307
+ roleCase,
308
+ opts,
309
+ result,
310
+ verdict,
311
+ portalUrl
312
+ );
313
+ } catch (error) {
314
+ const failedInput = mergeCaseExecutionIntoLifecycleResult(result, {
315
+ finalStatus: { status: 'failed' },
316
+ workResult: null,
317
+ workResultError: error.message || String(error),
318
+ interactions: []
319
+ });
320
+ failedInput.workResultError = error.message || String(error);
321
+ return attachCaseExecution(
322
+ evaluateRoleAssistantTestCase(roleCase, failedInput, verdict, portalUrl),
323
+ null,
324
+ error
325
+ );
326
+ }
289
327
  }
290
328
 
291
329
  async function roleAssistantTestHandler(roleKey, options, cmd) {
@@ -332,19 +370,19 @@ function setupRoleAssistantCommands(program) {
332
370
  .option('--force', 'Force upload when --publish is set')
333
371
  .option(
334
372
  '--subject-user-id <id>',
335
- 'Subject user id for governance generate (repeatable)',
373
+ 'Work Hub isolation user id (repeatable; not Connected System governance)',
336
374
  collectString,
337
375
  []
338
376
  )
339
377
  .option(
340
378
  '--subject-email <email>',
341
- 'Subject email for governance generate (repeatable)',
379
+ 'Work Hub isolation email (repeatable; not Connected System governance)',
342
380
  collectString,
343
381
  []
344
382
  )
345
383
  .option(
346
384
  '--certification-profile <profile>',
347
- 'Certification profile for governance generate (bronze, silver, gold, ...)',
385
+ 'Ignored for Role Assistant packages (Connected System governance generate does not run)',
348
386
  'bronze'
349
387
  )
350
388
  .option('--json', 'Machine-readable output envelope')
@@ -39,6 +39,99 @@ function deriveDatasourceKeyFromFileName(fileName, systemKey) {
39
39
  }
40
40
 
41
41
  /* eslint-disable max-statements -- Key resolution from system or files */
42
+ function datasourceKeyFromParsedOrFile(parsed, fileName, systemKey) {
43
+ if (parsed && typeof parsed.key === 'string' && parsed.key.trim()) {
44
+ return parsed.key.trim();
45
+ }
46
+ return deriveDatasourceKeyFromFileName(fileName, systemKey);
47
+ }
48
+
49
+ function cipFetchSources(parsed) {
50
+ const ops = parsed && parsed.execution && parsed.execution.cip && parsed.execution.cip.operations;
51
+ if (!ops || typeof ops !== 'object') {
52
+ return [];
53
+ }
54
+ const sources = [];
55
+ for (const op of Object.values(ops)) {
56
+ if (!op || typeof op !== 'object') continue;
57
+ for (const step of op.steps || []) {
58
+ const src = step && step.fetch && step.fetch.source;
59
+ if (typeof src === 'string' && src.trim()) sources.push(src.trim());
60
+ }
61
+ }
62
+ return sources;
63
+ }
64
+
65
+ function isExclusiveRecordFetchSource(parsed) {
66
+ const sources = cipFetchSources(parsed);
67
+ return sources.length > 0 && sources.every((src) => src === 'record');
68
+ }
69
+
70
+ /**
71
+ * Maps datasource keys to E2E skip reasons (`view` / `record`) or storageType.
72
+ * @param {string} appPath
73
+ * @param {string[]} datasourceFiles
74
+ * @param {string} systemKey
75
+ * @returns {Object<string, string|undefined>}
76
+ */
77
+ function loadDatasourceStorageByKey(appPath, datasourceFiles, systemKey) {
78
+ const byKey = {};
79
+ for (const fileName of datasourceFiles) {
80
+ const filePath = path.join(appPath, fileName);
81
+ if (!fs.existsSync(filePath)) continue;
82
+ try {
83
+ const parsed = loadConfigFile(filePath);
84
+ const key = datasourceKeyFromParsedOrFile(parsed, fileName, systemKey);
85
+ if (!key) continue;
86
+ if (parsed && parsed.storageType === 'view') byKey[key] = 'view';
87
+ else if (isExclusiveRecordFetchSource(parsed)) byKey[key] = 'record';
88
+ else byKey[key] = parsed && parsed.storageType;
89
+ } catch {
90
+ // Unreadable files stay unknown and remain eligible for E2E.
91
+ }
92
+ }
93
+ return byKey;
94
+ }
95
+
96
+ /**
97
+ * Table E2E (sync/CRUD) does not apply to viewpoint datasources.
98
+ * @param {string[]} keys
99
+ * @param {Object<string, string|undefined>} storageByKey
100
+ * @returns {{ runnable: string[], skipped: string[] }}
101
+ */
102
+ function selectE2eRunnableKeys(keys, storageByKey) {
103
+ const runnable = [];
104
+ const skipped = [];
105
+ for (const key of keys) {
106
+ if (storageByKey[key] === 'view' || storageByKey[key] === 'record') skipped.push(key);
107
+ else runnable.push(key);
108
+ }
109
+ return { runnable, skipped };
110
+ }
111
+
112
+ /**
113
+ * Drops storageType view keys and logs skips. Empty runnable is success (nothing to run).
114
+ * @param {string} externalSystem
115
+ * @param {string} appPath
116
+ * @param {string[]} datasourceFiles
117
+ * @param {string} systemKey
118
+ * @param {string[]} keys
119
+ * @returns {string[]}
120
+ */
121
+ function prepareE2eDatasourceKeys(externalSystem, appPath, datasourceFiles, systemKey, keys) {
122
+ const storageByKey = loadDatasourceStorageByKey(appPath, datasourceFiles, systemKey);
123
+ const { runnable, skipped } = selectE2eRunnableKeys(keys, storageByKey);
124
+ skipped.forEach((key) => {
125
+ const reason =
126
+ storageByKey[key] === 'record' ? 'fetch.source record' : 'storageType view';
127
+ logger.log(chalk.gray(`⏭ Skipping ${key} (${reason})`));
128
+ });
129
+ if (runnable.length === 0 && keys.length === 0) {
130
+ logger.log(chalk.yellow(`No datasources found for ${externalSystem}. Add datasource files and run aifabrix repair.`));
131
+ }
132
+ return runnable;
133
+ }
134
+
42
135
  /**
43
136
  * Resolves the list of datasource keys for an external system (from system file or discovered files).
44
137
  * @param {string} appPath - Integration app path
@@ -117,22 +210,29 @@ async function syncLocalIfRequested(systemKey, options) {
117
210
  return uploadCtx && uploadCtx.dataplaneUrl && uploadCtx.authConfig ? uploadCtx : null;
118
211
  }
119
212
 
120
- /* eslint-disable max-lines-per-function, max-statements -- Load context, then loop over keys */
121
- /**
122
- * Runs E2E for all datasources of an external system. Uses each datasource's payloadTemplate (no extra params required).
123
- *
124
- * @async
125
- * @param {string} externalSystem - System key (e.g. hubspot-demo)
126
- * @param {Object} options - Options passed to each runDatasourceTestE2E
127
- * @param {string} [options.env] - Environment (dev, tst, pro)
128
- * @param {boolean} [options.debug] - Include debug, write log
129
- * @param {boolean} [options.verbose] - Verbose output
130
- * @param {boolean} [options.async] - If false, sync mode (default true)
131
- * @param {boolean} [options.noPublish] - When true, skip upload (E2E uses dataplane config already deployed)
132
- * @returns {Promise<{ success: boolean, results: Array<{ key: string, success: boolean, error?: string }> }>}
133
- */
213
+ function isPlatformShellAppPath(appPath) {
214
+ const parent = path.basename(path.dirname(path.resolve(String(appPath || ''))));
215
+ return parent === 'role-assistant' || parent === 'enterprise-knowledge';
216
+ }
217
+
218
+ function platformShellIntegrationContext(systemKey, appPath) {
219
+ return { systemKey, keys: [], appPath, datasourceFiles: [] };
220
+ }
221
+
222
+ function tryApplicationConfigPath(appPath) {
223
+ try {
224
+ return resolveApplicationConfigPath(appPath);
225
+ } catch (error) {
226
+ if (isPlatformShellAppPath(appPath)) {
227
+ return null;
228
+ }
229
+ throw error;
230
+ }
231
+ }
232
+
134
233
  /**
135
234
  * Resolve integration folder, system key, and datasource keys for system-level tests.
235
+ * Role Assistant / Enterprise Knowledge packages have no application.yaml.
136
236
  * @param {string} externalSystem
137
237
  * @returns {{ systemKey: string, keys: string[] }}
138
238
  */
@@ -144,13 +244,19 @@ function resolveExternalIntegrationContext(externalSystem, pathOptions = {}) {
144
244
  if (!fs.existsSync(appPath)) {
145
245
  throw new Error(`Integration path not found: ${appPath}`);
146
246
  }
147
- const configPath = resolveApplicationConfigPath(appPath);
247
+ const configPath = tryApplicationConfigPath(appPath);
248
+ if (!configPath) {
249
+ return platformShellIntegrationContext(externalSystem, appPath);
250
+ }
148
251
  let variables = {};
149
252
  if (fs.existsSync(configPath)) {
150
253
  variables = loadConfigFile(configPath);
151
254
  }
152
255
  const { systemFiles, datasourceFiles: discovered } = discoverIntegrationFiles(appPath);
153
256
  if (systemFiles.length === 0) {
257
+ if (isPlatformShellAppPath(appPath)) {
258
+ return platformShellIntegrationContext(externalSystem, appPath);
259
+ }
154
260
  throw new Error(`No system file found in ${appPath}. Expected *-system.yaml or *-system.json`);
155
261
  }
156
262
  const datasourceFiles = buildEffectiveDatasourceFiles(
@@ -171,13 +277,33 @@ function resolveExternalIntegrationContext(externalSystem, pathOptions = {}) {
171
277
  systemParsed,
172
278
  datasourceFiles
173
279
  );
174
- return { systemKey, keys };
280
+ return { systemKey, keys, appPath, datasourceFiles };
175
281
  }
176
282
 
283
+ /* eslint-disable max-lines-per-function, max-statements -- Load context, then loop over keys */
284
+ /**
285
+ * Runs E2E for all datasources of an external system. Uses each datasource's payloadTemplate (no extra params required).
286
+ *
287
+ * @async
288
+ * @param {string} externalSystem - System key (e.g. hubspot-demo)
289
+ * @param {Object} options - Options passed to each runDatasourceTestE2E
290
+ * @param {string} [options.env] - Environment (dev, tst, pro)
291
+ * @param {boolean} [options.debug] - Include debug, write log
292
+ * @param {boolean} [options.verbose] - Verbose output
293
+ * @param {boolean} [options.async] - If false, sync mode (default true)
294
+ * @param {boolean} [options.noPublish] - When true, skip upload (E2E uses dataplane config already deployed)
295
+ * @returns {Promise<{ success: boolean, results: Array<{ key: string, success: boolean, error?: string }> }>}
296
+ */
177
297
  async function runTestE2EForExternalSystem(externalSystem, options = {}) {
178
- const { systemKey, keys } = resolveExternalIntegrationContext(externalSystem);
179
- if (keys.length === 0) {
180
- logger.log(chalk.yellow(`No datasources found for ${externalSystem}. Add datasource files and run aifabrix repair.`));
298
+ const { systemKey, keys, appPath, datasourceFiles } = resolveExternalIntegrationContext(externalSystem);
299
+ const e2eKeys = prepareE2eDatasourceKeys(
300
+ externalSystem,
301
+ appPath,
302
+ datasourceFiles,
303
+ systemKey,
304
+ keys
305
+ );
306
+ if (e2eKeys.length === 0) {
181
307
  return { success: true, results: [] };
182
308
  }
183
309
 
@@ -217,12 +343,12 @@ async function runTestE2EForExternalSystem(externalSystem, options = {}) {
217
343
  quietPollUi: options.quietPollUi === true,
218
344
  onPollProgress: options.onPollProgress
219
345
  };
220
- for (const key of keys) {
346
+ for (const key of e2eKeys) {
221
347
  if (typeof options.onDatasourceProgress === 'function') {
222
348
  options.onDatasourceProgress({
223
349
  key,
224
350
  index: results.length,
225
- total: keys.length
351
+ total: e2eKeys.length
226
352
  });
227
353
  }
228
354
  try {
@@ -246,6 +372,7 @@ async function runTestE2EForExternalSystem(externalSystem, options = {}) {
246
372
  module.exports = {
247
373
  runTestE2EForExternalSystem,
248
374
  getDatasourceKeys,
375
+ selectE2eRunnableKeys,
249
376
  resolveExternalIntegrationContext,
250
377
  syncLocalIfRequested
251
378
  };
@@ -91,7 +91,8 @@ async function pushAndLogCredentialSecrets(dataplaneUrl, authConfig, systemKey,
91
91
  pushCredentialSecrets(dataplaneUrl, authConfig, {
92
92
  envFilePath,
93
93
  appName: systemKey,
94
- payload
94
+ payload,
95
+ excludeKeys: uiOpts.excludeSecretKeys
95
96
  }),
96
97
  { systemKey, json: uiOpts.json === true }
97
98
  );
@@ -57,7 +57,7 @@ async function resolveUploadPublishContext(
57
57
  environment: options.environment
58
58
  });
59
59
  requireBearerForDataplanePipeline(resolved.authConfig);
60
- if (options.force === true) {
60
+ if (options.force === true && options.suppressSummary !== true) {
61
61
  logForcePublishWarning();
62
62
  }
63
63
  const controllerUrl = await resolveControllerUrl();
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Role Assistant upload without Connected System files.
3
+ *
4
+ * @fileoverview Settings + Evidence path for role-assistant/ packages
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const chalk = require('chalk');
10
+ const logger = require('../utils/logger');
11
+ const { detectAppType } = require('../utils/paths');
12
+ const { isRoleAssistantWorkspace } = require('../utils/platform-shell-package');
13
+ const {
14
+ SYSTEM_KIND_DIGITAL_WORKER,
15
+ readRoleAssistantSettings,
16
+ resolveRoleAssistantSettingsVersion,
17
+ resolveRoleAssistantEnvironmentSettings
18
+ } = require('../role-assistant/settings');
19
+ const { validateExternalSystemComplete } = require('../validation/validate');
20
+ const { displayValidationResults } = require('../validation/validate-display');
21
+ const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
22
+ const { runUploadSidecarFollowups } = require('./upload-sidecar-followups');
23
+ const { finalizeUploadPublishResult } = require('./upload-data-sync-finalize');
24
+
25
+ async function isRoleAssistantShellPackage(systemKey, options = {}) {
26
+ const pathOptions = options.pathOptions || {};
27
+ const detected = await detectAppType(systemKey, pathOptions);
28
+ return isRoleAssistantWorkspace(detected.baseDir);
29
+ }
30
+
31
+ function buildRoleAssistantShellPayload(systemKey, options = {}) {
32
+ const pathOptions = options.pathOptions || {};
33
+ const settings = readRoleAssistantSettings(systemKey, { required: true, pathOptions });
34
+ resolveRoleAssistantEnvironmentSettings(settings, options.env || 'dev', { required: true });
35
+ const version = resolveRoleAssistantSettingsVersion(settings) || '1.0.0';
36
+ return {
37
+ version,
38
+ application: {
39
+ key: systemKey,
40
+ systemKind: SYSTEM_KIND_DIGITAL_WORKER
41
+ },
42
+ dataSources: [],
43
+ status: options.uploadStatus === 'published' ? 'published' : 'draft'
44
+ };
45
+ }
46
+
47
+ function assertRoleAssistantShellValid(validationResult) {
48
+ if (validationResult && validationResult.valid) {
49
+ return;
50
+ }
51
+ displayValidationResults(validationResult);
52
+ const errors = (validationResult && validationResult.errors) || [];
53
+ const summary = errors.slice(0, 3).map((item) => (typeof item === 'string' ? item : String(item))).join('; ');
54
+ throw new Error(
55
+ summary
56
+ ? `Validation failed: ${summary}. Fix errors above and run the command again.`
57
+ : 'Validation failed. Fix errors before uploading.'
58
+ );
59
+ }
60
+
61
+ async function validateRoleAssistantShellPackage(systemKey, options = {}) {
62
+ const pathOptions = options.pathOptions || {};
63
+ const validationResult = await validateExternalSystemComplete(systemKey, {
64
+ type: 'external',
65
+ ...pathOptions
66
+ });
67
+ assertRoleAssistantShellValid(validationResult);
68
+ if (options.minimal !== true) {
69
+ logger.log(formatSuccessLine('Local validation passed'));
70
+ }
71
+ }
72
+
73
+ function logRoleAssistantShellDryRun(systemKey, payload) {
74
+ logger.log(
75
+ chalk.yellow(
76
+ 'Dry run: would apply Role Assistant settings and Evidence (no Connected System publish).'
77
+ )
78
+ );
79
+ logger.log(chalk.gray(` System: ${systemKey}, version: ${payload.version}`));
80
+ }
81
+
82
+ async function applyRoleAssistantShellSidecars(systemKey, options, payload, deps) {
83
+ const { dataplaneUrl, authConfig, environment } = await deps.resolveDataplaneAndAuth(
84
+ systemKey,
85
+ options
86
+ );
87
+ const sidecar = await runUploadSidecarFollowups({
88
+ systemKey,
89
+ options: { ...options, skipDataSync: true },
90
+ payload,
91
+ dataplaneUrl,
92
+ authConfig,
93
+ environment
94
+ });
95
+ if (options.suppressSummary !== true && options.minimal !== true) {
96
+ logger.log(
97
+ formatSuccessLine('Role Assistant settings and Evidence applied (no Connected System publish).')
98
+ );
99
+ }
100
+ return finalizeUploadPublishResult(
101
+ { dataplaneUrl, authConfig, environment, uploadSkipped: true, sidecar },
102
+ payload,
103
+ options
104
+ );
105
+ }
106
+
107
+ async function uploadRoleAssistantShellPackage(systemKey, options = {}, deps = {}) {
108
+ if (!deps.resolveDataplaneAndAuth) {
109
+ throw new Error('Role Assistant upload requires dataplane auth resolution');
110
+ }
111
+ await validateRoleAssistantShellPackage(systemKey, options);
112
+ const payload = buildRoleAssistantShellPayload(systemKey, options);
113
+ if (options.dryRun === true) {
114
+ logRoleAssistantShellDryRun(systemKey, payload);
115
+ return undefined;
116
+ }
117
+ return applyRoleAssistantShellSidecars(systemKey, options, payload, deps);
118
+ }
119
+
120
+ module.exports = {
121
+ isRoleAssistantShellPackage,
122
+ buildRoleAssistantShellPayload,
123
+ uploadRoleAssistantShellPackage
124
+ };
@@ -38,11 +38,14 @@ function buildRoleAssistantSyncContext(ctx, model) {
38
38
 
39
39
  async function runGovernanceSidecar(ctx, sidecar, quietSidecar) {
40
40
  try {
41
- const { uploadGovernanceScenarioPacks } = require('../lifecycle/scenario-upload');
42
- const uploaded = await uploadGovernanceScenarioPacks(ctx.systemKey, ctx.dataplaneUrl, ctx.authConfig, {
41
+ const {
42
+ uploadGovernanceScenarioPacks,
43
+ normalizeGovernanceUploadResult
44
+ } = require('../lifecycle/scenario-upload');
45
+ const result = await uploadGovernanceScenarioPacks(ctx.systemKey, ctx.dataplaneUrl, ctx.authConfig, {
43
46
  silent: quietSidecar
44
47
  });
45
- sidecar.governance = { uploaded: Number(uploaded || 0) };
48
+ sidecar.governance = normalizeGovernanceUploadResult(result);
46
49
  } catch (err) {
47
50
  sidecar.governance = { skipped: true, reason: err.message || String(err) };
48
51
  if (!quietSidecar) {
@@ -44,6 +44,7 @@ const { maybeSyncOpenApiFilesForMcp } = require('./repair-openapi-sync');
44
44
  const { exportProgrammaticOpenApiForRepair } = require('./repair-openapi-export');
45
45
  const { resolveUploadPublishContext } = require('./upload-publish-context');
46
46
  const { syncDeployJsonFromSources } = require('../external-system/sync-deploy-manifest');
47
+ const { assertUploadPackageIdentity } = require('../external-system/upload-identity');
47
48
  const { handlePublicationAndFollowups } = require('./upload-sidecar-followups');
48
49
  const { finalizeUploadPublishResult, finishUnchangedUploadPublication } = require('./upload-data-sync-finalize');
49
50
  const { pushAndLogCredentialSecrets } = require('./upload-credential-push-log');
@@ -53,6 +54,10 @@ const {
53
54
  resolveRoleAssistantSettingsVersion,
54
55
  resolveRoleAssistantEnvironmentSettings
55
56
  } = require('../role-assistant/settings');
57
+ const {
58
+ isRoleAssistantShellPackage,
59
+ uploadRoleAssistantShellPackage
60
+ } = require('./upload-role-assistant-shell');
56
61
 
57
62
  /**
58
63
  * Validates system-key format (same as download).
@@ -149,7 +154,10 @@ async function runUploadValidatePublish(
149
154
  { timeoutMs: options.timeoutMs }
150
155
  );
151
156
  if (res?.success === false) {
152
- throw new Error(formatApiError(res, dataplaneUrl));
157
+ const err = new Error(formatApiError(res, dataplaneUrl));
158
+ const status = Number(res.status || res.statusCode);
159
+ err.statusCode = status >= 400 && status < 600 ? status : 400;
160
+ throw err;
153
161
  }
154
162
  return res;
155
163
  }
@@ -256,6 +264,7 @@ async function buildValidatedUploadManifestPayload(systemKey, opts = {}) {
256
264
  }
257
265
  }
258
266
  await resolvePayloadConfiguration(systemKey, payload, pathOptions);
267
+ assertUploadPackageIdentity(payload, systemKey);
259
268
  return { manifest, payload };
260
269
  }
261
270
 
@@ -312,7 +321,8 @@ async function completeUploadAfterPublish(systemKey, options, manifest, payload,
312
321
  const pushMeta = await pushAndLogCredentialSecrets(ctx.dataplaneUrl, ctx.authConfig, systemKey, payload, {
313
322
  json: options.json === true,
314
323
  pathOptions: options.pathOptions,
315
- suppressCredentialLog: quietCompact
324
+ suppressCredentialLog: quietCompact,
325
+ excludeSecretKeys: options.excludeSecretKeys
316
326
  });
317
327
  await logAndSyncLocalOpenApiForUpload(systemKey, manifest, {
318
328
  dataplaneUrl: ctx.dataplaneUrl,
@@ -417,7 +427,12 @@ async function uploadExternalSystem(systemKey, options = {}) {
417
427
  : options.minimal === false
418
428
  ? false
419
429
  : options.verbose !== true;
420
- const uploadOptions = { ...options, minimal };
430
+ const uploadOptions = { ...options, minimal, pathOptions };
431
+ if (await isRoleAssistantShellPackage(systemKey, uploadOptions)) {
432
+ return uploadRoleAssistantShellPackage(systemKey, uploadOptions, {
433
+ resolveDataplaneAndAuth
434
+ });
435
+ }
421
436
  if (!minimal) {
422
437
  logger.log('');
423
438
  logger.log(sectionTitle('Upload external system'));
@@ -10,7 +10,7 @@ const fs = require('fs');
10
10
  const yaml = require('js-yaml');
11
11
  const config = require('./config');
12
12
  const { getEnvHosts } = require('../utils/env-endpoints');
13
- const { getContainerPortFromPath } = require('../utils/port-resolver');
13
+ const { getContainerPortFromPath, isExternalAppPath } = require('../utils/port-resolver');
14
14
 
15
15
  /**
16
16
  * Gets base docker environment config
@@ -69,6 +69,9 @@ function getContainerPortFromDockerEnv(dockerEnv) {
69
69
  * @returns {Promise<string>} Updated content with PORT set
70
70
  */
71
71
  async function updatePortForDocker(resolved, variablesPath) {
72
+ if (isExternalAppPath(variablesPath)) {
73
+ return resolved;
74
+ }
72
75
  let dockerEnv = await getBaseDockerEnv();
73
76
  dockerEnv = applyDockerEnvOverride(dockerEnv);
74
77