@flui-cloud/cli 0.1.0 → 0.2.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.
@@ -22,6 +22,7 @@ const api_client_1 = require("../../lib/api-client");
22
22
  const config_storage_1 = require("../../lib/config-storage");
23
23
  const provider_credential_schemas_1 = require("../../lib/provider-credential-schemas");
24
24
  const context_banner_1 = require("../../lib/context-banner");
25
+ const release_override_1 = require("../../config/release-override");
25
26
  const server_type_cache_service_1 = require("../../services/server-type-cache.service");
26
27
  const server_type_validator_service_1 = require("../../services/server-type-validator.service");
27
28
  const defaults_1 = require("../../config/defaults");
@@ -114,6 +115,10 @@ class EnvCreate extends core_1.Command {
114
115
  const acmeStaging = flags['acme-staging'];
115
116
  const useLatest = flags.latest;
116
117
  spinner.stop();
118
+ const overrideBanner = (0, release_override_1.formatReleaseOverrideBanner)((0, release_override_1.getEffectiveRelease)(useLatest));
119
+ if (overrideBanner) {
120
+ console.log(overrideBanner);
121
+ }
117
122
  if (acmeStaging) {
118
123
  console.log(chalk_1.default.yellow(`\n⚠ ACME endpoint: Let's Encrypt STAGING — cert will not be browser-trusted (warning expected).\n`));
119
124
  }
@@ -307,9 +307,11 @@ class EnvExportConfig extends core_1.Command {
307
307
  apiBaseUrl: 'http://localhost:3000',
308
308
  wsUrl: 'ws://localhost:3000',
309
309
  authMode: opts.authMode,
310
- oidcIssuer: opts.oidcIssuer || current.oidcIssuer || '',
311
- oidcClientId: opts.oidcClientId || current.oidcClientId || '',
312
- oidcAudience: opts.oidcAudience || current.oidcAudience || '',
310
+ // Always reflect the resolved cluster — never keep a previous cluster's
311
+ // value. Empty oidcClientId is fine: the dashboard fetches it at runtime.
312
+ oidcIssuer: opts.oidcIssuer || '',
313
+ oidcClientId: opts.oidcClientId || '',
314
+ oidcAudience: opts.oidcAudience || '',
313
315
  certificateMode,
314
316
  };
315
317
  fs.writeFileSync(configPath, JSON.stringify(updated, null, 2) + '\n', 'utf-8');
@@ -5,8 +5,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const core_1 = require("@oclif/core");
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
- const release_config_1 = require("../../../src/config/release.config");
9
8
  const bootstrap_config_1 = require("../config/bootstrap.config");
9
+ const release_override_1 = require("../config/release-override");
10
+ function describePlatform(release) {
11
+ if (release.source === 'latest') {
12
+ return chalk_1.default.yellow('latest (mobile tags)');
13
+ }
14
+ if (release.source === 'override') {
15
+ return `${chalk_1.default.yellow(release.version ?? 'override')}${chalk_1.default.dim(' (release override)')}`;
16
+ }
17
+ return `${chalk_1.default.cyan(release.version ?? '')}${chalk_1.default.dim(' (pinned release)')}`;
18
+ }
10
19
  /**
11
20
  * `flui version` — surfaces the CLI version AND the platform release it pins.
12
21
  *
@@ -19,8 +28,9 @@ class Version extends core_1.Command {
19
28
  async run() {
20
29
  const { flags } = await this.parse(Version);
21
30
  const useLatest = flags.latest;
22
- const tags = (0, release_config_1.resolveImageTags)(useLatest);
23
- const bootstrapRef = (0, release_config_1.resolveBootstrapRef)(useLatest);
31
+ const release = (0, release_override_1.getEffectiveRelease)(useLatest);
32
+ const tags = release.images;
33
+ const bootstrapRef = release.bootstrapRef;
24
34
  const scriptsBaseUrl = (0, bootstrap_config_1.getScriptsBaseUrl)(useLatest);
25
35
  const urlOverride = process.env.BOOTSTRAP_SCRIPTS_URL ?? null;
26
36
  const images = {
@@ -31,23 +41,24 @@ class Version extends core_1.Command {
31
41
  if (flags.json) {
32
42
  this.log(JSON.stringify({
33
43
  cli: this.config.version,
34
- mode: useLatest ? 'latest' : 'pinned',
35
- platform: useLatest ? null : release_config_1.RELEASE.version,
44
+ mode: release.source,
45
+ platform: release.version,
36
46
  bootstrapRef,
37
47
  scriptsBaseUrl,
38
48
  bootstrapUrlOverride: urlOverride,
49
+ releaseFile: release.filePath,
39
50
  images: tags,
40
51
  }, null, 2));
41
52
  return;
42
53
  }
43
54
  const label = (s) => chalk_1.default.dim(s.padEnd(15));
55
+ const cliName = chalk_1.default.dim(`(${this.config.name})`);
56
+ const platformLabel = describePlatform(release);
44
57
  this.log('');
45
58
  this.log(chalk_1.default.bold('Flui CLI'));
46
59
  this.log('');
47
- this.log(` ${label('CLI')}${chalk_1.default.cyan(this.config.version)} ${chalk_1.default.dim(`(${this.config.name})`)}`);
48
- this.log(` ${label('Platform')}${useLatest
49
- ? chalk_1.default.yellow('latest (mobile tags)')
50
- : `${chalk_1.default.cyan(release_config_1.RELEASE.version)}${chalk_1.default.dim(' (pinned release)')}`}`);
60
+ this.log(` ${label('CLI')}${chalk_1.default.cyan(this.config.version)} ${cliName}`);
61
+ this.log(` ${label('Platform')}${platformLabel}`);
51
62
  this.log(` ${label('Bootstrap ref')}${chalk_1.default.cyan(bootstrapRef)}`);
52
63
  this.log('');
53
64
  this.log(chalk_1.default.dim(' Component images:'));
@@ -59,7 +70,11 @@ class Version extends core_1.Command {
59
70
  if (urlOverride) {
60
71
  this.log(` ${label('')}${chalk_1.default.yellow('↑ overridden via BOOTSTRAP_SCRIPTS_URL')}`);
61
72
  }
62
- if (!useLatest) {
73
+ if (release.source === 'override' && release.filePath) {
74
+ const rel = (0, release_override_1.displayReleaseFilePath)(release.filePath);
75
+ this.log(` ${label('Release file')}${chalk_1.default.yellow(rel)}`);
76
+ }
77
+ if (!useLatest && release.source !== 'override') {
63
78
  this.log('');
64
79
  this.log(chalk_1.default.dim(' Tip: `flui version --latest` shows what `env create --latest` would use.'));
65
80
  }
@@ -10,6 +10,7 @@ exports.BOOTSTRAP_CONFIG = void 0;
10
10
  exports.getScriptsBaseUrl = getScriptsBaseUrl;
11
11
  exports.getScriptUrl = getScriptUrl;
12
12
  const release_config_1 = require("../../../src/config/release.config");
13
+ const release_override_1 = require("./release-override");
13
14
  const BOOTSTRAP_REPO_RAW_BASE = 'https://raw.githubusercontent.com/flui-cloud/bootstrap-scripts';
14
15
  /**
15
16
  * Base URL for the bootstrap scripts directory.
@@ -23,14 +24,16 @@ function getScriptsBaseUrl(useLatest = false) {
23
24
  if (process.env.BOOTSTRAP_SCRIPTS_URL) {
24
25
  return process.env.BOOTSTRAP_SCRIPTS_URL;
25
26
  }
26
- return `${BOOTSTRAP_REPO_RAW_BASE}/${(0, release_config_1.resolveBootstrapRef)(useLatest)}/scripts`;
27
+ return `${BOOTSTRAP_REPO_RAW_BASE}/${(0, release_override_1.resolveEffectiveBootstrapRef)(useLatest)}/scripts`;
27
28
  }
28
29
  /**
29
30
  * Default bootstrap configuration
30
31
  */
31
32
  exports.BOOTSTRAP_CONFIG = {
32
- // Pinned-release default; per-install resolution goes through getScriptsBaseUrl().
33
- scriptsBaseUrl: getScriptsBaseUrl(false),
33
+ // Static pinned default; per-install (override-aware) resolution goes through
34
+ // getScriptsBaseUrl() at runtime — keep this off the override path so importing
35
+ // the module never reads flui.release.json.
36
+ scriptsBaseUrl: `${BOOTSTRAP_REPO_RAW_BASE}/${(0, release_config_1.resolveBootstrapRef)(false)}/scripts`,
34
37
  scripts: {
35
38
  fluiInit: 'flui-init.sh',
36
39
  k3sMaster: 'k3s-master-init.sh',
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Per-install override of the pinned release manifest.
3
+ *
4
+ * Default install pins every component to the built-in RELEASE (see
5
+ * src/config/release.config.ts). A local `flui.release.json` in the cwd (or the
6
+ * path in FLUI_RELEASE_FILE) overrides any subset of it — used to install a
7
+ * dev/staging build from a branch, tag or commit. Omitted fields stay pinned.
8
+ *
9
+ * Each value is `branch:<x>` / `tag:<x>` / `commit:<x>` (or a bare literal).
10
+ * Scripts and images resolve a ref differently: scripts take any git ref
11
+ * verbatim (raw.githubusercontent serves branch/tag/sha), while an image tag
12
+ * must match what CI publishes — a branch name sanitized to a tag, or a
13
+ * short commit sha.
14
+ */
15
+ import { type ComponentImageTags } from '../../../src/config/release.config';
16
+ declare const IMAGE_KEYS: readonly ["fluiApi", "fluiWeb", "fluiAuthz"];
17
+ type ImageKey = (typeof IMAGE_KEYS)[number];
18
+ export interface ReleaseOverrideFile {
19
+ version?: string;
20
+ bootstrapRef?: string;
21
+ images?: Partial<Record<ImageKey, string>>;
22
+ }
23
+ export interface OverrideEntry {
24
+ label: string;
25
+ spec: string;
26
+ resolved: string;
27
+ }
28
+ export interface EffectiveRelease {
29
+ version: string | null;
30
+ bootstrapRef: string;
31
+ images: ComponentImageTags;
32
+ source: 'pinned' | 'latest' | 'override';
33
+ overrides: OverrideEntry[];
34
+ filePath: string | null;
35
+ }
36
+ export declare function getEffectiveRelease(useLatest: boolean): EffectiveRelease;
37
+ export declare function resolveEffectiveBootstrapRef(useLatest: boolean): string;
38
+ export declare function resolveEffectiveImageTags(useLatest: boolean): ComponentImageTags;
39
+ /** Display path: relative when inside cwd, absolute when it would escape it. */
40
+ export declare function displayReleaseFilePath(filePath: string): string;
41
+ /** Loud banner so a stale override is never installed unnoticed. */
42
+ export declare function formatReleaseOverrideBanner(eff: EffectiveRelease): string | null;
43
+ export {};
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+ /**
3
+ * Per-install override of the pinned release manifest.
4
+ *
5
+ * Default install pins every component to the built-in RELEASE (see
6
+ * src/config/release.config.ts). A local `flui.release.json` in the cwd (or the
7
+ * path in FLUI_RELEASE_FILE) overrides any subset of it — used to install a
8
+ * dev/staging build from a branch, tag or commit. Omitted fields stay pinned.
9
+ *
10
+ * Each value is `branch:<x>` / `tag:<x>` / `commit:<x>` (or a bare literal).
11
+ * Scripts and images resolve a ref differently: scripts take any git ref
12
+ * verbatim (raw.githubusercontent serves branch/tag/sha), while an image tag
13
+ * must match what CI publishes — a branch name sanitized to a tag, or a
14
+ * short commit sha.
15
+ */
16
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ var desc = Object.getOwnPropertyDescriptor(m, k);
19
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
20
+ desc = { enumerable: true, get: function() { return m[k]; } };
21
+ }
22
+ Object.defineProperty(o, k2, desc);
23
+ }) : (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ o[k2] = m[k];
26
+ }));
27
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
28
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
29
+ }) : function(o, v) {
30
+ o["default"] = v;
31
+ });
32
+ var __importStar = (this && this.__importStar) || (function () {
33
+ var ownKeys = function(o) {
34
+ ownKeys = Object.getOwnPropertyNames || function (o) {
35
+ var ar = [];
36
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
37
+ return ar;
38
+ };
39
+ return ownKeys(o);
40
+ };
41
+ return function (mod) {
42
+ if (mod && mod.__esModule) return mod;
43
+ var result = {};
44
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
45
+ __setModuleDefault(result, mod);
46
+ return result;
47
+ };
48
+ })();
49
+ var __importDefault = (this && this.__importDefault) || function (mod) {
50
+ return (mod && mod.__esModule) ? mod : { "default": mod };
51
+ };
52
+ Object.defineProperty(exports, "__esModule", { value: true });
53
+ exports.getEffectiveRelease = getEffectiveRelease;
54
+ exports.resolveEffectiveBootstrapRef = resolveEffectiveBootstrapRef;
55
+ exports.resolveEffectiveImageTags = resolveEffectiveImageTags;
56
+ exports.displayReleaseFilePath = displayReleaseFilePath;
57
+ exports.formatReleaseOverrideBanner = formatReleaseOverrideBanner;
58
+ const fs = __importStar(require("node:fs"));
59
+ const path = __importStar(require("node:path"));
60
+ const chalk_1 = __importDefault(require("chalk"));
61
+ const release_config_1 = require("../../../src/config/release.config");
62
+ const OVERRIDE_FILE = 'flui.release.json';
63
+ const IMAGE_KEYS = ['fluiApi', 'fluiWeb', 'fluiAuthz'];
64
+ const COMPONENT_LABELS = {
65
+ fluiApi: 'flui-api (core)',
66
+ fluiWeb: 'flui-web (dashboard)',
67
+ fluiAuthz: 'flui-authz',
68
+ };
69
+ function parseRef(raw) {
70
+ const idx = raw.indexOf(':');
71
+ if (idx === -1)
72
+ return { kind: 'literal', value: raw };
73
+ const prefix = raw.slice(0, idx);
74
+ const value = raw.slice(idx + 1);
75
+ switch (prefix) {
76
+ case 'branch':
77
+ return { kind: 'branch', value };
78
+ case 'tag':
79
+ return { kind: 'tag', value };
80
+ case 'commit':
81
+ case 'sha':
82
+ return { kind: 'commit', value };
83
+ default:
84
+ throw new Error(`Invalid ref "${raw}" in ${OVERRIDE_FILE}: unknown prefix "${prefix}:" — use branch:/tag:/commit:, or a bare tag.`);
85
+ }
86
+ }
87
+ /** Mirror docker/metadata-action `type=ref,event=branch`: invalid tag chars → "-". */
88
+ function branchToImageTag(branch) {
89
+ return branch.replace(/[^a-zA-Z0-9._-]+/g, '-');
90
+ }
91
+ function resolveScriptsRef(spec) {
92
+ return parseRef(spec).value;
93
+ }
94
+ function resolveImageTag(spec) {
95
+ const ref = parseRef(spec);
96
+ switch (ref.kind) {
97
+ case 'branch':
98
+ return branchToImageTag(ref.value);
99
+ case 'commit':
100
+ return ref.value.slice(0, 7); // CI publishes type=sha,format=short
101
+ default:
102
+ return ref.value;
103
+ }
104
+ }
105
+ function loadOverrideFile() {
106
+ const explicit = process.env.FLUI_RELEASE_FILE;
107
+ const filePath = explicit
108
+ ? path.resolve(explicit)
109
+ : path.join(process.cwd(), OVERRIDE_FILE);
110
+ if (!fs.existsSync(filePath))
111
+ return null;
112
+ let data;
113
+ try {
114
+ data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
115
+ }
116
+ catch (err) {
117
+ throw new Error(`Failed to parse ${filePath}: ${err.message}`);
118
+ }
119
+ if (typeof data !== 'object' || data === null || Array.isArray(data)) {
120
+ throw new Error(`${filePath} must contain a JSON object.`);
121
+ }
122
+ return { data, filePath };
123
+ }
124
+ let cache;
125
+ let cacheKey;
126
+ function applyOverride(base, data) {
127
+ const images = { ...base.images };
128
+ const overrides = [];
129
+ let bootstrapRef = base.bootstrapRef;
130
+ if (data.bootstrapRef !== undefined) {
131
+ bootstrapRef = resolveScriptsRef(data.bootstrapRef);
132
+ overrides.push({
133
+ label: 'bootstrap scripts',
134
+ spec: data.bootstrapRef,
135
+ resolved: bootstrapRef,
136
+ });
137
+ }
138
+ for (const k of IMAGE_KEYS) {
139
+ const spec = data.images?.[k];
140
+ if (spec === undefined)
141
+ continue;
142
+ const resolved = resolveImageTag(spec);
143
+ images[k] = resolved;
144
+ overrides.push({ label: COMPONENT_LABELS[k], spec, resolved });
145
+ }
146
+ return {
147
+ version: data.version ?? base.version,
148
+ bootstrapRef,
149
+ images,
150
+ overrides,
151
+ };
152
+ }
153
+ function getEffectiveRelease(useLatest) {
154
+ const key = `${useLatest}|${process.env.FLUI_RELEASE_FILE ?? ''}|${process.cwd()}`;
155
+ if (cache && cacheKey === key)
156
+ return cache;
157
+ const base = {
158
+ version: useLatest ? null : release_config_1.RELEASE.version,
159
+ bootstrapRef: (0, release_config_1.resolveBootstrapRef)(useLatest),
160
+ images: { ...(0, release_config_1.resolveImageTags)(useLatest) },
161
+ overrides: [],
162
+ };
163
+ const loaded = loadOverrideFile();
164
+ const resolved = loaded ? applyOverride(base, loaded.data) : base;
165
+ const isOverride = resolved.overrides.length > 0;
166
+ const pinnedSource = useLatest ? 'latest' : 'pinned';
167
+ const eff = {
168
+ version: resolved.version,
169
+ bootstrapRef: resolved.bootstrapRef,
170
+ images: resolved.images,
171
+ source: isOverride ? 'override' : pinnedSource,
172
+ overrides: resolved.overrides,
173
+ filePath: isOverride && loaded ? loaded.filePath : null,
174
+ };
175
+ cache = eff;
176
+ cacheKey = key;
177
+ return eff;
178
+ }
179
+ function resolveEffectiveBootstrapRef(useLatest) {
180
+ return getEffectiveRelease(useLatest).bootstrapRef;
181
+ }
182
+ function resolveEffectiveImageTags(useLatest) {
183
+ return getEffectiveRelease(useLatest).images;
184
+ }
185
+ /** Display path: relative when inside cwd, absolute when it would escape it. */
186
+ function displayReleaseFilePath(filePath) {
187
+ const rel = path.relative(process.cwd(), filePath);
188
+ return !rel || rel.startsWith('..') ? filePath : rel;
189
+ }
190
+ /** Loud banner so a stale override is never installed unnoticed. */
191
+ function formatReleaseOverrideBanner(eff) {
192
+ if (eff.source !== 'override' || !eff.filePath)
193
+ return null;
194
+ const rel = displayReleaseFilePath(eff.filePath);
195
+ const lines = eff.overrides.map((o) => {
196
+ const spec = chalk_1.default.dim(`(${o.spec})`);
197
+ return ` • ${o.label}: ${chalk_1.default.cyan(o.resolved)} ${spec}`;
198
+ });
199
+ return (chalk_1.default.yellow.bold('\n⚠ Release override active') +
200
+ chalk_1.default.dim(` — ${rel}\n`) +
201
+ chalk_1.default.dim(' Installing non-default component versions:\n') +
202
+ `${lines.join('\n')}\n`);
203
+ }
@@ -47,7 +47,7 @@ exports.CliControlClusterService = void 0;
47
47
  const common_1 = require("@nestjs/common");
