@aifabrix/builder 2.52.0 → 2.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/lib/api/datasources-extended.api.js +8 -8
  2. package/lib/api/keycloak.api.js +92 -0
  3. package/lib/api/token-providers.api.js +77 -0
  4. package/lib/api/types/keycloak.types.js +23 -0
  5. package/lib/api/types/token-providers.types.js +65 -0
  6. package/lib/app/deploy-config.js +3 -2
  7. package/lib/app/down.js +16 -1
  8. package/lib/channels/add-channel.js +134 -57
  9. package/lib/channels/approval-guides/chatgpt.js +1 -1
  10. package/lib/channels/approval-guides/index.js +3 -0
  11. package/lib/channels/approval-guides/microsoft-copilot.js +27 -14
  12. package/lib/channels/channel-add-ensure.js +128 -0
  13. package/lib/channels/channel-add-existing.js +72 -0
  14. package/lib/channels/channel-artifact-generator.js +11 -1
  15. package/lib/channels/channel-branding.js +94 -0
  16. package/lib/channels/channel-credential.js +8 -0
  17. package/lib/channels/channel-discovery.js +330 -0
  18. package/lib/channels/channel-external-system.js +1 -1
  19. package/lib/channels/channel-runtime-resolver.js +107 -14
  20. package/lib/channels/channel-status-display.js +36 -3
  21. package/lib/channels/microsoft-copilot-channel-add.js +138 -0
  22. package/lib/channels/microsoft-copilot-entra-sso-form.js +251 -0
  23. package/lib/channels/microsoft-copilot-entra-sso.js +285 -0
  24. package/lib/channels/microsoft-copilot-icons.js +74 -0
  25. package/lib/channels/microsoft-copilot-limits.js +103 -0
  26. package/lib/channels/microsoft-copilot-package.js +178 -52
  27. package/lib/channels/microsoft-copilot-validate.js +227 -0
  28. package/lib/cli/attach-default-help-examples.js +102 -0
  29. package/lib/cli/index.js +4 -0
  30. package/lib/cli/infra-guided.js +13 -6
  31. package/lib/cli/setup-credential-deployment.js +7 -5
  32. package/lib/cli/setup-infra.js +31 -4
  33. package/lib/cli/setup-utility-validate.js +1 -0
  34. package/lib/commands/channel-add-setup.js +28 -9
  35. package/lib/commands/channel.js +14 -10
  36. package/lib/commands/credential-push.js +37 -5
  37. package/lib/commands/integration-definition.js +158 -0
  38. package/lib/commands/package-score.js +72 -0
  39. package/lib/commands/repair-auth-apply.js +19 -5
  40. package/lib/commands/repair-datasource-sync-operations.js +4 -1
  41. package/lib/commands/role-assistant-test-output.js +200 -0
  42. package/lib/commands/role-assistant.js +163 -166
  43. package/lib/datasource/capability/capability-resolve.js +15 -5
  44. package/lib/datasource/capability/copy-operations.js +14 -4
  45. package/lib/deployment/deployer-poll-run.js +2 -2
  46. package/lib/deployment/deployer.js +1 -1
  47. package/lib/deployment/environment.js +2 -2
  48. package/lib/external-system/deploy.js +11 -21
  49. package/lib/infrastructure/index.js +19 -4
  50. package/lib/integration-definition/apply.js +476 -0
  51. package/lib/integration-definition/canonical-json.js +51 -0
  52. package/lib/integration-definition/emit-suite-bid.js +94 -0
  53. package/lib/integration-definition/enrich-crm-field-mappings.js +240 -0
  54. package/lib/integration-definition/enrich-openapi-operations.js +433 -0
  55. package/lib/integration-definition/from-discovery.js +339 -0
  56. package/lib/integration-definition/hash.js +37 -0
  57. package/lib/integration-definition/index.js +37 -0
  58. package/lib/integration-definition/resource-type-catalog.js +59 -0
  59. package/lib/integration-definition/system-kind-enum.js +40 -0
  60. package/lib/integration-definition/validate.js +148 -0
  61. package/lib/lab/package-parity-score.js +417 -0
  62. package/lib/programmatic/builder-api-request.js +5 -1
  63. package/lib/programmatic/builder-help-governance.js +3 -2
  64. package/lib/programmatic/capability-registry.js +20 -0
  65. package/lib/programmatic/help-content/channel-onboarding.md +35 -0
  66. package/lib/programmatic/help-content/cip-overview.md +27 -0
  67. package/lib/programmatic/help-content/connected-system-ui.md +70 -0
  68. package/lib/programmatic/help-content/dimensions-guide.md +23 -0
  69. package/lib/programmatic/help-content/enterprise-sync-fabrix.md +123 -0
  70. package/lib/programmatic/help-content/overview.md +25 -0
  71. package/lib/programmatic/help-content/subscription-guide.md +27 -0
  72. package/lib/programmatic/help-content/workflow.md +50 -0
  73. package/lib/programmatic/openapi-component-schemas.js +7 -1
  74. package/lib/programmatic/openapi-descriptions.js +46 -0
  75. package/lib/programmatic/openapi-envelope-examples.js +280 -0
  76. package/lib/programmatic/openapi-operation-bindings.js +50 -0
  77. package/lib/programmatic/openapi-request-schemas.js +40 -0
  78. package/lib/programmatic/openapi-result-schemas-overflow.js +101 -0
  79. package/lib/programmatic/openapi-result-schemas.js +76 -99
  80. package/lib/programmatic/openapi-schema-descriptions-core.js +25 -4
  81. package/lib/programmatic/openapi-schema-descriptions-help.js +1 -1
  82. package/lib/programmatic/openapi-schema-descriptions-operations.js +43 -0
  83. package/lib/programmatic/openapi-schema-helpers.js +9 -9
  84. package/lib/programmatic/openapi-spec.js +11 -1
  85. package/lib/programmatic/orchestration-openapi-meta.js +10 -0
  86. package/lib/programmatic/persist-supplied-openapi.js +180 -0
  87. package/lib/programmatic/route-handler-map.js +35 -1
  88. package/lib/programmatic/run-channel-package.js +236 -0
  89. package/lib/programmatic/run-integration-definition.js +77 -0
  90. package/lib/role-assistant/evidence-sync.js +55 -7
  91. package/lib/role-assistant/knowledge-sync-logging.js +58 -0
  92. package/lib/role-assistant/knowledge-sync.js +88 -93
  93. package/lib/role-assistant/test-cases-bid.js +155 -0
  94. package/lib/role-assistant/test-cases-evaluate.js +9 -1
  95. package/lib/role-assistant/test-cases-honesty.js +24 -10
  96. package/lib/role-assistant/test-cases.js +28 -0
  97. package/lib/role-assistant/test-runner-attachments.js +118 -0
  98. package/lib/role-assistant/test-runner-bid-apply.js +201 -0
  99. package/lib/role-assistant/test-runner-bid-document.js +278 -0
  100. package/lib/role-assistant/test-runner-start-payload.js +96 -0
  101. package/lib/role-assistant/test-runner-workhub-answers.js +249 -20
  102. package/lib/role-assistant/test-runner-workhub-helpers.js +100 -0
  103. package/lib/role-assistant/test-runner-workhub-soft.js +86 -0
  104. package/lib/role-assistant/test-runner-workhub.js +152 -107
  105. package/lib/role-assistant/test-runner.js +5 -63
  106. package/lib/role-assistant/test-suite.js +112 -0
  107. package/lib/schema/application-schema.json +56 -6
  108. package/lib/schema/external-datasource.schema.json +103 -17
  109. package/lib/schema/external-system.schema.json +54 -3
  110. package/lib/schema/integration-definition.schema.json +195 -0
  111. package/lib/utils/authentication-shape.js +6 -0
  112. package/lib/utils/compose-generator.js +10 -1
  113. package/lib/utils/compose-traefik-extra-routes.js +107 -0
  114. package/lib/utils/docker-build.js +2 -2
  115. package/lib/utils/help-builder.js +3 -1
  116. package/lib/utils/promote-dev-docker-image.js +102 -18
  117. package/lib/utils/transient-developer-id.js +28 -0
  118. package/package.json +14 -16
  119. package/templates/README.md +12 -1
  120. package/templates/applications/dataplane/application.yaml +10 -2
  121. package/templates/applications/dataplane/env.template +7 -6
  122. package/templates/applications/miso-controller/application.yaml +23 -8
  123. package/templates/applications/miso-controller/env.template +8 -2
  124. package/templates/applications/miso-controller/rbac.yaml +1 -0
  125. package/templates/channels/README.md +11 -1
  126. package/templates/channels/brand/color-192.png +0 -0
  127. package/templates/channels/brand/dark/128.png +0 -0
  128. package/templates/channels/brand/dark/192.png +0 -0
  129. package/templates/channels/brand/dark/256.png +0 -0
  130. package/templates/channels/brand/dark/32.png +0 -0
  131. package/templates/channels/brand/dark/512.png +0 -0
  132. package/templates/channels/brand/dark/64.png +0 -0
  133. package/templates/channels/brand/light/128.png +0 -0
  134. package/templates/channels/brand/light/192.png +0 -0
  135. package/templates/channels/brand/light/256.png +0 -0
  136. package/templates/channels/brand/light/32.png +0 -0
  137. package/templates/channels/brand/light/512.png +0 -0
  138. package/templates/channels/brand/light/64.png +0 -0
  139. package/templates/channels/brand/mono-white/128.png +0 -0
  140. package/templates/channels/brand/mono-white/192.png +0 -0
  141. package/templates/channels/brand/mono-white/256.png +0 -0
  142. package/templates/channels/brand/mono-white/32.png +0 -0
  143. package/templates/channels/brand/mono-white/512.png +0 -0
  144. package/templates/channels/brand/mono-white/64.png +0 -0
  145. package/templates/channels/brand/outline-32.png +0 -0
  146. package/templates/channels/chatgpt/install.template.md.hbs +6 -4
  147. package/templates/channels/chatgpt/integration/README.md +4 -5
  148. package/templates/channels/chatgpt/integration/chatgpt-system.json +1 -16
  149. package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +14 -16
  150. package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +5 -3
  151. package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +30 -0
  152. package/templates/channels/microsoft-copilot/fi-fi.template.json.hbs +7 -0
  153. package/templates/channels/microsoft-copilot/install.template.md.hbs +93 -22
  154. package/templates/channels/microsoft-copilot/integration/README.md +2 -3
  155. package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +1 -22
  156. package/templates/channels/microsoft-copilot/manifest.template.json.hbs +34 -19
  157. package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +15 -0
  158. package/templates/channels/slack/integration/README.md +2 -4
  159. package/templates/channels/teams-bot/install.template.md.hbs +4 -0
  160. package/templates/channels/teams-bot/integration/README.md +3 -5
  161. package/templates/channels/web-embed/integration/web-embed-system.json +1 -16
  162. package/templates/python/docker-compose.hbs +36 -0
  163. package/templates/typescript/docker-compose.hbs +36 -0
  164. package/.cursor/plans/Done/157.1-security-quality-violations-by-type.csv +0 -374
  165. package/.cursor/process/README.md +0 -9
  166. package/.cursor/rules/anchor-docs.mdc +0 -15
  167. package/.cursor/rules/assistant-driven-integration-build.mdc +0 -40
  168. package/.cursor/rules/cli-layout.mdc +0 -81
  169. package/.cursor/rules/cli-product-neutral.mdc +0 -43
  170. package/.cursor/rules/deploy-rules/docker-image-ip-policy.mdc +0 -49
  171. package/.cursor/rules/docs-rules.mdc +0 -32
  172. package/.cursor/rules/plan-rules/application-lifecycle.mdc +0 -30
  173. package/.cursor/rules/plan-rules/plan-frontmatter.mdc +0 -35
  174. package/.cursor/rules/plan-rules/plan-lifecycle.mdc +0 -31
  175. package/.cursor/rules/plan-rules/plan-validation-gate.mdc +0 -34
  176. package/.cursor/rules/project-rules.mdc +0 -913
  177. package/.cursor/skills/README.md +0 -15
  178. package/.dockerignore +0 -52
  179. package/.eslintignore +0 -22
  180. package/.markdownlint.json +0 -14
  181. package/anchor-docs/README.md +0 -10
  182. package/anchor-docs/_TEMPLATE +0 -24
  183. package/babel.config.js +0 -6
  184. package/bin/builder-api-cleanup.js +0 -26
  185. package/bin/builder-api-nest.js +0 -10
  186. package/bin/builder-api-spike.js +0 -19
  187. package/enterprise-knowledge/README.md +0 -50
  188. package/enterprise-knowledge/enterprise-integration-lifecycle/README.md +0 -22
  189. package/enterprise-knowledge/enterprise-integration-lifecycle/application.json +0 -15
  190. package/enterprise-knowledge/enterprise-integration-lifecycle/deploy.js +0 -69
  191. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-deploy.json +0 -52
  192. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-system.json +0 -29
  193. package/enterprise-knowledge/enterprise-integration-lifecycle/env.template +0 -2
  194. package/integration/README.md +0 -81
  195. package/integration/github/README.md +0 -53
  196. package/integration/github/application.json +0 -21
  197. package/integration/github/deploy.js +0 -72
  198. package/integration/github/env.template +0 -11
  199. package/integration/github/github-datasource-issue-comments.json +0 -239
  200. package/integration/github/github-datasource-issues.json +0 -399
  201. package/integration/github/github-datasource-repository.json +0 -354
  202. package/integration/github/github-deploy.json +0 -1202
  203. package/integration/github/github-system.json +0 -82
  204. package/integration/hubspot-test/README.md +0 -159
  205. package/integration/hubspot-test/application.json +0 -54
  206. package/integration/hubspot-test/companies.json +0 -2048
  207. package/integration/hubspot-test/create-hubspot.js +0 -523
  208. package/integration/hubspot-test/env.template +0 -4
  209. package/integration/hubspot-test/hubspot-test-datasource-company.json +0 -138
  210. package/integration/hubspot-test/hubspot-test-datasource-contact.json +0 -146
  211. package/integration/hubspot-test/hubspot-test-datasource-deal.json +0 -146
  212. package/integration/hubspot-test/hubspot-test-datasource-users.json +0 -76
  213. package/integration/hubspot-test/hubspot-test-deploy.json +0 -2160
  214. package/integration/hubspot-test/hubspot-test-system.json +0 -74
  215. package/integration/hubspot-test/rbac.json +0 -166
  216. package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +0 -20
  217. package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +0 -9
  218. package/integration/hubspot-test/test-artifacts/wizard-invalid-add-datasource.yaml +0 -5
  219. package/integration/hubspot-test/test-artifacts/wizard-invalid-app-name.yaml +0 -5
  220. package/integration/hubspot-test/test-artifacts/wizard-invalid-credential-create.yaml +0 -7
  221. package/integration/hubspot-test/test-artifacts/wizard-invalid-credential-select.yaml +0 -7
  222. package/integration/hubspot-test/test-artifacts/wizard-invalid-known-platform.yaml +0 -4
  223. package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-app.yaml +0 -4
  224. package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-source.yaml +0 -2
  225. package/integration/hubspot-test/test-artifacts/wizard-invalid-mode.yaml +0 -5
  226. package/integration/hubspot-test/test-artifacts/wizard-invalid-openapi-file.yaml +0 -5
  227. package/integration/hubspot-test/test-artifacts/wizard-invalid-openapi-url.yaml +0 -4
  228. package/integration/hubspot-test/test-artifacts/wizard-invalid-source.yaml +0 -4
  229. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-array-test.yaml +0 -5
  230. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-key-test.yaml +0 -5
  231. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-path-test.yaml +0 -5
  232. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-test.yaml +0 -5
  233. package/integration/hubspot-test/test-artifacts/wizard-valid-for-rbac-test.yaml +0 -5
  234. package/integration/hubspot-test/test-artifacts/wizard-valid-for-rbac-yaml-test.yaml +0 -5
  235. package/integration/hubspot-test/test-dataplane-down-helpers.js +0 -249
  236. package/integration/hubspot-test/test-dataplane-down-tests.js +0 -386
  237. package/integration/hubspot-test/test-dataplane-down.js +0 -209
  238. package/integration/hubspot-test/test.js +0 -1588
  239. package/integration/hubspot-test/wizard-hubspot-e2e.yaml +0 -16
  240. package/integration/hubspot-test/wizard-hubspot-platform.yaml +0 -8
  241. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +0 -23
  242. package/integration/roundtrip-test-local/README.md +0 -143
  243. package/integration/roundtrip-test-local/application.yaml +0 -13
  244. package/integration/roundtrip-test-local/env.template +0 -15
  245. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +0 -14
  246. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +0 -61
  247. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +0 -25
  248. package/integration/roundtrip-test-local2/README.md +0 -143
  249. package/integration/roundtrip-test-local2/application.yaml +0 -13
  250. package/integration/roundtrip-test-local2/env.template +0 -15
  251. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +0 -31
  252. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +0 -86
  253. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +0 -25
  254. package/integration/test/wizard.yaml +0 -8
  255. package/jest.config.coverage.js +0 -37
  256. package/jest.config.default.js +0 -11
  257. package/jest.config.integration.fixtures.js +0 -22
  258. package/jest.config.integration.js +0 -33
  259. package/jest.config.isolated.js +0 -11
  260. package/jest.config.manual.js +0 -30
  261. package/jest.global-live-fabrix-hooks.js +0 -36
  262. package/jest.isolated-projects.js +0 -260
  263. package/jest.projects.js +0 -76
  264. package/packages/builder-api/README.md +0 -120
  265. package/packages/builder-api/package.json +0 -30
  266. package/packages/builder-api/src/app.module.ts +0 -7
  267. package/packages/builder-api/src/auth/auth.module.ts +0 -5
  268. package/packages/builder-api/src/external-system/external-system.module.ts +0 -5
  269. package/packages/builder-api/src/main.ts +0 -16
  270. package/packages/builder-api/tsconfig.json +0 -15
  271. package/scripts/check-builder-api-architecture-grep.js +0 -79
  272. package/scripts/check-datasource-test-run-schema-sync.js +0 -34
  273. package/scripts/ci-fix.sh +0 -19
  274. package/scripts/ci-simulate.sh +0 -19
  275. package/scripts/diagnose-cli.js +0 -150
  276. package/scripts/docker_image_content_gate.js +0 -47
  277. package/scripts/docker_image_content_gate.sh +0 -5
  278. package/scripts/export-builder-api-evidence.js +0 -262
  279. package/scripts/install-local.js +0 -490
  280. package/scripts/lib/builder-api-docker-staging-copy.js +0 -60
  281. package/scripts/lib/builder-api-docker-staging-core.js +0 -183
  282. package/scripts/lib/docker-image-content-gate-core.js +0 -166
  283. package/scripts/lib/plan-actor.js +0 -109
  284. package/scripts/lib/plan-config.js +0 -20
  285. package/scripts/lib/plan-gates.js +0 -154
  286. package/scripts/lib/plan-meta.js +0 -104
  287. package/scripts/lib/plan-parse.js +0 -162
  288. package/scripts/lib/plan-prevalidate-gates.js +0 -337
  289. package/scripts/lib/plan-run-core.js +0 -125
  290. package/scripts/lib/plan-run-report.js +0 -119
  291. package/scripts/plan-approve.js +0 -24
  292. package/scripts/plan-archive.js +0 -49
  293. package/scripts/plan-run.js +0 -13
  294. package/scripts/plan-set-actor.js +0 -21
  295. package/scripts/plan-validate.js +0 -80
  296. package/scripts/pnpm/af.mjs +0 -110
  297. package/scripts/pnpm/check-quiet.mjs +0 -32
  298. package/scripts/pnpm/dev-install.mjs +0 -29
  299. package/scripts/pnpm/dev-reload.mjs +0 -18
  300. package/scripts/pnpm/help.mjs +0 -55
  301. package/scripts/pnpm/lib/dev-reload-core.mjs +0 -189
  302. package/scripts/pnpm/lib/dev-reload-log-capture.mjs +0 -67
  303. package/scripts/pnpm/lib/dev-reload-log-utils.mjs +0 -32
  304. package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +0 -124
  305. package/scripts/pnpm/lib/resolve-app-url.mjs +0 -183
  306. package/scripts/pnpm/lib/spinner.mjs +0 -42
  307. package/scripts/pnpm-global-remove.js +0 -48
  308. package/scripts/stage_builder_api_for_docker.js +0 -65
  309. package/scripts/sync-builder-api-template.js +0 -44
  310. package/scripts/test-dataplane-bootstrap.js +0 -331
