@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
|
@@ -16,6 +16,19 @@ const { loadConfigFile, writeConfigFile } = require('../utils/config-format');
|
|
|
16
16
|
const { backupIntegrationFile } = require('../utils/integration-file-backup');
|
|
17
17
|
const appConfigResolver = require('../utils/app-config-resolver');
|
|
18
18
|
const { extractRbacFromSystem } = require('./repair-rbac-extract');
|
|
19
|
+
const { toKebabAliasKey } = require('./repair-datasource-auto-rbac');
|
|
20
|
+
const { mergeRbacIntoSystemJson } = require('../generator/external');
|
|
21
|
+
const { bindOpenApiOperationSecurityFromRbac } = require('./repair-datasource-operation-security');
|
|
22
|
+
const {
|
|
23
|
+
ensureNonEmptyPermissionRoles,
|
|
24
|
+
ensureReaderRoleOnReadPermissions
|
|
25
|
+
} = require('./repair-rbac-reader-roles');
|
|
26
|
+
const {
|
|
27
|
+
ensurePlatformRolesOnRbac,
|
|
28
|
+
applyPlatformRolesToPermissions,
|
|
29
|
+
ensureOrchestrationResourceType
|
|
30
|
+
} = require('./repair-rbac-platform-preset');
|
|
31
|
+
const { trackRepairWrite } = require('./repair-changed-files');
|
|
19
32
|
|
|
20
33
|
const DEFAULT_CAPABILITIES = ['list', 'get', 'create', 'update', 'delete'];
|
|
21
34
|
|
|
@@ -26,6 +39,8 @@ function _safeString(v) {
|
|
|
26
39
|
function _normalizeOperationKey(opKey) {
|
|
27
40
|
const s = _safeString(opKey);
|
|
28
41
|
if (!s) return '';
|
|
42
|
+
// Match dataplane autoRbac permission names: lowercase schema-valid camelCase keys.
|
|
43
|
+
if (/^[a-z][a-zA-Z0-9]*$/.test(s)) return s.toLowerCase();
|
|
29
44
|
const withHyphens = s.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
|
|
30
45
|
const cleaned = withHyphens.replace(/[^a-z0-9-]+/g, '-');
|
|
31
46
|
return cleaned.replace(/-+/g, '-').replace(/^-+|-+$/g, '');
|
|
@@ -116,20 +131,39 @@ function _collectManagedResourceTypesFromDatasources(appPath, datasourceFiles) {
|
|
|
116
131
|
return out;
|
|
117
132
|
}
|
|
118
133
|
|
|
119
|
-
function
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
134
|
+
function _registerOpAlias(aliases, rt, opKey, canonicalOp, desired) {
|
|
135
|
+
const canonicalName = `${rt}:${canonicalOp}`;
|
|
136
|
+
desired.add(canonicalName);
|
|
137
|
+
const kebabLegacy = toKebabAliasKey(opKey);
|
|
138
|
+
if (kebabLegacy && kebabLegacy !== canonicalOp) {
|
|
139
|
+
aliases.set(`${rt}:${kebabLegacy}`, canonicalName);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
124
142
|
|
|
125
|
-
|
|
143
|
+
function _collectOpAliasesFromDatasources(appPath, datasourceFiles, desired) {
|
|
126
144
|
const aliases = new Map();
|
|
145
|
+
for (const fileName of datasourceFiles || []) {
|
|
146
|
+
const parsed = _safeLoadDatasource(appPath, fileName);
|
|
147
|
+
if (!parsed || !_hasAutoRbacOps(parsed)) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const rt = _safeString(parsed.resourceType) || 'document';
|
|
151
|
+
for (const opKey of Object.keys(parsed.openapi.operations)) {
|
|
152
|
+
const canonicalOp = _normalizeOperationKey(opKey) || _safeString(opKey);
|
|
153
|
+
if (!canonicalOp) {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
_registerOpAlias(aliases, rt, opKey, canonicalOp, desired);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return aliases;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function _addDesiredNameVariants(desired, aliases) {
|
|
127
163
|
for (const name of desired) {
|
|
128
164
|
const [rt, op] = String(name).split(':');
|
|
129
|
-
if (!rt || !op)
|
|
130
|
-
|
|
131
|
-
if (kebab && `${rt}:${kebab}` !== name) {
|
|
132
|
-
aliases.set(`${rt}:${kebab}`, name);
|
|
165
|
+
if (!rt || !op) {
|
|
166
|
+
continue;
|
|
133
167
|
}
|
|
134
168
|
const lower = `${rt}:${String(op).toLowerCase()}`;
|
|
135
169
|
if (lower !== name) {
|
|
@@ -140,6 +174,17 @@ function _buildDesiredPermissionNames(appPath, datasourceFiles) {
|
|
|
140
174
|
aliases.set(dehyphen, name);
|
|
141
175
|
}
|
|
142
176
|
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function _buildDesiredPermissionNames(appPath, datasourceFiles) {
|
|
180
|
+
const desired = collectPermissionNames(appPath, datasourceFiles);
|
|
181
|
+
if (desired.size === 0) {
|
|
182
|
+
return { desired, managedResourceTypes: new Set(), aliases: new Map() };
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const managedResourceTypes = _collectManagedResourceTypesFromDatasources(appPath, datasourceFiles);
|
|
186
|
+
const aliases = _collectOpAliasesFromDatasources(appPath, datasourceFiles, desired);
|
|
187
|
+
_addDesiredNameVariants(desired, aliases);
|
|
143
188
|
return { desired, managedResourceTypes, aliases };
|
|
144
189
|
}
|
|
145
190
|
|
|
@@ -253,80 +298,31 @@ function ensureDefaultRoles(rbac, systemKey, displayName, changes) {
|
|
|
253
298
|
return true;
|
|
254
299
|
}
|
|
255
300
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
function _pickReaderRoleValue(roleValues, systemKey) {
|
|
273
|
-
return (
|
|
274
|
-
roleValues.find(v => v === `${systemKey}-reader`) ||
|
|
275
|
-
roleValues.find(v => /-reader$/.test(v)) ||
|
|
276
|
-
null
|
|
277
|
-
);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
function _capabilityFromPermissionName(name) {
|
|
281
|
-
if (typeof name !== 'string' || !name.includes(':')) return null;
|
|
282
|
-
return name.split(':')[1] || null;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
function _defaultRolesForCapability(cap, { adminValue, readerValue }) {
|
|
286
|
-
const roles = [];
|
|
287
|
-
if ((cap === 'list' || cap === 'get') && readerValue) roles.push(readerValue);
|
|
288
|
-
if (adminValue) roles.push(adminValue);
|
|
289
|
-
return roles;
|
|
301
|
+
/**
|
|
302
|
+
* @param {Object} opts
|
|
303
|
+
* @returns {boolean}
|
|
304
|
+
*/
|
|
305
|
+
function applyRbacPresetRoles(opts) {
|
|
306
|
+
const { rbac, rbacPreset, systemKey, displayName, appPath, datasourceFiles, changes } = opts;
|
|
307
|
+
if (rbacPreset === 'platform') {
|
|
308
|
+
return (
|
|
309
|
+
ensurePlatformRolesOnRbac(rbac, changes) ||
|
|
310
|
+
applyPlatformRolesToPermissions(rbac, appPath, datasourceFiles, changes)
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
return ensureDefaultRoles(rbac, systemKey, displayName, changes);
|
|
290
314
|
}
|
|
291
315
|
|
|
292
316
|
/**
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
* When roles already exist, new permissions may be added with empty roles (invalid for manifest).
|
|
296
|
-
* Apply a safe default:
|
|
297
|
-
* - list/get -> reader + admin when those roles exist
|
|
298
|
-
* - create/update/delete -> admin when it exists (otherwise first available role)
|
|
299
|
-
*
|
|
300
|
-
* Mutates rbac.
|
|
301
|
-
* @param {Object} rbac - RBAC object (mutated)
|
|
302
|
-
* @param {string} systemKey - System key
|
|
303
|
-
* @param {string[]} changes - Array to append to
|
|
317
|
+
* @param {Object} opts
|
|
304
318
|
* @returns {boolean}
|
|
305
319
|
*/
|
|
306
|
-
function
|
|
307
|
-
const
|
|
308
|
-
if (
|
|
309
|
-
|
|
310
|
-
const adminValue = _pickAdminRoleValue(roleValues, systemKey);
|
|
311
|
-
const readerValue = _pickReaderRoleValue(roleValues, systemKey);
|
|
312
|
-
|
|
313
|
-
let updated = false;
|
|
314
|
-
for (const p of rbac.permissions) {
|
|
315
|
-
if (!p || typeof p !== 'object') continue;
|
|
316
|
-
if (!Array.isArray(p.roles)) p.roles = [];
|
|
317
|
-
if (p.roles.length > 0) continue;
|
|
318
|
-
|
|
319
|
-
const cap = _capabilityFromPermissionName(p.name);
|
|
320
|
-
const defaults = _defaultRolesForCapability(cap, { adminValue, readerValue });
|
|
321
|
-
for (const rv of defaults) {
|
|
322
|
-
if (!p.roles.includes(rv)) p.roles.push(rv);
|
|
323
|
-
}
|
|
324
|
-
if (p.roles.length > 0) {
|
|
325
|
-
changes.push(`RBAC: defaulted empty roles for ${p.name}`);
|
|
326
|
-
updated = true;
|
|
327
|
-
}
|
|
320
|
+
function applyReaderRolesIfNeeded(opts) {
|
|
321
|
+
const { rbac, rbacPreset, appPath, datasourceFiles, systemKey, changes } = opts;
|
|
322
|
+
if (rbacPreset === 'platform') {
|
|
323
|
+
return false;
|
|
328
324
|
}
|
|
329
|
-
return
|
|
325
|
+
return ensureReaderRoleOnReadPermissions(rbac, appPath, datasourceFiles, systemKey, changes);
|
|
330
326
|
}
|
|
331
327
|
|
|
332
328
|
/**
|
|
@@ -341,18 +337,35 @@ function ensureNonEmptyPermissionRoles(rbac, systemKey, changes) {
|
|
|
341
337
|
* @returns {boolean} True if rbac was updated (or would be in dry-run)
|
|
342
338
|
*/
|
|
343
339
|
function mergeRbacFromDatasources(appPath, systemParsed, datasourceFiles, extractRbacFromSystem, options) {
|
|
344
|
-
const { format = 'yaml', dryRun, changes, backupCtx } = options;
|
|
340
|
+
const { format = 'yaml', dryRun, changes, backupCtx, rbacPreset } = options;
|
|
345
341
|
const rbacFormat = format === 'json' ? 'json' : 'yaml';
|
|
346
|
-
const { desired: permissionNames, managedResourceTypes, aliases } = _buildDesiredPermissionNames(
|
|
347
|
-
|
|
342
|
+
const { desired: permissionNames, managedResourceTypes, aliases } = _buildDesiredPermissionNames(
|
|
343
|
+
appPath,
|
|
344
|
+
datasourceFiles
|
|
345
|
+
);
|
|
346
|
+
if (permissionNames.size === 0) {
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
348
349
|
const systemKey = systemParsed?.key || 'system';
|
|
349
350
|
const displayName = systemParsed?.displayName || systemKey;
|
|
350
351
|
const { rbac, rbacPath } = loadOrCreateRbac(appPath, systemParsed, extractRbacFromSystem, rbacFormat);
|
|
351
352
|
let updated = _renameExistingPermissionIfAliasMatches(rbac, aliases, changes);
|
|
352
353
|
updated = addMissingPermissions(rbac, permissionNames, changes) || updated;
|
|
353
354
|
updated = _removeExtraAutoRbacPermissions(rbac, permissionNames, managedResourceTypes, changes) || updated;
|
|
354
|
-
updated =
|
|
355
|
+
updated =
|
|
356
|
+
applyRbacPresetRoles({
|
|
357
|
+
rbac,
|
|
358
|
+
rbacPreset,
|
|
359
|
+
systemKey,
|
|
360
|
+
displayName,
|
|
361
|
+
appPath,
|
|
362
|
+
datasourceFiles,
|
|
363
|
+
changes
|
|
364
|
+
}) || updated;
|
|
355
365
|
updated = ensureNonEmptyPermissionRoles(rbac, systemKey, changes) || updated;
|
|
366
|
+
updated =
|
|
367
|
+
applyReaderRolesIfNeeded({ rbac, rbacPreset, appPath, datasourceFiles, systemKey, changes }) ||
|
|
368
|
+
updated;
|
|
356
369
|
if (updated && !dryRun) {
|
|
357
370
|
backupIntegrationFile(rbacPath, backupCtx);
|
|
358
371
|
writeConfigFile(rbacPath, rbac);
|
|
@@ -386,6 +399,44 @@ function createRbacFromSystemIfNeeded(opts) {
|
|
|
386
399
|
return true;
|
|
387
400
|
}
|
|
388
401
|
|
|
402
|
+
/**
|
|
403
|
+
* Copy roles/permissions from rbac file into *-system.json for dataplane COM publish.
|
|
404
|
+
* @param {string} appPath
|
|
405
|
+
* @param {string} systemFilePath
|
|
406
|
+
* @param {Object} systemParsed
|
|
407
|
+
* @param {boolean} dryRun
|
|
408
|
+
* @param {string[]} changes
|
|
409
|
+
* @param {Object} backupCtx
|
|
410
|
+
* @returns {boolean}
|
|
411
|
+
*/
|
|
412
|
+
function syncRbacFileIntoSystem(appPath, systemFilePath, systemParsed, dryRun, changes, backupCtx) {
|
|
413
|
+
const rbacPath = appConfigResolver.resolveRbacPath(appPath);
|
|
414
|
+
if (!rbacPath || !fs.existsSync(rbacPath)) return false;
|
|
415
|
+
let rbac;
|
|
416
|
+
try {
|
|
417
|
+
rbac = loadConfigFile(rbacPath);
|
|
418
|
+
} catch {
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
const before = JSON.stringify({
|
|
422
|
+
roles: systemParsed.roles || [],
|
|
423
|
+
permissions: systemParsed.permissions || []
|
|
424
|
+
});
|
|
425
|
+
mergeRbacIntoSystemJson(systemParsed, rbac);
|
|
426
|
+
const after = JSON.stringify({
|
|
427
|
+
roles: systemParsed.roles || [],
|
|
428
|
+
permissions: systemParsed.permissions || []
|
|
429
|
+
});
|
|
430
|
+
if (before === after) return false;
|
|
431
|
+
if (!dryRun) {
|
|
432
|
+
backupIntegrationFile(systemFilePath, backupCtx);
|
|
433
|
+
writeConfigFile(systemFilePath, systemParsed);
|
|
434
|
+
trackRepairWrite(systemFilePath, backupCtx);
|
|
435
|
+
}
|
|
436
|
+
changes.push('Synced roles/permissions from rbac file into system manifest');
|
|
437
|
+
return true;
|
|
438
|
+
}
|
|
439
|
+
|
|
389
440
|
/**
|
|
390
441
|
* @param {string} appPath
|
|
391
442
|
* @param {string} systemFilePath
|
|
@@ -395,20 +446,46 @@ function createRbacFromSystemIfNeeded(opts) {
|
|
|
395
446
|
* @returns {{ rbacMigratedFromSystem: boolean, rbacMergeUpdated: boolean }}
|
|
396
447
|
*/
|
|
397
448
|
function maybeRepairRbac(appPath, systemFilePath, systemParsed, datasourceFiles, options) {
|
|
398
|
-
if (!options.rbac)
|
|
399
|
-
|
|
449
|
+
if (!options.rbac) {
|
|
450
|
+
return {
|
|
451
|
+
rbacMigratedFromSystem: false,
|
|
452
|
+
rbacMergeUpdated: false,
|
|
453
|
+
rbacSyncedIntoSystem: false,
|
|
454
|
+
rbacSecurityBound: false
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
const { dryRun, changes, backupCtx, rbacFmt, rbacPreset } = options;
|
|
400
458
|
const rbacMigratedFromSystem = migrateSystemRbacIntoRbacFile(appPath, systemFilePath, systemParsed, {
|
|
401
459
|
dryRun,
|
|
402
460
|
changes,
|
|
403
461
|
backupCtx
|
|
404
462
|
});
|
|
463
|
+
if (rbacPreset === 'platform' && !dryRun) {
|
|
464
|
+
ensureOrchestrationResourceType(appPath, datasourceFiles, changes, backupCtx);
|
|
465
|
+
}
|
|
405
466
|
const rbacMergeUpdated = mergeRbacFromDatasources(appPath, systemParsed, datasourceFiles, extractRbacFromSystem, {
|
|
406
467
|
format: rbacFmt,
|
|
407
468
|
dryRun,
|
|
408
469
|
changes,
|
|
409
|
-
backupCtx
|
|
470
|
+
backupCtx,
|
|
471
|
+
rbacPreset
|
|
410
472
|
});
|
|
411
|
-
|
|
473
|
+
const rbacSyncedIntoSystem = syncRbacFileIntoSystem(
|
|
474
|
+
appPath,
|
|
475
|
+
systemFilePath,
|
|
476
|
+
systemParsed,
|
|
477
|
+
dryRun,
|
|
478
|
+
changes,
|
|
479
|
+
backupCtx
|
|
480
|
+
);
|
|
481
|
+
const rbacSecurityBound = bindOpenApiOperationSecurityFromRbac(
|
|
482
|
+
appPath,
|
|
483
|
+
datasourceFiles,
|
|
484
|
+
dryRun,
|
|
485
|
+
changes,
|
|
486
|
+
backupCtx
|
|
487
|
+
);
|
|
488
|
+
return { rbacMigratedFromSystem, rbacMergeUpdated, rbacSyncedIntoSystem, rbacSecurityBound };
|
|
412
489
|
}
|
|
413
490
|
|
|
414
491
|
module.exports = {
|
|
@@ -20,6 +20,10 @@ const {
|
|
|
20
20
|
ensureExternalIntegrationBlock,
|
|
21
21
|
removeAuthVarsFromConfiguration
|
|
22
22
|
} = require('./repair-system-alignment');
|
|
23
|
+
const {
|
|
24
|
+
repairAuthenticationsArray,
|
|
25
|
+
ensureAuthUsageSlots
|
|
26
|
+
} = require('./repair-authentications-454');
|
|
23
27
|
const {
|
|
24
28
|
isAllowedRepairAuth,
|
|
25
29
|
normalizeRepairAuthOption,
|
|
@@ -80,7 +84,8 @@ function persistSystemFileRepair(ctx, flags) {
|
|
|
80
84
|
flags.authShapeNormalized ||
|
|
81
85
|
flags.systemAuthConfigNormalized ||
|
|
82
86
|
flags.systemDataSourcesAligned ||
|
|
83
|
-
flags.authVarsRemoved
|
|
87
|
+
flags.authVarsRemoved ||
|
|
88
|
+
flags.authenticationsArrayUpdated;
|
|
84
89
|
if (!systemFileUpdated) {
|
|
85
90
|
return false;
|
|
86
91
|
}
|
|
@@ -94,21 +99,60 @@ function persistSystemFileRepair(ctx, flags) {
|
|
|
94
99
|
|
|
95
100
|
/**
|
|
96
101
|
* @param {Object} ctx
|
|
97
|
-
* @returns {{ updated: boolean,
|
|
102
|
+
* @returns {{ updated: boolean, authenticationsArrayUpdated: boolean }}
|
|
98
103
|
*/
|
|
99
|
-
function
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
+
function applyAuthUsageSlotsRepair(ctx) {
|
|
105
|
+
if (!ctx.options?.authWebhook && !ctx.options?.authSync) {
|
|
106
|
+
return { updated: false, authenticationsArrayUpdated: false };
|
|
107
|
+
}
|
|
108
|
+
const slotsResult = ensureAuthUsageSlots(ctx.systemParsed, {
|
|
109
|
+
authWebhook: Boolean(ctx.options.authWebhook),
|
|
110
|
+
authSync: Boolean(ctx.options.authSync),
|
|
111
|
+
systemKey: ctx.systemKey
|
|
112
|
+
});
|
|
113
|
+
if (slotsResult.warnings.length) {
|
|
114
|
+
ctx.warnings.push(...slotsResult.warnings);
|
|
115
|
+
slotsResult.warnings.forEach((msg) => ctx.changes.push(msg));
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
updated: slotsResult.changed,
|
|
119
|
+
authenticationsArrayUpdated: slotsResult.changed
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @param {Object} ctx
|
|
125
|
+
* @returns {{ updated: boolean, authReplaced: boolean, authShapeNormalized: boolean, authenticationsArrayUpdated: boolean }}
|
|
126
|
+
*/
|
|
127
|
+
function runAuthRepairSteps(ctx) {
|
|
104
128
|
const authReplaced = applyAuthMethod(ctx);
|
|
105
|
-
updated = updated || authReplaced;
|
|
106
129
|
const authShapeNormalized = normalizeAuthenticationSchemaShape(
|
|
107
130
|
ctx.systemParsed,
|
|
108
131
|
ctx.systemKey,
|
|
109
132
|
ctx.changes
|
|
110
133
|
);
|
|
111
|
-
|
|
134
|
+
const authArrayResult = repairAuthenticationsArray(ctx.systemParsed);
|
|
135
|
+
let updated = authReplaced || authShapeNormalized;
|
|
136
|
+
let authenticationsArrayUpdated = authArrayResult.changed;
|
|
137
|
+
if (authArrayResult.changed) {
|
|
138
|
+
ctx.changes.push('Normalized legacy authentication to authentications[]');
|
|
139
|
+
updated = true;
|
|
140
|
+
}
|
|
141
|
+
if (authArrayResult.warnings.length) {
|
|
142
|
+
ctx.warnings.push(...authArrayResult.warnings);
|
|
143
|
+
}
|
|
144
|
+
const slotsResult = applyAuthUsageSlotsRepair(ctx);
|
|
145
|
+
updated = updated || slotsResult.updated;
|
|
146
|
+
authenticationsArrayUpdated = authenticationsArrayUpdated || slotsResult.authenticationsArrayUpdated;
|
|
147
|
+
return { updated, authReplaced, authShapeNormalized, authenticationsArrayUpdated };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @param {Object} ctx
|
|
152
|
+
* @param {Object} authFlags
|
|
153
|
+
* @returns {boolean}
|
|
154
|
+
*/
|
|
155
|
+
function persistAuthSystemFileRepair(ctx, authFlags) {
|
|
112
156
|
const systemAuthConfigNormalized = normalizeSystemFileAuthAndConfig(
|
|
113
157
|
ctx.systemParsed, ctx.systemKey, ctx.changes
|
|
114
158
|
);
|
|
@@ -118,14 +162,20 @@ function runRepairSteps(ctx) {
|
|
|
118
162
|
const authVarsRemoved = removeAuthVarsFromConfiguration(
|
|
119
163
|
ctx.systemParsed, ctx.systemKey, ctx.dryRun, ctx.changes
|
|
120
164
|
);
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
authShapeNormalized,
|
|
165
|
+
return persistSystemFileRepair(ctx, {
|
|
166
|
+
...authFlags,
|
|
124
167
|
systemAuthConfigNormalized,
|
|
125
168
|
systemDataSourcesAligned,
|
|
126
169
|
authVarsRemoved
|
|
127
170
|
});
|
|
128
|
-
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @param {Object} ctx
|
|
175
|
+
* @param {Object} bc
|
|
176
|
+
* @returns {{ appKeyFixed: boolean, datasourceKeysFixed: boolean, rbacFileCreated: boolean, envTemplateRepaired: boolean }}
|
|
177
|
+
*/
|
|
178
|
+
function runManifestRepairSteps(ctx, bc) {
|
|
129
179
|
const appKeyFixed = alignAppKeyWithSystem(
|
|
130
180
|
ctx.variables, ctx.systemKey, ctx.systemParsed, ctx.changes
|
|
131
181
|
);
|
|
@@ -144,14 +194,29 @@ function runRepairSteps(ctx) {
|
|
|
144
194
|
const envTemplateRepaired = repairEnvTemplate(
|
|
145
195
|
ctx.appPath, ctx.systemParsed, ctx.systemKey, ctx.dryRun, ctx.changes, bc
|
|
146
196
|
);
|
|
147
|
-
|
|
197
|
+
return { appKeyFixed, datasourceKeysFixed, rbacFileCreated, envTemplateRepaired };
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* @param {Object} ctx
|
|
202
|
+
* @returns {{ updated: boolean, appKeyFixed: boolean, datasourceKeysFixed: boolean, rbacFileCreated: boolean, envTemplateRepaired: boolean }}
|
|
203
|
+
*/
|
|
204
|
+
function runRepairSteps(ctx) {
|
|
205
|
+
const bc = ctx.backupCtx;
|
|
206
|
+
let updated = ensureExternalIntegrationBlock(
|
|
207
|
+
ctx.variables, ctx.systemFiles, ctx.datasourceFiles, ctx.changes
|
|
208
|
+
);
|
|
209
|
+
const authResult = runAuthRepairSteps(ctx);
|
|
210
|
+
updated = updated || authResult.updated;
|
|
211
|
+
const systemFileUpdated = persistAuthSystemFileRepair(ctx, authResult);
|
|
212
|
+
updated = updated || systemFileUpdated;
|
|
213
|
+
const manifestResult = runManifestRepairSteps(ctx, bc);
|
|
214
|
+
updated = updated || manifestResult.appKeyFixed || manifestResult.datasourceKeysFixed
|
|
215
|
+
|| manifestResult.rbacFileCreated || manifestResult.envTemplateRepaired;
|
|
148
216
|
auditRepairAuthenticationWarnings(ctx.systemParsed, ctx.warnings);
|
|
149
217
|
return {
|
|
150
218
|
updated,
|
|
151
|
-
|
|
152
|
-
datasourceKeysFixed,
|
|
153
|
-
rbacFileCreated,
|
|
154
|
-
envTemplateRepaired
|
|
219
|
+
...manifestResult
|
|
155
220
|
};
|
|
156
221
|
}
|
|
157
222
|
|
|
@@ -17,6 +17,7 @@ function _safeString(v) {
|
|
|
17
17
|
function _normalizeOperationKey(opKey) {
|
|
18
18
|
const s = _safeString(opKey);
|
|
19
19
|
if (!s) return '';
|
|
20
|
+
if (/^[a-z][a-zA-Z0-9]*$/.test(s)) return s.toLowerCase();
|
|
20
21
|
const withHyphens = s.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
|
|
21
22
|
const cleaned = withHyphens.replace(/[^a-z0-9-]+/g, '-');
|
|
22
23
|
return cleaned.replace(/-+/g, '-').replace(/^-+|-+$/g, '');
|
package/lib/commands/repair.js
CHANGED
|
@@ -51,7 +51,7 @@ async function validateAndResolveRepairPaths(appName, options) {
|
|
|
51
51
|
if (authOption !== undefined && authOption !== null && typeof authOption !== 'string') {
|
|
52
52
|
throw new Error('Option --auth must be a string');
|
|
53
53
|
}
|
|
54
|
-
const { appPath, isExternal } = await detectAppType(appName);
|
|
54
|
+
const { appPath, isExternal } = await detectAppType(appName, options);
|
|
55
55
|
if (!isExternal) throw new Error(`App '${appName}' is not an external integration`);
|
|
56
56
|
const configPath = resolveApplicationConfigPath(appPath);
|
|
57
57
|
if (!fs.existsSync(configPath)) throw new Error(`Application config not found: ${configPath}`);
|
|
@@ -60,7 +60,7 @@ const RESOURCE_TYPE_CREATE_HELP_AFTER = `
|
|
|
60
60
|
|
|
61
61
|
Examples:
|
|
62
62
|
$ aifabrix resource-type create --key customer --display-name "Customer"
|
|
63
|
-
$ aifabrix resource-type create --key deal --display-name "Deal" --category business --default-risk-level medium
|
|
63
|
+
$ aifabrix resource-type create --key deal --display-name "Deal" --category business --default-risk-level medium --domain sales
|
|
64
64
|
$ aifabrix resource-type create --file ./customer.json
|
|
65
65
|
|
|
66
66
|
`;
|
|
@@ -145,10 +145,14 @@ function buildCreatePayload(options) {
|
|
|
145
145
|
if (options.category) payload.category = options.category;
|
|
146
146
|
if (options.defaultRiskLevel) payload.defaultRiskLevel = options.defaultRiskLevel;
|
|
147
147
|
if (options.status) payload.status = options.status;
|
|
148
|
+
if (options.domain) payload.domain = options.domain;
|
|
148
149
|
payload.key = requireResourceTypeKey(payload.key);
|
|
149
150
|
if (!payload.displayName) {
|
|
150
151
|
throw new Error('displayName is required (--display-name <name> or in --file).');
|
|
151
152
|
}
|
|
153
|
+
if (!payload.domain) {
|
|
154
|
+
throw new Error('domain is required (--domain <domain> or in --file).');
|
|
155
|
+
}
|
|
152
156
|
return payload;
|
|
153
157
|
}
|
|
154
158
|
|
|
@@ -224,6 +228,10 @@ function setupResourceTypeCreateCommand(rt) {
|
|
|
224
228
|
)
|
|
225
229
|
.option('--default-risk-level <level>', 'low | medium | high | critical')
|
|
226
230
|
.option('--status <status>', 'draft | active | deprecated | retired')
|
|
231
|
+
.option(
|
|
232
|
+
'--domain <domain>',
|
|
233
|
+
'sales | finance | people | collaboration | content | operations | governance | platform'
|
|
234
|
+
)
|
|
227
235
|
.action(async(options) => {
|
|
228
236
|
try {
|
|
229
237
|
const { controllerUrl, authConfig } = await resolveControllerAndAuth(options);
|
|
@@ -232,13 +240,20 @@ function setupResourceTypeCreateCommand(rt) {
|
|
|
232
240
|
const row = unwrapControllerData(out.response);
|
|
233
241
|
const category = row.category || payload.category || 'business';
|
|
234
242
|
const risk = row.defaultRiskLevel || payload.defaultRiskLevel || 'medium';
|
|
243
|
+
const domain = row.domain || payload.domain || '—';
|
|
235
244
|
if (out.created) {
|
|
236
245
|
logger.log(
|
|
237
|
-
formatSuccessLine(
|
|
246
|
+
formatSuccessLine(
|
|
247
|
+
`Resource type created: ${row.key} (category: ${category}, risk: ${risk}, domain: ${domain})`
|
|
248
|
+
)
|
|
238
249
|
);
|
|
239
250
|
return;
|
|
240
251
|
}
|
|
241
|
-
logger.log(
|
|
252
|
+
logger.log(
|
|
253
|
+
formatSuccessLine(
|
|
254
|
+
`Resource type exists: ${row.key} (category: ${category}, risk: ${risk}, domain: ${domain})`
|
|
255
|
+
)
|
|
256
|
+
);
|
|
242
257
|
logger.log(infoLine('No changes were needed.'));
|
|
243
258
|
} catch (e) {
|
|
244
259
|
logger.error(formatBlockingError(e.message));
|
|
@@ -265,6 +280,7 @@ function setupResourceTypeGetCommand(rt) {
|
|
|
265
280
|
logger.log(headerKeyValue('Display:', row.displayName || '—'));
|
|
266
281
|
logger.log(headerKeyValue('Category:', row.category || '—'));
|
|
267
282
|
logger.log(headerKeyValue('Default risk:', row.defaultRiskLevel || '—'));
|
|
283
|
+
logger.log(headerKeyValue('Domain:', row.domain || '—'));
|
|
268
284
|
logger.log(headerKeyValue('Status:', row.status || '—'));
|
|
269
285
|
if (row.description) {
|
|
270
286
|
logger.log(headerKeyValue('Description:', row.description));
|
|
@@ -282,6 +298,49 @@ function setupResourceTypeGetCommand(rt) {
|
|
|
282
298
|
* @param {string} environment
|
|
283
299
|
* @param {string} controllerUrl
|
|
284
300
|
*/
|
|
301
|
+
const RESOURCE_TYPE_LIST_COLUMNS = {
|
|
302
|
+
key: 22,
|
|
303
|
+
display: 24,
|
|
304
|
+
category: 14,
|
|
305
|
+
domain: 14,
|
|
306
|
+
risk: 8,
|
|
307
|
+
status: 10
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
function resourceTypeListSeparatorLength(columns) {
|
|
311
|
+
return (
|
|
312
|
+
columns.key +
|
|
313
|
+
columns.display +
|
|
314
|
+
columns.category +
|
|
315
|
+
columns.domain +
|
|
316
|
+
columns.risk +
|
|
317
|
+
columns.status
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function logResourceTypeListHeader(columns) {
|
|
322
|
+
const keyCol = 'Key'.padEnd(columns.key);
|
|
323
|
+
const displayCol = 'Display'.padEnd(columns.display);
|
|
324
|
+
const categoryCol = 'Category'.padEnd(columns.category);
|
|
325
|
+
const domainCol = 'Domain'.padEnd(columns.domain);
|
|
326
|
+
const riskCol = 'Risk'.padEnd(columns.risk);
|
|
327
|
+
const statusCol = 'Status'.padEnd(columns.status);
|
|
328
|
+
logger.log(chalk.gray(`${keyCol}${displayCol}${categoryCol}${domainCol}${riskCol}${statusCol}`));
|
|
329
|
+
logger.log(chalk.gray('-'.repeat(resourceTypeListSeparatorLength(columns))));
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function logResourceTypeListRows(items, columns) {
|
|
333
|
+
items.forEach((d) => {
|
|
334
|
+
const key = (d?.key ?? '—').toString().padEnd(columns.key);
|
|
335
|
+
const displayName = (d?.displayName ?? '—').toString().padEnd(columns.display);
|
|
336
|
+
const category = (d?.category ?? '—').toString().padEnd(columns.category);
|
|
337
|
+
const domain = (d?.domain ?? '—').toString().padEnd(columns.domain);
|
|
338
|
+
const risk = (d?.defaultRiskLevel ?? '—').toString().padEnd(columns.risk);
|
|
339
|
+
const status = (d?.status ?? '—').toString().padEnd(columns.status);
|
|
340
|
+
logger.log(`${key}${displayName}${category}${domain}${risk}${status}`);
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
285
344
|
function displayResourceTypeList(items, environment, controllerUrl) {
|
|
286
345
|
logger.log(
|
|
287
346
|
chalk.bold(`\n🏷️ Resource types in ${environment} environment (${controllerUrl}):\n`)
|
|
@@ -291,29 +350,9 @@ function displayResourceTypeList(items, environment, controllerUrl) {
|
|
|
291
350
|
return;
|
|
292
351
|
}
|
|
293
352
|
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
const RISK_WIDTH = 10;
|
|
298
|
-
const STATUS_WIDTH = 12;
|
|
299
|
-
const SEP_LEN = KEY_WIDTH + DISPLAY_WIDTH + CATEGORY_WIDTH + RISK_WIDTH + STATUS_WIDTH;
|
|
300
|
-
|
|
301
|
-
const keyCol = 'Key'.padEnd(KEY_WIDTH);
|
|
302
|
-
const displayCol = 'Display'.padEnd(DISPLAY_WIDTH);
|
|
303
|
-
const categoryCol = 'Category'.padEnd(CATEGORY_WIDTH);
|
|
304
|
-
const riskCol = 'Risk'.padEnd(RISK_WIDTH);
|
|
305
|
-
const statusCol = 'Status'.padEnd(STATUS_WIDTH);
|
|
306
|
-
logger.log(chalk.gray(`${keyCol}${displayCol}${categoryCol}${riskCol}${statusCol}`));
|
|
307
|
-
logger.log(chalk.gray('-'.repeat(SEP_LEN)));
|
|
308
|
-
|
|
309
|
-
items.forEach((d) => {
|
|
310
|
-
const key = (d?.key ?? '—').toString().padEnd(KEY_WIDTH);
|
|
311
|
-
const displayName = (d?.displayName ?? '—').toString().padEnd(DISPLAY_WIDTH);
|
|
312
|
-
const category = (d?.category ?? '—').toString().padEnd(CATEGORY_WIDTH);
|
|
313
|
-
const risk = (d?.defaultRiskLevel ?? '—').toString().padEnd(RISK_WIDTH);
|
|
314
|
-
const status = (d?.status ?? '—').toString().padEnd(STATUS_WIDTH);
|
|
315
|
-
logger.log(`${key}${displayName}${category}${risk}${status}`);
|
|
316
|
-
});
|
|
353
|
+
const columns = RESOURCE_TYPE_LIST_COLUMNS;
|
|
354
|
+
logResourceTypeListHeader(columns);
|
|
355
|
+
logResourceTypeListRows(items, columns);
|
|
317
356
|
logger.log('');
|
|
318
357
|
}
|
|
319
358
|
|