@aifabrix/builder 2.44.6 → 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/cli-layout.mdc +7 -3
- 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 +100 -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/app/helpers.js +3 -3
- package/lib/app/index.js +3 -3
- package/lib/app/register.js +7 -6
- package/lib/app/restart-display.js +52 -21
- package/lib/app/rotate-secret.js +7 -6
- package/lib/app/run-helpers.js +15 -8
- package/lib/app/run.js +57 -9
- package/lib/app/show-display.js +7 -0
- package/lib/app/show.js +87 -5
- package/lib/build/index.js +9 -5
- package/lib/cli/index.js +4 -2
- package/lib/cli/infra-guided.js +62 -28
- package/lib/cli/installation-log-command.js +73 -0
- package/lib/cli/setup-app.help.js +50 -2
- package/lib/cli/setup-app.js +44 -25
- package/lib/cli/setup-app.test-commands.js +80 -21
- package/lib/cli/setup-auth.js +124 -52
- package/lib/cli/setup-external-system.js +37 -3
- package/lib/cli/setup-infra-up-dataplane-action.js +111 -0
- package/lib/cli/setup-infra-up-platform-action.js +131 -0
- package/lib/cli/setup-infra.js +60 -119
- package/lib/cli/setup-platform.js +1 -1
- package/lib/cli/setup-utility-help-after.js +45 -0
- package/lib/cli/setup-utility-resolve.js +132 -0
- package/lib/cli/setup-utility.js +148 -116
- package/lib/commands/app-logs.js +81 -33
- package/lib/commands/auth-config.js +116 -18
- 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/setup-modes.js +19 -6
- package/lib/commands/setup-prompts.js +41 -8
- package/lib/commands/setup.js +114 -9
- package/lib/commands/teardown.js +54 -5
- 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/up-common.js +48 -14
- package/lib/commands/up-dataplane.js +21 -18
- package/lib/commands/up-miso.js +12 -8
- package/lib/commands/upload.js +38 -15
- package/lib/commands/wizard-core.js +3 -0
- package/lib/core/audit-logger.js +1 -34
- package/lib/core/config-admin-email.js +56 -0
- package/lib/core/config-device-dataplane.js +185 -0
- package/lib/core/config-normalize.js +60 -0
- package/lib/core/config-registered-controller-urls.js +54 -0
- package/lib/core/config.js +33 -50
- package/lib/core/secrets-ensure-infra.js +1 -1
- package/lib/core/secrets-env-content.js +86 -90
- package/lib/core/secrets-env-declarative-expand.js +170 -0
- package/lib/core/secrets-env-write.js +2 -0
- package/lib/core/secrets-load.js +106 -102
- 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/deploy.js +5 -1
- 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/internal/node-fs.js +2 -0
- 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/application-schema.json +4 -0
- package/lib/schema/external-datasource.schema.json +47 -13
- package/lib/schema/flag-map-validation-run.json +2 -2
- package/lib/schema/infra.parameter.yaml +10 -0
- 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/app-config-resolver.js +24 -1
- package/lib/utils/applications-config-defaults.js +206 -0
- package/lib/utils/auth-config-validator.js +2 -12
- package/lib/utils/bash-secret-env.js +1 -1
- package/lib/utils/cli-exit-codes.js +30 -0
- package/lib/utils/cli-sync-options.js +33 -0
- package/lib/utils/compose-generate-docker-compose.js +111 -6
- package/lib/utils/compose-generator.js +17 -8
- package/lib/utils/controller-url.js +50 -7
- 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/env-copy.js +99 -14
- package/lib/utils/env-template.js +5 -1
- package/lib/utils/health-check-url.js +18 -15
- package/lib/utils/health-check.js +7 -5
- package/lib/utils/help-builder.js +30 -24
- package/lib/utils/infra-optional-service-flags.js +69 -0
- package/lib/utils/installation-log-core.js +282 -0
- package/lib/utils/installation-log-record.js +237 -0
- package/lib/utils/installation-log.js +123 -0
- package/lib/utils/log-redaction.js +105 -0
- package/lib/utils/manifest-location.js +164 -0
- package/lib/utils/manifest-source-emit.js +184 -0
- package/lib/utils/paths.js +238 -89
- package/lib/utils/remote-secrets-loader.js +7 -1
- package/lib/utils/run-cli-flags.js +29 -0
- package/lib/utils/secrets-canonical.js +10 -3
- package/lib/utils/secrets-path.js +3 -4
- package/lib/utils/secrets-utils.js +20 -10
- package/lib/utils/semver-compare.js +127 -0
- package/lib/utils/system-builder-root.js +10 -2
- package/lib/utils/upload-pipeline-ui.js +91 -0
- package/lib/utils/url-declarative-public-base.js +80 -12
- package/lib/utils/url-declarative-resolve-build-urls.js +238 -0
- package/lib/utils/url-declarative-resolve-build.js +24 -393
- package/lib/utils/url-declarative-resolve-expand-token.js +189 -0
- package/lib/utils/url-declarative-resolve-load-doc.js +12 -3
- package/lib/utils/url-declarative-resolve-surface-state.js +102 -0
- package/lib/utils/url-declarative-resolve.js +47 -7
- package/lib/utils/url-declarative-runtime-base-path.js +21 -1
- package/lib/utils/urls-local-registry-scan.js +103 -0
- package/lib/utils/urls-local-registry.js +161 -90
- package/lib/utils/validation-poll-ui.js +14 -7
- package/lib/validation/wizard-config-validator.js +58 -19
- package/package.json +3 -1
- package/templates/applications/dataplane/application.yaml +4 -0
- package/templates/applications/dataplane/env.template +13 -1
- package/templates/applications/dataplane/rbac.yaml +4 -0
- package/templates/applications/miso-controller/application.yaml +2 -0
- package/templates/applications/miso-controller/env.template +27 -29
- package/templates/external-system/README.md.hbs +56 -8
- package/.npmrc.token +0 -1
package/lib/core/secrets-load.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Secrets loading
|
|
2
|
+
* Secrets loading: primary user file plus configured `aifabrix-secrets` (shared YAML or remote API).
|
|
3
3
|
*
|
|
4
|
-
* @fileoverview
|
|
4
|
+
* @fileoverview Default `kv://` resolution uses only `~/.aifabrix/secrets.local.yaml` and `aifabrix-secrets`
|
|
5
|
+
* from config — not cwd-ancestor `.aifabrix/secrets.local.yaml`, not `builder/secrets.local.yaml`,
|
|
6
|
+
* and not `~/.aifabrix/secrets.yaml`.
|
|
5
7
|
* @author AI Fabrix Team
|
|
6
8
|
* @version 1.0.0
|
|
7
9
|
*/
|
|
@@ -13,27 +15,75 @@ const path = require('path');
|
|
|
13
15
|
const config = require('./config');
|
|
14
16
|
const { readYamlAtPath, applyCanonicalSecretsOverride } = require('../utils/secrets-canonical');
|
|
15
17
|
const { ensureSecureFilePermissions } = require('../utils/secure-file-permissions');
|
|
18
|
+
const { resolveSecretsPath } = require('../utils/secrets-path');
|
|
16
19
|
const {
|
|
17
|
-
resolveSecretsPath
|
|
18
|
-
} = require('../utils/secrets-path');
|
|
19
|
-
const {
|
|
20
|
-
loadUserSecrets,
|
|
21
20
|
loadPrimaryUserSecrets,
|
|
22
21
|
loadDefaultSecrets,
|
|
23
22
|
ensurePrimaryUserSecretsFileExists
|
|
24
23
|
} = require('../utils/secrets-utils');
|
|
25
|
-
const { decryptSecret, isEncrypted } = require('../utils/secrets-encryption');
|
|
26
24
|
const pathsUtil = require('../utils/paths');
|
|
27
|
-
const {
|
|
25
|
+
const { decryptSecret, isEncrypted } = require('../utils/secrets-encryption');
|
|
26
|
+
const logger = require('../utils/logger');
|
|
27
|
+
const { isSecretKeyAllowedEmpty } = require('./secrets-ensure-infra');
|
|
28
|
+
|
|
29
|
+
/** Dedupe optional decrypt warnings across repeated `loadSecrets` (and duplicate module instances). */
|
|
30
|
+
function optionalDecryptWarnSeen(key) {
|
|
31
|
+
const g = globalThis;
|
|
32
|
+
if (!g.__aifabrixOptionalDecryptWarnOnce) {
|
|
33
|
+
g.__aifabrixOptionalDecryptWarnOnce = new Set();
|
|
34
|
+
}
|
|
35
|
+
const set = g.__aifabrixOptionalDecryptWarnOnce;
|
|
36
|
+
if (set.has(key)) return true;
|
|
37
|
+
set.add(key);
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {string} key
|
|
43
|
+
* @param {unknown} value
|
|
44
|
+
* @param {string} encryptionKey
|
|
45
|
+
* @param {Record<string, string>} decryptedSecrets
|
|
46
|
+
* @param {string} [sourceHint] - File path or API label for decrypt errors / warnings
|
|
47
|
+
*/
|
|
48
|
+
function mergeDecryptedEntry(key, value, encryptionKey, decryptedSecrets, sourceHint) {
|
|
49
|
+
if (!isEncrypted(value)) {
|
|
50
|
+
decryptedSecrets[key] = value;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
decryptedSecrets[key] = decryptSecret(value, encryptionKey);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
const msg = error && error.message ? error.message : String(error);
|
|
57
|
+
if (!isSecretKeyAllowedEmpty(key)) {
|
|
58
|
+
const where =
|
|
59
|
+
sourceHint && String(sourceHint).trim().length > 0
|
|
60
|
+
? ` (encrypted value loaded from: ${sourceHint})`
|
|
61
|
+
: ' (encrypted value source not recorded; check ~/.aifabrix/secrets.local.yaml and aifabrix-secrets)';
|
|
62
|
+
throw new Error(`Failed to decrypt secret '${key}'${where}: ${msg}`);
|
|
63
|
+
}
|
|
64
|
+
if (!optionalDecryptWarnSeen(key)) {
|
|
65
|
+
const where =
|
|
66
|
+
sourceHint && String(sourceHint).trim().length > 0
|
|
67
|
+
? ` Encrypted value loaded from: ${sourceHint}.`
|
|
68
|
+
: '';
|
|
69
|
+
logger.warn(
|
|
70
|
+
`Optional secret '${key}' could not be decrypted (${msg}). Treating as empty.${where} ` +
|
|
71
|
+
'Remove the stale key from shared or local secrets, or fix secrets-encryption alignment.'
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
decryptedSecrets[key] = '';
|
|
75
|
+
}
|
|
76
|
+
}
|
|
28
77
|
|
|
29
78
|
/**
|
|
30
79
|
* Decrypts encrypted values in secrets object
|
|
31
80
|
*
|
|
32
81
|
* @async
|
|
33
82
|
* @param {Object} secrets - Secrets object with potentially encrypted values
|
|
83
|
+
* @param {{ keySources?: Record<string, string>, defaultSourceLabel?: string }} [options] - Per-key file/API path for errors
|
|
34
84
|
* @returns {Promise<Object>} Secrets object with decrypted values
|
|
35
85
|
*/
|
|
36
|
-
async function decryptSecretsObject(secrets) {
|
|
86
|
+
async function decryptSecretsObject(secrets, options) {
|
|
37
87
|
if (!secrets || typeof secrets !== 'object') {
|
|
38
88
|
return secrets;
|
|
39
89
|
}
|
|
@@ -49,17 +99,13 @@ async function decryptSecretsObject(secrets) {
|
|
|
49
99
|
return secrets;
|
|
50
100
|
}
|
|
51
101
|
|
|
102
|
+
const keySources = options && options.keySources ? options.keySources : null;
|
|
103
|
+
const defaultLabel = options && options.defaultSourceLabel ? options.defaultSourceLabel : '';
|
|
104
|
+
|
|
52
105
|
const decryptedSecrets = {};
|
|
53
106
|
for (const [key, value] of Object.entries(secrets)) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
decryptedSecrets[key] = decryptSecret(value, encryptionKey);
|
|
57
|
-
} catch (error) {
|
|
58
|
-
throw new Error(`Failed to decrypt secret '${key}': ${error.message}`);
|
|
59
|
-
}
|
|
60
|
-
} else {
|
|
61
|
-
decryptedSecrets[key] = value;
|
|
62
|
-
}
|
|
107
|
+
const sourceHint = (keySources && keySources[key]) || defaultLabel || '';
|
|
108
|
+
mergeDecryptedEntry(key, value, encryptionKey, decryptedSecrets, sourceHint);
|
|
63
109
|
}
|
|
64
110
|
|
|
65
111
|
return decryptedSecrets;
|
|
@@ -67,8 +113,9 @@ async function decryptSecretsObject(secrets) {
|
|
|
67
113
|
|
|
68
114
|
/**
|
|
69
115
|
* Merges config file secrets into user secrets (user wins). Returns null if path missing or config empty.
|
|
116
|
+
* @param {Record<string, string>} [keySources] - Mutated: path for keys filled from this file
|
|
70
117
|
*/
|
|
71
|
-
function mergeUserWithConfigFile(userSecrets, resolvedConfigPath) {
|
|
118
|
+
function mergeUserWithConfigFile(userSecrets, resolvedConfigPath, keySources) {
|
|
72
119
|
if (!fs.existsSync(resolvedConfigPath)) {
|
|
73
120
|
return null;
|
|
74
121
|
}
|
|
@@ -86,6 +133,9 @@ function mergeUserWithConfigFile(userSecrets, resolvedConfigPath) {
|
|
|
86
133
|
for (const key of Object.keys(configSecrets)) {
|
|
87
134
|
if (!(key in merged) || merged[key] === undefined || merged[key] === null || merged[key] === '') {
|
|
88
135
|
merged[key] = configSecrets[key];
|
|
136
|
+
if (keySources) {
|
|
137
|
+
keySources[key] = resolvedConfigPath;
|
|
138
|
+
}
|
|
89
139
|
}
|
|
90
140
|
}
|
|
91
141
|
return merged;
|
|
@@ -99,122 +149,74 @@ function createMergeHelpers(userSecrets) {
|
|
|
99
149
|
};
|
|
100
150
|
}
|
|
101
151
|
|
|
102
|
-
async function mergeFromConfiguredSecretsPath(configSecretsPath, userSecrets, helpers) {
|
|
152
|
+
async function mergeFromConfiguredSecretsPath(configSecretsPath, userSecrets, helpers, keySources) {
|
|
103
153
|
const remoteDevAuth = require('../utils/remote-dev-auth');
|
|
104
154
|
const effectiveShared = await remoteDevAuth.resolveSharedSecretsEndpoint(configSecretsPath);
|
|
105
155
|
|
|
106
156
|
if (remoteDevAuth.isRemoteSecretsUrl(effectiveShared)) {
|
|
107
157
|
const { loadRemoteSharedSecrets, mergeUserWithRemoteSecrets } = require('../utils/remote-secrets-loader');
|
|
108
158
|
const remoteSecrets = await loadRemoteSharedSecrets();
|
|
109
|
-
const
|
|
159
|
+
const remoteLabel = `shared secrets API (${effectiveShared})`;
|
|
160
|
+
const merged = mergeUserWithRemoteSecrets(userSecrets, remoteSecrets, keySources, remoteLabel);
|
|
110
161
|
return helpers.hasKeys(merged) ? merged : helpers.userOrNull();
|
|
111
162
|
}
|
|
112
163
|
|
|
113
164
|
const resolvedConfigPath = path.isAbsolute(configSecretsPath)
|
|
114
165
|
? configSecretsPath
|
|
115
166
|
: path.resolve(process.cwd(), configSecretsPath);
|
|
116
|
-
const merged = mergeUserWithConfigFile(userSecrets, resolvedConfigPath);
|
|
167
|
+
const merged = mergeUserWithConfigFile(userSecrets, resolvedConfigPath, keySources);
|
|
117
168
|
return merged !== null ? merged : helpers.userOrNull();
|
|
118
169
|
}
|
|
119
170
|
|
|
120
171
|
async function loadMergedConfigAndUserSecrets() {
|
|
121
172
|
const userSecrets = loadPrimaryUserSecrets();
|
|
122
173
|
const helpers = createMergeHelpers(userSecrets);
|
|
174
|
+
const userPath = pathsUtil.getPrimaryUserSecretsLocalPath();
|
|
175
|
+
/** @type {Record<string, string>} */
|
|
176
|
+
const keySources = {};
|
|
177
|
+
for (const k of Object.keys(userSecrets || {})) {
|
|
178
|
+
keySources[k] = userPath;
|
|
179
|
+
}
|
|
123
180
|
|
|
124
181
|
try {
|
|
125
182
|
const configSecretsPath = await config.getSecretsPath();
|
|
126
183
|
if (!configSecretsPath) {
|
|
127
|
-
return helpers.userOrNull();
|
|
184
|
+
return { merged: helpers.userOrNull(), keySources };
|
|
128
185
|
}
|
|
129
|
-
|
|
186
|
+
const merged = await mergeFromConfiguredSecretsPath(configSecretsPath, userSecrets, helpers, keySources);
|
|
187
|
+
return { merged, keySources };
|
|
130
188
|
} catch (error) {
|
|
131
189
|
if (error.message && error.message.startsWith('Failed to load secrets file')) {
|
|
132
190
|
throw error;
|
|
133
191
|
}
|
|
134
|
-
return null;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function collectBuilderSecretsYamlPaths() {
|
|
139
|
-
const projectRoot = pathsUtil.getProjectRoot();
|
|
140
|
-
const candidates = [];
|
|
141
|
-
if (projectRoot) {
|
|
142
|
-
candidates.push(path.join(projectRoot, 'builder', 'secrets.local.yaml'));
|
|
143
|
-
}
|
|
144
|
-
try {
|
|
145
|
-
const alt = path.join(pathsUtil.getBuilderRoot(), 'secrets.local.yaml');
|
|
146
|
-
if (!candidates.length || path.resolve(candidates[0]) !== path.resolve(alt)) {
|
|
147
|
-
candidates.push(alt);
|
|
148
|
-
}
|
|
149
|
-
} catch {
|
|
150
|
-
/* ignore */
|
|
151
|
-
}
|
|
152
|
-
return candidates;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function mergeBuilderSecretsLocalFiles(merged) {
|
|
156
|
-
try {
|
|
157
|
-
const seen = new Set();
|
|
158
|
-
let out = merged;
|
|
159
|
-
for (const builderPath of collectBuilderSecretsYamlPaths()) {
|
|
160
|
-
if (!builderPath || seen.has(path.resolve(builderPath))) {
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
seen.add(path.resolve(builderPath));
|
|
164
|
-
if (fs.existsSync(builderPath)) {
|
|
165
|
-
ensureSecureFilePermissions(builderPath);
|
|
166
|
-
const builderSecrets = mergeUserWithConfigFile(out || {}, builderPath);
|
|
167
|
-
if (builderSecrets) out = builderSecrets;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
return out;
|
|
171
|
-
} catch {
|
|
172
|
-
return merged;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Merge each `cwd/.aifabrix/secrets.local.yaml` found walking up to filesystem root.
|
|
178
|
-
* Later files only fill keys missing or empty on the merged object (same as shared merge).
|
|
179
|
-
* Skips the primary user file path when it appears on the walk (already loaded in merge chain).
|
|
180
|
-
*
|
|
181
|
-
* @param {Object|null|undefined} merged - Current secrets map
|
|
182
|
-
* @returns {Object}
|
|
183
|
-
*/
|
|
184
|
-
function mergeAncestorAifabrixSecretsLocalFiles(merged) {
|
|
185
|
-
try {
|
|
186
|
-
const primaryUser = path.resolve(pathsUtil.getPrimaryUserSecretsLocalPath());
|
|
187
|
-
let out = merged && typeof merged === 'object' ? merged : {};
|
|
188
|
-
const ancestorPaths = collectAncestorAifabrixSecretsLocalYamlPaths(process.cwd(), fs.existsSync);
|
|
189
|
-
for (const secretsPath of ancestorPaths) {
|
|
190
|
-
if (path.resolve(secretsPath) === primaryUser) {
|
|
191
|
-
continue;
|
|
192
|
-
}
|
|
193
|
-
ensureSecureFilePermissions(secretsPath);
|
|
194
|
-
const next = mergeUserWithConfigFile(out, secretsPath);
|
|
195
|
-
if (next) out = next;
|
|
196
|
-
}
|
|
197
|
-
return out;
|
|
198
|
-
} catch {
|
|
199
|
-
return merged && typeof merged === 'object' ? merged : {};
|
|
192
|
+
return { merged: null, keySources };
|
|
200
193
|
}
|
|
201
194
|
}
|
|
202
195
|
|
|
203
196
|
async function loadSecretsWithFallbacks() {
|
|
204
|
-
|
|
197
|
+
const mergedResult = await loadMergedConfigAndUserSecrets();
|
|
198
|
+
let merged = mergedResult.merged;
|
|
199
|
+
const keySources = mergedResult.keySources;
|
|
205
200
|
if (!merged || Object.keys(merged).length === 0) {
|
|
206
201
|
merged = loadPrimaryUserSecrets();
|
|
207
|
-
|
|
208
|
-
|
|
202
|
+
const userPath = pathsUtil.getPrimaryUserSecretsLocalPath();
|
|
203
|
+
for (const k of Object.keys(merged || {})) {
|
|
204
|
+
keySources[k] = userPath;
|
|
209
205
|
}
|
|
210
|
-
merged = await applyCanonicalSecretsOverride(merged);
|
|
206
|
+
merged = await applyCanonicalSecretsOverride(merged || {}, keySources);
|
|
211
207
|
}
|
|
212
|
-
|
|
213
|
-
merged
|
|
214
|
-
if (Object.keys(merged).length === 0) {
|
|
208
|
+
const configuredShared = await config.getSecretsPath();
|
|
209
|
+
if ((!merged || Object.keys(merged).length === 0) && !configuredShared) {
|
|
215
210
|
merged = loadDefaultSecrets();
|
|
211
|
+
const defaultPath = path.join(pathsUtil.getAifabrixHome(), 'secrets.yaml');
|
|
212
|
+
for (const k of Object.keys(merged || {})) {
|
|
213
|
+
keySources[k] = defaultPath;
|
|
214
|
+
}
|
|
216
215
|
}
|
|
217
|
-
|
|
216
|
+
if (!merged || Object.keys(merged).length === 0) {
|
|
217
|
+
return { merged: {}, keySources };
|
|
218
|
+
}
|
|
219
|
+
return { merged, keySources };
|
|
218
220
|
}
|
|
219
221
|
|
|
220
222
|
/**
|
|
@@ -232,14 +234,16 @@ async function loadSecrets(secretsPath, _appName) {
|
|
|
232
234
|
if (!explicitSecrets || typeof explicitSecrets !== 'object') {
|
|
233
235
|
throw new Error(`Invalid secrets file format: ${resolvedPath}`);
|
|
234
236
|
}
|
|
235
|
-
return await decryptSecretsObject(explicitSecrets);
|
|
237
|
+
return await decryptSecretsObject(explicitSecrets, { defaultSourceLabel: resolvedPath });
|
|
236
238
|
}
|
|
237
|
-
let mergedSecrets = await loadSecretsWithFallbacks();
|
|
239
|
+
let { merged: mergedSecrets, keySources } = await loadSecretsWithFallbacks();
|
|
238
240
|
if (!mergedSecrets || Object.keys(mergedSecrets).length === 0) {
|
|
239
241
|
ensurePrimaryUserSecretsFileExists();
|
|
240
|
-
|
|
242
|
+
const again = await loadSecretsWithFallbacks();
|
|
243
|
+
mergedSecrets = again.merged;
|
|
244
|
+
keySources = again.keySources;
|
|
241
245
|
}
|
|
242
|
-
return await decryptSecretsObject(mergedSecrets || {});
|
|
246
|
+
return await decryptSecretsObject(mergedSecrets || {}, { keySources });
|
|
243
247
|
}
|
|
244
248
|
|
|
245
249
|
module.exports = {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Debug log writer for agent trust CLI runs (plan 143).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const logger = require('../utils/logger');
|
|
10
|
+
const { getIntegrationPath } = require('../utils/paths');
|
|
11
|
+
const { writeTestLog } = require('../utils/test-log-writer');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @async
|
|
15
|
+
* @param {string} appKey - Integration folder key
|
|
16
|
+
* @param {string} datasourceKey
|
|
17
|
+
* @param {Object} payload
|
|
18
|
+
* @returns {Promise<string|null>} Log path or null when skipped
|
|
19
|
+
*/
|
|
20
|
+
async function writeTrustDebugLog(appKey, datasourceKey, payload) {
|
|
21
|
+
const logPath = await writeTestLog(
|
|
22
|
+
appKey,
|
|
23
|
+
payload,
|
|
24
|
+
`test-trust-${datasourceKey}`,
|
|
25
|
+
path.dirname(getIntegrationPath(appKey))
|
|
26
|
+
);
|
|
27
|
+
return logPath;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @async
|
|
32
|
+
* @param {string} appKey
|
|
33
|
+
* @param {string} datasourceKey
|
|
34
|
+
* @param {Object} payload
|
|
35
|
+
*/
|
|
36
|
+
async function writeTrustDebugLogAndPrint(appKey, datasourceKey, payload) {
|
|
37
|
+
const logPath = await writeTrustDebugLog(appKey, datasourceKey, payload);
|
|
38
|
+
logger.log(chalk.gray(` Debug log: ${logPath}`));
|
|
39
|
+
return logPath;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = {
|
|
43
|
+
writeTrustDebugLog,
|
|
44
|
+
writeTrustDebugLogAndPrint
|
|
45
|
+
};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Dataplane fetch paths for agent trust runs (POST validate / GET latest).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
runAgentMetadataValidation,
|
|
9
|
+
getLatestAgentMetadataValidation
|
|
10
|
+
} = require('../api/agent-metadata-validation.api');
|
|
11
|
+
const { parseTrustTimeoutMs } = require('./agent-trust-timeout');
|
|
12
|
+
const { isAgentTrustMockEnabled, buildMockTrustRun } = require('./agent-trust-mock');
|
|
13
|
+
const { mapRunResponseToTrustRun, mapLatestResultToTrustRun } = require('./agent-trust-map');
|
|
14
|
+
const {
|
|
15
|
+
runWithAgentTrustWaitSpinner,
|
|
16
|
+
logAgentTrustWaitHintOnce
|
|
17
|
+
} = require('../utils/agent-trust-wait-ui');
|
|
18
|
+
|
|
19
|
+
function unwrapApiData(response) {
|
|
20
|
+
if (response && response.data !== undefined) return response.data;
|
|
21
|
+
return response;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {Object} options
|
|
26
|
+
* @returns {boolean}
|
|
27
|
+
*/
|
|
28
|
+
function shouldPreferLatestRead(options = {}) {
|
|
29
|
+
if (options.revalidate === true) return false;
|
|
30
|
+
return options.summary === true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {Error} err
|
|
35
|
+
* @returns {boolean}
|
|
36
|
+
*/
|
|
37
|
+
function isLatestNotFoundError(err) {
|
|
38
|
+
const code = err && (err.statusCode || err.status);
|
|
39
|
+
if (code === 404) return true;
|
|
40
|
+
const msg = err && err.message ? String(err.message) : '';
|
|
41
|
+
return /no agent metadata validation/i.test(msg);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @async
|
|
46
|
+
* @param {Object} params
|
|
47
|
+
* @returns {Promise<Object>}
|
|
48
|
+
*/
|
|
49
|
+
async function postValidateTrustRun(params) {
|
|
50
|
+
const { dataplaneUrl, datasourceKey, systemKey, authConfig, body, options } = params;
|
|
51
|
+
const timeoutMs = parseTrustTimeoutMs(options);
|
|
52
|
+
logAgentTrustWaitHintOnce(datasourceKey, timeoutMs);
|
|
53
|
+
const raw = await runWithAgentTrustWaitSpinner(
|
|
54
|
+
() =>
|
|
55
|
+
runAgentMetadataValidation(dataplaneUrl, datasourceKey, authConfig, body, { timeoutMs }),
|
|
56
|
+
{ datasourceKey, timeoutMs }
|
|
57
|
+
);
|
|
58
|
+
return mapRunResponseToTrustRun({
|
|
59
|
+
datasourceKey,
|
|
60
|
+
systemKey,
|
|
61
|
+
runResponse: unwrapApiData(raw)
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @async
|
|
67
|
+
* @param {Object} params
|
|
68
|
+
* @returns {Promise<Object>}
|
|
69
|
+
*/
|
|
70
|
+
async function getLatestTrustRun(params) {
|
|
71
|
+
const { dataplaneUrl, datasourceKey, systemKey, authConfig, options } = params;
|
|
72
|
+
const timeoutMs = parseTrustTimeoutMs(options);
|
|
73
|
+
const raw = await getLatestAgentMetadataValidation(dataplaneUrl, datasourceKey, authConfig, {
|
|
74
|
+
timeoutMs
|
|
75
|
+
});
|
|
76
|
+
return mapLatestResultToTrustRun({
|
|
77
|
+
datasourceKey,
|
|
78
|
+
systemKey,
|
|
79
|
+
latestResult: unwrapApiData(raw)
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* @async
|
|
85
|
+
* @param {Object} params
|
|
86
|
+
* @returns {Promise<Object>}
|
|
87
|
+
*/
|
|
88
|
+
async function fetchTrustRunFromDataplane(params) {
|
|
89
|
+
const { datasourceKey, systemKey, dataplaneUrl, authConfig, options } = params;
|
|
90
|
+
if (isAgentTrustMockEnabled()) {
|
|
91
|
+
return buildMockTrustRun(datasourceKey, systemKey);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const body = { forceRevalidate: options.revalidate === true };
|
|
95
|
+
if (options.peerDatasourceConfigs && typeof options.peerDatasourceConfigs === 'object') {
|
|
96
|
+
body.peerDatasourceConfigs = options.peerDatasourceConfigs;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!shouldPreferLatestRead(options)) {
|
|
100
|
+
return postValidateTrustRun({ dataplaneUrl, datasourceKey, systemKey, authConfig, body, options });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
return await getLatestTrustRun({ dataplaneUrl, datasourceKey, systemKey, authConfig, options });
|
|
105
|
+
} catch (err) {
|
|
106
|
+
if (!isLatestNotFoundError(err)) throw err;
|
|
107
|
+
return postValidateTrustRun({ dataplaneUrl, datasourceKey, systemKey, authConfig, body, options });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
module.exports = {
|
|
112
|
+
shouldPreferLatestRead,
|
|
113
|
+
fetchTrustRunFromDataplane,
|
|
114
|
+
isLatestNotFoundError
|
|
115
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Map dataplane agent metadata validation API payloads to CLI trust runs.
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {string} trustDecision
|
|
11
|
+
* @returns {'ok'|'warn'|'fail'}
|
|
12
|
+
*/
|
|
13
|
+
function trustDecisionToRowStatus(trustDecision) {
|
|
14
|
+
const td = String(trustDecision || '').trim();
|
|
15
|
+
if (td === 'trusted') return 'ok';
|
|
16
|
+
if (td === 'usableWithWarnings') return 'warn';
|
|
17
|
+
return 'fail';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {Object} result - AgentMetadataValidationResult from dataplane
|
|
22
|
+
* @returns {string[]}
|
|
23
|
+
*/
|
|
24
|
+
function highLevelWarningsFromResult(result) {
|
|
25
|
+
if (!result || !Array.isArray(result.findings)) return [];
|
|
26
|
+
return result.findings
|
|
27
|
+
.filter(f => f && (f.severity === 'warning' || f.severity === 'error'))
|
|
28
|
+
.slice(0, 8)
|
|
29
|
+
.map(f => {
|
|
30
|
+
const code = f.code ? String(f.code) : 'FINDING';
|
|
31
|
+
const msg = f.message ? String(f.message) : '';
|
|
32
|
+
return msg ? `${code} — ${msg}` : code;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {Object} params
|
|
38
|
+
* @param {string} params.datasourceKey
|
|
39
|
+
* @param {string} params.systemKey
|
|
40
|
+
* @param {Object} params.runResponse - POST run response body
|
|
41
|
+
* @returns {Object} AgentTrustRun-shaped object for CLI display/exit
|
|
42
|
+
*/
|
|
43
|
+
function mapRunResponseToTrustRun({ datasourceKey, systemKey, runResponse }) {
|
|
44
|
+
const body = runResponse && typeof runResponse === 'object' ? runResponse : {};
|
|
45
|
+
const result = body.result && typeof body.result === 'object' ? body.result : {};
|
|
46
|
+
const trustDecision = result.trustDecision || 'pending';
|
|
47
|
+
return {
|
|
48
|
+
datasourceKey,
|
|
49
|
+
systemKey,
|
|
50
|
+
status: trustDecisionToRowStatus(trustDecision),
|
|
51
|
+
trustDecision,
|
|
52
|
+
validationStatus: result.status || 'pending',
|
|
53
|
+
confidence: typeof result.confidence === 'number' ? result.confidence : 0,
|
|
54
|
+
summary: result.summary || '',
|
|
55
|
+
validatedAt: result.validatedAt || '',
|
|
56
|
+
inputHash: result.inputHash || '',
|
|
57
|
+
contractVersion: result.contractVersion || '',
|
|
58
|
+
cacheHit: body.reused === true,
|
|
59
|
+
highLevelWarnings: highLevelWarningsFromResult(result),
|
|
60
|
+
findings: Array.isArray(result.findings) ? result.findings : [],
|
|
61
|
+
observedBusinessModel: result.observedBusinessModel || null,
|
|
62
|
+
runId: body.id || null
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @param {Object} params
|
|
68
|
+
* @param {string} params.datasourceKey
|
|
69
|
+
* @param {string} params.systemKey
|
|
70
|
+
* @param {Object} params.latestResult - GET /agent-validation body
|
|
71
|
+
* @returns {Object}
|
|
72
|
+
*/
|
|
73
|
+
function mapLatestResultToTrustRun({ datasourceKey, systemKey, latestResult }) {
|
|
74
|
+
const result = latestResult && typeof latestResult === 'object' ? latestResult : {};
|
|
75
|
+
const trustDecision = result.trustDecision || 'pending';
|
|
76
|
+
return {
|
|
77
|
+
datasourceKey,
|
|
78
|
+
systemKey,
|
|
79
|
+
status: trustDecisionToRowStatus(trustDecision),
|
|
80
|
+
trustDecision,
|
|
81
|
+
validationStatus: result.status || 'pending',
|
|
82
|
+
confidence: typeof result.confidence === 'number' ? result.confidence : 0,
|
|
83
|
+
summary: result.summary || '',
|
|
84
|
+
validatedAt: result.validatedAt || '',
|
|
85
|
+
inputHash: result.inputHash || '',
|
|
86
|
+
contractVersion: result.contractVersion || '',
|
|
87
|
+
cacheHit: true,
|
|
88
|
+
highLevelWarnings: highLevelWarningsFromResult(result),
|
|
89
|
+
findings: Array.isArray(result.findings) ? result.findings : [],
|
|
90
|
+
observedBusinessModel: result.observedBusinessModel || null,
|
|
91
|
+
runId: null,
|
|
92
|
+
readLatest: true
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
module.exports = {
|
|
97
|
+
trustDecisionToRowStatus,
|
|
98
|
+
highLevelWarningsFromResult,
|
|
99
|
+
mapRunResponseToTrustRun,
|
|
100
|
+
mapLatestResultToTrustRun
|
|
101
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Dev-only mock trust runs when AIFABRIX_AGENT_TRUST_MOCK=1 (plan 143).
|
|
3
|
+
* Not documented in user-facing CLI docs; for local CLI development without dataplane 404.5.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @returns {boolean}
|
|
10
|
+
*/
|
|
11
|
+
function isAgentTrustMockEnabled() {
|
|
12
|
+
return String(process.env.AIFABRIX_AGENT_TRUST_MOCK || '').trim() === '1';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {string} datasourceKey
|
|
17
|
+
* @param {string} systemKey
|
|
18
|
+
* @returns {Object}
|
|
19
|
+
*/
|
|
20
|
+
function buildMockTrustRun(datasourceKey, systemKey) {
|
|
21
|
+
return {
|
|
22
|
+
datasourceKey,
|
|
23
|
+
systemKey,
|
|
24
|
+
status: 'warn',
|
|
25
|
+
trustDecision: 'usableWithWarnings',
|
|
26
|
+
validationStatus: 'warning',
|
|
27
|
+
confidence: 0.72,
|
|
28
|
+
summary: 'Mock trust run (AIFABRIX_AGENT_TRUST_MOCK=1)',
|
|
29
|
+
validatedAt: new Date().toISOString(),
|
|
30
|
+
inputHash: 'mock-input-hash',
|
|
31
|
+
contractVersion: '1.0.0',
|
|
32
|
+
cacheHit: false,
|
|
33
|
+
highLevelWarnings: ['MOCK_TRUST — set AIFABRIX_AGENT_TRUST_MOCK=0 for live dataplane validation'],
|
|
34
|
+
findings: [],
|
|
35
|
+
observedBusinessModel: null,
|
|
36
|
+
runId: 'mock-run-id',
|
|
37
|
+
mock: true
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = {
|
|
42
|
+
isAgentTrustMockEnabled,
|
|
43
|
+
buildMockTrustRun
|
|
44
|
+
};
|