@aifabrix/builder 2.49.2 → 2.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/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/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.api.js +172 -0
- package/lib/api/external-systems.api.js +8 -2
- package/lib/api/resource-types.api.js +1 -0
- package/lib/api/types/enterprise-knowledge.types.js +46 -0
- package/lib/api/types/evidence.types.js +67 -0
- package/lib/api/types/resource-types.types.js +2 -0
- 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 +37 -88
- 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/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 +16 -4
- 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 +27 -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 +38 -125
- 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 +7 -2
- 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-repair.js +26 -7
- 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 +163 -0
- package/lib/commands/deploy-gate-orchestrator.js +322 -0
- package/lib/commands/dev-cli-handlers.js +1 -59
- 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 +3 -1
- package/lib/commands/enterprise-knowledge.js +284 -0
- package/lib/commands/evidence-cli-leaves.js +250 -0
- package/lib/commands/evidence.js +51 -0
- package/lib/commands/governance-cli-shared.js +2 -2
- package/lib/commands/governance-command-action.js +2 -2
- 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 +19 -2
- 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 +65 -26
- package/lib/commands/run-post-publish-data-sync.js +68 -0
- package/lib/commands/setup-modes.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/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 +2 -2
- 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/secrets-env-content.js +10 -4
- package/lib/core/secrets-env-write.js +2 -13
- package/lib/datasource/agent-trust-run.js +3 -3
- 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/index.js +17 -2
- package/lib/generator/wizard.js +3 -36
- 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 +44 -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 +98 -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 +205 -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 +476 -0
- package/lib/programmatic/openapi-schema-descriptions-certify.js +139 -0
- package/lib/programmatic/openapi-schema-descriptions-core.js +159 -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 +93 -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 +54 -0
- package/lib/programmatic/run-template-workspace.js +61 -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/resource-type-file.js +22 -0
- package/lib/schema/external-datasource.schema.json +161 -1
- package/lib/schema/external-system.schema.json +244 -118
- package/lib/schema/flag-map-validation-run.json +3 -0
- package/lib/schema/type/credential-field-registry.json +2 -2
- package/lib/schema/type/document-storage.json +9 -0
- package/lib/utils/agent-trust-run-display.js +1 -1
- package/lib/utils/app-path-resolve.js +168 -0
- package/lib/utils/authentication-env-template.js +222 -0
- package/lib/utils/cli-sync-options.js +7 -11
- package/lib/utils/cli-utils.js +4 -0
- 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-init-ssh-merge.js +165 -23
- package/lib/utils/dev-pin-share-instructions.js +110 -0
- package/lib/utils/dev-ssh-config-helper.js +177 -33
- package/lib/utils/enterprise-knowledge-paths.js +142 -0
- package/lib/utils/env-copy.js +2 -1
- package/lib/utils/env-dotenv-format.js +103 -0
- package/lib/utils/external-env-template.js +4 -1
- package/lib/utils/external-system-display.js +5 -1
- package/lib/utils/external-system-readiness-compact-blocks.js +221 -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/help-builder.js +6 -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/integration-path-resolve.js +112 -0
- package/lib/utils/paths-reload-source.js +148 -0
- package/lib/utils/paths-system-builder-keys.js +25 -0
- package/lib/utils/paths.js +151 -26
- 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/upload-sync-options.js +4 -0
- 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 +426 -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/package.json +46 -29
- 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 +326 -0
- package/scripts/lib/plan-run-core.js +125 -0
- package/scripts/lib/plan-run-report.js +108 -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 +1 -1
- package/templates/applications/dataplane/env.template +10 -6
- package/templates/applications/dataplane/rbac.yaml +21 -1
- package/templates/applications/miso-controller/application.yaml +1 -1
- package/templates/applications/miso-controller/env.template +1 -3
- 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 +86 -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 +1 -1
- package/templates/typescript/docker-compose.hbs +11 -0
- package/lib/certification/cli-cert-sync-skip.js +0 -21
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Deploy pre-promote baseline tests and optional --gate steps (456.9).
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
const { sectionTitle } = require('../utils/cli-test-layout-chalk');
|
|
11
|
+
const logger = require('../utils/logger');
|
|
12
|
+
const { formatDeployGateFailure } = require('./deploy-gate-failure-details');
|
|
13
|
+
const { testExternalSystem, testExternalSystemIntegration } = require('../external-system/test');
|
|
14
|
+
const { runWithVerifyStepProgress } = require('../lifecycle/verify-step-progress');
|
|
15
|
+
const { runTestE2EForExternalSystem, syncLocalIfRequested, resolveExternalIntegrationContext } = require('./test-e2e-external');
|
|
16
|
+
const { cliOptsSkipPublish } = require('../utils/cli-sync-options');
|
|
17
|
+
const { resolveE2eSyncModeWhenPopulated } = require('./datasource-sync-policy');
|
|
18
|
+
const { runVerifyTrustForExternalSystem } = require('./verify-trust-external');
|
|
19
|
+
const { runVerifyGovernanceForExternalSystem } = require('./verify-governance-external');
|
|
20
|
+
const { runGovernanceGenerateForExternalSystem } = require('./governance-generate-external');
|
|
21
|
+
const { resolveGovernanceFixtureSubjectEmails } = require('./governance-fixture-subjects');
|
|
22
|
+
const { runVerifyGovernanceCombined } = require('./verify-governance-combined-external');
|
|
23
|
+
const { VERDICT } = require('../lifecycle/product-model');
|
|
24
|
+
|
|
25
|
+
const KNOWN_GATES = ['operations', 'trust', 'governance'];
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {string|undefined} gateRaw
|
|
29
|
+
* @returns {string[]}
|
|
30
|
+
*/
|
|
31
|
+
function parseDeployGateTokens(gateRaw) {
|
|
32
|
+
if (!gateRaw || typeof gateRaw !== 'string') {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
const tokens = gateRaw
|
|
36
|
+
.split(',')
|
|
37
|
+
.map((part) => part.trim().toLowerCase())
|
|
38
|
+
.filter(Boolean);
|
|
39
|
+
if (tokens.includes('full')) {
|
|
40
|
+
return [...KNOWN_GATES];
|
|
41
|
+
}
|
|
42
|
+
return tokens.filter((token) => KNOWN_GATES.includes(token));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Strict promote posture suggests full optional gates when caller requests profile resolution.
|
|
47
|
+
* @returns {string[]}
|
|
48
|
+
*/
|
|
49
|
+
function resolveStrictPromoteGateProfile() {
|
|
50
|
+
const level = (process.env.TRUST_CUSTOMER_POLICY_LEVEL || 'standard').trim().toLowerCase();
|
|
51
|
+
if (level === 'strict') {
|
|
52
|
+
return [...KNOWN_GATES];
|
|
53
|
+
}
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {string|undefined} gateRaw
|
|
59
|
+
* @param {Object} [options]
|
|
60
|
+
* @returns {Set<string>}
|
|
61
|
+
*/
|
|
62
|
+
function resolveDeployGateSet(gateRaw, options = {}) {
|
|
63
|
+
const explicit = parseDeployGateTokens(gateRaw);
|
|
64
|
+
if (explicit.length > 0) {
|
|
65
|
+
return new Set(explicit);
|
|
66
|
+
}
|
|
67
|
+
if (options.useStrictPromoteProfile === true) {
|
|
68
|
+
return new Set(resolveStrictPromoteGateProfile());
|
|
69
|
+
}
|
|
70
|
+
return new Set();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @param {Object} options
|
|
75
|
+
* @param {Object|null|undefined} uploadCtx
|
|
76
|
+
* @returns {Object}
|
|
77
|
+
*/
|
|
78
|
+
function mergeUploadAuthOptions(options, uploadCtx) {
|
|
79
|
+
if (!uploadCtx?.authConfig || !uploadCtx?.dataplaneUrl) {
|
|
80
|
+
return { ...options, noPublish: true, verbose: false };
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
...options,
|
|
84
|
+
noPublish: true,
|
|
85
|
+
verbose: false,
|
|
86
|
+
authConfig: uploadCtx.authConfig,
|
|
87
|
+
dataplaneUrl: uploadCtx.dataplaneUrl,
|
|
88
|
+
silentResolve: true
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @async
|
|
94
|
+
* @param {string} label
|
|
95
|
+
* @param {Function} runner
|
|
96
|
+
* @param {Function} isOk
|
|
97
|
+
* @param {Object} [stepOptions]
|
|
98
|
+
*/
|
|
99
|
+
async function runRequiredDeployStep(label, runner, isOk, stepOptions = {}) {
|
|
100
|
+
return runWithVerifyStepProgress(
|
|
101
|
+
label,
|
|
102
|
+
async() => {
|
|
103
|
+
const outcome = await runner();
|
|
104
|
+
if (!isOk(outcome)) {
|
|
105
|
+
const detail = formatDeployGateFailure(label, outcome);
|
|
106
|
+
logger.log(chalk.red(`✖ ${detail}`));
|
|
107
|
+
const err = new Error(`${label} failed: ${detail}`);
|
|
108
|
+
err.gateFailure = true;
|
|
109
|
+
throw err;
|
|
110
|
+
}
|
|
111
|
+
return outcome;
|
|
112
|
+
},
|
|
113
|
+
{ json: false, quietProgress: stepOptions.quietDeployUi === true }
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @async
|
|
119
|
+
* @param {string} systemKey
|
|
120
|
+
* @param {Object} options
|
|
121
|
+
* @returns {Promise<{ unitPassed: boolean, integrationPassed: boolean }>}
|
|
122
|
+
*/
|
|
123
|
+
async function runDeployBaselineSteps(systemKey, options) {
|
|
124
|
+
await runRequiredDeployStep(
|
|
125
|
+
'Running unit tests',
|
|
126
|
+
() => testExternalSystem(systemKey, { verbose: false }),
|
|
127
|
+
(result) => result.valid === true,
|
|
128
|
+
options
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
let stepOptions = { ...options, noPublish: true, verbose: false, uploadStatus: 'published' };
|
|
132
|
+
if (!cliOptsSkipPublish(options)) {
|
|
133
|
+
const uploadCtx = await syncLocalIfRequested(systemKey, {
|
|
134
|
+
...options,
|
|
135
|
+
uploadStatus: 'published',
|
|
136
|
+
minimal: true,
|
|
137
|
+
suppressSummary: true
|
|
138
|
+
});
|
|
139
|
+
stepOptions = mergeUploadAuthOptions({ ...options, uploadStatus: 'published' }, uploadCtx);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
await runRequiredDeployStep(
|
|
143
|
+
'Running integration tests',
|
|
144
|
+
() => testExternalSystemIntegration(systemKey, stepOptions),
|
|
145
|
+
(result) => result.success === true,
|
|
146
|
+
options
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
return { unitPassed: true, integrationPassed: true };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @async
|
|
154
|
+
* @param {string} systemKey
|
|
155
|
+
* @param {Object} options
|
|
156
|
+
* @returns {Promise<Object>}
|
|
157
|
+
*/
|
|
158
|
+
async function runOperationsGate(systemKey, options) {
|
|
159
|
+
let stepOptions = mergeUploadAuthOptions(options, null);
|
|
160
|
+
if (!stepOptions.dataplaneUrl || !stepOptions.authConfig) {
|
|
161
|
+
try {
|
|
162
|
+
const uploadCtx = await syncLocalIfRequested(systemKey, { ...options, noPublish: true });
|
|
163
|
+
stepOptions = mergeUploadAuthOptions(options, uploadCtx);
|
|
164
|
+
} catch {
|
|
165
|
+
stepOptions = mergeUploadAuthOptions(options, null);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
let e2eSyncMode = options.syncMode;
|
|
170
|
+
if (!e2eSyncMode && stepOptions.dataplaneUrl && stepOptions.authConfig) {
|
|
171
|
+
try {
|
|
172
|
+
const { keys } = resolveExternalIntegrationContext(systemKey);
|
|
173
|
+
e2eSyncMode = await resolveE2eSyncModeWhenPopulated(
|
|
174
|
+
stepOptions.dataplaneUrl,
|
|
175
|
+
stepOptions.authConfig,
|
|
176
|
+
keys
|
|
177
|
+
);
|
|
178
|
+
} catch {
|
|
179
|
+
e2eSyncMode = 'auto';
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
await runRequiredDeployStep(
|
|
184
|
+
'Running operations gate (E2E)',
|
|
185
|
+
() =>
|
|
186
|
+
runTestE2EForExternalSystem(systemKey, {
|
|
187
|
+
...stepOptions,
|
|
188
|
+
env: options.env,
|
|
189
|
+
async: options.async !== false,
|
|
190
|
+
quietPollUi: true,
|
|
191
|
+
syncMode: e2eSyncMode || stepOptions.syncMode
|
|
192
|
+
}),
|
|
193
|
+
(result) => result.success === true,
|
|
194
|
+
options
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
return { pillar: 'operations', verdict: VERDICT.VERIFIED };
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* @async
|
|
202
|
+
* @param {string} systemKey
|
|
203
|
+
* @param {Object} options
|
|
204
|
+
* @returns {Promise<Object>}
|
|
205
|
+
*/
|
|
206
|
+
async function runTrustGate(systemKey, options) {
|
|
207
|
+
const result = await runRequiredDeployStep(
|
|
208
|
+
'Running trust gate',
|
|
209
|
+
() => runVerifyTrustForExternalSystem(systemKey, { ...options, noPublish: true }),
|
|
210
|
+
(outcome) => outcome.verdict === VERDICT.VERIFIED,
|
|
211
|
+
options
|
|
212
|
+
);
|
|
213
|
+
return {
|
|
214
|
+
pillar: 'trust',
|
|
215
|
+
verdict: result.verdict,
|
|
216
|
+
percent: result.aiTrustPercent ?? undefined
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* @param {Object} options
|
|
222
|
+
* @returns {boolean}
|
|
223
|
+
*/
|
|
224
|
+
function governanceSubjectsProvided(options) {
|
|
225
|
+
return Boolean(options.subjectEmail);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* @async
|
|
230
|
+
* @param {string} systemKey
|
|
231
|
+
* @param {Object} options
|
|
232
|
+
* @returns {Promise<Object>}
|
|
233
|
+
*/
|
|
234
|
+
async function runGovernanceGate(systemKey, options) {
|
|
235
|
+
const gateOptions = { ...options, noPublish: true };
|
|
236
|
+
let runner;
|
|
237
|
+
if (governanceSubjectsProvided(gateOptions)) {
|
|
238
|
+
runner = () => runVerifyGovernanceCombined(systemKey, gateOptions);
|
|
239
|
+
} else {
|
|
240
|
+
const fixtureEmails = resolveGovernanceFixtureSubjectEmails(systemKey);
|
|
241
|
+
if (fixtureEmails.length > 0) {
|
|
242
|
+
runner = async() => {
|
|
243
|
+
await runGovernanceGenerateForExternalSystem(systemKey, {
|
|
244
|
+
...gateOptions,
|
|
245
|
+
subjectEmails: fixtureEmails
|
|
246
|
+
});
|
|
247
|
+
return runVerifyGovernanceForExternalSystem(systemKey, gateOptions);
|
|
248
|
+
};
|
|
249
|
+
} else {
|
|
250
|
+
runner = () => runVerifyGovernanceForExternalSystem(systemKey, gateOptions);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
const result = await runRequiredDeployStep(
|
|
254
|
+
'Running governance gate',
|
|
255
|
+
runner,
|
|
256
|
+
(outcome) => outcome.verdict === VERDICT.VERIFIED,
|
|
257
|
+
options
|
|
258
|
+
);
|
|
259
|
+
const scenarios = result.enforcementScenarios || {};
|
|
260
|
+
return {
|
|
261
|
+
pillar: 'governance',
|
|
262
|
+
verdict: result.verdict,
|
|
263
|
+
scenariosPassed: scenarios.passed,
|
|
264
|
+
scenariosTotal: scenarios.total
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* @async
|
|
270
|
+
* @param {string} systemKey
|
|
271
|
+
* @param {Set<string>} gates
|
|
272
|
+
* @param {Object} options
|
|
273
|
+
* @returns {Promise<Object[]>}
|
|
274
|
+
*/
|
|
275
|
+
async function runDeployOptionalGates(systemKey, gates, options) {
|
|
276
|
+
const outcomes = [];
|
|
277
|
+
if (gates.has('operations')) {
|
|
278
|
+
outcomes.push(await runOperationsGate(systemKey, options));
|
|
279
|
+
}
|
|
280
|
+
if (gates.has('trust')) {
|
|
281
|
+
outcomes.push(await runTrustGate(systemKey, options));
|
|
282
|
+
}
|
|
283
|
+
if (gates.has('governance')) {
|
|
284
|
+
outcomes.push(await runGovernanceGate(systemKey, options));
|
|
285
|
+
}
|
|
286
|
+
return outcomes;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Baseline validate + test + test-integration, then optional --gate steps before controller deploy.
|
|
291
|
+
* @async
|
|
292
|
+
* @param {string} systemKey
|
|
293
|
+
* @param {Object} [options]
|
|
294
|
+
* @returns {Promise<{ baseline: { unitPassed: boolean, integrationPassed: boolean }, gates: Object[] }>}
|
|
295
|
+
*/
|
|
296
|
+
async function runDeployGateOrchestrator(systemKey, options = {}) {
|
|
297
|
+
const quiet = options.quietDeployUi === true || options.verbose !== true;
|
|
298
|
+
if (!quiet) {
|
|
299
|
+
logger.log('');
|
|
300
|
+
logger.log(sectionTitle('Deploy preflight'));
|
|
301
|
+
}
|
|
302
|
+
const baseline = await runDeployBaselineSteps(systemKey, { ...options, quietDeployUi: quiet });
|
|
303
|
+
const gates = resolveDeployGateSet(options.gate, options);
|
|
304
|
+
if (gates.size === 0) {
|
|
305
|
+
return { baseline, gates: [] };
|
|
306
|
+
}
|
|
307
|
+
const gateOutcomes = await runDeployOptionalGates(systemKey, gates, {
|
|
308
|
+
...options,
|
|
309
|
+
quietDeployUi: quiet
|
|
310
|
+
});
|
|
311
|
+
return { baseline, gates: gateOutcomes };
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
module.exports = {
|
|
315
|
+
KNOWN_GATES,
|
|
316
|
+
parseDeployGateTokens,
|
|
317
|
+
resolveStrictPromoteGateProfile,
|
|
318
|
+
resolveDeployGateSet,
|
|
319
|
+
runDeployBaselineSteps,
|
|
320
|
+
runDeployOptionalGates,
|
|
321
|
+
runDeployGateOrchestrator
|
|
322
|
+
};
|
|
@@ -17,6 +17,7 @@ const {
|
|
|
17
17
|
augmentDevUserGroupsServerError
|
|
18
18
|
} = require('../utils/dev-user-groups');
|
|
19
19
|
const { handleProvisionDevUser, handleRemoveDevUser } = require('./dev-host-ops');
|
|
20
|
+
const { logDevPinShareInstructions } = require('../utils/dev-pin-share-instructions');
|
|
20
21
|
|
|
21
22
|
const REMOTE_NOT_CONFIGURED_MSG = 'Remote server is not configured. Set remote-server and run "aifabrix dev init" first.';
|
|
22
23
|
|
|
@@ -149,64 +150,6 @@ async function handleDevUpdate(developerId, options) {
|
|
|
149
150
|
}
|
|
150
151
|
}
|
|
151
152
|
|
|
152
|
-
function logPinHostsVariantLines(baseInit, id, hostsIp) {
|
|
153
|
-
logger.log(
|
|
154
|
-
chalk.cyan('2) Hosts file / administrator')
|
|
155
|
-
+ chalk.gray(
|
|
156
|
-
' — use when the hostname does not resolve and your organisation does not publish DNS for it. '
|
|
157
|
-
+ 'Run in an elevated terminal so the hosts file can be updated, or add the entry manually:'
|
|
158
|
-
)
|
|
159
|
-
);
|
|
160
|
-
if (hostsIp) {
|
|
161
|
-
logger.log(` ${baseInit} --add-hosts --hosts-ip ${hostsIp}`);
|
|
162
|
-
} else {
|
|
163
|
-
logger.log(` ${baseInit} --add-hosts --hosts-ip <server-LAN-IPv4>`);
|
|
164
|
-
logger.log(
|
|
165
|
-
chalk.gray(
|
|
166
|
-
` Replace <server-LAN-IPv4> with the Builder Server IPv4, or re-run: aifabrix dev pin ${id} --hosts-ip <ip>`
|
|
167
|
-
)
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Log copy-paste dev init commands for the developer (standard vs hosts-file).
|
|
174
|
-
* @param {Object} p
|
|
175
|
-
* @param {string} p.id - Developer ID
|
|
176
|
-
* @param {string} p.serverUrl - Builder Server base URL
|
|
177
|
-
* @param {string} p.pin - One-time PIN
|
|
178
|
-
* @param {string} p.expiresAt - PIN expiry (API string)
|
|
179
|
-
* @param {string} [p.hostsIp] - Optional IPv4 for the hosts variant
|
|
180
|
-
* @returns {void}
|
|
181
|
-
*/
|
|
182
|
-
function logDevPinShareInstructions(p) {
|
|
183
|
-
const { id, serverUrl, pin, expiresAt, hostsIp } = p;
|
|
184
|
-
const baseInit = `aifabrix dev init --developer-id ${id} --server ${serverUrl} --pin ${pin}`;
|
|
185
|
-
const pinOnly = `aifabrix dev init --pin ${pin}`;
|
|
186
|
-
logger.log(formatSuccessLine(`PIN created for ${id}, expires ${expiresAt}.`));
|
|
187
|
-
logger.log('');
|
|
188
|
-
logger.log(
|
|
189
|
-
chalk.bold('Share with the developer — they run one command (the PIN is one-time):')
|
|
190
|
-
);
|
|
191
|
-
logger.log('');
|
|
192
|
-
logger.log(
|
|
193
|
-
chalk.cyan('1) Standard')
|
|
194
|
-
+ chalk.gray(' — use when this machine can resolve the server hostname (DNS or hosts already set):')
|
|
195
|
-
);
|
|
196
|
-
logger.log(` ${baseInit}`);
|
|
197
|
-
logger.log('');
|
|
198
|
-
logPinHostsVariantLines(baseInit, id, hostsIp);
|
|
199
|
-
logger.log('');
|
|
200
|
-
logger.log(
|
|
201
|
-
chalk.cyan('3) Config already has remote-server + developer-id')
|
|
202
|
-
+ chalk.gray(
|
|
203
|
-
' — e.g. second machine / SSH session after settings were merged; same onboarding, PIN only:'
|
|
204
|
-
)
|
|
205
|
-
);
|
|
206
|
-
logger.log(` ${pinOnly}`);
|
|
207
|
-
logger.log('');
|
|
208
|
-
}
|
|
209
|
-
|
|
210
153
|
/**
|
|
211
154
|
* Handle dev pin – create/regenerate PIN (remote only).
|
|
212
155
|
* @param {string} [developerId] - Developer ID (optional; uses config if omitted)
|
|
@@ -294,7 +237,6 @@ async function handleDevDelete(developerId, options = {}) {
|
|
|
294
237
|
}
|
|
295
238
|
}
|
|
296
239
|
await handleRemoveDevUser(id, { ...options, developerId: id });
|
|
297
|
-
logger.log(formatSuccessLine(`Developer ${id} removal queued and completed.`));
|
|
298
240
|
}
|
|
299
241
|
|
|
300
242
|
module.exports = {
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Map Commander options to host-ops job params
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {Object} options
|
|
9
|
+
* @param {string[]} keys
|
|
10
|
+
* @returns {string|undefined}
|
|
11
|
+
*/
|
|
12
|
+
function firstOption(options, ...keys) {
|
|
13
|
+
for (const key of keys) {
|
|
14
|
+
const value = options[key];
|
|
15
|
+
if (value !== undefined && value !== null && value !== '') {
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {Object} params
|
|
24
|
+
* @param {Object} options
|
|
25
|
+
* @param {Array<[string, ...string[]]>} mappings
|
|
26
|
+
*/
|
|
27
|
+
function assignStringParams(params, options, mappings) {
|
|
28
|
+
for (const [paramKey, ...optionKeys] of mappings) {
|
|
29
|
+
const value = firstOption(options, ...optionKeys);
|
|
30
|
+
if (value !== undefined) {
|
|
31
|
+
params[paramKey] = value;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {Object} params
|
|
38
|
+
* @param {Object} options
|
|
39
|
+
* @param {Array<[string, ...string[]]>} mappings
|
|
40
|
+
*/
|
|
41
|
+
function assignFlagParams(params, options, mappings) {
|
|
42
|
+
for (const [paramKey, ...optionKeys] of mappings) {
|
|
43
|
+
if (optionKeys.some((k) => Boolean(options[k]))) {
|
|
44
|
+
params[paramKey] = true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const STRING_PARAM_MAPPINGS = [
|
|
50
|
+
['include', 'include'],
|
|
51
|
+
['exclude', 'exclude'],
|
|
52
|
+
['builderVersion', 'builderVersion', 'builder-version'],
|
|
53
|
+
['adminEmail', 'adminEmail', 'admin-email'],
|
|
54
|
+
['adminPassword', 'adminPassword', 'admin-password'],
|
|
55
|
+
['platform', 'platform'],
|
|
56
|
+
['installation', 'installation']
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
const FLAG_PARAM_MAPPINGS = [
|
|
60
|
+
['skipCert', 'skipCert', 'skip-cert'],
|
|
61
|
+
['skipPlatform', 'skipPlatform', 'skip-platform'],
|
|
62
|
+
['skipCli', 'skipCli', 'skip-cli'],
|
|
63
|
+
['check', 'check'],
|
|
64
|
+
['failOnBlocked', 'failOnBlocked']
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Build job params from Commander options.
|
|
69
|
+
* @param {Object} options
|
|
70
|
+
* @param {string} [developerId]
|
|
71
|
+
* @returns {Object}
|
|
72
|
+
*/
|
|
73
|
+
function buildJobParams(options, developerId) {
|
|
74
|
+
const params = {};
|
|
75
|
+
const id = developerId || firstOption(options, 'developerId', 'developer-id');
|
|
76
|
+
if (id) {
|
|
77
|
+
params.developerId = String(id).trim();
|
|
78
|
+
}
|
|
79
|
+
assignStringParams(params, options, STRING_PARAM_MAPPINGS);
|
|
80
|
+
assignFlagParams(params, options, FLAG_PARAM_MAPPINGS);
|
|
81
|
+
const timeoutMinutes = firstOption(options, 'timeoutMinutes', 'timeout-minutes');
|
|
82
|
+
if (timeoutMinutes) {
|
|
83
|
+
params.timeoutMinutes = parseInt(timeoutMinutes, 10);
|
|
84
|
+
}
|
|
85
|
+
return params;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = {
|
|
89
|
+
buildJobParams,
|
|
90
|
+
firstOption
|
|
91
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Host-ops job polling loop
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const hostOpsApi = require('../api/host-ops.api');
|
|
8
|
+
const { assertHostOpsJobSucceeded } = require('../utils/host-ops-job-result');
|
|
9
|
+
|
|
10
|
+
const POLL_INTERVAL_MS = 3000;
|
|
11
|
+
const POLL_TIMEOUT_MS = 3 * 60 * 60 * 1000;
|
|
12
|
+
const TRANSIENT_HTTP_STATUSES = new Set([502, 503, 504]);
|
|
13
|
+
/** Allow ~3 min of consecutive gateway errors (container restart during remove-dev-user). */
|
|
14
|
+
const MAX_TRANSIENT_POLL_ERRORS = 60;
|
|
15
|
+
|
|
16
|
+
function sleep(ms) {
|
|
17
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {Error} err
|
|
22
|
+
* @returns {boolean}
|
|
23
|
+
*/
|
|
24
|
+
function isTransientHostOpsPollError(err) {
|
|
25
|
+
return Boolean(err && TRANSIENT_HTTP_STATUSES.has(err.status));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {Error} err
|
|
30
|
+
* @param {string} jobId
|
|
31
|
+
* @returns {Error}
|
|
32
|
+
*/
|
|
33
|
+
function enhanceTransientHostOpsPollError(err, jobId) {
|
|
34
|
+
const status = err && err.status;
|
|
35
|
+
const base =
|
|
36
|
+
status === 502
|
|
37
|
+
? 'Builder server returned Bad Gateway while waiting for the host job.'
|
|
38
|
+
: `Builder server returned HTTP ${status} while waiting for the host job.`;
|
|
39
|
+
const hint =
|
|
40
|
+
'The job may still be running on the host (common during platform teardown or container restart). ' +
|
|
41
|
+
'Wait 1–2 minutes, then run "aifabrix dev list" to verify. ' +
|
|
42
|
+
`Job id: ${jobId}`;
|
|
43
|
+
return new Error(`${base} ${hint}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {Object} auth
|
|
48
|
+
* @param {string} jobId
|
|
49
|
+
* @param {Object} pollUi
|
|
50
|
+
* @returns {Promise<Object>}
|
|
51
|
+
*/
|
|
52
|
+
async function fetchHostOpsJobWithRetry(auth, jobId, pollUi) {
|
|
53
|
+
const started = Date.now();
|
|
54
|
+
for (let attempt = 0; attempt <= MAX_TRANSIENT_POLL_ERRORS; attempt += 1) {
|
|
55
|
+
try {
|
|
56
|
+
return await hostOpsApi.getHostOpsJob(
|
|
57
|
+
auth.serverUrl,
|
|
58
|
+
auth.clientCertPem,
|
|
59
|
+
jobId,
|
|
60
|
+
auth.serverCaPem || undefined
|
|
61
|
+
);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
if (!isTransientHostOpsPollError(err)) {
|
|
64
|
+
throw err;
|
|
65
|
+
}
|
|
66
|
+
if (attempt >= MAX_TRANSIENT_POLL_ERRORS) {
|
|
67
|
+
throw enhanceTransientHostOpsPollError(err, jobId);
|
|
68
|
+
}
|
|
69
|
+
if (pollUi && typeof pollUi.onTransientError === 'function') {
|
|
70
|
+
pollUi.onTransientError(err, Date.now() - started);
|
|
71
|
+
}
|
|
72
|
+
await sleep(POLL_INTERVAL_MS);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
throw new Error(`Failed to fetch host-ops job ${jobId} after transient retries`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @param {Object} auth
|
|
80
|
+
* @param {string} jobId
|
|
81
|
+
* @param {Object} pollUi
|
|
82
|
+
* @param {boolean} json
|
|
83
|
+
* @returns {Promise<Object>}
|
|
84
|
+
*/
|
|
85
|
+
async function pollHostOpsJobUntilTerminal(auth, jobId, pollUi, json) {
|
|
86
|
+
const started = Date.now();
|
|
87
|
+
while (Date.now() - started < POLL_TIMEOUT_MS) {
|
|
88
|
+
const job = await fetchHostOpsJobWithRetry(auth, jobId, pollUi);
|
|
89
|
+
if (!json) {
|
|
90
|
+
pollUi.onPollProgress(job.status);
|
|
91
|
+
}
|
|
92
|
+
if (job.status === 'failed') {
|
|
93
|
+
throw new Error(job.error || `Host-ops job ${jobId} failed`);
|
|
94
|
+
}
|
|
95
|
+
if (job.status === 'completed') {
|
|
96
|
+
assertHostOpsJobSucceeded(job);
|
|
97
|
+
return job;
|
|
98
|
+
}
|
|
99
|
+
await sleep(POLL_INTERVAL_MS);
|
|
100
|
+
}
|
|
101
|
+
throw new Error(`Timed out waiting for host-ops job ${jobId}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = {
|
|
105
|
+
POLL_INTERVAL_MS,
|
|
106
|
+
POLL_TIMEOUT_MS,
|
|
107
|
+
isTransientHostOpsPollError,
|
|
108
|
+
enhanceTransientHostOpsPollError,
|
|
109
|
+
fetchHostOpsJobWithRetry,
|
|
110
|
+
pollHostOpsJobUntilTerminal
|
|
111
|
+
};
|