@@ -1,33 +1,46 @@
1
1
  /**
2
- * Microsoft Copilot channel admin approval steps (plan 152).
2
+ * Microsoft Copilot channel install / approval steps.
3
3
  *
4
- * @fileoverview Copilot Studio / M365 admin connector guide
4
+ * @fileoverview Organisation publish via Developer Portal + Teams admin approval
5
5
  * @author AI Fabrix Team
6
- * @version 1.0.0
6
+ * @version 1.2.0
7
7
  */
8
8
 
9
9
  'use strict';
10
10
 
11
- const { formatCredentialPortalStep } = require('./credential-portal');
11
+ const DEVELOPER_PORTAL_URL = 'https://dev.teams.microsoft.com/';
12
+ const TEAMS_ADMIN_APPS_URL = 'https://admin.teams.microsoft.com/policies/manage-apps';
12
13
 
13
14
  /**
14
15
  * @param {Object} ctx
15
16
  * @returns {{ portalUrl: string, steps: string[] }}
16
17
  */
17
18
  function buildMicrosoftCopilotApprovalGuide(ctx) {
19
+ const env = typeof ctx.environment === 'string' && ctx.environment.trim()
20
+ ? ctx.environment.trim()
21
+ : 'dev';
22
+ const zipName = `appPackage.${env}.zip`;
23
+ const appName =
24
+ (typeof ctx.name === 'string' && ctx.name.trim()) ||
25
+ (typeof ctx.baseName === 'string' && ctx.baseName.trim()) ||
26
+ 'your app';
18
27
  return {
19
- portalUrl: 'https://admin.cloud.microsoft.com/',
28
+ portalUrl: DEVELOPER_PORTAL_URL,
20
29
  steps: [
21
- 'Sign in to Microsoft 365 admin (https://admin.cloud.microsoft.com/) or Copilot Studio as a tenant admin.',
22
- 'Upload or sideload the generated appPackage.<env>.zip package artifact.',
23
- 'Review declarative agent + Remote MCP plugin details and approve tenant distribution.',
24
- 'Configure Entra/OAuth consent and user assignment for target groups.',
25
- formatCredentialPortalStep(ctx, 'Copilot channel credential references (no secrets in package files)'),
26
- 'Verify Runtime MCP endpoint and Layer B tool visibility using INSTALL.md guidance.',
27
- `After Copilot shows the package as available, re-run: ${ctx.resumeCommand}`,
28
- 'Optional: use --probe for AI Fabrix-side checks; tenant upload/approval remains Microsoft-admin responsibility.'
30
+ `Open Teams Developer Portal (${DEVELOPER_PORTAL_URL}).`,
31
+ `Click Import an app → import ${zipName}. Preserve the generated stable manifest.json.id. Do not create an unrelated new Teams app.`,
32
+ 'Developer Portal → selected app → Publish to your org → Distribute / submit.',
33
+ `Teams admin approves in ${TEAMS_ADMIN_APPS_URL} (Manage apps → search → allow). Expect Published / Unblocked per organisation policy. Allow several minutes for propagation.`,
34
+ `Open Teams → Apps (Built for your org), click "${appName}", Add the application, then choose Open with Copilot.`,
35
+ 'In Copilot, click "Show my role assistants" and run the command.',
36
+ 'Confirm Runtime MCP and governed tools using INSTALL.md, then re-run with --probe after organisation publish.',
37
+ `After the app is available under Built for your org, re-run: ${ctx.resumeCommand}`
29
38
  ]
30
39
  };
31
40
  }
