@aifabrix/builder 2.51.0 → 2.52.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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-container-start.js +4 -0
- package/lib/app/run-deploy-job.js +216 -0
- package/lib/app/run-env-compose.js +32 -0
- package/lib/app/run-env-recovery.js +35 -0
- package/lib/app/run-helpers.js +15 -9
- package/lib/app/run.js +18 -2
- package/lib/channels/add-channel.js +54 -23
- package/lib/channels/approval-guides/chatgpt.js +13 -9
- 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 +25 -1
- 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/infra-guided-footers.js +1 -1
- package/lib/cli/infra-guided-public-url-warn.js +55 -0
- package/lib/cli/infra-guided.js +65 -56
- package/lib/cli/setup-app.help.js +4 -0
- package/lib/cli/setup-app.js +4 -0
- package/lib/cli/setup-app.test-commands.js +59 -28
- package/lib/cli/setup-external-system-help.js +8 -2
- package/lib/cli/setup-external-system.js +62 -12
- package/lib/commands/app-test.js +2 -14
- package/lib/commands/channel-add-setup.js +8 -2
- package/lib/commands/channel.js +16 -5
- package/lib/commands/datasource-load-export-cli.js +6 -1
- package/lib/commands/deploy-gate-failure-details.js +19 -17
- package/lib/commands/deploy-gate-orchestrator.js +3 -2
- 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/governance-verify-external.js +2 -5
- package/lib/commands/lifecycle-external.js +21 -8
- 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 +371 -0
- package/lib/commands/test-governance-external.js +2 -5
- package/lib/commands/up-miso.js +61 -24
- package/lib/commands/upload-data-sync-finalize.js +25 -7
- 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 +31 -10
- package/lib/commands/verify-operations-external.js +2 -5
- package/lib/commands/verify-operations-step-plan.js +31 -0
- package/lib/commands/verify-trust-command-action.js +2 -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-identifier.js +4 -3
- package/lib/datasource/datasource-validate-summary.js +2 -2
- package/lib/datasource/integration-context.js +3 -3
- package/lib/datasource/resolve-app.js +90 -8
- package/lib/datasource/test-e2e.js +2 -2
- package/lib/datasource/unified-validation-run-body.js +15 -1
- package/lib/datasource/unified-validation-run-resolve.js +2 -2
- package/lib/datasource/validate.js +13 -6
- package/lib/external-system/deploy-helpers.js +39 -1
- package/lib/external-system/deploy.js +25 -11
- 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-system-level.js +21 -3
- package/lib/external-system/test.js +43 -7
- package/lib/generator/builders.js +12 -15
- 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-markdown-frontmatter.js +75 -0
- package/lib/role-assistant/knowledge-sync.js +485 -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 +221 -0
- package/lib/role-assistant/test-runner-workhub.js +399 -0
- package/lib/role-assistant/test-runner.js +500 -0
- package/lib/schema/application-schema.json +24 -28
- 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/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/certify-external-workspace.js +40 -0
- package/lib/utils/deployment-validation.js +28 -3
- package/lib/utils/docker-run-ephemeral.js +115 -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/health-check-public-warn.js +31 -13
- package/lib/utils/health-check.js +11 -1
- package/lib/utils/help-builder.js +1 -0
- package/lib/utils/paths.js +80 -38
- package/lib/utils/pipeline-upload-auth-retry.js +15 -3
- package/lib/utils/role-assistant-paths.js +160 -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/upload-sync-options.js +7 -4
- package/lib/utils/url-declarative-resolve-load-doc.js +38 -1
- package/lib/validation/external-manifest-validator.js +31 -8
- package/lib/validation/reserved-system-key-prefixes.js +56 -0
- package/lib/validation/validate-external-file.js +8 -1
- package/lib/validation/validate.js +54 -19
- package/package.json +2 -1
- package/scripts/export-builder-api-evidence.js +1 -1
- package/templates/applications/builder-api/application.yaml +3 -3
- package/templates/applications/dataplane/application.yaml +24 -17
- package/templates/applications/dataplane/env.template +2 -2
- package/templates/applications/dataplane/rbac.yaml +24 -10
- package/templates/applications/keycloak/application.yaml +2 -2
- package/templates/applications/keycloak/env.template +5 -2
- package/templates/applications/miso-controller/application.yaml +3 -3
- package/templates/applications/miso-controller/env.template +17 -2
- package/templates/channels/chatgpt/install.template.md.hbs +82 -26
- package/templates/channels/chatgpt/integration/README.md +11 -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/install.template.md.hbs +6 -1
- package/templates/python/docker-compose.hbs +10 -0
- package/templates/typescript/docker-compose.hbs +10 -0
- /package/.cursor/plans/{157.1-security-quality-violations-by-type.csv → Done/157.1-security-quality-violations-by-type.csv} +0 -0
|
@@ -83,6 +83,7 @@ function requiresBearerAuth(handlerId) {
|
|
|
83
83
|
function applyOperationDurationHints(capability, operation) {
|
|
84
84
|
const durationByHandler = {
|
|
85
85
|
runUpload: Number(process.env.MAX_UPLOAD_TIMEOUT_MS || 300000),
|
|
86
|
+
runDeploySystem: Number(process.env.MAX_DEPLOY_TIMEOUT_MS || 300000),
|
|
86
87
|
runTest: Number(process.env.MAX_TEST_E2E_TIMEOUT_MS || 120000),
|
|
87
88
|
runCertifyPillar: Number(process.env.MAX_CERTIFY_TIMEOUT_MS || 120000)
|
|
88
89
|
};
|
|
@@ -133,6 +134,49 @@ function buildOperationObject(capability) {
|
|
|
133
134
|
return operation;
|
|
134
135
|
}
|
|
135
136
|
|
|
137
|
+
/**
|
|
138
|
+
* @returns {Object[]}
|
|
139
|
+
*/
|
|
140
|
+
function buildOpenApiTags() {
|
|
141
|
+
return [
|
|
142
|
+
{ name: 'workspace', description: 'Per-user integration workspaces (list, create, manifest, status, diff).' },
|
|
143
|
+
{ name: 'build', description: 'Wizard generation and manifest repair.' },
|
|
144
|
+
{ name: 'manifest', description: 'Governed section get/patch/repair for LLM and MCP workflows.' },
|
|
145
|
+
{ name: 'validate', description: 'Local AJV validation and preview-upload (no Dataplane mutation).' },
|
|
146
|
+
{ name: 'test', description: 'Unit, integration, and e2e test ladder.' },
|
|
147
|
+
{ name: 'certify', description: 'Verify operations/trust/governance and lifecycle certification.' },
|
|
148
|
+
{ name: 'apply', description: 'Dev Dataplane upload (requires external-system:publish).' },
|
|
149
|
+
{ name: 'template', description: 'Enterprise MCP template.materializeWorkspace and workspace reset.' },
|
|
150
|
+
{ name: 'repository', description: 'Enterprise MCP repository.sync, createReview, status, dispatchPipeline.' },
|
|
151
|
+
{ name: 'infra', description: 'Liveness and readiness probes (no authentication).' },
|
|
152
|
+
{
|
|
153
|
+
name: 'evidence',
|
|
154
|
+
description:
|
|
155
|
+
'BTA-facing Evidence authoring: metadata, download, upload (validate+certify), and human-gated activate.'
|
|
156
|
+
}
|
|
157
|
+
];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @returns {Object}
|
|
162
|
+
*/
|
|
163
|
+
function buildOpenApiInfo() {
|
|
164
|
+
return {
|
|
165
|
+
title: 'AI Fabrix Builder API',
|
|
166
|
+
version: '1.0.0',
|
|
167
|
+
description:
|
|
168
|
+
'Workspace orchestration for external-system dev publish. Repository and template operations delegate to Enterprise MCP (154.1). Successful JSON responses use `{ success, data, correlationId, requestId? }` with `application/json`. Errors use RFC 7807 Problem Details (`application/problem+json`) aligned with miso-controller and dataplane.',
|
|
169
|
+
'x-aifabrix': {
|
|
170
|
+
redocUrl: '/api/docs',
|
|
171
|
+
contractTier: 'public',
|
|
172
|
+
mcpGenerationReady: true,
|
|
173
|
+
rbacPreset: 'platform',
|
|
174
|
+
datasourceSplitMode: 'per-tag',
|
|
175
|
+
orchestrationDatasourceTags: listOrchestrationDatasourceTags()
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
136
180
|
/**
|
|
137
181
|
* @param {Object} [options]
|
|
138
182
|
* @param {string} [options.publicBaseUrl]
|
|
@@ -148,39 +192,14 @@ function buildOpenApiSpec(options = {}) {
|
|
|
148
192
|
if (!paths[pathKey]) {
|
|
149
193
|
paths[pathKey] = {};
|
|
150
194
|
}
|
|
151
|
-
|
|
152
|
-
paths[pathKey][method] = buildOperationObject(capability);
|
|
195
|
+
paths[pathKey][capability.method.toLowerCase()] = buildOperationObject(capability);
|
|
153
196
|
}
|
|
154
197
|
|
|
155
198
|
return {
|
|
156
199
|
openapi: '3.0.3',
|
|
157
|
-
info:
|
|
158
|
-
title: 'AI Fabrix Builder API',
|
|
159
|
-
version: '1.0.0',
|
|
160
|
-
description:
|
|
161
|
-
'Workspace orchestration for external-system dev publish. Repository and template operations delegate to Enterprise MCP (154.1). Successful JSON responses use `{ success, data, correlationId, requestId? }` with `application/json`. Errors use RFC 7807 Problem Details (`application/problem+json`) aligned with miso-controller and dataplane.',
|
|
162
|
-
'x-aifabrix': {
|
|
163
|
-
redocUrl: '/api/docs',
|
|
164
|
-
contractTier: 'public',
|
|
165
|
-
mcpGenerationReady: true,
|
|
166
|
-
rbacPreset: 'platform',
|
|
167
|
-
datasourceSplitMode: 'per-tag',
|
|
168
|
-
orchestrationDatasourceTags: listOrchestrationDatasourceTags()
|
|
169
|
-
}
|
|
170
|
-
},
|
|
200
|
+
info: buildOpenApiInfo(),
|
|
171
201
|
servers: [{ url: serverUrl, description: 'Builder API public base URL' }],
|
|
172
|
-
tags:
|
|
173
|
-
{ name: 'workspace', description: 'Per-user integration workspaces (list, create, manifest, status, diff).' },
|
|
174
|
-
{ name: 'build', description: 'Wizard generation and manifest repair.' },
|
|
175
|
-
{ name: 'manifest', description: 'Governed section get/patch/repair for LLM and MCP workflows.' },
|
|
176
|
-
{ name: 'validate', description: 'Local AJV validation and preview-upload (no Dataplane mutation).' },
|
|
177
|
-
{ name: 'test', description: 'Unit, integration, and e2e test ladder.' },
|
|
178
|
-
{ name: 'certify', description: 'Verify operations/trust/governance and lifecycle certification.' },
|
|
179
|
-
{ name: 'apply', description: 'Dev Dataplane upload (requires external-system:publish).' },
|
|
180
|
-
{ name: 'template', description: 'Enterprise MCP template.materializeWorkspace and workspace reset.' },
|
|
181
|
-
{ name: 'repository', description: 'Enterprise MCP repository.sync, createReview, status, dispatchPipeline.' },
|
|
182
|
-
{ name: 'infra', description: 'Liveness and readiness probes (no authentication).' }
|
|
183
|
-
],
|
|
202
|
+
tags: buildOpenApiTags(),
|
|
184
203
|
components: {
|
|
185
204
|
securitySchemes: {
|
|
186
205
|
bearerAuth: {
|
|
@@ -66,6 +66,11 @@ const ORCHESTRATION_TAG_CATALOG = Object.freeze({
|
|
|
66
66
|
resourceType: 'channel',
|
|
67
67
|
permissionClass: 'infra',
|
|
68
68
|
displayName: 'Infrastructure'
|
|
69
|
+
},
|
|
70
|
+
evidence: {
|
|
71
|
+
resourceType: 'role-evidence',
|
|
72
|
+
permissionClass: 'evidence',
|
|
73
|
+
displayName: 'Evidence'
|
|
69
74
|
}
|
|
70
75
|
});
|
|
71
76
|
|
|
@@ -16,6 +16,9 @@ function getTimeoutMsForHandler(handlerId) {
|
|
|
16
16
|
if (handlerId === 'runUpload') {
|
|
17
17
|
return Number(process.env.MAX_UPLOAD_TIMEOUT_MS || 300000);
|
|
18
18
|
}
|
|
19
|
+
if (handlerId === 'runDeploySystem') {
|
|
20
|
+
return Number(process.env.MAX_DEPLOY_TIMEOUT_MS || 300000);
|
|
21
|
+
}
|
|
19
22
|
if (handlerId === 'runTest') {
|
|
20
23
|
return Number(process.env.MAX_TEST_E2E_TIMEOUT_MS || 120000);
|
|
21
24
|
}
|
|
@@ -14,6 +14,8 @@ const { runWizard } = require('./run-wizard');
|
|
|
14
14
|
const { runRepair } = require('./run-repair');
|
|
15
15
|
const { runValidate } = require('./run-validate');
|
|
16
16
|
const { runPreviewUpload, runUpload } = require('./run-upload');
|
|
17
|
+
const { runDeploySystem } = require('./run-deploy');
|
|
18
|
+
const { runProtectionUpload, runProtectionCreate } = require('./run-protection');
|
|
17
19
|
const { runTest } = require('./run-test');
|
|
18
20
|
const { runCertifyPillar } = require('./run-certify');
|
|
19
21
|
const { getLifecycleReport } = require('./run-lifecycle');
|
|
@@ -32,6 +34,12 @@ const {
|
|
|
32
34
|
const { getManifestSection, listManifestSections } = require('./manifest-get-section');
|
|
33
35
|
const { patchManifestSection } = require('./manifest-patch-section');
|
|
34
36
|
const { runManifestRepair } = require('./manifest-repair');
|
|
37
|
+
const {
|
|
38
|
+
getEvidenceMetadata,
|
|
39
|
+
downloadEvidence,
|
|
40
|
+
uploadEvidenceCandidates,
|
|
41
|
+
activateEvidenceCandidates
|
|
42
|
+
} = require('./run-evidence-authoring');
|
|
35
43
|
|
|
36
44
|
/** @type {Record<string, Function>} */
|
|
37
45
|
const HANDLER_MAP = {
|
|
@@ -108,6 +116,36 @@ const HANDLER_MAP = {
|
|
|
108
116
|
probe: body.probe === true,
|
|
109
117
|
minimal: true
|
|
110
118
|
}),
|
|
119
|
+
runDeploySystem: (params, auth, body) =>
|
|
120
|
+
runDeploySystem(buildContext(auth, params.systemKey), {
|
|
121
|
+
gate: body.gate,
|
|
122
|
+
subjectEmail: body.subjectEmail,
|
|
123
|
+
probe: body.probe === true,
|
|
124
|
+
sync: body.sync === true,
|
|
125
|
+
verbose: body.verbose === true
|
|
126
|
+
}),
|
|
127
|
+
runProtectionUpload: (params, auth, body) =>
|
|
128
|
+
runProtectionUpload(buildContext(auth, params.systemKey), params.datasourceKey, {
|
|
129
|
+
dryRun: body.dryRun === true,
|
|
130
|
+
sync: body.sync === true,
|
|
131
|
+
verbose: body.verbose === true
|
|
132
|
+
}),
|
|
133
|
+
runProtectionCreate: (params, auth, body) =>
|
|
134
|
+
runProtectionCreate(buildContext(auth, params.systemKey), params.datasourceKey, {
|
|
135
|
+
type: body.type,
|
|
136
|
+
dimensionKey: body.dimensionKey,
|
|
137
|
+
field: body.field,
|
|
138
|
+
fkName: body.fkName,
|
|
139
|
+
protectionKey: body.protectionKey,
|
|
140
|
+
displayName: body.displayName,
|
|
141
|
+
ruleKey: body.ruleKey,
|
|
142
|
+
principalExpression: body.principalExpression,
|
|
143
|
+
valueExpression: body.valueExpression,
|
|
144
|
+
dryRun: body.dryRun === true,
|
|
145
|
+
force: body.force === true,
|
|
146
|
+
verbose: body.verbose === true,
|
|
147
|
+
disabled: body.disabled === true
|
|
148
|
+
}),
|
|
111
149
|
runTest: (params, auth, body, query) =>
|
|
112
150
|
runTest(buildContext(auth, params.systemKey), {
|
|
113
151
|
runType: body.runType || query.runType || 'integration',
|
|
@@ -117,7 +155,10 @@ const HANDLER_MAP = {
|
|
|
117
155
|
runCertifyPillar(buildContext(auth, params.systemKey), params.pillar, {
|
|
118
156
|
noPublish: body.noPublish === true,
|
|
119
157
|
pack: body.pack,
|
|
120
|
-
body: body.lifecycleBody
|
|
158
|
+
body: body.lifecycleBody,
|
|
159
|
+
subjectEmails: _certifySubjectEmails(body),
|
|
160
|
+
subjectUserIds: _stringList(body.subjectUserIds),
|
|
161
|
+
certificationProfile: body.certificationProfile
|
|
121
162
|
}),
|
|
122
163
|
getLifecycleReport: (params, auth, _body, query) =>
|
|
123
164
|
getLifecycleReport(buildContext(auth, params.systemKey), {
|
|
@@ -137,7 +178,53 @@ const HANDLER_MAP = {
|
|
|
137
178
|
runRepositoryDispatchPipeline: (params, auth, body) =>
|
|
138
179
|
runRepositoryDispatchPipeline(buildContext(auth, params.systemKey), body),
|
|
139
180
|
health: () => ({ status: 'ok' }),
|
|
140
|
-
ready: () => ({ status: 'ready', dataplaneUrl: process.env.DATAPLANE_URL || null })
|
|
181
|
+
ready: () => ({ status: 'ready', dataplaneUrl: process.env.DATAPLANE_URL || null }),
|
|
182
|
+
getEvidenceMetadata: (params, auth) =>
|
|
183
|
+
getEvidenceMetadata(buildContext(auth, '_evidence'), params.roleKey),
|
|
184
|
+
downloadEvidence: (params, auth, _body, query) =>
|
|
185
|
+
downloadEvidence(buildContext(auth, '_evidence'), {
|
|
186
|
+
roleKey: params.roleKey,
|
|
187
|
+
resourceType: query.resourceType,
|
|
188
|
+
status: query.status,
|
|
189
|
+
kindKey: query.kindKey,
|
|
190
|
+
aspect: query.aspect,
|
|
191
|
+
search: query.search,
|
|
192
|
+
genericOnly: query.genericOnly === 'true',
|
|
193
|
+
limit: query.limit,
|
|
194
|
+
offset: query.offset
|
|
195
|
+
}),
|
|
196
|
+
uploadEvidenceCandidates: (params, auth, body) =>
|
|
197
|
+
uploadEvidenceCandidates(buildContext(auth, '_evidence'), {
|
|
198
|
+
...(body && typeof body === 'object' ? body : {}),
|
|
199
|
+
roleKey: (body && body.roleKey) || params.roleKey
|
|
200
|
+
}),
|
|
201
|
+
activateEvidenceCandidates: (_params, auth, body) =>
|
|
202
|
+
activateEvidenceCandidates(buildContext(auth, '_evidence'), body)
|
|
141
203
|
};
|
|
142
204
|
|
|
205
|
+
/**
|
|
206
|
+
* @param {unknown} value
|
|
207
|
+
* @returns {string[]}
|
|
208
|
+
*/
|
|
209
|
+
function _stringList(value) {
|
|
210
|
+
if (!Array.isArray(value)) {
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
return value.map(item => String(item || '').trim()).filter(Boolean);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Normalize subject emails from CertifyRequest (singular or list).
|
|
218
|
+
* @param {Object} body
|
|
219
|
+
* @returns {string[]}
|
|
220
|
+
*/
|
|
221
|
+
function _certifySubjectEmails(body) {
|
|
222
|
+
const fromList = _stringList(body && body.subjectEmails);
|
|
223
|
+
const single = body && body.subjectEmail ? String(body.subjectEmail).trim() : '';
|
|
224
|
+
if (single && !fromList.includes(single)) {
|
|
225
|
+
return [single, ...fromList];
|
|
226
|
+
}
|
|
227
|
+
return fromList;
|
|
228
|
+
}
|
|
229
|
+
|
|
143
230
|
module.exports = { HANDLER_MAP };
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
const { runVerifyOperationsForExternalSystem } = require('../commands/verify-operations-external');
|
|
12
12
|
const { runVerifyTrustForExternalSystem } = require('../commands/verify-trust-external');
|
|
13
13
|
const { runVerifyGovernanceForExternalSystem } = require('../commands/verify-governance-external');
|
|
14
|
+
const { runVerifyGovernanceCombined } = require('../commands/verify-governance-combined-external');
|
|
14
15
|
const { runSystemLifecycle } = require('../api/lifecycle.api');
|
|
15
16
|
const { runWithWorkspaceContext } = require('./workspace-context');
|
|
16
17
|
const { mergeProgrammaticOptions } = require('./command-options');
|
|
@@ -45,7 +46,7 @@ async function runCertifyPillar(ctx, pillar, options = {}) {
|
|
|
45
46
|
} else if (pillar === 'trust') {
|
|
46
47
|
result = await runVerifyTrustForExternalSystem(ctx.systemKey, merged);
|
|
47
48
|
} else if (pillar === 'governance') {
|
|
48
|
-
result = await
|
|
49
|
+
result = await runGovernanceCertify(ctx.systemKey, merged);
|
|
49
50
|
} else {
|
|
50
51
|
result = await runSystemLifecycle(merged.dataplaneUrl, merged.authConfig, ctx.systemKey, options.body || {});
|
|
51
52
|
}
|
|
@@ -54,4 +55,16 @@ async function runCertifyPillar(ctx, pillar, options = {}) {
|
|
|
54
55
|
});
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Governance certify: generate packs (subjects required) then verify, unless pack override.
|
|
60
|
+
* @param {string} systemKey
|
|
61
|
+
* @param {Object} options
|
|
62
|
+
*/
|
|
63
|
+
async function runGovernanceCertify(systemKey, options) {
|
|
64
|
+
if (options.pack) {
|
|
65
|
+
return runVerifyGovernanceForExternalSystem(systemKey, options);
|
|
66
|
+
}
|
|
67
|
+
return runVerifyGovernanceCombined(systemKey, options);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = { runCertifyPillar, runGovernanceCertify, PILLARS };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatic deploy wrapper — CLI deploy parity for builder-api.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview runDeploySystem for POST /systems/:systemKey/deploy
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const { deployExternalSystem } = require('../external-system/deploy');
|
|
12
|
+
const { runWithWorkspaceContext } = require('./workspace-context');
|
|
13
|
+
const { mergeProgrammaticOptions } = require('./command-options');
|
|
14
|
+
const { touchWorkspaceMeta } = require('./workspace-meta');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {unknown} gate
|
|
18
|
+
* @returns {string|undefined}
|
|
19
|
+
*/
|
|
20
|
+
function normalizeGate(gate) {
|
|
21
|
+
if (gate === null || gate === undefined || gate === '') {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
if (typeof gate === 'string') {
|
|
25
|
+
return gate.trim() || undefined;
|
|
26
|
+
}
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Map gateFailure / deploy errors to Problem Details status codes.
|
|
32
|
+
* @param {Error & { gateFailure?: boolean, statusCode?: number }} err
|
|
33
|
+
*/
|
|
34
|
+
function attachDeployStatus(err) {
|
|
35
|
+
if (err && err.gateFailure === true && !err.statusCode) {
|
|
36
|
+
err.statusCode = 422;
|
|
37
|
+
}
|
|
38
|
+
return err;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
43
|
+
* @param {Object} [options]
|
|
44
|
+
* @param {string} [options.gate] - Same as CLI --gate (operations,trust,governance,full)
|
|
45
|
+
* @param {string} [options.subjectEmail]
|
|
46
|
+
* @param {boolean} [options.probe]
|
|
47
|
+
* @param {boolean} [options.sync]
|
|
48
|
+
* @param {boolean} [options.verbose]
|
|
49
|
+
* @returns {Promise<Object>}
|
|
50
|
+
*/
|
|
51
|
+
async function runDeploySystem(ctx, options = {}) {
|
|
52
|
+
const merged = mergeProgrammaticOptions(ctx, {
|
|
53
|
+
...options,
|
|
54
|
+
gate: normalizeGate(options.gate),
|
|
55
|
+
subjectEmail: options.subjectEmail,
|
|
56
|
+
probe: options.probe === true,
|
|
57
|
+
sync: options.sync === true,
|
|
58
|
+
verbose: options.verbose === true
|
|
59
|
+
});
|
|
60
|
+
return runWithWorkspaceContext(ctx, async() => {
|
|
61
|
+
try {
|
|
62
|
+
const result = await deployExternalSystem(ctx.systemKey, merged);
|
|
63
|
+
touchWorkspaceMeta(ctx, { lastOperation: 'deploy' });
|
|
64
|
+
return result && typeof result === 'object' ? result : { deployed: true };
|
|
65
|
+
} catch (err) {
|
|
66
|
+
throw attachDeployStatus(err);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = {
|
|
72
|
+
runDeploySystem,
|
|
73
|
+
normalizeGate
|
|
74
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatic Evidence authoring wrappers (plan 162.0 BTA-facing APIs).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview HTTP handlers → lib/api/evidence-authoring.api.js
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
getEvidenceMetadata: getEvidenceMetadataApi,
|
|
13
|
+
downloadEvidence: downloadEvidenceApi,
|
|
14
|
+
uploadEvidenceCandidates: uploadEvidenceCandidatesApi,
|
|
15
|
+
activateEvidenceCandidates: activateEvidenceCandidatesApi
|
|
16
|
+
} = require('../api/evidence-authoring.api');
|
|
17
|
+
const { mergeProgrammaticOptions } = require('./command-options');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
21
|
+
* @param {Object} [options]
|
|
22
|
+
* @returns {{ dataplaneUrl: string, authConfig: Object, apiOptions: Object }}
|
|
23
|
+
*/
|
|
24
|
+
function resolveEvidenceCallContext(ctx, options = {}) {
|
|
25
|
+
const merged = mergeProgrammaticOptions(ctx, options);
|
|
26
|
+
return {
|
|
27
|
+
dataplaneUrl: merged.dataplaneUrl,
|
|
28
|
+
authConfig: merged.authConfig,
|
|
29
|
+
apiOptions: {
|
|
30
|
+
controllerUrl: merged.controllerUrl || options.controllerUrl || null
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
37
|
+
* @param {string} roleKey
|
|
38
|
+
* @param {Object} [options]
|
|
39
|
+
*/
|
|
40
|
+
async function getEvidenceMetadata(ctx, roleKey, options = {}) {
|
|
41
|
+
const call = resolveEvidenceCallContext(ctx, options);
|
|
42
|
+
return getEvidenceMetadataApi(call.dataplaneUrl, call.authConfig, roleKey, call.apiOptions);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
47
|
+
* @param {Object} params
|
|
48
|
+
* @param {Object} [options]
|
|
49
|
+
*/
|
|
50
|
+
async function downloadEvidence(ctx, params = {}, options = {}) {
|
|
51
|
+
const call = resolveEvidenceCallContext(ctx, options);
|
|
52
|
+
return downloadEvidenceApi(call.dataplaneUrl, call.authConfig, params, call.apiOptions);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
57
|
+
* @param {Object|Object[]} payload
|
|
58
|
+
* @param {Object} [options]
|
|
59
|
+
*/
|
|
60
|
+
async function uploadEvidenceCandidates(ctx, payload = {}, options = {}) {
|
|
61
|
+
const call = resolveEvidenceCallContext(ctx, options);
|
|
62
|
+
return uploadEvidenceCandidatesApi(call.dataplaneUrl, call.authConfig, payload, call.apiOptions);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
67
|
+
* @param {Object} payload
|
|
68
|
+
* @param {Object} [options]
|
|
69
|
+
*/
|
|
70
|
+
async function activateEvidenceCandidates(ctx, payload = {}, options = {}) {
|
|
71
|
+
const call = resolveEvidenceCallContext(ctx, options);
|
|
72
|
+
return activateEvidenceCandidatesApi(call.dataplaneUrl, call.authConfig, payload, call.apiOptions);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = {
|
|
76
|
+
getEvidenceMetadata,
|
|
77
|
+
downloadEvidence,
|
|
78
|
+
uploadEvidenceCandidates,
|
|
79
|
+
activateEvidenceCandidates
|
|
80
|
+
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatic protection wrappers for builder-api.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview POST …/protection/upload and …/protection/create
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
runProtectionUpload: uploadProtectionCli
|
|
13
|
+
} = require('../protection/run-commands');
|
|
14
|
+
const { runProtectionCreate: createProtectionCli } = require('../protection/run-protection-create');
|
|
15
|
+
const { resolveProtectionArgument } = require('../protection/resolve');
|
|
16
|
+
const { runWithWorkspaceContext } = require('./workspace-context');
|
|
17
|
+
const { mergeProgrammaticOptions } = require('./command-options');
|
|
18
|
+
const { touchWorkspaceMeta } = require('./workspace-meta');
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Quiet logger for programmatic (non-TTY) protection calls.
|
|
22
|
+
* @returns {{ log: Function, error: Function, warn: Function }}
|
|
23
|
+
*/
|
|
24
|
+
function programmaticLogger() {
|
|
25
|
+
return {
|
|
26
|
+
log() {},
|
|
27
|
+
error() {},
|
|
28
|
+
warn() {}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {number} code
|
|
34
|
+
* @param {string} operation
|
|
35
|
+
*/
|
|
36
|
+
function assertExitOk(code, operation) {
|
|
37
|
+
if (code === 0 || code === null || code === undefined) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const err = new Error(`${operation} failed (exit ${code})`);
|
|
41
|
+
err.statusCode = 422;
|
|
42
|
+
throw err;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
47
|
+
* @param {string} datasourceKey
|
|
48
|
+
* @param {Object} [options]
|
|
49
|
+
* @param {boolean} [options.dryRun]
|
|
50
|
+
* @param {boolean} [options.sync]
|
|
51
|
+
* @param {boolean} [options.verbose]
|
|
52
|
+
* @returns {Promise<{ datasourceKey: string, uploaded: boolean, dryRun: boolean }>}
|
|
53
|
+
*/
|
|
54
|
+
async function runProtectionUpload(ctx, datasourceKey, options = {}) {
|
|
55
|
+
const merged = mergeProgrammaticOptions(ctx, options);
|
|
56
|
+
const logger = programmaticLogger();
|
|
57
|
+
return runWithWorkspaceContext(ctx, async() => {
|
|
58
|
+
const resolved = resolveProtectionArgument(datasourceKey);
|
|
59
|
+
const code = await uploadProtectionCli(resolved.datasourceKey, resolved.manifest, {
|
|
60
|
+
...merged,
|
|
61
|
+
manifestPath: resolved.manifestPath,
|
|
62
|
+
dryRun: options.dryRun === true,
|
|
63
|
+
sync: options.sync === true,
|
|
64
|
+
verbose: options.verbose === true
|
|
65
|
+
}, logger);
|
|
66
|
+
assertExitOk(code, 'Protection upload');
|
|
67
|
+
if (!options.dryRun) {
|
|
68
|
+
touchWorkspaceMeta(ctx, { lastOperation: 'protection:upload' });
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
datasourceKey: resolved.datasourceKey,
|
|
72
|
+
uploaded: options.dryRun !== true,
|
|
73
|
+
dryRun: options.dryRun === true
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
80
|
+
* @param {string} datasourceKey
|
|
81
|
+
* @param {Object} [options]
|
|
82
|
+
* @returns {Promise<{ datasourceKey: string, created: boolean, dryRun: boolean }>}
|
|
83
|
+
*/
|
|
84
|
+
async function runProtectionCreate(ctx, datasourceKey, options = {}) {
|
|
85
|
+
const merged = mergeProgrammaticOptions(ctx, options);
|
|
86
|
+
const logger = programmaticLogger();
|
|
87
|
+
return runWithWorkspaceContext(ctx, async() => {
|
|
88
|
+
const code = await createProtectionCli(
|
|
89
|
+
datasourceKey,
|
|
90
|
+
{
|
|
91
|
+
...merged,
|
|
92
|
+
type: options.type,
|
|
93
|
+
dimensionKey: options.dimensionKey,
|
|
94
|
+
field: options.field,
|
|
95
|
+
fkName: options.fkName,
|
|
96
|
+
protectionKey: options.protectionKey,
|
|
97
|
+
displayName: options.displayName,
|
|
98
|
+
ruleKey: options.ruleKey,
|
|
99
|
+
principalExpression: options.principalExpression,
|
|
100
|
+
valueExpression: options.valueExpression,
|
|
101
|
+
dryRun: options.dryRun === true,
|
|
102
|
+
force: options.force === true,
|
|
103
|
+
verbose: options.verbose === true,
|
|
104
|
+
disabled: options.disabled === true
|
|
105
|
+
},
|
|
106
|
+
logger
|
|
107
|
+
);
|
|
108
|
+
assertExitOk(code, 'Protection create');
|
|
109
|
+
if (!options.dryRun) {
|
|
110
|
+
touchWorkspaceMeta(ctx, { lastOperation: 'protection:create' });
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
datasourceKey,
|
|
114
|
+
created: options.dryRun !== true,
|
|
115
|
+
dryRun: options.dryRun === true
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
module.exports = {
|
|
121
|
+
runProtectionUpload,
|
|
122
|
+
runProtectionCreate,
|
|
123
|
+
programmaticLogger
|
|
124
|
+
};
|
|
@@ -12,6 +12,7 @@ const { runEnterpriseMcpCapability } = require('./run-enterprise-mcp');
|
|
|
12
12
|
const { getSystemManifest } = require('./workspace-ops');
|
|
13
13
|
const { invokeEnterpriseMcpCapability } = require('./enterprise-mcp-client');
|
|
14
14
|
const { runWithWorkspaceContext } = require('./workspace-context');
|
|
15
|
+
const { touchWorkspaceMeta } = require('./workspace-meta');
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
@@ -51,11 +52,37 @@ async function getWorkspaceStatus(ctx) {
|
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
/**
|
|
55
|
+
* Diff local draft vs remote/template baseline.
|
|
56
|
+
* Local-first when Enterprise MCP workspace DS is not published
|
|
57
|
+
* (default ENTERPRISE_MCP_SYSTEM_KEY=enterprise-integration-lifecycle has no workspace DS).
|
|
58
|
+
*
|
|
54
59
|
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
55
60
|
* @param {Object} body
|
|
56
61
|
*/
|
|
57
62
|
async function runWorkspaceDiff(ctx, body = {}) {
|
|
58
|
-
return
|
|
63
|
+
return runWithWorkspaceContext(ctx, async() => {
|
|
64
|
+
const local = getSystemManifest(ctx);
|
|
65
|
+
try {
|
|
66
|
+
const result = await invokeEnterpriseMcpCapability(ctx, 'workspace.diff', body);
|
|
67
|
+
touchWorkspaceMeta(ctx, { lastOperation: 'workspace.diff' });
|
|
68
|
+
return {
|
|
69
|
+
capabilityKey: 'workspace.diff',
|
|
70
|
+
source: 'enterprise-mcp',
|
|
71
|
+
result,
|
|
72
|
+
local
|
|
73
|
+
};
|
|
74
|
+
} catch (err) {
|
|
75
|
+
touchWorkspaceMeta(ctx, { lastOperation: 'workspace.diff' });
|
|
76
|
+
return {
|
|
77
|
+
capabilityKey: 'workspace.diff',
|
|
78
|
+
source: 'local',
|
|
79
|
+
local,
|
|
80
|
+
remote: { unavailable: true, message: err.message },
|
|
81
|
+
note:
|
|
82
|
+
'Enterprise MCP workspace.diff unavailable; returning local draft snapshot only'
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
});
|
|
59
86
|
}
|
|
60
87
|
|
|
61
88
|
/**
|
|
@@ -123,6 +123,12 @@ function runWithWorkspaceContext(ctx, fn) {
|
|
|
123
123
|
return alt;
|
|
124
124
|
}
|
|
125
125
|
return ctx.getIntegrationPath();
|
|
126
|
+
},
|
|
127
|
+
/** Workspace-scoped protection manifests: integration/.protection next to system folders. */
|
|
128
|
+
getProtectionRoot: () => {
|
|
129
|
+
const root = path.join(ctx.getIntegrationRoot(), '.protection');
|
|
130
|
+
assertPathContained(root, ctx.workspaceRoot);
|
|
131
|
+
return root;
|
|
126
132
|
}
|
|
127
133
|
};
|
|
128
134
|
return runWithIntegrationPathScope(scope, fn);
|