@aifabrix/builder 2.52.0 → 2.53.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 (310) hide show
  1. package/lib/api/datasources-extended.api.js +8 -8
  2. package/lib/api/keycloak.api.js +92 -0
  3. package/lib/api/token-providers.api.js +77 -0
  4. package/lib/api/types/keycloak.types.js +23 -0
  5. package/lib/api/types/token-providers.types.js +65 -0
  6. package/lib/app/deploy-config.js +3 -2
  7. package/lib/app/down.js +16 -1
  8. package/lib/channels/add-channel.js +134 -57
  9. package/lib/channels/approval-guides/chatgpt.js +1 -1
  10. package/lib/channels/approval-guides/index.js +3 -0
  11. package/lib/channels/approval-guides/microsoft-copilot.js +27 -14
  12. package/lib/channels/channel-add-ensure.js +128 -0
  13. package/lib/channels/channel-add-existing.js +72 -0
  14. package/lib/channels/channel-artifact-generator.js +11 -1
  15. package/lib/channels/channel-branding.js +94 -0
  16. package/lib/channels/channel-credential.js +8 -0
  17. package/lib/channels/channel-discovery.js +330 -0
  18. package/lib/channels/channel-external-system.js +1 -1
  19. package/lib/channels/channel-runtime-resolver.js +107 -14
  20. package/lib/channels/channel-status-display.js +36 -3
  21. package/lib/channels/microsoft-copilot-channel-add.js +138 -0
  22. package/lib/channels/microsoft-copilot-entra-sso-form.js +251 -0
  23. package/lib/channels/microsoft-copilot-entra-sso.js +285 -0
  24. package/lib/channels/microsoft-copilot-icons.js +74 -0
  25. package/lib/channels/microsoft-copilot-limits.js +103 -0
  26. package/lib/channels/microsoft-copilot-package.js +178 -52
  27. package/lib/channels/microsoft-copilot-validate.js +227 -0
  28. package/lib/cli/attach-default-help-examples.js +102 -0
  29. package/lib/cli/index.js +4 -0
  30. package/lib/cli/infra-guided.js +13 -6
  31. package/lib/cli/setup-credential-deployment.js +7 -5
  32. package/lib/cli/setup-infra.js +31 -4
  33. package/lib/cli/setup-utility-validate.js +1 -0
  34. package/lib/commands/channel-add-setup.js +28 -9
  35. package/lib/commands/channel.js +14 -10
  36. package/lib/commands/credential-push.js +37 -5
  37. package/lib/commands/integration-definition.js +158 -0
  38. package/lib/commands/package-score.js +72 -0
  39. package/lib/commands/repair-auth-apply.js +19 -5
  40. package/lib/commands/repair-datasource-sync-operations.js +4 -1
  41. package/lib/commands/role-assistant-test-output.js +200 -0
  42. package/lib/commands/role-assistant.js +163 -166
  43. package/lib/datasource/capability/capability-resolve.js +15 -5
  44. package/lib/datasource/capability/copy-operations.js +14 -4
  45. package/lib/deployment/deployer-poll-run.js +2 -2
  46. package/lib/deployment/deployer.js +1 -1
  47. package/lib/deployment/environment.js +2 -2
  48. package/lib/external-system/deploy.js +11 -21
  49. package/lib/infrastructure/index.js +19 -4
  50. package/lib/integration-definition/apply.js +476 -0
  51. package/lib/integration-definition/canonical-json.js +51 -0
  52. package/lib/integration-definition/emit-suite-bid.js +94 -0
  53. package/lib/integration-definition/enrich-crm-field-mappings.js +240 -0
  54. package/lib/integration-definition/enrich-openapi-operations.js +433 -0
  55. package/lib/integration-definition/from-discovery.js +339 -0
  56. package/lib/integration-definition/hash.js +37 -0
  57. package/lib/integration-definition/index.js +37 -0
  58. package/lib/integration-definition/resource-type-catalog.js +59 -0
  59. package/lib/integration-definition/system-kind-enum.js +40 -0
  60. package/lib/integration-definition/validate.js +148 -0
  61. package/lib/lab/package-parity-score.js +417 -0
  62. package/lib/programmatic/builder-api-request.js +5 -1
  63. package/lib/programmatic/builder-help-governance.js +3 -2
  64. package/lib/programmatic/capability-registry.js +20 -0
  65. package/lib/programmatic/help-content/channel-onboarding.md +35 -0
  66. package/lib/programmatic/help-content/cip-overview.md +27 -0
  67. package/lib/programmatic/help-content/connected-system-ui.md +70 -0
  68. package/lib/programmatic/help-content/dimensions-guide.md +23 -0
  69. package/lib/programmatic/help-content/enterprise-sync-fabrix.md +123 -0
  70. package/lib/programmatic/help-content/overview.md +25 -0
  71. package/lib/programmatic/help-content/subscription-guide.md +27 -0
  72. package/lib/programmatic/help-content/workflow.md +50 -0
  73. package/lib/programmatic/openapi-component-schemas.js +7 -1
  74. package/lib/programmatic/openapi-descriptions.js +46 -0
  75. package/lib/programmatic/openapi-envelope-examples.js +280 -0
  76. package/lib/programmatic/openapi-operation-bindings.js +50 -0
  77. package/lib/programmatic/openapi-request-schemas.js +40 -0
  78. package/lib/programmatic/openapi-result-schemas-overflow.js +101 -0
  79. package/lib/programmatic/openapi-result-schemas.js +76 -99
  80. package/lib/programmatic/openapi-schema-descriptions-core.js +25 -4
  81. package/lib/programmatic/openapi-schema-descriptions-help.js +1 -1
  82. package/lib/programmatic/openapi-schema-descriptions-operations.js +43 -0
  83. package/lib/programmatic/openapi-schema-helpers.js +9 -9
  84. package/lib/programmatic/openapi-spec.js +11 -1
  85. package/lib/programmatic/orchestration-openapi-meta.js +10 -0
  86. package/lib/programmatic/persist-supplied-openapi.js +180 -0
  87. package/lib/programmatic/route-handler-map.js +35 -1
  88. package/lib/programmatic/run-channel-package.js +236 -0
  89. package/lib/programmatic/run-integration-definition.js +77 -0
  90. package/lib/role-assistant/evidence-sync.js +55 -7
  91. package/lib/role-assistant/knowledge-sync-logging.js +58 -0
  92. package/lib/role-assistant/knowledge-sync.js +88 -93
  93. package/lib/role-assistant/test-cases-bid.js +155 -0
  94. package/lib/role-assistant/test-cases-evaluate.js +9 -1
  95. package/lib/role-assistant/test-cases-honesty.js +24 -10
  96. package/lib/role-assistant/test-cases.js +28 -0
  97. package/lib/role-assistant/test-runner-attachments.js +118 -0
  98. package/lib/role-assistant/test-runner-bid-apply.js +201 -0
  99. package/lib/role-assistant/test-runner-bid-document.js +278 -0
  100. package/lib/role-assistant/test-runner-start-payload.js +96 -0
  101. package/lib/role-assistant/test-runner-workhub-answers.js +249 -20
  102. package/lib/role-assistant/test-runner-workhub-helpers.js +100 -0
  103. package/lib/role-assistant/test-runner-workhub-soft.js +86 -0
  104. package/lib/role-assistant/test-runner-workhub.js +152 -107
  105. package/lib/role-assistant/test-runner.js +5 -63
  106. package/lib/role-assistant/test-suite.js +112 -0
  107. package/lib/schema/application-schema.json +56 -6
  108. package/lib/schema/external-datasource.schema.json +103 -17
  109. package/lib/schema/external-system.schema.json +54 -3
  110. package/lib/schema/integration-definition.schema.json +195 -0
  111. package/lib/utils/authentication-shape.js +6 -0
  112. package/lib/utils/compose-generator.js +10 -1
  113. package/lib/utils/compose-traefik-extra-routes.js +107 -0
  114. package/lib/utils/docker-build.js +2 -2
  115. package/lib/utils/help-builder.js +3 -1
  116. package/lib/utils/promote-dev-docker-image.js +102 -18
  117. package/lib/utils/transient-developer-id.js +28 -0
  118. package/package.json +14 -16
  119. package/templates/README.md +12 -1
  120. package/templates/applications/dataplane/application.yaml +10 -2
  121. package/templates/applications/dataplane/env.template +7 -6
  122. package/templates/applications/miso-controller/application.yaml +23 -8
  123. package/templates/applications/miso-controller/env.template +8 -2
  124. package/templates/applications/miso-controller/rbac.yaml +1 -0
  125. package/templates/channels/README.md +11 -1
  126. package/templates/channels/brand/color-192.png +0 -0
  127. package/templates/channels/brand/dark/128.png +0 -0
  128. package/templates/channels/brand/dark/192.png +0 -0
  129. package/templates/channels/brand/dark/256.png +0 -0
  130. package/templates/channels/brand/dark/32.png +0 -0
  131. package/templates/channels/brand/dark/512.png +0 -0
  132. package/templates/channels/brand/dark/64.png +0 -0
  133. package/templates/channels/brand/light/128.png +0 -0
  134. package/templates/channels/brand/light/192.png +0 -0
  135. package/templates/channels/brand/light/256.png +0 -0
  136. package/templates/channels/brand/light/32.png +0 -0
  137. package/templates/channels/brand/light/512.png +0 -0
  138. package/templates/channels/brand/light/64.png +0 -0
  139. package/templates/channels/brand/mono-white/128.png +0 -0
  140. package/templates/channels/brand/mono-white/192.png +0 -0
  141. package/templates/channels/brand/mono-white/256.png +0 -0
  142. package/templates/channels/brand/mono-white/32.png +0 -0
  143. package/templates/channels/brand/mono-white/512.png +0 -0
  144. package/templates/channels/brand/mono-white/64.png +0 -0
  145. package/templates/channels/brand/outline-32.png +0 -0
  146. package/templates/channels/chatgpt/install.template.md.hbs +6 -4
  147. package/templates/channels/chatgpt/integration/README.md +4 -5
  148. package/templates/channels/chatgpt/integration/chatgpt-system.json +1 -16
  149. package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +14 -16
  150. package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +5 -3
  151. package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +30 -0
  152. package/templates/channels/microsoft-copilot/fi-fi.template.json.hbs +7 -0
  153. package/templates/channels/microsoft-copilot/install.template.md.hbs +93 -22
  154. package/templates/channels/microsoft-copilot/integration/README.md +2 -3
  155. package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +1 -22
  156. package/templates/channels/microsoft-copilot/manifest.template.json.hbs +34 -19
  157. package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +15 -0
  158. package/templates/channels/slack/integration/README.md +2 -4
  159. package/templates/channels/teams-bot/install.template.md.hbs +4 -0
  160. package/templates/channels/teams-bot/integration/README.md +3 -5
  161. package/templates/channels/web-embed/integration/web-embed-system.json +1 -16
  162. package/templates/python/docker-compose.hbs +36 -0
  163. package/templates/typescript/docker-compose.hbs +36 -0
  164. package/.cursor/plans/Done/157.1-security-quality-violations-by-type.csv +0 -374
  165. package/.cursor/process/README.md +0 -9
  166. package/.cursor/rules/anchor-docs.mdc +0 -15
  167. package/.cursor/rules/assistant-driven-integration-build.mdc +0 -40
  168. package/.cursor/rules/cli-layout.mdc +0 -81
  169. package/.cursor/rules/cli-product-neutral.mdc +0 -43
  170. package/.cursor/rules/deploy-rules/docker-image-ip-policy.mdc +0 -49
  171. package/.cursor/rules/docs-rules.mdc +0 -32
  172. package/.cursor/rules/plan-rules/application-lifecycle.mdc +0 -30
  173. package/.cursor/rules/plan-rules/plan-frontmatter.mdc +0 -35
  174. package/.cursor/rules/plan-rules/plan-lifecycle.mdc +0 -31
  175. package/.cursor/rules/plan-rules/plan-validation-gate.mdc +0 -34
  176. package/.cursor/rules/project-rules.mdc +0 -913
  177. package/.cursor/skills/README.md +0 -15
  178. package/.dockerignore +0 -52
  179. package/.eslintignore +0 -22
  180. package/.markdownlint.json +0 -14
  181. package/anchor-docs/README.md +0 -10
  182. package/anchor-docs/_TEMPLATE +0 -24
  183. package/babel.config.js +0 -6
  184. package/bin/builder-api-cleanup.js +0 -26
  185. package/bin/builder-api-nest.js +0 -10
  186. package/bin/builder-api-spike.js +0 -19
  187. package/enterprise-knowledge/README.md +0 -50
  188. package/enterprise-knowledge/enterprise-integration-lifecycle/README.md +0 -22
  189. package/enterprise-knowledge/enterprise-integration-lifecycle/application.json +0 -15
  190. package/enterprise-knowledge/enterprise-integration-lifecycle/deploy.js +0 -69
  191. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-deploy.json +0 -52
  192. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-system.json +0 -29
  193. package/enterprise-knowledge/enterprise-integration-lifecycle/env.template +0 -2
  194. package/integration/README.md +0 -81
  195. package/integration/github/README.md +0 -53
  196. package/integration/github/application.json +0 -21
  197. package/integration/github/deploy.js +0 -72
  198. package/integration/github/env.template +0 -11
  199. package/integration/github/github-datasource-issue-comments.json +0 -239
  200. package/integration/github/github-datasource-issues.json +0 -399
  201. package/integration/github/github-datasource-repository.json +0 -354
  202. package/integration/github/github-deploy.json +0 -1202
  203. package/integration/github/github-system.json +0 -82
  204. package/integration/hubspot-test/README.md +0 -159
  205. package/integration/hubspot-test/application.json +0 -54
  206. package/integration/hubspot-test/companies.json +0 -2048
  207. package/integration/hubspot-test/create-hubspot.js +0 -523
  208. package/integration/hubspot-test/env.template +0 -4
  209. package/integration/hubspot-test/hubspot-test-datasource-company.json +0 -138
  210. package/integration/hubspot-test/hubspot-test-datasource-contact.json +0 -146
  211. package/integration/hubspot-test/hubspot-test-datasource-deal.json +0 -146
  212. package/integration/hubspot-test/hubspot-test-datasource-users.json +0 -76
  213. package/integration/hubspot-test/hubspot-test-deploy.json +0 -2160
  214. package/integration/hubspot-test/hubspot-test-system.json +0 -74
  215. package/integration/hubspot-test/rbac.json +0 -166
  216. package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +0 -20
  217. package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +0 -9
  218. package/integration/hubspot-test/test-artifacts/wizard-invalid-add-datasource.yaml +0 -5
  219. package/integration/hubspot-test/test-artifacts/wizard-invalid-app-name.yaml +0 -5
  220. package/integration/hubspot-test/test-artifacts/wizard-invalid-credential-create.yaml +0 -7
  221. package/integration/hubspot-test/test-artifacts/wizard-invalid-credential-select.yaml +0 -7
  222. package/integration/hubspot-test/test-artifacts/wizard-invalid-known-platform.yaml +0 -4
  223. package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-app.yaml +0 -4
  224. package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-source.yaml +0 -2
  225. package/integration/hubspot-test/test-artifacts/wizard-invalid-mode.yaml +0 -5
  226. package/integration/hubspot-test/test-artifacts/wizard-invalid-openapi-file.yaml +0 -5
  227. package/integration/hubspot-test/test-artifacts/wizard-invalid-openapi-url.yaml +0 -4
  228. package/integration/hubspot-test/test-artifacts/wizard-invalid-source.yaml +0 -4
  229. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-array-test.yaml +0 -5
  230. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-key-test.yaml +0 -5
  231. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-path-test.yaml +0 -5
  232. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-test.yaml +0 -5
  233. package/integration/hubspot-test/test-artifacts/wizard-valid-for-rbac-test.yaml +0 -5
  234. package/integration/hubspot-test/test-artifacts/wizard-valid-for-rbac-yaml-test.yaml +0 -5
  235. package/integration/hubspot-test/test-dataplane-down-helpers.js +0 -249
  236. package/integration/hubspot-test/test-dataplane-down-tests.js +0 -386
  237. package/integration/hubspot-test/test-dataplane-down.js +0 -209
  238. package/integration/hubspot-test/test.js +0 -1588
  239. package/integration/hubspot-test/wizard-hubspot-e2e.yaml +0 -16
  240. package/integration/hubspot-test/wizard-hubspot-platform.yaml +0 -8
  241. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +0 -23
  242. package/integration/roundtrip-test-local/README.md +0 -143
  243. package/integration/roundtrip-test-local/application.yaml +0 -13
  244. package/integration/roundtrip-test-local/env.template +0 -15
  245. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +0 -14
  246. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +0 -61
  247. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +0 -25
  248. package/integration/roundtrip-test-local2/README.md +0 -143
  249. package/integration/roundtrip-test-local2/application.yaml +0 -13
  250. package/integration/roundtrip-test-local2/env.template +0 -15
  251. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +0 -31
  252. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +0 -86
  253. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +0 -25
  254. package/integration/test/wizard.yaml +0 -8
  255. package/jest.config.coverage.js +0 -37
  256. package/jest.config.default.js +0 -11
  257. package/jest.config.integration.fixtures.js +0 -22
  258. package/jest.config.integration.js +0 -33
  259. package/jest.config.isolated.js +0 -11
  260. package/jest.config.manual.js +0 -30
  261. package/jest.global-live-fabrix-hooks.js +0 -36
  262. package/jest.isolated-projects.js +0 -260
  263. package/jest.projects.js +0 -76
  264. package/packages/builder-api/README.md +0 -120
  265. package/packages/builder-api/package.json +0 -30
  266. package/packages/builder-api/src/app.module.ts +0 -7
  267. package/packages/builder-api/src/auth/auth.module.ts +0 -5
  268. package/packages/builder-api/src/external-system/external-system.module.ts +0 -5
  269. package/packages/builder-api/src/main.ts +0 -16
  270. package/packages/builder-api/tsconfig.json +0 -15
  271. package/scripts/check-builder-api-architecture-grep.js +0 -79
  272. package/scripts/check-datasource-test-run-schema-sync.js +0 -34
  273. package/scripts/ci-fix.sh +0 -19
  274. package/scripts/ci-simulate.sh +0 -19
  275. package/scripts/diagnose-cli.js +0 -150
  276. package/scripts/docker_image_content_gate.js +0 -47
  277. package/scripts/docker_image_content_gate.sh +0 -5
  278. package/scripts/export-builder-api-evidence.js +0 -262
  279. package/scripts/install-local.js +0 -490
  280. package/scripts/lib/builder-api-docker-staging-copy.js +0 -60
  281. package/scripts/lib/builder-api-docker-staging-core.js +0 -183
  282. package/scripts/lib/docker-image-content-gate-core.js +0 -166
  283. package/scripts/lib/plan-actor.js +0 -109
  284. package/scripts/lib/plan-config.js +0 -20
  285. package/scripts/lib/plan-gates.js +0 -154
  286. package/scripts/lib/plan-meta.js +0 -104
  287. package/scripts/lib/plan-parse.js +0 -162
  288. package/scripts/lib/plan-prevalidate-gates.js +0 -337
  289. package/scripts/lib/plan-run-core.js +0 -125
  290. package/scripts/lib/plan-run-report.js +0 -119
  291. package/scripts/plan-approve.js +0 -24
  292. package/scripts/plan-archive.js +0 -49
  293. package/scripts/plan-run.js +0 -13
  294. package/scripts/plan-set-actor.js +0 -21
  295. package/scripts/plan-validate.js +0 -80
  296. package/scripts/pnpm/af.mjs +0 -110
  297. package/scripts/pnpm/check-quiet.mjs +0 -32
  298. package/scripts/pnpm/dev-install.mjs +0 -29
  299. package/scripts/pnpm/dev-reload.mjs +0 -18
  300. package/scripts/pnpm/help.mjs +0 -55
  301. package/scripts/pnpm/lib/dev-reload-core.mjs +0 -189
  302. package/scripts/pnpm/lib/dev-reload-log-capture.mjs +0 -67
  303. package/scripts/pnpm/lib/dev-reload-log-utils.mjs +0 -32
  304. package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +0 -124
  305. package/scripts/pnpm/lib/resolve-app-url.mjs +0 -183
  306. package/scripts/pnpm/lib/spinner.mjs +0 -42
  307. package/scripts/pnpm-global-remove.js +0 -48
  308. package/scripts/stage_builder_api_for_docker.js +0 -65
  309. package/scripts/sync-builder-api-template.js +0 -44
  310. package/scripts/test-dataplane-bootstrap.js +0 -331
