@aifabrix/builder 2.44.4 → 2.44.6
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 +1 -1
- package/.cursor/rules/project-rules.mdc +1 -1
- package/.npmrc.token +1 -1
- package/README.md +15 -23
- package/integration/hubspot-test/README.md +2 -0
- package/integration/hubspot-test/test.js +5 -3
- package/jest.projects.js +68 -17
- package/lib/api/controller-health.api.js +49 -0
- package/lib/api/dimension-values.api.js +82 -0
- package/lib/api/dimensions.api.js +114 -0
- package/lib/api/external-systems.api.js +1 -0
- package/lib/api/integration-clients.api.js +168 -0
- package/lib/api/types/dimension-values.types.js +28 -0
- package/lib/api/types/dimensions.types.js +31 -0
- package/lib/api/types/integration-clients.types.js +45 -0
- package/lib/api/types/wizard.types.js +2 -1
- package/lib/api/validation-runner.js +46 -25
- package/lib/app/deploy-config.js +11 -1
- package/lib/app/deploy-status-display.js +3 -3
- package/lib/app/deploy.js +36 -14
- package/lib/app/display.js +15 -11
- package/lib/app/push.js +46 -23
- package/lib/app/register.js +1 -1
- package/lib/app/restart-display.js +95 -0
- package/lib/app/rotate-secret.js +1 -1
- package/lib/app/run-container-start.js +12 -6
- package/lib/app/run-env-compose.js +30 -1
- package/lib/app/run-helpers.js +44 -12
- package/lib/app/run-reload-sync.js +148 -0
- package/lib/app/run-resolve-image.js +51 -1
- package/lib/app/run.js +99 -73
- package/lib/build/index.js +75 -45
- package/lib/cli/doctor-check.js +117 -0
- package/lib/cli/index.js +8 -2
- package/lib/cli/infra-guided.js +445 -0
- package/lib/cli/setup-app.help.js +1 -1
- package/lib/cli/setup-app.js +20 -2
- package/lib/cli/setup-app.test-commands.js +9 -5
- package/lib/cli/setup-auth.js +26 -0
- package/lib/cli/setup-dev-path-commands.js +50 -3
- package/lib/cli/setup-infra.js +138 -61
- package/lib/cli/setup-integration-client.js +182 -0
- package/lib/cli/setup-parameters.js +21 -2
- package/lib/cli/setup-platform.js +102 -0
- package/lib/cli/setup-secrets.js +18 -6
- package/lib/cli/setup-utility.js +97 -33
- package/lib/commands/datasource-capability-dimension-cli.js +128 -0
- package/lib/commands/datasource-capability-output.js +29 -0
- package/lib/commands/datasource-capability-relate-cli.js +140 -0
- package/lib/commands/datasource-capability.js +411 -0
- package/lib/commands/datasource-unified-test-cli.options.js +1 -1
- package/lib/commands/datasource.js +53 -13
- package/lib/commands/dev-down.js +3 -3
- package/lib/commands/dev-infra-gate.js +32 -0
- package/lib/commands/dev-init.js +13 -7
- package/lib/commands/dimension-value.js +179 -0
- package/lib/commands/dimension.js +330 -0
- package/lib/commands/integration-client.js +430 -0
- package/lib/commands/login-device.js +65 -30
- package/lib/commands/login.js +21 -10
- package/lib/commands/parameters-validate.js +78 -13
- package/lib/commands/repair-datasource-auto-rbac.js +166 -0
- package/lib/commands/repair-datasource-keys.js +10 -5
- package/lib/commands/repair-datasource.js +19 -7
- package/lib/commands/repair-env-template.js +4 -1
- package/lib/commands/repair-openapi-sync.js +172 -0
- package/lib/commands/repair-persist.js +102 -0
- package/lib/commands/repair-rbac-extract.js +27 -0
- package/lib/commands/repair-rbac-migrate.js +186 -0
- package/lib/commands/repair-rbac.js +225 -19
- package/lib/commands/repair-system-alignment.js +246 -0
- package/lib/commands/repair-system-permissions.js +168 -0
- package/lib/commands/repair.js +120 -354
- package/lib/commands/secure.js +1 -1
- package/lib/commands/setup-modes.js +455 -0
- package/lib/commands/setup-prompts.js +388 -0
- package/lib/commands/setup.js +149 -0
- package/lib/commands/teardown.js +228 -0
- package/lib/commands/test-e2e-external.js +4 -3
- package/lib/commands/up-common.js +97 -12
- package/lib/commands/up-dataplane.js +33 -11
- package/lib/commands/up-miso.js +7 -11
- package/lib/commands/upload.js +109 -23
- package/lib/commands/wizard-core-helpers.js +14 -11
- package/lib/commands/wizard-core.js +58 -15
- package/lib/commands/wizard-dataplane.js +2 -2
- package/lib/commands/wizard-entity-selection.js +72 -14
- package/lib/commands/wizard-headless.js +7 -3
- package/lib/commands/wizard-helpers.js +13 -1
- package/lib/commands/wizard.js +210 -61
- package/lib/constants/infra-compose-service-names.js +40 -0
- package/lib/core/env-reader.js +16 -3
- package/lib/core/secrets-admin-env.js +101 -0
- package/lib/core/secrets-ensure-infra.js +34 -1
- package/lib/core/secrets-ensure.js +88 -66
- package/lib/core/secrets-env-content.js +432 -0
- package/lib/core/secrets-env-write.js +27 -1
- package/lib/core/secrets-load.js +248 -0
- package/lib/core/secrets-names.js +32 -0
- package/lib/core/secrets.js +17 -757
- package/lib/datasource/capability/basic-exposure.js +76 -0
- package/lib/datasource/capability/capability-diff-slice.js +41 -0
- package/lib/datasource/capability/capability-key.js +34 -0
- package/lib/datasource/capability/capability-resolve.js +172 -0
- package/lib/datasource/capability/capability-storage-keys.js +22 -0
- package/lib/datasource/capability/copy-operations.js +348 -0
- package/lib/datasource/capability/copy-test-payload.js +139 -0
- package/lib/datasource/capability/create-operations.js +235 -0
- package/lib/datasource/capability/dimension-operations.js +151 -0
- package/lib/datasource/capability/dimension-validate.js +219 -0
- package/lib/datasource/capability/json-pointer.js +31 -0
- package/lib/datasource/capability/reference-rewrite.js +51 -0
- package/lib/datasource/capability/relate-operations.js +325 -0
- package/lib/datasource/capability/relate-validate.js +219 -0
- package/lib/datasource/capability/remove-operations.js +275 -0
- package/lib/datasource/capability/run-capability-copy.js +152 -0
- package/lib/datasource/capability/run-capability-diff.js +135 -0
- package/lib/datasource/capability/run-capability-dimension.js +291 -0
- package/lib/datasource/capability/run-capability-edit.js +377 -0
- package/lib/datasource/capability/run-capability-relate.js +193 -0
- package/lib/datasource/capability/run-capability-remove.js +105 -0
- package/lib/datasource/capability/templates/minimal-fetch.json +18 -0
- package/lib/datasource/capability/validate-capability-slice.js +35 -0
- package/lib/datasource/list.js +136 -23
- package/lib/datasource/log-viewer.js +2 -4
- package/lib/datasource/unified-validation-run.js +51 -16
- package/lib/datasource/validate.js +53 -1
- package/lib/deployment/deploy-poll-ui.js +60 -0
- package/lib/deployment/deployer-status.js +29 -3
- package/lib/deployment/deployer.js +48 -30
- package/lib/deployment/environment.js +7 -2
- package/lib/deployment/poll-interval.js +72 -0
- package/lib/deployment/push.js +11 -9
- package/lib/external-system/deploy.js +4 -1
- package/lib/external-system/download.js +61 -32
- package/lib/external-system/sync-deploy-manifest.js +33 -0
- package/lib/generator/wizard-prompts.js +7 -1
- package/lib/generator/wizard.js +34 -0
- package/lib/infrastructure/index.js +49 -19
- package/lib/infrastructure/orphan-infra-docker-teardown.js +177 -0
- package/lib/parameters/infra-kv-discovery.js +29 -4
- package/lib/parameters/infra-parameter-catalog.js +6 -3
- package/lib/parameters/infra-parameter-validate.js +67 -19
- package/lib/resolvers/datasource-resolver.js +53 -0
- package/lib/resolvers/dimension-file.js +52 -0
- package/lib/resolvers/manifest-resolver.js +133 -0
- package/lib/schema/external-datasource.schema.json +183 -53
- package/lib/schema/external-system.schema.json +23 -10
- package/lib/schema/infra.parameter.yaml +26 -11
- package/lib/schema/wizard-config.schema.json +2 -2
- package/lib/utils/aifabrix-config-dir-walk.js +40 -0
- package/lib/utils/aifabrix-runtime-config-dir.js +26 -3
- package/lib/utils/app-run-containers.js +2 -2
- package/lib/utils/bash-secret-env.js +59 -0
- package/lib/utils/cli-secrets-error-format.js +78 -0
- package/lib/utils/cli-test-layout-chalk.js +31 -9
- package/lib/utils/cli-utils.js +4 -36
- package/lib/utils/datasource-test-run-display.js +8 -0
- package/lib/utils/dev-hosts-helper.js +3 -2
- package/lib/utils/dev-init-ssh-merge.js +2 -1
- package/lib/utils/docker-build.js +17 -9
- package/lib/utils/docker-reload-mount.js +127 -0
- package/lib/utils/external-readme.js +117 -4
- package/lib/utils/external-system-local-test-tty.js +3 -2
- package/lib/utils/external-system-readiness-core.js +45 -12
- package/lib/utils/external-system-readiness-deploy-display.js +3 -3
- package/lib/utils/external-system-readiness-display-internals.js +33 -3
- package/lib/utils/external-system-readiness-display.js +10 -1
- package/lib/utils/file-upload.js +40 -3
- package/lib/utils/health-check-db-init.js +107 -0
- package/lib/utils/health-check-public-warn.js +69 -0
- package/lib/utils/health-check-url.js +19 -4
- package/lib/utils/health-check.js +135 -105
- package/lib/utils/help-builder.js +5 -1
- package/lib/utils/image-name.js +34 -7
- package/lib/utils/integration-file-backup.js +74 -0
- package/lib/utils/mutagen-install.js +30 -3
- package/lib/utils/paths.js +108 -25
- package/lib/utils/postgres-wipe.js +212 -0
- package/lib/utils/register-aifabrix-shell-env.js +15 -0
- package/lib/utils/remote-dev-auth.js +21 -5
- package/lib/utils/remote-docker-env.js +9 -1
- package/lib/utils/remote-secrets-loader.js +42 -3
- package/lib/utils/resolve-docker-image-ref.js +9 -3
- package/lib/utils/secrets-ancestor-paths.js +47 -0
- package/lib/utils/secrets-helpers.js +17 -10
- package/lib/utils/secrets-kv-refs.js +42 -0
- package/lib/utils/secrets-kv-scope.js +19 -2
- package/lib/utils/secrets-materialize-local.js +134 -0
- package/lib/utils/secrets-path.js +24 -10
- package/lib/utils/secrets-utils.js +2 -2
- package/lib/utils/system-builder-root.js +34 -0
- package/lib/utils/url-declarative-resolve-build.js +6 -1
- package/lib/utils/url-declarative-runtime-base-path.js +32 -0
- package/lib/utils/url-declarative-vdir-inactive-env.js +2 -1
- package/lib/utils/urls-local-registry.js +73 -20
- package/lib/utils/validation-poll-ui.js +81 -0
- package/lib/utils/validation-run-poll.js +29 -5
- package/lib/utils/with-muted-logger.js +53 -0
- package/package.json +1 -1
- package/templates/applications/dataplane/application.yaml +1 -1
- package/templates/applications/dataplane/rbac.yaml +10 -10
- package/templates/applications/keycloak/env.template +8 -6
- package/templates/applications/miso-controller/application.yaml +7 -0
- package/templates/applications/miso-controller/env.template +7 -7
- package/templates/applications/miso-controller/rbac.yaml +9 -9
- package/templates/external-system/README.md.hbs +89 -102
- package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +0 -1
- package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +0 -1
- package/.nyc_output/processinfo/index.json +0 -1
- package/lib/api/service-users.api.js +0 -150
- package/lib/api/types/service-users.types.js +0 -65
- package/lib/cli/setup-service-user.js +0 -187
- package/lib/commands/service-user.js +0 -429
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secrets loading cascade (user file, aifabrix-secrets file or remote API, builder YAML, defaults).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Split from secrets.js for module size limits
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const config = require('./config');
|
|
14
|
+
const { readYamlAtPath, applyCanonicalSecretsOverride } = require('../utils/secrets-canonical');
|
|
15
|
+
const { ensureSecureFilePermissions } = require('../utils/secure-file-permissions');
|
|
16
|
+
const {
|
|
17
|
+
resolveSecretsPath
|
|
18
|
+
} = require('../utils/secrets-path');
|
|
19
|
+
const {
|
|
20
|
+
loadUserSecrets,
|
|
21
|
+
loadPrimaryUserSecrets,
|
|
22
|
+
loadDefaultSecrets,
|
|
23
|
+
ensurePrimaryUserSecretsFileExists
|
|
24
|
+
} = require('../utils/secrets-utils');
|
|
25
|
+
const { decryptSecret, isEncrypted } = require('../utils/secrets-encryption');
|
|
26
|
+
const pathsUtil = require('../utils/paths');
|
|
27
|
+
const { collectAncestorAifabrixSecretsLocalYamlPaths } = require('../utils/secrets-ancestor-paths');
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Decrypts encrypted values in secrets object
|
|
31
|
+
*
|
|
32
|
+
* @async
|
|
33
|
+
* @param {Object} secrets - Secrets object with potentially encrypted values
|
|
34
|
+
* @returns {Promise<Object>} Secrets object with decrypted values
|
|
35
|
+
*/
|
|
36
|
+
async function decryptSecretsObject(secrets) {
|
|
37
|
+
if (!secrets || typeof secrets !== 'object') {
|
|
38
|
+
return secrets;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const encryptionKey = await config.getSecretsEncryptionKey();
|
|
42
|
+
if (!encryptionKey) {
|
|
43
|
+
const hasEncrypted = Object.values(secrets).some((value) => isEncrypted(value));
|
|
44
|
+
if (hasEncrypted) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
'Encrypted secrets found but no encryption key configured. Run "aifabrix secure --secrets-encryption <key>" to set encryption key.'
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
return secrets;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const decryptedSecrets = {};
|
|
53
|
+
for (const [key, value] of Object.entries(secrets)) {
|
|
54
|
+
if (isEncrypted(value)) {
|
|
55
|
+
try {
|
|
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
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return decryptedSecrets;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Merges config file secrets into user secrets (user wins). Returns null if path missing or config empty.
|
|
70
|
+
*/
|
|
71
|
+
function mergeUserWithConfigFile(userSecrets, resolvedConfigPath) {
|
|
72
|
+
if (!fs.existsSync(resolvedConfigPath)) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
ensureSecureFilePermissions(resolvedConfigPath);
|
|
76
|
+
let configSecrets;
|
|
77
|
+
try {
|
|
78
|
+
configSecrets = readYamlAtPath(resolvedConfigPath);
|
|
79
|
+
} catch (loadError) {
|
|
80
|
+
throw new Error(`Failed to load secrets file ${resolvedConfigPath}: ${loadError.message}`);
|
|
81
|
+
}
|
|
82
|
+
if (!configSecrets || typeof configSecrets !== 'object') {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
const merged = { ...userSecrets };
|
|
86
|
+
for (const key of Object.keys(configSecrets)) {
|
|
87
|
+
if (!(key in merged) || merged[key] === undefined || merged[key] === null || merged[key] === '') {
|
|
88
|
+
merged[key] = configSecrets[key];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return merged;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function createMergeHelpers(userSecrets) {
|
|
95
|
+
const hasKeys = (obj) => obj && Object.keys(obj).length > 0;
|
|
96
|
+
return {
|
|
97
|
+
hasKeys,
|
|
98
|
+
userOrNull: () => (hasKeys(userSecrets) ? userSecrets : null)
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async function mergeFromConfiguredSecretsPath(configSecretsPath, userSecrets, helpers) {
|
|
103
|
+
const remoteDevAuth = require('../utils/remote-dev-auth');
|
|
104
|
+
const effectiveShared = await remoteDevAuth.resolveSharedSecretsEndpoint(configSecretsPath);
|
|
105
|
+
|
|
106
|
+
if (remoteDevAuth.isRemoteSecretsUrl(effectiveShared)) {
|
|
107
|
+
const { loadRemoteSharedSecrets, mergeUserWithRemoteSecrets } = require('../utils/remote-secrets-loader');
|
|
108
|
+
const remoteSecrets = await loadRemoteSharedSecrets();
|
|
109
|
+
const merged = mergeUserWithRemoteSecrets(userSecrets, remoteSecrets);
|
|
110
|
+
return helpers.hasKeys(merged) ? merged : helpers.userOrNull();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const resolvedConfigPath = path.isAbsolute(configSecretsPath)
|
|
114
|
+
? configSecretsPath
|
|
115
|
+
: path.resolve(process.cwd(), configSecretsPath);
|
|
116
|
+
const merged = mergeUserWithConfigFile(userSecrets, resolvedConfigPath);
|
|
117
|
+
return merged !== null ? merged : helpers.userOrNull();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async function loadMergedConfigAndUserSecrets() {
|
|
121
|
+
const userSecrets = loadPrimaryUserSecrets();
|
|
122
|
+
const helpers = createMergeHelpers(userSecrets);
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
const configSecretsPath = await config.getSecretsPath();
|
|
126
|
+
if (!configSecretsPath) {
|
|
127
|
+
return helpers.userOrNull();
|
|
128
|
+
}
|
|
129
|
+
return await mergeFromConfiguredSecretsPath(configSecretsPath, userSecrets, helpers);
|
|
130
|
+
} catch (error) {
|
|
131
|
+
if (error.message && error.message.startsWith('Failed to load secrets file')) {
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
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 : {};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async function loadSecretsWithFallbacks() {
|
|
204
|
+
let merged = await loadMergedConfigAndUserSecrets();
|
|
205
|
+
if (!merged || Object.keys(merged).length === 0) {
|
|
206
|
+
merged = loadPrimaryUserSecrets();
|
|
207
|
+
if (Object.keys(merged).length === 0) {
|
|
208
|
+
merged = loadUserSecrets();
|
|
209
|
+
}
|
|
210
|
+
merged = await applyCanonicalSecretsOverride(merged);
|
|
211
|
+
}
|
|
212
|
+
merged = mergeAncestorAifabrixSecretsLocalFiles(merged);
|
|
213
|
+
merged = mergeBuilderSecretsLocalFiles(merged);
|
|
214
|
+
if (Object.keys(merged).length === 0) {
|
|
215
|
+
merged = loadDefaultSecrets();
|
|
216
|
+
}
|
|
217
|
+
return merged;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* @param {string} [secretsPath]
|
|
222
|
+
* @param {string} [_appName]
|
|
223
|
+
*/
|
|
224
|
+
async function loadSecrets(secretsPath, _appName) {
|
|
225
|
+
if (secretsPath) {
|
|
226
|
+
const resolvedPath = resolveSecretsPath(secretsPath);
|
|
227
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
228
|
+
throw new Error(`Secrets file not found: ${resolvedPath}`);
|
|
229
|
+
}
|
|
230
|
+
ensureSecureFilePermissions(resolvedPath);
|
|
231
|
+
const explicitSecrets = readYamlAtPath(resolvedPath);
|
|
232
|
+
if (!explicitSecrets || typeof explicitSecrets !== 'object') {
|
|
233
|
+
throw new Error(`Invalid secrets file format: ${resolvedPath}`);
|
|
234
|
+
}
|
|
235
|
+
return await decryptSecretsObject(explicitSecrets);
|
|
236
|
+
}
|
|
237
|
+
let mergedSecrets = await loadSecretsWithFallbacks();
|
|
238
|
+
if (!mergedSecrets || Object.keys(mergedSecrets).length === 0) {
|
|
239
|
+
ensurePrimaryUserSecretsFileExists();
|
|
240
|
+
mergedSecrets = await loadSecretsWithFallbacks();
|
|
241
|
+
}
|
|
242
|
+
return await decryptSecretsObject(mergedSecrets || {});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
module.exports = {
|
|
246
|
+
loadSecrets,
|
|
247
|
+
decryptSecretsObject
|
|
248
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical secret name normalization for env keys.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Split from secrets.js for module size limits
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generates a canonical secret name from an environment variable key.
|
|
13
|
+
* Converts to lowercase, replaces non-alphanumeric characters with hyphens,
|
|
14
|
+
* collapses consecutive hyphens, and trims leading/trailing hyphens.
|
|
15
|
+
*
|
|
16
|
+
* @param {string} key - Environment variable key (e.g., JWT_SECRET)
|
|
17
|
+
* @returns {string} Canonical secret name (e.g., jwt-secret)
|
|
18
|
+
*/
|
|
19
|
+
function getCanonicalSecretName(key) {
|
|
20
|
+
if (!key || typeof key !== 'string') {
|
|
21
|
+
return '';
|
|
22
|
+
}
|
|
23
|
+
const withHyphens = key.replace(/([a-z0-9])([A-Z])/g, '$1-$2');
|
|
24
|
+
const lower = withHyphens.toLowerCase();
|
|
25
|
+
const hyphenated = lower.replace(/[^a-z0-9]/g, '-');
|
|
26
|
+
const collapsed = hyphenated.replace(/-+/g, '-');
|
|
27
|
+
return collapsed.replace(/^-+|-+$/g, '');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = {
|
|
31
|
+
getCanonicalSecretName
|
|
32
|
+
};
|