@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
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability route execution for builder-api HTTP server.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Keeps handleRequest under max-lines-per-function
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const { executeCapabilityRequest } = require('./builder-api-request');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {Object} DispatchCapabilityRouteOptions
|
|
15
|
+
* @property {import('http').IncomingMessage} req
|
|
16
|
+
* @property {import('http').ServerResponse} res
|
|
17
|
+
* @property {Function} sendJson
|
|
18
|
+
* @property {Function} sendProblem
|
|
19
|
+
* @property {Function} readJsonBody
|
|
20
|
+
* @property {Object} resolved
|
|
21
|
+
* @property {Object} query
|
|
22
|
+
* @property {string} requestId
|
|
23
|
+
* @property {string} pathname
|
|
24
|
+
* @property {Function} logRequestOutcome
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {DispatchCapabilityRouteOptions} options
|
|
29
|
+
*/
|
|
30
|
+
async function dispatchCapabilityRoute(options) {
|
|
31
|
+
const {
|
|
32
|
+
req,
|
|
33
|
+
res,
|
|
34
|
+
sendJson,
|
|
35
|
+
sendProblem,
|
|
36
|
+
readJsonBody,
|
|
37
|
+
resolved,
|
|
38
|
+
query,
|
|
39
|
+
requestId,
|
|
40
|
+
pathname,
|
|
41
|
+
logRequestOutcome
|
|
42
|
+
} = options;
|
|
43
|
+
try {
|
|
44
|
+
const outcome = await executeCapabilityRequest({
|
|
45
|
+
req,
|
|
46
|
+
capability: resolved.capability,
|
|
47
|
+
params: resolved.params,
|
|
48
|
+
routeKey: resolved.routeKey,
|
|
49
|
+
requestId,
|
|
50
|
+
readJsonBody,
|
|
51
|
+
query
|
|
52
|
+
});
|
|
53
|
+
sendJson(res, outcome.httpStatus, outcome.body, outcome.requestId);
|
|
54
|
+
logRequestOutcome({
|
|
55
|
+
requestId: outcome.requestId,
|
|
56
|
+
correlationId: outcome.body.correlationId,
|
|
57
|
+
route: resolved.routeKey,
|
|
58
|
+
method: req.method,
|
|
59
|
+
status: outcome.httpStatus,
|
|
60
|
+
systemKey: resolved.params.systemKey,
|
|
61
|
+
userId: outcome.userId
|
|
62
|
+
});
|
|
63
|
+
} catch (err) {
|
|
64
|
+
const status = err.statusCode || 500;
|
|
65
|
+
if (status === 409 && err.retryAfter) {
|
|
66
|
+
res.setHeader('Retry-After', String(err.retryAfter));
|
|
67
|
+
}
|
|
68
|
+
sendProblem(req, res, err, status, requestId, pathname);
|
|
69
|
+
logRequestOutcome({
|
|
70
|
+
requestId,
|
|
71
|
+
route: resolved.routeKey,
|
|
72
|
+
method: req.method,
|
|
73
|
+
status,
|
|
74
|
+
systemKey: resolved.params.systemKey,
|
|
75
|
+
error: err.message
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports = {
|
|
81
|
+
dispatchCapabilityRoute
|
|
82
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docker dev-reload runtime config layout for builder-api.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Ensures AIFABRIX_CONFIG parent directory exists before kv:// resolution
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const fs = require('../internal/fs-real-sync');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Create the directory containing `AIFABRIX_CONFIG` when set (dev-reload bind mount).
|
|
16
|
+
* Does not write config or secrets — operators link or copy `config.yaml` and `secrets.local.yaml`
|
|
17
|
+
* under that directory (gitignored under repo `.aifabrix/` or persistent `mount/aifabrix/`).
|
|
18
|
+
*/
|
|
19
|
+
function ensureBuilderApiRuntimeConfigDir() {
|
|
20
|
+
const raw = process.env.AIFABRIX_CONFIG;
|
|
21
|
+
if (!raw || typeof raw !== 'string' || !raw.trim()) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const configPath = path.resolve(raw.trim());
|
|
25
|
+
const dir = path.dirname(configPath);
|
|
26
|
+
if (fs.existsSync(dir)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
31
|
+
} catch (err) {
|
|
32
|
+
// Named Docker volumes are often root-owned when compose runs without bind mount + UID mapping.
|
|
33
|
+
if (err && (err.code === 'EACCES' || err.code === 'EPERM')) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
throw err;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = {
|
|
41
|
+
ensureBuilderApiRuntimeConfigDir
|
|
42
|
+
};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builder API HTTP server (plan 154.0 — pre-Nest unified router).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Full V1 route set via capability registry
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const http = require('http');
|
|
12
|
+
const { URL } = require('url');
|
|
13
|
+
const { randomUUID } = require('crypto');
|
|
14
|
+
const { CAPABILITIES, getCapabilityByHandlerId } = require('./capability-registry');
|
|
15
|
+
const { BASE, matchRoutePattern } = require('./http-route-match');
|
|
16
|
+
const { buildOpenApiSpec } = require('./openapi-spec');
|
|
17
|
+
const { writeAccessLog } = require('./access-log');
|
|
18
|
+
const { dispatchCapabilityRoute } = require('./builder-api-route-dispatch');
|
|
19
|
+
const { renderBuilderApiRedocHtml, resolvePublicBaseUrl } = require('./openapi-docs-serving');
|
|
20
|
+
const { buildProblemDetails, writeProblemDetails } = require('./http-problem-details');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {import('http').ServerResponse} res
|
|
24
|
+
* @param {number} status
|
|
25
|
+
* @param {Object} body
|
|
26
|
+
* @param {string} [requestId]
|
|
27
|
+
*/
|
|
28
|
+
function sendJson(res, status, body, requestId) {
|
|
29
|
+
const payload =
|
|
30
|
+
body && typeof body.openapi === 'string'
|
|
31
|
+
? body
|
|
32
|
+
: { ...body, requestId: requestId || body.requestId };
|
|
33
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
34
|
+
res.end(JSON.stringify(payload));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {import('http').IncomingMessage} req
|
|
39
|
+
* @param {import('http').ServerResponse} res
|
|
40
|
+
* @param {unknown} error
|
|
41
|
+
* @param {number} status
|
|
42
|
+
* @param {string} requestId
|
|
43
|
+
* @param {string} pathname
|
|
44
|
+
*/
|
|
45
|
+
function sendProblem(req, res, error, status, requestId, pathname) {
|
|
46
|
+
const body = buildProblemDetails(error, status, req, requestId, pathname);
|
|
47
|
+
writeProblemDetails(res, status, body);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {import('http').IncomingMessage} req
|
|
52
|
+
* @returns {Promise<Object>}
|
|
53
|
+
*/
|
|
54
|
+
function readJsonBody(req) {
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
const chunks = [];
|
|
57
|
+
let size = 0;
|
|
58
|
+
const max = Number(process.env.MAX_BODY_BYTES || 10 * 1024 * 1024);
|
|
59
|
+
req.on('data', (chunk) => {
|
|
60
|
+
size += chunk.length;
|
|
61
|
+
if (size > max) {
|
|
62
|
+
reject(Object.assign(new Error('Request body too large'), { statusCode: 413 }));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
chunks.push(chunk);
|
|
66
|
+
});
|
|
67
|
+
req.on('end', () => {
|
|
68
|
+
if (chunks.length === 0) {
|
|
69
|
+
resolve({});
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
resolve(JSON.parse(Buffer.concat(chunks).toString('utf8')));
|
|
74
|
+
} catch {
|
|
75
|
+
reject(Object.assign(new Error('Invalid JSON body'), { statusCode: 400 }));
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
req.on('error', reject);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @param {string} method
|
|
84
|
+
* @param {string} pathname
|
|
85
|
+
* @returns {{ capability: Object, params: Object, routeKey: string }|null}
|
|
86
|
+
*/
|
|
87
|
+
function resolveCapabilityRoute(method, pathname) {
|
|
88
|
+
for (const capability of CAPABILITIES) {
|
|
89
|
+
if (capability.method !== method) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const params = matchRoutePattern(capability.route, pathname);
|
|
93
|
+
if (params) {
|
|
94
|
+
return { capability, params, routeKey: `${method} ${capability.route}` };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @param {import('http').ServerResponse} res
|
|
102
|
+
* @param {number} status
|
|
103
|
+
* @param {string} html
|
|
104
|
+
* @param {string} [requestId]
|
|
105
|
+
*/
|
|
106
|
+
function sendHtml(res, status, html, requestId) {
|
|
107
|
+
const headers = {
|
|
108
|
+
'Content-Type': 'text/html; charset=utf-8',
|
|
109
|
+
'Cache-Control': 'public, max-age=60'
|
|
110
|
+
};
|
|
111
|
+
if (requestId) {
|
|
112
|
+
headers['X-Request-Id'] = requestId;
|
|
113
|
+
}
|
|
114
|
+
res.writeHead(status, headers);
|
|
115
|
+
res.end(html);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @param {string} pathname
|
|
120
|
+
* @returns {boolean}
|
|
121
|
+
*/
|
|
122
|
+
function isRedocHtmlPath(pathname) {
|
|
123
|
+
return pathname === '/api/docs' || pathname === `${BASE}/api-docs`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @param {string} pathname
|
|
128
|
+
* @returns {boolean}
|
|
129
|
+
*/
|
|
130
|
+
function isOpenApiJsonPath(pathname) {
|
|
131
|
+
return pathname === `${BASE}/api-docs/openapi.json`;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @param {import('http').IncomingMessage} req
|
|
136
|
+
* @param {import('http').ServerResponse} res
|
|
137
|
+
* @param {string} pathname
|
|
138
|
+
* @param {string} requestId
|
|
139
|
+
*/
|
|
140
|
+
function handleOpenApiDocs(req, res, pathname, requestId) {
|
|
141
|
+
if (req.method !== 'GET') {
|
|
142
|
+
sendProblem(req, res, 'Method not allowed', 405, requestId, pathname);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (isOpenApiJsonPath(pathname)) {
|
|
146
|
+
const publicBaseUrl = resolvePublicBaseUrl(req);
|
|
147
|
+
sendJson(res, 200, buildOpenApiSpec({ publicBaseUrl }), requestId);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (isRedocHtmlPath(pathname)) {
|
|
151
|
+
sendHtml(res, 200, renderBuilderApiRedocHtml(req), requestId);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @param {Object} entry
|
|
157
|
+
*/
|
|
158
|
+
function logRequestOutcome(entry) {
|
|
159
|
+
if (process.env.BUILDER_API_ACCESS_LOG === '0') {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
writeAccessLog(entry);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @param {import('http').IncomingMessage} req
|
|
167
|
+
* @param {import('http').ServerResponse} res
|
|
168
|
+
*/
|
|
169
|
+
async function handleRequest(req, res) {
|
|
170
|
+
const requestId = req.headers['x-request-id'] || randomUUID();
|
|
171
|
+
const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);
|
|
172
|
+
const pathname = url.pathname;
|
|
173
|
+
|
|
174
|
+
if (isRedocHtmlPath(pathname) || isOpenApiJsonPath(pathname)) {
|
|
175
|
+
handleOpenApiDocs(req, res, pathname, requestId);
|
|
176
|
+
logRequestOutcome({
|
|
177
|
+
requestId,
|
|
178
|
+
route: pathname,
|
|
179
|
+
method: req.method,
|
|
180
|
+
status: 200,
|
|
181
|
+
userId: 'anonymous'
|
|
182
|
+
});
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const resolved = resolveCapabilityRoute(req.method || 'GET', pathname);
|
|
187
|
+
if (!resolved || !getCapabilityByHandlerId(resolved.capability.handlerId)) {
|
|
188
|
+
sendProblem(req, res, 'Not found', 404, requestId, pathname);
|
|
189
|
+
logRequestOutcome({ requestId, route: pathname, method: req.method, status: 404, userId: 'anonymous' });
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const query = Object.fromEntries(url.searchParams.entries());
|
|
194
|
+
await dispatchCapabilityRoute({
|
|
195
|
+
req,
|
|
196
|
+
res,
|
|
197
|
+
sendJson,
|
|
198
|
+
sendProblem,
|
|
199
|
+
readJsonBody,
|
|
200
|
+
resolved,
|
|
201
|
+
query,
|
|
202
|
+
requestId,
|
|
203
|
+
pathname,
|
|
204
|
+
logRequestOutcome
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @param {number} [port]
|
|
210
|
+
* @returns {import('http').Server}
|
|
211
|
+
*/
|
|
212
|
+
function createBuilderApiServer(port = Number(process.env.PORT || 3005)) {
|
|
213
|
+
const server = http.createServer((req, res) => {
|
|
214
|
+
handleRequest(req, res).catch((err) => {
|
|
215
|
+
const requestId = req.headers['x-request-id'] || randomUUID();
|
|
216
|
+
const pathname = String(req.url || '/').split('?')[0];
|
|
217
|
+
sendProblem(req, res, err, err.statusCode || 500, requestId, pathname);
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
server.listen(port);
|
|
221
|
+
return server;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
module.exports = {
|
|
225
|
+
createBuilderApiServer,
|
|
226
|
+
handleRequest,
|
|
227
|
+
sendJson,
|
|
228
|
+
sendProblem,
|
|
229
|
+
BASE
|
|
230
|
+
};
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication catalog for builder-api LLM help (external-system.schema.json).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview authType modes and credential.method templates for UI handoff guidance
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
const SCHEMA_DIR = path.join(__dirname, '..', 'schema');
|
|
15
|
+
const SYSTEM_SCHEMA_PATH = path.join(SCHEMA_DIR, 'external-system.schema.json');
|
|
16
|
+
const CREDENTIAL_REGISTRY_PATH = path.join(SCHEMA_DIR, 'type', 'credential-field-registry.json');
|
|
17
|
+
|
|
18
|
+
/** @type {Object|null} */
|
|
19
|
+
let cachedCatalog = null;
|
|
20
|
+
|
|
21
|
+
/** @type {Readonly<Record<string, string>>} */
|
|
22
|
+
const METHOD_UI_LABELS = Object.freeze({
|
|
23
|
+
oauth2: 'OAuth 2.0',
|
|
24
|
+
aad: 'Azure AD (aad)',
|
|
25
|
+
apikey: 'API Key',
|
|
26
|
+
bearerToken: 'Bearer token',
|
|
27
|
+
basic: 'Basic Auth',
|
|
28
|
+
queryParam: 'Query parameter',
|
|
29
|
+
oidc: 'OpenID Connect (OIDC)',
|
|
30
|
+
hmac: 'HMAC',
|
|
31
|
+
none: 'None'
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
/** @type {Readonly<Record<string, string>>} */
|
|
35
|
+
const METHOD_REGISTRY_KEY = Object.freeze({
|
|
36
|
+
oauth2: 'oauth2',
|
|
37
|
+
aad: 'oauth2',
|
|
38
|
+
apikey: 'apiKey',
|
|
39
|
+
bearerToken: 'bearerToken',
|
|
40
|
+
basic: 'basicAuth',
|
|
41
|
+
queryParam: 'queryParam',
|
|
42
|
+
oidc: 'oidc',
|
|
43
|
+
hmac: 'hmac',
|
|
44
|
+
none: 'none'
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/** @type {Readonly<Object>} */
|
|
48
|
+
const MANIFEST_AUTH_SPLIT = Object.freeze({
|
|
49
|
+
variables: {
|
|
50
|
+
manifestPath: 'authentication.credential.variables',
|
|
51
|
+
purpose:
|
|
52
|
+
'Non-secret configuration (baseUrl, tokenUrl, headerName, prefix, testEndpoint, and similar). Set in the manifest authentication section before upload.',
|
|
53
|
+
publishedBehavior:
|
|
54
|
+
'Upload publishes variables to dataplane. They appear pre-filled in Connected Systems Authentication — the user does not re-enter them.',
|
|
55
|
+
agentRule:
|
|
56
|
+
'Ensure variables are complete in the manifest during editing. After upload, do not ask the user to supply non-secret variable values again.'
|
|
57
|
+
},
|
|
58
|
+
security: {
|
|
59
|
+
manifestPath: 'authentication.credential.security',
|
|
60
|
+
purpose:
|
|
61
|
+
'Secret placeholders only. Manifest values must be kv:// references (unresolved in Builder API scope).',
|
|
62
|
+
publishedBehavior:
|
|
63
|
+
'Upload creates the credential template. The user adds live secret values in Authentication UI — typically only the token or apiKey.',
|
|
64
|
+
agentRule:
|
|
65
|
+
'After upload, ask the user only for requiredSecretKeys. This is the minimum post-upload handoff.'
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
/** @type {Readonly<Record<string, string>>} */
|
|
70
|
+
const METHOD_USER_HANDOFF = Object.freeze({
|
|
71
|
+
oauth2:
|
|
72
|
+
'User adds clientSecret (and clientId if empty). baseUrl, tokenUrl, grantType, and scope are already published from manifest variables.',
|
|
73
|
+
aad:
|
|
74
|
+
'User adds clientSecret (and clientId if empty). baseUrl, tokenUrl, tenantId, and grantType are already published from manifest variables.',
|
|
75
|
+
apikey:
|
|
76
|
+
'User adds only the API key token. baseUrl, headerName, prefix, and testEndpoint are already published from manifest variables.',
|
|
77
|
+
bearerToken:
|
|
78
|
+
'User adds only the bearer token. baseUrl, headerName, prefix, and testEndpoint are already published from manifest variables.',
|
|
79
|
+
basic:
|
|
80
|
+
'User adds username and password. baseUrl and testEndpoint are already published from manifest variables.',
|
|
81
|
+
queryParam:
|
|
82
|
+
'User adds only the paramValue secret. baseUrl, paramName, and testEndpoint are already published from manifest variables.',
|
|
83
|
+
oidc:
|
|
84
|
+
'openIdConfigUrl and clientId are already published from manifest variables. User confirms or completes any remaining OIDC fields shown in UI.',
|
|
85
|
+
hmac:
|
|
86
|
+
'User adds signingSecret. Algorithm and signature header settings are already published from manifest variables.',
|
|
87
|
+
none: 'No credential secrets required for this method.'
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
/** @type {ReadonlyArray<Object>} */
|
|
91
|
+
const AUTH_TYPES = Object.freeze([
|
|
92
|
+
{
|
|
93
|
+
authType: 'credential',
|
|
94
|
+
manifestPath: 'authentication.credential',
|
|
95
|
+
uiTab: 'authentication',
|
|
96
|
+
description:
|
|
97
|
+
'Local credential template from external-system.schema.json. Non-secret variables are published on upload; user adds live secrets in Authentication UI only.',
|
|
98
|
+
userAction:
|
|
99
|
+
'Open Authentication tab. Non-secret fields are already pre-filled from manifest variables. User adds only the required secret values (for example apiKey token, clientSecret).',
|
|
100
|
+
builderApiScope:
|
|
101
|
+
'Set authentication.credential.variables in the manifest before upload. Keep kv:// placeholders in security; upload does not resolve secrets. User replaces placeholders with live values in the UI.'
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
authType: 'apiProvider',
|
|
105
|
+
manifestPath: 'authentication.apiProvider.apiProviderKey',
|
|
106
|
+
uiTab: 'authentication',
|
|
107
|
+
description:
|
|
108
|
+
'Delegated authentication via a Miso API Provider — no dataplane-local vendor secrets.',
|
|
109
|
+
userAction:
|
|
110
|
+
'Open Authentication tab and link or select the API Provider referenced by apiProviderKey in the manifest.',
|
|
111
|
+
builderApiScope:
|
|
112
|
+
'Upload publishes the apiProviderKey reference only. User completes provider binding in the UI.'
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
authType: 'none',
|
|
116
|
+
manifestPath: 'authentication.authType',
|
|
117
|
+
uiTab: null,
|
|
118
|
+
description: 'No authentication block secrets. System does not use a local credential template.',
|
|
119
|
+
userAction:
|
|
120
|
+
'Skip credential entry unless the integration still needs network-level auth configured elsewhere.',
|
|
121
|
+
builderApiScope: 'No post-upload secret handoff for authType none unless live tests fail for other reasons.'
|
|
122
|
+
}
|
|
123
|
+
]);
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* @returns {Object}
|
|
127
|
+
*/
|
|
128
|
+
function loadSystemSchema() {
|
|
129
|
+
return JSON.parse(fs.readFileSync(SYSTEM_SCHEMA_PATH, 'utf8'));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @returns {Object}
|
|
134
|
+
*/
|
|
135
|
+
function loadCredentialRegistry() {
|
|
136
|
+
return JSON.parse(fs.readFileSync(CREDENTIAL_REGISTRY_PATH, 'utf8'));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @param {string|null|undefined} text
|
|
141
|
+
* @returns {string|null}
|
|
142
|
+
*/
|
|
143
|
+
function sanitizeHelpText(text) {
|
|
144
|
+
if (!text) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
const cleaned = String(text)
|
|
148
|
+
.replace(/https?:\/\/[^\s)]+/gi, '')
|
|
149
|
+
.replace(/\s{2,}/g, ' ')
|
|
150
|
+
.trim();
|
|
151
|
+
return cleaned || null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* @param {string} method
|
|
156
|
+
* @param {Object} registry
|
|
157
|
+
* @returns {string}
|
|
158
|
+
*/
|
|
159
|
+
function resolveUiLabel(method, registry) {
|
|
160
|
+
if (METHOD_UI_LABELS[method]) {
|
|
161
|
+
return METHOD_UI_LABELS[method];
|
|
162
|
+
}
|
|
163
|
+
const registryKey = METHOD_REGISTRY_KEY[method];
|
|
164
|
+
const entry = registryKey ? registry.credentialTypes?.[registryKey] : null;
|
|
165
|
+
if (entry?.display?.label) {
|
|
166
|
+
return entry.display.label;
|
|
167
|
+
}
|
|
168
|
+
return method;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @param {string} method
|
|
173
|
+
* @param {Object} methodDef
|
|
174
|
+
* @returns {Object}
|
|
175
|
+
*/
|
|
176
|
+
function summarizeMethodFields(method, methodDef) {
|
|
177
|
+
const variables = (methodDef.variables || []).map((item) => ({
|
|
178
|
+
key: item.key,
|
|
179
|
+
required: item.required === true,
|
|
180
|
+
description: sanitizeHelpText(item.description)
|
|
181
|
+
}));
|
|
182
|
+
const security = (methodDef.security || []).map((item) => ({
|
|
183
|
+
key: item.key,
|
|
184
|
+
required: item.required === true,
|
|
185
|
+
encrypted: true
|
|
186
|
+
}));
|
|
187
|
+
return {
|
|
188
|
+
method,
|
|
189
|
+
uiLabel: METHOD_UI_LABELS[method] || method,
|
|
190
|
+
variableKeys: variables.map((item) => item.key),
|
|
191
|
+
requiredVariableKeys: variables.filter((item) => item.required).map((item) => item.key),
|
|
192
|
+
secretKeys: security.map((item) => item.key),
|
|
193
|
+
requiredSecretKeys: security.filter((item) => item.required).map((item) => item.key),
|
|
194
|
+
variables,
|
|
195
|
+
security,
|
|
196
|
+
userHandoff: METHOD_USER_HANDOFF[method] || 'User completes secret fields shown for this method in Authentication.',
|
|
197
|
+
manifestPath: 'authentication.credential.method',
|
|
198
|
+
schemaDefKey: 'authenticationVariablesByMethod'
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* @returns {Object}
|
|
204
|
+
*/
|
|
205
|
+
function buildAuthenticationCatalog() {
|
|
206
|
+
if (cachedCatalog) {
|
|
207
|
+
return cachedCatalog;
|
|
208
|
+
}
|
|
209
|
+
const schema = loadSystemSchema();
|
|
210
|
+
const registry = loadCredentialRegistry();
|
|
211
|
+
const methodsByDef = schema.$defs?.authenticationVariablesByMethod || {};
|
|
212
|
+
const methodEnum =
|
|
213
|
+
schema.$defs?.credentialTemplate?.properties?.method?.enum ||
|
|
214
|
+
Object.keys(methodsByDef).sort();
|
|
215
|
+
|
|
216
|
+
const credentialMethods = methodEnum
|
|
217
|
+
.filter((method) => methodsByDef[method])
|
|
218
|
+
.map((method) => {
|
|
219
|
+
const summary = summarizeMethodFields(method, methodsByDef[method]);
|
|
220
|
+
summary.uiLabel = resolveUiLabel(method, registry);
|
|
221
|
+
return summary;
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
cachedCatalog = {
|
|
225
|
+
schemaSource: 'external-system.schema.json',
|
|
226
|
+
manifestSectionKey: 'system.authentication',
|
|
227
|
+
datasourceNote:
|
|
228
|
+
'Authentication is declared on the external system manifest (system.authentication), not on individual datasource manifests. Datasources inherit the linked system credential during sync and CIP execution.',
|
|
229
|
+
manifestAuthSplit: MANIFEST_AUTH_SPLIT,
|
|
230
|
+
authTypes: AUTH_TYPES,
|
|
231
|
+
credentialMethods,
|
|
232
|
+
agentHandoffSteps: [
|
|
233
|
+
'Read workspace section system.authentication (or the published system manifest) before prompting the user.',
|
|
234
|
+
'Identify authentication.authType: credential, apiProvider, or none.',
|
|
235
|
+
'When authType is credential, ensure authentication.credential.variables holds all non-secret config before upload (baseUrl, headerName, tokenUrl, and similar).',
|
|
236
|
+
'Upload publishes variables pre-filled in Authentication UI. Ask the user only for requiredSecretKeys — not for variables already in the manifest.',
|
|
237
|
+
'When authType is apiProvider, direct the user to link apiProviderKey in Authentication — do not ask for vendor API keys in Builder API scope.',
|
|
238
|
+
'When authType is none, skip secret handoff unless E2E still fails for unrelated configuration.',
|
|
239
|
+
'Provide the Connected Systems Authentication URL using connectedSystemUi urlTemplates plus the published systemKey.'
|
|
240
|
+
]
|
|
241
|
+
};
|
|
242
|
+
return cachedCatalog;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* @param {Object} query
|
|
247
|
+
* @returns {Object|null}
|
|
248
|
+
*/
|
|
249
|
+
function buildAuthenticationHandoffForManifest(query) {
|
|
250
|
+
const authType = query.authType ? String(query.authType) : null;
|
|
251
|
+
const method = query.credentialMethod ? String(query.credentialMethod) : null;
|
|
252
|
+
if (!authType && !method) {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
const catalog = buildAuthenticationCatalog();
|
|
256
|
+
const authTypeEntry = authType ? catalog.authTypes.find((entry) => entry.authType === authType) : null;
|
|
257
|
+
const methodEntry = method
|
|
258
|
+
? catalog.credentialMethods.find((entry) => entry.method === method)
|
|
259
|
+
: null;
|
|
260
|
+
if (!authTypeEntry && !methodEntry) {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
authType: authTypeEntry || null,
|
|
265
|
+
credentialMethod: methodEntry || null,
|
|
266
|
+
promptHints: [
|
|
267
|
+
authTypeEntry ? authTypeEntry.userAction : null,
|
|
268
|
+
'Non-secret authentication.credential.variables are already published and pre-filled in the UI.',
|
|
269
|
+
methodEntry ? methodEntry.userHandoff : null,
|
|
270
|
+
methodEntry && methodEntry.requiredSecretKeys.length
|
|
271
|
+
? `User adds only these secret fields: ${methodEntry.requiredSecretKeys.join(', ')}`
|
|
272
|
+
: null
|
|
273
|
+
].filter(Boolean)
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
module.exports = {
|
|
278
|
+
AUTH_TYPES,
|
|
279
|
+
METHOD_UI_LABELS,
|
|
280
|
+
buildAuthenticationCatalog,
|
|
281
|
+
buildAuthenticationHandoffForManifest
|
|
282
|
+
};
|