@aifabrix/builder 2.45.5 → 2.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/.cursor/rules/cli-layout.mdc +2 -0
  2. package/.cursor/rules/cli-product-neutral.mdc +43 -0
  3. package/.cursor/rules/project-rules.mdc +1 -0
  4. package/README.md +43 -17
  5. package/integration/hubspot-test/test-artifacts/wizard-hubspot-credential-real.yaml +1 -1
  6. package/integration/hubspot-test/test-artifacts/wizard-hubspot-env-vars.yaml +1 -1
  7. package/jest.config.default.js +2 -1
  8. package/jest.config.isolated.js +2 -1
  9. package/jest.global-live-fabrix-hooks.js +36 -0
  10. package/jest.isolated-projects.js +130 -0
  11. package/jest.projects.js +41 -136
  12. package/lib/api/api-response-errors.js +124 -0
  13. package/lib/api/governance-scenario-pack.api.js +159 -0
  14. package/lib/api/index.js +43 -3
  15. package/lib/api/lifecycle.api.js +77 -0
  16. package/lib/api/pipeline.api.js +3 -1
  17. package/lib/api/records-bulk.api.js +14 -1
  18. package/lib/api/validation-runner.js +3 -1
  19. package/lib/app/deploy-config.js +4 -1
  20. package/lib/app/down.js +20 -1
  21. package/lib/app/push.js +4 -5
  22. package/lib/app/register.js +7 -4
  23. package/lib/app/run-env-compose.js +84 -30
  24. package/lib/build/index.js +5 -0
  25. package/lib/certification/sync-system-certification.js +13 -6
  26. package/lib/cli/index.js +4 -0
  27. package/lib/cli/infra-guided-auth.js +109 -0
  28. package/lib/cli/infra-guided.js +84 -81
  29. package/lib/cli/setup-app.help.js +0 -31
  30. package/lib/cli/setup-app.js +28 -2
  31. package/lib/cli/setup-app.test-commands.js +5 -57
  32. package/lib/cli/setup-auth.js +25 -0
  33. package/lib/cli/setup-certification-commands.js +147 -0
  34. package/lib/cli/setup-certification.help.js +141 -0
  35. package/lib/cli/setup-environment.js +19 -2
  36. package/lib/cli/setup-external-system-help.js +62 -0
  37. package/lib/cli/setup-external-system.js +25 -3
  38. package/lib/cli/setup-infra.js +9 -1
  39. package/lib/cli/setup-platform.js +6 -1
  40. package/lib/cli/setup-secrets.js +33 -1
  41. package/lib/cli/setup-utility-help-after.js +22 -2
  42. package/lib/cli/setup-utility-repair.js +198 -0
  43. package/lib/cli/setup-utility-resolve.js +40 -4
  44. package/lib/cli/setup-utility-validate.js +197 -0
  45. package/lib/cli/setup-utility.js +4 -239
  46. package/lib/commands/auth-status-client-tokens.js +214 -0
  47. package/lib/commands/auth-status-dataplane-version.js +58 -20
  48. package/lib/commands/auth-status.js +41 -47
  49. package/lib/commands/datasource-test-trust-cli.js +27 -23
  50. package/lib/commands/datasource-unified-test-cli.js +6 -3
  51. package/lib/commands/datasource-unified-test-cli.options.js +5 -1
  52. package/lib/commands/datasource.js +7 -7
  53. package/lib/commands/dev-show-display.js +8 -1
  54. package/lib/commands/governance-cli-shared.js +94 -0
  55. package/lib/commands/governance-command-action.js +132 -0
  56. package/lib/commands/governance-download-external.js +34 -0
  57. package/lib/commands/governance-generate-external.js +71 -0
  58. package/lib/commands/governance-upload-external.js +36 -0
  59. package/lib/commands/governance-verify-external.js +64 -0
  60. package/lib/commands/governance.js +144 -0
  61. package/lib/commands/lifecycle-command-action.js +123 -0
  62. package/lib/commands/lifecycle-external.js +268 -0
  63. package/lib/commands/login.js +11 -2
  64. package/lib/commands/repair-auth-apply.js +127 -0
  65. package/lib/commands/repair-changed-files.js +41 -0
  66. package/lib/commands/repair-datasource-keys.js +4 -1
  67. package/lib/commands/repair-datasource-run.js +59 -0
  68. package/lib/commands/repair-datasource-test-payload.js +259 -0
  69. package/lib/commands/repair-datasource.js +1 -51
  70. package/lib/commands/repair-env-template.js +64 -13
  71. package/lib/commands/repair-external-run.js +216 -0
  72. package/lib/commands/repair-openapi-sync.js +23 -0
  73. package/lib/commands/repair-persist.js +4 -0
  74. package/lib/commands/repair-rbac.js +52 -1
  75. package/lib/commands/repair-steps.js +145 -0
  76. package/lib/commands/repair.js +29 -296
  77. package/lib/commands/secrets-get.js +184 -0
  78. package/lib/commands/secrets-remove-all.js +3 -1
  79. package/lib/commands/setup-image-refresh.js +146 -0
  80. package/lib/commands/setup-modes.js +158 -162
  81. package/lib/commands/setup-platform-auth.js +76 -0
  82. package/lib/commands/setup-prompts-admin.js +244 -0
  83. package/lib/commands/setup-prompts-platform-mode.js +67 -0
  84. package/lib/commands/setup-prompts-validators.js +36 -0
  85. package/lib/commands/setup-prompts.js +24 -76
  86. package/lib/commands/setup-run-context.js +45 -0
  87. package/lib/commands/setup-spinners.js +39 -0
  88. package/lib/commands/setup.js +27 -5
  89. package/lib/commands/teardown.js +39 -0
  90. package/lib/commands/test-e2e-external.js +24 -8
  91. package/lib/commands/test-governance-external.js +3 -24
  92. package/lib/commands/test-trust-external.js +20 -21
  93. package/lib/commands/up-common.js +25 -13
  94. package/lib/commands/up-dataplane.js +50 -13
  95. package/lib/commands/upload-publish-context.js +75 -0
  96. package/lib/commands/upload-sidecar-followups.js +89 -0
  97. package/lib/commands/upload.js +90 -108
  98. package/lib/commands/verify-governance-combined-external.js +61 -0
  99. package/lib/commands/verify-governance-command-action.js +64 -0
  100. package/lib/commands/verify-governance-db.js +102 -0
  101. package/lib/commands/verify-governance-external.js +77 -0
  102. package/lib/commands/verify-governance-result-builders.js +71 -0
  103. package/lib/commands/verify-operations-command-action.js +68 -0
  104. package/lib/commands/verify-operations-external.js +268 -0
  105. package/lib/commands/verify-operations-persist.js +75 -0
  106. package/lib/commands/verify-operations-step-plan.js +68 -0
  107. package/lib/commands/verify-operations-steps.js +111 -0
  108. package/lib/commands/verify-trust-command-action.js +70 -0
  109. package/lib/commands/verify-trust-external.js +67 -0
  110. package/lib/commands/wizard-config-normalizer.js +43 -23
  111. package/lib/commands/wizard-core.js +2 -0
  112. package/lib/core/admin-password-generator.js +38 -0
  113. package/lib/core/admin-secrets-bundle.js +111 -0
  114. package/lib/core/admin-secrets-env-overlay.js +62 -0
  115. package/lib/core/admin-secrets.js +32 -4
  116. package/lib/core/config-attach-extensions.js +3 -0
  117. package/lib/core/config-platform-controller.js +44 -0
  118. package/lib/core/config-setup-installation-profile.js +42 -0
  119. package/lib/core/config-setup-platform-mode.js +46 -0
  120. package/lib/core/config.js +46 -36
  121. package/lib/core/secrets-admin-env.js +6 -2
  122. package/lib/core/secrets-ensure.js +4 -0
  123. package/lib/core/secrets-env-content.js +54 -48
  124. package/lib/core/secrets-env-write.js +10 -1
  125. package/lib/core/secrets-infra-placeholder-sync.js +2 -0
  126. package/lib/core/setup-installation-profile.js +43 -0
  127. package/lib/core/setup-platform-mode.js +55 -0
  128. package/lib/datasource/agent-trust-debug-log.js +1 -1
  129. package/lib/datasource/agent-trust-run.js +5 -3
  130. package/lib/datasource/audit-evidence-extract-debug.js +30 -18
  131. package/lib/datasource/audit-evidence-extract.js +7 -4
  132. package/lib/datasource/audit-evidence-verify-matrix.js +54 -26
  133. package/lib/datasource/bulk-loader-run-batches.js +15 -3
  134. package/lib/datasource/datasource-load-export-context.js +3 -0
  135. package/lib/datasource/log-cleaner.js +2 -2
  136. package/lib/datasource/log-viewer.js +8 -8
  137. package/lib/datasource/test-e2e.js +4 -1
  138. package/lib/datasource/unified-validation-run-body.js +3 -1
  139. package/lib/datasource/unified-validation-run.js +5 -2
  140. package/lib/deployment/environment-poll-status.js +138 -0
  141. package/lib/deployment/environment.js +42 -34
  142. package/lib/external-system/download.js +21 -20
  143. package/lib/external-system/generator.js +5 -1
  144. package/lib/external-system/integration-auth-context.js +45 -0
  145. package/lib/external-system/test-auth.js +12 -5
  146. package/lib/external-system/test.js +6 -6
  147. package/lib/generator/external-controller-manifest.js +15 -0
  148. package/lib/governance/governance-cli-errors.js +96 -0
  149. package/lib/governance/governance-download-display.js +38 -0
  150. package/lib/governance/governance-run-display.js +215 -25
  151. package/lib/infrastructure/admin-secrets-apply.js +84 -0
  152. package/lib/infrastructure/admin-secrets-ensure.js +130 -0
  153. package/lib/infrastructure/admin-secrets-resolve.js +95 -0
  154. package/lib/infrastructure/admin-secrets-sync.js +91 -0
  155. package/lib/infrastructure/helpers.js +23 -129
  156. package/lib/infrastructure/index.js +5 -6
  157. package/lib/infrastructure/orphan-infra-docker-teardown.js +11 -5
  158. package/lib/lifecycle/certification-progress.js +231 -0
  159. package/lib/lifecycle/dataplane-ui-url.js +145 -0
  160. package/lib/lifecycle/exit-codes.js +24 -0
  161. package/lib/lifecycle/json-envelope.js +25 -0
  162. package/lib/lifecycle/lifecycle-governance-options.js +51 -0
  163. package/lib/lifecycle/logger-quiet.js +29 -0
  164. package/lib/lifecycle/open-api-published.js +59 -0
  165. package/lib/lifecycle/operations-readiness-metrics.js +101 -0
  166. package/lib/lifecycle/product-model.js +196 -0
  167. package/lib/lifecycle/report-display.js +471 -0
  168. package/lib/lifecycle/scenario-upload.js +191 -0
  169. package/lib/lifecycle/verify-step-progress.js +87 -0
  170. package/lib/parameters/infra-kv-discovery.js +27 -2
  171. package/lib/protection/auth-context.js +10 -4
  172. package/lib/schema/application-schema.json +1 -1
  173. package/lib/schema/datasource-test-run.schema.json +89 -6
  174. package/lib/schema/external-datasource.schema.json +2636 -2622
  175. package/lib/schema/external-system.schema.json +1089 -761
  176. package/lib/schema/infra.parameter.yaml +45 -0
  177. package/lib/schema/type/credential-field-registry.json +103 -97
  178. package/lib/utils/aifabrix-test-runtime-guard.js +125 -0
  179. package/lib/utils/api.js +55 -31
  180. package/lib/utils/app-relative-path-env.js +112 -0
  181. package/lib/utils/cli-secrets-error-format.js +83 -21
  182. package/lib/utils/cli-utils.js +16 -4
  183. package/lib/utils/compose-generate-docker-compose.js +4 -0
  184. package/lib/utils/compose-traefik-ingress-base.js +16 -1
  185. package/lib/utils/config-secrets-path.js +46 -0
  186. package/lib/utils/controller-url.js +88 -1
  187. package/lib/utils/credential-secrets-env.js +137 -9
  188. package/lib/utils/dataplane-resolver.js +129 -2
  189. package/lib/utils/declarative-url-ports.js +3 -3
  190. package/lib/utils/deployment-auth-mode.js +41 -0
  191. package/lib/utils/developer-volume-id.js +33 -0
  192. package/lib/utils/env-copy.js +14 -9
  193. package/lib/utils/env-kv-orphan-lines.js +43 -0
  194. package/lib/utils/error-formatters/network-errors.js +13 -4
  195. package/lib/utils/external-env-template.js +1 -0
  196. package/lib/utils/external-system-readiness-core.js +10 -0
  197. package/lib/utils/external-system-readiness-display.js +80 -23
  198. package/lib/utils/health-check.js +4 -1
  199. package/lib/utils/help-builder.js +11 -8
  200. package/lib/utils/keycloak-realm-ready.js +101 -0
  201. package/lib/utils/load-cip-capacity-display-config.js +61 -15
  202. package/lib/utils/manifest-source-emit.js +2 -0
  203. package/lib/utils/pipeline-upload-auth-retry.js +82 -0
  204. package/lib/utils/platform-controller-url.js +156 -0
  205. package/lib/utils/postgres-platform-bootstrap.js +199 -0
  206. package/lib/utils/postgres-wipe.js +9 -2
  207. package/lib/utils/resolve-env-mode.js +47 -0
  208. package/lib/utils/secrets-generator.js +31 -25
  209. package/lib/utils/secrets-missing-error.js +164 -0
  210. package/lib/utils/service-url-label.js +81 -0
  211. package/lib/utils/setup-quiet-output.js +25 -0
  212. package/lib/utils/template-helpers.js +15 -0
  213. package/lib/utils/token-manager-client-credentials.js +201 -0
  214. package/lib/utils/token-manager-messages.js +8 -0
  215. package/lib/utils/token-manager-refresh.js +12 -2
  216. package/lib/utils/token-manager.js +86 -105
  217. package/lib/utils/upload-pipeline-ui.js +12 -5
  218. package/lib/utils/upload-sync-options.js +42 -0
  219. package/lib/utils/url-declarative-public-base.js +21 -3
  220. package/lib/utils/url-declarative-vdir-inactive-env.js +14 -4
  221. package/lib/utils/validation-poll-ui.js +8 -0
  222. package/lib/utils/validation-run-stage.js +45 -0
  223. package/package.json +1 -1
  224. package/templates/applications/dataplane/application.yaml +2 -1
  225. package/templates/applications/dataplane/env.template +24 -1
  226. package/templates/applications/miso-controller/env.template +16 -0
  227. package/templates/external-system/README.md.hbs +74 -17
  228. package/templates/python/docker-compose.hbs +19 -18
  229. package/templates/typescript/docker-compose.hbs +18 -17
  230. package/lib/commands/test-governance-command-action.js +0 -55
  231. package/lib/commands/test-trust-command-action.js +0 -118
