@aifabrix/builder 2.51.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 (162) hide show
  1. package/jest.isolated-projects.js +77 -1
  2. package/jest.projects.js +5 -426
  3. package/lib/api/assistants.api.js +67 -0
  4. package/lib/api/datasources-extended.api.js +6 -6
  5. package/lib/api/evidence-authoring-helpers.js +267 -0
  6. package/lib/api/evidence-authoring.api.js +337 -0
  7. package/lib/api/evidence.api.js +57 -1
  8. package/lib/api/index.js +24 -7
  9. package/lib/api/pipeline.api.js +43 -3
  10. package/lib/api/records-bulk.api.js +28 -3
  11. package/lib/api/types/evidence.types.js +156 -8
  12. package/lib/api/work.api.js +283 -0
  13. package/lib/app/run-deploy-job.js +108 -0
  14. package/lib/app/run-helpers.js +10 -3
  15. package/lib/app/run.js +8 -0
  16. package/lib/channels/add-channel.js +54 -23
  17. package/lib/channels/approval-guides/chatgpt.js +8 -7
  18. package/lib/channels/approval-guides/microsoft-copilot.js +7 -8
  19. package/lib/channels/channel-artifact-generator.js +14 -2
  20. package/lib/channels/channel-credential.js +3 -1
  21. package/lib/channels/channel-probe-evidence.js +79 -0
  22. package/lib/channels/channel-probe.js +265 -13
  23. package/lib/channels/channel-runtime-resolver.js +120 -29
  24. package/lib/channels/channel-status-display.js +44 -0
  25. package/lib/channels/channel-targets.js +7 -0
  26. package/lib/channels/chatgpt-runtime-contract.js +29 -0
  27. package/lib/channels/microsoft-copilot-package.js +280 -0
  28. package/lib/channels/runtime-tool-catalog.js +165 -0
  29. package/lib/cli/index.js +2 -0
  30. package/lib/cli/setup-app.js +4 -0
  31. package/lib/cli/setup-external-system-help.js +8 -2
  32. package/lib/cli/setup-external-system.js +12 -0
  33. package/lib/commands/app-test.js +2 -14
  34. package/lib/commands/datasource-load-export-cli.js +6 -1
  35. package/lib/commands/deploy-gate-failure-details.js +19 -17
  36. package/lib/commands/dev-down.js +2 -6
  37. package/lib/commands/evidence-kind.js +65 -15
  38. package/lib/commands/governance-generate-external.js +56 -21
  39. package/lib/commands/lifecycle-external.js +10 -4
  40. package/lib/commands/repair-datasource-apply.js +10 -1
  41. package/lib/commands/repair-datasource-run.js +4 -2
  42. package/lib/commands/repair-datasource-test-payload.js +80 -19
  43. package/lib/commands/repair-datasource-webhooks-sync-bridge.js +42 -3
  44. package/lib/commands/repair-internal.js +9 -1
  45. package/lib/commands/repair-openapi-sync.js +34 -17
  46. package/lib/commands/role-assistant.js +313 -0
  47. package/lib/commands/upload-data-sync-finalize.js +5 -4
  48. package/lib/commands/upload-sidecar-followups.js +144 -47
  49. package/lib/commands/upload.js +43 -6
  50. package/lib/commands/verify-governance-combined-external.js +73 -9
  51. package/lib/commands/verify-governance-db.js +80 -25
  52. package/lib/commands/verify-governance-external.js +29 -5
  53. package/lib/commands/wizard-core-helpers.js +7 -3
  54. package/lib/commands/wizard-core.js +78 -9
  55. package/lib/datasource/bulk-loader-run-batches.js +4 -2
  56. package/lib/datasource/bulk-loader-service.js +5 -1
  57. package/lib/datasource/datasource-validate-summary.js +2 -2
  58. package/lib/datasource/validate.js +13 -6
  59. package/lib/external-system/deploy-helpers.js +35 -1
  60. package/lib/external-system/deploy.js +23 -10
  61. package/lib/external-system/download-helpers.js +111 -2
  62. package/lib/external-system/download-role-assistant.js +55 -0
  63. package/lib/external-system/download.js +45 -26
  64. package/lib/external-system/test-helpers.js +1 -1
  65. package/lib/external-system/test.js +39 -3
  66. package/lib/generator/builders.js +3 -0
  67. package/lib/generator/wizard.js +51 -4
  68. package/lib/lifecycle/access-control-abac.js +121 -0
  69. package/lib/lifecycle/lifecycle-governance-options.js +4 -1
  70. package/lib/lifecycle/product-model.js +3 -2
  71. package/lib/lifecycle/report-display.js +14 -2
  72. package/lib/programmatic/capability-registry.js +20 -1
  73. package/lib/programmatic/command-options.js +1 -0
  74. package/lib/programmatic/index.js +4 -0
  75. package/lib/programmatic/manifest-patch-section.js +48 -9
  76. package/lib/programmatic/manifest-section-registry-data.js +3 -2
  77. package/lib/programmatic/openapi-apply-result-schemas.js +44 -0
  78. package/lib/programmatic/openapi-component-schemas.js +16 -1
  79. package/lib/programmatic/openapi-description-enricher.js +3 -1
  80. package/lib/programmatic/openapi-descriptions.js +55 -5
  81. package/lib/programmatic/openapi-evidence-schemas.js +161 -0
  82. package/lib/programmatic/openapi-manifest-schemas.js +6 -2
  83. package/lib/programmatic/openapi-operation-bindings.js +99 -0
  84. package/lib/programmatic/openapi-request-schemas.js +36 -1
  85. package/lib/programmatic/openapi-result-schemas.js +1 -1
  86. package/lib/programmatic/openapi-schema-descriptions-certify.js +5 -1
  87. package/lib/programmatic/openapi-schema-descriptions-core.js +1 -1
  88. package/lib/programmatic/openapi-schema-descriptions-evidence.js +156 -0
  89. package/lib/programmatic/openapi-schema-descriptions-manifest.js +4 -3
  90. package/lib/programmatic/openapi-schema-descriptions-operations.js +70 -0
  91. package/lib/programmatic/openapi-spec.js +47 -28
  92. package/lib/programmatic/orchestration-openapi-meta.js +5 -0
  93. package/lib/programmatic/request-timeout.js +3 -0
  94. package/lib/programmatic/route-handler-map.js +89 -2
  95. package/lib/programmatic/run-certify.js +15 -2
  96. package/lib/programmatic/run-deploy.js +74 -0
  97. package/lib/programmatic/run-evidence-authoring.js +80 -0
  98. package/lib/programmatic/run-protection.js +124 -0
  99. package/lib/programmatic/run-template-workspace.js +28 -1
  100. package/lib/programmatic/workspace-context.js +6 -0
  101. package/lib/protection/auth-context.js +48 -6
  102. package/lib/protection/paths.js +22 -0
  103. package/lib/protection/run-protection-create-helpers.js +22 -1
  104. package/lib/protection/run-protection-create.js +1 -1
  105. package/lib/protection/sync-after-upload.js +1 -1
  106. package/lib/role-assistant/evidence-sync.js +450 -0
  107. package/lib/role-assistant/github-workflow.js +96 -0
  108. package/lib/role-assistant/knowledge-sync.js +465 -0
  109. package/lib/role-assistant/settings.js +126 -0
  110. package/lib/role-assistant/test-cases-evaluate.js +170 -0
  111. package/lib/role-assistant/test-cases-honesty.js +184 -0
  112. package/lib/role-assistant/test-cases.js +364 -0
  113. package/lib/role-assistant/test-runner-workhub-answers.js +203 -0
  114. package/lib/role-assistant/test-runner-workhub.js +385 -0
  115. package/lib/role-assistant/test-runner.js +500 -0
  116. package/lib/schema/application-schema.json +16 -2
  117. package/lib/schema/deployment-rules.yaml +1 -0
  118. package/lib/schema/external-datasource.schema.json +38 -4
  119. package/lib/schema/external-system.schema.json +4 -4
  120. package/lib/schema/infra.parameter.yaml +20 -0
  121. package/lib/schema/role-assistant-settings.schema.json +108 -0
  122. package/lib/utils/api.js +52 -27
  123. package/lib/utils/app-path-resolve.js +72 -24
  124. package/lib/utils/authentication-shape.js +3 -1
  125. package/lib/utils/deployment-validation.js +28 -3
  126. package/lib/utils/docker-run-ephemeral.js +55 -0
  127. package/lib/utils/enterprise-knowledge-paths.js +29 -12
  128. package/lib/utils/env-copy-keycloak.js +196 -0
  129. package/lib/utils/env-copy.js +34 -1
  130. package/lib/utils/external-system-readiness-compact-display.js +3 -0
  131. package/lib/utils/help-builder.js +1 -0
  132. package/lib/utils/paths.js +67 -23
  133. package/lib/utils/pipeline-upload-auth-retry.js +15 -3
  134. package/lib/utils/role-assistant-paths.js +98 -0
  135. package/lib/utils/schema-loader.js +41 -0
  136. package/lib/utils/schema-resolver.js +36 -4
  137. package/lib/utils/token-manager.js +38 -29
  138. package/lib/utils/url-declarative-resolve-load-doc.js +38 -1
  139. package/lib/validation/external-manifest-validator.js +31 -8
  140. package/lib/validation/validate-external-file.js +8 -1
  141. package/package.json +2 -1
  142. package/scripts/export-builder-api-evidence.js +1 -1
  143. package/templates/applications/dataplane/application.yaml +23 -15
  144. package/templates/applications/dataplane/env.template +1 -1
  145. package/templates/applications/dataplane/rbac.yaml +14 -0
  146. package/templates/applications/miso-controller/application.yaml +1 -1
  147. package/templates/applications/miso-controller/env.template +3 -1
  148. package/templates/channels/chatgpt/install.template.md.hbs +42 -24
  149. package/templates/channels/chatgpt/integration/README.md +10 -7
  150. package/templates/channels/chatgpt/integration/application.json +2 -2
  151. package/templates/channels/chatgpt/integration/chatgpt-system.json +3 -3
  152. package/templates/channels/chatgpt/integration/env.template +1 -1
  153. package/templates/channels/chatgpt/manifest.template.json.hbs +36 -5
  154. package/templates/channels/microsoft-copilot/ai-plugin.template.json.hbs +28 -0
  155. package/templates/channels/microsoft-copilot/declarative-agent.template.json.hbs +22 -0
  156. package/templates/channels/microsoft-copilot/install.template.md.hbs +32 -22
  157. package/templates/channels/microsoft-copilot/integration/README.md +9 -7
  158. package/templates/channels/microsoft-copilot/integration/application.json +2 -2
  159. package/templates/channels/microsoft-copilot/integration/env.template +1 -1
  160. package/templates/channels/microsoft-copilot/integration/microsoft-copilot-system.json +7 -6
  161. package/templates/channels/microsoft-copilot/manifest.template.json.hbs +34 -6
  162. /package/.cursor/plans/{157.1-security-quality-violations-by-type.csv → Done/157.1-security-quality-violations-by-type.csv} +0 -0