48
48
  const cluster_entity_1 = require("../../../src/modules/infrastructure/clusters/entities/cluster.entity");
49
49
  const cli_cluster_repository_1 = require("../lib/repositories/cli-cluster.repository");
50
- const release_config_1 = require("../../../src/config/release.config");
50
+ const release_override_1 = require("../config/release-override");
51
51
  const nip_base_domain_util_1 = require("../lib/nip-base-domain.util");
52
52
  const cli_node_repository_1 = require("../lib/repositories/cli-node.repository");
53
53
  const cli_clusters_service_1 = require("./cli-clusters.service");
@@ -127,6 +127,7 @@ let CliControlClusterService = CliControlClusterService_1 = class CliControlClus
127
127
  // --latest opted into mobile dev tags. Recorded on the cluster so the
128
128
  // installed version stays queryable after creation.
129
129
  const useLatest = options?.useLatest ?? false;
130
+ const release = (0, release_override_1.getEffectiveRelease)(useLatest);
130
131
  const createDto = {
131
132
  name: 'control-cluster',
132
133
  provider: provider,
@@ -146,9 +147,9 @@ let CliControlClusterService = CliControlClusterService_1 = class CliControlClus
146
147
  adminEmail,
147
148
  acmeStaging,
148
149
  useLatest,
149
- platformVersion: useLatest ? null : release_config_1.RELEASE.version,
150
- componentVersions: (0, release_config_1.resolveImageTags)(useLatest),
151
- bootstrapRef: (0, release_config_1.resolveBootstrapRef)(useLatest),
150
+ platformVersion: release.version,
151
+ componentVersions: release.images,
152
+ bootstrapRef: release.bootstrapRef,
152
153
  },
