@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
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Map ES configuration[] names to consumer propertyKeys and install options.
3
+ *
4
+ * @fileoverview CHANNEL_COMMAND_PREFIX → commandPrefix
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const SECRET_NAME_RE = /(SECRET|PASSWORD|TOKEN|KEY|CREDENTIAL)/i;
12
+
13
+ /**
14
+ * @param {string} envName
15
+ * @returns {string}
16
+ */
17
+ function envNameToPropertyKey(envName) {
18
+ const stripped = String(envName || '').replace(/^CHANNEL_/, '');
19
+ const lower = stripped.toLowerCase();
20
+ return lower.replace(/_([a-z0-9])/g, (_, ch) => ch.toUpperCase());
21
+ }
22
+
23
+ /**
24
+ * @param {Object} definition
25
+ * @returns {Object[]}
26
+ */
27
+ function listDefinitionConfiguration(definition) {
28
+ const rows = definition && Array.isArray(definition.configuration) ? definition.configuration : [];
29
+ return rows.filter((row) => row && typeof row.name === 'string');
30
+ }
31
+
32
+ /**
33
+ * @param {Object} definition
34
+ * @returns {Map<string, Object>}
35
+ */
36
+ function configurationByPropertyKey(definition) {
37
+ const map = new Map();
38
+ for (const row of listDefinitionConfiguration(definition)) {
39
+ map.set(envNameToPropertyKey(row.name), row);
40
+ }
41
+ return map;
42
+ }
43
+
44
+ /**
45
+ * @param {unknown} value
46
+ * @returns {boolean}
47
+ */
48
+ function isSecretShapedValue(value) {
49
+ if (typeof value !== 'string') {
50
+ return false;
51
+ }
52
+ return /kv:\/\//i.test(value) || SECRET_NAME_RE.test(value);
53
+ }
54
+
55
+ /**
56
+ * Safe configuration for GET definition (no secret-shaped values).
57
+ * @param {Object} definition
58
+ * @returns {Object[]}
59
+ */
60
+ function toSafeConfiguration(definition) {
61
+ return listDefinitionConfiguration(definition).map((row) => {
62
+ const copy = { ...row };
63
+ if (isSecretShapedValue(copy.value)) {
64
+ copy.value = '';
65
+ }
66
+ copy.propertyKey = envNameToPropertyKey(row.name);
67
+ return copy;
68
+ });
69
+ }
70
+
71
+ /**
72
+ * @param {Object} row
73
+ * @returns {Object|null}
74
+ */
75
+ function toPortalField(row) {
76
+ const portal = row && row.portalInput;
77
+ if (!portal || typeof portal !== 'object') {
78
+ return null;
79
+ }
80
+ if (typeof portal.label !== 'string' || !portal.label.trim()) {
81
+ return null;
82
+ }
83
+ if (isSecretShapedValue(row.value)) {
84
+ return null;
85
+ }
86
+ const propertyKey = envNameToPropertyKey(row.name);
87
+ const field = {
88
+ propertyKey,
89
+ label: portal.label.trim(),
90
+ required: row.required === true,
91
+ envName: row.name
92
+ };
93
+ if (portal.field) {
94
+ field.inputKind = portal.field;
95
+ }
96
+ if (portal.placeholder) {
97
+ field.placeholder = portal.placeholder;
98
+ }
99
+ if (Array.isArray(portal.options) && portal.options.length > 0) {
100
+ field.options = portal.options;
101
+ }
102
+ if (
103
+ typeof row.value === 'string' &&
104
+ row.value.trim() &&
105
+ !row.value.includes('{{') &&
106
+ !/kv:\/\//i.test(row.value)
107
+ ) {
108
+ field.defaultValue = row.value.trim();
109
+ }
110
+ assignPortalConstraints(field, portal.validation);
111
+ return field;
112
+ }
113
+
114
+ /**
115
+ * @param {Object} field
116
+ * @param {unknown} validation
117
+ */
118
+ function assignPortalConstraints(field, validation) {
119
+ if (!validation || typeof validation !== 'object') {
120
+ return;
121
+ }
122
+ const rules = /** @type {Record<string, unknown>} */ (validation);
123
+ if (typeof rules.minLength === 'number' && rules.minLength > 0) {
124
+ field.minLength = rules.minLength;
125
+ }
126
+ if (typeof rules.maxLength === 'number' && rules.maxLength > 0) {
127
+ field.maxLength = rules.maxLength;
128
+ }
129
+ if (typeof rules.pattern === 'string' && rules.pattern.trim()) {
130
+ field.pattern = rules.pattern.trim();
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Portal-facing fields only. Rows without portalInput are hidden system variables.
136
+ * @param {Object} definition
137
+ * @returns {Object[]}
138
+ */
139
+ function toPortalFields(definition) {
140
+ return listDefinitionConfiguration(definition)
141
+ .map(toPortalField)
142
+ .filter(Boolean);
143
+ }
144
+
145
+ /**
146
+ * @param {Object} definition
147
+ * @param {Object} configuration
148
+ * @returns {string[]}
149
+ */
150
+ function unknownConfigurationKeys(definition, configuration) {
151
+ if (!configuration || typeof configuration !== 'object') {
152
+ return [];
153
+ }
154
+ const known = configurationByPropertyKey(definition);
155
+ return Object.keys(configuration).filter((key) => !known.has(key));
156
+ }
157
+
158
+ /**
159
+ * @param {Object} definition
160
+ * @param {Object} configuration
161
+ * @returns {string[]}
162
+ */
163
+ function missingRequiredConfigurationKeys(definition, configuration) {
164
+ const provided = configuration && typeof configuration === 'object' ? configuration : {};
165
+ const missing = [];
166
+ for (const [propertyKey, row] of configurationByPropertyKey(definition).entries()) {
167
+ if (row.required === true && (provided[propertyKey] === undefined || provided[propertyKey] === '')) {
168
+ missing.push(propertyKey);
169
+ }
170
+ }
171
+ return missing;
172
+ }
173
+
174
+ const OPTION_BY_PROPERTY_KEY = {
175
+ commandPrefix: 'commandPrefix',
176
+ packageVersion: 'packageVersion',
177
+ oauthPluginVaultReferenceId: 'oauthPluginVaultReferenceId',
178
+ appDescription: 'description'
179
+ };
180
+
181
+ /**
182
+ * @param {Object} options
183
+ * @param {Object} configuration
184
+ * @returns {Object}
185
+ */
186
+ function applyConfigurationToAddOptions(options, configuration) {
187
+ if (!configuration || typeof configuration !== 'object') {
188
+ return options;
189
+ }
190
+ const next = { ...options };
191
+ for (const [propertyKey, value] of Object.entries(configuration)) {
192
+ if (SECRET_NAME_RE.test(propertyKey) && !OPTION_BY_PROPERTY_KEY[propertyKey]) {
193
+ continue;
194
+ }
195
+ const optionKey = OPTION_BY_PROPERTY_KEY[propertyKey] || propertyKey;
196
+ if (value !== undefined) {
197
+ next[optionKey] = value;
198
+ }
199
+ }
200
+ return next;
201
+ }
202
+
203
+ module.exports = {
204
+ envNameToPropertyKey,
205
+ listDefinitionConfiguration,
206
+ configurationByPropertyKey,
207
+ toSafeConfiguration,
208
+ toPortalFields,
209
+ unknownConfigurationKeys,
210
+ missingRequiredConfigurationKeys,
211
+ applyConfigurationToAddOptions,
212
+ isSecretShapedValue
213
+ };
@@ -26,7 +26,8 @@ const CREDENTIAL_SPECS = {
26
26
  method: 'hmac',
27
27
  credentialConfig: {
28
28
  type: 'hmac',
29
- signingSecret: 'pending-channel-install',
29
+ signingSecret: 'kv://slack/signingSecret',
30
+ botToken: 'kv://slack/botToken',
30
31
  algorithm: 'sha256',
31
32
  signatureHeader: 'X-Slack-Signature',
32
33
  timestampHeader: 'X-Slack-Request-Timestamp',
@@ -57,15 +58,6 @@ const CREDENTIAL_SPECS = {
57
58
  clientSecret: 'pending-channel-install'
58
59
  }
59
60
  },
60
- chatgpt: {
61
- method: 'apiKey',
62
- credentialConfig: {
63
- type: 'apiKey',
64
- apiKey: 'pending-channel-install',
65
- headerName: 'Authorization',
66
- prefix: 'Bearer'
67
- }
68
- },
69
61
  'web-embed': {
70
62
  method: 'apiKey',
71
63
  credentialConfig: {
@@ -148,10 +140,15 @@ async function createChannelCredential(ctx, channelTarget, target) {
148
140
  * @returns {Promise<{ pushed: number }>}
149
141
  */
150
142
  async function pushIntegrationSecrets(ctx, channelTarget) {
151
- const integrationDir = getIntegrationPath(channelTarget);
152
- const envPath = path.join(integrationDir, '.env');
143
+ const folderKey =
144
+ ctx && typeof ctx.instanceSystemKey === 'string' && ctx.instanceSystemKey.trim()
145
+ ? ctx.instanceSystemKey.trim()
146
+ : channelTarget;
147
+ const integrationDir = ctx && ctx.projectRoot
148
+ ? path.join(path.resolve(ctx.projectRoot), 'integration', folderKey)
149
+ : getIntegrationPath(folderKey);
153
150
  const result = await pushCredentialSecrets(ctx.dataplaneUrl, ctx.authConfig, {
154
- envFilePath: envPath,
151
+ envFilePath: path.join(integrationDir, '.env'),
155
152
  appName: channelTarget,
156
153
  quiet: true
157
154
  });
@@ -175,7 +172,7 @@ async function ensureChannelCredential(params) {
175
172
  if (skipsChannelOauthCredential(channelTarget)) {
176
173
  return {
177
174
  skipped: true,
178
- reason: 'entraSsoTrustedIssuer',
175
+ reason: channelTarget === 'microsoft-copilot' ? 'entraSsoTrustedIssuer' : 'integrationClientOAuth',
179
176
  credentialKey: target.credentialKey
180
177
  };
181
178
  }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Project Channel Definitions into the historic CHANNEL_TARGETS row shape.
3
+ *
4
+ * @fileoverview Catalog / wizard / adapter packaging from channel.json
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const { definitionRuntimeSystemKey } = require('./channel-definition-registry');
12
+
13
+ const DEFAULT_CAPABILITIES = ['chat', 'notify', 'documentApproval'];
14
+
15
+ /**
16
+ * @param {Object} definition
17
+ * @returns {Object}
18
+ */
19
+ function packagingOf(definition) {
20
+ const packing = definition && definition.channel && definition.channel.packaging;
21
+ return packing && typeof packing === 'object' ? packing : {};
22
+ }
23
+
24
+ /**
25
+ * @param {Object} definition
26
+ * @param {Object} packing
27
+ * @returns {string}
28
+ */
29
+ function credentialKeyOf(definition, packing) {
30
+ const fromAuth =
31
+ definition.authentication && definition.authentication.credential
32
+ ? definition.authentication.credential.credentialKey
33
+ : null;
34
+ return fromAuth || packing.credentialKey || `${definition.key}-channel`;
35
+ }
36
+
37
+ /**
38
+ * @param {Object} definition
39
+ * @param {Object} channel
40
+ * @returns {Object}
41
+ */
42
+ function runtimeTargetOf(definition, channel) {
43
+ return (
44
+ channel.runtimeTarget || {
45
+ defaultSystemKey: definitionRuntimeSystemKey(definition),
46
+ configurable: true
47
+ }
48
+ );
49
+ }
50
+
51
+ /**
52
+ * @param {Object} definition
53
+ * @param {Object} packing
54
+ * @returns {Object}
55
+ */
56
+ function packagingFields(definition, packing) {
57
+ return {
58
+ channelType: packing.channelType || definition.key,
59
+ templateDir: packing.templateDir || definition.key,
60
+ artifactFileName: packing.artifactFileName || `channel-${definition.key}.json`,
61
+ artifactFormat: packing.artifactFormat || 'json',
62
+ displayLabel: packing.displayLabel || definition.displayName,
63
+ category: packing.category || 'communication',
64
+ wizardOrder: Number.isInteger(packing.wizardOrder) ? packing.wizardOrder : 100,
65
+ remainingManualStep: packing.remainingManualStep || '',
66
+ docsAnchor: packing.docsAnchor || definition.key,
67
+ approvalRequired: packing.approvalRequired !== false,
68
+ vendorAuthRequired: packing.vendorAuthRequired !== false,
69
+ capabilities: Array.isArray(packing.capabilities)
70
+ ? [...packing.capabilities]
71
+ : [...DEFAULT_CAPABILITIES]
72
+ };
73
+ }
74
+
75
+ /**
76
+ * @param {Object} definition
77
+ * @returns {Object}
78
+ */
79
+ function toChannelTargetProjection(definition) {
80
+ const packing = packagingOf(definition);
81
+ const channel = definition.channel || {};
82
+ return {
83
+ key: definition.key,
84
+ ...packagingFields(definition, packing),
85
+ credentialKey: credentialKeyOf(definition, packing),
86
+ description: definition.description,
87
+ experimental: channel.experimental === true,
88
+ automatedProvisioning: Boolean(channel.provisioning && channel.provisioning.mode === 'automatic'),
89
+ provisioning: channel.provisioning || { mode: 'guided' },
90
+ runtimeTarget: runtimeTargetOf(definition, channel),
91
+ profiles: Array.isArray(channel.profiles) ? channel.profiles.map((row) => ({ ...row })) : [],
92
+ definitionKey: channel.definitionKey || definition.key,
93
+ artifacts: Array.isArray(channel.artifacts) ? [...channel.artifacts] : []
94
+ };
95
+ }
96
+
97
+ module.exports = {
98
+ packagingOf,
99
+ toChannelTargetProjection,
100
+ DEFAULT_CAPABILITIES
101
+ };
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Load Channel Definitions from templates/channels/<key>/channel.json.
3
+ *
4
+ * @fileoverview Canonical ES documents plus channel specialization
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const path = require('path');
12
+
13
+ const TEMPLATES_ROOT = path.join(__dirname, '..', '..', 'templates', 'channels');
14
+ const DEFAULT_RUNTIME = 'runtime-orchestration';
15
+
16
+ /** @type {Map<string, Object>|null} */
17
+ let cachedDefinitions = null;
18
+
19
+ /**
20
+ * Disk SSOT must ignore Jest `fs` mocks (brand/ is an icon pack, not a definition).
21
+ * @returns {typeof import('node:fs')}
22
+ */
23
+ function channelDiskFs() {
24
+ const jestApi = typeof globalThis.jest === 'object' ? globalThis.jest : null;
25
+ if (jestApi && typeof jestApi.requireActual === 'function') {
26
+ return jestApi.requireActual('node:fs');
27
+ }
28
+ const snap = global.__AIFABRIX_NODE_FS_UNMOCKED__;
29
+ if (snap && typeof snap.readdirSync === 'function' && typeof snap.readFileSync === 'function') {
30
+ return snap;
31
+ }
32
+ return require('node:fs');
33
+ }
34
+
35
+ /**
36
+ * @param {string} raw
37
+ * @param {string} filePath
38
+ * @returns {Object}
39
+ */
40
+ function parseDefinition(raw, filePath) {
41
+ const parsed = JSON.parse(raw);
42
+ if (!parsed || typeof parsed !== 'object' || typeof parsed.key !== 'string') {
43
+ throw new Error(`Invalid Channel Definition: ${filePath}`);
44
+ }
45
+ return parsed;
46
+ }
47
+
48
+ /**
49
+ * @param {object} disk
50
+ * @param {string} templatesRoot
51
+ * @param {string} name
52
+ * @param {Map<string, Object>} map
53
+ * @returns {void}
54
+ */
55
+ function loadOneDefinition(disk, templatesRoot, name, map) {
56
+ if (typeof name !== 'string' || name.startsWith('.')) {
57
+ return;
58
+ }
59
+ const filePath = path.join(templatesRoot, name, 'channel.json');
60
+ let raw;
61
+ try {
62
+ raw = disk.readFileSync(filePath, 'utf8');
63
+ } catch (err) {
64
+ if (err && (err.code === 'ENOENT' || err.code === 'EISDIR' || err.code === 'ENOTDIR')) {
65
+ return;
66
+ }
67
+ throw err;
68
+ }
69
+ if (typeof raw !== 'string' || !raw.trim()) {
70
+ return;
71
+ }
72
+ const definition = parseDefinition(raw, filePath);
73
+ map.set(definition.key, definition);
74
+ }
75
+
76
+ /**
77
+ * @param {string} [templatesRoot]
78
+ * @returns {Map<string, Object>}
79
+ */
80
+ function loadChannelDefinitions(templatesRoot = TEMPLATES_ROOT) {
81
+ const disk = channelDiskFs();
82
+ const map = new Map();
83
+ let names;
84
+ try {
85
+ names = disk.readdirSync(templatesRoot);
86
+ } catch {
87
+ return map;
88
+ }
89
+ if (!Array.isArray(names)) {
90
+ return map;
91
+ }
92
+ for (const name of names) {
93
+ loadOneDefinition(disk, templatesRoot, name, map);
94
+ }
95
+ return map;
96
+ }
97
+
98
+ /**
99
+ * @returns {Map<string, Object>}
100
+ */
101
+ function getChannelDefinitionMap() {
102
+ if (cachedDefinitions && cachedDefinitions.size > 0) {
103
+ return cachedDefinitions;
104
+ }
105
+ cachedDefinitions = loadChannelDefinitions();
106
+ return cachedDefinitions;
107
+ }
108
+
109
+ /**
110
+ * Test hook — clear cached definitions.
111
+ * @returns {void}
112
+ */
113
+ function resetChannelDefinitionCache() {
114
+ cachedDefinitions = null;
115
+ }
116
+
117
+ /**
118
+ * @param {string} key
119
+ * @returns {Object|null}
120
+ */
121
+ function getChannelDefinition(key) {
122
+ return getChannelDefinitionMap().get(key) || null;
123
+ }
124
+
125
+ /**
126
+ * @returns {string[]}
127
+ */
128
+ function listChannelDefinitionKeys() {
129
+ return [...getChannelDefinitionMap().keys()];
130
+ }
131
+
132
+ /**
133
+ * @param {Object} definition
134
+ * @returns {string}
135
+ */
136
+ function definitionRuntimeSystemKey(definition) {
137
+ const fromDoc = definition && definition.channel && definition.channel.runtimeTarget;
138
+ if (fromDoc && typeof fromDoc.defaultSystemKey === 'string' && fromDoc.defaultSystemKey) {
139
+ return fromDoc.defaultSystemKey;
140
+ }
141
+ return DEFAULT_RUNTIME;
142
+ }
143
+
144
+ module.exports = {
145
+ TEMPLATES_ROOT,
146
+ DEFAULT_RUNTIME,
147
+ channelDiskFs,
148
+ loadChannelDefinitions,
149
+ getChannelDefinitionMap,
150
+ getChannelDefinition,
151
+ listChannelDefinitionKeys,
152
+ resetChannelDefinitionCache,
153
+ definitionRuntimeSystemKey
154
+ };
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Slack manifest description limits (plan 152).
2
+ * Slack manifest description limits.
3
3
  *
4
- * @fileoverview Enforce Slack display_information.description max length
4
+ * @fileoverview Enforce Slack display_information short and long description lengths
5
5
  * @author AI Fabrix Team
6
6
  * @version 1.0.0
7
7
  */
@@ -11,6 +11,18 @@
11
11
  /** Slack manifest `display_information.description` max (api.slack.com/reference/manifests). */
12
12
  const SLACK_APP_DESCRIPTION_MAX_LENGTH = 140;
13
13
 
14
+ /** Slack App Settings reject `long_description` shorter than this. */
15
+ const SLACK_APP_LONG_DESCRIPTION_MIN_LENGTH = 175;
16
+
17
+ /** Slack manifest `display_information.long_description` max. */
18
+ const SLACK_APP_LONG_DESCRIPTION_MAX_LENGTH = 4000;
19
+
20
+ const DEFAULT_SLACK_APP_LONG_DESCRIPTION =
21
+ 'This Slack app connects employees to governed Role Assistants. Chat in DM, ' +
22
+ 'follow work that needs you, and open documents waiting for review. Access is ' +
23
+ 'limited by enterprise identity, and actions stay auditable. If a Slack ' +
24
+ 'profile email does not match a platform user, they can still link their account.';
25
+
14
26
  /**
15
27
  * @param {string} description
16
28
  * @returns {string}
@@ -51,9 +63,54 @@ function resolveAppDescription(channelTarget, description) {
51
63
  return text;
52
64
  }
53
65
 
66
+ /**
67
+ * @param {string} description
68
+ * @returns {string}
69
+ */
70
+ function normalizeSlackAppLongDescription(description) {
71
+ const text = String(description ?? '').trim();
72
+ if (text.length >= SLACK_APP_LONG_DESCRIPTION_MIN_LENGTH) {
73
+ return text.length > SLACK_APP_LONG_DESCRIPTION_MAX_LENGTH
74
+ ? text.slice(0, SLACK_APP_LONG_DESCRIPTION_MAX_LENGTH)
75
+ : text;
76
+ }
77
+ if (!text) {
78
+ return DEFAULT_SLACK_APP_LONG_DESCRIPTION;
79
+ }
80
+ const combined = `${text} ${DEFAULT_SLACK_APP_LONG_DESCRIPTION}`;
81
+ if (combined.length > SLACK_APP_LONG_DESCRIPTION_MAX_LENGTH) {
82
+ return combined.slice(0, SLACK_APP_LONG_DESCRIPTION_MAX_LENGTH);
83
+ }
84
+ return combined;
85
+ }
86
+
87
+ /**
88
+ * @param {string} channelTarget
89
+ * @param {Object} runtimeValues
90
+ * @returns {Object}
91
+ */
92
+ function fillSlackManifestDescriptions(channelTarget, runtimeValues) {
93
+ if (channelTarget !== 'slack' || !runtimeValues || typeof runtimeValues !== 'object') {
94
+ return runtimeValues;
95
+ }
96
+ const appLongDescription = normalizeSlackAppLongDescription(
97
+ runtimeValues.appLongDescription || runtimeValues.appDescription
98
+ );
99
+ return {
100
+ ...runtimeValues,
101
+ appLongDescription,
102
+ appLongDescriptionJson: JSON.stringify(appLongDescription)
103
+ };
104
+ }
105
+
54
106
  module.exports = {
55
107
  SLACK_APP_DESCRIPTION_MAX_LENGTH,
108
+ SLACK_APP_LONG_DESCRIPTION_MIN_LENGTH,
109
+ SLACK_APP_LONG_DESCRIPTION_MAX_LENGTH,
110
+ DEFAULT_SLACK_APP_LONG_DESCRIPTION,
56
111
  normalizeSlackAppDescription,
112
+ normalizeSlackAppLongDescription,
113
+ fillSlackManifestDescriptions,
57
114
  assertSlackAppDescription,
58
115
  resolveAppDescription
59
116
  };
@@ -75,6 +75,18 @@ function extractGovernedToolNames(discovery) {
75
75
  return tools.map((tool) => (tool && tool.name ? String(tool.name) : '')).filter(Boolean);
76
76
  }
77
77
 
78
+ /**
79
+ * Live discovery uses `publication.remoteMcpReady`. Older fixtures used `mcpReady`.
80
+ * @param {Object|null|undefined} publication
81
+ * @returns {boolean}
82
+ */
83
+ function isPublicationRemoteMcpReady(publication) {
84
+ if (!publication || typeof publication !== 'object') {
85
+ return false;
86
+ }
87
+ return publication.remoteMcpReady === true || publication.mcpReady === true;
88
+ }
89
+
78
90
  /**
79
91
  * @param {Object} discovery
80
92
  * @param {Object|null} adapter
@@ -93,7 +105,7 @@ function resolveMcpConnection(discovery, adapter, dataplaneBaseUrl) {
93
105
  'Gateway tools catalog must not be used as MCP server URL for channel packages'
94
106
  );
95
107
  }
96
- const mcpReady = discovery?.publication?.mcpReady === true;
108
+ const mcpReady = isPublicationRemoteMcpReady(discovery && discovery.publication);
97
109
  const connectable = adapter ? adapter.connectable === true : mcpReady;
98
110
  const remoteAvailable = discovery?.transport?.remoteMcp?.status === 'available';
99
111
  const installReady = Boolean(mcpReady && connectable && remoteAvailable && mcpServerUrl);
@@ -213,7 +225,8 @@ function mapDiscoveryToPackageContext(params) {
213
225
  authentication: mapAdapterAuthentication(adapter?.authentication || null),
214
226
  authenticationCapabilities: authCaps,
215
227
  publication: {
216
- mcpReady: discovery.publication?.mcpReady === true,
228
+ mcpReady: isPublicationRemoteMcpReady(discovery.publication),
229
+ remoteMcpReady: isPublicationRemoteMcpReady(discovery.publication),
217
230
  environment: discovery.publication?.environment || null
218
231
  },
219
232
  brandingApplied: isBrandingApplied(branding)
@@ -321,6 +334,7 @@ async function loadChannelPackageContext(params) {
321
334
  module.exports = {
322
335
  GATEWAY_TOOLS_CATALOG_MARKER,
323
336
  isGatewayToolsCatalogUrl,
337
+ isPublicationRemoteMcpReady,
324
338
  resolveDiscoveryUrl,
325
339
  mapDiscoveryToPackageContext,
326
340
  fetchExternalAiDiscovery,