32
41
 
33
- module.exports = { buildMicrosoftCopilotApprovalGuide };
42
+ module.exports = {
43
+ buildMicrosoftCopilotApprovalGuide,
44
+ DEVELOPER_PORTAL_URL,
45
+ TEAMS_ADMIN_APPS_URL
46
+ };
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Ensure local scaffold + dataplane upload before channel add install.
3
+ *
4
+ * @fileoverview One-command channel add prelude (scaffold → upload if needed)
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+ const chalk = require('chalk');
14
+ const logger = require('../utils/logger');
15
+ const { formatSuccessLine, metadata } = require('../utils/cli-test-layout-chalk');
16
+ const { getIntegrationPath } = require('../utils/paths');
17
+ const { getExternalSystem } = require('../api/external-systems.api');
18
+ const { unwrapApiData } = require('../utils/external-system-readiness-core');
19
+ const { scaffoldChannelIntegration } = require('./channel-integration-generator');
20
+ const { resolveChannelAuthContext } = require('./channel-auth-context');
21
+ const { uploadExternalSystem } = require('../commands/upload');
22
+
23
+ /**
24
+ * @param {string} channelTarget
25
+ * @param {string} [projectRoot]
26
+ * @returns {string}
27
+ */
28
+ function resolveIntegrationDir(channelTarget, projectRoot) {
29
+ if (projectRoot) {
30
+ return path.join(path.resolve(projectRoot), 'integration', channelTarget);
31
+ }
32
+ return getIntegrationPath(channelTarget);
33
+ }
34
+
35
+ /**
36
+ * @param {Object} ctx
37
+ * @param {string} channelTarget
38
+ * @returns {Promise<boolean>}
39
+ */
40
+ async function isCommunicationSystemUploaded(ctx, channelTarget) {
41
+ const res = await getExternalSystem(ctx.dataplaneUrl, channelTarget, ctx.authConfig);
42
+ const system = unwrapApiData(res);
43
+ return !!(system && typeof system === 'object');
44
+ }
45
+
46
+ /**
47
+ * Scaffold integration/<target>/ when missing (does not overwrite).
48
+ *
49
+ * @param {string} channelTarget
50
+ * @param {Object} options
51
+ * @returns {Promise<{ scaffolded: boolean, integrationDir: string }>}
52
+ */
53
+ async function ensureChannelScaffold(channelTarget, options = {}) {
54
+ const integrationDir = resolveIntegrationDir(channelTarget, options.projectRoot);
55
+ if (fs.existsSync(integrationDir)) {
56
+ return { scaffolded: false, integrationDir };
57
+ }
58
+ const result = await scaffoldChannelIntegration(channelTarget, {
59
+ projectRoot: options.projectRoot,
60
+ allowExperimental: options.allowExperimental === true
61
+ });
62
+ if (options.quiet !== true) {
63
+ logger.log(formatSuccessLine(`Scaffolded integration at ${result.integrationDir}`));
64
+ for (const file of result.files) {
65
+ logger.log(metadata(file));
66
+ }
67
+ }
68
+ return { scaffolded: true, integrationDir: result.integrationDir };
69
+ }
70
+
71
+ /**
72
+ * Upload when missing on dataplane; with --force upload every time.
73
+ *
74
+ * @param {string} channelTarget
75
+ * @param {Object} options
76
+ * @returns {Promise<{ uploaded: boolean, skipped: boolean, ctx: Object|null }>}
77
+ */
78
+ async function ensureChannelUploaded(channelTarget, options = {}) {
79
+ if (options.dryRun === true) {
80
+ return { uploaded: false, skipped: true, ctx: null };
81
+ }
82
+ const ctx = await resolveChannelAuthContext(channelTarget, { silent: options.quiet === true });
83
+ const force = options.force === true;
84
+ const alreadyUploaded = force ? false : await isCommunicationSystemUploaded(ctx, channelTarget);
85
+ if (alreadyUploaded) {
86
+ if (options.quiet !== true) {
87
+ logger.log(chalk.gray(` Communication system "${channelTarget}" already on dataplane`));
88
+ }
89
+ return { uploaded: false, skipped: true, ctx };
90
+ }
91
+ if (options.quiet !== true) {
92
+ const reason = force ? 'force upload' : 'not found on dataplane';
93
+ logger.log(chalk.white(`Uploading ${channelTarget} (${reason})…`));
94
+ }
95
+ await uploadExternalSystem(channelTarget, {
96
+ force: true,
97
+ minimal: options.quiet === true || options.minimal !== false
98
+ });
99
+ if (options.quiet !== true) {
100
+ logger.log(formatSuccessLine(`Uploaded ${channelTarget}`));
101
+ }
102
+ return { uploaded: true, skipped: false, ctx };
103
+ }
104
+
105
+ /**
106
+ * Scaffold if needed, then upload if missing (or always when --force).
107
+ *
108
+ * @param {string} channelTarget
109
+ * @param {Object} options
110
+ * @returns {Promise<{ scaffolded: boolean, uploaded: boolean, integrationDir: string }>}
111
+ */
112
+ async function ensureChannelReadyForAdd(channelTarget, options = {}) {
113
+ const scaffold = await ensureChannelScaffold(channelTarget, options);
114
+ const upload = await ensureChannelUploaded(channelTarget, options);
115
+ return {
116
+ scaffolded: scaffold.scaffolded,
117
+ uploaded: upload.uploaded,
118
+ integrationDir: scaffold.integrationDir
119
+ };
120
+ }
121
+
122
+ module.exports = {
123
+ resolveIntegrationDir,
124
+ isCommunicationSystemUploaded,
125
+ ensureChannelScaffold,
126
+ ensureChannelUploaded,
127
+ ensureChannelReadyForAdd
128
+ };
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Existing-channel skip path for aifabrix channel add.
3
+ *
4
+ * @fileoverview Keep add-channel.js under the 500-line limit
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+ const { getArtifactOutputPath } = require('./channel-artifact-generator');
14
+ const { buildChannelApprovalGuide } = require('./channel-approval-guide');
15
+ const { displayExistingChannelStatus } = require('./channel-status-display');
16
+
17
+ /**
18
+ * True when local channel package files are present under dist/channels/<target>/.
19
+ * @param {string} projectRoot
20
+ * @param {string} channelTarget
21
+ * @returns {boolean}
22
+ */
23
+ function localChannelArtifactsExist(projectRoot, channelTarget) {
24
+ const summaryPath = getArtifactOutputPath(projectRoot, channelTarget);
25
+ const installPath = path.join(path.dirname(summaryPath), 'INSTALL.md');
26
+ return fs.existsSync(summaryPath) && fs.existsSync(installPath);
27
+ }
28
+
29
+ /**
30
+ * @param {Object} params
31
+ * @returns {Object|null}
32
+ */
33
+ function showExistingChannelStatus(params) {
34
+ const { existing, options, channelTarget, name, baseName, ctx } = params;
35
+ if (!existing || options.force || options.dryRun) return null;
36
+ const sameInstall =
37
+ (existing.baseName && existing.baseName === baseName) ||
38
+ (!existing.baseName && existing.name === name);
39
+ if (!sameInstall) {
40
+ throw new Error(
41
+ `Channel already configured as "${existing.name}". ` +
42
+ `Use --force to replace with "${name}".`
43
+ );
44
+ }
45
+ const projectRoot = options.projectRoot || process.cwd();
46
+ // Dataplane may still have the channel while local dist/ was deleted — regenerate.
47
+ if (!localChannelArtifactsExist(projectRoot, channelTarget)) {
48
+ return null;
49
+ }
50
+ const approvalGuide =
51
+ existing.status === 'approvalRequired'
52
+ ? buildChannelApprovalGuide(channelTarget, {
53
+ projectRoot,
54
+ name: existing.name || name,
55
+ baseName,
56
+ dataplaneBaseUrl: ctx?.dataplaneUrl,
57
+ environment: ctx?.environment || 'dev'
58
+ })
59
+ : null;
60
+ displayExistingChannelStatus({
61
+ channelTarget,
62
+ name: existing.name || name,
63
+ channelExt: existing,
64
+ approvalGuide
65
+ });
66
+ return { skipped: true, channelExt: existing };
67
+ }
68
+
69
+ module.exports = {
70
+ localChannelArtifactsExist,
71
+ showExistingChannelStatus
72
+ };
@@ -147,11 +147,21 @@ function generateChannelArtifact(params) {
147
147
  params.dryRun === true
148
148
  );
