@aifabrix/builder 2.50.0 → 2.51.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 (236) hide show
  1. package/.cursor/plans/Done/157.1-security-quality-violations-by-type.csv +374 -0
  2. package/.cursor/rules/assistant-driven-integration-build.mdc +40 -0
  3. package/integration/hubspot-test/create-hubspot.js +1 -16
  4. package/jest.isolated-projects.js +77 -1
  5. package/jest.projects.js +5 -426
  6. package/lib/api/assistants.api.js +67 -0
  7. package/lib/api/datasources-extended.api.js +6 -6
  8. package/lib/api/evidence-authoring-helpers.js +267 -0
  9. package/lib/api/evidence-authoring.api.js +337 -0
  10. package/lib/api/evidence-kinds.api.js +128 -0
  11. package/lib/api/evidence.api.js +57 -1
  12. package/lib/api/index.js +24 -7
  13. package/lib/api/pipeline.api.js +47 -3
  14. package/lib/api/records-bulk.api.js +28 -3
  15. package/lib/api/resource-types.api.js +4 -4
  16. package/lib/api/roles.api.js +121 -0
  17. package/lib/api/types/evidence-kinds.types.js +42 -0
  18. package/lib/api/types/evidence.types.js +156 -8
  19. package/lib/api/types/roles.types.js +36 -0
  20. package/lib/api/work.api.js +283 -0
  21. package/lib/app/certification-verify-rows.js +1 -1
  22. package/lib/app/run-deploy-job.js +108 -0
  23. package/lib/app/run-helpers.js +10 -3
  24. package/lib/app/run.js +8 -0
  25. package/lib/app/show.js +2 -2
  26. package/lib/certification/merge-certification-from-artifact.js +1 -1
  27. package/lib/channels/add-channel.js +54 -23
  28. package/lib/channels/approval-guides/chatgpt.js +8 -7
  29. package/lib/channels/approval-guides/microsoft-copilot.js +7 -8
  30. package/lib/channels/channel-artifact-generator.js +16 -3
  31. package/lib/channels/channel-credential.js +3 -1
  32. package/lib/channels/channel-probe-evidence.js +79 -0
  33. package/lib/channels/channel-probe.js +265 -13
  34. package/lib/channels/channel-runtime-resolver.js +120 -29
  35. package/lib/channels/channel-status-display.js +44 -0
  36. package/lib/channels/channel-targets.js +7 -0
  37. package/lib/channels/chatgpt-runtime-contract.js +29 -0
  38. package/lib/channels/microsoft-copilot-package.js +280 -0
  39. package/lib/channels/runtime-tool-catalog.js +165 -0
  40. package/lib/cli/index.js +6 -0
  41. package/lib/cli/setup-app.js +26 -5
  42. package/lib/cli/setup-dev.js +23 -7
  43. package/lib/cli/setup-external-system-help.js +8 -2
  44. package/lib/cli/setup-external-system.js +12 -0
  45. package/lib/cli/setup-utility-help-after.js +12 -0
  46. package/lib/cli/setup-utility-validate.js +41 -2
  47. package/lib/commands/app-test.js +2 -14
  48. package/lib/commands/datasource-load-export-cli.js +6 -1
  49. package/lib/commands/deploy-gate-failure-details.js +23 -0
  50. package/lib/commands/deploy-gate-orchestrator.js +64 -18
  51. package/lib/commands/dev-cli-handlers.js +6 -3
  52. package/lib/commands/dev-down.js +2 -6
  53. package/lib/commands/dev-init.js +7 -109
  54. package/lib/commands/dev-refresh.js +197 -0
  55. package/lib/commands/evidence-kind.js +478 -0
  56. package/lib/commands/governance-command-action.js +4 -2
  57. package/lib/commands/governance-generate-external.js +56 -21
  58. package/lib/commands/lifecycle-external.js +10 -4
  59. package/lib/commands/repair-datasource-apply.js +10 -1
  60. package/lib/commands/repair-datasource-run.js +4 -2
  61. package/lib/commands/repair-datasource-test-payload.js +80 -19
  62. package/lib/commands/repair-datasource-webhooks-sync-bridge.js +42 -3
  63. package/lib/commands/repair-internal.js +9 -1
  64. package/lib/commands/repair-openapi-export.js +1 -1
  65. package/lib/commands/repair-openapi-sync.js +43 -18
  66. package/lib/commands/resource-type.js +101 -18
  67. package/lib/commands/role-assistant.js +313 -0
  68. package/lib/commands/role.js +452 -0
  69. package/lib/commands/setup.js +1 -1
  70. package/lib/commands/upload-data-sync-finalize.js +5 -4
  71. package/lib/commands/upload-sidecar-followups.js +144 -47
  72. package/lib/commands/upload.js +43 -6
  73. package/lib/commands/validate-json.js +230 -0
  74. package/lib/commands/verify-governance-combined-external.js +73 -9
  75. package/lib/commands/verify-governance-db.js +80 -25
  76. package/lib/commands/verify-governance-external.js +29 -5
  77. package/lib/commands/verify-operations-step-plan.js +78 -40
  78. package/lib/commands/wizard-core-helpers.js +7 -3
  79. package/lib/commands/wizard-core.js +78 -9
  80. package/lib/core/audit-logger.js +1 -1
  81. package/lib/core/secrets-load.js +1 -3
  82. package/lib/datasource/bulk-loader-run-batches.js +4 -2
  83. package/lib/datasource/bulk-loader-service.js +5 -1
  84. package/lib/datasource/capability/relate-operations.js +1 -1
  85. package/lib/datasource/datasource-validate-summary.js +2 -2
  86. package/lib/datasource/validate.js +13 -6
  87. package/lib/external-system/deploy-helpers.js +35 -1
  88. package/lib/external-system/deploy.js +23 -10
  89. package/lib/external-system/download-helpers.js +111 -2
  90. package/lib/external-system/download-role-assistant.js +55 -0
  91. package/lib/external-system/download.js +45 -26
  92. package/lib/external-system/test-helpers.js +1 -1
  93. package/lib/external-system/test.js +39 -3
  94. package/lib/generator/builders.js +3 -0
  95. package/lib/generator/helpers.js +13 -5
  96. package/lib/generator/split-variables.js +9 -3
  97. package/lib/generator/wizard.js +51 -4
  98. package/lib/infrastructure/helpers-docker-check.js +6 -0
  99. package/lib/infrastructure/helpers.js +1 -1
  100. package/lib/lifecycle/access-control-abac.js +121 -0
  101. package/lib/lifecycle/lifecycle-governance-options.js +4 -1
  102. package/lib/lifecycle/product-model.js +3 -2
  103. package/lib/lifecycle/report-display.js +14 -2
  104. package/lib/programmatic/auth-config.js +3 -2
  105. package/lib/programmatic/bearer-auth.js +1 -1
  106. package/lib/programmatic/capability-registry.js +20 -1
  107. package/lib/programmatic/command-options.js +1 -0
  108. package/lib/programmatic/enterprise-mcp-client.js +18 -2
  109. package/lib/programmatic/index.js +4 -0
  110. package/lib/programmatic/manifest-patch-section.js +48 -9
  111. package/lib/programmatic/manifest-section-registry-data.js +3 -2
  112. package/lib/programmatic/manifest-section-registry.js +18 -1
  113. package/lib/programmatic/openapi-apply-result-schemas.js +44 -0
  114. package/lib/programmatic/openapi-component-schemas.js +16 -1
  115. package/lib/programmatic/openapi-description-enricher.js +3 -1
  116. package/lib/programmatic/openapi-descriptions.js +55 -5
  117. package/lib/programmatic/openapi-evidence-schemas.js +161 -0
  118. package/lib/programmatic/openapi-manifest-schemas.js +6 -2
  119. package/lib/programmatic/openapi-operation-bindings.js +99 -0
  120. package/lib/programmatic/openapi-request-schemas.js +36 -1
  121. package/lib/programmatic/openapi-result-schemas.js +29 -12
  122. package/lib/programmatic/openapi-schema-descriptions-certify.js +5 -1
  123. package/lib/programmatic/openapi-schema-descriptions-core.js +6 -3
  124. package/lib/programmatic/openapi-schema-descriptions-evidence.js +156 -0
  125. package/lib/programmatic/openapi-schema-descriptions-manifest.js +4 -3
  126. package/lib/programmatic/openapi-schema-descriptions-operations.js +70 -0
  127. package/lib/programmatic/openapi-schema-helpers.js +16 -1
  128. package/lib/programmatic/openapi-spec.js +48 -29
  129. package/lib/programmatic/orchestration-openapi-meta.js +5 -0
  130. package/lib/programmatic/request-timeout.js +3 -0
  131. package/lib/programmatic/route-handler-map.js +89 -2
  132. package/lib/programmatic/run-certify.js +15 -2
  133. package/lib/programmatic/run-deploy.js +74 -0
  134. package/lib/programmatic/run-evidence-authoring.js +80 -0
  135. package/lib/programmatic/run-protection.js +124 -0
  136. package/lib/programmatic/run-repository-emcp.js +11 -3
  137. package/lib/programmatic/run-template-workspace.js +42 -2
  138. package/lib/programmatic/workspace-context.js +6 -0
  139. package/lib/protection/auth-context.js +48 -6
  140. package/lib/protection/paths.js +22 -0
  141. package/lib/protection/run-protection-create-helpers.js +22 -1
  142. package/lib/protection/run-protection-create.js +1 -1
  143. package/lib/protection/sync-after-upload.js +1 -1
  144. package/lib/resolvers/evidence-kind-file.js +230 -0
  145. package/lib/resolvers/resource-type-file.js +36 -1
  146. package/lib/resolvers/role-file.js +227 -0
  147. package/lib/role-assistant/evidence-sync.js +450 -0
  148. package/lib/role-assistant/github-workflow.js +96 -0
  149. package/lib/role-assistant/knowledge-sync.js +465 -0
  150. package/lib/role-assistant/settings.js +126 -0
  151. package/lib/role-assistant/test-cases-evaluate.js +170 -0
  152. package/lib/role-assistant/test-cases-honesty.js +184 -0
  153. package/lib/role-assistant/test-cases.js +364 -0
  154. package/lib/role-assistant/test-runner-workhub-answers.js +203 -0
  155. package/lib/role-assistant/test-runner-workhub.js +385 -0
  156. package/lib/role-assistant/test-runner.js +500 -0
  157. package/lib/schema/application-schema.json +36 -2
  158. package/lib/schema/deployment-rules.yaml +1 -0
  159. package/lib/schema/external-datasource.schema.json +121 -4
  160. package/lib/schema/external-system.schema.json +20 -6
  161. package/lib/schema/infra.parameter.yaml +45 -1
  162. package/lib/schema/role-assistant-settings.schema.json +108 -0
  163. package/lib/schema/type/credential-field-registry.json +19 -3
  164. package/lib/utils/api.js +52 -21
  165. package/lib/utils/app-path-resolve.js +72 -24
  166. package/lib/utils/app-register-config.js +4 -3
  167. package/lib/utils/authentication-shape.js +3 -1
  168. package/lib/utils/cli-sync-options.js +59 -3
  169. package/lib/utils/cli-utils.js +11 -3
  170. package/lib/utils/deployment-validation.js +28 -3
  171. package/lib/utils/dev-ca-install.js +5 -6
  172. package/lib/utils/dev-config.js +2 -2
  173. package/lib/utils/dev-list-sort.js +145 -0
  174. package/lib/utils/dev-platform-tls.js +0 -63
  175. package/lib/utils/docker-build.js +46 -27
  176. package/lib/utils/docker-daemon-tls-ca.js +1 -1
  177. package/lib/utils/docker-exec.js +91 -6
  178. package/lib/utils/docker-run-ephemeral.js +55 -0
  179. package/lib/utils/enterprise-knowledge-paths.js +29 -12
  180. package/lib/utils/env-copy-keycloak.js +196 -0
  181. package/lib/utils/env-copy.js +35 -4
  182. package/lib/utils/error-formatters/error-parser.js +0 -3
  183. package/lib/utils/external-env-template.js +1 -1
  184. package/lib/utils/external-system-readiness-compact-blocks.js +28 -1
  185. package/lib/utils/external-system-readiness-compact-display.js +3 -0
  186. package/lib/utils/health-check-request.js +2 -3
  187. package/lib/utils/help-builder.js +4 -0
  188. package/lib/utils/image-name.js +22 -4
  189. package/lib/utils/logger.js +37 -4
  190. package/lib/utils/manifest-source-emit.js +1 -1
  191. package/lib/utils/paths.js +98 -26
  192. package/lib/utils/pipeline-upload-auth-retry.js +19 -3
  193. package/lib/utils/postgres-platform-bootstrap.js +24 -17
  194. package/lib/utils/postgres-wipe.js +5 -2
  195. package/lib/utils/remote-dev-auth.js +39 -4
  196. package/lib/utils/resolve-docker-image-ref.js +36 -6
  197. package/lib/utils/role-assistant-paths.js +98 -0
  198. package/lib/utils/schema-loader.js +41 -0
  199. package/lib/utils/schema-resolver.js +36 -4
  200. package/lib/utils/token-manager.js +47 -22
  201. package/lib/utils/upload-sync-options.js +17 -3
  202. package/lib/utils/url-declarative-resolve-load-doc.js +38 -1
  203. package/lib/validation/external-manifest-validator.js +31 -8
  204. package/lib/validation/openapi-contract-surface-validator.js +4 -0
  205. package/lib/validation/validate-external-file.js +8 -1
  206. package/lib/validation/validator.js +6 -5
  207. package/package.json +35 -12
  208. package/scripts/export-builder-api-evidence.js +3 -3
  209. package/scripts/lib/plan-actor.js +2 -2
  210. package/scripts/lib/plan-meta.js +1 -1
  211. package/scripts/lib/plan-parse.js +1 -1
  212. package/scripts/lib/plan-prevalidate-gates.js +12 -1
  213. package/scripts/lib/plan-run-report.js +13 -2
  214. package/scripts/pnpm/lib/resolve-aifabrix-bin.mjs +10 -10
  215. package/templates/applications/dataplane/application.yaml +47 -17
  216. package/templates/applications/dataplane/env.template +28 -9
  217. package/templates/applications/dataplane/rbac.yaml +78 -2
  218. package/templates/applications/miso-controller/application.yaml +10 -1
  219. package/templates/applications/miso-controller/env.template +13 -8
  220. package/templates/applications/miso-controller/rbac.yaml +72 -0
  221. package/templates/channels/chatgpt/install.template.md.hbs +42 -24
  222. package/templates/channels/chatgpt/integration/README.md +10 -7
  223. package/templates/channels/chatgpt/integration/application.json +2 -2
  224. package/templates/channels/chatgpt/integration/chatgpt-system.json +3 -3
  225. package/templates/channels/chatgpt/integration/env.template +1 -1
  226. package/templates/channels/chatgpt/manifest.template.json.hbs +36 -5
  227. package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +28 -0
  228. package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +22 -0
  229. package/templates/channels/microsoft-copilot/install.template.md.hbs +32 -22
  230. package/templates/channels/microsoft-copilot/integration/README.md +9 -7
  231. package/templates/channels/microsoft-copilot/integration/application.json +2 -2
  232. package/templates/channels/microsoft-copilot/integration/env.template +1 -1
  233. package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +7 -6
  234. package/templates/channels/microsoft-copilot/manifest.template.json.hbs +34 -6
  235. package/templates/channels/slack/integration/slack-system.json +60 -2
  236. package/templates/python/requirements.txt +1 -1