@@ -28,6 +28,11 @@ standardUpInfraEnsureKeys:
28
28
  - databases-dataplane-2-passwordKeyVault
29
29
  - databases-dataplane-3-urlKeyVault
30
30
  - databases-dataplane-3-passwordKeyVault
31
+ # Miso-controller Entra onboarding (vendor app); required for aifabrix resolve miso-controller
32
+ - entra-callback-state-secret
33
+ - entra-callback-uri
34
+ - entra-client-idKeyVault
35
+ - entra-client-secretKeyVault
31
36
  parameters:
32
37
  - key: postgres-passwordKeyVault
33
38
  scope: infra
@@ -117,6 +122,46 @@ parameters:
117
122
  vaultSecretName: keycloak-client-secretKeyVault
118
123
  notes: Per-app OAuth client secret from Keycloak registration; generated on first ensure.
119
124
 
125
+ # Miso-controller Entra ID onboarding (vendor multi-tenant app). Empty client/callback values
126
+ # allow local resolve and start-dev; set real values before Entra admin-consent flows.
127
+ - key: entra-callback-state-secret
128
+ scope: shared-service
129
+ generator:
130
+ type: randomBytes32
131
+ ensureOn: [upInfra, resolveApp]
132
+ azure:
133
+ notes: >-
134
+ Shared HMAC secret (min 16 chars) for OAuth state between controller and Mori callback;
135
+ maps to ENTRA_CALLBACK_STATE_SECRET in miso-controller env.template.
136
+
137
+ - key: entra-callback-uri
138
+ scope: shared-service
139
+ generator:
140
+ type: emptyString
141
+ ensureOn: [upInfra, resolveApp]
142
+ azure:
143
+ notes: >-
144
+ ENTRA_ID_CENTRAL_CALLBACK_URI — Mori web redirect (e.g. …/entra-id-concent/callback);
145
+ empty locally until Mori URL is configured.
146
+
147
+ - key: entra-client-idKeyVault
148
+ scope: shared-service
149
+ generator:
150
+ type: emptyString
151
+ ensureOn: [upInfra, resolveApp]
152
+ azure:
153
+ notes: >-
154
+ Vendor Entra app client id (ENTRA_ID_CLIENT_ID); empty for local dev without Entra flows.
155
+
156
+ - key: entra-client-secretKeyVault
157
+ scope: shared-service
158
+ generator:
159
+ type: emptyString
160
+ ensureOn: [upInfra, resolveApp]
161
+ azure:
162
+ notes: >-
163
+ Vendor Entra app client secret (ENTRA_ID_CLIENT_SECRET); empty for local dev without Entra flows.
164
+
120
165
  # Keycloak events: webhook signature secret used by miso-controller (KEYCLOAK_EVENTS_SECRET).
