omegon 0.6.20 → 0.6.22

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.
@@ -317,6 +317,79 @@ const ociProvider: AuthProvider = {
317
317
  },
318
318
  };
319
319
 
320
+ const vaultProvider: AuthProvider = {
321
+ id: "vault",
322
+ name: "Vault",
323
+ cli: "vault",
324
+ tokenEnvVar: "VAULT_TOKEN",
325
+ refreshCommand: "vault login",
326
+
327
+ async check(pi, signal) {
328
+ // 1. Check CLI is installed
329
+ const which = await pi.exec("which", ["vault"], { signal, timeout: 3_000 });
330
+ if (which.code !== 0) {
331
+ return { provider: this.id, status: "missing", detail: "vault CLI not installed" };
332
+ }
333
+
334
+ // 2. Check VAULT_ADDR is configured — without it, no meaningful check is possible
335
+ const addr = process.env["VAULT_ADDR"];
336
+ if (!addr) {
337
+ return {
338
+ provider: this.id,
339
+ status: "none",
340
+ detail: "VAULT_ADDR not set",
341
+ refresh: this.refreshCommand,
342
+ secretHint: "VAULT_ADDR",
343
+ };
344
+ }
345
+
346
+ // 3. Run vault token lookup — read-only, returns token metadata (never the token itself)
347
+ // VAULT_TOKEN is read by the vault CLI from the environment; we never access it directly.
348
+ const result = await pi.exec("vault", ["token", "lookup", "-format=json"], { signal, timeout: 10_000 });
349
+
350
+ if (result.code === 0) {
351
+ try {
352
+ const data = JSON.parse(result.stdout.trim());
353
+ const tokenData = data?.data ?? {};
354
+
355
+ // Extract safe metadata — policies and expiry only, never the token value
356
+ const policies: string[] = tokenData.policies ?? [];
357
+ const displayName: string = tokenData.display_name ?? "";
358
+ const expireTime: string = tokenData.expire_time ?? "";
359
+
360
+ // Build a human-readable detail string
361
+ const parts: string[] = [];
362
+ if (displayName) parts.push(displayName);
363
+ if (policies.length > 0) parts.push(`policies: ${policies.filter(p => p !== "default").join(", ") || "default"}`);
364
+ if (expireTime) parts.push(`expires: ${expireTime.split("T")[0]}`);
365
+ else parts.push("no expiry");
366
+
367
+ return {
368
+ provider: this.id,
369
+ status: "ok",
370
+ detail: parts.join(" · ") || "authenticated",
371
+ refresh: this.refreshCommand,
372
+ };
373
+ } catch {
374
+ // JSON parse failed but command succeeded — still authenticated
375
+ return { provider: this.id, status: "ok", detail: "authenticated", refresh: this.refreshCommand };
376
+ }
377
+ }
378
+
379
+ // 4. Diagnose failure — truncate to 300 chars, never log token values
380
+ const output = (result.stdout + "\n" + result.stderr).trim();
381
+ const diag = diagnoseError(output);
382
+ return {
383
+ provider: this.id,
384
+ status: diag.status,
385
+ detail: `${addr} — ${diag.reason}`,
386
+ error: output.slice(0, 300),
387
+ refresh: this.refreshCommand,
388
+ secretHint: "VAULT_TOKEN",
389
+ };
390
+ },
391
+ };
392
+
320
393
  // ─── Provider Registry ───────────────────────────────────────────
321
394
 
322
395
  /** All providers, ordered by typical check priority. */
@@ -327,6 +400,7 @@ export const ALL_PROVIDERS: AuthProvider[] = [
327
400
  awsProvider,
328
401
  kubernetesProvider,
329
402
  ociProvider,
403
+ vaultProvider,
330
404
  ];
331
405
 
