@aifabrix/builder 2.52.1 → 2.53.1

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 (225) hide show
  1. package/lib/app/deploy-config.js +3 -2
  2. package/lib/channels/add-channel.js +11 -41
  3. package/lib/channels/approval-guides/index.js +3 -0
  4. package/lib/channels/approval-guides/microsoft-copilot.js +26 -17
  5. package/lib/channels/channel-add-existing.js +72 -0
  6. package/lib/channels/channel-runtime-resolver.js +5 -1
  7. package/lib/channels/channel-status-display.js +30 -3
  8. package/lib/channels/microsoft-copilot-entra-sso-form.js +73 -2
  9. package/lib/channels/microsoft-copilot-entra-sso.js +26 -5
  10. package/lib/channels/microsoft-copilot-limits.js +22 -3
  11. package/lib/channels/microsoft-copilot-package.js +59 -14
  12. package/lib/channels/microsoft-copilot-validate.js +40 -10
  13. package/lib/cli/attach-default-help-examples.js +102 -0
  14. package/lib/cli/index.js +2 -0
  15. package/lib/cli/setup-credential-deployment.js +7 -5
  16. package/lib/cli/setup-utility-validate.js +1 -0
  17. package/lib/commands/credential-push.js +37 -5
  18. package/lib/commands/package-score.js +72 -0
  19. package/lib/commands/role-assistant.js +46 -8
  20. package/lib/deployment/deployer-poll-run.js +2 -2
  21. package/lib/deployment/deployer.js +1 -1
  22. package/lib/deployment/environment.js +2 -2
  23. package/lib/external-system/deploy.js +11 -21
  24. package/lib/integration-definition/apply.js +12 -14
  25. package/lib/integration-definition/enrich-openapi-operations.js +9 -10
  26. package/lib/lab/package-parity-score.js +417 -0
  27. package/lib/programmatic/capability-registry.js +1 -0
  28. package/lib/programmatic/help-content/channel-onboarding.md +35 -0
  29. package/lib/programmatic/help-content/cip-overview.md +27 -0
  30. package/lib/programmatic/help-content/connected-system-ui.md +70 -0
  31. package/lib/programmatic/help-content/dimensions-guide.md +23 -0
  32. package/lib/programmatic/help-content/enterprise-sync-fabrix.md +123 -0
  33. package/lib/programmatic/help-content/overview.md +25 -0
  34. package/lib/programmatic/help-content/subscription-guide.md +27 -0
  35. package/lib/programmatic/help-content/workflow.md +50 -0
  36. package/lib/programmatic/openapi-component-schemas.js +1 -0
  37. package/lib/programmatic/openapi-descriptions.js +6 -0
  38. package/lib/programmatic/openapi-envelope-examples.js +11 -0
  39. package/lib/programmatic/openapi-operation-bindings.js +5 -0
  40. package/lib/programmatic/openapi-request-schemas.js +39 -13
  41. package/lib/programmatic/openapi-result-schemas.js +30 -0
  42. package/lib/programmatic/openapi-schema-descriptions-core.js +18 -0
  43. package/lib/programmatic/openapi-schema-descriptions-operations.js +19 -0
  44. package/lib/programmatic/persist-supplied-openapi.js +180 -0
  45. package/lib/programmatic/route-handler-map.js +6 -0
  46. package/lib/programmatic/run-integration-definition.js +13 -5
  47. package/lib/role-assistant/evidence-sync.js +55 -7
  48. package/lib/role-assistant/test-runner-attachments.js +118 -0
  49. package/lib/role-assistant/test-runner-bid-apply.js +100 -21
  50. package/lib/role-assistant/test-runner-bid-document.js +1 -1
  51. package/lib/role-assistant/test-runner-start-payload.js +96 -0
  52. package/lib/role-assistant/test-runner-workhub-answers.js +11 -7
  53. package/lib/role-assistant/test-runner-workhub-helpers.js +100 -0
  54. package/lib/role-assistant/test-runner-workhub-soft.js +86 -0
  55. package/lib/role-assistant/test-runner-workhub.js +68 -105
  56. package/lib/role-assistant/test-runner.js +5 -63
  57. package/lib/role-assistant/test-suite.js +33 -40
  58. package/lib/schema/external-datasource.schema.json +13 -4
  59. package/lib/utils/compose-generator.js +10 -1
  60. package/lib/utils/compose-traefik-extra-routes.js +107 -0
  61. package/lib/utils/docker-build.js +2 -2
  62. package/lib/utils/help-builder.js +2 -1
  63. package/lib/utils/promote-dev-docker-image.js +15 -10
  64. package/package.json +14 -16
  65. package/templates/README.md +12 -1
  66. package/templates/applications/dataplane/application.yaml +8 -1
  67. package/templates/applications/dataplane/env.template +1 -1
  68. package/templates/applications/miso-controller/application.yaml +2 -1
  69. package/templates/applications/miso-controller/rbac.yaml +1 -0
  70. package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +6 -2
  71. package/templates/channels/microsoft-copilot/entra-sso-registration.template.md.hbs +8 -5
  72. package/templates/channels/microsoft-copilot/fi-fi.template.json.hbs +7 -0
  73. package/templates/channels/microsoft-copilot/install.template.md.hbs +74 -22
  74. package/templates/channels/microsoft-copilot/manifest.template.json.hbs +29 -14
  75. package/templates/channels/microsoft-copilot/oauth-plugin-vault-required.template.md.hbs +6 -2
  76. package/templates/python/docker-compose.hbs +36 -0
  77. package/templates/typescript/docker-compose.hbs +36 -0
  78. package/.cursor/plans/Archive/157.1-security-quality-violations-by-type.csv +0 -374
  79. package/.cursor/process/README.md +0 -9
  80. package/.cursor/rules/anchor-docs.mdc +0 -15
  81. package/.cursor/rules/assistant-driven-integration-build.mdc +0 -40
  82. package/.cursor/rules/cli-layout.mdc +0 -81
  83. package/.cursor/rules/cli-product-neutral.mdc +0 -43
  84. package/.cursor/rules/deploy-rules/docker-image-ip-policy.mdc +0 -49
  85. package/.cursor/rules/docs-rules.mdc +0 -32
  86. package/.cursor/rules/plan-rules/application-lifecycle.mdc +0 -30
  87. package/.cursor/rules/plan-rules/plan-frontmatter.mdc +0 -35
  88. package/.cursor/rules/plan-rules/plan-lifecycle.mdc +0 -31
  89. package/.cursor/rules/plan-rules/plan-validation-gate.mdc +0 -34
  90. package/.cursor/rules/project-rules.mdc +0 -913
  91. package/.cursor/skills/README.md +0 -15
  92. package/.dockerignore +0 -52
  93. package/.eslintignore +0 -22
  94. package/.markdownlint.json +0 -14
  95. package/anchor-docs/README.md +0 -10
  96. package/anchor-docs/_TEMPLATE +0 -24
  97. package/babel.config.js +0 -6
  98. package/bin/builder-api-cleanup.js +0 -26
  99. package/bin/builder-api-nest.js +0 -10
  100. package/bin/builder-api-spike.js +0 -19
  101. package/enterprise-knowledge/README.md +0 -50
  102. package/enterprise-knowledge/enterprise-integration-lifecycle/README.md +0 -22
  103. package/enterprise-knowledge/enterprise-integration-lifecycle/application.json +0 -15
  104. package/enterprise-knowledge/enterprise-integration-lifecycle/deploy.js +0 -69
  105. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-deploy.json +0 -52
  106. package/enterprise-knowledge/enterprise-integration-lifecycle/enterprise-integration-lifecycle-system.json +0 -29
  107. package/enterprise-knowledge/enterprise-integration-lifecycle/env.template +0 -2
  108. package/integration/README.md +0 -81
  109. package/integration/github/README.md +0 -53
  110. package/integration/github/application.json +0 -21
  111. package/integration/github/deploy.js +0 -72
  112. package/integration/github/env.template +0 -11
  113. package/integration/github/github-datasource-issue-comments.json +0 -239
  114. package/integration/github/github-datasource-issues.json +0 -399
  115. package/integration/github/github-datasource-repository.json +0 -354
  116. package/integration/github/github-deploy.json +0 -1202
  117. package/integration/github/github-system.json +0 -82
  118. package/integration/hubspot-test/README.md +0 -159
  119. package/integration/hubspot-test/application.json +0 -54
  120. package/integration/hubspot-test/companies.json +0 -2048
  121. package/integration/hubspot-test/create-hubspot.js +0 -523
  122. package/integration/hubspot-test/env.template +0 -4
  123. package/integration/hubspot-test/hubspot-test-datasource-company.json +0 -138
  124. package/integration/hubspot-test/hubspot-test-datasource-contact.json +0 -146
  125. package/integration/hubspot-test/hubspot-test-datasource-deal.json +0 -146
  126. package/integration/hubspot-test/hubspot-test-datasource-users.json +0 -76
  127. package/integration/hubspot-test/hubspot-test-deploy.json +0 -2160
  128. package/integration/hubspot-test/hubspot-test-system.json +0 -74
  129. package/integration/hubspot-test/rbac.json +0 -166
  130. package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +0 -20
  131. package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +0 -9
  132. package/integration/hubspot-test/test-artifacts/wizard-invalid-add-datasource.yaml +0 -5
  133. package/integration/hubspot-test/test-artifacts/wizard-invalid-app-name.yaml +0 -5
  134. package/integration/hubspot-test/test-artifacts/wizard-invalid-credential-create.yaml +0 -7
  135. package/integration/hubspot-test/test-artifacts/wizard-invalid-credential-select.yaml +0 -7
  136. package/integration/hubspot-test/test-artifacts/wizard-invalid-known-platform.yaml +0 -4
  137. package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-app.yaml +0 -4
  138. package/integration/hubspot-test/test-artifacts/wizard-invalid-missing-source.yaml +0 -2
  139. package/integration/hubspot-test/test-artifacts/wizard-invalid-mode.yaml +0 -5
  140. package/integration/hubspot-test/test-artifacts/wizard-invalid-openapi-file.yaml +0 -5
  141. package/integration/hubspot-test/test-artifacts/wizard-invalid-openapi-url.yaml +0 -4
  142. package/integration/hubspot-test/test-artifacts/wizard-invalid-source.yaml +0 -4
  143. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-array-test.yaml +0 -5
  144. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-key-test.yaml +0 -5
  145. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-path-test.yaml +0 -5
  146. package/integration/hubspot-test/test-artifacts/wizard-valid-for-dimension-test.yaml +0 -5
  147. package/integration/hubspot-test/test-artifacts/wizard-valid-for-rbac-test.yaml +0 -5
  148. package/integration/hubspot-test/test-artifacts/wizard-valid-for-rbac-yaml-test.yaml +0 -5
  149. package/integration/hubspot-test/test-dataplane-down-helpers.js +0 -249
  150. package/integration/hubspot-test/test-dataplane-down-tests.js +0 -386
  151. package/integration/hubspot-test/test-dataplane-down.js +0 -209
  152. package/integration/hubspot-test/test.js +0 -1588
  153. package/integration/hubspot-test/wizard-hubspot-e2e.yaml +0 -16
  154. package/integration/hubspot-test/wizard-hubspot-platform.yaml +0 -8
  155. package/integration/hubspot-test/wizard-hubspot-test-headless.yaml +0 -23
  156. package/integration/roundtrip-test-local/README.md +0 -143
  157. package/integration/roundtrip-test-local/application.yaml +0 -13
  158. package/integration/roundtrip-test-local/env.template +0 -15
  159. package/integration/roundtrip-test-local/roundtrip-test-local-datasource-roundtrip-test-company.yaml +0 -14
  160. package/integration/roundtrip-test-local/roundtrip-test-local-deploy.json +0 -61
  161. package/integration/roundtrip-test-local/roundtrip-test-local-system.yaml +0 -25
  162. package/integration/roundtrip-test-local2/README.md +0 -143
  163. package/integration/roundtrip-test-local2/application.yaml +0 -13
  164. package/integration/roundtrip-test-local2/env.template +0 -15
  165. package/integration/roundtrip-test-local2/roundtrip-test-local2-datasource-company.yaml +0 -31
  166. package/integration/roundtrip-test-local2/roundtrip-test-local2-deploy.json +0 -86
  167. package/integration/roundtrip-test-local2/roundtrip-test-local2-system.yaml +0 -25
  168. package/integration/test/wizard.yaml +0 -8
  169. package/jest.config.coverage.js +0 -37
  170. package/jest.config.default.js +0 -11
  171. package/jest.config.integration.fixtures.js +0 -22
  172. package/jest.config.integration.js +0 -33
  173. package/jest.config.isolated.js +0 -11
  174. package/jest.config.manual.js +0 -30
  175. package/jest.global-live-fabrix-hooks.js +0 -36
  176. package/jest.isolated-projects.js +0 -283
  177. package/jest.projects.js +0 -79
  178. package/lib/integration-definition/openapi-enrichment/hubspot-crm-companies.json +0 -205
  179. package/packages/builder-api/README.md +0 -120
  180. package/packages/builder-api/package.json +0 -30
  181. package/packages/builder-api/src/app.module.ts +0 -7
  182. package/packages/builder-api/src/auth/auth.module.ts +0 -5
  183. package/packages/builder-api/src/external-system/external-system.module.ts +0 -5
  184. package/packages/builder-api/src/main.ts +0 -16
  185. package/packages/builder-api/tsconfig.json +0 -15
  186. package/scripts/check-builder-api-architecture-grep.js +0 -79
  187. package/scripts/check-datasource-test-run-schema-sync.js +0 -34
  188. package/scripts/ci-fix.sh +0 -19
  189. package/scripts/ci-simulate.sh +0 -19
  190. package/scripts/diagnose-cli.js +0 -150
  191. package/scripts/docker_image_content_gate.js +0 -47
  192. package/scripts/docker_image_content_gate.sh +0 -5
  193. package/scripts/export-builder-api-evidence.js +0 -262
  194. package/scripts/install-local.js +0 -490
  195. package/scripts/lib/builder-api-docker-staging-copy.js +0 -60
  196. package/scripts/lib/builder-api-docker-staging-core.js +0 -183
  197. package/scripts/lib/docker-image-content-gate-core.js +0 -166
  198. package/scripts/lib/plan-actor.js +0 -109
  199. package/scripts/lib/plan-config.js +0 -20
  200. package/scripts/lib/plan-gates.js +0 -154
  201. package/scripts/lib/plan-meta.js +0 -104
  202. package/scripts/lib/plan-parse.js +0 -162
  203. package/scripts/lib/plan-prevalidate-gates.js +0 -337
  204. package/scripts/lib/plan-run-core.js +0 -125
  205. package/scripts/lib/plan-run-report.js +0 -119
  206. package/scripts/plan-approve.js +0 -24
  207. package/scripts/plan-archive.js +0 -49
  208. package/scripts/plan-run.js +0 -13
  209. package/scripts/plan-set-actor.js +0 -21
  210. package/scripts/plan-validate.js +0 -80
  211. package/scripts/pnpm/af.mjs +0 -125
  212. package/scripts/pnpm/check-quiet.mjs +0 -32
  213. package/scripts/pnpm/dev-install.mjs +0 -29
  214. package/scripts/pnpm/dev-reload.mjs +0 -18
  215. package/scripts/pnpm/help.mjs +0 -55
  216. package/scripts/pnpm/lib/dev-reload-core.mjs +0 -189
  217. package/scripts/pnpm/lib/dev-reload-log-capture.mjs +0 -67
  218. package/scripts/pnpm/lib/dev-reload-log-utils.mjs +0 -32
  219. package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +0 -124
  220. package/scripts/pnpm/lib/resolve-app-url.mjs +0 -183
  221. package/scripts/pnpm/lib/spinner.mjs +0 -42
  222. package/scripts/pnpm-global-remove.js +0 -48
  223. package/scripts/stage_builder_api_for_docker.js +0 -65
  224. package/scripts/sync-builder-api-template.js +0 -44
  225. package/scripts/test-dataplane-bootstrap.js +0 -331