@@ -8,8 +8,17 @@
8
8
 
9
9
  'use strict';
10
10
 
11
+ const crypto = require('crypto');
11
12
  const { getChannelTarget } = require('./channel-targets');
12
13
  const { normalizeSlackAppDescription } = require('./channel-description');
14
+ const {
15
+ CHATGPT_RUNTIME_SYSTEM_KEY,
16
+ CHATGPT_RUNTIME_TRANSPORT,
17
+ CHATGPT_RUNTIME_AUTH_MODE,
18
+ COPILOT_RUNTIME_SYSTEM_KEY,
19
+ COPILOT_RUNTIME_TRANSPORT,
20
+ COPILOT_RUNTIME_AUTH_MODE
21
+ } = require('./chatgpt-runtime-contract');
13
22
 
14
23
  /** Default Slack slash prefix — matches dataplane `templates/slack/command_catalog.yaml`. */
15
24
  const DEFAULT_SLACK_COMMAND_PREFIX = 'af';
@@ -62,13 +71,10 @@ function getEndpointPathSuffixes(channelTarget) {
62
71
  botConfigUrl: '/bot-config'
63
72
  },
64
73
  'microsoft-copilot': {
65
- openapiUrl: '/openapi.yaml',
66
- actionsBaseUrl: '/actions'
74
+ mcpUrl: '/mcp'
67
75
  },
