@aifabrix/builder 2.45.0 → 2.45.5
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/rules/docs-rules.mdc +3 -1
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
- package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
- package/integration/hubspot-test/wizard-hubspot-e2e.yaml +1 -1
- package/jest.projects.js +44 -1
- package/lib/api/agent-metadata-validation.api.js +93 -0
- package/lib/api/audit-api-helpers.js +68 -0
- package/lib/api/audit.api.js +119 -0
- package/lib/api/auth-cache.api.js +44 -0
- package/lib/api/certificates.api.js +4 -4
- package/lib/api/credential.api.js +2 -2
- package/lib/api/dataplane-health.api.js +137 -0
- package/lib/api/dataplane-sync.api.js +27 -0
- package/lib/api/datasources-core.api.js +21 -18
- package/lib/api/datasources-extended.api.js +22 -22
- package/lib/api/dimensions.api.js +3 -0
- package/lib/api/external-systems.api.js +13 -13
- package/lib/api/governance-scenarios.api.js +39 -0
- package/lib/api/groups.api.js +79 -0
- package/lib/api/index.js +45 -2
- package/lib/api/pipeline.api.js +4 -4
- package/lib/api/protection.api.js +157 -0
- package/lib/api/records-bulk.api.js +30 -0
- package/lib/api/records-search-parse.js +49 -0
- package/lib/api/records-search.api.js +29 -0
- package/lib/api/types/agent-metadata-validation.types.js +67 -0
- package/lib/api/types/audit.types.js +72 -0
- package/lib/api/types/dataplane-health.types.js +27 -0
- package/lib/api/types/dimensions.types.js +2 -0
- package/lib/api/types/governance-scenarios.types.js +39 -0
- package/lib/api/types/protection.types.js +69 -0
- package/lib/api/types/records-bulk.types.js +35 -0
- package/lib/api/types/records-search.types.js +28 -0
- package/lib/api/user-groups.api.js +50 -0
- package/lib/api/users.api.js +95 -0
- package/lib/api/validation-run.api.js +3 -3
- package/lib/api/validation-runner.js +3 -3
- package/lib/api/wizard-platform.api.js +3 -3
- package/lib/api/wizard.api.js +21 -21
- package/lib/app/deploy.js +34 -19
- package/lib/cli/index.js +4 -2
- package/lib/cli/infra-guided.js +22 -3
- package/lib/cli/setup-app.help.js +50 -2
- package/lib/cli/setup-app.js +33 -24
- package/lib/cli/setup-app.test-commands.js +80 -21
- package/lib/cli/setup-auth.js +30 -3
- package/lib/cli/setup-external-system.js +37 -3
- package/lib/cli/setup-utility-help-after.js +45 -0
- package/lib/cli/setup-utility-resolve.js +2 -2
- package/lib/cli/setup-utility.js +99 -81
- package/lib/commands/auth-status-dataplane-version.js +231 -0
- package/lib/commands/auth-status-display.js +94 -0
- package/lib/commands/auth-status.js +70 -6
- package/lib/commands/credential-push.js +10 -5
- package/lib/commands/datasource-load-export-cli.js +178 -0
- package/lib/commands/datasource-test-trust-cli.js +114 -0
- package/lib/commands/datasource-unified-test-cli.js +25 -17
- package/lib/commands/datasource-unified-test-cli.options.js +18 -3
- package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +5 -5
- package/lib/commands/datasource-verify-audit-cli.js +96 -0
- package/lib/commands/datasource.js +68 -1
- package/lib/commands/dimension-value.js +43 -13
- package/lib/commands/dimension.js +38 -7
- package/lib/commands/identity-apply-sync.js +131 -0
- package/lib/commands/identity-group-cli.js +146 -0
- package/lib/commands/identity-membership-role-cache.js +175 -0
- package/lib/commands/identity-shared.js +94 -0
- package/lib/commands/identity-user-cli.js +158 -0
- package/lib/commands/identity.js +43 -0
- package/lib/commands/login.js +46 -16
- package/lib/commands/protection-cli-leaves.js +286 -0
- package/lib/commands/protection.js +50 -0
- package/lib/commands/repair.js +13 -3
- package/lib/commands/test-e2e-external.js +40 -9
- package/lib/commands/test-governance-cli-options.js +47 -0
- package/lib/commands/test-governance-command-action.js +55 -0
- package/lib/commands/test-governance-external.js +88 -0
- package/lib/commands/test-trust-cli-options.js +32 -0
- package/lib/commands/test-trust-command-action.js +118 -0
- package/lib/commands/test-trust-external.js +127 -0
- package/lib/commands/upload.js +34 -13
- package/lib/commands/wizard-core.js +3 -0
- package/lib/core/config-device-dataplane.js +185 -0
- package/lib/datasource/agent-trust-debug-log.js +45 -0
- package/lib/datasource/agent-trust-fetch.js +115 -0
- package/lib/datasource/agent-trust-map.js +101 -0
- package/lib/datasource/agent-trust-mock.js +44 -0
- package/lib/datasource/agent-trust-run.js +93 -0
- package/lib/datasource/agent-trust-timeout.js +25 -0
- package/lib/datasource/audit-evidence-display.js +80 -0
- package/lib/datasource/audit-evidence-extract-debug.js +103 -0
- package/lib/datasource/audit-evidence-extract.js +177 -0
- package/lib/datasource/audit-evidence-matrix-rows.js +158 -0
- package/lib/datasource/audit-evidence-operation-aliases.js +63 -0
- package/lib/datasource/audit-evidence-poll.js +109 -0
- package/lib/datasource/audit-evidence-run.js +177 -0
- package/lib/datasource/audit-evidence-verify-helpers.js +167 -0
- package/lib/datasource/audit-evidence-verify-matrix.js +177 -0
- package/lib/datasource/audit-evidence-verify.js +108 -0
- package/lib/datasource/bulk-loader-run-batches.js +88 -0
- package/lib/datasource/bulk-loader-service-retry.js +52 -0
- package/lib/datasource/bulk-loader-service.js +127 -0
- package/lib/datasource/capability/run-capability-dimension.js +2 -1
- package/lib/datasource/datasource-exporter-resolve.js +82 -0
- package/lib/datasource/datasource-exporter-service.js +144 -0
- package/lib/datasource/datasource-identifier.js +148 -0
- package/lib/datasource/datasource-load-export-context.js +92 -0
- package/lib/datasource/integration-context.js +6 -4
- package/lib/datasource/local-data-paths.js +145 -0
- package/lib/datasource/log-cleaner.js +241 -0
- package/lib/datasource/log-viewer.js +111 -6
- package/lib/datasource/record-file-parser.js +85 -0
- package/lib/datasource/record-mapper.js +129 -0
- package/lib/datasource/resolve-app.js +74 -55
- package/lib/datasource/test-e2e.js +26 -2
- package/lib/datasource/unified-validation-run-resolve.js +45 -12
- package/lib/datasource/unified-validation-run.js +43 -17
- package/lib/datasource/validate.js +37 -20
- package/lib/external-system/test-system-level.js +25 -4
- package/lib/external-system/test.js +3 -1
- package/lib/governance/governance-pack-loader.js +70 -0
- package/lib/governance/governance-run-display.js +119 -0
- package/lib/identity/identity-apply-core.js +108 -0
- package/lib/identity/identity-apply-phases.js +244 -0
- package/lib/identity/identity-apply-service.js +77 -0
- package/lib/identity/identity-csv-parser.js +114 -0
- package/lib/internal/fs-real-sync.js +29 -1
- package/lib/protection/auth-context.js +45 -0
- package/lib/protection/convert-batch.js +90 -0
- package/lib/protection/load.js +41 -0
- package/lib/protection/paths.js +158 -0
- package/lib/protection/preflight-datasource-ready.js +46 -0
- package/lib/protection/protection-create-probe-lines.js +142 -0
- package/lib/protection/protection-create-probes.js +95 -0
- package/lib/protection/protection-create-scaffold.js +281 -0
- package/lib/protection/protection-display-helpers.js +445 -0
- package/lib/protection/protection-display.js +215 -0
- package/lib/protection/protection-preset-registry.js +97 -0
- package/lib/protection/report-exit.js +62 -0
- package/lib/protection/resolve.js +202 -0
- package/lib/protection/run-commands-validate.js +130 -0
- package/lib/protection/run-commands.js +216 -0
- package/lib/protection/run-protection-create-helpers.js +134 -0
- package/lib/protection/run-protection-create-probes-flow.js +43 -0
- package/lib/protection/run-protection-create.js +191 -0
- package/lib/protection/scope.js +22 -0
- package/lib/protection/sync-after-upload.js +64 -0
- package/lib/protection/upload-batch.js +127 -0
- package/lib/protection/validate-batch.js +113 -0
- package/lib/protection/validate-local.js +65 -0
- package/lib/resolvers/dimension-file.js +29 -4
- package/lib/schema/external-datasource.schema.json +47 -13
- package/lib/schema/flag-map-validation-run.json +2 -2
- package/lib/schema/protection.schema.json +374 -0
- package/lib/schema/type/credential-field-registry.json +636 -0
- package/lib/schema/wizard-config.schema.json +1 -1
- package/lib/utils/agent-trust-run-display.js +231 -0
- package/lib/utils/agent-trust-run-exit.js +59 -0
- package/lib/utils/agent-trust-wait-ui.js +94 -0
- package/lib/utils/cli-exit-codes.js +30 -0
- package/lib/utils/cli-sync-options.js +33 -0
- package/lib/utils/credential-push-ui.js +90 -0
- package/lib/utils/dataplane-cli-version-gate.js +202 -0
- package/lib/utils/dataplane-cli-version-help.js +74 -0
- package/lib/utils/datasource-export-display.js +137 -0
- package/lib/utils/datasource-load-display.js +174 -0
- package/lib/utils/datasource-load-export-ui.js +120 -0
- package/lib/utils/datasource-test-run-capability-scope.js +3 -3
- package/lib/utils/datasource-test-run-display.js +3 -3
- package/lib/utils/datasource-test-run-tty-log.js +5 -1
- package/lib/utils/help-builder.js +30 -24
- package/lib/utils/manifest-source-emit.js +22 -0
- package/lib/utils/semver-compare.js +127 -0
- package/lib/utils/upload-pipeline-ui.js +91 -0
- package/lib/utils/validation-poll-ui.js +14 -7
- package/lib/validation/wizard-config-validator.js +58 -19
- package/package.json +1 -1
- package/templates/applications/dataplane/env.template +13 -1
- package/templates/applications/dataplane/rbac.yaml +4 -0
- package/templates/external-system/README.md.hbs +56 -8
|
@@ -16,6 +16,7 @@ const { getDeploymentAuth, requireBearerForDataplanePipeline } = require('../uti
|
|
|
16
16
|
const { resolveDataplaneUrl } = require('../utils/dataplane-resolver');
|
|
17
17
|
const { getIntegrationPath } = require('../utils/paths');
|
|
18
18
|
const { pushCredentialSecrets } = require('../utils/credential-secrets-env');
|
|
19
|
+
const { runWithCredentialPushSpinner } = require('../utils/credential-push-ui');
|
|
19
20
|
const { generateControllerManifest } = require('../generator/external-controller-manifest');
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -84,11 +85,15 @@ async function runCredentialPush(systemKey) {
|
|
|
84
85
|
const dataplaneUrl = await resolveDataplaneUrl(controllerUrl, environment, authConfig);
|
|
85
86
|
|
|
86
87
|
const payload = await buildPayload(systemKey);
|
|
87
|
-
const pushResult = await
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
const pushResult = await runWithCredentialPushSpinner(
|
|
89
|
+
() =>
|
|
90
|
+
pushCredentialSecrets(dataplaneUrl, authConfig, {
|
|
91
|
+
envFilePath,
|
|
92
|
+
appName: systemKey,
|
|
93
|
+
payload
|
|
94
|
+
}),
|
|
95
|
+
{ systemKey }
|
|
96
|
+
);
|
|
92
97
|
|
|
93
98
|
logPushResult(pushResult);
|
|
94
99
|
return { pushed: pushResult.pushed || 0 };
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CLI for `datasource load` and `datasource export` (plan 144)
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const logger = require('../utils/logger');
|
|
10
|
+
const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
|
|
11
|
+
const { runDatasourceLoad } = require('../datasource/bulk-loader-service');
|
|
12
|
+
const { runDatasourceExport } = require('../datasource/datasource-exporter-service');
|
|
13
|
+
const { displayDatasourceLoadTTY } = require('../utils/datasource-load-display');
|
|
14
|
+
const { displayDatasourceExportTTY } = require('../utils/datasource-export-display');
|
|
15
|
+
|
|
16
|
+
function loadHelpAfter() {
|
|
17
|
+
return `
|
|
18
|
+
Examples:
|
|
19
|
+
$ aifabrix datasource load hubspot-test-datasource-company
|
|
20
|
+
$ aifabrix datasource load hubspot-test-company --file ./fixtures/rows.ndjson -v
|
|
21
|
+
$ aifabrix datasource load hubspot-test-company --dry-run
|
|
22
|
+
$ af ds load hubspot-test-company --batch-size 50 --sync-type incremental
|
|
23
|
+
|
|
24
|
+
Notes:
|
|
25
|
+
- Imports local JSON/NDJSON via dataplane bulk record sync (not direct DB).
|
|
26
|
+
- Default file: integration/.data/<systemKey>-data-<entity>.json or .ndjson
|
|
27
|
+
- External integration folders only (integration/<systemKey>/).
|
|
28
|
+
`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function exportHelpAfter() {
|
|
32
|
+
return `
|
|
33
|
+
Examples:
|
|
34
|
+
$ aifabrix datasource export hubspot-test-datasource-company
|
|
35
|
+
$ aifabrix datasource export hubspot-test-company --format ndjson --limit 500
|
|
36
|
+
$ aifabrix datasource export hubspot-test-company --filter '{"status":{"eq":"active"}}' -v
|
|
37
|
+
$ af ds export hubspot-test-company --fields email,name --strict
|
|
38
|
+
|
|
39
|
+
Notes:
|
|
40
|
+
- Exports governed records search results (ABAC applied), not a raw DB dump.
|
|
41
|
+
- Default output: integration/.data/<systemKey>-data-<entity>.json or .ndjson
|
|
42
|
+
- Maximum 10000 rows per run (dataplane search limit).
|
|
43
|
+
`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {Object} result
|
|
48
|
+
* @returns {number}
|
|
49
|
+
*/
|
|
50
|
+
function computeLoadExitCode(result) {
|
|
51
|
+
if (result.dryRun) {
|
|
52
|
+
return 0;
|
|
53
|
+
}
|
|
54
|
+
return (result.totals.failedCount || 0) > 0 ? 1 : 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {Object} result
|
|
59
|
+
* @param {Object} options
|
|
60
|
+
* @returns {number}
|
|
61
|
+
*/
|
|
62
|
+
function computeExportExitCode(result, options) {
|
|
63
|
+
if (options.strict === true && result.recordCount === 0) {
|
|
64
|
+
return 1;
|
|
65
|
+
}
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function datasourceLoadAction(datasourceKey, options) {
|
|
70
|
+
try {
|
|
71
|
+
const result = await runDatasourceLoad(datasourceKey, {
|
|
72
|
+
app: options.app,
|
|
73
|
+
env: options.env,
|
|
74
|
+
file: options.file,
|
|
75
|
+
verbose: options.verbose,
|
|
76
|
+
dryRun: options.dryRun,
|
|
77
|
+
batchSize: options.batchSize,
|
|
78
|
+
syncType: options.syncType,
|
|
79
|
+
format: options.format
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
if (options.json) {
|
|
83
|
+
const { context: _ctx, ...payload } = result;
|
|
84
|
+
logger.log(JSON.stringify(payload, null, 2));
|
|
85
|
+
} else {
|
|
86
|
+
displayDatasourceLoadTTY(result, { environment: options.env, verbose: options.verbose });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
process.exit(computeLoadExitCode(result));
|
|
90
|
+
} catch (err) {
|
|
91
|
+
logger.error(formatBlockingError(`Load failed: ${err.message}`));
|
|
92
|
+
const code = err.message && /auth|login|token|version|unreachable/i.test(err.message) ? 3 : 1;
|
|
93
|
+
process.exit(code);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function datasourceExportAction(datasourceKey, options) {
|
|
98
|
+
try {
|
|
99
|
+
const result = await runDatasourceExport(datasourceKey, {
|
|
100
|
+
app: options.app,
|
|
101
|
+
env: options.env,
|
|
102
|
+
file: options.file,
|
|
103
|
+
verbose: options.verbose,
|
|
104
|
+
format: options.format,
|
|
105
|
+
filter: options.filter,
|
|
106
|
+
fields: options.fields,
|
|
107
|
+
limit: options.limit,
|
|
108
|
+
intent: options.intent,
|
|
109
|
+
strict: options.strict
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
if (options.json) {
|
|
113
|
+
const { context: _ctx, ...payload } = result;
|
|
114
|
+
logger.log(JSON.stringify(payload, null, 2));
|
|
115
|
+
} else {
|
|
116
|
+
displayDatasourceExportTTY(result, { environment: options.env, verbose: options.verbose });
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
process.exit(computeExportExitCode(result, options));
|
|
120
|
+
} catch (err) {
|
|
121
|
+
logger.error(formatBlockingError(`Export failed: ${err.message}`));
|
|
122
|
+
const code = err.message && /auth|login|token|version|unreachable/i.test(err.message) ? 3 : 1;
|
|
123
|
+
process.exit(code);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @param {import('commander').Command} datasource
|
|
129
|
+
*/
|
|
130
|
+
function setupDatasourceLoadExportCommands(datasource) {
|
|
131
|
+
datasource
|
|
132
|
+
.command('load <datasourceKey>')
|
|
133
|
+
.description('Import local JSON/NDJSON records via dataplane bulk sync')
|
|
134
|
+
.option('-a, --app <app>', 'Integration folder name')
|
|
135
|
+
.option('-e, --env <env>', 'Environment: dev, tst, or pro')
|
|
136
|
+
.option('--file <path>', 'Input file (default: integration/.data/...)')
|
|
137
|
+
.option('--format <json|ndjson>', 'File format when extension is ambiguous')
|
|
138
|
+
.option('--batch-size <n>', 'Records per bulk request', '100')
|
|
139
|
+
.option(
|
|
140
|
+
'--sync-type <incremental|bulk|validate>',
|
|
141
|
+
'Dataplane syncType',
|
|
142
|
+
'incremental'
|
|
143
|
+
)
|
|
144
|
+
.option('--dry-run', 'Parse and validate only; no upload')
|
|
145
|
+
.option('-v, --verbose', 'Per-batch progress')
|
|
146
|
+
.option('--json', 'Machine-readable result JSON')
|
|
147
|
+
.addHelpText('after', loadHelpAfter())
|
|
148
|
+
.action(datasourceLoadAction);
|
|
149
|
+
|
|
150
|
+
datasource
|
|
151
|
+
.command('export <datasourceKey>')
|
|
152
|
+
.description('Export governed records to local JSON/NDJSON via records search')
|
|
153
|
+
.option('-a, --app <app>', 'Integration folder name')
|
|
154
|
+
.option('-e, --env <env>', 'Environment: dev, tst, or pro')
|
|
155
|
+
.option('--file <path>', 'Output file (default: integration/.data/...)')
|
|
156
|
+
.option('--format <json|ndjson>', 'Output format')
|
|
157
|
+
.option('--filter <json>', 'Records search filters (JSON object)')
|
|
158
|
+
.option('--fields <csv>', 'Project metadata keys in export rows')
|
|
159
|
+
.option('--limit <n>', 'Max records (1–10000)', '1000')
|
|
160
|
+
.option(
|
|
161
|
+
'--intent <retrieval|grounding|analytics|validation>',
|
|
162
|
+
'Search intent',
|
|
163
|
+
'validation'
|
|
164
|
+
)
|
|
165
|
+
.option('--strict', 'Exit 1 when zero rows are exported')
|
|
166
|
+
.option('-v, --verbose', 'Search stats and file size')
|
|
167
|
+
.option('--json', 'Machine-readable result JSON')
|
|
168
|
+
.addHelpText('after', exportHelpAfter())
|
|
169
|
+
.action(datasourceExportAction);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
module.exports = {
|
|
173
|
+
setupDatasourceLoadExportCommands,
|
|
174
|
+
datasourceLoadAction,
|
|
175
|
+
datasourceExportAction,
|
|
176
|
+
computeLoadExitCode,
|
|
177
|
+
computeExportExitCode
|
|
178
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CLI wiring for `datasource test-trust` (404.5 / plan 143).
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const logger = require('../utils/logger');
|
|
10
|
+
const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
|
|
11
|
+
const { runDatasourceAgentTrust } = require('../datasource/agent-trust-run');
|
|
12
|
+
const { writeTrustDebugLogAndPrint } = require('../datasource/agent-trust-debug-log');
|
|
13
|
+
const { displayAgentTrustRunTTY } = require('../utils/agent-trust-run-display');
|
|
14
|
+
const { computeExitCodeFromTrustRun } = require('../utils/agent-trust-run-exit');
|
|
15
|
+
const { attachDatasourceTestCommonOptions } = require('./datasource-unified-test-cli.options');
|
|
16
|
+
const { cliOptsSkipSync } = require('../utils/cli-sync-options');
|
|
17
|
+
|
|
18
|
+
function datasourceTestTrustHelpAfter() {
|
|
19
|
+
return `
|
|
20
|
+
Examples:
|
|
21
|
+
$ aifabrix datasource test-trust hubspot-companies
|
|
22
|
+
$ aifabrix datasource test-trust hubspot-companies --app test-e2e-hubspot -v
|
|
23
|
+
$ aifabrix datasource test-trust hubspot-companies --revalidate --strict
|
|
24
|
+
$ aifabrix test-trust test-e2e-hubspot
|
|
25
|
+
|
|
26
|
+
Notes:
|
|
27
|
+
- Semantic trust only (agent metadata validation). For live API proof use test-e2e.
|
|
28
|
+
- Local files are published before run unless --no-sync.
|
|
29
|
+
- With --debug, JSON is saved under integration/<app>/logs/ (test-trust-<key>-*.json). View with: aifabrix datasource log-trust <key>
|
|
30
|
+
`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function runDatasourceTestTrustOnce(datasourceKey, options) {
|
|
34
|
+
const { trustRun, apiError } = await runDatasourceAgentTrust(datasourceKey, {
|
|
35
|
+
app: options.app,
|
|
36
|
+
environment: options.env,
|
|
37
|
+
noSync: options.noSync === true,
|
|
38
|
+
revalidate: options.revalidate === true,
|
|
39
|
+
summary: options.summary === true,
|
|
40
|
+
timeout: options.timeout
|
|
41
|
+
});
|
|
42
|
+
return { trustRun, apiError };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function finalizeDatasourceTestTrust(datasourceKey, options, result) {
|
|
46
|
+
const displayOpts = {
|
|
47
|
+
json: options.json,
|
|
48
|
+
verbose: options.verbose,
|
|
49
|
+
environment: options.env,
|
|
50
|
+
noSync: options.noSync === true,
|
|
51
|
+
strict: options.strict === true
|
|
52
|
+
};
|
|
53
|
+
if (options.json) {
|
|
54
|
+
logger.log(JSON.stringify(result.trustRun, null, 2));
|
|
55
|
+
} else if (options.summary) {
|
|
56
|
+
const tr = result.trustRun;
|
|
57
|
+
logger.log(
|
|
58
|
+
`${tr.datasourceKey}: ${tr.trustDecision} (${tr.validationStatus}, ${Math.round((tr.confidence || 0) * 100)}%)`
|
|
59
|
+
);
|
|
60
|
+
} else {
|
|
61
|
+
displayAgentTrustRunTTY(result.trustRun, displayOpts);
|
|
62
|
+
}
|
|
63
|
+
const exitOpts = {
|
|
64
|
+
warningsAsErrors: options.warningsAsErrors === true,
|
|
65
|
+
strict: options.strict === true
|
|
66
|
+
};
|
|
67
|
+
return computeExitCodeFromTrustRun(result.trustRun, exitOpts);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function datasourceTestTrustAction(datasourceKey, options, cmd) {
|
|
71
|
+
try {
|
|
72
|
+
const merged = { ...options, noSync: cliOptsSkipSync(options, cmd) };
|
|
73
|
+
const result = await runDatasourceTestTrustOnce(datasourceKey, merged);
|
|
74
|
+
const { resolveAppKeyForDatasource } = require('../datasource/resolve-app');
|
|
75
|
+
const { appKey } = await resolveAppKeyForDatasource(datasourceKey, options.app);
|
|
76
|
+
if (options.debug) {
|
|
77
|
+
await writeTrustDebugLogAndPrint(appKey, datasourceKey, {
|
|
78
|
+
request: { datasourceKey, revalidate: options.revalidate === true },
|
|
79
|
+
response: result.trustRun,
|
|
80
|
+
error: result.apiError ? result.apiError.message : null
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
const exitCode = await finalizeDatasourceTestTrust(datasourceKey, merged, result);
|
|
84
|
+
process.exit(exitCode);
|
|
85
|
+
} catch (err) {
|
|
86
|
+
logger.error(formatBlockingError('Agent trust validation failed:'), err.message);
|
|
87
|
+
process.exit(3);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function setupDatasourceTestTrustCommand(datasource) {
|
|
92
|
+
const cmd = datasource
|
|
93
|
+
.command('test-trust <datasourceKey>')
|
|
94
|
+
.description('Semantic agent metadata validation for one datasource (dataplane 404.5)');
|
|
95
|
+
attachDatasourceTestCommonOptions(cmd, {
|
|
96
|
+
includeNoAsync: false,
|
|
97
|
+
includePayload: false,
|
|
98
|
+
timeoutHelp: 'HTTP timeout for validate request (ms)',
|
|
99
|
+
timeoutDefault: '120000'
|
|
100
|
+
});
|
|
101
|
+
cmd
|
|
102
|
+
.option('--no-sync', 'Skip publishing local integration files before validate')
|
|
103
|
+
.option('--revalidate', 'Force new validation (ignore inputHash cache)')
|
|
104
|
+
.option('--strict', 'Exit 1 unless trustDecision is trusted')
|
|
105
|
+
.addHelpText('after', datasourceTestTrustHelpAfter())
|
|
106
|
+
.action(datasourceTestTrustAction);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = {
|
|
110
|
+
setupDatasourceTestTrustCommand,
|
|
111
|
+
runDatasourceTestTrustOnce,
|
|
112
|
+
finalizeDatasourceTestTrust,
|
|
113
|
+
datasourceTestTrustAction
|
|
114
|
+
};
|
|
@@ -28,6 +28,7 @@ const {
|
|
|
28
28
|
finalizeDatasourceTestE2ELegacyPath,
|
|
29
29
|
displayDatasourceTestE2EEnvelopeResults
|
|
30
30
|
} = require('./datasource-unified-test-e2e-cli-helpers');
|
|
31
|
+
const { maybeVerifyAuditAfterE2E } = require('../datasource/audit-evidence-run');
|
|
31
32
|
const {
|
|
32
33
|
datasourceTestHelpAfter,
|
|
33
34
|
datasourceTestIntegrationHelpAfter,
|
|
@@ -333,7 +334,7 @@ async function runDatasourceTestE2ECliOnce(datasourceKey, options) {
|
|
|
333
334
|
minProcessed: options.minProcessed,
|
|
334
335
|
minRecordCount: options.minRecordCount,
|
|
335
336
|
timeout: options.timeout,
|
|
336
|
-
capabilityKey: options.
|
|
337
|
+
capabilityKey: options.capabilityKey,
|
|
337
338
|
sync: options.sync === true
|
|
338
339
|
});
|
|
339
340
|
const unifiedModes =
|
|
@@ -352,7 +353,7 @@ async function runDatasourceTestE2ECliOnce(datasourceKey, options) {
|
|
|
352
353
|
warningsAsErrors: options.warningsAsErrors,
|
|
353
354
|
requireCert: options.requireCert,
|
|
354
355
|
debug: options.debug,
|
|
355
|
-
requestedCapabilityKey: options.
|
|
356
|
+
requestedCapabilityKey: options.capabilityKey,
|
|
356
357
|
strictCapabilityScope: options.strictCapabilityScope === true
|
|
357
358
|
}
|
|
358
359
|
);
|
|
@@ -370,24 +371,24 @@ async function runDatasourceTestE2ECliOnce(datasourceKey, options) {
|
|
|
370
371
|
|
|
371
372
|
async function runDatasourceTestE2ECliAction(datasourceKey, options) {
|
|
372
373
|
const { exitCode, envelope } = await runDatasourceTestE2ECliOnce(datasourceKey, options);
|
|
373
|
-
await
|
|
374
|
-
|
|
374
|
+
const finalExit = await maybeVerifyAuditAfterE2E(exitCode, datasourceKey, envelope, options);
|
|
375
|
+
await afterUnifiedValidationCertSync(
|
|
376
|
+
finalExit,
|
|
377
|
+
datasourceKey,
|
|
378
|
+
options,
|
|
379
|
+
'datasource test-e2e',
|
|
380
|
+
envelope
|
|
381
|
+
);
|
|
382
|
+
process.exit(finalExit);
|
|
375
383
|
}
|
|
376
384
|
|
|
377
385
|
async function e2eTestCommandAction(datasourceKey, capabilityKey, options) {
|
|
378
386
|
const optObj = options && typeof options === 'object' ? options : {};
|
|
379
387
|
const capFromArg = typeof capabilityKey === 'string' ? capabilityKey.trim() : '';
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
:
|
|
383
|
-
|
|
384
|
-
if (capFromArg && capFromFlag && capFromArg !== capFromFlag) {
|
|
385
|
-
logger.warn(
|
|
386
|
-
chalk.yellow('⚠ Capability mismatch:'),
|
|
387
|
-
`using positional '${capFromArg}' instead of --capability '${capFromFlag}'.`
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
const mergedOptions = { ...optObj, capability: requestedCapability || undefined };
|
|
388
|
+
const mergedOptions = {
|
|
389
|
+
...optObj,
|
|
390
|
+
capabilityKey: capFromArg || undefined
|
|
391
|
+
};
|
|
391
392
|
try {
|
|
392
393
|
if (mergedOptions.watch) {
|
|
393
394
|
const { appKey } = await resolveAppKeyForDatasource(datasourceKey, mergedOptions.app);
|
|
@@ -400,14 +401,20 @@ async function e2eTestCommandAction(datasourceKey, capabilityKey, options) {
|
|
|
400
401
|
runOnce: async() => {
|
|
401
402
|
try {
|
|
402
403
|
const r = await runDatasourceTestE2ECliOnce(datasourceKey, mergedOptions);
|
|
403
|
-
await
|
|
404
|
+
const finalExit = await maybeVerifyAuditAfterE2E(
|
|
404
405
|
r.exitCode,
|
|
405
406
|
datasourceKey,
|
|
407
|
+
r.envelope,
|
|
408
|
+
mergedOptions
|
|
409
|
+
);
|
|
410
|
+
await afterUnifiedValidationCertSync(
|
|
411
|
+
finalExit,
|
|
412
|
+
datasourceKey,
|
|
406
413
|
mergedOptions,
|
|
407
414
|
'datasource test-e2e (watch)',
|
|
408
415
|
r.envelope
|
|
409
416
|
);
|
|
410
|
-
return r;
|
|
417
|
+
return { exitCode: finalExit, envelope: r.envelope };
|
|
411
418
|
} catch (err) {
|
|
412
419
|
logger.error(formatBlockingError('E2E test failed:'), err.message);
|
|
413
420
|
return { exitCode: 3, envelope: null };
|
|
@@ -459,5 +466,6 @@ module.exports = {
|
|
|
459
466
|
runIntegrationOnceForWatch,
|
|
460
467
|
integrationTestCommandAction,
|
|
461
468
|
runDatasourceTestE2ECliOnce,
|
|
469
|
+
maybeVerifyAuditAfterE2E,
|
|
462
470
|
e2eTestCommandAction
|
|
463
471
|
};
|
|
@@ -44,6 +44,7 @@ Examples:
|
|
|
44
44
|
$ aifabrix datasource test-e2e hubspot-users --app test-e2e-hubspot -v --debug
|
|
45
45
|
$ aifabrix datasource test-e2e my-documents-ds --min-vector-hits 7 -v --debug
|
|
46
46
|
$ aifabrix datasource test-e2e hubspot-users -a test-e2e-hubspot --no-async
|
|
47
|
+
$ aifabrix datasource test-e2e hubspot-users --sync --verify-audit -v
|
|
47
48
|
$ aifabrix datasource test-e2e hubspot-users read
|
|
48
49
|
|
|
49
50
|
Notes:
|
|
@@ -53,6 +54,7 @@ Notes:
|
|
|
53
54
|
aifabrix datasource test-integration <datasourceKey>
|
|
54
55
|
- For system-level E2E rollup across datasources, use:
|
|
55
56
|
aifabrix test-e2e <systemKey>
|
|
57
|
+
- To prove governance audit evidence after a green E2E, add --verify-audit (see verify-audit command).
|
|
56
58
|
`;
|
|
57
59
|
}
|
|
58
60
|
|
|
@@ -175,11 +177,24 @@ function attachDatasourceTestE2eExclusiveOptions(cmd) {
|
|
|
175
177
|
'--primary-key-value <value|@path>',
|
|
176
178
|
'Primary key value or path to JSON file (e.g. @pk.json) for e2eOptions.primaryKeyValue'
|
|
177
179
|
)
|
|
178
|
-
.option('--capability <key>', 'Capability drill-down (deprecated; use positional [capabilityKey])')
|
|
179
180
|
.option(
|
|
180
181
|
'--strict-capability-scope',
|
|
181
|
-
'Exit 1
|
|
182
|
-
)
|
|
182
|
+
'Exit 1 when positional [capabilityKey] is set but the report lists more than one capabilities[] row'
|
|
183
|
+
)
|
|
184
|
+
.option(
|
|
185
|
+
'--verify-audit',
|
|
186
|
+
'After successful E2E, verify the nine-row audit evidence matrix on the dataplane (requires audit:read)'
|
|
187
|
+
)
|
|
188
|
+
.option(
|
|
189
|
+
'--no-verify-audit',
|
|
190
|
+
'Skip audit evidence verification even if enabled by default in a future release'
|
|
191
|
+
)
|
|
192
|
+
.option(
|
|
193
|
+
'--audit-poll-ms <ms>',
|
|
194
|
+
'Max wait for audit rows after E2E when using --verify-audit (default 15000)',
|
|
195
|
+
'15000'
|
|
196
|
+
)
|
|
197
|
+
.option('--audit-poll-interval-ms <ms>', 'Audit poll interval when using --verify-audit (default 2000)', '2000');
|
|
183
198
|
}
|
|
184
199
|
|
|
185
200
|
module.exports = {
|
|
@@ -46,7 +46,7 @@ function exitCodeFromDatasourceTestRunEnvelope(env, options) {
|
|
|
46
46
|
warningsAsErrors: options.warningsAsErrors === true,
|
|
47
47
|
requireCert: options.requireCert === true
|
|
48
48
|
});
|
|
49
|
-
const scope = analyzeCapabilityScope(env, options.
|
|
49
|
+
const scope = analyzeCapabilityScope(env, options.capabilityKey);
|
|
50
50
|
if (options.strictCapabilityScope === true && scope.violated) {
|
|
51
51
|
code = Math.max(code, 1);
|
|
52
52
|
}
|
|
@@ -62,10 +62,10 @@ function exitCodeFromDatasourceTestRunEnvelope(env, options) {
|
|
|
62
62
|
function finalizeDatasourceTestE2ELegacyPath(data, options) {
|
|
63
63
|
displayE2EResults(data, options.verbose);
|
|
64
64
|
logDatasourceTestRunDebugAppendix(data.datasourceTestRun, options.debug);
|
|
65
|
-
logE2eCapabilityFocusFromEnvelope(data.datasourceTestRun, options.
|
|
65
|
+
logE2eCapabilityFocusFromEnvelope(data.datasourceTestRun, options.capabilityKey);
|
|
66
66
|
const env = data.datasourceTestRun;
|
|
67
67
|
if (env) {
|
|
68
|
-
emitCapabilityScopeDiagnostics(env, { requestedCapabilityKey: options.
|
|
68
|
+
emitCapabilityScopeDiagnostics(env, { requestedCapabilityKey: options.capabilityKey });
|
|
69
69
|
const code = exitCodeFromDatasourceTestRunEnvelope(env, options);
|
|
70
70
|
return code === null ? 1 : code;
|
|
71
71
|
}
|
|
@@ -91,10 +91,10 @@ function displayDatasourceTestE2EEnvelopeResults(datasourceKey, env, options) {
|
|
|
91
91
|
{
|
|
92
92
|
debug: options.debug,
|
|
93
93
|
runType: 'e2e',
|
|
94
|
-
requestedCapabilityKey: options.
|
|
94
|
+
requestedCapabilityKey: options.capabilityKey
|
|
95
95
|
}
|
|
96
96
|
);
|
|
97
|
-
logE2eCapabilityFocusFromEnvelope(env, options.
|
|
97
|
+
logE2eCapabilityFocusFromEnvelope(env, options.capabilityKey);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
module.exports = {
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `aifabrix datasource verify-audit` — re-run 407.1 matrix from last E2E log
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const logger = require('../utils/logger');
|
|
10
|
+
const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
|
|
11
|
+
const { runAuditEvidenceVerification } = require('../datasource/audit-evidence-run');
|
|
12
|
+
const { loadEnvelopeFromLatestE2eLog } = require('../datasource/audit-evidence-extract');
|
|
13
|
+
|
|
14
|
+
const VERIFY_AUDIT_HELP_AFTER = `
|
|
15
|
+
Examples:
|
|
16
|
+
$ aifabrix datasource verify-audit test-e2e-hubspot-companies
|
|
17
|
+
$ aifabrix datasource verify-audit test-e2e-hubspot-companies --app test-e2e-hubspot -v
|
|
18
|
+
$ aifabrix datasource verify-audit test-e2e-hubspot-companies --correlation-id <testRunId>
|
|
19
|
+
$ aifabrix datasource verify-audit test-e2e-hubspot-companies --json
|
|
20
|
+
|
|
21
|
+
Notes:
|
|
22
|
+
- Re-checks audit evidence from the latest test-e2e debug log (or --file) without re-running E2E.
|
|
23
|
+
- Requires audit:read on the dataplane (same login as test-e2e).
|
|
24
|
+
- Pair with: aifabrix datasource test-e2e <datasourceKey> --verify-audit
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {string} datasourceKey
|
|
29
|
+
* @param {Object} options
|
|
30
|
+
*/
|
|
31
|
+
async function verifyAuditCommandAction(datasourceKey, options) {
|
|
32
|
+
const envelope = await loadEnvelopeFromLatestE2eLog(datasourceKey, options);
|
|
33
|
+
if (!envelope) {
|
|
34
|
+
logger.error(
|
|
35
|
+
formatBlockingError('verify-audit failed:'),
|
|
36
|
+
'No test-e2e debug log found (run test-e2e with --debug first)'
|
|
37
|
+
);
|
|
38
|
+
process.exit(3);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const pollMs = parseInt(String(options.auditPollMs || '15000'), 10);
|
|
42
|
+
const pollInterval = parseInt(String(options.auditPollIntervalMs || '2000'), 10);
|
|
43
|
+
const { exitCode } = await runAuditEvidenceVerification(datasourceKey, envelope, {
|
|
44
|
+
app: options.app,
|
|
45
|
+
env: options.env,
|
|
46
|
+
verbose: options.verbose,
|
|
47
|
+
json: options.json,
|
|
48
|
+
correlationId: options.correlationId,
|
|
49
|
+
executionId: options.executionId,
|
|
50
|
+
quiet: false,
|
|
51
|
+
auditPollMaxWaitMs: Number.isFinite(pollMs) ? pollMs : 15000,
|
|
52
|
+
auditPollIntervalMs: Number.isFinite(pollInterval) ? pollInterval : 2000
|
|
53
|
+
});
|
|
54
|
+
process.exit(exitCode);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {import('commander').Command} datasource
|
|
59
|
+
*/
|
|
60
|
+
function setupDatasourceVerifyAuditCommand(datasource) {
|
|
61
|
+
datasource
|
|
62
|
+
.command('verify-audit <datasourceKey>')
|
|
63
|
+
.description(
|
|
64
|
+
'Verify audit evidence matrix from latest E2E log (or --file) without re-running E2E'
|
|
65
|
+
)
|
|
66
|
+
.option(
|
|
67
|
+
'-a, --app <app>',
|
|
68
|
+
'Integration folder name (optional: resolve from cwd or datasource key if single match)'
|
|
69
|
+
)
|
|
70
|
+
.option('-e, --env <env>', 'Environment: dev, tst, or pro')
|
|
71
|
+
.option('-v, --verbose', 'Show matrix row codes and execution id count')
|
|
72
|
+
.option('--json', 'Print auditEvidenceVerification JSON block')
|
|
73
|
+
.option('-f, --file <path>', 'Path to test-e2e debug log JSON')
|
|
74
|
+
.option('--correlation-id <id>', 'Override correlation/testRunId filter')
|
|
75
|
+
.option('--execution-id <id>', 'Include execution id for sub-resource checks')
|
|
76
|
+
.option(
|
|
77
|
+
'--audit-poll-ms <ms>',
|
|
78
|
+
'Max wait for audit rows to appear (default 15000)',
|
|
79
|
+
'15000'
|
|
80
|
+
)
|
|
81
|
+
.option('--audit-poll-interval-ms <ms>', 'Poll interval (default 2000)', '2000')
|
|
82
|
+
.addHelpText('after', VERIFY_AUDIT_HELP_AFTER)
|
|
83
|
+
.action(async(datasourceKey, options) => {
|
|
84
|
+
try {
|
|
85
|
+
await verifyAuditCommandAction(datasourceKey, options);
|
|
86
|
+
} catch (error) {
|
|
87
|
+
logger.error(formatBlockingError('verify-audit failed:'), error.message);
|
|
88
|
+
process.exit(3);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = {
|
|
94
|
+
setupDatasourceVerifyAuditCommand,
|
|
95
|
+
verifyAuditCommandAction
|
|
96
|
+
};
|