149
149
 
150
+ const installReady = params.runtimeValues?.installReady === true;
151
+ const blocker = params.runtimeValues?.discoveryBlocker || null;
150
152
  return {
151
153
  outputPath,
152
154
  artifactHash,
153
155
  content,
154
- installPath: install?.installPath
156
+ installPath: install?.installPath,
157
+ zipPath: null,
158
+ links: {
159
+ readme: install?.installPath || null,
160
+ zip: null,
161
+ filesRoot: outputDir
162
+ },
163
+ installReady,
164
+ blocker
155
165
  };
156
166
  }
157
167
 
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Optional channel package branding in Builder workspace (plan 167.0).
3
+ *
4
+ * @fileoverview Read/write channel-branding.json under integration/<systemKey>/
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const fs = require('../internal/fs-real-sync');
12
+ const path = require('path');
13
+
14
+ const BRANDING_FILENAME = 'channel-branding.json';
15
+
16
+ /**
17
+ * @param {string} workspaceSystemDir
18
+ * @returns {string}
19
+ */
20
+ function brandingFilePath(workspaceSystemDir) {
21
+ return path.join(workspaceSystemDir, BRANDING_FILENAME);
22
+ }
23
+
24
+ /**
25
+ * @param {string} workspaceSystemDir
26
+ * @returns {{ displayName?: string, description?: string, iconColorPath?: string, iconOutlinePath?: string }}
27
+ */
28
+ function readChannelBranding(workspaceSystemDir) {
29
+ const filePath = brandingFilePath(workspaceSystemDir);
30
+ if (!fs.existsSync(filePath)) {
31
+ return {};
32
+ }
33
+ const raw = JSON.parse(fs.readFileSync(filePath, 'utf8'));
34
+ if (!raw || typeof raw !== 'object') {
35
+ return {};
36
+ }
37
+ /** @type {{ displayName?: string, description?: string, iconColorPath?: string, iconOutlinePath?: string }} */
38
+ const out = {};
39
+ if (typeof raw.displayName === 'string' && raw.displayName.trim()) {
40
+ out.displayName = raw.displayName.trim();
41
+ }
42
+ if (typeof raw.description === 'string' && raw.description.trim()) {
43
+ out.description = raw.description.trim();
44
+ }
45
+ if (typeof raw.iconColorPath === 'string' && raw.iconColorPath.trim()) {
46
+ out.iconColorPath = raw.iconColorPath.trim();
47
+ }
48
+ if (typeof raw.iconOutlinePath === 'string' && raw.iconOutlinePath.trim()) {
49
+ out.iconOutlinePath = raw.iconOutlinePath.trim();
50
+ }
51
+ return out;
52
+ }
53
+
54
+ /**
55
+ * @param {string} workspaceSystemDir
56
+ * @param {Object} branding
57
+ * @returns {Object}
58
+ */
59
+ function writeChannelBranding(workspaceSystemDir, branding) {
60
+ fs.mkdirSync(workspaceSystemDir, { recursive: true });
61
+ const next = {
62
+ ...readChannelBranding(workspaceSystemDir),
63
+ ...(branding && typeof branding === 'object' ? branding : {})
64
+ };
65
+ const cleaned = {};
66
+ for (const key of ['displayName', 'description', 'iconColorPath', 'iconOutlinePath']) {
67
+ if (typeof next[key] === 'string' && next[key].trim()) {
68
+ cleaned[key] = next[key].trim();
69
+ }
70
+ }
71
+ fs.writeFileSync(brandingFilePath(workspaceSystemDir), `${JSON.stringify(cleaned, null, 2)}\n`, 'utf8');
72
+ return cleaned;
73
+ }
74
+
75
+ /**
76
+ * Merge CLI/API overrides over workspace branding.
77
+ * @param {Object} [workspaceBranding]
78
+ * @param {Object} [overrides]
79
+ * @returns {Object}
80
+ */
81
+ function mergeChannelBranding(workspaceBranding, overrides) {
82
+ return {
83
+ ...(workspaceBranding && typeof workspaceBranding === 'object' ? workspaceBranding : {}),
84
+ ...(overrides && typeof overrides === 'object' ? overrides : {})
85
+ };
86
+ }
87
+
88
+ module.exports = {
89
+ BRANDING_FILENAME,
90
+ brandingFilePath,
91
+ readChannelBranding,
92
+ writeChannelBranding,
93
+ mergeChannelBranding
94
+ };
@@ -18,6 +18,7 @@ const {
18
18
  auditCredentialUpdated,
19
19
  auditFailed
20
20
  } = require('./channel-audit');
21
+ const { skipsChannelOauthCredential } = require('./microsoft-copilot-entra-sso');
21
22
 
22
23
  /** @type {Record<string, { method: string, displayName: string, credentialConfig: Object }>} */
23
24
  const CREDENTIAL_SPECS = {
@@ -171,6 +172,13 @@ async function pushIntegrationSecrets(ctx, channelTarget) {
171
172
  */
172
173
  async function ensureChannelCredential(params) {
173
174
  const { ctx, channelTarget, target, force = false } = params;
175
+ if (skipsChannelOauthCredential(channelTarget)) {
176
+ return {
177
+ skipped: true,
178
+ reason: 'entraSsoTrustedIssuer',
179
+ credentialKey: target.credentialKey
180
+ };
181
+ }
174
182
  const existing = await findCredentialByKey(ctx, target.credentialKey);
175
183
  if (existing) {
176
184
  auditCredentialUpdated(channelTarget, {