@rakay-technology/kraft 0.7.9 → 0.7.13

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 (46) hide show
  1. package/dist/bare-5S7IYNHZ.js +27 -0
  2. package/dist/{chunk-VFPLICBX.js → chunk-3AZY56JP.js} +107 -32
  3. package/dist/{chunk-IGTODKUA.js → chunk-5RWL7EFH.js} +5 -5
  4. package/dist/{chunk-ZQJU5CTZ.js → chunk-7VMXN646.js} +1 -1
  5. package/dist/{chunk-DJNKEVZ7.js → chunk-AADWLI2S.js} +1 -1
  6. package/dist/{chunk-MOSINQAM.js → chunk-AFUXAAFQ.js} +16 -388
  7. package/dist/{chunk-2UQFOUSZ.js → chunk-B2CUYCGY.js} +49 -16
  8. package/dist/{chunk-7O6MARHJ.js → chunk-B6B42QMZ.js} +9 -9
  9. package/dist/{chunk-HFOE2IXZ.js → chunk-BIOW6K3V.js} +1 -1
  10. package/dist/{chunk-YY5DEAZI.js → chunk-BQMBJ32I.js} +2 -2
  11. package/dist/{chunk-ULEEWX5M.js → chunk-C3LRTROB.js} +39 -8
  12. package/dist/{chunk-DFVWR6JM.js → chunk-C74WJ3U4.js} +2 -2
  13. package/dist/{chunk-K24SBFI2.js → chunk-D2IM25JV.js} +1 -1
  14. package/dist/{chunk-MC4X55BW.js → chunk-DNC4A3MZ.js} +3 -3
  15. package/dist/{chunk-3RCXJZJD.js → chunk-E3J47WO3.js} +1 -1
  16. package/dist/chunk-G4VGNFGV.js +27374 -0
  17. package/dist/{chunk-JK7KKBXI.js → chunk-KHAT3OZP.js} +4 -4
  18. package/dist/{chunk-7UKBMDUF.js → chunk-MK6GYBO4.js} +9 -9
  19. package/dist/{chunk-SPKRI7MF.js → chunk-N7AJ2D4I.js} +96 -12
  20. package/dist/{chunk-ZNVAHQRY.js → chunk-Q7FAE2MB.js} +6 -6
  21. package/dist/{chunk-2Y62WP2D.js → chunk-QCGVPIYN.js} +2 -2
  22. package/dist/{chunk-PCOTSRS4.js → chunk-QLPQ5NFE.js} +3 -3
  23. package/dist/{chunk-DI54Y66N.js → chunk-QPUEAYB3.js} +3 -3
  24. package/dist/{chunk-XBGSR22I.js → chunk-XAEYWDBX.js} +53 -9
  25. package/dist/{chunk-HLF5PMKE.js → chunk-Y2MET6MX.js} +1 -1
  26. package/dist/{chunk-BN23UUSF.js → chunk-YXXWTBXB.js} +1 -1
  27. package/dist/{detect-N4HFQZ6Y.js → detect-NDVA2MAF.js} +4 -4
  28. package/dist/{docker-DU7JA2AK.js → docker-Z2ILAC7A.js} +8 -8
  29. package/dist/{docker-edge-executor-MPIPQHNF.js → docker-edge-executor-JID2Q2HZ.js} +7 -7
  30. package/dist/{edge-import-RZD7MMOE.js → edge-import-WRU5JQ43.js} +22 -22
  31. package/dist/{edge-preflight-6YO27PPQ.js → edge-preflight-6FYNGFIH.js} +13 -13
  32. package/dist/{ensure-container-edge-ZKEKC47H.js → ensure-container-edge-VFCVCXW3.js} +11 -11
  33. package/dist/{executor-ZWF2J7GS.js → executor-LNKX5OMQ.js} +6 -6
  34. package/dist/{host-channel-preflight-Z64G3NIM.js → host-channel-preflight-V7Q6GPXE.js} +22 -22
  35. package/dist/index.js +40 -40
  36. package/dist/{local-executor-W3O5HDLM.js → local-executor-NPLQMF6A.js} +3 -3
  37. package/dist/{nginx-XLDZIG4E.js → nginx-V6DQWKON.js} +11 -9
  38. package/dist/{openresty-lua-ZNE6IBYU.js → openresty-lua-OECMHHON.js} +21 -7
  39. package/dist/{privilege-IMARWVU2.js → privilege-KI56M7OQ.js} +5 -5
  40. package/dist/server/index.js +1897 -58664
  41. package/dist/{setup-Q6GGIJ4Q.js → setup-A2LJ4IWU.js} +12 -12
  42. package/dist/{ssh-client-LOCZTEUC.js → ssh-client-NRBHQJVZ.js} +2 -2
  43. package/dist/{up-TU7622HW.js → up-XHQK2O2M.js} +25 -25
  44. package/package.json +1 -1
  45. package/dist/bare-JM3EX7S4.js +0 -27
  46. package/dist/chunk-ND23EK7Y.js +0 -81645
