@rallycry/conveyor-k3 0.1.12 → 0.1.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.
package/dist/index.js CHANGED
@@ -101,7 +101,7 @@ function createClusterProof(apiUrl, clusterToken, key) {
101
101
  const origin = new URL(apiUrl).origin;
102
102
  const timestamp = Date.now();
103
103
  const nonce = randomBytes(32).toString("base64url");
104
- const message = `conveyor-device-v1
104
+ const message2 = `conveyor-device-v1
105
105
  ${origin}
106
106
  ${clusterToken}
107
107
  ${timestamp}
@@ -109,7 +109,7 @@ ${nonce}`;
109
109
  return {
110
110
  timestamp,
111
111
  nonce,
112
- signature: sign(null, Buffer.from(message, "utf8"), key).toString("base64url")
112
+ signature: sign(null, Buffer.from(message2, "utf8"), key).toString("base64url")
113
113
  };
114
114
  }
115
115
  function deviceClusterAuth(apiUrl, clusterToken, keyPath = DEVICE_KEY_PATH, ownerUid = 0) {
@@ -487,104 +487,104 @@ ZodError.create = (issues) => {
487
487
 
488
488
  // ../../node_modules/.bun/zod@3.25.76/node_modules/zod/v3/locales/en.js
489
489
  var errorMap = (issue, _ctx) => {
490
- let message;
490
+ let message2;
491
491
  switch (issue.code) {
492
492
  case ZodIssueCode.invalid_type:
493
493
  if (issue.received === ZodParsedType.undefined) {
494
- message = "Required";
494
+ message2 = "Required";
495
495
  } else {
496
- message = `Expected ${issue.expected}, received ${issue.received}`;
496
+ message2 = `Expected ${issue.expected}, received ${issue.received}`;
497
497
  }
498
498
  break;
499
499
  case ZodIssueCode.invalid_literal:
500
- message = `Invalid literal value, expected ${JSON.stringify(issue.expected, util.jsonStringifyReplacer)}`;
500
+ message2 = `Invalid literal value, expected ${JSON.stringify(issue.expected, util.jsonStringifyReplacer)}`;
501
501
  break;
502
502
  case ZodIssueCode.unrecognized_keys:
503
- message = `Unrecognized key(s) in object: ${util.joinValues(issue.keys, ", ")}`;
503
+ message2 = `Unrecognized key(s) in object: ${util.joinValues(issue.keys, ", ")}`;
504
504
  break;
505
505
  case ZodIssueCode.invalid_union:
506
- message = `Invalid input`;
506
+ message2 = `Invalid input`;
507
507
  break;
508
508
  case ZodIssueCode.invalid_union_discriminator:
509
- message = `Invalid discriminator value. Expected ${util.joinValues(issue.options)}`;
509
+ message2 = `Invalid discriminator value. Expected ${util.joinValues(issue.options)}`;
510
510
  break;
511
511
  case ZodIssueCode.invalid_enum_value:
512
- message = `Invalid enum value. Expected ${util.joinValues(issue.options)}, received '${issue.received}'`;
512
+ message2 = `Invalid enum value. Expected ${util.joinValues(issue.options)}, received '${issue.received}'`;
513
513
  break;
514
514
  case ZodIssueCode.invalid_arguments:
515
- message = `Invalid function arguments`;
515
+ message2 = `Invalid function arguments`;
516
516
  break;
517
517
  case ZodIssueCode.invalid_return_type:
518
- message = `Invalid function return type`;
518
+ message2 = `Invalid function return type`;
519
519
  break;
520
520
  case ZodIssueCode.invalid_date:
521
- message = `Invalid date`;
521
+ message2 = `Invalid date`;
522
522
  break;
523
523
  case ZodIssueCode.invalid_string:
524
524
  if (typeof issue.validation === "object") {
525
525
  if ("includes" in issue.validation) {
526
- message = `Invalid input: must include "${issue.validation.includes}"`;
526
+ message2 = `Invalid input: must include "${issue.validation.includes}"`;
527
527
  if (typeof issue.validation.position === "number") {
528
- message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`;
528
+ message2 = `${message2} at one or more positions greater than or equal to ${issue.validation.position}`;
529
529
  }
530
530
  } else if ("startsWith" in issue.validation) {
531
- message = `Invalid input: must start with "${issue.validation.startsWith}"`;
531
+ message2 = `Invalid input: must start with "${issue.validation.startsWith}"`;
532
532
  } else if ("endsWith" in issue.validation) {
533
- message = `Invalid input: must end with "${issue.validation.endsWith}"`;
533
+ message2 = `Invalid input: must end with "${issue.validation.endsWith}"`;
534
534
  } else {
535
535
  util.assertNever(issue.validation);
536
536
  }
537
537
  } else if (issue.validation !== "regex") {
538
- message = `Invalid ${issue.validation}`;
538
+ message2 = `Invalid ${issue.validation}`;
539
539
  } else {
540
- message = "Invalid";
540
+ message2 = "Invalid";
541
541
  }
542
542
  break;
543
543
  case ZodIssueCode.too_small:
544
544
  if (issue.type === "array")
545
- message = `Array must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `more than`} ${issue.minimum} element(s)`;
545
+ message2 = `Array must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `more than`} ${issue.minimum} element(s)`;
546
546
  else if (issue.type === "string")
547
- message = `String must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`;
547
+ message2 = `String must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`;
548
548
  else if (issue.type === "number")
549
- message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
549
+ message2 = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
550
550
  else if (issue.type === "bigint")
551
- message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
551
+ message2 = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
552
552
  else if (issue.type === "date")
553
- message = `Date must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${new Date(Number(issue.minimum))}`;
553
+ message2 = `Date must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${new Date(Number(issue.minimum))}`;
554
554
  else
555
- message = "Invalid input";
555
+ message2 = "Invalid input";
556
556
  break;
557
557
  case ZodIssueCode.too_big:
558
558
  if (issue.type === "array")
559
- message = `Array must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `less than`} ${issue.maximum} element(s)`;
559
+ message2 = `Array must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `less than`} ${issue.maximum} element(s)`;
560
560
  else if (issue.type === "string")
561
- message = `String must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `under`} ${issue.maximum} character(s)`;
561
+ message2 = `String must contain ${issue.exact ? `exactly` : issue.inclusive ? `at most` : `under`} ${issue.maximum} character(s)`;
562
562
  else if (issue.type === "number")
563
- message = `Number must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;
563
+ message2 = `Number must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;
564
564
  else if (issue.type === "bigint")
565
- message = `BigInt must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;
565
+ message2 = `BigInt must be ${issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`} ${issue.maximum}`;
566
566
  else if (issue.type === "date")
567
- message = `Date must be ${issue.exact ? `exactly` : issue.inclusive ? `smaller than or equal to` : `smaller than`} ${new Date(Number(issue.maximum))}`;
567
+ message2 = `Date must be ${issue.exact ? `exactly` : issue.inclusive ? `smaller than or equal to` : `smaller than`} ${new Date(Number(issue.maximum))}`;
568
568
  else
569
- message = "Invalid input";
569
+ message2 = "Invalid input";
570
570
  break;
571
571
  case ZodIssueCode.custom:
572
- message = `Invalid input`;
572
+ message2 = `Invalid input`;
573
573
  break;
574
574
  case ZodIssueCode.invalid_intersection_types:
575
- message = `Intersection results could not be merged`;
575
+ message2 = `Intersection results could not be merged`;
576
576
  break;
577
577
  case ZodIssueCode.not_multiple_of:
578
- message = `Number must be a multiple of ${issue.multipleOf}`;
578
+ message2 = `Number must be a multiple of ${issue.multipleOf}`;
579
579
  break;
580
580
  case ZodIssueCode.not_finite:
581
- message = "Number must be finite";
581
+ message2 = "Number must be finite";
582
582
  break;
583
583
  default:
584
- message = _ctx.defaultError;
584
+ message2 = _ctx.defaultError;
585
585
  util.assertNever(issue);
586
586
  }
587
- return { message };
587
+ return { message: message2 };
588
588
  };
589
589
  var en_default = errorMap;
590
590
 
@@ -710,8 +710,8 @@ var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
710
710
  // ../../node_modules/.bun/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js
711
711
  var errorUtil;
712
712
  (function(errorUtil2) {
713
- errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {};
714
- errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message;
713
+ errorUtil2.errToObj = (message2) => typeof message2 === "string" ? { message: message2 } : message2 || {};
714
+ errorUtil2.toString = (message2) => typeof message2 === "string" ? message2 : message2?.message;
715
715
  })(errorUtil || (errorUtil = {}));
716
716
 
717
717
  // ../../node_modules/.bun/zod@3.25.76/node_modules/zod/v3/types.js
@@ -763,16 +763,16 @@ function processCreateParams(params) {
763
763
  if (errorMap2)
764
764
  return { errorMap: errorMap2, description };
765
765
  const customMap = (iss, ctx) => {
766
- const { message } = params;
766
+ const { message: message2 } = params;
767
767
  if (iss.code === "invalid_enum_value") {
768
- return { message: message ?? ctx.defaultError };
768
+ return { message: message2 ?? ctx.defaultError };
769
769
  }
770
770
  if (typeof ctx.data === "undefined") {
771
- return { message: message ?? required_error ?? ctx.defaultError };
771
+ return { message: message2 ?? required_error ?? ctx.defaultError };
772
772
  }
773
773
  if (iss.code !== "invalid_type")
774
774
  return { message: ctx.defaultError };
775
- return { message: message ?? invalid_type_error ?? ctx.defaultError };
775
+ return { message: message2 ?? invalid_type_error ?? ctx.defaultError };
776
776
  };
777
777
  return { errorMap: customMap, description };
778
778
  }
@@ -898,14 +898,14 @@ var ZodType = class {
898
898
  const result = await (isAsync(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult));
899
899
  return handleResult(ctx, result);
900
900
  }
