@aifabrix/builder 2.49.2 ā 2.51.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/plans/157.1-security-quality-violations-by-type.csv +374 -0
- package/.cursor/rules/assistant-driven-integration-build.mdc +40 -0
- package/.cursor/rules/deploy-rules/docker-image-ip-policy.mdc +49 -0
- package/.cursor/rules/plan-rules/application-lifecycle.mdc +30 -0
- package/.cursor/rules/plan-rules/plan-frontmatter.mdc +35 -0
- package/.cursor/rules/plan-rules/plan-lifecycle.mdc +31 -0
- package/.cursor/rules/plan-rules/plan-validation-gate.mdc +34 -0
- package/.cursor/skills/README.md +1 -0
- package/.dockerignore +52 -0
- package/.eslintignore +22 -0
- package/README.md +2 -0
- package/bin/builder-api-cleanup.js +26 -0
- package/bin/builder-api-nest.js +10 -0
- package/bin/builder-api-spike.js +19 -0
- package/enterprise-knowledge/README.md +50 -0
- package/enterprise-knowledge/enterprise-integration-lifecycle/README.md +22 -0
- package/enterprise-knowledge/enterprise-integration-lifecycle/application.json +15 -0
- package/enterprise-knowledge/enterprise-integration-lifecycle/deploy.js +69 -0
- package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-deploy.json +52 -0
- package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-system.json +29 -0
- package/enterprise-knowledge/enterprise-integration-lifecycle/env.template +2 -0
- package/integration/README.md +81 -0
- package/integration/github/README.md +53 -0
- package/integration/github/application.json +21 -0
- package/integration/github/deploy.js +72 -0
- package/integration/github/env.template +11 -0
- package/integration/github/github-datasource-issue-comments.json +239 -0
- package/integration/github/github-datasource-issues.json +399 -0
- package/integration/github/github-datasource-repository.json +354 -0
- package/integration/github/github-deploy.json +1202 -0
- package/integration/github/github-system.json +82 -0
- package/integration/hubspot-test/README.md +1 -1
- package/integration/hubspot-test/create-hubspot.js +1 -16
- package/jest.isolated-projects.js +31 -1
- package/jest.projects.js +87 -1
- package/lib/api/dev-server-https.js +1 -1
- package/lib/api/enterprise-knowledge.api.js +63 -0
- package/lib/api/evidence-kinds.api.js +128 -0
- package/lib/api/evidence.api.js +172 -0
- package/lib/api/external-systems.api.js +8 -2
- package/lib/api/pipeline.api.js +5 -1
- package/lib/api/resource-types.api.js +5 -4
- package/lib/api/roles.api.js +121 -0
- package/lib/api/types/enterprise-knowledge.types.js +46 -0
- package/lib/api/types/evidence-kinds.types.js +42 -0
- package/lib/api/types/evidence.types.js +67 -0
- package/lib/api/types/resource-types.types.js +2 -0
- package/lib/api/types/roles.types.js +36 -0
- package/lib/app/certification-verify-rows.js +1 -1
- package/lib/app/controller-application-filter.js +36 -0
- package/lib/app/deploy.js +1 -1
- package/lib/app/list-external-systems.js +130 -0
- package/lib/app/list.js +20 -8
- package/lib/app/run.js +3 -1
- package/lib/app/show-display.js +8 -3
- package/lib/app/show-online.js +178 -0
- package/lib/app/show.js +39 -90
- package/lib/build/builder-api-docker-staging.js +47 -0
- package/lib/build/miso-controller-npm-sdk-guard.js +2 -2
- package/lib/build/standard-docker-build.js +2 -0
- package/lib/certification/merge-certification-from-artifact.js +1 -1
- package/lib/certification/post-unified-cert-sync.js +4 -31
- package/lib/certification/sync-after-external-command.js +0 -1
- package/lib/certification/sync-system-certification.js +0 -3
- package/lib/channels/add-channel.js +40 -34
- package/lib/channels/approval-guides/chatgpt.js +33 -0
- package/lib/channels/approval-guides/credential-portal.js +38 -0
- package/lib/channels/approval-guides/index.js +110 -0
- package/lib/channels/approval-guides/microsoft-copilot.js +34 -0
- package/lib/channels/approval-guides/slack.js +34 -0
- package/lib/channels/approval-guides/teams-bot.js +35 -0
- package/lib/channels/approval-guides/web-embed.js +32 -0
- package/lib/channels/channel-approval-guide.js +11 -0
- package/lib/channels/channel-artifact-generator.js +18 -5
- package/lib/channels/channel-audit.js +3 -0
- package/lib/channels/channel-auth-context.js +1 -1
- package/lib/channels/channel-description.js +59 -0
- package/lib/channels/channel-integration-generator.js +13 -230
- package/lib/channels/channel-integration-template.js +94 -0
- package/lib/channels/channel-runtime-resolver.js +43 -3
- package/lib/channels/channel-status-display.js +66 -26
- package/lib/channels/channel-targets.js +3 -3
- package/lib/cli/index.js +31 -3
- package/lib/cli/infra-guided.js +5 -1
- package/lib/cli/setup-app-external-create.js +111 -0
- package/lib/cli/setup-app.help.js +1 -1
- package/lib/cli/setup-app.js +60 -130
- package/lib/cli/setup-app.test-commands.js +26 -52
- package/lib/cli/setup-certification-commands.js +4 -4
- package/lib/cli/setup-certification.help.js +9 -9
- package/lib/cli/setup-dev.js +30 -9
- package/lib/cli/setup-external-system-help.js +4 -6
- package/lib/cli/setup-external-system.js +58 -52
- package/lib/cli/setup-infra-up-builder-api-action.js +64 -0
- package/lib/cli/setup-infra-up-platform-action.js +3 -1
- package/lib/cli/setup-infra.js +15 -0
- package/lib/cli/setup-list.js +43 -0
- package/lib/cli/setup-utility-help-after.js +12 -0
- package/lib/cli/setup-utility-repair.js +26 -7
- package/lib/cli/setup-utility-validate.js +41 -2
- package/lib/cli/setup-utility.js +5 -3
- package/lib/commands/app.js +15 -43
- package/lib/commands/channel-add-setup.js +110 -0
- package/lib/commands/channel.js +42 -8
- package/lib/commands/datasource-sync-display.js +96 -0
- package/lib/commands/datasource-sync-policy.js +210 -0
- package/lib/commands/datasource-test-trust-cli.js +6 -6
- package/lib/commands/datasource-unified-test-cli.js +2 -1
- package/lib/commands/datasource-unified-test-cli.options.js +33 -23
- package/lib/commands/deploy-gate-failure-details.js +184 -0
- package/lib/commands/deploy-gate-orchestrator.js +368 -0
- package/lib/commands/dev-cli-handlers.js +7 -62
- package/lib/commands/dev-host-ops-params.js +91 -0
- package/lib/commands/dev-host-ops-poll.js +111 -0
- package/lib/commands/dev-host-ops.js +107 -94
- package/lib/commands/dev-init.js +6 -106
- package/lib/commands/dev-refresh.js +197 -0
- package/lib/commands/enterprise-knowledge.js +284 -0
- package/lib/commands/evidence-cli-leaves.js +250 -0
- package/lib/commands/evidence-kind.js +428 -0
- package/lib/commands/evidence.js +51 -0
- package/lib/commands/governance-cli-shared.js +2 -2
- package/lib/commands/governance-command-action.js +5 -3
- package/lib/commands/governance-fixture-subjects.js +85 -0
- package/lib/commands/governance.js +1 -1
- package/lib/commands/lifecycle-command-action.js +2 -2
- package/lib/commands/lifecycle-external.js +3 -3
- package/lib/commands/manifest-cli-auth.js +29 -0
- package/lib/commands/manifest-cli-commands.js +170 -0
- package/lib/commands/manifest-cli-integration-path.js +63 -0
- package/lib/commands/manifest.js +21 -0
- package/lib/commands/protection-cli-leaves.js +3 -3
- package/lib/commands/repair-auth-apply.js +15 -1
- package/lib/commands/repair-authentications-454.js +169 -0
- package/lib/commands/repair-capability-openapi-warnings.js +126 -0
- package/lib/commands/repair-datasource-apply.js +135 -0
- package/lib/commands/repair-datasource-auto-rbac.js +62 -1
- package/lib/commands/repair-datasource-http-service-contract.js +239 -0
- package/lib/commands/repair-datasource-operation-security.js +180 -0
- package/lib/commands/repair-datasource-run.js +7 -2
- package/lib/commands/repair-datasource-sync-operations.js +177 -0
- package/lib/commands/repair-datasource-webhooks-sync-bridge.js +133 -0
- package/lib/commands/repair-datasource.js +12 -68
- package/lib/commands/repair-env-template.js +11 -1
- package/lib/commands/repair-external-run.js +121 -31
- package/lib/commands/repair-internal.js +1 -1
- package/lib/commands/repair-openapi-export.js +156 -0
- package/lib/commands/repair-openapi-sync.js +33 -8
- package/lib/commands/repair-orchestration-datasource-split.js +259 -0
- package/lib/commands/repair-persist.js +22 -1
- package/lib/commands/repair-rbac-platform-preset.js +204 -0
- package/lib/commands/repair-rbac-reader-roles.js +191 -0
- package/lib/commands/repair-rbac.js +163 -86
- package/lib/commands/repair-steps.js +83 -18
- package/lib/commands/repair-system-permissions.js +1 -0
- package/lib/commands/repair.js +1 -1
- package/lib/commands/resource-type.js +166 -44
- package/lib/commands/role.js +452 -0
- package/lib/commands/run-post-publish-data-sync.js +68 -0
- package/lib/commands/setup-modes.js +1 -1
- package/lib/commands/setup.js +1 -1
- package/lib/commands/test-e2e-external.js +21 -8
- package/lib/commands/test-governance-cli-options.js +2 -2
- package/lib/commands/test-trust-cli-options.js +2 -2
- package/lib/commands/up-builder-api-bootstrap.js +71 -0
- package/lib/commands/up-builder-api-provision.js +241 -0
- package/lib/commands/up-builder-api.js +88 -0
- package/lib/commands/up-common.js +25 -1
- package/lib/commands/upload-credential-push-log.js +117 -0
- package/lib/commands/upload-data-sync-finalize.js +60 -0
- package/lib/commands/upload-probe.js +66 -0
- package/lib/commands/upload-publish-context.js +4 -1
- package/lib/commands/upload-sidecar-followups.js +55 -27
- package/lib/commands/upload.js +116 -157
- package/lib/commands/validate-json.js +230 -0
- package/lib/commands/verify-governance-combined-external.js +1 -1
- package/lib/commands/verify-governance-db.js +2 -2
- package/lib/commands/verify-operations-command-action.js +2 -2
- package/lib/commands/verify-operations-step-plan.js +79 -41
- package/lib/commands/verify-operations-steps.js +2 -2
- package/lib/commands/verify-trust-command-action.js +1 -1
- package/lib/commands/wizard-core.js +1 -1
- package/lib/commands/wizard-headless.js +2 -1
- package/lib/core/admin-secrets.js +2 -6
- package/lib/core/audit-logger.js +1 -1
- package/lib/core/secrets-env-content.js +10 -4
- package/lib/core/secrets-env-write.js +2 -13
- package/lib/core/secrets-load.js +1 -3
- package/lib/datasource/agent-trust-run.js +3 -3
- package/lib/datasource/capability/relate-operations.js +1 -1
- package/lib/datasource/deploy.js +3 -1
- package/lib/datasource/test-e2e.js +6 -1
- package/lib/datasource/unified-validation-run-body.js +4 -1
- package/lib/datasource/unified-validation-run.js +1 -1
- package/lib/deployment/deploy-poll-ui.js +73 -12
- package/lib/deployment/deployer-poll-run.js +113 -0
- package/lib/deployment/deployer.js +17 -87
- package/lib/evidence/dataplane-context.js +21 -0
- package/lib/evidence/evidence-display.js +78 -0
- package/lib/evidence/evidence-service.js +392 -0
- package/lib/external-system/deploy.js +290 -112
- package/lib/external-system/download.js +7 -3
- package/lib/external-system/test-execution.js +1 -1
- package/lib/external-system/test-system-level.js +8 -10
- package/lib/external-system/test.js +12 -6
- package/lib/generator/deploy-script.js +73 -0
- package/lib/generator/external.js +2 -1
- package/lib/generator/helpers.js +13 -5
- package/lib/generator/index.js +17 -2
- package/lib/generator/split-variables.js +9 -3
- package/lib/generator/wizard.js +3 -36
- package/lib/infrastructure/helpers-docker-check.js +6 -0
- package/lib/infrastructure/helpers.js +1 -1
- package/lib/internal/fs-real-sync.js +22 -1
- package/lib/internal/node-fs.js +2 -0
- package/lib/lifecycle/lifecycle-governance-options.js +1 -1
- package/lib/lifecycle/verify-step-progress.js +1 -1
- package/lib/programmatic/access-log.js +26 -0
- package/lib/programmatic/auth-config.js +45 -0
- package/lib/programmatic/bearer-auth.js +176 -0
- package/lib/programmatic/builder-api-request.js +175 -0
- package/lib/programmatic/builder-api-route-dispatch.js +82 -0
- package/lib/programmatic/builder-api-runtime-config.js +42 -0
- package/lib/programmatic/builder-api-server.js +230 -0
- package/lib/programmatic/builder-help-authentication-catalog.js +282 -0
- package/lib/programmatic/builder-help-connected-system-ui.js +266 -0
- package/lib/programmatic/builder-help-enterprise-sync-fabrix.js +60 -0
- package/lib/programmatic/builder-help-envelope.js +36 -0
- package/lib/programmatic/builder-help-fixtures.js +200 -0
- package/lib/programmatic/builder-help-governance.js +172 -0
- package/lib/programmatic/builder-help-schema-catalog.js +92 -0
- package/lib/programmatic/builder-help.js +361 -0
- package/lib/programmatic/capability-registry.js +77 -0
- package/lib/programmatic/command-options.js +32 -0
- package/lib/programmatic/enterprise-mcp-client.js +114 -0
- package/lib/programmatic/http-problem-details.js +99 -0
- package/lib/programmatic/http-route-match.js +40 -0
- package/lib/programmatic/idempotency-cache.js +69 -0
- package/lib/programmatic/index.js +53 -0
- package/lib/programmatic/integration-path-scope.js +39 -0
- package/lib/programmatic/log-redaction.js +66 -0
- package/lib/programmatic/manifest-get-section.js +146 -0
- package/lib/programmatic/manifest-patch-section.js +252 -0
- package/lib/programmatic/manifest-repair.js +122 -0
- package/lib/programmatic/manifest-section-dependency-graph.js +160 -0
- package/lib/programmatic/manifest-section-io.js +225 -0
- package/lib/programmatic/manifest-section-quality.js +171 -0
- package/lib/programmatic/manifest-section-registry-data.js +269 -0
- package/lib/programmatic/manifest-section-registry.js +222 -0
- package/lib/programmatic/nest-http-bridge.js +34 -0
- package/lib/programmatic/openapi-component-schemas.js +68 -0
- package/lib/programmatic/openapi-description-enricher.js +117 -0
- package/lib/programmatic/openapi-descriptions.js +190 -0
- package/lib/programmatic/openapi-docs-serving.js +123 -0
- package/lib/programmatic/openapi-help-schemas.js +63 -0
- package/lib/programmatic/openapi-manifest-schemas.js +141 -0
- package/lib/programmatic/openapi-operation-bindings.js +274 -0
- package/lib/programmatic/openapi-request-schemas.js +155 -0
- package/lib/programmatic/openapi-result-schemas.js +493 -0
- package/lib/programmatic/openapi-schema-descriptions-certify.js +139 -0
- package/lib/programmatic/openapi-schema-descriptions-core.js +162 -0
- package/lib/programmatic/openapi-schema-descriptions-help.js +40 -0
- package/lib/programmatic/openapi-schema-descriptions-manifest.js +143 -0
- package/lib/programmatic/openapi-schema-descriptions-mcp.js +118 -0
- package/lib/programmatic/openapi-schema-descriptions-operations.js +281 -0
- package/lib/programmatic/openapi-schema-helpers.js +108 -0
- package/lib/programmatic/openapi-spec.js +203 -0
- package/lib/programmatic/orchestration-openapi-meta.js +159 -0
- package/lib/programmatic/platform-rbac-catalog.js +90 -0
- package/lib/programmatic/request-timeout.js +53 -0
- package/lib/programmatic/route-handler-map.js +143 -0
- package/lib/programmatic/route-handlers-context.js +29 -0
- package/lib/programmatic/route-handlers.js +33 -0
- package/lib/programmatic/run-certify.js +57 -0
- package/lib/programmatic/run-enterprise-mcp.js +32 -0
- package/lib/programmatic/run-lifecycle.js +29 -0
- package/lib/programmatic/run-repair.js +41 -0
- package/lib/programmatic/run-repository-emcp.js +62 -0
- package/lib/programmatic/run-template-workspace.js +74 -0
- package/lib/programmatic/run-test.js +49 -0
- package/lib/programmatic/run-upload.js +63 -0
- package/lib/programmatic/run-validate.js +53 -0
- package/lib/programmatic/run-wizard.js +40 -0
- package/lib/programmatic/system-key.js +48 -0
- package/lib/programmatic/wizard-config-normalize.js +118 -0
- package/lib/programmatic/workspace-cleanup.js +128 -0
- package/lib/programmatic/workspace-context.js +145 -0
- package/lib/programmatic/workspace-lock.js +75 -0
- package/lib/programmatic/workspace-meta.js +64 -0
- package/lib/programmatic/workspace-ops.js +149 -0
- package/lib/protection/run-commands-upload-sync.js +35 -0
- package/lib/protection/run-commands.js +2 -20
- package/lib/protection/upload-batch.js +11 -7
- package/lib/resolvers/evidence-kind-file.js +230 -0
- package/lib/resolvers/resource-type-file.js +58 -1
- package/lib/resolvers/role-file.js +227 -0
- package/lib/schema/application-schema.json +22 -2
- package/lib/schema/external-datasource.schema.json +245 -2
- package/lib/schema/external-system.schema.json +259 -119
- package/lib/schema/flag-map-validation-run.json +3 -0
- package/lib/schema/infra.parameter.yaml +25 -1
- package/lib/schema/type/credential-field-registry.json +21 -5
- package/lib/schema/type/document-storage.json +9 -0
- package/lib/utils/agent-trust-run-display.js +1 -1
- package/lib/utils/api.js +8 -2
- package/lib/utils/app-path-resolve.js +168 -0
- package/lib/utils/app-register-config.js +4 -3
- package/lib/utils/authentication-env-template.js +222 -0
- package/lib/utils/cli-sync-options.js +62 -10
- package/lib/utils/cli-utils.js +15 -3
- package/lib/utils/cli-workspace-options.js +29 -0
- package/lib/utils/compose-generate-docker-compose.js +102 -0
- package/lib/utils/configuration-env-resolver.js +203 -27
- package/lib/utils/datasource-test-run-certificate-tty.js +28 -2
- package/lib/utils/datasource-test-run-certification-debug.js +130 -0
- package/lib/utils/datasource-test-run-debug-display.js +2 -0
- package/lib/utils/datasource-test-run-debug-slice.js +7 -0
- package/lib/utils/datasource-test-run-display.js +2 -1
- package/lib/utils/dev-ca-install.js +5 -6
- package/lib/utils/dev-config.js +2 -2
- package/lib/utils/dev-init-ssh-merge.js +165 -23
- package/lib/utils/dev-list-sort.js +145 -0
- package/lib/utils/dev-pin-share-instructions.js +110 -0
- package/lib/utils/dev-platform-tls.js +0 -63
- package/lib/utils/dev-ssh-config-helper.js +177 -33
- package/lib/utils/docker-build.js +46 -27
- package/lib/utils/docker-daemon-tls-ca.js +1 -1
- package/lib/utils/docker-exec.js +91 -6
- package/lib/utils/enterprise-knowledge-paths.js +142 -0
- package/lib/utils/env-copy.js +3 -4
- package/lib/utils/env-dotenv-format.js +103 -0
- package/lib/utils/error-formatters/error-parser.js +0 -3
- package/lib/utils/external-env-template.js +5 -2
- package/lib/utils/external-system-display.js +5 -1
- package/lib/utils/external-system-readiness-compact-blocks.js +248 -0
- package/lib/utils/external-system-readiness-compact-display.js +324 -0
- package/lib/utils/external-system-readiness-core.js +16 -0
- package/lib/utils/external-system-readiness-deploy-display.js +29 -11
- package/lib/utils/external-system-readiness-display-internals.js +3 -1
- package/lib/utils/external-system-readiness-display.js +20 -30
- package/lib/utils/external-system-system-test-tty-certification.js +135 -0
- package/lib/utils/external-system-system-test-tty.js +5 -41
- package/lib/utils/health-check-request.js +2 -3
- package/lib/utils/help-builder.js +9 -1
- package/lib/utils/host-ops-job-labels.js +236 -0
- package/lib/utils/host-ops-job-result.js +61 -0
- package/lib/utils/host-ops-poll-ui.js +163 -0
- package/lib/utils/image-name.js +22 -4
- package/lib/utils/integration-path-resolve.js +112 -0
- package/lib/utils/logger.js +37 -4
- package/lib/utils/manifest-source-emit.js +1 -1
- package/lib/utils/paths-reload-source.js +148 -0
- package/lib/utils/paths-system-builder-keys.js +25 -0
- package/lib/utils/paths.js +183 -30
- package/lib/utils/pipeline-upload-auth-retry.js +4 -0
- package/lib/utils/postgres-platform-bootstrap.js +24 -17
- package/lib/utils/postgres-wipe.js +5 -2
- package/lib/utils/remote-dev-auth.js +39 -4
- package/lib/utils/resolve-docker-image-ref.js +36 -6
- package/lib/utils/runtime-configuration-values.js +64 -2
- package/lib/utils/secrets-helpers.js +5 -1
- package/lib/utils/ssh-known-hosts.js +130 -0
- package/lib/utils/test-target-cli-options.js +75 -0
- package/lib/utils/token-manager.js +16 -0
- package/lib/utils/upload-sync-options.js +20 -2
- package/lib/utils/validation-run-request.js +11 -2
- package/lib/validation/external-manifest-validator.js +11 -1
- package/lib/validation/openapi-contract-surface-validator.js +430 -0
- package/lib/validation/openapi-contract-vendor-validation.js +238 -0
- package/lib/validation/validate-external-file.js +160 -0
- package/lib/validation/validate.js +6 -117
- package/lib/validation/validator.js +6 -5
- package/package.json +76 -37
- package/packages/builder-api/README.md +120 -0
- package/packages/builder-api/package.json +30 -0
- package/packages/builder-api/src/app.module.ts +7 -0
- package/packages/builder-api/src/auth/auth.module.ts +5 -0
- package/packages/builder-api/src/external-system/external-system.module.ts +5 -0
- package/packages/builder-api/src/main.ts +16 -0
- package/packages/builder-api/tsconfig.json +15 -0
- package/scripts/check-builder-api-architecture-grep.js +79 -0
- package/scripts/docker_image_content_gate.js +47 -0
- package/scripts/docker_image_content_gate.sh +5 -0
- package/scripts/export-builder-api-evidence.js +262 -0
- package/scripts/lib/builder-api-docker-staging-copy.js +60 -0
- package/scripts/lib/builder-api-docker-staging-core.js +183 -0
- package/scripts/lib/docker-image-content-gate-core.js +166 -0
- package/scripts/lib/plan-actor.js +109 -0
- package/scripts/lib/plan-config.js +20 -0
- package/scripts/lib/plan-gates.js +154 -0
- package/scripts/lib/plan-meta.js +104 -0
- package/scripts/lib/plan-parse.js +162 -0
- package/scripts/lib/plan-prevalidate-gates.js +337 -0
- package/scripts/lib/plan-run-core.js +125 -0
- package/scripts/lib/plan-run-report.js +119 -0
- package/scripts/plan-approve.js +24 -0
- package/scripts/plan-archive.js +49 -0
- package/scripts/plan-run.js +13 -0
- package/scripts/plan-set-actor.js +21 -0
- package/scripts/plan-validate.js +80 -0
- package/scripts/pnpm/af.mjs +110 -0
- package/scripts/pnpm/check-quiet.mjs +32 -0
- package/scripts/pnpm/dev-install.mjs +29 -0
- package/scripts/pnpm/dev-reload.mjs +18 -0
- package/scripts/pnpm/help.mjs +55 -0
- package/scripts/pnpm/lib/dev-reload-core.mjs +189 -0
- package/scripts/pnpm/lib/dev-reload-log-capture.mjs +67 -0
- package/scripts/pnpm/lib/dev-reload-log-utils.mjs +32 -0
- package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +124 -0
- package/scripts/pnpm/lib/resolve-app-url.mjs +183 -0
- package/scripts/pnpm/lib/spinner.mjs +42 -0
- package/scripts/stage_builder_api_for_docker.js +65 -0
- package/scripts/sync-builder-api-template.js +44 -0
- package/templates/README.md +3 -0
- package/templates/applications/builder-api/Dockerfile +38 -0
- package/templates/applications/builder-api/application.yaml +75 -0
- package/templates/applications/builder-api/env.template +48 -0
- package/templates/applications/dataplane/application.yaml +27 -5
- package/templates/applications/dataplane/env.template +38 -15
- package/templates/applications/dataplane/rbac.yaml +85 -3
- package/templates/applications/miso-controller/application.yaml +10 -1
- package/templates/applications/miso-controller/env.template +11 -10
- package/templates/applications/miso-controller/rbac.yaml +72 -0
- package/templates/channels/README.md +18 -0
- package/templates/channels/ai-fabrix-icon.jpg +0 -0
- package/templates/channels/chatgpt/install.template.md.hbs +21 -24
- package/templates/channels/chatgpt/integration/README.md +11 -0
- package/templates/channels/chatgpt/integration/application.json +15 -0
- package/templates/channels/chatgpt/integration/chatgpt-system.json +29 -0
- package/templates/channels/chatgpt/integration/env.template +4 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +20 -25
- package/templates/channels/microsoft-copilot/integration/README.md +11 -0
- package/templates/channels/microsoft-copilot/integration/application.json +15 -0
- package/templates/channels/microsoft-copilot/integration/env.template +6 -0
- package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +34 -0
- package/templates/channels/slack/install.template.md.hbs +48 -18
- package/templates/channels/slack/integration/README.md +38 -0
- package/templates/channels/slack/integration/application.json +18 -0
- package/templates/channels/slack/integration/env.template +29 -0
- package/templates/channels/slack/integration/slack-datasource-conversations.json +226 -0
- package/templates/channels/slack/integration/slack-datasource-messages.json +269 -0
- package/templates/channels/slack/integration/slack-system.json +144 -0
- package/templates/channels/slack/manifest.template.json.hbs +20 -10
- package/templates/channels/teams-bot/install.template.md.hbs +31 -17
- package/templates/channels/teams-bot/integration/README.md +18 -0
- package/templates/channels/teams-bot/integration/application.json +17 -0
- package/templates/channels/teams-bot/integration/env.template +5 -0
- package/templates/channels/teams-bot/integration/teams-bot-system.json +55 -0
- package/templates/channels/teams-bot/manifest.template.json.hbs +27 -0
- package/templates/channels/web-embed/install.template.md.hbs +16 -26
- package/templates/channels/web-embed/integration/README.md +11 -0
- package/templates/channels/web-embed/integration/application.json +15 -0
- package/templates/channels/web-embed/integration/env.template +4 -0
- package/templates/channels/web-embed/integration/web-embed-system.json +29 -0
- package/templates/openapi/redoc_page.html +86 -0
- package/templates/python/docker-compose.hbs +11 -0
- package/templates/python/requirements.txt +2 -2
- package/templates/typescript/docker-compose.hbs +11 -0
- package/lib/certification/cli-cert-sync-skip.js +0 -21
|
@@ -9,50 +9,30 @@ const chalk = require('chalk');
|
|
|
9
9
|
const logger = require('../utils/logger');
|
|
10
10
|
const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
|
|
11
11
|
const { getRemoteDevAuth } = require('../utils/remote-dev-auth');
|
|
12
|
+
const { createHostOpsPollHandlers } = require('../utils/host-ops-poll-ui');
|
|
13
|
+
const { buildHostOpsActionLabel, resolveHostOpsTargetLabel } = require('../utils/host-ops-job-labels');
|
|
14
|
+
const { pollHostOpsJobUntilTerminal } = require('./dev-host-ops-poll');
|
|
15
|
+
const { buildJobParams } = require('./dev-host-ops-params');
|
|
12
16
|
const hostOpsApi = require('../api/host-ops.api');
|
|
17
|
+
const { assertHostOpsJobSucceeded } = require('../utils/host-ops-job-result');
|
|
13
18
|
|
|
14
19
|
const REMOTE_NOT_CONFIGURED_MSG =
|
|
15
20
|
'Remote server is not configured. Set remote-server and run "aifabrix dev init" first.';
|
|
16
21
|
|
|
17
|
-
const POLL_INTERVAL_MS = 3000;
|
|
18
|
-
const POLL_TIMEOUT_MS = 3 * 60 * 60 * 1000;
|
|
19
|
-
|
|
20
|
-
function sleep(ms) {
|
|
21
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
22
|
-
}
|
|
23
|
-
|
|
24
22
|
/**
|
|
25
|
-
*
|
|
23
|
+
* @param {string} type
|
|
24
|
+
* @param {Object} params
|
|
26
25
|
* @param {Object} options
|
|
27
|
-
* @param {string} [developerId]
|
|
28
26
|
* @returns {Object}
|
|
29
27
|
*/
|
|
30
|
-
function
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
if (options.adminEmail || options['admin-email']) {
|
|
40
|
-
params.adminEmail = options.adminEmail || options['admin-email'];
|
|
41
|
-
}
|
|
42
|
-
if (options.adminPassword || options['admin-password']) {
|
|
43
|
-
params.adminPassword = options.adminPassword || options['admin-password'];
|
|
44
|
-
}
|
|
45
|
-
if (options.platform) params.platform = options.platform;
|
|
46
|
-
if (options.installation) params.installation = options.installation;
|
|
47
|
-
if (options.skipCert || options['skip-cert']) params.skipCert = true;
|
|
48
|
-
if (options.skipPlatform || options['skip-platform']) params.skipPlatform = true;
|
|
49
|
-
if (options.skipCli || options['skip-cli']) params.skipCli = true;
|
|
50
|
-
if (options.check) params.check = true;
|
|
51
|
-
if (options.failOnBlocked) params.failOnBlocked = true;
|
|
52
|
-
if (options.timeoutMinutes || options['timeout-minutes']) {
|
|
53
|
-
params.timeoutMinutes = parseInt(options.timeoutMinutes || options['timeout-minutes'], 10);
|
|
54
|
-
}
|
|
55
|
-
return params;
|
|
28
|
+
function buildHostOpsWaitOpts(type, params, options) {
|
|
29
|
+
return {
|
|
30
|
+
wait: options.wait !== false,
|
|
31
|
+
json: Boolean(options.json),
|
|
32
|
+
jobType: type,
|
|
33
|
+
targetLabel: resolveHostOpsTargetLabel(params),
|
|
34
|
+
params
|
|
35
|
+
};
|
|
56
36
|
}
|
|
57
37
|
|
|
58
38
|
/**
|
|
@@ -70,26 +50,20 @@ async function waitForHostOpsJob(auth, jobId, opts = {}) {
|
|
|
70
50
|
if (!wait) {
|
|
71
51
|
return { jobId, status: 'pending' };
|
|
72
52
|
}
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
throw new Error(job.error || `Host-ops job ${jobId} failed`);
|
|
87
|
-
}
|
|
88
|
-
return job;
|
|
89
|
-
}
|
|
90
|
-
await sleep(POLL_INTERVAL_MS);
|
|
53
|
+
const pollContext = {
|
|
54
|
+
jobType: opts.jobType,
|
|
55
|
+
targetLabel: opts.targetLabel,
|
|
56
|
+
params: opts.params,
|
|
57
|
+
startedAt: Date.now()
|
|
58
|
+
};
|
|
59
|
+
const pollUi = json
|
|
60
|
+
? { onPollProgress: () => {}, onTransientError: () => {}, finish: () => {} }
|
|
61
|
+
: createHostOpsPollHandlers(jobId, pollContext);
|
|
62
|
+
try {
|
|
63
|
+
return await pollHostOpsJobUntilTerminal(auth, jobId, pollUi, json);
|
|
64
|
+
} finally {
|
|
65
|
+
pollUi.finish();
|
|
91
66
|
}
|
|
92
|
-
throw new Error(`Timed out waiting for host-ops job ${jobId}`);
|
|
93
67
|
}
|
|
94
68
|
|
|
95
69
|
/**
|
|
@@ -135,13 +109,26 @@ async function runHostOpsJob(type, params, options = {}) {
|
|
|
135
109
|
{ type, params },
|
|
136
110
|
auth.serverCaPem || undefined
|
|
137
111
|
);
|
|
112
|
+
const waitOpts = buildHostOpsWaitOpts(type, params, options);
|
|
113
|
+
if (options.wait === false) {
|
|
114
|
+
if (options.json) {
|
|
115
|
+
logger.log(JSON.stringify({ jobId, status: 'pending', type }, null, 2));
|
|
116
|
+
} else {
|
|
117
|
+
const action = buildHostOpsActionLabel(type, waitOpts.targetLabel);
|
|
118
|
+
logger.log(formatSuccessLine(`${action} queued (job ${jobId}).`));
|
|
119
|
+
}
|
|
120
|
+
return { jobId, status: 'pending' };
|
|
121
|
+
}
|
|
138
122
|
if (options.json) {
|
|
139
|
-
const job = await waitForHostOpsJob(auth, jobId,
|
|
123
|
+
const job = await waitForHostOpsJob(auth, jobId, waitOpts);
|
|
124
|
+
assertHostOpsJobSucceeded(job);
|
|
140
125
|
logger.log(JSON.stringify(job, null, 2));
|
|
141
126
|
return job;
|
|
142
127
|
}
|
|
143
|
-
const job = await waitForHostOpsJob(auth, jobId,
|
|
144
|
-
|
|
128
|
+
const job = await waitForHostOpsJob(auth, jobId, waitOpts);
|
|
129
|
+
assertHostOpsJobSucceeded(job);
|
|
130
|
+
const action = buildHostOpsActionLabel(type, waitOpts.targetLabel);
|
|
131
|
+
logger.log(formatSuccessLine(`${action} completed.`));
|
|
145
132
|
return job;
|
|
146
133
|
}
|
|
147
134
|
|
|
@@ -161,6 +148,63 @@ async function handlePlatformUpdate(developerId, options) {
|
|
|
161
148
|
await runHostOpsJob('update-dev-platform', params, options);
|
|
162
149
|
}
|
|
163
150
|
|
|
151
|
+
function logPlatformInstallOutcomes(developerId, job, json) {
|
|
152
|
+
if (json) {
|
|
153
|
+
logger.log(JSON.stringify(job, null, 2));
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (!Array.isArray(job.outcomes)) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
job.outcomes.forEach((row) => {
|
|
160
|
+
logger.log(` ${row.linuxUser || developerId}: ${row.overall || row.status}${row.detail ? ` ā ${row.detail}` : ''}`);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async function runPlatformInstallPreflight(auth, params) {
|
|
165
|
+
const { jobId } = await hostOpsApi.preflightHostOps(
|
|
166
|
+
auth.serverUrl,
|
|
167
|
+
auth.clientCertPem,
|
|
168
|
+
{ type: 'install-dev-platform', params },
|
|
169
|
+
auth.serverCaPem || undefined
|
|
170
|
+
);
|
|
171
|
+
return waitForHostOpsJob(auth, jobId, buildHostOpsWaitOpts('install-dev-platform', params, {}));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async function handlePlatformInstallCheck(developerId, params, options) {
|
|
175
|
+
const auth = await getRemoteDevAuth();
|
|
176
|
+
if (!auth) throw new Error(REMOTE_NOT_CONFIGURED_MSG);
|
|
177
|
+
params.check = true;
|
|
178
|
+
const { jobId } = await hostOpsApi.preflightHostOps(
|
|
179
|
+
auth.serverUrl,
|
|
180
|
+
auth.clientCertPem,
|
|
181
|
+
{ type: 'install-dev-platform', params },
|
|
182
|
+
auth.serverCaPem || undefined
|
|
183
|
+
);
|
|
184
|
+
const job = await waitForHostOpsJob(auth, jobId, buildHostOpsWaitOpts('install-dev-platform', params, options));
|
|
185
|
+
logPlatformInstallOutcomes(developerId, job, options.json);
|
|
186
|
+
assertHostOpsJobSucceeded(job);
|
|
187
|
+
return job;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async function confirmPlatformReinstall(developerId, params, options) {
|
|
191
|
+
const auth = await getRemoteDevAuth();
|
|
192
|
+
if (!auth) throw new Error(REMOTE_NOT_CONFIGURED_MSG);
|
|
193
|
+
const preflight = await runPlatformInstallPreflight(auth, { ...params, developerId });
|
|
194
|
+
if (!platformAlreadyInstalled(preflight.outcomes)) {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
const ok = await promptYesNo(
|
|
198
|
+
`Platform already installed for dev${String(developerId).padStart(2, '0')}. Re-install?`
|
|
199
|
+
);
|
|
200
|
+
if (!ok) {
|
|
201
|
+
logger.log(chalk.gray('Cancelled.'));
|
|
202
|
+
return preflight;
|
|
203
|
+
}
|
|
204
|
+
await runHostOpsJob('reinstall-dev-platform', params, options);
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
|
|
164
208
|
async function handlePlatformInstall(developerId, options) {
|
|
165
209
|
if (!developerId) {
|
|
166
210
|
throw new Error('Developer ID is required (positional argument).');
|
|
@@ -168,46 +212,13 @@ async function handlePlatformInstall(developerId, options) {
|
|
|
168
212
|
const params = buildJobParams(options, developerId);
|
|
169
213
|
|
|
170
214
|
if (options.check) {
|
|
171
|
-
params
|
|
172
|
-
const auth = await getRemoteDevAuth();
|
|
173
|
-
if (!auth) throw new Error(REMOTE_NOT_CONFIGURED_MSG);
|
|
174
|
-
const { jobId } = await hostOpsApi.preflightHostOps(
|
|
175
|
-
auth.serverUrl,
|
|
176
|
-
auth.clientCertPem,
|
|
177
|
-
{ type: 'install-dev-platform', params },
|
|
178
|
-
auth.serverCaPem || undefined
|
|
179
|
-
);
|
|
180
|
-
const job = await waitForHostOpsJob(auth, jobId, options);
|
|
181
|
-
if (options.json) {
|
|
182
|
-
logger.log(JSON.stringify(job, null, 2));
|
|
183
|
-
} else if (Array.isArray(job.outcomes)) {
|
|
184
|
-
job.outcomes.forEach((row) => {
|
|
185
|
-
logger.log(` ${row.linuxUser || developerId}: ${row.overall || row.status}${row.detail ? ` ā ${row.detail}` : ''}`);
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
return job;
|
|
215
|
+
return handlePlatformInstallCheck(developerId, params, options);
|
|
189
216
|
}
|
|
190
217
|
|
|
191
218
|
if (!options.force && !options.yes) {
|
|
192
|
-
const
|
|
193
|
-
if (
|
|
194
|
-
|
|
195
|
-
auth.serverUrl,
|
|
196
|
-
auth.clientCertPem,
|
|
197
|
-
{ type: 'install-dev-platform', params: { ...params, developerId } },
|
|
198
|
-
auth.serverCaPem || undefined
|
|
199
|
-
);
|
|
200
|
-
const preflight = await waitForHostOpsJob(auth, jobId, { ...options, json: false });
|
|
201
|
-
if (platformAlreadyInstalled(preflight.outcomes)) {
|
|
202
|
-
const ok = await promptYesNo(
|
|
203
|
-
`Platform already installed for dev${String(developerId).padStart(2, '0')}. Re-install?`
|
|
204
|
-
);
|
|
205
|
-
if (!ok) {
|
|
206
|
-
logger.log(chalk.gray('Cancelled.'));
|
|
207
|
-
return preflight;
|
|
208
|
-
}
|
|
209
|
-
await runHostOpsJob('reinstall-dev-platform', params, options);
|
|
210
|
-
return;
|
|
219
|
+
const cancelled = await confirmPlatformReinstall(developerId, params, options);
|
|
220
|
+
if (cancelled) {
|
|
221
|
+
return cancelled;
|
|
211
222
|
}
|
|
212
223
|
}
|
|
213
224
|
|
|
@@ -230,7 +241,9 @@ async function handleRemoveDevUser(developerId, options) {
|
|
|
230
241
|
|
|
231
242
|
module.exports = {
|
|
232
243
|
buildJobParams,
|
|
244
|
+
buildHostOpsWaitOpts,
|
|
233
245
|
waitForHostOpsJob,
|
|
246
|
+
runHostOpsJob,
|
|
234
247
|
handlePlatformInstallCli,
|
|
235
248
|
handlePlatformUpdate,
|
|
236
249
|
handlePlatformInstall,
|
package/lib/commands/dev-init.js
CHANGED
|
@@ -14,10 +14,6 @@ const { getConfigDirForPaths } = require('../utils/paths');
|
|
|
14
14
|
const {
|
|
15
15
|
generateCSR,
|
|
16
16
|
getCertDir,
|
|
17
|
-
readClientCertPem,
|
|
18
|
-
readClientKeyPem,
|
|
19
|
-
readServerCaPem,
|
|
20
|
-
getCertValidNotAfter,
|
|
21
17
|
normalizePemNewlines,
|
|
22
18
|
mergeCaPemBlocks
|
|
23
19
|
} = require('../utils/dev-cert-helper');
|
|
@@ -35,7 +31,6 @@ const {
|
|
|
35
31
|
const { runOptionalHostsSetup } = require('../utils/dev-hosts-helper');
|
|
36
32
|
const { mergeDevSshConfigAfterInit } = require('../utils/dev-init-ssh-merge');
|
|
37
33
|
const { resolveInitOptions } = require('../utils/dev-init-resolve');
|
|
38
|
-
const { displayDevConfig } = require('./dev-show-display');
|
|
39
34
|
const {
|
|
40
35
|
isHealthHttpServerError,
|
|
41
36
|
formatEnsureServerTrustedFailure
|
|
@@ -383,104 +378,9 @@ async function runDevInit(options) {
|
|
|
383
378
|
logOnboardingFinished(sshInfo);
|
|
384
379
|
}
|
|
385
380
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
* @returns {boolean}
|
|
393
|
-
*/
|
|
394
|
-
function shouldRefreshDevCert(certDir) {
|
|
395
|
-
const validNotAfter = getCertValidNotAfter(certDir);
|
|
396
|
-
if (!validNotAfter) return true;
|
|
397
|
-
const now = Date.now();
|
|
398
|
-
const threshold = now + CERT_REFRESH_DAYS * 24 * 60 * 60 * 1000;
|
|
399
|
-
return validNotAfter.getTime() < threshold;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* Refresh developer certificate: create PIN (with current cert), issue new cert, save and apply settings.
|
|
404
|
-
* @param {{ serverUrl: string, clientCertPem: string, serverCaPem?: string|null }} auth - Current auth from getRemoteDevAuth
|
|
405
|
-
* @returns {Promise<void>}
|
|
406
|
-
*/
|
|
407
|
-
async function runCertificateRefresh(auth) {
|
|
408
|
-
const devId = await config.getDeveloperId();
|
|
409
|
-
if (!devId) throw new Error('developer-id not set in config.');
|
|
410
|
-
const configDir = getConfigDirForPaths();
|
|
411
|
-
const serverCaPem = auth.serverCaPem || undefined;
|
|
412
|
-
logger.log(chalk.blue('\nš Refreshing certificate (create PIN + issue-cert)...\n'));
|
|
413
|
-
const pinRes = await devApi.createPin(auth.serverUrl, auth.clientCertPem, devId, serverCaPem);
|
|
414
|
-
const pin = pinRes.pin;
|
|
415
|
-
if (!pin || typeof pin !== 'string') throw new Error('Server did not return a PIN.');
|
|
416
|
-
logger.log(chalk.gray(' Generating new certificate request...'));
|
|
417
|
-
const { csrPem, keyPem } = generateCSR(devId);
|
|
418
|
-
logger.log(chalk.gray(' Requesting new certificate (issue-cert)...'));
|
|
419
|
-
const issueResponse = await requestCertificate(auth.serverUrl, devId, pin, csrPem, serverCaPem);
|
|
420
|
-
const caPem = mergeCaPemBlocks(serverCaPem, issueResponse.caCertificate, issueResponse.ca);
|
|
421
|
-
await saveCertAndConfig(configDir, devId, issueResponse.certificate, keyPem, caPem);
|
|
422
|
-
await applySettingsFromServer(auth.serverUrl, devId, issueResponse, keyPem, serverCaPem);
|
|
423
|
-
await augmentAndSaveCaPemForRemoteDocker(configDir, devId, caPem, {
|
|
424
|
-
settings: issueResponse.settings,
|
|
425
|
-
remoteServerUrl: auth.serverUrl,
|
|
426
|
-
warn: (msg) => logger.log(chalk.yellow(` ā ${msg}`))
|
|
427
|
-
});
|
|
428
|
-
logger.log(formatSuccessLine('Certificate refreshed and config updated from server.\n'));
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* GET /api/dev/settings and merge into local config (used by dev refresh when cert is still valid).
|
|
433
|
-
* @param {{ serverUrl: string, serverCaPem?: string|null }} auth
|
|
434
|
-
* @param {string} clientCertPem
|
|
435
|
-
* @param {string|null|undefined} clientKeyPem
|
|
436
|
-
* @param {string} devId
|
|
437
|
-
* @returns {Promise<void>}
|
|
438
|
-
*/
|
|
439
|
-
async function fetchAndMergeRemoteSettings(auth, clientCertPem, clientKeyPem, devId) {
|
|
440
|
-
logger.log(chalk.blue('\nš Fetching settings from Builder Server...\n'));
|
|
441
|
-
const settings = await devApi.getSettings(
|
|
442
|
-
auth.serverUrl,
|
|
443
|
-
clientCertPem,
|
|
444
|
-
clientKeyPem || undefined,
|
|
445
|
-
auth.serverCaPem || undefined
|
|
446
|
-
);
|
|
447
|
-
await config.mergeRemoteSettings(settings);
|
|
448
|
-
const existingCa = readServerCaPem(getCertDir(getConfigDirForPaths(), devId));
|
|
449
|
-
await augmentAndSaveCaPemForRemoteDocker(getConfigDirForPaths(), devId, existingCa, {
|
|
450
|
-
settings,
|
|
451
|
-
remoteServerUrl: auth.serverUrl,
|
|
452
|
-
warn: (msg) => logger.log(chalk.yellow(` ā ${msg}`))
|
|
453
|
-
});
|
|
454
|
-
logger.log(formatSuccessLine('Config updated from server.\n'));
|
|
455
|
-
await displayDevConfig(devId);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
/**
|
|
459
|
-
* Fetch settings from Builder Server and merge into config (GET /api/dev/settings).
|
|
460
|
-
* If certificate expires within CERT_REFRESH_DAYS (or --cert), refresh cert first (create PIN + issue-cert).
|
|
461
|
-
* @param {Object} [options] - Commander options; options.cert = true forces cert refresh
|
|
462
|
-
* @returns {Promise<void>}
|
|
463
|
-
* @throws {Error} If remote server or certificate not configured, or getSettings fails
|
|
464
|
-
*/
|
|
465
|
-
async function runDevRefresh(options = {}) {
|
|
466
|
-
const { getRemoteDevAuth } = require('../utils/remote-dev-auth');
|
|
467
|
-
const auth = await getRemoteDevAuth();
|
|
468
|
-
if (!auth) {
|
|
469
|
-
throw new Error('Remote server is not configured. Set remote-server and run "aifabrix dev init" first.');
|
|
470
|
-
}
|
|
471
|
-
const devId = await config.getDeveloperId();
|
|
472
|
-
const certDir = getCertDir(getConfigDirForPaths(), devId);
|
|
473
|
-
const clientCertPem = readClientCertPem(certDir);
|
|
474
|
-
const clientKeyPem = readClientKeyPem(certDir);
|
|
475
|
-
if (!clientCertPem) {
|
|
476
|
-
throw new Error('Client certificate not found. Run "aifabrix dev init" first.');
|
|
477
|
-
}
|
|
478
|
-
if (Boolean(options.cert) || shouldRefreshDevCert(certDir)) {
|
|
479
|
-
await runCertificateRefresh(auth);
|
|
480
|
-
await displayDevConfig(devId);
|
|
481
|
-
return;
|
|
482
|
-
}
|
|
483
|
-
await fetchAndMergeRemoteSettings(auth, clientCertPem, clientKeyPem, devId);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
module.exports = { runDevInit, runDevRefresh };
|
|
381
|
+
module.exports = {
|
|
382
|
+
runDevInit,
|
|
383
|
+
requestCertificate,
|
|
384
|
+
saveCertAndConfig,
|
|
385
|
+
applySettingsFromServer
|
|
386
|
+
};
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview aifabrix dev refresh ā sync remote settings and renew client cert when due
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 2.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
const config = require('../core/config');
|
|
11
|
+
const { getConfigDirForPaths } = require('../utils/paths');
|
|
12
|
+
const {
|
|
13
|
+
generateCSR,
|
|
14
|
+
getCertDir,
|
|
15
|
+
readClientCertPem,
|
|
16
|
+
readClientKeyPem,
|
|
17
|
+
readServerCaPem,
|
|
18
|
+
getCertValidNotAfter,
|
|
19
|
+
mergeCaPemBlocks
|
|
20
|
+
} = require('../utils/dev-cert-helper');
|
|
21
|
+
const devApi = require('../api/dev.api');
|
|
22
|
+
const logger = require('../utils/logger');
|
|
23
|
+
const { mergeDevSshConfigAfterInit, logDevSshConnectHint } = require('../utils/dev-init-ssh-merge');
|
|
24
|
+
const { displayDevConfig } = require('./dev-show-display');
|
|
25
|
+
const { augmentAndSaveCaPemForRemoteDocker } = require('../utils/dev-ca-docker-augment');
|
|
26
|
+
const { formatSuccessLine } = require('../utils/cli-test-layout-chalk');
|
|
27
|
+
const {
|
|
28
|
+
requestCertificate,
|
|
29
|
+
saveCertAndConfig,
|
|
30
|
+
applySettingsFromServer
|
|
31
|
+
} = require('./dev-init');
|
|
32
|
+
|
|
33
|
+
/** Days before cert expiry at which we auto-refresh on dev refresh / auto-renew. */
|
|
34
|
+
const CERT_REFRESH_DAYS = 14;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* True if the cert expires within CERT_REFRESH_DAYS (or expiry cannot be read).
|
|
38
|
+
* Used by explicit `dev refresh` (also attempts when expiry is unknown).
|
|
39
|
+
* @param {string} certDir
|
|
40
|
+
* @returns {boolean}
|
|
41
|
+
*/
|
|
42
|
+
function shouldRefreshDevCert(certDir) {
|
|
43
|
+
const validNotAfter = getCertValidNotAfter(certDir);
|
|
44
|
+
if (!validNotAfter) return true;
|
|
45
|
+
const now = Date.now();
|
|
46
|
+
const threshold = now + CERT_REFRESH_DAYS * 24 * 60 * 60 * 1000;
|
|
47
|
+
return validNotAfter.getTime() < threshold;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* True when cert is still valid but expires within CERT_REFRESH_DAYS.
|
|
52
|
+
* Used for automatic renew (never tries when already expired).
|
|
53
|
+
* @param {string} certDir
|
|
54
|
+
* @returns {boolean}
|
|
55
|
+
*/
|
|
56
|
+
function isDevCertAutoRenewalDue(certDir) {
|
|
57
|
+
const validNotAfter = getCertValidNotAfter(certDir);
|
|
58
|
+
if (!validNotAfter) return false;
|
|
59
|
+
const now = Date.now();
|
|
60
|
+
if (validNotAfter.getTime() <= now) return false;
|
|
61
|
+
const threshold = now + CERT_REFRESH_DAYS * 24 * 60 * 60 * 1000;
|
|
62
|
+
return validNotAfter.getTime() < threshold;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Refresh developer certificate: create PIN (with current cert), issue new cert, save and apply settings.
|
|
67
|
+
* @param {{ serverUrl: string, clientCertPem: string, serverCaPem?: string|null }} auth
|
|
68
|
+
* @returns {Promise<void>}
|
|
69
|
+
*/
|
|
70
|
+
async function runCertificateRefresh(auth) {
|
|
71
|
+
const devId = await config.getDeveloperId();
|
|
72
|
+
if (!devId) throw new Error('developer-id not set in config.');
|
|
73
|
+
const configDir = getConfigDirForPaths();
|
|
74
|
+
const serverCaPem = auth.serverCaPem || undefined;
|
|
75
|
+
logger.log(chalk.blue('\nš Refreshing certificate (create PIN + issue-cert)...\n'));
|
|
76
|
+
const pinRes = await devApi.createPin(auth.serverUrl, auth.clientCertPem, devId, serverCaPem);
|
|
77
|
+
const pin = pinRes.pin;
|
|
78
|
+
if (!pin || typeof pin !== 'string') throw new Error('Server did not return a PIN.');
|
|
79
|
+
logger.log(chalk.gray(' Generating new certificate request...'));
|
|
80
|
+
const { csrPem, keyPem } = generateCSR(devId);
|
|
81
|
+
logger.log(chalk.gray(' Requesting new certificate (issue-cert)...'));
|
|
82
|
+
const issueResponse = await requestCertificate(auth.serverUrl, devId, pin, csrPem, serverCaPem);
|
|
83
|
+
const caPem = mergeCaPemBlocks(serverCaPem, issueResponse.caCertificate, issueResponse.ca);
|
|
84
|
+
await saveCertAndConfig(configDir, devId, issueResponse.certificate, keyPem, caPem);
|
|
85
|
+
await applySettingsFromServer(auth.serverUrl, devId, issueResponse, keyPem, serverCaPem);
|
|
86
|
+
await augmentAndSaveCaPemForRemoteDocker(configDir, devId, caPem, {
|
|
87
|
+
settings: issueResponse.settings,
|
|
88
|
+
remoteServerUrl: auth.serverUrl,
|
|
89
|
+
warn: (msg) => logger.log(chalk.yellow(` ā ${msg}`))
|
|
90
|
+
});
|
|
91
|
+
logger.log(formatSuccessLine('Certificate refreshed and config updated from server.\n'));
|
|
92
|
+
logDevSshConnectHint(await mergeDevSshConfigAfterInit(auth.serverUrl, devId));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* GET /api/dev/settings and merge into local config (when cert is still valid).
|
|
97
|
+
* @param {{ serverUrl: string, serverCaPem?: string|null }} auth
|
|
98
|
+
* @param {string} clientCertPem
|
|
99
|
+
* @param {string|null|undefined} clientKeyPem
|
|
100
|
+
* @param {string} devId
|
|
101
|
+
* @returns {Promise<void>}
|
|
102
|
+
*/
|
|
103
|
+
async function fetchAndMergeRemoteSettings(auth, clientCertPem, clientKeyPem, devId) {
|
|
104
|
+
logger.log(chalk.blue('\nš Fetching settings from Builder Server...\n'));
|
|
105
|
+
const settings = await devApi.getSettings(
|
|
106
|
+
auth.serverUrl,
|
|
107
|
+
clientCertPem,
|
|
108
|
+
clientKeyPem || undefined,
|
|
109
|
+
auth.serverCaPem || undefined
|
|
110
|
+
);
|
|
111
|
+
await config.mergeRemoteSettings(settings);
|
|
112
|
+
const existingCa = readServerCaPem(getCertDir(getConfigDirForPaths(), devId));
|
|
113
|
+
await augmentAndSaveCaPemForRemoteDocker(getConfigDirForPaths(), devId, existingCa, {
|
|
114
|
+
settings,
|
|
115
|
+
remoteServerUrl: auth.serverUrl,
|
|
116
|
+
warn: (msg) => logger.log(chalk.yellow(` ā ${msg}`))
|
|
117
|
+
});
|
|
118
|
+
logger.log(formatSuccessLine('Config updated from server.\n'));
|
|
119
|
+
await displayDevConfig(devId);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Fetch settings from Builder Server and merge into config.
|
|
124
|
+
* If certificate expires within CERT_REFRESH_DAYS (or --cert), refresh cert first.
|
|
125
|
+
* @param {Object} [options] - Commander options; options.cert = true forces cert refresh
|
|
126
|
+
* @returns {Promise<void>}
|
|
127
|
+
*/
|
|
128
|
+
async function runDevRefresh(options = {}) {
|
|
129
|
+
const { readRemoteDevAuth } = require('../utils/remote-dev-auth');
|
|
130
|
+
const auth = await readRemoteDevAuth();
|
|
131
|
+
if (!auth) {
|
|
132
|
+
throw new Error('Remote server is not configured. Set remote-server and run "aifabrix dev init" first.');
|
|
133
|
+
}
|
|
134
|
+
const devId = await config.getDeveloperId();
|
|
135
|
+
const certDir = getCertDir(getConfigDirForPaths(), devId);
|
|
136
|
+
const clientCertPem = readClientCertPem(certDir);
|
|
137
|
+
const clientKeyPem = readClientKeyPem(certDir);
|
|
138
|
+
if (!clientCertPem) {
|
|
139
|
+
throw new Error('Client certificate not found. Run "aifabrix dev init" first.');
|
|
140
|
+
}
|
|
141
|
+
if (Boolean(options.cert) || shouldRefreshDevCert(certDir)) {
|
|
142
|
+
await runCertificateRefresh(auth);
|
|
143
|
+
await displayDevConfig(devId);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
await fetchAndMergeRemoteSettings(auth, clientCertPem, clientKeyPem, devId);
|
|
147
|
+
logDevSshConnectHint(await mergeDevSshConfigAfterInit(auth.serverUrl, devId));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Automatically renew the developer client certificate when still valid but due within
|
|
152
|
+
* CERT_REFRESH_DAYS. Safe for any cert-using command: no-op when not due / offline.
|
|
153
|
+
* Uses readRemoteDevAuth (not getRemoteDevAuth) to avoid recursion with auto-renew.
|
|
154
|
+
* Does not display config (caller shows status afterward).
|
|
155
|
+
*
|
|
156
|
+
* @param {{ quiet?: boolean }} [opts] - quiet=true suppresses failure warnings
|
|
157
|
+
* @returns {Promise<{ refreshed: boolean, reason?: string, error?: Error }>}
|
|
158
|
+
*/
|
|
159
|
+
async function ensureDevCertFreshIfDue(opts = {}) {
|
|
160
|
+
const quiet = opts.quiet === true;
|
|
161
|
+
const { readRemoteDevAuth } = require('../utils/remote-dev-auth');
|
|
162
|
+
const auth = await readRemoteDevAuth();
|
|
163
|
+
if (!auth) {
|
|
164
|
+
return { refreshed: false, reason: 'no-remote-auth' };
|
|
165
|
+
}
|
|
166
|
+
const devId = await config.getDeveloperId();
|
|
167
|
+
if (!devId) {
|
|
168
|
+
return { refreshed: false, reason: 'no-developer-id' };
|
|
169
|
+
}
|
|
170
|
+
const certDir = getCertDir(getConfigDirForPaths(), devId);
|
|
171
|
+
if (!readClientCertPem(certDir)) {
|
|
172
|
+
return { refreshed: false, reason: 'no-cert' };
|
|
173
|
+
}
|
|
174
|
+
if (!isDevCertAutoRenewalDue(certDir)) {
|
|
175
|
+
return { refreshed: false, reason: 'not-due' };
|
|
176
|
+
}
|
|
177
|
+
try {
|
|
178
|
+
await runCertificateRefresh(auth);
|
|
179
|
+
return { refreshed: true };
|
|
180
|
+
} catch (error) {
|
|
181
|
+
if (!quiet) {
|
|
182
|
+
logger.warn(
|
|
183
|
+
chalk.yellow(`Could not auto-refresh developer certificate: ${error.message}`)
|
|
184
|
+
);
|
|
185
|
+
logger.warn(chalk.gray(' Run: aifabrix dev refresh --cert'));
|
|
186
|
+
}
|
|
187
|
+
return { refreshed: false, reason: 'refresh-failed', error };
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
module.exports = {
|
|
192
|
+
runDevRefresh,
|
|
193
|
+
ensureDevCertFreshIfDue,
|
|
194
|
+
isDevCertAutoRenewalDue,
|
|
195
|
+
shouldRefreshDevCert,
|
|
196
|
+
CERT_REFRESH_DAYS
|
|
197
|
+
};
|