@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
@@ -0,0 +1,146 @@
1
+ /**
2
+ * GET manifest section handler (plan 154.4).
3
+ *
4
+ * @fileoverview ManifestSectionView with quality, graph, read token
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const {
12
+ getDownstream,
13
+ computeNextActions,
14
+ getRepairTraversalOrder
15
+ } = require('./manifest-section-dependency-graph');
16
+ const {
17
+ getSectionDefinition,
18
+ listSectionKeys,
19
+ extractSectionValue,
20
+ buildSchemaFragment
21
+ } = require('./manifest-section-registry');
22
+ const { computeSectionQuality, hasRequiredMissingInputs } = require('./manifest-section-quality');
23
+ const {
24
+ loadSystemDocument,
25
+ loadDatasourceDocument,
26
+ hashValue,
27
+ redactSecrets,
28
+ listDatasourceKeys
29
+ } = require('./manifest-section-io');
30
+ const { runWithWorkspaceContext } = require('./workspace-context');
31
+
32
+ /**
33
+ * @param {Object} def
34
+ * @param {{ sectionKey: string, datasourceKey?: string }} options
35
+ */
36
+ function validateManifestSectionRequest(def, options) {
37
+ if (def.blocked) {
38
+ const err = new Error(`Section ${options.sectionKey} is blocked for MCP editing`);
39
+ err.statusCode = 403;
40
+ throw err;
41
+ }
42
+ if (def.target === 'datasource' && !options.datasourceKey) {
43
+ const err = new Error('datasourceKey is required for datasource sections');
44
+ err.statusCode = 400;
45
+ throw err;
46
+ }
47
+ if (def.target === 'system' && options.datasourceKey) {
48
+ const err = new Error('datasourceKey must not be set for system sections');
49
+ err.statusCode = 400;
50
+ throw err;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * @param {import('./workspace-context').WorkspaceContext} ctx
56
+ * @param {{ sectionKey: string, datasourceKey?: string }} options
57
+ * @param {Object} def
58
+ * @returns {Object}
59
+ */
60
+ function buildManifestSectionView(ctx, options, def) {
61
+ const { doc, datasourceDoc } = loadDocuments(ctx, def.target, options.datasourceKey);
62
+ const rawValue = extractSectionValue(doc, def);
63
+ const currentValue = redactSecrets(rawValue);
64
+ const quality = computeSectionQuality({
65
+ sectionKey: options.sectionKey,
66
+ currentValue: rawValue,
67
+ datasourceDoc
68
+ });
69
+ const downstreamFromThis = getDownstream(options.sectionKey);
70
+ const traversal = getRepairTraversalOrder(options.sectionKey);
71
+ let recommendedNextActions = computeNextActions(ctx, {
72
+ sectionKey: options.sectionKey,
73
+ lastOp: 'getSection',
74
+ quality
75
+ });
76
+ if (hasRequiredMissingInputs(quality)) {
77
+ recommendedNextActions = ['askUser'];
78
+ }
79
+
80
+ return {
81
+ sectionKey: options.sectionKey,
82
+ target: def.target,
83
+ datasourceKey: options.datasourceKey || null,
84
+ currentValue,
85
+ schemaFragment: buildSchemaFragment(def.target, def.paths[0]),
86
+ required: def.required,
87
+ mutable: def.mutable,
88
+ sourceOfTruth: def.sourceOfTruth,
89
+ dependencyGraph: { downstreamFromThis },
90
+ repairHooks: traversal.hooks,
91
+ recommendedNextActions,
92
+ sectionReadToken: hashValue({ sectionKey: options.sectionKey, value: rawValue }),
93
+ quality
94
+ };
95
+ }
96
+
97
+ /**
98
+ * @param {import('./workspace-context').WorkspaceContext} ctx
99
+ * @param {{ sectionKey: string, datasourceKey?: string }} options
100
+ */
101
+ async function getManifestSection(ctx, options) {
102
+ return runWithWorkspaceContext(ctx, async() => {
103
+ const def = getSectionDefinition(options.sectionKey);
104
+ validateManifestSectionRequest(def, options);
105
+ return buildManifestSectionView(ctx, options, def);
106
+ });
107
+ }
108
+
109
+ /**
110
+ * @param {import('./workspace-context').WorkspaceContext} ctx
111
+ * @param {{ target?: string }} [options]
112
+ */
113
+ async function listManifestSections(ctx, options = {}) {
114
+ return runWithWorkspaceContext(ctx, async() => {
115
+ const target = options.target;
116
+ const systemKeys = listSectionKeys(target === 'datasource' ? 'datasource' : target === 'system' ? 'system' : undefined);
117
+ const datasourceKeys = listDatasourceKeys(ctx);
118
+ return {
119
+ systemKey: ctx.systemKey,
120
+ sections: systemKeys.map((sectionKey) => ({
121
+ sectionKey,
122
+ target: getSectionDefinition(sectionKey).target
123
+ })),
124
+ datasourceKeys
125
+ };
126
+ });
127
+ }
128
+
129
+ /**
130
+ * @param {import('./workspace-context').WorkspaceContext} ctx
131
+ * @param {'system' | 'datasource'} target
132
+ * @param {string} [datasourceKey]
133
+ */
134
+ function loadDocuments(ctx, target, datasourceKey) {
135
+ if (target === 'system') {
136
+ const { systemDoc } = loadSystemDocument(ctx);
137
+ return { doc: systemDoc, datasourceDoc: undefined };
138
+ }
139
+ const { datasourceDoc } = loadDatasourceDocument(ctx, datasourceKey);
140
+ return { doc: datasourceDoc, datasourceDoc };
141
+ }
142
+
143
+ module.exports = {
144
+ getManifestSection,
145
+ listManifestSections
146
+ };
@@ -0,0 +1,252 @@
1
+ /**
2
+ * PATCH manifest section handler (plan 154.4).
3
+ *
4
+ * @fileoverview Intent audit, read token, risk hints
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const {
12
+ getDownstream,
13
+ computeNextActions,
14
+ getRepairTraversalOrder
15
+ } = require('./manifest-section-dependency-graph');
16
+ const {
17
+ getSectionDefinition,
18
+ extractSectionValue,
19
+ injectSectionValue
20
+ } = require('./manifest-section-registry');
21
+ const manifestSectionRegistry = require('./manifest-section-registry');
22
+ const { computeSectionQuality, hasRequiredMissingInputs } = require('./manifest-section-quality');
23
+ const {
24
+ loadSystemDocument,
25
+ loadDatasourceDocument,
26
+ writeJsonDocument,
27
+ backupFile,
28
+ hashValue,
29
+ appendSectionAudit,
30
+ getIntegrationPath
31
+ } = require('./manifest-section-io');
32
+ const { runWithWorkspaceContext } = require('./workspace-context');
33
+
34
+ /**
35
+ * @param {import('./workspace-context').WorkspaceContext} ctx
36
+ * @param {{ sectionKey: string, datasourceKey?: string, intent: string, patch: Object, mode: string, sectionReadToken: string, dryRun?: boolean }} body
37
+ */
38
+ async function patchManifestSection(ctx, body) {
39
+ return runWithWorkspaceContext(ctx, async() => {
40
+ assertPatchRequest(body);
41
+ const def = getSectionDefinition(body.sectionKey);
42
+ assertPatchAllowed(def, body);
43
+
44
+ const loaded = loadTargetDocument(ctx, def.target, body.datasourceKey);
45
+ const beforeValue = extractSectionValue(loaded.doc, def);
46
+ verifyReadToken(body, beforeValue);
47
+
48
+ const draft = JSON.parse(JSON.stringify(loaded.doc));
49
+ injectSectionValue(draft, def, body.patch, body.mode === 'replace' ? 'replace' : 'merge');
50
+ validateDraftDocument(def.target, draft);
51
+
52
+ const afterValue = extractSectionValue(draft, def);
53
+ if (body.dryRun !== true) {
54
+ persistPatchedDocument(ctx, loaded, draft, body, beforeValue, afterValue);
55
+ }
56
+
57
+ return buildPatchResult(ctx, body, def, beforeValue, afterValue, draft);
58
+ });
59
+ }
60
+
61
+ /**
62
+ * @param {Object} body
63
+ * @param {*} beforeValue
64
+ */
65
+ function verifyReadToken(body, beforeValue) {
66
+ const expectedToken = hashValue({ sectionKey: body.sectionKey, value: beforeValue });
67
+ if (body.sectionReadToken !== expectedToken) {
68
+ const err = new Error('Section read token is stale — GET the section again before patching');
69
+ err.statusCode = 409;
70
+ throw err;
71
+ }
72
+ }
73
+
74
+ /**
75
+ * @param {'system' | 'datasource'} target
76
+ * @param {Object} draft
77
+ */
78
+ function validateDraftDocument(target, draft) {
79
+ const validation = manifestSectionRegistry.validateManifestDocument(target, draft);
80
+ if (!validation.valid) {
81
+ const err = new Error('Patched manifest failed schema validation');
82
+ err.statusCode = 422;
83
+ err.errors = validation.errors;
84
+ throw err;
85
+ }
86
+ }
87
+
88
+ /**
89
+ * @param {import('./workspace-context').WorkspaceContext} ctx
90
+ * @param {Object} loaded
91
+ * @param {Object} draft
92
+ * @param {Object} body
93
+ * @param {*} beforeValue
94
+ * @param {*} afterValue
95
+ */
96
+ function persistPatchedDocument(ctx, loaded, draft, body, beforeValue, afterValue) {
97
+ backupFile(getIntegrationPath(ctx), loaded.fileName);
98
+ writeJsonDocument(loaded.filePath, draft);
99
+ appendSectionAudit(ctx, {
100
+ sectionKey: body.sectionKey,
101
+ datasourceKey: body.datasourceKey || null,
102
+ intent: body.intent,
103
+ beforeHash: hashValue(beforeValue),
104
+ afterHash: hashValue(afterValue),
105
+ mode: body.mode
106
+ });
107
+ }
108
+
109
+ /**
110
+ * @param {import('./workspace-context').WorkspaceContext} ctx
111
+ * @param {Object} body
112
+ * @param {import('./manifest-section-registry-data').SectionDefinition} def
113
+ * @param {*} beforeValue
114
+ * @param {*} afterValue
115
+ * @param {Object} draft
116
+ */
117
+ function buildPatchResult(ctx, body, def, beforeValue, afterValue, draft) {
118
+ const quality = computeSectionQuality({
119
+ sectionKey: body.sectionKey,
120
+ currentValue: afterValue,
121
+ datasourceDoc: def.target === 'datasource' ? draft : undefined
122
+ });
123
+ const downstream = getDownstream(body.sectionKey);
124
+ const traversal = getRepairTraversalOrder(body.sectionKey);
125
+ let nextActions = computeNextActions(ctx, {
126
+ sectionKey: body.sectionKey,
127
+ lastOp: 'patchSection',
128
+ quality
129
+ });
130
+ if (hasRequiredMissingInputs(quality)) {
131
+ nextActions = ['askUser'];
132
+ }
133
+ return {
134
+ sectionKey: body.sectionKey,
135
+ datasourceKey: body.datasourceKey || null,
136
+ intent: body.intent,
137
+ changedPaths: collectChangedPaths(beforeValue, afterValue),
138
+ beforeHash: hashValue(beforeValue),
139
+ afterHash: hashValue(afterValue),
140
+ derivedSectionsAffected: downstream,
141
+ repairRecommended: downstream.length > 0,
142
+ repairHooks: traversal.hooks,
143
+ validationPreview: { valid: true },
144
+ riskHints: buildRiskHints(body.sectionKey, body.patch, downstream),
145
+ nextActions,
146
+ dryRun: body.dryRun === true,
147
+ quality
148
+ };
149
+ }
150
+
151
+ /**
152
+ * @param {Object} body
153
+ */
154
+ function assertPatchRequest(body) {
155
+ if (!body.intent || typeof body.intent !== 'string' || !body.intent.trim()) {
156
+ const err = new Error('intent is required and must be a non-empty string');
157
+ err.statusCode = 400;
158
+ throw err;
159
+ }
160
+ if (!body.patch || typeof body.patch !== 'object') {
161
+ const err = new Error('patch object is required');
162
+ err.statusCode = 400;
163
+ throw err;
164
+ }
165
+ if (!body.sectionReadToken) {
166
+ const err = new Error('sectionReadToken is required — GET the section first');
167
+ err.statusCode = 400;
168
+ throw err;
169
+ }
170
+ if (body.mode !== 'merge' && body.mode !== 'replace') {
171
+ const err = new Error('mode must be merge or replace');
172
+ err.statusCode = 400;
173
+ throw err;
174
+ }
175
+ }
176
+
177
+ /**
178
+ * @param {import('./manifest-section-registry-data').SectionDefinition} def
179
+ * @param {Object} body
180
+ */
181
+ function assertPatchAllowed(def, body) {
182
+ if (def.blocked) {
183
+ const err = new Error(`Section ${body.sectionKey} is blocked for MCP editing`);
184
+ err.statusCode = 403;
185
+ throw err;
186
+ }
187
+ if (!def.mutable) {
188
+ const err = new Error(`Section ${body.sectionKey} is repair-only and cannot be patched directly`);
189
+ err.statusCode = 403;
190
+ throw err;
191
+ }
192
+ if (def.target === 'datasource' && !body.datasourceKey) {
193
+ const err = new Error('datasourceKey is required for datasource sections');
194
+ err.statusCode = 400;
195
+ throw err;
196
+ }
197
+ }
198
+
199
+ /**
200
+ * @param {import('./workspace-context').WorkspaceContext} ctx
201
+ * @param {'system' | 'datasource'} target
202
+ * @param {string} [datasourceKey]
203
+ */
204
+ function loadTargetDocument(ctx, target, datasourceKey) {
205
+ if (target === 'system') {
206
+ const { systemFile, systemPath, systemDoc } = loadSystemDocument(ctx);
207
+ return { doc: systemDoc, filePath: systemPath, fileName: systemFile };
208
+ }
209
+ const { datasourceFile, datasourcePath, datasourceDoc } = loadDatasourceDocument(ctx, datasourceKey);
210
+ return { doc: datasourceDoc, filePath: datasourcePath, fileName: datasourceFile };
211
+ }
212
+
213
+ /**
214
+ * @param {*} beforeValue
215
+ * @param {*} afterValue
216
+ * @returns {string[]}
217
+ */
218
+ function collectChangedPaths(beforeValue, afterValue) {
219
+ if (JSON.stringify(beforeValue) === JSON.stringify(afterValue)) {
220
+ return [];
221
+ }
222
+ return ['sectionRoot'];
223
+ }
224
+
225
+ /**
226
+ * @param {string} sectionKey
227
+ * @param {Object} patch
228
+ * @param {string[]} downstream
229
+ * @returns {string[]}
230
+ */
231
+ function buildRiskHints(sectionKey, patch, downstream) {
232
+ /** @type {string[]} */
233
+ const hints = [];
234
+ if (downstream.includes('datasource.fieldMappings')) {
235
+ hints.push('Derived fieldMappings will change on repair');
236
+ }
237
+ if (downstream.includes('system.rolesPermissions')) {
238
+ hints.push('Cross-system section system.rolesPermissions may change');
239
+ }
240
+ if (sectionKey === 'datasource.openapiOperations' || sectionKey === 'datasource.capabilities') {
241
+ hints.push('New write capability added');
242
+ hints.push('RBAC repair required before test');
243
+ }
244
+ if (JSON.stringify(patch).match(/put|post|patch|delete/i)) {
245
+ hints.push('Approval may be required before production');
246
+ }
247
+ return [...new Set(hints)];
248
+ }
249
+
250
+ module.exports = {
251
+ patchManifestSection
252
+ };
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Section-scoped manifest repair orchestration (plan 154.4).
3
+ *
4
+ * @fileoverview Graph-ordered hooks delegating to repair command
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const { repairExternalIntegration } = require('../commands/repair');
12
+ const { getRepairTraversalOrder } = require('./manifest-section-dependency-graph');
13
+ const { computeSectionQuality } = require('./manifest-section-quality');
14
+ const { loadSystemDocument, loadDatasourceDocument } = require('./manifest-section-io');
15
+ const { runWithWorkspaceContext } = require('./workspace-context');
16
+ const { touchWorkspaceMeta } = require('./workspace-meta');
17
+
18
+ const HOOK_FLAG_MAP = Object.freeze({
19
+ fieldMappings: 'sync',
20
+ expose: 'expose',
21
+ rbac: 'rbac',
22
+ sync: 'sync',
23
+ test: 'test',
24
+ api: 'api',
25
+ operations: 'operations'
26
+ });
27
+
28
+ /**
29
+ * @param {import('./workspace-context').WorkspaceContext} ctx
30
+ * @param {{ hooks?: string[], sectionKey?: string, datasourceKey?: string, dryRun?: boolean, auth?: string }} body
31
+ */
32
+ async function runManifestRepair(ctx, body = {}) {
33
+ return runWithWorkspaceContext(ctx, async() => {
34
+ const requestedHooks = normalizeHooks(body.hooks, body.sectionKey);
35
+ const repairOptions = buildRepairOptions(requestedHooks, body);
36
+ const result = await repairExternalIntegration(ctx.systemKey, repairOptions);
37
+ if (body.dryRun !== true) {
38
+ touchWorkspaceMeta(ctx, { lastOperation: 'manifest-repair' });
39
+ }
40
+ const qualitySnapshot = buildPostRepairQuality(ctx, body);
41
+ return {
42
+ hooksRun: requestedHooks,
43
+ derivedSectionsUpdated: body.sectionKey ? getRepairTraversalOrder(body.sectionKey).sections : [],
44
+ repairResult: result,
45
+ dryRun: body.dryRun === true,
46
+ quality: qualitySnapshot
47
+ };
48
+ });
49
+ }
50
+
51
+ /**
52
+ * @param {string[]|undefined} hooks
53
+ * @param {string|undefined} sectionKey
54
+ * @returns {string[]}
55
+ */
56
+ function normalizeHooks(hooks, sectionKey) {
57
+ if (Array.isArray(hooks) && hooks.length) {
58
+ return hooks.map(String);
59
+ }
60
+ if (sectionKey) {
61
+ return getRepairTraversalOrder(sectionKey).hooks;
62
+ }
63
+ const err = new Error('hooks[] is required when sectionKey is not provided');
64
+ err.statusCode = 400;
65
+ throw err;
66
+ }
67
+
68
+ /**
69
+ * @param {string[]} hooks
70
+ * @param {Object} body
71
+ * @returns {Object}
72
+ */
73
+ function buildRepairOptions(hooks, body) {
74
+ /** @type {Object} */
75
+ const options = {
76
+ dryRun: body.dryRun === true,
77
+ auth: body.auth
78
+ };
79
+ for (const hook of hooks) {
80
+ const flag = HOOK_FLAG_MAP[hook];
81
+ if (flag) {
82
+ options[flag] = true;
83
+ }
84
+ }
85
+ if (options.rbac === true) {
86
+ options.operations = true;
87
+ }
88
+ return options;
89
+ }
90
+
91
+ /**
92
+ * @param {import('./workspace-context').WorkspaceContext} ctx
93
+ * @param {Object} body
94
+ * @returns {Object|null}
95
+ */
96
+ function buildPostRepairQuality(ctx, body) {
97
+ if (!body.sectionKey) {
98
+ return null;
99
+ }
100
+ try {
101
+ if (body.sectionKey.startsWith('system.')) {
102
+ const { systemDoc } = loadSystemDocument(ctx);
103
+ return computeSectionQuality({ sectionKey: body.sectionKey, currentValue: systemDoc });
104
+ }
105
+ if (body.datasourceKey) {
106
+ const { datasourceDoc } = loadDatasourceDocument(ctx, body.datasourceKey);
107
+ return computeSectionQuality({
108
+ sectionKey: body.sectionKey,
109
+ currentValue: datasourceDoc,
110
+ datasourceDoc
111
+ });
112
+ }
113
+ } catch {
114
+ return null;
115
+ }
116
+ return null;
117
+ }
118
+
119
+ module.exports = {
120
+ runManifestRepair,
121
+ HOOK_FLAG_MAP
122
+ };
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Directed dependency graph for governed manifest sections (plan 154.4).
3
+ *
4
+ * @fileoverview Repair traversal and nextActions generation
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ /** @type {ReadonlyArray<[string, string]>} */
12
+ const SECTION_EDGES = Object.freeze([
13
+ ['datasource.metadata', 'datasource.fieldMappings'],
14
+ ['datasource.fieldMappings', 'datasource.exposedAttributes'],
15
+ ['datasource.exposedAttributes', 'datasource.openapiOperations'],
16
+ ['datasource.openapiOperations', 'datasource.mcpOperations'],
17
+ ['datasource.mcpOperations', 'system.rolesPermissions'],
18
+ ['datasource.capabilities', 'datasource.openapiOperations'],
19
+ ['datasource.identity', 'datasource.fieldMappings'],
20
+ ['datasource.entityType', 'datasource.metadata']
21
+ ]);
22
+
23
+ /** @type {Readonly<Record<string, string[]>>} */
24
+ const SECTION_REPAIR_HOOKS = Object.freeze({
25
+ 'datasource.metadata': ['fieldMappings', 'expose', 'rbac'],
26
+ 'datasource.fieldMappings': ['fieldMappings', 'expose'],
27
+ 'datasource.exposedAttributes': ['expose'],
28
+ 'datasource.openapiOperations': ['expose', 'rbac'],
29
+ 'datasource.mcpOperations': ['rbac'],
30
+ 'datasource.capabilities': ['expose', 'rbac', 'operations'],
31
+ 'datasource.identity': ['fieldMappings'],
32
+ 'system.rolesPermissions': ['rbac']
33
+ });
34
+
35
+ /**
36
+ * @param {string} sectionKey
37
+ * @returns {string[]}
38
+ */
39
+ function getDownstream(sectionKey) {
40
+ const adjacency = buildAdjacency();
41
+ const visited = new Set();
42
+ const order = [];
43
+ const queue = [sectionKey];
44
+ while (queue.length > 0) {
45
+ const current = queue.shift();
46
+ const next = adjacency.get(current) || [];
47
+ for (const dep of next) {
48
+ if (visited.has(dep)) {
49
+ continue;
50
+ }
51
+ visited.add(dep);
52
+ order.push(dep);
53
+ queue.push(dep);
54
+ }
55
+ }
56
+ return order;
57
+ }
58
+
59
+ /**
60
+ * @param {string} sectionKey
61
+ * @returns {{ sections: string[], hooks: string[] }}
62
+ */
63
+ function getRepairTraversalOrder(sectionKey) {
64
+ const sections = getDownstream(sectionKey);
65
+ const hookSet = new Set();
66
+ const allKeys = [sectionKey, ...sections];
67
+ for (const key of allKeys) {
68
+ const hooks = SECTION_REPAIR_HOOKS[key] || [];
69
+ for (const hook of hooks) {
70
+ hookSet.add(hook);
71
+ }
72
+ }
73
+ return { sections, hooks: [...hookSet] };
74
+ }
75
+
76
+ /**
77
+ * @param {Object} _ctx
78
+ * @param {{ sectionKey: string, lastOp?: string, quality?: Object }} input
79
+ * @returns {string[]}
80
+ */
81
+ function computeNextActions(_ctx, input) {
82
+ const quality = input.quality || {};
83
+ const missing = Array.isArray(quality.missingInputs) ? quality.missingInputs : [];
84
+ const hasRequiredMissing = missing.some((item) => item && item.required === true);
85
+ if (hasRequiredMissing) {
86
+ return ['askUser'];
87
+ }
88
+ if (input.lastOp === 'getSection') {
89
+ return ['patchSection', 'repair', 'validate'];
90
+ }
91
+ if (input.lastOp === 'patchSection') {
92
+ const downstream = getDownstream(input.sectionKey);
93
+ if (downstream.length > 0) {
94
+ return ['repair', 'validate', 'test'];
95
+ }
96
+ return ['validate', 'test'];
97
+ }
98
+ if (input.lastOp === 'repair') {
99
+ return ['validate', 'test'];
100
+ }
101
+ return ['patchSection', 'repair', 'validate'];
102
+ }
103
+
104
+ /**
105
+ * @returns {Map<string, string[]>}
106
+ */
107
+ function buildAdjacency() {
108
+ /** @type {Map<string, string[]>} */
109
+ const map = new Map();
110
+ for (const [source, target] of SECTION_EDGES) {
111
+ const list = map.get(source) || [];
112
+ list.push(target);
113
+ map.set(source, list);
114
+ }
115
+ return map;
116
+ }
117
+
118
+ /**
119
+ * @returns {boolean}
120
+ */
121
+ function isAcyclicGraph() {
122
+ const adjacency = buildAdjacency();
123
+ const visiting = new Set();
124
+ const visited = new Set();
125
+
126
+ /** @param {string} node */
127
+ function visit(node) {
128
+ if (visited.has(node)) {
129
+ return true;
130
+ }
131
+ if (visiting.has(node)) {
132
+ return false;
133
+ }
134
+ visiting.add(node);
135
+ for (const next of adjacency.get(node) || []) {
136
+ if (!visit(next)) {
137
+ return false;
138
+ }
139
+ }
140
+ visiting.delete(node);
141
+ visited.add(node);
142
+ return true;
143
+ }
144
+
145
+ for (const node of adjacency.keys()) {
146
+ if (!visit(node)) {
147
+ return false;
148
+ }
149
+ }
150
+ return true;
151
+ }
152
+
153
+ module.exports = {
154
+ SECTION_EDGES,
155
+ SECTION_REPAIR_HOOKS,
156
+ getDownstream,
157
+ getRepairTraversalOrder,
158
+ computeNextActions,
159
+ isAcyclicGraph
160
+ };