@@ -0,0 +1,70 @@
1
+ # Connected Systems UI navigation
2
+
3
+ Use this topic after validate, test, test-integration, and upload succeed without resolved integration secrets in Builder API scope.
4
+
5
+ ## Post-upload authentication handoff
6
+
7
+ Upload publishes the external system manifest. The user adds **live secrets only** in the dataplane Connected Systems Authentication tab — not by pasting tokens into Builder API or workspace files.
8
+
9
+ Authentication is declared on the **external system** manifest (`authentications[]` with usage slots, or legacy `authentication` normalized by repair), not on individual datasource manifests. Datasources inherit linked system credentials at sync and CIP runtime.
10
+
11
+ ### Variables vs secrets (manifest split)
12
+
13
+ | Manifest path | When to set | After upload |
14
+ | --- | --- | --- |
15
+ | `authentication.credential.variables` | During manifest editing (Builder API) | Published and **pre-filled** in Authentication UI — user does not re-enter |
16
+ | `authentication.credential.security` | kv:// placeholders in manifest only | User adds **live secret values** in Authentication UI (for example token, apiKey, clientSecret) |
17
+
18
+ **Enterprise-ready pattern:** put baseUrl, headerName, tokenUrl, prefix, testEndpoint, and similar non-secrets in `variables` before upload. After upload, the user opens Authentication and adds only the token or other required secret.
19
+
20
+ Before prompting the user:
21
+
22
+ 1. Read `authentications[]` usage slots from the published system manifest (prefer over legacy `authentication`).
23
+ 2. For each slot, read `authType` and `credential.method` when applicable.
24
+ 3. Confirm `variables` are already complete in the manifest — do not ask the user to supply them again.
25
+ 4. Tell the user which **secret keys only** they must add in the UI (`requiredSecretKeys`).
26
+ 5. When webhook or syncBridge is enabled, also hand off to datasource **Sync** tab (`tab=sync`) for activation guide URLs.
27
+
28
+ ## Authentication modes (authType)
29
+
30
+ | authType | Where in manifest | User action in UI |
31
+ | --- | --- | --- |
32
+ | `credential` | `authentication.credential` | Add secret values only; variables already pre-filled |
33
+ | `apiProvider` | `authentication.apiProvider.apiProviderKey` | Link the Miso API Provider — no local vendor secrets |
34
+ | `none` | `authentication.authType` only | No credential handoff unless live tests fail for other reasons |
35
+
36
+ ## Credential methods (when authType is credential)
37
+
38
+ Methods come from `external-system.schema.json` (`authentication.credential.method`). User adds **secrets only** after upload:
39
+
40
+ | method | User adds in UI (secrets only) | Already in manifest variables |
41
+ | --- | --- | --- |
42
+ | `oauth2` | clientSecret (clientId if empty) | baseUrl, tokenUrl, grantType, scope |
43
+ | `aad` | clientSecret (clientId if empty) | baseUrl, tokenUrl, tenantId, grantType |
44
+ | `apikey` | apiKey (token) | baseUrl, headerName, prefix, testEndpoint |
45
+ | `bearerToken` | token | baseUrl, headerName, prefix, testEndpoint |
46
+ | `basic` | username, password | baseUrl, testEndpoint |
47
+ | `queryParam` | paramValue | baseUrl, paramName, testEndpoint |
48
+ | `oidc` | any remaining OIDC secrets shown | openIdConfigUrl, clientId |
49
+ | `hmac` | signingSecret | algorithm, signature headers |
50
+ | `none` | none | — |
51
+
52
+ Use optional query params `authType` and `credentialMethod` on this topic to get `manifestHandoff.promptHints` tailored to the manifest.
53
+
54
+ ## URL structure
55
+
56
+ Combine `{dataplanePublicBase}` with a relative path:
57
+
58
+ - System: `/connected-systems/{systemKey}?tab=authentication`
59
+ - Datasource: `/connected-systems/{systemKey}/datasources/{datasourceKey}?tab={tab}`
60
+
61
+ Omit `?tab=` for the default Overview tab on each level. Tab values are case-insensitive; aliases are listed in the structured `systemTabs` and `datasourceTabs` arrays on this topic.
62
+
63
+ ## Typical tabs after publish
64
+
65
+ | Goal | System tab value |
66
+ | --- | --- |
67
+ | Add token / secrets | `authentication` |
68
+ | Review datasources | `datasources` or `business-entities` |
69
+ | Sync / webhook activation | Open datasource path with `tab=sync` |
70
+ | Execution logs | Open datasource path with `tab=logs` |
@@ -0,0 +1,23 @@
1
+ # Dimensions and ABAC grounding
2
+
3
+ Dimensions are governance attributes on datasource manifests. They map normalized metadata paths to ABAC policies, protection rules, and subscription filters.
4
+
5
+ ## When dimensions apply
6
+
7
+ Use dimensions on recordStorage, documentStorage, and serviceContract datasources. entityType none orchestration datasources must not declare fieldMappings.dimensions.
8
+
9
+ ## Authoring rules
10
+
11
+ Declare dimensions at fieldMappings.dimensions with values pointing to metadata paths, such as metadata.country or metadata.owner. Match metadataSchema properties so protection and sync can evaluate grants.
12
+
13
+ Ask the user for business context before patching datasource.dimensions. Common dimensions include country, region, department, owner, sensitivity, siteId, and lifecycleStage.
14
+
15
+ ## Challenge patterns
16
+
17
+ If a datasource uses resourceType customer but has no country or region dimension, ask whether geographic protection is required. If document libraries lack owner or sensitivity, ask before enabling protection.
18
+
19
+ When foreignKeys link a child datasource to a parent, confirm whether dimensions should inherit from the parent record metadata.
20
+
21
+ ## Related sections
22
+
23
+ datasource.dimensions, datasource.metadata, datasource.foreignKeys, datasource.governance, system.subscriptions
@@ -0,0 +1,123 @@
1
+ # Enterprise Synchronization Fabrix
2
+
3
+ Webhook change signals and syncBridge propagation connect vendor events to governed CIP sync without a separate webhook engine.
4
+
5
+ ## Overview
6
+
7
+ | Concept | Role |
8
+ | --- | --- |
9
+ | **webhook** | Inbound vendor POST trigger only — records WebhookDelivery and may create SyncIntent |
10
+ | **syncBridge** | Resource-type propagation mode (`disabled`, `master`, `bidirectional`) across datasources |
11
+ | **CIP get** | Business data always loaded via existing get operations and fieldMappings |
12
+
13
+ Webhook does not carry full record payloads for sync. The coordinator runs CIP get after a valid trigger.
14
+
15
+ ## authentications[] usage slots
16
+
17
+ Declare multiple authentication slots on the **external system** manifest (`authentications[]`), not on datasource files:
18
+
19
+ | usage | Purpose |
20
+ | --- | --- |
21
+ | `api` | Outbound vendor API calls (default slot) |
22
+ | `webhookInbound` | Validates inbound vendor webhook signatures or API keys |
23
+ | `syncExecution` | Credentials for syncBridge propagation CIP calls |
24
+
25
+ Example structure (YAML):
26
+
27
+ ```yaml
28
+ authentications:
29
+ - key: default
30
+ usage: api
31
+ authType: credential
32
+ credential:
33
+ method: apikey
34
+ security:
35
+ apiKey: kv://my-app/apiKey
36
+ - key: webhookInbound
37
+ usage: webhookInbound
38
+ authType: credential
39
+ credential:
40
+ method: hmac
41
+ security:
42
+ signingSecret: kv://my-app/webhookSigningSecret
43
+ - key: syncExecution
44
+ usage: syncExecution
45
+ authType: credential
46
+ credential:
47
+ method: apikey
48
+ security:
49
+ apiKey: kv://my-app/syncApiKey
50
+ ```
51
+
52
+ Repair helpers:
53
+
54
+ - `aifabrix repair <systemKey>` — normalize legacy `authentication` to `authentications[]`
55
+ - `aifabrix repair <systemKey> --auth apikey` — repair the default **api** slot only
56
+ - `aifabrix repair <systemKey> --auth-webhook` — add webhookInbound slot from template
57
+ - `aifabrix repair <systemKey> --auth-sync` — add syncExecution slot from template
58
+
59
+ ## Datasource webhook block
60
+
61
+ Minimal enabled configuration on a datasource manifest:
62
+
63
+ ```yaml
64
+ webhook:
65
+ enabled: true
66
+ endpointMode: datasource
67
+ events:
68
+ - company.updated
69
+ idPath: $.objectId
70
+ vendorDeliveryIdPath: $.deliveryId
71
+ ```
72
+
73
+ | Field | Notes |
74
+ | --- | --- |
75
+ | `endpointMode` | `system`, `datasource`, or `event` — controls generated POST path |
76
+ | `events` | Vendor event names that create SyncIntent |
77
+ | `idPath` | JSONPath to vendor object id in payload |
78
+ | `eventTypePath` | Required when multiple `events` and mode is not `event` |
79
+ | `vendorDeliveryIdPath` | Payload JSONPath for idempotent dedupe |
80
+
81
+ Generated receiver paths (first-party dataplane API):
82
+
83
+ - System: `POST /api/v1/webhooks/{systemKey}`
84
+ - Datasource: `POST /api/v1/webhooks/{systemKey}/{datasourceKey}`
85
+ - Event: `POST /api/v1/webhooks/{systemKey}/{datasourceKey}/{eventKey}`
86
+
87
+ Signature and API-key **headers** belong on the webhookInbound credential only — not on the datasource webhook block.
88
+
89
+ ## syncBridge modes
90
+
91
+ | Mode | Behavior |
92
+ | --- | --- |
93
+ | `disabled` | Default — no propagation |
94
+ | `master` | Authoritative source for a resourceType; receives webhook triggers |
95
+ | `bidirectional` | Participates in propagation; exactly one master per resourceType |
96
+
97
+ When syncBridge is not `disabled`, ensure `metadataSchema.properties.externalId` exists for routing.
98
+
99
+ ## Activation workflow
100
+
101
+ 1. Edit system + datasource manifests (authentications[], webhook, syncBridge).
102
+ 2. Run `aifabrix validate <app>` and `aifabrix repair <systemKey>` as needed.
103
+ 3. Run `aifabrix upload <app>` to publish.
104
+ 4. Open Connected Systems **Authentication** — add live secrets for each usage slot.
105
+ 5. Open datasource **Sync** tab — use **How to activate webhook** for operator copy/paste URLs.
106
+ 6. Run certification / test-e2e after credentials are live.
107
+
108
+ UI displays webhook and syncBridge config as **read-only**; manifest and API remain SSOT.
109
+
110
+ ## Validate and certification
111
+
112
+ - `aifabrix validate <app>` — schema + cross-field rules for webhook and syncBridge
113
+ - Dataplane certification readiness — webhookInbound auth, idPath, syncBridge master uniqueness
114
+
115
+ ## Logs and troubleshooting
116
+
117
+ After webhook POST, inspect datasource **Logs** tab for CIP execution traces. SyncIntent and coordinator outcomes appear in execution audit — no separate webhook log API.
118
+
119
+ ## Related help topics
120
+
121
+ - `connectedSystemUi` — post-upload Authentication and Sync tab URLs
122
+ - `workflow` — validate → upload → handoff ladder
123
+ - `schemaCatalog` — manifest property reference
@@ -0,0 +1,25 @@
1
+ # Builder manifest editing overview
2
+
3
+ The Builder API exposes governed manifest sections for external integrations. Agents read one section at a time, resolve missing inputs with the user, patch with explicit intent, repair derived sections, then validate and test the workspace draft.
4
+
5
+ ## Purpose
6
+
7
+ Help agents and MCP tools bootstrap without guessing manifest structure. Structured topics describe section keys, dependency order, repair hooks, workflow rules, golden patterns, and evidence expectations.
8
+
9
+ ## Core concepts
10
+
11
+ ### Governed sections
12
+
13
+ Manifests split into section keys for the external system and each datasource. Each section has schema fragments, mutability rules, and optional repair hooks.
14
+
15
+ ### Section quality
16
+
17
+ Every section read returns a quality score, missing-input questions, blocking issues, and recommended next actions. Required missing inputs must be collected from the user before patching.
18
+
19
+ ### Dependency graph
20
+
21
+ Some sections derive from others. After patching metadata or capabilities, run explicit repair hooks so field mappings, exposure, and RBAC stay aligned.
22
+
23
+ ## Getting started
24
+
25
+ Call the help endpoint with topic overview, then workflow, then schemaCatalog or sections. Use topic section with a sectionKey when editing a specific area. Use subscriptionGuide and cipOverview for subscriptions and execution depth. Use enterpriseSyncFabrix for webhook change signals and syncBridge propagation. After upload, use connectedSystemUi for shareable dataplane UI paths and post-upload authentication handoff.
@@ -0,0 +1,27 @@
1
+ # Subscription and role-scoped generation guide
2
+
3
+ Subscriptions on the external system manifest bootstrap platform tasks when records change or after publish. They connect certified datasources to role assistants without a separate workflow engine.
4
+
5
+ ## Where subscriptions live
6
+
7
+ Edit the system.subscriptions section. Each entry has a unique key, optional filter conditions, a task type, and optional runOnPublish flag.
8
+
9
+ Datasource manifests may declare subscriptionFilter to scope which role keys, system kinds, resource types, or datasource keys participate in generation.
10
+
11
+ ## Normalized record events
12
+
13
+ Vendor sync and pipeline execution emit normalized events only: record insert, update, delete, and sync completed. Subscription conditions reference generic field paths such as after.status with operators equals, in, changed, exists, and missing.
14
+
15
+ ## Role and resource scoping
16
+
17
+ Scope resourceTypes to business tokens on the datasource, such as company or deal, not generic placeholders. Match subscription filters to the same resourceType declared on each datasource.
18
+
19
+ For document libraries linked to CRM records, declare foreignKeys on the library datasource and use a business resourceType on that datasource. Exclude generic document resource types from role assistant subscription filters when business libraries exist.
20
+
21
+ ## Editing workflow
22
+
23
+ Read system.subscriptions with topic section before patch. Patch with intent describing the business trigger. Validate after edit; subscriptions do not auto-repair derived sections.
24
+
25
+ ## Related sections
26
+
27
+ system.subscriptions, system.rolesPermissions, datasource.resourceType, datasource.foreignKeys, datasource.governance
@@ -0,0 +1,50 @@
1
+ # Manifest development workflow
2
+
3
+ Follow this loop when editing external integration manifests through the Builder API.
4
+
5
+ ## Normative loop
6
+
7
+ Read a governed section, resolve required missing inputs with the user, patch with intent, repair derived sections, validate, then test.
8
+
9
+ ## Rules
10
+
11
+ ### Read before patch
12
+
13
+ Prefer GET when you need quality scores or `missingInputs`. `sectionReadToken` on PATCH is **optional**: when omitted, the server re-reads the section immediately before write (same race window as CLI `patch-section` without `--token`). If you send a token and it is stale, PATCH returns **409** — GET again and retry.
14
+
15
+ Do not invent primary keys, entity types, or similar values.
16
+
17
+ ### Ask when inputs are missing
18
+
19
+ When quality reports required missingInputs, ask the user. Do not invent primary keys, entity types, or similar values.
20
+
21
+ ### Patch requires intent
22
+
23
+ Every write records audit metadata describing why the change was made.
24
+
25
+ ### Repair is explicit
26
+
27
+ Pass named repair hooks after patches that affect derived sections. The dependency graph defines downstream order.
28
+
29
+ ### No auto-upload
30
+
31
+ Upload and certification are separate steps after validate and test succeed.
32
+
33
+ ### Post-upload authentication (enterprise handoff)
34
+
35
+ Validate, test, test-integration, and upload must not depend on resolved integration secrets in Builder API scope. Upload publishes configuration including `authentication.credential.variables` (non-secrets). The user adds live secrets in the dataplane Connected Systems Authentication UI afterward.
36
+
37
+ After upload succeeds:
38
+
39
+ 1. Read `authentication.authType` and `authentication.credential.method` from the published system manifest (`system.authentication`).
40
+ 2. Confirm non-secret `variables` (baseUrl, headerName, tokenUrl, and similar) were set in the manifest — they are pre-filled in the UI after upload.
41
+ 3. Fetch help topic `connectedSystemUi` with `systemKey`, optional `authType`, and optional `credentialMethod`.
42
+ 4. Ask the user for their dataplane public UI base (origin including `/data`).
43
+ 5. Provide the Authentication URL and tell the user to add **only the required secrets** (for example apiKey token for apikey method).
44
+ 6. User adds secrets in the UI, then re-runs E2E or live verification.
45
+
46
+ Do not instruct the user to paste vendor tokens into Builder API or workspace env files when UI authentication is the intended path.
47
+
48
+ ## Typical sequence
49
+
50
+ Start with datasource metadata for a new entity. Patch with intent describing the vendor payload mapping. Repair fieldMappings, expose, and rbac hooks. Patch openapiOperations when adding write capabilities. Repair again, validate, then test. Upload when ready, then hand off to Connected Systems Authentication per topic `connectedSystemUi`.
@@ -26,6 +26,7 @@ const { OPENAPI_HELP_RESULT_SCHEMAS } = require('./openapi-help-schemas');
26
26
  const RESPONSE_ENVELOPES = [
27
27
  ['ListSystemsResponse', 'ListSystemsData'],
28
28
  ['CreateSystemResponse', 'CreateSystemData'],
29
+ ['PersistSuppliedOpenApiResponse', 'PersistSuppliedOpenApiData'],
29
30
  ['SystemManifestResponse', 'SystemManifestData'],
30
31
  ['DeleteSystemResponse', 'DeleteSystemData'],
31
32
  ['WizardRunResponse', 'WizardRunData'],
@@ -22,6 +22,12 @@ const OPERATION_DESCRIPTIONS = Object.freeze({
22
22
  'Create an empty integration workspace for a systemKey. Mutating; requires Idempotency-Key on retries.',
23
23
  tags: ['workspace']
24
24
  },
25
+ persistSuppliedOpenApi: {
26
+ summary: 'Persist supplied OpenAPI documents to workspace',
27
+ description:
28
+ 'Validate Runtime-authorized OpenAPI documents and write them under integration/<systemKey>/openapi/. Does not run wizard or BID apply. Mutating.',
29
+ tags: ['workspace']
30
+ },
25
31
  getSystemManifest: {
26
32
  summary: 'Read workspace manifest summary',
27
33
  description: 'Return local workspace metadata and file manifest for one systemKey. Read-only.',
@@ -78,6 +78,17 @@ const OPENAPI_ENVELOPE_DATA_EXAMPLES = {
78
78
  EmptyResultData: {},
79
79
  ListSystemsData: { systems: [{ systemKey: SAMPLE_SYSTEM_KEY, meta: SAMPLE_META }] },
80
80
  CreateSystemData: { systemKey: SAMPLE_SYSTEM_KEY, meta: SAMPLE_META },
81
+ PersistSuppliedOpenApiData: {
82
+ accepted: [
83
+ {
84
+ filename: 'companies.json',
85
+ path: `integration/${SAMPLE_SYSTEM_KEY}/openapi/companies.json`,
86
+ digest: 'sha256:demo'
87
+ }
88
+ ],
89
+ rejected: [],
90
+ workspaceRoot: '/workspace/integration'
91
+ },
81
92
  SystemManifestData: SAMPLE_SYSTEM_MANIFEST,
82
93
  DeleteSystemData: { systemKey: SAMPLE_SYSTEM_KEY, deleted: true },
83
94
  WizardRunData: { systemKey: SAMPLE_SYSTEM_KEY, status: 'completed' },
@@ -81,6 +81,11 @@ const OPERATION_BINDINGS = Object.freeze({
81
81
  requestBody: jsonRequestBody('CreateSystemRequest', true),
82
82
  successResponse: 'CreateSystemResponse'
83
83
  },
84
+ persistSuppliedOpenApi: {
85
+ parameters: [SYSTEM_KEY_PARAM],
86
+ requestBody: jsonRequestBody('PersistSuppliedOpenApiRequest', true),
87
+ successResponse: 'PersistSuppliedOpenApiResponse'
88
+ },
84
89
  getSystemManifest: {
85
90
  parameters: [SYSTEM_KEY_PARAM],
86
91
  successResponse: 'SystemManifestResponse'
@@ -53,6 +53,29 @@ const OPENAPI_REQUEST_SCHEMAS = {
53
53
  sync: { type: 'boolean' }
54
54
  }),
55
55
  CreateSystemRequest: frozenObject({ systemKey: schemaRef('SystemKey') }, ['systemKey']),
56
+ PersistSuppliedOpenApiDocument: frozenObject(
57
+ {
58
+ filename: { type: 'string' },
59
+ name: { type: 'string' },
60
+ mediaType: { type: 'string' },
61
+ digest: { type: 'string' },
62
+ body: {
63
+ description: 'Authorized OpenAPI document object or JSON string (Runtime-resolved).',
64
+ oneOf: [{ type: 'object', additionalProperties: true }, { type: 'string' }]
65
+ }
66
+ },
67
+ ['body']
68
+ ),
69
+ PersistSuppliedOpenApiRequest: frozenObject(
70
+ {
71
+ documents: {
72
+ type: 'array',
73
+ minItems: 1,
74
+ items: schemaRef('PersistSuppliedOpenApiDocument')
75
+ }
76
+ },
77
+ ['documents']
78
+ ),
56
79
  WizardConfigRequest: frozenObject(
57
80
  {
58
81
  appName: { type: 'string' },
@@ -66,20 +89,23 @@ const OPENAPI_REQUEST_SCHEMAS = {
66
89
  },
67
90
  ['appName', 'source']
68
91
  ),
69
- IntegrationDefinitionApplyRequest: frozenObject({
70
- integrationDefinition: {
71
- type: 'object',
72
- additionalProperties: true,
73
- description: 'Builder Integration Definition (aifabrix.builder.integrationDefinition).'
74
- },
75
- bid: {
76
- type: 'object',
77
- additionalProperties: true,
78
- description: 'Alias for integrationDefinition.'
92
+ IntegrationDefinitionApplyRequest: frozenObject(
93
+ {
94
+ integrationDefinition: {
95
+ type: 'object',
96
+ additionalProperties: true,
97
+ description: 'Builder Integration Definition (aifabrix.builder.integrationDefinition).'
98
+ },
99
+ bid: {
100
+ type: 'object',
101
+ additionalProperties: true,
102
+ description: 'Alias for integrationDefinition.'
103
+ },
104
+ force: { type: 'boolean' },
105
+ dryRun: { type: 'boolean' }
79
106
  },
80
- force: { type: 'boolean' },
81
- dryRun: { type: 'boolean' }
82
- }),
107
+ ['integrationDefinition']
108
+ ),
83
109
  RepairRequest: frozenObject({
84
110
  dryRun: { type: 'boolean' },
85
111
  auth: { type: 'string' },
@@ -129,6 +129,36 @@ const OPENAPI_RESULT_SCHEMAS = {
129
129
  },
130
130
  ['systemKey', 'meta']
131
131
  ),
132
+ PersistSuppliedOpenApiAcceptedFile: frozenObject(
133
+ {
134
+ filename: { type: 'string' },
135
+ path: { type: 'string' },
136
+ digest: { type: 'string' }
137
+ },
138
+ ['filename', 'path', 'digest']
139
+ ),
140
+ PersistSuppliedOpenApiRejectedFile: frozenObject(
141
+ {
142
+ filename: { type: 'string' },
143
+ reason: { type: 'string' },
144
+ detail: { type: 'string' }
145
+ },
146
+ ['filename', 'reason']
147
+ ),
148
+ PersistSuppliedOpenApiData: frozenObject(
149
+ {
150
+ accepted: {
151
+ type: 'array',
152
+ items: schemaRef('PersistSuppliedOpenApiAcceptedFile')
153
+ },
154
+ rejected: {
155
+ type: 'array',
156
+ items: schemaRef('PersistSuppliedOpenApiRejectedFile')
157
+ },
158
+ workspaceRoot: { type: 'string' }
159
+ },
160
+ ['accepted', 'rejected', 'workspaceRoot']
161
+ ),
132
162
  SystemManifestData: frozenObject(
133
163
  {
134
164
  systemKey: schemaRef('SystemKey'),
@@ -78,6 +78,24 @@ const CORE_SCHEMA_DESCRIPTIONS = {
78
78
  _schema: 'Payload for listSystems: integration keys under the authenticated user.',
79
79
  systems: 'Workspace summaries ordered by systemKey.'
80
80
  },
81
+ PersistSuppliedOpenApiData: {
82
+ _schema: 'Findings for persistSuppliedOpenApi (accepted and rejected files).',
83
+ accepted: 'Successfully validated and written OpenAPI files.',
84
+ rejected: 'Documents that failed validation (no success claim).',
85
+ workspaceRoot: 'Absolute workspace integration root for this user.'
86
+ },
87
+ PersistSuppliedOpenApiAcceptedFile: {
88
+ _schema: 'One accepted OpenAPI file written under the workspace.',
89
+ filename: 'Basename written under openapi/.',
90
+ path: 'Workspace-relative path including integration/<systemKey>/openapi/.',
91
+ digest: 'sha256 digest of the serialized JSON body.'
92
+ },
93
+ PersistSuppliedOpenApiRejectedFile: {
94
+ _schema: 'One rejected OpenAPI document (not written).',
95
+ filename: 'Requested basename when available.',
96
+ reason: 'Stable rejection reason code (openapi.invalid, …).',
97
+ detail: 'Human-readable validation detail.'
98
+ },
81
99
  CreateSystemData: {
82
100
  _schema: 'Payload after createSystem: new workspace folder and metadata.',
83
101
  systemKey: 'Created integration system key.',
@@ -35,6 +35,25 @@ const OPERATIONS_SCHEMA_DESCRIPTIONS = {
35
35
  _schema: 'Request body to create an empty integration workspace folder.',
36
36
  systemKey: 'Unique integration system key for the new workspace.'
37
37
  },
38
+ PersistSuppliedOpenApiDocument: {
39
+ _schema: 'One Runtime-authorized OpenAPI document to persist.',
40
+ filename: 'Target basename under openapi/ (no path segments).',
41
+ name: 'Optional alias for filename.',
42
+ mediaType: 'Optional media type (application/json).',
43
+ digest: 'Optional sha256 digest of the serialized body for integrity check.',
44
+ body: 'OpenAPI document object or JSON string resolved by Runtime before CIP.'
45
+ },
46
+ PersistSuppliedOpenApiRequest: {
47
+ _schema: 'Request body for persistSuppliedOpenApi.',
48
+ documents: 'One or more authorized OpenAPI documents to validate and write.'
49
+ },
50
+ PersistSuppliedOpenApiResponse: {
51
+ _schema: '200 response envelope for persistSuppliedOpenApi.',
52
+ success: 'Always true for successful builder-api JSON responses.',
53
+ data: 'Typed payload; see PersistSuppliedOpenApiData.',
54
+ correlationId: 'UUID correlating logs for this request.',
55
+ requestId: 'Optional per-request UUID when emitted by the server.'
56
+ },
38
57
  WizardConfigRequest: {
39
58
  _schema: 'Headless wizard configuration to generate system and datasource JSON.',
40
59
  appName: 'Integration app folder name under the user workspace.',