332
406
  export function findProvider(idOrName: string): AuthProvider | undefined {
@@ -133,11 +133,21 @@ function hasCmd(cmd: string): boolean {
133
133
  /** Get the best install command for the current platform */
134
134
  export function bestInstallCmd(dep: Dep): string | undefined {
135
135
  const plat = process.platform === "darwin" ? "darwin" : "linux";
136
- return (
137
- dep.install.find((o) => o.platform === plat)?.cmd ??
138
- dep.install.find((o) => o.platform === "any")?.cmd ??
139
- dep.install[0]?.cmd
140
- );
136
+ const candidates = dep.install.filter((o) => o.platform === plat || o.platform === "any");
137
+ if (candidates.length === 0) return dep.install[0]?.cmd;
138
+
139
+ // If nix is available, prefer nix commands. Otherwise prefer brew.
140
+ const hasNix = hasCmd("nix");
141
+ const hasBrew = hasCmd("brew");
142
+ if (hasNix) {
143
+ const nix = candidates.find((o) => o.cmd.startsWith("nix "));
144
+ if (nix) return nix.cmd;
145
+ }
146
+ if (hasBrew) {
147
+ const brew = candidates.find((o) => o.cmd.startsWith("brew "));
148
+ if (brew) return brew.cmd;
149
+ }
150
+ return candidates[0]?.cmd;
141
151
  }
142
152
 
143
153
  /** Get all install options formatted for display */
@@ -154,28 +164,22 @@ export function installHints(dep: Dep): string[] {
154
164
  * Order matters: displayed in this order during bootstrap.
155
165
  */
156
166
  export const DEPS: Dep[] = [
157
- // --- Core: most users want these ---
167
+ // --- Core: package manager + essential tools ---
158
168
  {
159
169
  id: "nix",
160
170
  name: "Nix",
161
171
  purpose: "Universal package manager — installs all other dependencies on any OS",
162
172
  usedBy: ["bootstrap"],
163
173
  tier: "core",
164
- check: () => hasCmd("nix"),
165
- install: [
166
- // Immutable ostree-based Linux (Bazzite, Silverblue, Bluefin, etc.)
167
- // needs root.transient enabled and --persistence=/var/lib/nix so the
168
- // nix store lives on a writable partition. The upstream installer uses
169
- // the ostree planner automatically when it detects ostree.
170
- { platform: "linux", cmd: isOstree()
171
- ? "curl -sSfL https://install.determinate.systems/nix | sh -s -- install --no-confirm --persistence=/var/lib/nix"
172
- : "curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install --no-confirm" },
173
- { platform: "darwin", cmd: "curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install --no-confirm" },
174
- ],
174
+ // Either nix or brew satisfies this — we just need a working package manager
175
+ check: () => hasCmd("nix") || hasCmd("brew"),
176
+ install: isOstree()
177
+ ? [{ platform: "linux", cmd: '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"' }]
178
+ : [
179
+ { platform: "any", cmd: "curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install --no-confirm" },
180
+ { platform: "any", cmd: '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"' },
181
+ ],
175
182
  url: "https://zero-to-nix.com",
176
- // On ostree systems, root.transient must be enabled first for /nix to be created.
177
- // preflight returns instructions if the system isn't ready.
178
- preflight: isOstree() ? checkOstreeReadyForNix : undefined,
179
183
  },
180
184
  {
181
185
  id: "ollama",
@@ -187,6 +191,7 @@ export const DEPS: Dep[] = [
187
191
  requires: ["nix"],
188
192
  install: [
189
193
  { platform: "any", cmd: "nix profile install nixpkgs#ollama" },
194
+ { platform: "any", cmd: "brew install ollama" },
190
195
  ],
191
196
  url: "https://ollama.com",
192
197
  },
@@ -200,6 +205,7 @@ export const DEPS: Dep[] = [
200
205
  requires: ["nix"],
201
206
  install: [
202
207
  { platform: "any", cmd: "nix profile install nixpkgs#d2" },
208
+ { platform: "any", cmd: "brew install d2" },
203
209
  ],
204
210
  url: "https://d2lang.com",
205
211
  },
@@ -215,6 +221,7 @@ export const DEPS: Dep[] = [
215
221
  requires: ["nix"],
216
222
  install: [
217
223
  { platform: "any", cmd: "nix profile install nixpkgs#gh" },
224
+ { platform: "any", cmd: "brew install gh" },
218
225
  ],
219
226
  url: "https://cli.github.com",
220
227
  },
@@ -228,6 +235,7 @@ export const DEPS: Dep[] = [
228
235
  requires: ["nix"],
229
236
  install: [
230
237
  { platform: "any", cmd: "nix profile install nixpkgs#pandoc" },
238
+ { platform: "any", cmd: "brew install pandoc" },
231
239
  ],
232
240
  url: "https://pandoc.org",
233
241
  },
@@ -240,6 +248,7 @@ export const DEPS: Dep[] = [
240
248
  check: () => hasCmd("cargo"),
241
249
  install: [
242
250
  { platform: "any", cmd: "nix profile install nixpkgs#rustup && rustup default stable" },
251
+ { platform: "any", cmd: "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y" },
243
252
  ],
244
253
  url: "https://rustup.rs",
245
254
  },
@@ -268,6 +277,7 @@ export const DEPS: Dep[] = [
268
277
  requires: ["nix"],
269
278
  install: [
270
279
  { platform: "any", cmd: "nix profile install nixpkgs#librsvg" },
280
+ { platform: "any", cmd: "brew install librsvg" },
271
281
  ],
272
282
  },
273
283
  {
@@ -280,6 +290,7 @@ export const DEPS: Dep[] = [
280
290
  requires: ["nix"],
281
291
  install: [
282
292
  { platform: "any", cmd: "nix profile install nixpkgs#poppler_utils" },
293
+ { platform: "any", cmd: "brew install poppler" },
283
294
  ],
284
295
  },
285
296
  {
@@ -292,6 +303,7 @@ export const DEPS: Dep[] = [
292
303
  requires: ["nix"],
293
304
  install: [
294
305
  { platform: "any", cmd: "nix profile install nixpkgs#uv" },
306
+ { platform: "any", cmd: "brew install uv" },
295
307
  ],
296
308
  url: "https://docs.astral.sh/uv/",
297
309
  },
@@ -305,6 +317,7 @@ export const DEPS: Dep[] = [
305
317
  requires: ["nix"],
306
318
  install: [
307
319
  { platform: "any", cmd: "nix profile install nixpkgs#awscli2" },
320
+ { platform: "any", cmd: "brew install awscli" },
308
321
  ],
309
322
  },
310
323
  {
@@ -317,7 +330,22 @@ export const DEPS: Dep[] = [
317
330
  requires: ["nix"],
318
331
  install: [
319
332
  { platform: "any", cmd: "nix profile install nixpkgs#kubectl" },
333
+ { platform: "any", cmd: "brew install kubectl" },
334
+ ],
335
+ },
336
+ {
337
+ id: "vault",
338
+ name: "Vault CLI",
339
+ purpose: "HashiCorp Vault authentication status checking and secret management",
340
+ usedBy: ["01-auth"],
341
+ tier: "optional",
342
+ check: () => hasCmd("vault"),
343
+ requires: ["nix"],
344
+ install: [
345
+ { platform: "any", cmd: "nix profile install nixpkgs#vault" },
346
+ { platform: "any", cmd: "brew install hashicorp/tap/vault" },
320
347
  ],
348
+ url: "https://developer.hashicorp.com/vault/install",
321
349
  },
322
350
  ];
323
351
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omegon",
3
- "version": "0.6.20",
3
+ "version": "0.6.22",
4
4
  "description": "Omegon — an opinionated distribution of pi (by Mario Zechner) with extensions for lifecycle management, memory, orchestration, and visualization",
5
5
  "bin": {
6
6
  "omegon": "bin/omegon.mjs",