68
76
  chatgpt: {
69
- openapiUrl: '/openapi.yaml',
70
- mcpUrl: '/mcp',
71
- actionsBaseUrl: '/actions'
77
+ mcpUrl: '/mcp'
72
78
  },
73
79
  'web-embed': {
74
80
  configUrl: '/config'
@@ -78,21 +84,12 @@ function getEndpointPathSuffixes(channelTarget) {
78
84
  }
79
85
 
80
86
  /**
81
- * Legacy / non-external-system paths (Copilot/ChatGPT until dataplane routes exist).
87
+ * Legacy / non-external-system paths where fallback is still allowed.
82
88
  * @param {string} channelTarget
83
89
  * @returns {Record<string, string>}
84
90
  */
85
91
  function getLegacyApiPaths(channelTarget) {
86
92
  const legacy = {
87
- 'microsoft-copilot': {
88
- openapiUrl: '/api/v1/copilot/openapi.yaml',
89
- actionsBaseUrl: '/api/v1/copilot/actions'
90
- },
91
- chatgpt: {
92
- openapiUrl: '/api/v1/chatgpt/openapi.yaml',
93
- mcpUrl: '/api/v1/chatgpt/mcp',
94
- actionsBaseUrl: '/api/v1/chatgpt/actions'
95
- },
96
93
  'web-embed': {
97
94
  configUrl: '/api/v1/web-embed/config'
98
95
  }
@@ -120,6 +117,101 @@ function resolveSlackOAuthManifestFields(oauthCallbackUrl) {
120
117
  };
121
118
  }
122
119
 
120
+ /**
121
+ * @param {Object} resolved
122
+ * @param {Object} params
123
+ */
124
+ function applyChatGptRuntimeValues(resolved, params) {
125
+ resolved.runtimeSystemKey = CHATGPT_RUNTIME_SYSTEM_KEY;
126
+ resolved.runtimeTransport = CHATGPT_RUNTIME_TRANSPORT;
127
+ resolved.runtimeAuthMode = CHATGPT_RUNTIME_AUTH_MODE;
128
+ resolved.layerBToolNames = Array.isArray(params.layerBToolNames) ? [...params.layerBToolNames] : [];
129
+ resolved.scopes = Array.isArray(params.scopes) ? [...params.scopes] : [];
130
+ resolved.scopesJson = JSON.stringify(resolved.scopes);
131
+ }
132
+
133
+ /**
134
+ * @param {string} seed
135
+ * @returns {string}
136
+ */
137
+ function buildDeterministicGuid(seed) {
138
+ const hex = crypto.createHash('sha256').update(String(seed || ''), 'utf8').digest('hex');
139
+ const bytes = hex.slice(0, 32).split('');
140
+ bytes[12] = '4';
141
+ bytes[16] = 'a';
142
+ return [
143
+ bytes.slice(0, 8).join(''),
144
+ bytes.slice(8, 12).join(''),
145
+ bytes.slice(12, 16).join(''),
146
+ bytes.slice(16, 20).join(''),
147
+ bytes.slice(20, 32).join('')
148
+ ].join('-');
149
+ }
150
+
151
+ /**
152
+ * @param {Object} resolved
153
+ * @param {Object} params
154
+ */
155
+ function applyMicrosoftCopilotRuntimeValues(resolved, params) {
156
+ resolved.runtimeSystemKey = COPILOT_RUNTIME_SYSTEM_KEY;
157
+ resolved.runtimeTransport = COPILOT_RUNTIME_TRANSPORT;
158
+ resolved.runtimeAuthMode = COPILOT_RUNTIME_AUTH_MODE;
159
+ resolved.layerBToolNames = Array.isArray(params.layerBToolNames) ? [...params.layerBToolNames] : [];
160
+ resolved.scopes = Array.isArray(params.scopes)
161
+ ? [...params.scopes]
162
+ : ['openid', 'profile', 'offline_access'];
163
+ resolved.scopesJson = JSON.stringify(resolved.scopes);
164
+ resolved.packageVersion = typeof params.packageVersion === 'string' ? params.packageVersion : '1.0.0';
165
+ resolved.packageAppId = buildDeterministicGuid(
166
+ `${resolved.channelTarget}:${resolved.baseName}:${resolved.environment}:app`
167
+ );
168
+ resolved.pluginId = buildDeterministicGuid(
169
+ `${resolved.channelTarget}:${resolved.baseName}:${resolved.environment}:plugin`
170
+ );
171
+ resolved.runtimeDomain = '';
172
+ try {
173
+ resolved.runtimeDomain = new URL(resolved.mcpUrl).hostname;
174
+ } catch {
175
+ try {
176
+ resolved.runtimeDomain = new URL(resolved.dataplaneBaseUrl).hostname;
177
+ } catch {
178
+ resolved.runtimeDomain = '';
179
+ }
180
+ }
181
+ }
182
+
183
+ /**
184
+ * @param {Object} resolved
185
+ * @param {string} base
186
+ * @param {string} systemPrefix
187
+ * @param {Record<string, string>} suffixes
188
+ * @param {Record<string, string>} legacy
189
+ */
190
+ function applyResolvedPaths(resolved, base, systemPrefix, suffixes, legacy) {
191
+ for (const [key, suffix] of Object.entries(suffixes)) {
192
+ resolved[key] = joinUrl(base, `${systemPrefix}${suffix}`);
193
+ }
194
+ for (const [key, legacyPath] of Object.entries(legacy)) {
195
+ if (!resolved[key]) {
196
+ resolved[key] = joinUrl(base, legacyPath);
197
+ }
198
+ }
199
+ }
200
+
201
+ /**
202
+ * @param {Object} resolved
203
+ * @param {Object} params
204
+ */
205
+ function applySlackRuntimeValues(resolved, params) {
206
+ const oauthCallbackUrl = params.oauthCallbackUrl || resolved.oauthCallbackUrl;
207
+ Object.assign(resolved, resolveSlackOAuthManifestFields(oauthCallbackUrl));
208
+ const prefix =
209
+ typeof params.commandPrefix === 'string' && params.commandPrefix.trim()
210
+ ? params.commandPrefix.trim()
211
+ : DEFAULT_SLACK_COMMAND_PREFIX;
212
+ resolved.commandPrefix = prefix;
213
+ }
214
+
123
215
  /**
124
216
  * @param {Object} params
125
217
  * @param {string} params.dataplaneBaseUrl
@@ -158,24 +250,18 @@ function resolveChannelRuntimeValues(params) {
158
250
  scopes: []
159
251
  };
160
252
 
161
- for (const [key, suffix] of Object.entries(suffixes)) {
162
- resolved[key] = joinUrl(base, `${systemPrefix}${suffix}`);
253
+ applyResolvedPaths(resolved, base, systemPrefix, suffixes, legacy);
254
+
255
+ if (params.channelTarget === 'slack') {
256
+ applySlackRuntimeValues(resolved, params);
163
257
  }
164
258
 
165
- for (const [key, legacyPath] of Object.entries(legacy)) {
166
- if (!resolved[key]) {
167
- resolved[key] = joinUrl(base, legacyPath);
168
- }
259
+ if (params.channelTarget === 'microsoft-copilot') {
260
+ applyMicrosoftCopilotRuntimeValues(resolved, params);
169
261
  }
170
262
 
171
- if (params.channelTarget === 'slack') {
172
- const oauthCallbackUrl = params.oauthCallbackUrl || resolved.oauthCallbackUrl;
173
- Object.assign(resolved, resolveSlackOAuthManifestFields(oauthCallbackUrl));
174
- const prefix =
175
- typeof params.commandPrefix === 'string' && params.commandPrefix.trim()
176
- ? params.commandPrefix.trim()
177
- : DEFAULT_SLACK_COMMAND_PREFIX;
178
- resolved.commandPrefix = prefix;
263
+ if (params.channelTarget === 'chatgpt') {
264
+ applyChatGptRuntimeValues(resolved, params);
179
265
  }
180
266
 
181
267
  return resolved;
@@ -186,6 +272,11 @@ module.exports = {
186
272
  joinUrl,
187
273
  externalSystemsPrefix,
188
274
  getEndpointPathSuffixes,
275
+ buildDeterministicGuid,
276
+ applyResolvedPaths,
277
+ applySlackRuntimeValues,
278
+ applyMicrosoftCopilotRuntimeValues,
279
+ applyChatGptRuntimeValues,
189
280
  resolveSlackOAuthManifestFields,
190
281
  resolveChannelRuntimeValues,
191
282
  DEFAULT_SLACK_COMMAND_PREFIX
@@ -148,6 +148,50 @@ function displayValidationSection(validation) {
148
148
  if (validation.inboundVerification) {
149
149
  logger.log(formatSuccessLine('Inbound verification configured'));
150
150
  }
151
+ displayProbeTiers(validation.probeTiers);
152
+ displayRuntimeChecks(validation.runtimeChecks);
153
+ }
154
+
155
+ /**
156
+ * @param {Object|null} probeTiers
157
+ */
158
+ function displayProbeTiers(probeTiers) {
159
+ if (!probeTiers) return;
160
+ logger.log('');
161
+ logger.log(metadata('Probe tiers:'));
162
+ const rows = [];
163
+ if (Object.prototype.hasOwnProperty.call(probeTiers, 'builderValidated')) {
164
+ rows.push(['builderValidated', probeTiers.builderValidated, false]);
165
+ }
166
+ if (Object.prototype.hasOwnProperty.call(probeTiers, 'locallyValidated')) {
167
+ rows.push(['locallyValidated', probeTiers.locallyValidated, false]);
168
+ }
169
+ rows.push(['runtimeValidated', probeTiers.runtimeValidated, false]);
170
+ if (Object.prototype.hasOwnProperty.call(probeTiers, 'requiresMicrosoftAdmin')) {
171
+ rows.push(['requiresMicrosoftAdmin', probeTiers.requiresMicrosoftAdmin, true]);
172
+ }
173
+ if (Object.prototype.hasOwnProperty.call(probeTiers, 'requiresChatGptWorkspaceAdmin')) {
174
+ rows.push(['requiresChatGptWorkspaceAdmin', probeTiers.requiresChatGptWorkspaceAdmin, true]);
175
+ }
176
+ for (const [label, value, isPendingGate] of rows) {
177
+ if (isPendingGate) {
178
+ logger.log(value ? formatWarningLine(label) : formatSuccessLine(`${label} (cleared)`));
179
+ continue;
180
+ }
181
+ logger.log(value ? formatSuccessLine(label) : formatWarningLine(`${label} (pending or failed)`));
182
+ }
183
+ }
184
+
185
+ /**
186
+ * @param {Object|null} runtimeChecks
187
+ */
188
+ function displayRuntimeChecks(runtimeChecks) {
189
+ if (!runtimeChecks || typeof runtimeChecks !== 'object') return;
190
+ logger.log('');
191
+ logger.log(metadata('Runtime checks:'));
192
+ for (const [key, value] of Object.entries(runtimeChecks)) {
193
+ logger.log(value ? formatSuccessLine(key) : formatWarningLine(`${key} (failed)`));
194
+ }
151
195
  }
152
196
 
153
197
  /**
@@ -8,6 +8,11 @@
8
8
 
9
9
  'use strict';
10
10
 
11
+ const {
12
+ CHATGPT_RUNTIME_SYSTEM_KEY,
13
+ COPILOT_RUNTIME_SYSTEM_KEY
14
+ } = require('./chatgpt-runtime-contract');
15
+
11
16
  /** @typedef {'teams-bot'|'slack'|'microsoft-copilot'|'chatgpt'|'web-embed'} ChannelTargetKey */
12
17
 
13
18
  const DEFAULT_CAPABILITIES = ['chat', 'notify', 'documentApproval'];
@@ -44,6 +49,7 @@ const CHANNEL_TARGETS = {
44
49
  artifactFileName: 'channel-microsoft-copilot.json',
45
50
  artifactFormat: 'json',
46
51
  credentialKey: 'microsoft-copilot-channel',
52
+ routeSystemKey: COPILOT_RUNTIME_SYSTEM_KEY,
47
53
  capabilities: [...DEFAULT_CAPABILITIES, 'enterpriseActions'],
48
54
  approvalRequired: true,
49
55
  experimental: false
@@ -55,6 +61,7 @@ const CHANNEL_TARGETS = {
55
61
  artifactFileName: 'channel-chatgpt.json',
56
62
  artifactFormat: 'json',
57
63
  credentialKey: 'chatgpt-channel',
64
+ routeSystemKey: CHATGPT_RUNTIME_SYSTEM_KEY,
58
65
  capabilities: ['chat', 'enterpriseActions'],
59
66
  approvalRequired: true,
60
67
  experimental: false
@@ -0,0 +1,29 @@
1
+ /**
2
+ * ChatGPT custom MCP app runtime contract constants (plan 163).
3
+ *
4
+ * @fileoverview Runtime-orchestration MCP contract fields used by chatgpt channel templates and probes
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const RUNTIME_ORCHESTRATION_SYSTEM_KEY = 'runtime-orchestration';
12
+
13
+ const CHATGPT_RUNTIME_SYSTEM_KEY = RUNTIME_ORCHESTRATION_SYSTEM_KEY;
14
+ const CHATGPT_RUNTIME_TRANSPORT = 'streamable-http';
15
+ const CHATGPT_RUNTIME_AUTH_MODE = 'workspace-managed-oauth-or-api-key';
16
+
17
+ const COPILOT_RUNTIME_SYSTEM_KEY = RUNTIME_ORCHESTRATION_SYSTEM_KEY;
18
+ const COPILOT_RUNTIME_TRANSPORT = 'streamable-http';
19
+ const COPILOT_RUNTIME_AUTH_MODE = 'microsoft-entra-sso-or-oauth';
20
+
21
+ module.exports = {
22
+ RUNTIME_ORCHESTRATION_SYSTEM_KEY,
23
+ CHATGPT_RUNTIME_SYSTEM_KEY,
24
+ CHATGPT_RUNTIME_TRANSPORT,
25
+ CHATGPT_RUNTIME_AUTH_MODE,
26
+ COPILOT_RUNTIME_SYSTEM_KEY,
27
+ COPILOT_RUNTIME_TRANSPORT,
28
+ COPILOT_RUNTIME_AUTH_MODE
29
+ };
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Microsoft Copilot package artifact generation (plan 164).
3
+ *
4
+ * @fileoverview Build source files, package ZIP, and lifecycle summary for microsoft-copilot channel
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const crypto = require('crypto');
12
+ const fs = require('fs');
13
+ const path = require('path');
14
+ const AdmZip = require('adm-zip');
15
+
16
+ const PLACEHOLDER_ICON_BASE64 =
17
+ 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO2s9WQAAAAASUVORK5CYII=';
18
+
19
+ /**
20
+ * @param {string} outputPath
21
+ * @param {Object} runtimeValues
22
+ * @returns {Object}
23
+ */
24
+ function buildCopilotOutputPaths(outputPath, runtimeValues) {
25
+ const rootDir = path.dirname(outputPath);
26
+ const sourceDir = path.join(rootDir, 'source');
27
+ const buildDir = path.join(rootDir, 'build');
28
+ const installDir = path.join(rootDir, 'install');
29
+ const environment = String(runtimeValues.environment || 'dev').trim() || 'dev';
30
+ const zipFileName = `appPackage.${environment}.zip`;
31
+ return {
32
+ rootDir,
33
+ sourceDir,
34
+ buildDir,
35
+ installDir,
36
+ summaryPath: outputPath,
37
+ zipFileName,
38
+ zipPath: path.join(buildDir, zipFileName),
39
+ validationPath: path.join(installDir, 'validation.json'),
40
+ installPath: path.join(installDir, 'README.md')
41
+ };
42
+ }
43
+
44
+ /**
45
+ * @returns {{ color: Buffer, outline: Buffer }}
46
+ */
47
+ function getPlaceholderIcons() {
48
+ const icon = Buffer.from(PLACEHOLDER_ICON_BASE64, 'base64');
49
+ return { color: icon, outline: icon };
50
+ }
51
+
52
+ /**
53
+ * @param {Object} runtimeValues
54
+ * @param {(templatePath: string, context: Object) => string} renderTemplateFile
55
+ * @param {string} templatesDir
56
+ * @returns {{ sourceFiles: Record<string, string>, installText: string }}
57
+ */
58
+ function renderCopilotTemplates(runtimeValues, renderTemplateFile, templatesDir) {
59
+ const sourceFiles = {
60
+ 'manifest.json': renderTemplateFile(path.join(templatesDir, 'manifest.template.json.hbs'), runtimeValues),
61
+ 'declarativeAgent.json': renderTemplateFile(
62
+ path.join(templatesDir, 'declarative-agent.template.json.hbs'),
63
+ runtimeValues
64
+ ),
65
+ 'ai-plugin.json': renderTemplateFile(
66
+ path.join(templatesDir, 'ai-plugin.template.json.hbs'),
67
+ runtimeValues
68
+ )
69
+ };
70
+ const installText = renderTemplateFile(path.join(templatesDir, 'install.template.md.hbs'), runtimeValues);
71
+ return { sourceFiles, installText };
72
+ }
73
+
74
+ /**
75
+ * @param {Record<string, string>} sourceFiles
76
+ * @param {(content: string) => void} assertNoSecretsInArtifact
77
+ */
78
+ function assertNoSecretsInSourceFiles(sourceFiles, assertNoSecretsInArtifact) {
79
+ for (const content of Object.values(sourceFiles)) {
80
+ assertNoSecretsInArtifact(content);
81
+ }
82
+ }
83
+
84
+ /**
85
+ * @param {Record<string, string>} sourceFiles
86
+ * @param {{ color: Buffer, outline: Buffer }} icons
87
+ * @returns {Buffer}
88
+ */
89
+ function buildCopilotZipBuffer(sourceFiles, icons) {
90
+ const zip = new AdmZip();
91
+ zip.addFile('manifest.json', Buffer.from(sourceFiles['manifest.json'], 'utf8'));
92
+ zip.addFile('declarativeAgent.json', Buffer.from(sourceFiles['declarativeAgent.json'], 'utf8'));
93
+ zip.addFile('ai-plugin.json', Buffer.from(sourceFiles['ai-plugin.json'], 'utf8'));
94
+ zip.addFile('color.png', icons.color);
95
+ zip.addFile('outline.png', icons.outline);
96
+ return zip.toBuffer();
97
+ }
98
+
99
+ /**
100
+ * @param {Object} runtimeValues
101
+ * @param {Object} paths
102
+ * @param {string[]} sourceFileNames
103
+ * @returns {Object}
104
+ */
105
+ function buildCopilotValidation(runtimeValues, paths, sourceFileNames) {
106
+ return {
107
+ tier: 'builderValidated',
108
+ environment: runtimeValues.environment,
109
+ sourceFiles: sourceFileNames,
110
+ zipFile: paths.zipFileName,
111
+ runtimeSystemKey: runtimeValues.runtimeSystemKey,
112
+ runtimeMcpUrl: runtimeValues.mcpUrl,
113
+ runtimeTransport: runtimeValues.runtimeTransport,
114
+ expectedLayerBToolNames: runtimeValues.layerBToolNames || [],
115
+ boundaries: {
116
+ onePackagePerEnvironment: true,
117
+ topLevelVendorToolsExposed: false,
118
+ roleAssistantResolution: 'dynamic-runtime'
119
+ },
120
+ requiresMicrosoftAdmin: [
121
+ 'upload-package',
122
+ 'tenant-approval',
123
+ 'assignment-and-consent',
124
+ 'first-copilot-invoke'
125
+ ]
126
+ };
127
+ }
128
+
129
+ /**
130
+ * @param {Array<string|Buffer>} parts
131
+ * @returns {string}
132
+ */
133
+ function computeCopilotArtifactHash(parts) {
134
+ const hash = crypto.createHash('sha256');
135
+ for (const part of parts) {
136
+ if (Buffer.isBuffer(part)) {
137
+ hash.update(part);
138
+ continue;
139
+ }
140
+ hash.update(String(part), 'utf8');
141
+ }
142
+ return hash.digest('hex');
143
+ }
144
+
145
+ /**
146
+ * @param {Object} runtimeValues
147
+ * @param {Object} paths
148
+ * @param {Object} validation
149
+ * @param {string} artifactHash
150
+ * @returns {Object}
151
+ */
152
+ function buildCopilotSummary(runtimeValues, paths, validation, artifactHash) {
153
+ return {
154
+ channelTarget: runtimeValues.channelTarget,
155
+ name: runtimeValues.appName,
156
+ baseName: runtimeValues.baseName,
157
+ description: runtimeValues.appDescription,
158
+ environment: runtimeValues.environment,
159
+ runtime: {
160
+ runtimeSystemKey: runtimeValues.runtimeSystemKey,
161
+ remoteMcpUrl: runtimeValues.mcpUrl,
162
+ transport: runtimeValues.runtimeTransport,
163
+ assistantCatalogUrl: runtimeValues.assistantCatalogUrl,
164
+ roleAssistantResolution: 'dynamic-runtime',
165
+ layerBToolNames: runtimeValues.layerBToolNames || []
166
+ },
167
+ authentication: {
168
+ mode: runtimeValues.runtimeAuthMode,
169
+ credentialKey: runtimeValues.credentialKey,
170
+ credentialPortalUrl: runtimeValues.credentialPortalUrl,
171
+ scopes: runtimeValues.scopes || []
172
+ },
173
+ package: {
174
+ appId: runtimeValues.packageAppId,
175
+ version: runtimeValues.packageVersion,
176
+ sourceFiles: ['manifest.json', 'declarativeAgent.json', 'ai-plugin.json', 'color.png', 'outline.png'],
177
+ zipFileName: paths.zipFileName,
178
+ installGuide: path.relative(paths.rootDir, paths.installPath),
179
+ validationFile: path.relative(paths.rootDir, paths.validationPath)
180
+ },
181
+ probeTiers: {
182
+ builderValidated: true,
183
+ runtimeValidated: false,
184
+ requiresMicrosoftAdmin: true
185
+ },
186
+ artifact: {
187
+ format: 'microsoft-365-copilot-package',
188
+ hash: artifactHash,
189
+ generatedAt: new Date().toISOString()
190
+ },
191
+ validation
192
+ };
193
+ }
194
+
195
+ /**
196
+ * @param {Object} params
197
+ */
198
+ function writeCopilotArtifacts(params) {
199
+ const { paths, sourceFiles, icons, zipBuffer, installText, validationText, summaryText } = params;
200
+ fs.mkdirSync(paths.sourceDir, { recursive: true });
201
+ fs.mkdirSync(paths.buildDir, { recursive: true });
202
+ fs.mkdirSync(paths.installDir, { recursive: true });
203
+ fs.writeFileSync(path.join(paths.sourceDir, 'manifest.json'), sourceFiles['manifest.json'], 'utf8');
204
+ fs.writeFileSync(
205
+ path.join(paths.sourceDir, 'declarativeAgent.json'),
206
+ sourceFiles['declarativeAgent.json'],
207
+ 'utf8'
208
+ );
209
+ fs.writeFileSync(path.join(paths.sourceDir, 'ai-plugin.json'), sourceFiles['ai-plugin.json'], 'utf8');
210
+ fs.writeFileSync(path.join(paths.sourceDir, 'color.png'), icons.color);
211
+ fs.writeFileSync(path.join(paths.sourceDir, 'outline.png'), icons.outline);
212
+ fs.writeFileSync(paths.zipPath, zipBuffer);
213
+ fs.writeFileSync(paths.installPath, installText, 'utf8');
214
+ fs.writeFileSync(paths.validationPath, validationText, 'utf8');
215
+ fs.writeFileSync(paths.summaryPath, summaryText, 'utf8');
216
+ }
217
+
218
+ /**
219
+ * @param {Object} params
220
+ * @param {Object} params.runtimeValues
221
+ * @param {string} params.templatesDir
222
+ * @param {string} params.outputPath
223
+ * @param {boolean} [params.dryRun]
224
+ * @param {(content: string) => void} params.assertNoSecretsInArtifact
225
+ * @param {(templatePath: string, context: Object) => string} params.renderTemplateFile
226
+ * @returns {{ outputPath: string, artifactHash: string, content: string, installPath: string }}
227
+ */
228
+ function generateMicrosoftCopilotPackage(params) {
229
+ const runtimeValues = params.runtimeValues || {};
230
+ const paths = buildCopilotOutputPaths(params.outputPath, runtimeValues);
231
+ const icons = getPlaceholderIcons();
232
+ const { sourceFiles, installText } = renderCopilotTemplates(
233
+ runtimeValues,
234
+ params.renderTemplateFile,
235
+ params.templatesDir
236
+ );
237
+ assertNoSecretsInSourceFiles(sourceFiles, params.assertNoSecretsInArtifact);
238
+ params.assertNoSecretsInArtifact(installText);
239
+ const zipBuffer = buildCopilotZipBuffer(sourceFiles, icons);
240
+ const validation = buildCopilotValidation(runtimeValues, paths, Object.keys(sourceFiles));
241
+ const validationText = JSON.stringify(validation, null, 2);
242
+ const artifactHash = computeCopilotArtifactHash([
243
+ sourceFiles['manifest.json'],
244
+ sourceFiles['declarativeAgent.json'],
245
+ sourceFiles['ai-plugin.json'],
246
+ installText,
247
+ validationText,
248
+ zipBuffer
249
+ ]);
250
+ const summary = buildCopilotSummary(runtimeValues, paths, validation, artifactHash);
251
+ const summaryText = JSON.stringify(summary, null, 2);
252
+ params.assertNoSecretsInArtifact(summaryText);
253
+ if (!params.dryRun) {
254
+ writeCopilotArtifacts({
255
+ paths,
256
+ sourceFiles,
257
+ icons,
258
+ zipBuffer,
259
+ installText,
260
+ validationText,
261
+ summaryText
262
+ });
263
+ }
264
+ return {
265
+ outputPath: paths.summaryPath,
266
+ artifactHash,
267
+ content: summaryText,
268
+ installPath: paths.installPath
269
+ };
270
+ }
271
+
272
+ module.exports = {
273
+ generateMicrosoftCopilotPackage,
274
+ buildCopilotOutputPaths,
275
+ renderCopilotTemplates,
276
+ buildCopilotZipBuffer,
277
+ buildCopilotValidation,
278
+ buildCopilotSummary,
279
+ computeCopilotArtifactHash
280
+ };