@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.
- package/lib/api/datasources-extended.api.js +8 -8
- package/lib/api/keycloak.api.js +92 -0
- package/lib/api/token-providers.api.js +77 -0
- package/lib/api/types/keycloak.types.js +23 -0
- package/lib/api/types/token-providers.types.js +65 -0
- package/lib/app/deploy-config.js +3 -2
- package/lib/app/down.js +16 -1
- package/lib/channels/add-channel.js +134 -57
- package/lib/channels/approval-guides/chatgpt.js +1 -1
- package/lib/channels/approval-guides/index.js +3 -0
- package/lib/channels/approval-guides/microsoft-copilot.js +27 -14
- package/lib/channels/channel-add-ensure.js +128 -0
- package/lib/channels/channel-add-existing.js +72 -0
- package/lib/channels/channel-artifact-generator.js +11 -1
- package/lib/channels/channel-branding.js +94 -0
- package/lib/channels/channel-credential.js +8 -0
- package/lib/channels/channel-discovery.js +330 -0
- package/lib/channels/channel-external-system.js +1 -1
- package/lib/channels/channel-runtime-resolver.js +107 -14
- package/lib/channels/channel-status-display.js +36 -3
- package/lib/channels/microsoft-copilot-channel-add.js +138 -0
- package/lib/channels/microsoft-copilot-entra-sso-form.js +251 -0
- package/lib/channels/microsoft-copilot-entra-sso.js +285 -0
- package/lib/channels/microsoft-copilot-icons.js +74 -0
- package/lib/channels/microsoft-copilot-limits.js +103 -0
- package/lib/channels/microsoft-copilot-package.js +178 -52
- package/lib/channels/microsoft-copilot-validate.js +227 -0
- package/lib/cli/attach-default-help-examples.js +102 -0
- package/lib/cli/index.js +4 -0
- package/lib/cli/infra-guided.js +13 -6
- package/lib/cli/setup-credential-deployment.js +7 -5
- package/lib/cli/setup-infra.js +31 -4
- package/lib/cli/setup-utility-validate.js +1 -0
- package/lib/commands/channel-add-setup.js +28 -9
- package/lib/commands/channel.js +14 -10
- package/lib/commands/credential-push.js +37 -5
- package/lib/commands/integration-definition.js +158 -0
- package/lib/commands/package-score.js +72 -0
- package/lib/commands/repair-auth-apply.js +19 -5
- package/lib/commands/repair-datasource-sync-operations.js +4 -1
- package/lib/commands/role-assistant-test-output.js +200 -0
- package/lib/commands/role-assistant.js +163 -166
- package/lib/datasource/capability/capability-resolve.js +15 -5
- package/lib/datasource/capability/copy-operations.js +14 -4
- package/lib/deployment/deployer-poll-run.js +2 -2
- package/lib/deployment/deployer.js +1 -1
- package/lib/deployment/environment.js +2 -2
- package/lib/external-system/deploy.js +11 -21
- package/lib/infrastructure/index.js +19 -4
- package/lib/integration-definition/apply.js +476 -0
- package/lib/integration-definition/canonical-json.js +51 -0
- package/lib/integration-definition/emit-suite-bid.js +94 -0
- package/lib/integration-definition/enrich-crm-field-mappings.js +240 -0
- package/lib/integration-definition/enrich-openapi-operations.js +433 -0
- package/lib/integration-definition/from-discovery.js +339 -0
- package/lib/integration-definition/hash.js +37 -0
- package/lib/integration-definition/index.js +37 -0
- package/lib/integration-definition/resource-type-catalog.js +59 -0
- package/lib/integration-definition/system-kind-enum.js +40 -0
- package/lib/integration-definition/validate.js +148 -0
- package/lib/lab/package-parity-score.js +417 -0
- package/lib/programmatic/builder-api-request.js +5 -1
- package/lib/programmatic/builder-help-governance.js +3 -2
- package/lib/programmatic/capability-registry.js +20 -0
- package/lib/programmatic/help-content/channel-onboarding.md +35 -0
- package/lib/programmatic/help-content/cip-overview.md +27 -0
- package/lib/programmatic/help-content/connected-system-ui.md +70 -0
- package/lib/programmatic/help-content/dimensions-guide.md +23 -0
- package/lib/programmatic/help-content/enterprise-sync-fabrix.md +123 -0
- package/lib/programmatic/help-content/overview.md +25 -0
- package/lib/programmatic/help-content/subscription-guide.md +27 -0
- package/lib/programmatic/help-content/workflow.md +50 -0
- package/lib/programmatic/openapi-component-schemas.js +7 -1
- package/lib/programmatic/openapi-descriptions.js +46 -0
- package/lib/programmatic/openapi-envelope-examples.js +280 -0
- package/lib/programmatic/openapi-operation-bindings.js +50 -0
- package/lib/programmatic/openapi-request-schemas.js +40 -0
- package/lib/programmatic/openapi-result-schemas-overflow.js +101 -0
- package/lib/programmatic/openapi-result-schemas.js +76 -99
- package/lib/programmatic/openapi-schema-descriptions-core.js +25 -4
- package/lib/programmatic/openapi-schema-descriptions-help.js +1 -1
- package/lib/programmatic/openapi-schema-descriptions-operations.js +43 -0
- package/lib/programmatic/openapi-schema-helpers.js +9 -9
- package/lib/programmatic/openapi-spec.js +11 -1
- package/lib/programmatic/orchestration-openapi-meta.js +10 -0
- package/lib/programmatic/persist-supplied-openapi.js +180 -0
- package/lib/programmatic/route-handler-map.js +35 -1
- package/lib/programmatic/run-channel-package.js +236 -0
- package/lib/programmatic/run-integration-definition.js +77 -0
- package/lib/role-assistant/evidence-sync.js +55 -7
- package/lib/role-assistant/knowledge-sync-logging.js +58 -0
- package/lib/role-assistant/knowledge-sync.js +88 -93
- package/lib/role-assistant/test-cases-bid.js +155 -0
- package/lib/role-assistant/test-cases-evaluate.js +9 -1
- package/lib/role-assistant/test-cases-honesty.js +24 -10
- package/lib/role-assistant/test-cases.js +28 -0
- package/lib/role-assistant/test-runner-attachments.js +118 -0
- package/lib/role-assistant/test-runner-bid-apply.js +201 -0
- package/lib/role-assistant/test-runner-bid-document.js +278 -0
- package/lib/role-assistant/test-runner-start-payload.js +96 -0
- package/lib/role-assistant/test-runner-workhub-answers.js +249 -20
- package/lib/role-assistant/test-runner-workhub-helpers.js +100 -0
- package/lib/role-assistant/test-runner-workhub-soft.js +86 -0
- package/lib/role-assistant/test-runner-workhub.js +152 -107
- package/lib/role-assistant/test-runner.js +5 -63
- package/lib/role-assistant/test-suite.js +112 -0
- package/lib/schema/application-schema.json +56 -6
- package/lib/schema/external-datasource.schema.json +103 -17
- package/lib/schema/external-system.schema.json +54 -3
- package/lib/schema/integration-definition.schema.json +195 -0
- package/lib/utils/authentication-shape.js +6 -0
- package/lib/utils/compose-generator.js +10 -1
- package/lib/utils/compose-traefik-extra-routes.js +107 -0
- package/lib/utils/docker-build.js +2 -2
- package/lib/utils/help-builder.js +3 -1
- package/lib/utils/promote-dev-docker-image.js +102 -18
- package/lib/utils/transient-developer-id.js +28 -0
- package/package.json +14 -16
- package/templates/README.md +12 -1
- package/templates/applications/dataplane/application.yaml +10 -2
- package/templates/applications/dataplane/env.template +7 -6
- package/templates/applications/miso-controller/application.yaml +23 -8
- package/templates/applications/miso-controller/env.template +8 -2
- package/templates/applications/miso-controller/rbac.yaml +1 -0
- package/templates/channels/README.md +11 -1
- package/templates/channels/brand/color-192.png +0 -0
- package/templates/channels/brand/dark/128.png +0 -0
- package/templates/channels/brand/dark/192.png +0 -0
- package/templates/channels/brand/dark/256.png +0 -0
- package/templates/channels/brand/dark/32.png +0 -0
- package/templates/channels/brand/dark/512.png +0 -0
- package/templates/channels/brand/dark/64.png +0 -0
- package/templates/channels/brand/light/128.png +0 -0
- package/templates/channels/brand/light/192.png +0 -0
- package/templates/channels/brand/light/256.png +0 -0
- package/templates/channels/brand/light/32.png +0 -0
- package/templates/channels/brand/light/512.png +0 -0
- package/templates/channels/brand/light/64.png +0 -0
- package/templates/channels/brand/mono-white/128.png +0 -0
- package/templates/channels/brand/mono-white/192.png +0 -0
- package/templates/channels/brand/mono-white/256.png +0 -0
- package/templates/channels/brand/mono-white/32.png +0 -0
- package/templates/channels/brand/mono-white/512.png +0 -0
- package/templates/channels/brand/mono-white/64.png +0 -0
- package/templates/channels/brand/outline-32.png +0 -0
- package/templates/channels/chatgpt/install.template.md.hbs +6 -4
- package/templates/channels/chatgpt/integration/README.md +4 -5
- package/templates/channels/chatgpt/integration/chatgpt-system.json +1 -16
- package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +14 -16
- package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +5 -3
- package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +30 -0
- package/templates/channels/microsoft-copilot/fi-fi.template.json.hbs +7 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +93 -22
- package/templates/channels/microsoft-copilot/integration/README.md +2 -3
- package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +1 -22
- package/templates/channels/microsoft-copilot/manifest.template.json.hbs +34 -19
- package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +15 -0
- package/templates/channels/slack/integration/README.md +2 -4
- package/templates/channels/teams-bot/install.template.md.hbs +4 -0
- package/templates/channels/teams-bot/integration/README.md +3 -5
- package/templates/channels/web-embed/integration/web-embed-system.json +1 -16
- package/templates/python/docker-compose.hbs +36 -0
- package/templates/typescript/docker-compose.hbs +36 -0
- package/.cursor/plans/Done/157.1-security-quality-violations-by-type.csv +0 -374
- package/.cursor/process/README.md +0 -9
- package/.cursor/rules/anchor-docs.mdc +0 -15
- package/.cursor/rules/assistant-driven-integration-build.mdc +0 -40
- package/.cursor/rules/cli-layout.mdc +0 -81
- package/.cursor/rules/cli-product-neutral.mdc +0 -43
- package/.cursor/rules/deploy-rules/docker-image-ip-policy.mdc +0 -49
- package/.cursor/rules/docs-rules.mdc +0 -32
- package/.cursor/rules/plan-rules/application-lifecycle.mdc +0 -30
- package/.cursor/rules/plan-rules/plan-frontmatter.mdc +0 -35
- package/.cursor/rules/plan-rules/plan-lifecycle.mdc +0 -31
- package/.cursor/rules/plan-rules/plan-validation-gate.mdc +0 -34
- package/.cursor/rules/project-rules.mdc +0 -913
- package/.cursor/skills/README.md +0 -15
- package/.dockerignore +0 -52
- package/.eslintignore +0 -22
- package/.markdownlint.json +0 -14
- package/anchor-docs/README.md +0 -10
- package/anchor-docs/_TEMPLATE +0 -24
- package/babel.config.js +0 -6
- package/bin/builder-api-cleanup.js +0 -26
- package/bin/builder-api-nest.js +0 -10
- package/bin/builder-api-spike.js +0 -19
- package/enterprise-knowledge/README.md +0 -50
- package/enterprise-knowledge/enterprise-integration-lifecycle/README.md +0 -22
- package/enterprise-knowledge/enterprise-integration-lifecycle/application.json +0 -15
- package/enterprise-knowledge/enterprise-integration-lifecycle/deploy.js +0 -69
- package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-deploy.json +0 -52
- package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-system.json +0 -29
- package/enterprise-knowledge/enterprise-integration-lifecycle/env.template +0 -2
- package/integration/README.md +0 -81
- package/integration/github/README.md +0 -53
- package/integration/github/application.json +0 -21
- package/integration/github/deploy.js +0 -72
- package/integration/github/env.template +0 -11
- package/integration/github/github-datasource-issue-comments.json +0 -239
- package/integration/github/github-datasource-issues.json +0 -399
- package/integration/github/github-datasource-repository.json +0 -354
- package/integration/github/github-deploy.json +0 -1202
- package/integration/github/github-system.json +0 -82
- package/integration/hubspot-test/README.md +0 -159
- package/integration/hubspot-test/application.json +0 -54
- package/integration/hubspot-test/companies.json +0 -2048
- package/integration/hubspot-test/create-hubspot.js +0 -523
- package/integration/hubspot-test/env.template +0 -4
- package/integration/hubspot-test/hubspot-test-datasource-company.json +0 -138
- package/integration/hubspot-test/hubspot-test-datasource-contact.json +0 -146
- package/integration/hubspot-test/hubspot-test-datasource-deal.json +0 -146
- package/integration/hubspot-test/hubspot-test-datasource-users.json +0 -76
- package/integration/hubspot-test/hubspot-test-deploy.json +0 -2160
- package/integration/hubspot-test/hubspot-test-system.json +0 -74
- package/integration/hubspot-test/rbac.json +0 -166
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +0 -20
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +0 -9
- package/integration/hubspot-test/test-artifacts/wizard-invalid-add-datasource.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-invalid-app-name.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-invalid-credential-create.yaml +0 -7
- package/integration/hubspot-test/test-artifacts/wizard-invalid-credential-select.yaml +0 -7
- package/integration/hubspot-test/test-artifacts/wizard-invalid-known-platform.yaml +0 -4
- package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-app.yaml +0 -4
- package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-source.yaml +0 -2
- package/integration/hubspot-test/test-artifacts/wizard-invalid-mode.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-invalid-openapi-file.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-invalid-openapi-url.yaml +0 -4
- package/integration/hubspot-test/test-artifacts/wizard-invalid-source.yaml +0 -4
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-array-test.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-key-test.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-path-test.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-test.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-rbac-test.yaml +0 -5
- package/integration/hubspot-test/test-artifacts/wizard-valid-for-rbac-yaml-test.yaml +0 -5
- package/integration/hubspot-test/test-dataplane-down-helpers.js +0 -249
- package/integration/hubspot-test/test-dataplane-down-tests.js +0 -386
- package/integration/hubspot-test/test-dataplane-down.js +0 -209
- package/integration/hubspot-test/test.js +0 -1588
- package/integration/hubspot-test/wizard-hubspot-e2e.yaml +0 -16
- package/integration/hubspot-test/wizard-hubspot-platform.yaml +0 -8
- package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +0 -23
- package/integration/roundtrip-test-local/README.md +0 -143
- package/integration/roundtrip-test-local/application.yaml +0 -13
- package/integration/roundtrip-test-local/env.template +0 -15
- package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +0 -14
- package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +0 -61
- package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +0 -25
- package/integration/roundtrip-test-local2/README.md +0 -143
- package/integration/roundtrip-test-local2/application.yaml +0 -13
- package/integration/roundtrip-test-local2/env.template +0 -15
- package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +0 -31
- package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +0 -86
- package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +0 -25
- package/integration/test/wizard.yaml +0 -8
- package/jest.config.coverage.js +0 -37
- package/jest.config.default.js +0 -11
- package/jest.config.integration.fixtures.js +0 -22
- package/jest.config.integration.js +0 -33
- package/jest.config.isolated.js +0 -11
- package/jest.config.manual.js +0 -30
- package/jest.global-live-fabrix-hooks.js +0 -36
- package/jest.isolated-projects.js +0 -260
- package/jest.projects.js +0 -76
- package/packages/builder-api/README.md +0 -120
- package/packages/builder-api/package.json +0 -30
- package/packages/builder-api/src/app.module.ts +0 -7
- package/packages/builder-api/src/auth/auth.module.ts +0 -5
- package/packages/builder-api/src/external-system/external-system.module.ts +0 -5
- package/packages/builder-api/src/main.ts +0 -16
- package/packages/builder-api/tsconfig.json +0 -15
- package/scripts/check-builder-api-architecture-grep.js +0 -79
- package/scripts/check-datasource-test-run-schema-sync.js +0 -34
- package/scripts/ci-fix.sh +0 -19
- package/scripts/ci-simulate.sh +0 -19
- package/scripts/diagnose-cli.js +0 -150
- package/scripts/docker_image_content_gate.js +0 -47
- package/scripts/docker_image_content_gate.sh +0 -5
- package/scripts/export-builder-api-evidence.js +0 -262
- package/scripts/install-local.js +0 -490
- package/scripts/lib/builder-api-docker-staging-copy.js +0 -60
- package/scripts/lib/builder-api-docker-staging-core.js +0 -183
- package/scripts/lib/docker-image-content-gate-core.js +0 -166
- package/scripts/lib/plan-actor.js +0 -109
- package/scripts/lib/plan-config.js +0 -20
- package/scripts/lib/plan-gates.js +0 -154
- package/scripts/lib/plan-meta.js +0 -104
- package/scripts/lib/plan-parse.js +0 -162
- package/scripts/lib/plan-prevalidate-gates.js +0 -337
- package/scripts/lib/plan-run-core.js +0 -125
- package/scripts/lib/plan-run-report.js +0 -119
- package/scripts/plan-approve.js +0 -24
- package/scripts/plan-archive.js +0 -49
- package/scripts/plan-run.js +0 -13
- package/scripts/plan-set-actor.js +0 -21
- package/scripts/plan-validate.js +0 -80
- package/scripts/pnpm/af.mjs +0 -110
- package/scripts/pnpm/check-quiet.mjs +0 -32
- package/scripts/pnpm/dev-install.mjs +0 -29
- package/scripts/pnpm/dev-reload.mjs +0 -18
- package/scripts/pnpm/help.mjs +0 -55
- package/scripts/pnpm/lib/dev-reload-core.mjs +0 -189
- package/scripts/pnpm/lib/dev-reload-log-capture.mjs +0 -67
- package/scripts/pnpm/lib/dev-reload-log-utils.mjs +0 -32
- package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +0 -124
- package/scripts/pnpm/lib/resolve-app-url.mjs +0 -183
- package/scripts/pnpm/lib/spinner.mjs +0 -42
- package/scripts/pnpm-global-remove.js +0 -48
- package/scripts/stage_builder_api_for_docker.js +0 -65
- package/scripts/sync-builder-api-template.js +0 -44
- package/scripts/test-dataplane-bootstrap.js +0 -331
|
@@ -1,33 +1,46 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Microsoft Copilot channel
|
|
2
|
+
* Microsoft Copilot channel install / approval steps.
|
|
3
3
|
*
|
|
4
|
-
* @fileoverview
|
|
4
|
+
* @fileoverview Organisation publish via Developer Portal + Teams admin approval
|
|
5
5
|
* @author AI Fabrix Team
|
|
6
|
-
* @version 1.
|
|
6
|
+
* @version 1.2.0
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
|
-
const
|
|
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:
|
|
28
|
+
portalUrl: DEVELOPER_PORTAL_URL,
|
|
20
29
|
steps: [
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
'
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
'
|
|
27
|
-
|
|
28
|
-
|
|
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 = {
|
|
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, {
|