@aifabrix/builder 2.60.0 → 2.61.2

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 (112) hide show
  1. package/README.md +14 -11
  2. package/docs/README.md +80 -0
  3. package/docs/builder-help/evidence-patterns.json +155 -0
  4. package/docs/builder-help/golden-examples/crm-company.json +30 -0
  5. package/docs/builder-help/golden-examples/crm-deal.json +29 -0
  6. package/docs/builder-help/golden-examples/document-storage-keyed-get.json +85 -0
  7. package/docs/builder-help/golden-examples/document-storage.json +30 -0
  8. package/docs/builder-help/golden-examples/meeting-transcript.json +29 -0
  9. package/docs/builder-help/golden-examples/repository-template.json +29 -0
  10. package/docs/builder-help/golden-examples/service-ticket.json +29 -0
  11. package/docs/builder-help/platform-roles.json +98 -0
  12. package/docs/builder-help/resource-type-catalog.json +402 -0
  13. package/lib/api/configuration.api.js +131 -0
  14. package/lib/api/system-secrets.api.js +72 -0
  15. package/lib/app/run-docker-fallback.js +6 -1
  16. package/lib/app/run-helpers.js +2 -1
  17. package/lib/app/run-parameter-sync.js +142 -0
  18. package/lib/build/docker-build-args.js +5 -2
  19. package/lib/build/index.js +3 -2
  20. package/lib/build/standard-docker-build.js +2 -2
  21. package/lib/cli/setup-app.js +5 -0
  22. package/lib/cli/setup-environment.js +156 -0
  23. package/lib/commands/datasource-capability-upsert-cli.js +112 -0
  24. package/lib/commands/datasource-capability.js +4 -2
  25. package/lib/commands/env-secret-context.js +113 -0
  26. package/lib/commands/env-secret-list.js +200 -0
  27. package/lib/commands/env-secret-push-confirm.js +54 -0
  28. package/lib/commands/env-secret-push-run.js +227 -0
  29. package/lib/commands/env-secret-push.js +168 -0
  30. package/lib/commands/repair-datasource-apply.js +2 -0
  31. package/lib/commands/repair-datasource-keyed-document.js +122 -0
  32. package/lib/commands/repair-datasource-run.js +1 -0
  33. package/lib/commands/setup-modes.js +1 -8
  34. package/lib/commands/setup-prompts.js +2 -180
  35. package/lib/commands/verify-operations-skip-e2e.js +25 -1
  36. package/lib/commands/verify-operations-steps.js +13 -1
  37. package/lib/commands/wizard-config-normalizer.js +7 -4
  38. package/lib/commands/wizard-core.js +5 -157
  39. package/lib/commands/wizard-file-saving.js +163 -0
  40. package/lib/core/env-platform-expand.js +5 -1
  41. package/lib/core/secrets-env-content.js +5 -1
  42. package/lib/core/secrets-env-write.js +10 -3
  43. package/lib/core/secrets-load.js +4 -2
  44. package/lib/datasource/binary-documents-validator.js +190 -0
  45. package/lib/datasource/capability/run-capability-upsert.js +202 -0
  46. package/lib/datasource/capability/upsert-ingredients.js +291 -0
  47. package/lib/datasource/capability/upsert-operations.js +138 -0
  48. package/lib/datasource/capability/upsert-test-scaffold.js +189 -0
  49. package/lib/datasource/validate.js +12 -5
  50. package/lib/generator/index.js +3 -0
  51. package/lib/lifecycle/product-model.js +4 -3
  52. package/lib/lifecycle/report-display.js +3 -2
  53. package/lib/parameters/infra-parameter-catalog.js +1 -1
  54. package/lib/programmatic/builder-help-enterprise-sync-fabrix.js +1 -1
  55. package/lib/programmatic/builder-help-governance.js +1 -1
  56. package/lib/programmatic/builder-help.js +1 -1
  57. package/lib/role-assistant/test-runner-workhub-answers.js +4 -1
  58. package/lib/role-assistant/test-runner-workhub-missing-fields.js +42 -0
  59. package/lib/role-assistant/test-runner-workhub-wait-stop.js +94 -0
  60. package/lib/role-assistant/test-runner-workhub.js +28 -19
  61. package/lib/schema/application-schema.json +14 -2
  62. package/lib/schema/external-datasource.schema.json +23 -3
  63. package/lib/schema/infra.parameter.yaml +388 -38
  64. package/lib/utils/compose-generate-docker-compose.js +7 -12
  65. package/lib/utils/datasource-binary-evidence.js +92 -0
  66. package/lib/utils/datasource-test-run-capability-scope.js +44 -1
  67. package/lib/utils/datasource-test-run-debug-display.js +2 -0
  68. package/lib/utils/datasource-test-run-display.js +8 -2
  69. package/lib/utils/datasource-test-run-issue-guidance.js +176 -0
  70. package/lib/utils/datasource-test-run-tty-log.js +2 -0
  71. package/lib/utils/env-copy.js +11 -10
  72. package/lib/utils/external-system-system-test-tty.js +3 -2
  73. package/lib/utils/image-tags.js +2 -2
  74. package/lib/utils/platform-kv-ref.js +1 -1
  75. package/lib/utils/prepare-local-data-mount.js +58 -0
  76. package/lib/utils/secrets-helpers.js +0 -1
  77. package/lib/utils/system-secret-mapping.js +125 -0
  78. package/lib/utils/test-log-writer.js +2 -1
  79. package/lib/validation/external-manifest-validator.js +5 -0
  80. package/lib/validation/openapi-contract-surface-validator.js +3 -1
  81. package/lib/validation/validate-external-file.js +5 -1
  82. package/package.json +4 -3
  83. package/templates/agent-kit/agent-kit.yaml +1 -1
  84. package/templates/agent-kit/skills/aifabrix-connected-system/SKILL.md +2 -1
  85. package/templates/agent-kit/skills/aifabrix-connected-system/references/delivery-gates.md +15 -0
  86. package/templates/agent-kit/skills/aifabrix-plan/SKILL.md +3 -2
  87. package/templates/agent-kit/skills/aifabrix-prove/SKILL.md +6 -2
  88. package/templates/agent-kit/skills/aifabrix-prove/references/evidence-lifecycle.md +22 -0
  89. package/templates/agent-kit/skills/aifabrix-role-assistant/SKILL.md +7 -1
  90. package/templates/agent-kit/skills/aifabrix-role-assistant/references/testing-playbook.md +117 -0
  91. package/templates/agent-kit/skills/shared/interaction.md +83 -0
  92. package/templates/agent-kit/skills/shared/status.md +3 -12
  93. package/templates/applications/builder-api/application.yaml +1 -1
  94. package/templates/applications/builder-api/env.template +5 -1
  95. package/templates/applications/dataplane/application.yaml +1 -1
  96. package/templates/applications/dataplane/env.template +10 -12
  97. package/templates/applications/keycloak/application.yaml +6 -1
  98. package/templates/applications/miso-controller/application.yaml +74 -2
  99. package/templates/applications/miso-controller/env.template +42 -3
  100. package/templates/applications/miso-controller/rbac.yaml +17 -0
  101. package/templates/external-system/external-datasource.yaml.hbs +7 -1
  102. package/templates/marketplace/main.json +4 -4
  103. package/templates/python/docker-compose.hbs +1 -1
  104. package/templates/agent-kit/skills/aifabrix-plan/references/interaction.md +0 -41
  105. /package/{lib/programmatic/help-content → docs/builder-help/content}/channel-onboarding.md +0 -0
  106. /package/{lib/programmatic/help-content → docs/builder-help/content}/cip-overview.md +0 -0
  107. /package/{lib/programmatic/help-content → docs/builder-help/content}/connected-system-ui.md +0 -0
  108. /package/{lib/programmatic/help-content → docs/builder-help/content}/dimensions-guide.md +0 -0
  109. /package/{lib/programmatic/help-content → docs/builder-help/content}/enterprise-sync-fabrix.md +0 -0
  110. /package/{lib/programmatic/help-content → docs/builder-help/content}/overview.md +0 -0
  111. /package/{lib/programmatic/help-content → docs/builder-help/content}/subscription-guide.md +0 -0
  112. /package/{lib/programmatic/help-content → docs/builder-help/content}/workflow.md +0 -0
