@meshxdata/fops 0.1.44 → 0.1.46

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 (36) hide show
  1. package/CHANGELOG.md +183 -0
  2. package/package.json +1 -1
  3. package/src/commands/lifecycle.js +101 -5
  4. package/src/commands/setup.js +45 -4
  5. package/src/plugins/bundled/fops-plugin-azure/index.js +29 -0
  6. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-core.js +1185 -0
  7. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-flux.js +1180 -0
  8. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-ingress.js +393 -0
  9. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-naming.js +104 -0
  10. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-network.js +296 -0
  11. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-postgres.js +768 -0
  12. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-reconcilers.js +538 -0
  13. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-secrets.js +849 -0
  14. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-stacks.js +643 -0
  15. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-state.js +145 -0
  16. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-storage.js +496 -0
  17. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks-terraform.js +1032 -0
  18. package/src/plugins/bundled/fops-plugin-azure/lib/azure-aks.js +155 -4245
  19. package/src/plugins/bundled/fops-plugin-azure/lib/azure-keyvault.js +186 -0
  20. package/src/plugins/bundled/fops-plugin-azure/lib/azure-ops.js +29 -0
  21. package/src/plugins/bundled/fops-plugin-azure/lib/azure-results.js +78 -0
  22. package/src/plugins/bundled/fops-plugin-azure/lib/azure.js +1 -1
  23. package/src/plugins/bundled/fops-plugin-azure/lib/commands/infra-cmds.js +758 -0
  24. package/src/plugins/bundled/fops-plugin-azure/lib/commands/registry-cmds.js +250 -0
  25. package/src/plugins/bundled/fops-plugin-azure/lib/commands/test-cmds.js +52 -1
  26. package/src/plugins/bundled/fops-plugin-azure/lib/commands/vm-cmds.js +10 -0
  27. package/src/plugins/bundled/fops-plugin-foundation/lib/apply.js +3 -2
  28. package/src/plugins/bundled/fops-plugin-foundation/lib/helpers.js +21 -0
  29. package/src/plugins/bundled/fops-plugin-foundation/lib/tools-read.js +3 -5
  30. package/src/ui/tui/App.js +13 -13
  31. package/src/web/dist/assets/index-NXC8Hvnp.css +1 -0
  32. package/src/web/dist/assets/index-QH1N4ejK.js +112 -0
  33. package/src/web/dist/index.html +2 -2
  34. package/src/web/server.js +4 -4
  35. package/src/web/dist/assets/index-BphVaAUd.css +0 -1
  36. package/src/web/dist/assets/index-CSckLzuG.js +0 -129