153
154
  };
154
155
  const { cluster } = await this.clustersService.create(createDto);
@@ -61,28 +61,33 @@ let CliEndpointResolverService = CliEndpointResolverService_1 = class CliEndpoin
61
61
  const snapshot = await this.fetchSnapshot(masterIp);
62
62
  const configMapData = snapshot.configmap?.data ?? {};
63
63
  const secretData = snapshot.secret?.data ?? {};
64
- const authMode = configMapData['AUTH_MODE'] ?? 'unknown';
65
- const oidcIssuer = configMapData['OIDC_ISSUER'] ?? '';
66
- const oidcJwksUri = configMapData['OIDC_JWKS_URI'] ?? '';
67
- const oidcCliClientId = configMapData['OIDC_CLI_CLIENT_ID'] ?? '';
68
- const oidcAudience = secretData['OIDC_AUDIENCE']
64
+ const live = snapshot.authConfig ?? {};
65
+ const pick = (...vals) => vals.find((v) => typeof v === 'string' && v.trim() !== '')?.trim() ?? '';
66
+ const frozenAudience = secretData['OIDC_AUDIENCE']
69
67
  ? Buffer.from(secretData['OIDC_AUDIENCE'], 'base64').toString('utf-8')
70
68
  : '';
71
- // Dashboard public client_id lives inside the flui-web-config ConfigMap's
72
- // `config.json` data key — written by OidcBootstrapService.patchWebConfigMap.
73
- let oidcClientId = '';
69
+ let frozenClientId = '';
74
70
  const webConfigJson = snapshot.webConfigMap?.data?.['config.json'];
