@aifabrix/builder 2.45.0 → 2.46.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/docs-rules.mdc +3 -1
- package/.cursor/rules/project-rules.mdc +1 -0
- package/README.md +43 -17
- package/integration/hubspot-test/wizard-hubspot-e2e.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 +130 -0
- package/jest.projects.js +69 -121
- package/lib/api/agent-metadata-validation.api.js +93 -0
- package/lib/api/api-response-errors.js +124 -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-scenario-pack.api.js +159 -0
- package/lib/api/governance-scenarios.api.js +39 -0
- package/lib/api/groups.api.js +79 -0
- package/lib/api/index.js +88 -5
- package/lib/api/lifecycle.api.js +77 -0
- package/lib/api/pipeline.api.js +7 -5
- package/lib/api/protection.api.js +157 -0
- package/lib/api/records-bulk.api.js +43 -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 +5 -3
- package/lib/api/wizard-platform.api.js +3 -3
- package/lib/api/wizard.api.js +21 -21
- package/lib/app/deploy-config.js +4 -1
- package/lib/app/deploy.js +34 -19
- package/lib/app/down.js +20 -1
- 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/build/index.js +5 -0
- package/lib/certification/sync-system-certification.js +13 -6
- package/lib/cli/index.js +8 -2
- package/lib/cli/infra-guided-auth.js +109 -0
- package/lib/cli/infra-guided.js +91 -69
- package/lib/cli/setup-app.help.js +19 -2
- package/lib/cli/setup-app.js +58 -23
- package/lib/cli/setup-app.test-commands.js +28 -21
- package/lib/cli/setup-auth.js +55 -3
- 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 +62 -6
- 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 +65 -0
- package/lib/cli/setup-utility-repair.js +198 -0
- package/lib/cli/setup-utility-resolve.js +42 -6
- package/lib/cli/setup-utility-validate.js +197 -0
- package/lib/cli/setup-utility.js +41 -258
- package/lib/commands/auth-status-client-tokens.js +214 -0
- package/lib/commands/auth-status-dataplane-version.js +269 -0
- package/lib/commands/auth-status-display.js +94 -0
- package/lib/commands/auth-status.js +111 -53
- 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 +118 -0
- package/lib/commands/datasource-unified-test-cli.js +31 -20
- package/lib/commands/datasource-unified-test-cli.options.js +22 -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/dev-show-display.js +8 -1
- package/lib/commands/dimension-value.js +43 -13
- package/lib/commands/dimension.js +38 -7
- 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 +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/lifecycle-command-action.js +123 -0
- package/lib/commands/lifecycle-external.js +268 -0
- package/lib/commands/login.js +56 -17
- package/lib/commands/protection-cli-leaves.js +286 -0
- package/lib/commands/protection.js +50 -0
- package/lib/commands/repair-auth-apply.js +127 -0
- package/lib/commands/repair-changed-files.js +41 -0
- package/lib/commands/repair-datasource-keys.js +4 -1
- package/lib/commands/repair-datasource-run.js +59 -0
- package/lib/commands/repair-datasource-test-payload.js +259 -0
- package/lib/commands/repair-datasource.js +1 -51
- package/lib/commands/repair-env-template.js +64 -13
- package/lib/commands/repair-external-run.js +216 -0
- package/lib/commands/repair-openapi-sync.js +23 -0
- package/lib/commands/repair-persist.js +4 -0
- package/lib/commands/repair-rbac.js +52 -1
- package/lib/commands/repair-steps.js +145 -0
- package/lib/commands/repair.js +29 -286
- 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 +67 -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 +61 -14
- package/lib/commands/test-governance-cli-options.js +47 -0
- package/lib/commands/test-governance-external.js +67 -0
- package/lib/commands/test-trust-cli-options.js +32 -0
- package/lib/commands/test-trust-external.js +126 -0
- package/lib/commands/up-common.js +25 -13
- package/lib/commands/up-dataplane.js +50 -13
- package/lib/commands/upload-publish-context.js +75 -0
- package/lib/commands/upload-sidecar-followups.js +89 -0
- package/lib/commands/upload.js +108 -105
- 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 +70 -0
- package/lib/commands/verify-trust-external.js +67 -0
- package/lib/commands/wizard-config-normalizer.js +43 -23
- package/lib/commands/wizard-core.js +5 -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-device-dataplane.js +185 -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 +55 -0
- package/lib/datasource/agent-trust-debug-log.js +45 -0
- package/lib/datasource/agent-trust-fetch.js +115 -0
- package/lib/datasource/agent-trust-map.js +101 -0
- package/lib/datasource/agent-trust-mock.js +44 -0
- package/lib/datasource/agent-trust-run.js +95 -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 +115 -0
- package/lib/datasource/audit-evidence-extract.js +180 -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 +205 -0
- package/lib/datasource/audit-evidence-verify.js +108 -0
- package/lib/datasource/bulk-loader-run-batches.js +100 -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 +95 -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 +29 -2
- package/lib/datasource/unified-validation-run-body.js +3 -1
- package/lib/datasource/unified-validation-run-resolve.js +45 -12
- package/lib/datasource/unified-validation-run.js +47 -18
- package/lib/datasource/validate.js +37 -20
- package/lib/deployment/environment-poll-status.js +138 -0
- package/lib/deployment/environment.js +42 -34
- package/lib/external-system/download.js +21 -20
- package/lib/external-system/generator.js +5 -1
- package/lib/external-system/integration-auth-context.js +45 -0
- package/lib/external-system/test-auth.js +12 -5
- package/lib/external-system/test-system-level.js +25 -4
- package/lib/external-system/test.js +9 -7
- package/lib/generator/external-controller-manifest.js +15 -0
- package/lib/governance/governance-cli-errors.js +96 -0
- package/lib/governance/governance-download-display.js +38 -0
- package/lib/governance/governance-pack-loader.js +70 -0
- package/lib/governance/governance-run-display.js +309 -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/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/internal/fs-real-sync.js +29 -1
- 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.js +471 -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 +51 -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 +1 -1
- package/lib/schema/datasource-test-run.schema.json +89 -6
- package/lib/schema/external-datasource.schema.json +2636 -2588
- package/lib/schema/external-system.schema.json +1089 -761
- package/lib/schema/flag-map-validation-run.json +2 -2
- package/lib/schema/infra.parameter.yaml +45 -0
- package/lib/schema/protection.schema.json +374 -0
- package/lib/schema/type/credential-field-registry.json +642 -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/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/cli-exit-codes.js +30 -0
- package/lib/utils/cli-secrets-error-format.js +83 -21
- package/lib/utils/cli-sync-options.js +33 -0
- package/lib/utils/cli-utils.js +16 -4
- package/lib/utils/compose-generate-docker-compose.js +4 -0
- package/lib/utils/compose-traefik-ingress-base.js +16 -1
- package/lib/utils/config-secrets-path.js +46 -0
- package/lib/utils/controller-url.js +88 -1
- package/lib/utils/credential-push-ui.js +90 -0
- package/lib/utils/credential-secrets-env.js +137 -9
- package/lib/utils/dataplane-cli-version-gate.js +202 -0
- package/lib/utils/dataplane-cli-version-help.js +74 -0
- package/lib/utils/dataplane-resolver.js +129 -2
- 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/declarative-url-ports.js +3 -3
- package/lib/utils/deployment-auth-mode.js +41 -0
- package/lib/utils/developer-volume-id.js +33 -0
- 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 +1 -0
- package/lib/utils/external-system-readiness-core.js +10 -0
- package/lib/utils/external-system-readiness-display.js +80 -23
- package/lib/utils/health-check.js +4 -1
- package/lib/utils/help-builder.js +35 -26
- 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 +24 -0
- package/lib/utils/pipeline-upload-auth-retry.js +82 -0
- package/lib/utils/platform-controller-url.js +156 -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/secrets-generator.js +31 -25
- package/lib/utils/secrets-missing-error.js +164 -0
- package/lib/utils/semver-compare.js +127 -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 +98 -0
- 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 +22 -7
- package/lib/utils/validation-run-stage.js +45 -0
- package/lib/validation/wizard-config-validator.js +58 -19
- package/package.json +1 -1
- package/templates/applications/dataplane/application.yaml +2 -1
- package/templates/applications/dataplane/env.template +36 -1
- package/templates/applications/dataplane/rbac.yaml +4 -0
- package/templates/applications/miso-controller/env.template +16 -0
- package/templates/external-system/README.md.hbs +116 -11
- package/templates/python/docker-compose.hbs +19 -18
- package/templates/typescript/docker-compose.hbs +18 -17
|
@@ -15,12 +15,19 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
const { handleCommandError } = require('../utils/cli-utils');
|
|
18
|
+
const { cliOptsSkipSync } = require('../utils/cli-sync-options');
|
|
18
19
|
const { cliOptsSkipCertSync } = require('../certification/cli-cert-sync-skip');
|
|
19
20
|
const { TEST_INTEGRATION_HELP_AFTER } = require('./setup-app.help');
|
|
21
|
+
const {
|
|
22
|
+
UPLOAD_HELP_AFTER,
|
|
23
|
+
DOWNLOAD_HELP_AFTER,
|
|
24
|
+
DELETE_HELP_AFTER
|
|
25
|
+
} = require('./setup-external-system-help');
|
|
20
26
|
|
|
21
27
|
function setupDownloadCommand(program) {
|
|
22
28
|
program.command('download <systemKey>')
|
|
23
29
|
.description('Pull external system from dataplane into integration/<key>/')
|
|
30
|
+
.addHelpText('after', DOWNLOAD_HELP_AFTER)
|
|
24
31
|
.option('--format <format>', 'Output format: json | yaml (default: yaml or config format)')
|
|
25
32
|
.option('--dry-run', 'Show what would be downloaded without actually downloading')
|
|
26
33
|
.option('--force', 'Overwrite existing README.md without prompting')
|
|
@@ -42,8 +49,12 @@ function setupDownloadCommand(program) {
|
|
|
42
49
|
|
|
43
50
|
function setupUploadCommand(program) {
|
|
44
51
|
program.command('upload <systemKey>')
|
|
45
|
-
.description('Validate, publish to dataplane, and register with controller (draft application)')
|
|
52
|
+
.description('Validate, publish to dataplane, and register with controller (draft application); or upload .protection batch')
|
|
53
|
+
.addHelpText('after', UPLOAD_HELP_AFTER)
|
|
46
54
|
.option('--dry-run', 'Validate and build payload only; no API calls')
|
|
55
|
+
.option('--no-sync', 'For .protection: skip datasource sync after upload')
|
|
56
|
+
.option('--json', 'For .protection: JSON output')
|
|
57
|
+
.option('--warnings-as-errors', 'For .protection: pass strict=true to dataplane validate')
|
|
47
58
|
.option('-v, --verbose', 'Run server-side pipeline validate and print warnings before publish')
|
|
48
59
|
.option('--probe', 'After publish, run dataplane runtime checks (validation/run); slower')
|
|
49
60
|
.option('--minimal', 'Print only a short readiness summary after upload')
|
|
@@ -52,8 +63,32 @@ function setupUploadCommand(program) {
|
|
|
52
63
|
'--no-cert-sync',
|
|
53
64
|
'Skip updating the system file certification block from the dataplane active certificate after publish'
|
|
54
65
|
)
|
|
66
|
+
.option(
|
|
67
|
+
'--force',
|
|
68
|
+
'Bypass schema guards on active datasources during publish (dangerous; shows a warning)'
|
|
69
|
+
)
|
|
55
70
|
.action(async(systemKey, options) => {
|
|
56
71
|
try {
|
|
72
|
+
const { isProtectionScope } = require('../protection/scope');
|
|
73
|
+
if (isProtectionScope(systemKey)) {
|
|
74
|
+
const { uploadProtectionBatchCommand } = require('../protection/upload-batch');
|
|
75
|
+
const logger = require('../utils/logger');
|
|
76
|
+
const code = await uploadProtectionBatchCommand(
|
|
77
|
+
{
|
|
78
|
+
env: options.env,
|
|
79
|
+
dryRun: options.dryRun === true,
|
|
80
|
+
noSync: options.noSync === true,
|
|
81
|
+
json: options.json === true,
|
|
82
|
+
verbose: options.verbose === true,
|
|
83
|
+
warningsAsErrors: options.warningsAsErrors === true
|
|
84
|
+
},
|
|
85
|
+
logger
|
|
86
|
+
);
|
|
87
|
+
if (code !== 0) {
|
|
88
|
+
process.exit(code);
|
|
89
|
+
}
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
57
92
|
const upload = require('../commands/upload');
|
|
58
93
|
const probeTimeout =
|
|
59
94
|
options.probeTimeout === undefined || options.probeTimeout === null
|
|
@@ -74,11 +109,23 @@ function setupUploadCommand(program) {
|
|
|
74
109
|
function setupDeleteCommand(program) {
|
|
75
110
|
program.command('delete <systemKey>')
|
|
76
111
|
.description('Remove external system and its datasources from dataplane')
|
|
112
|
+
.addHelpText('after', DELETE_HELP_AFTER)
|
|
77
113
|
.option('--type <type>', 'Application type (default: external; use "external" to target integration/<systemKey>)')
|
|
78
114
|
.option('--yes', 'Skip confirmation prompt')
|
|
79
115
|
.option('--force', 'Skip confirmation prompt (alias for --yes)')
|
|
80
116
|
.action(async(systemKey, options) => {
|
|
81
117
|
try {
|
|
118
|
+
const { isProtectionScope } = require('../protection/scope');
|
|
119
|
+
if (isProtectionScope(systemKey)) {
|
|
120
|
+
const logger = require('../utils/logger');
|
|
121
|
+
const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
|
|
122
|
+
logger.error(
|
|
123
|
+
formatBlockingError(
|
|
124
|
+
'delete .protection is not supported. Use: aifabrix protection delete <datasourceKey>'
|
|
125
|
+
)
|
|
126
|
+
);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
82
129
|
const externalDelete = require('../external-system/delete');
|
|
83
130
|
await externalDelete.deleteExternalSystem(systemKey, options);
|
|
84
131
|
} catch (error) {
|
|
@@ -134,7 +181,7 @@ async function runExternalSystemTestIntegration(appName, options) {
|
|
|
134
181
|
environment: options.env || options.environment,
|
|
135
182
|
debug: options.debug,
|
|
136
183
|
perDatasource: options.perDatasource,
|
|
137
|
-
|
|
184
|
+
noSync: cliOptsSkipSync(options)
|
|
138
185
|
};
|
|
139
186
|
const results = await test.testExternalSystemIntegration(appName, opts);
|
|
140
187
|
test.displayIntegrationTestResults(results, options.verbose, { debug: options.debug, runType: 'integration' });
|
|
@@ -186,14 +233,22 @@ async function runTestIntegrationCommand(appName, options) {
|
|
|
186
233
|
|
|
187
234
|
function setupExternalSystemTestCommands(program) {
|
|
188
235
|
// 'test <app>' is registered in setup-app.js and dispatches by app type (builder vs external)
|
|
189
|
-
program.command('test-integration <
|
|
190
|
-
.description('Integration tests: builder in container; external via dataplane')
|
|
236
|
+
program.command('test-integration <appKey|systemKey>')
|
|
237
|
+
.description('Integration tests: builder appKey in container; external systemKey via dataplane')
|
|
191
238
|
.option('-e, --env <env>', 'Environment: dev, tst, or pro (builder: dev/tst for container)', 'dev')
|
|
192
239
|
.option('-v, --verbose', 'Show detailed test output')
|
|
193
240
|
.option('-d, --debug', 'Include debug output and write log to integration/<systemKey>/logs/')
|
|
241
|
+
.option(
|
|
242
|
+
'--no-sync',
|
|
243
|
+
'Skip publishing local integration files; use system config already on the dataplane'
|
|
244
|
+
)
|
|
194
245
|
.option(
|
|
195
246
|
'--sync',
|
|
196
|
-
'Publish local system and datasource files
|
|
247
|
+
'Publish local system and datasource files before tests (default for external integration; same as upload)'
|
|
248
|
+
)
|
|
249
|
+
.option(
|
|
250
|
+
'--force',
|
|
251
|
+
'With --sync, pass force to upload (bypass active-datasource schema replacement guards; same as aifabrix upload --force)'
|
|
197
252
|
)
|
|
198
253
|
.option('--warnings-as-errors', 'Treat aggregate warn as failure (exit 1)')
|
|
199
254
|
.option('--require-cert', 'Require certification passed on every datasource (exit 2 if not)')
|
|
@@ -208,7 +263,8 @@ function setupExternalSystemTestCommands(program) {
|
|
|
208
263
|
const envExplicit = rawArgs.includes('-e') || rawArgs.includes('--env');
|
|
209
264
|
const opts = {
|
|
210
265
|
...options,
|
|
211
|
-
env: envExplicit ? options.env : undefined
|
|
266
|
+
env: envExplicit ? options.env : undefined,
|
|
267
|
+
noSync: cliOptsSkipSync(options, cmd)
|
|
212
268
|
};
|
|
213
269
|
await runTestIntegrationCommand(appName, opts);
|
|
214
270
|
} catch (error) {
|
package/lib/cli/setup-infra.js
CHANGED
|
@@ -134,6 +134,8 @@ async function runUpInfraCommand(options) {
|
|
|
134
134
|
const cfg = await config.getConfig();
|
|
135
135
|
await persistOptionalInfraFlagsFromCli(options, cfg);
|
|
136
136
|
await maybePersistTlsFromUpInfra(options, cfg);
|
|
137
|
+
const { passwordBundleFromCliOptions } = require('../core/admin-secrets-bundle');
|
|
138
|
+
const bundle = passwordBundleFromCliOptions(options);
|
|
137
139
|
const adminPass = options.adminPassword || options.adminPwd;
|
|
138
140
|
const tlsEnabledEffective = cfg.tlsEnabled === true;
|
|
139
141
|
const effective = computeEffectiveInfraOptionalFlags(cfg, options);
|
|
@@ -145,6 +147,8 @@ async function runUpInfraCommand(options) {
|
|
|
145
147
|
adminPwd: adminPass,
|
|
146
148
|
adminEmail: options.adminEmail,
|
|
147
149
|
userPassword: options.userPassword,
|
|
150
|
+
passwordBundle: bundle,
|
|
151
|
+
syncAdminKv: options.syncAdminKv === true,
|
|
148
152
|
tlsEnabled: tlsEnabledEffective
|
|
149
153
|
});
|
|
150
154
|
await persistMissingInfraOptionalServiceFlags(cfg, effective);
|
|
@@ -156,8 +160,12 @@ function setupUpInfraCommand(program) {
|
|
|
156
160
|
.addHelpText('after', UP_INFRA_HELP_AFTER)
|
|
157
161
|
.option('-d, --developer <id>', 'Set developer ID and start infrastructure')
|
|
158
162
|
.option('--verbose', 'Show full orchestration output (default is guided summary)')
|
|
159
|
-
.option('--adminPassword <password>', 'Override
|
|
163
|
+
.option('--adminPassword <password>', 'Override admin password (dev: all roles; pro manual-single)')
|
|
160
164
|
.option('--adminEmail <email>', 'Override {{adminEmail}} default (e.g. pgAdmin login email)')
|
|
165
|
+
.option('--infraAdminPassword <password>', 'Pro profile: infra DB/pgAdmin/Redis Commander password')
|
|
166
|
+
.option('--keycloakAdminPassword <password>', 'Pro profile: Keycloak install admin password')
|
|
167
|
+
.option('--platformAdminPassword <password>', 'Pro profile: platform UI login password (user admin)')
|
|
168
|
+
.option('--syncAdminKv', 'Also sync {{adminPassword}} catalog keys into secrets.local.yaml (legacy)')
|
|
161
169
|
.option('--userPassword <password>', 'Override {{userPassword}} default (e.g. Keycloak default user password)')
|
|
162
170
|
.option('--pgAdmin', 'Include pgAdmin web UI and save to config')
|
|
163
171
|
.option('--no-pgAdmin', 'Exclude pgAdmin and save to config')
|
|
@@ -23,7 +23,7 @@ const { handleTeardown } = require('../commands/teardown');
|
|
|
23
23
|
|
|
24
24
|
const SETUP_HELP_AFTER = `
|
|
25
25
|
What this command does:
|
|
26
|
-
- With no infra running: prompts for
|
|
26
|
+
- With no infra running: prompts for installation profile (dev = one password for infra + Keycloak + platform UI; pro = autogen or manual split passwords). Credentials are stored in admin-secrets.env (encrypted secure:// values), not in secrets.local.yaml unless you pass --syncAdminKv on up-infra. The admin email is saved in config.yaml for the next run. Prompts for an AI tool (OpenAI or Azure OpenAI) only when keys are not already set, then runs up-infra and up-platform.
|
|
27
27
|
- With infra running: shows a mode menu:
|
|
28
28
|
1) Re-install — stop infra and remove all volumes, then up-infra + up-platform --force.
|
|
29
29
|
2) Wipe data — drop every database and DB user, then up-infra + up-platform --force.
|
|
@@ -54,6 +54,11 @@ function registerSetup(program) {
|
|
|
54
54
|
.command('setup')
|
|
55
55
|
.description('Install or refresh the full AI Fabrix platform (infra + miso + dataplane)')
|
|
56
56
|
.option('-d, --developer <id>', 'Pin developer ID before fresh install (fresh path only; ignored when infra is already up)')
|
|
57
|
+
.option('--platform <mode>', 'Platform mode: single (direct ports) or full (Traefik front door + multi-env)')
|
|
58
|
+
.option('--installation <profile>', 'Installation profile: dev (one password) or pro (autogen/manual)')
|
|
59
|
+
.option('--pro-password-mode <mode>', 'Pro profile only: autogen or manual')
|
|
60
|
+
.option('--admin-email <email>', 'Admin email (non-interactive fresh install)')
|
|
61
|
+
.option('--admin-password <password>', 'Admin password for dev or pro manual-single (non-interactive)')
|
|
57
62
|
.option('-y, --yes', 'Skip destructive confirmation prompts (re-install, wipe data, teardown)')
|
|
58
63
|
.addHelpText('after', SETUP_HELP_AFTER)
|
|
59
64
|
.action(async(options) => {
|
package/lib/cli/setup-secrets.js
CHANGED
|
@@ -10,6 +10,7 @@ const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
|
|
|
10
10
|
const { handleCommandError } = require('../utils/cli-utils');
|
|
11
11
|
const { handleSecretsSet } = require('../commands/secrets-set');
|
|
12
12
|
const { handleSecretsList } = require('../commands/secrets-list');
|
|
13
|
+
const { handleSecretsGet } = require('../commands/secrets-get');
|
|
13
14
|
const { handleSecretsRemove } = require('../commands/secrets-remove');
|
|
14
15
|
const { handleSecretsValidate } = require('../commands/secrets-validate');
|
|
15
16
|
const { handleSecure } = require('../commands/secure');
|
|
@@ -18,7 +19,7 @@ const logger = require('../utils/logger');
|
|
|
18
19
|
|
|
19
20
|
const SECRET_GROUP_HELP_AFTER = `
|
|
20
21
|
Subcommands:
|
|
21
|
-
list, set, remove, remove-all User secrets.local.yaml (add --shared for shared/remote)
|
|
22
|
+
list, get, set, remove, remove-all User secrets.local.yaml (add --shared for shared/remote)
|
|
22
23
|
set-secrets-file Point config at a shared secrets file or https URL
|
|
23
24
|
validate YAML structure (+ optional --naming)
|
|
24
25
|
|
|
@@ -38,6 +39,17 @@ Examples:
|
|
|
38
39
|
Shared over https: key BASH_NPM_TOKEN --shared → NPM_TOKEN available in terminal (exported).
|
|
39
40
|
`;
|
|
40
41
|
|
|
42
|
+
const SECRET_GET_HELP_AFTER = `
|
|
43
|
+
Examples:
|
|
44
|
+
$ aifabrix secret get hubspot-demo/token --shared --exists
|
|
45
|
+
$ aifabrix secret get myapp/clientSecret
|
|
46
|
+
$ aifabrix secret get hubspot/apiKey --shared --json
|
|
47
|
+
|
|
48
|
+
--exists Script mode: exit 0 when the key is present and non-empty; no output.
|
|
49
|
+
Default Local user secrets.local.yaml only (same target as secret set without --shared).
|
|
50
|
+
--shared aifabrix-secrets store only (team file or remote API; same as secret set --shared).
|
|
51
|
+
`;
|
|
52
|
+
|
|
41
53
|
const SECRET_LIST_HELP_AFTER = `
|
|
42
54
|
Examples:
|
|
43
55
|
$ aifabrix secret list
|
|
@@ -168,6 +180,25 @@ function setupSecureCommand(program) {
|
|
|
168
180
|
});
|
|
169
181
|
}
|
|
170
182
|
|
|
183
|
+
function setupSecretGetCommand(secretCmd) {
|
|
184
|
+
secretCmd
|
|
185
|
+
.command('get <key>')
|
|
186
|
+
.description('Get one secret (local user file by default; --shared for team store; --exists for scripts)')
|
|
187
|
+
.addHelpText('after', SECRET_GET_HELP_AFTER)
|
|
188
|
+
.option('--shared', 'Read from shared secrets (config aifabrix-secrets or remote API)')
|
|
189
|
+
.option('--exists', 'Exit 0 when key is present and non-empty; print nothing (for scripts)')
|
|
190
|
+
.option('--json', 'Output JSON { key, exists, value }')
|
|
191
|
+
.action(async(key, options) => {
|
|
192
|
+
try {
|
|
193
|
+
await config.ensureSecretsEncryptionKey();
|
|
194
|
+
await handleSecretsGet(key, options);
|
|
195
|
+
} catch (error) {
|
|
196
|
+
handleCommandError(error, 'secret get');
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
171
202
|
function setupSecretListCommand(secretCmd) {
|
|
172
203
|
secretCmd
|
|
173
204
|
.command('list')
|
|
@@ -196,6 +227,7 @@ function setupSecretsCommands(program) {
|
|
|
196
227
|
.addHelpText('after', SECRET_GROUP_HELP_AFTER);
|
|
197
228
|
|
|
198
229
|
setupSecretListCommand(secretCmd);
|
|
230
|
+
setupSecretGetCommand(secretCmd);
|
|
199
231
|
|
|
200
232
|
secretCmd
|
|
201
233
|
.command('set <key> <value>')
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Help-after strings for setup-utility CLI commands.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const JSON_HELP_AFTER = `
|
|
8
|
+
Example:
|
|
9
|
+
$ aifabrix json myapp
|
|
10
|
+
Generates *-deploy.json (or application-schema.json) for commit before deploy.
|
|
11
|
+
`;
|
|
12
|
+
|
|
13
|
+
const VALIDATE_HELP_AFTER = `
|
|
14
|
+
Examples:
|
|
15
|
+
$ aifabrix validate myapp
|
|
16
|
+
$ aifabrix validate myapp --cert-sync
|
|
17
|
+
$ aifabrix validate --integration
|
|
18
|
+
$ aifabrix validate --builder
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
const REPAIR_HELP_AFTER = `
|
|
22
|
+
Examples:
|
|
23
|
+
$ aifabrix repair hubspot-demo
|
|
24
|
+
Align manifest, system/datasource files, RBAC extract, env.template, and deploy JSON under integration/<systemKey>/.
|
|
25
|
+
|
|
26
|
+
$ aifabrix repair hubspot-demo --dry-run
|
|
27
|
+
Show what would change without writing files.
|
|
28
|
+
|
|
29
|
+
$ aifabrix repair hubspot-demo --auth bearerToken
|
|
30
|
+
Private-app style apikey: Authorization + Bearer prefix; preserves baseUrl/testEndpoint when present. Warns if testEndpoint is missing.
|
|
31
|
+
|
|
32
|
+
$ aifabrix repair hubspot-demo --auth oauth2
|
|
33
|
+
Set authentication method; updates the system file and env.template (oauth2, aad, apikey, bearerToken, basic, …).
|
|
34
|
+
|
|
35
|
+
$ aifabrix repair hubspot-demo --rbac --expose --sync --test
|
|
36
|
+
Optional datasource fixes: RBAC roles/permissions, exposed.schema from attributes, default sync block, testPayload stubs.
|
|
37
|
+
|
|
38
|
+
$ aifabrix repair hubspot-demo --doc
|
|
39
|
+
Regenerate README.md from the current deployment manifest only (other drift fixes unchanged).
|
|
40
|
+
|
|
41
|
+
Before overwriting files, repair writes timestamped backups under integration/<systemKey>/backup/ (same as datasource capability copy). Use --no-backup to skip.
|
|
42
|
+
`;
|
|
43
|
+
|
|
44
|
+
const RESOLVE_HELP_AFTER = `
|
|
45
|
+
Examples:
|
|
46
|
+
$ aifabrix resolve hubspot-demo
|
|
47
|
+
External integration: resolves integration/<systemKey>/env.template to .env using local host ports (no Docker rewrite).
|
|
48
|
+
|
|
49
|
+
$ aifabrix resolve dataplane --fresh
|
|
50
|
+
Regenerate the full .env from env.template (no merge with an existing file). Use after adding many new variables or when a normal resolve did not pick up new template lines.
|
|
51
|
+
|
|
52
|
+
$ aifabrix secret set hubspot-demo/token "<your-token>"
|
|
53
|
+
Store a secret when resolve reports a missing kv:// reference.
|
|
54
|
+
|
|
55
|
+
If a key is not required by your system file, comment out its line in env.template instead of creating a secret.
|
|
56
|
+
$ aifabrix repair hubspot-demo
|
|
57
|
+
Align env.template with authentication.security and comment stale OAuth KV lines after --auth bearerToken.
|
|
58
|
+
`;
|
|
59
|
+
|
|
60
|
+
module.exports = {
|
|
61
|
+
JSON_HELP_AFTER,
|
|
62
|
+
VALIDATE_HELP_AFTER,
|
|
63
|
+
REPAIR_HELP_AFTER,
|
|
64
|
+
RESOLVE_HELP_AFTER
|
|
65
|
+
};
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `aifabrix repair` command wiring and CLI output (split from setup-utility for size limits).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Repair CLI command
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const logger = require('../utils/logger');
|
|
13
|
+
const { handleCommandError, logOfflinePathWhenType } = require('../utils/cli-utils');
|
|
14
|
+
const { detectAppType } = require('../utils/paths');
|
|
15
|
+
const { formatSuccessParagraph, formatWarningLine } = require('../utils/cli-test-layout-chalk');
|
|
16
|
+
const { REPAIR_HELP_AFTER } = require('./setup-utility-help-after');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {string} appName
|
|
20
|
+
* @param {object} options
|
|
21
|
+
* @param {string} format
|
|
22
|
+
* @returns {object}
|
|
23
|
+
*/
|
|
24
|
+
function buildRepairExternalIntegrationOptions(appName, options, format) {
|
|
25
|
+
const all = options.all === true;
|
|
26
|
+
return {
|
|
27
|
+
auth: options.auth,
|
|
28
|
+
doc: options.doc || all,
|
|
29
|
+
dryRun: options.dryRun,
|
|
30
|
+
format,
|
|
31
|
+
rbac: options.rbac || all,
|
|
32
|
+
expose: options.expose || all,
|
|
33
|
+
sync: options.sync || all,
|
|
34
|
+
api: options.api || all,
|
|
35
|
+
test: options.test || all,
|
|
36
|
+
backup: options.backup,
|
|
37
|
+
noBackup: options.noBackup
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {string[]} changedFiles
|
|
43
|
+
* @param {boolean} dryRun
|
|
44
|
+
*/
|
|
45
|
+
function logRepairChangedFiles(changedFiles, dryRun) {
|
|
46
|
+
if (!Array.isArray(changedFiles) || changedFiles.length === 0) return;
|
|
47
|
+
const title = dryRun ? '\nWould change files:' : '\nChanged files:';
|
|
48
|
+
logger.log(chalk.white(title));
|
|
49
|
+
changedFiles.forEach((filePath) => logger.log(chalk.cyan(` ${filePath}`)));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {string[]} warnings
|
|
54
|
+
*/
|
|
55
|
+
function logRepairWarnings(warnings) {
|
|
56
|
+
if (!Array.isArray(warnings) || warnings.length === 0) return;
|
|
57
|
+
warnings.forEach((msg) => logger.log(formatWarningLine(msg)));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {string[]} changedFiles
|
|
62
|
+
* @param {string[]} warnings
|
|
63
|
+
*/
|
|
64
|
+
function logRepairNextActions(changedFiles, warnings) {
|
|
65
|
+
const hasFiles = Array.isArray(changedFiles) && changedFiles.length > 0;
|
|
66
|
+
const hasWarnings = Array.isArray(warnings) && warnings.length > 0;
|
|
67
|
+
if (!hasFiles && !hasWarnings) return;
|
|
68
|
+
logger.log(chalk.white('\nNext actions:'));
|
|
69
|
+
if (hasFiles) {
|
|
70
|
+
logger.log(chalk.gray(' • Open the paths above in your editor and review the diff'));
|
|
71
|
+
logger.log(chalk.gray(' • Run: aifabrix validate <systemKey>'));
|
|
72
|
+
}
|
|
73
|
+
if (hasWarnings) {
|
|
74
|
+
logger.log(chalk.gray(' • Fix warnings in the system file (especially authentication.variables.testEndpoint)'));
|
|
75
|
+
logger.log(chalk.gray(' • Run: aifabrix json <systemKey> && aifabrix upload <systemKey>'));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param {object} options
|
|
81
|
+
* @param {object} result
|
|
82
|
+
* @param {string[]} changedFiles
|
|
83
|
+
*/
|
|
84
|
+
function logRepairDryRunOutcome(options, result, changedFiles) {
|
|
85
|
+
logger.log(chalk.yellow('\nWould apply:'));
|
|
86
|
+
result.changes.forEach((c) => logger.log(chalk.gray(` ${c}`)));
|
|
87
|
+
logRepairChangedFiles(changedFiles, true);
|
|
88
|
+
logRepairWarnings(result.warnings);
|
|
89
|
+
logRepairNextActions(changedFiles, result.warnings);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @param {object} result
|
|
94
|
+
* @param {string[]} changedFiles
|
|
95
|
+
*/
|
|
96
|
+
function logRepairSuccessOutcome(result, changedFiles) {
|
|
97
|
+
if (result.updated) {
|
|
98
|
+
logger.log(formatSuccessParagraph('Repaired external integration config.'));
|
|
99
|
+
logRepairChangedFiles(changedFiles, false);
|
|
100
|
+
logRepairNextActions(changedFiles, result.warnings);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (Array.isArray(result.changes) && result.changes.length > 0) {
|
|
104
|
+
logger.log(formatSuccessParagraph('Repair actions completed.'));
|
|
105
|
+
result.changes.forEach((c) => logger.log(chalk.gray(` ${c}`)));
|
|
106
|
+
logRepairChangedFiles(changedFiles, false);
|
|
107
|
+
logRepairNextActions(changedFiles, result.warnings);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (result.readmeRegenerated) {
|
|
111
|
+
logger.log(formatSuccessParagraph('Regenerated README.md from deployment manifest.'));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (Array.isArray(result.warnings) && result.warnings.length > 0) {
|
|
115
|
+
logRepairNextActions(changedFiles, result.warnings);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
logger.log(chalk.gray('No changes needed; config already matches files on disk.'));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @param {object} options
|
|
123
|
+
* @param {object} result
|
|
124
|
+
*/
|
|
125
|
+
function logRepairResult(options, result) {
|
|
126
|
+
const changedFiles = result.changedFiles;
|
|
127
|
+
if (options.dryRun && result.updated && result.changes.length > 0) {
|
|
128
|
+
logRepairDryRunOutcome(options, result, changedFiles);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (Array.isArray(result.backupPaths) && result.backupPaths.length > 0) {
|
|
132
|
+
result.backupPaths.forEach((p) => logger.log(chalk.gray(`Backup: ${p}`)));
|
|
133
|
+
}
|
|
134
|
+
logRepairWarnings(result.warnings);
|
|
135
|
+
logRepairSuccessOutcome(result, changedFiles);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @param {string} appName
|
|
140
|
+
* @param {object} options
|
|
141
|
+
* @returns {Promise<void>}
|
|
142
|
+
*/
|
|
143
|
+
async function handleRepairCommand(appName, options) {
|
|
144
|
+
const { repairExternalIntegration } = require('../commands/repair');
|
|
145
|
+
const { appPath } = await detectAppType(appName);
|
|
146
|
+
logOfflinePathWhenType(appPath);
|
|
147
|
+
let format = 'yaml';
|
|
148
|
+
try {
|
|
149
|
+
const config = require('../core/config');
|
|
150
|
+
format = (await config.getFormat()) || format;
|
|
151
|
+
} catch (_) {
|
|
152
|
+
/* default yaml when config unavailable */
|
|
153
|
+
}
|
|
154
|
+
const result = await repairExternalIntegration(
|
|
155
|
+
appName,
|
|
156
|
+
buildRepairExternalIntegrationOptions(appName, options, format)
|
|
157
|
+
);
|
|
158
|
+
logRepairResult(options, result);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @param {import('commander').Command} program
|
|
163
|
+
*/
|
|
164
|
+
function setupRepairCommand(program) {
|
|
165
|
+
program.command('repair <systemKey>')
|
|
166
|
+
.description('Fix external integration drift (files, RBAC, manifest, …)')
|
|
167
|
+
.option('--all', 'Run all repair actions (api, doc, expose, rbac, sync, test)')
|
|
168
|
+
.option(
|
|
169
|
+
'--api',
|
|
170
|
+
'Validate and sync API contracts needed for OpenAPI/MCP (uses local OpenAPI specs at integration/<systemKey>/openapi/*.json when present)'
|
|
171
|
+
)
|
|
172
|
+
.option(
|
|
173
|
+
'--auth <method>',
|
|
174
|
+
'Set authentication method (oauth2, aad, apikey, bearerToken, basic, queryParam, oidc, hmac, none); updates system file and env.template'
|
|
175
|
+
)
|
|
176
|
+
.option('--doc', 'Regenerate README.md from deployment manifest')
|
|
177
|
+
.option('--expose', 'Set exposed.schema on each datasource from all fieldMappings.attributes keys (metadata.<key>); removes deprecated exposed.attributes if present')
|
|
178
|
+
.option('--rbac', 'Ensure RBAC permissions per datasource and add default Admin/Reader roles if none exist')
|
|
179
|
+
.option('--sync', 'Add default sync section to datasources that lack it')
|
|
180
|
+
.option('--test', 'Generate testPayload.payloadTemplate and testPayload.expectedResult from attributes')
|
|
181
|
+
.option('--no-backup', 'Skip timestamped copies under integration/<systemKey>/backup/')
|
|
182
|
+
.option('--dry-run', 'Report changes only; do not write')
|
|
183
|
+
.addHelpText('after', REPAIR_HELP_AFTER)
|
|
184
|
+
.action(async(appName, options) => {
|
|
185
|
+
try {
|
|
186
|
+
await handleRepairCommand(appName, options);
|
|
187
|
+
} catch (error) {
|
|
188
|
+
handleCommandError(error, 'repair');
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
module.exports = {
|
|
195
|
+
setupRepairCommand,
|
|
196
|
+
buildRepairExternalIntegrationOptions,
|
|
197
|
+
logRepairResult
|
|
198
|
+
};
|
|
@@ -8,13 +8,18 @@
|
|
|
8
8
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
|
+
const path = require('path');
|
|
11
12
|
const chalk = require('chalk');
|
|
12
13
|
const secrets = require('../core/secrets');
|
|
14
|
+
const secretsEnsure = require('../core/secrets-ensure');
|
|
13
15
|
const logger = require('../utils/logger');
|
|
14
16
|
const { handleCommandError } = require('../utils/cli-utils');
|
|
15
17
|
const coreConfig = require('../core/config');
|
|
18
|
+
const pathsUtil = require('../utils/paths');
|
|
16
19
|
const { resolvePreferLocalEnvOutputPathFlag } = require('../utils/applications-config-defaults');
|
|
17
20
|
const { getResolveAppPath } = require('../utils/paths');
|
|
21
|
+
const { resolveGenerateEnvEnvironment } = require('../utils/resolve-env-mode');
|
|
22
|
+
const { RESOLVE_HELP_AFTER } = require('./setup-utility-help-after');
|
|
18
23
|
|
|
19
24
|
/**
|
|
20
25
|
* @param {string} appName
|
|
@@ -50,10 +55,17 @@ async function runResolveJsonOutput(appName, appPath, envOnly, envPath, options,
|
|
|
50
55
|
* @param {string} envPath
|
|
51
56
|
* @param {boolean} envOnly
|
|
52
57
|
* @param {{ skipValidation?: boolean }} options
|
|
58
|
+
* @param {'local'|'docker'} environment
|
|
53
59
|
* @returns {Promise<void>}
|
|
54
60
|
*/
|
|
55
|
-
async function runResolveHumanOutput(appName, envPath, envOnly, options) {
|
|
61
|
+
async function runResolveHumanOutput(appName, envPath, envOnly, options, environment) {
|
|
56
62
|
logger.log(`✔ Generated .env file: ${envPath}`);
|
|
63
|
+
if (options.fresh) {
|
|
64
|
+
logger.log(chalk.gray(' Wrote full resolved content (--fresh; did not merge with an existing .env).'));
|
|
65
|
+
}
|
|
66
|
+
if (environment === 'local') {
|
|
67
|
+
logger.log(chalk.gray(' Resolved for local use (host ports; no Docker port rewrite).'));
|
|
68
|
+
}
|
|
57
69
|
logger.log(chalk.gray(' Note: up-platform / up-miso / up-dataplane / register / build resolve secrets in memory only.'));
|
|
58
70
|
logger.log(chalk.gray(` Re-run "aifabrix resolve ${appName}" whenever you need an on-disk .env again.`));
|
|
59
71
|
if (envOnly) {
|
|
@@ -77,9 +89,26 @@ async function runResolveHumanOutput(appName, envPath, envOnly, options) {
|
|
|
77
89
|
* @param {{ force?: boolean, skipValidation?: boolean, json?: boolean }} options
|
|
78
90
|
* @returns {Promise<void>}
|
|
79
91
|
*/
|
|
92
|
+
async function ensureResolveSecretsFromEnvTemplate(appPath, appName) {
|
|
93
|
+
const templatePath = path.join(appPath, 'env.template');
|
|
94
|
+
let emptyValuesForCredentials = false;
|
|
95
|
+
try {
|
|
96
|
+
const appType = await pathsUtil.detectAppType(appName);
|
|
97
|
+
emptyValuesForCredentials = appType?.baseDir === 'integration';
|
|
98
|
+
} catch {
|
|
99
|
+
emptyValuesForCredentials = false;
|
|
100
|
+
}
|
|
101
|
+
await secretsEnsure.ensureSecretsFromEnvTemplate(templatePath, {
|
|
102
|
+
preferredFilePath: pathsUtil.getPrimaryUserSecretsLocalPath(),
|
|
103
|
+
placeholderContext: secretsEnsure.buildInfraPlaceholderContext({}),
|
|
104
|
+
emptyValuesForCredentials
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
80
108
|
async function runResolveAppAction(appName, options) {
|
|
81
109
|
const jsonMode = options.json === true;
|
|
82
110
|
const { appPath, envOnly } = await getResolveAppPath(appName);
|
|
111
|
+
await ensureResolveSecretsFromEnvTemplate(appPath, appName);
|
|
83
112
|
const manifestEmit = require('../utils/manifest-source-emit');
|
|
84
113
|
manifestEmit.emitManifestMetadataLineIfTTY(logger, {
|
|
85
114
|
appKey: appName,
|
|
@@ -89,24 +118,26 @@ async function runResolveAppAction(appName, options) {
|
|
|
89
118
|
});
|
|
90
119
|
const userCfg = await coreConfig.getConfig();
|
|
91
120
|
const preferLocalEnvOutputPath = await resolvePreferLocalEnvOutputPathFlag(userCfg, appName);
|
|
121
|
+
const environment = resolveGenerateEnvEnvironment(appPath, appName);
|
|
92
122
|
const envPath = await secrets.generateEnvFile(
|
|
93
123
|
appName,
|
|
94
124
|
undefined,
|
|
95
|
-
|
|
125
|
+
environment,
|
|
96
126
|
options.force,
|
|
97
127
|
{
|
|
98
128
|
appPath,
|
|
99
129
|
envOnly,
|
|
100
130
|
skipOutputPath: false,
|
|
101
131
|
preserveFromPath: null,
|
|
102
|
-
preferLocalEnvOutputPath
|
|
132
|
+
preferLocalEnvOutputPath,
|
|
133
|
+
freshEnv: options.fresh === true
|
|
103
134
|
}
|
|
104
135
|
);
|
|
105
136
|
if (jsonMode) {
|
|
106
137
|
await runResolveJsonOutput(appName, appPath, envOnly, envPath, options, manifestEmit);
|
|
107
138
|
return;
|
|
108
139
|
}
|
|
109
|
-
await runResolveHumanOutput(appName, envPath, envOnly, options);
|
|
140
|
+
await runResolveHumanOutput(appName, envPath, envOnly, options, environment);
|
|
110
141
|
}
|
|
111
142
|
|
|
112
143
|
/**
|
|
@@ -114,9 +145,14 @@ async function runResolveAppAction(appName, options) {
|
|
|
114
145
|
* @returns {void}
|
|
115
146
|
*/
|
|
116
147
|
function setupResolveCommand(program) {
|
|
117
|
-
program.command('resolve <
|
|
118
|
-
.description('Generate .env from template; optional validate after')
|
|
148
|
+
program.command('resolve <appKey|systemKey>')
|
|
149
|
+
.description('Generate .env from template (builder/<appKey>/ or integration/<systemKey>/); optional validate after')
|
|
150
|
+
.addHelpText('after', RESOLVE_HELP_AFTER)
|
|
119
151
|
.option('-f, --force', 'Generate missing secret keys in secrets file')
|
|
152
|
+
.option(
|
|
153
|
+
'--fresh',
|
|
154
|
+
'Replace .env from env.template (no merge with existing .env or envOutputPath; same as deleting .env first)'
|
|
155
|
+
)
|
|
120
156
|
.option('--skip-validation', 'Skip file validation after generating .env')
|
|
121
157
|
.option('--json', 'Print JSON summary (envPath, manifestSource, optional validation)')
|
|
122
158
|
.action(async(appName, options) => {
|