package/CHANGELOG.md CHANGED
@@ -1,3 +1,186 @@
1
+ ## [0.1.46] - 2026-03-23
2
+
3
+ - default locust to CLI mode, add --web for UI (ca35bff)
4
+ - add locust command for load testing AKS clusters (1278722)
5
+ - update spot node pool default autoscaling to 1-20 (617c182)
6
+ - module for aks (3dd1a61)
7
+ - add hive to PG_SERVICE_DBS for fops pg-setup (afccb16)
8
+ - feat(azure): enhance aks doctor with ExternalSecrets and PGSSLMODE checks (8b14861)
9
+ - add foundation-postgres ExternalName service to reconciler (ea88e11)
10
+ - new flux templates (0e2e372)
11
+ - feat(azure): add storage-engine secrets to Key Vault (a4f488e)
12
+ - feat(azure-aks): add AUTH0_DOMAIN to template rendering variables (216c37e)
13
+ - feat(azure): add storage account creation per cluster (aa1b138)
14
+ - bump watcher (ab24473)
15
+ - fix: concurrent compute calls (#66) (03e2edf)
16
+ - bump backend version (5058ff5)
17
+ - bump fops to 0.1.44 (8c0ef5d)
18
+ - Mlflow and azure plugin fix (176881f)
19
+ - fix lifecycle (a2cb9e7)
20
+ - callback url for localhost (821fb94)
21
+ - disable 4 scaffolding plugin by default. (bfb2b76)
22
+ - jaccard improvements (b7494a0)
23
+ - refactor azure plugin (68dfef4)
24
+ - refactor azure plugin (b24a008)
25
+ - fix trino catalog missing (4928a55)
26
+ - v36 bump and changelog generation on openai (37a0440)
27
+ - v36 bump and changelog generation on openai (a3b02d9)
28
+ - bump (a990058)
29
+ - status bar fix and new plugin for ttyd (27dde1e)
30
+ - file demo and tray (1a3e704)
31
+ - electron app (59ad0bb)
32
+ - compose and fops file plugin (1cf0e81)
33
+ - bump (346ffc1)
34
+ - localhost replaced by 127.0.0.1 (82b9f30)
35
+ - .29 (587b0e1)
36
+ - improve up down and bootstrap script (b79ebaf)
37
+ - checksum (22c8086)
38
+ - checksum (96b434f)
39
+ - checksum (15ed3c0)
40
+ - checksum (8a6543a)
41
+ - bump embed trino linksg (8440504)
42
+ - bump data (765ffd9)
43
+ - bump (cb8b232)
44
+ - broken tests (c532229)
45
+ - release 0.1.18, preflight checks (d902249)
46
+ - fix compute display bug (d10f5d9)
47
+ - cleanup packer files (6330f18)
48
+ - plan mode (cb36a8a)
49
+ - bump to 0.1.16 - agent ui (41ac1a2)
50
+ - bump to 0.1.15 - agent ui (4ebe2e1)
51
+ - bump to 0.1.14 (6c3a7fa)
52
+ - bump to 0.1.13 (8db570f)
53
+ - release 0.1.12 (c1c79e5)
54
+ - bump (11aa3b0)
55
+ - git keep and bump tui (be1678e)
56
+ - skills, index, rrf, compacted context (100k > 10k) (7b2fffd)
57
+ - cloudflare and token consumption, graphs indexing (0ad9eec)
58
+ - bump storage default (22c83ba)
59
+ - storage fix (68a22a0)
60
+ - skills update (7f56500)
61
+ - v9 bump (3864446)
62
+ - bump (c95eedc)
63
+ - rrf (dbf8c95)
64
+ - feat: warning when running predictions (95e8c52)
65
+ - feat: support for local predictions (45cf26b)
66
+ - feat: wip support for predictions + mlflow (3457052)
67
+ - add Reciprocal Rank Fusion (RRF) to knowledge and skill retrieval (61549bc)
68
+ - validate CSV headers in compute_run readiness check (a8c7a43)
69
+ - fix corrupted Iceberg metadata: probe tables + force cleanup on re-apply (50578af)
70
+ - enforce: never use foundation_apply to fix broken products (2e049bf)
71
+ - update SKILL.md with complete tool reference for knowledge retrieval (30b1924)
72
+ - add storage read, input DP table probe, and compute_run improvements (34e6c4c)
73
+ - skills update (1220385)
74
+ - skills update (bb66958)
75
+ - some tui improvement andd tools apply overwrite (e90c35c)
76
+ - skills update (e9227a1)
77
+ - skills update (669c4b3)
78
+ - fix plugin pre-flight checks (f741743)
79
+ - increase agent context (6479aaa)
80
+ - skills and init sql fixes (5fce35e)
81
+ - checksum (3518b56)
82
+ - penging job limit (a139861)
83
+ - checksum (575d28c)
84
+ - bump (92049ba)
85
+ - fix bug per tab status (0a33657)
86
+ - fix bug per tab status (50457c6)
87
+ - checksumming (0ad842e)
88
+ - shot af mardkwon overlapping (51f63b9)
89
+ - add spark dockerfile for multiarch builds (95abbd1)
90
+ - fix plugin initialization (16b9782)
91
+ - split index.js (50902a2)
92
+ - cloudflare cidr (cc4e021)
93
+ - cloduflare restrictions (2f6ba2d)
94
+ - sequential start (86b496e)
95
+ - sequential start (4930fe1)
96
+ - sequential start (353f014)
97
+ - qa tests (2dc6a1a)
98
+ - bump sha for .85 (dc2edfe)
99
+ - preserve env on sudo (7831227)
100
+ - bump sha for .84 (6c052f9)
101
+ - non interactive for azure vms (0aa8a2f)
102
+ - keep .env if present (d072450)
103
+ - bump (7a8e732)
104
+ - ensure opa is on compose if not set (f4a5228)
105
+ - checksum bump (a2ccc20)
106
+ - netrc defensive checks (a0b0ccc)
107
+ - netrc defensive checks (ae37403)
108
+ - checksum (ec45d11)
109
+ - update sync and fix up (7f9af72)
110
+ - expand test for azure and add new per app tag support (388a168)
111
+ - checksum on update (44005fc)
112
+ - cleanup for later (15e5313)
113
+ - cleanup for later (11c9597)
114
+ - switch branch feature (822fecc)
115
+ - add pull (d1c19ab)
116
+ - Bump hono from 4.11.9 to 4.12.0 in /operator-cli (ad25144)
117
+ - tests (f180a9a)
118
+ - cleanup (39c49a3)
119
+ - registry (7b7126a)
120
+ - reconcile kafka (832d0db)
121
+ - gh login bug (025886c)
122
+ - cleanup (bb96cab)
123
+ - strip envs from process (2421180)
124
+ - force use of gh creds not tokens in envs var (fff7787)
125
+ - resolve import between npm installs and npm link (79522e1)
126
+ - fix gh scope and azure states (afd846c)
127
+ - refactoring (da50352)
128
+ - split fops repo (d447638)
129
+ - aks (b791f8f)
130
+ - refactor azure (67d3bad)
131
+ - wildcard (391f023)
132
+ - azure plugin (c074074)
133
+ - zap (d7e6e7f)
134
+ - fix knock (cf89c05)
135
+ - azure (4adec98)
136
+ - Bump tar from 7.5.7 to 7.5.9 in /operator-cli (e41e98e)
137
+ - azure stack index.js split (de12272)
138
+ - Bump ajv from 8.17.1 to 8.18.0 in /operator-cli (76da21f)
139
+ - packer (9665fbc)
140
+ - remove stack api (db0fd4d)
141
+ - packer cleanup (fe1bf14)
142
+ - force refresh token (3a3d7e2)
143
+ - provision shell (2ad505f)
144
+ - azure vm management (91dcb31)
145
+ - azure specific (2b0cca8)
146
+ - azure packer (12175b8)
147
+ - init hashed pwd (db8523c)
148
+ - packer (5b5c7c4)
149
+ - doctor for azure vm (ed524fa)
150
+ - packer and 1pwd (c6d053e)
151
+ - split big index.js (dc85a1b)
152
+ - kafka volume update (21815ec)
153
+ - fix openai azure tools confirmation and flow (0118cd1)
154
+ - nighly fixx, test fix (5e0d04f)
155
+ - open ai training (cdc494a)
156
+ - openai integration in azure (1ca1475)
157
+ - ci (672cea9)
158
+ - refresh ghcr creds (4220c48)
159
+ - cleaned up version (1a0074f)
160
+ - traefik on ghcr and templates (8e31a05)
161
+ - apply fcl (e78911f)
162
+ - demo landscape (dd205fe)
163
+ - smarter login and schema (1af514f)
164
+ - no down before up unless something broke (56b1132)
165
+ - dai, reconcile failed containers (12907fa)
166
+ - reconcile dead container (7da75e4)
167
+ - defensive around storage buckets dir (b98871d)
168
+ - defensive around storage buckets dir (e86e132)
169
+ - gear in for multiarch (bf3fa3e)
170
+ - up autofix (99c7f89)
171
+ - autofix stale containers on up (43c7d0f)
172
+ - shared sessions fix (5de1359)
173
+ - share sessions between ui and tui (8321391)
174
+ - fix chat view display details (e263996)
175
+ - fix chat view display details (9babdda)
176
+ - tui up fixes (86e9f17)
177
+ - fix commands init (442538b)
178
+ - enable k3s profile (b2dcfc8)
179
+ - test up till job creation (656d388)
180
+ - tui fixes (0599779)
181
+ - cleanup (27731f0)
182
+ - train (90bf559)
183
+
1
184
  # Changelog
2
185
 
3
186
  All notable changes to @meshxdata/fops (Foundation Operator CLI) are documented here.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshxdata/fops",
3
- "version": "0.1.44",
3
+ "version": "0.1.46",
4
4
  "description": "CLI to install and manage data mesh platforms",
5
5
  "keywords": [
6
6
  "fops",
@@ -32,6 +32,7 @@ export function registerLifecycleCommands(program, registry) {
32
32
  .option("--url <url>", "Set the public URL (e.g. https://192.168.1.10) — writes FOUNDATION_PUBLIC_URL to .env and enables traefik if port is 443")
33
33
  .option("--pull", "Pull latest images before starting (default: skip pull)")
34
34
  .option("--frontend-dev", "Run frontend in development mode (hot reload) instead of production build")
35
+ .option("--local", "Run frontend dev server locally (outside container) with npm run dev — requires --frontend-dev")
35
36
  .option("--minio-storage", "Use MinIO as the storage backend instead of foundation-storage-engine")
36
37
  .option("--non-interactive", "Skip interactive prompts (auto-grant admin, no browser open)")
37
38
  .action(async (component, branch, opts) => {
@@ -159,6 +160,26 @@ export function registerLifecycleCommands(program, registry) {
159
160
  await dockerCompose(root, args);
160
161
  });
161
162
 
163
+ program
164
+ .command("restart")
165
+ .description("Restart Foundation services (all or specific)")
166
+ .argument("[services...]", "Services to restart (e.g. backend, watcher)")
167
+ .action(async (services) => {
168
+ const root = requireRoot(program);
169
+ const serviceNames = (services || []).filter(Boolean).flatMap((s) => {
170
+ const sub = COMPONENT_SUBMODULES[s];
171
+ if (sub) return sub.restart;
172
+ return [resolveServiceName(root, s)];
173
+ });
174
+ if (serviceNames.length) {
175
+ console.log(chalk.cyan(` Restarting ${serviceNames.join(", ")}...`));
176
+ await dockerCompose(root, ["restart", ...serviceNames]);
177
+ } else {
178
+ console.log(chalk.cyan(" Restarting all services..."));
179
+ await dockerCompose(root, ["restart"]);
180
+ }
181
+ });
182
+
162
183
  program
163
184
  .command("bake")
164
185
  .description("Build and push multi-arch base container images (node, etc.)")
@@ -423,6 +444,14 @@ async function runUp(program, registry, opts) {
423
444
  console.error(chalk.dim(` Available: ${Object.keys(COMPONENT_SUBMODULES).join(", ")}\n`));
424
445
  process.exit(1);
425
446
  }
447
+
448
+ // --local requires --frontend-dev
449
+ if (opts.local && !opts.frontendDev) {
450
+ console.error(chalk.red(`\n --local requires --frontend-dev flag`));
451
+ console.error(chalk.dim(` Usage: fops up --frontend-dev --local\n`));
452
+ process.exit(1);
453
+ }
454
+
426
455
  if (comp && opts.branch) {
427
456
  const componentDir = path.join(root, comp.dir);
428
457
  if (!fs.existsSync(path.join(componentDir, ".git"))) {
@@ -560,7 +589,10 @@ async function runUp(program, registry, opts) {
560
589
  }
561
590
 
562
591
  // Frontend: either production (frontend-prod) or dev with hot reload (frontend-dev)
563
- activeProfiles.add(opts.frontendDev ? "frontend-dev" : "frontend-prod");
592
+ // --local: skip frontend profile entirely, we'll run npm dev locally
593
+ if (!opts.local) {
594
+ activeProfiles.add(opts.frontendDev ? "frontend-dev" : "frontend-prod");
595
+ }
564
596
 
565
597
  const profileArgs = [
566
598
  ...(opts.minioStorage ? ["-f", "docker-compose.yaml", "-f", "docker-compose.minio-storage.yaml"] : []),
@@ -1343,11 +1375,18 @@ async function runUp(program, registry, opts) {
1343
1375
  clearSpinner();
1344
1376
 
1345
1377
  let result;
1378
+ const skipFrontendContainer = opts.local && opts.frontendDev;
1346
1379
  if (componentOnlyUp) {
1347
- const serviceList = opts.frontendDev && opts.component === "frontend"
1348
- ? ["foundation-frontend-dev"]
1349
- : comp.restart;
1350
- result = await runUpInner(` Starting ${opts.component}...`, null, serviceList);
1380
+ if (skipFrontendContainer && opts.component === "frontend") {
1381
+ // --local: skip container, we'll run npm dev locally after
1382
+ result = { exitCode: 0 };
1383
+ console.log(chalk.dim(" Skipping frontend container (--local mode)..."));
1384
+ } else {
1385
+ const serviceList = opts.frontendDev && opts.component === "frontend"
1386
+ ? ["foundation-frontend-dev"]
1387
+ : comp.restart;
1388
+ result = await runUpInner(` Starting ${opts.component}...`, null, serviceList);
1389
+ }
1351
1390
  } else if (needsSequentialUp) {
1352
1391
  const k3sOnlyArgs = profileArgs.filter((a, i, arr) => !(a === "--profile" && arr[i + 1] === "traefik") && !(arr[i - 1] === "--profile" && a === "traefik"));
1353
1392
  result = await runUpInner(" Starting services (k3s)...", k3sOnlyArgs);
@@ -1459,6 +1498,63 @@ async function runUp(program, registry, opts) {
1459
1498
  }
1460
1499
  }
1461
1500
 
1501
+ // --local: Run frontend dev server locally with compose env vars
1502
+ if (skipFrontendContainer) {
1503
+ console.log(chalk.cyan("\n Starting local frontend dev server..."));
1504
+ const frontendDir = path.join(root, "foundation-frontend");
1505
+ if (!fs.existsSync(path.join(frontendDir, "package.json"))) {
1506
+ console.error(chalk.red(" foundation-frontend not found. Run: git submodule update --init foundation-frontend"));
1507
+ process.exitCode = 1;
1508
+ return;
1509
+ }
1510
+
1511
+ // Extract environment variables from compose config for frontend-dev service
1512
+ let frontendEnv = {};
1513
+ try {
1514
+ const { stdout: configJson } = await execa("docker", [
1515
+ "compose", "--profile", "frontend-dev", "config", "--format", "json",
1516
+ ], { cwd: root, reject: false, timeout: 15000 });
1517
+ if (configJson?.trim()) {
1518
+ const config = JSON.parse(configJson);
1519
+ const frontendSvc = config.services?.["foundation-frontend-dev"];
1520
+ if (frontendSvc?.environment) {
1521
+ for (const [key, val] of Object.entries(frontendSvc.environment)) {
1522
+ frontendEnv[key] = val;
1523
+ }
1524
+ }
1525
+ }
1526
+ } catch (err) {
1527
+ console.error(chalk.yellow(" Could not extract compose env vars:"), err.message);
1528
+ }
1529
+
1530
+ // Transform docker-internal URLs to localhost for local dev
1531
+ // Backend is exposed on host port 9001 (container 9000 → host 9001)
1532
+ frontendEnv.INTERNAL_API_URL = "http://localhost:9001";
1533
+ frontendEnv.PORT = "3002";
1534
+ // Remove WATCHPACK_POLLING - not needed outside container
1535
+ delete frontendEnv.WATCHPACK_POLLING;
1536
+
1537
+ // Merge with process.env (compose vars override, then specific overrides)
1538
+ const npmEnv = { ...process.env, ...frontendEnv };
1539
+
1540
+ console.log(chalk.dim(" Environment:"));
1541
+ console.log(chalk.dim(` NEXT_PUBLIC_API_URL=${frontendEnv.NEXT_PUBLIC_API_URL || "not set"}`));
1542
+ console.log(chalk.dim(` INTERNAL_API_URL=${frontendEnv.INTERNAL_API_URL}`));
1543
+ console.log(chalk.dim(` AUTH0_ENABLED=${frontendEnv.AUTH0_ENABLED || "not set"}`));
1544
+
1545
+ // Run npm run dev in foreground (replaces this process)
1546
+ console.log(chalk.cyan("\n Running: npm run dev"));
1547
+ console.log(chalk.dim(" Press Ctrl+C to stop the dev server\n"));
1548
+ const npmProc = execa("npm", ["run", "dev"], {
1549
+ cwd: frontendDir,
1550
+ env: npmEnv,
1551
+ stdio: "inherit",
1552
+ });
1553
+ npmProc.catch(() => {}); // Don't throw on Ctrl+C
1554
+ await npmProc;
1555
+ return;
1556
+ }
1557
+
1462
1558
  // Detect non-interactive environment (no TTY on stdin, e.g. remote VM, CI, cloud-init)
1463
1559
  // --non-interactive flag forces non-interactive mode (used by fops azure provisioning)
1464
1560
  const isInteractive = !opts.nonInteractive && process.stdin.isTTY === true;
@@ -246,12 +246,53 @@ export function registerSetupCommands(program, registry) {
246
246
  const root = rootDir();
247
247
  if (root) {
248
248
  console.log(DIM(" Updating compose project..."));
249
+ let stashedMain = false;
249
250
  try {
250
251
  const { stdout: branch } = await execa("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd: root, timeout: 5000 });
251
- await retry(
252
- () => execa("git", ["pull", "--ff-only", "origin", branch.trim()], { cwd: root, stdio: "inherit", timeout: 120_000 }),
253
- { attempts: 3, delay: 2000, onRetry: (n, max) => console.log(DIM(` Retrying pull (${n}/${max - 1})...`)) }
254
- );
252
+ const branchName = branch.trim();
253
+
254
+ const tryPull = async () => {
255
+ return execa("git", ["pull", "--ff-only", "origin", branchName], { cwd: root, stdio: "pipe", timeout: 120_000 });
256
+ };
257
+
258
+ try {
259
+ await retry(tryPull, { attempts: 3, delay: 2000, onRetry: (n, max) => console.log(DIM(` Retrying pull (${n}/${max - 1})...`)) });
260
+ } catch (pullErr) {
261
+ const errOut = (pullErr.stderr || pullErr.stdout || pullErr.message || "").toString();
262
+ const wouldOverwrite = /would be overwritten by merge|Your local changes to the following files would be overwritten/i.test(errOut);
263
+ const needsStash = /Please commit your changes or stash them/i.test(errOut);
264
+
265
+ if (wouldOverwrite || needsStash) {
266
+ if (!process.stdin.isTTY) {
267
+ console.log(WARN(" ⚠ Local changes would be overwritten by pull."));
268
+ console.log(DIM(" Run in a TTY to be prompted to stash, or: git stash && fops update"));
269
+ throw pullErr;
270
+ }
271
+ const { getInquirer } = await import("../lazy.js");
272
+ const { stash } = await (await getInquirer()).prompt([
273
+ {
274
+ type: "confirm",
275
+ name: "stash",
276
+ message: "Local changes would be overwritten. Stash them and continue?",
277
+ default: true,
278
+ },
279
+ ]);
280
+ if (!stash) {
281
+ console.log(DIM(" Skipping update. Stash or commit changes then run fops update again."));
282
+ throw pullErr;
283
+ }
284
+ await execa("git", ["stash", "push", "-m", "fops update: stashed before pull"], { cwd: root, timeout: 10_000 });
285
+ stashedMain = true;
286
+ await tryPull();
287
+ } else {
288
+ throw pullErr;
289
+ }
290
+ }
291
+
292
+ if (stashedMain) {
293
+ console.log(WARN(" Stashed local changes in compose project"));
294
+ console.log(DIM(" Restore with: git stash pop"));
295
+ }
255
296
  console.log(OK(" ✓ Compose project updated"));
256
297
  } catch (err) {
257
298
  console.log(WARN(` ⚠ git pull failed: ${err.message}`));
@@ -18,6 +18,7 @@ import { registerVmCommands } from "./lib/commands/vm-cmds.js";
18
18
  import { registerFleetCommands } from "./lib/commands/fleet-cmds.js";
19
19
  import { registerTestCommands } from "./lib/commands/test-cmds.js";
20
20
  import { registerInfraCommands } from "./lib/commands/infra-cmds.js";
21
+ import { registerRegistryCommands } from "./lib/commands/registry-cmds.js";
21
22
 
22
23
  export { resolveFoundationCreds, resolveAuth0Config, authenticateVm, vmFetch };
23
24
 
@@ -33,6 +34,7 @@ export async function register(api) {
33
34
  registerFleetCommands(azure);
34
35
  registerTestCommands(azure);
35
36
  registerInfraCommands(azure);
37
+ registerRegistryCommands(azure);
36
38
  });
37
39
 
38
40
  // ── Cost agent tools + agent ───────────────────────────────────────────
@@ -186,6 +188,22 @@ export async function register(api) {
186
188
  },
187
189
  });
188
190
 
191
+ api.registerDoctorCheck({
192
+ name: "cloudflared",
193
+ fn: async (ok, warn) => {
194
+ try {
195
+ const { execa } = await import("execa");
196
+ const { stdout } = await execa("cloudflared", ["--version"], { timeout: 10000 });
197
+ ok(stdout.trim().split("\n")[0]);
198
+ } catch {
199
+ const hint = process.platform === "darwin"
200
+ ? "optional — run: brew install cloudflared"
201
+ : "optional — see https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/";
202
+ warn("cloudflared not installed", hint);
203
+ }
204
+ },
205
+ });
206
+
189
207
  // ── Hook: before:up — auto-sync Key Vault secrets ─────────────────────
190
208
 
191
209
  api.registerHook("before:up", async () => {
@@ -381,6 +399,17 @@ export async function register(api) {
381
399
  "- `fops azure aks flux reconcile [name]` — Force reconciliation",
382
400
  "Flux watches a Git repo and auto-applies manifests to the cluster.",
383
401
  "Push to repo → Flux detects → applies. No kubectl needed.",
402
+ "",
403
+ "### Registry (OCI/Docker via Cloudflare Access)",
404
+ "Push images to AKS-hosted Zot registry through Cloudflare Access tunnel.",
405
+ "",
406
+ "- `fops azure registry login [--domain <url>]` — Authenticate via cloudflared (opens browser)",
407
+ "- `fops azure registry push <image> [--tag <tag>]` — Tag and push image to registry",
408
+ "- `fops azure registry pull <image>` — Pull image from registry",
409
+ "- `fops azure registry logout` — Remove stored credentials",
410
+ "",
411
+ "Workflow: login once per session → push branch images → they're available in AKS.",
412
+ "Credentials stored in ~/.fops/registry/ and ~/.docker/config.json.",
384
413
  ].join("\n"),
385
414
  score: 0.9,
386
415
  },