@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
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Vendor-facing dataplane and controller bases for channel webhooks and packages.
3
+ *
4
+ * @fileoverview Keep DATAPLANE_URL / MISO_CONTROLLER_URL internal for API calls
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ /**
10
+ * @param {unknown} value
11
+ * @returns {string}
12
+ */
13
+ function trimBase(value) {
14
+ return String(value || '').trim().replace(/\/$/, '');
15
+ }
16
+
17
+ /**
18
+ * @param {string} host
19
+ * @returns {boolean}
20
+ */
21
+ function isLoopbackHost(host) {
22
+ const hostname = String(host || '').toLowerCase();
23
+ return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1';
24
+ }
25
+
26
+ /**
27
+ * @param {unknown} value
28
+ * @returns {boolean}
29
+ */
30
+ function isPublicHttpsUrl(value) {
31
+ const raw = trimBase(value);
32
+ if (!raw) {
33
+ return false;
34
+ }
35
+ try {
36
+ const parsed = new URL(raw);
37
+ if (parsed.protocol !== 'https:') {
38
+ return false;
39
+ }
40
+ const host = parsed.hostname.toLowerCase();
41
+ return Boolean(host) && !isLoopbackHost(host) && host.includes('.');
42
+ } catch {
43
+ return false;
44
+ }
45
+ }
46
+
47
+ /**
48
+ * @param {string} internalUrl
49
+ * @returns {string}
50
+ */
51
+ function pathVdir(internalUrl) {
52
+ try {
53
+ const pathName = new URL(internalUrl).pathname.replace(/\/$/, '');
54
+ return pathName && pathName !== '/' ? pathName : '';
55
+ } catch {
56
+ return '';
57
+ }
58
+ }
59
+
60
+ /**
61
+ * @param {string} origin
62
+ * @param {string} vdir
63
+ * @returns {string}
64
+ */
65
+ function joinOriginAndVdir(origin, vdir) {
66
+ const base = trimBase(origin);
67
+ if (!base) {
68
+ return '';
69
+ }
70
+ if (!vdir) {
71
+ return base;
72
+ }
73
+ if (base.endsWith(vdir)) {
74
+ return base;
75
+ }
76
+ return `${base}${vdir.startsWith('/') ? vdir : `/${vdir}`}`;
77
+ }
78
+
79
+ /**
80
+ * Browser Origin / Referer that vendors can reach (portal host, not builder-api).
81
+ * @param {import('http').IncomingMessage|null|undefined} req
82
+ * @returns {string}
83
+ */
84
+ function publicOriginFromRequest(req) {
85
+ const headers = (req && req.headers) || {};
86
+ const origin = trimBase(headers.origin);
87
+ if (isPublicHttpsUrl(origin)) {
88
+ return new URL(origin).origin;
89
+ }
90
+ try {
91
+ const referer = new URL(String(headers.referer || ''));
92
+ if (isPublicHttpsUrl(referer.origin)) {
93
+ return referer.origin;
94
+ }
95
+ } catch {
96
+ // ignore invalid Referer
97
+ }
98
+ return '';
99
+ }
100
+
101
+ /**
102
+ * @param {NodeJS.ProcessEnv} [env]
103
+ * @returns {string}
104
+ */
105
+ function publicOriginFromAllowlist(env = process.env) {
106
+ for (const raw of String(env.ALLOWED_ORIGINS || '').split(',')) {
107
+ const candidate = trimBase(raw);
108
+ if (!candidate || candidate.includes('*')) {
109
+ continue;
110
+ }
111
+ try {
112
+ const parsed = new URL(candidate);
113
+ if (parsed.port && parsed.port !== '443') {
114
+ continue;
115
+ }
116
+ if (isPublicHttpsUrl(candidate)) {
117
+ return parsed.origin;
118
+ }
119
+ } catch {
120
+ // skip malformed allowlist entries
121
+ }
122
+ }
123
+ return '';
124
+ }
125
+
126
+ /**
127
+ * @param {string} [controllerUrl]
128
+ * @returns {string}
129
+ */
130
+ function publicOriginFromController(controllerUrl) {
131
+ const raw = trimBase(controllerUrl);
132
+ if (!isPublicHttpsUrl(raw)) {
133
+ return '';
134
+ }
135
+ try {
136
+ return new URL(raw).origin;
137
+ } catch {
138
+ return '';
139
+ }
140
+ }
141
+
142
+ /**
143
+ * @param {string} [internalUrl]
144
+ * @param {string} envKey
145
+ * @param {NodeJS.ProcessEnv} env
146
+ * @param {{ publicOrigin?: string, siblingPublicUrl?: string, defaultVdir?: string }} extras
147
+ * @returns {string}
148
+ */
149
+ function resolveVendorFacingBase(internalUrl, envKey, env, extras = {}) {
150
+ const internal = trimBase(internalUrl);
151
+ if (isPublicHttpsUrl(internal)) {
152
+ return internal;
153
+ }
154
+ const envUrl = trimBase(env[envKey]);
155
+ if (isPublicHttpsUrl(envUrl)) {
156
+ return envUrl;
157
+ }
158
+ const vdir = pathVdir(internal) || extras.defaultVdir || '';
159
+ const fromOrigin = joinOriginAndVdir(extras.publicOrigin, vdir);
160
+ if (isPublicHttpsUrl(fromOrigin)) {
161
+ return fromOrigin;
162
+ }
163
+ const fromAllow = joinOriginAndVdir(publicOriginFromAllowlist(env), vdir);
164
+ if (isPublicHttpsUrl(fromAllow)) {
165
+ return fromAllow;
166
+ }
167
+ const siblingOrigin = publicOriginFromController(extras.siblingPublicUrl);
168
+ const fromSibling = joinOriginAndVdir(siblingOrigin, vdir);
169
+ if (isPublicHttpsUrl(fromSibling)) {
170
+ return fromSibling;
171
+ }
172
+ return internal;
173
+ }
174
+
175
+ /**
176
+ * @param {NodeJS.ProcessEnv} env
177
+ * @param {string[]} keys
178
+ * @returns {string}
179
+ */
180
+ function firstPublicEnvUrl(env, keys) {
181
+ for (const key of keys) {
182
+ const value = trimBase(env[key]);
183
+ if (isPublicHttpsUrl(value)) {
184
+ return value;
185
+ }
186
+ }
187
+ return '';
188
+ }
189
+
190
+ /**
191
+ * @param {string} [internalUrl]
192
+ * @param {{ publicOrigin?: string, env?: NodeJS.ProcessEnv, controllerUrl?: string }} [options]
193
+ * @returns {string}
194
+ */
195
+ function resolveVendorFacingDataplaneUrl(internalUrl, options = {}) {
196
+ return resolveVendorFacingBase(internalUrl, 'DATAPLANE_PUBLIC_URL', options.env || process.env, {
197
+ publicOrigin: options.publicOrigin,
198
+ siblingPublicUrl: options.controllerUrl
199
+ });
200
+ }
201
+
202
+ /**
203
+ * @param {string} [internalUrl]
204
+ * @param {{ publicOrigin?: string, env?: NodeJS.ProcessEnv, dataplanePublicUrl?: string }} [options]
205
+ * @returns {string}
206
+ */
207
+ function resolveVendorFacingControllerUrl(internalUrl, options = {}) {
208
+ const env = options.env || process.env;
209
+ const dedicated = firstPublicEnvUrl(env, [
210
+ 'MISO_CONTROLLER_PUBLIC_URL',
211
+ 'CONTROLLER_PUBLIC_URL'
212
+ ]);
213
+ if (dedicated) {
214
+ return dedicated;
215
+ }
216
+ return resolveVendorFacingBase(internalUrl, 'MISO_CONTROLLER_PUBLIC_URL', env, {
217
+ publicOrigin: options.publicOrigin,
218
+ siblingPublicUrl: options.dataplanePublicUrl
219
+ });
220
+ }
221
+
222
+ /**
223
+ * @param {Object|null|undefined} ctx
224
+ * @param {NodeJS.ProcessEnv} [env]
225
+ * @returns {{ dataplaneBaseUrl: string, controllerUrl: string }}
226
+ */
227
+ function vendorFacingUrlsFromCtx(ctx, env) {
228
+ const options = {
229
+ publicOrigin: ctx && ctx.publicOrigin,
230
+ controllerUrl: ctx && ctx.controllerUrl,
231
+ env: env || process.env
232
+ };
233
+ const dataplaneBaseUrl = resolveVendorFacingDataplaneUrl(ctx && ctx.dataplaneUrl, options);
234
+ const controllerUrl = resolveVendorFacingControllerUrl(ctx && ctx.controllerUrl, {
235
+ publicOrigin: options.publicOrigin,
236
+ env: options.env,
237
+ dataplanePublicUrl: dataplaneBaseUrl
238
+ });
239
+ return { dataplaneBaseUrl, controllerUrl };
240
+ }
241
+
242
+ module.exports = {
243
+ isPublicHttpsUrl,
244
+ publicOriginFromRequest,
245
+ publicOriginFromAllowlist,
246
+ resolveVendorFacingDataplaneUrl,
247
+ resolveVendorFacingControllerUrl,
248
+ vendorFacingUrlsFromCtx
249
+ };
@@ -78,6 +78,8 @@ Examples:
78
78
 
