@aifabrix/builder 2.44.5 → 2.45.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.
- package/.cursor/rules/cli-layout.mdc +8 -4
- package/.cursor/rules/project-rules.mdc +1 -1
- package/README.md +15 -23
- package/integration/hubspot-test/README.md +2 -0
- package/integration/hubspot-test/test.js +5 -3
- package/jest.projects.js +104 -2
- package/lib/api/controller-health.api.js +49 -0
- package/lib/api/dimension-values.api.js +82 -0
- package/lib/api/dimensions.api.js +114 -0
- package/lib/api/external-systems.api.js +1 -0
- package/lib/api/integration-clients.api.js +168 -0
- package/lib/api/types/dimension-values.types.js +28 -0
- package/lib/api/types/dimensions.types.js +31 -0
- package/lib/api/types/integration-clients.types.js +45 -0
- package/lib/api/validation-runner.js +46 -25
- package/lib/app/deploy-config.js +11 -1
- package/lib/app/deploy-status-display.js +3 -3
- package/lib/app/deploy.js +36 -14
- package/lib/app/display.js +15 -11
- package/lib/app/helpers.js +3 -3
- package/lib/app/index.js +3 -3
- package/lib/app/push.js +46 -23
- package/lib/app/register.js +7 -6
- package/lib/app/restart-display.js +126 -0
- package/lib/app/rotate-secret.js +7 -6
- package/lib/app/run-container-start.js +12 -6
- package/lib/app/run-env-compose.js +30 -1
- package/lib/app/run-helpers.js +58 -19
- package/lib/app/run-reload-sync.js +148 -0
- package/lib/app/run-resolve-image.js +51 -1
- package/lib/app/run.js +148 -74
- package/lib/app/show-display.js +7 -0
- package/lib/app/show.js +87 -5
- package/lib/build/index.js +83 -49
- package/lib/cli/doctor-check.js +117 -0
- package/lib/cli/index.js +8 -2
- package/lib/cli/infra-guided.js +460 -0
- package/lib/cli/installation-log-command.js +73 -0
- package/lib/cli/setup-app.js +31 -3
- package/lib/cli/setup-auth.js +98 -27
- package/lib/cli/setup-dev-path-commands.js +50 -3
- package/lib/cli/setup-infra-up-dataplane-action.js +111 -0
- package/lib/cli/setup-infra-up-platform-action.js +131 -0
- package/lib/cli/setup-infra.js +132 -118
- package/lib/cli/setup-integration-client.js +182 -0
- package/lib/cli/setup-parameters.js +21 -2
- package/lib/cli/setup-platform.js +102 -0
- package/lib/cli/setup-secrets.js +18 -6
- package/lib/cli/setup-utility-resolve.js +132 -0
- package/lib/cli/setup-utility.js +143 -84
- package/lib/commands/app-logs.js +81 -33
- package/lib/commands/auth-config.js +116 -18
- package/lib/commands/datasource-capability-dimension-cli.js +128 -0
- package/lib/commands/datasource-capability-output.js +29 -0
- package/lib/commands/datasource-capability-relate-cli.js +140 -0
- package/lib/commands/datasource-capability.js +411 -0
- package/lib/commands/datasource-unified-test-cli.options.js +1 -1
- package/lib/commands/datasource.js +53 -13
- package/lib/commands/dev-down.js +3 -3
- package/lib/commands/dev-infra-gate.js +32 -0
- package/lib/commands/dev-init.js +13 -7
- package/lib/commands/dimension-value.js +179 -0
- package/lib/commands/dimension.js +330 -0
- package/lib/commands/integration-client.js +430 -0
- package/lib/commands/login-device.js +65 -30
- package/lib/commands/login.js +21 -10
- package/lib/commands/parameters-validate.js +78 -13
- package/lib/commands/repair-datasource-auto-rbac.js +166 -0
- package/lib/commands/repair-datasource-keys.js +10 -5
- package/lib/commands/repair-datasource.js +19 -7
- package/lib/commands/repair-env-template.js +4 -1
- package/lib/commands/repair-openapi-sync.js +172 -0
- package/lib/commands/repair-persist.js +102 -0
- package/lib/commands/repair-rbac-extract.js +27 -0
- package/lib/commands/repair-rbac-migrate.js +186 -0
- package/lib/commands/repair-rbac.js +214 -31
- package/lib/commands/repair-system-alignment.js +246 -0
- package/lib/commands/repair-system-permissions.js +168 -0
- package/lib/commands/repair.js +120 -338
- package/lib/commands/secure.js +1 -1
- package/lib/commands/setup-modes.js +468 -0
- package/lib/commands/setup-prompts.js +421 -0
- package/lib/commands/setup.js +254 -0
- package/lib/commands/teardown.js +277 -0
- package/lib/commands/up-common.js +113 -19
- package/lib/commands/up-dataplane.js +44 -19
- package/lib/commands/up-miso.js +18 -18
- package/lib/commands/upload.js +111 -23
- package/lib/commands/wizard-core-helpers.js +14 -11
- package/lib/commands/wizard-core.js +6 -5
- package/lib/commands/wizard-dataplane.js +2 -2
- package/lib/commands/wizard-entity-selection.js +4 -3
- package/lib/commands/wizard-headless.js +2 -1
- package/lib/commands/wizard.js +2 -1
- package/lib/constants/infra-compose-service-names.js +40 -0
- package/lib/core/audit-logger.js +1 -34
- package/lib/core/config-admin-email.js +56 -0
- package/lib/core/config-normalize.js +60 -0
- package/lib/core/config-registered-controller-urls.js +54 -0
- package/lib/core/config.js +33 -50
- package/lib/core/env-reader.js +16 -3
- package/lib/core/secrets-admin-env.js +101 -0
- package/lib/core/secrets-ensure-infra.js +34 -1
- package/lib/core/secrets-ensure.js +88 -66
- package/lib/core/secrets-env-content.js +428 -0
- package/lib/core/secrets-env-declarative-expand.js +170 -0
- package/lib/core/secrets-env-write.js +29 -1
- package/lib/core/secrets-load.js +252 -0
- package/lib/core/secrets-names.js +32 -0
- package/lib/core/secrets.js +17 -757
- package/lib/datasource/capability/basic-exposure.js +76 -0
- package/lib/datasource/capability/capability-diff-slice.js +41 -0
- package/lib/datasource/capability/capability-key.js +34 -0
- package/lib/datasource/capability/capability-resolve.js +172 -0
- package/lib/datasource/capability/capability-storage-keys.js +22 -0
- package/lib/datasource/capability/copy-operations.js +348 -0
- package/lib/datasource/capability/copy-test-payload.js +139 -0
- package/lib/datasource/capability/create-operations.js +235 -0
- package/lib/datasource/capability/dimension-operations.js +151 -0
- package/lib/datasource/capability/dimension-validate.js +219 -0
- package/lib/datasource/capability/json-pointer.js +31 -0
- package/lib/datasource/capability/reference-rewrite.js +51 -0
- package/lib/datasource/capability/relate-operations.js +325 -0
- package/lib/datasource/capability/relate-validate.js +219 -0
- package/lib/datasource/capability/remove-operations.js +275 -0
- package/lib/datasource/capability/run-capability-copy.js +152 -0
- package/lib/datasource/capability/run-capability-diff.js +135 -0
- package/lib/datasource/capability/run-capability-dimension.js +291 -0
- package/lib/datasource/capability/run-capability-edit.js +377 -0
- package/lib/datasource/capability/run-capability-relate.js +193 -0
- package/lib/datasource/capability/run-capability-remove.js +105 -0
- package/lib/datasource/capability/templates/minimal-fetch.json +18 -0
- package/lib/datasource/capability/validate-capability-slice.js +35 -0
- package/lib/datasource/list.js +136 -23
- package/lib/datasource/log-viewer.js +2 -4
- package/lib/datasource/unified-validation-run.js +51 -16
- package/lib/datasource/validate.js +53 -1
- package/lib/deployment/deploy-poll-ui.js +60 -0
- package/lib/deployment/deployer-status.js +29 -3
- package/lib/deployment/deployer.js +48 -30
- package/lib/deployment/environment.js +7 -2
- package/lib/deployment/poll-interval.js +72 -0
- package/lib/deployment/push.js +11 -9
- package/lib/external-system/deploy.js +9 -2
- package/lib/external-system/download.js +61 -32
- package/lib/external-system/sync-deploy-manifest.js +33 -0
- package/lib/infrastructure/index.js +49 -19
- package/lib/infrastructure/orphan-infra-docker-teardown.js +177 -0
- package/lib/internal/node-fs.js +2 -0
- package/lib/parameters/infra-kv-discovery.js +29 -4
- package/lib/parameters/infra-parameter-catalog.js +6 -3
- package/lib/parameters/infra-parameter-validate.js +67 -19
- package/lib/resolvers/datasource-resolver.js +53 -0
- package/lib/resolvers/dimension-file.js +52 -0
- package/lib/resolvers/manifest-resolver.js +133 -0
- package/lib/schema/application-schema.json +4 -0
- package/lib/schema/external-datasource.schema.json +183 -53
- package/lib/schema/external-system.schema.json +23 -10
- package/lib/schema/infra.parameter.yaml +26 -1
- package/lib/schema/wizard-config.schema.json +1 -1
- package/lib/utils/aifabrix-config-dir-walk.js +40 -0
- package/lib/utils/aifabrix-runtime-config-dir.js +26 -3
- package/lib/utils/app-config-resolver.js +24 -1
- package/lib/utils/app-run-containers.js +2 -2
- package/lib/utils/applications-config-defaults.js +206 -0
- package/lib/utils/auth-config-validator.js +2 -12
- package/lib/utils/bash-secret-env.js +59 -0
- package/lib/utils/cli-secrets-error-format.js +78 -0
- package/lib/utils/cli-test-layout-chalk.js +31 -9
- package/lib/utils/cli-utils.js +4 -36
- package/lib/utils/compose-generate-docker-compose.js +111 -6
- package/lib/utils/compose-generator.js +17 -8
- package/lib/utils/controller-url.js +50 -7
- package/lib/utils/datasource-test-run-display.js +8 -0
- package/lib/utils/dev-hosts-helper.js +3 -2
- package/lib/utils/dev-init-ssh-merge.js +2 -1
- package/lib/utils/docker-build.js +17 -9
- package/lib/utils/docker-reload-mount.js +127 -0
- package/lib/utils/env-copy.js +99 -14
- package/lib/utils/env-template.js +5 -1
- package/lib/utils/external-readme.js +71 -2
- package/lib/utils/external-system-local-test-tty.js +3 -2
- package/lib/utils/external-system-readiness-core.js +45 -12
- package/lib/utils/external-system-readiness-deploy-display.js +3 -3
- package/lib/utils/external-system-readiness-display-internals.js +33 -3
- package/lib/utils/external-system-readiness-display.js +10 -1
- package/lib/utils/file-upload.js +40 -3
- package/lib/utils/health-check-db-init.js +107 -0
- package/lib/utils/health-check-public-warn.js +69 -0
- package/lib/utils/health-check-url.js +28 -10
- package/lib/utils/health-check.js +139 -107
- package/lib/utils/help-builder.js +5 -1
- package/lib/utils/image-name.js +34 -7
- package/lib/utils/infra-optional-service-flags.js +69 -0
- package/lib/utils/installation-log-core.js +282 -0
- package/lib/utils/installation-log-record.js +237 -0
- package/lib/utils/installation-log.js +123 -0
- package/lib/utils/integration-file-backup.js +74 -0
- package/lib/utils/log-redaction.js +105 -0
- package/lib/utils/manifest-location.js +164 -0
- package/lib/utils/manifest-source-emit.js +162 -0
- package/lib/utils/mutagen-install.js +30 -3
- package/lib/utils/paths.js +308 -76
- package/lib/utils/postgres-wipe.js +212 -0
- package/lib/utils/register-aifabrix-shell-env.js +15 -0
- package/lib/utils/remote-dev-auth.js +21 -5
- package/lib/utils/remote-docker-env.js +9 -1
- package/lib/utils/remote-secrets-loader.js +49 -4
- package/lib/utils/resolve-docker-image-ref.js +9 -3
- package/lib/utils/run-cli-flags.js +29 -0
- package/lib/utils/secrets-ancestor-paths.js +47 -0
- package/lib/utils/secrets-canonical.js +10 -3
- package/lib/utils/secrets-helpers.js +17 -10
- package/lib/utils/secrets-kv-refs.js +42 -0
- package/lib/utils/secrets-kv-scope.js +19 -2
- package/lib/utils/secrets-materialize-local.js +134 -0
- package/lib/utils/secrets-path.js +26 -13
- package/lib/utils/secrets-utils.js +20 -10
- package/lib/utils/system-builder-root.js +42 -0
- package/lib/utils/url-declarative-public-base.js +80 -12
- package/lib/utils/url-declarative-resolve-build-urls.js +238 -0
- package/lib/utils/url-declarative-resolve-build.js +24 -388
- package/lib/utils/url-declarative-resolve-expand-token.js +189 -0
- package/lib/utils/url-declarative-resolve-load-doc.js +12 -3
- package/lib/utils/url-declarative-resolve-surface-state.js +102 -0
- package/lib/utils/url-declarative-resolve.js +47 -7
- package/lib/utils/url-declarative-runtime-base-path.js +52 -0
- package/lib/utils/url-declarative-vdir-inactive-env.js +2 -1
- package/lib/utils/urls-local-registry-scan.js +103 -0
- package/lib/utils/urls-local-registry.js +158 -76
- package/lib/utils/validation-poll-ui.js +81 -0
- package/lib/utils/validation-run-poll.js +29 -5
- package/lib/utils/with-muted-logger.js +53 -0
- package/package.json +3 -1
- package/templates/applications/dataplane/application.yaml +5 -1
- package/templates/applications/dataplane/rbac.yaml +10 -10
- package/templates/applications/keycloak/env.template +8 -6
- package/templates/applications/miso-controller/application.yaml +9 -0
- package/templates/applications/miso-controller/env.template +27 -29
- package/templates/applications/miso-controller/rbac.yaml +9 -9
- package/templates/external-system/README.md.hbs +83 -123
- package/.npmrc.token +0 -1
- package/.nyc_output/55e9d034-ddab-4579-a706-e02a91d75c91.json +0 -1
- package/.nyc_output/processinfo/55e9d034-ddab-4579-a706-e02a91d75c91.json +0 -1
- package/.nyc_output/processinfo/index.json +0 -1
- package/lib/api/service-users.api.js +0 -150
- package/lib/api/types/service-users.types.js +0 -65
- package/lib/cli/setup-service-user.js +0 -187
- package/lib/commands/service-user.js +0 -429
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* urls.local.yaml beside
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Primary `urls.local.yaml` beside `config.yaml` (same directory as {@link module:lib/utils/paths.getConfigDirForPaths}),
|
|
3
|
+
* aligned with `secrets.local.yaml`. When missing, {@link readUrlsLocalRegistrySync} may read a legacy
|
|
4
|
+
* file under {@link module:lib/utils/paths.getAifabrixHome} (older releases when `aifabrix-home` was `$HOME`).
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* Per-app keys (see {@link mergeDocIntoRegistry}): `appKey-port`, `appKey-pattern`, `appKey-containerPort`,
|
|
7
|
+
* optional `appKey-internalDockerUseOriginOnly` (boolean) — overrides `frontDoorRouting.internalDockerUseOriginOnly`
|
|
8
|
+
* for declarative `url://` resolution when set (e.g. Keycloak internal URL without `/auth` when true).
|
|
9
|
+
*
|
|
10
|
+
* @fileoverview Read/write registry; scan builder/package dirs in canonical order (plan 141 P3).
|
|
11
|
+
* Duplicate `app.key`: last scan directory wins — no cross-root mtime merge or `AIFABRIX_BUILDER_DIR` ordering.
|
|
7
12
|
* @author AI Fabrix Team
|
|
8
13
|
* @version 1.0.0
|
|
9
14
|
*/
|
|
@@ -15,16 +20,17 @@ const path = require('path');
|
|
|
15
20
|
const yaml = require('js-yaml');
|
|
16
21
|
const { DECLARATIVE_URL_INFRA_DEFAULTS } = require('./infra-env-defaults');
|
|
17
22
|
const pathsUtil = require('./paths');
|
|
23
|
+
const { collectLatestApplicationYamlEntriesPerApp } = require('./urls-local-registry-scan');
|
|
18
24
|
|
|
19
25
|
/**
|
|
20
|
-
* @returns {string} Absolute path to urls.local.yaml (
|
|
26
|
+
* @returns {string} Absolute path to urls.local.yaml (beside config.yaml)
|
|
21
27
|
*/
|
|
22
28
|
function getUrlsLocalYamlPath() {
|
|
23
29
|
return path.join(pathsUtil.getConfigDirForPaths(), 'urls.local.yaml');
|
|
24
30
|
}
|
|
25
31
|
|
|
26
|
-
/** @returns {string} Legacy path
|
|
27
|
-
function
|
|
32
|
+
/** @returns {string} Legacy primary path from older CLI (under resolved AI Fabrix home) */
|
|
33
|
+
function getLegacyUrlsLocalYamlPathAtAifabrixHome() {
|
|
28
34
|
return path.join(pathsUtil.getAifabrixHome(), 'urls.local.yaml');
|
|
29
35
|
}
|
|
30
36
|
|
|
@@ -45,8 +51,8 @@ function readUrlsLocalRegistrySync() {
|
|
|
45
51
|
if (fsRealSync.existsSync(primary)) {
|
|
46
52
|
return loadRegistryYamlFile(primary);
|
|
47
53
|
}
|
|
48
|
-
const legacy =
|
|
49
|
-
if (legacy !== primary && fsRealSync.existsSync(legacy)) {
|
|
54
|
+
const legacy = getLegacyUrlsLocalYamlPathAtAifabrixHome();
|
|
55
|
+
if (path.resolve(legacy) !== path.resolve(primary) && fsRealSync.existsSync(legacy)) {
|
|
50
56
|
return loadRegistryYamlFile(legacy);
|
|
51
57
|
}
|
|
52
58
|
return {};
|
|
@@ -91,22 +97,6 @@ function writeMergedRegistry(merged) {
|
|
|
91
97
|
return merged;
|
|
92
98
|
}
|
|
93
99
|
|
|
94
|
-
/**
|
|
95
|
-
* @param {string} cfgPath
|
|
96
|
-
* @returns {object|null}
|
|
97
|
-
*/
|
|
98
|
-
function tryLoadApplicationYaml(cfgPath) {
|
|
99
|
-
if (!fsRealSync.existsSync(cfgPath)) {
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
try {
|
|
103
|
-
const doc = yaml.load(fsRealSync.readFileSync(cfgPath, 'utf8'));
|
|
104
|
-
return doc && typeof doc === 'object' ? doc : null;
|
|
105
|
-
} catch {
|
|
106
|
-
return null;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
100
|
/**
|
|
111
101
|
* @param {object} doc
|
|
112
102
|
* @returns {number|null}
|
|
@@ -153,102 +143,193 @@ function mergeDocIntoRegistry(merged, doc, folderName) {
|
|
|
153
143
|
} else {
|
|
154
144
|
delete merged[ckey];
|
|
155
145
|
}
|
|
146
|
+
|
|
147
|
+
mergeInternalDockerOriginOnlyRegistryKeyFromDoc(merged, appKey, doc);
|
|
156
148
|
}
|
|
157
149
|
|
|
158
150
|
/**
|
|
151
|
+
* When `application.yaml` explicitly sets `frontDoorRouting.internalDockerUseOriginOnly`, mirror it into
|
|
152
|
+
* `urls.local.yaml` on refresh. If the property is absent, leave any existing registry value unchanged
|
|
153
|
+
* (supports hand-edited `appKey-internalDockerUseOriginOnly` without a YAML field).
|
|
154
|
+
*
|
|
159
155
|
* @param {Object} merged
|
|
160
|
-
* @param {string}
|
|
156
|
+
* @param {string} appKey
|
|
157
|
+
* @param {object} doc
|
|
161
158
|
*/
|
|
162
|
-
function
|
|
163
|
-
|
|
159
|
+
function mergeInternalDockerOriginOnlyRegistryKeyFromDoc(merged, appKey, doc) {
|
|
160
|
+
const key = `${appKey}-internalDockerUseOriginOnly`;
|
|
161
|
+
const fd = doc && doc.frontDoorRouting;
|
|
162
|
+
if (!fd || typeof fd !== 'object') {
|
|
164
163
|
return;
|
|
165
164
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
165
|
+
if (!Object.prototype.hasOwnProperty.call(fd, 'internalDockerUseOriginOnly')) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const v = fd.internalDockerUseOriginOnly;
|
|
169
|
+
if (v === true) {
|
|
170
|
+
merged[key] = true;
|
|
171
|
+
} else if (v === false) {
|
|
172
|
+
merged[key] = false;
|
|
173
|
+
} else {
|
|
174
|
+
delete merged[key];
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
/**
|
|
179
|
-
*
|
|
180
|
-
* @
|
|
181
|
-
*
|
|
182
|
-
* @
|
|
179
|
+
* Append a directory to the scan list when it exists, is a directory, and is not already included (resolved).
|
|
180
|
+
* Later entries win duplicate `app.key` merges (see {@link collectLatestApplicationYamlEntriesPerApp}).
|
|
181
|
+
*
|
|
182
|
+
* @param {string[]} scanDirs
|
|
183
|
+
* @param {string|null|undefined} dirPath
|
|
184
|
+
* @returns {void}
|
|
183
185
|
*/
|
|
184
|
-
function
|
|
185
|
-
|
|
186
|
+
function pushUniqueScanDir(scanDirs, dirPath) {
|
|
187
|
+
if (!dirPath || typeof dirPath !== 'string') {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
let resolved;
|
|
191
|
+
try {
|
|
192
|
+
resolved = path.resolve(dirPath);
|
|
193
|
+
} catch {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
if (!fsRealSync.existsSync(resolved) || !fsRealSync.statSync(resolved).isDirectory()) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
} catch {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
for (const existing of scanDirs) {
|
|
204
|
+
try {
|
|
205
|
+
if (path.resolve(existing) === resolved) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
} catch {
|
|
209
|
+
// ignore
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
scanDirs.push(resolved);
|
|
186
213
|
}
|
|
187
214
|
|
|
188
215
|
/**
|
|
189
|
-
* Builder dirs to scan in order; later merges overwrite registry keys from earlier dirs.
|
|
190
|
-
* When `AIFABRIX_BUILDER_DIR` is set and differs from projectRoot/builder, env builder root is merged last.
|
|
191
|
-
* Otherwise projectRoot/builder is merged last so explicit refresh roots override getBuilderRoot().
|
|
192
|
-
*
|
|
193
|
-
* @param {string} root - Resolved project root passed to refresh
|
|
194
|
-
* @param {string|null} effectiveBuilderDir - pathsUtil.getBuilderRoot()
|
|
195
216
|
* @returns {string[]}
|
|
196
217
|
*/
|
|
197
|
-
function
|
|
198
|
-
const
|
|
199
|
-
let resolvedLegacy;
|
|
200
|
-
let resolvedEffective;
|
|
218
|
+
function getPackageBuilderLikeDirsForRegistryScan() {
|
|
219
|
+
const out = [];
|
|
201
220
|
try {
|
|
202
|
-
|
|
203
|
-
resolvedEffective = effectiveBuilderDir ? path.resolve(effectiveBuilderDir) : null;
|
|
221
|
+
out.push(path.join(pathsUtil.getIntegrationBuilderBaseDir(), 'packages'));
|
|
204
222
|
} catch {
|
|
205
|
-
|
|
223
|
+
// ignore
|
|
206
224
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
225
|
+
try {
|
|
226
|
+
const pr = pathsUtil.getProjectRoot();
|
|
227
|
+
if (pr) {
|
|
228
|
+
out.push(path.join(pr, 'packages'));
|
|
229
|
+
}
|
|
230
|
+
} catch {
|
|
231
|
+
// ignore
|
|
232
|
+
}
|
|
233
|
+
return out;
|
|
234
|
+
}
|
|
213
235
|
|
|
214
|
-
|
|
215
|
-
|
|
236
|
+
/**
|
|
237
|
+
* Canonical builder/package scan roots (low → high priority). Plan 141 P3: fixed order replaces
|
|
238
|
+
* mtime merge and `AIFABRIX_BUILDER_DIR` scan ordering; `findProjectRootFromCwd` builder is last when enabled.
|
|
239
|
+
*
|
|
240
|
+
* @param {string|null} root
|
|
241
|
+
* @param {string|null} effectiveBuilderDir
|
|
242
|
+
* @param {{ excludeCwdBuilderScan?: boolean }} opts
|
|
243
|
+
* @returns {string[]}
|
|
244
|
+
*/
|
|
245
|
+
function buildCanonicalRegistryScanDirs(root, effectiveBuilderDir, opts = {}) {
|
|
246
|
+
const scanDirs = [];
|
|
247
|
+
pushUniqueScanDir(scanDirs, pathsUtil.getSystemBuilderRoot());
|
|
248
|
+
pushUniqueScanDir(scanDirs, effectiveBuilderDir);
|
|
249
|
+
if (root) {
|
|
250
|
+
pushUniqueScanDir(scanDirs, path.join(root, 'builder'));
|
|
216
251
|
}
|
|
217
|
-
|
|
218
|
-
|
|
252
|
+
for (const pkg of getPackageBuilderLikeDirsForRegistryScan()) {
|
|
253
|
+
pushUniqueScanDir(scanDirs, pkg);
|
|
219
254
|
}
|
|
220
|
-
if (
|
|
221
|
-
|
|
255
|
+
if (!opts.excludeCwdBuilderScan) {
|
|
256
|
+
let cwdRoot = null;
|
|
257
|
+
try {
|
|
258
|
+
cwdRoot = pathsUtil.findProjectRootFromCwd();
|
|
259
|
+
} catch {
|
|
260
|
+
cwdRoot = null;
|
|
261
|
+
}
|
|
262
|
+
if (cwdRoot && typeof cwdRoot === 'string') {
|
|
263
|
+
pushUniqueScanDir(scanDirs, path.join(cwdRoot, 'builder'));
|
|
264
|
+
}
|
|
222
265
|
}
|
|
223
|
-
return
|
|
266
|
+
return scanDirs;
|
|
224
267
|
}
|
|
225
268
|
|
|
226
269
|
/**
|
|
227
270
|
* Merge scan results into registry (does not remove stale keys).
|
|
228
271
|
* @param {string|null} projectRoot - getProjectRoot() or null (same semantics as projectRoot || getProjectRoot())
|
|
272
|
+
* @param {{ excludeCwdBuilderScan?: boolean }} [opts] - When `excludeCwdBuilderScan` is true, omit cwd
|
|
273
|
+
* checkout `builder/` (tests / `ctx.projectRoot` isolation — avoids merging ambient repo `builder/`).
|
|
229
274
|
* @returns {Object} Updated registry
|
|
230
275
|
*/
|
|
231
|
-
function refreshUrlsLocalRegistryFromBuilder(projectRoot) {
|
|
276
|
+
function refreshUrlsLocalRegistryFromBuilder(projectRoot, opts) {
|
|
277
|
+
const o = opts && typeof opts === 'object' ? opts : {};
|
|
232
278
|
const root = projectRoot || pathsUtil.getProjectRoot();
|
|
233
279
|
const merged = { ...readUrlsLocalRegistrySync() };
|
|
234
280
|
if (!root) {
|
|
235
281
|
return writeMergedRegistry(merged);
|
|
236
282
|
}
|
|
237
|
-
// Published npm tarball omits builder/ under the package root (.npmignore). Global installs
|
|
238
|
-
//
|
|
283
|
+
// Published npm tarball omits builder/ under the package root (.npmignore). Global installs still
|
|
284
|
+
// resolve materialized apps via getBuilderRoot() (same parent as getSystemBuilderRoot when aligned).
|
|
239
285
|
let effectiveBuilderDir = null;
|
|
240
286
|
try {
|
|
241
287
|
effectiveBuilderDir = pathsUtil.getBuilderRoot();
|
|
242
288
|
} catch {
|
|
243
289
|
effectiveBuilderDir = null;
|
|
244
290
|
}
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
|
|
291
|
+
const scanDirs = buildCanonicalRegistryScanDirs(root, effectiveBuilderDir, o);
|
|
292
|
+
const entries = collectLatestApplicationYamlEntriesPerApp(scanDirs);
|
|
293
|
+
for (const { folderName, doc } of entries) {
|
|
294
|
+
mergeDocIntoRegistry(merged, doc, folderName);
|
|
248
295
|
}
|
|
249
296
|
return writeMergedRegistry(merged);
|
|
250
297
|
}
|
|
251
298
|
|
|
299
|
+
const REGISTRY_BOOL_TRUE = new Set([true, 'true', 'yes', 'on', 1, '1']);
|
|
300
|
+
const REGISTRY_BOOL_FALSE = new Set([false, 'false', 'no', 'off', 0, '0']);
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* @param {unknown} raw
|
|
304
|
+
* @returns {boolean|undefined}
|
|
305
|
+
*/
|
|
306
|
+
function coerceRegistryBool(raw) {
|
|
307
|
+
if (REGISTRY_BOOL_TRUE.has(raw)) {
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
if (REGISTRY_BOOL_FALSE.has(raw)) {
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
return undefined;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Optional `appKey-internalDockerUseOriginOnly` in `urls.local.yaml` (boolean or common string coercions).
|
|
318
|
+
* When set, declarative URL resolution uses this value instead of (or in addition to) `application.yaml`.
|
|
319
|
+
*
|
|
320
|
+
* @param {string} appKey
|
|
321
|
+
* @param {Object|null|undefined} registry
|
|
322
|
+
* @returns {boolean|undefined} undefined when the key is absent or not coercible to boolean
|
|
323
|
+
*/
|
|
324
|
+
function readRegistryInternalDockerUseOriginOnly(appKey, registry) {
|
|
325
|
+
const r = registry && typeof registry === 'object' ? registry : {};
|
|
326
|
+
const key = `${appKey}-internalDockerUseOriginOnly`;
|
|
327
|
+
if (!Object.prototype.hasOwnProperty.call(r, key)) {
|
|
328
|
+
return undefined;
|
|
329
|
+
}
|
|
330
|
+
return coerceRegistryBool(r[key]);
|
|
331
|
+
}
|
|
332
|
+
|
|
252
333
|
/**
|
|
253
334
|
* @param {string} appKey
|
|
254
335
|
* @param {Object} registry
|
|
@@ -282,5 +363,6 @@ module.exports = {
|
|
|
282
363
|
writeUrlsLocalRegistrySync,
|
|
283
364
|
refreshUrlsLocalRegistryFromBuilder,
|
|
284
365
|
normalizePatternForUrl,
|
|
285
|
-
getRegistryEntryForApp
|
|
366
|
+
getRegistryEntryForApp,
|
|
367
|
+
readRegistryInternalDockerUseOriginOnly
|
|
286
368
|
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TTY ora spinner + throttled non-TTY lines for unified validation run polling (aligned with deploy-poll-ui).
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview Validation run poll presentation helpers
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const logger = require('./logger');
|
|
13
|
+
|
|
14
|
+
function shouldUseValidationPollSpinner() {
|
|
15
|
+
return Boolean(process && process.stdout && process.stdout.isTTY);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Single-line ora text / log line for validation polling.
|
|
20
|
+
*
|
|
21
|
+
* @param {Object|null|undefined} envelope - Latest GET envelope (optional before first poll tick)
|
|
22
|
+
* @param {number} attemptIndex - Zero-based poll index after initial POST
|
|
23
|
+
* @param {number} deadlineMs - Wall-clock deadline (Date.now() + remaining budget)
|
|
24
|
+
* @returns {string}
|
|
25
|
+
*/
|
|
26
|
+
function buildValidationPollSpinnerText(envelope, attemptIndex, deadlineMs) {
|
|
27
|
+
const remainingSec = Math.max(0, Math.ceil((deadlineMs - Date.now()) / 1000));
|
|
28
|
+
if (!envelope || typeof envelope !== 'object') {
|
|
29
|
+
return `Waiting for validation run… starting (budget ~${remainingSec}s)`;
|
|
30
|
+
}
|
|
31
|
+
const c =
|
|
32
|
+
envelope.reportCompleteness !== undefined && envelope.reportCompleteness !== null
|
|
33
|
+
? String(envelope.reportCompleteness)
|
|
34
|
+
: '?';
|
|
35
|
+
const st =
|
|
36
|
+
envelope.status !== undefined && envelope.status !== null ? String(envelope.status) : '?';
|
|
37
|
+
return `Waiting for validation run… completeness=${c} status=${st} (poll ${attemptIndex + 1} · ~${remainingSec}s left)`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const NON_TTY_THROTTLE_MS = 5000;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {number} deadlineMs - Absolute deadline for poll budget display
|
|
44
|
+
* @returns {{ usesSpinner: boolean, onPollProgress: Function, finish: () => void }}
|
|
45
|
+
*/
|
|
46
|
+
function createValidationPollHandlers(deadlineMs) {
|
|
47
|
+
if (shouldUseValidationPollSpinner()) {
|
|
48
|
+
const ora = require('ora');
|
|
49
|
+
const spinner = ora({
|
|
50
|
+
text: buildValidationPollSpinnerText(null, 0, deadlineMs),
|
|
51
|
+
spinner: 'dots'
|
|
52
|
+
}).start();
|
|
53
|
+
return {
|
|
54
|
+
usesSpinner: true,
|
|
55
|
+
onPollProgress: (envelope, attemptIndex, _meta) => {
|
|
56
|
+
spinner.text = buildValidationPollSpinnerText(envelope, attemptIndex, deadlineMs);
|
|
57
|
+
},
|
|
58
|
+
finish: () => {
|
|
59
|
+
spinner.stop();
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let lastNonTtyLogAt = 0;
|
|
65
|
+
return {
|
|
66
|
+
usesSpinner: false,
|
|
67
|
+
onPollProgress: (envelope, attemptIndex, _meta) => {
|
|
68
|
+
const now = Date.now();
|
|
69
|
+
if (now - lastNonTtyLogAt < NON_TTY_THROTTLE_MS) return;
|
|
70
|
+
lastNonTtyLogAt = now;
|
|
71
|
+
logger.log(chalk.gray(buildValidationPollSpinnerText(envelope, attemptIndex, deadlineMs)));
|
|
72
|
+
},
|
|
73
|
+
finish: () => {}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = {
|
|
78
|
+
createValidationPollHandlers,
|
|
79
|
+
shouldUseValidationPollSpinner,
|
|
80
|
+
buildValidationPollSpinnerText
|
|
81
|
+
};
|
|
@@ -34,8 +34,8 @@ function sleep(ms) {
|
|
|
34
34
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
function maybeLogPollProgress(envelope, verbosePoll, lastProgressLogAtRef) {
|
|
38
|
-
if (!verbosePoll || !envelope || typeof envelope !== 'object') return;
|
|
37
|
+
function maybeLogPollProgress(envelope, verbosePoll, lastProgressLogAtRef, skipBecauseUi) {
|
|
38
|
+
if (skipBecauseUi || !verbosePoll || !envelope || typeof envelope !== 'object') return;
|
|
39
39
|
const now = Date.now();
|
|
40
40
|
if (now - lastProgressLogAtRef[0] < 5000) return;
|
|
41
41
|
lastProgressLogAtRef[0] = now;
|
|
@@ -57,6 +57,21 @@ function isTerminalReportCompleteness(envelope) {
|
|
|
57
57
|
return envelope.reportCompleteness === 'full';
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
function emitPollProgressLine(
|
|
61
|
+
envelope,
|
|
62
|
+
verbosePoll,
|
|
63
|
+
lastProgressLogAtRef,
|
|
64
|
+
onPollProgress,
|
|
65
|
+
attempt,
|
|
66
|
+
deadline
|
|
67
|
+
) {
|
|
68
|
+
const hasPollUi = typeof onPollProgress === 'function';
|
|
69
|
+
maybeLogPollProgress(envelope, verbosePoll, lastProgressLogAtRef, hasPollUi);
|
|
70
|
+
if (hasPollUi) {
|
|
71
|
+
onPollProgress(envelope, attempt, { deadlineMs: deadline });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
60
75
|
/**
|
|
61
76
|
* Poll until reportCompleteness === 'full' or budget exhausted.
|
|
62
77
|
* @async
|
|
@@ -66,7 +81,8 @@ function isTerminalReportCompleteness(envelope) {
|
|
|
66
81
|
* @param {string} opts.testRunId
|
|
67
82
|
* @param {number} opts.budgetMs - Remaining wall-clock budget for polls only (POST excluded)
|
|
68
83
|
* @param {typeof getValidationRunWithTransportRetry} [opts.fetchRun] - Inject for tests (default: GET with transport retry)
|
|
69
|
-
* @param {boolean} [opts.verbosePoll] - Log throttled progress (plan §3.13)
|
|
84
|
+
* @param {boolean} [opts.verbosePoll] - Log throttled progress (plan §3.13); skipped when `onPollProgress` is set
|
|
85
|
+
* @param {Function|null} [opts.onPollProgress] - `(envelope, attemptIndex, { deadlineMs })` each non-terminal poll
|
|
70
86
|
* @param {number} [opts.pollRequestTimeoutMs] - Per-GET HTTP timeout (match validation aggregate budget)
|
|
71
87
|
* @returns {Promise<{ envelope: Object|null, timedOut: boolean, lastApiResult: Object|null }>}
|
|
72
88
|
*/
|
|
@@ -78,7 +94,8 @@ async function pollValidationRunUntilComplete(opts) {
|
|
|
78
94
|
budgetMs,
|
|
79
95
|
fetchRun = getValidationRunWithTransportRetry,
|
|
80
96
|
verbosePoll = false,
|
|
81
|
-
pollRequestTimeoutMs
|
|
97
|
+
pollRequestTimeoutMs,
|
|
98
|
+
onPollProgress = null
|
|
82
99
|
} = opts;
|
|
83
100
|
const pollTransportOpts =
|
|
84
101
|
Number.isFinite(pollRequestTimeoutMs) && pollRequestTimeoutMs > 0
|
|
@@ -100,7 +117,14 @@ async function pollValidationRunUntilComplete(opts) {
|
|
|
100
117
|
return { envelope, timedOut: false, lastApiResult };
|
|
101
118
|
}
|
|
102
119
|
|
|
103
|
-
|
|
120
|
+
emitPollProgressLine(
|
|
121
|
+
envelope,
|
|
122
|
+
verbosePoll,
|
|
123
|
+
lastProgressLogAtRef,
|
|
124
|
+
onPollProgress,
|
|
125
|
+
attempt,
|
|
126
|
+
deadline
|
|
127
|
+
);
|
|
104
128
|
|
|
105
129
|
const delay = Math.min(nextPollDelayMs(attempt), Math.max(0, deadline - Date.now()));
|
|
106
130
|
attempt += 1;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Temporarily mute logger.log output for guided UX flows.
|
|
3
|
+
*
|
|
4
|
+
* Used by guided installer-style commands (e.g. up-platform default mode) to avoid
|
|
5
|
+
* streaming orchestration mechanics while preserving errors and warnings.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
const logger = require('./logger');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Run a function while muting logger.log/info.
|
|
14
|
+
*
|
|
15
|
+
* - logger.error and logger.warn are preserved.
|
|
16
|
+
* - An optional allowlist can let specific messages through (rare).
|
|
17
|
+
*
|
|
18
|
+
* @template T
|
|
19
|
+
* @param {() => Promise<T>} fn
|
|
20
|
+
* @param {{ allow?: ((...args: any[]) => boolean) }} [opts]
|
|
21
|
+
* @returns {Promise<T>}
|
|
22
|
+
*/
|
|
23
|
+
async function withMutedLogger(fn, opts = {}) {
|
|
24
|
+
const original = {
|
|
25
|
+
log: logger.log,
|
|
26
|
+
info: logger.info
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const allow = typeof opts.allow === 'function' ? opts.allow : null;
|
|
30
|
+
|
|
31
|
+
const muted = (...args) => {
|
|
32
|
+
try {
|
|
33
|
+
if (allow && allow(...args)) {
|
|
34
|
+
return original.log(...args);
|
|
35
|
+
}
|
|
36
|
+
} catch {
|
|
37
|
+
// ignore allow errors; treat as muted
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
logger.log = muted;
|
|
43
|
+
logger.info = muted;
|
|
44
|
+
try {
|
|
45
|
+
return await fn();
|
|
46
|
+
} finally {
|
|
47
|
+
logger.log = original.log;
|
|
48
|
+
logger.info = original.info;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = { withMutedLogger };
|
|
53
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aifabrix/builder",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.45.0",
|
|
4
4
|
"description": "AI Fabrix Local Fabric & Deployment SDK",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -36,6 +36,8 @@
|
|
|
36
36
|
"precommit": "npm run lint:fix && npm run test",
|
|
37
37
|
"install:local": "node scripts/install-local.js && which aifabrix && which af",
|
|
38
38
|
"uninstall:local": "node scripts/install-local.js uninstall && which aifabrix && which af",
|
|
39
|
+
"install:global": "npm install -g . --force && which aifabrix && which af && aifabrix --version",
|
|
40
|
+
"uninstall:global": "npm uninstall -g @aifabrix/builder",
|
|
39
41
|
"diagnose:cli": "node scripts/diagnose-cli.js",
|
|
40
42
|
"check:schema-sync": "node scripts/check-datasource-test-run-schema-sync.js",
|
|
41
43
|
"check:flags": "jest tests/lib/schema/flag-map-validation-run.test.js --runInBand --config jest.config.default.js"
|
|
@@ -8,7 +8,7 @@ app:
|
|
|
8
8
|
version: 1.9.5
|
|
9
9
|
|
|
10
10
|
# Image Configuration
|
|
11
|
-
# Set tag to match your build (e.g. aifabrix build dataplane -t
|
|
11
|
+
# Set tag to match your build (e.g. aifabrix build dataplane -t 1.0.0 then tag: 1.0.0)
|
|
12
12
|
# Registry is required so the controller can pull the image (avoids "docker: not found" on the controller host).
|
|
13
13
|
image:
|
|
14
14
|
name: aifabrix/dataplane
|
|
@@ -26,6 +26,8 @@ environmentScopedResources: true
|
|
|
26
26
|
frontDoorRouting:
|
|
27
27
|
pattern: /data/*
|
|
28
28
|
enabled: true
|
|
29
|
+
# Docker url://internal full URLs: http://dataplane:PORT only (ingress /data is not on in-container routes).
|
|
30
|
+
internalDockerUseOriginOnly: false
|
|
29
31
|
host: ${DEV_USERNAME}.${REMOTE_HOST}
|
|
30
32
|
tls: ${TLS_ENABLED}
|
|
31
33
|
|
|
@@ -63,6 +65,8 @@ build:
|
|
|
63
65
|
envOutputPath: ../../.env # Copy to repo root for local dev
|
|
64
66
|
language: python # Runtime language for template selection (typescript or python)
|
|
65
67
|
reloadStart: uvicorn app.main:app --host 0.0.0.0 --port ${PORT:-3001} --reload # PORT set from port above at run time; default 3001 must match port
|
|
68
|
+
# Pulled-image local compose (no bind-mount): drives `command` in generated docker-compose. Override for non-standard images (e.g. stub ACR tags).
|
|
69
|
+
imageRun: exec python -m uvicorn app.main:app --host 0.0.0.0 --port ${PORT:-3001}
|
|
66
70
|
|
|
67
71
|
# =============================================================================
|
|
68
72
|
# Portal Input Configuration (Deployment Wizard)
|
|
@@ -232,19 +232,19 @@ permissions:
|
|
|
232
232
|
roles: ["aifabrix-platform-admin", "aifabrix-security-admin", "aifabrix-compliance-admin", "aifabrix-observer"]
|
|
233
233
|
description: "Read group information"
|
|
234
234
|
|
|
235
|
-
# OpenAPI
|
|
236
|
-
- name: "
|
|
235
|
+
# OpenAPI / MCP spec bundle (mounted specs under /api/v1/specs)
|
|
236
|
+
- name: "spec:read"
|
|
237
237
|
roles: ["aifabrix-platform-admin", "aifabrix-security-admin", "aifabrix-deployment-admin", "aifabrix-compliance-admin", "aifabrix-developer", "aifabrix-observer"]
|
|
238
|
-
description: "Read OpenAPI
|
|
239
|
-
|
|
240
|
-
- name: "
|
|
238
|
+
description: "Read OpenAPI/MCP spec bundles"
|
|
239
|
+
|
|
240
|
+
- name: "spec:update"
|
|
241
241
|
roles: ["aifabrix-platform-admin", "aifabrix-developer"]
|
|
242
|
-
description: "Update OpenAPI
|
|
243
|
-
|
|
244
|
-
- name: "
|
|
242
|
+
description: "Update OpenAPI/MCP spec bundles (uploaded or user-owned)"
|
|
243
|
+
|
|
244
|
+
- name: "spec:delete"
|
|
245
245
|
roles: ["aifabrix-platform-admin", "aifabrix-developer"]
|
|
246
|
-
description: "Delete OpenAPI
|
|
247
|
-
|
|
246
|
+
description: "Delete OpenAPI/MCP spec bundles (user-owned only; internal specs are not deletable via API)"
|
|
247
|
+
|
|
248
248
|
# External data source write operations
|
|
249
249
|
- name: "external-data-source:write"
|
|
250
250
|
roles: ["aifabrix-platform-admin", "aifabrix-developer"]
|
|
@@ -23,15 +23,17 @@ KC_HTTP_RELATIVE_PATH=url://vdir-public
|
|
|
23
23
|
# must use the PUBLIC URL as issuer in all tokens so they match what the
|
|
24
24
|
# controller expects (KEYCLOAK_SERVER_URL).
|
|
25
25
|
# - Users log in via http://localhost:${KEYCLOAK_PUBLIC_PORT} (browser/CLI)
|
|
26
|
-
# - Server calls Keycloak at
|
|
26
|
+
# - Server calls Keycloak at url://keycloak-internal for token exchange and refresh
|
|
27
27
|
# - Controller sends Host: localhost:${KEYCLOAK_PUBLIC_PORT} so Keycloak validates issuer
|
|
28
28
|
# against public URL (requires KC_HOSTNAME_BACKCHANNEL_DYNAMIC=true)
|
|
29
29
|
# When KC_HOSTNAME_BACKCHANNEL_DYNAMIC=true, hostname must be a full URL.
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
KC_HOSTNAME
|
|
30
|
+
# KC_HTTP_RELATIVE_PATH carries the runtime base path (url://vdir-public), and application.yaml
|
|
31
|
+
# frontDoorRouting exposes the same path for internal server-to-server URLs when enabled.
|
|
32
|
+
# Hostname v2: use a full public URL so Keycloak generates redirects that preserve the /auth base path.
|
|
33
|
+
# `url://public` expands to the full front-door URL (including /auth when Traefik + frontDoorRouting.enabled are on).
|
|
34
|
+
# NOTE: Prefer KC_HOSTNAME (not KC_HOSTNAME_URL). hostname-url triggers legacy hostname v1 warnings and, depending on
|
|
35
|
+
# runtime, may not be treated as an active hostname for hostname-backchannel-dynamic.
|
|
36
|
+
KC_HOSTNAME=url://public
|
|
35
37
|
# nginx / Traefik send X-Forwarded-*; required when using an edge proxy (Keycloak 26+).
|
|
36
38
|
KC_PROXY_HEADERS=xforwarded
|
|
37
39
|
# Required for Host header to work: Keycloak resolves backchannel URL from request headers
|
|
@@ -7,6 +7,8 @@ app:
|
|
|
7
7
|
version: '1.9.5'
|
|
8
8
|
|
|
9
9
|
# Image Configuration
|
|
10
|
+
# Set tag to match your build (e.g. aifabrix build miso-controller -t 1.0.0 then tag: 1.0.0)
|
|
11
|
+
# Registry is required so the controller can pull the image (avoids "docker: not found" on the controller host).
|
|
10
12
|
image:
|
|
11
13
|
name: aifabrix/miso-controller
|
|
12
14
|
tag: latest
|
|
@@ -21,6 +23,8 @@ port: 3000
|
|
|
21
23
|
frontDoorRouting:
|
|
22
24
|
pattern: /miso/*
|
|
23
25
|
enabled: true
|
|
26
|
+
# Docker url://internal full URLs: http://miso-controller:PORT only (ingress /miso is not on in-container routes).
|
|
27
|
+
internalDockerUseOriginOnly: false
|
|
24
28
|
host: ${DEV_USERNAME}.${REMOTE_HOST}
|
|
25
29
|
tls: ${TLS_ENABLED}
|
|
26
30
|
|
|
@@ -57,6 +61,11 @@ build:
|
|
|
57
61
|
language: typescript # Runtime language for template selection (typescript or python)
|
|
58
62
|
reloadStart: pnpm run start:reload # When running with --reload
|
|
59
63
|
|
|
64
|
+
# Repository Configuration (pipeline validate: REPOSITORY_URL_MISMATCH)
|
|
65
|
+
repository:
|
|
66
|
+
enabled: true
|
|
67
|
+
repositoryUrl: https://github.com/aifabrix/aifabrix-miso
|
|
68
|
+
|
|
60
69
|
# =============================================================================
|
|
61
70
|
# Portal Input Configuration (Deployment Wizard)
|
|
62
71
|
# =============================================================================
|