121
166
  # This must exist on first boot because up-platform runs containers from templates (no prior resolve).
122
167
  - key: keycloak-events-secretKeyVault
@@ -1,9 +1,9 @@
1
1
  {
2
- "version": 5,
2
+ "version": 6,
3
3
  "semantics": {
4
4
  "visibility.show": "When false, the field name is omitted from default portal field lists, embedded credential form field lists, and from public API credentialConfig read models (GET/list with decrypt=false), in addition to any omission driven by encrypted. GET with decrypt=true returns the full decrypted config for authorized callers and does not apply this visibility filter.",
5
5
  "visibility.showValue": "UI-only: whether stored values may be shown versus placeholders in form flows that honor this flag. Does not control encryption at rest or public API stripping.",
6
- "display.enabled": "When false, disables the input in linked credential edit mode only; create flow always allows editing.",
6
+ "display.enabled": "When false, disables the input in credential forms (create and linked edit).",
7
7
  "encrypted": "When true, this config key holds secret material: the server encrypts values at rest, omits the key from public credentialConfig (GET/list with decrypt=false), drives credentialSecretPresence hints, and must stay aligned with CredentialEncryptionService."
8
8
  },
9
9
  "credentialTypes": {
@@ -17,10 +17,6 @@
17
17
  {
18
18
  "name": "grantType",
19
19
  "options": [
20
- {
21
- "value": "authorization_code",
22
- "label": "Authorization Code"
23
- },
24
20
  {
25
21
  "value": "client_credentials",
26
22
  "label": "Client Credentials"
@@ -31,6 +27,20 @@
31
27
  "label": "Grant Type",
32
28
  "control": "select",
33
29
  "required": true,
30
+ "enabled": false
31
+ },
32
+ "visibility": {
33
+ "show": true,
34
+ "showValue": true
35
+ },
36
+ "encrypted": false
37
+ },
38
+ {
39
+ "name": "baseUrl",
40
+ "required": false,
41
+ "display": {
42
+ "label": "Base URL",
43
+ "control": "text",
34
44
  "enabled": true
35
45
  },
36
46
  "visibility": {
@@ -40,10 +50,10 @@
40
50
  "encrypted": false
41
51
  },
42
52
  {
43
- "name": "tokenUrl",
53
+ "name": "clientId",
44
54
  "required": true,
45
55
  "display": {
46
- "label": "Token URL",
56
+ "label": "Client ID",
47
57
  "control": "text",
48
58
  "required": true,
49
59
  "enabled": true
@@ -55,10 +65,10 @@
55
65
  "encrypted": false
56
66
  },
57
67
  {
58
- "name": "clientId",
68
+ "name": "tokenUrl",
59
69
  "required": true,
60
70
  "display": {
61
- "label": "Client ID",
71
+ "label": "Token URL",
62
72
  "control": "text",
63
73
  "required": true,
64
74
  "enabled": true
@@ -85,10 +95,10 @@
85
95
  "encrypted": true
86
96
  },
87
97
  {
88
- "name": "scope",
98
+ "name": "testEndpoint",
89
99
  "required": false,
90
100
  "display": {
91
- "label": "Scope",
101
+ "label": "Test Endpoint",
92
102
  "control": "text",
93
103
  "enabled": true
94
104
  },
@@ -99,18 +109,32 @@
99
109
  "encrypted": false
100
110
  },
101
111
  {
102
- "name": "refreshToken",
112
+ "name": "tenantId",
103
113
  "required": false,
104
114
  "display": {
105
- "label": "Refresh Token",
106
- "control": "password",
107
- "enabled": false
115
+ "label": "Tenant ID",
116
+ "control": "text",
117
+ "enabled": true
108
118
  },
109
119
  "visibility": {
110
120
  "show": false,
111
- "showValue": false
121
+ "showValue": true
112
122
  },
113
- "encrypted": true
123
+ "encrypted": false
124
+ },
125
+ {
126
+ "name": "scope",
127
+ "required": false,
128
+ "display": {
129
+ "label": "Scope",
130
+ "control": "text",
131
+ "enabled": true
132
+ },
133
+ "visibility": {
134
+ "show": true,
135
+ "showValue": true
136
+ },
137
+ "encrypted": false
114
138
  },
115
139
  {
116
140
  "name": "accessToken",
@@ -125,26 +149,36 @@
125
149
  "showValue": false
126
150
  },
127
151
  "encrypted": true
128
- },
152
+ }
153
+ ]
154
+ },
155
+ "apiKey": {
156
+ "active": true,
157
+ "display": {
158
+ "label": "API Key",
159
+ "order": 1
160
+ },
161
+ "configuration": [
129
162
  {
130
- "name": "baseUrl",
131
- "required": false,
163
+ "name": "apiKey",
164
+ "required": true,
132
165
  "display": {
133
- "label": "Base URL",
134
- "control": "text",
166
+ "label": "API Key",
167
+ "control": "password",
168
+ "required": true,
135
169
  "enabled": true
136
170
  },
137
171
  "visibility": {
138
172
  "show": true,
139
- "showValue": true
173
+ "showValue": false
140
174
  },
141
- "encrypted": false
175
+ "encrypted": true
142
176
  },
143
177
  {
144
- "name": "authorizationUrl",
178
+ "name": "baseUrl",
145
179
  "required": false,
146
180
  "display": {
147
- "label": "Authorization URL",
181
+ "label": "Base URL",
148
182
  "control": "text",
149
183
  "enabled": true
150
184
  },
@@ -155,10 +189,11 @@
155
189
  "encrypted": false
156
190
  },
157
191
  {
158
- "name": "redirectUri",
192
+ "name": "headerName",
193
+ "placeholder": "Authorization",
159
194
  "required": false,
160
195
  "display": {
161
- "label": "Redirect URI",
196
+ "label": "Header Name",
162
197
  "control": "text",
163
198
  "enabled": true
164
199
  },
@@ -169,10 +204,10 @@
169
204
  "encrypted": false
170
205
  },
171
206
  {
172
- "name": "tenantId",
207
+ "name": "testEndpoint",
173
208
  "required": false,
174
209
  "display": {
175
- "label": "Tenant ID",
210
+ "label": "Test Endpoint",
176
211
  "control": "text",
177
212
  "enabled": true
178
213
  },
@@ -183,10 +218,11 @@
183
218
  "encrypted": false
184
219
  },
185
220
  {
186
- "name": "testEndpoint",
221
+ "name": "prefix",
222
+ "placeholder": "Bearer",
187
223
  "required": false,
188
224
  "display": {
189
- "label": "Test Endpoint",
225
+ "label": "Prefix",
190
226
  "control": "text",
191
227
  "enabled": true
192
228
  },
@@ -198,18 +234,18 @@
198
234
  }
199
235
  ]
200
236
  },
201
- "apiKey": {
237
+ "bearerToken": {
202
238
  "active": true,
203
239
  "display": {
204
- "label": "API Key",
205
- "order": 1
240
+ "label": "Bearer token",
241
+ "order": 2
206
242
  },
207
243
  "configuration": [
208
244
  {
209
245
  "name": "apiKey",
210
246
  "required": true,
211
247
  "display": {
212
- "label": "API Key",
248
+ "label": "Bearer token",
213
249
  "control": "password",
214
250
  "required": true,
215
251
  "enabled": true
@@ -220,36 +256,6 @@
220
256
  },
221
257
  "encrypted": true
222
258
  },
223
- {
224
- "name": "headerName",
225
- "placeholder": "Authorization",
226
- "required": false,
227
- "display": {
228
- "label": "Header Name",
229
- "control": "text",
230
- "enabled": true
231
- },
232
- "visibility": {
233
- "show": true,
234
- "showValue": true
235
- },
236
- "encrypted": false
237
- },
238
- {
239
- "name": "prefix",
240
- "placeholder": "Bearer",
241
- "required": false,
242
- "display": {
243
- "label": "Prefix",
244
- "control": "text",
245
- "enabled": true
246
- },
247
- "visibility": {
248
- "show": true,
249
- "showValue": true
250
- },
251
- "encrypted": false
252
- },
253
259
  {
254
260
  "name": "baseUrl",
255
261
  "required": false,
@@ -284,7 +290,7 @@
284
290
  "active": true,
285
291
  "display": {
286
292
  "label": "Basic Auth",
287
- "order": 2
293
+ "order": 3
288
294
  },
289
295
  "configuration": [
290
296
  {
@@ -303,33 +309,33 @@
303
309
  "encrypted": true
304
310
  },
305
311
  {
306
- "name": "password",
307
- "required": true,
312
+ "name": "baseUrl",
313
+ "required": false,
308
314
  "display": {
309
- "label": "Password",
310
- "control": "password",
311
- "required": true,
315
+ "label": "Base URL",
316
+ "control": "text",
312
317
  "enabled": true
313
318
  },
314
319
  "visibility": {
315
320
  "show": true,
316
- "showValue": false
321
+ "showValue": true
317
322
  },
318
- "encrypted": true
323
+ "encrypted": false
319
324
  },
320
325
  {
321
- "name": "baseUrl",
322
- "required": false,
326
+ "name": "password",
327
+ "required": true,
323
328
  "display": {
324
- "label": "Base URL",
325
- "control": "text",
329
+ "label": "Password",
330
+ "control": "password",
331
+ "required": true,
326
332
  "enabled": true
327
333
  },
328
334
  "visibility": {
329
335
  "show": true,
330
- "showValue": true
336
+ "showValue": false
331
337
  },
332
- "encrypted": false
338
+ "encrypted": true
333
339
  }
334
340
  ]
335
341
  },
@@ -337,7 +343,7 @@
337
343
  "active": true,
338
344
  "display": {
339
345
  "label": "Query Parameter",
340
- "order": 3
346
+ "order": 4
341
347
  },
342
348
  "configuration": [
343
349
  {
@@ -357,33 +363,33 @@
357
363
  "encrypted": false
358
364
  },
359
365
  {
360
- "name": "paramValue",
361
- "required": true,
366
+ "name": "baseUrl",
367
+ "required": false,
362
368
  "display": {
363
- "label": "Parameter Value",
364
- "control": "password",
365
- "required": true,
369
+ "label": "Base URL",
370
+ "control": "text",
366
371
  "enabled": true
367
372
  },
368
373
  "visibility": {
369
374
  "show": true,
370
- "showValue": false
375
+ "showValue": true
371
376
  },
372
- "encrypted": true
377
+ "encrypted": false
373
378
  },
374
379
  {
375
- "name": "baseUrl",
376
- "required": false,
380
+ "name": "paramValue",
381
+ "required": true,
377
382
  "display": {
378
- "label": "Base URL",
379
- "control": "text",
383
+ "label": "Parameter Value",
384
+ "control": "password",
385
+ "required": true,
380
386
  "enabled": true
381
387
  },
382
388
  "visibility": {
383
389
  "show": true,
384
- "showValue": true
390
+ "showValue": false
385
391
  },
386
- "encrypted": false
392
+ "encrypted": true
387
393
  }
388
394
  ]
389
395
  },
@@ -391,7 +397,7 @@
391
397
  "active": false,
392
398
  "display": {
393
399
  "label": "OIDC",
394
- "order": 4
400
+ "order": 5
395
401
  },
396
402
  "configuration": [
397
403
  {
@@ -482,7 +488,7 @@
482
488
  "active": false,
483
489
  "display": {
484
490
  "label": "HMAC",
485
- "order": 5
491
+ "order": 6
486
492
  },
487
493
  "configuration": [
488
494
  {
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Refuse writes to live ~/.aifabrix paths during Jest runs.
3
+ *
4
+ * @fileoverview Test-runtime write guard for secrets and admin-secrets files
5
+ * @author AI Fabrix Team
6
+ * @version 1.0.0
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+ const os = require('os');
14
+
15
+ const ALLOW_ENV = 'ALLOW_AIFABRIX_TEST_WRITE_REAL_CONFIG';
16
+
17
+ /**
18
+ * @returns {boolean}
19
+ */
20
+ function isJestTestProcess() {
21
+ return Boolean(process.env.JEST_WORKER_ID) || process.env.NODE_ENV === 'test';
22
+ }
23
+
24
+ /** Legacy mock Fabrix dir used across unit tests (not the operator tree when homedir differs). */
25
+ const JEST_MOCK_FABRIX_ROOT = path.join('/home', 'test', '.aifabrix');
26
+
27
+ /** Additional protected trees in cloud / monorepo dev (see plan 185 Phase 2.5). */
28
+ const EXTRA_PROTECTED_FABRIX_ROOTS = ['/workspace/.aifabrix'];
29
+
30
+ /**
31
+ * Resolve symlinks so `~/.aifabrix` → `/workspace/.aifabrix` matches both paths.
32
+ * @param {string} p
33
+ * @returns {string}
34
+ */
35
+ function resolveFabrixPathKey(p) {
36
+ const resolved = path.resolve(p);
37
+ try {
38
+ if (fs.existsSync(resolved)) {
39
+ return fs.realpathSync(resolved);
40
+ }
41
+ } catch {
42
+ // ignore
43
+ }
44
+ return resolved;
45
+ }
46
+
47
+ /**
48
+ * @returns {string[]} Absolute live config directory paths (deduped by realpath).
49
+ */
50
+ function getLiveFabrixConfigDirCandidates() {
51
+ const keys = new Set();
52
+ const dirs = [];
53
+ const add = (dir) => {
54
+ if (!dir || typeof dir !== 'string') return;
55
+ const key = resolveFabrixPathKey(dir);
56
+ if (keys.has(key)) return;
57
+ keys.add(key);
58
+ dirs.push(key);
59
+ };
60
+ add(path.join(path.resolve(os.homedir()), '.aifabrix'));
61
+ for (const root of EXTRA_PROTECTED_FABRIX_ROOTS) {
62
+ add(root);
63
+ }
64
+ return dirs;
65
+ }
66
+
67
+ /**
68
+ * True when the path is the operator's live ~/.aifabrix tree (not the legacy /home/test mock).
69
+ * @param {string} filePath
70
+ * @returns {boolean}
71
+ */
72
+ function isLiveFabrixConfigPath(filePath) {
73
+ if (!filePath || typeof filePath !== 'string') return false;
74
+ const normalized = resolveFabrixPathKey(filePath);
75
+ if (
76
+ normalized === JEST_MOCK_FABRIX_ROOT ||
77
+ normalized.startsWith(`${JEST_MOCK_FABRIX_ROOT}${path.sep}`)
78
+ ) {
79
+ return false;
80
+ }
81
+ for (const liveRoot of getLiveFabrixConfigDirCandidates()) {
82
+ if (normalized === liveRoot || normalized.startsWith(`${liveRoot}${path.sep}`)) {
83
+ return true;
84
+ }
85
+ }
86
+ return false;
87
+ }
88
+
89
+ /**
90
+ * During Jest, writes are allowed everywhere except the live ~/.aifabrix tree.
91
+ * @param {string} filePath
92
+ * @returns {boolean}
93
+ */
94
+ function isAllowedTestWritePath(filePath) {
95
+ if (!filePath || typeof filePath !== 'string') return true;
96
+ if (process.env[ALLOW_ENV] === '1' || process.env[ALLOW_ENV] === 'true') {
97
+ return true;
98
+ }
99
+ if (!isJestTestProcess()) return true;
100
+ return !isLiveFabrixConfigPath(filePath);
101
+ }
102
+
103
+ /**
104
+ * @param {string} filePath
105
+ * @throws {Error} When Jest would write outside sandbox
106
+ */
107
+ function assertWritableSecretsPathForTests(filePath) {
108
+ if (!isJestTestProcess()) return;
109
+ if (isAllowedTestWritePath(filePath)) return;
110
+ throw new Error(
111
+ `Refusing to write secrets to live config path during tests: ${filePath}. ` +
112
+ 'Use the Jest sandbox (default) or set ALLOW_AIFABRIX_TEST_WRITE_REAL_CONFIG=1.'
113
+ );
114
+ }
115
+
116
+ module.exports = {
117
+ ALLOW_ENV,
118
+ EXTRA_PROTECTED_FABRIX_ROOTS,
119
+ isJestTestProcess,
120
+ resolveFabrixPathKey,
121
+ getLiveFabrixConfigDirCandidates,
122
+ isLiveFabrixConfigPath,
123
+ isAllowedTestWritePath,
124
+ assertWritableSecretsPathForTests
125
+ };