901
- refine(check, message) {
901
+ refine(check, message2) {
902
902
  const getIssueProperties = (val) => {
903
- if (typeof message === "string" || typeof message === "undefined") {
904
- return { message };
905
- } else if (typeof message === "function") {
906
- return message(val);
903
+ if (typeof message2 === "string" || typeof message2 === "undefined") {
904
+ return { message: message2 };
905
+ } else if (typeof message2 === "function") {
906
+ return message2(val);
907
907
  } else {
908
- return message;
908
+ return message2;
909
909
  }
910
910
  };
911
911
  return this._refinement((val, ctx) => {
@@ -1441,11 +1441,11 @@ var ZodString = class _ZodString extends ZodType {
1441
1441
  }
1442
1442
  return { status: status.value, value: input.data };
1443
1443
  }
1444
- _regex(regex, validation, message) {
1444
+ _regex(regex, validation, message2) {
1445
1445
  return this.refinement((data) => regex.test(data), {
1446
1446
  validation,
1447
1447
  code: ZodIssueCode.invalid_string,
1448
- ...errorUtil.errToObj(message)
1448
+ ...errorUtil.errToObj(message2)
1449
1449
  });
1450
1450
  }
1451
1451
  _addCheck(check) {
@@ -1454,37 +1454,37 @@ var ZodString = class _ZodString extends ZodType {
1454
1454
  checks: [...this._def.checks, check]
1455
1455
  });
1456
1456
  }
1457
- email(message) {
1458
- return this._addCheck({ kind: "email", ...errorUtil.errToObj(message) });
1457
+ email(message2) {
1458
+ return this._addCheck({ kind: "email", ...errorUtil.errToObj(message2) });
1459
1459
  }
1460
- url(message) {
1461
- return this._addCheck({ kind: "url", ...errorUtil.errToObj(message) });
1460
+ url(message2) {
1461
+ return this._addCheck({ kind: "url", ...errorUtil.errToObj(message2) });
1462
1462
  }
1463
- emoji(message) {
1464
- return this._addCheck({ kind: "emoji", ...errorUtil.errToObj(message) });
1463
+ emoji(message2) {
1464
+ return this._addCheck({ kind: "emoji", ...errorUtil.errToObj(message2) });
1465
1465
  }
1466
- uuid(message) {
1467
- return this._addCheck({ kind: "uuid", ...errorUtil.errToObj(message) });
1466
+ uuid(message2) {
1467
+ return this._addCheck({ kind: "uuid", ...errorUtil.errToObj(message2) });
1468
1468
  }
1469
- nanoid(message) {
1470
- return this._addCheck({ kind: "nanoid", ...errorUtil.errToObj(message) });
1469
+ nanoid(message2) {
1470
+ return this._addCheck({ kind: "nanoid", ...errorUtil.errToObj(message2) });
1471
1471
  }
1472
- cuid(message) {
1473
- return this._addCheck({ kind: "cuid", ...errorUtil.errToObj(message) });
1472
+ cuid(message2) {
1473
+ return this._addCheck({ kind: "cuid", ...errorUtil.errToObj(message2) });
1474
1474
  }
1475
- cuid2(message) {
1476
- return this._addCheck({ kind: "cuid2", ...errorUtil.errToObj(message) });
1475
+ cuid2(message2) {
1476
+ return this._addCheck({ kind: "cuid2", ...errorUtil.errToObj(message2) });
1477
1477
  }
1478
- ulid(message) {
1479
- return this._addCheck({ kind: "ulid", ...errorUtil.errToObj(message) });
1478
+ ulid(message2) {
1479
+ return this._addCheck({ kind: "ulid", ...errorUtil.errToObj(message2) });
1480
1480
  }
1481
- base64(message) {
1482
- return this._addCheck({ kind: "base64", ...errorUtil.errToObj(message) });
1481
+ base64(message2) {
1482
+ return this._addCheck({ kind: "base64", ...errorUtil.errToObj(message2) });
1483
1483
  }
1484
- base64url(message) {
1484
+ base64url(message2) {
1485
1485
  return this._addCheck({
1486
1486
  kind: "base64url",
1487
- ...errorUtil.errToObj(message)
1487
+ ...errorUtil.errToObj(message2)
1488
1488
  });
1489
1489
  }
1490
1490
  jwt(options) {
@@ -1514,8 +1514,8 @@ var ZodString = class _ZodString extends ZodType {
1514
1514
  ...errorUtil.errToObj(options?.message)
1515
1515
  });
1516
1516
  }
1517
- date(message) {
1518
- return this._addCheck({ kind: "date", message });
1517
+ date(message2) {
1518
+ return this._addCheck({ kind: "date", message: message2 });
1519
1519
  }
1520
1520
  time(options) {
1521
1521
  if (typeof options === "string") {
@@ -1531,14 +1531,14 @@ var ZodString = class _ZodString extends ZodType {
1531
1531
  ...errorUtil.errToObj(options?.message)
1532
1532
  });
1533
1533
  }
1534
- duration(message) {
1535
- return this._addCheck({ kind: "duration", ...errorUtil.errToObj(message) });
1534
+ duration(message2) {
1535
+ return this._addCheck({ kind: "duration", ...errorUtil.errToObj(message2) });
1536
1536
  }
1537
- regex(regex, message) {
1537
+ regex(regex, message2) {
1538
1538
  return this._addCheck({
1539
1539
  kind: "regex",
1540
1540
  regex,
1541
- ...errorUtil.errToObj(message)
1541
+ ...errorUtil.errToObj(message2)
1542
1542
  });
1543
1543
  }
1544
1544
  includes(value, options) {
@@ -1549,46 +1549,46 @@ var ZodString = class _ZodString extends ZodType {
1549
1549
  ...errorUtil.errToObj(options?.message)
1550
1550
  });
1551
1551
  }
1552
- startsWith(value, message) {
1552
+ startsWith(value, message2) {
1553
1553
  return this._addCheck({
1554
1554
  kind: "startsWith",
1555
1555
  value,
1556
- ...errorUtil.errToObj(message)
1556
+ ...errorUtil.errToObj(message2)
1557
1557
  });
1558
1558
  }
1559
- endsWith(value, message) {
1559
+ endsWith(value, message2) {
1560
1560
  return this._addCheck({
1561
1561
  kind: "endsWith",
1562
1562
  value,
1563
- ...errorUtil.errToObj(message)
1563
+ ...errorUtil.errToObj(message2)
1564
1564
  });
1565
1565
  }
1566
- min(minLength, message) {
1566
+ min(minLength, message2) {
1567
1567
  return this._addCheck({
1568
1568
  kind: "min",
1569
1569
  value: minLength,
1570
- ...errorUtil.errToObj(message)
1570
+ ...errorUtil.errToObj(message2)
1571
1571
  });
1572
1572
  }
1573
- max(maxLength, message) {
1573
+ max(maxLength, message2) {
1574
1574
  return this._addCheck({
1575
1575
  kind: "max",
1576
1576
  value: maxLength,
1577
- ...errorUtil.errToObj(message)
1577
+ ...errorUtil.errToObj(message2)
1578
1578
  });
1579
1579
  }
1580
- length(len, message) {
1580
+ length(len, message2) {
1581
1581
  return this._addCheck({
1582
1582
  kind: "length",
1583
1583
  value: len,
1584
- ...errorUtil.errToObj(message)
1584
+ ...errorUtil.errToObj(message2)
1585
1585
  });
1586
1586
  }
1587
1587
  /**
1588
1588
  * Equivalent to `.min(1)`
1589
1589
  */
1590
- nonempty(message) {
1591
- return this.min(1, errorUtil.errToObj(message));
1590
+ nonempty(message2) {
1591
+ return this.min(1, errorUtil.errToObj(message2));
1592
1592
  }
1593
1593
  trim() {
1594
1594
  return new _ZodString({
@@ -1781,19 +1781,19 @@ var ZodNumber = class _ZodNumber extends ZodType {
1781
1781
  }
1782
1782
  return { status: status.value, value: input.data };
1783
1783
  }
1784
- gte(value, message) {
1785
- return this.setLimit("min", value, true, errorUtil.toString(message));
1784
+ gte(value, message2) {
1785
+ return this.setLimit("min", value, true, errorUtil.toString(message2));
1786
1786
  }
1787
- gt(value, message) {
1788
- return this.setLimit("min", value, false, errorUtil.toString(message));
1787
+ gt(value, message2) {
1788
+ return this.setLimit("min", value, false, errorUtil.toString(message2));
1789
1789
  }
1790
- lte(value, message) {
1791
- return this.setLimit("max", value, true, errorUtil.toString(message));
1790
+ lte(value, message2) {
1791
+ return this.setLimit("max", value, true, errorUtil.toString(message2));
1792
1792
  }
1793
- lt(value, message) {
1794
- return this.setLimit("max", value, false, errorUtil.toString(message));
1793
+ lt(value, message2) {
1794
+ return this.setLimit("max", value, false, errorUtil.toString(message2));
1795
1795
  }
1796
- setLimit(kind, value, inclusive, message) {
1796
+ setLimit(kind, value, inclusive, message2) {
1797
1797
  return new _ZodNumber({
1798
1798
  ...this._def,
1799
1799
  checks: [
@@ -1802,7 +1802,7 @@ var ZodNumber = class _ZodNumber extends ZodType {
1802
1802
  kind,
1803
1803
  value,
1804
1804
  inclusive,
1805
- message: errorUtil.toString(message)
1805
+ message: errorUtil.toString(message2)
1806
1806
  }
1807
1807
  ]
1808
1808
  });
@@ -1813,68 +1813,68 @@ var ZodNumber = class _ZodNumber extends ZodType {
1813
1813
  checks: [...this._def.checks, check]
1814
1814
  });
1815
1815
  }
1816
- int(message) {
1816
+ int(message2) {
1817
1817
  return this._addCheck({
1818
1818
  kind: "int",
1819
- message: errorUtil.toString(message)
1819
+ message: errorUtil.toString(message2)
1820
1820
  });
1821
1821
  }
1822
- positive(message) {
1822
+ positive(message2) {
1823
1823
  return this._addCheck({
1824
1824
  kind: "min",
1825
1825
  value: 0,
1826
1826
  inclusive: false,
1827
- message: errorUtil.toString(message)
1827
+ message: errorUtil.toString(message2)
1828
1828
  });
1829
1829
  }
1830
- negative(message) {
1830
+ negative(message2) {
1831
1831
  return this._addCheck({
1832
1832
  kind: "max",
1833
1833
  value: 0,
1834
1834
  inclusive: false,
1835
- message: errorUtil.toString(message)
1835
+ message: errorUtil.toString(message2)
1836
1836
  });
1837
1837
  }
1838
- nonpositive(message) {
1838
+ nonpositive(message2) {
1839
1839
  return this._addCheck({
1840
1840
  kind: "max",
1841
1841
  value: 0,
1842
1842
  inclusive: true,
1843
- message: errorUtil.toString(message)
1843
+ message: errorUtil.toString(message2)
1844
1844
  });
1845
1845
  }
1846
- nonnegative(message) {
1846
+ nonnegative(message2) {
1847
1847
  return this._addCheck({
1848
1848
  kind: "min",
1849
1849
  value: 0,
1850
1850
  inclusive: true,
1851
- message: errorUtil.toString(message)
1851
+ message: errorUtil.toString(message2)
1852
1852
  });
1853
1853
  }
1854
- multipleOf(value, message) {
1854
+ multipleOf(value, message2) {
1855
1855
  return this._addCheck({
1856
1856
  kind: "multipleOf",
1857
1857
  value,
1858
- message: errorUtil.toString(message)
1858
+ message: errorUtil.toString(message2)
1859
1859
  });
1860
1860
  }
1861
- finite(message) {
1861
+ finite(message2) {
1862
1862
  return this._addCheck({
1863
1863
  kind: "finite",
1864
- message: errorUtil.toString(message)
1864
+ message: errorUtil.toString(message2)
1865
1865
  });
1866
1866
  }
1867
- safe(message) {
1867
+ safe(message2) {
1868
1868
  return this._addCheck({
1869
1869
  kind: "min",
1870
1870
  inclusive: true,
1871
1871
  value: Number.MIN_SAFE_INTEGER,
1872
- message: errorUtil.toString(message)
1872
+ message: errorUtil.toString(message2)
1873
1873
  })._addCheck({
1874
1874
  kind: "max",
1875
1875
  inclusive: true,
1876
1876
  value: Number.MAX_SAFE_INTEGER,
1877
- message: errorUtil.toString(message)
1877
+ message: errorUtil.toString(message2)
1878
1878
  });
1879
1879
  }
1880
1880
  get minValue() {
@@ -1997,19 +1997,19 @@ var ZodBigInt = class _ZodBigInt extends ZodType {
1997
1997
  });
1998
1998
  return INVALID;
1999
1999
  }
2000
- gte(value, message) {
2001
- return this.setLimit("min", value, true, errorUtil.toString(message));
2000
+ gte(value, message2) {
2001
+ return this.setLimit("min", value, true, errorUtil.toString(message2));
2002
2002
  }
2003
- gt(value, message) {
2004
- return this.setLimit("min", value, false, errorUtil.toString(message));
2003
+ gt(value, message2) {
2004
+ return this.setLimit("min", value, false, errorUtil.toString(message2));
2005
2005
  }
2006
- lte(value, message) {
2007
- return this.setLimit("max", value, true, errorUtil.toString(message));
2006
+ lte(value, message2) {
2007
+ return this.setLimit("max", value, true, errorUtil.toString(message2));
2008
2008
  }
2009
- lt(value, message) {
2010
- return this.setLimit("max", value, false, errorUtil.toString(message));
2009
+ lt(value, message2) {
2010
+ return this.setLimit("max", value, false, errorUtil.toString(message2));
2011
2011
  }
2012
- setLimit(kind, value, inclusive, message) {
2012
+ setLimit(kind, value, inclusive, message2) {
2013
2013
  return new _ZodBigInt({
2014
2014
  ...this._def,
2015
2015
  checks: [
@@ -2018,7 +2018,7 @@ var ZodBigInt = class _ZodBigInt extends ZodType {
2018
2018
  kind,
2019
2019
  value,
2020
2020
  inclusive,
2021
- message: errorUtil.toString(message)
2021
+ message: errorUtil.toString(message2)
2022
2022
  }
2023
2023
  ]
2024
2024
  });
@@ -2029,43 +2029,43 @@ var ZodBigInt = class _ZodBigInt extends ZodType {
2029
2029
  checks: [...this._def.checks, check]
2030
2030
  });
2031
2031
  }
2032
- positive(message) {
2032
+ positive(message2) {
2033
2033
  return this._addCheck({
2034
2034
  kind: "min",
2035
2035
  value: BigInt(0),
2036
2036
  inclusive: false,
2037
- message: errorUtil.toString(message)
2037
+ message: errorUtil.toString(message2)
2038
2038
  });
2039
2039
  }
2040
- negative(message) {
2040
+ negative(message2) {
2041
2041
  return this._addCheck({
2042
2042
  kind: "max",
2043
2043
  value: BigInt(0),
2044
2044
  inclusive: false,
2045
- message: errorUtil.toString(message)
2045
+ message: errorUtil.toString(message2)
2046
2046
  });
2047
2047
  }
2048
- nonpositive(message) {
2048
+ nonpositive(message2) {
2049
2049
  return this._addCheck({
2050
2050
  kind: "max",
2051
2051
  value: BigInt(0),
2052
2052
  inclusive: true,
2053
- message: errorUtil.toString(message)
2053
+ message: errorUtil.toString(message2)
2054
2054
  });
2055
2055
  }
2056
- nonnegative(message) {
2056
+ nonnegative(message2) {
2057
2057
  return this._addCheck({
2058
2058
  kind: "min",
2059
2059
  value: BigInt(0),
2060
2060
  inclusive: true,
2061
- message: errorUtil.toString(message)
2061
+ message: errorUtil.toString(message2)
2062
2062
  });
2063
2063
  }
2064
- multipleOf(value, message) {
2064
+ multipleOf(value, message2) {
2065
2065
  return this._addCheck({
2066
2066
  kind: "multipleOf",
2067
2067
  value,
2068
- message: errorUtil.toString(message)
2068
+ message: errorUtil.toString(message2)
2069
2069
  });
2070
2070
  }
2071
2071
  get minValue() {
@@ -2188,18 +2188,18 @@ var ZodDate = class _ZodDate extends ZodType {
2188
2188
  checks: [...this._def.checks, check]
2189
2189
  });
2190
2190
  }
2191
- min(minDate, message) {
2191
+ min(minDate, message2) {
2192
2192
  return this._addCheck({
2193
2193
  kind: "min",
2194
2194
  value: minDate.getTime(),
2195
- message: errorUtil.toString(message)
2195
+ message: errorUtil.toString(message2)
2196
2196
  });
2197
2197
  }
2198
- max(maxDate, message) {
2198
+ max(maxDate, message2) {
2199
2199
  return this._addCheck({
2200
2200
  kind: "max",
2201
2201
  value: maxDate.getTime(),
2202
- message: errorUtil.toString(message)
2202
+ message: errorUtil.toString(message2)
2203
2203
  });
2204
2204
  }
2205
2205
  get minDate() {
@@ -2431,26 +2431,26 @@ var ZodArray = class _ZodArray extends ZodType {
2431
2431
  get element() {
2432
2432
  return this._def.type;
2433
2433
  }
2434
- min(minLength, message) {
2434
+ min(minLength, message2) {
2435
2435
  return new _ZodArray({
2436
2436
  ...this._def,
2437
- minLength: { value: minLength, message: errorUtil.toString(message) }
2437
+ minLength: { value: minLength, message: errorUtil.toString(message2) }
2438
2438
  });
2439
2439
  }
2440
- max(maxLength, message) {
2440
+ max(maxLength, message2) {
2441
2441
  return new _ZodArray({
2442
2442
  ...this._def,
2443
- maxLength: { value: maxLength, message: errorUtil.toString(message) }
2443
+ maxLength: { value: maxLength, message: errorUtil.toString(message2) }
2444
2444
  });
2445
2445
  }
2446
- length(len, message) {
2446
+ length(len, message2) {
2447
2447
  return new _ZodArray({
2448
2448
  ...this._def,
2449
- exactLength: { value: len, message: errorUtil.toString(message) }
2449
+ exactLength: { value: len, message: errorUtil.toString(message2) }
2450
2450
  });
2451
2451
  }
2452
- nonempty(message) {
2453
- return this.min(1, message);
2452
+ nonempty(message2) {
2453
+ return this.min(1, message2);
2454
2454
  }
2455
2455
  };
2456
2456
  ZodArray.create = (schema, params) => {
@@ -2593,17 +2593,17 @@ var ZodObject = class _ZodObject extends ZodType {
2593
2593
  get shape() {
2594
2594
  return this._def.shape();
2595
2595
  }
2596
- strict(message) {
2596
+ strict(message2) {
2597
2597
  errorUtil.errToObj;
2598
2598
  return new _ZodObject({
2599
2599
  ...this._def,
2600
2600
  unknownKeys: "strict",
2601
- ...message !== void 0 ? {
2601
+ ...message2 !== void 0 ? {
2602
2602
  errorMap: (issue, ctx) => {
2603
2603
  const defaultError = this._def.errorMap?.(issue, ctx).message ?? ctx.defaultError;
2604
2604
  if (issue.code === "unrecognized_keys")
2605
2605
  return {
2606
- message: errorUtil.errToObj(message).message ?? defaultError
2606
+ message: errorUtil.errToObj(message2).message ?? defaultError
2607
2607
  };
2608
2608
  return {
2609
2609
  message: defaultError
@@ -3359,23 +3359,23 @@ var ZodSet = class _ZodSet extends ZodType {
3359
3359
  return finalizeSet(elements);
3360
3360
  }
3361
3361
  }
3362
- min(minSize, message) {
3362
+ min(minSize, message2) {
3363
3363
  return new _ZodSet({
3364
3364
  ...this._def,
3365
- minSize: { value: minSize, message: errorUtil.toString(message) }
3365
+ minSize: { value: minSize, message: errorUtil.toString(message2) }
3366
3366
  });
3367
3367
  }
3368
- max(maxSize, message) {
3368
+ max(maxSize, message2) {
3369
3369
  return new _ZodSet({
3370
3370
  ...this._def,
3371
- maxSize: { value: maxSize, message: errorUtil.toString(message) }
3371
+ maxSize: { value: maxSize, message: errorUtil.toString(message2) }
3372
3372
  });
3373
3373
  }
3374
- size(size, message) {
3375
- return this.min(size, message).max(size, message);
3374
+ size(size, message2) {
3375
+ return this.min(size, message2).max(size, message2);
3376
3376
  }
3377
- nonempty(message) {
3378
- return this.min(1, message);
3377
+ nonempty(message2) {
3378
+ return this.min(1, message2);
3379
3379
  }
3380
3380
  };
3381
3381
  ZodSet.create = (valueType, params) => {
@@ -4162,7 +4162,7 @@ var coerce = {
4162
4162
  };
4163
4163
  var NEVER = INVALID;
4164
4164
 
4165
- // ../shared/dist/chunk-BH4SLNGU.js
4165
+ // ../shared/dist/chunk-VSUBG7GR.js
4166
4166
  var DEFAULT_SONNET_MODEL = "claude-sonnet-5-5";
4167
4167
  var DEFAULT_OPUS_MODEL = "claude-opus-5-5";
4168
4168
  var DEFAULT_HAIKU_MODEL = "claude-haiku-4-5-20251001";
@@ -4780,7 +4780,8 @@ var DiscoveredPortSchema = external_exports.object({
4780
4780
  port: external_exports.number().int().min(1).max(65535),
4781
4781
  label: external_exports.string().min(1).max(64).optional(),
4782
4782
  protocol: external_exports.enum(["http", "tcp"]).optional(),
4783
- detectedAt: external_exports.string()
4783
+ detectedAt: external_exports.string(),
4784
+ hidden: external_exports.boolean().optional()
4784
4785
  });
4785
4786
  var ReportDiscoveredPortsRequestSchema = external_exports.object({
4786
4787
  sessionId: external_exports.string(),
@@ -4927,7 +4928,11 @@ var SubmitCodeReviewResultRequestSchema = external_exports.object({
4927
4928
  var CycleCodingAgentKeyRequestSchema = external_exports.object({
4928
4929
  sessionId: external_exports.string(),
4929
4930
  rateLimitType: external_exports.string(),
4930
- resetsAt: external_exports.string().optional()
4931
+ resetsAt: external_exports.string().optional(),
4932
+ // The key the pod is actually running (CONVEYOR_CODING_AGENT_KEY_ID). Wins
4933
+ // over the session's attribution stamp after owner validation; optional so
4934
+ // older agents keep the session fallback.
4935
+ codingAgentKeyId: external_exports.string().optional()
4931
4936
  });
4932
4937
  var PostChildChatMessageRequestSchema = external_exports.object({
4933
4938
  sessionId: external_exports.string(),
@@ -5341,11 +5346,12 @@ var QueryProjectGcpLogsRequestSchema = external_exports.object({
5341
5346
  sqlInstances: external_exports.array(external_exports.string().min(1).max(200)).max(25).optional(),
5342
5347
  allServices: external_exports.boolean().optional(),
5343
5348
  search: external_exports.string().max(256).optional(),
5344
- filter: external_exports.string().max(1e3).optional(),
5349
+ filter: external_exports.string().max(2e3).optional(),
5345
5350
  startTime: external_exports.string().optional(),
5346
5351
  endTime: external_exports.string().optional(),
5347
5352
  limit: external_exports.number().int().min(1).max(200).optional().default(50),
5348
- pageToken: external_exports.string().max(4096).optional()
5353
+ pageToken: external_exports.string().max(4096).optional(),
5354
+ full: external_exports.boolean().optional()
5349
5355
  });
5350
5356
  var QueryProjectGrafanaLogsRequestSchema = external_exports.object({
5351
5357
  projectId: external_exports.string(),
@@ -6290,6 +6296,7 @@ var BAKE_COMPONENT_LABEL = "claudespace.rallycry.com/component";
6290
6296
  var BAKE_COMPONENT_PREBAKE = "prebake";
6291
6297
  var BAKE_COMPONENT_STATE_BAKE = "state-bake";
6292
6298
  var BAKE_COMPONENT_VALUES = [BAKE_COMPONENT_PREBAKE, BAKE_COMPONENT_STATE_BAKE];
6299
+ var PERSONAL_BAKE_NAMESPACE = "conveyor-bakes";
6293
6300
  var MS_PER_DAY = 24 * 60 * 60 * 1e3;
6294
6301
  var POSTGRES_ENV = {
6295
6302
  POSTGRES_HOST_AUTH_METHOD: "trust",
@@ -6608,6 +6615,8 @@ var REPORT_CARD_TYPES = surfaceTypes("report");
6608
6615
  var DECISION_CARD_TYPES = surfaceTypes("decision");
6609
6616
 
6610
6617
  // src/daemon/connection.ts
6618
+ var REDIAL_FIRST_MS = 5e3;
6619
+ var REDIAL_MAX_MS = 5 * 6e4;
6611
6620
  function unwrap(ack, what) {
6612
6621
  if (!ack?.ok || ack.data === void 0) {
6613
6622
  throw new Error(`${what} failed: ${ack?.error ?? "no response"}`);
@@ -6617,6 +6626,8 @@ function unwrap(ack, what) {
6617
6626
  var ClusterConnection = class {
6618
6627
  socket = null;
6619
6628
  config;
6629
+ redialDelayMs = REDIAL_FIRST_MS;
6630
+ redialTimer = null;
6620
6631
  /** Called when Conveyor says the desired state changed. */
6621
6632
  onSyncRequested = null;
6622
6633
  /** Called when Conveyor asks the machine to remove itself. */
@@ -6652,6 +6663,7 @@ var ClusterConnection = class {
6652
6663
  });
6653
6664
  this.socket = socket;
6654
6665
  socket.on("connect", () => {
6666
+ this.redialDelayMs = REDIAL_FIRST_MS;
6655
6667
  if (!settled) {
6656
6668
  settled = true;
6657
6669
  resolve();
@@ -6670,6 +6682,9 @@ var ClusterConnection = class {
6670
6682
  socket.on("disconnect", (reason) => {
6671
6683
  process.stderr.write(`[conveyor-k3] disconnected: ${reason}
6672
6684
  `);
6685
+ if (reason === "io server disconnect" && this.config.reconnectWhenReplaced) {
6686
+ this.redial(socket);
6687
+ }
6673
6688
  });
6674
6689
  socket.on(PERSONAL_CLUSTER_EVENTS.syncRequested, () => {
6675
6690
  this.onSyncRequested?.();
@@ -6731,7 +6746,20 @@ var ClusterConnection = class {
6731
6746
  } catch {
6732
6747
  }
6733
6748
  }
6749
+ /** Dial again after the server closed the socket, waiting longer each time. */
6750
+ redial(socket) {
6751
+ if (this.redialTimer) return;
6752
+ const delay = this.redialDelayMs;
6753
+ this.redialDelayMs = Math.min(delay * 2, REDIAL_MAX_MS);
6754
+ this.redialTimer = setTimeout(() => {
6755
+ this.redialTimer = null;
6756
+ if (this.socket === socket && !socket.connected) socket.connect();
6757
+ }, delay);
6758
+ this.redialTimer.unref?.();
6759
+ }
6734
6760
  disconnect() {
6761
+ if (this.redialTimer) clearTimeout(this.redialTimer);
6762
+ this.redialTimer = null;
6735
6763
  this.socket?.disconnect();
6736
6764
  this.socket = null;
6737
6765
  }
@@ -7147,6 +7175,9 @@ async function writeState(fs, state) {
7147
7175
  await fs.writeFile(STATE_FILE, `${JSON.stringify(state, null, 2)}
7148
7176
  `, 384);
7149
7177
  }
7178
+ function managesK3s(desired, state) {
7179
+ return desired.isolation === void 0 || state.k3sInstalledByConveyor === true;
7180
+ }
7150
7181
 
7151
7182
  // src/lib/k3s-config.ts
7152
7183
  var IMAGE_GC_HIGH = "image-gc-high-threshold";
@@ -7160,6 +7191,15 @@ var K3S_INSTALL_EXEC = [
7160
7191
  `--${WRITE_KUBECONFIG_MODE}`,
7161
7192
  KUBECONFIG_MODE
7162
7193
  ].join(" ");
7194
+ function bareToken(token) {
7195
+ let bare = token.trim();
7196
+ if (bare.endsWith("\\")) bare = bare.slice(0, -1).trim();
7197
+ const quote = bare[0];
7198
+ if (bare.length >= 2 && (quote === "'" || quote === '"') && bare.endsWith(quote)) {
7199
+ bare = bare.slice(1, -1);
7200
+ }
7201
+ return bare;
7202
+ }
7163
7203
  function ownerConfiguredKubeletFlags(ownerConfig) {
7164
7204
  const found = /* @__PURE__ */ new Set();
7165
7205
  if (!ownerConfig) return found;
@@ -7185,7 +7225,7 @@ function ownerImageGcHighThreshold(ownerConfig) {
7185
7225
  const value = Number.parseInt(match[2] ?? "", 10);
7186
7226
  return Number.isInteger(value) && value >= 0 && value <= 100 ? value : null;
7187
7227
  }
7188
- function renderK3sDropIn(kubelet, ownerConfig) {
7228
+ function renderK3sDropIn(kubelet, ownerConfig, options = {}) {
7189
7229
  const ownerFlags = ownerConfiguredKubeletFlags(ownerConfig);
7190
7230
  const ownerKeys = ownerConfiguredKeys(ownerConfig);
7191
7231
  const args = [];
@@ -7209,8 +7249,10 @@ function renderK3sDropIn(kubelet, ownerConfig) {
7209
7249
  "# Your own /etc/rancher/k3s/config.yaml is never modified; k3s merges both.",
7210
7250
  "# `kubelet-arg+` and `disable+` append rather than replacing a list you set."
7211
7251
  ];
7212
- lines2.push("disable+:");
7213
- for (const component of K3S_DISABLED_COMPONENTS) lines2.push(` - ${component}`);
7252
+ if (options.disableComponents !== false) {
7253
+ lines2.push("disable+:");
7254
+ for (const component of K3S_DISABLED_COMPONENTS) lines2.push(` - ${component}`);
7255
+ }
7214
7256
  if (ownerKeys.has(WRITE_KUBECONFIG_MODE)) {
7215
7257
  skipped.push(WRITE_KUBECONFIG_MODE);
7216
7258
  } else {
@@ -7640,6 +7682,231 @@ async function loadRegistryMirror(ctx) {
7640
7682
  return { restarted: true, warning: null };
7641
7683
  }
7642
7684
 
7685
+ // src/lib/isolation.ts
7686
+ var EGRESS_POLICY_NAME = "conveyor-k3-egress";
7687
+ var MANAGED_BY2 = { "app.kubernetes.io/managed-by": "conveyor-k3" };
7688
+ var NON_ROUTABLE_IPV4 = [
7689
+ "0.0.0.0/8",
7690
+ "10.0.0.0/8",
7691
+ "100.64.0.0/10",
7692
+ "127.0.0.0/8",
7693
+ "169.254.0.0/16",
7694
+ "172.16.0.0/12",
7695
+ "192.0.0.0/24",
7696
+ "192.0.2.0/24",
7697
+ "192.88.99.0/24",
7698
+ "192.168.0.0/16",
7699
+ "198.18.0.0/15",
7700
+ "198.51.100.0/24",
7701
+ "203.0.113.0/24",
7702
+ "224.0.0.0/4",
7703
+ "240.0.0.0/4"
7704
+ ];
7705
+ var KUBE_DNS = { namespace: "kube-system", labels: { "k8s-app": "kube-dns" } };
7706
+ var PSA_PREFIX = "pod-security.kubernetes.io";
7707
+ function psaLabels(level) {
7708
+ const advisory = level === "baseline" ? "restricted" : level;
7709
+ return {
7710
+ [`${PSA_PREFIX}/enforce`]: level,
7711
+ [`${PSA_PREFIX}/warn`]: advisory,
7712
+ [`${PSA_PREFIX}/audit`]: advisory
7713
+ };
7714
+ }
7715
+ var PSA_LABEL_KEYS = Object.keys(psaLabels("baseline"));
7716
+ function ipv4Value(address) {
7717
+ const parts = address.split(".");
7718
+ if (parts.length !== 4) return null;
7719
+ let value = 0;
7720
+ for (const part of parts) {
7721
+ if (!/^\d{1,3}$/.test(part)) return null;
7722
+ const octet = Number(part);
7723
+ if (octet > 255) return null;
7724
+ value = value * 256 + octet;
7725
+ }
7726
+ return value;
7727
+ }
7728
+ function inNonRoutableRange(address) {
7729
+ const value = ipv4Value(address);
7730
+ if (value === null) return false;
7731
+ return NON_ROUTABLE_IPV4.some((cidr) => {
7732
+ const [base = "", bits = "32"] = cidr.split("/");
7733
+ const start = ipv4Value(base) ?? 0;
7734
+ return value >= start && value < start + 2 ** (32 - Number(bits));
7735
+ });
7736
+ }
7737
+ function hostAddressExceptions(addresses) {
7738
+ const kept = /* @__PURE__ */ new Set();
7739
+ for (const raw of addresses) {
7740
+ const address = raw.trim();
7741
+ if (ipv4Value(address) === null || inNonRoutableRange(address)) continue;
7742
+ kept.add(`${address}/32`);
7743
+ }
7744
+ return [...kept].sort();
7745
+ }
7746
+ function renderEgressNetworkPolicy(namespace, hostAddresses) {
7747
+ const policy = {
7748
+ apiVersion: "networking.k8s.io/v1",
7749
+ kind: "NetworkPolicy",
7750
+ metadata: {
7751
+ name: EGRESS_POLICY_NAME,
7752
+ namespace: assertK8sName(namespace, "namespace"),
7753
+ labels: MANAGED_BY2
7754
+ },
7755
+ spec: {
7756
+ podSelector: {},
7757
+ policyTypes: ["Egress"],
7758
+ egress: [
7759
+ {
7760
+ to: [
7761
+ {
7762
+ namespaceSelector: {
7763
+ matchLabels: { "kubernetes.io/metadata.name": KUBE_DNS.namespace }
7764
+ },
7765
+ podSelector: { matchLabels: KUBE_DNS.labels }
7766
+ }
7767
+ ],
7768
+ ports: [
7769
+ { protocol: "UDP", port: 53 },
7770
+ { protocol: "TCP", port: 53 }
7771
+ ]
7772
+ },
7773
+ {
7774
+ // kube-router enforces after the Service's DNAT, so the registry is
7775
+ // reached by its pods' labels, never by the service range.
7776
+ to: [
7777
+ {
7778
+ namespaceSelector: {
7779
+ matchLabels: { "kubernetes.io/metadata.name": PERSONAL_LOCAL_REGISTRY_NAMESPACE }
7780
+ },
7781
+ podSelector: { matchLabels: LOCAL_REGISTRY_SELECTOR }
7782
+ }
7783
+ ],
7784
+ ports: [{ protocol: "TCP", port: PERSONAL_LOCAL_REGISTRY_PORT }]
7785
+ },
7786
+ {
7787
+ to: [
7788
+ {
7789
+ ipBlock: {
7790
+ cidr: "0.0.0.0/0",
7791
+ except: [...NON_ROUTABLE_IPV4, ...hostAddressExceptions(hostAddresses)]
7792
+ }
7793
+ }
7794
+ ]
7795
+ }
7796
+ ]
7797
+ }
7798
+ };
7799
+ return `${JSON.stringify(policy, null, 2)}
7800
+ `;
7801
+ }
7802
+ var DISABLE_KEY = /(?:^|[\s{,])(["']?)disable-network-policy\1\s*:([^,}]*)/g;
7803
+ var DISABLE_FLAGS = /* @__PURE__ */ new Set(["--disable-network-policy", "-disable-network-policy"]);
7804
+ var FALSE_VALUES = /* @__PURE__ */ new Set(["false", "no", "off", "n", "f", "0"]);
7805
+ function setsTrue(raw) {
7806
+ const value = bareToken(raw).trim().toLowerCase();
7807
+ return !FALSE_VALUES.has(value);
7808
+ }
7809
+ function uncommented(line) {
7810
+ return /^\s*#/.test(line) ? "" : line.replace(/\s#.*$/, "");
7811
+ }
7812
+ function configSetsKey(text) {
7813
+ return text.split("\n").map(uncommented).some((line) => [...line.matchAll(DISABLE_KEY)].some((match) => setsTrue(match[2] ?? "")));
7814
+ }
7815
+ function unitLines(unitText) {
7816
+ const lines2 = [];
7817
+ let pending = "";
7818
+ for (const raw of unitText.split("\n")) {
7819
+ const line = raw.trimEnd();
7820
+ if (/^\s*[#;]/.test(line)) continue;
7821
+ if (line.endsWith("\\")) {
7822
+ pending += `${line.slice(0, -1)} `;
7823
+ continue;
7824
+ }
7825
+ lines2.push(pending + line);
7826
+ pending = "";
7827
+ }
7828
+ return pending ? [...lines2, pending] : lines2;
7829
+ }
7830
+ function flagSetIn(line) {
7831
+ return line.split(/\s+/).some((raw) => {
7832
+ const token = bareToken(raw).replace(/^["']+|["']+$/g, "");
7833
+ const [name = "", ...value] = token.split("=");
7834
+ return DISABLE_FLAGS.has(name) && (value.length === 0 || setsTrue(value.join("=")));
7835
+ });
7836
+ }
7837
+ function networkPolicyControllerDisabled(sources) {
7838
+ if (sources.configs.some((text) => text !== null && configSetsKey(text))) return true;
7839
+ return unitLines(sources.unitText).some(flagSetIn);
7840
+ }
7841
+
7842
+ // src/daemon/isolation-probes.ts
7843
+ var CONTROLLER_DISABLED_WARNING = "k3s runs with its network policy controller disabled, so the egress policy Conveyor applies here is not enforced. Remove disable-network-policy from the k3s config or unit and restart k3s. Until then this server is not isolated; Conveyor checks again within 10 minutes.";
7844
+ var CONTROLLER_UNKNOWN_WARNING = "Could not read the k3s unit or its config files to check that its network policy controller is on, so this server does not count as isolated. Check `systemctl cat k3s.service` and /etc/rancher/k3s; Conveyor checks again within 10 minutes.";
7845
+ var NODE_ADDRESSES_JSONPATH = '{range .items[*]}{range .status.addresses[?(@.type=="InternalIP")]}{.address}{"\\n"}{end}{range .status.addresses[?(@.type=="ExternalIP")]}{.address}{"\\n"}{end}{end}';
7846
+ var API_ENDPOINTS_JSONPATH = "{.items[*].endpoints[*].addresses[*]}";
7847
+ var IPV4_ON_INTERFACE = /\binet (\d{1,3}(?:\.\d{1,3}){3})(?:\/| peer )/g;
7848
+ async function stdoutOf(exec, bin, args) {
7849
+ const run = await exec(bin, args, { timeoutMs: 1e4 }).catch(() => null);
7850
+ return run && run.exitCode === 0 ? run.stdout : null;
7851
+ }
7852
+ async function readK3sConfigs(ctx) {
7853
+ const listed = await stdoutOf(ctx.exec, "find", [
7854
+ "-L",
7855
+ K3S_CONFIG_DROPIN_DIR,
7856
+ "-maxdepth",
7857
+ "1",
7858
+ "-type",
7859
+ "f",
7860
+ "(",
7861
+ "-iname",
7862
+ "*.yaml",
7863
+ "-o",
7864
+ "-iname",
7865
+ "*.yml",
7866
+ ")"
7867
+ ]);
7868
+ if (listed === null) return null;
7869
+ const paths = listed.split("\n").map((path) => path.trim()).filter(Boolean).sort();
7870
+ const dropIns = await Promise.all(paths.map((path) => ctx.fs.readFile(path)));
7871
+ if (dropIns.some((text) => text === null)) return null;
7872
+ return [await ctx.fs.readFile(K3S_OWNER_CONFIG), ...dropIns];
7873
+ }
7874
+ async function controllerProblem(ctx) {
7875
+ const unitText = await stdoutOf(ctx.exec, "systemctl", ["cat", "k3s.service"]);
7876
+ const configs = unitText === null ? null : await readK3sConfigs(ctx);
7877
+ if (unitText === null || configs === null) return CONTROLLER_UNKNOWN_WARNING;
7878
+ return networkPolicyControllerDisabled({ configs, unitText }) ? CONTROLLER_DISABLED_WARNING : null;
7879
+ }
7880
+ async function readHostAddresses(exec) {
7881
+ const nodes = await stdoutOf(exec, "k3s", [
7882
+ "kubectl",
7883
+ "get",
7884
+ "nodes",
7885
+ "-o",
7886
+ `jsonpath=${NODE_ADDRESSES_JSONPATH}`
7887
+ ]);
7888
+ const interfaces = await stdoutOf(exec, "ip", ["-o", "-4", "addr", "show"]);
7889
+ const api = await stdoutOf(exec, "k3s", [
7890
+ "kubectl",
7891
+ "get",
7892
+ "endpointslices",
7893
+ "-n",
7894
+ "default",
7895
+ "-l",
7896
+ "kubernetes.io/service-name=kubernetes",
7897
+ "-o",
7898
+ `jsonpath=${API_ENDPOINTS_JSONPATH}`
7899
+ ]);
7900
+ if (nodes === null || interfaces === null || api === null) return null;
7901
+ const onInterfaces = [...interfaces.matchAll(IPV4_ON_INTERFACE)].map((match) => match[1] ?? "");
7902
+ return [...nodes.split(/\s+/), ...onInterfaces, ...api.split(/\s+/)].filter(Boolean);
7903
+ }
7904
+ async function recheckIsolation(ctx, reconciled) {
7905
+ if (reconciled?.applied !== true) return { isolation: reconciled, warnings: [] };
7906
+ const problem = await controllerProblem(ctx);
7907
+ return problem ? { isolation: { applied: false }, warnings: [problem] } : { isolation: reconciled, warnings: [] };
7908
+ }
7909
+
7643
7910
  // src/daemon/prune-namespaces.ts
7644
7911
  var POOL_NAMESPACE_PREFIX = "claudespace-";
7645
7912
  var WORKSPACE_MANAGER_ROLE = "conveyor-workspace-manager";
@@ -7702,6 +7969,143 @@ async function pruneStaleNamespaces(ctx, desired, result) {
7702
7969
  }
7703
7970
  }
7704
7971
 
7972
+ // src/daemon/namespace-upkeep.ts
7973
+ function message(error) {
7974
+ return error instanceof Error ? error.message : String(error);
7975
+ }
7976
+ function renderLimitRange(namespace, limits) {
7977
+ const ns = assertK8sName(namespace, "namespace");
7978
+ const values = [
7979
+ assertQuantity(limits.defaultRequest.cpu, "defaultRequest.cpu"),
7980
+ assertQuantity(limits.defaultRequest.memory, "defaultRequest.memory"),
7981
+ assertQuantity(limits.default.cpu, "default.cpu"),
7982
+ assertQuantity(limits.default.memory, "default.memory")
7983
+ ];
7984
+ return [
7985
+ "apiVersion: v1",
7986
+ "kind: LimitRange",
7987
+ "metadata:",
7988
+ " name: conveyor-k3-defaults",
7989
+ ` namespace: ${ns}`,
7990
+ "spec:",
7991
+ " limits:",
7992
+ " - type: Container",
7993
+ " defaultRequest:",
7994
+ ` cpu: "${values[0]}"`,
7995
+ ` memory: "${values[1]}"`,
7996
+ " default:",
7997
+ ` cpu: "${values[2]}"`,
7998
+ ` memory: "${values[3]}"`,
7999
+ ""
8000
+ ].join("\n");
8001
+ }
8002
+ async function reconcileNamespaces(ctx, desired, result) {
8003
+ for (const namespace of desired.namespaces) {
8004
+ try {
8005
+ await kubectlApply(ctx.exec, renderLimitRange(namespace.name, namespace.limitRange));
8006
+ } catch (error) {
8007
+ result.warnings.push(
8008
+ `Could not apply resource defaults to ${namespace.name} (${namespace.projectName}): ${message(error)}`
8009
+ );
8010
+ }
8011
+ }
8012
+ }
8013
+ async function ensureBakeNamespace(ctx, desired) {
8014
+ const found = await ctx.exec(
8015
+ "k3s",
8016
+ ["kubectl", "get", "namespace", PERSONAL_BAKE_NAMESPACE],
8017
+ KUBECTL_TIMEOUT2
8018
+ );
8019
+ if (found.exitCode !== 0) {
8020
+ await runOrThrow(
8021
+ ctx.exec,
8022
+ "k3s",
8023
+ ["kubectl", "create", "namespace", PERSONAL_BAKE_NAMESPACE],
8024
+ KUBECTL_TIMEOUT2
8025
+ );
8026
+ }
8027
+ const limitRange = desired.namespaces[0]?.limitRange;
8028
+ if (limitRange) {
8029
+ await kubectlApply(ctx.exec, renderLimitRange(PERSONAL_BAKE_NAMESPACE, limitRange));
8030
+ }
8031
+ }
8032
+ function knownStance(isolation) {
8033
+ const { podSecurity, egress, ...rest } = { ...isolation };
8034
+ const extra = Object.keys(rest);
8035
+ if (podSecurity === "baseline" && egress === "no-private" && extra.length === 0) return null;
8036
+ const named = `Pod Security "${String(podSecurity).slice(0, 40)}", egress "${String(egress).slice(0, 40)}"`;
8037
+ return extra.length === 0 ? named : `${named}, and ${extra.slice(0, 3).join(", ").slice(0, 80)}`;
8038
+ }
8039
+ var KUBECTL_TIMEOUT2 = { timeoutMs: 3e4 };
8040
+ var RECHECK = "Conveyor checks again within 10 minutes.";
8041
+ async function isolateNamespace(ctx, namespace, isolation, fail) {
8042
+ const ns = assertK8sName(namespace, "namespace");
8043
+ const labels = Object.entries(psaLabels(isolation.podSecurity)).map(
8044
+ ([key, value]) => `${key}=${value}`
8045
+ );
8046
+ const labelled = await ctx.exec(
8047
+ "k3s",
8048
+ ["kubectl", "label", "namespace", ns, "--overwrite", ...labels],
8049
+ KUBECTL_TIMEOUT2
8050
+ );
8051
+ if (labelled.exitCode !== 0) {
8052
+ fail(
8053
+ `Could not apply Pod Security labels to ${ns}: ${labelled.stderr.trim().slice(0, 200)} ${RECHECK}`
8054
+ );
8055
+ }
8056
+ if (isolation.hostAddresses === null) return;
8057
+ try {
8058
+ await kubectlApply(ctx.exec, renderEgressNetworkPolicy(ns, isolation.hostAddresses));
8059
+ } catch (error) {
8060
+ fail(`Could not apply the egress policy to ${ns}: ${message(error).slice(0, 200)} ${RECHECK}`);
8061
+ }
8062
+ }
8063
+ async function reconcileIsolation(ctx, desired, result) {
8064
+ try {
8065
+ await ensureBakeNamespace(ctx, desired);
8066
+ } catch (error) {
8067
+ result.warnings.push(
8068
+ `Could not prepare the bake namespace ${PERSONAL_BAKE_NAMESPACE}: ${message(error)}`
8069
+ );
8070
+ }
8071
+ const isolation = desired.isolation;
8072
+ if (!isolation) {
8073
+ result.isolation = void 0;
8074
+ return;
8075
+ }
8076
+ const unknown = knownStance(isolation);
8077
+ if (unknown) {
8078
+ result.warnings.push(
8079
+ `Conveyor asks for pod isolation this version of conveyor-k3 does not know (${unknown}), so nothing was changed and this server does not count as isolated. Run \`sudo conveyor-k3 update\`.`
8080
+ );
8081
+ result.isolation = { applied: false };
8082
+ return;
8083
+ }
8084
+ let applied = true;
8085
+ const fail = (warning) => {
8086
+ applied = false;
8087
+ result.warnings.push(warning);
8088
+ };
8089
+ const problem = await controllerProblem(ctx);
8090
+ if (problem) fail(problem);
8091
+ const hostAddresses = await readHostAddresses(ctx.exec);
8092
+ if (hostAddresses === null) {
8093
+ fail(
8094
+ `Could not read every address this server answers on, so the egress policies in place were left as they are and this server does not count as isolated. ${RECHECK}`
8095
+ );
8096
+ }
8097
+ for (const namespace of desired.namespaces) {
8098
+ await isolateNamespace(ctx, namespace.name, { podSecurity: "baseline", hostAddresses }, fail);
8099
+ }
8100
+ await isolateNamespace(
8101
+ ctx,
8102
+ PERSONAL_BAKE_NAMESPACE,
8103
+ { podSecurity: "privileged", hostAddresses },
8104
+ fail
8105
+ );
8106
+ result.isolation = { applied };
8107
+ }
8108
+
7705
8109
  // src/daemon/registry-tags.ts
7706
8110
  var REPO_NAME = /^[a-z0-9]+(?:[._-][a-z0-9]+)*(?:\/[a-z0-9]+(?:[._-][a-z0-9]+)*)*$/;
7707
8111
  var TAG_NAME = /^[A-Za-z0-9_][A-Za-z0-9._-]{0,127}$/;
@@ -8285,14 +8689,22 @@ async function collectHeartbeat(ports, state, inventory) {
8285
8689
  ...runnerUsers.length > 0 ? { runnerUsers } : {},
8286
8690
  ...localImages ? { localImages } : {},
8287
8691
  ...registry.fields,
8288
- localWarnings: [
8692
+ ...state.isolation ? { isolation: state.isolation } : {},
8693
+ localWarnings: withinHeartbeatBounds([
8289
8694
  ...state.localWarnings,
8290
8695
  ...gcWarning ? [gcWarning] : [],
8291
8696
  ...ungranted.length > 0 ? [ungrantedRunnersWarning(ungranted)] : [],
8292
8697
  ...registry.warnings
8293
- ]
8698
+ ])
8294
8699
  };
8295
8700
  }
8701
+ var HEARTBEAT_LIST_MAX = 64;
8702
+ var HEARTBEAT_STRING_MAX = 512;
8703
+ function withinHeartbeatBounds(warnings) {
8704
+ return warnings.slice(0, HEARTBEAT_LIST_MAX).map(
8705
+ (warning) => warning.length > HEARTBEAT_STRING_MAX ? `${warning.slice(0, HEARTBEAT_STRING_MAX - 1)}\u2026` : warning
8706
+ );
8707
+ }
8296
8708
  async function readPodIdentities(exec) {
8297
8709
  const result = await exec(
8298
8710
  "k3s",
@@ -8374,9 +8786,12 @@ async function runRegistryUpkeep(ports, lastGcAt, maintenanceHour) {
8374
8786
  }
8375
8787
 
8376
8788
  // src/daemon/reconcile.ts
8377
- async function reconcileKubelet(ctx, desired, result) {
8789
+ function ownerRestartWarning(change) {
8790
+ return `${change} Conveyor did not install this server's k3s, so it never restarts it: run \`sudo systemctl restart k3s\` when no build runs.`;
8791
+ }
8792
+ async function reconcileKubelet(ctx, desired, result, managed) {
8378
8793
  const ownerConfig = await ctx.fs.readFile(K3S_OWNER_CONFIG);
8379
- const rendered = renderK3sDropIn(desired.kubelet, ownerConfig);
8794
+ const rendered = renderK3sDropIn(desired.kubelet, ownerConfig, { disableComponents: managed });
8380
8795
  result.skippedKubeletFlags = rendered.skipped;
8381
8796
  result.effectiveImageGcHighThreshold = rendered.skipped.includes("image-gc-high-threshold") ? ownerImageGcHighThreshold(ownerConfig) : desired.kubelet.imageGcHighThreshold;
8382
8797
  for (const flag of rendered.skipped) {
@@ -8392,6 +8807,10 @@ async function reconcileKubelet(ctx, desired, result) {
8392
8807
  if (current === rendered.content) return;
8393
8808
  await ctx.fs.ensureDir(K3S_CONFIG_DROPIN.slice(0, K3S_CONFIG_DROPIN.lastIndexOf("/")));
8394
8809
  await ctx.fs.writeFile(K3S_CONFIG_DROPIN, rendered.content, 420);
8810
+ if (!managed) {
8811
+ result.warnings.push(ownerRestartWarning("Kubelet settings changed."));
8812
+ return;
8813
+ }
8395
8814
  if (!mayDisrupt(ctx.runningConveyorPods)) {
8396
8815
  result.warnings.push(
8397
8816
  `Kubelet settings changed but ${busyReason(ctx.runningConveyorPods)} \u2014 the restart is deferred until the machine is idle.`
@@ -8442,43 +8861,6 @@ async function reconcilePriorityClass(ctx, desired, result) {
8442
8861
  );
8443
8862
  }
8444
8863
  }
8445
- function renderLimitRange(namespace, limits) {
8446
- const ns = assertK8sName(namespace, "namespace");
8447
- const values = [
8448
- assertQuantity(limits.defaultRequest.cpu, "defaultRequest.cpu"),
8449
- assertQuantity(limits.defaultRequest.memory, "defaultRequest.memory"),
8450
- assertQuantity(limits.default.cpu, "default.cpu"),
8451
- assertQuantity(limits.default.memory, "default.memory")
8452
- ];
8453
- return [
8454
- "apiVersion: v1",
8455
- "kind: LimitRange",
8456
- "metadata:",
8457
- " name: conveyor-k3-defaults",
8458
- ` namespace: ${ns}`,
8459
- "spec:",
8460
- " limits:",
8461
- " - type: Container",
8462
- " defaultRequest:",
8463
- ` cpu: "${values[0]}"`,
8464
- ` memory: "${values[1]}"`,
8465
- " default:",
8466
- ` cpu: "${values[2]}"`,
8467
- ` memory: "${values[3]}"`,
8468
- ""
8469
- ].join("\n");
8470
- }
8471
- async function reconcileNamespaces(ctx, desired, result) {
8472
- for (const namespace of desired.namespaces) {
8473
- try {
8474
- await kubectlApply(ctx.exec, renderLimitRange(namespace.name, namespace.limitRange));
8475
- } catch (error) {
8476
- result.warnings.push(
8477
- `Could not apply resource defaults to ${namespace.name} (${namespace.projectName}): ${error instanceof Error ? error.message : String(error)}`
8478
- );
8479
- }
8480
- }
8481
- }
8482
8864
  async function step(result, label, run) {
8483
8865
  try {
8484
8866
  await run();
@@ -8515,6 +8897,12 @@ async function reconcile(ctx, desired) {
8515
8897
  "Could not apply namespace defaults",
8516
8898
  () => reconcileNamespaces(ctx, desired, result)
8517
8899
  );
8900
+ await step(
8901
+ result,
8902
+ "Could not apply pod isolation",
8903
+ () => reconcileIsolation(ctx, desired, result)
8904
+ );
8905
+ if (desired.isolation && result.isolation === void 0) result.isolation = { applied: false };
8518
8906
  if (manifestAccepted) {
8519
8907
  await step(
8520
8908
  result,
@@ -8523,6 +8911,7 @@ async function reconcile(ctx, desired) {
8523
8911
  );
8524
8912
  }
8525
8913
  const registry = desired.localRegistry?.enabled === true;
8914
+ const managed = managesK3s(desired, await readState(ctx.fs).catch(() => ({})));
8526
8915
  if (registry) {
8527
8916
  await step(result, "Could not reconcile the local image registry", async () => {
8528
8917
  await deployLocalRegistry(ctx);
@@ -8531,10 +8920,15 @@ async function reconcile(ctx, desired) {
8531
8920
  await step(
8532
8921
  result,
8533
8922
  "Could not apply kubelet settings",
8534
- () => reconcileKubelet(ctx, desired, result)
8923
+ () => reconcileKubelet(ctx, desired, result, managed)
8535
8924
  );
8536
8925
  if (registry && !result.restartedK3s) {
8537
8926
  await step(result, "Could not load the local image registry mirror", async () => {
8927
+ if (!managed) {
8928
+ if (await registryMirrorPending(ctx.fs))
8929
+ result.warnings.push(ownerRestartWarning("The local image registry's mirror is new."));
8930
+ return;
8931
+ }
8538
8932
  const loaded = await loadRegistryMirror(ctx);
8539
8933
  result.restartedK3s = loaded.restarted;
8540
8934
  if (loaded.warning) result.warnings.push(loaded.warning);
@@ -8547,6 +8941,8 @@ async function reconcile(ctx, desired) {
8547
8941
  var HOUR_MS2 = 60 * 6e4;
8548
8942
  var DAY_MS = 24 * HOUR_MS2;
8549
8943
  var STORE_MEASURE_INTERVAL_MS = 55 * 6e4;
8944
+ var ISOLATION_RETRY_FIRST_MS = 6e4;
8945
+ var ISOLATION_RETRY_MAX_MS = 10 * 6e4;
8550
8946
  var DISK_PRESSURE_FREE_FRACTION = 0.2;
8551
8947
  var STRANDED_PRUNE_BYTES = 20 * 1024 ** 3;
8552
8948
  function flattenWanted(desired) {
@@ -8587,12 +8983,22 @@ var ClusterDaemon = class {
8587
8983
  localImageHashes = /* @__PURE__ */ new Map();
8588
8984
  /** How long the in-cluster registry has been not ready, across beats. */
8589
8985
  registryWatch = { notReadySince: null };
8986
+ /**
8987
+ * Whether pod isolation is in force, from the last reconcile; undefined
8988
+ * while desired state does not ask for it. Every heartbeat checks it again
8989
+ * against k3s's own settings before reporting it.
8990
+ */
8991
+ isolation = void 0;
8590
8992
  timers = [];
8591
8993
  /** When the last store walk started, so one that failed is not retried on every reconcile. */
8592
8994
  storeWalkStartedAt = 0;
8593
8995
  /** Serializes reconcile against itself — a sync nudge during a reconcile
8594
8996
  * must queue, not interleave two kubectl applies of the same manifests. */
8595
8997
  reconciling = null;
8998
+ /** The run queued behind the running one, until it starts. At most one waits. */
8999
+ queuedRun = null;
9000
+ /** The next reconcile while pod isolation is not applied; `dueAt` 0 = none. */
9001
+ isolationRetry = { delayMs: ISOLATION_RETRY_FIRST_MS, dueAt: 0 };
8596
9002
  constructor(ports) {
8597
9003
  this.ports = ports;
8598
9004
  }
@@ -8628,10 +9034,27 @@ var ClusterDaemon = class {
8628
9034
  }
8629
9035
  /** Fetch the desired state and converge to it. Queued, never concurrent. */
8630
9036
  syncAndReconcile() {
8631
- const run = (this.reconciling ?? Promise.resolve()).then(() => this.runReconcile());
9037
+ if (this.queuedRun) return this.queuedRun;
9038
+ const run = (this.reconciling ?? Promise.resolve()).then(() => {
9039
+ this.queuedRun = null;
9040
+ return this.runReconcile();
9041
+ });
9042
+ this.queuedRun = run;
8632
9043
  this.reconciling = run.catch(() => void 0);
8633
9044
  return run;
8634
9045
  }
9046
+ /** Reconcile again later while pod isolation is not applied; stop once it is. */
9047
+ scheduleIsolationRetry() {
9048
+ if (this.isolation?.applied !== false) {
9049
+ this.isolationRetry = { delayMs: ISOLATION_RETRY_FIRST_MS, dueAt: 0 };
9050
+ return;
9051
+ }
9052
+ const { delayMs } = this.isolationRetry;
9053
+ this.isolationRetry = {
9054
+ delayMs: Math.min(delayMs * 2, ISOLATION_RETRY_MAX_MS),
9055
+ dueAt: Date.now() + delayMs
9056
+ };
9057
+ }
8635
9058
  async runReconcile() {
8636
9059
  try {
8637
9060
  this.desired = await this.ports.connection.requestDesiredState();
@@ -8647,6 +9070,8 @@ var ClusterDaemon = class {
8647
9070
  this.desired
8648
9071
  );
8649
9072
  this.warnings = result.warnings;
9073
+ this.isolation = result.isolation;
9074
+ this.scheduleIsolationRetry();
8650
9075
  for (const warning of result.warnings) this.ports.log(warning);
8651
9076
  if (result.prunedNamespaces.length > 0) {
8652
9077
  this.ports.log(
@@ -8817,6 +9242,10 @@ var ClusterDaemon = class {
8817
9242
  const inventory = await readImageInventory(this.ports.exec).catch(() => null);
8818
9243
  const registryOn = this.desired?.localRegistry?.enabled === true;
8819
9244
  if (!registryOn) this.registryWatch.notReadySince = null;
9245
+ const isolation = await recheckIsolation(
9246
+ { exec: this.ports.exec, fs: this.ports.fs },
9247
+ this.isolation
9248
+ );
8820
9249
  return await collectHeartbeat(
8821
9250
  {
8822
9251
  exec: this.ports.exec,
@@ -8831,10 +9260,11 @@ var ClusterDaemon = class {
8831
9260
  lastPruneAt: this.state?.lastPruneAt ?? null,
8832
9261
  lastWarmAt: this.state?.lastWarmAt ?? null,
8833
9262
  lastUpdateAt: this.state?.lastUpdateAt ?? null,
8834
- localWarnings: [...this.warnings, ...this.warmWarnings],
9263
+ localWarnings: [...this.warnings, ...this.warmWarnings, ...isolation.warnings],
8835
9264
  imageGcHighThreshold: this.effectiveImageGcHigh,
8836
9265
  localImageHashes: this.localImageHashes,
8837
9266
  ...registryOn ? { localRegistry: this.registryWatch } : {},
9267
+ ...isolation.isolation ? { isolation: isolation.isolation } : {},
8838
9268
  k3sStoreBytes: this.measuredStoreBytes
8839
9269
  },
8840
9270
  inventory
@@ -8859,6 +9289,10 @@ var ClusterDaemon = class {
8859
9289
  return this.beating;
8860
9290
  }
8861
9291
  async runBeat() {
9292
+ if (this.isolationRetry.dueAt > 0 && Date.now() >= this.isolationRetry.dueAt) {
9293
+ this.isolationRetry.dueAt = 0;
9294
+ void this.syncAndReconcile();
9295
+ }
8862
9296
  try {
8863
9297
  const workloads = await this.ports.connection.sendHeartbeat({
8864
9298
  ...await this.buildHeartbeat(),
@@ -9017,6 +9451,7 @@ function createMemoryFileSystem(seed = {}) {
9017
9451
  // src/verbs.ts
9018
9452
  var VERBS = [
9019
9453
  "vm",
9454
+ "host",
9020
9455
  "setup",
9021
9456
  "start",
9022
9457
  "stop",
@@ -9049,14 +9484,22 @@ function parseArgs(argv) {
9049
9484
  }
9050
9485
  return { verb, positional, flags };
9051
9486
  }
9052
- var HELP = `conveyor-k3 \u2014 managed personal compute for Conveyor
9487
+ var HELP = `conveyor-k3 \u2014 Personal Compute for Conveyor
9053
9488
 
9054
9489
  Usage: conveyor-k3 <command> [options]
9055
9490
 
9056
- Commands:
9057
- vm Manage isolated compute on macOS or Linux.
9058
- Run conveyor-k3 vm for host lifecycle commands.
9059
- setup Install and enrol this machine. Safe to re-run.
9491
+ One product, two runtimes. Pick the one that fits the machine:
9492
+
9493
+ On your computer or server:
9494
+ vm Personal computer runtime: an isolated VM on macOS or
9495
+ Linux. Run conveyor-k3 vm for its commands.
9496
+ host Dedicated server runtime: k3s and the daemon on this
9497
+ Linux machine, with no VM. Root only. Run
9498
+ conveyor-k3 host for its commands.
9499
+
9500
+ Inside a linked machine (the VM guest, or the server itself):
9501
+ setup VM guest only: install and enrol this machine. Safe
9502
+ to re-run. On a server, use conveyor-k3 host setup.
9060
9503
  start Start the tunnel and the daemon.
9061
9504
  stop Stop both, and tell Conveyor at once so your next
9062
9505
  build goes straight to project compute.
@@ -9081,10 +9524,12 @@ Commands:
9081
9524
  into this node and pin it. Writes one file under
9082
9525
  /etc/sudoers.d, checked with visudo first. Needed only
9083
9526
  when a project has Bake Locally turned on.
9084
- uninstall Remove Conveyor's units, environment, state, and image
9085
- registry. Your k3s config, your own registries.yaml
9086
- entries, your workloads, and the registry's data are
9087
- left alone.
9527
+ uninstall VM guest only: remove Conveyor's units, environment,
9528
+ state, and image registry. Your k3s config, your own
9529
+ registries.yaml entries, your workloads, and the
9530
+ registry's data are left alone. On a server, use
9531
+ conveyor-k3 host uninstall: it also removes the
9532
+ device key.
9088
9533
  --purge-k3s --yes also remove k3s itself and the
9089
9534
  registry's data
9090
9535
  daemon Run in the foreground (what the systemd unit calls).
@@ -9181,6 +9626,47 @@ async function removeLocalRegistry(ports) {
9181
9626
  `Removed the local image registry's mirror from ${REGISTRIES_FILE} (backup: ${backup}).`
9182
9627
  );
9183
9628
  }
9629
+ async function removeIsolation(ports) {
9630
+ const [key, value] = Object.entries(MANAGED_BY2)[0] ?? [];
9631
+ const removed = await ports.exec(
9632
+ "k3s",
9633
+ ["kubectl", "delete", "networkpolicy", "-A", "-l", `${key}=${value}`, "--ignore-not-found"],
9634
+ { timeoutMs: 12e4 }
9635
+ );
9636
+ if (removed.exitCode !== 0) {
9637
+ ports.log(
9638
+ `Could not remove Conveyor's network policies: ${removed.stderr.trim().slice(0, 200)}`
9639
+ );
9640
+ }
9641
+ const listed = await ports.exec("k3s", [
9642
+ "kubectl",
9643
+ "get",
9644
+ "namespaces",
9645
+ "-o",
9646
+ "jsonpath={.items[*].metadata.name}"
9647
+ ]);
9648
+ if (listed.exitCode !== 0) {
9649
+ ports.log(
9650
+ `Could not list namespaces to remove Conveyor's Pod Security labels: ${listed.stderr.trim().slice(0, 200)}`
9651
+ );
9652
+ return;
9653
+ }
9654
+ const namespaces = listed.stdout.split(/\s+/).filter((name) => name.startsWith("claudespace-") || name === PERSONAL_BAKE_NAMESPACE);
9655
+ for (const namespace of namespaces) {
9656
+ const unlabelled = await ports.exec("k3s", [
9657
+ "kubectl",
9658
+ "label",
9659
+ "namespace",
9660
+ namespace,
9661
+ ...PSA_LABEL_KEYS.map((labelKey) => `${labelKey}-`)
9662
+ ]);
9663
+ if (unlabelled.exitCode !== 0) {
9664
+ ports.log(
9665
+ `Could not remove Conveyor's Pod Security labels from ${namespace}: ${unlabelled.stderr.trim().slice(0, 200)}`
9666
+ );
9667
+ }
9668
+ }
9669
+ }
9184
9670
  async function uninstall(ports, options = {}) {
9185
9671
  const result = { stoppedUnits: [], removedFiles: [], purgedK3s: false };
9186
9672
  if (options.purgeK3s && !options.confirmed) {
@@ -9193,6 +9679,7 @@ async function uninstall(ports, options = {}) {
9193
9679
  result.stoppedUnits.push(unit);
9194
9680
  }
9195
9681
  await removeLocalRegistry(ports);
9682
+ await removeIsolation(ports);
9196
9683
  for (const path of OWNED_FILES) {
9197
9684
  await ports.fs.removeFile(path);
9198
9685
  result.removedFiles.push(path);
@@ -9259,12 +9746,6 @@ function readExecStart(unit) {
9259
9746
  }
9260
9747
  return collected.join(" ");
9261
9748
  }
9262
- function bareToken(token) {
9263
- let bare = token.trim();
9264
- if (bare.endsWith("\\")) bare = bare.slice(0, -1).trim();
9265
- if (bare.length >= 2 && bare.startsWith("'") && bare.endsWith("'")) bare = bare.slice(1, -1);
9266
- return bare;
9267
- }
9268
9749
  function parseForeignExecFlags(execStart) {
9269
9750
  const ours = new Set(K3S_INSTALL_EXEC.split(/\s+/).filter((token) => token.startsWith("--")));
9270
9751
  const foreign = [];
@@ -9284,6 +9765,12 @@ async function foreignK3sExecFlags(exec) {
9284
9765
  return parseForeignExecFlags(readExecStart(unit.stdout));
9285
9766
  }
9286
9767
  function decideK3sUpgrade(input) {
9768
+ if (input.managesK3s === false) {
9769
+ return {
9770
+ upgrade: false,
9771
+ reason: "Conveyor did not install this server's k3s, so its owner upgrades it"
9772
+ };
9773
+ }
9287
9774
  if (!input.autoUpgradeK3s) {
9288
9775
  return { upgrade: false, reason: "automatic k3s upgrades are turned off for this machine" };
9289
9776
  }