@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,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Evidence kinds API (Controller /api/v1/evidence-kinds)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { ApiClient } = require('./index');
|
|
10
|
+
|
|
11
|
+
const BASE = '/api/v1/evidence-kinds';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* List evidence kinds (paginated)
|
|
15
|
+
* @requiresPermission {Controller} evidence-kinds:read
|
|
16
|
+
* @async
|
|
17
|
+
* @param {string} controllerUrl
|
|
18
|
+
* @param {Object} authConfig
|
|
19
|
+
* @param {Object} [options]
|
|
20
|
+
* @returns {Promise<Object>}
|
|
21
|
+
*/
|
|
22
|
+
async function listEvidenceKinds(controllerUrl, authConfig, options = {}) {
|
|
23
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
24
|
+
return await client.get(BASE, { params: options });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get an evidence kind by id or key
|
|
29
|
+
* @requiresPermission {Controller} evidence-kinds:read
|
|
30
|
+
* @async
|
|
31
|
+
* @param {string} controllerUrl
|
|
32
|
+
* @param {Object} authConfig
|
|
33
|
+
* @param {string} evidenceKindIdOrKey
|
|
34
|
+
* @returns {Promise<Object>}
|
|
35
|
+
*/
|
|
36
|
+
async function getEvidenceKind(controllerUrl, authConfig, evidenceKindIdOrKey) {
|
|
37
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
38
|
+
return await client.get(`${BASE}/${encodeURIComponent(evidenceKindIdOrKey)}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {Object} payload
|
|
43
|
+
* @param {string} key
|
|
44
|
+
* @param {*} value
|
|
45
|
+
* @returns {void}
|
|
46
|
+
*/
|
|
47
|
+
function assignOptionalString(payload, key, value) {
|
|
48
|
+
if (value !== undefined && value !== null && value !== '') {
|
|
49
|
+
payload[key] = value;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param {import('./types/evidence-kinds.types').CreateEvidenceKindRequest} body
|
|
55
|
+
* @returns {Object}
|
|
56
|
+
*/
|
|
57
|
+
function buildCreateEvidenceKindBody(body) {
|
|
58
|
+
const payload = {
|
|
59
|
+
key: body.key,
|
|
60
|
+
domainKey: body.domainKey,
|
|
61
|
+
displayName: body.displayName,
|
|
62
|
+
purpose: body.purpose
|
|
63
|
+
};
|
|
64
|
+
assignOptionalString(payload, 'description', body.description);
|
|
65
|
+
assignOptionalString(payload, 'expectedUse', body.expectedUse);
|
|
66
|
+
assignOptionalString(payload, 'source', body.source);
|
|
67
|
+
if (body.defaultSeverity) payload.defaultSeverity = body.defaultSeverity;
|
|
68
|
+
if (body.requiresApproval !== undefined && body.requiresApproval !== null) {
|
|
69
|
+
payload.requiresApproval = Boolean(body.requiresApproval);
|
|
70
|
+
}
|
|
71
|
+
if (body.isActive !== undefined && body.isActive !== null) {
|
|
72
|
+
payload.isActive = Boolean(body.isActive);
|
|
73
|
+
}
|
|
74
|
+
if (body.sortOrder !== undefined && body.sortOrder !== null) {
|
|
75
|
+
payload.sortOrder = Number(body.sortOrder);
|
|
76
|
+
}
|
|
77
|
+
if (body.metadata && typeof body.metadata === 'object') {
|
|
78
|
+
payload.metadata = body.metadata;
|
|
79
|
+
}
|
|
80
|
+
return payload;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Create an evidence kind
|
|
85
|
+
* @requiresPermission {Controller} evidence-kinds:create
|
|
86
|
+
* @async
|
|
87
|
+
* @param {string} controllerUrl
|
|
88
|
+
* @param {Object} authConfig
|
|
89
|
+
* @param {import('./types/evidence-kinds.types').CreateEvidenceKindRequest} body
|
|
90
|
+
* @returns {Promise<Object>}
|
|
91
|
+
*/
|
|
92
|
+
async function createEvidenceKind(controllerUrl, authConfig, body) {
|
|
93
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
94
|
+
return await client.post(BASE, { body: buildCreateEvidenceKindBody(body) });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Create-if-missing (idempotent): if an evidence kind already exists for the key, return success.
|
|
99
|
+
* @requiresPermission {Controller} evidence-kinds:read + evidence-kinds:create
|
|
100
|
+
* @async
|
|
101
|
+
* @param {string} controllerUrl
|
|
102
|
+
* @param {Object} authConfig
|
|
103
|
+
* @param {import('./types/evidence-kinds.types').CreateEvidenceKindRequest} body
|
|
104
|
+
* @returns {Promise<{ created: boolean, response: Object }>}
|
|
105
|
+
*/
|
|
106
|
+
async function createEvidenceKindIdempotent(controllerUrl, authConfig, body) {
|
|
107
|
+
const key = String(body?.key || '').trim();
|
|
108
|
+
if (!key) {
|
|
109
|
+
throw new Error('Evidence kind key is required');
|
|
110
|
+
}
|
|
111
|
+
const getRes = await getEvidenceKind(controllerUrl, authConfig, key);
|
|
112
|
+
if (getRes && getRes.success === true) {
|
|
113
|
+
return { created: false, response: getRes };
|
|
114
|
+
}
|
|
115
|
+
const createRes = await createEvidenceKind(controllerUrl, authConfig, body);
|
|
116
|
+
if (createRes && createRes.success === true) {
|
|
117
|
+
return { created: true, response: createRes };
|
|
118
|
+
}
|
|
119
|
+
const msg = createRes?.error || createRes?.formattedError || 'Failed to create evidence kind';
|
|
120
|
+
throw new Error(msg);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
module.exports = {
|
|
124
|
+
listEvidenceKinds,
|
|
125
|
+
getEvidenceKind,
|
|
126
|
+
createEvidenceKind,
|
|
127
|
+
createEvidenceKindIdempotent
|
|
128
|
+
};
|
package/lib/api/evidence.api.js
CHANGED
|
@@ -162,11 +162,67 @@ async function loadEvidenceBulk(dataplaneUrl, authConfig, rows, options = {}) {
|
|
|
162
162
|
};
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
/**
|
|
166
|
+
* @param {string} dataplaneUrl
|
|
167
|
+
* @param {Object} authConfig
|
|
168
|
+
* @param {string} evidenceIdOrKey
|
|
169
|
+
* @param {Object} [options]
|
|
170
|
+
* @returns {Promise<Object>}
|
|
171
|
+
*/
|
|
172
|
+
async function validateEvidenceCandidate(dataplaneUrl, authConfig, evidenceIdOrKey, options = {}) {
|
|
173
|
+
const client = createEvidenceClient(dataplaneUrl, authConfig, options);
|
|
174
|
+
const res = assertApiSuccess(
|
|
175
|
+
await client.post(`${BASE}/${encodeURIComponent(evidenceIdOrKey)}/validate`, { body: {} }),
|
|
176
|
+
'Validate evidence'
|
|
177
|
+
);
|
|
178
|
+
return unwrapBody(res);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @param {string} dataplaneUrl
|
|
183
|
+
* @param {Object} authConfig
|
|
184
|
+
* @param {string} evidenceIdOrKey
|
|
185
|
+
* @param {{ comment?: string }} [payload]
|
|
186
|
+
* @param {Object} [options]
|
|
187
|
+
* @returns {Promise<Object>}
|
|
188
|
+
*/
|
|
189
|
+
async function certifyEvidenceCandidate(dataplaneUrl, authConfig, evidenceIdOrKey, payload = {}, options = {}) {
|
|
190
|
+
const client = createEvidenceClient(dataplaneUrl, authConfig, options);
|
|
191
|
+
const body = {};
|
|
192
|
+
if (payload && typeof payload.comment === 'string' && payload.comment.trim()) {
|
|
193
|
+
body.comment = payload.comment.trim();
|
|
194
|
+
}
|
|
195
|
+
const res = assertApiSuccess(
|
|
196
|
+
await client.post(`${BASE}/${encodeURIComponent(evidenceIdOrKey)}/certify`, { body }),
|
|
197
|
+
'Certify evidence'
|
|
198
|
+
);
|
|
199
|
+
return unwrapBody(res);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* @param {string} dataplaneUrl
|
|
204
|
+
* @param {Object} authConfig
|
|
205
|
+
* @param {string} evidenceIdOrKey
|
|
206
|
+
* @param {Object} [options]
|
|
207
|
+
* @returns {Promise<Object>}
|
|
208
|
+
*/
|
|
209
|
+
async function activateEvidenceCandidate(dataplaneUrl, authConfig, evidenceIdOrKey, options = {}) {
|
|
210
|
+
const client = createEvidenceClient(dataplaneUrl, authConfig, options);
|
|
211
|
+
const res = assertApiSuccess(
|
|
212
|
+
await client.post(`${BASE}/${encodeURIComponent(evidenceIdOrKey)}/activate`, { body: {} }),
|
|
213
|
+
'Activate evidence'
|
|
214
|
+
);
|
|
215
|
+
return unwrapBody(res);
|
|
216
|
+
}
|
|
217
|
+
|
|
165
218
|
module.exports = {
|
|
166
219
|
listEvidence,
|
|
167
220
|
getEvidence,
|
|
168
221
|
insertEvidence,
|
|
169
222
|
updateEvidence,
|
|
170
223
|
deleteEvidence,
|
|
171
|
-
loadEvidenceBulk
|
|
224
|
+
loadEvidenceBulk,
|
|
225
|
+
validateEvidenceCandidate,
|
|
226
|
+
certifyEvidenceCandidate,
|
|
227
|
+
activateEvidenceCandidate
|
|
172
228
|
};
|
package/lib/api/index.js
CHANGED
|
@@ -79,7 +79,7 @@ class ApiClient {
|
|
|
79
79
|
headers['Content-Type'] = 'application/json';
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
// User token (bearer) → Authorization: Bearer;
|
|
82
|
+
// User token (bearer) → Authorization: Bearer; app token (client-token) → x-client-token.
|
|
83
83
|
if (this.authConfig.type === 'bootstrap' && this.authConfig.encryptionKey) {
|
|
84
84
|
headers['x-encryption-key'] = String(this.authConfig.encryptionKey);
|
|
85
85
|
} else if (this.authConfig.token) {
|
|
@@ -160,7 +160,10 @@ class ApiClient {
|
|
|
160
160
|
transport.timeoutMs = options.timeoutMs;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
if (
|
|
163
|
+
if (
|
|
164
|
+
this.authConfig.type === 'bearer' ||
|
|
165
|
+
this.authConfig.type === 'client-token'
|
|
166
|
+
) {
|
|
164
167
|
// Pass full authConfig to enable proper token refresh using controller URL
|
|
165
168
|
return await authenticatedApiCall(url, transport, this.authConfig);
|
|
166
169
|
}
|
|
@@ -213,7 +216,10 @@ class ApiClient {
|
|
|
213
216
|
requestOptions.timeoutMs = options.timeoutMs;
|
|
214
217
|
}
|
|
215
218
|
|
|
216
|
-
if (
|
|
219
|
+
if (
|
|
220
|
+
this.authConfig.type === 'bearer' ||
|
|
221
|
+
this.authConfig.type === 'client-token'
|
|
222
|
+
) {
|
|
217
223
|
// Pass full authConfig to enable proper token refresh using controller URL
|
|
218
224
|
return await authenticatedApiCall(url, requestOptions, this.authConfig);
|
|
219
225
|
}
|
|
@@ -241,7 +247,9 @@ class ApiClient {
|
|
|
241
247
|
body: formData
|
|
242
248
|
};
|
|
243
249
|
|
|
244
|
-
const hasToken =
|
|
250
|
+
const hasToken =
|
|
251
|
+
this.authConfig.type === 'bearer' ||
|
|
252
|
+
this.authConfig.type === 'client-token';
|
|
245
253
|
if (hasToken && this.authConfig.token) {
|
|
246
254
|
return await authenticatedApiCall(url, requestOptions, this.authConfig);
|
|
247
255
|
}
|
|
@@ -272,7 +280,10 @@ class ApiClient {
|
|
|
272
280
|
requestOptions.body = JSON.stringify(options.body);
|
|
273
281
|
}
|
|
274
282
|
|
|
275
|
-
if (
|
|
283
|
+
if (
|
|
284
|
+
this.authConfig.type === 'bearer' ||
|
|
285
|
+
this.authConfig.type === 'client-token'
|
|
286
|
+
) {
|
|
276
287
|
// Pass full authConfig to enable proper token refresh using controller URL
|
|
277
288
|
return await authenticatedApiCall(url, requestOptions, this.authConfig);
|
|
278
289
|
}
|
|
@@ -303,7 +314,10 @@ class ApiClient {
|
|
|
303
314
|
requestOptions.body = JSON.stringify(options.body);
|
|
304
315
|
}
|
|
305
316
|
|
|
306
|
-
if (
|
|
317
|
+
if (
|
|
318
|
+
this.authConfig.type === 'bearer' ||
|
|
319
|
+
this.authConfig.type === 'client-token'
|
|
320
|
+
) {
|
|
307
321
|
// Pass full authConfig to enable proper token refresh using controller URL
|
|
308
322
|
return await authenticatedApiCall(url, requestOptions, this.authConfig);
|
|
309
323
|
}
|
|
@@ -329,7 +343,10 @@ class ApiClient {
|
|
|
329
343
|
headers
|
|
330
344
|
};
|
|
331
345
|
|
|
332
|
-
if (
|
|
346
|
+
if (
|
|
347
|
+
this.authConfig.type === 'bearer' ||
|
|
348
|
+
this.authConfig.type === 'client-token'
|
|
349
|
+
) {
|
|
333
350
|
// Pass full authConfig to enable proper token refresh using controller URL
|
|
334
351
|
return await authenticatedApiCall(url, requestOptions, this.authConfig);
|
|
335
352
|
}
|
package/lib/api/pipeline.api.js
CHANGED
|
@@ -247,11 +247,53 @@ async function testDatasourceViaPipeline({ dataplaneUrl, systemKey, datasourceKe
|
|
|
247
247
|
* @returns {Promise<Object>} API envelope `{ success, data }` where `data` is PublicationResult (uploadId, system, datasources, generateMcpContract, …)
|
|
248
248
|
* @throws {Error} If upload fails
|
|
249
249
|
*/
|
|
250
|
-
|
|
250
|
+
/** Multi-datasource publish often exceeds the default 30s HTTP timeout. */
|
|
251
|
+
const PIPELINE_UPLOAD_TIMEOUT_MS = 300000;
|
|
252
|
+
const PIPELINE_UPLOAD_TIMEOUT_MIN_MS = 5000;
|
|
253
|
+
const PIPELINE_UPLOAD_TIMEOUT_MAX_MS = 45 * 60 * 1000;
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Resolve pipeline upload timeout (ms) for HTTP + dataplane budget.
|
|
257
|
+
* @param {number|string|undefined|null} raw
|
|
258
|
+
* @returns {number}
|
|
259
|
+
*/
|
|
260
|
+
function resolvePipelineUploadTimeoutMs(raw) {
|
|
261
|
+
if (raw === undefined || raw === null || raw === '') {
|
|
262
|
+
return PIPELINE_UPLOAD_TIMEOUT_MS;
|
|
263
|
+
}
|
|
264
|
+
const n = typeof raw === 'number' ? raw : Number(raw);
|
|
265
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
266
|
+
throw new Error(
|
|
267
|
+
`--timeout must be a positive number of milliseconds (got ${String(raw)})`
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
return Math.min(
|
|
271
|
+
PIPELINE_UPLOAD_TIMEOUT_MAX_MS,
|
|
272
|
+
Math.max(PIPELINE_UPLOAD_TIMEOUT_MIN_MS, Math.floor(n))
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* @param {string} dataplaneUrl
|
|
278
|
+
* @param {Object} authConfig
|
|
279
|
+
* @param {Object} payload
|
|
280
|
+
* @param {Object} [options]
|
|
281
|
+
* @param {number|string} [options.timeoutMs] - HTTP + dataplane publish budget (default 300000)
|
|
282
|
+
*/
|
|
283
|
+
async function uploadApplicationViaPipeline(
|
|
284
|
+
dataplaneUrl,
|
|
285
|
+
authConfig,
|
|
286
|
+
payload,
|
|
287
|
+
options = {}
|
|
288
|
+
) {
|
|
251
289
|
const body = { ...payload, status: payload.status ?? 'draft' };
|
|
290
|
+
const timeoutMs = resolvePipelineUploadTimeoutMs(options.timeoutMs);
|
|
252
291
|
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
253
292
|
return await client.post('/api/v1/pipeline/upload', {
|
|
254
|
-
body
|
|
293
|
+
body,
|
|
294
|
+
timeoutMs,
|
|
295
|
+
params: { timeoutMs: String(timeoutMs) },
|
|
296
|
+
headers: { 'X-Aifabrix-Timeout-Ms': String(timeoutMs) }
|
|
255
297
|
});
|
|
256
298
|
}
|
|
257
299
|
|
|
@@ -264,6 +306,8 @@ module.exports = {
|
|
|
264
306
|
validatePipelineConfig,
|
|
265
307
|
testSystemViaPipeline,
|
|
266
308
|
testDatasourceViaPipeline,
|
|
267
|
-
uploadApplicationViaPipeline
|
|
309
|
+
uploadApplicationViaPipeline,
|
|
310
|
+
resolvePipelineUploadTimeoutMs,
|
|
311
|
+
PIPELINE_UPLOAD_TIMEOUT_MS
|
|
268
312
|
};
|
|
269
313
|
|
|
@@ -7,6 +7,26 @@
|
|
|
7
7
|
const { createDataplaneApiClient } = require('./index');
|
|
8
8
|
const { unwrapApiData } = require('../utils/external-system-readiness-core');
|
|
9
9
|
|
|
10
|
+
/** Default HTTP budget for records/bulk (ABAC projection can exceed 30s under load). */
|
|
11
|
+
const DEFAULT_BULK_SYNC_TIMEOUT_MS = 120000;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Resolve per-request timeout for bulk sync.
|
|
15
|
+
* @param {Object} [transportOpts]
|
|
16
|
+
* @returns {number}
|
|
17
|
+
*/
|
|
18
|
+
function resolveBulkSyncTimeoutMs(transportOpts = {}) {
|
|
19
|
+
const raw = transportOpts.timeoutMs ?? transportOpts.timeout;
|
|
20
|
+
if (raw === undefined || raw === null || raw === '') {
|
|
21
|
+
return DEFAULT_BULK_SYNC_TIMEOUT_MS;
|
|
22
|
+
}
|
|
23
|
+
const n = typeof raw === 'number' ? raw : parseInt(String(raw), 10);
|
|
24
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
25
|
+
return DEFAULT_BULK_SYNC_TIMEOUT_MS;
|
|
26
|
+
}
|
|
27
|
+
return n;
|
|
28
|
+
}
|
|
29
|
+
|
|
10
30
|
/**
|
|
11
31
|
* Bulk sync external records for a datasource.
|
|
12
32
|
* POST /api/v1/data-storage/{sourceIdOrKey}/records/bulk
|
|
@@ -16,13 +36,16 @@ const { unwrapApiData } = require('../utils/external-system-readiness-core');
|
|
|
16
36
|
* @param {string} sourceIdOrKey
|
|
17
37
|
* @param {Object} authConfig
|
|
18
38
|
* @param {import('./types/records-bulk.types').ExternalRecordBulkRequest} body
|
|
39
|
+
* @param {Object} [transportOpts]
|
|
40
|
+
* @param {number} [transportOpts.timeoutMs] - Per-request HTTP timeout (default 120000)
|
|
19
41
|
* @returns {Promise<import('./types/records-bulk.types').ExternalRecordBulkResponse>}
|
|
20
42
|
*/
|
|
21
|
-
async function bulkSyncRecords(dataplaneUrl, sourceIdOrKey, authConfig, body) {
|
|
43
|
+
async function bulkSyncRecords(dataplaneUrl, sourceIdOrKey, authConfig, body, transportOpts = {}) {
|
|
22
44
|
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
45
|
+
const timeoutMs = resolveBulkSyncTimeoutMs(transportOpts);
|
|
23
46
|
const res = await client.post(
|
|
24
47
|
`/api/v1/data-storage/${encodeURIComponent(sourceIdOrKey)}/records/bulk`,
|
|
25
|
-
{ body }
|
|
48
|
+
{ body, timeoutMs }
|
|
26
49
|
);
|
|
27
50
|
if (res && res.success === false) {
|
|
28
51
|
const msg =
|
|
@@ -39,5 +62,7 @@ async function bulkSyncRecords(dataplaneUrl, sourceIdOrKey, authConfig, body) {
|
|
|
39
62
|
}
|
|
40
63
|
|
|
41
64
|
module.exports = {
|
|
42
|
-
bulkSyncRecords
|
|
65
|
+
bulkSyncRecords,
|
|
66
|
+
resolveBulkSyncTimeoutMs,
|
|
67
|
+
DEFAULT_BULK_SYNC_TIMEOUT_MS
|
|
43
68
|
};
|
|
@@ -12,7 +12,7 @@ const BASE = '/api/v1/resource-types';
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* List resource types (paginated)
|
|
15
|
-
* @requiresPermission {Controller}
|
|
15
|
+
* @requiresPermission {Controller} resource-types:read
|
|
16
16
|
* @async
|
|
17
17
|
* @function listResourceTypes
|
|
18
18
|
* @param {string} controllerUrl
|
|
@@ -34,7 +34,7 @@ async function listResourceTypes(controllerUrl, authConfig, options = {}) {
|
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
36
|
* Get a resource type by id or key
|
|
37
|
-
* @requiresPermission {Controller}
|
|
37
|
+
* @requiresPermission {Controller} resource-types:read
|
|
38
38
|
* @async
|
|
39
39
|
* @function getResourceType
|
|
40
40
|
* @param {string} controllerUrl
|
|
@@ -49,7 +49,7 @@ async function getResourceType(controllerUrl, authConfig, resourceTypeIdOrKey) {
|
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* Create a resource type
|
|
52
|
-
* @requiresPermission {Controller}
|
|
52
|
+
* @requiresPermission {Controller} resource-types:create
|
|
53
53
|
* @async
|
|
54
54
|
* @function createResourceType
|
|
55
55
|
* @param {string} controllerUrl
|
|
@@ -75,7 +75,7 @@ async function createResourceType(controllerUrl, authConfig, body) {
|
|
|
75
75
|
|
|
76
76
|
/**
|
|
77
77
|
* Create-if-missing (idempotent): if a resource type already exists for the key, return success.
|
|
78
|
-
* @requiresPermission {Controller}
|
|
78
|
+
* @requiresPermission {Controller} resource-types:read + resource-types:create
|
|
79
79
|
* @async
|
|
80
80
|
* @function createResourceTypeIdempotent
|
|
81
81
|
* @param {string} controllerUrl
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Business roles API (Controller /api/v1/roles)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { ApiClient } = require('./index');
|
|
10
|
+
|
|
11
|
+
const BASE = '/api/v1/roles';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* List business roles (paginated)
|
|
15
|
+
* @requiresPermission {Controller} roles:read
|
|
16
|
+
* @async
|
|
17
|
+
* @param {string} controllerUrl
|
|
18
|
+
* @param {Object} authConfig
|
|
19
|
+
* @param {Object} [options]
|
|
20
|
+
* @returns {Promise<Object>}
|
|
21
|
+
*/
|
|
22
|
+
async function listRoles(controllerUrl, authConfig, options = {}) {
|
|
23
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
24
|
+
return await client.get(BASE, { params: options });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get a business role by id or key
|
|
29
|
+
* @requiresPermission {Controller} roles:read
|
|
30
|
+
* @async
|
|
31
|
+
* @param {string} controllerUrl
|
|
32
|
+
* @param {Object} authConfig
|
|
33
|
+
* @param {string} roleIdOrKey
|
|
34
|
+
* @returns {Promise<Object>}
|
|
35
|
+
*/
|
|
36
|
+
async function getRole(controllerUrl, authConfig, roleIdOrKey) {
|
|
37
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
38
|
+
return await client.get(`${BASE}/${encodeURIComponent(roleIdOrKey)}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {Object} payload
|
|
43
|
+
* @param {string} key
|
|
44
|
+
* @param {*} value
|
|
45
|
+
* @returns {void}
|
|
46
|
+
*/
|
|
47
|
+
function assignOptionalString(payload, key, value) {
|
|
48
|
+
if (value !== undefined && value !== null && value !== '') {
|
|
49
|
+
payload[key] = value;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param {import('./types/roles.types').CreateBusinessRoleRequest} body
|
|
55
|
+
* @returns {Object}
|
|
56
|
+
*/
|
|
57
|
+
function buildCreateRoleBody(body) {
|
|
58
|
+
const payload = {
|
|
59
|
+
key: body.key,
|
|
60
|
+
domainKey: body.domainKey,
|
|
61
|
+
displayName: body.displayName
|
|
62
|
+
};
|
|
63
|
+
assignOptionalString(payload, 'description', body.description);
|
|
64
|
+
assignOptionalString(payload, 'purpose', body.purpose);
|
|
65
|
+
assignOptionalString(payload, 'businessOutcome', body.businessOutcome);
|
|
66
|
+
assignOptionalString(payload, 'source', body.source);
|
|
67
|
+
if (body.isActive !== undefined && body.isActive !== null) {
|
|
68
|
+
payload.isActive = Boolean(body.isActive);
|
|
69
|
+
}
|
|
70
|
+
if (body.metadata && typeof body.metadata === 'object') {
|
|
71
|
+
payload.metadata = body.metadata;
|
|
72
|
+
}
|
|
73
|
+
return payload;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Create a business role
|
|
78
|
+
* @requiresPermission {Controller} roles:create
|
|
79
|
+
* @async
|
|
80
|
+
* @param {string} controllerUrl
|
|
81
|
+
* @param {Object} authConfig
|
|
82
|
+
* @param {import('./types/roles.types').CreateBusinessRoleRequest} body
|
|
83
|
+
* @returns {Promise<Object>}
|
|
84
|
+
*/
|
|
85
|
+
async function createRole(controllerUrl, authConfig, body) {
|
|
86
|
+
const client = new ApiClient(controllerUrl, authConfig);
|
|
87
|
+
return await client.post(BASE, { body: buildCreateRoleBody(body) });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Create-if-missing (idempotent): if a role already exists for the key, return success.
|
|
92
|
+
* @requiresPermission {Controller} roles:read + roles:create
|
|
93
|
+
* @async
|
|
94
|
+
* @param {string} controllerUrl
|
|
95
|
+
* @param {Object} authConfig
|
|
96
|
+
* @param {import('./types/roles.types').CreateBusinessRoleRequest} body
|
|
97
|
+
* @returns {Promise<{ created: boolean, response: Object }>}
|
|
98
|
+
*/
|
|
99
|
+
async function createRoleIdempotent(controllerUrl, authConfig, body) {
|
|
100
|
+
const key = String(body?.key || '').trim();
|
|
101
|
+
if (!key) {
|
|
102
|
+
throw new Error('Role key is required');
|
|
103
|
+
}
|
|
104
|
+
const getRes = await getRole(controllerUrl, authConfig, key);
|
|
105
|
+
if (getRes && getRes.success === true) {
|
|
106
|
+
return { created: false, response: getRes };
|
|
107
|
+
}
|
|
108
|
+
const createRes = await createRole(controllerUrl, authConfig, body);
|
|
109
|
+
if (createRes && createRes.success === true) {
|
|
110
|
+
return { created: true, response: createRes };
|
|
111
|
+
}
|
|
112
|
+
const msg = createRes?.error || createRes?.formattedError || 'Failed to create role';
|
|
113
|
+
throw new Error(msg);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
module.exports = {
|
|
117
|
+
listRoles,
|
|
118
|
+
getRole,
|
|
119
|
+
createRole,
|
|
120
|
+
createRoleIdempotent
|
|
121
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Evidence kind API type definitions (Controller /api/v1/evidence-kinds)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Create evidence kind request body (API shape uses domainKey)
|
|
9
|
+
* @typedef {Object} CreateEvidenceKindRequest
|
|
10
|
+
* @property {string} key - Catalog key (lowercase, digits, underscores)
|
|
11
|
+
* @property {string} domainKey - Enterprise domain key
|
|
12
|
+
* @property {string} displayName - Human-readable name
|
|
13
|
+
* @property {string} purpose - Purpose (required by Controller)
|
|
14
|
+
* @property {string} [description] - Optional description
|
|
15
|
+
* @property {string} [expectedUse] - Expected use guidance
|
|
16
|
+
* @property {string} [defaultSeverity] - low | medium | high | critical
|
|
17
|
+
* @property {boolean} [requiresApproval] - Approval flag
|
|
18
|
+
* @property {boolean} [isActive] - Active flag
|
|
19
|
+
* @property {number} [sortOrder] - Sort order
|
|
20
|
+
* @property {string} [source] - Provenance source
|
|
21
|
+
* @property {Object} [metadata] - Extensions
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Evidence kind record
|
|
26
|
+
* @typedef {Object} EvidenceKindRecord
|
|
27
|
+
* @property {string} id - Controller id
|
|
28
|
+
* @property {string} key - Catalog key
|
|
29
|
+
* @property {string} domainKey - Enterprise domain key
|
|
30
|
+
* @property {string} displayName - Display name
|
|
31
|
+
* @property {string} purpose - Purpose
|
|
32
|
+
* @property {string} [description] - Description
|
|
33
|
+
* @property {string} [expectedUse] - Expected use
|
|
34
|
+
* @property {string} [defaultSeverity] - Default severity
|
|
35
|
+
* @property {boolean} requiresApproval - Approval flag
|
|
36
|
+
* @property {boolean} isActive - Active flag
|
|
37
|
+
* @property {number} sortOrder - Sort order
|
|
38
|
+
* @property {string} [source] - Source
|
|
39
|
+
* @property {Object} [metadata] - Metadata
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
module.exports = {};
|