@aifabrix/builder 2.44.3 → 2.44.4
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/.npmrc.token +1 -1
- package/integration/roundtrip-test-local/README.md +1 -2
- package/integration/roundtrip-test-local2/README.md +1 -2
- package/jest.projects.js +12 -1
- package/lib/api/certificates.api.js +21 -3
- package/lib/certification/post-unified-cert-sync.js +13 -2
- package/lib/certification/sync-after-external-command.js +6 -3
- package/lib/certification/sync-system-certification.js +60 -14
- package/lib/cli/setup-app.test-commands.js +67 -35
- package/lib/cli/setup-utility.js +1 -1
- package/lib/commands/datasource-unified-test-cli.js +81 -46
- package/lib/commands/datasource-unified-test-cli.options.js +4 -2
- package/lib/commands/datasource.js +3 -31
- package/lib/commands/repair-datasource-keys.js +1 -1
- package/lib/commands/repair-datasource-openapi.js +57 -0
- package/lib/commands/repair-datasource.js +5 -0
- package/lib/commands/repair-internal.js +2 -4
- package/lib/commands/repair.js +1 -2
- package/lib/commands/test-e2e-external.js +5 -6
- package/lib/commands/upload.js +18 -4
- package/lib/commands/wizard-dataplane.js +14 -6
- package/lib/datasource/datasource-validate-display.js +162 -0
- package/lib/datasource/datasource-validate-summary.js +194 -0
- package/lib/datasource/test-e2e.js +65 -37
- package/lib/datasource/unified-validation-run-body.js +1 -2
- package/lib/datasource/validate.js +14 -6
- package/lib/external-system/test.js +12 -8
- package/lib/generator/external-controller-manifest.js +12 -2
- package/lib/schema/cip-capacity-display.fallback.json +7 -0
- package/lib/schema/datasource-test-run.schema.json +79 -1
- package/lib/schema/external-datasource.schema.json +94 -2
- package/lib/schema/flag-map-validation-run.json +1 -2
- package/lib/schema/type/document-storage.json +83 -3
- package/lib/utils/configuration-env-resolver.js +38 -0
- package/lib/utils/dataplane-resolver.js +3 -2
- package/lib/utils/datasource-test-run-capacity-operations.js +149 -0
- package/lib/utils/datasource-test-run-debug-display.js +143 -1
- package/lib/utils/datasource-test-run-display.js +46 -33
- package/lib/utils/datasource-test-run-tty-log.js +6 -2
- package/lib/utils/datasource-test-run-tty-meta-lines.js +123 -0
- package/lib/utils/error-formatter.js +32 -2
- package/lib/utils/external-system-readiness-core.js +39 -0
- package/lib/utils/external-system-readiness-deploy-display.js +2 -3
- package/lib/utils/external-system-readiness-display-internals.js +3 -2
- package/lib/utils/external-system-system-test-tty.js +33 -9
- package/lib/utils/external-system-validators.js +62 -5
- package/lib/utils/load-cip-capacity-display-config.js +130 -0
- package/lib/utils/paths.js +10 -3
- package/lib/utils/schema-resolver.js +98 -2
- package/lib/utils/validation-run-poll.js +15 -4
- package/lib/utils/validation-run-request.js +4 -6
- package/lib/validation/dimension-display-helpers.js +60 -0
- package/lib/validation/validate-display-log-helpers.js +39 -0
- package/lib/validation/validate-display.js +89 -83
- package/package.json +1 -1
- package/templates/external-system/README.md.hbs +1 -2
|
@@ -33,9 +33,8 @@ function buildUnifiedE2eRunOptions(options, timeoutMs, pk) {
|
|
|
33
33
|
verbose: options.verbose,
|
|
34
34
|
async: options.async !== false,
|
|
35
35
|
noAsync: options.async === false,
|
|
36
|
-
testCrud: options.testCrud,
|
|
37
|
-
recordId: options.recordId,
|
|
38
36
|
cleanup: options.cleanup,
|
|
37
|
+
runScenarios: options.runScenarios,
|
|
39
38
|
primaryKeyValue: pk,
|
|
40
39
|
minVectorHits: options.minVectorHits,
|
|
41
40
|
minProcessed: options.minProcessed,
|
|
@@ -72,6 +71,59 @@ function e2eIntegrationLogDir(appKey) {
|
|
|
72
71
|
return path.dirname(getIntegrationPath(appKey));
|
|
73
72
|
}
|
|
74
73
|
|
|
74
|
+
/**
|
|
75
|
+
* @param {Object} options
|
|
76
|
+
* @returns {number}
|
|
77
|
+
*/
|
|
78
|
+
function resolveE2ePollTimeoutMs(options) {
|
|
79
|
+
const raw =
|
|
80
|
+
options.timeout !== undefined && options.timeout !== null && options.timeout !== ''
|
|
81
|
+
? parseInt(String(options.timeout), 10)
|
|
82
|
+
: options.pollTimeoutMs;
|
|
83
|
+
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_POLL_TIMEOUT_MS;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @param {string} datasourceKey
|
|
88
|
+
* @param {Object} options
|
|
89
|
+
* @param {string|Object|null} pk
|
|
90
|
+
* @returns {Object}
|
|
91
|
+
*/
|
|
92
|
+
function buildE2eRequestMeta(datasourceKey, options, pk) {
|
|
93
|
+
return {
|
|
94
|
+
datasourceKey,
|
|
95
|
+
runType: 'e2e',
|
|
96
|
+
includeDebug: includeDebugForRequest(options.debug),
|
|
97
|
+
cleanup: options.cleanup,
|
|
98
|
+
runScenarios: options.runScenarios,
|
|
99
|
+
primaryKeyValue: pk !== undefined && pk !== null,
|
|
100
|
+
minVectorHits: options.minVectorHits,
|
|
101
|
+
minProcessed: options.minProcessed,
|
|
102
|
+
minRecordCount: options.minRecordCount
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Write JSON debug log and print paths + CLI wall clock when --debug.
|
|
108
|
+
* @param {string} appKey
|
|
109
|
+
* @param {Object} requestMeta
|
|
110
|
+
* @param {Object} envelope
|
|
111
|
+
* @param {number} cliWallSeconds
|
|
112
|
+
* @returns {Promise<void>}
|
|
113
|
+
*/
|
|
114
|
+
async function logE2eDebugSuccess(appKey, requestMeta, envelope, cliWallSeconds) {
|
|
115
|
+
const logPath = await writeTestLog(
|
|
116
|
+
appKey,
|
|
117
|
+
{ request: { ...requestMeta, cliWallSeconds }, response: envelope },
|
|
118
|
+
'test-e2e',
|
|
119
|
+
e2eIntegrationLogDir(appKey)
|
|
120
|
+
);
|
|
121
|
+
logger.log(chalk.gray(` Debug log: ${logPath}`));
|
|
122
|
+
logger.log(
|
|
123
|
+
chalk.gray(` CLI wall time: ${cliWallSeconds}s (URL resolve, POST, poll, log write)`)
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
75
127
|
/**
|
|
76
128
|
* Throw when unified run failed, timed out, or needs async; optionally write debug log.
|
|
77
129
|
* @returns {Promise<void>}
|
|
@@ -112,42 +164,19 @@ async function throwIfUnifiedE2EBlocked(unifiedResult, appKey, options, requestM
|
|
|
112
164
|
}
|
|
113
165
|
|
|
114
166
|
/**
|
|
115
|
-
* Run E2E
|
|
116
|
-
* @
|
|
117
|
-
* @param {string} datasourceKey
|
|
118
|
-
* @param {Object} options
|
|
119
|
-
* @param {boolean} [options.sync] - Publish local datasource JSON before validation when true
|
|
120
|
-
* @returns {Promise<Object>} Shape compatible with displayE2EResults (steps, success, status)
|
|
167
|
+
* Run E2E for one datasource (unified validation API).
|
|
168
|
+
* @returns {Promise<Object>} displayE2EResults-compatible shape
|
|
121
169
|
*/
|
|
122
170
|
async function runDatasourceTestE2E(datasourceKey, options = {}) {
|
|
123
171
|
if (!datasourceKey || typeof datasourceKey !== 'string') {
|
|
124
172
|
throw new Error('Datasource key is required');
|
|
125
173
|
}
|
|
174
|
+
const cliWallStartedAt = Date.now();
|
|
126
175
|
const { appKey } = await resolveAppKeyForDatasource(datasourceKey, options.app);
|
|
127
|
-
|
|
128
176
|
logE2eDatasourceBanner(datasourceKey, options.verbose);
|
|
129
|
-
|
|
130
177
|
const pk = await resolvePrimaryKeyValue(options.primaryKeyValue);
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
? parseInt(String(options.timeout), 10)
|
|
134
|
-
: options.pollTimeoutMs;
|
|
135
|
-
const timeoutMs =
|
|
136
|
-
Number.isFinite(timeoutRaw) && timeoutRaw > 0 ? timeoutRaw : DEFAULT_POLL_TIMEOUT_MS;
|
|
137
|
-
|
|
138
|
-
const requestMeta = {
|
|
139
|
-
datasourceKey,
|
|
140
|
-
runType: 'e2e',
|
|
141
|
-
includeDebug: includeDebugForRequest(options.debug),
|
|
142
|
-
testCrud: options.testCrud,
|
|
143
|
-
recordId: options.recordId,
|
|
144
|
-
cleanup: options.cleanup,
|
|
145
|
-
primaryKeyValue: pk !== undefined && pk !== null,
|
|
146
|
-
minVectorHits: options.minVectorHits,
|
|
147
|
-
minProcessed: options.minProcessed,
|
|
148
|
-
minRecordCount: options.minRecordCount
|
|
149
|
-
};
|
|
150
|
-
|
|
178
|
+
const timeoutMs = resolveE2ePollTimeoutMs(options);
|
|
179
|
+
const requestMeta = buildE2eRequestMeta(datasourceKey, options, pk);
|
|
151
180
|
const unifiedResult = await runUnifiedDatasourceValidation(
|
|
152
181
|
datasourceKey,
|
|
153
182
|
buildUnifiedE2eRunOptions(options, timeoutMs, pk)
|
|
@@ -158,14 +187,13 @@ async function runDatasourceTestE2E(datasourceKey, options = {}) {
|
|
|
158
187
|
const display = e2eShapeFromEnvelope(unifiedResult.envelope);
|
|
159
188
|
Object.assign(display, { datasourceTestRun: unifiedResult.envelope });
|
|
160
189
|
|
|
190
|
+
const cliWallSeconds = Math.round((Date.now() - cliWallStartedAt) / 10) / 100;
|
|
191
|
+
if (unifiedResult.envelope && typeof unifiedResult.envelope === 'object') {
|
|
192
|
+
unifiedResult.envelope.cliWallSeconds = cliWallSeconds;
|
|
193
|
+
}
|
|
194
|
+
|
|
161
195
|
if (options.debug) {
|
|
162
|
-
|
|
163
|
-
appKey,
|
|
164
|
-
{ request: requestMeta, response: unifiedResult.envelope },
|
|
165
|
-
'test-e2e',
|
|
166
|
-
e2eIntegrationLogDir(appKey)
|
|
167
|
-
);
|
|
168
|
-
logger.log(chalk.gray(` Debug log: ${logPath}`));
|
|
196
|
+
await logE2eDebugSuccess(appKey, requestMeta, unifiedResult.envelope, cliWallSeconds);
|
|
169
197
|
}
|
|
170
198
|
|
|
171
199
|
return display;
|
|
@@ -42,10 +42,9 @@ async function buildUnifiedValidationBody(params) {
|
|
|
42
42
|
? buildE2eOptionsFromCli({
|
|
43
43
|
debug: options.debug,
|
|
44
44
|
verbose: options.verbose,
|
|
45
|
-
testCrud: options.testCrud,
|
|
46
|
-
recordId: options.recordId,
|
|
47
45
|
cleanup: options.cleanup,
|
|
48
46
|
primaryKeyValue: options.primaryKeyValue,
|
|
47
|
+
runScenarios: options.runScenarios,
|
|
49
48
|
minVectorHits: options.minVectorHits,
|
|
50
49
|
minProcessed: options.minProcessed,
|
|
51
50
|
minRecordCount: options.minRecordCount,
|
|
@@ -15,6 +15,7 @@ const { loadExternalDataSourceSchema } = require('../utils/schema-loader');
|
|
|
15
15
|
const { formatValidationErrors } = require('../utils/error-formatter');
|
|
16
16
|
const { validateFieldReferences } = require('./field-reference-validator');
|
|
17
17
|
const { validateAbac } = require('./abac-validator');
|
|
18
|
+
const { buildDatasourceValidateSummary } = require('./datasource-validate-summary');
|
|
18
19
|
|
|
19
20
|
const EXCLUDE_JSON_NAMES = new Set(['application.json', 'rbac.json', 'package.json', 'package-lock.json']);
|
|
20
21
|
|
|
@@ -161,7 +162,8 @@ function resolveValidateInputPath(identifier) {
|
|
|
161
162
|
* @async
|
|
162
163
|
* @function validateDatasourceFile
|
|
163
164
|
* @param {string} filePathOrKey - Path to the datasource JSON file, or datasource `key` resolved under integration/<app>/
|
|
164
|
-
* @returns {Promise<Object>} Validation result
|
|
165
|
+
* @returns {Promise<Object>} Validation result: `valid`, `errors`, `warnings`, `resolvedPath`, and `summary`
|
|
166
|
+
* (from `buildDatasourceValidateSummary` when JSON parses; `null` on JSON syntax errors).
|
|
165
167
|
* @throws {Error} If file cannot be read or parsed
|
|
166
168
|
*
|
|
167
169
|
* @example
|
|
@@ -185,19 +187,23 @@ async function validateDatasourceFile(filePathOrKey) {
|
|
|
185
187
|
valid: false,
|
|
186
188
|
errors: [`Invalid JSON syntax: ${error.message}`],
|
|
187
189
|
warnings: [],
|
|
188
|
-
resolvedPath: filePath
|
|
190
|
+
resolvedPath: filePath,
|
|
191
|
+
summary: null
|
|
189
192
|
};
|
|
190
193
|
}
|
|
191
194
|
|
|
195
|
+
const summary = buildDatasourceValidateSummary(parsed);
|
|
196
|
+
|
|
192
197
|
const validate = loadExternalDataSourceSchema();
|
|
193
198
|
const schemaValid = validate(parsed);
|
|
194
199
|
|
|
195
200
|
if (!schemaValid) {
|
|
196
201
|
return {
|
|
197
202
|
valid: false,
|
|
198
|
-
errors: formatValidationErrors(validate.errors),
|
|
203
|
+
errors: formatValidationErrors(validate.errors, { rootData: parsed, dedupe: true }),
|
|
199
204
|
warnings: [],
|
|
200
|
-
resolvedPath: filePath
|
|
205
|
+
resolvedPath: filePath,
|
|
206
|
+
summary
|
|
201
207
|
};
|
|
202
208
|
}
|
|
203
209
|
|
|
@@ -209,7 +215,8 @@ async function validateDatasourceFile(filePathOrKey) {
|
|
|
209
215
|
valid: false,
|
|
210
216
|
errors: postSchemaErrors,
|
|
211
217
|
warnings: [],
|
|
212
|
-
resolvedPath: filePath
|
|
218
|
+
resolvedPath: filePath,
|
|
219
|
+
summary
|
|
213
220
|
};
|
|
214
221
|
}
|
|
215
222
|
|
|
@@ -217,7 +224,8 @@ async function validateDatasourceFile(filePathOrKey) {
|
|
|
217
224
|
valid: true,
|
|
218
225
|
errors: [],
|
|
219
226
|
warnings: [],
|
|
220
|
-
resolvedPath: filePath
|
|
227
|
+
resolvedPath: filePath,
|
|
228
|
+
summary
|
|
221
229
|
};
|
|
222
230
|
}
|
|
223
231
|
|
|
@@ -154,12 +154,21 @@ async function loadDatasourceFiles(datasourceFiles, schemaBasePath, appPath) {
|
|
|
154
154
|
async function loadExternalSystemFiles(appName) {
|
|
155
155
|
const { appPath } = await detectAppType(appName);
|
|
156
156
|
const { resolveApplicationConfigPath } = require('../utils/app-config-resolver');
|
|
157
|
+
const { orderDatasourceFileNamesBySystemKeys } = require('../utils/schema-resolver');
|
|
157
158
|
const configPath = resolveApplicationConfigPath(appPath);
|
|
158
159
|
const variables = await loadVariablesYamlFile(configPath);
|
|
159
160
|
|
|
160
161
|
const schemaBasePath = variables.externalIntegration.schemaBasePath || './';
|
|
161
162
|
const systemFiles = variables.externalIntegration.systems || [];
|
|
162
|
-
const
|
|
163
|
+
const rawDatasourceFiles = variables.externalIntegration.dataSources || [];
|
|
164
|
+
const schemaResolved = path.isAbsolute(schemaBasePath)
|
|
165
|
+
? schemaBasePath
|
|
166
|
+
: path.resolve(appPath, schemaBasePath);
|
|
167
|
+
const datasourceFiles = orderDatasourceFileNamesBySystemKeys(
|
|
168
|
+
schemaResolved,
|
|
169
|
+
systemFiles,
|
|
170
|
+
rawDatasourceFiles
|
|
171
|
+
);
|
|
163
172
|
|
|
164
173
|
const systemJsonFiles = await loadSystemFiles(systemFiles, schemaBasePath, appPath);
|
|
165
174
|
const datasourceJsonFiles = await loadDatasourceFiles(datasourceFiles, schemaBasePath, appPath);
|
|
@@ -198,10 +207,10 @@ function validateDatasourceSchema(datasource, systemKey, externalDataSourceSchem
|
|
|
198
207
|
/**
|
|
199
208
|
* Test datasource with payload template
|
|
200
209
|
* @param {Object} datasource - Datasource configuration
|
|
201
|
-
* @param {boolean}
|
|
210
|
+
* @param {boolean} _verbose - Show detailed output (reserved; not used in this path yet)
|
|
202
211
|
* @returns {Object} Test results
|
|
203
212
|
*/
|
|
204
|
-
function testDatasourceWithPayload(datasource,
|
|
213
|
+
function testDatasourceWithPayload(datasource, _verbose) {
|
|
205
214
|
const errors = [];
|
|
206
215
|
const warnings = [];
|
|
207
216
|
|
|
@@ -223,11 +232,6 @@ function testDatasourceWithPayload(datasource, verbose) {
|
|
|
223
232
|
warnings.push(...metadataSchemaResults.warnings);
|
|
224
233
|
}
|
|
225
234
|
|
|
226
|
-
// Compare with expectedResult if provided
|
|
227
|
-
if (datasource.testPayload.expectedResult && fieldMappingResults.mappedFields && verbose) {
|
|
228
|
-
warnings.push('expectedResult validation not yet implemented (requires transformation engine)');
|
|
229
|
-
}
|
|
230
|
-
|
|
231
235
|
return {
|
|
232
236
|
fieldMappingResults,
|
|
233
237
|
metadataSchemaResults,
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
const path = require('path');
|
|
13
13
|
const { detectAppType } = require('../utils/paths');
|
|
14
14
|
const { resolveApplicationConfigPath, resolveRbacPath } = require('../utils/app-config-resolver');
|
|
15
|
+
const { orderDatasourceFileNamesBySystemKeys } = require('../utils/schema-resolver');
|
|
15
16
|
const { loadSystemFile, loadDatasourceFiles } = require('./external');
|
|
16
17
|
const { loadVariables, loadRbac } = require('./helpers');
|
|
17
18
|
|
|
@@ -124,9 +125,18 @@ async function generateControllerManifest(appName, options = {}) {
|
|
|
124
125
|
if (systemFiles.length === 0) {
|
|
125
126
|
throw new Error('No system files specified in externalIntegration.systems');
|
|
126
127
|
}
|
|
128
|
+
const schemaResolved = path.isAbsolute(schemaBasePath)
|
|
129
|
+
? schemaBasePath
|
|
130
|
+
: path.resolve(appPath, schemaBasePath);
|
|
131
|
+
const rawDatasourceNames = variables.externalIntegration.dataSources || [];
|
|
132
|
+
const orderedDatasourceNames = orderDatasourceFileNamesBySystemKeys(
|
|
133
|
+
schemaResolved,
|
|
134
|
+
systemFiles,
|
|
135
|
+
rawDatasourceNames
|
|
136
|
+
);
|
|
127
137
|
const [systemJson, datasourceJsons] = await Promise.all([
|
|
128
138
|
loadSystemWithRbac(appPath, schemaBasePath, systemFiles[0]),
|
|
129
|
-
loadDatasourceFiles(appPath, schemaBasePath,
|
|
139
|
+
loadDatasourceFiles(appPath, schemaBasePath, orderedDatasourceNames, {
|
|
130
140
|
skipMissingDatasourceFiles: options.skipMissingDatasourceFiles
|
|
131
141
|
})
|
|
132
142
|
]);
|
|
@@ -134,7 +144,7 @@ async function generateControllerManifest(appName, options = {}) {
|
|
|
134
144
|
const externalIntegration = {
|
|
135
145
|
schemaBasePath,
|
|
136
146
|
systems: systemFiles,
|
|
137
|
-
dataSources:
|
|
147
|
+
dataSources: orderedDatasourceNames,
|
|
138
148
|
autopublish: variables.externalIntegration.autopublish !== false,
|
|
139
149
|
version: appVersion
|
|
140
150
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "Used when external-datasource.schema.json is not on disk. standardOperationOrder must match $defs.cipDefinition.properties.operations.properties key order in dataplane app/schemas/json/external-datasource.schema.json.",
|
|
3
|
+
"standardOperationOrder": ["list", "get", "create", "update", "delete"],
|
|
4
|
+
"displayAliases": {
|
|
5
|
+
"create": "insert (create)"
|
|
6
|
+
}
|
|
7
|
+
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"reportVersion": {
|
|
10
10
|
"type": "string",
|
|
11
11
|
"description": "Semver-style contract version for this envelope. Policy: additive fields => minor bump within same major; removed/renamed fields => major bump. Route migrations must cite target reportVersion.",
|
|
12
|
-
"example": "1.
|
|
12
|
+
"example": "1.3.0"
|
|
13
13
|
},
|
|
14
14
|
"runType": {
|
|
15
15
|
"type": "string",
|
|
@@ -51,6 +51,10 @@
|
|
|
51
51
|
"certificate": {
|
|
52
52
|
"$ref": "#/$defs/CertificateResult"
|
|
53
53
|
},
|
|
54
|
+
"certificateIssuance": {
|
|
55
|
+
"$ref": "#/$defs/CertificateIssuanceResult",
|
|
56
|
+
"description": "Integration-certificate auto-issue outcome for this datasource scope (VALIDATION_AUTO_ISSUE_INTEGRATION_CERTIFICATE)."
|
|
57
|
+
},
|
|
54
58
|
"capabilitySummary": {
|
|
55
59
|
"$ref": "#/$defs/CapabilitySummary"
|
|
56
60
|
},
|
|
@@ -69,9 +73,50 @@
|
|
|
69
73
|
},
|
|
70
74
|
"developer": {
|
|
71
75
|
"$ref": "#/$defs/DeveloperSummary"
|
|
76
|
+
},
|
|
77
|
+
"datasourceSummaries": {
|
|
78
|
+
"type": "array",
|
|
79
|
+
"description": "Optional per-datasource rollups when the underlying run evaluated multiple datasources (e.g. validationScope=externalSystem).",
|
|
80
|
+
"items": {
|
|
81
|
+
"$ref": "#/$defs/DatasourceSummary"
|
|
82
|
+
}
|
|
72
83
|
}
|
|
73
84
|
},
|
|
74
85
|
"$defs": {
|
|
86
|
+
"DatasourceSummary": {
|
|
87
|
+
"type": "object",
|
|
88
|
+
"required": ["datasourceKey", "status"],
|
|
89
|
+
"additionalProperties": false,
|
|
90
|
+
"description": "Lightweight per-datasource rollup for system-scoped runs.",
|
|
91
|
+
"properties": {
|
|
92
|
+
"datasourceKey": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"description": "Datasource key within the system."
|
|
95
|
+
},
|
|
96
|
+
"status": {
|
|
97
|
+
"type": "string",
|
|
98
|
+
"description": "Datasource rollup: ok | warn | fail | skipped.",
|
|
99
|
+
"enum": ["ok", "warn", "fail", "skipped"]
|
|
100
|
+
},
|
|
101
|
+
"validationStatus": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"description": "Validation layer rollup for this datasource.",
|
|
104
|
+
"enum": ["ok", "warn", "fail"]
|
|
105
|
+
},
|
|
106
|
+
"certificateStatus": {
|
|
107
|
+
"type": "string",
|
|
108
|
+
"description": "Certification rollup for this datasource.",
|
|
109
|
+
"enum": ["passed", "not_passed"]
|
|
110
|
+
},
|
|
111
|
+
"issues": {
|
|
112
|
+
"type": "array",
|
|
113
|
+
"description": "Blocking/warning issues for this datasource.",
|
|
114
|
+
"items": {
|
|
115
|
+
"$ref": "#/$defs/Issue"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
},
|
|
75
120
|
"ValidationLayerResult": {
|
|
76
121
|
"type": "object",
|
|
77
122
|
"required": ["status"],
|
|
@@ -161,6 +206,39 @@
|
|
|
161
206
|
}
|
|
162
207
|
}
|
|
163
208
|
},
|
|
209
|
+
"CertificateIssuanceResult": {
|
|
210
|
+
"type": "object",
|
|
211
|
+
"additionalProperties": false,
|
|
212
|
+
"required": ["status", "systemKey", "datasourceKey"],
|
|
213
|
+
"description": "Structured result when the dataplane evaluates integration-certificate auto-issue (safe for clients and logs).",
|
|
214
|
+
"properties": {
|
|
215
|
+
"status": {
|
|
216
|
+
"type": "string",
|
|
217
|
+
"enum": ["issued", "reusedActive", "skipped", "failed"],
|
|
218
|
+
"description": "issued | reusedActive | skipped | failed."
|
|
219
|
+
},
|
|
220
|
+
"reasonCode": {
|
|
221
|
+
"type": "string",
|
|
222
|
+
"description": "Stable machine code when status is skipped or failed."
|
|
223
|
+
},
|
|
224
|
+
"message": {
|
|
225
|
+
"type": "string",
|
|
226
|
+
"description": "Human-readable summary."
|
|
227
|
+
},
|
|
228
|
+
"validationHint": {
|
|
229
|
+
"type": "string",
|
|
230
|
+
"description": "Optional remediation hint."
|
|
231
|
+
},
|
|
232
|
+
"systemKey": {
|
|
233
|
+
"type": "string",
|
|
234
|
+
"description": "External system key for this issuance scope."
|
|
235
|
+
},
|
|
236
|
+
"datasourceKey": {
|
|
237
|
+
"type": "string",
|
|
238
|
+
"description": "Datasource key for this issuance scope."
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
},
|
|
164
242
|
"CertificateResult": {
|
|
165
243
|
"type": "object",
|
|
166
244
|
"required": ["status"],
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"key":"external-datasource-schema",
|
|
8
8
|
"name":"External Data Source Configuration Schema",
|
|
9
9
|
"description":"JSON schema for validating ExternalDataSource configuration files",
|
|
10
|
-
|
|
10
|
+
"version":"2.4.6",
|
|
11
11
|
"type":"schema",
|
|
12
12
|
"category":"integration",
|
|
13
13
|
"author":"AI Fabrix Team",
|
|
14
14
|
"createdAt":"2024-01-01T00:00:00Z",
|
|
15
|
-
"updatedAt":"2026-04-
|
|
15
|
+
"updatedAt":"2026-04-20T00:00:00Z",
|
|
16
16
|
"compatibility":{
|
|
17
17
|
"minVersion":"1.0.0",
|
|
18
18
|
"maxVersion":"3.0.0",
|
|
@@ -175,6 +175,14 @@
|
|
|
175
175
|
"exposed.profiles object profiles: attributes may be an object map (property names = field keys; values ignored), matching runtime exposed_profile_field_names and CIP/ExposedFieldsValidator behavior."
|
|
176
176
|
],
|
|
177
177
|
"breaking":false
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"version":"2.4.6",
|
|
181
|
+
"date":"2026-04-24T00:00:00Z",
|
|
182
|
+
"changes":[
|
|
183
|
+
"Added optional fetch.httpResponseNormalization for manifest-driven GET response shaping (302 Location follow, JSON redirect envelopes, nested JSON string URL follow-up)."
|
|
184
|
+
],
|
|
185
|
+
"breaking":false
|
|
178
186
|
}
|
|
179
187
|
]
|
|
180
188
|
},
|
|
@@ -705,6 +713,10 @@
|
|
|
705
713
|
"input":{
|
|
706
714
|
"type":"object",
|
|
707
715
|
"additionalProperties":true
|
|
716
|
+
},
|
|
717
|
+
"order":{
|
|
718
|
+
"type":"integer",
|
|
719
|
+
"description":"Optional stable sort hint for scenario execution / diagnostics."
|
|
708
720
|
}
|
|
709
721
|
},
|
|
710
722
|
"additionalProperties":false
|
|
@@ -950,6 +962,83 @@
|
|
|
950
962
|
}
|
|
951
963
|
],
|
|
952
964
|
"$defs":{
|
|
965
|
+
"httpResponseNormalization":{
|
|
966
|
+
"type":"object",
|
|
967
|
+
"description":"Optional GET response shaping for miso-client adapter dicts and native 302 Location follows. Omitted = disabled.",
|
|
968
|
+
"additionalProperties":false,
|
|
969
|
+
"properties":{
|
|
970
|
+
"applyWhenUrlContains":{
|
|
971
|
+
"type":"array",
|
|
972
|
+
"items":{
|
|
973
|
+
"type":"string",
|
|
974
|
+
"minLength":1
|
|
975
|
+
},
|
|
976
|
+
"description":"When non-empty, normalization applies only if the request URL (path plus query, lowercased) contains at least one substring (case-insensitive)."
|
|
977
|
+
},
|
|
978
|
+
"followRedirectJsonEnvelope":{
|
|
979
|
+
"type":"object",
|
|
980
|
+
"additionalProperties":false,
|
|
981
|
+
"properties":{
|
|
982
|
+
"enabled":{
|
|
983
|
+
"type":"boolean",
|
|
984
|
+
"default":false
|
|
985
|
+
},
|
|
986
|
+
"locationHostSuffixAllowlist":{
|
|
987
|
+
"type":"array",
|
|
988
|
+
"items":{
|
|
989
|
+
"type":"string",
|
|
990
|
+
"minLength":1
|
|
991
|
+
},
|
|
992
|
+
"description":"Location header URL must contain one of these substrings (case-insensitive) before an unauthenticated follow-up GET."
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
},
|
|
996
|
+
"followNestedJsonStringUrl":{
|
|
997
|
+
"type":"object",
|
|
998
|
+
"additionalProperties":false,
|
|
999
|
+
"properties":{
|
|
1000
|
+
"enabled":{
|
|
1001
|
+
"type":"boolean",
|
|
1002
|
+
"default":false
|
|
1003
|
+
},
|
|
1004
|
+
"jsonKeys":{
|
|
1005
|
+
"type":"array",
|
|
1006
|
+
"items":{
|
|
1007
|
+
"type":"string",
|
|
1008
|
+
"minLength":1
|
|
1009
|
+
},
|
|
1010
|
+
"description":"JSON object key names searched depth-first for a non-empty string URL."
|
|
1011
|
+
},
|
|
1012
|
+
"targetUrlHostSuffixAllowlist":{
|
|
1013
|
+
"type":"array",
|
|
1014
|
+
"items":{
|
|
1015
|
+
"type":"string",
|
|
1016
|
+
"minLength":1
|
|
1017
|
+
},
|
|
1018
|
+
"description":"Discovered URL must contain one of these substrings before an unauthenticated follow-up GET."
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
},
|
|
1022
|
+
"followNativeHttpRedirect302":{
|
|
1023
|
+
"type":"object",
|
|
1024
|
+
"additionalProperties":false,
|
|
1025
|
+
"properties":{
|
|
1026
|
+
"enabled":{
|
|
1027
|
+
"type":"boolean",
|
|
1028
|
+
"default":false
|
|
1029
|
+
},
|
|
1030
|
+
"locationHostSuffixAllowlist":{
|
|
1031
|
+
"type":"array",
|
|
1032
|
+
"items":{
|
|
1033
|
+
"type":"string",
|
|
1034
|
+
"minLength":1
|
|
1035
|
+
},
|
|
1036
|
+
"description":"Native httpx 302 Location URL must contain one of these substrings before follow-up GET."
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
},
|
|
953
1042
|
"metadataSchemaNode":{
|
|
954
1043
|
"type":"object",
|
|
955
1044
|
"description":"Strict supported subset of JSON Schema for metadataSchema.",
|
|
@@ -1829,6 +1918,9 @@
|
|
|
1829
1918
|
"additionalProperties":{
|
|
1830
1919
|
"type":"string"
|
|
1831
1920
|
}
|
|
1921
|
+
},
|
|
1922
|
+
"httpResponseNormalization":{
|
|
1923
|
+
"$ref":"#/$defs/httpResponseNormalization"
|
|
1832
1924
|
}
|
|
1833
1925
|
},
|
|
1834
1926
|
"allOf":[
|
|
@@ -11,8 +11,7 @@
|
|
|
11
11
|
{ "cliFlag": "--timeout <ms>", "requestField": null, "note": "Client aggregate HTTP budget (POST + polls)" },
|
|
12
12
|
{ "cliFlag": "--debug [level]", "requestField": "includeDebug", "default": false, "note": "summary|full|raw affects TTY appendix only; any presence sets includeDebug" },
|
|
13
13
|
{ "cliFlag": "--no-async", "requestField": "asyncRun", "note": "When true on CLI, omit asyncRun or set false; sync-only POST" },
|
|
14
|
-
{ "cliFlag": "--
|
|
15
|
-
{ "cliFlag": "--record-id", "requestField": "e2eOptions.recordId", "runType": "e2e" },
|
|
14
|
+
{ "cliFlag": "--no-run-scenarios", "requestField": "e2eOptions.runScenarios", "runType": "e2e" },
|
|
16
15
|
{ "cliFlag": "--no-cleanup", "requestField": "e2eOptions.cleanup", "runType": "e2e" },
|
|
17
16
|
{ "cliFlag": "--primary-key-value", "requestField": "e2eOptions.primaryKeyValue", "runType": "e2e" },
|
|
18
17
|
{ "cliFlag": "--capability <key>", "requestField": "e2eOptions.capabilityKeys", "runType": "e2e", "note": "Single key forwarded as capabilityKeys array in request body when set" },
|