@aifabrix/builder 2.51.0 → 2.51.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/jest.isolated-projects.js +77 -1
- package/jest.projects.js +5 -426
- package/lib/api/assistants.api.js +67 -0
- package/lib/api/datasources-extended.api.js +6 -6
- package/lib/api/evidence-authoring-helpers.js +267 -0
- package/lib/api/evidence-authoring.api.js +337 -0
- package/lib/api/evidence.api.js +57 -1
- package/lib/api/index.js +24 -7
- package/lib/api/pipeline.api.js +43 -3
- package/lib/api/records-bulk.api.js +28 -3
- package/lib/api/types/evidence.types.js +156 -8
- package/lib/api/work.api.js +283 -0
- package/lib/app/run-deploy-job.js +108 -0
- package/lib/app/run-helpers.js +10 -3
- package/lib/app/run.js +8 -0
- package/lib/channels/add-channel.js +54 -23
- package/lib/channels/approval-guides/chatgpt.js +8 -7
- package/lib/channels/approval-guides/microsoft-copilot.js +7 -8
- package/lib/channels/channel-artifact-generator.js +14 -2
- package/lib/channels/channel-credential.js +3 -1
- package/lib/channels/channel-probe-evidence.js +79 -0
- package/lib/channels/channel-probe.js +265 -13
- package/lib/channels/channel-runtime-resolver.js +120 -29
- package/lib/channels/channel-status-display.js +44 -0
- package/lib/channels/channel-targets.js +7 -0
- package/lib/channels/chatgpt-runtime-contract.js +29 -0
- package/lib/channels/microsoft-copilot-package.js +280 -0
- package/lib/channels/runtime-tool-catalog.js +165 -0
- package/lib/cli/index.js +2 -0
- package/lib/cli/setup-app.js +4 -0
- package/lib/cli/setup-external-system-help.js +8 -2
- package/lib/cli/setup-external-system.js +12 -0
- package/lib/commands/app-test.js +2 -14
- package/lib/commands/datasource-load-export-cli.js +6 -1
- package/lib/commands/deploy-gate-failure-details.js +19 -17
- package/lib/commands/dev-down.js +2 -6
- package/lib/commands/evidence-kind.js +65 -15
- package/lib/commands/governance-generate-external.js +56 -21
- package/lib/commands/lifecycle-external.js +10 -4
- package/lib/commands/repair-datasource-apply.js +10 -1
- package/lib/commands/repair-datasource-run.js +4 -2
- package/lib/commands/repair-datasource-test-payload.js +80 -19
- package/lib/commands/repair-datasource-webhooks-sync-bridge.js +42 -3
- package/lib/commands/repair-internal.js +9 -1
- package/lib/commands/repair-openapi-sync.js +34 -17
- package/lib/commands/role-assistant.js +313 -0
- package/lib/commands/upload-data-sync-finalize.js +5 -4
- package/lib/commands/upload-sidecar-followups.js +144 -47
- package/lib/commands/upload.js +43 -6
- package/lib/commands/verify-governance-combined-external.js +73 -9
- package/lib/commands/verify-governance-db.js +80 -25
- package/lib/commands/verify-governance-external.js +29 -5
- package/lib/commands/wizard-core-helpers.js +7 -3
- package/lib/commands/wizard-core.js +78 -9
- package/lib/datasource/bulk-loader-run-batches.js +4 -2
- package/lib/datasource/bulk-loader-service.js +5 -1
- package/lib/datasource/datasource-validate-summary.js +2 -2
- package/lib/datasource/validate.js +13 -6
- package/lib/external-system/deploy-helpers.js +35 -1
- package/lib/external-system/deploy.js +23 -10
- package/lib/external-system/download-helpers.js +111 -2
- package/lib/external-system/download-role-assistant.js +55 -0
- package/lib/external-system/download.js +45 -26
- package/lib/external-system/test-helpers.js +1 -1
- package/lib/external-system/test.js +39 -3
- package/lib/generator/builders.js +3 -0
- package/lib/generator/wizard.js +51 -4
- package/lib/lifecycle/access-control-abac.js +121 -0
- package/lib/lifecycle/lifecycle-governance-options.js +4 -1
- package/lib/lifecycle/product-model.js +3 -2
- package/lib/lifecycle/report-display.js +14 -2
- package/lib/programmatic/capability-registry.js +20 -1
- package/lib/programmatic/command-options.js +1 -0
- package/lib/programmatic/index.js +4 -0
- package/lib/programmatic/manifest-patch-section.js +48 -9
- package/lib/programmatic/manifest-section-registry-data.js +3 -2
- package/lib/programmatic/openapi-apply-result-schemas.js +44 -0
- package/lib/programmatic/openapi-component-schemas.js +16 -1
- package/lib/programmatic/openapi-description-enricher.js +3 -1
- package/lib/programmatic/openapi-descriptions.js +55 -5
- package/lib/programmatic/openapi-evidence-schemas.js +161 -0
- package/lib/programmatic/openapi-manifest-schemas.js +6 -2
- package/lib/programmatic/openapi-operation-bindings.js +99 -0
- package/lib/programmatic/openapi-request-schemas.js +36 -1
- package/lib/programmatic/openapi-result-schemas.js +1 -1
- package/lib/programmatic/openapi-schema-descriptions-certify.js +5 -1
- package/lib/programmatic/openapi-schema-descriptions-core.js +1 -1
- package/lib/programmatic/openapi-schema-descriptions-evidence.js +156 -0
- package/lib/programmatic/openapi-schema-descriptions-manifest.js +4 -3
- package/lib/programmatic/openapi-schema-descriptions-operations.js +70 -0
- package/lib/programmatic/openapi-spec.js +47 -28
- package/lib/programmatic/orchestration-openapi-meta.js +5 -0
- package/lib/programmatic/request-timeout.js +3 -0
- package/lib/programmatic/route-handler-map.js +89 -2
- package/lib/programmatic/run-certify.js +15 -2
- package/lib/programmatic/run-deploy.js +74 -0
- package/lib/programmatic/run-evidence-authoring.js +80 -0
- package/lib/programmatic/run-protection.js +124 -0
- package/lib/programmatic/run-template-workspace.js +28 -1
- package/lib/programmatic/workspace-context.js +6 -0
- package/lib/protection/auth-context.js +48 -6
- package/lib/protection/paths.js +22 -0
- package/lib/protection/run-protection-create-helpers.js +22 -1
- package/lib/protection/run-protection-create.js +1 -1
- package/lib/protection/sync-after-upload.js +1 -1
- package/lib/role-assistant/evidence-sync.js +450 -0
- package/lib/role-assistant/github-workflow.js +96 -0
- package/lib/role-assistant/knowledge-sync.js +465 -0
- package/lib/role-assistant/settings.js +126 -0
- package/lib/role-assistant/test-cases-evaluate.js +170 -0
- package/lib/role-assistant/test-cases-honesty.js +184 -0
- package/lib/role-assistant/test-cases.js +364 -0
- package/lib/role-assistant/test-runner-workhub-answers.js +203 -0
- package/lib/role-assistant/test-runner-workhub.js +385 -0
- package/lib/role-assistant/test-runner.js +500 -0
- package/lib/schema/application-schema.json +16 -2
- package/lib/schema/deployment-rules.yaml +1 -0
- package/lib/schema/external-datasource.schema.json +38 -4
- package/lib/schema/external-system.schema.json +4 -4
- package/lib/schema/infra.parameter.yaml +20 -0
- package/lib/schema/role-assistant-settings.schema.json +108 -0
- package/lib/utils/api.js +52 -27
- package/lib/utils/app-path-resolve.js +72 -24
- package/lib/utils/authentication-shape.js +3 -1
- package/lib/utils/deployment-validation.js +28 -3
- package/lib/utils/docker-run-ephemeral.js +55 -0
- package/lib/utils/enterprise-knowledge-paths.js +29 -12
- package/lib/utils/env-copy-keycloak.js +196 -0
- package/lib/utils/env-copy.js +34 -1
- package/lib/utils/external-system-readiness-compact-display.js +3 -0
- package/lib/utils/help-builder.js +1 -0
- package/lib/utils/paths.js +67 -23
- package/lib/utils/pipeline-upload-auth-retry.js +15 -3
- package/lib/utils/role-assistant-paths.js +98 -0
- package/lib/utils/schema-loader.js +41 -0
- package/lib/utils/schema-resolver.js +36 -4
- package/lib/utils/token-manager.js +38 -29
- package/lib/utils/url-declarative-resolve-load-doc.js +38 -1
- package/lib/validation/external-manifest-validator.js +31 -8
- package/lib/validation/validate-external-file.js +8 -1
- package/package.json +2 -1
- package/scripts/export-builder-api-evidence.js +1 -1
- package/templates/applications/dataplane/application.yaml +23 -15
- package/templates/applications/dataplane/env.template +1 -1
- package/templates/applications/dataplane/rbac.yaml +14 -0
- package/templates/applications/miso-controller/application.yaml +1 -1
- package/templates/applications/miso-controller/env.template +3 -1
- package/templates/channels/chatgpt/install.template.md.hbs +42 -24
- package/templates/channels/chatgpt/integration/README.md +10 -7
- package/templates/channels/chatgpt/integration/application.json +2 -2
- package/templates/channels/chatgpt/integration/chatgpt-system.json +3 -3
- package/templates/channels/chatgpt/integration/env.template +1 -1
- package/templates/channels/chatgpt/manifest.template.json.hbs +36 -5
- package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +28 -0
- package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +22 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +32 -22
- package/templates/channels/microsoft-copilot/integration/README.md +9 -7
- package/templates/channels/microsoft-copilot/integration/application.json +2 -2
- package/templates/channels/microsoft-copilot/integration/env.template +1 -1
- package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +7 -6
- package/templates/channels/microsoft-copilot/manifest.template.json.hbs +34 -6
- /package/.cursor/plans/{157.1-security-quality-violations-by-type.csv → Done/157.1-security-quality-violations-by-type.csv} +0 -0
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
'use strict';
|
|
9
9
|
|
|
10
|
-
/** @typedef {'VERIFIED'|'FAILED'|'NOT_VERIFIED'} LifecycleVerdict */
|
|
10
|
+
/** @typedef {'VERIFIED'|'FAILED'|'NOT_VERIFIED'|'NOT_APPLICABLE'} LifecycleVerdict */
|
|
11
11
|
|
|
12
12
|
/** @typedef {'BRONZE'|'SILVER'|'GOLD'|'PLATINUM'|'NONE'} CertificationLevel */
|
|
13
13
|
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
const VERDICT = Object.freeze({
|
|
17
17
|
VERIFIED: 'VERIFIED',
|
|
18
18
|
FAILED: 'FAILED',
|
|
19
|
-
NOT_VERIFIED: 'NOT_VERIFIED'
|
|
19
|
+
NOT_VERIFIED: 'NOT_VERIFIED',
|
|
20
|
+
NOT_APPLICABLE: 'NOT_APPLICABLE'
|
|
20
21
|
});
|
|
21
22
|
|
|
22
23
|
const CERTIFICATION_LEVEL = Object.freeze({
|
|
@@ -58,9 +58,13 @@ function displayHeroMetric(label, percent) {
|
|
|
58
58
|
logger.log('');
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
function displayVerdictLine(verdict, verifiedLabel, failedLabel) {
|
|
61
|
+
function displayVerdictLine(verdict, verifiedLabel, failedLabel, notApplicableLabel) {
|
|
62
62
|
if (verdict === VERDICT.VERIFIED) {
|
|
63
63
|
logger.log(formatSuccessParagraph(verifiedLabel));
|
|
64
|
+
} else if (verdict === VERDICT.NOT_APPLICABLE) {
|
|
65
|
+
logger.log(
|
|
66
|
+
formatSuccessParagraph(notApplicableLabel || 'NOT APPLICABLE')
|
|
67
|
+
);
|
|
64
68
|
} else {
|
|
65
69
|
logger.log(formatBlockingError(failedLabel));
|
|
66
70
|
}
|
|
@@ -196,7 +200,12 @@ function displayVerifyGovernanceTTY(systemKey, result, opts = {}) {
|
|
|
196
200
|
logger.log(chalk.white('Enforcement Scenarios'));
|
|
197
201
|
logger.log(chalk.cyan.bold(`${passed}/${total} Passed`));
|
|
198
202
|
logger.log('');
|
|
199
|
-
displayVerdictLine(
|
|
203
|
+
displayVerdictLine(
|
|
204
|
+
result.verdict,
|
|
205
|
+
'GOVERNANCE VERIFIED',
|
|
206
|
+
'GOVERNANCE FAILED',
|
|
207
|
+
'GOVERNANCE NOT APPLICABLE'
|
|
208
|
+
);
|
|
200
209
|
if (opts.details === true) {
|
|
201
210
|
displayGovernanceVerboseDetails(result);
|
|
202
211
|
}
|
|
@@ -209,6 +218,9 @@ function formatPillarLine(label, verdict) {
|
|
|
209
218
|
if (verdict === VERDICT.FAILED) {
|
|
210
219
|
return `${label.padEnd(24)}${failureGlyph()} FAILED`;
|
|
211
220
|
}
|
|
221
|
+
if (verdict === VERDICT.NOT_APPLICABLE) {
|
|
222
|
+
return `${label.padEnd(24)}— NOT APPLICABLE`;
|
|
223
|
+
}
|
|
212
224
|
return `${label.padEnd(24)}— NOT VERIFIED`;
|
|
213
225
|
}
|
|
214
226
|
|
|
@@ -40,6 +40,21 @@ const CAPABILITIES = Object.freeze([
|
|
|
40
40
|
{ method: 'POST', route: '/systems/:systemKey/certify/:pillar', handlerId: 'runCertifyPillar', operationType: 'certify', mutating: true },
|
|
41
41
|
{ method: 'GET', route: '/systems/:systemKey/lifecycle', handlerId: 'getLifecycleReport', operationType: 'certify.read', mutating: false },
|
|
42
42
|
{ method: 'POST', route: '/systems/:systemKey/upload', handlerId: 'runUpload', operationType: 'apply.dev', mutating: true },
|
|
43
|
+
{ method: 'POST', route: '/systems/:systemKey/deploy', handlerId: 'runDeploySystem', operationType: 'apply.prod', mutating: true },
|
|
44
|
+
{
|
|
45
|
+
method: 'POST',
|
|
46
|
+
route: '/systems/:systemKey/datasources/:datasourceKey/protection/upload',
|
|
47
|
+
handlerId: 'runProtectionUpload',
|
|
48
|
+
operationType: 'apply.protection',
|
|
49
|
+
mutating: true
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
method: 'POST',
|
|
53
|
+
route: '/systems/:systemKey/datasources/:datasourceKey/protection/create',
|
|
54
|
+
handlerId: 'runProtectionCreate',
|
|
55
|
+
operationType: 'apply.protection',
|
|
56
|
+
mutating: true
|
|
57
|
+
},
|
|
43
58
|
{ method: 'POST', route: '/systems/:systemKey/template/materialize', handlerId: 'materializeTemplate', operationType: 'template', mutating: true },
|
|
44
59
|
{ method: 'GET', route: '/systems/:systemKey/workspace/status', handlerId: 'getWorkspaceStatus', operationType: 'workspace.read', mutating: false },
|
|
45
60
|
{ method: 'POST', route: '/systems/:systemKey/workspace/diff', handlerId: 'runWorkspaceDiff', operationType: 'workspace.read', mutating: false },
|
|
@@ -49,7 +64,11 @@ const CAPABILITIES = Object.freeze([
|
|
|
49
64
|
{ method: 'GET', route: '/systems/:systemKey/repository/status', handlerId: 'getRepositoryStatus', operationType: 'repository.read', mutating: false },
|
|
50
65
|
{ method: 'POST', route: '/systems/:systemKey/repository/dispatch-pipeline', handlerId: 'runRepositoryDispatchPipeline', operationType: 'repository', mutating: true },
|
|
51
66
|
{ method: 'GET', route: '/health', handlerId: 'health', operationType: 'infra', mutating: false },
|
|
52
|
-
{ method: 'GET', route: '/health/ready', handlerId: 'ready', operationType: 'infra', mutating: false }
|
|
67
|
+
{ method: 'GET', route: '/health/ready', handlerId: 'ready', operationType: 'infra', mutating: false },
|
|
68
|
+
{ method: 'GET', route: '/evidence/:roleKey/metadata', handlerId: 'getEvidenceMetadata', operationType: 'evidence.read', mutating: false },
|
|
69
|
+
{ method: 'GET', route: '/evidence/:roleKey/download', handlerId: 'downloadEvidence', operationType: 'evidence.read', mutating: false },
|
|
70
|
+
{ method: 'POST', route: '/evidence/:roleKey/upload', handlerId: 'uploadEvidenceCandidates', operationType: 'evidence.write', mutating: true },
|
|
71
|
+
{ method: 'POST', route: '/evidence/:roleKey/activate', handlerId: 'activateEvidenceCandidates', operationType: 'evidence.activate', mutating: true }
|
|
53
72
|
]);
|
|
54
73
|
|
|
55
74
|
/**
|
|
@@ -22,6 +22,7 @@ function mergeProgrammaticOptions(ctx, options = {}) {
|
|
|
22
22
|
authConfig: auth.authConfig,
|
|
23
23
|
dataplaneUrl: auth.dataplaneUrl,
|
|
24
24
|
environment: auth.environment,
|
|
25
|
+
controllerUrl: ctx.controllerUrl || options.controllerUrl,
|
|
25
26
|
silentResolve: true,
|
|
26
27
|
minimal: options.minimal !== false
|
|
27
28
|
};
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
const workspaceContext = require('./workspace-context');
|
|
8
8
|
const runUpload = require('./run-upload');
|
|
9
|
+
const runDeploy = require('./run-deploy');
|
|
10
|
+
const runProtection = require('./run-protection');
|
|
9
11
|
const runWizard = require('./run-wizard');
|
|
10
12
|
const runRepair = require('./run-repair');
|
|
11
13
|
const runValidate = require('./run-validate');
|
|
@@ -29,6 +31,8 @@ const enterpriseMcpClient = require('./enterprise-mcp-client');
|
|
|
29
31
|
module.exports = {
|
|
30
32
|
...workspaceContext,
|
|
31
33
|
...runUpload,
|
|
34
|
+
...runDeploy,
|
|
35
|
+
...runProtection,
|
|
32
36
|
...runWizard,
|
|
33
37
|
...runRepair,
|
|
34
38
|
...runValidate,
|
|
@@ -33,7 +33,7 @@ const { runWithWorkspaceContext } = require('./workspace-context');
|
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* @param {import('./workspace-context').WorkspaceContext} ctx
|
|
36
|
-
* @param {{ sectionKey: string, datasourceKey?: string, intent: string, patch: Object, mode: string, sectionReadToken
|
|
36
|
+
* @param {{ sectionKey: string, datasourceKey?: string, intent: string, patch: Object, mode: string, sectionReadToken?: string, dryRun?: boolean }} body
|
|
37
37
|
*/
|
|
38
38
|
async function patchManifestSection(ctx, body) {
|
|
39
39
|
return runWithWorkspaceContext(ctx, async() => {
|
|
@@ -43,10 +43,11 @@ async function patchManifestSection(ctx, body) {
|
|
|
43
43
|
|
|
44
44
|
const loaded = loadTargetDocument(ctx, def.target, body.datasourceKey);
|
|
45
45
|
const beforeValue = extractSectionValue(loaded.doc, def);
|
|
46
|
-
|
|
46
|
+
assertSectionReadToken(body, beforeValue);
|
|
47
47
|
|
|
48
48
|
const draft = JSON.parse(JSON.stringify(loaded.doc));
|
|
49
|
-
|
|
49
|
+
const patchValue = normalizeSectionPatch(def, body.patch);
|
|
50
|
+
injectSectionValue(draft, def, patchValue, body.mode === 'replace' ? 'replace' : 'merge');
|
|
50
51
|
validateDraftDocument(def.target, draft);
|
|
51
52
|
|
|
52
53
|
const afterValue = extractSectionValue(draft, def);
|
|
@@ -58,6 +59,47 @@ async function patchManifestSection(ctx, body) {
|
|
|
58
59
|
});
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Scalar single-path sections (resourceType, entityType, syncBridge, …) accept
|
|
64
|
+
* `{ value: <scalar> }` or `{ <leaf>: <scalar> }` because OpenAPI types `patch` as object.
|
|
65
|
+
*
|
|
66
|
+
* @param {import('./manifest-section-registry-data').SectionDefinition} def
|
|
67
|
+
* @param {Object} patch
|
|
68
|
+
* @returns {*}
|
|
69
|
+
*/
|
|
70
|
+
function normalizeSectionPatch(def, patch) {
|
|
71
|
+
if (!def || !Array.isArray(def.paths) || def.paths.length !== 1) {
|
|
72
|
+
return patch;
|
|
73
|
+
}
|
|
74
|
+
if (!patch || typeof patch !== 'object' || Array.isArray(patch)) {
|
|
75
|
+
return patch;
|
|
76
|
+
}
|
|
77
|
+
const keys = Object.keys(patch);
|
|
78
|
+
if (keys.length !== 1) {
|
|
79
|
+
return patch;
|
|
80
|
+
}
|
|
81
|
+
const leaf = def.paths[0].includes('.') ? def.paths[0].split('.').pop() : def.paths[0];
|
|
82
|
+
if (keys[0] === 'value' || keys[0] === leaf) {
|
|
83
|
+
return patch[keys[0]];
|
|
84
|
+
}
|
|
85
|
+
return patch;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* When sectionReadToken is omitted, trust the freshly loaded section value
|
|
90
|
+
* (CLI patch-section parity — plan 496.2). Explicit tokens still verify.
|
|
91
|
+
*
|
|
92
|
+
* @param {Object} body
|
|
93
|
+
* @param {*} beforeValue
|
|
94
|
+
*/
|
|
95
|
+
function assertSectionReadToken(body, beforeValue) {
|
|
96
|
+
const token = typeof body.sectionReadToken === 'string' ? body.sectionReadToken.trim() : '';
|
|
97
|
+
if (!token) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
verifyReadToken({ ...body, sectionReadToken: token }, beforeValue);
|
|
101
|
+
}
|
|
102
|
+
|
|
61
103
|
/**
|
|
62
104
|
* @param {Object} body
|
|
63
105
|
* @param {*} beforeValue
|
|
@@ -162,11 +204,6 @@ function assertPatchRequest(body) {
|
|
|
162
204
|
err.statusCode = 400;
|
|
163
205
|
throw err;
|
|
164
206
|
}
|
|
165
|
-
if (!body.sectionReadToken) {
|
|
166
|
-
const err = new Error('sectionReadToken is required — GET the section first');
|
|
167
|
-
err.statusCode = 400;
|
|
168
|
-
throw err;
|
|
169
|
-
}
|
|
170
207
|
if (body.mode !== 'merge' && body.mode !== 'replace') {
|
|
171
208
|
const err = new Error('mode must be merge or replace');
|
|
172
209
|
err.statusCode = 400;
|
|
@@ -248,5 +285,7 @@ function buildRiskHints(sectionKey, patch, downstream) {
|
|
|
248
285
|
}
|
|
249
286
|
|
|
250
287
|
module.exports = {
|
|
251
|
-
patchManifestSection
|
|
288
|
+
patchManifestSection,
|
|
289
|
+
normalizeSectionPatch,
|
|
290
|
+
assertSectionReadToken
|
|
252
291
|
};
|
|
@@ -226,11 +226,12 @@ const SECTION_DEFINITIONS = Object.freeze({
|
|
|
226
226
|
},
|
|
227
227
|
'datasource.dimensions': {
|
|
228
228
|
target: 'datasource',
|
|
229
|
-
|
|
229
|
+
// Canonical root is top-level `dimensions` (fieldMappings.dimensions removed).
|
|
230
|
+
paths: ['dimensions'],
|
|
230
231
|
mutable: true,
|
|
231
232
|
required: false,
|
|
232
233
|
sourceOfTruth: true,
|
|
233
|
-
repairHooks: [
|
|
234
|
+
repairHooks: []
|
|
234
235
|
},
|
|
235
236
|
'datasource.abac': {
|
|
236
237
|
target: 'datasource',
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI result schemas for deploy and protection apply routes.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Split from openapi-result-schemas for file-size limits
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const { frozenObject, schemaRef } = require('./openapi-schema-helpers');
|
|
12
|
+
|
|
13
|
+
/** @type {Record<string, Object>} */
|
|
14
|
+
const OPENAPI_APPLY_RESULT_SCHEMAS = {
|
|
15
|
+
DeployResultData: frozenObject(
|
|
16
|
+
{
|
|
17
|
+
deployed: { type: 'boolean' },
|
|
18
|
+
deploymentId: { type: 'string' },
|
|
19
|
+
environment: { type: 'string' },
|
|
20
|
+
systemKey: schemaRef('SystemKey')
|
|
21
|
+
},
|
|
22
|
+
['deployed']
|
|
23
|
+
),
|
|
24
|
+
ProtectionUploadData: frozenObject(
|
|
25
|
+
{
|
|
26
|
+
datasourceKey: schemaRef('DatasourceKey'),
|
|
27
|
+
uploaded: { type: 'boolean' },
|
|
28
|
+
dryRun: { type: 'boolean' }
|
|
29
|
+
},
|
|
30
|
+
['datasourceKey', 'uploaded', 'dryRun']
|
|
31
|
+
),
|
|
32
|
+
ProtectionCreateData: frozenObject(
|
|
33
|
+
{
|
|
34
|
+
datasourceKey: schemaRef('DatasourceKey'),
|
|
35
|
+
created: { type: 'boolean' },
|
|
36
|
+
dryRun: { type: 'boolean' }
|
|
37
|
+
},
|
|
38
|
+
['datasourceKey', 'created', 'dryRun']
|
|
39
|
+
)
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
module.exports = {
|
|
43
|
+
OPENAPI_APPLY_RESULT_SCHEMAS
|
|
44
|
+
};
|
|
@@ -12,10 +12,15 @@ const { enrichOpenApiComponentSchemas } = require('./openapi-description-enriche
|
|
|
12
12
|
const { buildSuccessEnvelopeSchema } = require('./openapi-schema-helpers');
|
|
13
13
|
const { OPENAPI_REQUEST_SCHEMAS } = require('./openapi-request-schemas');
|
|
14
14
|
const { OPENAPI_RESULT_SCHEMAS } = require('./openapi-result-schemas');
|
|
15
|
+
const { OPENAPI_APPLY_RESULT_SCHEMAS } = require('./openapi-apply-result-schemas');
|
|
15
16
|
const {
|
|
16
17
|
OPENAPI_MANIFEST_REQUEST_SCHEMAS,
|
|
17
18
|
OPENAPI_MANIFEST_RESULT_SCHEMAS
|
|
18
19
|
} = require('./openapi-manifest-schemas');
|
|
20
|
+
const {
|
|
21
|
+
OPENAPI_EVIDENCE_REQUEST_SCHEMAS,
|
|
22
|
+
OPENAPI_EVIDENCE_RESULT_SCHEMAS
|
|
23
|
+
} = require('./openapi-evidence-schemas');
|
|
19
24
|
|
|
20
25
|
const RESPONSE_ENVELOPES = [
|
|
21
26
|
['ListSystemsResponse', 'ListSystemsData'],
|
|
@@ -27,6 +32,9 @@ const RESPONSE_ENVELOPES = [
|
|
|
27
32
|
['ValidateResultResponse', 'ValidateResultData'],
|
|
28
33
|
['PreviewUploadResponse', 'PreviewUploadData'],
|
|
29
34
|
['UploadResultResponse', 'UploadResultData'],
|
|
35
|
+
['DeployResultResponse', 'DeployResultData'],
|
|
36
|
+
['ProtectionUploadResponse', 'ProtectionUploadData'],
|
|
37
|
+
['ProtectionCreateResponse', 'ProtectionCreateData'],
|
|
30
38
|
['TestResultResponse', 'TestResultData'],
|
|
31
39
|
['CertifyResultResponse', 'CertifyResultData'],
|
|
32
40
|
['LifecycleReportResponse', 'LifecycleReportData'],
|
|
@@ -39,7 +47,11 @@ const RESPONSE_ENVELOPES = [
|
|
|
39
47
|
['ManifestSectionViewResponse', 'ManifestSectionViewData'],
|
|
40
48
|
['ManifestPatchResultResponse', 'ManifestPatchResultData'],
|
|
41
49
|
['ManifestSectionsListResponse', 'ManifestSectionsListData'],
|
|
42
|
-
['ManifestRepairResultResponse', 'ManifestRepairResultData']
|
|
50
|
+
['ManifestRepairResultResponse', 'ManifestRepairResultData'],
|
|
51
|
+
['EvidenceAuthoringMetadataResponse', 'EvidenceAuthoringMetadataData'],
|
|
52
|
+
['EvidenceDownloadResponse', 'EvidenceDownloadData'],
|
|
53
|
+
['EvidenceUploadResponse', 'EvidenceUploadData'],
|
|
54
|
+
['EvidenceActivateResponse', 'EvidenceActivateData']
|
|
43
55
|
];
|
|
44
56
|
|
|
45
57
|
/**
|
|
@@ -53,8 +65,11 @@ function buildOpenApiComponentSchemas() {
|
|
|
53
65
|
return enrichOpenApiComponentSchemas({
|
|
54
66
|
...OPENAPI_REQUEST_SCHEMAS,
|
|
55
67
|
...OPENAPI_MANIFEST_REQUEST_SCHEMAS,
|
|
68
|
+
...OPENAPI_EVIDENCE_REQUEST_SCHEMAS,
|
|
56
69
|
...OPENAPI_RESULT_SCHEMAS,
|
|
70
|
+
...OPENAPI_APPLY_RESULT_SCHEMAS,
|
|
57
71
|
...OPENAPI_MANIFEST_RESULT_SCHEMAS,
|
|
72
|
+
...OPENAPI_EVIDENCE_RESULT_SCHEMAS,
|
|
58
73
|
EmptyResultData: { type: 'object', properties: {}, additionalProperties: false },
|
|
59
74
|
...envelopes
|
|
60
75
|
});
|
|
@@ -14,6 +14,7 @@ const { CERTIFY_SCHEMA_DESCRIPTIONS } = require('./openapi-schema-descriptions-c
|
|
|
14
14
|
const { MANIFEST_SCHEMA_DESCRIPTIONS } = require('./openapi-schema-descriptions-manifest');
|
|
15
15
|
const { MCP_SCHEMA_DESCRIPTIONS } = require('./openapi-schema-descriptions-mcp');
|
|
16
16
|
const { HELP_SCHEMA_DESCRIPTIONS } = require('./openapi-schema-descriptions-help');
|
|
17
|
+
const { EVIDENCE_SCHEMA_DESCRIPTIONS } = require('./openapi-schema-descriptions-evidence');
|
|
17
18
|
|
|
18
19
|
/** @type {Record<string, Object>} */
|
|
19
20
|
const MERGED_SCHEMA_DESCRIPTIONS = {
|
|
@@ -22,7 +23,8 @@ const MERGED_SCHEMA_DESCRIPTIONS = {
|
|
|
22
23
|
...CERTIFY_SCHEMA_DESCRIPTIONS,
|
|
23
24
|
...MANIFEST_SCHEMA_DESCRIPTIONS,
|
|
24
25
|
...MCP_SCHEMA_DESCRIPTIONS,
|
|
25
|
-
...HELP_SCHEMA_DESCRIPTIONS
|
|
26
|
+
...HELP_SCHEMA_DESCRIPTIONS,
|
|
27
|
+
...EVIDENCE_SCHEMA_DESCRIPTIONS
|
|
26
28
|
};
|
|
27
29
|
|
|
28
30
|
/**
|
|
@@ -53,25 +53,32 @@ const OPERATION_DESCRIPTIONS = Object.freeze({
|
|
|
53
53
|
getManifestSection: {
|
|
54
54
|
summary: 'Read one system manifest section',
|
|
55
55
|
description:
|
|
56
|
-
'Return section value, schema fragment, quality, dependency graph, and sectionReadToken.
|
|
56
|
+
'Return section value, schema fragment, quality, dependency graph, and sectionReadToken. ' +
|
|
57
|
+
'Recommended before patch when quality or missingInputs are needed; token is optional on PATCH.',
|
|
57
58
|
tags: ['manifest']
|
|
58
59
|
},
|
|
59
60
|
patchManifestSection: {
|
|
60
61
|
summary: 'Patch one system manifest section',
|
|
61
62
|
description:
|
|
62
|
-
'Apply governed merge/replace to a system section. Requires intent
|
|
63
|
+
'Apply governed merge/replace to a system section. Requires intent. ' +
|
|
64
|
+
'sectionReadToken from GET is optional — when omitted, the server re-reads the section before write. ' +
|
|
65
|
+
'Stale tokens return 409. Mutating.',
|
|
63
66
|
tags: ['manifest']
|
|
64
67
|
},
|
|
65
68
|
getDatasourceManifestSection: {
|
|
66
69
|
summary: 'Read one datasource manifest section',
|
|
67
70
|
description:
|
|
68
|
-
'Return datasource section value, quality, missingInputs, and sectionReadToken.
|
|
71
|
+
'Return datasource section value, quality, missingInputs, and sectionReadToken. ' +
|
|
72
|
+
'Recommended before patch when quality or missingInputs are needed; token is optional on PATCH.',
|
|
69
73
|
tags: ['manifest']
|
|
70
74
|
},
|
|
71
75
|
patchDatasourceManifestSection: {
|
|
72
76
|
summary: 'Patch one datasource manifest section',
|
|
73
77
|
description:
|
|
74
|
-
'Apply governed merge/replace to a datasource section. Requires intent
|
|
78
|
+
'Apply governed merge/replace to a datasource section. Requires intent. ' +
|
|
79
|
+
'sectionReadToken is optional (server re-reads when omitted; stale token → 409). ' +
|
|
80
|
+
'For scalar sections (e.g. datasource.resourceType), send patch as { "value": "<scalar>" } or ' +
|
|
81
|
+
'{ "<leafName>": "<scalar>" }. Mutating.',
|
|
75
82
|
tags: ['manifest']
|
|
76
83
|
},
|
|
77
84
|
runManifestRepair: {
|
|
@@ -115,6 +122,24 @@ const OPERATION_DESCRIPTIONS = Object.freeze({
|
|
|
115
122
|
'Full dev publish: validate, sync deploy JSON, push credentials, pipeline upload. Requires external-system:publish in dev. Mutating; use Idempotency-Key; may take up to MAX_UPLOAD_TIMEOUT_MS.',
|
|
116
123
|
tags: ['apply']
|
|
117
124
|
},
|
|
125
|
+
runDeploySystem: {
|
|
126
|
+
summary: 'Deploy integration via controller (promote)',
|
|
127
|
+
description:
|
|
128
|
+
'Controller deploy for external systems (CLI aifabrix deploy parity). Optional body.gate matches CLI --gate (operations,trust,governance,full). Certificate seal is a platform side-effect of published Deploy — not a separate certificates issue call. Mutating; use Idempotency-Key.',
|
|
129
|
+
tags: ['apply']
|
|
130
|
+
},
|
|
131
|
+
runProtectionUpload: {
|
|
132
|
+
summary: 'Upload protection manifest for a datasource',
|
|
133
|
+
description:
|
|
134
|
+
'Validate and upload the workspace protection manifest for the datasource (CLI aifabrix protection upload parity). Optional sync after upload. Mutating; use Idempotency-Key.',
|
|
135
|
+
tags: ['apply']
|
|
136
|
+
},
|
|
137
|
+
runProtectionCreate: {
|
|
138
|
+
summary: 'Scaffold a local protection manifest',
|
|
139
|
+
description:
|
|
140
|
+
'Probe dataplane + dimension catalog and write integration/.protection scaffold (CLI aifabrix protection create parity). Mutating; use Idempotency-Key.',
|
|
141
|
+
tags: ['apply']
|
|
142
|
+
},
|
|
118
143
|
materializeTemplate: {
|
|
119
144
|
summary: 'Materialize workspace from template',
|
|
120
145
|
description:
|
|
@@ -128,7 +153,8 @@ const OPERATION_DESCRIPTIONS = Object.freeze({
|
|
|
128
153
|
},
|
|
129
154
|
runWorkspaceDiff: {
|
|
130
155
|
summary: 'Diff workspace draft',
|
|
131
|
-
description:
|
|
156
|
+
description:
|
|
157
|
+
'Diff local workspace draft vs remote/template baseline via Enterprise MCP workspace.diff when published; otherwise returns a local draft snapshot (source=local) without failing.',
|
|
132
158
|
tags: ['workspace']
|
|
133
159
|
},
|
|
134
160
|
resetWorkspaceFromTemplate: {
|
|
@@ -167,6 +193,30 @@ const OPERATION_DESCRIPTIONS = Object.freeze({
|
|
|
167
193
|
summary: 'Readiness probe',
|
|
168
194
|
description: 'Returns ready with configured dataplaneUrl. Does not verify Dataplane connectivity in V1.',
|
|
169
195
|
tags: ['infra']
|
|
196
|
+
},
|
|
197
|
+
getEvidenceMetadata: {
|
|
198
|
+
summary: 'Evidence authoring metadata',
|
|
199
|
+
description:
|
|
200
|
+
'Return live Evidence kinds, aspects, resource types, Role Assistant capabilities, writable fields, and certification/activation constraints for the selected roleKey. Read-only aggregation over Dataplane and Controller catalogs.',
|
|
201
|
+
tags: ['evidence']
|
|
202
|
+
},
|
|
203
|
+
downloadEvidence: {
|
|
204
|
+
summary: 'Download Role Assistant Evidence',
|
|
205
|
+
description:
|
|
206
|
+
'List or search Evidence for the selected roleKey using existing Dataplane Evidence filters. Read-only projection for AI authoring.',
|
|
207
|
+
tags: ['evidence']
|
|
208
|
+
},
|
|
209
|
+
uploadEvidenceCandidates: {
|
|
210
|
+
summary: 'Upload Evidence candidates',
|
|
211
|
+
description:
|
|
212
|
+
'Load one or many Evidence rows as inactive candidates, validate each row, and technically certify valid rows. Never activates. Mutating; use Idempotency-Key.',
|
|
213
|
+
tags: ['evidence']
|
|
214
|
+
},
|
|
215
|
+
activateEvidenceCandidates: {
|
|
216
|
+
summary: 'Activate certified Evidence',
|
|
217
|
+
description:
|
|
218
|
+
'Activate one or many human-approved certified Evidence ids. Organizational gate after technical certification. Mutating; use Idempotency-Key.',
|
|
219
|
+
tags: ['evidence']
|
|
170
220
|
}
|
|
171
221
|
});
|
|
172
222
|
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frozen OpenAPI request/result schemas for Evidence authoring routes (162.0).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview BTA-facing Evidence metadata/download/upload/activate models
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const { frozenObject, schemaRef, stringArraySchema } = require('./openapi-schema-helpers');
|
|
12
|
+
|
|
13
|
+
/** @type {Record<string, Object>} */
|
|
14
|
+
const OPENAPI_EVIDENCE_REQUEST_SCHEMAS = {
|
|
15
|
+
EvidenceUploadRow: frozenObject(
|
|
16
|
+
{
|
|
17
|
+
key: { type: 'string' },
|
|
18
|
+
resourceType: { type: 'string' },
|
|
19
|
+
roleKey: { type: 'string' },
|
|
20
|
+
kindKey: { type: 'string' },
|
|
21
|
+
kindVersion: { type: 'string' },
|
|
22
|
+
title: { type: 'string' },
|
|
23
|
+
description: { type: 'string' },
|
|
24
|
+
when: { type: 'string' },
|
|
25
|
+
expectedBehavior: { type: 'string' },
|
|
26
|
+
aspect: { type: 'string' },
|
|
27
|
+
order: { type: 'integer' },
|
|
28
|
+
status: { type: 'string', enum: ['candidate', 'active', 'disabled', 'archived'] }
|
|
29
|
+
},
|
|
30
|
+
['title', 'when', 'expectedBehavior']
|
|
31
|
+
),
|
|
32
|
+
EvidenceUploadRequest: frozenObject(
|
|
33
|
+
{
|
|
34
|
+
roleKey: {
|
|
35
|
+
type: 'string',
|
|
36
|
+
description: 'Optional override; defaults to the path roleKey.'
|
|
37
|
+
},
|
|
38
|
+
rows: { type: 'array', items: schemaRef('EvidenceUploadRow') },
|
|
39
|
+
comment: { type: 'string' }
|
|
40
|
+
},
|
|
41
|
+
['rows']
|
|
42
|
+
),
|
|
43
|
+
EvidenceActivateRequest: frozenObject(
|
|
44
|
+
{
|
|
45
|
+
evidenceIds: stringArraySchema()
|
|
46
|
+
},
|
|
47
|
+
['evidenceIds']
|
|
48
|
+
)
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** @type {Record<string, Object>} */
|
|
52
|
+
const OPENAPI_EVIDENCE_RESULT_SCHEMAS = {
|
|
53
|
+
EvidenceKindSummary: frozenObject({
|
|
54
|
+
key: { type: ['string', 'null'] },
|
|
55
|
+
version: { type: ['string', 'null'] },
|
|
56
|
+
displayName: { type: ['string', 'null'] },
|
|
57
|
+
purpose: { type: ['string', 'null'] }
|
|
58
|
+
}),
|
|
59
|
+
EvidenceResourceTypeSummary: frozenObject({
|
|
60
|
+
key: { type: ['string', 'null'] },
|
|
61
|
+
displayName: { type: ['string', 'null'] },
|
|
62
|
+
category: { type: ['string', 'null'] }
|
|
63
|
+
}),
|
|
64
|
+
EvidenceAuthoringConstraints: frozenObject({
|
|
65
|
+
certification: frozenObject({
|
|
66
|
+
validationStatus: { type: 'string' },
|
|
67
|
+
candidateStatus: { type: 'string' }
|
|
68
|
+
}),
|
|
69
|
+
activation: frozenObject({
|
|
70
|
+
requiresCertified: { type: 'boolean' },
|
|
71
|
+
requiresAuthority: { type: 'boolean' }
|
|
72
|
+
})
|
|
73
|
+
}),
|
|
74
|
+
EvidenceAuthoringMetadataData: frozenObject(
|
|
75
|
+
{
|
|
76
|
+
roleKey: { type: 'string' },
|
|
77
|
+
evidenceKinds: { type: 'array', items: schemaRef('EvidenceKindSummary') },
|
|
78
|
+
aspects: stringArraySchema(),
|
|
79
|
+
resourceTypes: { type: 'array', items: schemaRef('EvidenceResourceTypeSummary') },
|
|
80
|
+
assistantCapabilities: stringArraySchema(),
|
|
81
|
+
writableFields: stringArraySchema(),
|
|
82
|
+
requiredFields: stringArraySchema(),
|
|
83
|
+
constraints: schemaRef('EvidenceAuthoringConstraints')
|
|
84
|
+
},
|
|
85
|
+
[
|
|
86
|
+
'roleKey',
|
|
87
|
+
'evidenceKinds',
|
|
88
|
+
'aspects',
|
|
89
|
+
'resourceTypes',
|
|
90
|
+
'assistantCapabilities',
|
|
91
|
+
'writableFields',
|
|
92
|
+
'requiredFields',
|
|
93
|
+
'constraints'
|
|
94
|
+
]
|
|
95
|
+
),
|
|
96
|
+
EvidenceRowProjection: frozenObject({
|
|
97
|
+
id: { type: 'string' },
|
|
98
|
+
key: { type: ['string', 'null'] },
|
|
99
|
+
resourceType: { type: ['string', 'null'] },
|
|
100
|
+
roleKey: { type: ['string', 'null'] },
|
|
101
|
+
kindKey: { type: ['string', 'null'] },
|
|
102
|
+
kindVersion: { type: ['string', 'null'] },
|
|
103
|
+
title: { type: 'string' },
|
|
104
|
+
description: { type: ['string', 'null'] },
|
|
105
|
+
when: { type: 'string' },
|
|
106
|
+
expectedBehavior: { type: 'string' },
|
|
107
|
+
aspect: { type: ['string', 'null'] },
|
|
108
|
+
order: { type: 'integer' },
|
|
109
|
+
status: { type: 'string' },
|
|
110
|
+
fingerprint: { type: ['string', 'null'] }
|
|
111
|
+
}),
|
|
112
|
+
EvidenceDownloadData: frozenObject(
|
|
113
|
+
{
|
|
114
|
+
roleKey: { type: 'string' },
|
|
115
|
+
count: { type: 'integer', minimum: 0 },
|
|
116
|
+
data: { type: 'array', items: schemaRef('EvidenceRowProjection') }
|
|
117
|
+
},
|
|
118
|
+
['roleKey', 'count', 'data']
|
|
119
|
+
),
|
|
120
|
+
EvidenceUploadItemOutcome: frozenObject({
|
|
121
|
+
rowIndex: { type: 'integer' },
|
|
122
|
+
evidenceId: { type: ['string', 'null'] },
|
|
123
|
+
evidenceRef: { type: ['string', 'null'] },
|
|
124
|
+
status: { type: 'string' },
|
|
125
|
+
message: { type: 'string' },
|
|
126
|
+
issues: { type: 'array', items: { type: 'string' } }
|
|
127
|
+
}),
|
|
128
|
+
EvidenceUploadData: frozenObject(
|
|
129
|
+
{
|
|
130
|
+
roleKey: { type: 'string' },
|
|
131
|
+
inserted: { type: 'integer', minimum: 0 },
|
|
132
|
+
updated: { type: 'integer', minimum: 0 },
|
|
133
|
+
accepted: { type: 'array', items: schemaRef('EvidenceUploadItemOutcome') },
|
|
134
|
+
rejected: { type: 'array', items: schemaRef('EvidenceUploadItemOutcome') },
|
|
135
|
+
warnings: { type: 'array', items: schemaRef('EvidenceUploadItemOutcome') },
|
|
136
|
+
certified: { type: 'array', items: schemaRef('EvidenceUploadItemOutcome') },
|
|
137
|
+
readyToActivate: { type: 'boolean' }
|
|
138
|
+
},
|
|
139
|
+
['roleKey', 'accepted', 'rejected', 'warnings', 'certified', 'readyToActivate']
|
|
140
|
+
),
|
|
141
|
+
EvidenceActivateItemOutcome: frozenObject({
|
|
142
|
+
evidenceId: { type: 'string' },
|
|
143
|
+
result: schemaRef('EvidenceRowProjection'),
|
|
144
|
+
error: { type: 'string' },
|
|
145
|
+
status: { type: ['integer', 'null'] }
|
|
146
|
+
}),
|
|
147
|
+
EvidenceActivateData: frozenObject(
|
|
148
|
+
{
|
|
149
|
+
requested: { type: 'integer', minimum: 0 },
|
|
150
|
+
activated: { type: 'array', items: schemaRef('EvidenceActivateItemOutcome') },
|
|
151
|
+
failed: { type: 'array', items: schemaRef('EvidenceActivateItemOutcome') },
|
|
152
|
+
success: { type: 'boolean' }
|
|
153
|
+
},
|
|
154
|
+
['requested', 'activated', 'failed', 'success']
|
|
155
|
+
)
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
module.exports = {
|
|
159
|
+
OPENAPI_EVIDENCE_REQUEST_SCHEMAS,
|
|
160
|
+
OPENAPI_EVIDENCE_RESULT_SCHEMAS
|
|
161
|
+
};
|
|
@@ -54,10 +54,14 @@ const OPENAPI_MANIFEST_REQUEST_SCHEMAS = {
|
|
|
54
54
|
intent: { type: 'string', minLength: 1, description: 'Why this patch is made — audit and repair hints.' },
|
|
55
55
|
patch: { type: 'object', description: 'Section-scoped merge/replace payload.' },
|
|
56
56
|
mode: { type: 'string', enum: ['merge', 'replace'], description: 'Merge into or replace section value.' },
|
|
57
|
-
sectionReadToken: {
|
|
57
|
+
sectionReadToken: {
|
|
58
|
+
type: 'string',
|
|
59
|
+
description:
|
|
60
|
+
'Optional token from prior GET. When omitted, the server re-reads the section immediately before write. Stale token returns 409.'
|
|
61
|
+
},
|
|
58
62
|
dryRun: { type: 'boolean', description: 'Validate patch without writing files.' }
|
|
59
63
|
},
|
|
60
|
-
['intent', 'patch', 'mode'
|
|
64
|
+
['intent', 'patch', 'mode']
|
|
61
65
|
),
|
|
62
66
|
ManifestRepairRequest: frozenObject(
|
|
63
67
|
{
|