@@ -68,7 +68,18 @@ function buildHonestyObservation(workResult) {
68
68
  };
69
69
  }
70
70
 
71
- function pushHonestyAssertion(assertions, id, passed, message) {
71
+ function pushHonestyAssertion(assertions, id, passed, message, options = {}) {
72
+ const soft = options.soft === true;
73
+ if (soft && !passed) {
74
+ assertions.push({
75
+ id,
76
+ passed: true,
77
+ soft: true,
78
+ warn: true,
79
+ message: `${message} (soft — warning only)`
80
+ });
81
+ return;
82
+ }
72
83
  assertions.push({ id, passed, message });
73
84
  }
74
85
 
@@ -87,7 +98,7 @@ function assertWorkResultPresent(assertions, honesty, observation) {
87
98
  );
88
99
  }
89
100
 
90
- function assertSchemaVersion(assertions, honestySpec, honesty) {
101
+ function assertSchemaVersion(assertions, honestySpec, honesty, soft) {
91
102
  if (!honestySpec.schemaVersion) {
92
103
  return;
93
104
  }
@@ -99,11 +110,12 @@ function assertSchemaVersion(assertions, honestySpec, honesty) {
99
110
  passed,
100
111
  passed
101
112
  ? `schemaVersion matched "${expected}".`
102
- : `schemaVersion expected "${expected}" but got ${JSON.stringify(honesty.schemaVersion)}.`
113
+ : `schemaVersion expected "${expected}" but got ${JSON.stringify(honesty.schemaVersion)}.`,
114
+ { soft }
103
115
  );
104
116
  }
105
117
 
106
- function assertCompletion(assertions, honestySpec, honesty) {
118
+ function assertCompletion(assertions, honestySpec, honesty, soft) {
107
119
  if (honestySpec.requireCompletion === false) {
108
120
  return;
109
121
  }
@@ -115,11 +127,12 @@ function assertCompletion(assertions, honestySpec, honesty) {
115
127
  stateOk && goalOk,
116
128
  stateOk && goalOk
117
129
  ? `completion.state/goalStatus honest (${honesty.completionState}/${honesty.goalStatus}).`
118
- : `completion missing or invalid: state=${JSON.stringify(honesty.completionState)} goalStatus=${JSON.stringify(honesty.goalStatus)}.`
130
+ : `completion missing or invalid: state=${JSON.stringify(honesty.completionState)} goalStatus=${JSON.stringify(honesty.goalStatus)}.`,
131
+ { soft }
119
132
  );
120
133
  }
121
134
 
122
- function assertContribution(assertions, honestySpec, honesty) {
135
+ function assertContribution(assertions, honestySpec, honesty, soft) {
123
136
  if (honestySpec.requireContributionObservation === false) {
124
137
  return;
125
138
  }
@@ -130,7 +143,8 @@ function assertContribution(assertions, honestySpec, honesty) {
130
143
  ok,
131
144
  ok
132
145
  ? `contributionObservation.status honest (${honesty.contributionStatus}).`
133
- : `contributionObservation.status missing or invalid: ${JSON.stringify(honesty.contributionStatus)}.`
146
+ : `contributionObservation.status missing or invalid: ${JSON.stringify(honesty.contributionStatus)}.`,
147
+ { soft }
134
148
  );
135
149
  }
136
150
 
@@ -171,9 +185,9 @@ function evaluateHonestyExpectations(honestySpec, observation, options = {}) {
171
185
  // Missing Output is always a hard failure when required — soft does not waive it.
172
186
  return assertions;
173
187
  }
174
- assertSchemaVersion(assertions, honestySpec, honesty);
175
- assertCompletion(assertions, honestySpec, honesty);
176
- assertContribution(assertions, honestySpec, honesty);
188
+ assertSchemaVersion(assertions, honestySpec, honesty, soft);
189
+ assertCompletion(assertions, honestySpec, honesty, soft);
190
+ assertContribution(assertions, honestySpec, honesty, soft);
177
191
  assertMinResourceChanges(assertions, honestySpec, honesty, soft);
178
192
  return assertions;
179
193
  }
@@ -331,6 +331,32 @@ function collectCapabilitiesFromWorkSteps(out, steps) {
331
331
  }
332
332
  }
333
333
 
334
+ /**
335
+ * Work-result artifactIndex often carries CIP fingerprints like
336
+ * `capabilityKey=customer.createBasic|operationId=createbasic` when steps[] is empty.
337
+ * @param {Set<string>} out
338
+ * @param {unknown} artifacts
339
+ */
340
+ function collectCapabilitiesFromArtifactIndex(out, artifacts) {
341
+ if (!Array.isArray(artifacts)) return;
342
+ for (const row of artifacts) {
343
+ if (!row || typeof row !== 'object') continue;
344
+ addCapabilityToken(out, row.capabilityKey);
345
+ addCapabilityToken(out, row.capability);
346
+ const fingerprint = typeof row.fingerprint === 'string' ? row.fingerprint : '';
347
+ const match = fingerprint.match(/(?:^|[|,])capabilityKey=([^|,]+)/);
348
+ if (match) {
349
+ addCapabilityToken(out, match[1]);
350
+ }
351
+ const artifactRef = typeof row.artifactRef === 'string' ? row.artifactRef : '';
352
+ // cip-log:fallback:customer.create:create:<id>
353
+ const refMatch = artifactRef.match(/^cip-log:[^:]+:([^:]+):/);
354
+ if (refMatch) {
355
+ addCapabilityToken(out, refMatch[1]);
356
+ }
357
+ }
358
+ }
359
+
334
360
  function collectObservedCapabilities(result) {
335
361
  const out = new Set();
336
362
  const steps = Array.isArray(result?.stepsRun) ? result.stepsRun : [];
@@ -341,6 +367,8 @@ function collectObservedCapabilities(result) {
341
367
  }
342
368
  collectCapabilitiesFromWorkSteps(out, result?.steps);
343
369
  collectCapabilitiesFromWorkSteps(out, result?.workResult?.steps);
370
+ collectCapabilitiesFromArtifactIndex(out, result?.workResult?.artifactIndex);
371
+ collectCapabilitiesFromArtifactIndex(out, result?.artifactIndex);
344
372
  addCapabilityToken(out, result?.task?.capabilityKey);
345
373
  addCapabilityToken(out, result?.task?.capability);
346
374
  if (result?.task?.approvalContext && typeof result.task.approvalContext === 'object') {
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Build work.start attachments from case YAML (paths / openapiDir).
3
+ * @fileoverview 517.1 — map suite OpenAPI files to ATT attachment shape
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ const path = require('path');
9
+ const fs = require('../internal/fs-real-sync');
10
+
11
+ function resolveCaseDirectory(testCase) {
12
+ const sourceFile =
13
+ testCase && typeof testCase.sourceFile === 'string' ? testCase.sourceFile.trim() : '';
14
+ if (!sourceFile) {
15
+ return process.cwd();
16
+ }
17
+ return path.dirname(path.resolve(sourceFile));
18
+ }
19
+
20
+ function readJsonAttachmentBody(absolutePath) {
21
+ if (!fs.existsSync(absolutePath)) {
22
+ throw new Error(`Role assistant attachment file not found: ${absolutePath}`);
23
+ }
24
+ const text = fs.readFileSync(absolutePath, 'utf8');
25
+ try {
26
+ return JSON.parse(text);
27
+ } catch (error) {
28
+ throw new Error(`Role assistant attachment is not valid JSON: ${absolutePath}`);
29
+ }
30
+ }
31
+
32
+ function attachmentFromFile(absolutePath, meta = {}) {
33
+ const basename = path.basename(absolutePath);
34
+ const role = typeof meta.role === 'string' && meta.role.trim() ? meta.role.trim() : 'openapi';
35
+ return {
36
+ name: basename,
37
+ filename: basename,
38
+ mediaType: 'application/json',
39
+ role,
40
+ contributionPurpose: 'task',
41
+ body: readJsonAttachmentBody(absolutePath)
42
+ };
43
+ }
44
+
45
+ function resolveRelativeAttachmentPath(caseDir, relativePath) {
46
+ if (typeof relativePath !== 'string' || !relativePath.trim()) {
47
+ throw new Error('Role assistant attachment path must be a non-empty string');
48
+ }
49
+ const absolutePath = path.resolve(caseDir, relativePath.trim());
50
+ return absolutePath;
51
+ }
52
+
53
+ function collectExplicitAttachments(caseDir, attachments) {
54
+ if (!Array.isArray(attachments) || attachments.length === 0) {
55
+ return [];
56
+ }
57
+ return attachments.map((row) => {
58
+ if (!row || typeof row !== 'object' || Array.isArray(row)) {
59
+ throw new Error('Role assistant input.attachments entries must be objects');
60
+ }
61
+ const rel = row.path || row.file || row.filename;
62
+ const absolutePath = resolveRelativeAttachmentPath(caseDir, rel);
63
+ return attachmentFromFile(absolutePath, row);
64
+ });
65
+ }
66
+
67
+ function listOpenapiJsonFiles(absoluteDir, allowList) {
68
+ if (!fs.existsSync(absoluteDir)) {
69
+ throw new Error(`Role assistant openapiDir not found: ${absoluteDir}`);
70
+ }
71
+ const names = fs
72
+ .readdirSync(absoluteDir)
73
+ .filter((entry) => /\.json$/i.test(entry))
74
+ .sort();
75
+ if (Array.isArray(allowList) && allowList.length > 0) {
76
+ const wanted = new Set(allowList.map((row) => String(row).trim()).filter(Boolean));
77
+ return names.filter((name) => wanted.has(name));
78
+ }
79
+ return names;
80
+ }
81
+
82
+ function collectOpenapiDirAttachments(caseDir, input) {
83
+ if (typeof input.openapiDir !== 'string' || !input.openapiDir.trim()) {
84
+ return [];
85
+ }
86
+ const absoluteDir = path.resolve(caseDir, input.openapiDir.trim());
87
+ const files = listOpenapiJsonFiles(absoluteDir, input.openapiFiles);
88
+ if (files.length === 0) {
89
+ throw new Error(`Role assistant openapiDir has no matching *.json files: ${absoluteDir}`);
90
+ }
91
+ return files.map((name) => attachmentFromFile(path.join(absoluteDir, name), { role: 'openapi' }));
92
+ }
93
+
94
+ /**
95
+ * Build ATT-shaped attachments for work.start from case input.
96
+ * @param {Object} testCase - Normalized case (may include sourceFile)
97
+ * @returns {Object[]|undefined}
98
+ */
99
+ function buildStartAttachments(testCase) {
100
+ const input =
101
+ testCase && typeof testCase.input === 'object' && testCase.input && !Array.isArray(testCase.input)
102
+ ? testCase.input
103
+ : {};
104
+ const caseDir = resolveCaseDirectory(testCase);
105
+ const fromExplicit = collectExplicitAttachments(caseDir, input.attachments);
106
+ const fromDir = collectOpenapiDirAttachments(caseDir, input);
107
+ const merged = [...fromExplicit, ...fromDir];
108
+ if (merged.length === 0) {
109
+ return undefined;
110
+ }
111
+ return merged;
112
+ }
113
+
114
+ module.exports = {
115
+ buildStartAttachments,
116
+ resolveCaseDirectory,
117
+ attachmentFromFile
118
+ };
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Soft-loop BID apply after workspace.createsystem (suite 002 / plan 512.4).
3
+ * @fileoverview LAB-ONLY debt helper: POST Builder-api HTTP apply when the RA
4
+ * soft loop needs a package materialize. Product path is Decision Engine →
5
+ * capability.execute(template.applyintegrationdefinition) → COM/CIP.
6
+ * Do not treat this module as the product apply path once Runtime COM invoke
7
+ * works for the suite (plan 517.5). Non-product — lab helper only.
8
+ */
9
+
10
+ 'use strict';
11
+
12
+ const fs = require('../internal/fs-real-sync');
13
+ const path = require('path');
14
+ const {
15
+ loadCaseBidDocument,
16
+ resolveTargetSystemKey
17
+ } = require('./test-runner-bid-document');
18
+ const { buildStartAttachments } = require('./test-runner-attachments');
19
+
20
+ /**
21
+ * @returns {string}
22
+ */
23
+ function resolveBuilderApiBaseUrl() {
24
+ const fromEnv = String(process.env.BUILDER_API_URL || process.env.BUILDER_URL || '').trim();
25
+ if (fromEnv) {
26
+ return fromEnv.replace(/\/$/, '');
27
+ }
28
+ let developerId = 0;
29
+ try {
30
+ const yaml = require('js-yaml');
31
+ const cfgPath = path.join(
32
+ process.env.HOME || '',
33
+ '.aifabrix',
34
+ 'config.yaml'
35
+ );
36
+ if (fs.existsSync(cfgPath)) {
37
+ const cfg = yaml.load(fs.readFileSync(cfgPath, 'utf8')) || {};
38
+ developerId = Number(cfg['developer-id'] || cfg.developerId || 0) || 0;
39
+ }
40
+ } catch (_err) {
41
+ developerId = 0;
42
+ }
43
+ return `http://localhost:${3005 + developerId * 100}`;
44
+ }
45
+
46
+ /**
47
+ * @param {Object} authConfig
48
+ * @returns {string}
49
+ */
50
+ function extractBearer(authConfig) {
51
+ if (!authConfig || typeof authConfig !== 'object') {
52
+ return '';
53
+ }
54
+ if (typeof authConfig.token === 'string' && authConfig.token.trim()) {
55
+ return authConfig.token.trim();
56
+ }
57
+ if (typeof authConfig.bearerToken === 'string' && authConfig.bearerToken.trim()) {
58
+ return authConfig.bearerToken.trim();
59
+ }
60
+ const header = authConfig.headers && authConfig.headers.Authorization;
61
+ const m = /^Bearer\s+(.+)$/i.exec(String(header || ''));
62
+ return m ? m[1].trim() : '';
63
+ }
64
+
65
+ /**
66
+ * True when wait is for template.applyintegrationdefinition and a case BID exists.
67
+ * @param {Object} testCase
68
+ * @param {Object} wait
69
+ * @returns {boolean}
70
+ */
71
+ function shouldApplyBidAfterWait(testCase, wait) {
72
+ const bid = loadCaseBidDocument(testCase);
73
+ if (!bid) {
74
+ return false;
75
+ }
76
+ const capability = String(
77
+ wait.questionKey || wait.objectRef?.capabilityKey || wait.prompt || ''
78
+ ).toLowerCase();
79
+ // Product path: DE → capability.execute(template.applyintegrationdefinition).
80
+ return capability.includes('applyintegrationdefinition');
81
+ }
82
+
83
+ /**
84
+ * Lab-only soft HTTP BID apply. Hard cases (expected.soft !== true) must rely on
85
+ * Runtime COM/CIP apply after respond+continue — not Builder-api HTTP (517.5 / 517.4.7).
86
+ * @param {Object} testCase
87
+ * @param {Object} wait
88
+ * @returns {boolean}
89
+ */
90
+ function shouldSoftHttpBidApply(testCase, wait) {
91
+ if (!shouldApplyBidAfterWait(testCase, wait)) {
92
+ return false;
93
+ }
94
+ return testCase?.expected?.soft === true;
95
+ }
96
+
97
+ /**
98
+ * @param {Object} testCase
99
+ * @returns {Object[]|null}
100
+ */
101
+ function collectOpenApiPersistDocuments(testCase) {
102
+ let attachments = [];
103
+ try {
104
+ attachments = buildStartAttachments(testCase) || [];
105
+ } catch (_err) {
106
+ return null;
107
+ }
108
+ const documents = attachments
109
+ .filter((row) => row && (row.role === 'openapi' || !row.role) && row.body)
110
+ .map((row) => ({
111
+ filename: row.filename || row.name,
112
+ body: row.body
113
+ }))
114
+ .filter((row) => row.filename);
115
+ return documents.length > 0 ? documents : null;
116
+ }
117
+
118
+ /**
119
+ * @param {Response} res
120
+ * @param {string} label
121
+ * @returns {Promise<Object|null>}
122
+ */
123
+ async function readBuilderApiJsonOrThrow(res, label) {
124
+ const text = await res.text();
125
+ let body = null;
126
+ try {
127
+ body = text ? JSON.parse(text) : null;
128
+ } catch (_err) {
129
+ body = { raw: text };
130
+ }
131
+ if (!res.ok) {
132
+ const err = new Error(
133
+ `${label} HTTP ${res.status}: ${typeof body === 'object' ? JSON.stringify(body).slice(0, 300) : text}`
134
+ );
135
+ err.status = res.status;
136
+ throw err;
137
+ }
138
+ return body && body.data ? body.data : body;
139
+ }
140
+
141
+ /**
142
+ * Lab debt: stage suite OpenAPI into workspace via 517.2 persist API before apply.
143
+ * Product path is DE → capability.execute(persistsuppliedopenapi).
144
+ * @param {Object} authConfig
145
+ * @param {Object} testCase
146
+ * @param {string} systemKey
147
+ * @returns {Promise<Object|null>}
148
+ */
149
+ async function persistCaseOpenApiViaBuilderApi(authConfig, testCase, systemKey) {
150
+ const token = extractBearer(authConfig);
151
+ if (!token || !systemKey) {
152
+ return null;
153
+ }
154
+ const documents = collectOpenApiPersistDocuments(testCase);
155
+ if (!documents) {
156
+ return null;
157
+ }
158
+ const url = `${resolveBuilderApiBaseUrl()}/api/v1/builder/systems/${encodeURIComponent(systemKey)}/openapi/persist-supplied`;
159
+ const res = await fetch(url, {
160
+ method: 'POST',
161
+ headers: {
162
+ Authorization: `Bearer ${token}`,
163
+ 'Content-Type': 'application/json'
164
+ },
165
+ body: JSON.stringify({ documents })
166
+ });
167
+ return readBuilderApiJsonOrThrow(res, 'OpenAPI persist failed');
168
+ }
169
+
170
+ /**
171
+ * @param {Object} authConfig
172
+ * @param {Object} testCase
173
+ * @returns {Promise<Object|null>}
174
+ */
175
+ async function applyCaseBidViaBuilderApi(authConfig, testCase) {
176
+ const bid = loadCaseBidDocument(testCase);
177
+ const systemKey = resolveTargetSystemKey(testCase);
178
+ const token = extractBearer(authConfig);
179
+ if (!bid || !systemKey || !token) {
180
+ return null;
181
+ }
182
+ await persistCaseOpenApiViaBuilderApi(authConfig, testCase, systemKey);
183
+ const url = `${resolveBuilderApiBaseUrl()}/api/v1/builder/systems/${encodeURIComponent(systemKey)}/integration-definition/apply`;
184
+ const res = await fetch(url, {
185
+ method: 'POST',
186
+ headers: {
187
+ Authorization: `Bearer ${token}`,
188
+ 'Content-Type': 'application/json'
189
+ },
190
+ body: JSON.stringify({ integrationDefinition: bid, force: true })
191
+ });
192
+ return readBuilderApiJsonOrThrow(res, 'BID apply failed');
193
+ }
194
+
195
+ module.exports = {
196
+ resolveBuilderApiBaseUrl,
197
+ shouldApplyBidAfterWait,
198
+ shouldSoftHttpBidApply,
199
+ persistCaseOpenApiViaBuilderApi,
200
+ applyCaseBidViaBuilderApi
201
+ };