@aifabrix/builder 2.45.5 → 2.47.0
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 +2 -0
- package/.cursor/rules/cli-product-neutral.mdc +43 -0
- package/.cursor/rules/project-rules.mdc +1 -0
- package/.npmrc.token +1 -0
- package/.temp/jest-protection-convert/run-IFN2nv/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-IvmKLO/.protection/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-convert/run-SdvblF/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-b51TsW/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-fiLmb1/.protection/hubspot-companies.json +1 -0
- package/.temp/jest-protection-convert/run-qYGHMU/.protection/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-Mq5re8/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-f3u4YL/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-iQtd1O/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-mdmz5M/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-qbKYxQ/hubspot-companies.yaml +17 -0
- package/.temp/jest-protection-fixtures/hubspot-yzlJy6/hubspot-companies.yaml +17 -0
- package/.temp/validation/summary.txt +5 -0
- package/README.md +43 -17
- 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/jest.config.default.js +2 -1
- package/jest.config.isolated.js +2 -1
- package/jest.global-live-fabrix-hooks.js +36 -0
- package/jest.isolated-projects.js +146 -0
- package/jest.projects.js +65 -136
- package/lib/api/api-response-errors.js +124 -0
- package/lib/api/dataplane-health.api.js +19 -7
- package/lib/api/governance-scenario-pack.api.js +159 -0
- package/lib/api/index.js +43 -3
- package/lib/api/lifecycle.api.js +98 -0
- package/lib/api/pipeline.api.js +3 -1
- package/lib/api/records-bulk.api.js +14 -1
- package/lib/api/resource-types.api.js +107 -0
- package/lib/api/runtime-configuration.api.js +72 -0
- package/lib/api/types/resource-types.types.js +45 -0
- package/lib/api/user-groups.api.js +9 -9
- package/lib/api/users.api.js +8 -8
- package/lib/api/validation-runner.js +3 -1
- package/lib/api/wizard.api.js +10 -2
- package/lib/app/deploy-config.js +4 -1
- package/lib/app/down.js +78 -27
- package/lib/app/index.js +2 -2
- package/lib/app/push.js +4 -5
- package/lib/app/register.js +7 -4
- package/lib/app/run-env-compose.js +84 -30
- package/lib/app/run-resolve-image.js +2 -1
- package/lib/app/run-stop-containers.js +113 -0
- package/lib/app/run.js +1 -31
- package/lib/app/show-display.js +35 -0
- package/lib/app/show.js +32 -1
- package/lib/build/index.js +22 -5
- package/lib/build/miso-controller-npm-sdk-guard.js +25 -0
- package/lib/certification/sync-system-certification.js +13 -6
- package/lib/channels/add-channel.js +348 -0
- package/lib/channels/channel-artifact-generator.js +141 -0
- package/lib/channels/channel-audit.js +101 -0
- package/lib/channels/channel-auth-context.js +37 -0
- package/lib/channels/channel-credential.js +200 -0
- package/lib/channels/channel-display-name.js +64 -0
- package/lib/channels/channel-external-system.js +106 -0
- package/lib/channels/channel-integration-generator.js +274 -0
- package/lib/channels/channel-probe.js +89 -0
- package/lib/channels/channel-runtime-resolver.js +152 -0
- package/lib/channels/channel-status-display.js +141 -0
- package/lib/channels/channel-targets.js +115 -0
- package/lib/cli/index.js +20 -4
- package/lib/cli/infra-guided-auth.js +109 -0
- package/lib/cli/infra-guided.js +84 -81
- package/lib/cli/setup-app.help.js +0 -31
- package/lib/cli/setup-app.js +82 -5
- package/lib/cli/setup-app.test-commands.js +5 -57
- package/lib/cli/setup-auth.js +25 -0
- package/lib/cli/setup-certification-commands.js +147 -0
- package/lib/cli/setup-certification.help.js +141 -0
- package/lib/cli/setup-environment.js +19 -2
- package/lib/cli/setup-external-system-help.js +62 -0
- package/lib/cli/setup-external-system.js +25 -3
- package/lib/cli/setup-infra-up-dataplane-action.js +2 -2
- package/lib/cli/setup-infra-up-platform-action.js +2 -1
- package/lib/cli/setup-infra.js +9 -1
- package/lib/cli/setup-platform.js +6 -1
- package/lib/cli/setup-secrets.js +33 -1
- package/lib/cli/setup-utility-help-after.js +25 -2
- package/lib/cli/setup-utility-repair.js +198 -0
- package/lib/cli/setup-utility-resolve.js +44 -5
- package/lib/cli/setup-utility-validate.js +197 -0
- package/lib/cli/setup-utility.js +4 -239
- package/lib/commands/app-logs.js +54 -26
- package/lib/commands/app.js +41 -0
- package/lib/commands/auth-status-client-tokens.js +214 -0
- package/lib/commands/auth-status-dataplane-version.js +142 -68
- package/lib/commands/auth-status.js +43 -54
- package/lib/commands/channel.js +58 -0
- package/lib/commands/datasource-test-trust-cli.js +27 -23
- package/lib/commands/datasource-unified-test-cli.js +6 -3
- package/lib/commands/datasource-unified-test-cli.options.js +5 -1
- package/lib/commands/datasource.js +8 -8
- package/lib/commands/dev-show-display.js +8 -1
- package/lib/commands/governance-cli-shared.js +94 -0
- package/lib/commands/governance-command-action.js +132 -0
- package/lib/commands/governance-download-external.js +34 -0
- package/lib/commands/governance-generate-external.js +71 -0
- package/lib/commands/governance-upload-external.js +36 -0
- package/lib/commands/governance-verify-external.js +64 -0
- package/lib/commands/governance.js +144 -0
- package/lib/commands/identity-apply-sync.js +49 -8
- package/lib/commands/identity-group-cli.js +66 -26
- package/lib/commands/identity-membership-role-cache.js +58 -37
- package/lib/commands/identity-shared.js +22 -1
- package/lib/commands/identity-user-cli.js +80 -34
- package/lib/commands/lifecycle-command-action.js +123 -0
- package/lib/commands/lifecycle-external.js +268 -0
- package/lib/commands/login.js +11 -2
- package/lib/commands/repair-auth-apply.js +153 -0
- package/lib/commands/repair-auth-config.js +8 -13
- package/lib/commands/repair-changed-files.js +41 -0
- package/lib/commands/repair-datasource-com-v2.js +15 -0
- package/lib/commands/repair-datasource-keys.js +4 -1
- package/lib/commands/repair-datasource-run.js +59 -0
- package/lib/commands/repair-datasource-service-contract.js +206 -0
- package/lib/commands/repair-datasource-test-payload.js +259 -0
- package/lib/commands/repair-datasource.js +49 -64
- package/lib/commands/repair-env-template.js +76 -25
- package/lib/commands/repair-external-run.js +216 -0
- package/lib/commands/repair-openapi-sync.js +49 -4
- package/lib/commands/repair-persist.js +4 -0
- package/lib/commands/repair-rbac.js +52 -1
- package/lib/commands/repair-steps.js +160 -0
- package/lib/commands/repair-system-alignment.js +7 -4
- package/lib/commands/repair.js +29 -296
- package/lib/commands/resource-type.js +371 -0
- package/lib/commands/secrets-get.js +184 -0
- package/lib/commands/secrets-remove-all.js +3 -1
- package/lib/commands/setup-image-refresh.js +146 -0
- package/lib/commands/setup-modes.js +158 -162
- package/lib/commands/setup-platform-auth.js +76 -0
- package/lib/commands/setup-prompts-admin.js +244 -0
- package/lib/commands/setup-prompts-platform-mode.js +70 -0
- package/lib/commands/setup-prompts-validators.js +36 -0
- package/lib/commands/setup-prompts.js +24 -76
- package/lib/commands/setup-run-context.js +45 -0
- package/lib/commands/setup-spinners.js +39 -0
- package/lib/commands/setup.js +27 -5
- package/lib/commands/teardown.js +39 -0
- package/lib/commands/test-e2e-external.js +24 -8
- package/lib/commands/test-governance-external.js +3 -24
- package/lib/commands/test-trust-external.js +48 -100
- package/lib/commands/up-common.js +57 -13
- package/lib/commands/up-dataplane.js +56 -15
- package/lib/commands/upload-publish-context.js +75 -0
- package/lib/commands/upload-sidecar-followups.js +89 -0
- package/lib/commands/upload.js +113 -110
- package/lib/commands/verify-governance-combined-external.js +61 -0
- package/lib/commands/verify-governance-command-action.js +64 -0
- package/lib/commands/verify-governance-db.js +102 -0
- package/lib/commands/verify-governance-external.js +77 -0
- package/lib/commands/verify-governance-result-builders.js +71 -0
- package/lib/commands/verify-operations-command-action.js +68 -0
- package/lib/commands/verify-operations-external.js +268 -0
- package/lib/commands/verify-operations-persist.js +75 -0
- package/lib/commands/verify-operations-step-plan.js +68 -0
- package/lib/commands/verify-operations-steps.js +111 -0
- package/lib/commands/verify-trust-command-action.js +73 -0
- package/lib/commands/verify-trust-external.js +59 -0
- package/lib/commands/wizard-config-normalizer.js +43 -23
- package/lib/commands/wizard-core.js +2 -0
- package/lib/core/admin-password-generator.js +38 -0
- package/lib/core/admin-secrets-bundle.js +111 -0
- package/lib/core/admin-secrets-env-overlay.js +62 -0
- package/lib/core/admin-secrets.js +32 -4
- package/lib/core/config-attach-extensions.js +3 -0
- package/lib/core/config-platform-controller.js +44 -0
- package/lib/core/config-setup-installation-profile.js +42 -0
- package/lib/core/config-setup-platform-mode.js +46 -0
- package/lib/core/config.js +46 -36
- package/lib/core/secrets-admin-env.js +6 -2
- package/lib/core/secrets-ensure.js +4 -0
- package/lib/core/secrets-env-content.js +54 -48
- package/lib/core/secrets-env-write.js +10 -1
- package/lib/core/secrets-infra-placeholder-sync.js +2 -0
- package/lib/core/setup-installation-profile.js +43 -0
- package/lib/core/setup-platform-mode.js +90 -0
- package/lib/datasource/agent-trust-debug-log.js +1 -1
- package/lib/datasource/agent-trust-run.js +5 -3
- package/lib/datasource/audit-evidence-extract-debug.js +30 -18
- package/lib/datasource/audit-evidence-extract.js +7 -4
- package/lib/datasource/audit-evidence-verify-matrix.js +54 -26
- package/lib/datasource/bulk-loader-run-batches.js +15 -3
- package/lib/datasource/capability/capability-diff-slice.js +2 -2
- package/lib/datasource/capability/capability-manifest.js +254 -0
- package/lib/datasource/capability/capability-resolve.js +3 -4
- package/lib/datasource/capability/copy-operations.js +5 -3
- package/lib/datasource/capability/remove-operations.js +2 -1
- package/lib/datasource/capability/run-capability-copy.js +32 -4
- package/lib/datasource/capability/run-capability-diff.js +3 -3
- package/lib/datasource/capability/run-capability-dimension.js +2 -4
- package/lib/datasource/capability/run-capability-edit.js +4 -7
- package/lib/datasource/capability/run-capability-relate.js +2 -4
- package/lib/datasource/capability/run-capability-remove.js +2 -4
- package/lib/datasource/capability/validate-capability-slice.js +2 -1
- package/lib/datasource/datasource-identifier.js +2 -1
- package/lib/datasource/datasource-load-export-context.js +3 -0
- package/lib/datasource/datasource-validate-display.js +1 -1
- package/lib/datasource/field-reference-validator.js +24 -3
- package/lib/datasource/log-cleaner.js +2 -2
- package/lib/datasource/log-viewer.js +8 -8
- package/lib/datasource/orphan-profiles-validator.js +98 -0
- package/lib/datasource/test-e2e.js +4 -1
- package/lib/datasource/unified-validation-run-body.js +3 -1
- package/lib/datasource/unified-validation-run.js +5 -2
- package/lib/datasource/validate.js +41 -23
- package/lib/deployment/environment-poll-status.js +138 -0
- package/lib/deployment/environment.js +42 -34
- package/lib/external-system/download-helpers.js +87 -0
- package/lib/external-system/download.js +78 -138
- package/lib/external-system/generator.js +1 -55
- package/lib/external-system/integration-auth-context.js +45 -0
- package/lib/external-system/test-auth.js +12 -5
- package/lib/external-system/test.js +16 -21
- package/lib/generator/builders.js +11 -1
- package/lib/generator/external-controller-manifest.js +18 -0
- package/lib/generator/split.js +3 -1
- package/lib/generator/wizard.js +1 -28
- package/lib/governance/governance-cli-errors.js +96 -0
- package/lib/governance/governance-download-display.js +38 -0
- package/lib/governance/governance-run-display.js +215 -25
- package/lib/identity/fk-reference.js +65 -0
- package/lib/identity/identity-apply-core.js +13 -58
- package/lib/identity/identity-apply-phases.js +5 -1
- package/lib/identity/identity-display.js +243 -0
- package/lib/identity/identity-response-helpers.js +52 -0
- package/lib/identity/identity-sync-errors.js +62 -0
- package/lib/identity/resolve-user-id.js +129 -0
- package/lib/identity/username-default.js +31 -0
- package/lib/infrastructure/admin-secrets-apply.js +84 -0
- package/lib/infrastructure/admin-secrets-ensure.js +130 -0
- package/lib/infrastructure/admin-secrets-resolve.js +95 -0
- package/lib/infrastructure/admin-secrets-sync.js +91 -0
- package/lib/infrastructure/helpers.js +23 -129
- package/lib/infrastructure/index.js +5 -6
- package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
- package/lib/lifecycle/certification-progress.js +231 -0
- package/lib/lifecycle/dataplane-ui-url.js +145 -0
- package/lib/lifecycle/exit-codes.js +24 -0
- package/lib/lifecycle/json-envelope.js +25 -0
- package/lib/lifecycle/lifecycle-governance-options.js +51 -0
- package/lib/lifecycle/logger-quiet.js +29 -0
- package/lib/lifecycle/open-api-published.js +59 -0
- package/lib/lifecycle/operations-readiness-metrics.js +101 -0
- package/lib/lifecycle/product-model.js +196 -0
- package/lib/lifecycle/report-display-trust.js +70 -0
- package/lib/lifecycle/report-display.js +472 -0
- package/lib/lifecycle/scenario-upload.js +191 -0
- package/lib/lifecycle/verify-step-progress.js +87 -0
- package/lib/parameters/infra-kv-discovery.js +27 -2
- package/lib/protection/auth-context.js +10 -4
- package/lib/resolvers/datasource-resolver.js +2 -3
- package/lib/resolvers/resource-type-file.js +159 -0
- package/lib/schema/application-schema.json +17 -1
- package/lib/schema/datasource-test-run.schema.json +89 -6
- package/lib/schema/deployment-rules.yaml +2 -1
- package/lib/schema/external-datasource.schema.json +2947 -2619
- package/lib/schema/external-system.schema.json +1418 -761
- package/lib/schema/infra.parameter.yaml +45 -0
- package/lib/schema/type/credential-field-registry.json +103 -97
- package/lib/schema/type/document-storage.json +9 -5
- package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
- package/lib/utils/api.js +55 -31
- package/lib/utils/app-relative-path-env.js +112 -0
- package/lib/utils/app-run-containers.js +25 -2
- package/lib/utils/authentication-shape.js +224 -0
- package/lib/utils/build-copy.js +36 -5
- package/lib/utils/build-resolve-image.js +66 -12
- package/lib/utils/celery-companion-apps.js +53 -0
- package/lib/utils/cli-secrets-error-format.js +83 -21
- package/lib/utils/cli-utils.js +20 -4
- package/lib/utils/compose-celery-worker.js +23 -0
- package/lib/utils/compose-generate-docker-compose.js +13 -1
- package/lib/utils/compose-traefik-ingress-base.js +16 -1
- package/lib/utils/config-secrets-path.js +46 -0
- package/lib/utils/configuration-env-resolver.js +36 -0
- package/lib/utils/controller-url.js +88 -1
- package/lib/utils/credential-secrets-env-kv.js +216 -0
- package/lib/utils/credential-secrets-env.js +175 -257
- package/lib/utils/dataplane-resolver.js +18 -2
- package/lib/utils/declarative-url-ports.js +27 -4
- package/lib/utils/deployment-auth-mode.js +41 -0
- package/lib/utils/developer-volume-id.js +33 -0
- package/lib/utils/docker-build.js +1 -4
- package/lib/utils/env-copy.js +14 -9
- package/lib/utils/env-kv-orphan-lines.js +43 -0
- package/lib/utils/error-formatters/network-errors.js +13 -4
- package/lib/utils/external-env-template.js +11 -3
- package/lib/utils/external-system-readiness-core.js +10 -0
- package/lib/utils/external-system-readiness-display.js +80 -23
- package/lib/utils/external-system-validators.js +8 -2
- package/lib/utils/health-check.js +4 -1
- package/lib/utils/help-builder.js +13 -8
- package/lib/utils/keycloak-realm-ready.js +101 -0
- package/lib/utils/load-cip-capacity-display-config.js +61 -15
- package/lib/utils/manifest-source-emit.js +2 -0
- package/lib/utils/paths.js +25 -0
- package/lib/utils/pipeline-upload-auth-retry.js +82 -0
- package/lib/utils/platform-controller-url.js +157 -0
- package/lib/utils/platform-kv-ref.js +57 -0
- package/lib/utils/postgres-platform-bootstrap.js +199 -0
- package/lib/utils/postgres-wipe.js +9 -2
- package/lib/utils/resolve-env-mode.js +47 -0
- package/lib/utils/runtime-configuration-download.js +189 -0
- package/lib/utils/runtime-configuration-values.js +119 -0
- package/lib/utils/schema-loader.js +19 -4
- package/lib/utils/secrets-generator.js +31 -25
- package/lib/utils/secrets-missing-error.js +164 -0
- package/lib/utils/service-url-label.js +81 -0
- package/lib/utils/setup-quiet-output.js +25 -0
- package/lib/utils/template-helpers.js +15 -0
- package/lib/utils/token-manager-client-credentials.js +201 -0
- package/lib/utils/token-manager-messages.js +8 -0
- package/lib/utils/token-manager-refresh.js +12 -2
- package/lib/utils/token-manager.js +86 -105
- package/lib/utils/upload-pipeline-ui.js +12 -5
- package/lib/utils/upload-sync-options.js +42 -0
- package/lib/utils/url-declarative-public-base.js +21 -3
- package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
- package/lib/utils/validation-poll-ui.js +8 -0
- package/lib/utils/validation-run-stage.js +45 -0
- package/lib/utils/worker-sidecars.js +142 -0
- package/lib/validation/external-manifest-validator.js +2 -0
- package/lib/validation/runtime-configuration-rules.js +98 -0
- package/lib/validation/validate-display-dimensions.js +154 -0
- package/lib/validation/validate-display-sections.js +276 -0
- package/lib/validation/validate-display-steps.js +67 -0
- package/lib/validation/validate-display.js +24 -402
- package/package.json +1 -1
- package/templates/applications/dataplane/application.yaml +7 -1
- package/templates/applications/dataplane/env.template +50 -14
- package/templates/applications/dataplane/rbac.yaml +108 -1
- package/templates/applications/miso-controller/application.yaml +2 -2
- package/templates/applications/miso-controller/env.template +53 -122
- package/templates/applications/miso-controller/rbac.yaml +28 -13
- package/templates/channels/chatgpt/install.template.md.hbs +49 -0
- package/templates/channels/chatgpt/manifest.template.json.hbs +9 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +49 -0
- package/templates/channels/microsoft-copilot/manifest.template.json.hbs +8 -0
- package/templates/channels/slack/install.template.md.hbs +49 -0
- package/templates/channels/slack/manifest.template.json.hbs +66 -0
- package/templates/channels/teams-bot/install.template.md.hbs +49 -0
- package/templates/channels/teams-bot/manifest.template.json.hbs +13 -0
- package/templates/channels/web-embed/install.template.md.hbs +49 -0
- package/templates/channels/web-embed/manifest.template.json.hbs +8 -0
- package/templates/external-system/README.md.hbs +74 -17
- package/templates/python/docker-compose.hbs +75 -18
- package/templates/typescript/docker-compose.hbs +70 -17
- package/lib/commands/test-governance-command-action.js +0 -55
- package/lib/commands/test-trust-command-action.js +0 -118
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Collect KV_* env vars as secret store items and push to dataplane.
|
|
3
|
-
* Reads integration .env, resolves kv:// in values, scans payload for kv:// refs,
|
|
4
|
-
* and pushes plain values to POST /api/v1/credential/secret.
|
|
5
3
|
*
|
|
6
4
|
* @fileoverview Credential secrets push from .env and payload (Dataplane)
|
|
7
5
|
* @author AI Fabrix Team
|
|
@@ -11,305 +9,245 @@
|
|
|
11
9
|
const fs = require('fs');
|
|
12
10
|
const { loadSecrets } = require('../core/secrets');
|
|
13
11
|
const { storeCredentialSecrets } = require('../api/credential.api');
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
const {
|
|
13
|
+
collectKvEnvVarsAsSecretItems,
|
|
14
|
+
collectKvRefsFromPayload,
|
|
15
|
+
getKvPathSegmentForSecurityKey,
|
|
16
|
+
isNonEmptySecretValue,
|
|
17
|
+
isValidKvPath,
|
|
18
|
+
kvEnvKeyToPath,
|
|
19
|
+
resolveKvValue,
|
|
20
|
+
securityKeyToVar,
|
|
21
|
+
systemKeyToKvPrefix
|
|
22
|
+
} = require('./credential-secrets-env-kv');
|
|
17
23
|
|
|
18
24
|
/**
|
|
19
|
-
*
|
|
20
|
-
* @param {string}
|
|
21
|
-
* @returns {string}
|
|
25
|
+
* Parses .env-style content into key-value map (first = separates key and value).
|
|
26
|
+
* @param {string} content - Raw .env content
|
|
27
|
+
* @returns {Object.<string, string>}
|
|
22
28
|
*/
|
|
23
|
-
function
|
|
24
|
-
if (!
|
|
25
|
-
|
|
29
|
+
function parseEnvToMap(content) {
|
|
30
|
+
if (!content || typeof content !== 'string') return {};
|
|
31
|
+
const map = {};
|
|
32
|
+
const lines = content.split(/\r?\n/);
|
|
33
|
+
for (const line of lines) {
|
|
34
|
+
const trimmed = line.trim();
|
|
35
|
+
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
36
|
+
const eq = trimmed.indexOf('=');
|
|
37
|
+
if (eq > 0) {
|
|
38
|
+
const key = trimmed.substring(0, eq).trim();
|
|
39
|
+
const value = trimmed.substring(eq + 1);
|
|
40
|
+
map[key] = value;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return map;
|
|
26
44
|
}
|
|
27
45
|
|
|
28
46
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* @param {string}
|
|
32
|
-
* @
|
|
47
|
+
* @param {string} envFilePath
|
|
48
|
+
* @param {Object} secrets
|
|
49
|
+
* @param {Map<string, string>} itemsByKey
|
|
50
|
+
* @param {string} [systemKey]
|
|
33
51
|
*/
|
|
34
|
-
function
|
|
35
|
-
if (!
|
|
36
|
-
|
|
52
|
+
function buildItemsFromEnv(envFilePath, secrets, itemsByKey, systemKey) {
|
|
53
|
+
if (!envFilePath || typeof envFilePath !== 'string' || !fs.existsSync(envFilePath)) return;
|
|
54
|
+
try {
|
|
55
|
+
const content = fs.readFileSync(envFilePath, 'utf8');
|
|
56
|
+
const envMap = parseEnvToMap(content);
|
|
57
|
+
const fromEnv = collectKvEnvVarsAsSecretItems(envMap, systemKey);
|
|
58
|
+
for (const { key, value } of fromEnv) {
|
|
59
|
+
const resolved = resolveKvValue(secrets, value);
|
|
60
|
+
if (
|
|
61
|
+
isNonEmptySecretValue(resolved) &&
|
|
62
|
+
isValidKvPath(key) &&
|
|
63
|
+
String(resolved).trim() !== key.trim()
|
|
64
|
+
) {
|
|
65
|
+
itemsByKey.set(key, resolved);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
} catch {
|
|
69
|
+
// Best-effort: continue without .env items
|
|
70
|
+
}
|
|
37
71
|
}
|
|
38
72
|
|
|
39
|
-
/** Known single-segment variable suffixes (uppercase) for inferring var vs namespace in env keys */
|
|
40
|
-
const VAR_SUFFIXES = new Set(['ID', 'SECRET', 'KEY', 'TOKEN', 'URL', 'USERNAME', 'PASSWORD']);
|
|
41
|
-
|
|
42
73
|
/**
|
|
43
|
-
*
|
|
44
|
-
* @param {
|
|
45
|
-
* @
|
|
74
|
+
* @param {Object} payload
|
|
75
|
+
* @param {Object} secrets
|
|
76
|
+
* @param {Map<string, string>} itemsByKey
|
|
46
77
|
*/
|
|
47
|
-
function
|
|
48
|
-
if (!
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (
|
|
56
|
-
|
|
78
|
+
function buildItemsFromPayload(payload, secrets, itemsByKey) {
|
|
79
|
+
if (!payload || typeof payload !== 'object') return;
|
|
80
|
+
const refs = collectKvRefsFromPayload(payload);
|
|
81
|
+
const existingKeys = new Set(itemsByKey.keys());
|
|
82
|
+
for (const ref of refs) {
|
|
83
|
+
if (existingKeys.has(ref)) continue;
|
|
84
|
+
const pathKey = ref.replace(/^kv:\/\//, '');
|
|
85
|
+
const resolved = secrets[pathKey];
|
|
86
|
+
if (isNonEmptySecretValue(resolved) && isValidKvPath(ref)) {
|
|
87
|
+
itemsByKey.set(ref, typeof resolved === 'string' ? resolved : String(resolved));
|
|
88
|
+
}
|
|
57
89
|
}
|
|
58
|
-
return varSegments.map((seg, i) => {
|
|
59
|
-
const lower = seg.toLowerCase();
|
|
60
|
-
return i === 0 ? lower : lower.charAt(0).toUpperCase() + lower.slice(1);
|
|
61
|
-
}).join('');
|
|
62
90
|
}
|
|
63
91
|
|
|
64
92
|
/**
|
|
65
|
-
*
|
|
66
|
-
* @param {
|
|
67
|
-
* @
|
|
68
|
-
* @returns {string|null}
|
|
93
|
+
* @param {Object} res
|
|
94
|
+
* @param {number} fallback
|
|
95
|
+
* @returns {number}
|
|
69
96
|
*/
|
|
70
|
-
function
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const prefixMatch = prefixSegs.every((p, i) => segments[i] === p);
|
|
75
|
-
if (!prefixMatch) return null;
|
|
76
|
-
const varSegments = segments.slice(prefixSegs.length);
|
|
77
|
-
const pathVar = varSegmentsToCamelCase(varSegments);
|
|
78
|
-
return pathVar ? `kv://${systemKey}/${pathVar}` : null;
|
|
97
|
+
function storedCountFromResponse(res, fallback) {
|
|
98
|
+
if (res && typeof res.stored === 'number') return res.stored;
|
|
99
|
+
if (res && res.data && res.data.stored !== undefined && res.data.stored !== null) return res.data.stored;
|
|
100
|
+
return fallback;
|
|
79
101
|
}
|
|
80
102
|
|
|
81
103
|
/**
|
|
82
|
-
*
|
|
83
|
-
* @param {string[]
|
|
84
|
-
* @
|
|
104
|
+
* @param {Map<string, string>} itemsByKey
|
|
105
|
+
* @param {string} [systemKey]
|
|
106
|
+
* @param {Object} [authConfig]
|
|
85
107
|
*/
|
|
86
|
-
function
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
108
|
+
function reconcileBearerTokenSecretPaths(itemsByKey, systemKey, authConfig) {
|
|
109
|
+
const method = (
|
|
110
|
+
authConfig?.method ||
|
|
111
|
+
authConfig?.type ||
|
|
112
|
+
''
|
|
113
|
+
)
|
|
114
|
+
.toString()
|
|
115
|
+
.toLowerCase()
|
|
116
|
+
.replace(/_/g, '');
|
|
117
|
+
if (method !== 'bearertoken' || !systemKey) return;
|
|
118
|
+
const tokenPath = `kv://${systemKey}/token`;
|
|
119
|
+
const apiKeyPath = `kv://${systemKey}/apiKey`;
|
|
120
|
+
if (!itemsByKey.has(apiKeyPath)) return;
|
|
121
|
+
if (!itemsByKey.has(tokenPath)) {
|
|
122
|
+
itemsByKey.set(tokenPath, itemsByKey.get(apiKeyPath));
|
|
123
|
+
}
|
|
124
|
+
itemsByKey.delete(apiKeyPath);
|
|
93
125
|
}
|
|
94
126
|
|
|
95
127
|
/**
|
|
96
|
-
*
|
|
97
|
-
* Uses the same derivation as env key → path (securityKeyToVar + varSegmentsToCamelCase).
|
|
98
|
-
* @param {string} securityKey - Security key (e.g. 'apiKey', 'clientId', 'clientSecret')
|
|
99
|
-
* @returns {string} Canonical path segment (e.g. 'apiKey', 'clientId')
|
|
128
|
+
* @returns {string|null}
|
|
100
129
|
*/
|
|
101
|
-
function
|
|
102
|
-
|
|
103
|
-
|
|
130
|
+
function resolveLabDataplaneApiKey() {
|
|
131
|
+
const candidates = [
|
|
132
|
+
process.env.AIFABRIX_DATAPLANE_API_KEY,
|
|
133
|
+
process.env.DATAPLANE_API_KEY,
|
|
134
|
+
process.env.API_KEY
|
|
135
|
+
];
|
|
136
|
+
for (const raw of candidates) {
|
|
137
|
+
const trimmed = typeof raw === 'string' ? raw.trim() : '';
|
|
138
|
+
if (trimmed) return trimmed;
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
104
141
|
}
|
|
105
142
|
|
|
106
143
|
/**
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* When systemKey is provided, uses it as the path namespace; otherwise infers from segments.
|
|
110
|
-
*
|
|
111
|
-
* @param {string} envKey - Env var name (e.g. KV_MICROSOFT_TEAMS_CLIENT_ID)
|
|
112
|
-
* @param {string} [systemKey] - Optional system key (e.g. 'microsoft-teams'); when provided, path is kv://systemKey/variable
|
|
113
|
-
* @returns {string|null} kv:// path or null if invalid
|
|
144
|
+
* @param {string} token
|
|
145
|
+
* @returns {{ type: string, token: string }}
|
|
114
146
|
*/
|
|
115
|
-
function
|
|
116
|
-
|
|
117
|
-
const rest = envKey.slice(KV_PREFIX.length).trim();
|
|
118
|
-
if (!rest) return null;
|
|
119
|
-
const segments = rest.split('_').filter(Boolean);
|
|
120
|
-
if (segments.length === 0) return null;
|
|
121
|
-
|
|
122
|
-
const hasSystemKey = typeof systemKey === 'string' && systemKey.length > 0;
|
|
123
|
-
if (hasSystemKey) return kvPathWithSystemKey(segments, systemKey);
|
|
124
|
-
return kvPathInferred(segments);
|
|
147
|
+
function apiKeyAuthConfig(token) {
|
|
148
|
+
return { type: 'bearer', token };
|
|
125
149
|
}
|
|
126
150
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
* When value is a kv:// path, uses it as the key so it matches payload paths (e.g. kv://microsoft-teams/clientId).
|
|
130
|
-
* Otherwise derives path from env key via kvEnvKeyToPath(envKey).
|
|
131
|
-
*
|
|
132
|
-
* @param {Object.<string, string>} envMap - Key-value map from .env
|
|
133
|
-
* @returns {Array<{ key: string, value: string }>} Items (key = kv://..., value = raw)
|
|
134
|
-
*/
|
|
135
|
-
function collectKvEnvVarsAsSecretItems(envMap, systemKey) {
|
|
136
|
-
if (!envMap || typeof envMap !== 'object') {
|
|
137
|
-
return [];
|
|
138
|
-
}
|
|
139
|
-
const items = [];
|
|
140
|
-
for (const [envKey, rawValue] of Object.entries(envMap)) {
|
|
141
|
-
const value = typeof rawValue === 'string' ? rawValue.trim() : '';
|
|
142
|
-
if (value === '') continue;
|
|
143
|
-
let kvPath = null;
|
|
144
|
-
if (value.startsWith('kv://') && isValidKvPath(value)) {
|
|
145
|
-
kvPath = value;
|
|
146
|
-
}
|
|
147
|
-
if (!kvPath) kvPath = kvEnvKeyToPath(envKey, systemKey) || kvEnvKeyToPath(envKey);
|
|
148
|
-
if (!kvPath) continue;
|
|
149
|
-
items.push({ key: kvPath, value });
|
|
150
|
-
}
|
|
151
|
-
return items;
|
|
152
|
-
}
|
|
151
|
+
const PERMISSION_DENIED_WARNING =
|
|
152
|
+
'Could not push credential secrets (permission denied or unauthenticated). Ensure dataplane role has credential:create if you use KV_* in .env, or set AIFABRIX_DATAPLANE_API_KEY for local lab bypass.';
|
|
153
153
|
|
|
154
154
|
/**
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
* @param {Object} secrets - Loaded secrets object
|
|
159
|
-
* @param {string} value - Value (may be "kv://..." or plain)
|
|
160
|
-
* @returns {string|null} Resolved plain value or null if unresolved
|
|
155
|
+
* @param {Object} res
|
|
156
|
+
* @returns {boolean}
|
|
161
157
|
*/
|
|
162
|
-
function
|
|
163
|
-
|
|
164
|
-
const trimmed = value.trim();
|
|
165
|
-
if (!trimmed.startsWith('kv://')) {
|
|
166
|
-
return trimmed;
|
|
167
|
-
}
|
|
168
|
-
const pathMatch = trimmed.match(/^kv:\/\/([a-zA-Z0-9_\-/]+)$/);
|
|
169
|
-
if (!pathMatch) return null;
|
|
170
|
-
const pathKey = pathMatch[1];
|
|
171
|
-
const resolved = secrets[pathKey];
|
|
172
|
-
if (resolved === undefined) return null;
|
|
173
|
-
return typeof resolved === 'string' ? resolved : String(resolved);
|
|
158
|
+
function isStoreResponseFailed(res) {
|
|
159
|
+
return Boolean(res && (res.success === false || res.data?.success === false));
|
|
174
160
|
}
|
|
175
161
|
|
|
176
162
|
/**
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
* @param {Object|Array|string|number|boolean|null} obj - Upload payload (application + dataSources)
|
|
180
|
-
* @param {Set<string>} [acc] - Accumulator set (internal)
|
|
181
|
-
* @returns {string[]} Unique kv:// refs (e.g. ["kv://secrets/foo"])
|
|
163
|
+
* @param {Object} res
|
|
164
|
+
* @returns {number|undefined}
|
|
182
165
|
*/
|
|
183
|
-
function
|
|
184
|
-
|
|
185
|
-
return Array.from(acc);
|
|
186
|
-
}
|
|
187
|
-
if (typeof obj === 'string') {
|
|
188
|
-
let m;
|
|
189
|
-
KV_REF_PATTERN.lastIndex = 0;
|
|
190
|
-
while ((m = KV_REF_PATTERN.exec(obj)) !== null) {
|
|
191
|
-
acc.add(`kv://${m[1]}`);
|
|
192
|
-
}
|
|
193
|
-
return Array.from(acc);
|
|
194
|
-
}
|
|
195
|
-
if (Array.isArray(obj)) {
|
|
196
|
-
for (const item of obj) {
|
|
197
|
-
collectKvRefsFromPayload(item, acc);
|
|
198
|
-
}
|
|
199
|
-
return Array.from(acc);
|
|
200
|
-
}
|
|
201
|
-
if (typeof obj === 'object') {
|
|
202
|
-
for (const v of Object.values(obj)) {
|
|
203
|
-
collectKvRefsFromPayload(v, acc);
|
|
204
|
-
}
|
|
205
|
-
return Array.from(acc);
|
|
206
|
-
}
|
|
207
|
-
return Array.from(acc);
|
|
166
|
+
function storeResponseStatus(res) {
|
|
167
|
+
return res?.status ?? res?.statusCode;
|
|
208
168
|
}
|
|
209
169
|
|
|
210
170
|
/**
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
* @param {string} key - kv:// path
|
|
214
|
-
* @returns {boolean}
|
|
171
|
+
* @param {Object} res
|
|
172
|
+
* @returns {{ pushed: number, warning: string }}
|
|
215
173
|
*/
|
|
216
|
-
function
|
|
217
|
-
|
|
174
|
+
function storeErrorWarning(res) {
|
|
175
|
+
const errMsg =
|
|
176
|
+
res.formattedError ||
|
|
177
|
+
res.data?.formattedError ||
|
|
178
|
+
res.error ||
|
|
179
|
+
res.data?.error ||
|
|
180
|
+
'Failed to push credential secrets to dataplane.';
|
|
181
|
+
return { pushed: 0, warning: errMsg };
|
|
218
182
|
}
|
|
219
183
|
|
|
220
184
|
/**
|
|
221
|
-
*
|
|
222
|
-
* @param {
|
|
223
|
-
* @param {
|
|
224
|
-
* @
|
|
185
|
+
* @param {string} dataplaneUrl
|
|
186
|
+
* @param {Object} authConfig
|
|
187
|
+
* @param {Array<{ key: string, value: string }>} items
|
|
188
|
+
* @returns {Promise<{ pushed: number }|null>}
|
|
225
189
|
*/
|
|
226
|
-
function
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
const envMap = parseEnvToMap(content);
|
|
231
|
-
const fromEnv = collectKvEnvVarsAsSecretItems(envMap, systemKey);
|
|
232
|
-
for (const { key, value } of fromEnv) {
|
|
233
|
-
const resolved = resolveKvValue(secrets, value);
|
|
234
|
-
// Skip placeholder: value that equals the kv path (e.g. from env.template) must not be pushed as the secret
|
|
235
|
-
if (resolved !== null && resolved !== undefined && isValidKvPath(key) && resolved.trim() !== key.trim()) {
|
|
236
|
-
itemsByKey.set(key, resolved);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
} catch {
|
|
240
|
-
// Best-effort: continue without .env items
|
|
190
|
+
async function tryLabApiKeyRetry(dataplaneUrl, authConfig, items) {
|
|
191
|
+
const labKey = resolveLabDataplaneApiKey();
|
|
192
|
+
if (!labKey || authConfig?.token === labKey) {
|
|
193
|
+
return null;
|
|
241
194
|
}
|
|
195
|
+
const retry = await storeCredentialSecrets(
|
|
196
|
+
dataplaneUrl,
|
|
197
|
+
apiKeyAuthConfig(labKey),
|
|
198
|
+
items
|
|
199
|
+
);
|
|
200
|
+
if (isStoreResponseFailed(retry)) {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
return { pushed: storedCountFromResponse(retry, items.length) };
|
|
242
204
|
}
|
|
243
205
|
|
|
244
206
|
/**
|
|
245
|
-
*
|
|
246
|
-
* @param {Object}
|
|
247
|
-
* @param {
|
|
248
|
-
* @param {
|
|
207
|
+
* @param {string} dataplaneUrl
|
|
208
|
+
* @param {Object} authConfig
|
|
209
|
+
* @param {Array<{ key: string, value: string }>} items
|
|
210
|
+
* @param {Object} res
|
|
211
|
+
* @returns {Promise<{ pushed: number, warning?: string }>}
|
|
249
212
|
*/
|
|
250
|
-
function
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const pathKey = ref.replace(/^kv:\/\//, '');
|
|
257
|
-
const resolved = secrets[pathKey];
|
|
258
|
-
if (resolved !== null && resolved !== undefined && isValidKvPath(ref)) {
|
|
259
|
-
itemsByKey.set(ref, typeof resolved === 'string' ? resolved : String(resolved));
|
|
213
|
+
async function handleFailedStoreResponse(dataplaneUrl, authConfig, items, res) {
|
|
214
|
+
const status = storeResponseStatus(res);
|
|
215
|
+
if (status === 403 || status === 401) {
|
|
216
|
+
const retryResult = await tryLabApiKeyRetry(dataplaneUrl, authConfig, items);
|
|
217
|
+
if (retryResult) {
|
|
218
|
+
return retryResult;
|
|
260
219
|
}
|
|
220
|
+
return { pushed: 0, warning: PERMISSION_DENIED_WARNING };
|
|
261
221
|
}
|
|
222
|
+
return storeErrorWarning(res);
|
|
262
223
|
}
|
|
263
224
|
|
|
264
225
|
/**
|
|
265
|
-
*
|
|
266
|
-
* @param {Object}
|
|
267
|
-
* @param {
|
|
268
|
-
* @returns {number}
|
|
269
|
-
*/
|
|
270
|
-
function storedCountFromResponse(res, fallback) {
|
|
271
|
-
if (res && typeof res.stored === 'number') return res.stored;
|
|
272
|
-
if (res && res.data && res.data.stored !== undefined && res.data.stored !== null) return res.data.stored;
|
|
273
|
-
return fallback;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Sends items to dataplane credential API; returns pushed count or warning.
|
|
278
|
-
* @param {string} dataplaneUrl - Dataplane URL
|
|
279
|
-
* @param {Object} authConfig - Auth config
|
|
280
|
-
* @param {Array<{ key: string, value: string }>} items - Items to send
|
|
226
|
+
* @param {string} dataplaneUrl
|
|
227
|
+
* @param {Object} authConfig
|
|
228
|
+
* @param {Array<{ key: string, value: string }>} items
|
|
281
229
|
* @returns {Promise<{ pushed: number, warning?: string }>}
|
|
282
230
|
*/
|
|
283
231
|
async function sendCredentialSecrets(dataplaneUrl, authConfig, items) {
|
|
284
232
|
try {
|
|
285
233
|
const res = await storeCredentialSecrets(dataplaneUrl, authConfig, items);
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
const status = res.status ?? res.statusCode;
|
|
289
|
-
if (status === 403 || status === 401) {
|
|
290
|
-
return { pushed: 0, warning: 'Could not push credential secrets (permission denied or unauthenticated). Ensure dataplane role has credential:create if you use KV_* in .env.' };
|
|
291
|
-
}
|
|
292
|
-
const errMsg = res.formattedError || res.data?.formattedError || res.error || res.data?.error || 'Failed to push credential secrets to dataplane.';
|
|
293
|
-
return { pushed: 0, warning: errMsg };
|
|
234
|
+
if (isStoreResponseFailed(res)) {
|
|
235
|
+
return handleFailedStoreResponse(dataplaneUrl, authConfig, items, res);
|
|
294
236
|
}
|
|
295
237
|
return { pushed: storedCountFromResponse(res, items.length) };
|
|
296
238
|
} catch (err) {
|
|
297
|
-
return {
|
|
239
|
+
return {
|
|
240
|
+
pushed: 0,
|
|
241
|
+
warning: err.message || 'Failed to push credential secrets to dataplane.'
|
|
242
|
+
};
|
|
298
243
|
}
|
|
299
244
|
}
|
|
300
245
|
|
|
301
246
|
/**
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
* @param {string} dataplaneUrl - Dataplane base URL
|
|
307
|
-
* @param {Object} authConfig - Auth config (Bearer)
|
|
308
|
-
* @param {Object} options - Options
|
|
309
|
-
* @param {string} [options.envFilePath] - Path to .env (integration/<systemKey>/.env)
|
|
310
|
-
* @param {string} [options.appName] - App/system name for loadSecrets context
|
|
311
|
-
* @param {Object} [options.payload] - Upload payload { application, dataSources } for kv scan
|
|
312
|
-
* @returns {Promise<{ pushed: number, keys?: string[], skipped?: boolean, warning?: string }>} Count pushed, keys (on success), skipped (when nothing to push), optional warning
|
|
247
|
+
* @param {string} dataplaneUrl
|
|
248
|
+
* @param {Object} authConfig
|
|
249
|
+
* @param {Object} options
|
|
250
|
+
* @returns {Promise<{ pushed: number, keys?: string[], skipped?: boolean, warning?: string }>}
|
|
313
251
|
*/
|
|
314
252
|
async function pushCredentialSecrets(dataplaneUrl, authConfig, options = {}) {
|
|
315
253
|
const { envFilePath, appName, payload } = options;
|
|
@@ -322,6 +260,7 @@ async function pushCredentialSecrets(dataplaneUrl, authConfig, options = {}) {
|
|
|
322
260
|
const itemsByKey = new Map();
|
|
323
261
|
buildItemsFromEnv(envFilePath, secrets, itemsByKey, appName);
|
|
324
262
|
buildItemsFromPayload(payload, secrets, itemsByKey);
|
|
263
|
+
reconcileBearerTokenSecretPaths(itemsByKey, appName, authConfig);
|
|
325
264
|
|
|
326
265
|
const items = Array.from(itemsByKey.entries())
|
|
327
266
|
.filter(([k]) => isValidKvPath(k))
|
|
@@ -335,33 +274,12 @@ async function pushCredentialSecrets(dataplaneUrl, authConfig, options = {}) {
|
|
|
335
274
|
return sendResult;
|
|
336
275
|
}
|
|
337
276
|
|
|
338
|
-
/**
|
|
339
|
-
* Parses .env-style content into key-value map (first = separates key and value).
|
|
340
|
-
*
|
|
341
|
-
* @param {string} content - Raw .env content
|
|
342
|
-
* @returns {Object.<string, string>}
|
|
343
|
-
*/
|
|
344
|
-
function parseEnvToMap(content) {
|
|
345
|
-
if (!content || typeof content !== 'string') return {};
|
|
346
|
-
const map = {};
|
|
347
|
-
const lines = content.split(/\r?\n/);
|
|
348
|
-
for (const line of lines) {
|
|
349
|
-
const trimmed = line.trim();
|
|
350
|
-
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
351
|
-
const eq = trimmed.indexOf('=');
|
|
352
|
-
if (eq > 0) {
|
|
353
|
-
const key = trimmed.substring(0, eq).trim();
|
|
354
|
-
const value = trimmed.substring(eq + 1);
|
|
355
|
-
map[key] = value;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
return map;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
277
|
module.exports = {
|
|
362
278
|
collectKvEnvVarsAsSecretItems,
|
|
363
279
|
collectKvRefsFromPayload,
|
|
364
280
|
pushCredentialSecrets,
|
|
281
|
+
reconcileBearerTokenSecretPaths,
|
|
282
|
+
resolveLabDataplaneApiKey,
|
|
365
283
|
kvEnvKeyToPath,
|
|
366
284
|
getKvPathSegmentForSecurityKey,
|
|
367
285
|
systemKeyToKvPrefix,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dataplane URL Resolver
|
|
3
3
|
*
|
|
4
|
-
* Resolves dataplane URL by discovering from controller
|
|
4
|
+
* Resolves dataplane URL by discovering from controller (application.url in Miso).
|
|
5
|
+
* The controller registration is the source of truth — the CLI does not rewrite ports.
|
|
5
6
|
*
|
|
6
7
|
* @fileoverview Dataplane URL resolution utilities
|
|
7
8
|
* @author AI Fabrix Team
|
|
@@ -10,6 +11,17 @@
|
|
|
10
11
|
|
|
11
12
|
const { discoverDataplaneUrl } = require('../commands/wizard-dataplane');
|
|
12
13
|
|
|
14
|
+
/**
|
|
15
|
+
* @returns {string|null}
|
|
16
|
+
*/
|
|
17
|
+
function dataplaneUrlFromProcessEnv() {
|
|
18
|
+
const raw = process.env.DP || process.env.DATAPLANE_URL;
|
|
19
|
+
if (!raw || typeof raw !== 'string') {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return raw.trim().replace(/\/$/, '');
|
|
23
|
+
}
|
|
24
|
+
|
|
13
25
|
/**
|
|
14
26
|
* Resolve dataplane URL by discovering from controller
|
|
15
27
|
* @async
|
|
@@ -22,7 +34,11 @@ const { discoverDataplaneUrl } = require('../commands/wizard-dataplane');
|
|
|
22
34
|
* @throws {Error} If dataplane URL cannot be resolved
|
|
23
35
|
*/
|
|
24
36
|
async function resolveDataplaneUrl(controllerUrl, environment, authConfig, opts = {}) {
|
|
25
|
-
|
|
37
|
+
const envUrl = dataplaneUrlFromProcessEnv();
|
|
38
|
+
if (envUrl) {
|
|
39
|
+
return envUrl;
|
|
40
|
+
}
|
|
41
|
+
return discoverDataplaneUrl(controllerUrl, environment, authConfig, opts);
|
|
26
42
|
}
|
|
27
43
|
|
|
28
44
|
module.exports = {
|
|
@@ -21,7 +21,7 @@ function parseDeveloperIdNum(raw) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
24
|
+
* Host port for compose publish, localhost URLs, and health checks: port + devId×100 (dev 0 → base port).
|
|
25
25
|
* @param {number} appPort - Manifest listen port
|
|
26
26
|
* @param {number} developerIdNum
|
|
27
27
|
* @returns {number}
|
|
@@ -31,17 +31,40 @@ function publishedHostPort(appPort, developerIdNum) {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
34
|
+
* Same as {@link publishedHostPort} (legacy name kept for call sites).
|
|
35
35
|
* @param {number} appPort
|
|
36
36
|
* @param {number} developerIdNum
|
|
37
37
|
* @returns {number}
|
|
38
38
|
*/
|
|
39
39
|
function localHostPort(appPort, developerIdNum) {
|
|
40
|
-
return appPort
|
|
40
|
+
return publishedHostPort(appPort, developerIdNum);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Host port for local dataplane Docker (`aifabrix up-dataplane` / `run --env dev|tst`).
|
|
45
|
+
* Matches {@link computeDataplanePortOverride} in up-dataplane.js (+10 dev, +20 tst).
|
|
46
|
+
*
|
|
47
|
+
* @param {number} appPort - Manifest listen port (dataplane default 3001)
|
|
48
|
+
* @param {number} developerIdNum
|
|
49
|
+
* @param {string} [environmentKey] - dev | tst | other
|
|
50
|
+
* @returns {number}
|
|
51
|
+
*/
|
|
52
|
+
function dataplaneDockerHostPort(appPort, developerIdNum, environmentKey = 'dev') {
|
|
53
|
+
const id = Number.isFinite(developerIdNum) && developerIdNum >= 0 ? developerIdNum : 0;
|
|
54
|
+
const baseHostPort = appPort + id * 100;
|
|
55
|
+
const env = String(environmentKey || '').trim().toLowerCase();
|
|
56
|
+
if (env === 'dev') {
|
|
57
|
+
return baseHostPort + 10;
|
|
58
|
+
}
|
|
59
|
+
if (env === 'tst') {
|
|
60
|
+
return baseHostPort + 20;
|
|
61
|
+
}
|
|
62
|
+
return id === 0 ? appPort : baseHostPort;
|
|
41
63
|
}
|
|
42
64
|
|
|
43
65
|
module.exports = {
|
|
44
66
|
parseDeveloperIdNum,
|
|
45
67
|
publishedHostPort,
|
|
46
|
-
localHostPort
|
|
68
|
+
localHostPort,
|
|
69
|
+
dataplaneDockerHostPort
|
|
47
70
|
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment auth mode for pipeline publish / external integration CLI.
|
|
3
|
+
* @fileoverview AIFABRIX_DEPLOYMENT_AUTH and options.deploymentAuth parsing
|
|
4
|
+
* @author AI Fabrix Team
|
|
5
|
+
* @version 1.0.0
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {'auto'|'client-credentials'|'device'} DeploymentAuthMode
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {Object} [options] - CLI or caller options
|
|
16
|
+
* @returns {DeploymentAuthMode}
|
|
17
|
+
*/
|
|
18
|
+
function getDeploymentAuthMode(options = {}) {
|
|
19
|
+
const raw = options.deploymentAuth || process.env.AIFABRIX_DEPLOYMENT_AUTH || 'auto';
|
|
20
|
+
const mode = String(raw).trim().toLowerCase().replace(/_/g, '-');
|
|
21
|
+
if (mode === 'client-credentials' || mode === 'client') {
|
|
22
|
+
return 'client-credentials';
|
|
23
|
+
}
|
|
24
|
+
if (mode === 'device' || mode === 'device-token' || mode === 'bearer') {
|
|
25
|
+
return 'device';
|
|
26
|
+
}
|
|
27
|
+
return 'auto';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {DeploymentAuthMode} mode
|
|
32
|
+
* @returns {boolean}
|
|
33
|
+
*/
|
|
34
|
+
function shouldUseDeviceTokenForDeployment(mode) {
|
|
35
|
+
return mode !== 'client-credentials';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = {
|
|
39
|
+
getDeploymentAuthMode,
|
|
40
|
+
shouldUseDeviceTokenForDeployment
|
|
41
|
+
};
|