@aifabrix/builder 2.51.0 → 2.51.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/jest.isolated-projects.js +77 -1
- package/jest.projects.js +5 -426
- package/lib/api/assistants.api.js +67 -0
- package/lib/api/datasources-extended.api.js +6 -6
- package/lib/api/evidence-authoring-helpers.js +267 -0
- package/lib/api/evidence-authoring.api.js +337 -0
- package/lib/api/evidence.api.js +57 -1
- package/lib/api/index.js +24 -7
- package/lib/api/pipeline.api.js +43 -3
- package/lib/api/records-bulk.api.js +28 -3
- package/lib/api/types/evidence.types.js +156 -8
- package/lib/api/work.api.js +283 -0
- package/lib/app/run-deploy-job.js +108 -0
- package/lib/app/run-helpers.js +10 -3
- package/lib/app/run.js +8 -0
- package/lib/channels/add-channel.js +54 -23
- package/lib/channels/approval-guides/chatgpt.js +8 -7
- package/lib/channels/approval-guides/microsoft-copilot.js +7 -8
- package/lib/channels/channel-artifact-generator.js +14 -2
- package/lib/channels/channel-credential.js +3 -1
- package/lib/channels/channel-probe-evidence.js +79 -0
- package/lib/channels/channel-probe.js +265 -13
- package/lib/channels/channel-runtime-resolver.js +120 -29
- package/lib/channels/channel-status-display.js +44 -0
- package/lib/channels/channel-targets.js +7 -0
- package/lib/channels/chatgpt-runtime-contract.js +29 -0
- package/lib/channels/microsoft-copilot-package.js +280 -0
- package/lib/channels/runtime-tool-catalog.js +165 -0
- package/lib/cli/index.js +2 -0
- package/lib/cli/setup-app.js +4 -0
- package/lib/cli/setup-external-system-help.js +8 -2
- package/lib/cli/setup-external-system.js +12 -0
- package/lib/commands/app-test.js +2 -14
- package/lib/commands/datasource-load-export-cli.js +6 -1
- package/lib/commands/deploy-gate-failure-details.js +19 -17
- package/lib/commands/dev-down.js +2 -6
- package/lib/commands/evidence-kind.js +65 -15
- package/lib/commands/governance-generate-external.js +56 -21
- package/lib/commands/lifecycle-external.js +10 -4
- package/lib/commands/repair-datasource-apply.js +10 -1
- package/lib/commands/repair-datasource-run.js +4 -2
- package/lib/commands/repair-datasource-test-payload.js +80 -19
- package/lib/commands/repair-datasource-webhooks-sync-bridge.js +42 -3
- package/lib/commands/repair-internal.js +9 -1
- package/lib/commands/repair-openapi-sync.js +34 -17
- package/lib/commands/role-assistant.js +313 -0
- package/lib/commands/upload-data-sync-finalize.js +5 -4
- package/lib/commands/upload-sidecar-followups.js +144 -47
- package/lib/commands/upload.js +43 -6
- package/lib/commands/verify-governance-combined-external.js +73 -9
- package/lib/commands/verify-governance-db.js +80 -25
- package/lib/commands/verify-governance-external.js +29 -5
- package/lib/commands/wizard-core-helpers.js +7 -3
- package/lib/commands/wizard-core.js +78 -9
- package/lib/datasource/bulk-loader-run-batches.js +4 -2
- package/lib/datasource/bulk-loader-service.js +5 -1
- package/lib/datasource/datasource-validate-summary.js +2 -2
- package/lib/datasource/validate.js +13 -6
- package/lib/external-system/deploy-helpers.js +35 -1
- package/lib/external-system/deploy.js +23 -10
- package/lib/external-system/download-helpers.js +111 -2
- package/lib/external-system/download-role-assistant.js +55 -0
- package/lib/external-system/download.js +45 -26
- package/lib/external-system/test-helpers.js +1 -1
- package/lib/external-system/test.js +39 -3
- package/lib/generator/builders.js +3 -0
- package/lib/generator/wizard.js +51 -4
- package/lib/lifecycle/access-control-abac.js +121 -0
- package/lib/lifecycle/lifecycle-governance-options.js +4 -1
- package/lib/lifecycle/product-model.js +3 -2
- package/lib/lifecycle/report-display.js +14 -2
- package/lib/programmatic/capability-registry.js +20 -1
- package/lib/programmatic/command-options.js +1 -0
- package/lib/programmatic/index.js +4 -0
- package/lib/programmatic/manifest-patch-section.js +48 -9
- package/lib/programmatic/manifest-section-registry-data.js +3 -2
- package/lib/programmatic/openapi-apply-result-schemas.js +44 -0
- package/lib/programmatic/openapi-component-schemas.js +16 -1
- package/lib/programmatic/openapi-description-enricher.js +3 -1
- package/lib/programmatic/openapi-descriptions.js +55 -5
- package/lib/programmatic/openapi-evidence-schemas.js +161 -0
- package/lib/programmatic/openapi-manifest-schemas.js +6 -2
- package/lib/programmatic/openapi-operation-bindings.js +99 -0
- package/lib/programmatic/openapi-request-schemas.js +36 -1
- package/lib/programmatic/openapi-result-schemas.js +1 -1
- package/lib/programmatic/openapi-schema-descriptions-certify.js +5 -1
- package/lib/programmatic/openapi-schema-descriptions-core.js +1 -1
- package/lib/programmatic/openapi-schema-descriptions-evidence.js +156 -0
- package/lib/programmatic/openapi-schema-descriptions-manifest.js +4 -3
- package/lib/programmatic/openapi-schema-descriptions-operations.js +70 -0
- package/lib/programmatic/openapi-spec.js +47 -28
- package/lib/programmatic/orchestration-openapi-meta.js +5 -0
- package/lib/programmatic/request-timeout.js +3 -0
- package/lib/programmatic/route-handler-map.js +89 -2
- package/lib/programmatic/run-certify.js +15 -2
- package/lib/programmatic/run-deploy.js +74 -0
- package/lib/programmatic/run-evidence-authoring.js +80 -0
- package/lib/programmatic/run-protection.js +124 -0
- package/lib/programmatic/run-template-workspace.js +28 -1
- package/lib/programmatic/workspace-context.js +6 -0
- package/lib/protection/auth-context.js +48 -6
- package/lib/protection/paths.js +22 -0
- package/lib/protection/run-protection-create-helpers.js +22 -1
- package/lib/protection/run-protection-create.js +1 -1
- package/lib/protection/sync-after-upload.js +1 -1
- package/lib/role-assistant/evidence-sync.js +450 -0
- package/lib/role-assistant/github-workflow.js +96 -0
- package/lib/role-assistant/knowledge-sync.js +465 -0
- package/lib/role-assistant/settings.js +126 -0
- package/lib/role-assistant/test-cases-evaluate.js +170 -0
- package/lib/role-assistant/test-cases-honesty.js +184 -0
- package/lib/role-assistant/test-cases.js +364 -0
- package/lib/role-assistant/test-runner-workhub-answers.js +203 -0
- package/lib/role-assistant/test-runner-workhub.js +385 -0
- package/lib/role-assistant/test-runner.js +500 -0
- package/lib/schema/application-schema.json +16 -2
- package/lib/schema/deployment-rules.yaml +1 -0
- package/lib/schema/external-datasource.schema.json +38 -4
- package/lib/schema/external-system.schema.json +4 -4
- package/lib/schema/infra.parameter.yaml +20 -0
- package/lib/schema/role-assistant-settings.schema.json +108 -0
- package/lib/utils/api.js +52 -27
- package/lib/utils/app-path-resolve.js +72 -24
- package/lib/utils/authentication-shape.js +3 -1
- package/lib/utils/deployment-validation.js +28 -3
- package/lib/utils/docker-run-ephemeral.js +55 -0
- package/lib/utils/enterprise-knowledge-paths.js +29 -12
- package/lib/utils/env-copy-keycloak.js +196 -0
- package/lib/utils/env-copy.js +34 -1
- package/lib/utils/external-system-readiness-compact-display.js +3 -0
- package/lib/utils/help-builder.js +1 -0
- package/lib/utils/paths.js +67 -23
- package/lib/utils/pipeline-upload-auth-retry.js +15 -3
- package/lib/utils/role-assistant-paths.js +98 -0
- package/lib/utils/schema-loader.js +41 -0
- package/lib/utils/schema-resolver.js +36 -4
- package/lib/utils/token-manager.js +38 -29
- package/lib/utils/url-declarative-resolve-load-doc.js +38 -1
- package/lib/validation/external-manifest-validator.js +31 -8
- package/lib/validation/validate-external-file.js +8 -1
- package/package.json +2 -1
- package/scripts/export-builder-api-evidence.js +1 -1
- package/templates/applications/dataplane/application.yaml +23 -15
- package/templates/applications/dataplane/env.template +1 -1
- package/templates/applications/dataplane/rbac.yaml +14 -0
- package/templates/applications/miso-controller/application.yaml +1 -1
- package/templates/applications/miso-controller/env.template +3 -1
- package/templates/channels/chatgpt/install.template.md.hbs +42 -24
- package/templates/channels/chatgpt/integration/README.md +10 -7
- package/templates/channels/chatgpt/integration/application.json +2 -2
- package/templates/channels/chatgpt/integration/chatgpt-system.json +3 -3
- package/templates/channels/chatgpt/integration/env.template +1 -1
- package/templates/channels/chatgpt/manifest.template.json.hbs +36 -5
- package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +28 -0
- package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +22 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +32 -22
- package/templates/channels/microsoft-copilot/integration/README.md +9 -7
- package/templates/channels/microsoft-copilot/integration/application.json +2 -2
- package/templates/channels/microsoft-copilot/integration/env.template +1 -1
- package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +7 -6
- package/templates/channels/microsoft-copilot/manifest.template.json.hbs +34 -6
- /package/.cursor/plans/{157.1-security-quality-violations-by-type.csv → Done/157.1-security-quality-violations-by-type.csv} +0 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional build.deployJob — one-shot before long-running aifabrix run start.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Run deployJob once per aifabrix run
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 2.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const config = require('../core/config');
|
|
10
|
+
const logger = require('../utils/logger');
|
|
11
|
+
const {
|
|
12
|
+
infoLine,
|
|
13
|
+
formatSuccessLine,
|
|
14
|
+
formatBlockingError
|
|
15
|
+
} = require('../utils/cli-test-layout-chalk');
|
|
16
|
+
const { runDockerRunEphemeral } = require('../utils/docker-run-ephemeral');
|
|
17
|
+
const { getInfraBridgeNetworkName } = require('../infrastructure/orphan-infra-docker-teardown');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Resolve trimmed deployJob from app config, or null if unset.
|
|
21
|
+
* @param {Object} appConfig - Application configuration
|
|
22
|
+
* @returns {string|null}
|
|
23
|
+
*/
|
|
24
|
+
function resolveDeployJobCommand(appConfig) {
|
|
25
|
+
const raw = appConfig?.build?.deployJob;
|
|
26
|
+
if (typeof raw !== 'string') {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const trimmed = raw.trim();
|
|
30
|
+
return trimmed ? trimmed : null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Developer infra bridge so ephemeral jobs resolve compose DNS (e.g. postgres).
|
|
35
|
+
* @returns {Promise<string>}
|
|
36
|
+
*/
|
|
37
|
+
async function resolveDeployJobNetwork() {
|
|
38
|
+
const developerId = await config.getDeveloperId();
|
|
39
|
+
return getInfraBridgeNetworkName(developerId);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* If build.deployJob is set, run it once in an ephemeral container (same image + env).
|
|
44
|
+
* Fail-closed on non-zero exit. No-op when unset.
|
|
45
|
+
*
|
|
46
|
+
* When `devMountPath` is set (aifabrix run --reload), bind-mount that path at `/app`
|
|
47
|
+
* so migrate/deploy sees the same tree as the long-running reload container.
|
|
48
|
+
*
|
|
49
|
+
* @async
|
|
50
|
+
* @param {Object} params
|
|
51
|
+
* @param {Object} params.appConfig - Application configuration
|
|
52
|
+
* @param {string} params.fullImage - Image:tag used for the run
|
|
53
|
+
* @param {string|null} [params.runEnvPath] - Ephemeral .env.run path for --env-file
|
|
54
|
+
* @param {string|null} [params.devMountPath] - Host path mounted at /app for --reload
|
|
55
|
+
* @param {boolean} [params.debug]
|
|
56
|
+
* @returns {Promise<void>}
|
|
57
|
+
* @throws {Error} If deployJob exits non-zero
|
|
58
|
+
*/
|
|
59
|
+
async function runDeployJobIfConfigured({
|
|
60
|
+
appConfig,
|
|
61
|
+
fullImage,
|
|
62
|
+
runEnvPath = null,
|
|
63
|
+
devMountPath = null,
|
|
64
|
+
debug = false
|
|
65
|
+
}) {
|
|
66
|
+
const cmd = resolveDeployJobCommand(appConfig);
|
|
67
|
+
if (!cmd) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (!fullImage || typeof fullImage !== 'string') {
|
|
71
|
+
throw new Error('build.deployJob requires a resolved container image');
|
|
72
|
+
}
|
|
73
|
+
const network = await resolveDeployJobNetwork();
|
|
74
|
+
const volumeMounts = _deployJobVolumeMounts(devMountPath);
|
|
75
|
+
logger.log(infoLine(`Running build.deployJob once before start (${fullImage})…`));
|
|
76
|
+
if (debug) {
|
|
77
|
+
logger.log(infoLine(`deployJob: ${cmd}`));
|
|
78
|
+
logger.log(infoLine(`deployJob network: ${network}`));
|
|
79
|
+
if (volumeMounts.length) {
|
|
80
|
+
logger.log(infoLine(`deployJob mount: ${volumeMounts[0].host} -> /app`));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const code = await runDockerRunEphemeral(fullImage, cmd, runEnvPath, {
|
|
84
|
+
network,
|
|
85
|
+
volumeMounts
|
|
86
|
+
});
|
|
87
|
+
if (code !== 0) {
|
|
88
|
+
logger.log(formatBlockingError(`build.deployJob failed with exit code ${code}`));
|
|
89
|
+
throw new Error(`build.deployJob failed with exit code ${code}`);
|
|
90
|
+
}
|
|
91
|
+
logger.log(formatSuccessLine('build.deployJob completed'));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @param {string|null|undefined} devMountPath
|
|
96
|
+
* @returns {Array<{ host: string, container: string }>}
|
|
97
|
+
*/
|
|
98
|
+
function _deployJobVolumeMounts(devMountPath) {
|
|
99
|
+
if (typeof devMountPath !== 'string' || !devMountPath.trim()) {
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
return [{ host: devMountPath.trim(), container: '/app' }];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = {
|
|
106
|
+
resolveDeployJobCommand,
|
|
107
|
+
runDeployJobIfConfigured
|
|
108
|
+
};
|
package/lib/app/run-helpers.js
CHANGED
|
@@ -34,7 +34,12 @@ const runEnvCompose = require('./run-env-compose');
|
|
|
34
34
|
const { getAppInfraRequirements } = require('./run-infra-requirements');
|
|
35
35
|
const { resolveRunImage } = require('./run-resolve-image');
|
|
36
36
|
const { startContainer } = require('./run-container-start');
|
|
37
|
-
const {
|
|
37
|
+
const {
|
|
38
|
+
resolveEnvOutputPath,
|
|
39
|
+
resolveEnvLocalOutputPath,
|
|
40
|
+
writeEnvOutputForReload,
|
|
41
|
+
writeEnvOutputForLocal
|
|
42
|
+
} = require('../utils/env-copy');
|
|
38
43
|
const { resolveVersionForApp } = require('../utils/image-version');
|
|
39
44
|
const healthCheckUtil = require('../utils/health-check');
|
|
40
45
|
const { computeTraefikPublicAppUrl } = require('../utils/health-check-url');
|
|
@@ -303,8 +308,8 @@ async function generateComposeFile(appName, appConfig, composeOptions, devDir, l
|
|
|
303
308
|
|
|
304
309
|
/**
|
|
305
310
|
* Writes `build.envOutputPath` after each `aifabrix run`: **local**-flavored env for the host/IDE
|
|
306
|
-
* when not using `--reload`; with **`--reload`**, merges container `.env.run` into
|
|
307
|
-
*
|
|
311
|
+
* when not using `--reload`; with **`--reload`**, merges container `.env.run` into `.env` and also
|
|
312
|
+
* writes a sibling **`.env.local`** with localhost / published-port URLs for host CLI and manual tests.
|
|
308
313
|
*
|
|
309
314
|
* @async
|
|
310
315
|
* @param {string} appName - Application name
|
|
@@ -326,6 +331,8 @@ async function writeEnvOutputIfConfigured(appName, appConfig, runEnvPath, option
|
|
|
326
331
|
}
|
|
327
332
|
if (options && options.reload === true) {
|
|
328
333
|
await writeEnvOutputForReload(outputPath, runEnvPath, appName);
|
|
334
|
+
const localOutputPath = resolveEnvLocalOutputPath(outputPath);
|
|
335
|
+
await writeEnvOutputForLocal(appName, localOutputPath);
|
|
329
336
|
} else {
|
|
330
337
|
await writeEnvOutputForLocal(appName, outputPath);
|
|
331
338
|
}
|
package/lib/app/run.js
CHANGED
|
@@ -404,6 +404,14 @@ async function runApp(appName, options = {}) {
|
|
|
404
404
|
logger.log(chalk.gray(`[DEBUG] Compose file generated: ${prepared.tempComposePath}`));
|
|
405
405
|
}
|
|
406
406
|
logReloadDevSummary(Boolean(prepared.mergedRunOptions.reload), prepared.mergedRunOptions.reloadSyncSummary);
|
|
407
|
+
const { runDeployJobIfConfigured } = require('./run-deploy-job');
|
|
408
|
+
await runDeployJobIfConfigured({
|
|
409
|
+
appConfig: prepared.appConfig,
|
|
410
|
+
fullImage: prepared.mergedRunOptions.image,
|
|
411
|
+
runEnvPath: prepared.runEnvPath,
|
|
412
|
+
devMountPath: prepared.devMountPath || null,
|
|
413
|
+
debug
|
|
414
|
+
});
|
|
407
415
|
await startAppContainer(appName, prepared.tempComposePath, prepared.hostPort, prepared.appConfig, {
|
|
408
416
|
debug,
|
|
409
417
|
runEnvPath: prepared.runEnvPath,
|
|
@@ -12,6 +12,7 @@ const { getChannelTarget, getDefaultChannelDescription } = require('./channel-ta
|
|
|
12
12
|
const { resolveAppDescription } = require('./channel-description');
|
|
13
13
|
const { resolveChannelRuntimeValues } = require('./channel-runtime-resolver');
|
|
14
14
|
const { generateChannelArtifact } = require('./channel-artifact-generator');
|
|
15
|
+
const { fetchRuntimeLayerBToolNames } = require('./runtime-tool-catalog');
|
|
15
16
|
const {
|
|
16
17
|
getExistingChannelExtension,
|
|
17
18
|
buildChannelExtensionBlock,
|
|
@@ -66,7 +67,9 @@ function toValidationDisplay(validation) {
|
|
|
66
67
|
callbackReachable: validation.callbackReachable,
|
|
67
68
|
credentialValid: validation.credentialValid,
|
|
68
69
|
assistantCatalogReachable: validation.assistantCatalogReachable,
|
|
69
|
-
inboundVerification: Object.values(validation.inboundVerification).every(Boolean)
|
|
70
|
+
inboundVerification: Object.values(validation.inboundVerification).every(Boolean),
|
|
71
|
+
probeTiers: validation.probeTiers || null,
|
|
72
|
+
runtimeChecks: validation.runtimeChecks || null
|
|
70
73
|
};
|
|
71
74
|
}
|
|
72
75
|
|
|
@@ -156,7 +159,13 @@ async function patchConfigWithAudit(ctx, channelTarget, channelBlock, status, ar
|
|
|
156
159
|
async function maybeRunProbe(ctx, channelBlock, channelTarget, probe) {
|
|
157
160
|
if (!probe) return null;
|
|
158
161
|
const validation = await runChannelProbe(
|
|
159
|
-
{
|
|
162
|
+
{
|
|
163
|
+
dataplaneUrl: ctx.dataplaneUrl,
|
|
164
|
+
authConfig: ctx.authConfig,
|
|
165
|
+
environment: ctx.environment,
|
|
166
|
+
controllerUrl: ctx.controllerUrl,
|
|
167
|
+
channelTarget
|
|
168
|
+
},
|
|
160
169
|
channelBlock
|
|
161
170
|
);
|
|
162
171
|
if (validation.passed) {
|
|
@@ -268,6 +277,42 @@ function finishDryRunInstall(params) {
|
|
|
268
277
|
return { dryRun: true, channelBlock: params.channelBlock, artifact: params.artifact };
|
|
269
278
|
}
|
|
270
279
|
|
|
280
|
+
/**
|
|
281
|
+
* @param {Object} params
|
|
282
|
+
* @returns {Promise<{ artifact: Object, channelBlock: Object, status: string }>}
|
|
283
|
+
*/
|
|
284
|
+
async function buildInstallArtifacts(params) {
|
|
285
|
+
const { channelTarget, options, target, existing, name, baseName, description, ctx } = params;
|
|
286
|
+
const runtimeToolNames =
|
|
287
|
+
channelTarget === 'chatgpt' || channelTarget === 'microsoft-copilot'
|
|
288
|
+
? await fetchRuntimeLayerBToolNames(ctx.dataplaneUrl, ctx.authConfig, channelTarget)
|
|
289
|
+
: [];
|
|
290
|
+
const runtimeValues = resolveChannelRuntimeValues({
|
|
291
|
+
dataplaneBaseUrl: ctx.dataplaneUrl,
|
|
292
|
+
channelTarget,
|
|
293
|
+
appName: name,
|
|
294
|
+
baseName,
|
|
295
|
+
environment: ctx.environment,
|
|
296
|
+
appDescription: description,
|
|
297
|
+
icon: options.icon,
|
|
298
|
+
commandPrefix: options.commandPrefix,
|
|
299
|
+
layerBToolNames: runtimeToolNames
|
|
300
|
+
});
|
|
301
|
+
const projectRoot = options.projectRoot || process.cwd();
|
|
302
|
+
const artifact = generateArtifactWithAudit(channelTarget, {
|
|
303
|
+
projectRoot,
|
|
304
|
+
channelTarget,
|
|
305
|
+
runtimeValues,
|
|
306
|
+
dryRun: options.dryRun === true
|
|
307
|
+
});
|
|
308
|
+
const status = resolveInstallStatus(target, existing, options.dryRun === true);
|
|
309
|
+
const channelBlock = buildChannelExtensionBlock(
|
|
310
|
+
{ name, baseName, description, artifactHash: artifact.artifactHash, status },
|
|
311
|
+
target
|
|
312
|
+
);
|
|
313
|
+
return { artifact, channelBlock, status };
|
|
314
|
+
}
|
|
315
|
+
|
|
271
316
|
/**
|
|
272
317
|
* @param {string} channelTarget
|
|
273
318
|
* @param {Object} options
|
|
@@ -289,31 +334,17 @@ async function runAddChannel(channelTarget, options = {}) {
|
|
|
289
334
|
});
|
|
290
335
|
if (skipped) return skipped;
|
|
291
336
|
|
|
292
|
-
const
|
|
293
|
-
dataplaneBaseUrl: ctx.dataplaneUrl,
|
|
337
|
+
const { artifact, channelBlock, status } = await buildInstallArtifacts({
|
|
294
338
|
channelTarget,
|
|
295
|
-
|
|
339
|
+
options,
|
|
340
|
+
target,
|
|
341
|
+
existing,
|
|
342
|
+
name,
|
|
296
343
|
baseName,
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
icon: options.icon,
|
|
300
|
-
commandPrefix: options.commandPrefix
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
const projectRoot = options.projectRoot || process.cwd();
|
|
304
|
-
const artifact = generateArtifactWithAudit(channelTarget, {
|
|
305
|
-
projectRoot,
|
|
306
|
-
channelTarget,
|
|
307
|
-
runtimeValues,
|
|
308
|
-
dryRun: options.dryRun === true
|
|
344
|
+
description,
|
|
345
|
+
ctx
|
|
309
346
|
});
|
|
310
347
|
|
|
311
|
-
const status = resolveInstallStatus(target, existing, options.dryRun === true);
|
|
312
|
-
const channelBlock = buildChannelExtensionBlock(
|
|
313
|
-
{ name, baseName, description, artifactHash: artifact.artifactHash, status },
|
|
314
|
-
target
|
|
315
|
-
);
|
|
316
|
-
|
|
317
348
|
if (options.dryRun) {
|
|
318
349
|
return finishDryRunInstall({ channelTarget, name, baseName, target, artifact, channelBlock });
|
|
319
350
|
}
|
|
@@ -19,13 +19,14 @@ function buildChatGptApprovalGuide(ctx) {
|
|
|
19
19
|
portalUrl: 'https://platform.openai.com/',
|
|
20
20
|
steps: [
|
|
21
21
|
'Sign in to OpenAI Platform (https://platform.openai.com/) or your ChatGPT Enterprise workspace admin console.',
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
|
|
26
|
-
'
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
'Enable Developer mode / custom MCP app creation for the workspace (if policy requires admin allow-listing).',
|
|
23
|
+
'Create a custom MCP app using the generated channel-chatgpt.json reference artifact (path shown below).',
|
|
24
|
+
'Configure the Runtime MCP endpoint from INSTALL.md and verify Runtime Layer B tool discovery.',
|
|
25
|
+
'Complete workspace authentication setup for the custom MCP app.',
|
|
26
|
+
formatCredentialPortalStep(ctx, 'workspace credential references used by the ChatGPT channel'),
|
|
27
|
+
'Publish the app to your workspace and configure end-user access controls.',
|
|
28
|
+
`After ChatGPT lists the app as active, re-run: ${ctx.resumeCommand}`,
|
|
29
|
+
'Optional: use --probe for AI Fabrix-side runtime checks; OpenAI-side publication remains a manual admin responsibility.'
|
|
29
30
|
]
|
|
30
31
|
};
|
|
31
32
|
}
|
|
@@ -19,14 +19,13 @@ function buildMicrosoftCopilotApprovalGuide(ctx) {
|
|
|
19
19
|
portalUrl: 'https://admin.cloud.microsoft.com/',
|
|
20
20
|
steps: [
|
|
21
21
|
'Sign in to Microsoft 365 admin (https://admin.cloud.microsoft.com/) or Copilot Studio as a tenant admin.',
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
'Optional: add --probe when dataplane Copilot runtime routes are live on your environment.'
|
|
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
29
|
]
|
|
31
30
|
};
|
|
32
31
|
}
|
|
@@ -14,6 +14,7 @@ const path = require('path');
|
|
|
14
14
|
const Handlebars = require('handlebars');
|
|
15
15
|
const { getChannelTarget } = require('./channel-targets');
|
|
16
16
|
const { BUILDER_ROOT } = require('./channel-integration-template');
|
|
17
|
+
const { generateMicrosoftCopilotPackage } = require('./microsoft-copilot-package');
|
|
17
18
|
|
|
18
19
|
const SECRET_PATTERNS = [/xoxb-/i, /xoxp-/i, /client_secret/i, /signing_secret/i, /Bearer\s+/i];
|
|
19
20
|
const PLACEHOLDER_DOMAIN_RE = /\byour-domain\.com\b/i;
|
|
@@ -115,11 +116,22 @@ function renderInstallGuideIfPresent(templatesDir, runtimeValues, outputDir, dry
|
|
|
115
116
|
*/
|
|
116
117
|
function generateChannelArtifact(params) {
|
|
117
118
|
const templatesDir = getChannelTemplatesDir(params.channelTarget);
|
|
119
|
+
const outputPath = getArtifactOutputPath(params.projectRoot, params.channelTarget);
|
|
120
|
+
|
|
121
|
+
if (params.channelTarget === 'microsoft-copilot') {
|
|
122
|
+
return generateMicrosoftCopilotPackage({
|
|
123
|
+
runtimeValues: params.runtimeValues,
|
|
124
|
+
templatesDir,
|
|
125
|
+
outputPath,
|
|
126
|
+
dryRun: params.dryRun === true,
|
|
127
|
+
assertNoSecretsInArtifact,
|
|
128
|
+
renderTemplateFile
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
118
132
|
const manifestTemplate = path.join(templatesDir, 'manifest.template.json.hbs');
|
|
119
133
|
const content = renderTemplateFile(manifestTemplate, params.runtimeValues);
|
|
120
134
|
assertNoSecretsInArtifact(content);
|
|
121
|
-
|
|
122
|
-
const outputPath = getArtifactOutputPath(params.projectRoot, params.channelTarget);
|
|
123
135
|
const artifactHash = crypto.createHash('sha256').update(content, 'utf8').digest('hex');
|
|
124
136
|
const outputDir = path.dirname(outputPath);
|
|
125
137
|
|
|
@@ -48,8 +48,10 @@ const CREDENTIAL_SPECS = {
|
|
|
48
48
|
method: 'oauth2',
|
|
49
49
|
credentialConfig: {
|
|
50
50
|
type: 'oauth2',
|
|
51
|
-
grantType: '
|
|
51
|
+
grantType: 'authorization_code',
|
|
52
|
+
authorizationUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
|
|
52
53
|
tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
|
|
54
|
+
scope: 'openid profile offline_access',
|
|
53
55
|
clientId: 'pending-channel-install',
|
|
54
56
|
clientSecret: 'pending-channel-install'
|
|
55
57
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Probe BTA Evidence authoring reachability for channel installs (plan 163 T7).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Evidence metadata/download live checks without mutating activate/upload
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
getEvidenceMetadata,
|
|
13
|
+
downloadEvidence
|
|
14
|
+
} = require('../api/evidence-authoring.api');
|
|
15
|
+
|
|
16
|
+
const EVIDENCE_AUTHORING_CAPABILITY_KEYS = Object.freeze([
|
|
17
|
+
'evidence.metadata',
|
|
18
|
+
'evidence.download',
|
|
19
|
+
'evidence.upload',
|
|
20
|
+
'evidence.activate'
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Prefer Business Transformation when present; otherwise first catalog role key.
|
|
25
|
+
*
|
|
26
|
+
* @param {Object[]} catalogItems
|
|
27
|
+
* @returns {string}
|
|
28
|
+
*/
|
|
29
|
+
function pickEvidenceRoleKey(catalogItems) {
|
|
30
|
+
const keys = (Array.isArray(catalogItems) ? catalogItems : [])
|
|
31
|
+
.map((item) => String(item?.key || item?.roleKey || item?.roleRef || '').trim())
|
|
32
|
+
.filter(Boolean);
|
|
33
|
+
const preferred = keys.find((key) => key.includes('business-transformation'));
|
|
34
|
+
return preferred || keys[0] || '';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Live metadata + download prove Evidence path; upload/activate remain contract keys.
|
|
39
|
+
*
|
|
40
|
+
* @async
|
|
41
|
+
* @param {Object} ctx
|
|
42
|
+
* @param {Object[]} catalogItems
|
|
43
|
+
* @returns {Promise<{ reachable: boolean, roleKey: string, capabilityKeys: string[] }>}
|
|
44
|
+
*/
|
|
45
|
+
async function probeEvidenceAuthoringReachable(ctx, catalogItems) {
|
|
46
|
+
const roleKey = pickEvidenceRoleKey(catalogItems);
|
|
47
|
+
const capabilityKeys = [...EVIDENCE_AUTHORING_CAPABILITY_KEYS];
|
|
48
|
+
if (!roleKey || !ctx?.dataplaneUrl || !ctx?.authConfig || !ctx?.controllerUrl) {
|
|
49
|
+
return { reachable: false, roleKey, capabilityKeys };
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const options = { controllerUrl: ctx.controllerUrl };
|
|
53
|
+
const metadata = await getEvidenceMetadata(
|
|
54
|
+
ctx.dataplaneUrl,
|
|
55
|
+
ctx.authConfig,
|
|
56
|
+
roleKey,
|
|
57
|
+
options
|
|
58
|
+
);
|
|
59
|
+
const downloaded = await downloadEvidence(
|
|
60
|
+
ctx.dataplaneUrl,
|
|
61
|
+
ctx.authConfig,
|
|
62
|
+
{ roleKey, pageSize: 1 },
|
|
63
|
+
options
|
|
64
|
+
);
|
|
65
|
+
const reachable =
|
|
66
|
+
Boolean(metadata?.roleKey) &&
|
|
67
|
+
Array.isArray(metadata?.evidenceKinds) &&
|
|
68
|
+
Array.isArray(downloaded?.data);
|
|
69
|
+
return { reachable, roleKey, capabilityKeys };
|
|
70
|
+
} catch {
|
|
71
|
+
return { reachable: false, roleKey, capabilityKeys };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = {
|
|
76
|
+
EVIDENCE_AUTHORING_CAPABILITY_KEYS,
|
|
77
|
+
pickEvidenceRoleKey,
|
|
78
|
+
probeEvidenceAuthoringReachable
|
|
79
|
+
};
|