@aifabrix/builder 2.43.0 ā 2.44.1
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/anchor-docs.mdc +15 -0
- package/.cursor/rules/cli-layout.mdc +75 -0
- package/.cursor/rules/project-rules.mdc +8 -0
- package/.npmrc.token +1 -0
- package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
- package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -0
- package/README.md +1 -1
- package/anchor-docs/README.md +10 -0
- package/anchor-docs/_TEMPLATE +24 -0
- package/bin/aifabrix.js +13 -4
- package/integration/hubspot-test/README.md +31 -0
- package/integration/hubspot-test/create-hubspot.js +5 -5
- package/integration/hubspot-test/hubspot-test-datasource-company.json +58 -462
- package/integration/hubspot-test/hubspot-test-datasource-contact.json +61 -555
- package/integration/hubspot-test/hubspot-test-datasource-deal.json +63 -506
- package/integration/hubspot-test/hubspot-test-datasource-users.json +42 -83
- package/integration/hubspot-test/hubspot-test-deploy.json +3 -3
- package/integration/hubspot-test/test-dataplane-down-tests.js +1 -7
- package/integration/hubspot-test/test-dataplane-down.js +3 -3
- package/integration/hubspot-test/test.js +35 -43
- package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +23 -0
- package/integration/roundtrip-test-local/README.md +144 -0
- package/integration/roundtrip-test-local/application.yaml +13 -0
- package/integration/roundtrip-test-local/env.template +15 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +14 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +61 -0
- package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +25 -0
- package/integration/roundtrip-test-local2/README.md +144 -0
- package/integration/roundtrip-test-local2/application.yaml +13 -0
- package/integration/roundtrip-test-local2/env.template +15 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +31 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +86 -0
- package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +25 -0
- package/integration/test/wizard.yaml +8 -0
- package/jest.config.default.js +10 -0
- package/jest.config.integration.fixtures.js +22 -0
- package/jest.config.integration.js +21 -18
- package/jest.config.isolated.js +10 -0
- package/jest.projects.js +301 -0
- package/lib/api/certificates.api.js +62 -0
- package/lib/api/datasources-core.api.js +3 -3
- package/lib/api/dev-mtls-request.js +110 -0
- package/lib/api/dev-server-https.js +145 -0
- package/lib/api/dev.api.js +133 -144
- package/lib/api/index.js +11 -3
- package/lib/api/pipeline.api.js +67 -20
- package/lib/api/types/certificates.types.js +48 -0
- package/lib/api/types/dev.types.js +4 -3
- package/lib/api/types/pipeline.types.js +8 -5
- package/lib/api/types/validation-run.types.js +56 -0
- package/lib/api/validation-run.api.js +111 -0
- package/lib/api/validation-runner.js +109 -0
- package/lib/app/certification-show-enrich.js +129 -0
- package/lib/app/certification-verify-rows.js +60 -0
- package/lib/app/config.js +1 -1
- package/lib/app/deploy-status-display.js +2 -2
- package/lib/app/deploy.js +7 -6
- package/lib/app/display.js +2 -1
- package/lib/app/dockerfile.js +3 -2
- package/lib/app/down.js +2 -1
- package/lib/app/helpers.js +6 -5
- package/lib/app/index.js +27 -8
- package/lib/app/list.js +7 -6
- package/lib/app/push.js +4 -3
- package/lib/app/register.js +16 -7
- package/lib/app/rotate-secret.js +14 -13
- package/lib/app/run-container-start.js +184 -0
- package/lib/app/run-docker-fallback.js +108 -0
- package/lib/app/run-env-compose.js +30 -42
- package/lib/app/run-helpers.js +49 -126
- package/lib/app/run-infra-requirements.js +30 -0
- package/lib/app/run-resolve-image.js +21 -0
- package/lib/app/run.js +74 -21
- package/lib/app/show-display.js +44 -1
- package/lib/app/show.js +93 -9
- package/lib/build/index.js +13 -10
- package/lib/certification/cli-cert-sync-skip.js +21 -0
- package/lib/certification/merge-certification-from-artifact.js +185 -0
- package/lib/certification/post-unified-cert-sync.js +33 -0
- package/lib/certification/sync-after-external-command.js +52 -0
- package/lib/certification/sync-system-certification.js +197 -0
- package/lib/cli/index.js +2 -0
- package/lib/cli/setup-app.help.js +67 -0
- package/lib/cli/setup-app.js +61 -121
- package/lib/cli/setup-app.test-commands.js +195 -0
- package/lib/cli/setup-auth.js +19 -5
- package/lib/cli/setup-credential-deployment.js +22 -8
- package/lib/cli/setup-dev-path-commands.js +124 -0
- package/lib/cli/setup-dev.js +170 -113
- package/lib/cli/setup-environment.js +7 -1
- package/lib/cli/setup-external-system.js +84 -23
- package/lib/cli/setup-infra.js +126 -47
- package/lib/cli/setup-parameters.js +32 -0
- package/lib/cli/setup-secrets.js +137 -18
- package/lib/cli/setup-service-user.js +1 -1
- package/lib/cli/setup-utility.js +54 -22
- package/lib/commands/app-down.js +5 -7
- package/lib/commands/app-install.js +14 -7
- package/lib/commands/app-logs.js +13 -10
- package/lib/commands/app-shell.js +4 -1
- package/lib/commands/app-test.js +25 -19
- package/lib/commands/app.js +32 -11
- package/lib/commands/auth-config.js +6 -6
- package/lib/commands/auth-status.js +4 -3
- package/lib/commands/credential-env.js +4 -3
- package/lib/commands/credential-list.js +5 -4
- package/lib/commands/credential-push.js +4 -3
- package/lib/commands/datasource-unified-test-cli.js +428 -0
- package/lib/commands/datasource-unified-test-cli.options.js +191 -0
- package/lib/commands/datasource-unified-test-e2e-cli-helpers.js +106 -0
- package/lib/commands/datasource-validation-cli.js +143 -0
- package/lib/commands/datasource.js +125 -95
- package/lib/commands/deployment-list.js +6 -5
- package/lib/commands/dev-cli-handlers.js +122 -18
- package/lib/commands/dev-down.js +4 -3
- package/lib/commands/dev-init.js +231 -116
- package/lib/commands/dev-show-display.js +473 -0
- package/lib/commands/login-credentials.js +3 -2
- package/lib/commands/login-device.js +4 -3
- package/lib/commands/login.js +5 -4
- package/lib/commands/logout.js +8 -7
- package/lib/commands/parameters-validate.js +54 -0
- package/lib/commands/repair-datasource.js +314 -68
- package/lib/commands/repair-env-template.js +2 -2
- package/lib/commands/repair.js +21 -3
- package/lib/commands/secrets-list.js +23 -12
- package/lib/commands/secrets-remove-all.js +220 -0
- package/lib/commands/secrets-remove.js +21 -12
- package/lib/commands/secrets-set.js +21 -12
- package/lib/commands/secrets-validate.js +4 -4
- package/lib/commands/secure.js +10 -9
- package/lib/commands/service-user.js +26 -25
- package/lib/commands/test-e2e-external.js +27 -1
- package/lib/commands/up-common.js +3 -2
- package/lib/commands/up-dataplane.js +29 -16
- package/lib/commands/up-miso.js +19 -29
- package/lib/commands/upload.js +149 -39
- package/lib/commands/wizard-core-helpers.js +1 -1
- package/lib/commands/wizard-dataplane.js +4 -3
- package/lib/commands/wizard-helpers.js +3 -3
- package/lib/commands/wizard.js +2 -2
- package/lib/core/admin-secrets.js +14 -5
- package/lib/core/audit-logger.js +12 -4
- package/lib/core/config-attach-extensions.js +46 -0
- package/lib/core/config-runtime-paths.js +29 -0
- package/lib/core/config.js +55 -56
- package/lib/core/diff.js +3 -2
- package/lib/core/ensure-encryption-key.js +1 -1
- package/lib/core/secrets-ensure-infra.js +77 -0
- package/lib/core/secrets-ensure.js +120 -64
- package/lib/core/secrets-env-write.js +35 -7
- package/lib/core/secrets-infra-placeholder-sync.js +61 -0
- package/lib/core/secrets.js +200 -37
- package/lib/core/templates-env.js +4 -3
- package/lib/datasource/abac-validator.js +1 -10
- package/lib/datasource/deploy.js +75 -53
- package/lib/datasource/field-reference-validator.js +9 -6
- package/lib/datasource/integration-context.js +63 -0
- package/lib/datasource/list.js +8 -7
- package/lib/datasource/log-viewer.js +189 -67
- package/lib/datasource/resolve-app.js +4 -4
- package/lib/datasource/test-e2e.js +113 -146
- package/lib/datasource/test-integration.js +114 -122
- package/lib/datasource/unified-validation-run-body.js +68 -0
- package/lib/datasource/unified-validation-run-post.js +23 -0
- package/lib/datasource/unified-validation-run-resolve.js +43 -0
- package/lib/datasource/unified-validation-run.js +93 -0
- package/lib/datasource/validate.js +157 -13
- package/lib/deployment/deployer.js +4 -3
- package/lib/deployment/environment.js +7 -6
- package/lib/deployment/push.js +17 -8
- package/lib/external-system/delete.js +4 -3
- package/lib/external-system/deploy.js +166 -53
- package/lib/external-system/download-helpers.js +1 -1
- package/lib/external-system/download.js +7 -6
- package/lib/external-system/generator.js +92 -6
- package/lib/external-system/integration-test-dispatch.js +26 -0
- package/lib/external-system/test-execution.js +5 -1
- package/lib/external-system/test-helpers.js +0 -4
- package/lib/external-system/test-system-level-helpers.js +110 -0
- package/lib/external-system/test-system-level.js +83 -44
- package/lib/external-system/test.js +59 -8
- package/lib/generator/builders.js +23 -11
- package/lib/generator/deploy-manifest-azure-kv.js +81 -0
- package/lib/generator/external.js +16 -4
- package/lib/generator/helpers.js +58 -3
- package/lib/generator/index.js +4 -0
- package/lib/generator/split-readme.js +12 -7
- package/lib/generator/split-variables.js +2 -1
- package/lib/generator/split.js +1 -1
- package/lib/generator/wizard-readme.js +3 -3
- package/lib/generator/wizard.js +8 -8
- package/lib/infrastructure/compose.js +70 -7
- package/lib/infrastructure/helpers-docker-check.js +67 -0
- package/lib/infrastructure/helpers.js +203 -42
- package/lib/infrastructure/index.js +31 -18
- package/lib/infrastructure/services.js +21 -67
- package/lib/internal/fs-real-sync.js +104 -0
- package/lib/internal/node-fs.js +98 -0
- package/lib/parameters/database-secret-values.js +173 -0
- package/lib/parameters/infra-kv-discovery.js +121 -0
- package/lib/parameters/infra-parameter-catalog.js +458 -0
- package/lib/parameters/infra-parameter-validate.js +64 -0
- package/lib/schema/application-schema.json +37 -17
- package/lib/schema/datasource-test-run.schema.json +493 -0
- package/lib/schema/deployment-rules.yaml +102 -63
- package/lib/schema/external-datasource.schema.json +1200 -442
- package/lib/schema/external-system.schema.json +203 -5
- package/lib/schema/flag-map-validation-run.json +31 -0
- package/lib/schema/infra-parameter.schema.json +106 -0
- package/lib/schema/infra.parameter.yaml +421 -0
- package/lib/schema/type/credential-auth-templates.json +40 -0
- package/lib/schema/type/document-storage.json +226 -0
- package/lib/schema/type/message-service.json +123 -0
- package/lib/schema/type/vector-store.json +88 -0
- package/lib/utils/aifabrix-runtime-config-dir.js +132 -0
- package/lib/utils/api-error-handler.js +2 -2
- package/lib/utils/api.js +77 -17
- package/lib/utils/app-register-api.js +3 -2
- package/lib/utils/app-register-auth.js +1 -1
- package/lib/utils/app-register-config.js +4 -4
- package/lib/utils/app-register-display.js +3 -2
- package/lib/utils/app-register-validator.js +3 -2
- package/lib/utils/app-run-containers.js +26 -22
- package/lib/utils/app-scoped-config.js +31 -0
- package/lib/utils/app-service-env-from-builder.js +164 -0
- package/lib/utils/build-copy.js +1 -1
- package/lib/utils/build-helpers.js +20 -20
- package/lib/utils/build-resolve-image.js +165 -0
- package/lib/utils/cli-layout-chalk.js +8 -0
- package/lib/utils/cli-test-layout-chalk.js +267 -0
- package/lib/utils/cli-utils.js +88 -11
- package/lib/utils/compose-db-passwords.js +138 -0
- package/lib/utils/compose-generate-docker-compose.js +216 -0
- package/lib/utils/compose-generator.js +197 -291
- package/lib/utils/compose-miso-env.js +18 -0
- package/lib/utils/compose-traefik-ingress-base.js +158 -0
- package/lib/utils/config-paths.js +166 -7
- package/lib/utils/config-scoped-resources-preference.js +41 -0
- package/lib/utils/configuration-env-resolver.js +11 -8
- package/lib/utils/controller-deployment-outcome.js +68 -0
- package/lib/utils/credential-display.js +2 -2
- package/lib/utils/credential-secrets-env.js +5 -5
- package/lib/utils/dataplane-pipeline-warning.js +4 -3
- package/lib/utils/datasource-test-run-capability-scope.js +43 -0
- package/lib/utils/datasource-test-run-certificate-tty.js +82 -0
- package/lib/utils/datasource-test-run-debug-display.js +137 -0
- package/lib/utils/datasource-test-run-debug-slice.js +93 -0
- package/lib/utils/datasource-test-run-display.js +459 -0
- package/lib/utils/datasource-test-run-exit.js +83 -0
- package/lib/utils/datasource-test-run-legacy-adapter.js +93 -0
- package/lib/utils/datasource-test-run-report-version.js +51 -0
- package/lib/utils/datasource-test-run-schema-sync.js +59 -0
- package/lib/utils/datasource-test-run-tty-log.js +81 -0
- package/lib/utils/datasource-validation-watch.js +266 -0
- package/lib/utils/declarative-url-ports.js +47 -0
- package/lib/utils/derive-env-key-from-client-id.js +41 -0
- package/lib/utils/dev-ca-install.js +185 -23
- package/lib/utils/dev-cert-helper.js +266 -17
- package/lib/utils/dev-hosts-helper.js +307 -0
- package/lib/utils/dev-init-cert-hints.js +37 -0
- package/lib/utils/dev-init-health-messages.js +52 -0
- package/lib/utils/dev-init-resolve.js +86 -0
- package/lib/utils/dev-init-ssh-merge.js +65 -0
- package/lib/utils/dev-ssh-config-helper.js +196 -0
- package/lib/utils/dev-user-groups.js +93 -0
- package/lib/utils/docker-build.js +42 -17
- package/lib/utils/docker-exec.js +28 -0
- package/lib/utils/docker-manifest-public-port.js +116 -0
- package/lib/utils/docker-not-running-hint.js +52 -0
- package/lib/utils/docker.js +98 -11
- package/lib/utils/ensure-dev-certs-for-remote-docker.js +192 -0
- package/lib/utils/env-config-loader.js +10 -91
- package/lib/utils/env-copy.js +19 -10
- package/lib/utils/env-map.js +35 -8
- package/lib/utils/env-template.js +2 -2
- package/lib/utils/environment-scoped-resources.js +144 -0
- package/lib/utils/error-formatter.js +92 -13
- package/lib/utils/error-formatters/http-status-errors.js +6 -5
- package/lib/utils/error-formatters/network-errors.js +2 -1
- package/lib/utils/error-formatters/permission-errors.js +2 -1
- package/lib/utils/error-formatters/validation-errors.js +2 -1
- package/lib/utils/external-readme.js +8 -1
- package/lib/utils/external-system-display.js +242 -136
- package/lib/utils/external-system-local-test-tty.js +389 -0
- package/lib/utils/external-system-readiness-core.js +377 -0
- package/lib/utils/external-system-readiness-deploy-display.js +270 -0
- package/lib/utils/external-system-readiness-display-internals.js +150 -0
- package/lib/utils/external-system-readiness-display.js +186 -0
- package/lib/utils/external-system-system-test-tty-overview.js +120 -0
- package/lib/utils/external-system-system-test-tty.js +417 -0
- package/lib/utils/external-system-test-helpers.js +24 -6
- package/lib/utils/external-system-validators.js +30 -12
- package/lib/utils/health-check-url.js +119 -0
- package/lib/utils/health-check.js +59 -25
- package/lib/utils/help-builder.js +11 -8
- package/lib/utils/image-version.js +4 -8
- package/lib/utils/infra-containers.js +4 -7
- package/lib/utils/infra-env-defaults.js +162 -0
- package/lib/utils/infra-status-display.js +167 -0
- package/lib/utils/infra-status.js +16 -8
- package/lib/utils/local-secrets.js +3 -4
- package/lib/utils/paths.js +148 -47
- package/lib/utils/port-resolver.js +10 -23
- package/lib/utils/redis-env-scope.js +62 -0
- package/lib/utils/register-aifabrix-shell-env.js +204 -0
- package/lib/utils/remote-builder-validation.js +99 -0
- package/lib/utils/remote-dev-auth.js +117 -21
- package/lib/utils/remote-docker-env.js +67 -15
- package/lib/utils/remote-secrets-loader.js +13 -4
- package/lib/utils/resolve-docker-image-ref.js +124 -0
- package/lib/utils/schema-loader.js +22 -9
- package/lib/utils/secrets-bash-kv.js +25 -0
- package/lib/utils/secrets-generator.js +169 -49
- package/lib/utils/secrets-helpers.js +70 -59
- package/lib/utils/secrets-kv-scope.js +60 -0
- package/lib/utils/secrets-utils.js +32 -38
- package/lib/utils/secrets-validation.js +3 -1
- package/lib/utils/secrets-yaml-preserve.js +109 -0
- package/lib/utils/ssh-key-helper.js +4 -2
- package/lib/utils/template-helpers.js +2 -2
- package/lib/utils/test-log-writer.js +3 -3
- package/lib/utils/token-manager.js +1 -2
- package/lib/utils/url-declarative-public-base.js +188 -0
- package/lib/utils/url-declarative-resolve-build.js +493 -0
- package/lib/utils/url-declarative-resolve-load-doc.js +51 -0
- package/lib/utils/url-declarative-resolve.js +220 -0
- package/lib/utils/url-declarative-token-parse.js +74 -0
- package/lib/utils/url-declarative-url-flags.js +50 -0
- package/lib/utils/url-declarative-vdir-inactive-env.js +99 -0
- package/lib/utils/url-public-path-prefix.js +34 -0
- package/lib/utils/urls-local-registry.js +220 -0
- package/lib/utils/validation-report-tty-kit.js +77 -0
- package/lib/utils/validation-run-poll.js +112 -0
- package/lib/utils/validation-run-post-retry.js +85 -0
- package/lib/utils/validation-run-request.js +116 -0
- package/lib/utils/variable-transformer.js +21 -4
- package/lib/utils/yaml-preserve.js +33 -14
- package/lib/validation/datasource-warnings.js +56 -0
- package/lib/validation/env-template-auth.js +1 -1
- package/lib/validation/external-manifest-validator.js +27 -7
- package/lib/validation/validate-display.js +37 -31
- package/lib/validation/validate-external-cert-sync.js +23 -0
- package/lib/validation/validate.js +8 -14
- package/lib/validation/validator-unresolved-placeholders.js +98 -0
- package/lib/validation/validator.js +22 -65
- package/lib/validation/wizard-config-validator.js +2 -1
- package/package.json +9 -4
- package/scripts/check-datasource-test-run-schema-sync.js +34 -0
- package/scripts/diagnose-cli.js +150 -0
- package/scripts/install-local.js +307 -55
- package/scripts/pnpm-global-remove.js +48 -0
- package/templates/README.md +15 -2
- package/templates/applications/dataplane/application.yaml +52 -2
- package/templates/applications/dataplane/env.template +79 -17
- package/templates/applications/dataplane/rbac.yaml +8 -0
- package/templates/applications/keycloak/application.yaml +9 -1
- package/templates/applications/keycloak/env.template +15 -6
- package/templates/applications/miso-controller/application.yaml +10 -2
- package/templates/applications/miso-controller/env.template +42 -12
- package/templates/applications/miso-controller/rbac.yaml +5 -0
- package/templates/external-system/README.md.hbs +20 -7
- package/templates/external-system/deploy.js.hbs +5 -5
- package/templates/external-system/external-datasource.yaml.hbs +197 -118
- package/templates/infra/compose.yaml.hbs +33 -16
- package/templates/infra/servers.json.hbs +3 -1
- package/templates/python/docker-compose.hbs +16 -0
- package/templates/typescript/docker-compose.hbs +16 -0
- package/lib/api/external-test.api.js +0 -111
- package/lib/schema/env-config.yaml +0 -60
package/lib/commands/dev-init.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
const { formatSuccessLine, formatSuccessParagraph } = require('../utils/cli-test-layout-chalk');
|
|
1
2
|
/**
|
|
2
|
-
* @fileoverview aifabrix dev init ā onboard with Builder Server (issue-cert, save cert, get settings, add SSH key).
|
|
3
|
-
* Auth: first call (issue-cert) uses no client cert;
|
|
3
|
+
* @fileoverview aifabrix dev init ā onboard with Builder Server (issue-cert, save cert, get settings, add SSH key, SSH config alias).
|
|
4
|
+
* Auth: first call (issue-cert) uses no client cert; other calls send the client cert (mTLS on https, X-Client-Cert header on http for getSettings/addSshKey).
|
|
4
5
|
* @author AI Fabrix Team
|
|
5
6
|
* @version 2.0.0
|
|
6
7
|
*/
|
|
@@ -10,69 +11,138 @@ const path = require('path');
|
|
|
10
11
|
const chalk = require('chalk');
|
|
11
12
|
const config = require('../core/config');
|
|
12
13
|
const { getConfigDirForPaths } = require('../utils/paths');
|
|
13
|
-
const {
|
|
14
|
+
const {
|
|
15
|
+
generateCSR,
|
|
16
|
+
getCertDir,
|
|
17
|
+
readClientCertPem,
|
|
18
|
+
readClientKeyPem,
|
|
19
|
+
getCertValidNotAfter,
|
|
20
|
+
normalizePemNewlines,
|
|
21
|
+
mergeCaPemBlocks
|
|
22
|
+
} = require('../utils/dev-cert-helper');
|
|
14
23
|
const { getOrCreatePublicKeyContent } = require('../utils/ssh-key-helper');
|
|
15
24
|
const devApi = require('../api/dev.api');
|
|
16
25
|
const logger = require('../utils/logger');
|
|
17
26
|
const {
|
|
18
27
|
isSslUntrustedError,
|
|
28
|
+
isSslHostnameMismatchError,
|
|
19
29
|
fetchInstallCa,
|
|
20
30
|
installCaPlatform,
|
|
21
|
-
promptInstallCa
|
|
31
|
+
promptInstallCa,
|
|
32
|
+
isLinuxCaSudoRequiredError
|
|
22
33
|
} = require('../utils/dev-ca-install');
|
|
34
|
+
const { runOptionalHostsSetup } = require('../utils/dev-hosts-helper');
|
|
35
|
+
const { mergeDevSshConfigAfterInit } = require('../utils/dev-init-ssh-merge');
|
|
36
|
+
const { resolveInitOptions } = require('../utils/dev-init-resolve');
|
|
37
|
+
const { displayDevConfig } = require('./dev-show-display');
|
|
38
|
+
const {
|
|
39
|
+
isHealthHttpServerError,
|
|
40
|
+
formatEnsureServerTrustedFailure
|
|
41
|
+
} = require('../utils/dev-init-health-messages');
|
|
42
|
+
const { getBadRequestHint, logCertTroubleshootingHint } = require('../utils/dev-init-cert-hints');
|
|
23
43
|
|
|
24
44
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
45
|
+
* Install dev CA into the OS trust store. On Linux without sudo, log and return false so the caller can use in-process PEM.
|
|
46
|
+
* @param {Buffer} caBuf - CA PEM buffer
|
|
47
|
+
* @param {string} baseUrlForInstall - Builder Server base URL (for install-ca-help paths)
|
|
48
|
+
* @returns {Promise<boolean>} true if the OS store was updated
|
|
49
|
+
*/
|
|
50
|
+
async function tryInstallDevCaToOsStoreOrWarnLinuxSudo(caBuf, baseUrlForInstall) {
|
|
51
|
+
try {
|
|
52
|
+
await installCaPlatform(caBuf, baseUrlForInstall);
|
|
53
|
+
return true;
|
|
54
|
+
} catch (installErr) {
|
|
55
|
+
if (isLinuxCaSudoRequiredError(installErr)) {
|
|
56
|
+
logger.log(
|
|
57
|
+
chalk.yellow(
|
|
58
|
+
' ā Could not install the development CA into the system trust store (sudo/root required). ' +
|
|
59
|
+
'Continuing with the downloaded CA for this CLI session; browsers and curl may still warn until you install it manually.\n' +
|
|
60
|
+
' ' +
|
|
61
|
+
(installErr.message || String(installErr))
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
throw installErr;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Prompt, fetch dev CA, install into OS store, verify health with PEM for Node TLS.
|
|
27
72
|
* @param {string} baseUrl - Builder Server base URL
|
|
28
|
-
* @param {Object} options - Commander options
|
|
29
|
-
* @returns {Promise<
|
|
73
|
+
* @param {Object} options - Commander options
|
|
74
|
+
* @returns {Promise<string>} Dev root CA PEM
|
|
30
75
|
*/
|
|
31
|
-
async function
|
|
76
|
+
async function installDevCaAndRetryHealth(baseUrl, options) {
|
|
32
77
|
const skipInstall = options['no-install-ca'];
|
|
33
78
|
const autoInstall = options.yes || options.y;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
79
|
+
const manualUrl = `${baseUrl.replace(/\/+$/, '')}/install-ca`;
|
|
80
|
+
if (skipInstall) {
|
|
81
|
+
throw new Error(`Server certificate not trusted. Install CA manually: ${manualUrl}`);
|
|
82
|
+
}
|
|
83
|
+
if (!autoInstall) {
|
|
84
|
+
const install = await promptInstallCa();
|
|
85
|
+
if (!install) {
|
|
40
86
|
throw new Error(`Server certificate not trusted. Install CA manually: ${manualUrl}`);
|
|
41
87
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
88
|
+
}
|
|
89
|
+
logger.log(chalk.gray(' Downloading and installing CA...'));
|
|
90
|
+
const caBuf = await fetchInstallCa(baseUrl);
|
|
91
|
+
const caPemStr = caBuf.toString('utf8').trim();
|
|
92
|
+
const installedToOsStore = await tryInstallDevCaToOsStoreOrWarnLinuxSudo(caBuf, baseUrl);
|
|
93
|
+
logger.log(
|
|
94
|
+
chalk.gray(
|
|
95
|
+
installedToOsStore ? ' CA installed. Retrying...' : ' Retrying with downloaded CA (in-process trust)...'
|
|
96
|
+
)
|
|
97
|
+
);
|
|
98
|
+
try {
|
|
99
|
+
await devApi.getHealth(baseUrl, caPemStr);
|
|
100
|
+
} catch (healthErr) {
|
|
101
|
+
if (isHealthHttpServerError(healthErr)) {
|
|
102
|
+
logger.log(
|
|
103
|
+
chalk.yellow(
|
|
104
|
+
` ā GET /health returned HTTP ${healthErr.status} (${healthErr.message || 'Server Error'}). ` +
|
|
105
|
+
'TLS is verified; continuing with certificate onboarding.'
|
|
106
|
+
)
|
|
107
|
+
);
|
|
108
|
+
} else {
|
|
109
|
+
throw healthErr;
|
|
47
110
|
}
|
|
48
|
-
logger.log(chalk.gray(' Downloading and installing CA...'));
|
|
49
|
-
const caPem = await fetchInstallCa(baseUrl);
|
|
50
|
-
await installCaPlatform(caPem, baseUrl);
|
|
51
|
-
logger.log(chalk.gray(' CA installed. Retrying...'));
|
|
52
|
-
await devApi.getHealth(baseUrl);
|
|
53
111
|
}
|
|
112
|
+
return caPemStr;
|
|
54
113
|
}
|
|
55
114
|
|
|
56
115
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* @
|
|
116
|
+
* Ensure the Builder Server is trusted: run health check; on SSL untrusted error,
|
|
117
|
+
* optionally fetch and install CA, then retry using the PEM in-process (Node does not use Windows user ROOT for fetch).
|
|
118
|
+
* @param {string} baseUrl - Builder Server base URL
|
|
119
|
+
* @param {Object} options - Commander options (yes, y, no-install-ca)
|
|
120
|
+
* @returns {Promise<string|null>} Dev root CA PEM to pass to dev API for TLS, or null if no install-ca path was used
|
|
60
121
|
*/
|
|
61
|
-
function
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
122
|
+
async function ensureServerTrusted(baseUrl, options) {
|
|
123
|
+
try {
|
|
124
|
+
await devApi.getHealth(baseUrl);
|
|
125
|
+
return null;
|
|
126
|
+
} catch (err) {
|
|
127
|
+
if (isSslHostnameMismatchError(err)) {
|
|
128
|
+
throw new Error(
|
|
129
|
+
`TLS hostname does not match the server certificate for ${baseUrl}. Open the site in a browser only after accepting a warning, or the certificate may list a different DNS name. Use a URL whose hostname is in the certificate (SAN), or reissue the server certificate for this host.`
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
if (!isSslUntrustedError(err)) {
|
|
133
|
+
if (isHealthHttpServerError(err)) {
|
|
134
|
+
logger.log(
|
|
135
|
+
chalk.yellow(
|
|
136
|
+
` ā GET /health returned HTTP ${err.status} (${err.message || 'Server Error'}). ` +
|
|
137
|
+
'Continuing certificate onboarding; fix server health if later steps fail.'
|
|
138
|
+
)
|
|
139
|
+
);
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
throw err;
|
|
143
|
+
}
|
|
144
|
+
return installDevCaAndRetryHealth(baseUrl, options);
|
|
74
145
|
}
|
|
75
|
-
return { baseUrl: server.trim().replace(/\/+$/, ''), devId };
|
|
76
146
|
}
|
|
77
147
|
|
|
78
148
|
/**
|
|
@@ -81,15 +151,16 @@ function validateInitOptions(options) {
|
|
|
81
151
|
* @param {string} devId - Developer ID
|
|
82
152
|
* @param {string} pin - One-time PIN
|
|
83
153
|
* @param {string} csrPem - PEM CSR
|
|
154
|
+
* @param {string} [serverCaPem] - Dev root CA for Node TLS (after install-ca)
|
|
84
155
|
* @returns {Promise<Object>} IssueCertResponseDto
|
|
85
156
|
*/
|
|
86
|
-
async function requestCertificate(baseUrl, devId, pin, csrPem) {
|
|
157
|
+
async function requestCertificate(baseUrl, devId, pin, csrPem, serverCaPem) {
|
|
87
158
|
try {
|
|
88
159
|
return await devApi.issueCert(baseUrl, {
|
|
89
160
|
developerId: devId,
|
|
90
161
|
pin: pin.trim(),
|
|
91
162
|
csr: csrPem
|
|
92
|
-
});
|
|
163
|
+
}, serverCaPem);
|
|
93
164
|
} catch (err) {
|
|
94
165
|
if (err.status === 401) {
|
|
95
166
|
throw new Error('Invalid or expired PIN. Ask your admin for a new PIN (aifabrix dev pin <developerId>).');
|
|
@@ -104,17 +175,6 @@ async function requestCertificate(baseUrl, devId, pin, csrPem) {
|
|
|
104
175
|
}
|
|
105
176
|
}
|
|
106
177
|
|
|
107
|
-
/**
|
|
108
|
-
* Normalize PEM string: turn literal \n (backslash-n) into real newlines so Docker/OpenSSL accept it.
|
|
109
|
-
* Some servers return JSON with escaped newlines in the PEM string.
|
|
110
|
-
* @param {string} pem - PEM string (certificate or CA)
|
|
111
|
-
* @returns {string} PEM with real newlines
|
|
112
|
-
*/
|
|
113
|
-
function normalizePemNewlines(pem) {
|
|
114
|
-
if (typeof pem !== 'string') return pem;
|
|
115
|
-
return pem.replace(/\\n/g, '\n');
|
|
116
|
-
}
|
|
117
|
-
|
|
118
178
|
/**
|
|
119
179
|
* Save certificate, key, and optional CA to cert dir; set developer-id in config.
|
|
120
180
|
* Remote Docker requires ca.pem in the cert dir; if the server provides it (e.g. issue-cert
|
|
@@ -135,34 +195,12 @@ async function saveCertAndConfig(configDir, devId, certificatePem, keyPem, caPem
|
|
|
135
195
|
if (caPem && typeof caPem === 'string' && caPem.trim()) {
|
|
136
196
|
const caNormalized = normalizePemNewlines(caPem.trim());
|
|
137
197
|
await fs.writeFile(path.join(certDir, 'ca.pem'), caNormalized, { mode: 0o600 });
|
|
138
|
-
logger.log(chalk.green('
|
|
198
|
+
logger.log(chalk.green(' ā Certificate and CA saved to ') + chalk.cyan(path.join(certDir, 'cert.pem')));
|
|
139
199
|
} else {
|
|
140
|
-
logger.log(chalk.green('
|
|
200
|
+
logger.log(chalk.green(' ā Certificate saved to ') + chalk.cyan(path.join(certDir, 'cert.pem')));
|
|
141
201
|
}
|
|
142
202
|
await config.setDeveloperId(devId);
|
|
143
|
-
logger.log(chalk.green('
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Message for 400 Bad Request: nginx often forwards X-Client-Cert with literal newlines.
|
|
148
|
-
* @returns {string} Hint for server-side nginx fix
|
|
149
|
-
*/
|
|
150
|
-
function getBadRequestHint() {
|
|
151
|
-
return 'Bad Request (400) often means the server\'s nginx is forwarding the client certificate with literal newlines in X-Client-Cert. On the server, use nginx njs to escape newlines (see .cursor/plans/builder-cli.md §5).';
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Log a one-line hint for cert troubleshooting (curl test and docs).
|
|
156
|
-
* @param {string} configDir - Config directory
|
|
157
|
-
* @param {string} devId - Developer ID
|
|
158
|
-
* @param {string} baseUrl - Builder Server base URL
|
|
159
|
-
*/
|
|
160
|
-
function logCertTroubleshootingHint(configDir, devId, baseUrl) {
|
|
161
|
-
const certDir = getCertDir(configDir, devId);
|
|
162
|
-
const certPath = path.join(certDir, 'cert.pem');
|
|
163
|
-
const keyPath = path.join(certDir, 'key.pem');
|
|
164
|
-
logger.log(chalk.gray(` Test with: curl -v --cert ${certPath} --key ${keyPath} ${baseUrl}/api/dev/settings`));
|
|
165
|
-
logger.log(chalk.gray(' See .cursor/plans/builder-cli.md §5 for 200 vs 401 vs 400 and nginx/server fix.'));
|
|
203
|
+
logger.log(chalk.green(' ā Developer ID set to ') + chalk.cyan(devId));
|
|
166
204
|
}
|
|
167
205
|
|
|
168
206
|
/**
|
|
@@ -172,14 +210,14 @@ function logCertTroubleshootingHint(configDir, devId, baseUrl) {
|
|
|
172
210
|
* @param {string} clientKeyPem - Client private key PEM (for mTLS)
|
|
173
211
|
* @param {string} devId - Developer ID
|
|
174
212
|
*/
|
|
175
|
-
async function registerSshKey(baseUrl, clientCertPem, clientKeyPem, devId) {
|
|
213
|
+
async function registerSshKey(baseUrl, clientCertPem, clientKeyPem, devId, serverCaPem) {
|
|
176
214
|
const publicKey = getOrCreatePublicKeyContent();
|
|
177
215
|
try {
|
|
178
216
|
await devApi.addSshKey(baseUrl, clientCertPem, devId, {
|
|
179
217
|
publicKey,
|
|
180
218
|
label: 'aifabrix-init'
|
|
181
|
-
}, clientKeyPem);
|
|
182
|
-
logger.log(chalk.green('
|
|
219
|
+
}, clientKeyPem, serverCaPem);
|
|
220
|
+
logger.log(chalk.green(' ā SSH key registered'));
|
|
183
221
|
} catch (err) {
|
|
184
222
|
if (err.status === 409) {
|
|
185
223
|
logger.log(chalk.yellow(' ā SSH key already registered'));
|
|
@@ -198,13 +236,13 @@ async function registerSshKey(baseUrl, clientCertPem, clientKeyPem, devId) {
|
|
|
198
236
|
* @param {string} devId - Developer ID
|
|
199
237
|
* @private
|
|
200
238
|
*/
|
|
201
|
-
async function _runSshKeyRegistrationStep(baseUrl, issueResponse, keyPem, configDir, devId) {
|
|
239
|
+
async function _runSshKeyRegistrationStep(baseUrl, issueResponse, keyPem, configDir, devId, serverCaPem) {
|
|
202
240
|
logger.log(chalk.gray(' Registering SSH key for Mutagen sync...'));
|
|
203
241
|
try {
|
|
204
242
|
if (keyPem && typeof keyPem === 'string') {
|
|
205
243
|
logger.log(chalk.gray(' Using client certificate for TLS'));
|
|
206
244
|
}
|
|
207
|
-
await registerSshKey(baseUrl, issueResponse.certificate, keyPem, devId);
|
|
245
|
+
await registerSshKey(baseUrl, issueResponse.certificate, keyPem, devId, serverCaPem);
|
|
208
246
|
} catch (err) {
|
|
209
247
|
const msg = err.status === 400 ? getBadRequestHint() : (err.message || String(err));
|
|
210
248
|
logger.log(chalk.yellow(' ā Could not register SSH key: ' + msg));
|
|
@@ -218,12 +256,13 @@ async function _runSshKeyRegistrationStep(baseUrl, issueResponse, keyPem, config
|
|
|
218
256
|
* @param {string} devId - Developer ID
|
|
219
257
|
* @param {Object} issueResponse - IssueCert response (certificate, settings)
|
|
220
258
|
* @param {string} keyPem - Client key PEM
|
|
259
|
+
* @param {string} [serverCaPem] - Dev root CA for Node TLS
|
|
221
260
|
*/
|
|
222
|
-
async function applySettingsFromServer(baseUrl, devId, issueResponse, keyPem) {
|
|
261
|
+
async function applySettingsFromServer(baseUrl, devId, issueResponse, keyPem, serverCaPem) {
|
|
223
262
|
const configDir = getConfigDirForPaths();
|
|
224
263
|
if (issueResponse.settings && typeof issueResponse.settings === 'object') {
|
|
225
264
|
await config.mergeRemoteSettings(issueResponse.settings);
|
|
226
|
-
logger.log(chalk.green('
|
|
265
|
+
logger.log(chalk.green(' ā Config updated from server (issue-cert response)'));
|
|
227
266
|
return;
|
|
228
267
|
}
|
|
229
268
|
logger.log(chalk.gray(' Fetching settings...'));
|
|
@@ -231,9 +270,9 @@ async function applySettingsFromServer(baseUrl, devId, issueResponse, keyPem) {
|
|
|
231
270
|
if (keyPem && typeof keyPem === 'string') {
|
|
232
271
|
logger.log(chalk.gray(' Using client certificate for TLS'));
|
|
233
272
|
}
|
|
234
|
-
const settings = await devApi.getSettings(baseUrl, issueResponse.certificate, keyPem);
|
|
273
|
+
const settings = await devApi.getSettings(baseUrl, issueResponse.certificate, keyPem, serverCaPem);
|
|
235
274
|
await config.mergeRemoteSettings(settings);
|
|
236
|
-
logger.log(chalk.green('
|
|
275
|
+
logger.log(chalk.green(' ā Config updated from server'));
|
|
237
276
|
} catch (err) {
|
|
238
277
|
const msg = err.status === 400 ? getBadRequestHint() : (err.message || String(err));
|
|
239
278
|
logger.log(chalk.yellow(' ā Could not fetch settings (server may not support cert yet): ' + msg));
|
|
@@ -241,36 +280,94 @@ async function applySettingsFromServer(baseUrl, devId, issueResponse, keyPem) {
|
|
|
241
280
|
}
|
|
242
281
|
}
|
|
243
282
|
|
|
283
|
+
/**
|
|
284
|
+
* @param {Object} options - Commander options
|
|
285
|
+
* @param {string} baseUrl
|
|
286
|
+
* @param {string} devId - Developer ID (--developer-id) for devNN.hosts line
|
|
287
|
+
*/
|
|
288
|
+
async function maybeAddHostsDuringInit(options, baseUrl, devId) {
|
|
289
|
+
if (!options.addHosts && !options['add-hosts']) return;
|
|
290
|
+
const hostsIp = options.hostsIp || options['hosts-ip'];
|
|
291
|
+
await runOptionalHostsSetup({
|
|
292
|
+
baseUrl,
|
|
293
|
+
developerId: devId,
|
|
294
|
+
hostsIp: typeof hostsIp === 'string' ? hostsIp : undefined,
|
|
295
|
+
skipConfirm: Boolean(options.yes || options.y),
|
|
296
|
+
logger
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* @param {string} baseUrl
|
|
302
|
+
* @param {Object} options
|
|
303
|
+
* @returns {Promise<string|null>}
|
|
304
|
+
*/
|
|
305
|
+
async function resolveServerCaPemForTls(baseUrl, options) {
|
|
306
|
+
try {
|
|
307
|
+
return await ensureServerTrusted(baseUrl, options);
|
|
308
|
+
} catch (err) {
|
|
309
|
+
throw new Error(formatEnsureServerTrustedFailure(baseUrl, err));
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* @param {{ hostAlias: string|null, syncUser: string, syncHost: string|null }} p
|
|
315
|
+
*/
|
|
316
|
+
function logOnboardingFinished({ hostAlias, syncUser, syncHost }) {
|
|
317
|
+
logger.log(formatSuccessParagraph('Onboarding complete. You can use remote Docker and Mutagen sync.'));
|
|
318
|
+
if (hostAlias) {
|
|
319
|
+
logger.log(
|
|
320
|
+
chalk.gray(' You can also open an SSH session on the builder with ') +
|
|
321
|
+
chalk.cyan(`ssh ${hostAlias}`) +
|
|
322
|
+
chalk.gray(' (uses your registered SSH key; see ~/.ssh/config).')
|
|
323
|
+
);
|
|
324
|
+
} else if (syncHost && syncUser) {
|
|
325
|
+
logger.log(
|
|
326
|
+
chalk.gray(' You can SSH to the builder with ') +
|
|
327
|
+
chalk.cyan(`ssh ${syncUser}@${syncHost}`) +
|
|
328
|
+
chalk.gray(' when your key is authorized there.')
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
logger.log('');
|
|
332
|
+
}
|
|
333
|
+
|
|
244
334
|
/**
|
|
245
335
|
* Run dev init: validate PIN via issue-cert, save certificate, fetch settings, add SSH key.
|
|
246
336
|
* @param {Object} options - Commander options (devId, server, pin)
|
|
247
337
|
* @returns {Promise<void>}
|
|
248
338
|
*/
|
|
249
339
|
async function runDevInit(options) {
|
|
250
|
-
const { baseUrl, devId } =
|
|
340
|
+
const { baseUrl, devId } = await resolveInitOptions(options);
|
|
341
|
+
|
|
342
|
+
// Save developer-id and remote-server before TLS / issue-cert so ~/.aifabrix/config.yaml
|
|
343
|
+
// matches the CLI even if onboarding fails later (PIN, network, etc.). User can retry init.
|
|
344
|
+
await config.setDeveloperId(devId);
|
|
345
|
+
await config.setRemoteServer(baseUrl);
|
|
346
|
+
process.env.AIFABRIX_DEVELOPERID = devId;
|
|
347
|
+
|
|
251
348
|
logger.log(chalk.blue('\nš Onboarding with Builder Server...\n'));
|
|
252
349
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
} catch (err) {
|
|
256
|
-
throw new Error(`Cannot reach Builder Server at ${baseUrl}. Check URL and network. ${err.message}`);
|
|
257
|
-
}
|
|
350
|
+
await maybeAddHostsDuringInit(options, baseUrl, devId);
|
|
351
|
+
const serverCaPemForTls = await resolveServerCaPemForTls(baseUrl, options);
|
|
258
352
|
|
|
259
353
|
logger.log(chalk.gray(' Generating certificate request...'));
|
|
260
354
|
const { csrPem, keyPem } = generateCSR(devId);
|
|
261
355
|
|
|
262
356
|
logger.log(chalk.gray(' Requesting certificate (issue-cert)...'));
|
|
263
|
-
const issueResponse = await requestCertificate(baseUrl, devId, options.pin, csrPem);
|
|
357
|
+
const issueResponse = await requestCertificate(baseUrl, devId, options.pin, csrPem, serverCaPemForTls || undefined);
|
|
264
358
|
|
|
265
359
|
const configDir = getConfigDirForPaths();
|
|
266
|
-
const caPem =
|
|
360
|
+
const caPem = mergeCaPemBlocks(
|
|
361
|
+
serverCaPemForTls,
|
|
362
|
+
issueResponse.caCertificate,
|
|
363
|
+
issueResponse.ca
|
|
364
|
+
);
|
|
267
365
|
await saveCertAndConfig(configDir, devId, issueResponse.certificate, keyPem, caPem);
|
|
268
366
|
|
|
269
|
-
await
|
|
270
|
-
|
|
271
|
-
await
|
|
272
|
-
|
|
273
|
-
logger.log(chalk.green('\nā Onboarding complete. You can use remote Docker and Mutagen sync.\n'));
|
|
367
|
+
await applySettingsFromServer(baseUrl, devId, issueResponse, keyPem, serverCaPemForTls || undefined);
|
|
368
|
+
await _runSshKeyRegistrationStep(baseUrl, issueResponse, keyPem, configDir, devId, serverCaPemForTls || undefined);
|
|
369
|
+
const sshInfo = await mergeDevSshConfigAfterInit(baseUrl, devId);
|
|
370
|
+
logOnboardingFinished(sshInfo);
|
|
274
371
|
}
|
|
275
372
|
|
|
276
373
|
/** Days before cert expiry at which we auto-refresh on dev refresh. */
|
|
@@ -291,25 +388,47 @@ function shouldRefreshDevCert(certDir) {
|
|
|
291
388
|
|
|
292
389
|
/**
|
|
293
390
|
* Refresh developer certificate: create PIN (with current cert), issue new cert, save and apply settings.
|
|
294
|
-
* @param {{ serverUrl: string, clientCertPem: string }} auth - Current auth from getRemoteDevAuth
|
|
391
|
+
* @param {{ serverUrl: string, clientCertPem: string, serverCaPem?: string|null }} auth - Current auth from getRemoteDevAuth
|
|
295
392
|
* @returns {Promise<void>}
|
|
296
393
|
*/
|
|
297
394
|
async function runCertificateRefresh(auth) {
|
|
298
395
|
const devId = await config.getDeveloperId();
|
|
299
396
|
if (!devId) throw new Error('developer-id not set in config.');
|
|
300
397
|
const configDir = getConfigDirForPaths();
|
|
398
|
+
const serverCaPem = auth.serverCaPem || undefined;
|
|
301
399
|
logger.log(chalk.blue('\nš Refreshing certificate (create PIN + issue-cert)...\n'));
|
|
302
|
-
const pinRes = await devApi.createPin(auth.serverUrl, auth.clientCertPem, devId);
|
|
400
|
+
const pinRes = await devApi.createPin(auth.serverUrl, auth.clientCertPem, devId, serverCaPem);
|
|
303
401
|
const pin = pinRes.pin;
|
|
304
402
|
if (!pin || typeof pin !== 'string') throw new Error('Server did not return a PIN.');
|
|
305
403
|
logger.log(chalk.gray(' Generating new certificate request...'));
|
|
306
404
|
const { csrPem, keyPem } = generateCSR(devId);
|
|
307
405
|
logger.log(chalk.gray(' Requesting new certificate (issue-cert)...'));
|
|
308
|
-
const issueResponse = await requestCertificate(auth.serverUrl, devId, pin, csrPem);
|
|
309
|
-
const caPem = issueResponse.caCertificate
|
|
406
|
+
const issueResponse = await requestCertificate(auth.serverUrl, devId, pin, csrPem, serverCaPem);
|
|
407
|
+
const caPem = mergeCaPemBlocks(serverCaPem, issueResponse.caCertificate, issueResponse.ca);
|
|
310
408
|
await saveCertAndConfig(configDir, devId, issueResponse.certificate, keyPem, caPem);
|
|
311
|
-
await applySettingsFromServer(auth.serverUrl, devId, issueResponse, keyPem);
|
|
312
|
-
logger.log(
|
|
409
|
+
await applySettingsFromServer(auth.serverUrl, devId, issueResponse, keyPem, serverCaPem);
|
|
410
|
+
logger.log(formatSuccessLine('Certificate refreshed and config updated from server.\n'));
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* GET /api/dev/settings and merge into local config (used by dev refresh when cert is still valid).
|
|
415
|
+
* @param {{ serverUrl: string, serverCaPem?: string|null }} auth
|
|
416
|
+
* @param {string} clientCertPem
|
|
417
|
+
* @param {string|null|undefined} clientKeyPem
|
|
418
|
+
* @param {string} devId
|
|
419
|
+
* @returns {Promise<void>}
|
|
420
|
+
*/
|
|
421
|
+
async function fetchAndMergeRemoteSettings(auth, clientCertPem, clientKeyPem, devId) {
|
|
422
|
+
logger.log(chalk.blue('\nš Fetching settings from Builder Server...\n'));
|
|
423
|
+
const settings = await devApi.getSettings(
|
|
424
|
+
auth.serverUrl,
|
|
425
|
+
clientCertPem,
|
|
426
|
+
clientKeyPem || undefined,
|
|
427
|
+
auth.serverCaPem || undefined
|
|
428
|
+
);
|
|
429
|
+
await config.mergeRemoteSettings(settings);
|
|
430
|
+
logger.log(formatSuccessLine('Config updated from server.\n'));
|
|
431
|
+
await displayDevConfig(devId);
|
|
313
432
|
}
|
|
314
433
|
|
|
315
434
|
/**
|
|
@@ -326,22 +445,18 @@ async function runDevRefresh(options = {}) {
|
|
|
326
445
|
throw new Error('Remote server is not configured. Set remote-server and run "aifabrix dev init" first.');
|
|
327
446
|
}
|
|
328
447
|
const devId = await config.getDeveloperId();
|
|
329
|
-
const
|
|
330
|
-
const certDir = getCertDir(configDir, devId);
|
|
448
|
+
const certDir = getCertDir(getConfigDirForPaths(), devId);
|
|
331
449
|
const clientCertPem = readClientCertPem(certDir);
|
|
332
450
|
const clientKeyPem = readClientKeyPem(certDir);
|
|
333
451
|
if (!clientCertPem) {
|
|
334
452
|
throw new Error('Client certificate not found. Run "aifabrix dev init" first.');
|
|
335
453
|
}
|
|
336
|
-
|
|
337
|
-
if (forceCertRefresh || shouldRefreshDevCert(certDir)) {
|
|
454
|
+
if (Boolean(options.cert) || shouldRefreshDevCert(certDir)) {
|
|
338
455
|
await runCertificateRefresh(auth);
|
|
456
|
+
await displayDevConfig(devId);
|
|
339
457
|
return;
|
|
340
458
|
}
|
|
341
|
-
|
|
342
|
-
const settings = await devApi.getSettings(auth.serverUrl, clientCertPem, clientKeyPem || undefined);
|
|
343
|
-
await config.mergeRemoteSettings(settings);
|
|
344
|
-
logger.log(chalk.green('ā Config updated from server. Run "aifabrix dev show" to verify.\n'));
|
|
459
|
+
await fetchAndMergeRemoteSettings(auth, clientCertPem, clientKeyPem, devId);
|
|
345
460
|
}
|
|
346
461
|
|
|
347
462
|
module.exports = { runDevInit, runDevRefresh };
|