@aifabrix/builder 2.49.1 → 2.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (413) hide show
  1. package/.cursor/process/README.md +9 -0
  2. package/.cursor/rules/deploy-rules/docker-image-ip-policy.mdc +49 -0
  3. package/.cursor/rules/plan-rules/application-lifecycle.mdc +30 -0
  4. package/.cursor/rules/plan-rules/plan-frontmatter.mdc +35 -0
  5. package/.cursor/rules/plan-rules/plan-lifecycle.mdc +31 -0
  6. package/.cursor/rules/plan-rules/plan-validation-gate.mdc +34 -0
  7. package/.cursor/skills/README.md +1 -0
  8. package/.dockerignore +52 -0
  9. package/.eslintignore +22 -0
  10. package/README.md +2 -0
  11. package/bin/builder-api-cleanup.js +26 -0
  12. package/bin/builder-api-nest.js +10 -0
  13. package/bin/builder-api-spike.js +19 -0
  14. package/enterprise-knowledge/README.md +50 -0
  15. package/enterprise-knowledge/enterprise-integration-lifecycle/README.md +22 -0
  16. package/enterprise-knowledge/enterprise-integration-lifecycle/application.json +15 -0
  17. package/enterprise-knowledge/enterprise-integration-lifecycle/deploy.js +69 -0
  18. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-deploy.json +52 -0
  19. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-system.json +29 -0
  20. package/enterprise-knowledge/enterprise-integration-lifecycle/env.template +2 -0
  21. package/integration/README.md +81 -0
  22. package/integration/github/README.md +53 -0
  23. package/integration/github/application.json +21 -0
  24. package/integration/github/deploy.js +72 -0
  25. package/integration/github/env.template +11 -0
  26. package/integration/github/github-datasource-issue-comments.json +239 -0
  27. package/integration/github/github-datasource-issues.json +399 -0
  28. package/integration/github/github-datasource-repository.json +354 -0
  29. package/integration/github/github-deploy.json +1202 -0
  30. package/integration/github/github-system.json +82 -0
  31. package/integration/hubspot-test/README.md +1 -1
  32. package/jest.isolated-projects.js +31 -1
  33. package/jest.projects.js +87 -1
  34. package/lib/api/dev-server-https.js +1 -1
  35. package/lib/api/dev.api.js +1 -0
  36. package/lib/api/enterprise-knowledge.api.js +63 -0
  37. package/lib/api/evidence.api.js +172 -0
  38. package/lib/api/external-systems.api.js +8 -2
  39. package/lib/api/host-ops.api.js +69 -0
  40. package/lib/api/resource-types.api.js +1 -0
  41. package/lib/api/types/enterprise-knowledge.types.js +46 -0
  42. package/lib/api/types/evidence.types.js +67 -0
  43. package/lib/api/types/resource-types.types.js +2 -0
  44. package/lib/app/controller-application-filter.js +36 -0
  45. package/lib/app/deploy.js +1 -1
  46. package/lib/app/list-external-systems.js +130 -0
  47. package/lib/app/list.js +20 -8
  48. package/lib/app/run.js +3 -1
  49. package/lib/app/show-display.js +8 -3
  50. package/lib/app/show-online.js +178 -0
  51. package/lib/app/show.js +37 -88
  52. package/lib/build/builder-api-docker-staging.js +47 -0
  53. package/lib/build/miso-controller-npm-sdk-guard.js +2 -2
  54. package/lib/build/standard-docker-build.js +2 -0
  55. package/lib/certification/post-unified-cert-sync.js +4 -31
  56. package/lib/certification/sync-after-external-command.js +0 -1
  57. package/lib/certification/sync-system-certification.js +0 -3
  58. package/lib/channels/add-channel.js +40 -34
  59. package/lib/channels/approval-guides/chatgpt.js +33 -0
  60. package/lib/channels/approval-guides/credential-portal.js +38 -0
  61. package/lib/channels/approval-guides/index.js +110 -0
  62. package/lib/channels/approval-guides/microsoft-copilot.js +34 -0
  63. package/lib/channels/approval-guides/slack.js +34 -0
  64. package/lib/channels/approval-guides/teams-bot.js +35 -0
  65. package/lib/channels/approval-guides/web-embed.js +32 -0
  66. package/lib/channels/channel-approval-guide.js +11 -0
  67. package/lib/channels/channel-artifact-generator.js +16 -4
  68. package/lib/channels/channel-audit.js +3 -0
  69. package/lib/channels/channel-auth-context.js +1 -1
  70. package/lib/channels/channel-description.js +59 -0
  71. package/lib/channels/channel-integration-generator.js +13 -230
  72. package/lib/channels/channel-integration-template.js +94 -0
  73. package/lib/channels/channel-runtime-resolver.js +43 -3
  74. package/lib/channels/channel-status-display.js +66 -26
  75. package/lib/channels/channel-targets.js +3 -3
  76. package/lib/cli/index.js +27 -3
  77. package/lib/cli/infra-guided.js +5 -1
  78. package/lib/cli/setup-app-external-create.js +111 -0
  79. package/lib/cli/setup-app.help.js +1 -1
  80. package/lib/cli/setup-app.js +38 -125
  81. package/lib/cli/setup-app.test-commands.js +26 -52
  82. package/lib/cli/setup-certification-commands.js +4 -4
  83. package/lib/cli/setup-certification.help.js +9 -9
  84. package/lib/cli/setup-dev-path-commands.js +24 -0
  85. package/lib/cli/setup-dev.js +115 -16
  86. package/lib/cli/setup-external-system-help.js +4 -6
  87. package/lib/cli/setup-external-system.js +58 -52
  88. package/lib/cli/setup-infra-up-builder-api-action.js +64 -0
  89. package/lib/cli/setup-infra-up-platform-action.js +3 -1
  90. package/lib/cli/setup-infra.js +15 -0
  91. package/lib/cli/setup-list.js +43 -0
  92. package/lib/cli/setup-utility-repair.js +26 -7
  93. package/lib/cli/setup-utility.js +5 -3
  94. package/lib/commands/app.js +15 -43
  95. package/lib/commands/channel-add-setup.js +110 -0
  96. package/lib/commands/channel.js +42 -8
  97. package/lib/commands/datasource-sync-display.js +96 -0
  98. package/lib/commands/datasource-sync-policy.js +210 -0
  99. package/lib/commands/datasource-test-trust-cli.js +6 -6
  100. package/lib/commands/datasource-unified-test-cli.js +2 -1
  101. package/lib/commands/datasource-unified-test-cli.options.js +33 -23
  102. package/lib/commands/deploy-gate-failure-details.js +163 -0
  103. package/lib/commands/deploy-gate-orchestrator.js +322 -0
  104. package/lib/commands/dev-cli-handlers.js +64 -61
  105. package/lib/commands/dev-host-ops-params.js +91 -0
  106. package/lib/commands/dev-host-ops-poll.js +111 -0
  107. package/lib/commands/dev-host-ops.js +252 -0
  108. package/lib/commands/dev-init.js +3 -1
  109. package/lib/commands/enterprise-knowledge.js +284 -0
  110. package/lib/commands/evidence-cli-leaves.js +250 -0
  111. package/lib/commands/evidence.js +51 -0
  112. package/lib/commands/governance-cli-shared.js +2 -2
  113. package/lib/commands/governance-command-action.js +2 -2
  114. package/lib/commands/governance-fixture-subjects.js +85 -0
  115. package/lib/commands/governance.js +1 -1
  116. package/lib/commands/lifecycle-command-action.js +2 -2
  117. package/lib/commands/lifecycle-external.js +3 -3
  118. package/lib/commands/manifest-cli-auth.js +29 -0
  119. package/lib/commands/manifest-cli-commands.js +170 -0
  120. package/lib/commands/manifest-cli-integration-path.js +63 -0
  121. package/lib/commands/manifest.js +21 -0
  122. package/lib/commands/protection-cli-leaves.js +3 -3
  123. package/lib/commands/repair-auth-apply.js +15 -1
  124. package/lib/commands/repair-authentications-454.js +169 -0
  125. package/lib/commands/repair-capability-openapi-warnings.js +126 -0
  126. package/lib/commands/repair-datasource-apply.js +135 -0
  127. package/lib/commands/repair-datasource-auto-rbac.js +62 -1
  128. package/lib/commands/repair-datasource-http-service-contract.js +239 -0
  129. package/lib/commands/repair-datasource-operation-security.js +180 -0
  130. package/lib/commands/repair-datasource-run.js +7 -2
  131. package/lib/commands/repair-datasource-sync-operations.js +177 -0
  132. package/lib/commands/repair-datasource-webhooks-sync-bridge.js +133 -0
  133. package/lib/commands/repair-datasource.js +12 -68
  134. package/lib/commands/repair-env-template.js +11 -1
  135. package/lib/commands/repair-external-run.js +121 -31
  136. package/lib/commands/repair-internal.js +1 -1
  137. package/lib/commands/repair-openapi-export.js +156 -0
  138. package/lib/commands/repair-openapi-sync.js +19 -2
  139. package/lib/commands/repair-orchestration-datasource-split.js +259 -0
  140. package/lib/commands/repair-persist.js +22 -1
  141. package/lib/commands/repair-rbac-platform-preset.js +204 -0
  142. package/lib/commands/repair-rbac-reader-roles.js +191 -0
  143. package/lib/commands/repair-rbac.js +163 -86
  144. package/lib/commands/repair-steps.js +83 -18
  145. package/lib/commands/repair-system-permissions.js +1 -0
  146. package/lib/commands/repair.js +1 -1
  147. package/lib/commands/resource-type.js +65 -26
  148. package/lib/commands/run-post-publish-data-sync.js +68 -0
  149. package/lib/commands/setup-modes.js +1 -1
  150. package/lib/commands/test-e2e-external.js +21 -8
  151. package/lib/commands/test-governance-cli-options.js +2 -2
  152. package/lib/commands/test-trust-cli-options.js +2 -2
  153. package/lib/commands/up-builder-api-bootstrap.js +71 -0
  154. package/lib/commands/up-builder-api-provision.js +241 -0
  155. package/lib/commands/up-builder-api.js +88 -0
  156. package/lib/commands/up-common.js +25 -1
  157. package/lib/commands/upload-credential-push-log.js +117 -0
  158. package/lib/commands/upload-data-sync-finalize.js +60 -0
  159. package/lib/commands/upload-probe.js +66 -0
  160. package/lib/commands/upload-publish-context.js +4 -1
  161. package/lib/commands/upload-sidecar-followups.js +55 -27
  162. package/lib/commands/upload.js +116 -157
  163. package/lib/commands/verify-governance-combined-external.js +1 -1
  164. package/lib/commands/verify-governance-db.js +2 -2
  165. package/lib/commands/verify-operations-command-action.js +2 -2
  166. package/lib/commands/verify-operations-step-plan.js +2 -2
  167. package/lib/commands/verify-operations-steps.js +2 -2
  168. package/lib/commands/verify-trust-command-action.js +1 -1
  169. package/lib/commands/wizard-core.js +1 -1
  170. package/lib/commands/wizard-headless.js +2 -1
  171. package/lib/core/admin-secrets.js +2 -6
  172. package/lib/core/secrets-env-content.js +10 -4
  173. package/lib/core/secrets-env-write.js +2 -13
  174. package/lib/datasource/agent-trust-run.js +3 -3
  175. package/lib/datasource/deploy.js +3 -1
  176. package/lib/datasource/test-e2e.js +6 -1
  177. package/lib/datasource/unified-validation-run-body.js +4 -1
  178. package/lib/datasource/unified-validation-run.js +1 -1
  179. package/lib/deployment/deploy-poll-ui.js +73 -12
  180. package/lib/deployment/deployer-poll-run.js +113 -0
  181. package/lib/deployment/deployer.js +17 -87
  182. package/lib/evidence/dataplane-context.js +21 -0
  183. package/lib/evidence/evidence-display.js +78 -0
  184. package/lib/evidence/evidence-service.js +392 -0
  185. package/lib/external-system/deploy.js +290 -112
  186. package/lib/external-system/download.js +7 -3
  187. package/lib/external-system/test-execution.js +1 -1
  188. package/lib/external-system/test-system-level.js +8 -10
  189. package/lib/external-system/test.js +12 -6
  190. package/lib/generator/deploy-script.js +73 -0
  191. package/lib/generator/external.js +2 -1
  192. package/lib/generator/index.js +17 -2
  193. package/lib/generator/wizard.js +3 -36
  194. package/lib/internal/fs-real-sync.js +22 -1
  195. package/lib/internal/node-fs.js +2 -0
  196. package/lib/lifecycle/lifecycle-governance-options.js +1 -1
  197. package/lib/lifecycle/verify-step-progress.js +1 -1
  198. package/lib/programmatic/access-log.js +26 -0
  199. package/lib/programmatic/auth-config.js +44 -0
  200. package/lib/programmatic/bearer-auth.js +176 -0
  201. package/lib/programmatic/builder-api-request.js +175 -0
  202. package/lib/programmatic/builder-api-route-dispatch.js +82 -0
  203. package/lib/programmatic/builder-api-runtime-config.js +42 -0
  204. package/lib/programmatic/builder-api-server.js +230 -0
  205. package/lib/programmatic/builder-help-authentication-catalog.js +282 -0
  206. package/lib/programmatic/builder-help-connected-system-ui.js +266 -0
  207. package/lib/programmatic/builder-help-enterprise-sync-fabrix.js +60 -0
  208. package/lib/programmatic/builder-help-envelope.js +36 -0
  209. package/lib/programmatic/builder-help-fixtures.js +200 -0
  210. package/lib/programmatic/builder-help-governance.js +172 -0
  211. package/lib/programmatic/builder-help-schema-catalog.js +92 -0
  212. package/lib/programmatic/builder-help.js +361 -0
  213. package/lib/programmatic/capability-registry.js +77 -0
  214. package/lib/programmatic/command-options.js +32 -0
  215. package/lib/programmatic/enterprise-mcp-client.js +98 -0
  216. package/lib/programmatic/http-problem-details.js +99 -0
  217. package/lib/programmatic/http-route-match.js +40 -0
  218. package/lib/programmatic/idempotency-cache.js +69 -0
  219. package/lib/programmatic/index.js +53 -0
  220. package/lib/programmatic/integration-path-scope.js +39 -0
  221. package/lib/programmatic/log-redaction.js +66 -0
  222. package/lib/programmatic/manifest-get-section.js +146 -0
  223. package/lib/programmatic/manifest-patch-section.js +252 -0
  224. package/lib/programmatic/manifest-repair.js +122 -0
  225. package/lib/programmatic/manifest-section-dependency-graph.js +160 -0
  226. package/lib/programmatic/manifest-section-io.js +225 -0
  227. package/lib/programmatic/manifest-section-quality.js +171 -0
  228. package/lib/programmatic/manifest-section-registry-data.js +269 -0
  229. package/lib/programmatic/manifest-section-registry.js +205 -0
  230. package/lib/programmatic/nest-http-bridge.js +34 -0
  231. package/lib/programmatic/openapi-component-schemas.js +68 -0
  232. package/lib/programmatic/openapi-description-enricher.js +117 -0
  233. package/lib/programmatic/openapi-descriptions.js +190 -0
  234. package/lib/programmatic/openapi-docs-serving.js +123 -0
  235. package/lib/programmatic/openapi-help-schemas.js +63 -0
  236. package/lib/programmatic/openapi-manifest-schemas.js +141 -0
  237. package/lib/programmatic/openapi-operation-bindings.js +274 -0
  238. package/lib/programmatic/openapi-request-schemas.js +155 -0
  239. package/lib/programmatic/openapi-result-schemas.js +476 -0
  240. package/lib/programmatic/openapi-schema-descriptions-certify.js +139 -0
  241. package/lib/programmatic/openapi-schema-descriptions-core.js +159 -0
  242. package/lib/programmatic/openapi-schema-descriptions-help.js +40 -0
  243. package/lib/programmatic/openapi-schema-descriptions-manifest.js +143 -0
  244. package/lib/programmatic/openapi-schema-descriptions-mcp.js +118 -0
  245. package/lib/programmatic/openapi-schema-descriptions-operations.js +281 -0
  246. package/lib/programmatic/openapi-schema-helpers.js +93 -0
  247. package/lib/programmatic/openapi-spec.js +203 -0
  248. package/lib/programmatic/orchestration-openapi-meta.js +159 -0
  249. package/lib/programmatic/platform-rbac-catalog.js +90 -0
  250. package/lib/programmatic/request-timeout.js +53 -0
  251. package/lib/programmatic/route-handler-map.js +143 -0
  252. package/lib/programmatic/route-handlers-context.js +29 -0
  253. package/lib/programmatic/route-handlers.js +33 -0
  254. package/lib/programmatic/run-certify.js +57 -0
  255. package/lib/programmatic/run-enterprise-mcp.js +32 -0
  256. package/lib/programmatic/run-lifecycle.js +29 -0
  257. package/lib/programmatic/run-repair.js +41 -0
  258. package/lib/programmatic/run-repository-emcp.js +54 -0
  259. package/lib/programmatic/run-template-workspace.js +61 -0
  260. package/lib/programmatic/run-test.js +49 -0
  261. package/lib/programmatic/run-upload.js +63 -0
  262. package/lib/programmatic/run-validate.js +53 -0
  263. package/lib/programmatic/run-wizard.js +40 -0
  264. package/lib/programmatic/system-key.js +48 -0
  265. package/lib/programmatic/wizard-config-normalize.js +118 -0
  266. package/lib/programmatic/workspace-cleanup.js +128 -0
  267. package/lib/programmatic/workspace-context.js +145 -0
  268. package/lib/programmatic/workspace-lock.js +75 -0
  269. package/lib/programmatic/workspace-meta.js +64 -0
  270. package/lib/programmatic/workspace-ops.js +149 -0
  271. package/lib/protection/run-commands-upload-sync.js +35 -0
  272. package/lib/protection/run-commands.js +2 -20
  273. package/lib/protection/upload-batch.js +11 -7
  274. package/lib/resolvers/resource-type-file.js +22 -0
  275. package/lib/schema/external-datasource.schema.json +161 -1
  276. package/lib/schema/external-system.schema.json +242 -4
  277. package/lib/schema/flag-map-validation-run.json +3 -0
  278. package/lib/schema/type/credential-field-registry.json +2 -2
  279. package/lib/schema/type/document-storage.json +9 -0
  280. package/lib/utils/agent-trust-run-display.js +1 -1
  281. package/lib/utils/app-path-resolve.js +168 -0
  282. package/lib/utils/authentication-env-template.js +222 -0
  283. package/lib/utils/cli-sync-options.js +7 -11
  284. package/lib/utils/cli-utils.js +4 -0
  285. package/lib/utils/cli-workspace-options.js +29 -0
  286. package/lib/utils/compose-generate-docker-compose.js +102 -0
  287. package/lib/utils/configuration-env-resolver.js +203 -27
  288. package/lib/utils/datasource-test-run-certificate-tty.js +28 -2
  289. package/lib/utils/datasource-test-run-certification-debug.js +130 -0
  290. package/lib/utils/datasource-test-run-debug-display.js +2 -0
  291. package/lib/utils/datasource-test-run-debug-slice.js +7 -0
  292. package/lib/utils/datasource-test-run-display.js +2 -1
  293. package/lib/utils/dev-init-ssh-merge.js +165 -23
  294. package/lib/utils/dev-pin-share-instructions.js +110 -0
  295. package/lib/utils/dev-ssh-config-helper.js +177 -33
  296. package/lib/utils/enterprise-knowledge-paths.js +142 -0
  297. package/lib/utils/env-copy.js +2 -1
  298. package/lib/utils/env-dotenv-format.js +103 -0
  299. package/lib/utils/external-env-template.js +4 -1
  300. package/lib/utils/external-system-display.js +5 -1
  301. package/lib/utils/external-system-readiness-compact-blocks.js +221 -0
  302. package/lib/utils/external-system-readiness-compact-display.js +324 -0
  303. package/lib/utils/external-system-readiness-core.js +16 -0
  304. package/lib/utils/external-system-readiness-deploy-display.js +29 -11
  305. package/lib/utils/external-system-readiness-display-internals.js +3 -1
  306. package/lib/utils/external-system-readiness-display.js +20 -30
  307. package/lib/utils/external-system-system-test-tty-certification.js +135 -0
  308. package/lib/utils/external-system-system-test-tty.js +5 -41
  309. package/lib/utils/help-builder.js +6 -1
  310. package/lib/utils/host-ops-job-labels.js +236 -0
  311. package/lib/utils/host-ops-job-result.js +61 -0
  312. package/lib/utils/host-ops-poll-ui.js +163 -0
  313. package/lib/utils/integration-path-resolve.js +112 -0
  314. package/lib/utils/paths-reload-source.js +148 -0
  315. package/lib/utils/paths-system-builder-keys.js +25 -0
  316. package/lib/utils/paths.js +151 -26
  317. package/lib/utils/runtime-configuration-values.js +64 -2
  318. package/lib/utils/secrets-helpers.js +5 -1
  319. package/lib/utils/ssh-known-hosts.js +130 -0
  320. package/lib/utils/test-target-cli-options.js +75 -0
  321. package/lib/utils/upload-sync-options.js +4 -0
  322. package/lib/utils/validation-run-request.js +11 -2
  323. package/lib/validation/external-manifest-validator.js +11 -1
  324. package/lib/validation/openapi-contract-surface-validator.js +426 -0
  325. package/lib/validation/openapi-contract-vendor-validation.js +238 -0
  326. package/lib/validation/validate-external-file.js +160 -0
  327. package/lib/validation/validate.js +6 -117
  328. package/package.json +46 -29
  329. package/packages/builder-api/README.md +120 -0
  330. package/packages/builder-api/package.json +30 -0
  331. package/packages/builder-api/src/app.module.ts +7 -0
  332. package/packages/builder-api/src/auth/auth.module.ts +5 -0
  333. package/packages/builder-api/src/external-system/external-system.module.ts +5 -0
  334. package/packages/builder-api/src/main.ts +16 -0
  335. package/packages/builder-api/tsconfig.json +15 -0
  336. package/scripts/check-builder-api-architecture-grep.js +79 -0
  337. package/scripts/docker_image_content_gate.js +47 -0
  338. package/scripts/docker_image_content_gate.sh +5 -0
  339. package/scripts/export-builder-api-evidence.js +262 -0
  340. package/scripts/lib/builder-api-docker-staging-copy.js +60 -0
  341. package/scripts/lib/builder-api-docker-staging-core.js +183 -0
  342. package/scripts/lib/docker-image-content-gate-core.js +166 -0
  343. package/scripts/lib/plan-actor.js +109 -0
  344. package/scripts/lib/plan-config.js +20 -0
  345. package/scripts/lib/plan-gates.js +154 -0
  346. package/scripts/lib/plan-meta.js +104 -0
  347. package/scripts/lib/plan-parse.js +162 -0
  348. package/scripts/lib/plan-prevalidate-gates.js +326 -0
  349. package/scripts/lib/plan-run-core.js +125 -0
  350. package/scripts/lib/plan-run-report.js +108 -0
  351. package/scripts/plan-approve.js +24 -0
  352. package/scripts/plan-archive.js +49 -0
  353. package/scripts/plan-run.js +13 -0
  354. package/scripts/plan-set-actor.js +21 -0
  355. package/scripts/plan-validate.js +80 -0
  356. package/scripts/pnpm/af.mjs +110 -0
  357. package/scripts/pnpm/check-quiet.mjs +32 -0
  358. package/scripts/pnpm/dev-install.mjs +29 -0
  359. package/scripts/pnpm/dev-reload.mjs +18 -0
  360. package/scripts/pnpm/help.mjs +55 -0
  361. package/scripts/pnpm/lib/dev-reload-core.mjs +189 -0
  362. package/scripts/pnpm/lib/dev-reload-log-capture.mjs +67 -0
  363. package/scripts/pnpm/lib/dev-reload-log-utils.mjs +32 -0
  364. package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +124 -0
  365. package/scripts/pnpm/lib/resolve-app-url.mjs +183 -0
  366. package/scripts/pnpm/lib/spinner.mjs +42 -0
  367. package/scripts/stage_builder_api_for_docker.js +65 -0
  368. package/scripts/sync-builder-api-template.js +44 -0
  369. package/templates/README.md +3 -0
  370. package/templates/applications/builder-api/Dockerfile +38 -0
  371. package/templates/applications/builder-api/application.yaml +75 -0
  372. package/templates/applications/builder-api/env.template +48 -0
  373. package/templates/applications/dataplane/application.yaml +1 -1
  374. package/templates/applications/dataplane/env.template +10 -6
  375. package/templates/applications/dataplane/rbac.yaml +21 -1
  376. package/templates/applications/miso-controller/application.yaml +1 -1
  377. package/templates/applications/miso-controller/env.template +1 -3
  378. package/templates/channels/README.md +18 -0
  379. package/templates/channels/ai-fabrix-icon.jpg +0 -0
  380. package/templates/channels/chatgpt/install.template.md.hbs +21 -24
  381. package/templates/channels/chatgpt/integration/README.md +11 -0
  382. package/templates/channels/chatgpt/integration/application.json +15 -0
  383. package/templates/channels/chatgpt/integration/chatgpt-system.json +29 -0
  384. package/templates/channels/chatgpt/integration/env.template +4 -0
  385. package/templates/channels/microsoft-copilot/install.template.md.hbs +20 -25
  386. package/templates/channels/microsoft-copilot/integration/README.md +11 -0
  387. package/templates/channels/microsoft-copilot/integration/application.json +15 -0
  388. package/templates/channels/microsoft-copilot/integration/env.template +6 -0
  389. package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +34 -0
  390. package/templates/channels/slack/install.template.md.hbs +48 -18
  391. package/templates/channels/slack/integration/README.md +38 -0
  392. package/templates/channels/slack/integration/application.json +18 -0
  393. package/templates/channels/slack/integration/env.template +29 -0
  394. package/templates/channels/slack/integration/slack-datasource-conversations.json +226 -0
  395. package/templates/channels/slack/integration/slack-datasource-messages.json +269 -0
  396. package/templates/channels/slack/integration/slack-system.json +86 -0
  397. package/templates/channels/slack/manifest.template.json.hbs +20 -10
  398. package/templates/channels/teams-bot/install.template.md.hbs +31 -17
  399. package/templates/channels/teams-bot/integration/README.md +18 -0
  400. package/templates/channels/teams-bot/integration/application.json +17 -0
  401. package/templates/channels/teams-bot/integration/env.template +5 -0
  402. package/templates/channels/teams-bot/integration/teams-bot-system.json +55 -0
  403. package/templates/channels/teams-bot/manifest.template.json.hbs +27 -0
  404. package/templates/channels/web-embed/install.template.md.hbs +16 -26
  405. package/templates/channels/web-embed/integration/README.md +11 -0
  406. package/templates/channels/web-embed/integration/application.json +15 -0
  407. package/templates/channels/web-embed/integration/env.template +4 -0
  408. package/templates/channels/web-embed/integration/web-embed-system.json +29 -0
  409. package/templates/openapi/redoc_page.html +86 -0
  410. package/templates/python/docker-compose.hbs +11 -0
  411. package/templates/python/requirements.txt +1 -1
  412. package/templates/typescript/docker-compose.hbs +11 -0
  413. 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 _buildDesiredPermissionNames(appPath, datasourceFiles) {
120
- const desired = collectPermissionNames(appPath, datasourceFiles);
121
- if (desired.size === 0) return { desired, managedResourceTypes: new Set(), aliases: new Map() };
122
-
123
- const managedResourceTypes = _collectManagedResourceTypesFromDatasources(appPath, datasourceFiles);
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
- // Build alias map for rename support (kebab-case or case variants -> canonical).
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) continue;
130
- const kebab = _normalizeOperationKey(op);
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
- function _roleValues(rbac) {
257
- const roles = Array.isArray(rbac.roles) ? rbac.roles : [];
258
- return roles
259
- .map(r => r?.value)
260
- .filter(v => typeof v === 'string' && v.trim());
261
- }
262
-
263
- function _pickAdminRoleValue(roleValues, systemKey) {
264
- return (
265
- roleValues.find(v => v === `${systemKey}-admin`) ||
266
- roleValues.find(v => /-admin$/.test(v)) ||
267
- roleValues[0] ||
268
- null
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
- * Ensures every permission has at least one role assigned.
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 ensureNonEmptyPermissionRoles(rbac, systemKey, changes) {
307
- const roleValues = _roleValues(rbac);
308
- if (!Array.isArray(rbac.permissions) || roleValues.length === 0) return false;
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 updated;
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(appPath, datasourceFiles);
347
- if (permissionNames.size === 0) return false;
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 = ensureDefaultRoles(rbac, systemKey, displayName, changes) || 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) return { rbacMigratedFromSystem: false, rbacMergeUpdated: false };
399
- const { dryRun, changes, backupCtx, rbacFmt } = options;
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
- return { rbacMigratedFromSystem, rbacMergeUpdated };
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, appKeyFixed: boolean, datasourceKeysFixed: boolean, rbacFileCreated: boolean, envTemplateRepaired: boolean }}
102
+ * @returns {{ updated: boolean, authenticationsArrayUpdated: boolean }}
98
103
  */
99
- function runRepairSteps(ctx) {
100
- const bc = ctx.backupCtx;
101
- let updated = ensureExternalIntegrationBlock(
102
- ctx.variables, ctx.systemFiles, ctx.datasourceFiles, ctx.changes
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
- updated = updated || authShapeNormalized;
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
- const systemFileUpdated = persistSystemFileRepair(ctx, {
122
- authReplaced,
123
- authShapeNormalized,
165
+ return persistSystemFileRepair(ctx, {
166
+ ...authFlags,
124
167
  systemAuthConfigNormalized,
125
168
  systemDataSourcesAligned,
126
169
  authVarsRemoved
127
170
  });
128
- updated = updated || systemFileUpdated;
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
- updated = updated || appKeyFixed || datasourceKeysFixed || rbacFileCreated || envTemplateRepaired;
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
- appKeyFixed,
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, '');
@@ -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(`Resource type created: ${row.key} (category: ${category}, risk: ${risk})`)
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(formatSuccessLine(`Resource type exists: ${row.key} (category: ${category}, risk: ${risk})`));
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 KEY_WIDTH = 22;
295
- const DISPLAY_WIDTH = 30;
296
- const CATEGORY_WIDTH = 16;
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