79
79
  Notes:
80
80
  - Expert path: pushes integration/<systemKey>/scenarios/*.yaml to the dataplane.
81
+ - Each file is stored on the datasource named by the filename (scenarios/<datasourceKey>.yaml).
82
+ - Search datasourceKeys in the YAML are what verification searches; they may differ for views (carrier storage datasource).
81
83
  - Packs must satisfy the 424.0 schema (spec.coverage, metadata.generationState). Use governance generate
82
84
  or verify-governance for dataplane-first packs.
83
85
  `;
@@ -29,6 +29,7 @@ Notes:
29
29
  - --probe runs dataplane runtime checks after publish (slower).
30
30
  - --timeout sets publish budget in ms (HTTP client and dataplane); default 300000.
31
31
  - --env selects role-assistant.yaml section (dev|tst|pro) for digital workers; default dev.
32
+ - Role Assistant packages under role-assistant/ do not use application.yaml; upload applies settings and Evidence only.
32
33
  - test-e2e and test-integration publish local files first by default; use --no-publish on those commands to skip.
33
34
  - After dimension/FK edits on active datasources, use --force (or test-e2e / test-integration / datasource test-* with --sync --force).
34
35
  - For one datasource only: aifabrix datasource upload <datasourceKey>
@@ -45,6 +46,7 @@ Examples:
45
46
 
46
47
  Notes:
47
48
  - Requires login and a system that already exists on the dataplane.
49
+ - Omit --format to use the developer default from aifabrix dev set-format (else yaml).
48
50
  - Overwrite prompts apply when integration/<systemKey>/ already exists (--force for README).
49
51
  `;
50
52
 
@@ -63,7 +63,7 @@ function setupDownloadCommand(program) {
63
63
  program.command('download <systemKey>')
64
64
  .description('Pull external system from dataplane into integration/<key>/')
65
65
  .addHelpText('after', DOWNLOAD_HELP_AFTER)
66
- .option('--format <format>', 'Output format: json | yaml (default: yaml or config format)')
66
+ .option('--format <format>', 'Output format: json | yaml (default: aifabrix dev set-format, else yaml)')
67
67
  .option('--dry-run', 'Show what would be downloaded without actually downloading')
68
68
  .option('--force', 'Overwrite existing README.md without prompting')
69
69
  .option(
@@ -0,0 +1,366 @@
1
+ /**
2
+ * Target-scoped help for `aifabrix channel add`.
3
+ *
4
+ * `channel add -h` is the full catalog. `channel add chatgpt -h` lists ChatGPT
5
+ * flags and examples only (no Slack, Copilot, or MCP-client leftovers).
6
+ *
7
+ * @fileoverview Channel add help — catalog vs named-target options
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ const { Help } = require('commander');
13
+ const {
14
+ formatSupportedChannelTargetsHelp,
15
+ isChannelTargetKey
16
+ } = require('../channels/channel-targets');
17
+
18
+ const SHARED_OPTION_LONG = new Set([
19
+ '--name',
20
+ '--description',
21
+ '--icon',
22
+ '--template',
23
+ '--dry-run',
24
+ '--force',
25
+ '--system-key',
26
+ '--probe',
27
+ '--verbose',
28
+ '--json',
29
+ '--help'
30
+ ]);
31
+
32
+ const TARGET_OPTION_LONG = {
33
+ slack: new Set(['--command-prefix', '--onboard-users', '--no-onboard-users']),
34
+ 'microsoft-copilot': new Set(['--oauth-plugin-vault-reference-id', '--package-version']),
35
+ chatgpt: new Set(['--callback-url']),
36
+ claude: new Set(['--callback-url']),
37
+ 'mcp-client': new Set(['--target', '--profile']),
38
+ 'teams-bot': new Set(),
39
+ 'web-embed': new Set(['--allow-experimental'])
40
+ };
41
+
42
+ const VALUE_FLAGS = new Set([
43
+ '-n',
44
+ '--name',
45
+ '-d',
46
+ '--description',
47
+ '--icon',
48
+ '--template',
49
+ '--command-prefix',
50
+ '--oauth-plugin-vault-reference-id',
51
+ '--package-version',
52
+ '--callback-url',
53
+ '--target',
54
+ '--profile'
55
+ ]);
56
+
57
+ const CHANNEL_ADD_HELP_AFTER = `
58
+ ${formatSupportedChannelTargetsHelp()}
59
+
60
+ One command covers scaffold → upload → install:
61
+ $ aifabrix channel add slack --name "Elsa" --probe
62
+
63
+ Examples:
64
+ $ aifabrix channel add
65
+ $ aifabrix channel add slack --name "Elsa"
66
+ $ aifabrix channel add teams-bot --name "Elsa" --description "Enterprise AI assistant for employees"
67
+ $ aifabrix channel add chatgpt --name "Your Assistant"
68
+ $ aifabrix channel add chatgpt --name "Your Assistant" \\
69
+ --callback-url "https://chatgpt.com/connector/oauth/callback"
70
+ $ aifabrix channel configure chatgpt --callback-url "https://chatgpt.com/connector/oauth/callback"
71
+ $ aifabrix channel add claude --name "Onni"
72
+ $ aifabrix channel configure claude --callback-url "https://claude.ai/api/mcp/auth_callback"
73
+ $ aifabrix channel add mcp-client --target cursor --name "Onni"
74
+ $ aifabrix channel add mcp-client --target vscode --name "Onni"
75
+ $ aifabrix channel add mcp-client --target github-copilot --name "Onni"
76
+ $ aifabrix channel add microsoft-copilot --name "Your Assistant" \\
77
+ --oauth-plugin-vault-reference-id "<Teams-Entra-SSO-auth-config-id>"
78
+
79
+ # Slack slash-command prefix (registers /{prefix}-help in manifest)
80
+ $ aifabrix channel add slack --name "Elsa" --command-prefix af
81
+
82
+ # Generate artifacts only; no dataplane patch / upload
83
+ $ aifabrix channel add slack --name "Elsa" --dry-run
84
+
85
+ # Refresh local integration from the channel template, re-upload, regenerate config
86
+ $ aifabrix channel add slack --name "Elsa" --force
87
+
88
+ # Copilot: after MCP URL / Entra change — regenerate ZIP (bumps Teams version 1.0.0 → 1.1.0)
89
+ $ aifabrix channel add microsoft-copilot --name "Your Assistant" --force \\
90
+ --oauth-plugin-vault-reference-id "<Teams-Entra-SSO-auth-config-id>"
91
+
92
+ # Optional: pin Teams manifest version instead of auto minor bump
93
+ $ aifabrix channel add microsoft-copilot --name "Your Assistant" --force --package-version 1.2.0 \\
94
+ --oauth-plugin-vault-reference-id "<Teams-Entra-SSO-auth-config-id>"
95
+
96
+ # Validate callbacks and assistant catalog after install
97
+ $ aifabrix channel add slack --name "Elsa" --probe
98
+
99
+ # Slack onboard (email match) without a TTY prompt
100
+ $ aifabrix channel add slack --name "Elsa" --onboard-users
101
+ $ aifabrix channel add slack --name "Elsa" --no-onboard-users
102
+
103
+ Behavior:
104
+ - Omit the target in a terminal to choose name and channel interactively
105
+ - --name is required when the target is specified (scripts and CI)
106
+ - -name is the same as --name; quoted names may contain spaces
107
+ - Scaffolds integration/<target>/ when missing, empty, or incomplete
108
+ - With --force, refreshes integration/<target>/ from the channel template, then uploads every time
109
+ - Uploads when the system is not on the dataplane
110
+ - Then configures the channel install (artifacts, credentials, admin guide)
111
+ - slack may ask **Onboard users?** and match Slack profile email to platform user email.
112
+ Non-interactive: --onboard-users or --no-onboard-users. Default is skip when not asked.
113
+ - chatgpt registers the ChatGPT callback URL when provided (--callback-url or TTY prompt).
114
+ It does not rotate the client secret. Remaining ChatGPT steps: Create with logo (cannot change later), Publish, Connect.
115
+ - claude registers the Claude callback URL (https://claude.ai/api/mcp/auth_callback) and prints
116
+ Name and Server URL. Open https://claude.ai/new#settings/customize-connectors and add a
117
+ custom connector with those two values. Use channel configure claude --callback-url only if
118
+ Claude shows a callback that is not already registered.
119
+ - mcp-client writes the Runtime MCP URL into the editor MCP config. Pass --target (or --profile)
120
+ with cursor, vscode, or github-copilot. It creates or reuses the Integration Client and never
121
+ rotates the client secret. Remaining step: Reload the editor.
122
+ - microsoft-copilot uses Entra SSO (trustedIssuer). Agents Toolkit (atk) creates or reuses
123
+ the Teams Entra SSO auth-config when you are signed in to the matching tenant. Pass
124
+ --oauth-plugin-vault-reference-id only when you already have the id or toolkit cannot
125
+ create it. Does not create Fabrix oauth2 channel credentials. Re-run with --force after
126
+ Runtime MCP URL or SSO changes; Teams manifest version auto-bumps minor (1.0.0 → 1.1.0)
127
+ unless --package-version is set. --force reuses the existing auth-config id.
128
+ - teams-bot uses Teams Developer CLI (teams app create --azure) around the existing
129
+ AI Fabrix messages URL. Azure subscription, resource group, and Entra tenant come
130
+ from the controller environment (same as Copilot Entra SSO). Remaining Microsoft
131
+ steps are tenant policy only. --force reuses the Azure-managed bot for this
132
+ environment and tenant.
133
+
134
+ Requires: aifabrix login
135
+ `;
136
+
137
+ const SHARED_TARGET_BEHAVIOR = `Behavior:
138
+ - --name is required when the target is specified (scripts and CI)
139
+ - Quoted names may contain spaces
140
+ - Scaffolds integration/<target>/ when missing, empty, or incomplete
141
+ - With --force, refreshes integration/<target>/ from the channel template, then uploads every time
142
+ - Uploads when the system is not on the dataplane
143
+ - Then configures the channel install (artifacts, credentials, admin guide)`;
144
+
145
+ const TARGET_HELP_AFTER = {
146
+ chatgpt: `
147
+ Examples:
148
+ $ aifabrix channel add chatgpt --name "Your Assistant"
149
+ $ aifabrix channel add chatgpt --name "Your Assistant" \\
150
+ --callback-url "https://chatgpt.com/connector/oauth/callback"
151
+ $ aifabrix channel add chatgpt --name "Your Assistant" --force
152
+ $ aifabrix channel add chatgpt --name "Your Assistant" --probe
153
+ $ aifabrix channel configure chatgpt --callback-url "https://chatgpt.com/connector/oauth/callback"
154
+
155
+ ${SHARED_TARGET_BEHAVIOR}
156
+ - chatgpt registers the ChatGPT callback URL when provided (--callback-url or TTY prompt).
157
+ It does not rotate the client secret. Remaining ChatGPT steps: Create with logo (cannot change later), Publish, Connect.
158
+
159
+ Requires: aifabrix login
160
+
161
+ See all channels:
162
+ $ aifabrix channel add -h
163
+ `,
164
+ claude: `
165
+ Examples:
166
+ $ aifabrix channel add claude --name "Onni"
167
+ $ aifabrix channel add claude --name "Onni" --force
168
+ $ aifabrix channel configure claude --callback-url "https://claude.ai/api/mcp/auth_callback"
169
+
170
+ ${SHARED_TARGET_BEHAVIOR}
171
+ - claude registers the Claude callback URL (https://claude.ai/api/mcp/auth_callback) and prints
172
+ Name and Server URL. Open https://claude.ai/new#settings/customize-connectors and add a
173
+ custom connector with those two values.
174
+
175
+ Requires: aifabrix login
176
+
177
+ See all channels:
178
+ $ aifabrix channel add -h
179
+ `,
180
+ slack: `
181
+ Examples:
182
+ $ aifabrix channel add slack --name "Elsa"
183
+ $ aifabrix channel add slack --name "Elsa" --command-prefix af
184
+ $ aifabrix channel add slack --name "Elsa" --force --probe
185
+ $ aifabrix channel add slack --name "Elsa" --onboard-users
186
+ $ aifabrix channel add slack --name "Elsa" --no-onboard-users
187
+
188
+ ${SHARED_TARGET_BEHAVIOR}
189
+ - slack may ask **Onboard users?** and match Slack profile email to platform user email.
190
+ Non-interactive: --onboard-users or --no-onboard-users. Default is skip when not asked.
191
+
192
+ Requires: aifabrix login
193
+
194
+ See all channels:
195
+ $ aifabrix channel add -h
196
+ `,
197
+ 'microsoft-copilot': `
198
+ Examples:
199
+ $ aifabrix channel add microsoft-copilot --name "Your Assistant" \\
200
+ --oauth-plugin-vault-reference-id "<Teams-Entra-SSO-auth-config-id>"
201
+ $ aifabrix channel add microsoft-copilot --name "Your Assistant" --force \\
202
+ --oauth-plugin-vault-reference-id "<Teams-Entra-SSO-auth-config-id>"
203
+ $ aifabrix channel add microsoft-copilot --name "Your Assistant" --force --package-version 1.2.0 \\
204
+ --oauth-plugin-vault-reference-id "<Teams-Entra-SSO-auth-config-id>"
205
+
206
+ ${SHARED_TARGET_BEHAVIOR}
207
+ - microsoft-copilot uses Entra SSO (trustedIssuer). Pass --oauth-plugin-vault-reference-id
208
+ only when you already have the Teams Entra SSO auth-config id or toolkit cannot create it.
209
+ --force reuses the existing auth-config id. Teams manifest version auto-bumps minor
210
+ unless --package-version is set.
211
+
212
+ Requires: aifabrix login
213
+
214
+ See all channels:
215
+ $ aifabrix channel add -h
216
+ `,
217
+ 'mcp-client': `
218
+ Examples:
219
+ $ aifabrix channel add mcp-client --target cursor --name "Onni"
220
+ $ aifabrix channel add mcp-client --target vscode --name "Onni"
221
+ $ aifabrix channel add mcp-client --target github-copilot --name "Onni"
222
+
223
+ ${SHARED_TARGET_BEHAVIOR}
224
+ - mcp-client writes the Runtime MCP URL into the editor MCP config. Pass --target (or --profile)
225
+ with cursor, vscode, or github-copilot. Remaining step: Reload the editor.
226
+
227
+ Requires: aifabrix login
228
+
229
+ See all channels:
230
+ $ aifabrix channel add -h
231
+ `,
232
+ 'teams-bot': `
233
+ Examples:
234
+ $ aifabrix channel add teams-bot --name "Elsa" --description "Enterprise AI assistant for employees"
235
+ $ aifabrix channel add teams-bot --name "Elsa" --force
236
+
237
+ ${SHARED_TARGET_BEHAVIOR}
238
+ - teams-bot uses Teams Developer CLI (teams app create --azure) around the existing
239
+ AI Fabrix messages URL. Azure subscription, resource group, and Entra tenant come
240
+ from the controller environment. Remaining Microsoft steps are tenant policy only.
241
+
242
+ Requires: aifabrix login
243
+
244
+ See all channels:
245
+ $ aifabrix channel add -h
246
+ `,
247
+ 'web-embed': `
248
+ Examples:
249
+ $ aifabrix channel add web-embed --name "Onni" --allow-experimental
250
+
251
+ ${SHARED_TARGET_BEHAVIOR}
252
+ - web-embed is experimental. Pass --allow-experimental to install.
253
+
254
+ Requires: aifabrix login
255
+
256
+ See all channels:
257
+ $ aifabrix channel add -h
258
+ `
259
+ };
260
+
261
+ /**
262
+ * Read the named channel target from `channel add` argv (help runs before parse).
263
+ * @param {string[]} [argv]
264
+ * @returns {string|null}
265
+ */
266
+ function resolveChannelAddHelpTarget(argv = process.argv) {
267
+ const start = channelAddArgStart(argv);
268
+ for (let i = start; i < argv.length; i += 1) {
269
+ const arg = argv[i];
270
+ if (arg === '--') {
271
+ break;
272
+ }
273
+ if (arg.startsWith('-')) {
274
+ i += skipOptionValue(arg, argv[i + 1]);
275
+ continue;
276
+ }
277
+ if (isChannelTargetKey(arg)) {
278
+ return arg;
279
+ }
280
+ }
281
+ return null;
282
+ }
283
+
284
+ /**
285
+ * @param {string[]} argv
286
+ * @returns {number}
287
+ */
288
+ function channelAddArgStart(argv) {
289
+ for (let i = 1; i < argv.length; i += 1) {
290
+ if (argv[i] === 'add' && argv[i - 1] === 'channel') {
291
+ return i + 1;
292
+ }
293
+ }
294
+ return argv.length;
295
+ }
296
+
297
+ /**
298
+ * @param {string} arg
299
+ * @param {string|undefined} next
300
+ * @returns {number} extra indexes consumed
301
+ */
302
+ function skipOptionValue(arg, next) {
303
+ const eq = arg.indexOf('=');
304
+ if (eq !== -1) {
305
+ return 0;
306
+ }
307
+ const flag = arg;
308
+ if (VALUE_FLAGS.has(flag) && next && !next.startsWith('-')) {
309
+ return 1;
310
+ }
311
+ return 0;
312
+ }
313
+
314
+ /**
315
+ * @param {import('commander').Option} option
316
+ * @param {string|null} target
317
+ * @returns {boolean}
318
+ */
319
+ function isChannelAddOptionVisible(option, target) {
320
+ if (!target) {
321
+ return true;
322
+ }
323
+ const long = option.long;
324
+ if (!long || SHARED_OPTION_LONG.has(long)) {
325
+ return true;
326
+ }
327
+ const extra = TARGET_OPTION_LONG[target];
328
+ return Boolean(extra && extra.has(long));
329
+ }
330
+
331
+ /**
332
+ * @param {string|null} [target]
333
+ * @returns {string}
334
+ */
335
+ function channelAddHelpAfter(target) {
336
+ if (target && TARGET_HELP_AFTER[target]) {
337
+ return TARGET_HELP_AFTER[target];
338
+ }
339
+ return CHANNEL_ADD_HELP_AFTER;
340
+ }
341
+
342
+ /**
343
+ * @param {import('commander').Command} cmd
344
+ * @returns {import('commander').Command}
345
+ */
346
+ function configureChannelAddHelp(cmd) {
347
+ if (typeof cmd.configureHelp !== 'function') {
348
+ return cmd;
349
+ }
350
+ cmd.configureHelp({
351
+ visibleOptions(command) {
352
+ const listed = Help.prototype.visibleOptions.call(this, command);
353
+ const target = resolveChannelAddHelpTarget();
354
+ return listed.filter((option) => isChannelAddOptionVisible(option, target));
355
+ }
356
+ });
357
+ return cmd;
358
+ }
359
+
360
+ module.exports = {
361
+ CHANNEL_ADD_HELP_AFTER,
362
+ channelAddHelpAfter,
363
+ configureChannelAddHelp,
364
+ isChannelAddOptionVisible,
365
+ resolveChannelAddHelpTarget
366
+ };