75
71
  if (webConfigJson) {
76
72
  try {
77
73
  const parsed = JSON.parse(webConfigJson);
78
74
  if (typeof parsed.oidcClientId === 'string') {
79
- oidcClientId = parsed.oidcClientId;
75
+ frozenClientId = parsed.oidcClientId;
80
76
  }
81
77
  }
82
78
  catch (err) {
83
79
  this.logger.warn(`flui-web-config/config.json is not valid JSON: ${err.message}`);
84
80
  }
85
81
  }
82
+ // Prefer the live values; fall back to the frozen ConfigMap/Secret only if
83
+ // the API was unreachable (k3s auto-deploy resets the frozen ones).
84
+ const authMode = pick(live.authMode, configMapData['AUTH_MODE'], 'unknown');
85
+ const oidcIssuer = pick(live.issuer, configMapData['OIDC_ISSUER']);
86
+ const oidcJwksUri = configMapData['OIDC_JWKS_URI'] ?? '';
87
+ const oidcCliClientId = pick(live.cliClientId, configMapData['OIDC_CLI_CLIENT_ID']);
88
+ const oidcClientId = pick(live.clientId, frozenClientId);
89
+ // audience = web client id
90
+ const oidcAudience = pick(live.clientId, frozenAudience);
86
91
  const endpoints = {};
