@aifabrix/builder 2.49.2 → 2.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/deploy-rules/docker-image-ip-policy.mdc +49 -0
- package/.cursor/rules/plan-rules/application-lifecycle.mdc +30 -0
- package/.cursor/rules/plan-rules/plan-frontmatter.mdc +35 -0
- package/.cursor/rules/plan-rules/plan-lifecycle.mdc +31 -0
- package/.cursor/rules/plan-rules/plan-validation-gate.mdc +34 -0
- package/.cursor/skills/README.md +1 -0
- package/.dockerignore +52 -0
- package/.eslintignore +22 -0
- package/README.md +2 -0
- package/bin/builder-api-cleanup.js +26 -0
- package/bin/builder-api-nest.js +10 -0
- package/bin/builder-api-spike.js +19 -0
- package/enterprise-knowledge/README.md +50 -0
- package/enterprise-knowledge/enterprise-integration-lifecycle/README.md +22 -0
- package/enterprise-knowledge/enterprise-integration-lifecycle/application.json +15 -0
- package/enterprise-knowledge/enterprise-integration-lifecycle/deploy.js +69 -0
- package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-deploy.json +52 -0
- package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-system.json +29 -0
- package/enterprise-knowledge/enterprise-integration-lifecycle/env.template +2 -0
- package/integration/README.md +81 -0
- package/integration/github/README.md +53 -0
- package/integration/github/application.json +21 -0
- package/integration/github/deploy.js +72 -0
- package/integration/github/env.template +11 -0
- package/integration/github/github-datasource-issue-comments.json +239 -0
- package/integration/github/github-datasource-issues.json +399 -0
- package/integration/github/github-datasource-repository.json +354 -0
- package/integration/github/github-deploy.json +1202 -0
- package/integration/github/github-system.json +82 -0
- package/integration/hubspot-test/README.md +1 -1
- package/jest.isolated-projects.js +31 -1
- package/jest.projects.js +87 -1
- package/lib/api/dev-server-https.js +1 -1
- package/lib/api/enterprise-knowledge.api.js +63 -0
- package/lib/api/evidence.api.js +172 -0
- package/lib/api/external-systems.api.js +8 -2
- package/lib/api/resource-types.api.js +1 -0
- package/lib/api/types/enterprise-knowledge.types.js +46 -0
- package/lib/api/types/evidence.types.js +67 -0
- package/lib/api/types/resource-types.types.js +2 -0
- package/lib/app/controller-application-filter.js +36 -0
- package/lib/app/deploy.js +1 -1
- package/lib/app/list-external-systems.js +130 -0
- package/lib/app/list.js +20 -8
- package/lib/app/run.js +3 -1
- package/lib/app/show-display.js +8 -3
- package/lib/app/show-online.js +178 -0
- package/lib/app/show.js +37 -88
- package/lib/build/builder-api-docker-staging.js +47 -0
- package/lib/build/miso-controller-npm-sdk-guard.js +2 -2
- package/lib/build/standard-docker-build.js +2 -0
- package/lib/certification/post-unified-cert-sync.js +4 -31
- package/lib/certification/sync-after-external-command.js +0 -1
- package/lib/certification/sync-system-certification.js +0 -3
- package/lib/channels/add-channel.js +40 -34
- package/lib/channels/approval-guides/chatgpt.js +33 -0
- package/lib/channels/approval-guides/credential-portal.js +38 -0
- package/lib/channels/approval-guides/index.js +110 -0
- package/lib/channels/approval-guides/microsoft-copilot.js +34 -0
- package/lib/channels/approval-guides/slack.js +34 -0
- package/lib/channels/approval-guides/teams-bot.js +35 -0
- package/lib/channels/approval-guides/web-embed.js +32 -0
- package/lib/channels/channel-approval-guide.js +11 -0
- package/lib/channels/channel-artifact-generator.js +16 -4
- package/lib/channels/channel-audit.js +3 -0
- package/lib/channels/channel-auth-context.js +1 -1
- package/lib/channels/channel-description.js +59 -0
- package/lib/channels/channel-integration-generator.js +13 -230
- package/lib/channels/channel-integration-template.js +94 -0
- package/lib/channels/channel-runtime-resolver.js +43 -3
- package/lib/channels/channel-status-display.js +66 -26
- package/lib/channels/channel-targets.js +3 -3
- package/lib/cli/index.js +27 -3
- package/lib/cli/infra-guided.js +5 -1
- package/lib/cli/setup-app-external-create.js +111 -0
- package/lib/cli/setup-app.help.js +1 -1
- package/lib/cli/setup-app.js +38 -125
- package/lib/cli/setup-app.test-commands.js +26 -52
- package/lib/cli/setup-certification-commands.js +4 -4
- package/lib/cli/setup-certification.help.js +9 -9
- package/lib/cli/setup-dev.js +7 -2
- package/lib/cli/setup-external-system-help.js +4 -6
- package/lib/cli/setup-external-system.js +58 -52
- package/lib/cli/setup-infra-up-builder-api-action.js +64 -0
- package/lib/cli/setup-infra-up-platform-action.js +3 -1
- package/lib/cli/setup-infra.js +15 -0
- package/lib/cli/setup-list.js +43 -0
- package/lib/cli/setup-utility-repair.js +26 -7
- package/lib/cli/setup-utility.js +5 -3
- package/lib/commands/app.js +15 -43
- package/lib/commands/channel-add-setup.js +110 -0
- package/lib/commands/channel.js +42 -8
- package/lib/commands/datasource-sync-display.js +96 -0
- package/lib/commands/datasource-sync-policy.js +210 -0
- package/lib/commands/datasource-test-trust-cli.js +6 -6
- package/lib/commands/datasource-unified-test-cli.js +2 -1
- package/lib/commands/datasource-unified-test-cli.options.js +33 -23
- package/lib/commands/deploy-gate-failure-details.js +163 -0
- package/lib/commands/deploy-gate-orchestrator.js +322 -0
- package/lib/commands/dev-cli-handlers.js +1 -59
- package/lib/commands/dev-host-ops-params.js +91 -0
- package/lib/commands/dev-host-ops-poll.js +111 -0
- package/lib/commands/dev-host-ops.js +107 -94
- package/lib/commands/dev-init.js +3 -1
- package/lib/commands/enterprise-knowledge.js +284 -0
- package/lib/commands/evidence-cli-leaves.js +250 -0
- package/lib/commands/evidence.js +51 -0
- package/lib/commands/governance-cli-shared.js +2 -2
- package/lib/commands/governance-command-action.js +2 -2
- package/lib/commands/governance-fixture-subjects.js +85 -0
- package/lib/commands/governance.js +1 -1
- package/lib/commands/lifecycle-command-action.js +2 -2
- package/lib/commands/lifecycle-external.js +3 -3
- package/lib/commands/manifest-cli-auth.js +29 -0
- package/lib/commands/manifest-cli-commands.js +170 -0
- package/lib/commands/manifest-cli-integration-path.js +63 -0
- package/lib/commands/manifest.js +21 -0
- package/lib/commands/protection-cli-leaves.js +3 -3
- package/lib/commands/repair-auth-apply.js +15 -1
- package/lib/commands/repair-authentications-454.js +169 -0
- package/lib/commands/repair-capability-openapi-warnings.js +126 -0
- package/lib/commands/repair-datasource-apply.js +135 -0
- package/lib/commands/repair-datasource-auto-rbac.js +62 -1
- package/lib/commands/repair-datasource-http-service-contract.js +239 -0
- package/lib/commands/repair-datasource-operation-security.js +180 -0
- package/lib/commands/repair-datasource-run.js +7 -2
- package/lib/commands/repair-datasource-sync-operations.js +177 -0
- package/lib/commands/repair-datasource-webhooks-sync-bridge.js +133 -0
- package/lib/commands/repair-datasource.js +12 -68
- package/lib/commands/repair-env-template.js +11 -1
- package/lib/commands/repair-external-run.js +121 -31
- package/lib/commands/repair-internal.js +1 -1
- package/lib/commands/repair-openapi-export.js +156 -0
- package/lib/commands/repair-openapi-sync.js +19 -2
- package/lib/commands/repair-orchestration-datasource-split.js +259 -0
- package/lib/commands/repair-persist.js +22 -1
- package/lib/commands/repair-rbac-platform-preset.js +204 -0
- package/lib/commands/repair-rbac-reader-roles.js +191 -0
- package/lib/commands/repair-rbac.js +163 -86
- package/lib/commands/repair-steps.js +83 -18
- package/lib/commands/repair-system-permissions.js +1 -0
- package/lib/commands/repair.js +1 -1
- package/lib/commands/resource-type.js +65 -26
- package/lib/commands/run-post-publish-data-sync.js +68 -0
- package/lib/commands/setup-modes.js +1 -1
- package/lib/commands/test-e2e-external.js +21 -8
- package/lib/commands/test-governance-cli-options.js +2 -2
- package/lib/commands/test-trust-cli-options.js +2 -2
- package/lib/commands/up-builder-api-bootstrap.js +71 -0
- package/lib/commands/up-builder-api-provision.js +241 -0
- package/lib/commands/up-builder-api.js +88 -0
- package/lib/commands/up-common.js +25 -1
- package/lib/commands/upload-credential-push-log.js +117 -0
- package/lib/commands/upload-data-sync-finalize.js +60 -0
- package/lib/commands/upload-probe.js +66 -0
- package/lib/commands/upload-publish-context.js +4 -1
- package/lib/commands/upload-sidecar-followups.js +55 -27
- package/lib/commands/upload.js +116 -157
- package/lib/commands/verify-governance-combined-external.js +1 -1
- package/lib/commands/verify-governance-db.js +2 -2
- package/lib/commands/verify-operations-command-action.js +2 -2
- package/lib/commands/verify-operations-step-plan.js +2 -2
- package/lib/commands/verify-operations-steps.js +2 -2
- package/lib/commands/verify-trust-command-action.js +1 -1
- package/lib/commands/wizard-core.js +1 -1
- package/lib/commands/wizard-headless.js +2 -1
- package/lib/core/admin-secrets.js +2 -6
- package/lib/core/secrets-env-content.js +10 -4
- package/lib/core/secrets-env-write.js +2 -13
- package/lib/datasource/agent-trust-run.js +3 -3
- package/lib/datasource/deploy.js +3 -1
- package/lib/datasource/test-e2e.js +6 -1
- package/lib/datasource/unified-validation-run-body.js +4 -1
- package/lib/datasource/unified-validation-run.js +1 -1
- package/lib/deployment/deploy-poll-ui.js +73 -12
- package/lib/deployment/deployer-poll-run.js +113 -0
- package/lib/deployment/deployer.js +17 -87
- package/lib/evidence/dataplane-context.js +21 -0
- package/lib/evidence/evidence-display.js +78 -0
- package/lib/evidence/evidence-service.js +392 -0
- package/lib/external-system/deploy.js +290 -112
- package/lib/external-system/download.js +7 -3
- package/lib/external-system/test-execution.js +1 -1
- package/lib/external-system/test-system-level.js +8 -10
- package/lib/external-system/test.js +12 -6
- package/lib/generator/deploy-script.js +73 -0
- package/lib/generator/external.js +2 -1
- package/lib/generator/index.js +17 -2
- package/lib/generator/wizard.js +3 -36
- package/lib/internal/fs-real-sync.js +22 -1
- package/lib/internal/node-fs.js +2 -0
- package/lib/lifecycle/lifecycle-governance-options.js +1 -1
- package/lib/lifecycle/verify-step-progress.js +1 -1
- package/lib/programmatic/access-log.js +26 -0
- package/lib/programmatic/auth-config.js +44 -0
- package/lib/programmatic/bearer-auth.js +176 -0
- package/lib/programmatic/builder-api-request.js +175 -0
- package/lib/programmatic/builder-api-route-dispatch.js +82 -0
- package/lib/programmatic/builder-api-runtime-config.js +42 -0
- package/lib/programmatic/builder-api-server.js +230 -0
- package/lib/programmatic/builder-help-authentication-catalog.js +282 -0
- package/lib/programmatic/builder-help-connected-system-ui.js +266 -0
- package/lib/programmatic/builder-help-enterprise-sync-fabrix.js +60 -0
- package/lib/programmatic/builder-help-envelope.js +36 -0
- package/lib/programmatic/builder-help-fixtures.js +200 -0
- package/lib/programmatic/builder-help-governance.js +172 -0
- package/lib/programmatic/builder-help-schema-catalog.js +92 -0
- package/lib/programmatic/builder-help.js +361 -0
- package/lib/programmatic/capability-registry.js +77 -0
- package/lib/programmatic/command-options.js +32 -0
- package/lib/programmatic/enterprise-mcp-client.js +98 -0
- package/lib/programmatic/http-problem-details.js +99 -0
- package/lib/programmatic/http-route-match.js +40 -0
- package/lib/programmatic/idempotency-cache.js +69 -0
- package/lib/programmatic/index.js +53 -0
- package/lib/programmatic/integration-path-scope.js +39 -0
- package/lib/programmatic/log-redaction.js +66 -0
- package/lib/programmatic/manifest-get-section.js +146 -0
- package/lib/programmatic/manifest-patch-section.js +252 -0
- package/lib/programmatic/manifest-repair.js +122 -0
- package/lib/programmatic/manifest-section-dependency-graph.js +160 -0
- package/lib/programmatic/manifest-section-io.js +225 -0
- package/lib/programmatic/manifest-section-quality.js +171 -0
- package/lib/programmatic/manifest-section-registry-data.js +269 -0
- package/lib/programmatic/manifest-section-registry.js +205 -0
- package/lib/programmatic/nest-http-bridge.js +34 -0
- package/lib/programmatic/openapi-component-schemas.js +68 -0
- package/lib/programmatic/openapi-description-enricher.js +117 -0
- package/lib/programmatic/openapi-descriptions.js +190 -0
- package/lib/programmatic/openapi-docs-serving.js +123 -0
- package/lib/programmatic/openapi-help-schemas.js +63 -0
- package/lib/programmatic/openapi-manifest-schemas.js +141 -0
- package/lib/programmatic/openapi-operation-bindings.js +274 -0
- package/lib/programmatic/openapi-request-schemas.js +155 -0
- package/lib/programmatic/openapi-result-schemas.js +476 -0
- package/lib/programmatic/openapi-schema-descriptions-certify.js +139 -0
- package/lib/programmatic/openapi-schema-descriptions-core.js +159 -0
- package/lib/programmatic/openapi-schema-descriptions-help.js +40 -0
- package/lib/programmatic/openapi-schema-descriptions-manifest.js +143 -0
- package/lib/programmatic/openapi-schema-descriptions-mcp.js +118 -0
- package/lib/programmatic/openapi-schema-descriptions-operations.js +281 -0
- package/lib/programmatic/openapi-schema-helpers.js +93 -0
- package/lib/programmatic/openapi-spec.js +203 -0
- package/lib/programmatic/orchestration-openapi-meta.js +159 -0
- package/lib/programmatic/platform-rbac-catalog.js +90 -0
- package/lib/programmatic/request-timeout.js +53 -0
- package/lib/programmatic/route-handler-map.js +143 -0
- package/lib/programmatic/route-handlers-context.js +29 -0
- package/lib/programmatic/route-handlers.js +33 -0
- package/lib/programmatic/run-certify.js +57 -0
- package/lib/programmatic/run-enterprise-mcp.js +32 -0
- package/lib/programmatic/run-lifecycle.js +29 -0
- package/lib/programmatic/run-repair.js +41 -0
- package/lib/programmatic/run-repository-emcp.js +54 -0
- package/lib/programmatic/run-template-workspace.js +61 -0
- package/lib/programmatic/run-test.js +49 -0
- package/lib/programmatic/run-upload.js +63 -0
- package/lib/programmatic/run-validate.js +53 -0
- package/lib/programmatic/run-wizard.js +40 -0
- package/lib/programmatic/system-key.js +48 -0
- package/lib/programmatic/wizard-config-normalize.js +118 -0
- package/lib/programmatic/workspace-cleanup.js +128 -0
- package/lib/programmatic/workspace-context.js +145 -0
- package/lib/programmatic/workspace-lock.js +75 -0
- package/lib/programmatic/workspace-meta.js +64 -0
- package/lib/programmatic/workspace-ops.js +149 -0
- package/lib/protection/run-commands-upload-sync.js +35 -0
- package/lib/protection/run-commands.js +2 -20
- package/lib/protection/upload-batch.js +11 -7
- package/lib/resolvers/resource-type-file.js +22 -0
- package/lib/schema/external-datasource.schema.json +161 -1
- package/lib/schema/external-system.schema.json +244 -118
- package/lib/schema/flag-map-validation-run.json +3 -0
- package/lib/schema/type/credential-field-registry.json +2 -2
- package/lib/schema/type/document-storage.json +9 -0
- package/lib/utils/agent-trust-run-display.js +1 -1
- package/lib/utils/app-path-resolve.js +168 -0
- package/lib/utils/authentication-env-template.js +222 -0
- package/lib/utils/cli-sync-options.js +7 -11
- package/lib/utils/cli-utils.js +4 -0
- package/lib/utils/cli-workspace-options.js +29 -0
- package/lib/utils/compose-generate-docker-compose.js +102 -0
- package/lib/utils/configuration-env-resolver.js +203 -27
- package/lib/utils/datasource-test-run-certificate-tty.js +28 -2
- package/lib/utils/datasource-test-run-certification-debug.js +130 -0
- package/lib/utils/datasource-test-run-debug-display.js +2 -0
- package/lib/utils/datasource-test-run-debug-slice.js +7 -0
- package/lib/utils/datasource-test-run-display.js +2 -1
- package/lib/utils/dev-init-ssh-merge.js +165 -23
- package/lib/utils/dev-pin-share-instructions.js +110 -0
- package/lib/utils/dev-ssh-config-helper.js +177 -33
- package/lib/utils/enterprise-knowledge-paths.js +142 -0
- package/lib/utils/env-copy.js +2 -1
- package/lib/utils/env-dotenv-format.js +103 -0
- package/lib/utils/external-env-template.js +4 -1
- package/lib/utils/external-system-display.js +5 -1
- package/lib/utils/external-system-readiness-compact-blocks.js +221 -0
- package/lib/utils/external-system-readiness-compact-display.js +324 -0
- package/lib/utils/external-system-readiness-core.js +16 -0
- package/lib/utils/external-system-readiness-deploy-display.js +29 -11
- package/lib/utils/external-system-readiness-display-internals.js +3 -1
- package/lib/utils/external-system-readiness-display.js +20 -30
- package/lib/utils/external-system-system-test-tty-certification.js +135 -0
- package/lib/utils/external-system-system-test-tty.js +5 -41
- package/lib/utils/help-builder.js +6 -1
- package/lib/utils/host-ops-job-labels.js +236 -0
- package/lib/utils/host-ops-job-result.js +61 -0
- package/lib/utils/host-ops-poll-ui.js +163 -0
- package/lib/utils/integration-path-resolve.js +112 -0
- package/lib/utils/paths-reload-source.js +148 -0
- package/lib/utils/paths-system-builder-keys.js +25 -0
- package/lib/utils/paths.js +151 -26
- package/lib/utils/runtime-configuration-values.js +64 -2
- package/lib/utils/secrets-helpers.js +5 -1
- package/lib/utils/ssh-known-hosts.js +130 -0
- package/lib/utils/test-target-cli-options.js +75 -0
- package/lib/utils/upload-sync-options.js +4 -0
- package/lib/utils/validation-run-request.js +11 -2
- package/lib/validation/external-manifest-validator.js +11 -1
- package/lib/validation/openapi-contract-surface-validator.js +426 -0
- package/lib/validation/openapi-contract-vendor-validation.js +238 -0
- package/lib/validation/validate-external-file.js +160 -0
- package/lib/validation/validate.js +6 -117
- package/package.json +46 -29
- package/packages/builder-api/README.md +120 -0
- package/packages/builder-api/package.json +30 -0
- package/packages/builder-api/src/app.module.ts +7 -0
- package/packages/builder-api/src/auth/auth.module.ts +5 -0
- package/packages/builder-api/src/external-system/external-system.module.ts +5 -0
- package/packages/builder-api/src/main.ts +16 -0
- package/packages/builder-api/tsconfig.json +15 -0
- package/scripts/check-builder-api-architecture-grep.js +79 -0
- package/scripts/docker_image_content_gate.js +47 -0
- package/scripts/docker_image_content_gate.sh +5 -0
- package/scripts/export-builder-api-evidence.js +262 -0
- package/scripts/lib/builder-api-docker-staging-copy.js +60 -0
- package/scripts/lib/builder-api-docker-staging-core.js +183 -0
- package/scripts/lib/docker-image-content-gate-core.js +166 -0
- package/scripts/lib/plan-actor.js +109 -0
- package/scripts/lib/plan-config.js +20 -0
- package/scripts/lib/plan-gates.js +154 -0
- package/scripts/lib/plan-meta.js +104 -0
- package/scripts/lib/plan-parse.js +162 -0
- package/scripts/lib/plan-prevalidate-gates.js +326 -0
- package/scripts/lib/plan-run-core.js +125 -0
- package/scripts/lib/plan-run-report.js +108 -0
- package/scripts/plan-approve.js +24 -0
- package/scripts/plan-archive.js +49 -0
- package/scripts/plan-run.js +13 -0
- package/scripts/plan-set-actor.js +21 -0
- package/scripts/plan-validate.js +80 -0
- package/scripts/pnpm/af.mjs +110 -0
- package/scripts/pnpm/check-quiet.mjs +32 -0
- package/scripts/pnpm/dev-install.mjs +29 -0
- package/scripts/pnpm/dev-reload.mjs +18 -0
- package/scripts/pnpm/help.mjs +55 -0
- package/scripts/pnpm/lib/dev-reload-core.mjs +189 -0
- package/scripts/pnpm/lib/dev-reload-log-capture.mjs +67 -0
- package/scripts/pnpm/lib/dev-reload-log-utils.mjs +32 -0
- package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +124 -0
- package/scripts/pnpm/lib/resolve-app-url.mjs +183 -0
- package/scripts/pnpm/lib/spinner.mjs +42 -0
- package/scripts/stage_builder_api_for_docker.js +65 -0
- package/scripts/sync-builder-api-template.js +44 -0
- package/templates/README.md +3 -0
- package/templates/applications/builder-api/Dockerfile +38 -0
- package/templates/applications/builder-api/application.yaml +75 -0
- package/templates/applications/builder-api/env.template +48 -0
- package/templates/applications/dataplane/application.yaml +1 -1
- package/templates/applications/dataplane/env.template +10 -6
- package/templates/applications/dataplane/rbac.yaml +21 -1
- package/templates/applications/miso-controller/application.yaml +1 -1
- package/templates/applications/miso-controller/env.template +1 -3
- package/templates/channels/README.md +18 -0
- package/templates/channels/ai-fabrix-icon.jpg +0 -0
- package/templates/channels/chatgpt/install.template.md.hbs +21 -24
- package/templates/channels/chatgpt/integration/README.md +11 -0
- package/templates/channels/chatgpt/integration/application.json +15 -0
- package/templates/channels/chatgpt/integration/chatgpt-system.json +29 -0
- package/templates/channels/chatgpt/integration/env.template +4 -0
- package/templates/channels/microsoft-copilot/install.template.md.hbs +20 -25
- package/templates/channels/microsoft-copilot/integration/README.md +11 -0
- package/templates/channels/microsoft-copilot/integration/application.json +15 -0
- package/templates/channels/microsoft-copilot/integration/env.template +6 -0
- package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +34 -0
- package/templates/channels/slack/install.template.md.hbs +48 -18
- package/templates/channels/slack/integration/README.md +38 -0
- package/templates/channels/slack/integration/application.json +18 -0
- package/templates/channels/slack/integration/env.template +29 -0
- package/templates/channels/slack/integration/slack-datasource-conversations.json +226 -0
- package/templates/channels/slack/integration/slack-datasource-messages.json +269 -0
- package/templates/channels/slack/integration/slack-system.json +86 -0
- package/templates/channels/slack/manifest.template.json.hbs +20 -10
- package/templates/channels/teams-bot/install.template.md.hbs +31 -17
- package/templates/channels/teams-bot/integration/README.md +18 -0
- package/templates/channels/teams-bot/integration/application.json +17 -0
- package/templates/channels/teams-bot/integration/env.template +5 -0
- package/templates/channels/teams-bot/integration/teams-bot-system.json +55 -0
- package/templates/channels/teams-bot/manifest.template.json.hbs +27 -0
- package/templates/channels/web-embed/install.template.md.hbs +16 -26
- package/templates/channels/web-embed/integration/README.md +11 -0
- package/templates/channels/web-embed/integration/application.json +15 -0
- package/templates/channels/web-embed/integration/env.template +4 -0
- package/templates/channels/web-embed/integration/web-embed-system.json +29 -0
- package/templates/openapi/redoc_page.html +86 -0
- package/templates/python/docker-compose.hbs +11 -0
- package/templates/python/requirements.txt +1 -1
- package/templates/typescript/docker-compose.hbs +11 -0
- package/lib/certification/cli-cert-sync-skip.js +0 -21
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CLI normalization for manifest version target and test sync policy (456.17).
|
|
3
|
+
* @author AI Fabrix Team
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const SYNC_MODES = new Set(['auto', 'never', 'force']);
|
|
10
|
+
const VERSION_KEYWORDS = new Set(['latest', 'running']);
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {string|undefined|null} raw
|
|
14
|
+
* @param {string} [defaultValue='latest']
|
|
15
|
+
* @returns {string}
|
|
16
|
+
*/
|
|
17
|
+
function normalizeVersionTarget(raw, defaultValue = 'latest') {
|
|
18
|
+
const value = String(raw ?? defaultValue).trim();
|
|
19
|
+
if (!value) {
|
|
20
|
+
throw new Error('--version is required (latest, running, or explicit version id).');
|
|
21
|
+
}
|
|
22
|
+
const lower = value.toLowerCase();
|
|
23
|
+
if (VERSION_KEYWORDS.has(lower)) {
|
|
24
|
+
return lower;
|
|
25
|
+
}
|
|
26
|
+
if (!/^[a-zA-Z0-9._-]+$/.test(value)) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
'--version must be latest, running, or an explicit version id (letters, numbers, ., _, -).'
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {string|undefined|null} raw
|
|
36
|
+
* @param {string} [defaultValue='auto']
|
|
37
|
+
* @returns {string}
|
|
38
|
+
*/
|
|
39
|
+
function normalizeSyncMode(raw, defaultValue = 'auto') {
|
|
40
|
+
const value = String(raw ?? defaultValue).trim().toLowerCase();
|
|
41
|
+
if (!SYNC_MODES.has(value)) {
|
|
42
|
+
throw new Error('--sync-mode must be auto, never, or force.');
|
|
43
|
+
}
|
|
44
|
+
return value;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Merge versionTarget and syncMode from CLI options into e2eOptions for ValidationRunRequest.
|
|
49
|
+
*
|
|
50
|
+
* @param {Object} cliOptions - Commander-parsed options
|
|
51
|
+
* @param {Object} [e2eOptions={}]
|
|
52
|
+
* @returns {Object}
|
|
53
|
+
*/
|
|
54
|
+
function mergeTestTargetIntoE2eOptions(cliOptions, e2eOptions = {}) {
|
|
55
|
+
const merged = { ...e2eOptions };
|
|
56
|
+
if (cliOptions && cliOptions.version !== undefined && cliOptions.version !== null) {
|
|
57
|
+
merged.versionTarget = normalizeVersionTarget(cliOptions.version);
|
|
58
|
+
} else {
|
|
59
|
+
merged.versionTarget = normalizeVersionTarget(undefined, 'latest');
|
|
60
|
+
}
|
|
61
|
+
if (cliOptions && cliOptions.syncMode !== undefined && cliOptions.syncMode !== null) {
|
|
62
|
+
merged.syncMode = normalizeSyncMode(cliOptions.syncMode);
|
|
63
|
+
} else {
|
|
64
|
+
merged.syncMode = normalizeSyncMode(undefined, 'auto');
|
|
65
|
+
}
|
|
66
|
+
return merged;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = {
|
|
70
|
+
SYNC_MODES,
|
|
71
|
+
VERSION_KEYWORDS,
|
|
72
|
+
normalizeVersionTarget,
|
|
73
|
+
normalizeSyncMode,
|
|
74
|
+
mergeTestTargetIntoE2eOptions
|
|
75
|
+
};
|
|
@@ -19,11 +19,15 @@ function buildMinimalUploadSyncOptions(options = {}) {
|
|
|
19
19
|
verbose: false,
|
|
20
20
|
silentResolve: true,
|
|
21
21
|
syncMode: true,
|
|
22
|
+
skipDataSync: true,
|
|
22
23
|
suppressPipelineSpinner: options.suppressPipelineSpinner === true
|
|
23
24
|
};
|
|
24
25
|
if (options.force === true) {
|
|
25
26
|
out.force = true;
|
|
26
27
|
}
|
|
28
|
+
if (options.suppressSummary === true) {
|
|
29
|
+
out.suppressSummary = true;
|
|
30
|
+
}
|
|
27
31
|
return out;
|
|
28
32
|
}
|
|
29
33
|
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* @version 2.0.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
const { mergeTestTargetIntoE2eOptions, normalizeVersionTarget } = require('./test-target-cli-options');
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* Whether the unified validation request should set includeDebug (any `--debug` or `--debug <level>`).
|
|
9
11
|
* @param {*} debugOpt - Commander `options.debug`
|
|
@@ -60,7 +62,7 @@ function buildE2eOptionsFromCli(options = {}) {
|
|
|
60
62
|
if (options.e2eOptionsExtra && typeof options.e2eOptionsExtra === 'object') {
|
|
61
63
|
Object.assign(e2e, options.e2eOptionsExtra);
|
|
62
64
|
}
|
|
63
|
-
return e2e;
|
|
65
|
+
return mergeTestTargetIntoE2eOptions(options, e2e);
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
/**
|
|
@@ -73,6 +75,8 @@ function buildE2eOptionsFromCli(options = {}) {
|
|
|
73
75
|
* @param {boolean} [params.asyncRun]
|
|
74
76
|
* @param {boolean} [params.includeDebug]
|
|
75
77
|
* @param {boolean} [params.explain]
|
|
78
|
+
* @param {boolean} [params.explainCertification]
|
|
79
|
+
* @param {boolean} [params.explainMetrics]
|
|
76
80
|
* @param {Object} [params.e2eOptions] - Merged with buildE2eOptionsFromCli when both used by caller
|
|
77
81
|
* @returns {import('../api/types/validation-run.types').ValidationRunRequestBody}
|
|
78
82
|
*/
|
|
@@ -85,6 +89,8 @@ function buildExternalDataSourceValidationRequest(params) {
|
|
|
85
89
|
asyncRun,
|
|
86
90
|
includeDebug,
|
|
87
91
|
explain,
|
|
92
|
+
explainCertification,
|
|
93
|
+
explainMetrics,
|
|
88
94
|
e2eOptions
|
|
89
95
|
} = params;
|
|
90
96
|
if (!systemKey || !datasourceKey || !runType) {
|
|
@@ -101,6 +107,8 @@ function buildExternalDataSourceValidationRequest(params) {
|
|
|
101
107
|
if (asyncRun === true) body.asyncRun = true;
|
|
102
108
|
if (includeDebug === true) body.includeDebug = true;
|
|
103
109
|
if (explain === true) body.explain = true;
|
|
110
|
+
if (explainCertification === true) body.explainCertification = true;
|
|
111
|
+
if (explainMetrics === true) body.explainMetrics = true;
|
|
104
112
|
if (e2eOptions && typeof e2eOptions === 'object' && Object.keys(e2eOptions).length > 0) {
|
|
105
113
|
body.e2eOptions = e2eOptions;
|
|
106
114
|
}
|
|
@@ -110,5 +118,6 @@ function buildExternalDataSourceValidationRequest(params) {
|
|
|
110
118
|
module.exports = {
|
|
111
119
|
includeDebugForRequest,
|
|
112
120
|
buildE2eOptionsFromCli,
|
|
113
|
-
buildExternalDataSourceValidationRequest
|
|
121
|
+
buildExternalDataSourceValidationRequest,
|
|
122
|
+
normalizeVersionTarget
|
|
114
123
|
};
|
|
@@ -17,6 +17,7 @@ const { formatValidationErrors } = require('../utils/error-formatter');
|
|
|
17
17
|
const { validateFieldReferences } = require('../datasource/field-reference-validator');
|
|
18
18
|
const { validateAbac } = require('../datasource/abac-validator');
|
|
19
19
|
const { validateManifestRuntimeConfiguration } = require('./runtime-configuration-rules');
|
|
20
|
+
const { validateAppContractSurface } = require('./openapi-contract-surface-validator');
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* Load and normalize external-system + external-datasource schema objects for manifest AJV.
|
|
@@ -223,6 +224,7 @@ function validateDatasourceSystemKeyAlignment(manifest, errors) {
|
|
|
223
224
|
* @async
|
|
224
225
|
* @function validateControllerManifest
|
|
225
226
|
* @param {Object} manifest - Controller manifest object
|
|
227
|
+
* @param {Object} [options] - Optional context (appPath for contract-surface checks)
|
|
226
228
|
* @returns {Promise<Object>} Validation result
|
|
227
229
|
* @throws {Error} If validation fails critically
|
|
228
230
|
*
|
|
@@ -230,7 +232,7 @@ function validateDatasourceSystemKeyAlignment(manifest, errors) {
|
|
|
230
232
|
* const result = await validateControllerManifest(manifest);
|
|
231
233
|
* // Returns: { valid: true, errors: [], warnings: [] }
|
|
232
234
|
*/
|
|
233
|
-
async function validateControllerManifest(manifest) {
|
|
235
|
+
async function validateControllerManifest(manifest, options = {}) {
|
|
234
236
|
if (!manifest || typeof manifest !== 'object') {
|
|
235
237
|
return {
|
|
236
238
|
valid: false,
|
|
@@ -249,6 +251,14 @@ async function validateControllerManifest(manifest) {
|
|
|
249
251
|
validateDatasources(manifest, ajv, externalDatasourceSchema, errors, warnings);
|
|
250
252
|
validateDatasourceSystemKeyAlignment(manifest, errors);
|
|
251
253
|
errors.push(...validateManifestRuntimeConfiguration(manifest));
|
|
254
|
+
if (manifest.type === 'external' && Array.isArray(manifest.dataSources) && manifest.system?.key) {
|
|
255
|
+
const appPath = options.appPath;
|
|
256
|
+
if (typeof appPath === 'string' && appPath) {
|
|
257
|
+
const contract = validateAppContractSurface(appPath, manifest.system.key, manifest.dataSources);
|
|
258
|
+
errors.push(...contract.errors);
|
|
259
|
+
warnings.push(...contract.warnings);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
252
262
|
validateConditionalRequirements(manifest, errors, warnings);
|
|
253
263
|
validateRequiredFields(manifest, errors);
|
|
254
264
|
|
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate that OpenAPI / MCP contract surfaces are meaningful (not dataplane stubs).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Contract surface validation for orchestration vs record datasources
|
|
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
|
+
const { buildOpenApiSpec } = require('../programmatic/openapi-spec');
|
|
14
|
+
const {
|
|
15
|
+
documentKeyToLocalOpenApiPath,
|
|
16
|
+
isProgrammaticOrchestrationSystem,
|
|
17
|
+
specHasComponentSchemas
|
|
18
|
+
} = require('../commands/repair-openapi-export');
|
|
19
|
+
const {
|
|
20
|
+
validateVendorOperationContract,
|
|
21
|
+
findVendorOperation,
|
|
22
|
+
validateOrchestrationDatasourceContracts
|
|
23
|
+
} = require('./openapi-contract-vendor-validation');
|
|
24
|
+
|
|
25
|
+
const JSON_METHODS = new Set(['get', 'post', 'put', 'patch', 'delete', 'head', 'options']);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {Object} ds
|
|
29
|
+
* @returns {boolean}
|
|
30
|
+
*/
|
|
31
|
+
function isServiceContractDatasource(ds) {
|
|
32
|
+
const entity = String(ds?.entityType || '').trim().toLowerCase();
|
|
33
|
+
return entity === 'servicecontract';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {Object} ds
|
|
38
|
+
* @returns {boolean}
|
|
39
|
+
*/
|
|
40
|
+
function isCompositionNoneDatasource(ds) {
|
|
41
|
+
return String(ds?.entityType || '').trim().toLowerCase() === 'none';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {Object} ds
|
|
46
|
+
* @returns {boolean}
|
|
47
|
+
*/
|
|
48
|
+
function hasVendorOpenapiOnManifest(ds) {
|
|
49
|
+
const openapi = ds?.openapi;
|
|
50
|
+
if (!openapi || typeof openapi !== 'object' || openapi.enabled === false) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const operations = openapi.operations;
|
|
54
|
+
if (operations && typeof operations === 'object' && Object.keys(operations).length > 0) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
const documentKey =
|
|
58
|
+
typeof openapi.documentKey === 'string' ? openapi.documentKey.trim() : '';
|
|
59
|
+
return Boolean(documentKey) || openapi.enabled === true;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @deprecated use isServiceContractDatasource — kept for tests importing legacy name
|
|
64
|
+
* @param {Object} ds
|
|
65
|
+
* @returns {boolean}
|
|
66
|
+
*/
|
|
67
|
+
function isOrchestrationDatasource(ds) {
|
|
68
|
+
return isServiceContractDatasource(ds);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @param {Object|undefined} op
|
|
73
|
+
* @returns {boolean}
|
|
74
|
+
*/
|
|
75
|
+
function operationHasRequestOrResponseSchema(op) {
|
|
76
|
+
if (!op || typeof op !== 'object') {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
if (op.requestBody) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
const responses = op.responses;
|
|
83
|
+
if (!responses || typeof responses !== 'object') {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
for (const response of Object.values(responses)) {
|
|
87
|
+
if (response && typeof response === 'object' && response.content) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @param {Object|undefined} paths
|
|
96
|
+
* @returns {boolean}
|
|
97
|
+
*/
|
|
98
|
+
function pathsHaveRequestOrResponseSchemas(paths) {
|
|
99
|
+
if (!paths || typeof paths !== 'object') {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
for (const pathItem of Object.values(paths)) {
|
|
103
|
+
if (!pathItem || typeof pathItem !== 'object') {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
for (const [method, op] of Object.entries(pathItem)) {
|
|
107
|
+
if (!JSON_METHODS.has(method)) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (operationHasRequestOrResponseSchema(op)) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @param {unknown} spec
|
|
120
|
+
* @returns {boolean}
|
|
121
|
+
*/
|
|
122
|
+
function isThinOpenApiSpec(spec) {
|
|
123
|
+
if (!spec || typeof spec !== 'object') {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
if (specHasComponentSchemas(spec)) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
return !pathsHaveRequestOrResponseSchemas(spec.paths);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @param {string} filePath
|
|
134
|
+
* @returns {Object|null}
|
|
135
|
+
*/
|
|
136
|
+
function readJsonIfExists(filePath) {
|
|
137
|
+
if (!filePath || !fs.existsSync(filePath)) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
142
|
+
} catch {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* @param {string} appPath
|
|
149
|
+
* @param {string} systemKey
|
|
150
|
+
* @param {string} documentKey
|
|
151
|
+
* @returns {{ spec: Object|null, localPath: string, fromMemory: boolean }}
|
|
152
|
+
*/
|
|
153
|
+
function resolveVendorOpenApiSpec(appPath, systemKey, documentKey) {
|
|
154
|
+
const localPath = documentKeyToLocalOpenApiPath(appPath, systemKey, documentKey);
|
|
155
|
+
const fromDisk = readJsonIfExists(localPath);
|
|
156
|
+
if (fromDisk) {
|
|
157
|
+
return { spec: fromDisk, localPath, fromMemory: false };
|
|
158
|
+
}
|
|
159
|
+
if (isProgrammaticOrchestrationSystem(systemKey)) {
|
|
160
|
+
const spec = buildOpenApiSpec();
|
|
161
|
+
return { spec, localPath, fromMemory: true };
|
|
162
|
+
}
|
|
163
|
+
return { spec: null, localPath, fromMemory: false };
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @param {Object} ds
|
|
168
|
+
* @param {string} prefix
|
|
169
|
+
* @returns {string[]}
|
|
170
|
+
*/
|
|
171
|
+
function collectServiceContractFieldMappingErrors(ds, prefix) {
|
|
172
|
+
const fieldMappings = ds.fieldMappings;
|
|
173
|
+
const attributes =
|
|
174
|
+
fieldMappings && typeof fieldMappings === 'object' ? fieldMappings.attributes : null;
|
|
175
|
+
const hasAttributes =
|
|
176
|
+
attributes && typeof attributes === 'object' && Object.keys(attributes).length > 0;
|
|
177
|
+
if (hasAttributes) {
|
|
178
|
+
return [];
|
|
179
|
+
}
|
|
180
|
+
return [
|
|
181
|
+
`${prefix}serviceContract requires fieldMappings.attributes — public contract must be testable`
|
|
182
|
+
];
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* @param {Object} ds
|
|
187
|
+
* @param {string} prefix
|
|
188
|
+
* @returns {{ errors: string[], warnings: string[] }}
|
|
189
|
+
*/
|
|
190
|
+
function collectServiceContractExposedIssues(ds, prefix) {
|
|
191
|
+
const errors = [];
|
|
192
|
+
const warnings = [];
|
|
193
|
+
const exposed = ds.exposed;
|
|
194
|
+
const schema = exposed && typeof exposed === 'object' ? exposed.schema : null;
|
|
195
|
+
if (!schema || typeof schema !== 'object' || Object.keys(schema).length === 0) {
|
|
196
|
+
errors.push(`${prefix}serviceContract requires exposed.schema for MCP/REST contract`);
|
|
197
|
+
}
|
|
198
|
+
const profiles = exposed && typeof exposed === 'object' ? exposed.profiles : null;
|
|
199
|
+
if (!profiles || typeof profiles !== 'object' || Object.keys(profiles).length === 0) {
|
|
200
|
+
warnings.push(`${prefix}serviceContract missing exposed.profiles — add default envelope`);
|
|
201
|
+
}
|
|
202
|
+
return { errors, warnings };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @param {Object} ds
|
|
207
|
+
* @param {string} prefix
|
|
208
|
+
* @returns {{ errors: string[], warnings: string[] }}
|
|
209
|
+
*/
|
|
210
|
+
function validateServiceContractDatasourceContracts(ds, prefix) {
|
|
211
|
+
const errors = collectServiceContractFieldMappingErrors(ds, prefix);
|
|
212
|
+
const exposed = collectServiceContractExposedIssues(ds, prefix);
|
|
213
|
+
errors.push(...exposed.errors);
|
|
214
|
+
return { errors, warnings: exposed.warnings };
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* @param {Object} ds
|
|
219
|
+
* @param {string} prefix
|
|
220
|
+
* @returns {{ errors: string[], warnings: string[] }}
|
|
221
|
+
*/
|
|
222
|
+
function validateRecordDatasourceContracts(ds, prefix) {
|
|
223
|
+
const errors = [];
|
|
224
|
+
const warnings = [];
|
|
225
|
+
const caps = ds.capabilities;
|
|
226
|
+
const capList = Array.isArray(caps) ? caps.map((c) => String(c).toLowerCase()) : [];
|
|
227
|
+
const needsExposed = capList.some((c) => ['create', 'update', 'list', 'get'].includes(c));
|
|
228
|
+
const fieldMappings = ds.fieldMappings;
|
|
229
|
+
const attributes =
|
|
230
|
+
fieldMappings && typeof fieldMappings === 'object' ? fieldMappings.attributes : null;
|
|
231
|
+
const hasAttributes =
|
|
232
|
+
attributes && typeof attributes === 'object' && Object.keys(attributes).length > 0;
|
|
233
|
+
if (!hasAttributes) {
|
|
234
|
+
errors.push(
|
|
235
|
+
`${prefix}fieldMappings.attributes is missing or empty — record entities need mapped fields for sync and MCP schemas`
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
const exposed = ds.exposed;
|
|
239
|
+
const profiles = exposed && typeof exposed === 'object' ? exposed.profiles : null;
|
|
240
|
+
const hasProfiles =
|
|
241
|
+
profiles && typeof profiles === 'object' && Object.keys(profiles).length > 0;
|
|
242
|
+
if (needsExposed && !hasProfiles) {
|
|
243
|
+
errors.push(
|
|
244
|
+
`${prefix}exposed.profiles is missing or empty — record entities need exposed schema profiles for MCP/OpenAPI`
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
return { errors, warnings };
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* @param {Object} ds
|
|
252
|
+
* @param {string} prefix
|
|
253
|
+
* @returns {{ errors: string[], warnings: string[] }}
|
|
254
|
+
*/
|
|
255
|
+
function validateNoneDatasourceContract(ds, prefix) {
|
|
256
|
+
const errors = [];
|
|
257
|
+
const warnings = [];
|
|
258
|
+
if (hasVendorOpenapiOnManifest(ds)) {
|
|
259
|
+
warnings.push(
|
|
260
|
+
`${prefix}entityType none must not bind vendor OpenAPI — run repair to migrate to serviceContract`
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
return { errors, warnings };
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* @param {string} documentKey
|
|
268
|
+
* @param {string} prefix
|
|
269
|
+
* @param {string} appPath
|
|
270
|
+
* @param {string} systemKey
|
|
271
|
+
* @param {Map<string, Object|null>} vendorCache
|
|
272
|
+
* @returns {{ errors: string[], warnings: string[] }}
|
|
273
|
+
*/
|
|
274
|
+
function resolveCachedVendorSpec(documentKey, prefix, appPath, systemKey, vendorCache) {
|
|
275
|
+
const errors = [];
|
|
276
|
+
const warnings = [];
|
|
277
|
+
const resolved = resolveVendorOpenApiSpec(appPath, systemKey, documentKey);
|
|
278
|
+
vendorCache.set(documentKey, resolved.spec);
|
|
279
|
+
if (!resolved.spec) {
|
|
280
|
+
errors.push(
|
|
281
|
+
`${prefix}missing vendor OpenAPI at ${resolved.localPath} — run: aifabrix repair ${systemKey} --api`
|
|
282
|
+
);
|
|
283
|
+
return { errors, warnings, spec: null };
|
|
284
|
+
}
|
|
285
|
+
if (isThinOpenApiSpec(resolved.spec)) {
|
|
286
|
+
errors.push(
|
|
287
|
+
`${prefix}vendor OpenAPI "${documentKey}" is a thin stub (no component schemas / body schemas) — run: aifabrix repair ${systemKey} --api`
|
|
288
|
+
);
|
|
289
|
+
return { errors, warnings, spec: null };
|
|
290
|
+
}
|
|
291
|
+
if (resolved.fromMemory) {
|
|
292
|
+
warnings.push(
|
|
293
|
+
`${prefix}vendor OpenAPI "${documentKey}" not on disk; validated from in-memory programmatic spec — run: aifabrix repair ${systemKey} --api to materialize openapi/`
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
return { errors, warnings, spec: resolved.spec };
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* @param {Object} ds
|
|
301
|
+
* @param {string} prefix
|
|
302
|
+
* @param {string} appPath
|
|
303
|
+
* @param {string} systemKey
|
|
304
|
+
* @param {Map<string, Object|null>} vendorCache
|
|
305
|
+
* @returns {{ errors: string[], warnings: string[] }}
|
|
306
|
+
*/
|
|
307
|
+
function validateServiceContractVendorOpenApi(ds, prefix, appPath, systemKey, vendorCache) {
|
|
308
|
+
const errors = [];
|
|
309
|
+
const warnings = [];
|
|
310
|
+
const documentKey =
|
|
311
|
+
typeof ds.openapi?.documentKey === 'string' ? ds.openapi.documentKey.trim() : '';
|
|
312
|
+
if (!documentKey) {
|
|
313
|
+
errors.push(`${prefix}serviceContract with OpenAPI upstream requires openapi.documentKey`);
|
|
314
|
+
return { errors, warnings };
|
|
315
|
+
}
|
|
316
|
+
if (!vendorCache.has(documentKey)) {
|
|
317
|
+
const cached = resolveCachedVendorSpec(documentKey, prefix, appPath, systemKey, vendorCache);
|
|
318
|
+
errors.push(...cached.errors);
|
|
319
|
+
warnings.push(...cached.warnings);
|
|
320
|
+
if (!cached.spec) {
|
|
321
|
+
return { errors, warnings };
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
const vendorSpec = vendorCache.get(documentKey);
|
|
325
|
+
const orch = validateOrchestrationDatasourceContracts(ds, vendorSpec, prefix);
|
|
326
|
+
errors.push(...orch.errors);
|
|
327
|
+
warnings.push(...orch.warnings);
|
|
328
|
+
return { errors, warnings };
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* @param {Object} ds
|
|
333
|
+
* @param {string} appPath
|
|
334
|
+
* @param {string} systemKey
|
|
335
|
+
* @param {Map<string, Object|null>} vendorCache
|
|
336
|
+
* @returns {{ errors: string[], warnings: string[] }}
|
|
337
|
+
*/
|
|
338
|
+
function validateDatasourceContractSurface(ds, appPath, systemKey, vendorCache) {
|
|
339
|
+
const prefix = `Datasource "${ds.key || '(unknown)'}": `;
|
|
340
|
+
if (isCompositionNoneDatasource(ds)) {
|
|
341
|
+
return validateNoneDatasourceContract(ds, prefix);
|
|
342
|
+
}
|
|
343
|
+
if (isServiceContractDatasource(ds)) {
|
|
344
|
+
const sc = validateServiceContractDatasourceContracts(ds, prefix);
|
|
345
|
+
const vendor = validateServiceContractVendorOpenApi(
|
|
346
|
+
ds,
|
|
347
|
+
prefix,
|
|
348
|
+
appPath,
|
|
349
|
+
systemKey,
|
|
350
|
+
vendorCache
|
|
351
|
+
);
|
|
352
|
+
return {
|
|
353
|
+
errors: [...sc.errors, ...vendor.errors],
|
|
354
|
+
warnings: [...sc.warnings, ...vendor.warnings]
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
return validateRecordDatasourceContracts(ds, prefix);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* @param {string} appPath
|
|
362
|
+
* @param {string} systemKey
|
|
363
|
+
* @param {Object[]} datasources
|
|
364
|
+
* @returns {{ errors: string[], warnings: string[] }}
|
|
365
|
+
*/
|
|
366
|
+
function validateAppContractSurface(appPath, systemKey, datasources) {
|
|
367
|
+
const errors = [];
|
|
368
|
+
const warnings = [];
|
|
369
|
+
const vendorCache = new Map();
|
|
370
|
+
for (const ds of datasources || []) {
|
|
371
|
+
if (!ds || typeof ds !== 'object') {
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
const result = validateDatasourceContractSurface(ds, appPath, systemKey, vendorCache);
|
|
375
|
+
errors.push(...result.errors);
|
|
376
|
+
warnings.push(...result.warnings);
|
|
377
|
+
}
|
|
378
|
+
return { errors, warnings };
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* @param {string} filePath
|
|
383
|
+
* @returns {{ appPath: string, systemKey: string }|null}
|
|
384
|
+
*/
|
|
385
|
+
function inferIntegrationContextFromPath(filePath) {
|
|
386
|
+
const normalized = path.normalize(filePath);
|
|
387
|
+
const parts = normalized.split(path.sep);
|
|
388
|
+
const integrationIdx = parts.lastIndexOf('integration');
|
|
389
|
+
if (integrationIdx < 0 || integrationIdx + 1 >= parts.length) {
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
const systemKey = parts[integrationIdx + 1];
|
|
393
|
+
const appPath = parts.slice(0, integrationIdx + 2).join(path.sep);
|
|
394
|
+
return { appPath, systemKey };
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* @param {Object} parsedDatasource
|
|
399
|
+
* @param {string} filePath
|
|
400
|
+
* @returns {{ errors: string[], warnings: string[] }}
|
|
401
|
+
*/
|
|
402
|
+
function validateDatasourceFileContractSurface(parsedDatasource, filePath) {
|
|
403
|
+
const ctx = inferIntegrationContextFromPath(filePath);
|
|
404
|
+
if (!ctx) {
|
|
405
|
+
return { errors: [], warnings: [] };
|
|
406
|
+
}
|
|
407
|
+
return validateDatasourceContractSurface(
|
|
408
|
+
parsedDatasource,
|
|
409
|
+
ctx.appPath,
|
|
410
|
+
ctx.systemKey,
|
|
411
|
+
new Map()
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
module.exports = {
|
|
416
|
+
isOrchestrationDatasource,
|
|
417
|
+
isServiceContractDatasource,
|
|
418
|
+
isCompositionNoneDatasource,
|
|
419
|
+
hasVendorOpenapiOnManifest,
|
|
420
|
+
isThinOpenApiSpec,
|
|
421
|
+
validateAppContractSurface,
|
|
422
|
+
validateDatasourceFileContractSurface,
|
|
423
|
+
validateVendorOperationContract,
|
|
424
|
+
validateServiceContractDatasourceContracts,
|
|
425
|
+
findVendorOperation
|
|
426
|
+
};
|