@aifabrix/builder 2.50.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/.cursor/plans/Done/157.1-security-quality-violations-by-type.csv +374 -0
- package/.cursor/rules/assistant-driven-integration-build.mdc +40 -0
- package/integration/hubspot-test/create-hubspot.js +1 -16
- 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-kinds.api.js +128 -0
- package/lib/api/evidence.api.js +57 -1
- package/lib/api/index.js +24 -7
- package/lib/api/pipeline.api.js +47 -3
- package/lib/api/records-bulk.api.js +28 -3
- package/lib/api/resource-types.api.js +4 -4
- package/lib/api/roles.api.js +121 -0
- package/lib/api/types/evidence-kinds.types.js +42 -0
- package/lib/api/types/evidence.types.js +156 -8
- package/lib/api/types/roles.types.js +36 -0
- package/lib/api/work.api.js +283 -0
- package/lib/app/certification-verify-rows.js +1 -1
- 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/app/show.js +2 -2
- package/lib/certification/merge-certification-from-artifact.js +1 -1
- 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 +16 -3
- 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 +6 -0
- package/lib/cli/setup-app.js +26 -5
- package/lib/cli/setup-dev.js +23 -7
- package/lib/cli/setup-external-system-help.js +8 -2
- package/lib/cli/setup-external-system.js +12 -0
- package/lib/cli/setup-utility-help-after.js +12 -0
- package/lib/cli/setup-utility-validate.js +41 -2
- 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 +23 -0
- package/lib/commands/deploy-gate-orchestrator.js +64 -18
- package/lib/commands/dev-cli-handlers.js +6 -3
- package/lib/commands/dev-down.js +2 -6
- package/lib/commands/dev-init.js +7 -109
- package/lib/commands/dev-refresh.js +197 -0
- package/lib/commands/evidence-kind.js +478 -0
- package/lib/commands/governance-command-action.js +4 -2
- 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-export.js +1 -1
- package/lib/commands/repair-openapi-sync.js +43 -18
- package/lib/commands/resource-type.js +101 -18
- package/lib/commands/role-assistant.js +313 -0
- package/lib/commands/role.js +452 -0
- package/lib/commands/setup.js +1 -1
- 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/validate-json.js +230 -0
- 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/verify-operations-step-plan.js +78 -40
- package/lib/commands/wizard-core-helpers.js +7 -3
- package/lib/commands/wizard-core.js +78 -9
- package/lib/core/audit-logger.js +1 -1
- package/lib/core/secrets-load.js +1 -3
- package/lib/datasource/bulk-loader-run-batches.js +4 -2
- package/lib/datasource/bulk-loader-service.js +5 -1
- package/lib/datasource/capability/relate-operations.js +1 -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/helpers.js +13 -5
- package/lib/generator/split-variables.js +9 -3
- package/lib/generator/wizard.js +51 -4
- package/lib/infrastructure/helpers-docker-check.js +6 -0
- package/lib/infrastructure/helpers.js +1 -1
- 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/auth-config.js +3 -2
- package/lib/programmatic/bearer-auth.js +1 -1
- package/lib/programmatic/capability-registry.js +20 -1
- package/lib/programmatic/command-options.js +1 -0
- package/lib/programmatic/enterprise-mcp-client.js +18 -2
- 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/manifest-section-registry.js +18 -1
- 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 +29 -12
- package/lib/programmatic/openapi-schema-descriptions-certify.js +5 -1
- package/lib/programmatic/openapi-schema-descriptions-core.js +6 -3
- 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-schema-helpers.js +16 -1
- package/lib/programmatic/openapi-spec.js +48 -29
- 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-repository-emcp.js +11 -3
- package/lib/programmatic/run-template-workspace.js +42 -2
- 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/resolvers/evidence-kind-file.js +230 -0
- package/lib/resolvers/resource-type-file.js +36 -1
- package/lib/resolvers/role-file.js +227 -0
- 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 +36 -2
- package/lib/schema/deployment-rules.yaml +1 -0
- package/lib/schema/external-datasource.schema.json +121 -4
- package/lib/schema/external-system.schema.json +20 -6
- package/lib/schema/infra.parameter.yaml +45 -1
- package/lib/schema/role-assistant-settings.schema.json +108 -0
- package/lib/schema/type/credential-field-registry.json +19 -3
- package/lib/utils/api.js +52 -21
- package/lib/utils/app-path-resolve.js +72 -24
- package/lib/utils/app-register-config.js +4 -3
- package/lib/utils/authentication-shape.js +3 -1
- package/lib/utils/cli-sync-options.js +59 -3
- package/lib/utils/cli-utils.js +11 -3
- package/lib/utils/deployment-validation.js +28 -3
- package/lib/utils/dev-ca-install.js +5 -6
- package/lib/utils/dev-config.js +2 -2
- package/lib/utils/dev-list-sort.js +145 -0
- package/lib/utils/dev-platform-tls.js +0 -63
- package/lib/utils/docker-build.js +46 -27
- package/lib/utils/docker-daemon-tls-ca.js +1 -1
- package/lib/utils/docker-exec.js +91 -6
- 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 +35 -4
- package/lib/utils/error-formatters/error-parser.js +0 -3
- package/lib/utils/external-env-template.js +1 -1
- package/lib/utils/external-system-readiness-compact-blocks.js +28 -1
- package/lib/utils/external-system-readiness-compact-display.js +3 -0
- package/lib/utils/health-check-request.js +2 -3
- package/lib/utils/help-builder.js +4 -0
- package/lib/utils/image-name.js +22 -4
- package/lib/utils/logger.js +37 -4
- package/lib/utils/manifest-source-emit.js +1 -1
- package/lib/utils/paths.js +98 -26
- package/lib/utils/pipeline-upload-auth-retry.js +19 -3
- package/lib/utils/postgres-platform-bootstrap.js +24 -17
- package/lib/utils/postgres-wipe.js +5 -2
- package/lib/utils/remote-dev-auth.js +39 -4
- package/lib/utils/resolve-docker-image-ref.js +36 -6
- 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 +47 -22
- package/lib/utils/upload-sync-options.js +17 -3
- package/lib/utils/url-declarative-resolve-load-doc.js +38 -1
- package/lib/validation/external-manifest-validator.js +31 -8
- package/lib/validation/openapi-contract-surface-validator.js +4 -0
- package/lib/validation/validate-external-file.js +8 -1
- package/lib/validation/validator.js +6 -5
- package/package.json +35 -12
- package/scripts/export-builder-api-evidence.js +3 -3
- package/scripts/lib/plan-actor.js +2 -2
- package/scripts/lib/plan-meta.js +1 -1
- package/scripts/lib/plan-parse.js +1 -1
- package/scripts/lib/plan-prevalidate-gates.js +12 -1
- package/scripts/lib/plan-run-report.js +13 -2
- package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +10 -10
- package/templates/applications/dataplane/application.yaml +47 -17
- package/templates/applications/dataplane/env.template +28 -9
- package/templates/applications/dataplane/rbac.yaml +78 -2
- package/templates/applications/miso-controller/application.yaml +10 -1
- package/templates/applications/miso-controller/env.template +13 -8
- package/templates/applications/miso-controller/rbac.yaml +72 -0
- 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/templates/channels/slack/integration/slack-system.json +60 -2
- package/templates/python/requirements.txt +1 -1
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve Runtime Layer B tool names from Dataplane.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Runtime-orchestration MCP tool discovery for channel artifacts and probes
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.1.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const { createDataplaneApiClient } = require('../api/index');
|
|
12
|
+
const { getChannelTarget } = require('./channel-targets');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Prefer the first-party MCP gateway catalog, then MCP OpenAPI, then legacy paths.
|
|
16
|
+
*/
|
|
17
|
+
const TOOL_CATALOG_BUILDERS = Object.freeze([
|
|
18
|
+
(systemKey) =>
|
|
19
|
+
`/api/v1/mcp/servers/tools?filter=${encodeURIComponent(`systemKey:eq:${systemKey}`)}&pageSize=100`,
|
|
20
|
+
(systemKey) => `/api/v1/mcp/${systemKey}/docs/mcp-openapi.json`,
|
|
21
|
+
(systemKey) => `/api/v1/external/systems/${systemKey}/mcp/tools`,
|
|
22
|
+
(systemKey) => `/api/v1/external/systems/${systemKey}/mcp/tools/list`,
|
|
23
|
+
(systemKey) => `/api/v1/external/systems/${systemKey}/mcp/catalog`,
|
|
24
|
+
(systemKey) => `/api/v1/external/systems/${systemKey}/tools`
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {unknown} value
|
|
29
|
+
* @returns {string[]}
|
|
30
|
+
*/
|
|
31
|
+
function extractToolNames(value) {
|
|
32
|
+
if (Array.isArray(value)) {
|
|
33
|
+
return value
|
|
34
|
+
.map((item) => {
|
|
35
|
+
if (typeof item === 'string') return item.trim();
|
|
36
|
+
if (!item || typeof item !== 'object') return '';
|
|
37
|
+
return String(item.name || item.toolName || item.key || '').trim();
|
|
38
|
+
})
|
|
39
|
+
.filter(Boolean);
|
|
40
|
+
}
|
|
41
|
+
if (!value || typeof value !== 'object') {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
const body = /** @type {Record<string, unknown>} */ (value);
|
|
45
|
+
if (body.paths && typeof body.paths === 'object') {
|
|
46
|
+
return extractToolNamesFromOpenApiPaths(body.paths);
|
|
47
|
+
}
|
|
48
|
+
const candidates = [body.tools, body.items, body.data, body.result];
|
|
49
|
+
for (const candidate of candidates) {
|
|
50
|
+
const names = extractToolNames(candidate);
|
|
51
|
+
if (names.length > 0) {
|
|
52
|
+
return names;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @param {Record<string, unknown>} paths
|
|
60
|
+
* @returns {string[]}
|
|
61
|
+
*/
|
|
62
|
+
function extractToolNamesFromOpenApiPaths(paths) {
|
|
63
|
+
const names = [];
|
|
64
|
+
for (const pathKey of Object.keys(paths || {})) {
|
|
65
|
+
const match = String(pathKey).match(/\/tools\/([^/]+)\/execute$/);
|
|
66
|
+
if (match && match[1] && match[1] !== 'execute') {
|
|
67
|
+
names.push(match[1]);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return [...new Set(names)];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @param {string} routeSystemKey
|
|
75
|
+
* @returns {string[]}
|
|
76
|
+
*/
|
|
77
|
+
function buildToolCatalogEndpoints(routeSystemKey) {
|
|
78
|
+
return TOOL_CATALOG_BUILDERS.map((build) => build(routeSystemKey));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @param {Object} response
|
|
83
|
+
* @returns {string[]}
|
|
84
|
+
*/
|
|
85
|
+
function extractToolNamesFromClientResponse(response) {
|
|
86
|
+
const direct = extractToolNames(response);
|
|
87
|
+
if (direct.length > 0) return preferLayerBToolNames(direct);
|
|
88
|
+
return preferLayerBToolNames(extractToolNames(response?.data ?? response));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Prefer MCP Layer B names (`work.start`) over REST-ish operation ids.
|
|
93
|
+
*
|
|
94
|
+
* @param {string[]} names
|
|
95
|
+
* @returns {string[]}
|
|
96
|
+
*/
|
|
97
|
+
function preferLayerBToolNames(names) {
|
|
98
|
+
const list = Array.isArray(names) ? names : [];
|
|
99
|
+
const dotted = list.filter((name) => /^[a-z][a-z0-9]*\.[a-z][a-z0-9.]*$/i.test(name));
|
|
100
|
+
return dotted.length > 0 ? dotted : list;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @param {string} dataplaneUrl
|
|
105
|
+
* @param {Object} authConfig
|
|
106
|
+
* @param {string} channelTarget
|
|
107
|
+
* @returns {Promise<string[]>}
|
|
108
|
+
*/
|
|
109
|
+
async function fetchRuntimeLayerBToolNames(dataplaneUrl, authConfig, channelTarget) {
|
|
110
|
+
const target = getChannelTarget(channelTarget);
|
|
111
|
+
const routeSystemKey = target.routeSystemKey || target.key;
|
|
112
|
+
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
113
|
+
const endpoints = buildToolCatalogEndpoints(routeSystemKey);
|
|
114
|
+
for (const endpoint of endpoints) {
|
|
115
|
+
try {
|
|
116
|
+
const response = await client.get(endpoint, { timeoutMs: 10000 });
|
|
117
|
+
const names = extractToolNamesFromClientResponse(response);
|
|
118
|
+
if (Array.isArray(names) && names.length > 0) {
|
|
119
|
+
return [...new Set(names)].sort();
|
|
120
|
+
}
|
|
121
|
+
} catch {
|
|
122
|
+
// Try the next endpoint candidate.
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* True when Runtime MCP gateway docs or tool catalog is reachable.
|
|
130
|
+
*
|
|
131
|
+
* @async
|
|
132
|
+
* @param {string} dataplaneUrl
|
|
133
|
+
* @param {Object} authConfig
|
|
134
|
+
* @param {string} routeSystemKey
|
|
135
|
+
* @returns {Promise<boolean>}
|
|
136
|
+
*/
|
|
137
|
+
async function isRuntimeMcpGatewayReachable(dataplaneUrl, authConfig, routeSystemKey) {
|
|
138
|
+
if (!dataplaneUrl || !routeSystemKey) return false;
|
|
139
|
+
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
140
|
+
const candidates = [
|
|
141
|
+
`/api/v1/mcp/${routeSystemKey}/docs/mcp-openapi.json`,
|
|
142
|
+
`/api/v1/mcp/servers/tools?filter=${encodeURIComponent(`systemKey:eq:${routeSystemKey}`)}&pageSize=1`
|
|
143
|
+
];
|
|
144
|
+
for (const endpoint of candidates) {
|
|
145
|
+
try {
|
|
146
|
+
const response = await client.get(endpoint, { timeoutMs: 8000 });
|
|
147
|
+
if (response && response.success !== false) {
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
} catch {
|
|
151
|
+
// try next
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
module.exports = {
|
|
158
|
+
TOOL_CATALOG_BUILDERS,
|
|
159
|
+
extractToolNames,
|
|
160
|
+
extractToolNamesFromOpenApiPaths,
|
|
161
|
+
preferLayerBToolNames,
|
|
162
|
+
buildToolCatalogEndpoints,
|
|
163
|
+
fetchRuntimeLayerBToolNames,
|
|
164
|
+
isRuntimeMcpGatewayReachable
|
|
165
|
+
};
|
package/lib/cli/index.js
CHANGED
|
@@ -23,6 +23,9 @@ const { setupAppCommands: setupAppManagementCommands } = require('../commands/ap
|
|
|
23
23
|
const { setupDatasourceCommands } = require('../commands/datasource');
|
|
24
24
|
const { setupDimensionCommands } = require('../commands/dimension');
|
|
25
25
|
const { setupResourceTypeCommands } = require('../commands/resource-type');
|
|
26
|
+
const { setupRoleCommands } = require('../commands/role');
|
|
27
|
+
const { setupRoleAssistantCommands } = require('../commands/role-assistant');
|
|
28
|
+
const { setupEvidenceKindCommands } = require('../commands/evidence-kind');
|
|
26
29
|
const { setupEnterpriseKnowledgeCommands } = require('../commands/enterprise-knowledge');
|
|
27
30
|
const { setupIdentityCommands } = require('../commands/identity');
|
|
28
31
|
const { setupProtectionCommands } = require('../commands/protection');
|
|
@@ -73,6 +76,9 @@ function setupCoreCliCommands(program) {
|
|
|
73
76
|
function setupExtendedCliCommands(program) {
|
|
74
77
|
setupDimensionCommands(program);
|
|
75
78
|
setupResourceTypeCommands(program);
|
|
79
|
+
setupRoleCommands(program);
|
|
80
|
+
setupRoleAssistantCommands(program);
|
|
81
|
+
setupEvidenceKindCommands(program);
|
|
76
82
|
setupEnterpriseKnowledgeCommands(program);
|
|
77
83
|
setupIdentityCommands(program);
|
|
78
84
|
setupProtectionCommands(program);
|
package/lib/cli/setup-app.js
CHANGED
|
@@ -56,12 +56,18 @@ Examples:
|
|
|
56
56
|
$ aifabrix validate hubspot-demo
|
|
57
57
|
$ aifabrix upload hubspot-demo --probe
|
|
58
58
|
$ aifabrix deploy hubspot-demo --probe -v
|
|
59
|
+
# Prove pillars in tst/CI, then promote (plain deploy seals cert on published Deploy)
|
|
59
60
|
$ aifabrix deploy ek-sales --gate full --subject-email ops@example.com
|
|
61
|
+
$ aifabrix deploy ek-sales
|
|
60
62
|
|
|
61
63
|
Notes:
|
|
62
64
|
- Login or set MISO_CONTROLLER_URL + environment (aifabrix login / aifabrix auth).
|
|
63
65
|
- CI: register once (aifabrix app register <appKey>), store DEV_MISO_CLIENTID and DEV_MISO_CLIENTSECRET in pipeline secrets.
|
|
64
66
|
- upload = dataplane publish for dev iteration; deploy = controller validate + deploy (Azure or local Docker).
|
|
67
|
+
- Prove (tst/CI): use --gate full (optional --subject-email) before promote; plain deploy promotes without live E2E gates.
|
|
68
|
+
- After a successful published Deploy, the platform seals the integration certificate (no separate certificates issue step).
|
|
69
|
+
- Default output is a compact status card; use -v for expanded preflight and readiness detail.
|
|
70
|
+
- Controller deploy always polls to a terminal status (no --poll / --no-poll on this command).
|
|
65
71
|
- --repository-url overrides repo URL for pipeline validate (default: application.yaml repository.repositoryUrl).
|
|
66
72
|
`;
|
|
67
73
|
|
|
@@ -219,7 +225,7 @@ Examples:
|
|
|
219
225
|
});
|
|
220
226
|
}
|
|
221
227
|
|
|
222
|
-
function
|
|
228
|
+
function registerBuildCommand(program) {
|
|
223
229
|
program.command('build <appKey>')
|
|
224
230
|
.description('Build Docker image for builder appKey (auto-detect runtime)')
|
|
225
231
|
.option('-l, --language <lang>', 'Override language detection')
|
|
@@ -243,9 +249,9 @@ function setupBuildRunLogsDownCommands(program) {
|
|
|
243
249
|
process.exit(1);
|
|
244
250
|
}
|
|
245
251
|
});
|
|
252
|
+
}
|
|
246
253
|
|
|
247
|
-
|
|
248
|
-
|
|
254
|
+
function registerLogsCommand(program) {
|
|
249
255
|
program.command('logs <appKey>')
|
|
250
256
|
.description('Tail container logs for appKey (optional env summary; secrets masked)')
|
|
251
257
|
.option('-f', 'Follow log stream')
|
|
@@ -256,14 +262,22 @@ function setupBuildRunLogsDownCommands(program) {
|
|
|
256
262
|
try {
|
|
257
263
|
const { runAppLogs } = require('../commands/app-logs');
|
|
258
264
|
const tailNum = parseInt(options.tail, 10);
|
|
259
|
-
const level = options.level !== undefined && options.level !== null && options.level !== ''
|
|
260
|
-
|
|
265
|
+
const level = options.level !== undefined && options.level !== null && options.level !== ''
|
|
266
|
+
? String(options.level).trim()
|
|
267
|
+
: undefined;
|
|
268
|
+
await runAppLogs(appName, {
|
|
269
|
+
follow: options.f,
|
|
270
|
+
tail: Number.isNaN(tailNum) ? 100 : tailNum,
|
|
271
|
+
level
|
|
272
|
+
});
|
|
261
273
|
} catch (error) {
|
|
262
274
|
handleCommandError(error, 'logs');
|
|
263
275
|
process.exit(1);
|
|
264
276
|
}
|
|
265
277
|
});
|
|
278
|
+
}
|
|
266
279
|
|
|
280
|
+
function registerDownAppCommand(program) {
|
|
267
281
|
program.command('down-app <appKey>')
|
|
268
282
|
.description('Stop and remove container for appKey (--volumes removes data volume)')
|
|
269
283
|
.option('--volumes', 'Remove application Docker volume')
|
|
@@ -278,6 +292,13 @@ function setupBuildRunLogsDownCommands(program) {
|
|
|
278
292
|
});
|
|
279
293
|
}
|
|
280
294
|
|
|
295
|
+
function setupBuildRunLogsDownCommands(program) {
|
|
296
|
+
registerBuildCommand(program);
|
|
297
|
+
registerRunCommand(program);
|
|
298
|
+
registerLogsCommand(program);
|
|
299
|
+
registerDownAppCommand(program);
|
|
300
|
+
}
|
|
301
|
+
|
|
281
302
|
function setupShellTestStopCommands(program) {
|
|
282
303
|
program.command('stop <appKey>')
|
|
283
304
|
.description('Alias for down-app: stop and remove container for appKey')
|
package/lib/cli/setup-dev.js
CHANGED
|
@@ -12,7 +12,8 @@ const config = require('../core/config');
|
|
|
12
12
|
const logger = require('../utils/logger');
|
|
13
13
|
const { handleCommandError } = require('../utils/cli-utils');
|
|
14
14
|
const { setupDevPathAndFormatCommands } = require('./setup-dev-path-commands');
|
|
15
|
-
const { runDevInit
|
|
15
|
+
const { runDevInit } = require('../commands/dev-init');
|
|
16
|
+
const { runDevRefresh, ensureDevCertFreshIfDue } = require('../commands/dev-refresh');
|
|
16
17
|
const { displayDevConfig } = require('../commands/dev-show-display');
|
|
17
18
|
const {
|
|
18
19
|
handleDevList,
|
|
@@ -49,11 +50,21 @@ Examples:
|
|
|
49
50
|
Requires a configured remote Builder Server and an admin client certificate (same machine setup as dev list / dev pin). After add, run dev pin <id> once to create a PIN for aifabrix dev init.
|
|
50
51
|
`;
|
|
51
52
|
|
|
53
|
+
/** Appended to `dev list --help` (sort examples). */
|
|
54
|
+
const DEV_LIST_HELP_AFTER = `
|
|
55
|
+
Examples:
|
|
56
|
+
$ aifabrix dev list
|
|
57
|
+
$ aifabrix dev list --sort id
|
|
58
|
+
$ aifabrix dev list --sort -until
|
|
59
|
+
|
|
60
|
+
Sort fields: id, name, email, until. Prefix - for descending (default: name ascending).
|
|
61
|
+
`;
|
|
62
|
+
|
|
52
63
|
/** Appended to `aifabrix dev --help` (overview; keep subcommand .description lines short). */
|
|
53
64
|
const DEV_GROUP_HELP_AFTER = `
|
|
54
65
|
Categories:
|
|
55
66
|
Local config show, set-id, set-scoped-resources, set-env-config, set-home, set-work, set-format, print-home, print-work
|
|
56
|
-
Onboarding init (PIN onboarding), refresh (sync settings / renew cert)
|
|
67
|
+
Onboarding init (PIN onboarding), refresh (sync settings / renew cert); show auto-renews when due
|
|
57
68
|
Remote admin list, add, update, pin, delete, platform-install, platform-update, platform-install-cli (need remote-server + client cert in ~/.aifabrix)
|
|
58
69
|
Sync / stop down (Mutagen; optional --apps for containers)
|
|
59
70
|
|
|
@@ -168,9 +179,10 @@ async function handleSetScopedResources(value) {
|
|
|
168
179
|
function setupDevShowAndSetId(dev) {
|
|
169
180
|
dev
|
|
170
181
|
.command('show')
|
|
171
|
-
.description('Show dev ports and ~/.aifabrix config')
|
|
182
|
+
.description('Show dev ports and ~/.aifabrix config (auto-renews cert when due)')
|
|
172
183
|
.action(async() => {
|
|
173
184
|
try {
|
|
185
|
+
await ensureDevCertFreshIfDue();
|
|
174
186
|
const devId = await config.getDeveloperId();
|
|
175
187
|
await displayDevConfig(devId);
|
|
176
188
|
} catch (error) {
|
|
@@ -286,9 +298,14 @@ function setupDevListAddCommands(dev) {
|
|
|
286
298
|
dev
|
|
287
299
|
.command('list')
|
|
288
300
|
.description('List developers (remote Builder Server)')
|
|
289
|
-
.
|
|
301
|
+
.option(
|
|
302
|
+
'--sort <field>',
|
|
303
|
+
'Sort field/direction (id|name|email|until; prefix - for descending; default name)'
|
|
304
|
+
)
|
|
305
|
+
.addHelpText('after', DEV_LIST_HELP_AFTER)
|
|
306
|
+
.action(async(options) => {
|
|
290
307
|
try {
|
|
291
|
-
await handleDevList();
|
|
308
|
+
await handleDevList(options);
|
|
292
309
|
} catch (error) {
|
|
293
310
|
handleCommandError(error, 'dev list');
|
|
294
311
|
process.exit(1);
|
|
@@ -398,8 +415,6 @@ function setupDevUpdatePinDeleteCommands(dev) {
|
|
|
398
415
|
process.exit(1);
|
|
399
416
|
}
|
|
400
417
|
});
|
|
401
|
-
|
|
402
|
-
setupDevDownCommand(dev);
|
|
403
418
|
}
|
|
404
419
|
|
|
405
420
|
/**
|
|
@@ -457,6 +472,7 @@ function setupDevPlatformCommands(dev) {
|
|
|
457
472
|
function setupDevUserCommands(dev) {
|
|
458
473
|
setupDevListAddCommands(dev);
|
|
459
474
|
setupDevUpdatePinDeleteCommands(dev);
|
|
475
|
+
setupDevDownCommand(dev);
|
|
460
476
|
setupDevPlatformCommands(dev);
|
|
461
477
|
}
|
|
462
478
|
|
|
@@ -10,6 +10,7 @@ Examples:
|
|
|
10
10
|
$ aifabrix upload hubspot-demo
|
|
11
11
|
$ aifabrix upload hubspot-demo -v
|
|
12
12
|
$ aifabrix upload hubspot-demo --probe
|
|
13
|
+
$ aifabrix upload hubspot-demo --timeout 600000
|
|
13
14
|
|
|
14
15
|
# Build and validate payload only (no API calls)
|
|
15
16
|
$ aifabrix upload hubspot-demo --dry-run
|
|
@@ -18,11 +19,16 @@ Examples:
|
|
|
18
19
|
$ aifabrix upload .protection
|
|
19
20
|
$ aifabrix upload .protection --warnings-as-errors
|
|
20
21
|
|
|
22
|
+
# Role Assistant package (settings section + Evidence sidecars)
|
|
23
|
+
$ aifabrix upload sales-representative --env dev
|
|
24
|
+
|
|
21
25
|
Notes:
|
|
22
26
|
- Requires login (aifabrix auth status).
|
|
23
|
-
- Reads files under integration/<systemKey>/
|
|
27
|
+
- Reads files under integration/<systemKey>/ or role-assistant/<roleKey>/ for digital workers.
|
|
24
28
|
- Default output is a compact readiness summary; use -v for expanded detail and server-side validate warnings.
|
|
25
|
-
- --probe runs dataplane runtime checks after publish (slower
|
|
29
|
+
- --probe runs dataplane runtime checks after publish (slower).
|
|
30
|
+
- --timeout sets publish budget in ms (HTTP client and dataplane); default 300000.
|
|
31
|
+
- --env selects role-assistant.yaml section (dev|tst|pro) for digital workers; default dev.
|
|
26
32
|
- test-e2e and test-integration publish local files first by default; use --no-publish on those commands to skip.
|
|
27
33
|
- After dimension/FK edits on active datasources, use --force (or test-e2e / test-integration / datasource test-* with --sync --force).
|
|
28
34
|
- For one datasource only: aifabrix datasource upload <datasourceKey>
|
|
@@ -45,13 +45,16 @@ async function handleUploadCommandAction(systemKey, options) {
|
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
const upload = require('../commands/upload');
|
|
48
|
+
const { resolvePipelineUploadTimeoutMs } = require('../api/pipeline.api');
|
|
48
49
|
const probeTimeout =
|
|
49
50
|
options.probeTimeout === undefined || options.probeTimeout === null
|
|
50
51
|
? 120000
|
|
51
52
|
: Number(options.probeTimeout);
|
|
53
|
+
const timeoutMs = resolvePipelineUploadTimeoutMs(options.timeout);
|
|
52
54
|
await upload.uploadExternalSystem(systemKey, {
|
|
53
55
|
...options,
|
|
54
56
|
probeTimeout: Number.isFinite(probeTimeout) ? probeTimeout : 120000,
|
|
57
|
+
timeoutMs,
|
|
55
58
|
pathOptions: {}
|
|
56
59
|
});
|
|
57
60
|
}
|
|
@@ -98,10 +101,19 @@ function setupUploadCommand(program) {
|
|
|
98
101
|
.option('-v, --verbose', 'Expanded upload summary and server-side pipeline validate warnings before publish')
|
|
99
102
|
.option('--probe', 'After publish, run dataplane runtime checks (validation/run); slower')
|
|
100
103
|
.option('--probe-timeout <ms>', 'Timeout for --probe (default: 120000)', '120000')
|
|
104
|
+
.option(
|
|
105
|
+
'--timeout <ms>',
|
|
106
|
+
'Publish timeout in ms for HTTP and dataplane budget (default: 300000; min 5000, max 2700000)'
|
|
107
|
+
)
|
|
101
108
|
.option(
|
|
102
109
|
'--force',
|
|
103
110
|
'Bypass schema guards on active datasources during publish (dangerous; shows a warning)'
|
|
104
111
|
)
|
|
112
|
+
.option(
|
|
113
|
+
'-e, --env <env>',
|
|
114
|
+
'Role Assistant settings environment section: dev, tst, or pro (default: dev)',
|
|
115
|
+
'dev'
|
|
116
|
+
)
|
|
105
117
|
.action(async(systemKey, options) => {
|
|
106
118
|
try {
|
|
107
119
|
await handleUploadCommandAction(systemKey, options);
|
|
@@ -18,6 +18,17 @@ Examples:
|
|
|
18
18
|
$ aifabrix validate --builder
|
|
19
19
|
`;
|
|
20
20
|
|
|
21
|
+
const VALIDATE_JSON_HELP_AFTER = `
|
|
22
|
+
Examples:
|
|
23
|
+
$ aifabrix validate-json myapp
|
|
24
|
+
$ aifabrix validate-json my-system
|
|
25
|
+
$ aifabrix validate-json --integration
|
|
26
|
+
$ aifabrix validate-json --builder
|
|
27
|
+
$ aifabrix validate-json --integration --builder --format json
|
|
28
|
+
|
|
29
|
+
Runs full local validation first; writes *-deploy.json only when validation succeeds (offline).
|
|
30
|
+
`;
|
|
31
|
+
|
|
21
32
|
const REPAIR_HELP_AFTER = `
|
|
22
33
|
Examples:
|
|
23
34
|
$ aifabrix repair hubspot-demo
|
|
@@ -63,6 +74,7 @@ Examples:
|
|
|
63
74
|
module.exports = {
|
|
64
75
|
JSON_HELP_AFTER,
|
|
65
76
|
VALIDATE_HELP_AFTER,
|
|
77
|
+
VALIDATE_JSON_HELP_AFTER,
|
|
66
78
|
REPAIR_HELP_AFTER,
|
|
67
79
|
RESOLVE_HELP_AFTER
|
|
68
80
|
};
|
|
@@ -12,7 +12,7 @@ const fs = require('fs');
|
|
|
12
12
|
const chalk = require('chalk');
|
|
13
13
|
const logger = require('../utils/logger');
|
|
14
14
|
const { handleCommandError } = require('../utils/cli-utils');
|
|
15
|
-
const { VALIDATE_HELP_AFTER } = require('./setup-utility-help-after');
|
|
15
|
+
const { VALIDATE_HELP_AFTER, VALIDATE_JSON_HELP_AFTER } = require('./setup-utility-help-after');
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @param {string} appOrFile
|
|
@@ -154,7 +154,7 @@ async function runValidateCommand(appOrFile, options) {
|
|
|
154
154
|
/**
|
|
155
155
|
* @param {import('commander').Command} program
|
|
156
156
|
*/
|
|
157
|
-
function
|
|
157
|
+
function setupValidateCommand(program) {
|
|
158
158
|
program.command('validate [appKey|systemKey|file]')
|
|
159
159
|
.description('Validate appKey, systemKey, file path, .protection batch, or all under integration/ and builder/')
|
|
160
160
|
.addHelpText('after', VALIDATE_HELP_AFTER)
|
|
@@ -173,7 +173,37 @@ function setupValidateDiffCommands(program) {
|
|
|
173
173
|
process.exit(1);
|
|
174
174
|
});
|
|
175
175
|
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* @param {import('commander').Command} program
|
|
180
|
+
*/
|
|
181
|
+
function setupValidateJsonCommand(program) {
|
|
182
|
+
program.command('validate-json [appKey|systemKey]')
|
|
183
|
+
.description(
|
|
184
|
+
'Validate locally then write *-deploy.json only when validation succeeds (offline; no file-path mode)'
|
|
185
|
+
)
|
|
186
|
+
.addHelpText('after', VALIDATE_JSON_HELP_AFTER)
|
|
187
|
+
.option('--format <format>', 'Output format: json | default (human-readable)')
|
|
188
|
+
.option('--integration', 'Validate and write deploy JSON for all apps under integration/')
|
|
189
|
+
.option('--builder', 'Validate and write deploy JSON for all apps under builder/')
|
|
190
|
+
.action((appKey, options) => {
|
|
191
|
+
const { runValidateJsonCommand } = require('../commands/validate-json');
|
|
192
|
+
runValidateJsonCommand(appKey, options)
|
|
193
|
+
.then(({ exitCode }) => {
|
|
194
|
+
if (exitCode !== 0) process.exit(exitCode);
|
|
195
|
+
})
|
|
196
|
+
.catch((error) => {
|
|
197
|
+
handleCommandError(error, 'validate-json');
|
|
198
|
+
process.exit(1);
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
}
|
|
176
202
|
|
|
203
|
+
/**
|
|
204
|
+
* @param {import('commander').Command} program
|
|
205
|
+
*/
|
|
206
|
+
function setupDiffCommand(program) {
|
|
177
207
|
program.command('diff <file1> <file2>')
|
|
178
208
|
.description('Diff two config files (optional schema validate)')
|
|
179
209
|
.option('--no-validate', 'Skip schema validation (type check still applied)')
|
|
@@ -191,6 +221,15 @@ function setupValidateDiffCommands(program) {
|
|
|
191
221
|
});
|
|
192
222
|
}
|
|
193
223
|
|
|
224
|
+
/**
|
|
225
|
+
* @param {import('commander').Command} program
|
|
226
|
+
*/
|
|
227
|
+
function setupValidateDiffCommands(program) {
|
|
228
|
+
setupValidateCommand(program);
|
|
229
|
+
setupValidateJsonCommand(program);
|
|
230
|
+
setupDiffCommand(program);
|
|
231
|
+
}
|
|
232
|
+
|
|
194
233
|
module.exports = {
|
|
195
234
|
setupValidateDiffCommands,
|
|
196
235
|
runValidateCommand
|
package/lib/commands/app-test.js
CHANGED
|
@@ -166,20 +166,8 @@ async function runDockerExec(containerName, testCmd, envFilePath = null) {
|
|
|
166
166
|
* @returns {Promise<number>} Exit code
|
|
167
167
|
*/
|
|
168
168
|
async function runDockerRunEphemeral(fullImage, testCmd, envFilePath = null) {
|
|
169
|
-
const {
|
|
170
|
-
|
|
171
|
-
return new Promise((resolve) => {
|
|
172
|
-
const args = ['run', '--rm'];
|
|
173
|
-
if (envFilePath) args.push('--env-file', envFilePath);
|
|
174
|
-
args.push(fullImage, 'sh', '-c', testCmd);
|
|
175
|
-
const proc = spawn('docker', args, {
|
|
176
|
-
stdio: 'inherit',
|
|
177
|
-
shell: false,
|
|
178
|
-
env: dockerEnv
|
|
179
|
-
});
|
|
180
|
-
proc.on('close', code => resolve(code !== null ? code : 1));
|
|
181
|
-
proc.on('error', () => resolve(1));
|
|
182
|
-
});
|
|
169
|
+
const { runDockerRunEphemeral: runEphemeral } = require('../utils/docker-run-ephemeral');
|
|
170
|
+
return runEphemeral(fullImage, testCmd, envFilePath);
|
|
183
171
|
}
|
|
184
172
|
|
|
185
173
|
/**
|
|
@@ -76,7 +76,8 @@ async function datasourceLoadAction(datasourceKey, options) {
|
|
|
76
76
|
dryRun: options.dryRun,
|
|
77
77
|
batchSize: options.batchSize,
|
|
78
78
|
syncType: options.syncType,
|
|
79
|
-
format: options.format
|
|
79
|
+
format: options.format,
|
|
80
|
+
timeoutMs: options.timeout
|
|
80
81
|
});
|
|
81
82
|
|
|
82
83
|
if (options.json) {
|
|
@@ -141,6 +142,10 @@ function setupDatasourceLoadExportCommands(datasource) {
|
|
|
141
142
|
'Dataplane syncType',
|
|
142
143
|
'incremental'
|
|
143
144
|
)
|
|
145
|
+
.option(
|
|
146
|
+
'--timeout <ms>',
|
|
147
|
+
'Per-batch HTTP timeout for records/bulk (default 120000)'
|
|
148
|
+
)
|
|
144
149
|
.option('--dry-run', 'Parse and validate only; no upload')
|
|
145
150
|
.option('-v, --verbose', 'Per-batch progress')
|
|
146
151
|
.option('--json', 'Machine-readable result JSON')
|
|
@@ -113,6 +113,24 @@ function formatOperationsGateFailure(result) {
|
|
|
113
113
|
return 'E2E validation did not succeed for one or more datasources';
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
/**
|
|
117
|
+
* @param {Object} row
|
|
118
|
+
* @returns {string|null}
|
|
119
|
+
*/
|
|
120
|
+
function formatFailedDatasourceRowHint(row) {
|
|
121
|
+
if (!row || row.success !== false) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const key = row.key || row.datasourceKey || 'datasource';
|
|
125
|
+
const issues = row.datasourceTestRun?.validation?.issues;
|
|
126
|
+
if (Array.isArray(issues) && issues.length > 0) {
|
|
127
|
+
const first = issues[0];
|
|
128
|
+
const code = first.code ? `${first.code}: ` : '';
|
|
129
|
+
return `${key}: ${code}${first.message || 'validation failed'}`;
|
|
130
|
+
}
|
|
131
|
+
return row.error ? `${key}: ${row.error}` : null;
|
|
132
|
+
}
|
|
133
|
+
|
|
116
134
|
/**
|
|
117
135
|
* @param {Object} result
|
|
118
136
|
* @returns {string}
|
|
@@ -124,6 +142,11 @@ function formatIntegrationGateFailure(result) {
|
|
|
124
142
|
if (result?.message) {
|
|
125
143
|
return String(result.message);
|
|
126
144
|
}
|
|
145
|
+
const rows = Array.isArray(result?.datasourceResults) ? result.datasourceResults : [];
|
|
146
|
+
const hints = rows.map(formatFailedDatasourceRowHint).filter(Boolean);
|
|
147
|
+
if (hints.length > 0) {
|
|
148
|
+
return hints.slice(0, 3).join('; ');
|
|
149
|
+
}
|
|
127
150
|
return 'integration test did not succeed';
|
|
128
151
|
}
|
|
129
152
|
|