87
92
  for (const key of Object.keys(SYSTEM_APPS)) {
88
93
  endpoints[key] = this.resolveApp(key, SYSTEM_APPS[key], snapshot.ingresses.items ?? [], snapshot.ingressRoutes.items ?? [], masterIp, nipHostnameToken);
@@ -104,7 +109,10 @@ let CliEndpointResolverService = CliEndpointResolverService_1 = class CliEndpoin
104
109
  `CM=$(kubectl get configmap flui-api-config -n flui-system -o json 2>/dev/null || echo '{}')`,
105
110
  `SEC=$(kubectl get secret flui-secrets -n flui-system -o json 2>/dev/null || echo '{}')`,
106
111
  `WCM=$(kubectl get configmap flui-web-config -n flui-system -o json 2>/dev/null || echo '{}')`,
107
- `printf '{"ingresses":%s,"ingressRoutes":%s,"configmap":%s,"secret":%s,"webConfigMap":%s}' "$ING" "$IR" "$CM" "$SEC" "$WCM"`,
112
+ `AIP=$(kubectl get svc flui-api -n flui-system -o jsonpath='{.spec.clusterIP}' 2>/dev/null)`,
113
+ `APT=$(kubectl get svc flui-api -n flui-system -o jsonpath='{.spec.ports[0].port}' 2>/dev/null)`,
114
+ `AC=$(curl -s --max-time 5 "http://$AIP:$APT/api/v1/auth/config" 2>/dev/null || echo '{}')`,
115
+ `printf '{"ingresses":%s,"ingressRoutes":%s,"configmap":%s,"secret":%s,"webConfigMap":%s,"authConfig":%s}' "$ING" "$IR" "$CM" "$SEC" "$WCM" "$AC"`,
108
116
  ].join('; ');
