@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
|
@@ -13,6 +13,7 @@ const fs = require('fs');
|
|
|
13
13
|
const path = require('path');
|
|
14
14
|
const Handlebars = require('handlebars');
|
|
15
15
|
const { getChannelTarget } = require('./channel-targets');
|
|
16
|
+
const { BUILDER_ROOT } = require('./channel-integration-template');
|
|
16
17
|
|
|
17
18
|
const SECRET_PATTERNS = [/xoxb-/i, /xoxp-/i, /client_secret/i, /signing_secret/i, /Bearer\s+/i];
|
|
18
19
|
|
|
@@ -32,13 +33,23 @@ function assertNoSecretsInArtifact(content) {
|
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
/**
|
|
35
|
-
* @
|
|
36
|
+
* Handlebars templates ship with @aifabrix/builder (not the caller's cwd).
|
|
36
37
|
* @param {string} channelTarget
|
|
37
38
|
* @returns {string}
|
|
38
39
|
*/
|
|
39
|
-
function
|
|
40
|
+
function getChannelTemplatesDir(channelTarget) {
|
|
40
41
|
const target = getChannelTarget(channelTarget);
|
|
41
|
-
return path.join(
|
|
42
|
+
return path.join(BUILDER_ROOT, 'templates', 'channels', target.templateDir);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @param {string} _projectRoot
|
|
47
|
+
* @param {string} channelTarget
|
|
48
|
+
* @returns {string}
|
|
49
|
+
* @deprecated Use getChannelTemplatesDir — templates are package-rooted.
|
|
50
|
+
*/
|
|
51
|
+
function getTemplatesDir(_projectRoot, channelTarget) {
|
|
52
|
+
return getChannelTemplatesDir(channelTarget);
|
|
42
53
|
}
|
|
43
54
|
|
|
44
55
|
/**
|
|
@@ -102,7 +113,7 @@ function renderInstallGuideIfPresent(templatesDir, runtimeValues, outputDir, dry
|
|
|
102
113
|
* @returns {{ outputPath: string, artifactHash: string, content: string, installPath?: string }}
|
|
103
114
|
*/
|
|
104
115
|
function generateChannelArtifact(params) {
|
|
105
|
-
const templatesDir =
|
|
116
|
+
const templatesDir = getChannelTemplatesDir(params.channelTarget);
|
|
106
117
|
const manifestTemplate = path.join(templatesDir, 'manifest.template.json.hbs');
|
|
107
118
|
const content = renderTemplateFile(manifestTemplate, params.runtimeValues);
|
|
108
119
|
assertNoSecretsInArtifact(content);
|
|
@@ -133,6 +144,7 @@ function generateChannelArtifact(params) {
|
|
|
133
144
|
|
|
134
145
|
module.exports = {
|
|
135
146
|
assertNoSecretsInArtifact,
|
|
147
|
+
getChannelTemplatesDir,
|
|
136
148
|
getTemplatesDir,
|
|
137
149
|
getArtifactOutputPath,
|
|
138
150
|
renderTemplateFile,
|
|
@@ -15,6 +15,9 @@ const logger = require('../utils/logger');
|
|
|
15
15
|
* @param {Object} payload
|
|
16
16
|
*/
|
|
17
17
|
function emitChannelAuditEvent(eventName, payload) {
|
|
18
|
+
if (process.env.AIFABRIX_CHANNEL_AUDIT !== '1') {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
18
21
|
logger.log(
|
|
19
22
|
JSON.stringify({
|
|
20
23
|
event: eventName,
|
|
@@ -21,7 +21,7 @@ const { resolveDataplaneUrl } = require('../utils/dataplane-resolver');
|
|
|
21
21
|
*/
|
|
22
22
|
async function resolveChannelAuthContext(channelTarget, opts = {}) {
|
|
23
23
|
const controllerUrl = await resolveControllerUrl();
|
|
24
|
-
const environment = (await config.
|
|
24
|
+
const environment = (await config.resolveEnvironment()) || 'dev';
|
|
25
25
|
const authConfig = await getDeploymentAuth(controllerUrl, environment, channelTarget);
|
|
26
26
|
if (!authConfig) {
|
|
27
27
|
throw new Error('Authentication required. Run "aifabrix login" first.');
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slack manifest description limits (plan 152).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Enforce Slack display_information.description max length
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
/** Slack manifest `display_information.description` max (api.slack.com/reference/manifests). */
|
|
12
|
+
const SLACK_APP_DESCRIPTION_MAX_LENGTH = 140;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {string} description
|
|
16
|
+
* @returns {string}
|
|
17
|
+
*/
|
|
18
|
+
function normalizeSlackAppDescription(description) {
|
|
19
|
+
const text = String(description ?? '').trim();
|
|
20
|
+
if (!text || text.length <= SLACK_APP_DESCRIPTION_MAX_LENGTH) {
|
|
21
|
+
return text;
|
|
22
|
+
}
|
|
23
|
+
return `${text.slice(0, SLACK_APP_DESCRIPTION_MAX_LENGTH - 1)}…`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {string} description
|
|
28
|
+
* @returns {string}
|
|
29
|
+
* @throws {Error}
|
|
30
|
+
*/
|
|
31
|
+
function assertSlackAppDescription(description) {
|
|
32
|
+
const text = String(description ?? '').trim();
|
|
33
|
+
if (text.length > SLACK_APP_DESCRIPTION_MAX_LENGTH) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
`Slack app description must be at most ${SLACK_APP_DESCRIPTION_MAX_LENGTH} characters (got ${text.length}). Provide a shorter --description.`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
return text;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {string} channelTarget
|
|
43
|
+
* @param {string} description
|
|
44
|
+
* @returns {string}
|
|
45
|
+
*/
|
|
46
|
+
function resolveAppDescription(channelTarget, description) {
|
|
47
|
+
const text = String(description ?? '').trim();
|
|
48
|
+
if (channelTarget === 'slack') {
|
|
49
|
+
return assertSlackAppDescription(text);
|
|
50
|
+
}
|
|
51
|
+
return text;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = {
|
|
55
|
+
SLACK_APP_DESCRIPTION_MAX_LENGTH,
|
|
56
|
+
normalizeSlackAppDescription,
|
|
57
|
+
assertSlackAppDescription,
|
|
58
|
+
resolveAppDescription
|
|
59
|
+
};
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Scaffold integration/<channelTarget>/ from published templates (plan 152).
|
|
3
|
+
* Manifest SSOT: dataplane integration/ (slack via make sync-json) → templates/channels/{target}/integration/.
|
|
4
|
+
* Builder generates only *-deploy.json at scaffold time.
|
|
3
5
|
*
|
|
4
|
-
* @fileoverview
|
|
6
|
+
* @fileoverview Channel integration scaffold — template copy + deploy JSON
|
|
5
7
|
* @author AI Fabrix Team
|
|
6
|
-
* @version
|
|
8
|
+
* @version 2.0.0
|
|
7
9
|
*/
|
|
8
10
|
|
|
9
11
|
'use strict';
|
|
@@ -12,201 +14,8 @@ const fs = require('fs');
|
|
|
12
14
|
const path = require('path');
|
|
13
15
|
const { getChannelTarget } = require('./channel-targets');
|
|
14
16
|
const { getIntegrationPath } = require('../utils/paths');
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const AUTH_BLOCKS = {
|
|
18
|
-
slack: {
|
|
19
|
-
authType: 'credential',
|
|
20
|
-
credential: {
|
|
21
|
-
credentialKey: 'slack-app',
|
|
22
|
-
displayName: 'Slack assistant channel',
|
|
23
|
-
method: 'hmac',
|
|
24
|
-
variables: {},
|
|
25
|
-
security: {
|
|
26
|
-
signingSecret: 'kv://slack/signingSecret',
|
|
27
|
-
clientId: 'kv://slack/clientId',
|
|
28
|
-
clientSecret: 'kv://slack/clientSecret'
|
|
29
|
-
},
|
|
30
|
-
writeOnce: true
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
'teams-bot': {
|
|
34
|
-
authType: 'credential',
|
|
35
|
-
credential: {
|
|
36
|
-
credentialKey: 'teams-bot',
|
|
37
|
-
displayName: 'Microsoft Teams assistant bot',
|
|
38
|
-
method: 'oidc',
|
|
39
|
-
variables: {
|
|
40
|
-
openIdConfigUrl: 'https://login.botframework.com/v1/.well-known/openid_configuration',
|
|
41
|
-
clientId: 'kv://teams-bot/botAppId',
|
|
42
|
-
expectedIssuer: 'https://api.botframework.com'
|
|
43
|
-
},
|
|
44
|
-
security: {},
|
|
45
|
-
writeOnce: true
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
'microsoft-copilot': {
|
|
49
|
-
authType: 'credential',
|
|
50
|
-
credential: {
|
|
51
|
-
credentialKey: 'microsoft-copilot-channel',
|
|
52
|
-
displayName: 'Microsoft Copilot assistant channel',
|
|
53
|
-
method: 'oauth2',
|
|
54
|
-
variables: {
|
|
55
|
-
tokenUrl: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
|
|
56
|
-
grantType: 'client_credentials'
|
|
57
|
-
},
|
|
58
|
-
security: {
|
|
59
|
-
clientId: 'kv://microsoft-copilot/clientId',
|
|
60
|
-
clientSecret: 'kv://microsoft-copilot/clientSecret'
|
|
61
|
-
},
|
|
62
|
-
writeOnce: true
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
chatgpt: {
|
|
66
|
-
authType: 'credential',
|
|
67
|
-
credential: {
|
|
68
|
-
credentialKey: 'chatgpt-channel',
|
|
69
|
-
displayName: 'ChatGPT assistant channel',
|
|
70
|
-
method: 'apikey',
|
|
71
|
-
variables: {},
|
|
72
|
-
security: {
|
|
73
|
-
apiKey: 'kv://chatgpt/apiKey'
|
|
74
|
-
},
|
|
75
|
-
writeOnce: true
|
|
76
|
-
}
|
|
77
|
-
},
|
|
78
|
-
'web-embed': {
|
|
79
|
-
authType: 'credential',
|
|
80
|
-
credential: {
|
|
81
|
-
credentialKey: 'web-embed-channel',
|
|
82
|
-
displayName: 'Web embed assistant channel',
|
|
83
|
-
method: 'apikey',
|
|
84
|
-
variables: {},
|
|
85
|
-
security: {
|
|
86
|
-
apiKey: 'kv://web-embed/apiKey'
|
|
87
|
-
},
|
|
88
|
-
writeOnce: true
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* @param {string} channelTarget
|
|
95
|
-
* @param {typeof import('./channel-targets').CHANNEL_TARGETS[string]} target
|
|
96
|
-
* @returns {Object}
|
|
97
|
-
*/
|
|
98
|
-
function buildAuthenticationBlock(channelTarget, target) {
|
|
99
|
-
const block = AUTH_BLOCKS[channelTarget];
|
|
100
|
-
if (!block) {
|
|
101
|
-
throw new Error(`No authentication block for channel target "${channelTarget}"`);
|
|
102
|
-
}
|
|
103
|
-
const auth = JSON.parse(JSON.stringify(block));
|
|
104
|
-
auth.credential.credentialKey = target.credentialKey;
|
|
105
|
-
return auth;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* @param {string} channelTarget
|
|
110
|
-
* @returns {Object}
|
|
111
|
-
*/
|
|
112
|
-
function buildSystemJson(channelTarget) {
|
|
113
|
-
const target = getChannelTarget(channelTarget);
|
|
114
|
-
const system = {
|
|
115
|
-
key: channelTarget,
|
|
116
|
-
displayName: 'Microsoft Teams assistant bot',
|
|
117
|
-
description: 'Bot Framework assistant channel (not full Teams / Graph integration)',
|
|
118
|
-
type: 'custom',
|
|
119
|
-
systemKind: 'communication',
|
|
120
|
-
enabled: true,
|
|
121
|
-
authentication: buildAuthenticationBlock(channelTarget, target),
|
|
122
|
-
configuration: [],
|
|
123
|
-
dataSources: []
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
if (channelTarget === 'teams-bot') {
|
|
127
|
-
system.displayName = 'Microsoft Teams assistant bot';
|
|
128
|
-
system.endpoints = [
|
|
129
|
-
{
|
|
130
|
-
type: 'messages',
|
|
131
|
-
path: '/messages',
|
|
132
|
-
router: 'teams_bot_router',
|
|
133
|
-
description: 'Bot Framework messaging endpoint',
|
|
134
|
-
active: true
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
type: 'notifications',
|
|
138
|
-
path: '/notifications',
|
|
139
|
-
router: 'teams_notifications_router',
|
|
140
|
-
description: 'Proactive notification endpoint',
|
|
141
|
-
active: true
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
type: 'config',
|
|
145
|
-
path: '/bot-config',
|
|
146
|
-
router: 'teams_config_router',
|
|
147
|
-
description: 'Bot configuration endpoint',
|
|
148
|
-
active: true
|
|
149
|
-
}
|
|
150
|
-
];
|
|
151
|
-
system.endpointsActive = true;
|
|
152
|
-
} else {
|
|
153
|
-
system.displayName = `${target.key} assistant channel`;
|
|
154
|
-
system.description = 'Communication external system for assistant channel install (plan 152)';
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return system;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* @param {string} channelTarget
|
|
162
|
-
* @returns {Object}
|
|
163
|
-
*/
|
|
164
|
-
function buildApplicationJson(channelTarget) {
|
|
165
|
-
const target = getChannelTarget(channelTarget);
|
|
166
|
-
const systemFile = `${channelTarget}-system.json`;
|
|
167
|
-
return {
|
|
168
|
-
app: {
|
|
169
|
-
key: channelTarget,
|
|
170
|
-
displayName: `${target.key} assistant channel`,
|
|
171
|
-
description: 'Assistant communication channel — deploy then app add-channel',
|
|
172
|
-
type: 'external'
|
|
173
|
-
},
|
|
174
|
-
externalIntegration: {
|
|
175
|
-
schemaBasePath: './',
|
|
176
|
-
systems: [systemFile],
|
|
177
|
-
dataSources: [],
|
|
178
|
-
autopublish: true,
|
|
179
|
-
version: '1.0.0'
|
|
180
|
-
}
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* @param {string} channelTarget
|
|
186
|
-
* @returns {string}
|
|
187
|
-
*/
|
|
188
|
-
function buildEnvTemplate(channelTarget) {
|
|
189
|
-
const kvPrefix = channelTarget === 'web-embed' ? 'web-embed' : channelTarget;
|
|
190
|
-
const lines = [
|
|
191
|
-
`# ${channelTarget} assistant channel — resolve secrets before deploy/add-channel`,
|
|
192
|
-
'# kv:// paths are pushed via aifabrix credential push or add-channel secret sync',
|
|
193
|
-
''
|
|
194
|
-
];
|
|
195
|
-
if (channelTarget === 'slack') {
|
|
196
|
-
lines.push('KV_SLACK_SIGNINGSECRET=kv://slack/signingSecret');
|
|
197
|
-
lines.push('KV_SLACK_CLIENTID=kv://slack/clientId');
|
|
198
|
-
lines.push('KV_SLACK_CLIENTSECRET=kv://slack/clientSecret');
|
|
199
|
-
} else if (channelTarget === 'teams-bot') {
|
|
200
|
-
lines.push('KV_TEAMS_BOT_BOTAPPID=kv://teams-bot/botAppId');
|
|
201
|
-
} else if (channelTarget === 'microsoft-copilot') {
|
|
202
|
-
lines.push('KV_MICROSOFT_COPILOT_CLIENTID=kv://microsoft-copilot/clientId');
|
|
203
|
-
lines.push('KV_MICROSOFT_COPILOT_CLIENTSECRET=kv://microsoft-copilot/clientSecret');
|
|
204
|
-
} else {
|
|
205
|
-
lines.push(`KV_${kvPrefix.toUpperCase().replace(/-/g, '_')}_APIKEY=kv://${kvPrefix}/apiKey`);
|
|
206
|
-
}
|
|
207
|
-
lines.push('');
|
|
208
|
-
return lines.join('\n');
|
|
209
|
-
}
|
|
17
|
+
const { copyChannelIntegrationTemplate } = require('./channel-integration-template');
|
|
18
|
+
const { generateDeployJson } = require('../generator/index');
|
|
210
19
|
|
|
211
20
|
/**
|
|
212
21
|
* @param {string} channelTarget
|
|
@@ -214,9 +23,9 @@ function buildEnvTemplate(channelTarget) {
|
|
|
214
23
|
* @param {boolean} [options.force]
|
|
215
24
|
* @param {boolean} [options.allowExperimental]
|
|
216
25
|
* @param {string} [options.projectRoot]
|
|
217
|
-
* @returns {{ integrationDir: string, files: string[] }}
|
|
26
|
+
* @returns {Promise<{ integrationDir: string, files: string[] }>}
|
|
218
27
|
*/
|
|
219
|
-
function scaffoldChannelIntegration(channelTarget, options = {}) {
|
|
28
|
+
async function scaffoldChannelIntegration(channelTarget, options = {}) {
|
|
220
29
|
const target = getChannelTarget(channelTarget);
|
|
221
30
|
if (target.experimental && !options.allowExperimental) {
|
|
222
31
|
throw new Error(
|
|
@@ -233,42 +42,16 @@ function scaffoldChannelIntegration(channelTarget, options = {}) {
|
|
|
233
42
|
);
|
|
234
43
|
}
|
|
235
44
|
|
|
236
|
-
|
|
237
|
-
const
|
|
238
|
-
const
|
|
239
|
-
const envPath = path.join(integrationDir, 'env.template');
|
|
240
|
-
const readmePath = path.join(integrationDir, 'README.md');
|
|
241
|
-
|
|
242
|
-
fs.writeFileSync(systemPath, `${JSON.stringify(buildSystemJson(channelTarget), null, 2)}\n`, 'utf8');
|
|
243
|
-
fs.writeFileSync(appPath, `${JSON.stringify(buildApplicationJson(channelTarget), null, 2)}\n`, 'utf8');
|
|
244
|
-
fs.writeFileSync(envPath, buildEnvTemplate(channelTarget), 'utf8');
|
|
245
|
-
fs.writeFileSync(
|
|
246
|
-
readmePath,
|
|
247
|
-
[
|
|
248
|
-
`# ${channelTarget} assistant channel`,
|
|
249
|
-
'',
|
|
250
|
-
'## Two-step install',
|
|
251
|
-
'',
|
|
252
|
-
'```bash',
|
|
253
|
-
`aifabrix deploy ${channelTarget}`,
|
|
254
|
-
`aifabrix app add-channel ${channelTarget} --name "Your Assistant"`,
|
|
255
|
-
'```',
|
|
256
|
-
'',
|
|
257
|
-
'Generated by `aifabrix channel scaffold`. Secrets belong in kv:// env.template only.',
|
|
258
|
-
''
|
|
259
|
-
].join('\n'),
|
|
260
|
-
'utf8'
|
|
261
|
-
);
|
|
45
|
+
const copied = copyChannelIntegrationTemplate(channelTarget, integrationDir);
|
|
46
|
+
const deployPath = await generateDeployJson(channelTarget, { appPath: integrationDir });
|
|
47
|
+
const files = [...copied, deployPath];
|
|
262
48
|
|
|
263
49
|
return {
|
|
264
50
|
integrationDir,
|
|
265
|
-
files
|
|
51
|
+
files
|
|
266
52
|
};
|
|
267
53
|
}
|
|
268
54
|
|
|
269
55
|
module.exports = {
|
|
270
|
-
buildSystemJson,
|
|
271
|
-
buildApplicationJson,
|
|
272
|
-
buildEnvTemplate,
|
|
273
56
|
scaffoldChannelIntegration
|
|
274
57
|
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channel integration templates — copied from templates/channels/<target>/integration/.
|
|
3
|
+
* SSOT for slack: aifabrix-dataplane/integration/slack (make sync-json in dataplane).
|
|
4
|
+
*
|
|
5
|
+
* @fileoverview Template resolution and copy for channel scaffold (plan 152)
|
|
6
|
+
* @author AI Fabrix Team
|
|
7
|
+
* @version 2.0.0
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const { nodeFs } = require('../internal/node-fs');
|
|
13
|
+
const fs = nodeFs();
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const { getChannelTarget } = require('./channel-targets');
|
|
16
|
+
|
|
17
|
+
const BUILDER_ROOT = path.join(__dirname, '..', '..');
|
|
18
|
+
|
|
19
|
+
/** @type {RegExp[]} */
|
|
20
|
+
const SKIP_TEMPLATE_FILE = [
|
|
21
|
+
/^\./,
|
|
22
|
+
/-deploy\.json$/,
|
|
23
|
+
/^INTEGRATION_CHANGELOG\.md$/i
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {string} channelTarget
|
|
28
|
+
* @returns {string}
|
|
29
|
+
*/
|
|
30
|
+
function getChannelIntegrationTemplateDir(channelTarget) {
|
|
31
|
+
const target = getChannelTarget(channelTarget);
|
|
32
|
+
return path.join(BUILDER_ROOT, 'templates', 'channels', target.templateDir, 'integration');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {string} name
|
|
37
|
+
* @returns {boolean}
|
|
38
|
+
*/
|
|
39
|
+
function shouldCopyTemplateFile(name) {
|
|
40
|
+
return !SKIP_TEMPLATE_FILE.some((pattern) => pattern.test(name));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {string} templateDir
|
|
45
|
+
* @returns {string[]}
|
|
46
|
+
*/
|
|
47
|
+
function listChannelIntegrationTemplateFiles(templateDir) {
|
|
48
|
+
if (!fs.existsSync(templateDir)) {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
return fs
|
|
52
|
+
.readdirSync(templateDir)
|
|
53
|
+
.filter((name) => {
|
|
54
|
+
const full = path.join(templateDir, name);
|
|
55
|
+
return fs.statSync(full).isFile() && shouldCopyTemplateFile(name);
|
|
56
|
+
})
|
|
57
|
+
.sort();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {string} channelTarget
|
|
62
|
+
* @param {string} integrationDir
|
|
63
|
+
* @returns {string[]} Copied file paths
|
|
64
|
+
*/
|
|
65
|
+
function copyChannelIntegrationTemplate(channelTarget, integrationDir) {
|
|
66
|
+
const templateDir = getChannelIntegrationTemplateDir(channelTarget);
|
|
67
|
+
const names = listChannelIntegrationTemplateFiles(templateDir);
|
|
68
|
+
if (names.length === 0) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Channel integration template missing for "${channelTarget}" (${templateDir}). ` +
|
|
71
|
+
'For slack: edit aifabrix-dataplane/integration/slack and run make sync-json. ' +
|
|
72
|
+
'For other targets: add templates/channels/<target>/integration/ until dataplane SSOT exists.'
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
fs.mkdirSync(integrationDir, { recursive: true });
|
|
77
|
+
const copied = [];
|
|
78
|
+
for (const name of names) {
|
|
79
|
+
const src = path.join(templateDir, name);
|
|
80
|
+
const dest = path.join(integrationDir, name);
|
|
81
|
+
fs.copyFileSync(src, dest);
|
|
82
|
+
copied.push(dest);
|
|
83
|
+
}
|
|
84
|
+
return copied;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = {
|
|
88
|
+
BUILDER_ROOT,
|
|
89
|
+
SKIP_TEMPLATE_FILE,
|
|
90
|
+
getChannelIntegrationTemplateDir,
|
|
91
|
+
shouldCopyTemplateFile,
|
|
92
|
+
listChannelIntegrationTemplateFiles,
|
|
93
|
+
copyChannelIntegrationTemplate
|
|
94
|
+
};
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
11
|
const { getChannelTarget } = require('./channel-targets');
|
|
12
|
+
const { normalizeSlackAppDescription } = require('./channel-description');
|
|
13
|
+
|
|
14
|
+
/** Default Slack slash prefix — matches dataplane `templates/slack/command_catalog.yaml`. */
|
|
15
|
+
const DEFAULT_SLACK_COMMAND_PREFIX = 'af';
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
18
|
* Normalize dataplane base URL (no trailing slash).
|
|
@@ -50,7 +54,6 @@ function getEndpointPathSuffixes(channelTarget) {
|
|
|
50
54
|
slack: {
|
|
51
55
|
eventsUrl: '/events',
|
|
52
56
|
interactionUrl: '/interactive',
|
|
53
|
-
oauthCallbackUrl: '/oauth/callback',
|
|
54
57
|
commandUrl: '/commands'
|
|
55
58
|
},
|
|
56
59
|
'teams-bot': {
|
|
@@ -97,6 +100,26 @@ function getLegacyApiPaths(channelTarget) {
|
|
|
97
100
|
return legacy[channelTarget] || {};
|
|
98
101
|
}
|
|
99
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Slack token rotation requires OAuth redirect URLs (api.slack.com app manifest).
|
|
105
|
+
* @param {string|undefined} oauthCallbackUrl
|
|
106
|
+
* @returns {{ oauthCallbackUrl?: string, slackRedirectUrlsJson: string, slackTokenRotationEnabled: boolean }}
|
|
107
|
+
*/
|
|
108
|
+
function resolveSlackOAuthManifestFields(oauthCallbackUrl) {
|
|
109
|
+
const url = typeof oauthCallbackUrl === 'string' ? oauthCallbackUrl.trim() : '';
|
|
110
|
+
if (!url) {
|
|
111
|
+
return {
|
|
112
|
+
slackRedirectUrlsJson: '[]',
|
|
113
|
+
slackTokenRotationEnabled: false
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
oauthCallbackUrl: url,
|
|
118
|
+
slackRedirectUrlsJson: JSON.stringify([url]),
|
|
119
|
+
slackTokenRotationEnabled: true
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
100
123
|
/**
|
|
101
124
|
* @param {Object} params
|
|
102
125
|
* @param {string} params.dataplaneBaseUrl
|
|
@@ -106,6 +129,7 @@ function getLegacyApiPaths(channelTarget) {
|
|
|
106
129
|
* @param {string} [params.environment]
|
|
107
130
|
* @param {string} params.appDescription
|
|
108
131
|
* @param {string} [params.icon]
|
|
132
|
+
* @param {string} [params.commandPrefix] Slack slash alias prefix (default `af`)
|
|
109
133
|
* @returns {Object}
|
|
110
134
|
*/
|
|
111
135
|
function resolveChannelRuntimeValues(params) {
|
|
@@ -123,9 +147,13 @@ function resolveChannelRuntimeValues(params) {
|
|
|
123
147
|
appName: params.appName,
|
|
124
148
|
baseName: params.baseName || params.appName,
|
|
125
149
|
environment: params.environment || 'dev',
|
|
126
|
-
appDescription:
|
|
150
|
+
appDescription:
|
|
151
|
+
params.channelTarget === 'slack'
|
|
152
|
+
? normalizeSlackAppDescription(params.appDescription)
|
|
153
|
+
: params.appDescription,
|
|
127
154
|
icon: params.icon || '',
|
|
128
155
|
credentialKey: target.credentialKey,
|
|
156
|
+
credentialPortalUrl: joinUrl(base, `/connected-systems/${params.channelTarget}?tab=authentication`),
|
|
129
157
|
assistantCatalogUrl: joinUrl(base, '/api/v1/workers/available'),
|
|
130
158
|
scopes: []
|
|
131
159
|
};
|
|
@@ -140,6 +168,16 @@ function resolveChannelRuntimeValues(params) {
|
|
|
140
168
|
}
|
|
141
169
|
}
|
|
142
170
|
|
|
171
|
+
if (params.channelTarget === 'slack') {
|
|
172
|
+
const oauthCallbackUrl = params.oauthCallbackUrl || resolved.oauthCallbackUrl;
|
|
173
|
+
Object.assign(resolved, resolveSlackOAuthManifestFields(oauthCallbackUrl));
|
|
174
|
+
const prefix =
|
|
175
|
+
typeof params.commandPrefix === 'string' && params.commandPrefix.trim()
|
|
176
|
+
? params.commandPrefix.trim()
|
|
177
|
+
: DEFAULT_SLACK_COMMAND_PREFIX;
|
|
178
|
+
resolved.commandPrefix = prefix;
|
|
179
|
+
}
|
|
180
|
+
|
|
143
181
|
return resolved;
|
|
144
182
|
}
|
|
145
183
|
|
|
@@ -148,5 +186,7 @@ module.exports = {
|
|
|
148
186
|
joinUrl,
|
|
149
187
|
externalSystemsPrefix,
|
|
150
188
|
getEndpointPathSuffixes,
|
|
151
|
-
|
|
189
|
+
resolveSlackOAuthManifestFields,
|
|
190
|
+
resolveChannelRuntimeValues,
|
|
191
|
+
DEFAULT_SLACK_COMMAND_PREFIX
|
|
152
192
|
};
|