@aifabrix/builder 2.49.1 → 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/process/README.md +9 -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/jest.isolated-projects.js +31 -1
- package/jest.projects.js +87 -1
- package/lib/api/dev-server-https.js +1 -1
- package/lib/api/dev.api.js +1 -0
- 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/host-ops.api.js +69 -0
- 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-path-commands.js +24 -0
- package/lib/cli/setup-dev.js +115 -16
- 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 +64 -61
- 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 +252 -0
- 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 +242 -4
- 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
package/lib/commands/app.js
CHANGED
|
@@ -17,17 +17,17 @@ const { registerApplication } = require('../app/register');
|
|
|
17
17
|
const { rotateSecret } = require('../app/rotate-secret');
|
|
18
18
|
const { showApp } = require('../app/show');
|
|
19
19
|
const { runAppDeploymentList } = require('./deployment-list');
|
|
20
|
-
const {
|
|
21
|
-
const { addChannelCommand } = require('../channels/add-channel');
|
|
20
|
+
const { registerChannelAddCommand } = require('./channel-add-setup');
|
|
22
21
|
|
|
23
22
|
const APP_HELP_AFTER = `
|
|
24
23
|
Subcommands:
|
|
25
24
|
register <appKey> Register app; get pipeline client id/secret
|
|
26
|
-
list
|
|
25
|
+
list Controller applications only (not connected systems)
|
|
27
26
|
rotate-secret <key> New ClientSecret (shown once)
|
|
28
|
-
show <key>
|
|
27
|
+
show <key> Controller application details (pipeline apps only)
|
|
29
28
|
deployment <key> Deployment history for app
|
|
30
|
-
|
|
29
|
+
|
|
30
|
+
Connected systems and channels: aifabrix list · aifabrix channel · aifabrix show <systemKey> --online
|
|
31
31
|
|
|
32
32
|
Requires: aifabrix login
|
|
33
33
|
`;
|
|
@@ -51,7 +51,7 @@ function setupAppRegisterCommand(app) {
|
|
|
51
51
|
|
|
52
52
|
function setupAppListCommand(app) {
|
|
53
53
|
app.command('list')
|
|
54
|
-
.description('List
|
|
54
|
+
.description('List controller applications (excludes connected systems)')
|
|
55
55
|
.action(async(options) => {
|
|
56
56
|
try {
|
|
57
57
|
await listApplications(options);
|
|
@@ -91,7 +91,8 @@ function setupAppShowCommand(app) {
|
|
|
91
91
|
online: true,
|
|
92
92
|
json: !!options.json,
|
|
93
93
|
permissions: !!options.permissions,
|
|
94
|
-
verifyCert: options.verifyCert === true
|
|
94
|
+
verifyCert: options.verifyCert === true,
|
|
95
|
+
appsOnly: true
|
|
95
96
|
});
|
|
96
97
|
} catch (error) {
|
|
97
98
|
logger.error(chalk.red(`Error: ${error.message}`));
|
|
@@ -121,41 +122,12 @@ function setupAppDeploymentCommand(app) {
|
|
|
121
122
|
});
|
|
122
123
|
}
|
|
123
124
|
|
|
124
|
-
function
|
|
125
|
-
app
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
.option('-d, --description <text>', 'Channel description (default generated)')
|
|
131
|
-
.option('--icon <path>', 'Path to channel icon asset')
|
|
132
|
-
.option('--template <name>', 'Template override (default from channel target)')
|
|
133
|
-
.option('--dry-run', 'Generate artifacts only; do not patch external system or credentials')
|
|
134
|
-
.option('--force', 'Regenerate artifacts and patch config (does not rotate secrets)')
|
|
135
|
-
.option('--probe', 'After install, validate callbacks and assistant catalog')
|
|
136
|
-
.action(async(channelTarget, options) => {
|
|
137
|
-
try {
|
|
138
|
-
if (!isChannelTargetKey(channelTarget)) {
|
|
139
|
-
throw new Error(
|
|
140
|
-
`Unknown channel target "${channelTarget}". Use teams-bot, slack, microsoft-copilot, or chatgpt.`
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
await addChannelCommand(channelTarget, {
|
|
144
|
-
name: options.name,
|
|
145
|
-
description: options.description,
|
|
146
|
-
icon: options.icon,
|
|
147
|
-
template: options.template,
|
|
148
|
-
dryRun: options.dryRun === true,
|
|
149
|
-
force: options.force === true,
|
|
150
|
-
probe: options.probe === true
|
|
151
|
-
});
|
|
152
|
-
} catch (error) {
|
|
153
|
-
if (!error.message?.includes('Authentication required')) {
|
|
154
|
-
logger.error(formatBlockingError('Channel install failed:'), error.message);
|
|
155
|
-
}
|
|
156
|
-
process.exit(1);
|
|
157
|
-
}
|
|
158
|
-
});
|
|
125
|
+
function setupAppDeprecatedAddChannelAlias(app) {
|
|
126
|
+
registerChannelAddCommand(app, {
|
|
127
|
+
commandName: 'add-channel <channelTarget>',
|
|
128
|
+
hidden: true,
|
|
129
|
+
deprecatedVia: 'aifabrix app add-channel'
|
|
130
|
+
});
|
|
159
131
|
}
|
|
160
132
|
|
|
161
133
|
/**
|
|
@@ -169,7 +141,7 @@ function setupAppCommands(program) {
|
|
|
169
141
|
setupAppRotateSecretCommand(app);
|
|
170
142
|
setupAppShowCommand(app);
|
|
171
143
|
setupAppDeploymentCommand(app);
|
|
172
|
-
|
|
144
|
+
setupAppDeprecatedAddChannelAlias(app);
|
|
173
145
|
}
|
|
174
146
|
|
|
175
147
|
module.exports = { setupAppCommands };
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register `channel add` (and optional deprecated aliases).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Shared Commander wiring for assistant channel install (plan 152)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
const logger = require('../utils/logger');
|
|
11
|
+
const { formatBlockingError } = require('../utils/cli-test-layout-chalk');
|
|
12
|
+
const { isChannelTargetKey } = require('../channels/channel-targets');
|
|
13
|
+
const { addChannelCommand } = require('../channels/add-channel');
|
|
14
|
+
|
|
15
|
+
const CHANNEL_ADD_HELP_AFTER = `
|
|
16
|
+
|
|
17
|
+
Examples:
|
|
18
|
+
# After upload/deploy of the communication external system
|
|
19
|
+
$ aifabrix channel add slack --name "Elsa"
|
|
20
|
+
$ aifabrix channel add teams-bot --name "Elsa" --description "Enterprise AI assistant for employees"
|
|
21
|
+
|
|
22
|
+
# Slack slash-command prefix (registers /{prefix}-help in manifest)
|
|
23
|
+
$ aifabrix channel add slack --name "Elsa" --command-prefix af
|
|
24
|
+
|
|
25
|
+
# Generate artifacts only; no dataplane patch
|
|
26
|
+
$ aifabrix channel add slack --name "Elsa" --dry-run
|
|
27
|
+
|
|
28
|
+
# Regenerate artifacts and patch config (does not rotate secrets)
|
|
29
|
+
$ aifabrix channel add slack --name "Elsa" --force
|
|
30
|
+
|
|
31
|
+
# Validate callbacks and assistant catalog after install
|
|
32
|
+
$ aifabrix channel add slack --name "Elsa" --probe
|
|
33
|
+
|
|
34
|
+
Prerequisites: aifabrix upload <target> (or deploy) and aifabrix login
|
|
35
|
+
`;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {string} channelTarget
|
|
39
|
+
* @param {Object} options
|
|
40
|
+
* @param {{ deprecatedVia?: string }} [meta]
|
|
41
|
+
*/
|
|
42
|
+
async function runChannelAddAction(channelTarget, options, meta = {}) {
|
|
43
|
+
if (meta.deprecatedVia) {
|
|
44
|
+
logger.warn(
|
|
45
|
+
chalk.yellow(
|
|
46
|
+
`Deprecated: use "aifabrix channel add ${channelTarget} ..." instead of "${meta.deprecatedVia}".`
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
if (!isChannelTargetKey(channelTarget)) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`Unknown channel target "${channelTarget}". Use teams-bot, slack, microsoft-copilot, or chatgpt.`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
await addChannelCommand(channelTarget, {
|
|
56
|
+
name: options.name,
|
|
57
|
+
description: options.description,
|
|
58
|
+
icon: options.icon,
|
|
59
|
+
template: options.template,
|
|
60
|
+
commandPrefix: options.commandPrefix,
|
|
61
|
+
dryRun: options.dryRun === true,
|
|
62
|
+
force: options.force === true,
|
|
63
|
+
probe: options.probe === true
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @param {import('commander').Command} parent
|
|
69
|
+
* @param {{ deprecatedVia?: string, commandName?: string, hidden?: boolean }} [meta]
|
|
70
|
+
* @returns {import('commander').Command}
|
|
71
|
+
*/
|
|
72
|
+
function registerChannelAddCommand(parent, meta = {}) {
|
|
73
|
+
const description =
|
|
74
|
+
'Configure channel install (manifest, credentials, admin guide) after upload/deploy';
|
|
75
|
+
const commandName = meta.commandName || 'add <channelTarget>';
|
|
76
|
+
const cmd = meta.hidden
|
|
77
|
+
? parent.command(commandName, { hidden: true })
|
|
78
|
+
: parent.command(commandName);
|
|
79
|
+
cmd
|
|
80
|
+
.description(meta.deprecatedVia ? `(deprecated) ${description}` : description)
|
|
81
|
+
.requiredOption('-n, --name <name>', 'Customer-visible channel name (e.g. "Elsa")')
|
|
82
|
+
.option('-d, --description <text>', 'Channel description (default generated)')
|
|
83
|
+
.option('--icon <path>', 'Path to channel icon asset')
|
|
84
|
+
.option('--template <name>', 'Template override (default from channel target)')
|
|
85
|
+
.option('--dry-run', 'Generate artifacts only; do not patch external system or credentials')
|
|
86
|
+
.option('--force', 'Regenerate artifacts and patch config (does not rotate secrets)')
|
|
87
|
+
.option(
|
|
88
|
+
'--command-prefix <key>',
|
|
89
|
+
'Slack slash alias prefix (default af) — registers /{prefix}-help etc. in manifest'
|
|
90
|
+
)
|
|
91
|
+
.option('--probe', 'After install, validate callbacks and assistant catalog')
|
|
92
|
+
.addHelpText('after', CHANNEL_ADD_HELP_AFTER)
|
|
93
|
+
.action(async(channelTarget, options) => {
|
|
94
|
+
try {
|
|
95
|
+
await runChannelAddAction(channelTarget, options, meta);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
if (!error.message?.includes('Authentication required')) {
|
|
98
|
+
logger.error(formatBlockingError('Channel install failed:'), error.message);
|
|
99
|
+
}
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
return cmd;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = {
|
|
107
|
+
CHANNEL_ADD_HELP_AFTER,
|
|
108
|
+
registerChannelAddCommand,
|
|
109
|
+
runChannelAddAction
|
|
110
|
+
};
|
package/lib/commands/channel.js
CHANGED
|
@@ -1,18 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Channel CLI commands (plan 152).
|
|
3
3
|
*
|
|
4
|
-
* @fileoverview Scaffold
|
|
4
|
+
* @fileoverview Scaffold and install assistant communication channels (Slack, Teams, …)
|
|
5
5
|
* @author AI Fabrix Team
|
|
6
|
-
* @version 1.
|
|
6
|
+
* @version 1.1.0
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
11
|
const chalk = require('chalk');
|
|
12
12
|
const logger = require('../utils/logger');
|
|
13
|
-
const {
|
|
13
|
+
const {
|
|
14
|
+
formatSuccessLine,
|
|
15
|
+
formatBlockingError,
|
|
16
|
+
sectionTitle,
|
|
17
|
+
metadata
|
|
18
|
+
} = require('../utils/cli-test-layout-chalk');
|
|
14
19
|
const { CHANNEL_TARGET_KEYS, isChannelTargetKey } = require('../channels/channel-targets');
|
|
15
20
|
const { scaffoldChannelIntegration } = require('../channels/channel-integration-generator');
|
|
21
|
+
const { registerChannelAddCommand } = require('./channel-add-setup');
|
|
22
|
+
|
|
23
|
+
const CHANNEL_HELP_AFTER = `
|
|
24
|
+
Subcommands:
|
|
25
|
+
scaffold <target> Create integration/<target>/ files locally (step 1)
|
|
26
|
+
add <target> Channel install guide + manifest/credential patch (step 3)
|
|
27
|
+
|
|
28
|
+
Targets:
|
|
29
|
+
teams-bot, slack, microsoft-copilot, chatgpt
|
|
30
|
+
web-embed (experimental — scaffold with --allow-experimental)
|
|
31
|
+
|
|
32
|
+
Typical flow (channels are connected systems, not controller apps):
|
|
33
|
+
aifabrix channel scaffold slack
|
|
34
|
+
aifabrix upload slack --force
|
|
35
|
+
aifabrix channel add slack --name "Elsa" --probe
|
|
36
|
+
|
|
37
|
+
Controller pipeline apps only: aifabrix app register · aifabrix app list
|
|
38
|
+
|
|
39
|
+
Requires: aifabrix login (for add)
|
|
40
|
+
`;
|
|
16
41
|
|
|
17
42
|
/**
|
|
18
43
|
* @param {import('commander').Command} program
|
|
@@ -20,11 +45,16 @@ const { scaffoldChannelIntegration } = require('../channels/channel-integration-
|
|
|
20
45
|
function setupChannelCommands(program) {
|
|
21
46
|
const channel = program
|
|
22
47
|
.command('channel')
|
|
23
|
-
.description(
|
|
48
|
+
.description(
|
|
49
|
+
'Assistant channels (Slack, Teams, Copilot, ChatGPT) — scaffold integration and install'
|
|
50
|
+
)
|
|
51
|
+
.addHelpText('after', CHANNEL_HELP_AFTER);
|
|
24
52
|
|
|
25
53
|
channel
|
|
26
54
|
.command('scaffold <channelTarget>')
|
|
27
|
-
.description(
|
|
55
|
+
.description(
|
|
56
|
+
'Generate integration/<target>/ communication external system (local files only)'
|
|
57
|
+
)
|
|
28
58
|
.option('--force', 'Overwrite generated scaffold files when folder exists')
|
|
29
59
|
.option('--allow-experimental', 'Allow web-embed scaffold')
|
|
30
60
|
.action(async(channelTarget, options) => {
|
|
@@ -34,7 +64,7 @@ function setupChannelCommands(program) {
|
|
|
34
64
|
`Unknown channel target "${channelTarget}". Expected: ${CHANNEL_TARGET_KEYS.join(', ')}`
|
|
35
65
|
);
|
|
36
66
|
}
|
|
37
|
-
const result = scaffoldChannelIntegration(channelTarget, {
|
|
67
|
+
const result = await scaffoldChannelIntegration(channelTarget, {
|
|
38
68
|
force: options.force === true,
|
|
39
69
|
allowExperimental: options.allowExperimental === true
|
|
40
70
|
});
|
|
@@ -46,13 +76,17 @@ function setupChannelCommands(program) {
|
|
|
46
76
|
}
|
|
47
77
|
logger.log('');
|
|
48
78
|
logger.log(chalk.white('Next steps:'));
|
|
49
|
-
logger.log(chalk.gray(` aifabrix
|
|
50
|
-
logger.log(
|
|
79
|
+
logger.log(chalk.gray(` aifabrix upload ${channelTarget} --force`));
|
|
80
|
+
logger.log(
|
|
81
|
+
chalk.gray(` aifabrix channel add ${channelTarget} --name "Your Assistant" --probe`)
|
|
82
|
+
);
|
|
51
83
|
} catch (error) {
|
|
52
84
|
logger.error(formatBlockingError(error.message || String(error)));
|
|
53
85
|
process.exit(1);
|
|
54
86
|
}
|
|
55
87
|
});
|
|
88
|
+
|
|
89
|
+
registerChannelAddCommand(channel);
|
|
56
90
|
}
|
|
57
91
|
|
|
58
92
|
module.exports = { setupChannelCommands };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TTY/JSON output for post-publish datasource data sync.
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const logger = require('../utils/logger');
|
|
10
|
+
const {
|
|
11
|
+
formatProgress,
|
|
12
|
+
formatSuccessLine,
|
|
13
|
+
formatWarningLine,
|
|
14
|
+
infoLine,
|
|
15
|
+
metadata
|
|
16
|
+
} = require('../utils/cli-test-layout-chalk');
|
|
17
|
+
|
|
18
|
+
const SKIP_REASON_LABELS = {
|
|
19
|
+
has_data: 'records already present',
|
|
20
|
+
no_connectivity: 'datasource not available on dataplane',
|
|
21
|
+
skipped: 'sync disabled'
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {Object|null|undefined} result
|
|
26
|
+
* @param {Object} [options]
|
|
27
|
+
* @param {boolean} [options.syncExplicit]
|
|
28
|
+
* @returns {boolean}
|
|
29
|
+
*/
|
|
30
|
+
function shouldEmitDatasourceSyncSummary(result, options = {}) {
|
|
31
|
+
if (!result || options.json === true) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
// Default upload/deploy: bootstrap may run, but output only when user passed --sync.
|
|
35
|
+
if (options.syncExplicit !== true) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
const executed = result.executed || [];
|
|
39
|
+
const skipped = result.skipped || [];
|
|
40
|
+
return executed.length > 0 || skipped.length > 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {Object} row
|
|
45
|
+
* @returns {string}
|
|
46
|
+
*/
|
|
47
|
+
function formatSkippedSyncLine(row) {
|
|
48
|
+
const detail = SKIP_REASON_LABELS[row.reason] || row.reason;
|
|
49
|
+
if (row.reason === 'has_data') {
|
|
50
|
+
return metadata(` ${row.datasourceKey}: ${detail} (bootstrap not needed)`);
|
|
51
|
+
}
|
|
52
|
+
return formatWarningLine(` Skipped ${row.datasourceKey}: ${detail}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @param {Object} result
|
|
57
|
+
* @param {Object} [options]
|
|
58
|
+
* @param {boolean} [options.json]
|
|
59
|
+
* @param {boolean} [options.syncExplicit]
|
|
60
|
+
* @param {string} [options.label]
|
|
61
|
+
*/
|
|
62
|
+
function logDatasourceSyncSummary(result, options = {}) {
|
|
63
|
+
if (!shouldEmitDatasourceSyncSummary(result, options)) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const label = options.label || 'Data sync';
|
|
67
|
+
logger.log('');
|
|
68
|
+
logger.log(infoLine(label));
|
|
69
|
+
for (const row of result.skipped || []) {
|
|
70
|
+
if (!options.syncExplicit && row.reason === 'has_data') {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
logger.log(formatSkippedSyncLine(row));
|
|
74
|
+
}
|
|
75
|
+
for (const row of result.executed || []) {
|
|
76
|
+
if (row.syncJobId) {
|
|
77
|
+
logger.log(
|
|
78
|
+
formatSuccessLine(
|
|
79
|
+
` Synced ${row.datasourceKey} (${row.reason}; syncJobId ${row.syncJobId})`
|
|
80
|
+
)
|
|
81
|
+
);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const warn = row.warning ? ` — ${row.warning}` : '';
|
|
85
|
+
logger.log(formatWarningLine(` Sync failed ${row.datasourceKey}${warn}`));
|
|
86
|
+
}
|
|
87
|
+
if ((result.executed || []).length === 0 && (result.skipped || []).length === 0) {
|
|
88
|
+
logger.log(formatProgress(' No datasource keys to evaluate.'));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = {
|
|
93
|
+
logDatasourceSyncSummary,
|
|
94
|
+
shouldEmitDatasourceSyncSummary,
|
|
95
|
+
SKIP_REASON_LABELS
|
|
96
|
+
};
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Bootstrap vs explicit datasource data sync policy for upload/deploy.
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { getDatasource, getDatasourceStatus } = require('../api/datasources-core.api');
|
|
10
|
+
const { unwrapApiData } = require('../utils/external-system-readiness-core');
|
|
11
|
+
const { assertDatasourceExistsOnDataplane } = require('../protection/preflight-datasource-ready');
|
|
12
|
+
const { syncDatasourceAfterProtectionUpload } = require('../protection/sync-after-upload');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {Object|null|undefined} row
|
|
16
|
+
* @returns {number|null}
|
|
17
|
+
*/
|
|
18
|
+
function readRecordCountFromRow(row) {
|
|
19
|
+
if (!row || typeof row !== 'object') {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const candidates = [
|
|
23
|
+
row.recordCount,
|
|
24
|
+
row.totalRecords,
|
|
25
|
+
row.activeRecords,
|
|
26
|
+
row.data?.recordCount,
|
|
27
|
+
row.data?.totalRecords,
|
|
28
|
+
row.data?.activeRecords,
|
|
29
|
+
row.stats?.recordCount,
|
|
30
|
+
row.stats?.totalRecords
|
|
31
|
+
];
|
|
32
|
+
for (const value of candidates) {
|
|
33
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {string} dataplaneUrl
|
|
42
|
+
* @param {Object} authConfig
|
|
43
|
+
* @param {string} datasourceKey
|
|
44
|
+
* @param {Map<string, number|null>} [cache]
|
|
45
|
+
* @returns {Promise<number|null>}
|
|
46
|
+
*/
|
|
47
|
+
async function resolveDatasourceRecordCount(dataplaneUrl, authConfig, datasourceKey, cache) {
|
|
48
|
+
const key = String(datasourceKey || '').trim();
|
|
49
|
+
if (!key) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
if (cache && cache.has(key)) {
|
|
53
|
+
return cache.get(key);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let count = null;
|
|
57
|
+
try {
|
|
58
|
+
const statusRes = await getDatasourceStatus(dataplaneUrl, key, authConfig);
|
|
59
|
+
count = readRecordCountFromRow(unwrapApiData(statusRes));
|
|
60
|
+
} catch {
|
|
61
|
+
count = null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (count === null) {
|
|
65
|
+
try {
|
|
66
|
+
const dsRes = await getDatasource(dataplaneUrl, key, authConfig);
|
|
67
|
+
count = readRecordCountFromRow(unwrapApiData(dsRes));
|
|
68
|
+
} catch {
|
|
69
|
+
count = null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (cache) {
|
|
74
|
+
cache.set(key, count);
|
|
75
|
+
}
|
|
76
|
+
return count;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Bootstrap preflight: datasource is deployed and readable on the dataplane.
|
|
81
|
+
* Does not call legacy POST /external/{key}/test (removed from dataplane OpenAPI).
|
|
82
|
+
*
|
|
83
|
+
* @param {string} dataplaneUrl
|
|
84
|
+
* @param {Object} authConfig
|
|
85
|
+
* @param {string} datasourceKey
|
|
86
|
+
* @returns {Promise<boolean>}
|
|
87
|
+
*/
|
|
88
|
+
async function checkDatasourceConnectivity(dataplaneUrl, authConfig, datasourceKey) {
|
|
89
|
+
try {
|
|
90
|
+
await assertDatasourceExistsOnDataplane(dataplaneUrl, authConfig, datasourceKey);
|
|
91
|
+
return true;
|
|
92
|
+
} catch {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {string} datasourceKey
|
|
99
|
+
* @param {Object} params
|
|
100
|
+
* @param {Map<string, number|null>} cache
|
|
101
|
+
* @returns {Promise<{ datasourceKey: string, bucket: string, reason: string }>}
|
|
102
|
+
*/
|
|
103
|
+
async function evaluateBootstrapSyncCandidate(datasourceKey, params, cache) {
|
|
104
|
+
const count = await resolveDatasourceRecordCount(
|
|
105
|
+
params.dataplaneUrl,
|
|
106
|
+
params.authConfig,
|
|
107
|
+
datasourceKey,
|
|
108
|
+
cache
|
|
109
|
+
);
|
|
110
|
+
if (typeof count === 'number' && count > 0) {
|
|
111
|
+
return { datasourceKey, bucket: 'skipped', reason: 'has_data' };
|
|
112
|
+
}
|
|
113
|
+
const connected = await checkDatasourceConnectivity(
|
|
114
|
+
params.dataplaneUrl,
|
|
115
|
+
params.authConfig,
|
|
116
|
+
datasourceKey
|
|
117
|
+
);
|
|
118
|
+
if (!connected) {
|
|
119
|
+
return { datasourceKey, bucket: 'skipped', reason: 'no_connectivity' };
|
|
120
|
+
}
|
|
121
|
+
return { datasourceKey, bucket: 'run', reason: 'bootstrap' };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @param {Object} params
|
|
126
|
+
* @param {boolean} [params.syncExplicit]
|
|
127
|
+
* @param {boolean} [params.skipSync]
|
|
128
|
+
* @param {string[]} params.datasourceKeys
|
|
129
|
+
* @param {string} dataplaneUrl
|
|
130
|
+
* @param {Object} authConfig
|
|
131
|
+
* @returns {Promise<{ run: Object[], skipped: Object[] }>}
|
|
132
|
+
*/
|
|
133
|
+
async function resolveSyncPlan(params) {
|
|
134
|
+
const keys = [
|
|
135
|
+
...new Set((params.datasourceKeys || []).map((k) => String(k || '').trim()).filter(Boolean))
|
|
136
|
+
];
|
|
137
|
+
const skipped = [];
|
|
138
|
+
const run = [];
|
|
139
|
+
const cache = new Map();
|
|
140
|
+
|
|
141
|
+
if (params.skipSync === true) {
|
|
142
|
+
keys.forEach((datasourceKey) => skipped.push({ datasourceKey, reason: 'skipped' }));
|
|
143
|
+
return { run, skipped };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (params.syncExplicit === true) {
|
|
147
|
+
keys.forEach((datasourceKey) => run.push({ datasourceKey, reason: 'explicit' }));
|
|
148
|
+
return { run, skipped };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
for (const datasourceKey of keys) {
|
|
152
|
+
const decision = await evaluateBootstrapSyncCandidate(datasourceKey, params, cache);
|
|
153
|
+
if (decision.bucket === 'skipped') {
|
|
154
|
+
skipped.push({ datasourceKey: decision.datasourceKey, reason: decision.reason });
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
run.push({ datasourceKey: decision.datasourceKey, reason: decision.reason });
|
|
158
|
+
}
|
|
159
|
+
return { run, skipped };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* @param {{ run: Object[] }} plan
|
|
164
|
+
* @param {string} dataplaneUrl
|
|
165
|
+
* @param {Object} authConfig
|
|
166
|
+
* @returns {Promise<{ executed: Object[], skipped: Object[] }>}
|
|
167
|
+
*/
|
|
168
|
+
async function executeSyncPlan(plan, dataplaneUrl, authConfig) {
|
|
169
|
+
const executed = [];
|
|
170
|
+
for (const item of plan.run) {
|
|
171
|
+
const syncResult = await syncDatasourceAfterProtectionUpload(
|
|
172
|
+
dataplaneUrl,
|
|
173
|
+
authConfig,
|
|
174
|
+
item.datasourceKey
|
|
175
|
+
);
|
|
176
|
+
executed.push({ ...item, ...syncResult });
|
|
177
|
+
}
|
|
178
|
+
return { executed, skipped: plan.skipped || [] };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @param {string} dataplaneUrl
|
|
183
|
+
* @param {Object} authConfig
|
|
184
|
+
* @param {string[]} datasourceKeys
|
|
185
|
+
* @returns {Promise<'never'|'auto'>}
|
|
186
|
+
*/
|
|
187
|
+
async function resolveE2eSyncModeWhenPopulated(dataplaneUrl, authConfig, datasourceKeys) {
|
|
188
|
+
const keys = [
|
|
189
|
+
...new Set((datasourceKeys || []).map((k) => String(k || '').trim()).filter(Boolean))
|
|
190
|
+
];
|
|
191
|
+
if (keys.length === 0) {
|
|
192
|
+
return 'auto';
|
|
193
|
+
}
|
|
194
|
+
const cache = new Map();
|
|
195
|
+
for (const key of keys) {
|
|
196
|
+
const count = await resolveDatasourceRecordCount(dataplaneUrl, authConfig, key, cache);
|
|
197
|
+
if (count === null || count === 0) {
|
|
198
|
+
return 'auto';
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return 'never';
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
module.exports = {
|
|
205
|
+
readRecordCountFromRow,
|
|
206
|
+
resolveDatasourceRecordCount,
|
|
207
|
+
resolveSyncPlan,
|
|
208
|
+
executeSyncPlan,
|
|
209
|
+
resolveE2eSyncModeWhenPopulated
|
|
210
|
+
};
|
|
@@ -13,7 +13,7 @@ const { writeTrustDebugLogAndPrint } = require('../datasource/agent-trust-debug-
|
|
|
13
13
|
const { displayAgentTrustRunTTY } = require('../utils/agent-trust-run-display');
|
|
14
14
|
const { computeExitCodeFromTrustRun } = require('../utils/agent-trust-run-exit');
|
|
15
15
|
const { attachDatasourceTestCommonOptions } = require('./datasource-unified-test-cli.options');
|
|
16
|
-
const {
|
|
16
|
+
const { cliOptsSkipPublish } = require('../utils/cli-sync-options');
|
|
17
17
|
|
|
18
18
|
function datasourceVerifyTrustHelpAfter() {
|
|
19
19
|
return `
|
|
@@ -25,7 +25,7 @@ Examples:
|
|
|
25
25
|
|
|
26
26
|
Notes:
|
|
27
27
|
- Semantic trust only (agent metadata validation). For live API proof use test-e2e.
|
|
28
|
-
- Local files are published before run unless --no-
|
|
28
|
+
- Local files are published before run unless --no-publish.
|
|
29
29
|
- With --debug, JSON is saved under integration/<app>/logs/ (verify-trust-<key>-*.json). View with: aifabrix datasource log-trust <key>
|
|
30
30
|
`;
|
|
31
31
|
}
|
|
@@ -34,7 +34,7 @@ async function runDatasourceVerifyTrustOnce(datasourceKey, options) {
|
|
|
34
34
|
const { trustRun, apiError } = await runDatasourceAgentTrust(datasourceKey, {
|
|
35
35
|
app: options.app,
|
|
36
36
|
environment: options.env,
|
|
37
|
-
|
|
37
|
+
noPublish: options.noPublish === true,
|
|
38
38
|
force: options.force === true,
|
|
39
39
|
revalidate: options.revalidate === true,
|
|
40
40
|
summary: options.summary === true,
|
|
@@ -48,7 +48,7 @@ async function finalizeDatasourceVerifyTrust(datasourceKey, options, result) {
|
|
|
48
48
|
json: options.json,
|
|
49
49
|
verbose: options.verbose,
|
|
50
50
|
environment: options.env,
|
|
51
|
-
|
|
51
|
+
noPublish: options.noPublish === true,
|
|
52
52
|
strict: options.strict === true
|
|
53
53
|
};
|
|
54
54
|
if (options.json) {
|
|
@@ -70,7 +70,7 @@ async function finalizeDatasourceVerifyTrust(datasourceKey, options, result) {
|
|
|
70
70
|
|
|
71
71
|
async function datasourceVerifyTrustAction(datasourceKey, options, cmd) {
|
|
72
72
|
try {
|
|
73
|
-
const merged = { ...options,
|
|
73
|
+
const merged = { ...options, noPublish: cliOptsSkipPublish(options, cmd) };
|
|
74
74
|
const result = await runDatasourceVerifyTrustOnce(datasourceKey, merged);
|
|
75
75
|
const { resolveAppKeyForDatasource } = require('../datasource/resolve-app');
|
|
76
76
|
const { appKey } = await resolveAppKeyForDatasource(datasourceKey, options.app);
|
|
@@ -97,7 +97,7 @@ function attachDatasourceTrustOptions(cmd) {
|
|
|
97
97
|
timeoutDefault: '120000'
|
|
98
98
|
});
|
|
99
99
|
cmd
|
|
100
|
-
.option('--no-
|
|
100
|
+
.option('--no-publish', 'Skip publishing local integration files before validate')
|
|
101
101
|
.option('--revalidate', 'Force new validation (ignore inputHash cache)')
|
|
102
102
|
.option('--strict', 'Exit 1 unless trustDecision is trusted');
|
|
103
103
|
}
|
|
@@ -47,7 +47,8 @@ async function writeDatasourceTestDebugLogIfRequested(appKey, datasourceKey, res
|
|
|
47
47
|
const requestMeta = {
|
|
48
48
|
datasourceKey,
|
|
49
49
|
runType: 'test',
|
|
50
|
-
includeDebug: includeDebugForRequest(options.debug)
|
|
50
|
+
includeDebug: includeDebugForRequest(options.debug),
|
|
51
|
+
explainCertification: includeDebugForRequest(options.debug)
|
|
51
52
|
};
|
|
52
53
|
const envelope = result && typeof result === 'object' ? result.envelope : null;
|
|
53
54
|
const apiError = result && typeof result === 'object' ? result.apiError : null;
|