109
117
  const output = await this.sshService.sshExec(masterIp, command);
110
118
  try {
@@ -50,7 +50,7 @@ const path = __importStar(require("node:path"));
50
50
  const os = __importStar(require("node:os"));
51
51
  const cli_logger_service_1 = require("./cli-logger.service");
52
52
  const bootstrap_config_1 = require("../config/bootstrap.config");
53
- const release_config_1 = require("../../../src/config/release.config");
53
+ const release_override_1 = require("../config/release-override");
54
54
  /**
55
55
  * CLI K3s Script Service
56
56
  *
@@ -95,7 +95,7 @@ let CliK3sScriptService = CliK3sScriptService_1 = class CliK3sScriptService {
95
95
  this.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`, opId);
96
96
  this.log(`[BOOTSTRAP MASTER SCRIPT] Cluster: ${config.clusterName}`, opId);
97
97
  const scriptsBaseUrl = (0, bootstrap_config_1.getScriptsBaseUrl)(config.useLatest ?? false);
98
- const imageTags = (0, release_config_1.resolveImageTags)(config.useLatest ?? false);
98
+ const imageTags = (0, release_override_1.resolveEffectiveImageTags)(config.useLatest ?? false);
99
99
  this.log(`Scripts URL: ${scriptsBaseUrl}`, opId);
100
100
  // Generate bootstrap script that downloads and executes k3s-master-init.sh from GitHub
101
101
  const script = this.generateBootstrapScript('master', {
@@ -11,10 +11,10 @@ exports.RELEASE = void 0;
11
11
  exports.resolveBootstrapRef = resolveBootstrapRef;
12
12
  exports.resolveImageTags = resolveImageTags;
13
13
  exports.RELEASE = {
14
- version: '0.5.0',
15
- bootstrapRef: 'v0.5.0',
14
+ version: '0.5.1',
15
+ bootstrapRef: 'v0.5.1',
16
16
  images: {
17
- fluiApi: '0.5.0',
17
+ fluiApi: '0.5.1',
18
18
  fluiWeb: '0.5.0',
19
19
  fluiAuthz: '0.5.0',
20
20
  },