@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
|
@@ -69,28 +69,28 @@ async function detachPolicy(dataplaneUrl, sourceIdOrKey, policyIdOrKey, authConf
|
|
|
69
69
|
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
70
70
|
return await client.delete(`/api/v1/external/${sourceIdOrKey}/policies/${policyIdOrKey}`);
|
|
71
71
|
}
|
|
72
|
-
/** @requiresPermission {Dataplane} external-
|
|
72
|
+
/** @requiresPermission {Dataplane} external-data-source:read (sync under /data-storage) */
|
|
73
73
|
async function listSyncJobs(dataplaneUrl, sourceIdOrKey, authConfig, options = {}) {
|
|
74
74
|
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
75
|
-
return await client.get(`/api/v1/
|
|
75
|
+
return await client.get(`/api/v1/data-storage/${sourceIdOrKey}/sync`, { params: options });
|
|
76
76
|
}
|
|
77
77
|
async function createSyncJob(dataplaneUrl, sourceIdOrKey, authConfig, syncData) {
|
|
78
78
|
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
79
|
-
return await client.post(`/api/v1/
|
|
79
|
+
return await client.post(`/api/v1/data-storage/${sourceIdOrKey}/sync`, { body: syncData });
|
|
80
80
|
}
|
|
81
|
-
/** @requiresPermission {Dataplane} external-
|
|
81
|
+
/** @requiresPermission {Dataplane} external-data-source:read */
|
|
82
82
|
async function getSyncJob(dataplaneUrl, sourceIdOrKey, syncJobId, authConfig) {
|
|
83
83
|
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
84
|
-
return await client.get(`/api/v1/
|
|
84
|
+
return await client.get(`/api/v1/data-storage/${sourceIdOrKey}/sync/${syncJobId}`);
|
|
85
85
|
}
|
|
86
|
-
/** @requiresPermission {Dataplane} external-
|
|
86
|
+
/** @requiresPermission {Dataplane} external-data-source:sync */
|
|
87
87
|
async function updateSyncJob(dataplaneUrl, sourceIdOrKey, syncJobId, authConfig, updateData) {
|
|
88
88
|
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
89
|
-
return await client.put(`/api/v1/
|
|
89
|
+
return await client.put(`/api/v1/data-storage/${sourceIdOrKey}/sync/${syncJobId}`, { body: updateData });
|
|
90
90
|
}
|
|
91
91
|
async function executeSyncJob(dataplaneUrl, sourceIdOrKey, syncJobId, authConfig) {
|
|
92
92
|
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
93
|
-
return await client.post(`/api/v1/
|
|
93
|
+
return await client.post(`/api/v1/data-storage/${sourceIdOrKey}/sync/${syncJobId}/execute`);
|
|
94
94
|
}
|
|
95
95
|
/** @requiresPermission {Dataplane} external-data-source:sync */
|
|
96
96
|
async function validateDocuments(dataplaneUrl, sourceIdOrKey, authConfig, validateData) {
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Keycloak status API (Controller) — Entra IdP ids for packaging
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { ApiClient } = require('./index');
|
|
10
|
+
|
|
11
|
+
const KEYCLOAK_STATUS_PATH = '/api/v1/keycloak/status';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {Object} response
|
|
15
|
+
* @returns {import('./types/keycloak.types').KeycloakStatus|null}
|
|
16
|
+
*/
|
|
17
|
+
function extractKeycloakStatus(response) {
|
|
18
|
+
if (!response || typeof response !== 'object' || response.success === false) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const body = response.data ?? response;
|
|
22
|
+
const data = body?.data !== undefined ? body.data : body;
|
|
23
|
+
if (!data || typeof data !== 'object' || Array.isArray(data)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {unknown} value
|
|
31
|
+
* @returns {string|null}
|
|
32
|
+
*/
|
|
33
|
+
function trimNonEmptyString(value) {
|
|
34
|
+
if (typeof value !== 'string') {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const trimmed = value.trim();
|
|
38
|
+
return trimmed || null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {import('./types/keycloak.types').KeycloakStatus|null} status
|
|
43
|
+
* @returns {import('./types/keycloak.types').KeycloakEntraIdentityProvider|null}
|
|
44
|
+
*/
|
|
45
|
+
function extractEntraIdentityProvider(status) {
|
|
46
|
+
const raw = status?.entraIdentityProvider;
|
|
47
|
+
if (!raw || typeof raw !== 'object') {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const enterpriseAppId = trimNonEmptyString(raw.enterpriseAppId);
|
|
51
|
+
if (!enterpriseAppId) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const tenantId = trimNonEmptyString(raw.tenantId);
|
|
55
|
+
return tenantId ? { enterpriseAppId, tenantId } : { enterpriseAppId };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* GET /api/v1/keycloak/status
|
|
60
|
+
* @requiresPermission {Controller} admin:keycloak
|
|
61
|
+
* @async
|
|
62
|
+
* @param {string} controllerUrl - Miso Controller base URL
|
|
63
|
+
* @param {Object} authConfig - Authentication configuration (device Bearer)
|
|
64
|
+
* @returns {Promise<import('./types/keycloak.types').KeycloakStatus|null>}
|
|
65
|
+
*/
|
|
66
|
+
async function getKeycloakStatus(controllerUrl, authConfig) {
|
|
67
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
68
|
+
const response = await client.get(KEYCLOAK_STATUS_PATH);
|
|
69
|
+
return extractKeycloakStatus(response);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Resolve Entra SSO enterprise app id from Keycloak status, or null when missing.
|
|
74
|
+
* Does not invent ids.
|
|
75
|
+
* @requiresPermission {Controller} admin:keycloak
|
|
76
|
+
* @async
|
|
77
|
+
* @param {string} controllerUrl - Miso Controller base URL
|
|
78
|
+
* @param {Object} authConfig - Authentication configuration
|
|
79
|
+
* @returns {Promise<import('./types/keycloak.types').KeycloakEntraIdentityProvider|null>}
|
|
80
|
+
*/
|
|
81
|
+
async function getKeycloakEntraIdentityProvider(controllerUrl, authConfig) {
|
|
82
|
+
const status = await getKeycloakStatus(controllerUrl, authConfig);
|
|
83
|
+
return extractEntraIdentityProvider(status);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
module.exports = {
|
|
87
|
+
KEYCLOAK_STATUS_PATH,
|
|
88
|
+
getKeycloakStatus,
|
|
89
|
+
getKeycloakEntraIdentityProvider,
|
|
90
|
+
extractKeycloakStatus,
|
|
91
|
+
extractEntraIdentityProvider
|
|
92
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Admin token providers API (Controller Trust sources)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { ApiClient } = require('./index');
|
|
10
|
+
|
|
11
|
+
const ADMIN_BASE = '/api/v1/admin/token-providers';
|
|
12
|
+
const MICROSOFT_ENTRA_ID_KEY = 'microsoft-entra-id';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {Object} response
|
|
16
|
+
* @returns {import('./types/token-providers.types').TokenProvider[]}
|
|
17
|
+
*/
|
|
18
|
+
function extractTokenProviders(response) {
|
|
19
|
+
const body = response?.data ?? response;
|
|
20
|
+
const data = body?.data ?? body;
|
|
21
|
+
if (Array.isArray(data)) {
|
|
22
|
+
return data;
|
|
23
|
+
}
|
|
24
|
+
if (Array.isArray(data?.items)) {
|
|
25
|
+
return data.items;
|
|
26
|
+
}
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* List admin token providers (paginated).
|
|
32
|
+
* GET /api/v1/admin/token-providers
|
|
33
|
+
* @requiresPermission {Controller} token-provider:read
|
|
34
|
+
* @async
|
|
35
|
+
* @param {string} controllerUrl - Miso Controller base URL
|
|
36
|
+
* @param {Object} authConfig - Authentication configuration (device Bearer)
|
|
37
|
+
* @param {import('./types/token-providers.types').ListAdminTokenProvidersOptions} options
|
|
38
|
+
* @returns {Promise<Object>} Controller list response
|
|
39
|
+
* @throws {Error} If direction is missing or request fails
|
|
40
|
+
*/
|
|
41
|
+
async function listAdminTokenProviders(controllerUrl, authConfig, options = {}) {
|
|
42
|
+
const direction = options?.direction;
|
|
43
|
+
if (direction !== 'inbound' && direction !== 'outbound') {
|
|
44
|
+
throw new Error('direction is required and must be "inbound" or "outbound"');
|
|
45
|
+
}
|
|
46
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
47
|
+
const params = { ...options, direction };
|
|
48
|
+
return await client.get(ADMIN_BASE, { params });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Resolve inbound Microsoft Entra ID Trust source, or null when missing.
|
|
53
|
+
* Does not invent issuer, audience, or scopes.
|
|
54
|
+
* @requiresPermission {Controller} token-provider:read
|
|
55
|
+
* @async
|
|
56
|
+
* @param {string} controllerUrl - Miso Controller base URL
|
|
57
|
+
* @param {Object} authConfig - Authentication configuration
|
|
58
|
+
* @returns {Promise<import('./types/token-providers.types').TokenProvider|null>}
|
|
59
|
+
*/
|
|
60
|
+
async function getInboundMicrosoftEntraIdProvider(controllerUrl, authConfig) {
|
|
61
|
+
const response = await listAdminTokenProviders(controllerUrl, authConfig, {
|
|
62
|
+
direction: 'inbound',
|
|
63
|
+
search: MICROSOFT_ENTRA_ID_KEY,
|
|
64
|
+
page: 1,
|
|
65
|
+
pageSize: 50
|
|
66
|
+
});
|
|
67
|
+
const items = extractTokenProviders(response);
|
|
68
|
+
const exact = items.find((item) => item && item.key === MICROSOFT_ENTRA_ID_KEY);
|
|
69
|
+
return exact || null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = {
|
|
73
|
+
listAdminTokenProviders,
|
|
74
|
+
getInboundMicrosoftEntraIdProvider,
|
|
75
|
+
extractTokenProviders,
|
|
76
|
+
MICROSOFT_ENTRA_ID_KEY
|
|
77
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Keycloak status API type definitions (Controller)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Entra identity provider fragment from Keycloak status.
|
|
9
|
+
* @typedef {Object} KeycloakEntraIdentityProvider
|
|
10
|
+
* @property {string} enterpriseAppId - Entra SSO application (client) id
|
|
11
|
+
* @property {string} [tenantId] - Entra tenant id when known
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Keycloak configuration status payload (`data` of GET /api/v1/keycloak/status).
|
|
16
|
+
* @typedef {Object} KeycloakStatus
|
|
17
|
+
* @property {string} [realm]
|
|
18
|
+
* @property {string} [status]
|
|
19
|
+
* @property {string} [controllerClientId]
|
|
20
|
+
* @property {KeycloakEntraIdentityProvider} [entraIdentityProvider]
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
module.exports = {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Token provider API type definitions (Controller admin Trust sources)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Token provider direction
|
|
9
|
+
* @typedef {'inbound'|'outbound'} TokenProviderDirection
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Token provider subject type
|
|
14
|
+
* @typedef {'user'|'service'|'both'} TokenProviderSubjectType
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Allowed operation on a token provider
|
|
19
|
+
* @typedef {'mcp.invoke'|'dataplane.read'|'dataplane.write'} TokenProviderAllowedOperation
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Admin token provider list item (Controller TokenProvider schema)
|
|
24
|
+
* @typedef {Object} TokenProvider
|
|
25
|
+
* @property {string} id - Unique identifier (cuid)
|
|
26
|
+
* @property {string} key - Unique slug (e.g. microsoft-entra-id)
|
|
27
|
+
* @property {string} displayName - Human-readable name
|
|
28
|
+
* @property {string} issuer - JWT issuer URL (iss claim)
|
|
29
|
+
* @property {string} jwksUri - JWKS endpoint for key verification
|
|
30
|
+
* @property {string|null} [audience] - Expected audience claim (may be null)
|
|
31
|
+
* @property {TokenProviderSubjectType} subjectType - Subject type
|
|
32
|
+
* @property {TokenProviderDirection} direction - inbound or outbound
|
|
33
|
+
* @property {string|null} [identityClaim] - Claim used for user identity
|
|
34
|
+
* @property {string|null} [emailClaim] - Claim used for email
|
|
35
|
+
* @property {boolean} [autoProvision] - Whether to auto-create users
|
|
36
|
+
* @property {string|null} [serviceUserKey] - Service user key for service flow
|
|
37
|
+
* @property {TokenProviderAllowedOperation[]} [allowedOperations] - Allowed operations
|
|
38
|
+
* @property {string[]} [allowedScopes] - OAuth scopes (may be empty)
|
|
39
|
+
* @property {boolean} enabled - Whether this provider is enabled
|
|
40
|
+
* @property {string} [createdAt] - Created at
|
|
41
|
+
* @property {string} [updatedAt] - Updated at
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* List admin token providers query options
|
|
46
|
+
* @typedef {Object} ListAdminTokenProvidersOptions
|
|
47
|
+
* @property {TokenProviderDirection} direction - Required by OpenAPI
|
|
48
|
+
* @property {string} [search] - Search across key, displayName, issuer
|
|
49
|
+
* @property {number} [page] - Page number
|
|
50
|
+
* @property {number} [pageSize] - Page size
|
|
51
|
+
* @property {string} [sort] - Sort expression
|
|
52
|
+
* @property {string} [filter] - Filter expression
|
|
53
|
+
* @property {string} [enabled] - 'true' | 'false'
|
|
54
|
+
* @property {TokenProviderSubjectType} [subjectType] - Subject type filter
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Paginated list response for admin token providers
|
|
59
|
+
* @typedef {Object} ListAdminTokenProvidersResponse
|
|
60
|
+
* @property {TokenProvider[]} data - Provider rows
|
|
61
|
+
* @property {Object} meta - Pagination meta
|
|
62
|
+
* @property {Object} [links] - Pagination links
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
module.exports = {};
|
package/lib/app/deploy-config.js
CHANGED
|
@@ -78,9 +78,10 @@ async function extractDeploymentConfig(options, _variables) {
|
|
|
78
78
|
// Used by guided installers which already show a top-level spinner.
|
|
79
79
|
silentPoll: options.silentPoll === true,
|
|
80
80
|
repositoryUrl: options.repositoryUrl,
|
|
81
|
-
// Omit default here so deployer can resolve
|
|
81
|
+
// Omit default here so deployer can resolve 1s vs 5s from controller deploymentType (GET /api/v1/health)
|
|
82
82
|
pollInterval: Number.isFinite(pollIntervalExplicit) ? pollIntervalExplicit : undefined,
|
|
83
|
-
|
|
83
|
+
// Default 300 attempts: ~5 min at 1s (local) / ~25 min at 5s (azure) — deploy may run tests/gates
|
|
84
|
+
pollMaxAttempts: options.pollMaxAttempts || 300,
|
|
84
85
|
deploymentAuth: options.deploymentAuth
|
|
85
86
|
};
|
|
86
87
|
}
|
package/lib/app/down.js
CHANGED
|
@@ -111,6 +111,20 @@ async function stopAppContainers(appName, companionKeys, developerId) {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Resolve developer id for downApp (optional override does not change config).
|
|
116
|
+
* @param {Object} options
|
|
117
|
+
* @returns {Promise<string>}
|
|
118
|
+
*/
|
|
119
|
+
async function resolveDownAppDeveloperId(options) {
|
|
120
|
+
const override = options && options.developerId;
|
|
121
|
+
if (override === undefined || override === null || override === '') {
|
|
122
|
+
return config.getDeveloperId();
|
|
123
|
+
}
|
|
124
|
+
const { validateAndNormalizeDeveloperId } = require('../core/config-normalize');
|
|
125
|
+
return validateAndNormalizeDeveloperId(override);
|
|
126
|
+
}
|
|
127
|
+
|
|
114
128
|
/**
|
|
115
129
|
* Stops and removes a specific application's container.
|
|
116
130
|
* If --volumes is passed, attempts to remove the app's named Docker volume.
|
|
@@ -122,6 +136,7 @@ async function stopAppContainers(appName, companionKeys, developerId) {
|
|
|
122
136
|
* @param {string} appName - Application name
|
|
123
137
|
* @param {Object} options - Options
|
|
124
138
|
* @param {boolean} [options.volumes=false] - Remove Docker volume data
|
|
139
|
+
* @param {string|number} [options.developerId] - Target developer for this stop only
|
|
125
140
|
* @returns {Promise<void>} Resolves when operation completes
|
|
126
141
|
* @throws {Error} If validation fails or Docker operations error (other than missing volume)
|
|
127
142
|
*
|
|
@@ -136,7 +151,7 @@ async function downApp(appName, options = {}) {
|
|
|
136
151
|
validateAppName(appName);
|
|
137
152
|
|
|
138
153
|
const volumes = !!options.volumes;
|
|
139
|
-
const developerId = await
|
|
154
|
+
const developerId = await resolveDownAppDeveloperId(options);
|
|
140
155
|
const appConfig = loadBuilderApplicationConfig(appName);
|
|
141
156
|
const companionKeys = getCeleryCompanionAppKeys(appName, appConfig);
|
|
142
157
|
|
|
@@ -8,11 +8,17 @@
|
|
|
8
8
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
|
+
const path = require('path');
|
|
11
12
|
const { getChannelTarget, getDefaultChannelDescription } = require('./channel-targets');
|
|
12
13
|
const { resolveAppDescription } = require('./channel-description');
|
|
13
14
|
const { resolveChannelRuntimeValues } = require('./channel-runtime-resolver');
|
|
14
15
|
const { generateChannelArtifact } = require('./channel-artifact-generator');
|
|
15
16
|
const { fetchRuntimeLayerBToolNames } = require('./runtime-tool-catalog');
|
|
17
|
+
const { loadChannelPackageContext } = require('./channel-discovery');
|
|
18
|
+
const {
|
|
19
|
+
readChannelBranding,
|
|
20
|
+
mergeChannelBranding
|
|
21
|
+
} = require('./channel-branding');
|
|
16
22
|
const {
|
|
17
23
|
getExistingChannelExtension,
|
|
18
24
|
buildChannelExtensionBlock,
|
|
@@ -37,11 +43,14 @@ const {
|
|
|
37
43
|
normalizeBaseChannelName,
|
|
38
44
|
resolveChannelDisplayName
|
|
39
45
|
} = require('./channel-display-name');
|
|
46
|
+
const { displayChannelInstallResult } = require('./channel-status-display');
|
|
47
|
+
const { ensureChannelReadyForAdd } = require('./channel-add-ensure');
|
|
48
|
+
const { showExistingChannelStatus } = require('./channel-add-existing');
|
|
40
49
|
const {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
} = require('./channel-
|
|
50
|
+
assertMicrosoftCopilotOauthReference,
|
|
51
|
+
assertMicrosoftCopilotOauthReferenceBeforeForce,
|
|
52
|
+
loadMicrosoftCopilotEntraContext
|
|
53
|
+
} = require('./microsoft-copilot-channel-add');
|
|
45
54
|
|
|
46
55
|
/**
|
|
47
56
|
* @param {typeof import('./channel-targets').CHANNEL_TARGETS[string]} target
|
|
@@ -73,41 +82,6 @@ function toValidationDisplay(validation) {
|
|
|
73
82
|
};
|
|
74
83
|
}
|
|
75
84
|
|
|
76
|
-
/**
|
|
77
|
-
* @param {Object} params
|
|
78
|
-
* @returns {Object|null}
|
|
79
|
-
*/
|
|
80
|
-
function showExistingChannelStatus(params) {
|
|
81
|
-
const { existing, options, channelTarget, name, baseName, ctx } = params;
|
|
82
|
-
if (!existing || options.force || options.dryRun) return null;
|
|
83
|
-
const sameInstall =
|
|
84
|
-
(existing.baseName && existing.baseName === baseName) ||
|
|
85
|
-
(!existing.baseName && existing.name === name);
|
|
86
|
-
if (!sameInstall) {
|
|
87
|
-
throw new Error(
|
|
88
|
-
`Channel already configured as "${existing.name}". ` +
|
|
89
|
-
`Use --force to replace with "${name}".`
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
const projectRoot = options.projectRoot || process.cwd();
|
|
93
|
-
const approvalGuide =
|
|
94
|
-
existing.status === 'approvalRequired'
|
|
95
|
-
? buildChannelApprovalGuide(channelTarget, {
|
|
96
|
-
projectRoot,
|
|
97
|
-
name: existing.name || name,
|
|
98
|
-
baseName,
|
|
99
|
-
dataplaneBaseUrl: ctx?.dataplaneUrl
|
|
100
|
-
})
|
|
101
|
-
: null;
|
|
102
|
-
displayExistingChannelStatus({
|
|
103
|
-
channelTarget,
|
|
104
|
-
name: existing.name || name,
|
|
105
|
-
channelExt: existing,
|
|
106
|
-
approvalGuide
|
|
107
|
-
});
|
|
108
|
-
return { skipped: true, channelExt: existing };
|
|
109
|
-
}
|
|
110
|
-
|
|
111
85
|
/**
|
|
112
86
|
* @param {string} channelTarget
|
|
113
87
|
* @param {Object} artifactParams
|
|
@@ -234,7 +208,8 @@ async function completeLiveInstall(params) {
|
|
|
234
208
|
name,
|
|
235
209
|
baseName,
|
|
236
210
|
artifactPath: artifact.outputPath,
|
|
237
|
-
dataplaneBaseUrl: ctx.dataplaneUrl
|
|
211
|
+
dataplaneBaseUrl: ctx.dataplaneUrl,
|
|
212
|
+
environment: ctx.environment || options.environment || 'dev'
|
|
238
213
|
})
|
|
239
214
|
: null;
|
|
240
215
|
if (approvalGuide?.portalUrl) {
|
|
@@ -252,6 +227,15 @@ async function completeLiveInstall(params) {
|
|
|
252
227
|
capabilities: target.capabilities,
|
|
253
228
|
artifactPath: artifact.outputPath,
|
|
254
229
|
installGuidePath: artifact.installPath,
|
|
230
|
+
zipPath: artifact.zipPath,
|
|
231
|
+
installReady: artifact.installReady,
|
|
232
|
+
blocker: artifact.blocker,
|
|
233
|
+
packageReady: artifact.packageReady,
|
|
234
|
+
packageBlocker: artifact.packageBlocker,
|
|
235
|
+
microsoftPublicationPending:
|
|
236
|
+
artifact.microsoftPublicationPending !== undefined
|
|
237
|
+
? artifact.microsoftPublicationPending
|
|
238
|
+
: status === 'approvalRequired',
|
|
255
239
|
validation: toValidationDisplay(validation),
|
|
256
240
|
approvalGuide
|
|
257
241
|
});
|
|
@@ -272,7 +256,10 @@ function finishDryRunInstall(params) {
|
|
|
272
256
|
credentialKey: params.target.credentialKey,
|
|
273
257
|
capabilities: params.target.capabilities,
|
|
274
258
|
artifactPath: params.artifact.outputPath,
|
|
275
|
-
installGuidePath: params.artifact.installPath
|
|
259
|
+
installGuidePath: params.artifact.installPath,
|
|
260
|
+
zipPath: params.artifact.zipPath,
|
|
261
|
+
installReady: params.artifact.installReady,
|
|
262
|
+
blocker: params.artifact.blocker
|
|
276
263
|
});
|
|
277
264
|
return { dryRun: true, channelBlock: params.channelBlock, artifact: params.artifact };
|
|
278
265
|
}
|
|
@@ -281,12 +268,78 @@ function finishDryRunInstall(params) {
|
|
|
281
268
|
* @param {Object} params
|
|
282
269
|
* @returns {Promise<{ artifact: Object, channelBlock: Object, status: string }>}
|
|
283
270
|
*/
|
|
271
|
+
/**
|
|
272
|
+
* @param {Object|null} packageContext
|
|
273
|
+
* @param {Object} options
|
|
274
|
+
* @param {'iconColorPath'|'iconOutlinePath'} key
|
|
275
|
+
* @returns {string|undefined}
|
|
276
|
+
*/
|
|
277
|
+
function brandingIconOrOption(packageContext, options, key) {
|
|
278
|
+
if (typeof options[key] === 'string' && options[key].trim()) {
|
|
279
|
+
return options[key].trim();
|
|
280
|
+
}
|
|
281
|
+
if (packageContext && typeof packageContext[key] === 'string' && packageContext[key].trim()) {
|
|
282
|
+
return packageContext[key].trim();
|
|
283
|
+
}
|
|
284
|
+
return undefined;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
async function resolvePackageContextForInstall(params) {
|
|
288
|
+
const { channelTarget, options, name, description, ctx } = params;
|
|
289
|
+
const packagingTargets = new Set(['chatgpt', 'microsoft-copilot', 'slack', 'teams-bot']);
|
|
290
|
+
if (!packagingTargets.has(channelTarget)) {
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
const projectRoot = options.projectRoot || process.cwd();
|
|
294
|
+
const workspaceDir = path.join(projectRoot, 'integration', channelTarget);
|
|
295
|
+
const branding = mergeChannelBranding(readChannelBranding(workspaceDir), {
|
|
296
|
+
displayName: options.overrideDisplayName || undefined,
|
|
297
|
+
description: options.overrideDescription || undefined,
|
|
298
|
+
iconColorPath: options.iconColorPath || undefined,
|
|
299
|
+
iconOutlinePath: options.iconOutlinePath || undefined
|
|
300
|
+
});
|
|
301
|
+
let packageContext;
|
|
302
|
+
try {
|
|
303
|
+
packageContext = await loadChannelPackageContext({
|
|
304
|
+
dataplaneBaseUrl: ctx.dataplaneUrl,
|
|
305
|
+
authConfig: ctx.authConfig,
|
|
306
|
+
channelTarget,
|
|
307
|
+
branding
|
|
308
|
+
});
|
|
309
|
+
} catch {
|
|
310
|
+
packageContext = {
|
|
311
|
+
displayName: name,
|
|
312
|
+
description,
|
|
313
|
+
governedToolNames: [],
|
|
314
|
+
mcpServerUrl: null,
|
|
315
|
+
installReady: false,
|
|
316
|
+
blocker: 'discoveryUnavailable',
|
|
317
|
+
authentication: null,
|
|
318
|
+
authenticationCapabilities: []
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
return {
|
|
322
|
+
...packageContext,
|
|
323
|
+
iconColorPath: branding.iconColorPath,
|
|
324
|
+
iconOutlinePath: branding.iconOutlinePath
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
284
328
|
async function buildInstallArtifacts(params) {
|
|
285
329
|
const { channelTarget, options, target, existing, name, baseName, description, ctx } = params;
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
330
|
+
const packageContext = await resolvePackageContextForInstall(params);
|
|
331
|
+
let runtimeToolNames = [];
|
|
332
|
+
if (channelTarget === 'chatgpt' || channelTarget === 'microsoft-copilot') {
|
|
333
|
+
runtimeToolNames =
|
|
334
|
+
packageContext?.governedToolNames?.length > 0
|
|
335
|
+
? packageContext.governedToolNames
|
|
336
|
+
: await fetchRuntimeLayerBToolNames(ctx.dataplaneUrl, ctx.authConfig, channelTarget);
|
|
337
|
+
}
|
|
338
|
+
let entraProvider = null;
|
|
339
|
+
let entraIdentityProvider = null;
|
|
340
|
+
if (channelTarget === 'microsoft-copilot') {
|
|
341
|
+
({ entraProvider, entraIdentityProvider } = await loadMicrosoftCopilotEntraContext(ctx));
|
|
342
|
+
}
|
|
290
343
|
const runtimeValues = resolveChannelRuntimeValues({
|
|
291
344
|
dataplaneBaseUrl: ctx.dataplaneUrl,
|
|
292
345
|
channelTarget,
|
|
@@ -296,7 +349,14 @@ async function buildInstallArtifacts(params) {
|
|
|
296
349
|
appDescription: description,
|
|
297
350
|
icon: options.icon,
|
|
298
351
|
commandPrefix: options.commandPrefix,
|
|
299
|
-
layerBToolNames: runtimeToolNames
|
|
352
|
+
layerBToolNames: runtimeToolNames,
|
|
353
|
+
packageContext,
|
|
354
|
+
entraProvider,
|
|
355
|
+
entraIdentityProvider,
|
|
356
|
+
oauthPluginVaultReferenceId: options.oauthPluginVaultReferenceId,
|
|
357
|
+
scopes: options.scopes,
|
|
358
|
+
iconColorPath: brandingIconOrOption(packageContext, options, 'iconColorPath'),
|
|
359
|
+
iconOutlinePath: brandingIconOrOption(packageContext, options, 'iconOutlinePath')
|
|
300
360
|
});
|
|
301
361
|
const projectRoot = options.projectRoot || process.cwd();
|
|
302
362
|
const artifact = generateArtifactWithAudit(channelTarget, {
|
|
@@ -313,17 +373,39 @@ async function buildInstallArtifacts(params) {
|
|
|
313
373
|
return { artifact, channelBlock, status };
|
|
314
374
|
}
|
|
315
375
|
|
|
376
|
+
/**
|
|
377
|
+
* @param {string} channelTarget
|
|
378
|
+
* @param {Object} options
|
|
379
|
+
* @returns {Object}
|
|
380
|
+
*/
|
|
381
|
+
function assertChannelAddOptions(channelTarget, options) {
|
|
382
|
+
const target = getChannelTarget(channelTarget);
|
|
383
|
+
if (target.experimental) {
|
|
384
|
+
throw new Error(
|
|
385
|
+
`Channel target "${channelTarget}" is experimental. Confirm product requirement before use.`
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
if (!options.name || typeof options.name !== 'string' || !options.name.trim()) {
|
|
389
|
+
throw new Error('--name is required for channel add');
|
|
390
|
+
}
|
|
391
|
+
return target;
|
|
392
|
+
}
|
|
393
|
+
|
|
316
394
|
/**
|
|
317
395
|
* @param {string} channelTarget
|
|
318
396
|
* @param {Object} options
|
|
319
397
|
* @returns {Promise<Object>}
|
|
320
398
|
*/
|
|
321
399
|
async function runAddChannel(channelTarget, options = {}) {
|
|
322
|
-
const
|
|
400
|
+
const target = assertChannelAddOptions(channelTarget, options);
|
|
401
|
+
if (channelTarget === 'microsoft-copilot' && options.force === true) {
|
|
402
|
+
await assertMicrosoftCopilotOauthReferenceBeforeForce(options);
|
|
403
|
+
}
|
|
404
|
+
await ensureChannelReadyForAdd(channelTarget, options);
|
|
405
|
+
const { name, baseName, description, ctx, existing } = await prepareChannelContext(
|
|
323
406
|
channelTarget,
|
|
324
407
|
options
|
|
325
408
|
);
|
|
326
|
-
|
|
327
409
|
const skipped = showExistingChannelStatus({
|
|
328
410
|
existing,
|
|
329
411
|
options,
|
|
@@ -333,7 +415,9 @@ async function runAddChannel(channelTarget, options = {}) {
|
|
|
333
415
|
ctx
|
|
334
416
|
});
|
|
335
417
|
if (skipped) return skipped;
|
|
336
|
-
|
|
418
|
+
if (channelTarget === 'microsoft-copilot') {
|
|
419
|
+
await assertMicrosoftCopilotOauthReference({ options, ctx, name, baseName, description });
|
|
420
|
+
}
|
|
337
421
|
const { artifact, channelBlock, status } = await buildInstallArtifacts({
|
|
338
422
|
channelTarget,
|
|
339
423
|
options,
|
|
@@ -344,11 +428,9 @@ async function runAddChannel(channelTarget, options = {}) {
|
|
|
344
428
|
description,
|
|
345
429
|
ctx
|
|
346
430
|
});
|
|
347
|
-
|
|
348
431
|
if (options.dryRun) {
|
|
349
432
|
return finishDryRunInstall({ channelTarget, name, baseName, target, artifact, channelBlock });
|
|
350
433
|
}
|
|
351
|
-
|
|
352
434
|
return completeLiveInstall({
|
|
353
435
|
ctx,
|
|
354
436
|
channelTarget,
|
|
@@ -367,12 +449,7 @@ async function runAddChannel(channelTarget, options = {}) {
|
|
|
367
449
|
* @param {Object} options
|
|
368
450
|
*/
|
|
369
451
|
async function addChannelCommand(channelTarget, options = {}) {
|
|
370
|
-
|
|
371
|
-
await runAddChannel(channelTarget, options);
|
|
372
|
-
} catch (err) {
|
|
373
|
-
displayChannelError(err.message || String(err));
|
|
374
|
-
throw err;
|
|
375
|
-
}
|
|
452
|
+
await runAddChannel(channelTarget, options);
|
|
376
453
|
}
|
|
377
454
|
|
|
378
455
|
module.exports = {
|
|
@@ -22,7 +22,7 @@ function buildChatGptApprovalGuide(ctx) {
|
|
|
22
22
|
'Enable Developer mode for custom MCP apps (Business: Workspace settings → Apps, or Settings → Apps → Advanced settings; Enterprise/Edu: grant Developer mode under Permissions & roles → Connected data first).',
|
|
23
23
|
'Create a custom MCP app with the Remote MCP URL from INSTALL.md (channel-chatgpt.json is a deployment reference, not a plugin archive).',
|
|
24
24
|
'Select OAuth (authorization-code + PKCE S256). Do not configure a custom API key for a remote custom MCP app.',
|
|
25
|
-
'Scan tools, complete OAuth if prompted, review discovered
|
|
25
|
+
'Scan tools, complete OAuth if prompted, review discovered governed tools, then save the app as a draft.',
|
|
26
26
|
formatCredentialPortalStep(
|
|
27
27
|
ctx,
|
|
28
28
|
`${ctx.credentialKey || 'channel'} credential references (not secrets to paste into ChatGPT)`
|
|
@@ -71,6 +71,9 @@ function buildChannelApprovalGuide(channelTarget, context = {}) {
|
|
|
71
71
|
: null;
|
|
72
72
|
const baseCtx = {
|
|
73
73
|
channelTarget,
|
|
74
|
+
name,
|
|
75
|
+
baseName: context.baseName || name,
|
|
76
|
+
environment: context.environment || 'dev',
|
|
74
77
|
artifactPath,
|
|
75
78
|
resumeCommand,
|
|
76
79
|
credentialKey: target.credentialKey,
|