@@ -40,6 +40,14 @@ const DATASOURCE_KEY_PARAM = {
40
40
  description: 'Datasource key within the integration workspace.'
41
41
  };
42
42
 
43
+ const ROLE_KEY_PARAM = {
44
+ name: 'roleKey',
45
+ in: 'path',
46
+ required: true,
47
+ schema: { type: 'string' },
48
+ description: 'Role Assistant key that scopes Evidence authoring.'
49
+ };
50
+
43
51
  const IDEMPOTENCY_HEADER = {
44
52
  name: 'Idempotency-Key',
45
53
  in: 'header',
@@ -208,6 +216,21 @@ const OPERATION_BINDINGS = Object.freeze({
208
216
  requestBody: jsonRequestBody('UploadRequest'),
209
217
  successResponse: 'UploadResultResponse'
210
218
  },
219
+ runDeploySystem: {
220
+ parameters: [SYSTEM_KEY_PARAM],
221
+ requestBody: jsonRequestBody('DeployRequest'),
222
+ successResponse: 'DeployResultResponse'
223
+ },
224
+ runProtectionUpload: {
225
+ parameters: [SYSTEM_KEY_PARAM, DATASOURCE_KEY_PARAM],
226
+ requestBody: jsonRequestBody('ProtectionUploadRequest'),
227
+ successResponse: 'ProtectionUploadResponse'
228
+ },
229
+ runProtectionCreate: {
230
+ parameters: [SYSTEM_KEY_PARAM, DATASOURCE_KEY_PARAM],
231
+ requestBody: jsonRequestBody('ProtectionCreateRequest'),
232
+ successResponse: 'ProtectionCreateResponse'
233
+ },
211
234
  materializeTemplate: {
212
235
  parameters: [SYSTEM_KEY_PARAM],
213
236
  requestBody: jsonRequestBody('TemplateMaterializeRequest'),
@@ -251,6 +274,82 @@ const OPERATION_BINDINGS = Object.freeze({
251
274
  },
252
275
  ready: {
253
276
  successResponse: 'ReadyResponse'
277
+ },
278
+ getEvidenceMetadata: {
279
+ parameters: [ROLE_KEY_PARAM],
280
+ successResponse: 'EvidenceAuthoringMetadataResponse'
281
+ },
282
+ downloadEvidence: {
283
+ parameters: [ROLE_KEY_PARAM],
284
+ queryParameters: [
285
+ {
286
+ name: 'resourceType',
287
+ in: 'query',
288
+ required: false,
289
+ schema: { type: 'string' },
290
+ description: 'Filter Evidence by catalog resource type key.'
291
+ },
292
+ {
293
+ name: 'status',
294
+ in: 'query',
295
+ required: false,
296
+ schema: { type: 'string', enum: ['candidate', 'active', 'disabled', 'archived'] },
297
+ description: 'Filter Evidence by lifecycle status.'
298
+ },
299
+ {
300
+ name: 'kindKey',
301
+ in: 'query',
302
+ required: false,
303
+ schema: { type: 'string' },
304
+ description: 'Filter Evidence by kind key.'
305
+ },
306
+ {
307
+ name: 'aspect',
308
+ in: 'query',
309
+ required: false,
310
+ schema: { type: 'string' },
311
+ description: 'Filter Evidence by aspect label.'
312
+ },
313
+ {
314
+ name: 'search',
315
+ in: 'query',
316
+ required: false,
317
+ schema: { type: 'string' },
318
+ description: 'Search Evidence title or text fields.'
319
+ },
320
+ {
321
+ name: 'genericOnly',
322
+ in: 'query',
323
+ required: false,
324
+ schema: { type: 'boolean' },
325
+ description: 'When true, return only generic (non role-bound) Evidence.'
326
+ },
327
+ {
328
+ name: 'limit',
329
+ in: 'query',
330
+ required: false,
331
+ schema: { type: 'integer', minimum: 1 },
332
+ description: 'Maximum number of Evidence rows to return.'
333
+ },
334
+ {
335
+ name: 'offset',
336
+ in: 'query',
337
+ required: false,
338
+ schema: { type: 'integer', minimum: 0 },
339
+ description: 'Offset for Evidence list pagination.'
340
+ }
341
+ ],
342
+ successResponse: 'EvidenceDownloadResponse'
343
+ },
344
+ uploadEvidenceCandidates: {
345
+ parameters: [ROLE_KEY_PARAM],
346
+ requestBody: jsonRequestBody('EvidenceUploadRequest'),
347
+ successResponse: 'EvidenceUploadResponse'
348
+ },
349
+ activateEvidenceCandidates: {
350
+ parameters: [ROLE_KEY_PARAM],
351
+ requestBody: jsonRequestBody('EvidenceActivateRequest'),
352
+ successResponse: 'EvidenceActivateResponse'
254
353
  }
255
354
  });
256
355
 
@@ -96,6 +96,37 @@ const OPENAPI_REQUEST_SCHEMAS = {
96
96
  force: { type: 'boolean' },
97
97
  probe: { type: 'boolean' }
98
98
  }),
99
+ DeployRequest: frozenObject({
100
+ gate: {
101
+ type: 'string',
102
+ description:
103
+ 'Optional pre-promote gates, same as CLI --gate (comma-separated: operations, trust, governance, full).'
104
+ },
105
+ subjectEmail: { type: 'string', format: 'email' },
106
+ probe: { type: 'boolean' },
107
+ sync: { type: 'boolean' },
108
+ verbose: { type: 'boolean' }
109
+ }),
110
+ ProtectionUploadRequest: frozenObject({
111
+ dryRun: { type: 'boolean' },
112
+ sync: { type: 'boolean' },
113
+ verbose: { type: 'boolean' }
114
+ }),
115
+ ProtectionCreateRequest: frozenObject({
116
+ type: { type: 'string' },
117
+ dimensionKey: { type: 'string' },
118
+ field: { type: 'string' },
119
+ fkName: { type: 'string' },
120
+ protectionKey: { type: 'string' },
121
+ displayName: { type: 'string' },
122
+ ruleKey: { type: 'string' },
123
+ principalExpression: { type: 'string' },
124
+ valueExpression: { type: 'string' },
125
+ dryRun: { type: 'boolean' },
126
+ force: { type: 'boolean' },
127
+ verbose: { type: 'boolean' },
128
+ disabled: { type: 'boolean' }
129
+ }),
99
130
  TestRequest: frozenObject({
100
131
  runType: schemaRef('TestRunType'),
101
132
  noPublish: { type: 'boolean' }
@@ -103,7 +134,11 @@ const OPENAPI_REQUEST_SCHEMAS = {
103
134
  CertifyRequest: frozenObject({
104
135
  noPublish: { type: 'boolean' },
105
136
  pack: { type: 'string' },
106
- lifecycleBody: schemaRef('LifecycleRunRequest')
137
+ lifecycleBody: schemaRef('LifecycleRunRequest'),
138
+ subjectEmail: { type: 'string', format: 'email' },
139
+ subjectEmails: stringArraySchema(),
140
+ subjectUserIds: stringArraySchema(),
141
+ certificationProfile: { type: 'string' }
107
142
  }),
108
143
  LifecycleRunRequest: frozenObject({
109
144
  subjectEmail: { type: 'string', format: 'email' },
@@ -51,7 +51,7 @@ const OPENAPI_RESULT_SCHEMAS = {
51
51
  ),
52
52
  LifecycleVerdict: {
53
53
  type: 'string',
54
- enum: ['VERIFIED', 'FAILED', 'NOT_VERIFIED']
54
+ enum: ['VERIFIED', 'FAILED', 'NOT_VERIFIED', 'NOT_APPLICABLE']
55
55
  },
56
56
  CertificationLevel: {
57
57
  type: 'string',
@@ -14,7 +14,11 @@ const CERTIFY_SCHEMA_DESCRIPTIONS = {
14
14
  _schema: 'Optional flags for certification pillar commands.',
15
15
  noPublish: 'When true, skip publishing local files before verify commands.',
16
16
  pack: 'Governance scenario pack key for verify-governance.',
17
- lifecycleBody: 'Optional subject and dry-run options when pillar is lifecycle-run.'
17
+ lifecycleBody: 'Optional subject and dry-run options when pillar is lifecycle-run.',
18
+ subjectEmail: 'Subject user email for governance pack generate (governance pillar).',
19
+ subjectEmails: 'Additional subject emails for governance pack generate.',
20
+ subjectUserIds: 'Subject user ids for governance pack generate.',
21
+ certificationProfile: 'Certification profile for governance generate (bronze, silver, …).'
18
22
  },
19
23
  LifecycleRunRequest: {
20
24
  _schema: 'Options for lifecycle-run certification pillar.',
@@ -42,7 +42,7 @@ const CORE_SCHEMA_DESCRIPTIONS = {
42
42
  value: 'Rejected value when safe to echo (may be omitted for secrets).'
43
43
  },
44
44
  LifecycleVerdict: {
45
- _schema: 'Lifecycle verification outcome: VERIFIED, FAILED, or NOT_VERIFIED.'
45
+ _schema: 'Lifecycle verification outcome: VERIFIED, FAILED, NOT_VERIFIED, or NOT_APPLICABLE.'
46
46
  },
47
47
  CertificationLevel: {
48
48
  _schema: 'Certification tier: BRONZE through PLATINUM, or NONE when uncertified.'
@@ -0,0 +1,156 @@
1
+ /**
2
+ * OpenAPI schema descriptions — Evidence authoring (162.0).
3
+ *
4
+ * @fileoverview Request/result models for BTA Evidence APIs
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ /** @type {Record<string, Object>} */
12
+ const EVIDENCE_SCHEMA_DESCRIPTIONS = {
13
+ EvidenceUploadRow: {
14
+ _schema: 'One Evidence candidate row proposed for upload.',
15
+ key: 'Stable Evidence key when known.',
16
+ resourceType: 'Catalog resource type key this Evidence applies to.',
17
+ roleKey: 'Role Assistant key; must match the selected Role Assistant.',
18
+ kindKey: 'Evidence kind key from live metadata.',
19
+ kindVersion: 'Evidence kind version from live metadata.',
20
+ title: 'Short Evidence title.',
21
+ description: 'Optional longer description.',
22
+ when: 'Condition describing when this Evidence applies.',
23
+ expectedBehavior: 'Required expected behavior text.',
24
+ aspect: 'Optional Evidence aspect label.',
25
+ order: 'Optional display or priority order.',
26
+ status: 'Lifecycle status; upload persists as candidate.'
27
+ },
28
+ EvidenceUploadRequest: {
29
+ _schema: 'Upload one or many Evidence candidates for technical certification.',
30
+ roleKey: 'Selected Role Assistant key for authoring scope.',
31
+ rows: 'Evidence candidate rows to load, validate, and certify.',
32
+ comment: 'Optional certification comment applied to valid rows.'
33
+ },
34
+ EvidenceActivateRequest: {
35
+ _schema: 'Activate human-approved certified Evidence candidates.',
36
+ evidenceIds: 'Evidence ids or keys approved for activation.'
37
+ },
38
+ EvidenceKindSummary: {
39
+ _schema: 'Evidence kind available for authoring.',
40
+ key: 'Evidence kind key.',
41
+ version: 'Evidence kind version.',
42
+ displayName: 'Human-readable kind name.',
43
+ purpose: 'Kind purpose summary when present.'
44
+ },
45
+ EvidenceResourceTypeSummary: {
46
+ _schema: 'Resource type available for Evidence scoping.',
47
+ key: 'Resource type catalog key.',
48
+ displayName: 'Human-readable resource type name.',
49
+ category: 'Resource type category when present.'
50
+ },
51
+ EvidenceAuthoringConstraints: {
52
+ _schema: 'Certification and activation constraints for authoring.',
53
+ certification: 'Technical certification prerequisites.',
54
+ activation: 'Human-gate activation prerequisites.'
55
+ },
56
+ EvidenceAuthoringMetadataData: {
57
+ _schema: 'Authoritative Evidence authoring structure for a Role Assistant.',
58
+ roleKey: 'Selected Role Assistant key.',
59
+ evidenceKinds: 'Live Evidence kinds and versions.',
60
+ aspects: 'Distinct aspects already used by this Role Assistant.',
61
+ resourceTypes: 'Catalog resource types available for scoping.',
62
+ assistantCapabilities: 'Capability keys from the Role Assistant.',
63
+ writableFields: 'Fields the authoring API accepts on upload rows.',
64
+ requiredFields: 'Fields required on every upload row.',
65
+ constraints: 'Certification and activation constraints.'
66
+ },
67
+ EvidenceRowProjection: {
68
+ _schema: 'Evidence row projection returned by download/upload/activate.',
69
+ id: 'Dataplane Evidence id.',
70
+ key: 'Stable Evidence key when present.',
71
+ resourceType: 'Resource type key.',
72
+ roleKey: 'Role Assistant key.',
73
+ kindKey: 'Evidence kind key.',
74
+ kindVersion: 'Evidence kind version.',
75
+ title: 'Evidence title.',
76
+ description: 'Optional description.',
77
+ when: 'When condition text.',
78
+ expectedBehavior: 'Expected behavior text.',
79
+ aspect: 'Aspect label when present.',
80
+ order: 'Order value.',
81
+ status: 'Lifecycle status.',
82
+ fingerprint: 'Content fingerprint when present.'
83
+ },
84
+ EvidenceDownloadData: {
85
+ _schema: 'Existing Evidence for the selected Role Assistant.',
86
+ roleKey: 'Selected Role Assistant key.',
87
+ count: 'Number of Evidence rows returned.',
88
+ data: 'Evidence rows matching the download filters.'
89
+ },
90
+ EvidenceUploadItemOutcome: {
91
+ _schema: 'Per-row upload, validation, or certification outcome.',
92
+ rowIndex: 'Zero-based index in the upload rows array.',
93
+ evidenceId: 'Resolved Evidence id when available.',
94
+ evidenceRef: 'Evidence reference used for lifecycle calls.',
95
+ status: 'Outcome status label.',
96
+ message: 'Human-readable outcome message.',
97
+ issues: 'Validation or certification issues for the row.'
98
+ },
99
+ EvidenceUploadData: {
100
+ _schema: 'Upload result after load, validate, and certify (never activate).',
101
+ roleKey: 'Selected Role Assistant key.',
102
+ inserted: 'Rows inserted by bulk load.',
103
+ updated: 'Rows updated by bulk load.',
104
+ accepted: 'Rows accepted after technical certification.',
105
+ rejected: 'Rows rejected by validation or certification.',
106
+ warnings: 'Non-fatal row warnings.',
107
+ certified: 'Rows that completed technical certification.',
108
+ readyToActivate: 'True when at least one certified inactive row is ready.'
109
+ },
110
+ EvidenceActivateItemOutcome: {
111
+ _schema: 'Per-id activation outcome.',
112
+ evidenceId: 'Requested Evidence id or key.',
113
+ result: 'Activated Evidence projection when successful.',
114
+ error: 'Error message when activation failed.',
115
+ status: 'HTTP or API status code when activation failed.'
116
+ },
117
+ EvidenceActivateData: {
118
+ _schema: 'Activation result for one or many Evidence ids.',
119
+ requested: 'Number of unique Evidence ids requested.',
120
+ activated: 'Successfully activated Evidence outcomes.',
121
+ failed: 'Failed activation outcomes.',
122
+ success: 'True when every requested id activated.'
123
+ },
124
+ EvidenceAuthoringMetadataResponse: {
125
+ _schema: '200 response envelope for getEvidenceMetadata.',
126
+ success: 'Always true for successful builder-api JSON responses.',
127
+ data: 'Typed payload; see EvidenceAuthoringMetadataData.',
128
+ correlationId: 'UUID correlating logs for this request.',
129
+ requestId: 'Optional per-request UUID when emitted by the server.'
130
+ },
131
+ EvidenceDownloadResponse: {
132
+ _schema: '200 response envelope for downloadEvidence.',
133
+ success: 'Always true for successful builder-api JSON responses.',
134
+ data: 'Typed payload; see EvidenceDownloadData.',
135
+ correlationId: 'UUID correlating logs for this request.',
136
+ requestId: 'Optional per-request UUID when emitted by the server.'
137
+ },
138
+ EvidenceUploadResponse: {
139
+ _schema: '200 response envelope for uploadEvidenceCandidates.',
140
+ success: 'Always true for successful builder-api JSON responses.',
141
+ data: 'Typed payload; see EvidenceUploadData.',
142
+ correlationId: 'UUID correlating logs for this request.',
143
+ requestId: 'Optional per-request UUID when emitted by the server.'
144
+ },
145
+ EvidenceActivateResponse: {
146
+ _schema: '200 response envelope for activateEvidenceCandidates.',
147
+ success: 'Always true for successful builder-api JSON responses.',
148
+ data: 'Typed payload; see EvidenceActivateData.',
149
+ correlationId: 'UUID correlating logs for this request.',
150
+ requestId: 'Optional per-request UUID when emitted by the server.'
151
+ }
152
+ };
153
+
154
+ module.exports = {
155
+ EVIDENCE_SCHEMA_DESCRIPTIONS
156
+ };
@@ -37,11 +37,12 @@ const MANIFEST_SCHEMA_DESCRIPTIONS = {
37
37
  assumptions: 'Assumptions recorded during quality scoring.'
38
38
  },
39
39
  ManifestPatchSectionRequest: {
40
- _schema: 'Governed patch body; requires prior GET sectionReadToken.',
40
+ _schema: 'Governed patch body; intent required. sectionReadToken optional (auto re-read when omitted).',
41
41
  intent: 'Why this patch is made — audit and repair hints.',
42
42
  patch: 'Section-scoped merge or replace payload.',
43
43
  mode: 'Merge into existing section value or replace entirely.',
44
- sectionReadToken: 'Token from prior GET; stale token returns 409.',
44
+ sectionReadToken:
45
+ 'Optional token from prior GET. When omitted, server re-reads before write. Stale token returns 409.',
45
46
  dryRun: 'Validate patch without writing files.'
46
47
  },
47
48
  ManifestRepairRequest: {
@@ -68,7 +69,7 @@ const MANIFEST_SCHEMA_DESCRIPTIONS = {
68
69
  },
69
70
  repairHooks: 'Suggested repair hook names after patch.',
70
71
  recommendedNextActions: 'Agent-facing next steps (validate, repair, ask user).',
71
- sectionReadToken: 'Opaque token required for PATCH; obtained from this GET.',
72
+ sectionReadToken: 'Opaque token for optimistic concurrency on PATCH; optional when PATCH auto-refreshes.',
72
73
  quality: 'Deterministic quality score and blocking issues.'
73
74
  },
74
75
  ManifestPatchResultData: {
@@ -73,6 +73,36 @@ const OPERATIONS_SCHEMA_DESCRIPTIONS = {
73
73
  force: 'When true, upload even when validation reports non-blocking issues.',
74
74
  probe: 'When true, perform connectivity probe before upload.'
75
75
  },
76
+ DeployRequest: {
77
+ _schema: 'Optional flags for controller Deploy (CLI aifabrix deploy parity).',
78
+ gate: 'Optional pre-promote gates (comma-separated: operations, trust, governance, full).',
79
+ subjectEmail: 'Subject email for governance gate when gate includes governance or full.',
80
+ probe: 'When true, run dataplane probe checks after deploy.',
81
+ sync: 'When true, force full datasource data sync after deploy.',
82
+ verbose: 'When true, expand deploy summary output.'
83
+ },
84
+ ProtectionUploadRequest: {
85
+ _schema: 'Optional flags for protection upload (CLI protection upload parity).',
86
+ dryRun: 'When true, validate only; do not upload or sync.',
87
+ sync: 'When true, force full datasource data sync after upload.',
88
+ verbose: 'When true, emit verbose protection logs.'
89
+ },
90
+ ProtectionCreateRequest: {
91
+ _schema: 'Optional flags for protection create (CLI protection create parity).',
92
+ type: 'Preset type (for example country-sales).',
93
+ dimensionKey: 'Dimension catalog key when not inferred from type.',
94
+ field: 'Metadata field used by preset value templates.',
95
+ fkName: 'FK binding name in expressions.',
96
+ protectionKey: 'metadata.key override.',
97
+ displayName: 'metadata.displayName override.',
98
+ ruleKey: 'Rule key inside spec.rules[0].',
99
+ principalExpression: 'Group principal expression override.',
100
+ valueExpression: 'Grant valueExpression override.',
101
+ dryRun: 'When true, print scaffold without writing the file.',
102
+ force: 'When true, overwrite an existing local protection manifest.',
103
+ verbose: 'When true, emit verbose probe logs.',
104
+ disabled: 'When true, set spec.enabled to false.'
105
+ },
76
106
  TestRequest: {
77
107
  _schema: 'Optional test ladder options; runType may also be passed as query param.',
78
108
  runType: 'Test stage: unit, integration (default), or e2e.',
@@ -267,6 +297,46 @@ const OPERATIONS_SCHEMA_DESCRIPTIONS = {
267
297
  correlationId: 'UUID correlating logs for this request.',
268
298
  requestId: 'Optional per-request UUID when emitted by the server.'
269
299
  },
300
+ DeployResultData: {
301
+ _schema: 'Controller deploy outcome summary.',
302
+ deployed: 'True when controller deploy completed without gate failure.',
303
+ deploymentId: 'Controller deployment id when returned.',
304
+ environment: 'Target environment key.',
305
+ systemKey: 'Deployed integration system key.'
306
+ },
307
+ DeployResultResponse: {
308
+ _schema: '200 response envelope for runDeploySystem.',
309
+ success: 'Always true for successful builder-api JSON responses.',
310
+ data: 'Typed payload; see DeployResultData.',
311
+ correlationId: 'UUID correlating logs for this request.',
312
+ requestId: 'Optional per-request UUID when emitted by the server.'
313
+ },
314
+ ProtectionUploadData: {
315
+ _schema: 'Protection upload outcome.',
316
+ datasourceKey: 'Datasource key whose protection manifest was uploaded.',
317
+ uploaded: 'True when the manifest was published (false on dryRun).',
318
+ dryRun: 'True when validate-only dry run was requested.'
319
+ },
320
+ ProtectionUploadResponse: {
321
+ _schema: '200 response envelope for runProtectionUpload.',
322
+ success: 'Always true for successful builder-api JSON responses.',
323
+ data: 'Typed payload; see ProtectionUploadData.',
324
+ correlationId: 'UUID correlating logs for this request.',
325
+ requestId: 'Optional per-request UUID when emitted by the server.'
326
+ },
327
+ ProtectionCreateData: {
328
+ _schema: 'Protection create outcome.',
329
+ datasourceKey: 'Datasource key for the scaffolded protection manifest.',
330
+ created: 'True when the local manifest was written (false on dryRun).',
331
+ dryRun: 'True when scaffold was not written to disk.'
332
+ },
333
+ ProtectionCreateResponse: {
334
+ _schema: '200 response envelope for runProtectionCreate.',
335
+ success: 'Always true for successful builder-api JSON responses.',
336
+ data: 'Typed payload; see ProtectionCreateData.',
337
+ correlationId: 'UUID correlating logs for this request.',
338
+ requestId: 'Optional per-request UUID when emitted by the server.'
339
+ },
270
340
  TestResultResponse: {
271
341
  _schema: '200 response envelope for runTest.',
272
342
  success: 'Always true for successful builder-api JSON responses.',
@@ -83,6 +83,7 @@ function requiresBearerAuth(handlerId) {
83
83
  function applyOperationDurationHints(capability, operation) {
84
84
  const durationByHandler = {
85
85
  runUpload: Number(process.env.MAX_UPLOAD_TIMEOUT_MS || 300000),
86
+ runDeploySystem: Number(process.env.MAX_DEPLOY_TIMEOUT_MS || 300000),
86
87
  runTest: Number(process.env.MAX_TEST_E2E_TIMEOUT_MS || 120000),
87
88
  runCertifyPillar: Number(process.env.MAX_CERTIFY_TIMEOUT_MS || 120000)
88
89
  };
@@ -133,6 +134,49 @@ function buildOperationObject(capability) {
133
134
  return operation;
134
135
  }
135
136
 
137
+ /**
138
+ * @returns {Object[]}
139
+ */
140
+ function buildOpenApiTags() {
141
+ return [
142
+ { name: 'workspace', description: 'Per-user integration workspaces (list, create, manifest, status, diff).' },
143
+ { name: 'build', description: 'Wizard generation and manifest repair.' },
144
+ { name: 'manifest', description: 'Governed section get/patch/repair for LLM and MCP workflows.' },
145
+ { name: 'validate', description: 'Local AJV validation and preview-upload (no Dataplane mutation).' },
146
+ { name: 'test', description: 'Unit, integration, and e2e test ladder.' },
147
+ { name: 'certify', description: 'Verify operations/trust/governance and lifecycle certification.' },
148
+ { name: 'apply', description: 'Dev Dataplane upload (requires external-system:publish).' },
149
+ { name: 'template', description: 'Enterprise MCP template.materializeWorkspace and workspace reset.' },
150
+ { name: 'repository', description: 'Enterprise MCP repository.sync, createReview, status, dispatchPipeline.' },
151
+ { name: 'infra', description: 'Liveness and readiness probes (no authentication).' },
152
+ {
153
+ name: 'evidence',
154
+ description:
155
+ 'BTA-facing Evidence authoring: metadata, download, upload (validate+certify), and human-gated activate.'
156
+ }
157
+ ];
158
+ }
159
+
160
+ /**
161
+ * @returns {Object}
162
+ */
163
+ function buildOpenApiInfo() {
164
+ return {
165
+ title: 'AI Fabrix Builder API',
166
+ version: '1.0.0',
167
+ description:
168
+ 'Workspace orchestration for external-system dev publish. Repository and template operations delegate to Enterprise MCP (154.1). Successful JSON responses use `{ success, data, correlationId, requestId? }` with `application/json`. Errors use RFC 7807 Problem Details (`application/problem+json`) aligned with miso-controller and dataplane.',
169
+ 'x-aifabrix': {
170
+ redocUrl: '/api/docs',
171
+ contractTier: 'public',
172
+ mcpGenerationReady: true,
173
+ rbacPreset: 'platform',
174
+ datasourceSplitMode: 'per-tag',
175
+ orchestrationDatasourceTags: listOrchestrationDatasourceTags()
176
+ }
177
+ };
178
+ }
179
+
136
180
  /**
137
181
  * @param {Object} [options]
138
182
  * @param {string} [options.publicBaseUrl]
@@ -148,39 +192,14 @@ function buildOpenApiSpec(options = {}) {
148
192
  if (!paths[pathKey]) {
149
193
  paths[pathKey] = {};
150
194
  }
151
- const method = capability.method.toLowerCase();
152
- paths[pathKey][method] = buildOperationObject(capability);
195
+ paths[pathKey][capability.method.toLowerCase()] = buildOperationObject(capability);
153
196
  }
154
197
 
155
198
  return {
156
199
  openapi: '3.0.3',
157
- info: {
158
- title: 'AI Fabrix Builder API',
159
- version: '1.0.0',
160
- description:
161
- 'Workspace orchestration for external-system dev publish. Repository and template operations delegate to Enterprise MCP (154.1). Successful JSON responses use `{ success, data, correlationId, requestId? }` with `application/json`. Errors use RFC 7807 Problem Details (`application/problem+json`) aligned with miso-controller and dataplane.',
162
- 'x-aifabrix': {
163
- redocUrl: '/api/docs',
164
- contractTier: 'public',
165
- mcpGenerationReady: true,
166
- rbacPreset: 'platform',
167
- datasourceSplitMode: 'per-tag',
168
- orchestrationDatasourceTags: listOrchestrationDatasourceTags()
169
- }
170
- },
200
+ info: buildOpenApiInfo(),
171
201
  servers: [{ url: serverUrl, description: 'Builder API public base URL' }],
172
- tags: [
173
- { name: 'workspace', description: 'Per-user integration workspaces (list, create, manifest, status, diff).' },
174
- { name: 'build', description: 'Wizard generation and manifest repair.' },
175
- { name: 'manifest', description: 'Governed section get/patch/repair for LLM and MCP workflows.' },
176
- { name: 'validate', description: 'Local AJV validation and preview-upload (no Dataplane mutation).' },
177
- { name: 'test', description: 'Unit, integration, and e2e test ladder.' },
178
- { name: 'certify', description: 'Verify operations/trust/governance and lifecycle certification.' },
179
- { name: 'apply', description: 'Dev Dataplane upload (requires external-system:publish).' },
180
- { name: 'template', description: 'Enterprise MCP template.materializeWorkspace and workspace reset.' },
181
- { name: 'repository', description: 'Enterprise MCP repository.sync, createReview, status, dispatchPipeline.' },
182
- { name: 'infra', description: 'Liveness and readiness probes (no authentication).' }
183
- ],
202
+ tags: buildOpenApiTags(),
184
203
  components: {
185
204
  securitySchemes: {
186
205
  bearerAuth: {
@@ -66,6 +66,11 @@ const ORCHESTRATION_TAG_CATALOG = Object.freeze({
66
66
  resourceType: 'channel',
67
67
  permissionClass: 'infra',
68
68
  displayName: 'Infrastructure'
69
+ },
70
+ evidence: {
71
+ resourceType: 'role-evidence',
72
+ permissionClass: 'evidence',
73
+ displayName: 'Evidence'
69
74
  }
70
75
  });
71
76
 
@@ -16,6 +16,9 @@ function getTimeoutMsForHandler(handlerId) {
16
16
  if (handlerId === 'runUpload') {
17
17
  return Number(process.env.MAX_UPLOAD_TIMEOUT_MS || 300000);
18
18
  }
19
+ if (handlerId === 'runDeploySystem') {
20
+ return Number(process.env.MAX_DEPLOY_TIMEOUT_MS || 300000);
21
+ }
19
22
  if (handlerId === 'runTest') {
20
23
  return Number(process.env.MAX_TEST_E2E_TIMEOUT_MS || 120000);
21
24
  }