@@ -5,11 +5,10 @@ const require = __ospCreateRequire(import.meta.url);
5
5
  import {
6
6
  containerCommand,
7
7
  edgeContainerExecutor,
8
- isSafeCertPath,
9
8
  readDeclaredPair,
10
9
  readMaybeInContainer,
11
10
  validateCertFor
12
- } from "./chunk-VFPLICBX.js";
11
+ } from "./chunk-3AZY56JP.js";
13
12
  import {
14
13
  EdgeConflictError,
15
14
  EdgeMigrateRequested,
@@ -24,42 +23,42 @@ import {
24
23
  sanitizeEdgeVhosts,
25
24
  sq as sq2,
26
25
  stopTargetsForStatus
27
- } from "./chunk-PCOTSRS4.js";
26
+ } from "./chunk-QLPQ5NFE.js";
28
27
  import {
29
28
  privilegedExecutor,
30
29
  rootChecked,
31
30
  rootOrDegrade
32
- } from "./chunk-DI54Y66N.js";
31
+ } from "./chunk-QPUEAYB3.js";
33
32
  import {
34
33
  EDGE_CHALLENGE_HOST_DIR,
35
34
  EDGE_CONTAINER_MOUNTS,
36
35
  EDGE_HOST_PATHS,
37
36
  OPENRESTY_DEFAULT_PATHS
38
- } from "./chunk-XBGSR22I.js";
37
+ } from "./chunk-XAEYWDBX.js";
39
38
  import {
40
39
  waitForPortListening
41
- } from "./chunk-2Y62WP2D.js";
40
+ } from "./chunk-QCGVPIYN.js";
42
41
  import {
43
42
  EDGE_CONTAINER_NAME,
44
43
  probeExec,
45
44
  probeExecElevated,
46
45
  tryExec,
47
46
  withReason
48
- } from "./chunk-3RCXJZJD.js";
47
+ } from "./chunk-E3J47WO3.js";
49
48
  import {
50
49
  envOps,
51
50
  opScript
52
- } from "./chunk-ZQJU5CTZ.js";
51
+ } from "./chunk-7VMXN646.js";
53
52
  import {
54
53
  resolveEnvironment
55
- } from "./chunk-YY5DEAZI.js";
54
+ } from "./chunk-BQMBJ32I.js";
56
55
  import {
57
56
  formatDuration,
58
57
  systemDebug
59
58
  } from "./chunk-3CJLKL6E.js";
60
59
  import {
61
60
  sq
62
- } from "./chunk-BN23UUSF.js";
61
+ } from "./chunk-YXXWTBXB.js";
63
62
  import {
64
63
  AppError,
65
64
  PROXY_DIRECTIVES,
@@ -73,7 +72,7 @@ import {
73
72
  safeErrorMessage,
74
73
  sanitizeProxySettings,
75
74
  shellQuote
76
- } from "./chunk-ND23EK7Y.js";
75
+ } from "./chunk-G4VGNFGV.js";
77
76
 
78
77
  // ../../packages/adapters/src/system/managed-image.ts
79
78
  import { posix } from "path";
@@ -1334,237 +1333,6 @@ async function scanApache(executor) {
1334
1333
  return { proxy: "apache", sites: kept, warnings };
1335
1334
  }
1336
1335
 