@@ -0,0 +1,402 @@
1
+ {
2
+ "schemaVersion": "1.0.0",
3
+ "source": "baseline-resourcetypes.json",
4
+ "lastSynced": "2026-08-22",
5
+ "minimumSystemKeys": [
6
+ "customer",
7
+ "contact",
8
+ "employee",
9
+ "project",
10
+ "task",
11
+ "meeting",
12
+ "document",
13
+ "approval",
14
+ "contract",
15
+ "invoice",
16
+ "deal",
17
+ "ticket",
18
+ "message",
19
+ "channel",
20
+ "workspace",
21
+ "knowledge",
22
+ "event"
23
+ ],
24
+ "resourceTypes": [
25
+ {
26
+ "key": "approval",
27
+ "displayName": "Approval",
28
+ "description": "Approval request, decision, review process, or authorization workflow item.",
29
+ "category": "governance",
30
+ "defaultRiskLevel": "high",
31
+ "status": "active"
32
+ },
33
+ {
34
+ "key": "asset",
35
+ "displayName": "Asset",
36
+ "description": "Managed physical, digital, financial, or operational business asset.",
37
+ "category": "business",
38
+ "defaultRiskLevel": "medium",
39
+ "status": "active"
40
+ },
41
+ {
42
+ "key": "attachment",
43
+ "displayName": "Attachment",
44
+ "description": "File attachment, uploaded content, supporting artifact, or binary business asset.",
45
+ "category": "content",
46
+ "defaultRiskLevel": "low",
47
+ "status": "active"
48
+ },
49
+ {
50
+ "key": "balance",
51
+ "displayName": "Balance",
52
+ "description": "Leave, absence, or accrued time-off balance for a person.",
53
+ "category": "people",
54
+ "defaultRiskLevel": "medium",
55
+ "status": "active"
56
+ },
57
+ {
58
+ "key": "budget",
59
+ "displayName": "Budget",
60
+ "description": "Budget allocation, financial plan, spending target, or funding record.",
61
+ "category": "business",
62
+ "defaultRiskLevel": "medium",
63
+ "status": "active"
64
+ },
65
+ {
66
+ "key": "case",
67
+ "displayName": "Case",
68
+ "description": "Support request, incident, issue, service ticket, or customer problem record.",
69
+ "category": "business",
70
+ "defaultRiskLevel": "medium",
71
+ "status": "active"
72
+ },
73
+ {
74
+ "key": "channel",
75
+ "displayName": "Channel",
76
+ "description": "Collaboration channel, team space, or communication group.",
77
+ "category": "collaboration",
78
+ "defaultRiskLevel": "low",
79
+ "status": "active"
80
+ },
81
+ {
82
+ "key": "contact",
83
+ "displayName": "Contact",
84
+ "description": "Individual person associated with a customer, supplier, partner, or other business entity.",
85
+ "category": "people",
86
+ "defaultRiskLevel": "medium",
87
+ "status": "active"
88
+ },
89
+ {
90
+ "key": "contract",
91
+ "displayName": "Contract",
92
+ "description": "Formal agreement, legal commitment, or business contract between parties.",
93
+ "category": "governance",
94
+ "defaultRiskLevel": "high",
95
+ "status": "active"
96
+ },
97
+ {
98
+ "key": "customer",
99
+ "displayName": "Customer",
100
+ "description": "Organization, account, client, or business entity that purchases, receives, or is associated with products or services.",
101
+ "category": "business",
102
+ "defaultRiskLevel": "medium",
103
+ "status": "active"
104
+ },
105
+ {
106
+ "key": "deal",
107
+ "displayName": "Deal",
108
+ "description": "Commercial deal, sales opportunity, or revenue pursuit in the sales pipeline.",
109
+ "category": "business",
110
+ "defaultRiskLevel": "medium",
111
+ "status": "active"
112
+ },
113
+ {
114
+ "key": "decision",
115
+ "displayName": "Decision",
116
+ "description": "Business decision, resolution, approved action, or governance outcome.",
117
+ "category": "governance",
118
+ "defaultRiskLevel": "high",
119
+ "status": "active"
120
+ },
121
+ {
122
+ "key": "department",
123
+ "displayName": "Department",
124
+ "description": "Organizational unit, business function, or department.",
125
+ "category": "people",
126
+ "defaultRiskLevel": "medium",
127
+ "status": "active"
128
+ },
129
+ {
130
+ "key": "document",
131
+ "displayName": "Document",
132
+ "description": "Business document, file, presentation, contract, or knowledge artifact.",
133
+ "category": "content",
134
+ "defaultRiskLevel": "medium",
135
+ "status": "active"
136
+ },
137
+ {
138
+ "key": "folder",
139
+ "displayName": "Folder",
140
+ "description": "Container or directory for documents and files.",
141
+ "category": "content",
142
+ "defaultRiskLevel": "low",
143
+ "status": "active"
144
+ },
145
+ {
146
+ "key": "hr-report",
147
+ "displayName": "HR Report",
148
+ "description": "People and HR report, workforce analytics rollup, or period summary. Distinct from Document.",
149
+ "category": "people",
150
+ "defaultRiskLevel": "medium",
151
+ "status": "active"
152
+ },
153
+ {
154
+ "key": "email",
155
+ "displayName": "Email",
156
+ "description": "Email message, conversation, or business communication record.",
157
+ "category": "communication",
158
+ "defaultRiskLevel": "low",
159
+ "status": "active"
160
+ },
161
+ {
162
+ "key": "employee",
163
+ "displayName": "Employee",
164
+ "description": "Internal worker, staff member, contractor, or workforce resource.",
165
+ "category": "people",
166
+ "defaultRiskLevel": "medium",
167
+ "status": "active"
168
+ },
169
+ {
170
+ "key": "event",
171
+ "displayName": "Event",
172
+ "description": "Business event, calendar event, milestone, or scheduled activity.",
173
+ "category": "communication",
174
+ "defaultRiskLevel": "low",
175
+ "status": "active"
176
+ },
177
+ {
178
+ "key": "expense",
179
+ "displayName": "Expense",
180
+ "description": "Expense claim, cost record, reimbursement, or financial expenditure.",
181
+ "category": "business",
182
+ "defaultRiskLevel": "medium",
183
+ "status": "active"
184
+ },
185
+ {
186
+ "key": "finance-report",
187
+ "displayName": "Finance Report",
188
+ "description": "Financial report, analytics rollup, or period summary over finance records. Distinct from Document.",
189
+ "category": "business",
190
+ "defaultRiskLevel": "medium",
191
+ "status": "active"
192
+ },
193
+ {
194
+ "key": "invoice",
195
+ "displayName": "Invoice",
196
+ "description": "Billing document, payment request, or financial charge record.",
197
+ "category": "business",
198
+ "defaultRiskLevel": "high",
199
+ "status": "active"
200
+ },
201
+ {
202
+ "key": "knowledge",
203
+ "displayName": "Knowledge",
204
+ "description": "Knowledge article, FAQ, guidance, procedure, or reference content.",
205
+ "category": "content",
206
+ "defaultRiskLevel": "low",
207
+ "status": "active"
208
+ },
209
+ {
210
+ "key": "llm",
211
+ "displayName": "LLM",
212
+ "description": "Large language model provider capability surface for chat completion and embedding operations.",
213
+ "category": "content",
214
+ "defaultRiskLevel": "medium",
215
+ "status": "active"
216
+ },
217
+ {
218
+ "key": "meeting",
219
+ "displayName": "Meeting",
220
+ "description": "Scheduled interaction, discussion, workshop, or business event involving participants.",
221
+ "category": "collaboration",
222
+ "defaultRiskLevel": "low",
223
+ "status": "active"
224
+ },
225
+ {
226
+ "key": "message",
227
+ "displayName": "Message",
228
+ "description": "Chat, Teams message, discussion, or conversational communication record.",
229
+ "category": "communication",
230
+ "defaultRiskLevel": "low",
231
+ "status": "active"
232
+ },
233
+ {
234
+ "key": "note",
235
+ "displayName": "Note",
236
+ "description": "Business note, comment, activity note, CRM note, or user-generated contextual information.",
237
+ "category": "content",
238
+ "defaultRiskLevel": "low",
239
+ "status": "active"
240
+ },
241
+ {
242
+ "key": "objective",
243
+ "displayName": "Objective",
244
+ "description": "Strategic goal, business objective, target outcome, or organizational priority.",
245
+ "category": "business",
246
+ "defaultRiskLevel": "medium",
247
+ "status": "active"
248
+ },
249
+ {
250
+ "key": "opportunity",
251
+ "displayName": "Opportunity",
252
+ "description": "Potential sales, revenue, business development, or commercial opportunity.",
253
+ "category": "business",
254
+ "defaultRiskLevel": "medium",
255
+ "status": "active"
256
+ },
257
+ {
258
+ "key": "operations-report",
259
+ "displayName": "Operations Report",
260
+ "description": "Operations report, operational analytics rollup, or period summary. Distinct from Document.",
261
+ "category": "business",
262
+ "defaultRiskLevel": "medium",
263
+ "status": "active"
264
+ },
265
+ {
266
+ "key": "order",
267
+ "displayName": "Order",
268
+ "description": "Customer order, purchase request, sales order, or transaction record.",
269
+ "category": "business",
270
+ "defaultRiskLevel": "medium",
271
+ "status": "active"
272
+ },
273
+ {
274
+ "key": "organization",
275
+ "displayName": "Organization",
276
+ "description": "Internal organizational entity, subsidiary, legal entity, or business unit.",
277
+ "category": "business",
278
+ "defaultRiskLevel": "medium",
279
+ "status": "active"
280
+ },
281
+ {
282
+ "key": "owner",
283
+ "displayName": "Owner",
284
+ "description": "Individual user or account responsible for ownership, stewardship, or accountability of a record or business object.",
285
+ "category": "people",
286
+ "defaultRiskLevel": "medium",
287
+ "status": "active"
288
+ },
289
+ {
290
+ "key": "partner",
291
+ "displayName": "Partner",
292
+ "description": "External organization participating in business collaboration, delivery, sales, or strategic activities.",
293
+ "category": "business",
294
+ "defaultRiskLevel": "medium",
295
+ "status": "active"
296
+ },
297
+ {
298
+ "key": "payment",
299
+ "displayName": "Payment",
300
+ "description": "Payment transaction, settlement, receipt, or financial payment record.",
301
+ "category": "business",
302
+ "defaultRiskLevel": "high",
303
+ "status": "active"
304
+ },
305
+ {
306
+ "key": "policy",
307
+ "displayName": "Policy",
308
+ "description": "Policy, guideline, compliance rule, or governance document.",
309
+ "category": "governance",
310
+ "defaultRiskLevel": "high",
311
+ "status": "active"
312
+ },
313
+ {
314
+ "key": "position",
315
+ "displayName": "Position",
316
+ "description": "Job role, position, title, or workforce assignment.",
317
+ "category": "people",
318
+ "defaultRiskLevel": "medium",
319
+ "status": "active"
320
+ },
321
+ {
322
+ "key": "product",
323
+ "displayName": "Product",
324
+ "description": "Product, service offering, subscription, or item available for sale or delivery.",
325
+ "category": "business",
326
+ "defaultRiskLevel": "medium",
327
+ "status": "active"
328
+ },
329
+ {
330
+ "key": "project",
331
+ "displayName": "Project",
332
+ "description": "Temporary initiative or work effort with defined objectives, timelines, resources, and deliverables.",
333
+ "category": "business",
334
+ "defaultRiskLevel": "medium",
335
+ "status": "active"
336
+ },
337
+ {
338
+ "key": "repository",
339
+ "displayName": "Repository",
340
+ "description": "Version-controlled source repository for integration manifests, CIP pipelines, and workspace sync.",
341
+ "category": "content",
342
+ "defaultRiskLevel": "medium",
343
+ "status": "active"
344
+ },
345
+ {
346
+ "key": "risk",
347
+ "displayName": "Risk",
348
+ "description": "Potential business, operational, compliance, security, or financial risk.",
349
+ "category": "governance",
350
+ "defaultRiskLevel": "high",
351
+ "status": "active"
352
+ },
353
+ {
354
+ "key": "sales-report",
355
+ "displayName": "Sales Report",
356
+ "description": "Sales report, pipeline analytics rollup, or commercial period summary. Distinct from Document.",
357
+ "category": "business",
358
+ "defaultRiskLevel": "medium",
359
+ "status": "active"
360
+ },
361
+ {
362
+ "key": "supplier",
363
+ "displayName": "Supplier",
364
+ "description": "Organization providing products, services, materials, or external resources.",
365
+ "category": "business",
366
+ "defaultRiskLevel": "medium",
367
+ "status": "active"
368
+ },
369
+ {
370
+ "key": "task",
371
+ "displayName": "Task",
372
+ "description": "Work item, action, assignment, or activity that can be completed by an individual or team.",
373
+ "category": "business",
374
+ "defaultRiskLevel": "medium",
375
+ "status": "active"
376
+ },
377
+ {
378
+ "key": "template",
379
+ "displayName": "Template",
380
+ "description": "Integration workspace template used to materialize local Builder workspaces.",
381
+ "category": "content",
382
+ "defaultRiskLevel": "low",
383
+ "status": "active"
384
+ },
385
+ {
386
+ "key": "ticket",
387
+ "displayName": "Ticket",
388
+ "description": "Support ticket, service request, incident, or customer issue record.",
389
+ "category": "business",
390
+ "defaultRiskLevel": "medium",
391
+ "status": "active"
392
+ },
393
+ {
394
+ "key": "workspace",
395
+ "displayName": "Workspace",
396
+ "description": "Shared workspace, site, or collaboration area for teams and content.",
397
+ "category": "collaboration",
398
+ "defaultRiskLevel": "low",
399
+ "status": "active"
400
+ }
401
+ ]
402
+ }
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Parameter-backed installation configuration API.
3
+ *
4
+ * @fileoverview Read safe configuration metadata from Miso Controller
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const { ApiClient } = require('./index');
12
+
13
+ const PAGE_SIZE = 100;
14
+
15
+ /**
16
+ * @param {string} envKey - Environment key
17
+ * @returns {string} Configuration collection endpoint
18
+ */
19
+ function configurationEndpoint(envKey) {
20
+ return `/api/v1/environments/${encodeURIComponent(envKey)}/configuration`;
21
+ }
22
+
23
+ /**
24
+ * @param {Object} meta - Pagination metadata
25
+ * @param {number} requestedPage - Requested one-based page
26
+ * @param {boolean} hasRows - Whether the page contains rows
27
+ * @returns {number} Validated total page count
28
+ */
29
+ function validatePageMeta(meta, requestedPage, hasRows) {
30
+ const currentPage = Number(meta && meta.currentPage);
31
+ const totalPages = Number(meta && meta.totalPages);
32
+ if (!Number.isInteger(currentPage) || currentPage !== requestedPage) {
33
+ throw new Error('Configuration list response has invalid pagination metadata');
34
+ }
35
+ if (!Number.isInteger(totalPages) || totalPages < 0 || (hasRows && totalPages === 0)) {
36
+ throw new Error('Configuration list response has invalid pagination metadata');
37
+ }
38
+ return totalPages;
39
+ }
40
+
41
+ /**
42
+ * @param {Object} response - API response
43
+ * @param {number} requestedPage - Requested one-based page
44
+ * @returns {{ rows: Object[], totalPages: number }} Validated page
45
+ */
46
+ function readConfigurationPage(response, requestedPage) {
47
+ if (response && response.success === false) {
48
+ throw new Error(response.formattedError || response.error || 'Configuration list request failed');
49
+ }
50
+ const body = response && response.data !== undefined ? response.data : response;
51
+ if (!body || !Array.isArray(body.data) || !body.meta) {
52
+ throw new Error('Configuration list response is not a paginated result');
53
+ }
54
+ const totalPages = validatePageMeta(body.meta, requestedPage, body.data.length > 0);
55
+ return { rows: body.data, totalPages };
56
+ }
57
+
58
+ /**
59
+ * List configuration declarations, optionally for one exact owner.
60
+ *
61
+ * GET /api/v1/environments/{envKey}/configuration
62
+ * @requiresPermission {Controller} controller:monitor or admin:read
63
+ * @async
64
+ * @function listEnvironmentConfiguration
65
+ * @param {string} controllerUrl - Controller base URL
66
+ * @param {Object} authConfig - Authentication configuration
67
+ * @param {string} envKey - Environment key
68
+ * @param {string} [application] - Exact owning application key
69
+ * @param {Object} [options] - Optional safe search
70
+ * @param {string} [options.search] - Partial key/name search
71
+ * @returns {Promise<Object[]>} Safe configuration metadata rows
72
+ */
73
+ async function listEnvironmentConfiguration(controllerUrl, authConfig, envKey, application, options = {}) {
74
+ if (!controllerUrl || typeof controllerUrl !== 'string') {
75
+ throw new Error('controllerUrl is required and must be a string');
76
+ }
77
+ const environment = typeof envKey === 'string' ? envKey.trim() : '';
78
+ const owner = typeof application === 'string' ? application.trim() : '';
79
+ if (!environment) {
80
+ throw new Error('envKey is required and must be a string');
81
+ }
82
+ const client = new ApiClient(controllerUrl, authConfig);
83
+ const common = {
84
+ pageSize: PAGE_SIZE,
85
+ sort: owner ? 'key' : 'application'
86
+ };
87
+ if (owner) common.application = owner;
88
+ if (options.search) common.search = String(options.search).trim();
89
+ const rows = [];
90
+ for (let page = 1;; page += 1) {
91
+ const response = await client.get(configurationEndpoint(environment), {
92
+ params: { ...common, page }
93
+ });
94
+ const result = readConfigurationPage(response, page);
95
+ rows.push(...result.rows);
96
+ if (page >= result.totalPages) return rows;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Update one authoritatively non-sensitive configuration declaration.
102
+ * @param {string} controllerUrl - Controller base URL
103
+ * @param {Object} authConfig - Authentication configuration
104
+ * @param {string} envKey - Environment key
105
+ * @param {string} application - Exact application owner
106
+ * @param {string} key - Configuration declaration key
107
+ * @param {Object} update - Value and concurrency revision
108
+ * @param {string} update.value - Non-sensitive value
109
+ * @param {string} update.revision - Opaque revision from the configuration list
110
+ * @returns {Promise<Object>} Safe updated metadata
111
+ */
112
+ async function putEnvironmentConfiguration(
113
+ controllerUrl, authConfig, envKey, application, key, update
114
+ ) {
115
+ const value = update && update.value;
116
+ const revision = update && update.revision;
117
+ const required = { controllerUrl, envKey, application, key, revision };
118
+ for (const [name, input] of Object.entries(required)) {
119
+ if (!input || typeof input !== 'string') throw new Error(`${name} is required`);
120
+ }
121
+ if (typeof value !== 'string') throw new Error('value must be a string');
122
+ const client = new ApiClient(controllerUrl, authConfig);
123
+ const endpoint = `${configurationEndpoint(envKey)}/${encodeURIComponent(application)}/` +
124
+ encodeURIComponent(key);
125
+ return await client.put(endpoint, { body: { value }, headers: { 'If-Match': revision } });
126
+ }
127
+
128
+ module.exports = {
129
+ listEnvironmentConfiguration,
130
+ putEnvironmentConfiguration
131
+ };
@@ -0,0 +1,72 @@
1
+ /**
2
+ * System secrets API (Miso Controller).
3
+ *
4
+ * Deliberately narrow: a value can be written and never read back, and only against a
5
+ * catalog key the installation already defines. There is no create endpoint, so this module
6
+ * must not grow one — a key that does not exist is a catalog change in aifabrix-miso, not
7
+ * something the CLI can fix.
8
+ *
9
+ * The PUT request body marks `value` as writeOnly. Nothing here returns a value, and no
10
+ * caller should construct a response shape that could carry one.
11
+ *
12
+ * @fileoverview System secrets API functions (put-only over catalog keys)
13
+ * @author AI Fabrix Team
14
+ * @version 1.0.0
15
+ */
16
+
17
+ 'use strict';
18
+
19
+ const { ApiClient } = require('./index');
20
+
21
+ /**
22
+ * @param {string} envKey - Environment key
23
+ * @returns {string} Collection endpoint for that environment
24
+ */
25
+ function systemSecretsEndpoint(envKey) {
26
+ return `/api/v1/environments/${encodeURIComponent(envKey)}/system-secrets`;
27
+ }
28
+
29
+ /**
30
+ * Set one system secret value. The value is write-only: it cannot be read back, and this
31
+ * function returns the server response unchanged without echoing what was sent.
32
+ *
33
+ * PUT /api/v1/environments/{envKey}/system-secrets/{catalogKey}
34
+ * @requiresPermission {Miso} controller:admin
35
+ * @async
36
+ * @function putSystemSecret
37
+ * @param {string} controllerUrl - Controller base URL
38
+ * @param {Object} authConfig - Authentication configuration
39
+ * @param {string} envKey - Environment key
40
+ * @param {string} catalogKey - Catalog key the installation already defines
41
+ * @param {string} value - Secret value, read from a file by the caller
42
+ * @param {string} revision - Opaque revision returned by the configuration list
43
+ * @returns {Promise<Object>} Server response; carries no value
44
+ * @throws {Error} If the request fails. The message must never include the value
45
+ */
46
+ async function putSystemSecret(controllerUrl, authConfig, envKey, catalogKey, value, revision) {
47
+ if (!controllerUrl || typeof controllerUrl !== 'string') {
48
+ throw new Error('controllerUrl is required and must be a string');
49
+ }
50
+ if (!envKey || typeof envKey !== 'string') {
51
+ throw new Error('envKey is required and must be a string');
52
+ }
53
+ if (!catalogKey || typeof catalogKey !== 'string') {
54
+ throw new Error('catalogKey is required and must be a string');
55
+ }
56
+ if (typeof value !== 'string' || value.length === 0) {
57
+ // Names the key, never the value, because this message reaches the terminal.
58
+ throw new Error(`No value supplied for ${catalogKey}`);
59
+ }
60
+ if (!revision || typeof revision !== 'string') {
61
+ throw new Error(`No configuration revision supplied for ${catalogKey}`);
62
+ }
63
+ const client = new ApiClient(controllerUrl, authConfig);
64
+ return await client.put(`${systemSecretsEndpoint(envKey)}/${encodeURIComponent(catalogKey)}`, {
65
+ body: { value },
66
+ headers: { 'If-Match': revision }
67
+ });
68
+ }
69
+
70
+ module.exports = {
71
+ putSystemSecret
72
+ };
@@ -8,6 +8,8 @@
8
8
  'use strict';
9
9
 
10
10
  const chalk = require('chalk');
11
+ const { prepareLocalDataMount } = require('../utils/prepare-local-data-mount');
12
+ const { resolveLocalDataMountPathForCompose } = require('../utils/compose-generate-docker-compose');
11
13
  const logger = require('../utils/logger');
12
14
  const { execWithDockerEnv } = require('../utils/docker-exec');
13
15
  const { getContainerPort } = require('../utils/port-resolver');
@@ -87,7 +89,10 @@ async function executeDockerRunUp(o) {
87
89
  ];
88
90
 
89
91
  if (needsStorage) {
90
- parts.push(`-v ${shellSingleQuote(storageVolumeName(appName, appConfig.developerId))}:/mnt/data`);
92
+ const localPath = resolveLocalDataMountPathForCompose({ appName, appConfig });
93
+ if (localPath) prepareLocalDataMount(localPath, runEnvPath);
94
+ const source = localPath || storageVolumeName(appName, appConfig.developerId);
95
+ parts.push(`-v ${shellSingleQuote(source)}:/mnt/data`);
91
96
  }
92
97
  if (runEnvPath && typeof runEnvPath === 'string') {
93
98
  parts.push(`--env-file ${shellSingleQuote(runEnvPath)}`);
@@ -368,6 +368,8 @@ async function prepareEnvironment(appName, appConfig, options) {
368
368
  developerId,
369
369
  { runEnvKey, effectiveEnvironmentScopedResources }
370
370
  );
371
+ const { hydrateMissingLocalParameters } = require('./run-parameter-sync');
372
+ await hydrateMissingLocalParameters(appName, runEnvPath);
371
373
 
372
374
  const composeOptions = {
373
375
  ...options,
@@ -438,4 +440,3 @@ module.exports = {
438
440
  displayRunStatus,
439
441
  cleanApplicationsDir: runEnvCompose.cleanApplicationsDir
440
442
  };
441
-