@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,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Role Assistant CLI command group.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview role-assistant test command with portal deep-link output
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const logger = require('../utils/logger');
|
|
12
|
+
const { handleCommandError } = require('../utils/cli-utils');
|
|
13
|
+
const {
|
|
14
|
+
runLifecycleForExternalSystem,
|
|
15
|
+
resolveLifecycleAuth
|
|
16
|
+
} = require('./lifecycle-external');
|
|
17
|
+
const { lifecycleVerdictFromReport } = require('./lifecycle-command-action');
|
|
18
|
+
const { buildExternalSystemUiUrl } = require('../lifecycle/dataplane-ui-url');
|
|
19
|
+
const { VERDICT } = require('../lifecycle/product-model');
|
|
20
|
+
const { exitCodeFromVerdict } = require('../lifecycle/exit-codes');
|
|
21
|
+
const {
|
|
22
|
+
loadRoleAssistantTestCase,
|
|
23
|
+
evaluateRoleAssistantTestCase
|
|
24
|
+
} = require('../role-assistant/test-cases');
|
|
25
|
+
const {
|
|
26
|
+
isExecutableRoleAssistantCase,
|
|
27
|
+
runRoleAssistantCaseLifecycle,
|
|
28
|
+
mergeCaseExecutionIntoLifecycleResult,
|
|
29
|
+
lifecycleVerdictFromCaseExecution
|
|
30
|
+
} = require('../role-assistant/test-runner');
|
|
31
|
+
const { collectString } = require('./governance');
|
|
32
|
+
const {
|
|
33
|
+
sectionTitle,
|
|
34
|
+
headerKeyValue,
|
|
35
|
+
formatSuccessLine,
|
|
36
|
+
formatSuccessParagraph,
|
|
37
|
+
formatWarningLine,
|
|
38
|
+
formatBlockingError,
|
|
39
|
+
metadata
|
|
40
|
+
} = require('../utils/cli-test-layout-chalk');
|
|
41
|
+
|
|
42
|
+
function roleAssistantHelpAfter() {
|
|
43
|
+
return `
|
|
44
|
+
Examples:
|
|
45
|
+
$ aifabrix role-assistant test customer-support-bot
|
|
46
|
+
$ aifabrix role-assistant test customer-support-bot --case smoke
|
|
47
|
+
$ aifabrix role-assistant test customer-support-bot --case tests/customer-address-change.yaml
|
|
48
|
+
$ aifabrix role-assistant test customer-support-bot --subject-email ops@example.com
|
|
49
|
+
$ aifabrix role-assistant test customer-support-bot --json
|
|
50
|
+
$ aifabrix role-assistant test customer-support-bot --publish --force
|
|
51
|
+
|
|
52
|
+
Notes:
|
|
53
|
+
- Uses the public/running Role Assistant on the dataplane by default (does not publish local datasources).
|
|
54
|
+
- Use \`aifabrix upload <roleKey> --env …\` (or \`--publish\`) when you intentionally refresh the package.
|
|
55
|
+
- Runs lifecycle checks, then prints a portal deep link for full step-by-step status.
|
|
56
|
+
- Case files with input.message/input.content execute Work Hub plan→accept (or work.start when executionPath: intent).
|
|
57
|
+
- answers[] and approvals[] are matched to runtime wait payloads (questionKey/requestKey/waitReason).
|
|
58
|
+
- Use the portal URL for detailed human review while automation reads CLI/JSON output.
|
|
59
|
+
`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function rawArgsInclude(cmd, flag) {
|
|
63
|
+
const raw = cmd && Array.isArray(cmd.rawArgs) ? cmd.rawArgs : [];
|
|
64
|
+
return raw.includes(flag);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function optionOrFlag(options, key, cmd, ...flags) {
|
|
68
|
+
if (options[key] === true) {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
return flags.some((flag) => rawArgsInclude(cmd, flag));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function trimOptionalString(value) {
|
|
75
|
+
return value ? String(value).trim() : '';
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function normalizeRoleAssistantTestOptions(options, cmd) {
|
|
79
|
+
// Role Assistant test uses the public/running digital worker by default.
|
|
80
|
+
// Opt in to publish with --publish (optional --force).
|
|
81
|
+
const wantsPublish = optionOrFlag(options, 'publish', cmd, '--publish');
|
|
82
|
+
return {
|
|
83
|
+
env: options.env || 'dev',
|
|
84
|
+
verbose: optionOrFlag(options, 'verbose', cmd, '-v', '--verbose'),
|
|
85
|
+
debug: optionOrFlag(options, 'debug', cmd, '-d', '--debug'),
|
|
86
|
+
json: optionOrFlag(options, 'json', cmd, '--json'),
|
|
87
|
+
noPublish: !wantsPublish,
|
|
88
|
+
force: optionOrFlag(options, 'force', cmd, '--force'),
|
|
89
|
+
subjectUserId: options.subjectUserId || [],
|
|
90
|
+
subjectEmail: options.subjectEmail || [],
|
|
91
|
+
certificationProfile: options.certificationProfile || 'bronze',
|
|
92
|
+
case: trimOptionalString(options.case),
|
|
93
|
+
testsDir: trimOptionalString(options.testsDir),
|
|
94
|
+
run: true
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function buildRoleAssistantTestEnvelope(roleKey, verdict, portalUrl, result, opts, caseResult = null) {
|
|
99
|
+
const report = result.report || {};
|
|
100
|
+
const envelope = {
|
|
101
|
+
roleKey,
|
|
102
|
+
command: 'role-assistant test',
|
|
103
|
+
verdict,
|
|
104
|
+
portalUrl,
|
|
105
|
+
openApiPublished: result.openApiPublished === true,
|
|
106
|
+
certification: report.certification || null,
|
|
107
|
+
recommendations: Array.isArray(report.recommendations) ? report.recommendations : [],
|
|
108
|
+
warnings: Array.isArray(report.warnings) ? report.warnings : [],
|
|
109
|
+
stepsRun: result.stepsRun || [],
|
|
110
|
+
case: caseResult
|
|
111
|
+
? {
|
|
112
|
+
caseId: caseResult.caseId,
|
|
113
|
+
sourceFile: caseResult.sourceFile,
|
|
114
|
+
passed: caseResult.passed,
|
|
115
|
+
lifecycleState: caseResult.lifecycleState,
|
|
116
|
+
assertions: caseResult.assertions,
|
|
117
|
+
failedAssertions: caseResult.failedAssertions,
|
|
118
|
+
warnings: Array.isArray(caseResult.warnings) ? caseResult.warnings : [],
|
|
119
|
+
execution: caseResult.execution || null
|
|
120
|
+
}
|
|
121
|
+
: null
|
|
122
|
+
};
|
|
123
|
+
if (opts.verbose || opts.debug) {
|
|
124
|
+
envelope.report = report;
|
|
125
|
+
}
|
|
126
|
+
if (opts.debug) {
|
|
127
|
+
envelope.debug = {
|
|
128
|
+
observation: caseResult ? caseResult.observation : null,
|
|
129
|
+
lifecycleResult: result
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return envelope;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function displayCaseResultSummary(caseResult) {
|
|
136
|
+
if (!caseResult) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
logger.log(headerKeyValue('Case:', caseResult.caseId));
|
|
140
|
+
logger.log(headerKeyValue('Case file:', caseResult.sourceFile));
|
|
141
|
+
logger.log(headerKeyValue('Observed state:', caseResult.lifecycleState));
|
|
142
|
+
if (caseResult.execution) {
|
|
143
|
+
logger.log(headerKeyValue('Execution id:', caseResult.execution.processExecutionId || 'n/a'));
|
|
144
|
+
logger.log(headerKeyValue('Final runtime status:', caseResult.execution.finalStatus || 'n/a'));
|
|
145
|
+
}
|
|
146
|
+
if (caseResult.passed) {
|
|
147
|
+
logger.log(formatSuccessLine('Case assertions passed.'));
|
|
148
|
+
const warnings = Array.isArray(caseResult.warnings) ? caseResult.warnings : [];
|
|
149
|
+
for (const row of warnings) {
|
|
150
|
+
logger.log(formatWarningLine(row.message || String(row)));
|
|
151
|
+
}
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
logger.log(formatBlockingError('Case assertions failed.'));
|
|
155
|
+
for (const row of caseResult.failedAssertions) {
|
|
156
|
+
logger.log(formatWarningLine(row.message));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function displayRoleAssistantTestSummary(roleKey, verdict, portalUrl, result, caseResult = null) {
|
|
161
|
+
logger.log('');
|
|
162
|
+
logger.log(sectionTitle(`${String(roleKey).toUpperCase()} ROLE ASSISTANT TEST`));
|
|
163
|
+
logger.log('');
|
|
164
|
+
logger.log(headerKeyValue('Role key:', roleKey));
|
|
165
|
+
if (portalUrl) {
|
|
166
|
+
logger.log(headerKeyValue('Portal:', portalUrl));
|
|
167
|
+
} else {
|
|
168
|
+
logger.log(formatWarningLine('Portal link unavailable. Configure dataplane public URL and retry.'));
|
|
169
|
+
}
|
|
170
|
+
const verdictMessage =
|
|
171
|
+
verdict === VERDICT.VERIFIED
|
|
172
|
+
? 'Lifecycle checks passed. Open portal for full execution steps and logs.'
|
|
173
|
+
: 'Lifecycle checks are not fully verified. Open portal to inspect blocking steps.';
|
|
174
|
+
if (verdict === VERDICT.VERIFIED) {
|
|
175
|
+
logger.log(formatSuccessParagraph(verdictMessage));
|
|
176
|
+
} else {
|
|
177
|
+
logger.log(formatWarningLine(verdictMessage));
|
|
178
|
+
}
|
|
179
|
+
const steps = Array.isArray(result.stepsRun) ? result.stepsRun : [];
|
|
180
|
+
if (steps.length > 0) {
|
|
181
|
+
const labels = steps.map((row) => (row && row.pillar ? row.pillar : String(row)));
|
|
182
|
+
logger.log(metadata(`Steps run: ${labels.join(', ')}`));
|
|
183
|
+
}
|
|
184
|
+
displayCaseResultSummary(caseResult);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async function resolveRoleAssistantCaseResult(roleKey, opts, result, verdict, portalUrl) {
|
|
188
|
+
if (!opts.case) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
const roleCase = loadRoleAssistantTestCase(roleKey, opts.case, {
|
|
192
|
+
testsDir: opts.testsDir || null
|
|
193
|
+
});
|
|
194
|
+
if (!isExecutableRoleAssistantCase(roleCase)) {
|
|
195
|
+
return evaluateRoleAssistantTestCase(roleCase, result, verdict, portalUrl);
|
|
196
|
+
}
|
|
197
|
+
const authContext = await resolveLifecycleAuth(roleKey, {
|
|
198
|
+
...opts,
|
|
199
|
+
run: false,
|
|
200
|
+
noPublish: true
|
|
201
|
+
});
|
|
202
|
+
const executionResult = await runRoleAssistantCaseLifecycle(roleKey, roleCase, authContext, opts);
|
|
203
|
+
const executionVerdict = lifecycleVerdictFromCaseExecution(executionResult, verdict);
|
|
204
|
+
const evaluationInput = mergeCaseExecutionIntoLifecycleResult(result, executionResult);
|
|
205
|
+
const evaluation = evaluateRoleAssistantTestCase(
|
|
206
|
+
roleCase,
|
|
207
|
+
evaluationInput,
|
|
208
|
+
executionVerdict,
|
|
209
|
+
portalUrl
|
|
210
|
+
);
|
|
211
|
+
evaluation.execution = {
|
|
212
|
+
processExecutionId: executionResult.processExecutionId || null,
|
|
213
|
+
finalStatus: executionResult.finalStatus?.status || null,
|
|
214
|
+
waitReason: executionResult.finalStatus?.wait?.waitReason || null,
|
|
215
|
+
interactions: executionResult.interactions || [],
|
|
216
|
+
workResultError: executionResult.workResultError || null
|
|
217
|
+
};
|
|
218
|
+
return evaluation;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function computeRoleAssistantExitCode(verdict, caseResult) {
|
|
222
|
+
if (caseResult) {
|
|
223
|
+
return caseResult.passed ? 0 : 2;
|
|
224
|
+
}
|
|
225
|
+
if (verdict === VERDICT.VERIFIED) {
|
|
226
|
+
return 0;
|
|
227
|
+
}
|
|
228
|
+
return exitCodeFromVerdict(verdict, { partial: verdict === VERDICT.NOT_VERIFIED });
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async function runRoleAssistantTestAction(roleKey, options, cmd) {
|
|
232
|
+
const opts = normalizeRoleAssistantTestOptions(options, cmd);
|
|
233
|
+
const result = await runLifecycleForExternalSystem(roleKey, opts);
|
|
234
|
+
const verdict = lifecycleVerdictFromReport(result.report || {});
|
|
235
|
+
const portalUrl = buildExternalSystemUiUrl(result.dataplaneUiBaseUrl, roleKey);
|
|
236
|
+
const caseResult = await resolveRoleAssistantCaseResult(roleKey, opts, result, verdict, portalUrl);
|
|
237
|
+
|
|
238
|
+
if (opts.json) {
|
|
239
|
+
logger.log(
|
|
240
|
+
JSON.stringify(
|
|
241
|
+
buildRoleAssistantTestEnvelope(roleKey, verdict, portalUrl, result, opts, caseResult),
|
|
242
|
+
null,
|
|
243
|
+
2
|
|
244
|
+
)
|
|
245
|
+
);
|
|
246
|
+
} else {
|
|
247
|
+
displayRoleAssistantTestSummary(roleKey, verdict, portalUrl, result, caseResult);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const exitCode = computeRoleAssistantExitCode(verdict, caseResult);
|
|
251
|
+
if (exitCode !== 0) {
|
|
252
|
+
process.exit(exitCode);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
async function roleAssistantTestHandler(roleKey, options, cmd) {
|
|
257
|
+
try {
|
|
258
|
+
await runRoleAssistantTestAction(roleKey, options, cmd);
|
|
259
|
+
} catch (error) {
|
|
260
|
+
handleCommandError(error, 'role-assistant test');
|
|
261
|
+
process.exit(3);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function setupRoleAssistantCommands(program) {
|
|
266
|
+
const roleAssistant = program
|
|
267
|
+
.command('role-assistant')
|
|
268
|
+
.description('Role Assistant lifecycle and portal workflows');
|
|
269
|
+
|
|
270
|
+
roleAssistant
|
|
271
|
+
.command('test <roleKey>')
|
|
272
|
+
.description('Run role-assistant lifecycle checks and print portal deep link')
|
|
273
|
+
.option('-e, --env <env>', 'Environment: dev, tst, or pro', 'dev')
|
|
274
|
+
.option('--case <caseIdOrPath>', 'Run and evaluate one role-assistant test case')
|
|
275
|
+
.option('--tests-dir <dir>', 'Override role-assistant test case directory')
|
|
276
|
+
.option('-v, --verbose', 'Include full lifecycle report payload in --json output')
|
|
277
|
+
.option('-d, --debug', 'Write debug logs under role-assistant/<roleKey>/logs/')
|
|
278
|
+
.option(
|
|
279
|
+
'--publish',
|
|
280
|
+
'Publish local Role Assistant package before checks (default: use public/running worker)'
|
|
281
|
+
)
|
|
282
|
+
.option('--force', 'Force upload when --publish is set')
|
|
283
|
+
.option(
|
|
284
|
+
'--subject-user-id <id>',
|
|
285
|
+
'Subject user id for governance generate (repeatable)',
|
|
286
|
+
collectString,
|
|
287
|
+
[]
|
|
288
|
+
)
|
|
289
|
+
.option(
|
|
290
|
+
'--subject-email <email>',
|
|
291
|
+
'Subject email for governance generate (repeatable)',
|
|
292
|
+
collectString,
|
|
293
|
+
[]
|
|
294
|
+
)
|
|
295
|
+
.option(
|
|
296
|
+
'--certification-profile <profile>',
|
|
297
|
+
'Certification profile for governance generate (bronze, silver, gold, ...)',
|
|
298
|
+
'bronze'
|
|
299
|
+
)
|
|
300
|
+
.option('--json', 'Machine-readable output envelope')
|
|
301
|
+
.addHelpText('after', roleAssistantHelpAfter())
|
|
302
|
+
.action((roleKey, options, cmd) => roleAssistantTestHandler(roleKey, options, cmd));
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
module.exports = {
|
|
306
|
+
setupRoleAssistantCommands,
|
|
307
|
+
roleAssistantTestHandler,
|
|
308
|
+
runRoleAssistantTestAction,
|
|
309
|
+
normalizeRoleAssistantTestOptions,
|
|
310
|
+
buildRoleAssistantTestEnvelope,
|
|
311
|
+
computeRoleAssistantExitCode,
|
|
312
|
+
resolveRoleAssistantCaseResult
|
|
313
|
+
};
|
|
@@ -27,7 +27,7 @@ async function finalizeUploadPublishResult(ctx, payload, options) {
|
|
|
27
27
|
options,
|
|
28
28
|
label: 'Upload data sync'
|
|
29
29
|
});
|
|
30
|
-
return { ...ctx, dataSync };
|
|
30
|
+
return { ...ctx, dataSync, sidecar: ctx.sidecar || null };
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
@@ -40,15 +40,16 @@ async function finishUnchangedUploadPublication(params) {
|
|
|
40
40
|
if (!isQuietMinimalSync(options)) {
|
|
41
41
|
logger.log(formatSuccessLine('Config unchanged on dataplane — upload skipped.'));
|
|
42
42
|
}
|
|
43
|
-
await runUploadSidecarFollowups({
|
|
43
|
+
const sidecar = await runUploadSidecarFollowups({
|
|
44
44
|
systemKey,
|
|
45
45
|
options,
|
|
46
46
|
payload,
|
|
47
47
|
dataplaneUrl,
|
|
48
|
-
authConfig
|
|
48
|
+
authConfig,
|
|
49
|
+
environment
|
|
49
50
|
});
|
|
50
51
|
return finalizeUploadPublishResult(
|
|
51
|
-
{ dataplaneUrl, authConfig, environment, uploadSkipped: true },
|
|
52
|
+
{ dataplaneUrl, authConfig, environment, uploadSkipped: true, sidecar },
|
|
52
53
|
payload,
|
|
53
54
|
options
|
|
54
55
|
);
|
|
@@ -12,22 +12,123 @@ const { unwrapPublicationResult, isPublicationUnchanged } = require('../utils/ex
|
|
|
12
12
|
const { logUploadReadinessSummary } = require('../utils/external-system-readiness-display');
|
|
13
13
|
const { isQuietMinimalSync } = require('../utils/upload-sync-options');
|
|
14
14
|
|
|
15
|
+
function buildRoleAssistantModel(payload) {
|
|
16
|
+
return {
|
|
17
|
+
application: payload?.application,
|
|
18
|
+
dataSources: payload?.dataSources || []
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function buildRoleAssistantSyncContext(ctx, model) {
|
|
23
|
+
// Controller deploy env (e.g. miso) ≠ role-assistant.yaml section (dev|tst|pro).
|
|
24
|
+
const { resolveRoleAssistantSettingsEnvKey } = require('../role-assistant/knowledge-sync');
|
|
25
|
+
const raEnv = resolveRoleAssistantSettingsEnvKey(
|
|
26
|
+
(ctx.options && (ctx.options.env || ctx.options.roleAssistantEnv)) || 'dev'
|
|
27
|
+
);
|
|
28
|
+
return {
|
|
29
|
+
systemKey: ctx.systemKey,
|
|
30
|
+
dataplaneUrl: ctx.dataplaneUrl,
|
|
31
|
+
authConfig: ctx.authConfig,
|
|
32
|
+
model,
|
|
33
|
+
environment: raEnv,
|
|
34
|
+
pathOptions: ctx.options.pathOptions || {},
|
|
35
|
+
dryRun: ctx.options.dryRun === true
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function runGovernanceSidecar(ctx, sidecar, quietSidecar) {
|
|
40
|
+
try {
|
|
41
|
+
const { uploadGovernanceScenarioPacks } = require('../lifecycle/scenario-upload');
|
|
42
|
+
const uploaded = await uploadGovernanceScenarioPacks(ctx.systemKey, ctx.dataplaneUrl, ctx.authConfig, {
|
|
43
|
+
silent: quietSidecar
|
|
44
|
+
});
|
|
45
|
+
sidecar.governance = { uploaded: Number(uploaded || 0) };
|
|
46
|
+
} catch (err) {
|
|
47
|
+
sidecar.governance = { skipped: true, reason: err.message || String(err) };
|
|
48
|
+
if (!quietSidecar) {
|
|
49
|
+
logger.log(formatWarningLine(`Governance scenario upload skipped: ${err.message}`));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function runEvidenceSidecar(ctx, model, sidecar, quietSidecar) {
|
|
55
|
+
const { importRoleAssistantEvidence, logRoleAssistantEvidenceImportSummary } = require('../role-assistant/evidence-sync');
|
|
56
|
+
const result = await importRoleAssistantEvidence(buildRoleAssistantSyncContext(ctx, model));
|
|
57
|
+
sidecar.evidence = result;
|
|
58
|
+
if (!quietSidecar) {
|
|
59
|
+
logRoleAssistantEvidenceImportSummary(ctx.systemKey, result, { verbose: ctx.options.verbose === true });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function runKnowledgeSidecar(ctx, model, sidecar, quietSidecar) {
|
|
64
|
+
const {
|
|
65
|
+
importRoleAssistantKnowledge,
|
|
66
|
+
logKnowledgeImportSummary,
|
|
67
|
+
pushRoleAssistantDocumentStorageSettings,
|
|
68
|
+
logDocumentStorageSettingsPushSummary
|
|
69
|
+
} = require('../role-assistant/knowledge-sync');
|
|
70
|
+
const syncCtx = buildRoleAssistantSyncContext(ctx, model);
|
|
71
|
+
try {
|
|
72
|
+
const settingsResult = await pushRoleAssistantDocumentStorageSettings(syncCtx);
|
|
73
|
+
sidecar.documentStorageSettings = settingsResult;
|
|
74
|
+
if (!quietSidecar) {
|
|
75
|
+
logDocumentStorageSettingsPushSummary(ctx.systemKey, settingsResult, {
|
|
76
|
+
verbose: ctx.options.verbose === true
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
} catch (err) {
|
|
80
|
+
sidecar.documentStorageSettings = {
|
|
81
|
+
skipped: true,
|
|
82
|
+
reason: err.message || String(err)
|
|
83
|
+
};
|
|
84
|
+
if (!quietSidecar) {
|
|
85
|
+
logger.log(
|
|
86
|
+
formatWarningLine(
|
|
87
|
+
`Knowledge document storage settings update failed: ${err.message}`
|
|
88
|
+
)
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
throw err;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const result = await importRoleAssistantKnowledge(syncCtx);
|
|
95
|
+
sidecar.knowledge = result;
|
|
96
|
+
if (!quietSidecar) {
|
|
97
|
+
logKnowledgeImportSummary(ctx.systemKey, result, { verbose: ctx.options.verbose === true });
|
|
98
|
+
}
|
|
99
|
+
} catch (err) {
|
|
100
|
+
sidecar.knowledge = { skipped: true, reason: err.message || String(err) };
|
|
101
|
+
if (!quietSidecar) {
|
|
102
|
+
logger.log(formatWarningLine(`Role assistant knowledge sync skipped: ${err.message}`));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
15
107
|
/**
|
|
16
108
|
* Sidecar follow-ups that are independent of pipeline publish hash (scenario packs).
|
|
17
109
|
* @param {Object} ctx
|
|
18
110
|
* @returns {Promise<void>}
|
|
19
111
|
*/
|
|
20
112
|
async function runUploadSidecarFollowups(ctx) {
|
|
21
|
-
const
|
|
22
|
-
|
|
113
|
+
const sidecar = {
|
|
114
|
+
governance: null,
|
|
115
|
+
evidence: null,
|
|
116
|
+
knowledge: null,
|
|
117
|
+
documentStorageSettings: null
|
|
118
|
+
};
|
|
119
|
+
const quietSidecar = isQuietMinimalSync(ctx.options);
|
|
120
|
+
const model = buildRoleAssistantModel(ctx.payload);
|
|
121
|
+
await runGovernanceSidecar(ctx, sidecar, quietSidecar);
|
|
23
122
|
try {
|
|
24
|
-
|
|
25
|
-
await uploadGovernanceScenarioPacks(systemKey, dataplaneUrl, authConfig, { silent: quietSidecar });
|
|
123
|
+
await runEvidenceSidecar(ctx, model, sidecar, quietSidecar);
|
|
26
124
|
} catch (err) {
|
|
27
|
-
if (
|
|
28
|
-
|
|
125
|
+
if (err && err.evidenceSummary) {
|
|
126
|
+
sidecar.evidence = err.evidenceSummary;
|
|
29
127
|
}
|
|
128
|
+
throw err;
|
|
30
129
|
}
|
|
130
|
+
await runKnowledgeSidecar(ctx, model, sidecar, quietSidecar);
|
|
131
|
+
return sidecar;
|
|
31
132
|
}
|
|
32
133
|
|
|
33
134
|
/**
|
|
@@ -54,61 +155,57 @@ async function resolveUploadProbeData(ctx, maybeRunUploadProbeFn) {
|
|
|
54
155
|
return { probeData: null, compact };
|
|
55
156
|
}
|
|
56
157
|
|
|
158
|
+
function logUploadSummary(ctx, publication, probeData) {
|
|
159
|
+
if (ctx.options.suppressSummary === true) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
logUploadReadinessSummary({
|
|
163
|
+
environment: ctx.environment,
|
|
164
|
+
dataplaneUrl: ctx.dataplaneUrl,
|
|
165
|
+
systemKey: ctx.systemKey,
|
|
166
|
+
publication,
|
|
167
|
+
manifest: ctx.manifest,
|
|
168
|
+
minimal: !!ctx.options.minimal,
|
|
169
|
+
willProbe: false,
|
|
170
|
+
credentialPush: ctx.credentialPush,
|
|
171
|
+
configPush: ctx.configPush,
|
|
172
|
+
forcePublish: ctx.options.force === true,
|
|
173
|
+
probeData
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async function runProbeAfterSummary(ctx, maybeRunUploadProbe, compact) {
|
|
178
|
+
if (ctx.options.probe && !compact) {
|
|
179
|
+
await maybeRunUploadProbe(ctx.dataplaneUrl, ctx.systemKey, ctx.authConfig, ctx.options.probeTimeout, {
|
|
180
|
+
compact: false
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async function runSidecarAndWrap(ctx) {
|
|
186
|
+
const sidecar = await runUploadSidecarFollowups(ctx);
|
|
187
|
+
return { sidecar };
|
|
188
|
+
}
|
|
189
|
+
|
|
57
190
|
/**
|
|
58
191
|
* @param {Object} ctx
|
|
59
192
|
* @param {Function} maybeRunUploadProbe
|
|
60
193
|
* @returns {Promise<void>}
|
|
61
194
|
*/
|
|
62
195
|
async function handlePublicationAndFollowups(ctx, maybeRunUploadProbe) {
|
|
63
|
-
const
|
|
64
|
-
systemKey,
|
|
65
|
-
options,
|
|
66
|
-
manifest,
|
|
67
|
-
payload,
|
|
68
|
-
environment,
|
|
69
|
-
dataplaneUrl,
|
|
70
|
-
authConfig,
|
|
71
|
-
rawRes,
|
|
72
|
-
credentialPush,
|
|
73
|
-
configPush
|
|
74
|
-
} = ctx;
|
|
75
|
-
const publication = unwrapPublicationResult(rawRes);
|
|
196
|
+
const publication = unwrapPublicationResult(ctx.rawRes);
|
|
76
197
|
if (!publication) {
|
|
77
198
|
throw new Error(
|
|
78
199
|
'Unexpected response from dataplane upload: missing publication result (uploadId/system/datasources).'
|
|
79
200
|
);
|
|
80
201
|
}
|
|
81
202
|
if (isPublicationUnchanged(publication)) {
|
|
82
|
-
|
|
83
|
-
return;
|
|
203
|
+
return runSidecarAndWrap(ctx);
|
|
84
204
|
}
|
|
85
|
-
|
|
86
|
-
const suppressSummary = options.suppressSummary === true;
|
|
87
205
|
const { probeData, compact } = await resolveUploadProbeData(ctx, maybeRunUploadProbe);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
environment,
|
|
92
|
-
dataplaneUrl,
|
|
93
|
-
systemKey,
|
|
94
|
-
publication,
|
|
95
|
-
manifest,
|
|
96
|
-
minimal: !!options.minimal,
|
|
97
|
-
willProbe: false,
|
|
98
|
-
credentialPush,
|
|
99
|
-
configPush,
|
|
100
|
-
forcePublish: options.force === true,
|
|
101
|
-
probeData
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (options.probe && !compact) {
|
|
106
|
-
await maybeRunUploadProbe(dataplaneUrl, systemKey, authConfig, options.probeTimeout, {
|
|
107
|
-
compact: false
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
await runUploadSidecarFollowups({ systemKey, options, payload, dataplaneUrl, authConfig });
|
|
206
|
+
logUploadSummary(ctx, publication, probeData);
|
|
207
|
+
await runProbeAfterSummary(ctx, maybeRunUploadProbe, compact);
|
|
208
|
+
return runSidecarAndWrap(ctx);
|
|
112
209
|
}
|
|
113
210
|
|
|
114
211
|
module.exports = {
|
package/lib/commands/upload.js
CHANGED
|
@@ -47,6 +47,12 @@ const { syncDeployJsonFromSources } = require('../external-system/sync-deploy-ma
|
|
|
47
47
|
const { handlePublicationAndFollowups } = require('./upload-sidecar-followups');
|
|
48
48
|
const { finalizeUploadPublishResult, finishUnchangedUploadPublication } = require('./upload-data-sync-finalize');
|
|
49
49
|
const { pushAndLogCredentialSecrets } = require('./upload-credential-push-log');
|
|
50
|
+
const {
|
|
51
|
+
SYSTEM_KIND_DIGITAL_WORKER,
|
|
52
|
+
readRoleAssistantSettings,
|
|
53
|
+
resolveRoleAssistantSettingsVersion,
|
|
54
|
+
resolveRoleAssistantEnvironmentSettings
|
|
55
|
+
} = require('../role-assistant/settings');
|
|
50
56
|
|
|
51
57
|
/**
|
|
52
58
|
* Validates system-key format (same as download).
|
|
@@ -123,14 +129,24 @@ async function resolveDataplaneAndAuth(systemKey, opts = {}) {
|
|
|
123
129
|
* @param {string} dataplaneUrl - Dataplane base URL
|
|
124
130
|
* @param {Object} authConfig - Auth config
|
|
125
131
|
* @param {Object} payload - { version, application, dataSources, status: "draft" }
|
|
132
|
+
* @param {string} systemKey
|
|
133
|
+
* @param {Object} [options]
|
|
134
|
+
* @param {number|string} [options.timeoutMs]
|
|
126
135
|
* @returns {Promise<Object>} Raw API response envelope
|
|
127
136
|
*/
|
|
128
|
-
async function runUploadValidatePublish(
|
|
137
|
+
async function runUploadValidatePublish(
|
|
138
|
+
dataplaneUrl,
|
|
139
|
+
authConfig,
|
|
140
|
+
payload,
|
|
141
|
+
systemKey,
|
|
142
|
+
options = {}
|
|
143
|
+
) {
|
|
129
144
|
const res = await uploadApplicationViaPipelineWithAuthRetry(
|
|
130
145
|
dataplaneUrl,
|
|
131
146
|
authConfig,
|
|
132
147
|
payload,
|
|
133
|
-
systemKey
|
|
148
|
+
systemKey,
|
|
149
|
+
{ timeoutMs: options.timeoutMs }
|
|
134
150
|
);
|
|
135
151
|
if (res?.success === false) {
|
|
136
152
|
throw new Error(formatApiError(res, dataplaneUrl));
|
|
@@ -231,6 +247,14 @@ async function buildValidatedUploadManifestPayload(systemKey, opts = {}) {
|
|
|
231
247
|
force: opts.force === true,
|
|
232
248
|
status: opts.uploadStatus === 'published' ? 'published' : 'draft'
|
|
233
249
|
});
|
|
250
|
+
if (String(manifest?.system?.systemKind || '').trim() === SYSTEM_KIND_DIGITAL_WORKER) {
|
|
251
|
+
const settings = readRoleAssistantSettings(systemKey, { required: true, pathOptions });
|
|
252
|
+
resolveRoleAssistantEnvironmentSettings(settings, opts.env || 'dev', { required: true });
|
|
253
|
+
const settingsVersion = resolveRoleAssistantSettingsVersion(settings);
|
|
254
|
+
if (settingsVersion) {
|
|
255
|
+
payload.version = settingsVersion;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
234
258
|
await resolvePayloadConfiguration(systemKey, payload, pathOptions);
|
|
235
259
|
return { manifest, payload };
|
|
236
260
|
}
|
|
@@ -264,7 +288,10 @@ async function logAndSyncLocalOpenApiForUpload(systemKey, manifest, uploadContex
|
|
|
264
288
|
systemKey,
|
|
265
289
|
datasourceFiles,
|
|
266
290
|
dataplaneUrl: uploadContext.dataplaneUrl,
|
|
267
|
-
authConfig: uploadContext.authConfig
|
|
291
|
+
authConfig: uploadContext.authConfig,
|
|
292
|
+
// Always replace SpecFile rows keyed by openapi.documentKey so vendor/full
|
|
293
|
+
// specs are not left missing while only thin internal:* slices remain.
|
|
294
|
+
force: true
|
|
268
295
|
});
|
|
269
296
|
if (!uploadContext.quiet) {
|
|
270
297
|
for (const line of openapiSyncLines) {
|
|
@@ -293,7 +320,7 @@ async function completeUploadAfterPublish(systemKey, options, manifest, payload,
|
|
|
293
320
|
pathOptions: options.pathOptions,
|
|
294
321
|
quiet: quietCompact
|
|
295
322
|
});
|
|
296
|
-
await handlePublicationAndFollowups(
|
|
323
|
+
const followupResult = await handlePublicationAndFollowups(
|
|
297
324
|
{
|
|
298
325
|
systemKey,
|
|
299
326
|
options,
|
|
@@ -309,7 +336,13 @@ async function completeUploadAfterPublish(systemKey, options, manifest, payload,
|
|
|
309
336
|
maybeRunUploadProbe
|
|
310
337
|
);
|
|
311
338
|
return finalizeUploadPublishResult(
|
|
312
|
-
{
|
|
339
|
+
{
|
|
340
|
+
dataplaneUrl: ctx.dataplaneUrl,
|
|
341
|
+
authConfig: ctx.authConfig,
|
|
342
|
+
environment: ctx.environment,
|
|
343
|
+
uploadSkipped: false,
|
|
344
|
+
sidecar: followupResult?.sidecar || null
|
|
345
|
+
},
|
|
313
346
|
payload,
|
|
314
347
|
options
|
|
315
348
|
);
|
|
@@ -331,7 +364,10 @@ async function runUploadPublishAndSummary(systemKey, options, manifest, payload)
|
|
|
331
364
|
payload
|
|
332
365
|
);
|
|
333
366
|
const rawRes = await runWithUploadPipelineSpinner(
|
|
334
|
-
async() =>
|
|
367
|
+
async() =>
|
|
368
|
+
runUploadValidatePublish(dataplaneUrl, authConfig, payload, systemKey, {
|
|
369
|
+
timeoutMs: options.timeoutMs
|
|
370
|
+
}),
|
|
335
371
|
{
|
|
336
372
|
systemKey,
|
|
337
373
|
json: options.json === true,
|
|
@@ -367,6 +403,7 @@ async function runUploadPublishAndSummary(systemKey, options, manifest, payload)
|
|
|
367
403
|
* @param {boolean} [options.verbose] - Expanded summary and server-side pipeline validate warnings
|
|
368
404
|
* @param {boolean} [options.probe] - POST validation/run after publish
|
|
369
405
|
* @param {number} [options.probeTimeout] - Probe timeout ms (default 120000)
|
|
406
|
+
* @param {number} [options.timeoutMs] - Pipeline publish timeout ms (HTTP + dataplane; default 300000)
|
|
370
407
|
* @param {boolean} [options.minimal] - Short summary (default: compact unless --verbose)
|
|
371
408
|
* @returns {Promise<{ dataplaneUrl: string, authConfig: Object, environment: string }|void>}
|
|
372
409
|
* @throws {Error} If validation or API calls fail
|