1337
- // ../../packages/adapters/src/system/proxy/import/traefik.ts
1338
- function lowerKeys(labels) {
1339
- const out = {};
1340
- for (const [k, v] of Object.entries(labels)) out[k.toLowerCase()] = v;
1341
- return out;
1342
- }
1343
- function extractHosts(rule) {
1344
- const hosts = [];
1345
- for (const call of rule.matchAll(/\bHost\(([^)]*)\)/gi)) {
1346
- for (const m of call[1].matchAll(/[`'"]([^`'"]+)[`'"]/g)) {
1347
- const h = m[1].trim();
1348
- if (h) hosts.push(h);
1349
- }
1350
- }
1351
- return [...new Set(hosts)];
1352
- }
1353
- function extraMatchers(rule) {
1354
- const found = /* @__PURE__ */ new Set();
1355
- for (const m of rule.matchAll(
1356
- /\b(PathPrefix|PathRegexp|Path|HeadersRegexp|Headers|Method|Query|ClientIP|HostRegexp)\b/gi
1357
- )) {
1358
- found.add(m[1]);
1359
- }
1360
- return [...found];
1361
- }
1362
- function collectDefinitions(containers) {
1363
- const services = /* @__PURE__ */ new Map();
1364
- const redirectMiddlewares = /* @__PURE__ */ new Set();
1365
- const streamRouters = [];
1366
- let fileProvider = false;
1367
- let exposedByDefault = true;
1368
- for (const c of containers) {
1369
- const labels = lowerKeys(c.labels);
1370
- for (const [k, v] of Object.entries(labels)) {
1371
- let m = k.match(
1372
- /^traefik\.http\.services\.([^.]+)\.loadbalancer\.server\.(port|scheme)$/
1373
- );
1374
- if (m) {
1375
- const def = services.get(m[1]) ?? {};
1376
- if (m[2] === "port") def.port = v;
1377
- else def.scheme = v;
1378
- services.set(m[1], def);
1379
- continue;
1380
- }
1381
- m = k.match(/^traefik\.http\.middlewares\.([^.]+)\.redirectscheme\./);
1382
- if (m) {
1383
- redirectMiddlewares.add(m[1]);
1384
- continue;
1385
- }
1386
- m = k.match(/^traefik\.(tcp|udp)\.routers\.([^.]+)\.rule$/);
1387
- if (m) streamRouters.push(`${m[1]} router "${m[2]}"`);
1388
- }
1389
- const cmd = c.cmd ?? "";
1390
- if (/--?providers\.file/i.test(cmd)) fileProvider = true;
1391
- if (/--?providers\.docker\.exposedbydefault[= ]?false/i.test(cmd))
1392
- exposedByDefault = false;
1393
- }
1394
- return {
1395
- services,
1396
- redirectMiddlewares,
1397
- streamRouters,
1398
- fileProvider,
1399
- exposedByDefault
1400
- };
1401
- }
1402
- function resolveIp(c, labels) {
1403
- const wanted = labels["traefik.docker.network"];
1404
- if (wanted && c.networks?.[wanted]) return c.networks[wanted];
1405
- if (c.ip) return c.ip;
1406
- const first = Object.values(c.networks ?? {}).find(Boolean);
1407
- return first || void 0;
1408
- }
1409
- function parseTraefikLabels(containers) {
1410
- const warnings = [];
1411
- const defs = collectDefinitions(containers);
1412
- const candidates = [];
1413
- for (const c of containers) {
1414
- const labels = lowerKeys(c.labels);
1415
- if (labels["traefik.enable"] === "false") continue;
1416
- if (!defs.exposedByDefault && labels["traefik.enable"] !== "true") continue;
1417
- const routers = /* @__PURE__ */ new Map();
1418
- for (const [key, val] of Object.entries(labels)) {
1419
- const r = key.match(/^traefik\.http\.routers\.([^.]+)\.(.+)$/);
1420
- if (!r) continue;
1421
- const bag = routers.get(r[1]) ?? {};
1422
- bag[r[2]] = val;
1423
- routers.set(r[1], bag);
1424
- }
1425
- for (const [rname, props] of routers) {
1426
- const rule = props.rule;
1427
- if (!rule) continue;
1428
- const hosts = extractHosts(rule);
1429
- if (hosts.length === 0) {
1430
- warnings.push(
1431
- /HostRegexp/i.test(rule) ? `traefik: router "${rname}" uses HostRegexp (${rule}) \u2014 regex hosts aren't migratable` : `traefik: router "${rname}" has no Host() rule (${rule}) \u2014 skipped`
1432
- );
1433
- continue;
1434
- }
1435
- const ip = resolveIp(c, labels);
1436
- if (!ip) {
1437
- warnings.push(
1438
- `traefik: ${hosts.join(", ")} \u2014 couldn't resolve container ${c.name}'s IP; re-add the upstream manually`
1439
- );
1440
- continue;
1441
- }
1442
- const svc = props.service?.replace(/@.*$/, "");
1443
- const def = (svc ? defs.services.get(svc) : void 0) ?? (defs.services.size === 1 ? [...defs.services.values()][0] : void 0);
1444
- const onlyExposed = c.exposedPorts?.length === 1 ? c.exposedPorts[0].split("/")[0] : void 0;
1445
- const rawPort = def?.port ?? onlyExposed;
1446
- const port = /^\d{1,5}$/.test(String(rawPort)) ? String(rawPort) : "80";
1447
- const scheme = def?.scheme?.toLowerCase() === "https" ? "https" : "http";
1448
- const middlewares = (props.middlewares ?? "").split(",").map((m) => m.trim().replace(/@.*$/, "")).filter(Boolean);
1449
- candidates.push({
1450
- hosts,
1451
- ssl: Object.keys(props).some(
1452
- (p) => p === "tls" || p.startsWith("tls.")
1453
- ),
1454
- url: `${scheme}://${ip}:${port}`,
1455
- container: c.name,
1456
- router: rname,
1457
- rule,
1458
- middlewares,
1459
- redirectOnly: middlewares.length > 0 && middlewares.every((m) => defs.redirectMiddlewares.has(m)),
1460
- portGuessed: rawPort === void 0
1461
- });
1462
- }
1463
- }
1464
- const { kept: sites, dropped } = collapseByHost(
1465
- candidates,
1466
- (c) => c.hosts,
1467
- (c) => c.redirectOnly ? 0 : c.ssl ? 2 : 1
1468
- );
1469
- for (const cand of sites) {
1470
- const extras = extraMatchers(cand.rule);
1471
- if (extras.length > 0) {
1472
- warnings.push(
1473
- `traefik: ${cand.hosts.join(", ")} also matches ${extras.join(", ")} \u2014 only the Host() part is migrated; re-add path/header rules manually`
1474
- );
1475
- }
1476
- const carried = cand.middlewares.filter(
1477
- (m) => !defs.redirectMiddlewares.has(m)
1478
- );
1479
- if (carried.length > 0) {
1480
- warnings.push(
1481
- `traefik: ${cand.hosts.join(", ")} uses middleware(s) "${carried.join(", ")}" \u2014 not migrated`
1482
- );
1483
- }
1484
- if (cand.portGuessed) {
1485
- warnings.push(
1486
- `traefik: ${cand.hosts.join(", ")} \u2014 no service port label and no single exposed port on ${cand.container}; assumed :80, check the upstream`
1487
- );
1488
- }
1489
- }
1490
- for (const d of dropped) {
1491
- warnings.push(
1492
- `traefik: ${d.hosts.join(", ")} router "${d.router}" is an http\u2192https redirect \u2014 Kraft's edge does that itself (nothing to migrate)`
1493
- );
1494
- }
1495
- for (const s of defs.streamRouters) {
1496
- warnings.push(
1497
- `traefik: ${s} can't migrate \u2014 Kraft's edge routes HTTP(S), not raw TCP/UDP`
1498
- );
1499
- }
1500
- if (defs.fileProvider) {
1501
- warnings.push(
1502
- "traefik: a file provider is configured \u2014 routes defined in its YAML/TOML files are NOT read here, only container labels. Re-add those domains manually."
1503
- );
1504
- }
1505
- return {
1506
- proxy: "traefik",
1507
- sites: sites.map((cand) => ({
1508
- serverNames: cand.hosts,
1509
- ssl: cand.ssl,
1510
- target: { kind: "proxy", url: cand.url },
1511
- source: `traefik container ${cand.container}`
1512
- })),
1513
- warnings
1514
- };
1515
- }
1516
- async function scanTraefik(executor) {
1517
- const out = await tryExec(
1518
- executor,
1519
- `docker ps -q 2>/dev/null | xargs -r docker inspect --format '{{.Name}} {{json .Config.Labels}} {{range $n, $v := .NetworkSettings.Networks}}{{$n}}={{$v.IPAddress}} {{end}} {{range $p, $v := .Config.ExposedPorts}}{{$p}} {{end}} {{if .Config.Cmd}}{{join .Config.Cmd " "}}{{end}}' 2>/dev/null`
1520
- );
1521
- if (!out) {
1522
- return {
1523
- proxy: "traefik",
1524
- sites: [],
1525
- warnings: ["traefik: couldn't read container labels via docker inspect"]
1526
- };
1527
- }
1528
- const containers = [];
1529
- for (const line of out.split("\n")) {
1530
- const [rawName, rawLabels, rawNets, rawPorts, rawCmd] = line.split(" ");
1531
- if (!rawName || !rawLabels) continue;
1532
- let labels;
1533
- try {
1534
- labels = JSON.parse(rawLabels) ?? {};
1535
- } catch {
1536
- continue;
1537
- }
1538
- const networks = {};
1539
- let bareIp;
1540
- for (const pair of (rawNets ?? "").trim().split(/\s+/)) {
1541
- if (!pair) continue;
1542
- const eq = pair.indexOf("=");
1543
- if (eq > 0) {
1544
- const ip = pair.slice(eq + 1);
1545
- if (ip) networks[pair.slice(0, eq)] = ip;
1546
- } else if (!bareIp) {
1547
- bareIp = pair;
1548
- }
1549
- }
1550
- const exposedPorts = (rawPorts ?? "").trim().split(/\s+/).filter(Boolean);
1551
- const hasTraefikLabels = Object.keys(labels).some(
1552
- (k) => k.toLowerCase().startsWith("traefik.")
1553
- );
1554
- const looksLikeTraefik = /traefik/i.test(rawCmd ?? "") || /--?providers\./i.test(rawCmd ?? "");
1555
- if (!hasTraefikLabels && !looksLikeTraefik) continue;
1556
- containers.push({
1557
- name: rawName.replace(/^\//, ""),
1558
- labels,
1559
- ip: Object.values(networks)[0] ?? bareIp,
1560
- networks,
1561
- exposedPorts,
1562
- cmd: rawCmd ?? void 0
1563
- });
1564
- }
1565
- return parseTraefikLabels(containers);
1566
- }
1567
-
1568
1336
  // ../../packages/adapters/src/system/proxy/import/index.ts
1569
1337
  var INSTALLED_MARKERS = [
1570
1338
  { proxy: "nginx", paths: ["/etc/nginx/nginx.conf"] },
@@ -1607,8 +1375,6 @@ async function scanImportableSites(executor, proxy) {
1607
1375
  return scanCaddy(executor);
1608
1376
  case "apache":
1609
1377
  return scanApache(executor);
1610
- case "traefik":
1611
- return scanTraefik(executor);
1612
1378
  case "openresty":
1613
1379
  return scanForeignOpenResty(executor);
1614
1380
  default:
@@ -1620,7 +1386,7 @@ async function scanImportableSites(executor, proxy) {
1620
1386
  }
1621
1387
  }
1622
1388
  function canImportProxy(proxy) {
1623
- return proxy === "nginx" || proxy === "caddy" || proxy === "apache" || proxy === "traefik" || proxy === "openresty";
1389
+ return proxy === "nginx" || proxy === "caddy" || proxy === "apache" || proxy === "openresty";
1624
1390
  }
1625
1391
  function unreachableStaticRoots(sites, opts) {
1626
1392
  if (!opts.containerEdge) return [];
@@ -1693,125 +1459,6 @@ async function caddyStoreCert(exec, host, container) {
1693
1459
  return null;
1694
1460
  }
1695
1461
 
1696
- // ../../packages/adapters/src/system/proxy/import/traefik-certs.ts
1697
- var DEFAULT_ACME_PATHS = [
1698
- "/acme.json",
1699
- "/etc/traefik/acme.json",
1700
- "/data/acme.json",
1701
- "/letsencrypt/acme.json"
1702
- ];
1703
- var TRAEFIK_STATIC_CONFIGS = [
1704
- "/etc/traefik/traefik.yml",
1705
- "/etc/traefik/traefik.yaml",
1706
- "/etc/traefik/traefik.toml"
1707
- ];
1708
- function prop(obj, name) {
1709
- const hit = Object.keys(obj).find(
1710
- (k) => k.toLowerCase() === name.toLowerCase()
1711
- );
1712
- return hit === void 0 ? void 0 : obj[hit];
1713
- }
1714
- async function candidateStoragePaths(exec, container) {
1715
- const found = [];
1716
- const collect = (text) => {
1717
- for (const m of (text ?? "").matchAll(
1718
- /acme\.storage[=:\s]+["']?(\/[^\s"',}]+)/gi
1719
- )) {
1720
- if (isSafeCertPath(m[1])) found.push(m[1]);
1721
- }
1722
- for (const m of (text ?? "").matchAll(
1723
- /(?:^|\s)storage:\s*["']?(\/[^\s"',}]+\.json)/gi
1724
- )) {
1725
- if (isSafeCertPath(m[1])) found.push(m[1]);
1726
- }
1727
- };
1728
- if (container) {
1729
- collect(
1730
- await tryExec(
1731
- exec,
1732
- `docker inspect ${sq2(container)} --format '{{json .Config.Cmd}} {{json .Args}} {{json .Config.Env}}' 2>/dev/null`
1733
- )
1734
- );
1735
- for (const cfg of TRAEFIK_STATIC_CONFIGS) {
1736
- collect(await readMaybeInContainer(exec, cfg, container));
1737
- }
1738
- }
1739
- return [.../* @__PURE__ */ new Set([...found, ...DEFAULT_ACME_PATHS])];
1740
- }
1741
- async function loadAcmeJson(exec, container) {
1742
- for (const path of await candidateStoragePaths(exec, container)) {
1743
- const raw = await readMaybeInContainer(exec, path, container);
1744
- if (raw.trim().startsWith("{")) return { raw, path };
1745
- }
1746
- return null;
1747
- }
1748
- function certFromAcmeJson(raw, host) {
1749
- let parsed;
1750
- try {
1751
- parsed = JSON.parse(raw);
1752
- } catch {
1753
- return null;
1754
- }
1755
- const target = host.toLowerCase();
1756
- const matches = (name) => {
1757
- const n = (name ?? "").toLowerCase();
1758
- if (!n) return false;
1759
- if (n === target) return true;
1760
- if (!n.startsWith("*.")) return false;
1761
- const suffix = n.slice(1);
1762
- return target.endsWith(suffix) && !target.slice(0, -suffix.length).includes(".");
1763
- };
1764
- for (const [resolver, value] of Object.entries(parsed)) {
1765
- if (!value || typeof value !== "object") continue;
1766
- const certs = prop(value, "certificates");
1767
- if (!Array.isArray(certs)) continue;
1768
- for (const entry of certs) {
1769
- const domain = entry && prop(entry, "domain");
1770
- const names = [domain?.main, ...domain?.sans ?? []];
1771
- if (!names.some(matches)) continue;
1772
- const certB64 = prop(entry, "certificate");
1773
- const keyB64 = prop(entry, "key");
1774
- if (typeof certB64 !== "string" || typeof keyB64 !== "string") continue;
1775
- const certPem = Buffer.from(certB64, "base64").toString("utf-8");
1776
- const keyPem = Buffer.from(keyB64, "base64").toString("utf-8");
1777
- if (!certPem.includes("-----BEGIN") || !keyPem.includes("-----BEGIN"))
1778
- continue;
1779
- return { certPem, keyPem, resolver };
1780
- }
1781
- }
1782
- return null;
1783
- }
1784
- async function traefikAcmeCert(exec, host, container) {
1785
- const loaded = await loadAcmeJson(exec, container);
1786
- if (!loaded) return null;
1787
- const hit = certFromAcmeJson(loaded.raw, host);
1788
- if (!hit) return null;
1789
- return {
1790
- certPem: hit.certPem,
1791
- keyPem: hit.keyPem,
1792
- source: `traefik ${loaded.path} (resolver ${hit.resolver})`
1793
- };
1794
- }
1795
- async function traefikDeclaredCertPaths(exec, container) {
1796
- const pairs = [];
1797
- for (const cfg of TRAEFIK_STATIC_CONFIGS) {
1798
- const text = await readMaybeInContainer(exec, cfg, container);
1799
- if (!text.trim()) continue;
1800
- const certFiles = [
1801
- ...text.matchAll(/certFile:\s*["']?(\/[^\s"',}]+)/gi)
1802
- ].map((m) => m[1]);
1803
- const keyFiles = [...text.matchAll(/keyFile:\s*["']?(\/[^\s"',}]+)/gi)].map(
1804
- (m) => m[1]
1805
- );
1806
- for (let i = 0; i < Math.min(certFiles.length, keyFiles.length); i++) {
1807
- if (isSafeCertPath(certFiles[i]) && isSafeCertPath(keyFiles[i])) {
1808
- pairs.push({ certPath: certFiles[i], keyPath: keyFiles[i] });
1809
- }
1810
- }
1811
- }
1812
- return pairs;
1813
- }
1814
-
1815
1462
  // ../../packages/adapters/src/system/proxy/api.ts
1816
1463
  function buildProxyRouteIndex(sites) {
1817
1464
  const byPort = /* @__PURE__ */ new Map();
@@ -1878,28 +1525,9 @@ var CERT_SOURCES = {
1878
1525
  openresty: [declaredCert],
1879
1526
  apache: [declaredCert],
1880
1527
  caddy: [declaredCert, (c) => caddyStoreCert(c.exec, c.host, c.container)],
1881
- traefik: [
1882
- (c) => traefikAcmeCert(c.exec, c.host, c.container),
1883
- // File provider: paths aren't bound to a hostname (traefik picks by SNI), so
1884
- // hand every declared pair to the validator and let coverage decide.
1885
- async (c) => {
1886
- for (const pair of await traefikDeclaredCertPaths(c.exec, c.container)) {
1887
- const pems = await readDeclaredPair(
1888
- c.exec,
1889
- pair.certPath,
1890
- pair.keyPath,
1891
- c.container
1892
- );
1893
- if (!pems) continue;
1894
- if (validateCertFor(c.host, pems, pair.certPath).cert) {
1895
- return { ...pems, source: pair.certPath };
1896
- }
1897
- }
1898
- return null;
1899
- }
1900
- ],
1901
1528
  // Takeover-only: no importable config, so no cert to find either.
1902
- haproxy: []
1529
+ haproxy: [],
1530
+ traefik: []
1903
1531
  };
1904
1532
  async function edgeProxy(exec, opts = {}) {
1905
1533
  const status = opts.status ?? await probeEdge(exec).catch(() => null);
@@ -2867,7 +2495,7 @@ function edgeHostExecutor(executor) {
2867
2495
  });
2868
2496
  }
2869
2497
  async function containerEdgeProvider(executor, container, opts) {
2870
- const { NginxProvider: Provider } = await import("./nginx-XLDZIG4E.js");
2498
+ const { NginxProvider: Provider } = await import("./nginx-V6DQWKON.js");
2871
2499
  return new Provider({
2872
2500
  ...opts,
2873
2501
  // Vhosts go to the BIND-MOUNTED HOST dir (so every host-side reader — the
@@ -2894,8 +2522,8 @@ async function containerEdgeProvider(executor, container, opts) {
2894
2522
  });
2895
2523
  }
2896
2524
  async function localContainerEdgeProvider(container, opts) {
2897
- const { DockerEdgeExecutor } = await import("./docker-edge-executor-MPIPQHNF.js");
2898
- const { NginxProvider: Provider } = await import("./nginx-XLDZIG4E.js");
2525
+ const { DockerEdgeExecutor } = await import("./docker-edge-executor-JID2Q2HZ.js");
2526
+ const { NginxProvider: Provider } = await import("./nginx-V6DQWKON.js");
2899
2527
  return new Provider({
2900
2528
  ...opts,
2901
2529
  paths: OPENRESTY_DEFAULT_PATHS,
@@ -140,29 +140,29 @@ import {
140
140
  resolveExecExitCode,
141
141
  startAttachStream,
142
142
  startExecStream
143
- } from "./chunk-ZNVAHQRY.js";
143
+ } from "./chunk-Q7FAE2MB.js";
144
144
  import {
145
145
  BareRuntime
146
- } from "./chunk-7UKBMDUF.js";
146
+ } from "./chunk-MK6GYBO4.js";
147
147
  import {
148
148
  createExecutor
149
- } from "./chunk-SPKRI7MF.js";
149
+ } from "./chunk-N7AJ2D4I.js";
150
150
  import {
151
151
  OPENRESTY_DEFAULT_PATHS
152
- } from "./chunk-XBGSR22I.js";
152
+ } from "./chunk-XAEYWDBX.js";
153
153
  import {
154
154
  MAIL_HOST_STATE_DIR
155
- } from "./chunk-3RCXJZJD.js";
155
+ } from "./chunk-E3J47WO3.js";
156
156
  import {
157
157
  envOps
158
- } from "./chunk-ZQJU5CTZ.js";
158
+ } from "./chunk-7VMXN646.js";
159
159
  import {
160
160
  ENVIRONMENT_PROBE_SCRIPT,
161
161
  ENVIRONMENT_PROBE_TIMEOUT_MS,
162
162
  cacheEnvironment,
163
163
  parseEnvironmentProbe,
164
164
  profileIsFresh
165
- } from "./chunk-YY5DEAZI.js";
165
+ } from "./chunk-BQMBJ32I.js";
166
166
  import {
167
167
  FAMILY_BY_DISTRO,
168
168
  PRICING,
@@ -175,7 +175,7 @@ import {
175
175
  validateBackupPath,
176
176
  validateClearPath,
177
177
  withTimeout
178
- } from "./chunk-ND23EK7Y.js";
178
+ } from "./chunk-G4VGNFGV.js";
179
179
 
180
180
  // ../../packages/adapters/src/types.ts
181
181
  var DEFAULT_BUILD_RESOURCE_CONFIG = {
@@ -293,13 +293,16 @@ function registerDestination(kind, factory) {
293
293
  }
294
294
 
295
295
  // ../../packages/adapters/src/backup/common/credentials.ts
296
- import { createDecipheriv, createHash as createHash2 } from "crypto";
297
- var PREFIX = "enc1:";
296
+ import { createDecipheriv, createHash as createHash2, hkdfSync } from "crypto";
297
+ var PREFIX_V1 = "enc1:";
298
+ var PREFIX_V2 = "enc2:";
298
299
  var ALGORITHM = "aes-256-gcm";
299
300
  var IV_LENGTH = 16;
300
301
  var AUTH_TAG_LENGTH = 16;
302
+ var HKDF_SALT_V2 = "kraft-enc-salt-v2";
303
+ var SSH_CREDENTIAL_PURPOSE = "ssh-credential-v1";
301
304
  var injectedSecret;
302
- function deriveKey() {
305
+ function deriveKeyV1() {
303
306
  const secret = injectedSecret ?? process.env.BETTER_AUTH_SECRET;
304
307
  if (!secret) {
305
308
  throw new Error(
@@ -308,23 +311,53 @@ function deriveKey() {
308
311
  }
309
312
  return createHash2("sha256").update(secret).digest();
310
313
  }
311
- function decryptCredential(stored) {
312
- if (stored == null || stored === "") return void 0;
313
- if (!stored.startsWith(PREFIX)) return stored;
314
- const packed = Buffer.from(stored.slice(PREFIX.length), "base64");
314
+ function deriveKeyV2() {
315
+ const secret = injectedSecret ?? process.env.BETTER_AUTH_SECRET;
316
+ if (!secret) {
317
+ throw new Error(
318
+ "BETTER_AUTH_SECRET is not set \u2014 cannot decrypt backup destination credentials."
319
+ );
320
+ }
321
+ return Buffer.from(
322
+ hkdfSync(
323
+ "sha256",
324
+ Buffer.from(secret, "utf8"),
325
+ HKDF_SALT_V2,
326
+ SSH_CREDENTIAL_PURPOSE,
327
+ 32
328
+ )
329
+ );
330
+ }
331
+ function openEnvelope(packed, key) {
315
332
  if (packed.length < IV_LENGTH + AUTH_TAG_LENGTH) {
316
333
  throw new Error("Invalid credential ciphertext: too short");
317
334
  }
318
335
  const iv = packed.subarray(0, IV_LENGTH);
319
336
  const authTag = packed.subarray(IV_LENGTH, IV_LENGTH + AUTH_TAG_LENGTH);
320
337
  const ciphertext = packed.subarray(IV_LENGTH + AUTH_TAG_LENGTH);
321
- const decipher = createDecipheriv(ALGORITHM, deriveKey(), iv);
338
+ const decipher = createDecipheriv(ALGORITHM, key, iv);
322
339
  decipher.setAuthTag(authTag);
323
340
  return Buffer.concat([
324
341
  decipher.update(ciphertext),
325
342
  decipher.final()
326
343
  ]).toString("utf8");
327
344
  }
345
+ function decryptCredential(stored) {
346
+ if (stored == null || stored === "") return void 0;
347
+ if (stored.startsWith(PREFIX_V2)) {
348
+ return openEnvelope(
349
+ Buffer.from(stored.slice(PREFIX_V2.length), "base64"),
350
+ deriveKeyV2()
351
+ );
352
+ }
353
+ if (stored.startsWith(PREFIX_V1)) {
354
+ return openEnvelope(
355
+ Buffer.from(stored.slice(PREFIX_V1.length), "base64"),
356
+ deriveKeyV1()
357
+ );
358
+ }
359
+ return stored;
360
+ }
328
361
 
329
362
  // ../../packages/adapters/src/backup/common/sha256-stream.ts
330
363
  import { createHash as createHash3 } from "crypto";
@@ -9,14 +9,14 @@ import {
9
9
  internalPost,
10
10
  mintBareInternalToken,
11
11
  waitHealthy
12
- } from "./chunk-JK7KKBXI.js";
12
+ } from "./chunk-KHAT3OZP.js";
13
13
  import {
14
14
  completeHostEdge,
15
15
  markStoppedProxyImported,
16
16
  planAndApplyHostEdge,
17
17
  previewHostEdge,
18
18
  rollbackHostEdge
19
- } from "./chunk-IGTODKUA.js";
19
+ } from "./chunk-5RWL7EFH.js";
20
20
  import {
21
21
  DEFAULT_REPO,
22
22
  PORTS_FILE,
@@ -43,11 +43,11 @@ import {
43
43
  resolvePorts,
44
44
  sourceBuildDir,
45
45
  verifyHostChannel
46
- } from "./chunk-ULEEWX5M.js";
46
+ } from "./chunk-C3LRTROB.js";
47
47
  import {
48
48
  startUnitHint,
49
49
  thisHost
50
- } from "./chunk-2UQFOUSZ.js";
50
+ } from "./chunk-B2CUYCGY.js";
51
51
  import {
52
52
  AUTH_SECRET_FILE,
53
53
  DATA_DIR,
@@ -59,16 +59,16 @@ import {
59
59
  import {
60
60
  edgeCrashReason,
61
61
  edgeIsBroken
62
- } from "./chunk-PCOTSRS4.js";
62
+ } from "./chunk-QLPQ5NFE.js";
63
63
  import {
64
64
  LocalExecutor
65
- } from "./chunk-HFOE2IXZ.js";
65
+ } from "./chunk-BIOW6K3V.js";
66
66
  import {
67
67
  EDGE_CONTAINER_NAME
68
- } from "./chunk-3RCXJZJD.js";
68
+ } from "./chunk-E3J47WO3.js";
69
69
  import {
70
70
  isValidEmail
71
- } from "./chunk-ND23EK7Y.js";
71
+ } from "./chunk-G4VGNFGV.js";
72
72
 
73
73
  // src/commands/up.ts
74
74
  import { Command } from "commander";
@@ -1942,7 +1942,7 @@ async function runForeground(opts, source) {
1942
1942
  const uiSpinner = ora("Preparing the dashboard\u2026").start();
1943
1943
  try {
1944
1944
  const bundle = await ensureDashboard({
1945
- tag: source ? "local" : opts.uiVersion || `v${"0.7.9"}`,
1945
+ tag: source ? "local" : opts.uiVersion || `v${"0.7.13"}`,
1946
1946
  onProgress: (received, total) => {
1947
1947
  if (total) {
1948
1948
  uiSpinner.text = `Downloading dashboard\u2026 ${Math.round(received / total * 100)}%`;
@@ -8,7 +8,7 @@ import {
8
8
  getLocalShellPath,
9
9
  logEntry,
10
10
  sq
11
- } from "./chunk-BN23UUSF.js";
11
+ } from "./chunk-YXXWTBXB.js";
12
12
 
13
13
  // ../../packages/adapters/src/system/local-executor.ts
14
14
  import { exec, spawn } from "child_process";