@homeflare/alchemy 0.41.0 → 0.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/dist/litellm/budget-errors.d.ts +36 -0
  2. package/dist/litellm/budget-errors.d.ts.map +1 -0
  3. package/dist/litellm/budget-form.d.ts +50 -0
  4. package/dist/litellm/budget-form.d.ts.map +1 -0
  5. package/dist/litellm/budget-operations.d.ts +20 -0
  6. package/dist/litellm/budget-operations.d.ts.map +1 -0
  7. package/dist/litellm/budget.d.ts +61 -0
  8. package/dist/litellm/budget.d.ts.map +1 -0
  9. package/dist/litellm/fake-litellm.d.ts +5 -0
  10. package/dist/litellm/fake-litellm.d.ts.map +1 -1
  11. package/dist/litellm/index.d.ts +2 -0
  12. package/dist/litellm/index.d.ts.map +1 -1
  13. package/dist/litellm/index.js +125 -2
  14. package/dist/litellm/index.js.map +9 -5
  15. package/dist/litellm/operations.d.ts +22 -0
  16. package/dist/litellm/operations.d.ts.map +1 -1
  17. package/dist/litellm/providers.d.ts +1 -1
  18. package/dist/litellm/providers.d.ts.map +1 -1
  19. package/dist/openbao/auth-role-form.d.ts +9 -0
  20. package/dist/openbao/auth-role-form.d.ts.map +1 -1
  21. package/dist/openbao/auth-role-wire.d.ts.map +1 -1
  22. package/dist/openbao/fake-engines-roles.d.ts.map +1 -1
  23. package/dist/openbao/index.js +9 -6
  24. package/dist/openbao/index.js.map +4 -4
  25. package/dist/postgres/connection.d.ts +20 -2
  26. package/dist/postgres/connection.d.ts.map +1 -1
  27. package/dist/postgres/database-sql.d.ts +1 -1
  28. package/dist/postgres/database-sql.d.ts.map +1 -1
  29. package/dist/postgres/database.d.ts +1 -1
  30. package/dist/postgres/database.d.ts.map +1 -1
  31. package/dist/postgres/index.d.ts +5 -3
  32. package/dist/postgres/index.d.ts.map +1 -1
  33. package/dist/postgres/index.js +124 -38
  34. package/dist/postgres/index.js.map +8 -7
  35. package/dist/postgres/providers.d.ts +4 -2
  36. package/dist/postgres/providers.d.ts.map +1 -1
  37. package/dist/postgres/psql-executor.d.ts +21 -0
  38. package/dist/postgres/psql-executor.d.ts.map +1 -0
  39. package/dist/proxmox/acl.d.ts.map +1 -1
  40. package/dist/proxmox/api-token.d.ts.map +1 -1
  41. package/dist/proxmox/ceph-flag-types.d.ts +57 -0
  42. package/dist/proxmox/ceph-flag-types.d.ts.map +1 -0
  43. package/dist/proxmox/ceph-flag-wire.d.ts +77 -0
  44. package/dist/proxmox/ceph-flag-wire.d.ts.map +1 -0
  45. package/dist/proxmox/ceph-flag.d.ts +15 -50
  46. package/dist/proxmox/ceph-flag.d.ts.map +1 -1
  47. package/dist/proxmox/ceph-osd-write.d.ts +10 -13
  48. package/dist/proxmox/ceph-osd-write.d.ts.map +1 -1
  49. package/dist/proxmox/credential-errors.d.ts +18 -4
  50. package/dist/proxmox/credential-errors.d.ts.map +1 -1
  51. package/dist/proxmox/credentials.d.ts +35 -1
  52. package/dist/proxmox/credentials.d.ts.map +1 -1
  53. package/dist/proxmox/group.d.ts.map +1 -1
  54. package/dist/proxmox/index.js +805 -757
  55. package/dist/proxmox/index.js.map +21 -19
  56. package/dist/proxmox/lease-cache.d.ts +67 -5
  57. package/dist/proxmox/lease-cache.d.ts.map +1 -1
  58. package/dist/proxmox/mint.d.ts +4 -2
  59. package/dist/proxmox/mint.d.ts.map +1 -1
  60. package/dist/proxmox/node-network.d.ts.map +1 -1
  61. package/dist/proxmox/role.d.ts.map +1 -1
  62. package/dist/proxmox/storage.d.ts.map +1 -1
  63. package/dist/proxmox/unreadable-read.d.ts +8 -1
  64. package/dist/proxmox/unreadable-read.d.ts.map +1 -1
  65. package/dist/proxmox/user.d.ts.map +1 -1
  66. package/dist/proxmox/zfs-pool.d.ts.map +1 -1
  67. package/docs/credentials.md +14 -1
  68. package/docs/litellm-budget.md +55 -0
  69. package/docs/litellm.md +7 -6
  70. package/docs/postgres.md +22 -0
  71. package/docs/proxmox-sdk-migration.md +45 -0
  72. package/package.json +3 -3
  73. package/src/litellm/budget-errors.ts +38 -0
  74. package/src/litellm/budget-form.ts +94 -0
  75. package/src/litellm/budget-operations.ts +51 -0
  76. package/src/litellm/budget.test.ts +105 -0
  77. package/src/litellm/budget.ts +127 -0
  78. package/src/litellm/fake-litellm.ts +50 -1
  79. package/src/litellm/index.ts +13 -0
  80. package/src/litellm/operations.ts +1 -1
  81. package/src/litellm/providers.ts +4 -1
  82. package/src/openbao/auth-role-form.test.ts +37 -0
  83. package/src/openbao/auth-role-form.ts +12 -1
  84. package/src/openbao/auth-role-wire.test.ts +1 -0
  85. package/src/openbao/auth-role-wire.ts +13 -1
  86. package/src/openbao/distilled-retry.test.ts +1 -0
  87. package/src/openbao/fake-engines-roles.ts +7 -1
  88. package/src/postgres/connection.ts +37 -3
  89. package/src/postgres/database-sql.ts +4 -3
  90. package/src/postgres/database.ts +3 -2
  91. package/src/postgres/index.ts +10 -3
  92. package/src/postgres/providers.ts +15 -2
  93. package/src/postgres/psql-executor.test.ts +106 -0
  94. package/src/postgres/psql-executor.ts +130 -0
  95. package/src/proxmox/acl.ts +7 -1
  96. package/src/proxmox/api-token.ts +7 -1
  97. package/src/proxmox/ceph-flag-types.ts +70 -0
  98. package/src/proxmox/ceph-flag-wire.test.ts +72 -0
  99. package/src/proxmox/ceph-flag-wire.ts +123 -0
  100. package/src/proxmox/ceph-flag.ts +77 -130
  101. package/src/proxmox/ceph-osd-write.ts +10 -13
  102. package/src/proxmox/credential-errors.ts +19 -5
  103. package/src/proxmox/credentials.test.ts +73 -1
  104. package/src/proxmox/credentials.ts +72 -1
  105. package/src/proxmox/group.ts +7 -1
  106. package/src/proxmox/lease-cache-mint.test.ts +70 -0
  107. package/src/proxmox/lease-cache.test.ts +83 -7
  108. package/src/proxmox/lease-cache.ts +74 -10
  109. package/src/proxmox/mint.ts +12 -5
  110. package/src/proxmox/node-network.ts +7 -1
  111. package/src/proxmox/role.ts +7 -1
  112. package/src/proxmox/storage.ts +7 -1
  113. package/src/proxmox/unreadable-read.ts +16 -4
  114. package/src/proxmox/user.ts +7 -1
  115. package/src/proxmox/zfs-pool.ts +7 -1
@@ -1025,6 +1025,20 @@ import * as Duration from "effect/Duration";
1025
1025
  import * as Effect3 from "effect/Effect";
1026
1026
  import * as Exit from "effect/Exit";
1027
1027
 
1028
+ // src/proxmox/credentials.ts
1029
+ var VALID_TIER = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
1030
+ var mintTier = (target, role) => {
1031
+ if (target.scheme !== "pve")
1032
+ return role;
1033
+ const tier = target.roles?.[role];
1034
+ if (tier === undefined)
1035
+ return role;
1036
+ if (!VALID_TIER.test(tier)) {
1037
+ throw new Error(`PveTarget.roles.${role} = ${JSON.stringify(tier)} is not a valid OpenBao tier name -- ` + 'it would be interpolated straight into "<mount>/creds/<tier>" and must be a plain name ' + '(letters, digits, ".", "_", "-", not starting with one of those and not "..").');
1038
+ }
1039
+ return tier;
1040
+ };
1041
+
1028
1042
  // src/proxmox/mint.ts
1029
1043
  import * as Effect2 from "effect/Effect";
1030
1044
  import * as Option from "effect/Option";
@@ -1038,14 +1052,15 @@ import * as Data from "effect/Data";
1038
1052
 
1039
1053
  class PveCredentialDenied extends Data.TaggedError("PveCredentialDenied") {
1040
1054
  get message() {
1041
- return `OpenBao GET /v1/${this.mount}/creds/${this.role} -> 403: ${this.detail}. This identity's ` + "AppRole has no grant for this role -- a refused read, not evidence the object is gone.";
1055
+ return `OpenBao GET /v1/${this.mount}/creds/${this.tier} -> 403: ${this.detail}. This identity's ` + "AppRole has no grant for this role -- a refused read, not evidence the object is gone.";
1042
1056
  }
1043
1057
  }
1044
1058
 
1045
1059
  // src/proxmox/mint.ts
1046
1060
  var baoVariable = (env, name) => env[`BAO_${name}`] ?? env[`VAULT_${name}`] ?? "";
1047
1061
  var mint = (target, role, env = process.env) => Effect2.gen(function* () {
1048
- const path = `${target.mount}/creds/${role}`;
1062
+ const tier = mintTier(target, role);
1063
+ const path = `${target.mount}/creds/${tier}`;
1049
1064
  const refuse = (status2, detail) => new Error(`OpenBao GET /v1/${path} -> ${status2 === 0 ? "no response" : status2}: ${detail}`);
1050
1065
  const address = baoVariable(env, "AGENT_ADDR") || baoVariable(env, "ADDR") || "https://127.0.0.1:8200";
1051
1066
  const socket = address.startsWith("unix://") ? address.slice("unix://".length) : undefined;
@@ -1078,14 +1093,14 @@ var mint = (target, role, env = process.env) => Effect2.gen(function* () {
1078
1093
  const isOpenBaoBody = Array.isArray(errors);
1079
1094
  const detail = isOpenBaoBody ? errors.map(String).join("; ") : "not an OpenBao error body";
1080
1095
  if (status === 403 && isOpenBaoBody) {
1081
- return yield* Effect2.fail(new PveCredentialDenied({ detail, mount: target.mount, role }));
1096
+ return yield* Effect2.fail(new PveCredentialDenied({ detail, mount: target.mount, tier }));
1082
1097
  }
1083
1098
  return yield* Effect2.fail(refuse(status, detail || "(no errors given)"));
1084
1099
  }
1085
1100
  const tokenId = parsed?.data?.token_id;
1086
1101
  const secret = parsed?.data?.secret;
1087
1102
  if (typeof tokenId !== "string" || typeof secret !== "string") {
1088
- return yield* Effect2.fail(new Error(`${target.mount}/creds/${role} returned no token_id/secret. Either this approle lacks ` + `the grant, or the mount is not ${target.mount}. Say which mount and role you needed ` + `than falling back to a stored credential -- every stored PVE token is read-only.`));
1103
+ return yield* Effect2.fail(new Error(`${target.mount}/creds/${tier} returned no token_id/secret. Either this approle lacks ` + `the grant, or the mount is not ${target.mount}. Say which mount and role you needed ` + `than falling back to a stored credential -- every stored PVE token is read-only.`));
1089
1104
  }
1090
1105
  const lease = parsed?.lease_duration;
1091
1106
  const leaseSeconds = typeof lease === "number" ? lease : 0;
@@ -1097,13 +1112,14 @@ var authorization = (credential, target) => target.scheme === "pbs" ? `PBSAPITok
1097
1112
  var REMINT_MARGIN_SECONDS = 60;
1098
1113
  var keyOf = (target, role) => ({
1099
1114
  mount: target.mount,
1100
- role,
1101
- scheme: target.scheme
1115
+ scheme: target.scheme,
1116
+ tier: mintTier(target, role)
1102
1117
  });
1103
1118
  var timeToLive = (exit) => Exit.isSuccess(exit) && exit.value.leaseSeconds > REMINT_MARGIN_SECONDS ? Duration.seconds(exit.value.leaseSeconds - REMINT_MARGIN_SECONDS) : Duration.zero;
1104
1119
  var makeLeases = (mintFor) => Cache.makeWith(mintFor, { capacity: 64, requireServicesAt: "lookup", timeToLive });
1105
- var targetForKey = (key) => key.scheme === "pbs" ? { api: "https://pbs.invalid/api2/json", mount: key.mount, scheme: "pbs" } : { members: [], mount: key.mount, scheme: "pve" };
1106
- var leases = Effect3.runSync(makeLeases((key) => mint(targetForKey(key), key.role)));
1120
+ var targetForKey = (key) => key.scheme === "pbs" ? { api: "https://pbs.invalid/api2/json", mount: key.mount, scheme: "pbs" } : { members: [], mount: key.mount, roles: { read: key.tier }, scheme: "pve" };
1121
+ var mintForKey = (key, env = process.env) => mint(targetForKey(key), key.scheme === "pbs" ? key.tier : "read", env);
1122
+ var leases = Effect3.runSync(makeLeases(mintForKey));
1107
1123
  var leased = (target, role) => Cache.get(leases, keyOf(target, role));
1108
1124
 
1109
1125
  // src/proxmox/members.ts
@@ -1233,7 +1249,7 @@ var runPve = (target, role, isWrite, op) => Effect5.gen(function* () {
1233
1249
  import * as Effect6 from "effect/Effect";
1234
1250
  var UNREADABLE = Symbol("pve-unreadable");
1235
1251
  var readOrUnreadable = (effect) => effect.pipe(Effect6.catchTag("PveCredentialDenied", () => Effect6.succeed(UNREADABLE)));
1236
- var unreadableWarning = (type, identity2) => Effect6.logWarning(`${type} ${identity2}: the read was refused (no grant for this credential's role) -- ` + "reporting noop rather than forcing an update with nothing compared. Re-plan on a lane " + "that can read this object before trusting this row.");
1252
+ var unreadableWarning = (type, identity2, mount, tier) => Effect6.logWarning(`${type} ${identity2}: the read of ${mount}/creds/${tier} was refused (no grant for this ` + "credential's role) -- reporting noop rather than forcing an update with nothing compared. " + "Re-plan on a lane that can read this object before trusting this row.");
1237
1253
 
1238
1254
  // src/proxmox/acl.ts
1239
1255
  var ProxmoxAcl = Resource("Proxmox.Acl");
@@ -1255,7 +1271,7 @@ var ProxmoxAclProvider = () => Provider.effect(ProxmoxAcl, Effect7.succeed(Proxm
1255
1271
  return;
1256
1272
  const live = yield* readAttributes(news);
1257
1273
  if (live === UNREADABLE) {
1258
- yield* unreadableWarning("Proxmox.Acl", identity(news));
1274
+ yield* unreadableWarning("Proxmox.Acl", identity(news), news.target.mount, mintTier(news.target, "provision"));
1259
1275
  return { action: "noop" };
1260
1276
  }
1261
1277
  return live !== undefined && matches(live, news) ? { action: "noop" } : { action: "update" };
@@ -1425,7 +1441,7 @@ var ProxmoxApiTokenProvider = () => Provider2.effect(ProxmoxApiToken, Effect8.su
1425
1441
  return;
1426
1442
  const live = yield* readToken(news);
1427
1443
  if (live === UNREADABLE) {
1428
- yield* unreadableWarning("Proxmox.ApiToken", `${news.userid}!${news.tokenid}`);
1444
+ yield* unreadableWarning("Proxmox.ApiToken", `${news.userid}!${news.tokenid}`, news.target.mount, mintTier(news.target, "provision"));
1429
1445
  return { action: "noop" };
1430
1446
  }
1431
1447
  return live !== undefined && matches2(live, news) ? { action: "noop" } : { action: "update" };
@@ -1729,143 +1745,57 @@ var ProxmoxCephDaemonProvider = () => Provider4.effect(ProxmoxCephDaemon, Effect
1729
1745
  })));
1730
1746
  // src/proxmox/ceph-flag.ts
1731
1747
  import { Resource as Resource5 } from "alchemy";
1732
- import * as Provider5 from "alchemy/Provider";
1733
- import * as Effect16 from "effect/Effect";
1734
-
1735
- // src/proxmox/resource.ts
1736
1748
  import { isResolved as isResolved5 } from "alchemy/Diff";
1749
+ import * as Provider5 from "alchemy/Provider";
1737
1750
  import * as Effect15 from "effect/Effect";
1738
1751
 
1739
- // src/proxmox/client.ts
1752
+ // src/proxmox/ceph-flag-wire.ts
1753
+ import * as cluster3 from "@distilled.cloud/proxmox/cluster";
1740
1754
  import * as Effect14 from "effect/Effect";
1741
- import * as HttpClient5 from "effect/unstable/http/HttpClient";
1742
- import * as HttpClientRequest2 from "effect/unstable/http/HttpClientRequest";
1743
- class PveError extends Error {
1744
- status;
1745
- method;
1746
- path;
1747
- constructor(status, method, path, detail) {
1748
- super(`PVE ${method} ${path} -> ${String(status)}: ${detail}`);
1749
- this.status = status;
1750
- this.method = method;
1751
- this.path = path;
1752
- this.name = "PveError";
1753
- }
1754
- }
1755
- var clusterExhausted = (method, path, attempts) => new PveError(0, method, path, `all members failed: ${attempts.map((a) => `${a.member} (${a.why})`).join("; ")}`);
1756
- var encode = (form) => {
1757
- const params = new URLSearchParams;
1758
- for (const [key, value] of Object.entries(form)) {
1759
- if (typeof value === "string")
1760
- params.append(key, value);
1761
- else
1762
- for (const item of value)
1763
- params.append(key, item);
1764
- }
1765
- return params.toString();
1766
- };
1767
- var buildRequest = (method, apiBase, path, credential, target, form) => {
1768
- const url = `${apiBase}/${path}`;
1769
- return HttpClientRequest2.make(method)(url).pipe(HttpClientRequest2.setHeaders({ Authorization: authorization(credential, target) }), form === undefined ? (self) => self : HttpClientRequest2.bodyText(encode(form), "application/x-www-form-urlencoded"));
1770
- };
1771
- var executeOne = (target, credential, method, path, form, apiBase) => Effect14.gen(function* () {
1772
- const client = yield* HttpClient5.HttpClient;
1773
- const request = buildRequest(method, apiBase, path, credential, target, form);
1774
- return yield* client.execute(request).pipe(Effect14.mapError((cause) => new PveError(0, method, path, String(cause))));
1775
- });
1776
- var readResponse = (response, method, path) => Effect14.gen(function* () {
1777
- if (response.status < 200 || response.status >= 300) {
1778
- const detail = yield* response.text.pipe(Effect14.orElseSucceed(() => ""));
1779
- return yield* Effect14.fail(new PveError(response.status, method, path, detail.slice(0, 300)));
1780
- }
1781
- const body = yield* response.json.pipe(Effect14.mapError((cause) => new PveError(0, method, path, String(cause))));
1782
- return body.data;
1783
- });
1784
- var pveWith = (target, credential, method, path, form) => Effect14.gen(function* () {
1785
- const response = target.scheme === "pve" ? yield* executeOnCluster(target, method, path, (apiBase) => buildRequest(method, apiBase, path, credential, target, form)).pipe(Effect14.mapError((failure) => failure.tag === "cluster" ? clusterExhausted(failure.method, failure.path, failure.attempts) : new PveError(0, method, path, String(failure)))) : yield* executeOne(target, credential, method, path, form, target.api);
1786
- return yield* readResponse(response, method, path);
1755
+ var CEPH_FLAG_UPDATE = "pve:PUT /cluster/ceph/flags/{flag}";
1756
+ var attributesOf3 = (live, props) => ({
1757
+ flag: props.flag,
1758
+ value: bool(live)
1787
1759
  });
1788
- var pve = (target, role, method, path, form) => Effect14.gen(function* () {
1789
- const credential = yield* leased(target, role);
1790
- return yield* pveWith(target, credential, method, path, form);
1791
- });
1792
-
1793
- // src/proxmox/resource.ts
1794
- var pveOperations = (spec) => {
1795
- const { guardCreate: guardCreate2, guardUpdate: guardUpdate2 } = specGuards(spec);
1796
- const read = (props) => pve(props.target, spec.readRole ?? "read", "GET", spec.path(props)).pipe(Effect15.map((data) => data == null ? undefined : spec.attributes(data, props)), Effect15.orElseSucceed(() => {
1797
- return;
1798
- }));
1799
- return {
1800
- guardCreate: guardCreate2,
1801
- guardUpdate: guardUpdate2,
1802
- read,
1803
- diff: (news, output) => Effect15.gen(function* () {
1804
- if (!isResolved5(news))
1805
- return;
1806
- yield* guardCreate2(news, output === undefined);
1807
- yield* guardUpdate2(news);
1808
- if (output === undefined)
1809
- return;
1810
- const live = yield* read(news);
1811
- if (live === undefined) {
1812
- yield* guardCreate2(news, true);
1813
- return { action: "update" };
1814
- }
1815
- if (spec.matches(live, news))
1816
- return { action: "noop" };
1817
- return spec.updateForm === undefined ? { action: "replace" } : { action: "update" };
1818
- }),
1819
- reconcile: (news) => Effect15.gen(function* () {
1820
- const live = yield* read(news);
1821
- yield* guardCreate2(news, live === undefined);
1822
- yield* guardUpdate2(news);
1823
- if (live === undefined) {
1824
- yield* pve(news.target, "provision", "POST", spec.collection(news), spec.createForm(news));
1825
- } else if (spec.updateForm !== undefined) {
1826
- const form = formToSend(spec.matches, live, news, spec.updateForm(news));
1827
- if (form !== undefined) {
1828
- yield* pve(news.target, "provision", "PUT", spec.path(news), form);
1829
- }
1830
- }
1831
- const after = yield* read(news);
1832
- if (after === undefined) {
1833
- return yield* Effect15.die(new Error(`${spec.path(news)}: the write returned no error but the object is still absent. ` + 'PVE wraps every answer in {"data":...} and can report success on a call that did ' + "nothing -- read back rather than trusting the status code."));
1834
- }
1835
- return after;
1836
- }),
1837
- destroy: (olds) => pve(olds.target, "provision", "DELETE", spec.path(olds))
1838
- };
1839
- };
1840
- var pveHandlers = (spec) => {
1841
- const ops = pveOperations(spec);
1842
- return {
1843
- list: () => Effect15.succeed([]),
1844
- read: ({ olds }) => ops.read(olds),
1845
- diff: ({ news, output }) => ops.diff(news, output),
1846
- reconcile: ({ news }) => ops.reconcile(news),
1847
- delete: ({ olds }) => ops.destroy(olds)
1848
- };
1760
+ var scalarFlagOrDie = (live, props) => {
1761
+ const scalar = typeof live === "boolean" || live === 0 || live === 1 || live === "0" || live === "1";
1762
+ return scalar ? Effect14.succeed(live) : Effect14.die(new Error(`cluster/ceph/flags/${props.flag}: GET answered ${JSON.stringify(live)}, not a bare ` + "boolean. This endpoint's success is a scalar; an empty object is what the protocol " + 'substitutes for `{"data":null}`. Check `ceph osd dump | head -1` and the cluster ' + "log rather than trust a coerced `false`."));
1849
1763
  };
1764
+ var readClusterCephFlag = (props) => runPve(props.target, "read", false, cluster3.getClusterCephFlag({ flag: props.flag })).pipe(Effect14.flatMap((live) => scalarFlagOrDie(live, props)), Effect14.map((live) => attributesOf3(live, props)));
1765
+ var readClusterCephFlagForDiff = (props) => readOrUnreadable(readClusterCephFlag(props));
1766
+ var updateForm = (props) => ({ value: flag(props.value) ?? "0" });
1767
+ var writeClusterCephFlag = (props) => runPve(props.target, "provision", true, cluster3.putClusterCephFlag({ flag: props.flag, value: updateForm(props).value }));
1850
1768
 
1851
1769
  // src/proxmox/ceph-flag.ts
1852
1770
  var ProxmoxCephFlag = Resource5("Proxmox.CephFlag");
1853
- var handlers = pveHandlers({
1854
- attributes: (live, props) => ({ flag: props.flag, value: bool(live) }),
1855
- collection: () => "cluster/ceph/flags",
1856
- createForm: (props) => ({ [props.flag]: flag(props.value) ?? "0" }),
1857
- endpoint: { update: "pve:PUT /cluster/ceph/flags/{flag}" },
1858
- matches: (attributes, props) => attributes.value === props.value,
1859
- path: (props) => `cluster/ceph/flags/${props.flag}`,
1860
- updateForm: (props) => ({ value: flag(props.value) ?? "0" })
1861
- });
1862
- var ProxmoxCephFlagProvider = () => Provider5.effect(ProxmoxCephFlag, Effect16.succeed(ProxmoxCephFlag.Provider.of({
1863
- ...handlers,
1864
- delete: () => Effect16.void,
1865
- reconcile: Effect16.fn(function* ({ news }) {
1866
- const after = yield* handlers.reconcile({ news });
1771
+ var matches3 = (attributes, props) => attributes.value === props.value;
1772
+ var ProxmoxCephFlagProvider = () => Provider5.effect(ProxmoxCephFlag, Effect15.succeed(ProxmoxCephFlag.Provider.of({
1773
+ list: () => Effect15.succeed([]),
1774
+ read: ({ olds }) => readClusterCephFlag(olds),
1775
+ diff: Effect15.fn(function* ({ news, output }) {
1776
+ if (!isResolved5(news))
1777
+ return;
1778
+ yield* guardWrite2(CEPH_FLAG_UPDATE, updateForm(news), false);
1779
+ if (output === undefined)
1780
+ return;
1781
+ const live = yield* readClusterCephFlagForDiff(news);
1782
+ if (live === UNREADABLE) {
1783
+ yield* unreadableWarning("Proxmox.CephFlag", news.flag, news.target.mount, mintTier(news.target, "read"));
1784
+ return { action: "noop" };
1785
+ }
1786
+ return { action: matches3(live, news) ? "noop" : "update" };
1787
+ }),
1788
+ delete: () => Effect15.void,
1789
+ reconcile: Effect15.fn(function* ({ news }) {
1790
+ const live = yield* readClusterCephFlag(news);
1791
+ const form = formToSend(matches3, live, news, updateForm(news));
1792
+ if (form !== undefined) {
1793
+ yield* guardWrite2(CEPH_FLAG_UPDATE, updateForm(news), false);
1794
+ yield* writeClusterCephFlag(news);
1795
+ }
1796
+ const after = yield* readClusterCephFlag(news);
1867
1797
  if (after.value !== news.value) {
1868
- return yield* Effect16.die(new Error(`cluster/ceph/flags/${news.flag}: the PUT returned no error but ceph still ` + `reports the flag ${after.value ? "set" : "clear"} rather than ` + `${news.value ? "set" : "clear"}. This endpoint's success is documented as a ` + "null body, so the status code proves nothing -- check `ceph osd dump | " + "head -1` and the cluster log. `pause` in particular is two ceph flags read " + "as one; see the header."));
1798
+ return yield* Effect15.die(new Error(`cluster/ceph/flags/${news.flag}: the PUT returned no error but ceph still ` + `reports the flag ${after.value ? "set" : "clear"} rather than ` + `${news.value ? "set" : "clear"}. This endpoint's success is documented as a ` + "null body, so the status code proves nothing -- check `ceph osd dump | " + "head -1` and the cluster log. `pause` in particular is two ceph flags read " + "as one; see the header."));
1869
1799
  }
1870
1800
  return after;
1871
1801
  })
@@ -1874,11 +1804,11 @@ var ProxmoxCephFlagProvider = () => Provider5.effect(ProxmoxCephFlag, Effect16.s
1874
1804
  import { Resource as Resource6 } from "alchemy";
1875
1805
  import { isResolved as isResolved6 } from "alchemy/Diff";
1876
1806
  import * as Provider6 from "alchemy/Provider";
1877
- import * as Effect18 from "effect/Effect";
1807
+ import * as Effect17 from "effect/Effect";
1878
1808
 
1879
1809
  // src/proxmox/ceph-fs-distilled.ts
1880
1810
  import * as nodes2 from "@distilled.cloud/proxmox/nodes";
1881
- import * as Effect17 from "effect/Effect";
1811
+ import * as Effect16 from "effect/Effect";
1882
1812
 
1883
1813
  // src/proxmox/ceph-fs-wire.ts
1884
1814
  var readRow = (live, props) => {
@@ -1906,40 +1836,40 @@ var notCreated2 = (props) => new Error(`${objectPath(props)}: the create task fi
1906
1836
  var notDestroyed = (props) => new Error(`${objectPath(props)}: the destroy task finished but the filesystem is still in ` + `GET nodes/${props.node}/ceph/fs. PVE refuses to destroy a CephFS while a PVE storage entry ` + "of type cephfs still references it and is not disabled.");
1907
1837
 
1908
1838
  // src/proxmox/ceph-fs-distilled.ts
1909
- var readFs = (props) => runPve(props.target, "read", false, nodes2.listNodeCephFs({ node: props.node })).pipe(Effect17.map((rows) => readRow(rows, props)));
1839
+ var readFs = (props) => runPve(props.target, "read", false, nodes2.listNodeCephFs({ node: props.node })).pipe(Effect16.map((rows) => readRow(rows, props)));
1910
1840
  var toDistilledCreate = (props) => ({
1911
1841
  ...createForm2(props),
1912
1842
  name: props.name,
1913
1843
  node: props.node
1914
1844
  });
1915
- var settleTask = (props, upid) => Effect17.gen(function* () {
1845
+ var settleTask = (props, upid) => Effect16.gen(function* () {
1916
1846
  for (let attempt = 0;attempt < POLL_ATTEMPTS; attempt += 1) {
1917
- const status = yield* runPve(props.target, "read", false, nodes2.getNodeTaskStatus({ node: props.node, upid })).pipe(Effect17.orElseSucceed(() => {
1847
+ const status = yield* runPve(props.target, "read", false, nodes2.getNodeTaskStatus({ node: props.node, upid })).pipe(Effect16.orElseSucceed(() => {
1918
1848
  return;
1919
1849
  }));
1920
1850
  if (status?.status === "stopped") {
1921
1851
  if (status.exitstatus === "OK")
1922
1852
  return;
1923
- return yield* Effect17.die(new Error(`${objectPath(props)}: PVE task ${upid} finished with "${status.exitstatus ?? "no exit status"}". ` + "The write returned HTTP 200 because it only forked the worker -- the real error is " + `in \`pvesh get /nodes/${props.node}/tasks/${upid}/log\`.`));
1853
+ return yield* Effect16.die(new Error(`${objectPath(props)}: PVE task ${upid} finished with "${status.exitstatus ?? "no exit status"}". ` + "The write returned HTTP 200 because it only forked the worker -- the real error is " + `in \`pvesh get /nodes/${props.node}/tasks/${upid}/log\`.`));
1924
1854
  }
1925
- yield* Effect17.sleep(POLL_SECONDS * 1000);
1855
+ yield* Effect16.sleep(POLL_SECONDS * 1000);
1926
1856
  }
1927
- return yield* Effect17.die(new Error(`${objectPath(props)}: PVE task ${upid} was still running after ` + `${String(POLL_ATTEMPTS * POLL_SECONDS)}s, or its status could not be read. Check the ` + "task log, and check that the `read` role holds Sys.Audit on " + `/nodes/${props.node} -- each call mints a new token, so the poller is never the task ` + "owner and is answered 403 rather than told to wait."));
1857
+ return yield* Effect16.die(new Error(`${objectPath(props)}: PVE task ${upid} was still running after ` + `${String(POLL_ATTEMPTS * POLL_SECONDS)}s, or its status could not be read. Check the ` + "task log, and check that the `read` role holds Sys.Audit on " + `/nodes/${props.node} -- each call mints a new token, so the poller is never the task ` + "owner and is answered 403 rather than told to wait."));
1928
1858
  });
1929
- var createFs = (props) => Effect17.gen(function* () {
1859
+ var createFs = (props) => Effect16.gen(function* () {
1930
1860
  const upid = yield* runPve(props.target, "provision", true, nodes2.updateNodeCephFs(toDistilledCreate(props)));
1931
1861
  if (upid === "") {
1932
- return yield* Effect17.die(new Error(`${objectPath(props)}: POST returned no task id. PVE wraps every answer in ` + '{"data":...} and can report success on a call that did nothing.'));
1862
+ return yield* Effect16.die(new Error(`${objectPath(props)}: POST returned no task id. PVE wraps every answer in ` + '{"data":...} and can report success on a call that did nothing.'));
1933
1863
  }
1934
1864
  yield* settleTask(props, upid);
1935
1865
  });
1936
- var destroyFs = (props) => Effect17.gen(function* () {
1866
+ var destroyFs = (props) => Effect16.gen(function* () {
1937
1867
  const upid = yield* runPve(props.target, "provision", true, nodes2.deleteNodeCephFs({
1938
1868
  node: props.node,
1939
1869
  name: props.name,
1940
1870
  ...props["remove-pools"] === true ? { remove_pools: "1" } : {},
1941
1871
  ...props["remove-storages"] === true ? { remove_storages: "1" } : {}
1942
- })).pipe(Effect17.catchTag("CephFsNotFound", () => Effect17.succeed("")));
1872
+ })).pipe(Effect16.catchTag("CephFsNotFound", () => Effect16.succeed("")));
1943
1873
  if (upid !== "")
1944
1874
  yield* settleTask(props, upid);
1945
1875
  });
@@ -1948,12 +1878,12 @@ var destroyFs = (props) => Effect17.gen(function* () {
1948
1878
  var ProxmoxCephFs = Resource6("Proxmox.CephFs", {
1949
1879
  defaultRemovalPolicy: "retain"
1950
1880
  });
1951
- var ProxmoxCephFsProvider = () => Provider6.effect(ProxmoxCephFs, Effect18.succeed(ProxmoxCephFs.Provider.of({
1952
- list: () => Effect18.succeed([]),
1953
- read: Effect18.fn(function* ({ olds }) {
1881
+ var ProxmoxCephFsProvider = () => Provider6.effect(ProxmoxCephFs, Effect17.succeed(ProxmoxCephFs.Provider.of({
1882
+ list: () => Effect17.succeed([]),
1883
+ read: Effect17.fn(function* ({ olds }) {
1954
1884
  return yield* readFs(olds);
1955
1885
  }),
1956
- diff: Effect18.fn(function* ({ news, output }) {
1886
+ diff: Effect17.fn(function* ({ news, output }) {
1957
1887
  if (!isResolved6(news))
1958
1888
  return;
1959
1889
  yield* guardWrite2(CEPH_FS_CREATE, createForm2(news), output === undefined);
@@ -1969,34 +1899,34 @@ var ProxmoxCephFsProvider = () => Provider6.effect(ProxmoxCephFs, Effect18.succe
1969
1899
  }
1970
1900
  return { action: "noop" };
1971
1901
  }),
1972
- reconcile: Effect18.fn(function* ({ news }) {
1902
+ reconcile: Effect17.fn(function* ({ news }) {
1973
1903
  const live = yield* readFs(news);
1974
1904
  if (live !== undefined)
1975
1905
  return live;
1976
1906
  yield* createFs(news);
1977
1907
  const after = yield* readFs(news);
1978
1908
  if (after === undefined)
1979
- return yield* Effect18.die(notCreated2(news));
1909
+ return yield* Effect17.die(notCreated2(news));
1980
1910
  return after;
1981
1911
  }),
1982
- delete: Effect18.fn(function* ({ olds }) {
1912
+ delete: Effect17.fn(function* ({ olds }) {
1983
1913
  if ((yield* readFs(olds)) === undefined)
1984
1914
  return;
1985
1915
  yield* destroyFs(olds);
1986
1916
  const after = yield* readFs(olds);
1987
1917
  if (after !== undefined)
1988
- return yield* Effect18.die(notDestroyed(olds));
1918
+ return yield* Effect17.die(notDestroyed(olds));
1989
1919
  })
1990
1920
  })));
1991
1921
  // src/proxmox/ceph-osd.ts
1992
1922
  import { Resource as Resource7 } from "alchemy";
1993
1923
  import { isResolved as isResolved7 } from "alchemy/Diff";
1994
1924
  import * as Provider7 from "alchemy/Provider";
1995
- import * as Effect21 from "effect/Effect";
1925
+ import * as Effect20 from "effect/Effect";
1996
1926
 
1997
1927
  // src/proxmox/ceph-osd-tree.ts
1998
1928
  import * as nodes3 from "@distilled.cloud/proxmox/nodes";
1999
- import * as Effect19 from "effect/Effect";
1929
+ import * as Effect18 from "effect/Effect";
2000
1930
  var branches = (node) => (Array.isArray(node["children"]) ? node["children"] : []).filter((child) => typeof child === "object" && child !== null);
2001
1931
  var osdLeaves = (tree) => {
2002
1932
  const root = tree["root"];
@@ -2022,23 +1952,23 @@ var osdAttributes = (leaf, props) => ({
2022
1952
  status: text(leaf["status"]),
2023
1953
  total_space: num(leaf["total_space"], 0)
2024
1954
  });
2025
- var readOsd = (props) => runPve(props.target, "read", false, nodes3.getNodeCephOsd({ node: props.node })).pipe(Effect19.map((t) => {
1955
+ var readOsd = (props) => runPve(props.target, "read", false, nodes3.getNodeCephOsd({ node: props.node })).pipe(Effect18.map((t) => {
2026
1956
  const leaf = findOsd(t, props.osdid);
2027
1957
  return leaf === undefined ? undefined : osdAttributes(leaf, props);
2028
1958
  }));
2029
1959
 
2030
1960
  // src/proxmox/ceph-osd-write.ts
2031
1961
  import * as nodes4 from "@distilled.cloud/proxmox/nodes";
2032
- import * as Effect20 from "effect/Effect";
1962
+ import * as Effect19 from "effect/Effect";
2033
1963
  var OSD_CREATE_ENDPOINT = "pve:POST /nodes/{node}/ceph/osd";
2034
1964
  var describe = (props) => `osd.${String(props.osdid)} on ${props.node}`;
2035
1965
  var createOsdForm = (props, dev) => ({
2036
1966
  dev,
2037
1967
  ...props.device_class === undefined ? {} : { "crush-device-class": props.device_class }
2038
1968
  });
2039
- var createOsd = Effect20.fn(function* (news) {
1969
+ var createOsd = Effect19.fn(function* (news) {
2040
1970
  if (news.dev === undefined) {
2041
- return yield* Effect20.die(new Error(`${describe(news)}: no such OSD in the CRUSH tree, and no \`dev\` was declared. ` + "Without a device this resource is an ASSERTION over an OSD that must already " + "exist. Declare `dev` to let it create one -- which WIPES that device -- or fix " + "the declaration; if the disk was there yesterday, a replica is missing and Ceph " + "is degraded."));
1971
+ return yield* Effect19.die(new Error(`${describe(news)}: no such OSD in the CRUSH tree, and no \`dev\` was declared. ` + "Without a device this resource is an ASSERTION over an OSD that must already " + "exist. Declare `dev` to let it create one -- which WIPES that device -- or fix " + "the declaration; if the disk was there yesterday, a replica is missing and Ceph " + "is degraded."));
2042
1972
  }
2043
1973
  const form = createOsdForm(news, news.dev);
2044
1974
  yield* guardForm(OSD_CREATE_ENDPOINT, form, true);
@@ -2049,7 +1979,7 @@ var createOsd = Effect20.fn(function* (news) {
2049
1979
  }));
2050
1980
  const created = yield* readOsd(news);
2051
1981
  if (created === undefined) {
2052
- return yield* Effect20.die(new Error(`${describe(news)}: the create returned no error but osd.${String(news.osdid)} is ` + "still absent. Ceph allocates OSD ids and cannot be told which to use, so it most " + "likely assigned a different number -- check `ceph osd tree`, and declare the id it " + "actually gave the device rather than deploying again."));
1982
+ return yield* Effect19.die(new Error(`${describe(news)}: the create returned no error but osd.${String(news.osdid)} is ` + "still absent. Ceph allocates OSD ids and cannot be told which to use, so it most " + "likely assigned a different number -- check `ceph osd tree`, and declare the id it " + "actually gave the device rather than deploying again."));
2053
1983
  }
2054
1984
  return created;
2055
1985
  });
@@ -2065,12 +1995,12 @@ var ProxmoxCephOsd = Resource7("Proxmox.CephOsd", {
2065
1995
  });
2066
1996
  var settled = (live, props) => (props.host === undefined || props.host === live.host) && (props.device_class === undefined || props.device_class === live.device_class);
2067
1997
  var describe2 = (props) => `osd.${String(props.osdid)} (read via nodes/${props.node}/ceph/osd)`;
2068
- var handlers2 = {
2069
- list: () => Effect21.succeed([]),
2070
- read: Effect21.fn(function* ({ olds }) {
1998
+ var handlers = {
1999
+ list: () => Effect20.succeed([]),
2000
+ read: Effect20.fn(function* ({ olds }) {
2071
2001
  return yield* readOsd(olds);
2072
2002
  }),
2073
- diff: Effect21.fn(function* ({
2003
+ diff: Effect20.fn(function* ({
2074
2004
  news,
2075
2005
  output
2076
2006
  }) {
@@ -2083,27 +2013,27 @@ var handlers2 = {
2083
2013
  return { action: "update" };
2084
2014
  return settled(live, news) ? { action: "noop" } : { action: "update" };
2085
2015
  }),
2086
- reconcile: Effect21.fn(function* ({ news }) {
2016
+ reconcile: Effect20.fn(function* ({ news }) {
2087
2017
  const live = yield* readOsd(news);
2088
2018
  if (live === undefined) {
2089
2019
  return yield* createOsd(news);
2090
2020
  }
2091
2021
  if (!settled(live, news)) {
2092
- return yield* Effect21.die(new Error(`${describe2(news)}: exists but not as declared -- live host=${live.host} ` + `device_class=${live.device_class}. Nothing here moves an OSD between hosts or ` + "reclassifies it; fix the declaration, or move it deliberately with `ceph osd crush " + "move` / `ceph osd crush set-device-class` and deploy again."));
2022
+ return yield* Effect20.die(new Error(`${describe2(news)}: exists but not as declared -- live host=${live.host} ` + `device_class=${live.device_class}. Nothing here moves an OSD between hosts or ` + "reclassifies it; fix the declaration, or move it deliberately with `ceph osd crush " + "move` / `ceph osd crush set-device-class` and deploy again."));
2093
2023
  }
2094
2024
  return live;
2095
2025
  }),
2096
- delete: Effect21.fn(function* ({ olds }) {
2026
+ delete: Effect20.fn(function* ({ olds }) {
2097
2027
  yield* destroyOsd(olds);
2098
2028
  })
2099
2029
  };
2100
- var ProxmoxCephOsdProvider = () => Provider7.effect(ProxmoxCephOsd, Effect21.succeed(ProxmoxCephOsd.Provider.of(handlers2)));
2030
+ var ProxmoxCephOsdProvider = () => Provider7.effect(ProxmoxCephOsd, Effect20.succeed(ProxmoxCephOsd.Provider.of(handlers)));
2101
2031
  // src/proxmox/ceph-pool.ts
2102
2032
  import { Resource as Resource8 } from "alchemy";
2103
2033
  import { isResolved as isResolved8 } from "alchemy/Diff";
2104
2034
  import * as Provider8 from "alchemy/Provider";
2105
2035
  import * as nodes7 from "@distilled.cloud/proxmox/nodes";
2106
- import * as Effect24 from "effect/Effect";
2036
+ import * as Effect23 from "effect/Effect";
2107
2037
 
2108
2038
  // src/proxmox/ceph-pool-form.ts
2109
2039
  var object = (props) => `nodes/${props.node}/ceph/pool/${props.name}`;
@@ -2132,22 +2062,22 @@ var createBody = (props) => ({
2132
2062
 
2133
2063
  // src/proxmox/ceph-pool-settle.ts
2134
2064
  import * as nodes5 from "@distilled.cloud/proxmox/nodes";
2135
- import * as Effect22 from "effect/Effect";
2136
- var confirmAbsent = (props, describe3) => runPve(props.target, "read", false, nodes5.listNodeCephPool({ node: props.node })).pipe(Effect22.flatMap((rows) => rows.some((row) => row.pool_name === props.name) ? Effect22.die(new Error(`${describe3}: the cluster lists this pool but its status could not be read, ` + "so this deploy will NOT create over it. Check that the node is up and that the " + "read role holds Sys.Audit or Datastore.Audit on / -- a create here would apply " + "pg_num to a live pool and start a PG merge.")) : Effect22.void));
2137
- var settle = (props, read, done) => Effect22.gen(function* () {
2065
+ import * as Effect21 from "effect/Effect";
2066
+ var confirmAbsent = (props, describe3) => runPve(props.target, "read", false, nodes5.listNodeCephPool({ node: props.node })).pipe(Effect21.flatMap((rows) => rows.some((row) => row.pool_name === props.name) ? Effect21.die(new Error(`${describe3}: the cluster lists this pool but its status could not be read, ` + "so this deploy will NOT create over it. Check that the node is up and that the " + "read role holds Sys.Audit or Datastore.Audit on / -- a create here would apply " + "pg_num to a live pool and start a PG merge.")) : Effect21.void));
2067
+ var settle = (props, read, done) => Effect21.gen(function* () {
2138
2068
  for (let attempt = 0;attempt < 30; attempt += 1) {
2139
2069
  const live = yield* read(props);
2140
2070
  if (done(live))
2141
2071
  return live;
2142
- yield* Effect22.sleep("2 seconds");
2072
+ yield* Effect21.sleep("2 seconds");
2143
2073
  }
2144
2074
  return yield* read(props);
2145
2075
  });
2146
2076
 
2147
2077
  // src/proxmox/ceph-pool-wire.ts
2148
2078
  import * as nodes6 from "@distilled.cloud/proxmox/nodes";
2149
- import * as Effect23 from "effect/Effect";
2150
- var attributesOf3 = (live, props) => {
2079
+ import * as Effect22 from "effect/Effect";
2080
+ var attributesOf4 = (live, props) => {
2151
2081
  const row = live;
2152
2082
  if (typeof row["name"] !== "string")
2153
2083
  return;
@@ -2169,7 +2099,7 @@ var attributesOf3 = (live, props) => {
2169
2099
  target_size_ratio: num(row["target_size_ratio"], UNSET)
2170
2100
  };
2171
2101
  };
2172
- var readPoolStatus = (props) => runPve(props.target, "read", false, nodes6.getNodeCephPoolStatus({ name: props.name, node: props.node, verbose: "1" })).pipe(Effect23.map((live) => attributesOf3(live, props)), Effect23.catchTag("CephPoolNotFound", () => Effect23.succeed(undefined)));
2102
+ var readPoolStatus = (props) => runPve(props.target, "read", false, nodes6.getNodeCephPoolStatus({ name: props.name, node: props.node, verbose: "1" })).pipe(Effect22.map((live) => attributesOf4(live, props)), Effect22.catchTag("CephPoolNotFound", () => Effect22.succeed(undefined)));
2173
2103
  var CEPH_POOL_CREATE = "pve:POST /nodes/{node}/ceph/pool";
2174
2104
  var CEPH_POOL_UPDATE = "pve:PUT /nodes/{node}/ceph/pool/{name}";
2175
2105
  var toDistilledCreate2 = (props) => ({
@@ -2186,11 +2116,11 @@ var toDistilledUpdate = (props) => ({
2186
2116
  var ProxmoxCephPool = Resource8("Proxmox.CephPool", {
2187
2117
  defaultRemovalPolicy: "retain"
2188
2118
  });
2189
- var matches3 = (attributes, props) => same(props.size, attributes.size, attributes.nosizechange) && same(props.min_size, attributes.min_size, attributes.nosizechange) && same(props.pg_autoscale_mode, attributes.pg_autoscale_mode) && same(hint(props.pg_num_min), attributes.pg_num_min, attributes.nopgchange) && same(props.crush_rule, attributes.crush_rule, attributes.crush_rule === "") && same(hint(props.target_size), attributes.target_size);
2190
- var ProxmoxCephPoolProvider = () => Provider8.effect(ProxmoxCephPool, Effect24.succeed(ProxmoxCephPool.Provider.of({
2191
- list: () => Effect24.succeed([]),
2119
+ var matches4 = (attributes, props) => same(props.size, attributes.size, attributes.nosizechange) && same(props.min_size, attributes.min_size, attributes.nosizechange) && same(props.pg_autoscale_mode, attributes.pg_autoscale_mode) && same(hint(props.pg_num_min), attributes.pg_num_min, attributes.nopgchange) && same(props.crush_rule, attributes.crush_rule, attributes.crush_rule === "") && same(hint(props.target_size), attributes.target_size);
2120
+ var ProxmoxCephPoolProvider = () => Provider8.effect(ProxmoxCephPool, Effect23.succeed(ProxmoxCephPool.Provider.of({
2121
+ list: () => Effect23.succeed([]),
2192
2122
  read: ({ olds }) => readPoolStatus(olds),
2193
- diff: Effect24.fn(function* ({ news, output }) {
2123
+ diff: Effect23.fn(function* ({ news, output }) {
2194
2124
  if (!isResolved8(news))
2195
2125
  return;
2196
2126
  yield* guardWrite2(CEPH_POOL_CREATE, createBody(news), output === undefined);
@@ -2202,9 +2132,9 @@ var ProxmoxCephPoolProvider = () => Provider8.effect(ProxmoxCephPool, Effect24.s
2202
2132
  yield* guardWrite2(CEPH_POOL_CREATE, createBody(news), true);
2203
2133
  return { action: "update" };
2204
2134
  }
2205
- return matches3(live, news) ? { action: "noop" } : { action: "update" };
2135
+ return matches4(live, news) ? { action: "noop" } : { action: "update" };
2206
2136
  }),
2207
- reconcile: Effect24.fn(function* ({ news }) {
2137
+ reconcile: Effect23.fn(function* ({ news }) {
2208
2138
  const live = yield* readPoolStatus(news);
2209
2139
  let upid;
2210
2140
  if (live === undefined) {
@@ -2212,36 +2142,36 @@ var ProxmoxCephPoolProvider = () => Provider8.effect(ProxmoxCephPool, Effect24.s
2212
2142
  yield* confirmAbsent(news, object(news));
2213
2143
  upid = yield* runPve(news.target, "provision", true, nodes7.createNodeCephPool(toDistilledCreate2(news)));
2214
2144
  } else {
2215
- const form = formToSend(matches3, live, news, updateBody(news));
2145
+ const form = formToSend(matches4, live, news, updateBody(news));
2216
2146
  if (form !== undefined) {
2217
2147
  yield* guardWrite2(CEPH_POOL_UPDATE, updateBody(news), false);
2218
2148
  upid = yield* runPve(news.target, "provision", true, nodes7.putNodeCephPool(toDistilledUpdate(news)));
2219
2149
  }
2220
2150
  }
2221
- const after = yield* settle(news, readPoolStatus, (row) => row !== undefined && matches3(row, news));
2222
- if (after === undefined || !matches3(after, news)) {
2223
- return yield* Effect24.die(new Error(`${object(news)}: the write returned no error but the pool still does not match ` + `the declaration after 60s. PVE answered with task ${upid ?? "(none)"} -- read ` + "its log with `pvesh get /nodes/<node>/tasks/<upid>/log` to see what Ceph " + "refused."));
2151
+ const after = yield* settle(news, readPoolStatus, (row) => row !== undefined && matches4(row, news));
2152
+ if (after === undefined || !matches4(after, news)) {
2153
+ return yield* Effect23.die(new Error(`${object(news)}: the write returned no error but the pool still does not match ` + `the declaration after 60s. PVE answered with task ${upid ?? "(none)"} -- read ` + "its log with `pvesh get /nodes/<node>/tasks/<upid>/log` to see what Ceph " + "refused."));
2224
2154
  }
2225
2155
  return after;
2226
2156
  }),
2227
- delete: Effect24.fn(function* ({ olds }) {
2157
+ delete: Effect23.fn(function* ({ olds }) {
2228
2158
  yield* runPve(olds.target, "provision", true, nodes7.deleteNodeCephPool({ name: olds.name, node: olds.node }));
2229
2159
  const left = yield* settle(olds, readPoolStatus, (row) => row === undefined);
2230
2160
  if (left !== undefined) {
2231
- return yield* Effect24.die(new Error(`${object(olds)}: the DELETE returned no error but the pool is still there after ` + "60s. Either a storage on it still holds RBD images, or the mons are running " + "with mon_allow_pool_delete false."));
2161
+ return yield* Effect23.die(new Error(`${object(olds)}: the DELETE returned no error but the pool is still there after ` + "60s. Either a storage on it still holds RBD images, or the mons are running " + "with mon_allow_pool_delete false."));
2232
2162
  }
2233
2163
  })
2234
2164
  })));
2235
2165
  // src/proxmox/firewall-alias.ts
2236
2166
  import { Resource as Resource9 } from "alchemy";
2237
2167
  import * as Provider9 from "alchemy/Provider";
2238
- import * as Effect26 from "effect/Effect";
2168
+ import * as Effect25 from "effect/Effect";
2239
2169
 
2240
2170
  // src/proxmox/firewall-alias-lifecycle.ts
2241
2171
  import { isResolved as isResolved9 } from "alchemy/Diff";
2242
- import * as cluster3 from "@distilled.cloud/proxmox/cluster";
2172
+ import * as cluster4 from "@distilled.cloud/proxmox/cluster";
2243
2173
  import { ProxmoxParseError as ProxmoxParseError2 } from "@distilled.cloud/proxmox/Errors";
2244
- import * as Effect25 from "effect/Effect";
2174
+ import * as Effect24 from "effect/Effect";
2245
2175
 
2246
2176
  // src/proxmox/firewall-alias-form.ts
2247
2177
  var fold = (name) => name.trim().toLowerCase();
@@ -2283,20 +2213,20 @@ var firewallAliasSpec = {
2283
2213
 
2284
2214
  // src/proxmox/firewall-alias-lifecycle.ts
2285
2215
  var { guardCreate: guardCreate2, guardUpdate: guardUpdate2 } = specGuards(firewallAliasSpec);
2286
- var readFirewallAlias = (props) => runPve(props.target, "read", false, cluster3.getClusterFirewallAlias({ name: props.name })).pipe(Effect25.flatMap((live) => {
2216
+ var readFirewallAlias = (props) => runPve(props.target, "read", false, cluster4.getClusterFirewallAlias({ name: props.name })).pipe(Effect24.flatMap((live) => {
2287
2217
  if (live === null || typeof live !== "object" || Array.isArray(live) || !("name" in live) || typeof live.name !== "string" || fold(live.name) !== fold(props.name) || !("cidr" in live) || typeof live.cidr !== "string" || cidr(live.cidr) === "") {
2288
- return Effect25.fail(new ProxmoxParseError2({
2218
+ return Effect24.fail(new ProxmoxParseError2({
2289
2219
  body: undefined,
2290
2220
  cause: "Firewall alias response does not match the requested vendor identity"
2291
2221
  }));
2292
2222
  }
2293
- return Effect25.succeed(firewallAliasSpec.attributes({ ...live }, props));
2294
- }), Effect25.catchTag("FirewallAliasNotFound", () => Effect25.succeed(undefined)));
2295
- var deleteFirewallAlias = (props) => runPve(props.target, "provision", true, cluster3.deleteClusterFirewallAlias({ name: props.name }));
2223
+ return Effect24.succeed(firewallAliasSpec.attributes({ ...live }, props));
2224
+ }), Effect24.catchTag("FirewallAliasNotFound", () => Effect24.succeed(undefined)));
2225
+ var deleteFirewallAlias = (props) => runPve(props.target, "provision", true, cluster4.deleteClusterFirewallAlias({ name: props.name }));
2296
2226
  var firewallAliasHandlers = {
2297
- list: () => Effect25.succeed([]),
2227
+ list: () => Effect24.succeed([]),
2298
2228
  read: ({ olds }) => readFirewallAlias(olds),
2299
- diff: Effect25.fn(function* ({
2229
+ diff: Effect24.fn(function* ({
2300
2230
  news,
2301
2231
  output
2302
2232
  }) {
@@ -2315,20 +2245,20 @@ var firewallAliasHandlers = {
2315
2245
  }
2316
2246
  return { action: firewallAliasSpec.matches(live, news) ? "noop" : "update" };
2317
2247
  }),
2318
- reconcile: Effect25.fn(function* ({ news }) {
2248
+ reconcile: Effect24.fn(function* ({ news }) {
2319
2249
  const live = yield* readFirewallAlias(news);
2320
2250
  yield* guardCreate2(news, live === undefined);
2321
2251
  yield* guardUpdate2(news);
2322
2252
  if (live === undefined) {
2323
- yield* runPve(news.target, "provision", true, cluster3.createClusterFirewallAlias(firewallAliasSpec.createForm(news)));
2253
+ yield* runPve(news.target, "provision", true, cluster4.createClusterFirewallAlias(firewallAliasSpec.createForm(news)));
2324
2254
  } else {
2325
2255
  const form = formToSend(firewallAliasSpec.matches, live, news, firewallAliasSpec.updateForm(news));
2326
2256
  if (form !== undefined)
2327
- yield* runPve(news.target, "provision", true, cluster3.putClusterFirewallAlias({ ...form, name: news.name }));
2257
+ yield* runPve(news.target, "provision", true, cluster4.putClusterFirewallAlias({ ...form, name: news.name }));
2328
2258
  }
2329
2259
  const after = yield* readFirewallAlias(news);
2330
2260
  if (after === undefined)
2331
- return yield* Effect25.fail(new Error(`${firewallAliasSpec.path(news)}: write returned success but the resource is still absent`));
2261
+ return yield* Effect24.fail(new Error(`${firewallAliasSpec.path(news)}: write returned success but the resource is still absent`));
2332
2262
  return after;
2333
2263
  }),
2334
2264
  delete: ({ olds }) => deleteFirewallAlias(olds)
@@ -2336,17 +2266,17 @@ var firewallAliasHandlers = {
2336
2266
 
2337
2267
  // src/proxmox/firewall-alias.ts
2338
2268
  var ProxmoxFirewallAlias = Resource9("Proxmox.FirewallAlias");
2339
- var ProxmoxFirewallAliasProvider = () => Provider9.effect(ProxmoxFirewallAlias, Effect26.succeed(ProxmoxFirewallAlias.Provider.of(firewallAliasHandlers)));
2269
+ var ProxmoxFirewallAliasProvider = () => Provider9.effect(ProxmoxFirewallAlias, Effect25.succeed(ProxmoxFirewallAlias.Provider.of(firewallAliasHandlers)));
2340
2270
  // src/proxmox/group.ts
2341
2271
  import { Resource as Resource10 } from "alchemy";
2342
2272
  import { isResolved as isResolved10 } from "alchemy/Diff";
2343
2273
  import * as Provider10 from "alchemy/Provider";
2344
2274
  import * as access4 from "@distilled.cloud/proxmox/access";
2345
- import * as Effect28 from "effect/Effect";
2275
+ import * as Effect27 from "effect/Effect";
2346
2276
 
2347
2277
  // src/proxmox/group-wire.ts
2348
2278
  import * as access3 from "@distilled.cloud/proxmox/access";
2349
- import * as Effect27 from "effect/Effect";
2279
+ import * as Effect26 from "effect/Effect";
2350
2280
  var GROUP_CREATE = "pve:POST /access/groups";
2351
2281
  var GROUP_UPDATE = "pve:PUT /access/groups/{groupid}";
2352
2282
  var storedComment = (comment2) => {
@@ -2361,70 +2291,188 @@ var createForm3 = (props) => ({
2361
2291
  comment: storedComment(props.comment),
2362
2292
  groupid: props.groupid
2363
2293
  });
2364
- var updateForm = (props) => ({
2294
+ var updateForm2 = (props) => ({
2365
2295
  comment: storedComment(props.comment),
2366
2296
  groupid: props.groupid
2367
2297
  });
2368
- var attributesOf4 = (live, props) => ({
2298
+ var attributesOf5 = (live, props) => ({
2369
2299
  comment: text(live.comment),
2370
2300
  groupid: props.groupid,
2371
2301
  members: memberList(live.members)
2372
2302
  });
2373
- var matches4 = (attributes, props) => attributes.comment === storedComment(props.comment);
2374
- var readGroupOrFail = (props) => readOrUnreadable(runPve(props.target, "read", false, access3.getAccessGroup({ groupid: props.groupid }))).pipe(Effect27.map((live) => live === UNREADABLE ? UNREADABLE : live.members === undefined ? undefined : attributesOf4(live, props)));
2375
- var readGroup = (props) => readGroupOrFail(props).pipe(Effect27.catchTag("GroupNotFound", () => Effect27.succeed(undefined)));
2303
+ var matches5 = (attributes, props) => attributes.comment === storedComment(props.comment);
2304
+ var readGroupOrFail = (props) => readOrUnreadable(runPve(props.target, "read", false, access3.getAccessGroup({ groupid: props.groupid }))).pipe(Effect26.map((live) => live === UNREADABLE ? UNREADABLE : live.members === undefined ? undefined : attributesOf5(live, props)));
2305
+ var readGroup = (props) => readGroupOrFail(props).pipe(Effect26.catchTag("GroupNotFound", () => Effect26.succeed(undefined)));
2376
2306
  var dropUnreadable3 = (live) => live === UNREADABLE ? undefined : live;
2377
2307
 
2378
2308
  // src/proxmox/group.ts
2379
2309
  var ProxmoxGroup = Resource10("Proxmox.Group", {
2380
2310
  defaultRemovalPolicy: "retain"
2381
2311
  });
2382
- var ProxmoxGroupProvider = () => Provider10.effect(ProxmoxGroup, Effect28.succeed(ProxmoxGroup.Provider.of({
2383
- list: () => Effect28.succeed([]),
2384
- read: Effect28.fn(function* ({ olds, output }) {
2312
+ var ProxmoxGroupProvider = () => Provider10.effect(ProxmoxGroup, Effect27.succeed(ProxmoxGroup.Provider.of({
2313
+ list: () => Effect27.succeed([]),
2314
+ read: Effect27.fn(function* ({ olds, output }) {
2385
2315
  return dropUnreadable3(yield* output === undefined ? readGroup(olds) : readGroupOrFail(olds));
2386
2316
  }),
2387
- diff: Effect28.fn(function* ({ news, output }) {
2317
+ diff: Effect27.fn(function* ({ news, output }) {
2388
2318
  if (!isResolved10(news))
2389
2319
  return;
2390
2320
  yield* guardWrite2(GROUP_CREATE, createForm3(news), output === undefined);
2391
- yield* guardWrite2(GROUP_UPDATE, updateForm(news), false);
2321
+ yield* guardWrite2(GROUP_UPDATE, updateForm2(news), false);
2392
2322
  if (output === undefined)
2393
2323
  return;
2394
2324
  const live = yield* readGroupOrFail(news);
2395
2325
  if (live === UNREADABLE) {
2396
- yield* unreadableWarning("Proxmox.Group", news.groupid);
2326
+ yield* unreadableWarning("Proxmox.Group", news.groupid, news.target.mount, mintTier(news.target, "read"));
2397
2327
  return { action: "noop" };
2398
2328
  }
2399
2329
  if (live === undefined) {
2400
2330
  yield* guardWrite2(GROUP_CREATE, createForm3(news), true);
2401
2331
  return { action: "update" };
2402
2332
  }
2403
- return matches4(live, news) ? { action: "noop" } : { action: "update" };
2333
+ return matches5(live, news) ? { action: "noop" } : { action: "update" };
2404
2334
  }),
2405
- reconcile: Effect28.fn(function* ({ news }) {
2335
+ reconcile: Effect27.fn(function* ({ news }) {
2406
2336
  const before = dropUnreadable3(yield* readGroup(news));
2407
2337
  yield* guardWrite2(GROUP_CREATE, createForm3(news), before === undefined);
2408
- yield* guardWrite2(GROUP_UPDATE, updateForm(news), false);
2338
+ yield* guardWrite2(GROUP_UPDATE, updateForm2(news), false);
2409
2339
  if (before === undefined) {
2410
2340
  yield* runPve(news.target, "provision", true, access4.createAccessGroup(createForm3(news)));
2411
- } else if (!matches4(before, news)) {
2412
- yield* runPve(news.target, "provision", true, access4.putAccessGroup(updateForm(news)));
2341
+ } else if (!matches5(before, news)) {
2342
+ yield* runPve(news.target, "provision", true, access4.putAccessGroup(updateForm2(news)));
2413
2343
  }
2414
2344
  const after = dropUnreadable3(yield* readGroup(news));
2415
2345
  if (after === undefined) {
2416
- return yield* Effect28.die(new Error(`access/groups/${news.groupid}: the write returned no error but the group is ` + 'still absent. PVE wraps every answer in {"data":...} and can report success ' + "on a call that did nothing -- read back rather than trusting the status code."));
2346
+ return yield* Effect27.die(new Error(`access/groups/${news.groupid}: the write returned no error but the group is ` + 'still absent. PVE wraps every answer in {"data":...} and can report success ' + "on a call that did nothing -- read back rather than trusting the status code."));
2417
2347
  }
2418
2348
  return after;
2419
2349
  }),
2420
- delete: Effect28.fn(function* ({ olds }) {
2350
+ delete: Effect27.fn(function* ({ olds }) {
2421
2351
  yield* runPve(olds.target, "provision", true, access4.deleteAccessGroup({ groupid: olds.groupid }));
2422
2352
  })
2423
2353
  })));
2424
2354
  // src/proxmox/ha-resource.ts
2425
2355
  import { Resource as Resource11 } from "alchemy";
2426
2356
  import * as Provider11 from "alchemy/Provider";
2357
+ import * as Effect30 from "effect/Effect";
2358
+
2359
+ // src/proxmox/resource.ts
2360
+ import { isResolved as isResolved11 } from "alchemy/Diff";
2427
2361
  import * as Effect29 from "effect/Effect";
2362
+
2363
+ // src/proxmox/client.ts
2364
+ import * as Effect28 from "effect/Effect";
2365
+ import * as HttpClient5 from "effect/unstable/http/HttpClient";
2366
+ import * as HttpClientRequest2 from "effect/unstable/http/HttpClientRequest";
2367
+ class PveError extends Error {
2368
+ status;
2369
+ method;
2370
+ path;
2371
+ constructor(status, method, path, detail) {
2372
+ super(`PVE ${method} ${path} -> ${String(status)}: ${detail}`);
2373
+ this.status = status;
2374
+ this.method = method;
2375
+ this.path = path;
2376
+ this.name = "PveError";
2377
+ }
2378
+ }
2379
+ var clusterExhausted = (method, path, attempts) => new PveError(0, method, path, `all members failed: ${attempts.map((a) => `${a.member} (${a.why})`).join("; ")}`);
2380
+ var encode = (form) => {
2381
+ const params = new URLSearchParams;
2382
+ for (const [key, value] of Object.entries(form)) {
2383
+ if (typeof value === "string")
2384
+ params.append(key, value);
2385
+ else
2386
+ for (const item of value)
2387
+ params.append(key, item);
2388
+ }
2389
+ return params.toString();
2390
+ };
2391
+ var buildRequest = (method, apiBase, path, credential, target, form) => {
2392
+ const url = `${apiBase}/${path}`;
2393
+ return HttpClientRequest2.make(method)(url).pipe(HttpClientRequest2.setHeaders({ Authorization: authorization(credential, target) }), form === undefined ? (self) => self : HttpClientRequest2.bodyText(encode(form), "application/x-www-form-urlencoded"));
2394
+ };
2395
+ var executeOne = (target, credential, method, path, form, apiBase) => Effect28.gen(function* () {
2396
+ const client = yield* HttpClient5.HttpClient;
2397
+ const request = buildRequest(method, apiBase, path, credential, target, form);
2398
+ return yield* client.execute(request).pipe(Effect28.mapError((cause) => new PveError(0, method, path, String(cause))));
2399
+ });
2400
+ var readResponse = (response, method, path) => Effect28.gen(function* () {
2401
+ if (response.status < 200 || response.status >= 300) {
2402
+ const detail = yield* response.text.pipe(Effect28.orElseSucceed(() => ""));
2403
+ return yield* Effect28.fail(new PveError(response.status, method, path, detail.slice(0, 300)));
2404
+ }
2405
+ const body2 = yield* response.json.pipe(Effect28.mapError((cause) => new PveError(0, method, path, String(cause))));
2406
+ return body2.data;
2407
+ });
2408
+ var pveWith = (target, credential, method, path, form) => Effect28.gen(function* () {
2409
+ const response = target.scheme === "pve" ? yield* executeOnCluster(target, method, path, (apiBase) => buildRequest(method, apiBase, path, credential, target, form)).pipe(Effect28.mapError((failure) => failure.tag === "cluster" ? clusterExhausted(failure.method, failure.path, failure.attempts) : new PveError(0, method, path, String(failure)))) : yield* executeOne(target, credential, method, path, form, target.api);
2410
+ return yield* readResponse(response, method, path);
2411
+ });
2412
+ var pve = (target, role, method, path, form) => Effect28.gen(function* () {
2413
+ const credential = yield* leased(target, role);
2414
+ return yield* pveWith(target, credential, method, path, form);
2415
+ });
2416
+
2417
+ // src/proxmox/resource.ts
2418
+ var pveOperations = (spec) => {
2419
+ const { guardCreate: guardCreate3, guardUpdate: guardUpdate3 } = specGuards(spec);
2420
+ const read = (props) => pve(props.target, spec.readRole ?? "read", "GET", spec.path(props)).pipe(Effect29.map((data) => data == null ? undefined : spec.attributes(data, props)), Effect29.orElseSucceed(() => {
2421
+ return;
2422
+ }));
2423
+ return {
2424
+ guardCreate: guardCreate3,
2425
+ guardUpdate: guardUpdate3,
2426
+ read,
2427
+ diff: (news, output) => Effect29.gen(function* () {
2428
+ if (!isResolved11(news))
2429
+ return;
2430
+ yield* guardCreate3(news, output === undefined);
2431
+ yield* guardUpdate3(news);
2432
+ if (output === undefined)
2433
+ return;
2434
+ const live = yield* read(news);
2435
+ if (live === undefined) {
2436
+ yield* guardCreate3(news, true);
2437
+ return { action: "update" };
2438
+ }
2439
+ if (spec.matches(live, news))
2440
+ return { action: "noop" };
2441
+ return spec.updateForm === undefined ? { action: "replace" } : { action: "update" };
2442
+ }),
2443
+ reconcile: (news) => Effect29.gen(function* () {
2444
+ const live = yield* read(news);
2445
+ yield* guardCreate3(news, live === undefined);
2446
+ yield* guardUpdate3(news);
2447
+ if (live === undefined) {
2448
+ yield* pve(news.target, "provision", "POST", spec.collection(news), spec.createForm(news));
2449
+ } else if (spec.updateForm !== undefined) {
2450
+ const form = formToSend(spec.matches, live, news, spec.updateForm(news));
2451
+ if (form !== undefined) {
2452
+ yield* pve(news.target, "provision", "PUT", spec.path(news), form);
2453
+ }
2454
+ }
2455
+ const after = yield* read(news);
2456
+ if (after === undefined) {
2457
+ return yield* Effect29.die(new Error(`${spec.path(news)}: the write returned no error but the object is still absent. ` + 'PVE wraps every answer in {"data":...} and can report success on a call that did ' + "nothing -- read back rather than trusting the status code."));
2458
+ }
2459
+ return after;
2460
+ }),
2461
+ destroy: (olds) => pve(olds.target, "provision", "DELETE", spec.path(olds))
2462
+ };
2463
+ };
2464
+ var pveHandlers = (spec) => {
2465
+ const ops = pveOperations(spec);
2466
+ return {
2467
+ list: () => Effect29.succeed([]),
2468
+ read: ({ olds }) => ops.read(olds),
2469
+ diff: ({ news, output }) => ops.diff(news, output),
2470
+ reconcile: ({ news }) => ops.reconcile(news),
2471
+ delete: ({ olds }) => ops.destroy(olds)
2472
+ };
2473
+ };
2474
+
2475
+ // src/proxmox/ha-resource.ts
2428
2476
  var ProxmoxHaResource = Resource11("Proxmox.HaResource");
2429
2477
  var kind = (sid) => sid.split(":")[0] ?? "";
2430
2478
  var shape3 = (props) => ({
@@ -2433,7 +2481,7 @@ var shape3 = (props) => ({
2433
2481
  max_restart: String(props.max_restart ?? 1),
2434
2482
  state: props.state ?? "started"
2435
2483
  });
2436
- var handlers3 = pveHandlers({
2484
+ var handlers2 = pveHandlers({
2437
2485
  attributes: (live, props) => ({
2438
2486
  comment: typeof live["comment"] === "string" ? live["comment"] : "",
2439
2487
  max_relocate: num(live["max_relocate"], 1),
@@ -2452,11 +2500,11 @@ var handlers3 = pveHandlers({
2452
2500
  path: (props) => `cluster/ha/resources/${props.sid}`,
2453
2501
  updateForm: shape3
2454
2502
  });
2455
- var ProxmoxHaResourceProvider = () => Provider11.effect(ProxmoxHaResource, Effect29.succeed(ProxmoxHaResource.Provider.of(handlers3)));
2503
+ var ProxmoxHaResourceProvider = () => Provider11.effect(ProxmoxHaResource, Effect30.succeed(ProxmoxHaResource.Provider.of(handlers2)));
2456
2504
  // src/proxmox/ha-rule.ts
2457
2505
  import { Resource as Resource12 } from "alchemy";
2458
2506
  import * as Provider12 from "alchemy/Provider";
2459
- import * as Effect30 from "effect/Effect";
2507
+ import * as Effect31 from "effect/Effect";
2460
2508
 
2461
2509
  // src/proxmox/ha-rule-form.ts
2462
2510
  var nodeList = (value) => {
@@ -2504,7 +2552,7 @@ var clearList = (props) => Object.entries(optional(props)).filter(([, value]) =>
2504
2552
 
2505
2553
  // src/proxmox/ha-rule.ts
2506
2554
  var ProxmoxHaRule = Resource12("Proxmox.HaRule");
2507
- var handlers4 = pveHandlers({
2555
+ var handlers3 = pveHandlers({
2508
2556
  attributes: (live, props) => {
2509
2557
  const liveType = text(live["type"]);
2510
2558
  if (liveType !== "" && liveType !== props.type)
@@ -2533,43 +2581,43 @@ var handlers4 = pveHandlers({
2533
2581
  return withClears(fields, clear);
2534
2582
  }
2535
2583
  });
2536
- var ProxmoxHaRuleProvider = () => Provider12.effect(ProxmoxHaRule, Effect30.succeed(ProxmoxHaRule.Provider.of(handlers4)));
2584
+ var ProxmoxHaRuleProvider = () => Provider12.effect(ProxmoxHaRule, Effect31.succeed(ProxmoxHaRule.Provider.of(handlers3)));
2537
2585
  // src/proxmox/lxc.ts
2538
2586
  import { Resource as Resource13 } from "alchemy";
2539
- import { isResolved as isResolved11 } from "alchemy/Diff";
2587
+ import { isResolved as isResolved12 } from "alchemy/Diff";
2540
2588
  import * as Provider13 from "alchemy/Provider";
2541
- import * as Effect41 from "effect/Effect";
2589
+ import * as Effect42 from "effect/Effect";
2542
2590
 
2543
2591
  // src/ownership/adopt.ts
2544
2592
  import { AdoptPolicy } from "alchemy/AdoptPolicy";
2545
2593
  import { AlchemyContext } from "alchemy/AlchemyContext";
2546
2594
  import { Stack as Stack3 } from "alchemy/Stack";
2547
- import * as Effect34 from "effect/Effect";
2595
+ import * as Effect35 from "effect/Effect";
2548
2596
  import * as Option5 from "effect/Option";
2549
2597
 
2550
2598
  // src/ownership/resume.ts
2551
2599
  import { Unowned } from "alchemy/AdoptPolicy";
2552
2600
  import { Artifacts } from "alchemy/Artifacts";
2553
- import * as Effect31 from "effect/Effect";
2601
+ import * as Effect32 from "effect/Effect";
2554
2602
  import * as Option2 from "effect/Option";
2555
2603
  var PROVEN = "homeflare/ownership/resumes";
2556
2604
  var UNFINISHED = "homeflare/ownership/unfinished";
2557
- var note = (key, instanceId) => Effect31.gen(function* () {
2558
- const bag = yield* Effect31.serviceOption(Artifacts);
2605
+ var note = (key, instanceId) => Effect32.gen(function* () {
2606
+ const bag = yield* Effect32.serviceOption(Artifacts);
2559
2607
  if (Option2.isSome(bag))
2560
2608
  yield* bag.value.set(key, instanceId);
2561
2609
  });
2562
- var noted = (key, instanceId) => Effect31.gen(function* () {
2563
- const bag = yield* Effect31.serviceOption(Artifacts);
2610
+ var noted = (key, instanceId) => Effect32.gen(function* () {
2611
+ const bag = yield* Effect32.serviceOption(Artifacts);
2564
2612
  if (Option2.isNone(bag))
2565
2613
  return false;
2566
2614
  return (yield* bag.value.get(key)) === instanceId;
2567
2615
  });
2568
- var noteUnfinished = (instanceId) => Effect31.as(note(UNFINISHED, instanceId), undefined);
2569
- var noteResume = (instanceId, recovered) => Effect31.gen(function* () {
2616
+ var noteUnfinished = (instanceId) => Effect32.as(note(UNFINISHED, instanceId), undefined);
2617
+ var noteResume = (instanceId, recovered) => Effect32.gen(function* () {
2570
2618
  yield* noteUnfinished(instanceId);
2571
- const unproven = () => Effect31.succeed(undefined);
2572
- const found = yield* recovered.pipe(Effect31.catch(unproven), Effect31.catchDefect(unproven));
2619
+ const unproven = () => Effect32.succeed(undefined);
2620
+ const found = yield* recovered.pipe(Effect32.catch(unproven), Effect32.catchDefect(unproven));
2573
2621
  if (found === undefined || found === null || Unowned.is(found))
2574
2622
  return;
2575
2623
  yield* note(PROVEN, instanceId);
@@ -2580,7 +2628,7 @@ var provingResumes = (service) => {
2580
2628
  const { diff, read } = service;
2581
2629
  if (diff === undefined || read === undefined)
2582
2630
  return service;
2583
- const proving = (input) => Effect31.gen(function* () {
2631
+ const proving = (input) => Effect32.gen(function* () {
2584
2632
  if (input.output === undefined) {
2585
2633
  yield* noteResume(input.instanceId, read({ ...input, output: undefined }));
2586
2634
  }
@@ -2592,12 +2640,12 @@ var provingResumes = (service) => {
2592
2640
  // src/ownership/rows.ts
2593
2641
  import { Stack as Stack2 } from "alchemy/Stack";
2594
2642
  import { State, isActionState } from "alchemy/State/State";
2595
- import * as Effect33 from "effect/Effect";
2643
+ import * as Effect34 from "effect/Effect";
2596
2644
  import * as Option4 from "effect/Option";
2597
2645
 
2598
2646
  // src/ownership/whole.ts
2599
2647
  import { Stack } from "alchemy/Stack";
2600
- import * as Effect32 from "effect/Effect";
2648
+ import * as Effect33 from "effect/Effect";
2601
2649
  import * as Option3 from "effect/Option";
2602
2650
  var absent = (value) => value === undefined || value === null;
2603
2651
  var isPlainObject = (value) => {
@@ -2623,22 +2671,22 @@ var carries = (declared, recorded) => {
2623
2671
  }
2624
2672
  return true;
2625
2673
  };
2626
- var wholeDeclaration = (fqn, props) => Effect32.map(Effect32.serviceOption(Stack), (stack) => {
2674
+ var wholeDeclaration = (fqn, props) => Effect33.map(Effect33.serviceOption(Stack), (stack) => {
2627
2675
  const declared = Option3.isSome(stack) ? stack.value.resources[fqn] : undefined;
2628
2676
  return declared !== undefined && carries(declared.Props, props);
2629
2677
  });
2630
2678
 
2631
2679
  // src/ownership/rows.ts
2632
- var storeOf = Effect33.gen(function* () {
2633
- const stack = yield* Effect33.serviceOption(Stack2);
2634
- const state = yield* Effect33.serviceOption(State);
2680
+ var storeOf = Effect34.gen(function* () {
2681
+ const stack = yield* Effect34.serviceOption(Stack2);
2682
+ const state = yield* Effect34.serviceOption(State);
2635
2683
  if (Option4.isNone(stack) || Option4.isNone(state))
2636
2684
  return;
2637
2685
  const store = yield* state.value;
2638
2686
  const where = { stack: stack.value.name, stage: stack.value.stage };
2639
2687
  return { resources: stack.value.resources, store, where };
2640
2688
  });
2641
- var rowAt = (store, where, fqn) => store.get({ ...where, fqn }).pipe(Effect33.orElseSucceed(() => {
2689
+ var rowAt = (store, where, fqn) => store.get({ ...where, fqn }).pipe(Effect34.orElseSucceed(() => {
2642
2690
  return;
2643
2691
  }));
2644
2692
  var generationOf = (row, instanceId) => {
@@ -2651,7 +2699,7 @@ var generationOf = (row, instanceId) => {
2651
2699
  }
2652
2700
  return;
2653
2701
  };
2654
- var recordedGeneration = (fqn, instanceId) => Effect33.gen(function* () {
2702
+ var recordedGeneration = (fqn, instanceId) => Effect34.gen(function* () {
2655
2703
  const found = yield* storeOf;
2656
2704
  if (found === undefined)
2657
2705
  return;
@@ -2662,14 +2710,14 @@ var recordedGeneration = (fqn, instanceId) => Effect33.gen(function* () {
2662
2710
  }
2663
2711
  return;
2664
2712
  });
2665
- var recordedInstance = (fqn, instanceId) => Effect33.gen(function* () {
2713
+ var recordedInstance = (fqn, instanceId) => Effect34.gen(function* () {
2666
2714
  const generation = yield* recordedGeneration(fqn, instanceId);
2667
2715
  if (generation === undefined)
2668
2716
  return "absent";
2669
2717
  return (yield* wholeDeclaration(fqn, generation.props)) ? "whole" : "partial";
2670
2718
  });
2671
- var isCreate = (fqn, instanceId) => Effect33.map(recordedGeneration(fqn, instanceId), (generation) => generation?.status === "creating");
2672
- var forgetRefusedCreate = (fqn, instanceId) => Effect33.gen(function* () {
2719
+ var isCreate = (fqn, instanceId) => Effect34.map(recordedGeneration(fqn, instanceId), (generation) => generation?.status === "creating");
2720
+ var forgetRefusedCreate = (fqn, instanceId) => Effect34.gen(function* () {
2673
2721
  const found = yield* storeOf;
2674
2722
  if (found === undefined)
2675
2723
  return;
@@ -2678,32 +2726,32 @@ var forgetRefusedCreate = (fqn, instanceId) => Effect33.gen(function* () {
2678
2726
  if (mine?.status !== "creating" || mine.instanceId !== instanceId || mine.attr !== undefined) {
2679
2727
  return;
2680
2728
  }
2681
- yield* found.store.delete({ ...found.where, fqn }).pipe(Effect33.ignore);
2729
+ yield* found.store.delete({ ...found.where, fqn }).pipe(Effect34.ignore);
2682
2730
  });
2683
2731
 
2684
2732
  // src/ownership/adopt.ts
2685
- var adoptEnabled = (fqn) => Effect34.gen(function* () {
2686
- const stack = yield* Effect34.serviceOption(Stack3);
2733
+ var adoptEnabled = (fqn) => Effect35.gen(function* () {
2734
+ const stack = yield* Effect35.serviceOption(Stack3);
2687
2735
  const scoped = Option5.isSome(stack) ? stack.value.resources[fqn]?.Adopt : undefined;
2688
2736
  if (scoped !== undefined)
2689
2737
  return scoped;
2690
- const policy = yield* Effect34.serviceOption(AdoptPolicy);
2738
+ const policy = yield* Effect35.serviceOption(AdoptPolicy);
2691
2739
  if (Option5.isSome(policy))
2692
2740
  return policy.value;
2693
- const context = yield* Effect34.serviceOption(AlchemyContext);
2741
+ const context = yield* Effect35.serviceOption(AlchemyContext);
2694
2742
  return Option5.isSome(context) ? context.value.adopt : false;
2695
2743
  });
2696
- var adoptable = (owner) => Effect34.gen(function* () {
2744
+ var adoptable = (owner) => Effect35.gen(function* () {
2697
2745
  if (yield* isCreate(owner.fqn, owner.instanceId))
2698
2746
  return true;
2699
2747
  return yield* unfinished(owner.instanceId);
2700
2748
  });
2701
- var adoptsAtApply = (owner) => Effect34.gen(function* () {
2749
+ var adoptsAtApply = (owner) => Effect35.gen(function* () {
2702
2750
  if (!(yield* adoptEnabled(owner.fqn)))
2703
2751
  return false;
2704
2752
  return yield* adoptable(owner);
2705
2753
  });
2706
- var refuseTakeover = (owner, what) => Effect34.gen(function* () {
2754
+ var refuseTakeover = (owner, what) => Effect35.gen(function* () {
2707
2755
  if (owner.output !== undefined)
2708
2756
  return;
2709
2757
  if (yield* resumes(owner.instanceId))
@@ -2713,25 +2761,25 @@ var refuseTakeover = (owner, what) => Effect34.gen(function* () {
2713
2761
  return;
2714
2762
  yield* forgetRefusedCreate(owner.fqn, owner.instanceId);
2715
2763
  const remedy = may ? "Deploy with --adopt (or wrap the resource in adopt(true)) to take it over, or remove it first." : "It is the new identity of a replace, which --adopt does not cover: remove it first.";
2716
- return yield* Effect34.die(new Error(`${what}: already exists, and this stack holds no state for it — the plan could not ask ` + "first (a prop was still an Output, a replace moved onto it, or it appeared after the " + `plan). Nothing was written. ${remedy}`));
2764
+ return yield* Effect35.die(new Error(`${what}: already exists, and this stack holds no state for it — the plan could not ask ` + "first (a prop was still an Output, a replace moved onto it, or it appeared after the " + `plan). Nothing was written. ${remedy}`));
2717
2765
  });
2718
2766
  var claimFor = (owner) => (what) => refuseTakeover(owner, what);
2719
2767
 
2720
2768
  // src/ownership/probe.ts
2721
2769
  import { Unowned as Unowned2 } from "alchemy/AdoptPolicy";
2722
- import * as Effect35 from "effect/Effect";
2723
- var provenOurs = (ask, settled2) => Effect35.gen(function* () {
2770
+ import * as Effect36 from "effect/Effect";
2771
+ var provenOurs = (ask, settled2) => Effect36.gen(function* () {
2724
2772
  const recorded = yield* recordedInstance(ask.fqn, ask.instanceId);
2725
2773
  if (recorded === "absent")
2726
2774
  return false;
2727
2775
  if (recorded === "partial") {
2728
- yield* Effect35.logWarning(`${ask.fqn}: the interrupted create's state row lacks part of the declaration (a prop ` + "was still an Output when it was written), so the live object is not proven ours");
2776
+ yield* Effect36.logWarning(`${ask.fqn}: the interrupted create's state row lacks part of the declaration (a prop ` + "was still an Output when it was written), so the live object is not proven ours");
2729
2777
  return false;
2730
2778
  }
2731
- const unproven = (reason) => Effect35.as(Effect35.logWarning(`${ask.fqn}: the interrupted create's object could not be compared with its props ` + `(${reason instanceof Error ? reason.message : String(reason)}), so it is not treated as ours`), false);
2732
- return yield* settled2.pipe(Effect35.catch(unproven), Effect35.catchDefect(unproven));
2779
+ const unproven = (reason) => Effect36.as(Effect36.logWarning(`${ask.fqn}: the interrupted create's object could not be compared with its props ` + `(${reason instanceof Error ? reason.message : String(reason)}), so it is not treated as ours`), false);
2780
+ return yield* settled2.pipe(Effect36.catch(unproven), Effect36.catchDefect(unproven));
2733
2781
  });
2734
- var ownedRead = (ask, found, settled2) => Effect35.gen(function* () {
2782
+ var ownedRead = (ask, found, settled2) => Effect36.gen(function* () {
2735
2783
  if (found === undefined || ask.output !== undefined)
2736
2784
  return found;
2737
2785
  return (yield* provenOurs(ask, settled2)) ? found : Unowned2(found);
@@ -2789,8 +2837,8 @@ var optionMap = (value, family, defaultKey) => {
2789
2837
  return out;
2790
2838
  };
2791
2839
  var sameMap = (left, right) => left.size === right.size && [...left].every(([key, value]) => right.get(key) === value);
2792
- var sortedForm = (map13) => [...map13].map(([key, value]) => `${key}=${value}`).sort().join(",");
2793
- var printMap = (map13, lead = []) => [...lead.filter((key) => map13.has(key)), ...[...map13.keys()].filter((k) => !lead.includes(k))].map((key) => `${key}=${map13.get(key) ?? ""}`).join(",");
2840
+ var sortedForm = (map14) => [...map14].map(([key, value]) => `${key}=${value}`).sort().join(",");
2841
+ var printMap = (map14, lead = []) => [...lead.filter((key) => map14.has(key)), ...[...map14.keys()].filter((k) => !lead.includes(k))].map((key) => `${key}=${map14.get(key) ?? ""}`).join(",");
2794
2842
  var netMaps = (declared, live) => {
2795
2843
  const want = optionMap(declared, "net");
2796
2844
  const have = optionMap(live, "net");
@@ -3186,11 +3234,11 @@ var identityRefusals = (news, olds, output) => {
3186
3234
  };
3187
3235
 
3188
3236
  // src/proxmox/lxc-adoption.ts
3189
- import * as Effect40 from "effect/Effect";
3237
+ import * as Effect41 from "effect/Effect";
3190
3238
 
3191
3239
  // src/ownership/adopting.ts
3192
- import * as Effect36 from "effect/Effect";
3193
- var adopting = (owner, settled2) => Effect36.gen(function* () {
3240
+ import * as Effect37 from "effect/Effect";
3241
+ var adopting = (owner, settled2) => Effect37.gen(function* () {
3194
3242
  if (owner.output === undefined)
3195
3243
  return false;
3196
3244
  const generation = yield* recordedGeneration(owner.fqn, owner.instanceId);
@@ -3202,7 +3250,7 @@ var adopting = (owner, settled2) => Effect36.gen(function* () {
3202
3250
  });
3203
3251
 
3204
3252
  // src/proxmox/lxc-lifecycle.ts
3205
- import * as Effect39 from "effect/Effect";
3253
+ import * as Effect40 from "effect/Effect";
3206
3254
  import * as nodes10 from "@distilled.cloud/proxmox/nodes";
3207
3255
 
3208
3256
  // src/proxmox/lxc-errors.ts
@@ -3211,44 +3259,44 @@ class LxcRefusedError extends Error {
3211
3259
  }
3212
3260
 
3213
3261
  // src/proxmox/lxc-read.ts
3214
- import * as cluster4 from "@distilled.cloud/proxmox/cluster";
3262
+ import * as cluster5 from "@distilled.cloud/proxmox/cluster";
3215
3263
  import * as nodes8 from "@distilled.cloud/proxmox/nodes";
3216
- import * as Effect37 from "effect/Effect";
3217
- var readLive = (where) => Effect37.gen(function* () {
3264
+ import * as Effect38 from "effect/Effect";
3265
+ var readLive = (where) => Effect38.gen(function* () {
3218
3266
  const credential = yield* leased(where.target, "read");
3219
- const answer = yield* runPveWith(where.target, credential, false, nodes8.getNodeLxcConfig({ node: where.node, vmid: String(where.vmid) })).pipe(Effect37.map((data) => ({ data, error: undefined })), Effect37.catchTag("LxcConfigNotFound", (error) => Effect37.succeed({ data: undefined, error })));
3267
+ const answer = yield* runPveWith(where.target, credential, false, nodes8.getNodeLxcConfig({ node: where.node, vmid: String(where.vmid) })).pipe(Effect38.map((data) => ({ data, error: undefined })), Effect38.catchTag("LxcConfigNotFound", (error) => Effect38.succeed({ data: undefined, error })));
3220
3268
  if (answer.error === undefined) {
3221
3269
  const live = answer.data;
3222
3270
  if (live === null || typeof live !== "object" || Array.isArray(live) || !("digest" in live) || typeof live.digest !== "string" || live.digest === "") {
3223
- return yield* Effect37.fail(new LxcRefusedError(`CT ${String(where.vmid)}: config read did not return a valid digest-bearing config.`));
3271
+ return yield* Effect38.fail(new LxcRefusedError(`CT ${String(where.vmid)}: config read did not return a valid digest-bearing config.`));
3224
3272
  }
3225
3273
  return live;
3226
3274
  }
3227
- const rows = yield* runPveWith(where.target, credential, false, cluster4.listClusterResources({ type: "vm" }));
3275
+ const rows = yield* runPveWith(where.target, credential, false, cluster5.listClusterResources({ type: "vm" }));
3228
3276
  if (!Array.isArray(rows) || rows.some((row) => !Number.isSafeInteger(Number(row?.vmid)) || Number(row?.vmid) <= 0 || typeof row?.node !== "string" || row.node === "" || !["lxc", "qemu"].includes(row.type))) {
3229
- return yield* Effect37.fail(new LxcRefusedError("The cluster guest index did not identify its rows."));
3277
+ return yield* Effect38.fail(new LxcRefusedError("The cluster guest index did not identify its rows."));
3230
3278
  }
3231
3279
  const found = rows.find((row) => Number(row.vmid) === where.vmid);
3232
3280
  if (found !== undefined && found.node === where.node && found.type === "lxc") {
3233
- return yield* Effect37.fail(answer.error);
3281
+ return yield* Effect38.fail(answer.error);
3234
3282
  }
3235
3283
  if (found !== undefined) {
3236
- return yield* Effect37.fail(new LxcRefusedError(`vmid ${String(where.vmid)} is a ${text(found.type, "guest")} on ` + `${text(found.node, "?")}, not a container on ${where.node}. A migration is not an ` + "update and vmids are cluster-wide: declare the node it is on, or pick a free vmid."));
3284
+ return yield* Effect38.fail(new LxcRefusedError(`vmid ${String(where.vmid)} is a ${text(found.type, "guest")} on ` + `${text(found.node, "?")}, not a container on ${where.node}. A migration is not an ` + "update and vmids are cluster-wide: declare the node it is on, or pick a free vmid."));
3237
3285
  }
3238
3286
  return;
3239
3287
  });
3240
3288
 
3241
3289
  // src/proxmox/lxc-task.ts
3242
3290
  import * as nodes9 from "@distilled.cloud/proxmox/nodes";
3243
- import * as Effect38 from "effect/Effect";
3244
- var lxcTask = (where, operation, what, polls) => Effect38.gen(function* () {
3291
+ import * as Effect39 from "effect/Effect";
3292
+ var lxcTask = (where, operation, what, polls) => Effect39.gen(function* () {
3245
3293
  const credential = yield* mint(where.target, "provision");
3246
3294
  const upid = text(yield* runPveWith(where.target, credential, true, operation));
3247
3295
  if (upid === "")
3248
- return yield* Effect38.fail(new LxcRefusedError(`${what}: PVE returned no task id, so the write cannot be confirmed and is not claimed.`));
3296
+ return yield* Effect39.fail(new LxcRefusedError(`${what}: PVE returned no task id, so the write cannot be confirmed and is not claimed.`));
3249
3297
  let exit = "still running when this provider stopped waiting";
3250
3298
  for (let attempt = 0;attempt < polls; attempt++) {
3251
- const status = yield* runPveWith(where.target, credential, false, nodes9.getNodeTaskStatus({ node: where.node, upid })).pipe(Effect38.orElseSucceed(() => {
3299
+ const status = yield* runPveWith(where.target, credential, false, nodes9.getNodeTaskStatus({ node: where.node, upid })).pipe(Effect39.orElseSucceed(() => {
3252
3300
  return;
3253
3301
  }));
3254
3302
  if (status === undefined || status.status === undefined) {
@@ -3259,10 +3307,10 @@ var lxcTask = (where, operation, what, polls) => Effect38.gen(function* () {
3259
3307
  exit = text(status.exitstatus, "stopped with no exitstatus");
3260
3308
  break;
3261
3309
  }
3262
- yield* Effect38.sleep("1 second");
3310
+ yield* Effect39.sleep("1 second");
3263
3311
  }
3264
3312
  if (exit !== "OK")
3265
- return yield* Effect38.fail(new LxcRefusedError(`${what}: task ${upid} ended "${exit}". Read \`pvesh get /nodes/${where.node}/tasks/` + `${upid}/log\` before running the deploy again.`));
3313
+ return yield* Effect39.fail(new LxcRefusedError(`${what}: task ${upid} ended "${exit}". Read \`pvesh get /nodes/${where.node}/tasks/` + `${upid}/log\` before running the deploy again.`));
3266
3314
  });
3267
3315
 
3268
3316
  // src/proxmox/lxc-lifecycle.ts
@@ -3273,13 +3321,13 @@ var LXC_ENDPOINTS = {
3273
3321
  };
3274
3322
  var CREATE_POLLS = 180;
3275
3323
  var TASK_POLLS = 60;
3276
- var attributesOf5 = (where, live) => ({
3324
+ var attributesOf6 = (where, live) => ({
3277
3325
  config: storedConfig(live),
3278
3326
  node: where.node,
3279
3327
  rawKeys: rawKeysOf(live),
3280
3328
  vmid: where.vmid
3281
3329
  });
3282
- var createGuest = (props) => Effect39.gen(function* () {
3330
+ var createGuest = (props) => Effect40.gen(function* () {
3283
3331
  const form = createForm4(props);
3284
3332
  yield* guardForm(LXC_ENDPOINTS.create, form, true);
3285
3333
  return yield* lxcTask(props, nodes10.createNodeLxc({
@@ -3289,7 +3337,7 @@ var createGuest = (props) => Effect39.gen(function* () {
3289
3337
  ostemplate: text(form["ostemplate"])
3290
3338
  }), `create CT ${String(props.vmid)}`, CREATE_POLLS);
3291
3339
  });
3292
- var updateGuest = (props, change, digest) => Effect39.gen(function* () {
3340
+ var updateGuest = (props, change, digest) => Effect40.gen(function* () {
3293
3341
  if (Object.keys(change.put).length > 0 || change.clear.length > 0) {
3294
3342
  const form = withClears({ ...change.put, ...digest === "" ? {} : { digest } }, change.clear);
3295
3343
  yield* guardForm(LXC_ENDPOINTS.update, form, false);
@@ -3301,47 +3349,47 @@ var updateGuest = (props, change, digest) => Effect39.gen(function* () {
3301
3349
  yield* lxcTask(props, nodes10.putNodeLxcResize({ ...grown, node: props.node, vmid: String(props.vmid) }), `grow ${grow.disk} of CT ${String(props.vmid)} to ${grow.size}`, TASK_POLLS);
3302
3350
  }
3303
3351
  });
3304
- var destroyGuest = (where, declared) => Effect39.gen(function* () {
3352
+ var destroyGuest = (where, declared) => Effect40.gen(function* () {
3305
3353
  const live = yield* readLive(where);
3306
3354
  if (live === undefined)
3307
3355
  return;
3308
3356
  const drift = judge(declared, live).drift;
3309
3357
  if (drift.length > 0) {
3310
- return yield* Effect39.fail(new LxcRefusedError(`destroy CT ${String(where.vmid)}: the guest on ${where.node} no longer matches its last ` + `declaration (${drift.join(", ")}), so it may not be the guest this stack made. ` + "Nothing was deleted. Delete it by hand if it should go, or declare it again."));
3358
+ return yield* Effect40.fail(new LxcRefusedError(`destroy CT ${String(where.vmid)}: the guest on ${where.node} no longer matches its last ` + `declaration (${drift.join(", ")}), so it may not be the guest this stack made. ` + "Nothing was deleted. Delete it by hand if it should go, or declare it again."));
3311
3359
  }
3312
3360
  yield* lxcTask(where, nodes10.deleteNodeLxc({ node: where.node, vmid: String(where.vmid) }), `destroy CT ${String(where.vmid)}`, TASK_POLLS);
3313
3361
  });
3314
3362
 
3315
3363
  // src/proxmox/lxc-adoption.ts
3316
3364
  var adoptionRefusal = (props, drift) => `CT ${String(props.vmid)} on ${props.node}: adopting it would change ${drift.join(", ")}. An ` + "adoption never changes a guest, so nothing is written. Declare what is live for these keys " + "(the plan names keys, never values) and plan again; change them after the adoption, as an " + "update.";
3317
- var refuseAdoptedDrift = (owner, props, live, change) => Effect40.gen(function* () {
3365
+ var refuseAdoptedDrift = (owner, props, live, change) => Effect41.gen(function* () {
3318
3366
  if (change.drift.length === 0)
3319
3367
  return;
3320
- const settled2 = (recorded) => Effect40.sync(() => judge(recorded, live).drift.length === 0);
3368
+ const settled2 = (recorded) => Effect41.sync(() => judge(recorded, live).drift.length === 0);
3321
3369
  if (!(yield* adopting(owner, settled2)))
3322
3370
  return;
3323
- return yield* Effect40.fail(new LxcRefusedError(adoptionRefusal(props, change.drift)));
3371
+ return yield* Effect41.fail(new LxcRefusedError(adoptionRefusal(props, change.drift)));
3324
3372
  });
3325
3373
 
3326
3374
  // src/proxmox/lxc.ts
3327
3375
  var ProxmoxLxc = Resource13("Proxmox.Lxc", { defaultRemovalPolicy: "retain" });
3328
- var refused = (reasons) => Effect41.fail(new LxcRefusedError(reasons.join(`
3376
+ var refused = (reasons) => Effect42.fail(new LxcRefusedError(reasons.join(`
3329
3377
  `)));
3330
- var diff = (owner, news, olds) => Effect41.gen(function* () {
3378
+ var diff = (owner, news, olds) => Effect42.gen(function* () {
3331
3379
  const { output } = owner;
3332
3380
  const identity2 = identityRefusals(news, olds, output);
3333
3381
  if (identity2.length > 0)
3334
3382
  return yield* refused(identity2);
3335
3383
  if (output === undefined)
3336
3384
  return;
3337
- if (!isResolved11(news))
3385
+ if (!isResolved12(news))
3338
3386
  return;
3339
3387
  const live = yield* readLive(news);
3340
3388
  if (live === undefined) {
3341
3389
  const refusals = createRefusals(news);
3342
3390
  if (refusals.length > 0)
3343
3391
  return yield* refused(refusals);
3344
- yield* Effect41.logWarning(`Proxmox.Lxc ${news.node}/${String(news.vmid)}: the cluster lists no guest with this ` + "vmid -- a deploy CREATES it again from ostemplate, with new, empty volumes.");
3392
+ yield* Effect42.logWarning(`Proxmox.Lxc ${news.node}/${String(news.vmid)}: the cluster lists no guest with this ` + "vmid -- a deploy CREATES it again from ostemplate, with new, empty volumes.");
3345
3393
  return { action: "update" };
3346
3394
  }
3347
3395
  const change = judge(news, live);
@@ -3352,10 +3400,10 @@ var diff = (owner, news, olds) => Effect41.gen(function* () {
3352
3400
  if (change.drift.length === 0 && !moved)
3353
3401
  return { action: "noop" };
3354
3402
  const what = change.drift.length === 0 ? `the guest is on ${news.node} now, not ${output.node} -- a deploy re-records it, ` + "writing nothing." : `live config differs from the declaration in ${change.drift.join(", ")} -- a ` + "deploy writes these.";
3355
- yield* Effect41.logWarning(`Proxmox.Lxc ${news.node}/${String(news.vmid)}: ${what}`);
3403
+ yield* Effect42.logWarning(`Proxmox.Lxc ${news.node}/${String(news.vmid)}: ${what}`);
3356
3404
  return { action: "update" };
3357
3405
  });
3358
- var reconcile = (owner, news) => Effect41.gen(function* () {
3406
+ var reconcile = (owner, news) => Effect42.gen(function* () {
3359
3407
  const { output } = owner;
3360
3408
  const identity2 = identityRefusals(news, news, output);
3361
3409
  if (identity2.length > 0)
@@ -3394,22 +3442,22 @@ var reconcile = (owner, news) => Effect41.gen(function* () {
3394
3442
  `CT ${String(news.vmid)}: after the write, ${left.join(", ")} still differ from the ` + "declaration. PVE may have normalised the value (tags are lower-cased by default) -- " + "declare what it stores."
3395
3443
  ]);
3396
3444
  }
3397
- return attributesOf5(news, after);
3445
+ return attributesOf6(news, after);
3398
3446
  });
3399
3447
  var whereOf = (olds, output) => ({
3400
3448
  node: output?.node ?? olds.node,
3401
3449
  target: olds.target,
3402
3450
  vmid: output?.vmid ?? olds.vmid
3403
3451
  });
3404
- var read = (owner, olds) => Effect41.gen(function* () {
3452
+ var read = (owner, olds) => Effect42.gen(function* () {
3405
3453
  const where = whereOf(olds, owner.output);
3406
3454
  const live = yield* readLive(where);
3407
3455
  if (live === undefined)
3408
3456
  return;
3409
- const settled2 = Effect41.sync(() => judge(olds, live).drift.length === 0);
3410
- return yield* ownedRead(owner, attributesOf5(where, live), settled2);
3457
+ const settled2 = Effect42.sync(() => judge(olds, live).drift.length === 0);
3458
+ return yield* ownedRead(owner, attributesOf6(where, live), settled2);
3411
3459
  });
3412
- var handlers5 = {
3460
+ var handlers4 = {
3413
3461
  delete: ({ olds, output }) => destroyGuest(whereOf(olds, output), olds),
3414
3462
  diff: ({
3415
3463
  fqn,
@@ -3418,7 +3466,7 @@ var handlers5 = {
3418
3466
  olds,
3419
3467
  output
3420
3468
  }) => diff({ fqn, instanceId, output }, news, olds),
3421
- list: () => Effect41.succeed([]),
3469
+ list: () => Effect42.succeed([]),
3422
3470
  read: ({
3423
3471
  fqn,
3424
3472
  instanceId,
@@ -3432,11 +3480,11 @@ var handlers5 = {
3432
3480
  output
3433
3481
  }) => reconcile({ fqn, instanceId, output }, news)
3434
3482
  };
3435
- var ProxmoxLxcProvider = () => Provider13.effect(ProxmoxLxc, Effect41.succeed(ProxmoxLxc.Provider.of(handlers5)).pipe(Effect41.map(provingResumes)));
3483
+ var ProxmoxLxcProvider = () => Provider13.effect(ProxmoxLxc, Effect42.succeed(ProxmoxLxc.Provider.of(handlers4)).pipe(Effect42.map(provingResumes)));
3436
3484
  // src/proxmox/metric-server.ts
3437
3485
  import { Resource as Resource14 } from "alchemy";
3438
- import { isResolved as isResolved12 } from "alchemy/Diff";
3439
- import * as cluster6 from "@distilled.cloud/proxmox/cluster";
3486
+ import { isResolved as isResolved13 } from "alchemy/Diff";
3487
+ import * as cluster7 from "@distilled.cloud/proxmox/cluster";
3440
3488
 
3441
3489
  // src/proxmox/metric-server-form.ts
3442
3490
  var UNSET2 = -1;
@@ -3550,15 +3598,15 @@ var metricServerSpec = {
3550
3598
  };
3551
3599
 
3552
3600
  // src/proxmox/metric-server-distilled.ts
3553
- import * as cluster5 from "@distilled.cloud/proxmox/cluster";
3601
+ import * as cluster6 from "@distilled.cloud/proxmox/cluster";
3554
3602
  import { ProxmoxParseError as ProxmoxParseError3 } from "@distilled.cloud/proxmox/Errors";
3555
- import * as Effect42 from "effect/Effect";
3603
+ import * as Effect43 from "effect/Effect";
3556
3604
  import * as Schema2 from "effect/Schema";
3557
- var readMetricServerRow = (props) => runPve(props.target, "read", false, cluster5.getClusterMetricsServer({ id: props.id })).pipe(Effect42.flatMap((body4) => Schema2.decodeUnknownEffect(Schema2.Record(Schema2.String, Schema2.Unknown))(body4).pipe(Effect42.mapError(() => new ProxmoxParseError3({
3605
+ var readMetricServerRow = (props) => runPve(props.target, "read", false, cluster6.getClusterMetricsServer({ id: props.id })).pipe(Effect43.flatMap((body4) => Schema2.decodeUnknownEffect(Schema2.Record(Schema2.String, Schema2.Unknown))(body4).pipe(Effect43.mapError(() => new ProxmoxParseError3({
3558
3606
  body: undefined,
3559
3607
  cause: "Metric server response must be an object"
3560
- })))), Effect42.catchTag("MetricServerNotFound", () => Effect42.succeed(undefined)), Effect42.catchTag("NotFound", () => Effect42.succeed(undefined)));
3561
- var readMetricServer = (props) => readMetricServerRow(props).pipe(Effect42.map((row) => row === undefined ? undefined : metricServerSpec.attributes(row, props)));
3608
+ })))), Effect43.catchTag("MetricServerNotFound", () => Effect43.succeed(undefined)), Effect43.catchTag("NotFound", () => Effect43.succeed(undefined)));
3609
+ var readMetricServer = (props) => readMetricServerRow(props).pipe(Effect43.map((row) => row === undefined ? undefined : metricServerSpec.attributes(row, props)));
3562
3610
  var metricServerRequest = (props, form) => ({
3563
3611
  ...asForm2({
3564
3612
  api_path_prefix: form["api-path-prefix"],
@@ -3583,22 +3631,22 @@ var metricServerRequest = (props, form) => ({
3583
3631
  port: String(props.port),
3584
3632
  server: props.server
3585
3633
  });
3586
- var deleteMetricServer = (props) => Effect42.gen(function* () {
3634
+ var deleteMetricServer = (props) => Effect43.gen(function* () {
3587
3635
  if ((yield* readMetricServerRow(props)) === undefined)
3588
3636
  return;
3589
- yield* runPve(props.target, "provision", true, cluster5.deleteClusterMetricsServer({ id: props.id }));
3637
+ yield* runPve(props.target, "provision", true, cluster6.deleteClusterMetricsServer({ id: props.id }));
3590
3638
  });
3591
3639
 
3592
3640
  // src/proxmox/metric-server.ts
3593
3641
  import * as Provider14 from "alchemy/Provider";
3594
- import * as Effect43 from "effect/Effect";
3642
+ import * as Effect44 from "effect/Effect";
3595
3643
  var ProxmoxMetricServer = Resource14("Proxmox.MetricServer");
3596
3644
  var { guardCreate: guardCreate3, guardUpdate: guardUpdate3 } = specGuards(metricServerSpec);
3597
- var ProxmoxMetricServerProvider = () => Provider14.effect(ProxmoxMetricServer, Effect43.succeed(ProxmoxMetricServer.Provider.of({
3598
- list: () => Effect43.succeed([]),
3645
+ var ProxmoxMetricServerProvider = () => Provider14.effect(ProxmoxMetricServer, Effect44.succeed(ProxmoxMetricServer.Provider.of({
3646
+ list: () => Effect44.succeed([]),
3599
3647
  read: ({ olds }) => readMetricServer(olds),
3600
- diff: Effect43.fn(function* ({ news, output }) {
3601
- if (!isResolved12(news))
3648
+ diff: Effect44.fn(function* ({ news, output }) {
3649
+ if (!isResolved13(news))
3602
3650
  return;
3603
3651
  yield* guardCreate3(news, output === undefined);
3604
3652
  yield* guardUpdate3(news);
@@ -3611,36 +3659,36 @@ var ProxmoxMetricServerProvider = () => Provider14.effect(ProxmoxMetricServer, E
3611
3659
  }
3612
3660
  return { action: metricServerSpec.matches(live, news) ? "noop" : "update" };
3613
3661
  }),
3614
- reconcile: Effect43.fn(function* ({ news }) {
3662
+ reconcile: Effect44.fn(function* ({ news }) {
3615
3663
  const live = yield* readMetricServer(news);
3616
3664
  yield* guardCreate3(news, live === undefined);
3617
3665
  yield* guardUpdate3(news);
3618
3666
  if (live === undefined) {
3619
- yield* runPve(news.target, "provision", true, cluster6.updateClusterMetricsServer({
3667
+ yield* runPve(news.target, "provision", true, cluster7.updateClusterMetricsServer({
3620
3668
  ...metricServerRequest(news, metricServerSpec.createForm(news)),
3621
3669
  type: news.type
3622
3670
  }));
3623
3671
  } else {
3624
3672
  const form = formToSend(metricServerSpec.matches, live, news, metricServerSpec.updateForm(news));
3625
3673
  if (form !== undefined)
3626
- yield* runPve(news.target, "provision", true, cluster6.putClusterMetricsServer(metricServerRequest(news, form)));
3674
+ yield* runPve(news.target, "provision", true, cluster7.putClusterMetricsServer(metricServerRequest(news, form)));
3627
3675
  }
3628
3676
  const after = yield* readMetricServer(news);
3629
3677
  if (after === undefined)
3630
- return yield* Effect43.fail(new Error(`${metricServerSpec.path(news)}: write returned success but the resource is still absent`));
3678
+ return yield* Effect44.fail(new Error(`${metricServerSpec.path(news)}: write returned success but the resource is still absent`));
3631
3679
  return after;
3632
3680
  }),
3633
3681
  delete: ({ olds }) => deleteMetricServer(olds)
3634
3682
  })));
3635
3683
  // src/proxmox/network-apply.ts
3636
3684
  import { Resource as Resource15 } from "alchemy";
3637
- import { isResolved as isResolved13 } from "alchemy/Diff";
3685
+ import { isResolved as isResolved14 } from "alchemy/Diff";
3638
3686
  import * as Provider15 from "alchemy/Provider";
3639
- import * as Effect46 from "effect/Effect";
3687
+ import * as Effect47 from "effect/Effect";
3640
3688
 
3641
3689
  // src/proxmox/network-apply-run.ts
3642
3690
  import * as nodes12 from "@distilled.cloud/proxmox/nodes";
3643
- import * as Effect45 from "effect/Effect";
3691
+ import * as Effect46 from "effect/Effect";
3644
3692
 
3645
3693
  // src/proxmox/apply-endpoints.ts
3646
3694
  var NETWORK_APPLY_ENDPOINT = "pve:PUT /nodes/{node}/network";
@@ -3649,10 +3697,10 @@ var guardNetworkApply = guardForm(NETWORK_APPLY_ENDPOINT, {}, true);
3649
3697
  var guardSdnApply = guardForm(SDN_APPLY_ENDPOINT, {}, true);
3650
3698
 
3651
3699
  // src/proxmox/network-apply-read.ts
3652
- import * as cluster7 from "@distilled.cloud/proxmox/cluster";
3700
+ import * as cluster8 from "@distilled.cloud/proxmox/cluster";
3653
3701
  import * as nodes11 from "@distilled.cloud/proxmox/nodes";
3654
- import * as Effect44 from "effect/Effect";
3655
- var stagedDiff = (target, node) => Effect44.gen(function* () {
3702
+ import * as Effect45 from "effect/Effect";
3703
+ var stagedDiff = (target, node) => Effect45.gen(function* () {
3656
3704
  const credential = yield* leased(target, "read");
3657
3705
  const live = yield* runPveWith(target, credential, false, nodes11.listNodeNetwork({ node }));
3658
3706
  return Array.isArray(live) ? "" : live.changes;
@@ -3664,36 +3712,36 @@ var pendingLines = (diff2) => {
3664
3712
  `).filter((line) => (line.startsWith("+") || line.startsWith("-")) && !line.startsWith("+++") && !line.startsWith("---")).length;
3665
3713
  return Math.max(changed, 1);
3666
3714
  };
3667
- var pendingCount = (target, node) => stagedDiff(target, node).pipe(Effect44.map(pendingLines));
3668
- var clusterHealth = (target) => runPve(target, "read", false, cluster7.listClusterStatus({})).pipe(Effect44.map((rows) => {
3715
+ var pendingCount = (target, node) => stagedDiff(target, node).pipe(Effect45.map(pendingLines));
3716
+ var clusterHealth = (target) => runPve(target, "read", false, cluster8.listClusterStatus({})).pipe(Effect45.map((rows) => {
3669
3717
  const all = rows ?? [];
3670
- const cluster8 = all.find((row) => row.type === "cluster");
3718
+ const cluster9 = all.find((row) => row.type === "cluster");
3671
3719
  return {
3672
3720
  offline: all.filter((row) => row.type === "node" && !bool(row.online)).map((row) => text(row.name, "<unnamed>")),
3673
- quorate: cluster8 === undefined ? true : bool(cluster8.quorate)
3721
+ quorate: cluster9 === undefined ? true : bool(cluster9.quorate)
3674
3722
  };
3675
3723
  }));
3676
- var degradedReason = (target) => clusterHealth(target).pipe(Effect44.map((health) => health.quorate && health.offline.length === 0 ? undefined : `quorate=${String(health.quorate)} offline=[${health.offline.join(", ")}]`));
3724
+ var degradedReason = (target) => clusterHealth(target).pipe(Effect45.map((health) => health.quorate && health.offline.length === 0 ? undefined : `quorate=${String(health.quorate)} offline=[${health.offline.join(", ")}]`));
3677
3725
  var UNREACHABLE = "the task could not be read -- the node stopped answering, or this lease cannot see it";
3678
3726
  var STILL_RUNNING = "still running when this provider stopped waiting";
3679
3727
  var ATTEMPTS = 30;
3680
- var awaitTask = (target, credential, node, upid, attempts = ATTEMPTS) => Effect44.gen(function* () {
3728
+ var awaitTask = (target, credential, node, upid, attempts = ATTEMPTS) => Effect45.gen(function* () {
3681
3729
  for (let attempt = 0;attempt < attempts; attempt += 1) {
3682
- const status = yield* runPveWith(target, credential, false, nodes11.getNodeTaskStatus({ node, upid })).pipe(Effect44.orElseSucceed(() => {
3730
+ const status = yield* runPveWith(target, credential, false, nodes11.getNodeTaskStatus({ node, upid })).pipe(Effect45.orElseSucceed(() => {
3683
3731
  return;
3684
3732
  }));
3685
3733
  if (status === undefined)
3686
3734
  return UNREACHABLE;
3687
3735
  if (status.status === "stopped")
3688
3736
  return text(status.exitstatus, "stopped with no exitstatus");
3689
- yield* Effect44.sleep("1 second");
3737
+ yield* Effect45.sleep("1 second");
3690
3738
  }
3691
3739
  return STILL_RUNNING;
3692
3740
  });
3693
3741
 
3694
3742
  // src/proxmox/network-apply-run.ts
3695
- var refuse = (node, why) => Effect45.die(new Error(`Proxmox.NetworkApply ${node}: ${why}`));
3696
- var applyNetwork = (props) => Effect45.gen(function* () {
3743
+ var refuse = (node, why) => Effect46.die(new Error(`Proxmox.NetworkApply ${node}: ${why}`));
3744
+ var applyNetwork = (props) => Effect46.gen(function* () {
3697
3745
  const node = props.node;
3698
3746
  const staged = yield* pendingCount(props.target, node);
3699
3747
  if (staged === 0)
@@ -3725,27 +3773,27 @@ var applyNetwork = (props) => Effect45.gen(function* () {
3725
3773
 
3726
3774
  // src/proxmox/network-apply.ts
3727
3775
  var ProxmoxNetworkApply = Resource15("Proxmox.NetworkApply");
3728
- var read2 = (props) => pendingCount(props.target, props.node).pipe(Effect46.map((pending) => ({ node: props.node, pending })));
3729
- var diff2 = (news) => Effect46.gen(function* () {
3730
- if (!isResolved13(news))
3776
+ var read2 = (props) => pendingCount(props.target, props.node).pipe(Effect47.map((pending) => ({ node: props.node, pending })));
3777
+ var diff2 = (news) => Effect47.gen(function* () {
3778
+ if (!isResolved14(news))
3731
3779
  return;
3732
3780
  const { pending } = yield* read2(news);
3733
3781
  return pending === 0 ? { action: "noop" } : { action: "update" };
3734
3782
  });
3735
- var handlers6 = {
3736
- delete: () => Effect46.void,
3783
+ var handlers5 = {
3784
+ delete: () => Effect47.void,
3737
3785
  diff: ({ news }) => diff2(news),
3738
- list: () => Effect46.succeed([]),
3786
+ list: () => Effect47.succeed([]),
3739
3787
  read: ({ olds }) => read2(olds),
3740
3788
  reconcile: ({ news }) => applyNetwork(news)
3741
3789
  };
3742
- var ProxmoxNetworkApplyProvider = () => Provider15.effect(ProxmoxNetworkApply, Effect46.succeed(ProxmoxNetworkApply.Provider.of(handlers6)));
3790
+ var ProxmoxNetworkApplyProvider = () => Provider15.effect(ProxmoxNetworkApply, Effect47.succeed(ProxmoxNetworkApply.Provider.of(handlers5)));
3743
3791
  // src/proxmox/node-network.ts
3744
3792
  import { Resource as Resource16 } from "alchemy";
3745
- import { isResolved as isResolved14 } from "alchemy/Diff";
3793
+ import { isResolved as isResolved15 } from "alchemy/Diff";
3746
3794
  import * as Provider16 from "alchemy/Provider";
3747
3795
  import * as nodes14 from "@distilled.cloud/proxmox/nodes";
3748
- import * as Effect48 from "effect/Effect";
3796
+ import * as Effect49 from "effect/Effect";
3749
3797
 
3750
3798
  // src/proxmox/node-network-form.ts
3751
3799
  var NODE_NETWORK_CREATE = "pve:POST /nodes/{node}/network";
@@ -3778,7 +3826,7 @@ var createForm5 = (props) => ({
3778
3826
  ...body4(props),
3779
3827
  iface: props.iface
3780
3828
  });
3781
- var updateForm2 = (props) => {
3829
+ var updateForm3 = (props) => {
3782
3830
  const clear = [
3783
3831
  ...props.cidr === undefined ? ["cidr"] : [],
3784
3832
  ...props.bridge_vlan_aware === false ? ["bridge_vlan_aware"] : []
@@ -3788,8 +3836,8 @@ var updateForm2 = (props) => {
3788
3836
 
3789
3837
  // src/proxmox/node-network-wire.ts
3790
3838
  import * as nodes13 from "@distilled.cloud/proxmox/nodes";
3791
- import * as Effect47 from "effect/Effect";
3792
- var attributesOf6 = (live, props) => {
3839
+ import * as Effect48 from "effect/Effect";
3840
+ var attributesOf7 = (live, props) => {
3793
3841
  const data = live;
3794
3842
  const liveType = text(data["type"]);
3795
3843
  if (liveType !== "" && liveType !== props.type)
@@ -3822,16 +3870,16 @@ var attributesOf6 = (live, props) => {
3822
3870
  "vlan-raw-device": text(data["vlan-raw-device"])
3823
3871
  };
3824
3872
  };
3825
- var readInterfaceOrFail = (props) => readOrUnreadable(runPve(props.target, "read", false, nodes13.getNodeNetwork({ iface: props.iface, node: props.node })).pipe(Effect47.catchTag("NetworkInterfaceNotFound", () => Effect47.succeed(undefined)))).pipe(Effect47.map((live) => {
3873
+ var readInterfaceOrFail = (props) => readOrUnreadable(runPve(props.target, "read", false, nodes13.getNodeNetwork({ iface: props.iface, node: props.node })).pipe(Effect48.catchTag("NetworkInterfaceNotFound", () => Effect48.succeed(undefined)))).pipe(Effect48.map((live) => {
3826
3874
  if (live === UNREADABLE)
3827
3875
  return UNREADABLE;
3828
- return live === undefined ? undefined : attributesOf6(live, props);
3876
+ return live === undefined ? undefined : attributesOf7(live, props);
3829
3877
  }));
3830
- var readInterface = (props) => readInterfaceOrFail(props).pipe(Effect47.orElseSucceed(() => {
3878
+ var readInterface = (props) => readInterfaceOrFail(props).pipe(Effect48.orElseSucceed(() => {
3831
3879
  return;
3832
3880
  }));
3833
3881
  var dropUnreadable4 = (live) => live === UNREADABLE ? undefined : live;
3834
- var matches5 = (attributes, props) => attributes.cidr === (props.cidr ?? "") && same2(props.gateway, attributes.gateway) && same2(props.autostart, attributes.autostart) && same2(props.mtu, attributes.mtu) && sameComment(props.comments, attributes.comments) && sameList(props.bridge_ports, attributes.bridge_ports) && sameList(props.bridge_vids, attributes.bridge_vids) && same2(props.bridge_vlan_aware, attributes.bridge_vlan_aware) && sameList(props.slaves, attributes.slaves) && same2(props.bond_mode, attributes.bond_mode) && same2(props.bond_xmit_hash_policy, attributes.bond_xmit_hash_policy) && same2(props["bond-primary"], attributes["bond-primary"]) && same2(props["vlan-id"], attributes["vlan-id"]) && same2(props["vlan-raw-device"], attributes["vlan-raw-device"]);
3882
+ var matches6 = (attributes, props) => attributes.cidr === (props.cidr ?? "") && same2(props.gateway, attributes.gateway) && same2(props.autostart, attributes.autostart) && same2(props.mtu, attributes.mtu) && sameComment(props.comments, attributes.comments) && sameList(props.bridge_ports, attributes.bridge_ports) && sameList(props.bridge_vids, attributes.bridge_vids) && same2(props.bridge_vlan_aware, attributes.bridge_vlan_aware) && sameList(props.slaves, attributes.slaves) && same2(props.bond_mode, attributes.bond_mode) && same2(props.bond_xmit_hash_policy, attributes.bond_xmit_hash_policy) && same2(props["bond-primary"], attributes["bond-primary"]) && same2(props["vlan-id"], attributes["vlan-id"]) && same2(props["vlan-raw-device"], attributes["vlan-raw-device"]);
3835
3883
 
3836
3884
  // src/proxmox/node-network.ts
3837
3885
  var ProxmoxNodeNetwork = Resource16("Proxmox.NodeNetwork", {
@@ -3848,60 +3896,60 @@ var toDistilledCreate3 = (props) => ({
3848
3896
  node: props.node
3849
3897
  });
3850
3898
  var toDistilledUpdate2 = (props) => ({
3851
- ...toDistilled(updateForm2(props)),
3899
+ ...toDistilled(updateForm3(props)),
3852
3900
  iface: props.iface,
3853
3901
  node: props.node
3854
3902
  });
3855
- var ProxmoxNodeNetworkProvider = () => Provider16.effect(ProxmoxNodeNetwork, Effect48.succeed(ProxmoxNodeNetwork.Provider.of({
3856
- list: () => Effect48.succeed([]),
3857
- read: Effect48.fn(function* ({ olds, output }) {
3903
+ var ProxmoxNodeNetworkProvider = () => Provider16.effect(ProxmoxNodeNetwork, Effect49.succeed(ProxmoxNodeNetwork.Provider.of({
3904
+ list: () => Effect49.succeed([]),
3905
+ read: Effect49.fn(function* ({ olds, output }) {
3858
3906
  return dropUnreadable4(yield* output === undefined ? readInterface(olds) : readInterfaceOrFail(olds));
3859
3907
  }),
3860
- diff: Effect48.fn(function* ({ news, output }) {
3861
- if (!isResolved14(news))
3908
+ diff: Effect49.fn(function* ({ news, output }) {
3909
+ if (!isResolved15(news))
3862
3910
  return;
3863
3911
  yield* guardWrite2(NODE_NETWORK_CREATE, createForm5(news), output === undefined);
3864
- yield* guardWrite2(NODE_NETWORK_UPDATE, updateForm2(news), false);
3912
+ yield* guardWrite2(NODE_NETWORK_UPDATE, updateForm3(news), false);
3865
3913
  if (output === undefined)
3866
3914
  return;
3867
3915
  const live = yield* readInterfaceOrFail(news);
3868
3916
  if (live === UNREADABLE) {
3869
- yield* unreadableWarning("Proxmox.NodeNetwork", `${news.node}/${news.iface}`);
3917
+ yield* unreadableWarning("Proxmox.NodeNetwork", `${news.node}/${news.iface}`, news.target.mount, mintTier(news.target, "read"));
3870
3918
  return { action: "noop" };
3871
3919
  }
3872
3920
  if (live === undefined) {
3873
3921
  yield* guardWrite2(NODE_NETWORK_CREATE, createForm5(news), true);
3874
3922
  return { action: "update" };
3875
3923
  }
3876
- return matches5(live, news) ? { action: "noop" } : { action: "update" };
3924
+ return matches6(live, news) ? { action: "noop" } : { action: "update" };
3877
3925
  }),
3878
- reconcile: Effect48.fn(function* ({ news }) {
3926
+ reconcile: Effect49.fn(function* ({ news }) {
3879
3927
  const before = dropUnreadable4(yield* readInterface(news));
3880
3928
  yield* guardWrite2(NODE_NETWORK_CREATE, createForm5(news), before === undefined);
3881
- yield* guardWrite2(NODE_NETWORK_UPDATE, updateForm2(news), false);
3929
+ yield* guardWrite2(NODE_NETWORK_UPDATE, updateForm3(news), false);
3882
3930
  if (before === undefined) {
3883
3931
  yield* runPve(news.target, "provision", true, nodes14.createNodeNetwork(toDistilledCreate3(news)));
3884
- } else if (!matches5(before, news)) {
3932
+ } else if (!matches6(before, news)) {
3885
3933
  yield* runPve(news.target, "provision", true, nodes14.putNodeNetwork2(toDistilledUpdate2(news)));
3886
3934
  }
3887
3935
  const after = dropUnreadable4(yield* readInterface(news));
3888
3936
  if (after === undefined) {
3889
- return yield* Effect48.die(new Error(`nodes/${news.node}/network/${news.iface}: wrote with no error, but the ` + 'interface is still absent -- PVE wraps every answer in {"data":...} and can ' + "report success on a call that did nothing, so read back rather than trust it."));
3937
+ return yield* Effect49.die(new Error(`nodes/${news.node}/network/${news.iface}: wrote with no error, but the ` + 'interface is still absent -- PVE wraps every answer in {"data":...} and can ' + "report success on a call that did nothing, so read back rather than trust it."));
3890
3938
  }
3891
3939
  return after;
3892
3940
  }),
3893
- delete: Effect48.fn(function* ({ olds }) {
3941
+ delete: Effect49.fn(function* ({ olds }) {
3894
3942
  yield* runPve(olds.target, "provision", true, nodes14.deleteNodeNetwork2({ iface: olds.iface, node: olds.node }));
3895
3943
  })
3896
3944
  })));
3897
3945
  // src/proxmox/notification-matcher.ts
3898
3946
  import { Resource as Resource17 } from "alchemy";
3899
3947
  import * as Provider17 from "alchemy/Provider";
3900
- import * as Effect52 from "effect/Effect";
3948
+ import * as Effect53 from "effect/Effect";
3901
3949
 
3902
3950
  // src/proxmox/notification-matcher-lifecycle.ts
3903
- import { isResolved as isResolved15 } from "alchemy/Diff";
3904
- import * as Effect51 from "effect/Effect";
3951
+ import { isResolved as isResolved16 } from "alchemy/Diff";
3952
+ import * as Effect52 from "effect/Effect";
3905
3953
 
3906
3954
  // src/proxmox/notification-matcher-form.ts
3907
3955
  var list = (value) => Array.isArray(value) ? value.map((item) => String(item)) : [];
@@ -3978,49 +4026,49 @@ var matcherUpdateForm = (fields) => {
3978
4026
  };
3979
4027
 
3980
4028
  // src/proxmox/notification-matcher-distilled.ts
3981
- import * as cluster8 from "@distilled.cloud/proxmox/cluster";
3982
- import * as Effect50 from "effect/Effect";
4029
+ import * as cluster9 from "@distilled.cloud/proxmox/cluster";
4030
+ import * as Effect51 from "effect/Effect";
3983
4031
 
3984
4032
  // src/proxmox/notification-sdk-input.ts
3985
4033
  import { ProxmoxParseError as ProxmoxParseError4 } from "@distilled.cloud/proxmox/Errors";
3986
4034
  import * as Data2 from "effect/Data";
3987
- import * as Effect49 from "effect/Effect";
4035
+ import * as Effect50 from "effect/Effect";
3988
4036
  import * as Schema3 from "effect/Schema";
3989
4037
 
3990
4038
  class NotificationRequestInvalid extends Data2.TaggedError("NotificationRequestInvalid") {
3991
4039
  }
3992
- var notificationRequest = (schema, fields) => Schema3.decodeUnknownEffect(Schema3.toType(schema), { onExcessProperty: "error" })(Object.fromEntries(Object.entries(fields).map(([key, value]) => [key.replaceAll("-", "_"), value]))).pipe(Effect49.mapError(() => new NotificationRequestInvalid({ operation: "PVE notification write" })));
3993
- var notificationResponse = (schema) => (body5) => Schema3.decodeUnknownEffect(Schema3.toType(schema))(body5).pipe(Effect49.as(body5), Effect49.mapError(() => new ProxmoxParseError4({
4040
+ var notificationRequest = (schema, fields) => Schema3.decodeUnknownEffect(Schema3.toType(schema), { onExcessProperty: "error" })(Object.fromEntries(Object.entries(fields).map(([key, value]) => [key.replaceAll("-", "_"), value]))).pipe(Effect50.mapError(() => new NotificationRequestInvalid({ operation: "PVE notification write" })));
4041
+ var notificationResponse = (schema) => (body5) => Schema3.decodeUnknownEffect(Schema3.toType(schema))(body5).pipe(Effect50.as(body5), Effect50.mapError(() => new ProxmoxParseError4({
3994
4042
  body: undefined,
3995
4043
  cause: "PVE notification response does not match its SDK schema"
3996
4044
  })));
3997
4045
 
3998
4046
  // src/proxmox/notification-matcher-distilled.ts
3999
- var readMatcher = (props) => runPve(props.target, "read", false, cluster8.getClusterNotificationMatcher({ name: props.name })).pipe(Effect50.flatMap(notificationResponse(cluster8.GetClusterNotificationMatcherResponse)), Effect50.map((live) => matcherAttributes({
4047
+ var readMatcher = (props) => runPve(props.target, "read", false, cluster9.getClusterNotificationMatcher({ name: props.name })).pipe(Effect51.flatMap(notificationResponse(cluster9.GetClusterNotificationMatcherResponse)), Effect51.map((live) => matcherAttributes({
4000
4048
  ...live,
4001
4049
  "invert-match": live.invert_match,
4002
4050
  "match-calendar": live.match_calendar,
4003
4051
  "match-field": live.match_field,
4004
4052
  "match-severity": live.match_severity
4005
- }, props.name)), Effect50.catchTag("NotFound", () => Effect50.succeed(undefined)));
4006
- var createMatcher = (props) => Effect50.gen(function* () {
4007
- const input = yield* notificationRequest(cluster8.CreateClusterNotificationMatcherRequest, matcherCreateForm(props));
4008
- yield* runPve(props.target, "provision", true, cluster8.createClusterNotificationMatcher(input));
4053
+ }, props.name)), Effect51.catchTag("NotFound", () => Effect51.succeed(undefined)));
4054
+ var createMatcher = (props) => Effect51.gen(function* () {
4055
+ const input = yield* notificationRequest(cluster9.CreateClusterNotificationMatcherRequest, matcherCreateForm(props));
4056
+ yield* runPve(props.target, "provision", true, cluster9.createClusterNotificationMatcher(input));
4009
4057
  });
4010
- var updateMatcher = (props) => Effect50.gen(function* () {
4011
- const input = yield* notificationRequest(cluster8.PutClusterNotificationMatcherRequest, {
4058
+ var updateMatcher = (props) => Effect51.gen(function* () {
4059
+ const input = yield* notificationRequest(cluster9.PutClusterNotificationMatcherRequest, {
4012
4060
  ...matcherUpdateForm(props),
4013
4061
  name: props.name
4014
4062
  });
4015
- yield* runPve(props.target, "provision", true, cluster8.putClusterNotificationMatcher(input));
4063
+ yield* runPve(props.target, "provision", true, cluster9.putClusterNotificationMatcher(input));
4016
4064
  });
4017
- var deleteMatcher = (props) => runPve(props.target, "provision", true, cluster8.deleteClusterNotificationMatcher({ name: props.name })).pipe(Effect50.catchTag("NotFound", () => Effect50.void));
4065
+ var deleteMatcher = (props) => runPve(props.target, "provision", true, cluster9.deleteClusterNotificationMatcher({ name: props.name })).pipe(Effect51.catchTag("NotFound", () => Effect51.void));
4018
4066
 
4019
4067
  // src/proxmox/notification-matcher-lifecycle.ts
4020
- var guard = (props, create) => guardForm("pve:POST /cluster/notifications/matchers", matcherCreateForm(props), create).pipe(Effect51.andThen(guardForm("pve:PUT /cluster/notifications/matchers/{name}", matcherUpdateForm(props), false)));
4068
+ var guard = (props, create) => guardForm("pve:POST /cluster/notifications/matchers", matcherCreateForm(props), create).pipe(Effect52.andThen(guardForm("pve:PUT /cluster/notifications/matchers/{name}", matcherUpdateForm(props), false)));
4021
4069
  var matcherHandlers = {
4022
- list: () => Effect51.succeed([]),
4023
- read: ({ olds }) => Effect51.gen(function* () {
4070
+ list: () => Effect52.succeed([]),
4071
+ read: ({ olds }) => Effect52.gen(function* () {
4024
4072
  const live = yield* readMatcher(olds);
4025
4073
  yield* guard(olds, live === undefined);
4026
4074
  return live;
@@ -4029,8 +4077,8 @@ var matcherHandlers = {
4029
4077
  news,
4030
4078
  olds,
4031
4079
  output
4032
- }) => Effect51.gen(function* () {
4033
- if (!isResolved15(news))
4080
+ }) => Effect52.gen(function* () {
4081
+ if (!isResolved16(news))
4034
4082
  return;
4035
4083
  if (olds.name !== news.name)
4036
4084
  return { action: "replace" };
@@ -4044,7 +4092,7 @@ var matcherHandlers = {
4044
4092
  }
4045
4093
  return { action: matcherMatches(live, news) ? "noop" : "update" };
4046
4094
  }),
4047
- reconcile: ({ news }) => Effect51.gen(function* () {
4095
+ reconcile: ({ news }) => Effect52.gen(function* () {
4048
4096
  const live = yield* readMatcher(news);
4049
4097
  yield* guard(news, live === undefined);
4050
4098
  if (live === undefined)
@@ -4053,7 +4101,7 @@ var matcherHandlers = {
4053
4101
  yield* updateMatcher(news);
4054
4102
  const after = yield* readMatcher(news);
4055
4103
  if (after === undefined)
4056
- return yield* Effect51.die(new Error(`Notification matcher ${news.name}: write returned but read-back is absent.`));
4104
+ return yield* Effect52.die(new Error(`Notification matcher ${news.name}: write returned but read-back is absent.`));
4057
4105
  return after;
4058
4106
  }),
4059
4107
  delete: ({ olds }) => deleteMatcher(olds)
@@ -4061,15 +4109,15 @@ var matcherHandlers = {
4061
4109
 
4062
4110
  // src/proxmox/notification-matcher.ts
4063
4111
  var ProxmoxNotificationMatcher = Resource17("Proxmox.NotificationMatcher");
4064
- var ProxmoxNotificationMatcherProvider = () => Provider17.effect(ProxmoxNotificationMatcher, Effect52.succeed(ProxmoxNotificationMatcher.Provider.of(matcherHandlers)));
4112
+ var ProxmoxNotificationMatcherProvider = () => Provider17.effect(ProxmoxNotificationMatcher, Effect53.succeed(ProxmoxNotificationMatcher.Provider.of(matcherHandlers)));
4065
4113
  // src/proxmox/notification-target.ts
4066
4114
  import { Resource as Resource18 } from "alchemy";
4067
4115
  import * as Provider18 from "alchemy/Provider";
4068
- import * as Effect55 from "effect/Effect";
4116
+ import * as Effect56 from "effect/Effect";
4069
4117
 
4070
4118
  // src/proxmox/notification-target-lifecycle.ts
4071
- import { isResolved as isResolved16 } from "alchemy/Diff";
4072
- import * as Effect54 from "effect/Effect";
4119
+ import { isResolved as isResolved17 } from "alchemy/Diff";
4120
+ import * as Effect55 from "effect/Effect";
4073
4121
 
4074
4122
  // src/proxmox/notification-target-endpoint.ts
4075
4123
  var ENDPOINTS = {
@@ -4152,30 +4200,30 @@ var targetSpec = {
4152
4200
  };
4153
4201
 
4154
4202
  // src/proxmox/notification-target-distilled.ts
4155
- import * as cluster9 from "@distilled.cloud/proxmox/cluster";
4156
- import * as Effect53 from "effect/Effect";
4203
+ import * as cluster10 from "@distilled.cloud/proxmox/cluster";
4204
+ import * as Effect54 from "effect/Effect";
4157
4205
  var read3 = (props) => {
4158
4206
  const request = { name: props.name };
4159
4207
  switch (props.type) {
4160
4208
  case "gotify":
4161
- return cluster9.getClusterNotificationEndpointGotify(request).pipe(Effect53.flatMap(notificationResponse(cluster9.GetClusterNotificationEndpointGotifyResponse)), Effect53.map((row) => ({ ...row })));
4209
+ return cluster10.getClusterNotificationEndpointGotify(request).pipe(Effect54.flatMap(notificationResponse(cluster10.GetClusterNotificationEndpointGotifyResponse)), Effect54.map((row) => ({ ...row })));
4162
4210
  case "sendmail":
4163
- return cluster9.getClusterNotificationEndpointSendmail(request).pipe(Effect53.flatMap(notificationResponse(cluster9.GetClusterNotificationEndpointSendmailResponse)), Effect53.map((row) => ({
4211
+ return cluster10.getClusterNotificationEndpointSendmail(request).pipe(Effect54.flatMap(notificationResponse(cluster10.GetClusterNotificationEndpointSendmailResponse)), Effect54.map((row) => ({
4164
4212
  ...row,
4165
4213
  "from-address": row.from_address,
4166
4214
  "mailto-user": row.mailto_user
4167
4215
  })));
4168
4216
  case "smtp":
4169
- return cluster9.getClusterNotificationEndpointSmtp(request).pipe(Effect53.flatMap(notificationResponse(cluster9.GetClusterNotificationEndpointSmtpResponse)), Effect53.map((row) => ({
4217
+ return cluster10.getClusterNotificationEndpointSmtp(request).pipe(Effect54.flatMap(notificationResponse(cluster10.GetClusterNotificationEndpointSmtpResponse)), Effect54.map((row) => ({
4170
4218
  ...row,
4171
4219
  "from-address": row.from_address,
4172
4220
  "mailto-user": row.mailto_user
4173
4221
  })));
4174
4222
  case "webhook":
4175
- return cluster9.getClusterNotificationEndpointWebhook(request).pipe(Effect53.flatMap(notificationResponse(cluster9.GetClusterNotificationEndpointWebhookResponse)), Effect53.map((row) => ({ ...row })));
4223
+ return cluster10.getClusterNotificationEndpointWebhook(request).pipe(Effect54.flatMap(notificationResponse(cluster10.GetClusterNotificationEndpointWebhookResponse)), Effect54.map((row) => ({ ...row })));
4176
4224
  }
4177
4225
  };
4178
- var readTarget = (props) => runPve(props.target, "read", false, read3(props)).pipe(Effect53.map((row) => targetSpec.attributes(row, props)), Effect53.catchTag("NotFound", () => Effect53.succeed(undefined)));
4226
+ var readTarget = (props) => runPve(props.target, "read", false, read3(props)).pipe(Effect54.map((row) => targetSpec.attributes(row, props)), Effect54.catchTag("NotFound", () => Effect54.succeed(undefined)));
4179
4227
  var fields = (props, create) => {
4180
4228
  const form = {
4181
4229
  ...create ? createShape(props) : shape4(props),
@@ -4209,40 +4257,40 @@ var fields = (props, create) => {
4209
4257
  };
4210
4258
  var validateTargetWrite = (props, create) => {
4211
4259
  const schema = create ? {
4212
- sendmail: cluster9.CreateClusterNotificationEndpointSendmailRequest,
4213
- smtp: cluster9.CreateClusterNotificationEndpointSmtpRequest,
4214
- gotify: cluster9.CreateClusterNotificationEndpointGotifyRequest,
4215
- webhook: cluster9.CreateClusterNotificationEndpointWebhookRequest
4260
+ sendmail: cluster10.CreateClusterNotificationEndpointSendmailRequest,
4261
+ smtp: cluster10.CreateClusterNotificationEndpointSmtpRequest,
4262
+ gotify: cluster10.CreateClusterNotificationEndpointGotifyRequest,
4263
+ webhook: cluster10.CreateClusterNotificationEndpointWebhookRequest
4216
4264
  }[props.type] : {
4217
- sendmail: cluster9.PutClusterNotificationEndpointSendmailRequest,
4218
- smtp: cluster9.PutClusterNotificationEndpointSmtpRequest,
4219
- gotify: cluster9.PutClusterNotificationEndpointGotifyRequest,
4220
- webhook: cluster9.PutClusterNotificationEndpointWebhookRequest
4265
+ sendmail: cluster10.PutClusterNotificationEndpointSendmailRequest,
4266
+ smtp: cluster10.PutClusterNotificationEndpointSmtpRequest,
4267
+ gotify: cluster10.PutClusterNotificationEndpointGotifyRequest,
4268
+ webhook: cluster10.PutClusterNotificationEndpointWebhookRequest
4221
4269
  }[props.type];
4222
- return notificationRequest(schema, fields(props, create)).pipe(Effect53.asVoid);
4270
+ return notificationRequest(schema, fields(props, create)).pipe(Effect54.asVoid);
4223
4271
  };
4224
4272
  var createTarget = (props) => {
4225
4273
  const form = fields(props, true);
4226
- const operation = props.type === "sendmail" ? notificationRequest(cluster9.CreateClusterNotificationEndpointSendmailRequest, form).pipe(Effect53.flatMap(cluster9.createClusterNotificationEndpointSendmail)) : props.type === "smtp" ? notificationRequest(cluster9.CreateClusterNotificationEndpointSmtpRequest, form).pipe(Effect53.flatMap(cluster9.createClusterNotificationEndpointSmtp)) : props.type === "gotify" ? notificationRequest(cluster9.CreateClusterNotificationEndpointGotifyRequest, form).pipe(Effect53.flatMap(cluster9.createClusterNotificationEndpointGotify)) : notificationRequest(cluster9.CreateClusterNotificationEndpointWebhookRequest, form).pipe(Effect53.flatMap(cluster9.createClusterNotificationEndpointWebhook));
4274
+ const operation = props.type === "sendmail" ? notificationRequest(cluster10.CreateClusterNotificationEndpointSendmailRequest, form).pipe(Effect54.flatMap(cluster10.createClusterNotificationEndpointSendmail)) : props.type === "smtp" ? notificationRequest(cluster10.CreateClusterNotificationEndpointSmtpRequest, form).pipe(Effect54.flatMap(cluster10.createClusterNotificationEndpointSmtp)) : props.type === "gotify" ? notificationRequest(cluster10.CreateClusterNotificationEndpointGotifyRequest, form).pipe(Effect54.flatMap(cluster10.createClusterNotificationEndpointGotify)) : notificationRequest(cluster10.CreateClusterNotificationEndpointWebhookRequest, form).pipe(Effect54.flatMap(cluster10.createClusterNotificationEndpointWebhook));
4227
4275
  return runPve(props.target, "provision", true, operation);
4228
4276
  };
4229
4277
  var updateTarget = (props) => {
4230
4278
  const form = fields(props, false);
4231
- const operation = props.type === "sendmail" ? notificationRequest(cluster9.PutClusterNotificationEndpointSendmailRequest, form).pipe(Effect53.flatMap(cluster9.putClusterNotificationEndpointSendmail)) : props.type === "smtp" ? notificationRequest(cluster9.PutClusterNotificationEndpointSmtpRequest, form).pipe(Effect53.flatMap(cluster9.putClusterNotificationEndpointSmtp)) : props.type === "gotify" ? notificationRequest(cluster9.PutClusterNotificationEndpointGotifyRequest, form).pipe(Effect53.flatMap(cluster9.putClusterNotificationEndpointGotify)) : notificationRequest(cluster9.PutClusterNotificationEndpointWebhookRequest, form).pipe(Effect53.flatMap(cluster9.putClusterNotificationEndpointWebhook));
4279
+ const operation = props.type === "sendmail" ? notificationRequest(cluster10.PutClusterNotificationEndpointSendmailRequest, form).pipe(Effect54.flatMap(cluster10.putClusterNotificationEndpointSendmail)) : props.type === "smtp" ? notificationRequest(cluster10.PutClusterNotificationEndpointSmtpRequest, form).pipe(Effect54.flatMap(cluster10.putClusterNotificationEndpointSmtp)) : props.type === "gotify" ? notificationRequest(cluster10.PutClusterNotificationEndpointGotifyRequest, form).pipe(Effect54.flatMap(cluster10.putClusterNotificationEndpointGotify)) : notificationRequest(cluster10.PutClusterNotificationEndpointWebhookRequest, form).pipe(Effect54.flatMap(cluster10.putClusterNotificationEndpointWebhook));
4232
4280
  return runPve(props.target, "provision", true, operation);
4233
4281
  };
4234
4282
  var deleteTarget = (props) => {
4235
4283
  const request = { name: props.name };
4236
- const operation = props.type === "sendmail" ? cluster9.deleteClusterNotificationEndpointSendmail(request) : props.type === "smtp" ? cluster9.deleteClusterNotificationEndpointSmtp(request) : props.type === "gotify" ? cluster9.deleteClusterNotificationEndpointGotify(request) : cluster9.deleteClusterNotificationEndpointWebhook(request);
4237
- return runPve(props.target, "provision", true, operation).pipe(Effect53.catchTag("NotFound", () => Effect53.void));
4284
+ const operation = props.type === "sendmail" ? cluster10.deleteClusterNotificationEndpointSendmail(request) : props.type === "smtp" ? cluster10.deleteClusterNotificationEndpointSmtp(request) : props.type === "gotify" ? cluster10.deleteClusterNotificationEndpointGotify(request) : cluster10.deleteClusterNotificationEndpointWebhook(request);
4285
+ return runPve(props.target, "provision", true, operation).pipe(Effect54.catchTag("NotFound", () => Effect54.void));
4238
4286
  };
4239
4287
 
4240
4288
  // src/proxmox/notification-target-lifecycle.ts
4241
4289
  var { guardCreate: guardCreate4, guardUpdate: guardUpdate4 } = specGuards(targetSpec);
4242
- var guard2 = (props, create) => guardCreate4(props, create).pipe(Effect54.andThen(guardUpdate4(props)));
4290
+ var guard2 = (props, create) => guardCreate4(props, create).pipe(Effect55.andThen(guardUpdate4(props)));
4243
4291
  var targetHandlers = {
4244
- list: () => Effect54.succeed([]),
4245
- read: ({ olds }) => Effect54.gen(function* () {
4292
+ list: () => Effect55.succeed([]),
4293
+ read: ({ olds }) => Effect55.gen(function* () {
4246
4294
  const live = yield* readTarget(olds);
4247
4295
  yield* guard2(olds, live === undefined);
4248
4296
  return live;
@@ -4251,8 +4299,8 @@ var targetHandlers = {
4251
4299
  news,
4252
4300
  olds,
4253
4301
  output
4254
- }) => Effect54.gen(function* () {
4255
- if (!isResolved16(news))
4302
+ }) => Effect55.gen(function* () {
4303
+ if (!isResolved17(news))
4256
4304
  return;
4257
4305
  if (olds.name !== news.name || olds.type !== news.type) {
4258
4306
  const destination = yield* readTarget(news);
@@ -4270,7 +4318,7 @@ var targetHandlers = {
4270
4318
  }
4271
4319
  return { action: targetSpec.matches(live, news) ? "noop" : "update" };
4272
4320
  }),
4273
- reconcile: ({ news }) => Effect54.gen(function* () {
4321
+ reconcile: ({ news }) => Effect55.gen(function* () {
4274
4322
  const live = yield* readTarget(news);
4275
4323
  yield* guard2(news, live === undefined);
4276
4324
  if (live === undefined)
@@ -4279,7 +4327,7 @@ var targetHandlers = {
4279
4327
  yield* updateTarget(news);
4280
4328
  const after = yield* readTarget(news);
4281
4329
  if (after === undefined)
4282
- return yield* Effect54.die(new Error(`Notification target ${news.name}: write returned but read-back is absent.`));
4330
+ return yield* Effect55.die(new Error(`Notification target ${news.name}: write returned but read-back is absent.`));
4283
4331
  return after;
4284
4332
  }),
4285
4333
  delete: ({ olds }) => deleteTarget(olds)
@@ -4287,15 +4335,15 @@ var targetHandlers = {
4287
4335
 
4288
4336
  // src/proxmox/notification-target.ts
4289
4337
  var ProxmoxNotificationTarget = Resource18("Proxmox.NotificationTarget");
4290
- var ProxmoxNotificationTargetProvider = () => Provider18.effect(ProxmoxNotificationTarget, Effect55.succeed(ProxmoxNotificationTarget.Provider.of(targetHandlers)));
4338
+ var ProxmoxNotificationTargetProvider = () => Provider18.effect(ProxmoxNotificationTarget, Effect56.succeed(ProxmoxNotificationTarget.Provider.of(targetHandlers)));
4291
4339
  // src/proxmox/pbs-datastore.ts
4292
4340
  import { Resource as Resource19 } from "alchemy";
4293
4341
  import * as Provider19 from "alchemy/Provider";
4294
- import * as Effect61 from "effect/Effect";
4342
+ import * as Effect62 from "effect/Effect";
4295
4343
 
4296
4344
  // src/proxmox/pbs-datastore-lifecycle.ts
4297
- import { isResolved as isResolved17 } from "alchemy/Diff";
4298
- import * as Effect60 from "effect/Effect";
4345
+ import { isResolved as isResolved18 } from "alchemy/Diff";
4346
+ import * as Effect61 from "effect/Effect";
4299
4347
 
4300
4348
  // src/proxmox/pbs-datastore-form.ts
4301
4349
  var attributes = (live, props) => ({
@@ -4320,7 +4368,7 @@ var attributes = (live, props) => ({
4320
4368
  "verify-new": bool(live["verify-new"])
4321
4369
  });
4322
4370
  var same4 = (declared, live) => declared === undefined || declared === live;
4323
- var matches6 = (live, props) => same4(props.comment, live.comment) && same4(props["gc-schedule"]?.trim(), live["gc-schedule"]) && same4(props["prune-schedule"]?.trim(), live["prune-schedule"]) && same4(props["keep-last"], live["keep-last"]) && same4(props["keep-hourly"], live["keep-hourly"]) && same4(props["keep-daily"], live["keep-daily"]) && same4(props["keep-weekly"], live["keep-weekly"]) && same4(props["keep-monthly"], live["keep-monthly"]) && same4(props["keep-yearly"], live["keep-yearly"]) && same4(props["notify-user"], live["notify-user"]) && same4(props["counter-reset-schedule"]?.trim(), live["counter-reset-schedule"]) && (props["notification-thresholds"] === undefined || propertyString(props["notification-thresholds"]) === live["notification-thresholds"]) && same4(props["verify-new"], live["verify-new"]) && (props.notify === undefined || propertyString(props.notify) === live.notify) && (props.tuning === undefined || propertyString(props.tuning) === live.tuning) && (props["maintenance-mode"] === undefined || propertyString(props["maintenance-mode"], "type") === live["maintenance-mode"]);
4371
+ var matches7 = (live, props) => same4(props.comment, live.comment) && same4(props["gc-schedule"]?.trim(), live["gc-schedule"]) && same4(props["prune-schedule"]?.trim(), live["prune-schedule"]) && same4(props["keep-last"], live["keep-last"]) && same4(props["keep-hourly"], live["keep-hourly"]) && same4(props["keep-daily"], live["keep-daily"]) && same4(props["keep-weekly"], live["keep-weekly"]) && same4(props["keep-monthly"], live["keep-monthly"]) && same4(props["keep-yearly"], live["keep-yearly"]) && same4(props["notify-user"], live["notify-user"]) && same4(props["counter-reset-schedule"]?.trim(), live["counter-reset-schedule"]) && (props["notification-thresholds"] === undefined || propertyString(props["notification-thresholds"]) === live["notification-thresholds"]) && same4(props["verify-new"], live["verify-new"]) && (props.notify === undefined || propertyString(props.notify) === live.notify) && (props.tuning === undefined || propertyString(props.tuning) === live.tuning) && (props["maintenance-mode"] === undefined || propertyString(props["maintenance-mode"], "type") === live["maintenance-mode"]);
4324
4372
  var set2 = (key, value) => value === undefined ? {} : { [key]: value };
4325
4373
  var count = (value) => value === undefined ? undefined : String(value);
4326
4374
  var mutable = (props) => ({
@@ -4347,23 +4395,23 @@ var createForm6 = (props) => ({
4347
4395
  path: props.path,
4348
4396
  ...props.backend === undefined ? {} : { backend: props.backend }
4349
4397
  });
4350
- var updateForm3 = (props) => mutable(props);
4398
+ var updateForm4 = (props) => mutable(props);
4351
4399
  var object2 = (props) => `config/datastore/${props.name}`;
4352
4400
 
4353
4401
  // src/proxmox/pbs-datastore-wire.ts
4354
4402
  import * as config from "@distilled.cloud/proxmox-backup/config";
4355
- import * as Effect57 from "effect/Effect";
4403
+ import * as Effect58 from "effect/Effect";
4356
4404
 
4357
4405
  // src/proxmox/distilled-pbs.ts
4358
4406
  import { credentials } from "@distilled.cloud/proxmox-backup/Credentials";
4359
4407
  import * as Retry from "@distilled.cloud/proxmox-backup/Retry";
4360
- import * as Effect56 from "effect/Effect";
4361
- var runPbsWith = (target, credential, op, timeout5 = MEMBER_TIMEOUT) => op.pipe(Retry.none, Effect56.provide(credentials({
4408
+ import * as Effect57 from "effect/Effect";
4409
+ var runPbsWith = (target, credential, op, timeout5 = MEMBER_TIMEOUT) => op.pipe(Retry.none, Effect57.provide(credentials({
4362
4410
  baseUrl: target.api,
4363
4411
  secret: credential.secret,
4364
4412
  tokenId: credential.tokenId
4365
- })), Effect56.timeout(timeout5));
4366
- var runPbs = (target, role, op) => Effect56.gen(function* () {
4413
+ })), Effect57.timeout(timeout5));
4414
+ var runPbs = (target, role, op) => Effect57.gen(function* () {
4367
4415
  const credential = yield* leased(target, role);
4368
4416
  return yield* runPbsWith(target, credential, op);
4369
4417
  });
@@ -4394,7 +4442,7 @@ var createRequest = (props) => ({
4394
4442
  ...props.backend === undefined ? {} : { backend: props.backend }
4395
4443
  });
4396
4444
  var updateRequest = (props) => ({
4397
- ...members(updateForm3(props)),
4445
+ ...members(updateForm4(props)),
4398
4446
  name: props.name
4399
4447
  });
4400
4448
  var wire = (row) => ({
@@ -4413,53 +4461,53 @@ var wire = (row) => ({
4413
4461
  "prune-schedule": row.prune_schedule,
4414
4462
  "verify-new": row.verify_new
4415
4463
  });
4416
- var readOne = (props) => runPbs(props.target, "read", config.getConfigDatastore({ name: props.name })).pipe(Effect57.map((live) => attributes(wire(live), props)), Effect57.catchTag("DatastoreNotFound", () => Effect57.succeed(undefined)));
4464
+ var readOne = (props) => runPbs(props.target, "read", config.getConfigDatastore({ name: props.name })).pipe(Effect58.map((live) => attributes(wire(live), props)), Effect58.catchTag("DatastoreNotFound", () => Effect58.succeed(undefined)));
4417
4465
  var createOne = (props) => runPbs(props.target, "provision", config.createConfigDatastore(createRequest(props)));
4418
4466
  var updateOne = (props) => runPbs(props.target, "provision", config.putConfigDatastore(updateRequest(props)));
4419
- var deleteOne = (props) => Effect57.gen(function* () {
4467
+ var deleteOne = (props) => Effect58.gen(function* () {
4420
4468
  if ((yield* readOne(props)) === undefined)
4421
4469
  return;
4422
4470
  return yield* runPbs(props.target, "provision", config.deleteConfigDatastore({ name: props.name }));
4423
4471
  });
4424
4472
 
4425
4473
  // src/proxmox/pbs-datastore-guard.ts
4426
- import * as Effect58 from "effect/Effect";
4474
+ import * as Effect59 from "effect/Effect";
4427
4475
  var samePath = (left, right) => {
4428
4476
  const trim = (value) => value.length > 1 ? value.replace(/\/+$/, "") : value;
4429
4477
  return trim(left) === trim(right);
4430
4478
  };
4431
- var guardPath = (live, props) => live.path === "" || samePath(live.path, props.path) ? Effect58.void : Effect58.die(new Error(`${object2(props)}: declared path ${props.path} but PBS holds ${live.path}. \`path\` ` + "is create-only, so this cannot be reconciled and will NOT be planned as a silent " + "noop: backups would keep landing in the old directory behind a green plan. Correct " + "the declaration, or remove the datastore and declare a new one -- the contents live, " + "because `destroy-data` is never sent."));
4432
- var guardBackend = (live, props) => props.backend === undefined || propertyString(props.backend) === live.backend ? Effect58.void : Effect58.die(new Error(`${object2(props)}: declared backend ${props.backend} but PBS holds ` + `${live.backend === "" ? "(none — a local datastore)" : live.backend}. \`backend\` ` + "is create-only: PBS has no update for it, so this cannot be reconciled and will NOT " + "be planned as a silent noop. Correct the declaration to match what is really there, " + "or remove the datastore and declare a new one -- the contents live, because " + "`destroy-data` is never sent."));
4433
- var settle2 = (read4, done) => Effect58.gen(function* () {
4479
+ var guardPath = (live, props) => live.path === "" || samePath(live.path, props.path) ? Effect59.void : Effect59.die(new Error(`${object2(props)}: declared path ${props.path} but PBS holds ${live.path}. \`path\` ` + "is create-only, so this cannot be reconciled and will NOT be planned as a silent " + "noop: backups would keep landing in the old directory behind a green plan. Correct " + "the declaration, or remove the datastore and declare a new one -- the contents live, " + "because `destroy-data` is never sent."));
4480
+ var guardBackend = (live, props) => props.backend === undefined || propertyString(props.backend) === live.backend ? Effect59.void : Effect59.die(new Error(`${object2(props)}: declared backend ${props.backend} but PBS holds ` + `${live.backend === "" ? "(none — a local datastore)" : live.backend}. \`backend\` ` + "is create-only: PBS has no update for it, so this cannot be reconciled and will NOT " + "be planned as a silent noop. Correct the declaration to match what is really there, " + "or remove the datastore and declare a new one -- the contents live, because " + "`destroy-data` is never sent."));
4481
+ var settle2 = (read4, done) => Effect59.gen(function* () {
4434
4482
  for (let attempt = 0;attempt < 60; attempt += 1) {
4435
4483
  const live = yield* read4;
4436
4484
  if (done(live))
4437
4485
  return live;
4438
- yield* Effect58.sleep("2 seconds");
4486
+ yield* Effect59.sleep("2 seconds");
4439
4487
  }
4440
4488
  return yield* read4;
4441
4489
  });
4442
4490
 
4443
4491
  // src/proxmox/pbs-datastore-endpoint.ts
4444
- import * as Effect59 from "effect/Effect";
4492
+ import * as Effect60 from "effect/Effect";
4445
4493
  var DATASTORE_ENDPOINT = {
4446
4494
  create: "pbs:POST /config/datastore",
4447
4495
  update: "pbs:PUT /config/datastore/{name}"
4448
4496
  };
4449
- var guardDatastoreForms = (props) => Effect59.gen(function* () {
4497
+ var guardDatastoreForms = (props) => Effect60.gen(function* () {
4450
4498
  yield* guardForm(DATASTORE_ENDPOINT.create, createForm6(props), true);
4451
- yield* guardForm(DATASTORE_ENDPOINT.update, updateForm3(props), false);
4499
+ yield* guardForm(DATASTORE_ENDPOINT.update, updateForm4(props), false);
4452
4500
  });
4453
4501
 
4454
4502
  // src/proxmox/pbs-datastore-lifecycle.ts
4455
- var handlers7 = {
4456
- list: () => Effect60.succeed([]),
4503
+ var handlers6 = {
4504
+ list: () => Effect61.succeed([]),
4457
4505
  read: ({ olds }) => readOne(olds),
4458
4506
  diff: ({
4459
4507
  news,
4460
4508
  output
4461
- }) => Effect60.gen(function* () {
4462
- if (!isResolved17(news))
4509
+ }) => Effect61.gen(function* () {
4510
+ if (!isResolved18(news))
4463
4511
  return;
4464
4512
  yield* guardDatastoreForms(news);
4465
4513
  if (output === undefined)
@@ -4469,9 +4517,9 @@ var handlers7 = {
4469
4517
  return { action: "update" };
4470
4518
  yield* guardPath(live, news);
4471
4519
  yield* guardBackend(live, news);
4472
- return matches6(live, news) ? { action: "noop" } : { action: "update" };
4520
+ return matches7(live, news) ? { action: "noop" } : { action: "update" };
4473
4521
  }),
4474
- reconcile: Effect60.fn(function* ({ news }) {
4522
+ reconcile: Effect61.fn(function* ({ news }) {
4475
4523
  yield* guardDatastoreForms(news);
4476
4524
  const live = yield* readOne(news);
4477
4525
  if (live === undefined) {
@@ -4479,22 +4527,22 @@ var handlers7 = {
4479
4527
  } else {
4480
4528
  yield* guardPath(live, news);
4481
4529
  yield* guardBackend(live, news);
4482
- const form = formToSend(matches6, live, news, updateForm3(news));
4530
+ const form = formToSend(matches7, live, news, updateForm4(news));
4483
4531
  if (form !== undefined) {
4484
4532
  yield* updateOne(news);
4485
4533
  }
4486
4534
  }
4487
- const after = yield* settle2(readOne(news), (row) => row !== undefined && matches6(row, news));
4488
- if (after === undefined || !matches6(after, news)) {
4489
- return yield* Effect60.die(new Error(`${object2(news)}: the write returned no error but the datastore still does not ` + "match the declaration after 120s. Check the PBS task list " + "-- read it with `proxmox-backup-manager task log <upid>`. A slow disk is a " + "plausible cause (see `settle`); a create over an existing chunk store is not, " + "because PBS refuses that outright rather than timing out."));
4535
+ const after = yield* settle2(readOne(news), (row) => row !== undefined && matches7(row, news));
4536
+ if (after === undefined || !matches7(after, news)) {
4537
+ return yield* Effect61.die(new Error(`${object2(news)}: the write returned no error but the datastore still does not ` + "match the declaration after 120s. Check the PBS task list " + "-- read it with `proxmox-backup-manager task log <upid>`. A slow disk is a " + "plausible cause (see `settle`); a create over an existing chunk store is not, " + "because PBS refuses that outright rather than timing out."));
4490
4538
  }
4491
4539
  return after;
4492
4540
  }),
4493
- delete: Effect60.fn(function* ({ olds }) {
4541
+ delete: Effect61.fn(function* ({ olds }) {
4494
4542
  yield* deleteOne(olds);
4495
4543
  const left = yield* settle2(readOne(olds), (row) => row === undefined);
4496
4544
  if (left !== undefined) {
4497
- return yield* Effect60.die(new Error(`${object2(olds)}: the DELETE returned no error but the datastore is still in ` + "datastore.cfg after 120s. Either a backup, verify or GC task still holds it, " + "or the provision role lacks Datastore.Allocate on /datastore/" + `${olds.name}. Read the task log with \`proxmox-backup-manager task log <upid>\`.`));
4545
+ return yield* Effect61.die(new Error(`${object2(olds)}: the DELETE returned no error but the datastore is still in ` + "datastore.cfg after 120s. Either a backup, verify or GC task still holds it, " + "or the provision role lacks Datastore.Allocate on /datastore/" + `${olds.name}. Read the task log with \`proxmox-backup-manager task log <upid>\`.`));
4498
4546
  }
4499
4547
  })
4500
4548
  };
@@ -4503,36 +4551,36 @@ var handlers7 = {
4503
4551
  var PbsDatastore = Resource19("Pbs.Datastore", {
4504
4552
  defaultRemovalPolicy: "retain"
4505
4553
  });
4506
- var PbsDatastoreProvider = () => Provider19.effect(PbsDatastore, Effect61.succeed(PbsDatastore.Provider.of(handlers7)));
4554
+ var PbsDatastoreProvider = () => Provider19.effect(PbsDatastore, Effect62.succeed(PbsDatastore.Provider.of(handlers6)));
4507
4555
  // src/proxmox/pbs-notification-matcher.ts
4508
4556
  import { Resource as Resource20 } from "alchemy";
4509
4557
  import * as Provider20 from "alchemy/Provider";
4510
- import { isResolved as isResolved18 } from "alchemy/Diff";
4511
- import * as Effect64 from "effect/Effect";
4558
+ import { isResolved as isResolved19 } from "alchemy/Diff";
4559
+ import * as Effect65 from "effect/Effect";
4512
4560
 
4513
4561
  // src/proxmox/pbs-notification-matcher-distilled.ts
4514
4562
  import * as config2 from "@distilled.cloud/proxmox-backup/config";
4515
- import * as Effect63 from "effect/Effect";
4563
+ import * as Effect64 from "effect/Effect";
4516
4564
 
4517
4565
  // src/proxmox/pbs-notification-input.ts
4518
4566
  import * as Data3 from "effect/Data";
4519
- import * as Effect62 from "effect/Effect";
4567
+ import * as Effect63 from "effect/Effect";
4520
4568
  import * as Schema4 from "effect/Schema";
4521
4569
 
4522
4570
  class PbsNotificationInputRefusal extends Data3.TaggedError("PbsNotificationInputRefusal") {
4523
4571
  }
4524
- var notificationInput = (schema, fields2) => Schema4.decodeUnknownEffect(Schema4.toType(schema))(fields2).pipe(Effect62.mapError(() => new PbsNotificationInputRefusal({
4572
+ var notificationInput = (schema, fields2) => Schema4.decodeUnknownEffect(Schema4.toType(schema))(fields2).pipe(Effect63.mapError(() => new PbsNotificationInputRefusal({
4525
4573
  message: "PBS notification fields do not match the SDK request schema; no PBS request was sent."
4526
4574
  })));
4527
4575
 
4528
4576
  // src/proxmox/pbs-notification-matcher-distilled.ts
4529
- var readMatcher2 = (props) => runPbs(props.target, "read", config2.getConfigNotificationMatcher({ name: props.name })).pipe(Effect63.map((row) => matcherAttributes({
4577
+ var readMatcher2 = (props) => runPbs(props.target, "read", config2.getConfigNotificationMatcher({ name: props.name })).pipe(Effect64.map((row) => matcherAttributes({
4530
4578
  ...row,
4531
4579
  "invert-match": row.invert_match,
4532
4580
  "match-calendar": row.match_calendar,
4533
4581
  "match-field": row.match_field,
4534
4582
  "match-severity": row.match_severity
4535
- }, props.name)), Effect63.catchTag("NotFound", () => Effect63.succeed(undefined)));
4583
+ }, props.name)), Effect64.catchTag("NotFound", () => Effect64.succeed(undefined)));
4536
4584
  var requestFields = (props, form) => ({
4537
4585
  ...form,
4538
4586
  invert_match: form["invert-match"],
@@ -4541,23 +4589,23 @@ var requestFields = (props, form) => ({
4541
4589
  match_severity: form["match-severity"],
4542
4590
  name: props.name
4543
4591
  });
4544
- var createMatcher2 = (props, form) => runPbs(props.target, "provision", notificationInput(config2.CreateConfigNotificationMatcherRequest, requestFields(props, form)).pipe(Effect63.flatMap(config2.createConfigNotificationMatcher)));
4545
- var updateMatcher2 = (props, form) => runPbs(props.target, "provision", notificationInput(config2.PutConfigNotificationMatcherRequest, requestFields(props, form)).pipe(Effect63.flatMap(config2.putConfigNotificationMatcher)));
4546
- var deleteMatcher2 = (props) => runPbs(props.target, "provision", config2.deleteConfigNotificationMatcher({ name: props.name })).pipe(Effect63.catchTag("NotFound", () => Effect63.void));
4592
+ var createMatcher2 = (props, form) => runPbs(props.target, "provision", notificationInput(config2.CreateConfigNotificationMatcherRequest, requestFields(props, form)).pipe(Effect64.flatMap(config2.createConfigNotificationMatcher)));
4593
+ var updateMatcher2 = (props, form) => runPbs(props.target, "provision", notificationInput(config2.PutConfigNotificationMatcherRequest, requestFields(props, form)).pipe(Effect64.flatMap(config2.putConfigNotificationMatcher)));
4594
+ var deleteMatcher2 = (props) => runPbs(props.target, "provision", config2.deleteConfigNotificationMatcher({ name: props.name })).pipe(Effect64.catchTag("NotFound", () => Effect64.void));
4547
4595
 
4548
4596
  // src/proxmox/pbs-notification-matcher.ts
4549
4597
  var PbsNotificationMatcher = Resource20("Pbs.NotificationMatcher");
4550
4598
  var guardCreate5 = (props, requirePresence) => guardForm("pbs:POST /config/notifications/matchers", matcherCreateForm(props), requirePresence);
4551
4599
  var guardUpdate5 = (props) => guardForm("pbs:PUT /config/notifications/matchers/{name}", matcherUpdateForm(props), false);
4552
- var handlers8 = {
4553
- list: () => Effect64.succeed([]),
4600
+ var handlers7 = {
4601
+ list: () => Effect65.succeed([]),
4554
4602
  read: ({ olds }) => readMatcher2(olds),
4555
4603
  diff: ({
4556
4604
  news,
4557
4605
  olds,
4558
4606
  output
4559
- }) => Effect64.gen(function* () {
4560
- if (!isResolved18(news))
4607
+ }) => Effect65.gen(function* () {
4608
+ if (!isResolved19(news))
4561
4609
  return;
4562
4610
  yield* guardCreate5(news, output === undefined);
4563
4611
  yield* guardUpdate5(news);
@@ -4572,7 +4620,7 @@ var handlers8 = {
4572
4620
  }
4573
4621
  return { action: matcherMatches(live, news) ? "noop" : "update" };
4574
4622
  }),
4575
- reconcile: ({ news }) => Effect64.gen(function* () {
4623
+ reconcile: ({ news }) => Effect65.gen(function* () {
4576
4624
  const live = yield* readMatcher2(news);
4577
4625
  yield* guardCreate5(news, live === undefined);
4578
4626
  yield* guardUpdate5(news);
@@ -4582,24 +4630,24 @@ var handlers8 = {
4582
4630
  yield* updateMatcher2(news, matcherUpdateForm(news));
4583
4631
  const after = yield* readMatcher2(news);
4584
4632
  if (after === undefined)
4585
- return yield* Effect64.fail(new Error(`config/notifications/matchers/${news.name}: the write returned no error but the matcher is still absent.`));
4633
+ return yield* Effect65.fail(new Error(`config/notifications/matchers/${news.name}: the write returned no error but the matcher is still absent.`));
4586
4634
  return after;
4587
4635
  }),
4588
4636
  delete: ({ olds }) => deleteMatcher2(olds)
4589
4637
  };
4590
- var PbsNotificationMatcherProvider = () => Provider20.effect(PbsNotificationMatcher, Effect64.succeed(PbsNotificationMatcher.Provider.of(handlers8)));
4638
+ var PbsNotificationMatcherProvider = () => Provider20.effect(PbsNotificationMatcher, Effect65.succeed(PbsNotificationMatcher.Provider.of(handlers7)));
4591
4639
  // src/proxmox/pbs-notification-target.ts
4592
4640
  import { Resource as Resource21 } from "alchemy";
4593
4641
  import * as Provider21 from "alchemy/Provider";
4594
- import * as Effect67 from "effect/Effect";
4642
+ import * as Effect68 from "effect/Effect";
4595
4643
 
4596
4644
  // src/proxmox/pbs-notification-target-lifecycle.ts
4597
- import { isResolved as isResolved19 } from "alchemy/Diff";
4598
- import * as Effect66 from "effect/Effect";
4645
+ import { isResolved as isResolved20 } from "alchemy/Diff";
4646
+ import * as Effect67 from "effect/Effect";
4599
4647
 
4600
4648
  // src/proxmox/pbs-notification-target-distilled.ts
4601
4649
  import * as config3 from "@distilled.cloud/proxmox-backup/config";
4602
- import * as Effect65 from "effect/Effect";
4650
+ import * as Effect66 from "effect/Effect";
4603
4651
 
4604
4652
  // src/proxmox/pbs-notification-target-wire.ts
4605
4653
  import { Buffer as Buffer2 } from "node:buffer";
@@ -4700,22 +4748,22 @@ var requestFields2 = (props, form) => ({
4700
4748
  var read4 = (props) => {
4701
4749
  switch (props.type) {
4702
4750
  case "sendmail":
4703
- return config3.getConfigNotificationEndpointSendmail({ name: props.name }).pipe(Effect65.map((row) => ({
4751
+ return config3.getConfigNotificationEndpointSendmail({ name: props.name }).pipe(Effect66.map((row) => ({
4704
4752
  ...row,
4705
4753
  "from-address": row.from_address,
4706
4754
  "mailto-user": row.mailto_user
4707
4755
  })));
4708
4756
  case "smtp":
4709
- return config3.getConfigNotificationEndpointSmtp({ name: props.name }).pipe(Effect65.map((row) => ({
4757
+ return config3.getConfigNotificationEndpointSmtp({ name: props.name }).pipe(Effect66.map((row) => ({
4710
4758
  ...row,
4711
4759
  "from-address": row.from_address,
4712
4760
  "mailto-user": row.mailto_user
4713
4761
  })));
4714
4762
  case "webhook":
4715
- return config3.getConfigNotificationEndpointWebhook({ name: props.name }).pipe(Effect65.map((row) => ({ ...row })));
4763
+ return config3.getConfigNotificationEndpointWebhook({ name: props.name }).pipe(Effect66.map((row) => ({ ...row })));
4716
4764
  }
4717
4765
  };
4718
- var readTarget2 = (props) => runPbs(props.target, "read", read4(props)).pipe(Effect65.map((row) => targetAttributes(row, props)), Effect65.catchTag("NotFound", () => Effect65.succeed(undefined)));
4766
+ var readTarget2 = (props) => runPbs(props.target, "read", read4(props)).pipe(Effect66.map((row) => targetAttributes(row, props)), Effect66.catchTag("NotFound", () => Effect66.succeed(undefined)));
4719
4767
  var validateTargetWrite2 = (props, form, mode) => {
4720
4768
  const schema = mode === "create" ? {
4721
4769
  sendmail: config3.CreateConfigNotificationEndpointSendmailRequest,
@@ -4726,22 +4774,22 @@ var validateTargetWrite2 = (props, form, mode) => {
4726
4774
  smtp: config3.PutConfigNotificationEndpointSmtpRequest,
4727
4775
  webhook: config3.PutConfigNotificationEndpointWebhookRequest
4728
4776
  }[props.type];
4729
- return notificationInput(schema, requestFields2(props, form)).pipe(Effect65.asVoid);
4777
+ return notificationInput(schema, requestFields2(props, form)).pipe(Effect66.asVoid);
4730
4778
  };
4731
4779
  var createTarget2 = (props, form) => {
4732
4780
  const fields2 = requestFields2(props, form);
4733
- const operation = props.type === "sendmail" ? notificationInput(config3.CreateConfigNotificationEndpointSendmailRequest, fields2).pipe(Effect65.flatMap(config3.createConfigNotificationEndpointSendmail)) : props.type === "smtp" ? notificationInput(config3.CreateConfigNotificationEndpointSmtpRequest, fields2).pipe(Effect65.flatMap(config3.createConfigNotificationEndpointSmtp)) : notificationInput(config3.CreateConfigNotificationEndpointWebhookRequest, fields2).pipe(Effect65.flatMap(config3.createConfigNotificationEndpointWebhook));
4781
+ const operation = props.type === "sendmail" ? notificationInput(config3.CreateConfigNotificationEndpointSendmailRequest, fields2).pipe(Effect66.flatMap(config3.createConfigNotificationEndpointSendmail)) : props.type === "smtp" ? notificationInput(config3.CreateConfigNotificationEndpointSmtpRequest, fields2).pipe(Effect66.flatMap(config3.createConfigNotificationEndpointSmtp)) : notificationInput(config3.CreateConfigNotificationEndpointWebhookRequest, fields2).pipe(Effect66.flatMap(config3.createConfigNotificationEndpointWebhook));
4734
4782
  return runPbs(props.target, "provision", operation);
4735
4783
  };
4736
4784
  var updateTarget2 = (props, form) => {
4737
4785
  const fields2 = requestFields2(props, form);
4738
- const operation = props.type === "sendmail" ? notificationInput(config3.PutConfigNotificationEndpointSendmailRequest, fields2).pipe(Effect65.flatMap(config3.putConfigNotificationEndpointSendmail)) : props.type === "smtp" ? notificationInput(config3.PutConfigNotificationEndpointSmtpRequest, fields2).pipe(Effect65.flatMap(config3.putConfigNotificationEndpointSmtp)) : notificationInput(config3.PutConfigNotificationEndpointWebhookRequest, fields2).pipe(Effect65.flatMap(config3.putConfigNotificationEndpointWebhook));
4786
+ const operation = props.type === "sendmail" ? notificationInput(config3.PutConfigNotificationEndpointSendmailRequest, fields2).pipe(Effect66.flatMap(config3.putConfigNotificationEndpointSendmail)) : props.type === "smtp" ? notificationInput(config3.PutConfigNotificationEndpointSmtpRequest, fields2).pipe(Effect66.flatMap(config3.putConfigNotificationEndpointSmtp)) : notificationInput(config3.PutConfigNotificationEndpointWebhookRequest, fields2).pipe(Effect66.flatMap(config3.putConfigNotificationEndpointWebhook));
4739
4787
  return runPbs(props.target, "provision", operation);
4740
4788
  };
4741
4789
  var deleteTarget2 = (props) => {
4742
4790
  const request = { name: props.name };
4743
4791
  const operation = props.type === "sendmail" ? config3.deleteConfigNotificationEndpointSendmail(request) : props.type === "smtp" ? config3.deleteConfigNotificationEndpointSmtp(request) : config3.deleteConfigNotificationEndpointWebhook(request);
4744
- return runPbs(props.target, "provision", operation).pipe(Effect65.catchTag("NotFound", () => Effect65.void));
4792
+ return runPbs(props.target, "provision", operation).pipe(Effect66.catchTag("NotFound", () => Effect66.void));
4745
4793
  };
4746
4794
 
4747
4795
  // src/proxmox/pbs-notification-target-endpoint.ts
@@ -4932,7 +4980,7 @@ var targetForm = (props, groups, carry, mode) => {
4932
4980
  var path = (props) => `config/notifications/endpoints/${props.type}/${props.name}`;
4933
4981
  var refuse2 = (props) => {
4934
4982
  const reasons = refusals(props);
4935
- return reasons.length === 0 ? Effect66.void : Effect66.die(new Error(`${path(props)}: ${reasons.join("; ")}.`));
4983
+ return reasons.length === 0 ? Effect67.void : Effect67.die(new Error(`${path(props)}: ${reasons.join("; ")}.`));
4936
4984
  };
4937
4985
  var toCarry = (live, props, groups, sealed) => {
4938
4986
  const header = headerState(live, props, groups) === "stale";
@@ -4944,17 +4992,17 @@ var requireValues = (props, groups, carry) => {
4944
4992
  ...carry.header ? groups.header.missing : [],
4945
4993
  ...carry.sealed ? groups.sealed.missing : []
4946
4994
  ];
4947
- return missing.length === 0 ? Effect66.void : Effect66.die(new Error(`${path(props)}: this write must send write-only values, and ${missing.join(", ")} ` + "is unset or empty in the deploying environment. Export it and deploy again."));
4995
+ return missing.length === 0 ? Effect67.void : Effect67.die(new Error(`${path(props)}: this write must send write-only values, and ${missing.join(", ")} ` + "is unset or empty in the deploying environment. Export it and deploy again."));
4948
4996
  };
4949
- var handlers9 = {
4950
- list: () => Effect66.succeed([]),
4951
- read: ({ olds, output }) => (output === undefined ? refuse2(olds) : Effect66.void).pipe(Effect66.andThen(readTarget2(olds)), Effect66.map((live) => live === undefined ? undefined : { ...live, sealed: output?.sealed ?? "" })),
4997
+ var handlers8 = {
4998
+ list: () => Effect67.succeed([]),
4999
+ read: ({ olds, output }) => (output === undefined ? refuse2(olds) : Effect67.void).pipe(Effect67.andThen(readTarget2(olds)), Effect67.map((live) => live === undefined ? undefined : { ...live, sealed: output?.sealed ?? "" })),
4952
5000
  diff: ({
4953
5001
  news,
4954
5002
  olds,
4955
5003
  output
4956
- }) => Effect66.gen(function* () {
4957
- if (output === undefined || !isResolved19(news))
5004
+ }) => Effect67.gen(function* () {
5005
+ if (output === undefined || !isResolved20(news))
4958
5006
  return;
4959
5007
  yield* refuse2(news);
4960
5008
  if (olds !== undefined && (olds.type !== news.type || olds.name !== news.name)) {
@@ -4975,7 +5023,7 @@ var handlers9 = {
4975
5023
  return { action: "update" };
4976
5024
  return toCarry(live, news, resolveGroups(news), output.sealed) === undefined ? { action: "noop" } : { action: "update" };
4977
5025
  }),
4978
- reconcile: ({ news, output }) => Effect66.gen(function* () {
5026
+ reconcile: ({ news, output }) => Effect67.gen(function* () {
4979
5027
  yield* refuse2(news);
4980
5028
  const groups = resolveGroups(news);
4981
5029
  const live = yield* readTarget2(news);
@@ -5000,7 +5048,7 @@ var handlers9 = {
5000
5048
  }
5001
5049
  const after = yield* readTarget2(news);
5002
5050
  if (after === undefined) {
5003
- return yield* Effect66.die(new Error(`${path(news)}: the write returned no error but the target is still absent.`));
5051
+ return yield* Effect67.die(new Error(`${path(news)}: the write returned no error but the target is still absent.`));
5004
5052
  }
5005
5053
  return { ...after, sealed };
5006
5054
  }),
@@ -5009,15 +5057,15 @@ var handlers9 = {
5009
5057
 
5010
5058
  // src/proxmox/pbs-notification-target.ts
5011
5059
  var PbsNotificationTarget = Resource21("Pbs.NotificationTarget");
5012
- var PbsNotificationTargetProvider = () => Provider21.effect(PbsNotificationTarget, Effect67.succeed(PbsNotificationTarget.Provider.of(handlers9)));
5060
+ var PbsNotificationTargetProvider = () => Provider21.effect(PbsNotificationTarget, Effect68.succeed(PbsNotificationTarget.Provider.of(handlers8)));
5013
5061
  // src/proxmox/pbs-prune-job.ts
5014
5062
  import { Resource as Resource22 } from "alchemy";
5015
5063
  import * as Provider22 from "alchemy/Provider";
5016
- import * as Effect70 from "effect/Effect";
5064
+ import * as Effect71 from "effect/Effect";
5017
5065
 
5018
5066
  // src/proxmox/pbs-prune-job-lifecycle.ts
5019
- import { isResolved as isResolved20 } from "alchemy/Diff";
5020
- import * as Effect69 from "effect/Effect";
5067
+ import { isResolved as isResolved21 } from "alchemy/Diff";
5068
+ import * as Effect70 from "effect/Effect";
5021
5069
 
5022
5070
  // src/proxmox/pbs-prune-job-form.ts
5023
5071
  var KEEP_KEYS = [
@@ -5095,7 +5143,7 @@ var spec = {
5095
5143
 
5096
5144
  // src/proxmox/pbs-prune-job-wire.ts
5097
5145
  import * as config4 from "@distilled.cloud/proxmox-backup/config";
5098
- import * as Effect68 from "effect/Effect";
5146
+ import * as Effect69 from "effect/Effect";
5099
5147
  var members2 = (form) => ({
5100
5148
  ...form["comment"] === undefined ? {} : { comment: form["comment"] },
5101
5149
  ...form["disable"] === undefined ? {} : { disable: form["disable"] },
@@ -5130,10 +5178,10 @@ var wire2 = (row) => ({
5130
5178
  "keep-yearly": row.keep_yearly,
5131
5179
  "max-depth": row.max_depth
5132
5180
  });
5133
- var readOne2 = (props) => runPbs(props.target, "read", config4.getConfigPrune({ id: props.id })).pipe(Effect68.map((row) => spec.attributes(wire2(row), props)), Effect68.catchTag("PruneJobNotFound", () => Effect68.succeed(undefined)));
5181
+ var readOne2 = (props) => runPbs(props.target, "read", config4.getConfigPrune({ id: props.id })).pipe(Effect69.map((row) => spec.attributes(wire2(row), props)), Effect69.catchTag("PruneJobNotFound", () => Effect69.succeed(undefined)));
5134
5182
  var createOne2 = (props) => runPbs(props.target, "provision", config4.createConfigPrune(createRequest2(props)));
5135
5183
  var updateOne2 = (props) => runPbs(props.target, "provision", config4.putConfigPrune(updateRequest2(props)));
5136
- var deleteOne2 = (props) => Effect68.gen(function* () {
5184
+ var deleteOne2 = (props) => Effect69.gen(function* () {
5137
5185
  if ((yield* readOne2(props)) === undefined)
5138
5186
  return;
5139
5187
  return yield* runPbs(props.target, "provision", config4.deleteConfigPrune({ id: props.id }));
@@ -5141,14 +5189,14 @@ var deleteOne2 = (props) => Effect68.gen(function* () {
5141
5189
 
5142
5190
  // src/proxmox/pbs-prune-job-lifecycle.ts
5143
5191
  var { guardCreate: guardCreate6, guardUpdate: guardUpdate6 } = specGuards(spec);
5144
- var handlers10 = {
5145
- list: () => Effect69.succeed([]),
5192
+ var handlers9 = {
5193
+ list: () => Effect70.succeed([]),
5146
5194
  read: ({ olds }) => readOne2(olds),
5147
5195
  diff: ({
5148
5196
  news,
5149
5197
  output
5150
- }) => Effect69.gen(function* () {
5151
- if (!isResolved20(news))
5198
+ }) => Effect70.gen(function* () {
5199
+ if (!isResolved21(news))
5152
5200
  return;
5153
5201
  yield* guardCreate6(news, output === undefined);
5154
5202
  yield* guardUpdate6(news);
@@ -5161,7 +5209,7 @@ var handlers10 = {
5161
5209
  }
5162
5210
  return { action: spec.matches(live, news) ? "noop" : "update" };
5163
5211
  }),
5164
- reconcile: ({ news }) => Effect69.gen(function* () {
5212
+ reconcile: ({ news }) => Effect70.gen(function* () {
5165
5213
  const live = yield* readOne2(news);
5166
5214
  yield* guardCreate6(news, live === undefined);
5167
5215
  yield* guardUpdate6(news);
@@ -5171,7 +5219,7 @@ var handlers10 = {
5171
5219
  yield* updateOne2(news);
5172
5220
  const after = yield* readOne2(news);
5173
5221
  if (after === undefined) {
5174
- return yield* Effect69.fail(new Error(`${spec.path(news)}: write succeeded but job is absent.`));
5222
+ return yield* Effect70.fail(new Error(`${spec.path(news)}: write succeeded but job is absent.`));
5175
5223
  }
5176
5224
  return after;
5177
5225
  }),
@@ -5180,15 +5228,15 @@ var handlers10 = {
5180
5228
 
5181
5229
  // src/proxmox/pbs-prune-job.ts
5182
5230
  var PbsPruneJob = Resource22("Pbs.PruneJob");
5183
- var PbsPruneJobProvider = () => Provider22.effect(PbsPruneJob, Effect70.succeed(PbsPruneJob.Provider.of(handlers10)));
5231
+ var PbsPruneJobProvider = () => Provider22.effect(PbsPruneJob, Effect71.succeed(PbsPruneJob.Provider.of(handlers9)));
5184
5232
  // src/proxmox/pbs-sync-job.ts
5185
5233
  import { Resource as Resource23 } from "alchemy";
5186
5234
  import * as Provider23 from "alchemy/Provider";
5187
- import * as Effect73 from "effect/Effect";
5235
+ import * as Effect74 from "effect/Effect";
5188
5236
 
5189
5237
  // src/proxmox/pbs-sync-job-lifecycle.ts
5190
- import { isResolved as isResolved21 } from "alchemy/Diff";
5191
- import * as Effect72 from "effect/Effect";
5238
+ import { isResolved as isResolved22 } from "alchemy/Diff";
5239
+ import * as Effect73 from "effect/Effect";
5192
5240
 
5193
5241
  // src/proxmox/pbs-sync-job-form.ts
5194
5242
  var UNSET4 = -1;
@@ -5265,7 +5313,7 @@ var spec2 = {
5265
5313
 
5266
5314
  // src/proxmox/pbs-sync-job-wire.ts
5267
5315
  import * as config5 from "@distilled.cloud/proxmox-backup/config";
5268
- import * as Effect71 from "effect/Effect";
5316
+ import * as Effect72 from "effect/Effect";
5269
5317
  var members3 = (form) => ({
5270
5318
  ...form["remote-store"] === undefined ? {} : { remote_store: form["remote-store"] },
5271
5319
  ...form["remove-vanished"] === undefined ? {} : { remove_vanished: form["remove-vanished"] },
@@ -5304,10 +5352,10 @@ var wire3 = (row) => ({
5304
5352
  "sync-direction": row.sync_direction,
5305
5353
  "group-filter": row.group_filter
5306
5354
  });
5307
- var readOne3 = (props) => runPbs(props.target, "read", config5.getConfigSync({ id: props.id })).pipe(Effect71.map((row) => spec2.attributes(wire3(row), props)), Effect71.catchTag("SyncJobNotFound", () => Effect71.succeed(undefined)));
5355
+ var readOne3 = (props) => runPbs(props.target, "read", config5.getConfigSync({ id: props.id })).pipe(Effect72.map((row) => spec2.attributes(wire3(row), props)), Effect72.catchTag("SyncJobNotFound", () => Effect72.succeed(undefined)));
5308
5356
  var createOne3 = (props) => runPbs(props.target, "provision", config5.syncConfig(createRequest3(props)));
5309
5357
  var updateOne3 = (props) => runPbs(props.target, "provision", config5.putConfigSync(updateRequest3(props)));
5310
- var deleteOne3 = (props) => Effect71.gen(function* () {
5358
+ var deleteOne3 = (props) => Effect72.gen(function* () {
5311
5359
  if ((yield* readOne3(props)) === undefined)
5312
5360
  return;
5313
5361
  return yield* runPbs(props.target, "provision", config5.deleteConfigSync({ id: props.id }));
@@ -5315,11 +5363,11 @@ var deleteOne3 = (props) => Effect71.gen(function* () {
5315
5363
 
5316
5364
  // src/proxmox/pbs-sync-job-lifecycle.ts
5317
5365
  var { guardCreate: guardCreate7, guardUpdate: guardUpdate7 } = specGuards(spec2);
5318
- var handlers11 = {
5319
- list: () => Effect72.succeed([]),
5366
+ var handlers10 = {
5367
+ list: () => Effect73.succeed([]),
5320
5368
  read: ({ olds }) => readOne3(olds),
5321
- diff: ({ news, output }) => Effect72.gen(function* () {
5322
- if (!isResolved21(news))
5369
+ diff: ({ news, output }) => Effect73.gen(function* () {
5370
+ if (!isResolved22(news))
5323
5371
  return;
5324
5372
  yield* guardCreate7(news, output === undefined);
5325
5373
  yield* guardUpdate7(news);
@@ -5332,7 +5380,7 @@ var handlers11 = {
5332
5380
  }
5333
5381
  return { action: spec2.matches(live, news) ? "noop" : "update" };
5334
5382
  }),
5335
- reconcile: ({ news }) => Effect72.gen(function* () {
5383
+ reconcile: ({ news }) => Effect73.gen(function* () {
5336
5384
  const live = yield* readOne3(news);
5337
5385
  yield* guardCreate7(news, live === undefined);
5338
5386
  yield* guardUpdate7(news);
@@ -5342,7 +5390,7 @@ var handlers11 = {
5342
5390
  yield* updateOne3(news);
5343
5391
  const after = yield* readOne3(news);
5344
5392
  if (after === undefined) {
5345
- return yield* Effect72.fail(new Error(`${spec2.path(news)}: write succeeded but job is absent.`));
5393
+ return yield* Effect73.fail(new Error(`${spec2.path(news)}: write succeeded but job is absent.`));
5346
5394
  }
5347
5395
  return after;
5348
5396
  }),
@@ -5351,15 +5399,15 @@ var handlers11 = {
5351
5399
 
5352
5400
  // src/proxmox/pbs-sync-job.ts
5353
5401
  var PbsSyncJob = Resource23("Pbs.SyncJob");
5354
- var PbsSyncJobProvider = () => Provider23.effect(PbsSyncJob, Effect73.succeed(PbsSyncJob.Provider.of(handlers11)));
5402
+ var PbsSyncJobProvider = () => Provider23.effect(PbsSyncJob, Effect74.succeed(PbsSyncJob.Provider.of(handlers10)));
5355
5403
  // src/proxmox/pbs-verify-job.ts
5356
5404
  import { Resource as Resource24 } from "alchemy";
5357
5405
  import * as Provider24 from "alchemy/Provider";
5358
- import * as Effect76 from "effect/Effect";
5406
+ import * as Effect77 from "effect/Effect";
5359
5407
 
5360
5408
  // src/proxmox/pbs-verify-job-lifecycle.ts
5361
- import { isResolved as isResolved22 } from "alchemy/Diff";
5362
- import * as Effect75 from "effect/Effect";
5409
+ import { isResolved as isResolved23 } from "alchemy/Diff";
5410
+ import * as Effect76 from "effect/Effect";
5363
5411
 
5364
5412
  // src/proxmox/pbs-verify-job-form.ts
5365
5413
  var rechecks = (ignoreVerified, outdatedAfter) => {
@@ -5406,7 +5454,7 @@ var spec3 = {
5406
5454
 
5407
5455
  // src/proxmox/pbs-verify-job-wire.ts
5408
5456
  import * as config6 from "@distilled.cloud/proxmox-backup/config";
5409
- import * as Effect74 from "effect/Effect";
5457
+ import * as Effect75 from "effect/Effect";
5410
5458
  var members4 = (form) => ({
5411
5459
  ...form["ignore-verified"] === undefined ? {} : { ignore_verified: form["ignore-verified"] },
5412
5460
  ...form["store"] === undefined ? {} : { store: form["store"] },
@@ -5431,10 +5479,10 @@ var wire4 = (row) => ({
5431
5479
  "max-depth": row.max_depth,
5432
5480
  "outdated-after": row.outdated_after
5433
5481
  });
5434
- var readOne4 = (props) => runPbs(props.target, "read", config6.getConfigVerify({ id: props.id })).pipe(Effect74.map((row) => spec3.attributes(wire4(row), props)), Effect74.catchTag("VerifyJobNotFound", () => Effect74.succeed(undefined)));
5482
+ var readOne4 = (props) => runPbs(props.target, "read", config6.getConfigVerify({ id: props.id })).pipe(Effect75.map((row) => spec3.attributes(wire4(row), props)), Effect75.catchTag("VerifyJobNotFound", () => Effect75.succeed(undefined)));
5435
5483
  var createOne4 = (props) => runPbs(props.target, "provision", config6.verifyConfig(createRequest4(props)));
5436
5484
  var updateOne4 = (props) => runPbs(props.target, "provision", config6.putConfigVerify(updateRequest4(props)));
5437
- var deleteOne4 = (props) => Effect74.gen(function* () {
5485
+ var deleteOne4 = (props) => Effect75.gen(function* () {
5438
5486
  if ((yield* readOne4(props)) === undefined)
5439
5487
  return;
5440
5488
  return yield* runPbs(props.target, "provision", config6.deleteConfigVerify({ id: props.id }));
@@ -5442,14 +5490,14 @@ var deleteOne4 = (props) => Effect74.gen(function* () {
5442
5490
 
5443
5491
  // src/proxmox/pbs-verify-job-lifecycle.ts
5444
5492
  var { guardCreate: guardCreate8, guardUpdate: guardUpdate8 } = specGuards(spec3);
5445
- var handlers12 = {
5446
- list: () => Effect75.succeed([]),
5493
+ var handlers11 = {
5494
+ list: () => Effect76.succeed([]),
5447
5495
  read: ({ olds }) => readOne4(olds),
5448
5496
  diff: ({
5449
5497
  news,
5450
5498
  output
5451
- }) => Effect75.gen(function* () {
5452
- if (!isResolved22(news))
5499
+ }) => Effect76.gen(function* () {
5500
+ if (!isResolved23(news))
5453
5501
  return;
5454
5502
  yield* guardCreate8(news, output === undefined);
5455
5503
  yield* guardUpdate8(news);
@@ -5462,7 +5510,7 @@ var handlers12 = {
5462
5510
  }
5463
5511
  return { action: spec3.matches(live, news) ? "noop" : "update" };
5464
5512
  }),
5465
- reconcile: ({ news }) => Effect75.gen(function* () {
5513
+ reconcile: ({ news }) => Effect76.gen(function* () {
5466
5514
  const live = yield* readOne4(news);
5467
5515
  yield* guardCreate8(news, live === undefined);
5468
5516
  yield* guardUpdate8(news);
@@ -5472,7 +5520,7 @@ var handlers12 = {
5472
5520
  yield* updateOne4(news);
5473
5521
  const after = yield* readOne4(news);
5474
5522
  if (after === undefined) {
5475
- return yield* Effect75.fail(new Error(`${spec3.path(news)}: write succeeded but job is absent.`));
5523
+ return yield* Effect76.fail(new Error(`${spec3.path(news)}: write succeeded but job is absent.`));
5476
5524
  }
5477
5525
  return after;
5478
5526
  }),
@@ -5481,15 +5529,15 @@ var handlers12 = {
5481
5529
 
5482
5530
  // src/proxmox/pbs-verify-job.ts
5483
5531
  var PbsVerifyJob = Resource24("Pbs.VerifyJob");
5484
- var PbsVerifyJobProvider = () => Provider24.effect(PbsVerifyJob, Effect76.succeed(PbsVerifyJob.Provider.of(handlers12)));
5532
+ var PbsVerifyJobProvider = () => Provider24.effect(PbsVerifyJob, Effect77.succeed(PbsVerifyJob.Provider.of(handlers11)));
5485
5533
  // src/proxmox/pool.ts
5486
5534
  import { Resource as Resource25 } from "alchemy";
5487
- import { isResolved as isResolved23 } from "alchemy/Diff";
5535
+ import { isResolved as isResolved24 } from "alchemy/Diff";
5488
5536
  import * as Provider25 from "alchemy/Provider";
5489
5537
  import * as pools from "@distilled.cloud/proxmox/pools";
5490
5538
  import { ProxmoxParseError as ProxmoxParseError5 } from "@distilled.cloud/proxmox/Errors";
5491
5539
  import * as Schema5 from "effect/Schema";
5492
- import * as Effect77 from "effect/Effect";
5540
+ import * as Effect78 from "effect/Effect";
5493
5541
  var ProxmoxPool = Resource25("Proxmox.Pool");
5494
5542
  var poolCreateForm = (props) => ({
5495
5543
  comment: props.comment ?? "",
@@ -5515,16 +5563,16 @@ var spec4 = {
5515
5563
  updateForm: poolUpdateForm
5516
5564
  };
5517
5565
  var { guardCreate: guardCreate9, guardUpdate: guardUpdate9 } = specGuards(spec4);
5518
- var readPool = (props) => runPve(props.target, "read", false, pools.getPool({ poolid: props.poolid })).pipe(Effect77.flatMap((live) => Schema5.decodeUnknownEffect(Schema5.toType(pools.GetPoolResponse))(live).pipe(Effect77.mapError(() => new ProxmoxParseError5({
5566
+ var readPool = (props) => runPve(props.target, "read", false, pools.getPool({ poolid: props.poolid })).pipe(Effect78.flatMap((live) => Schema5.decodeUnknownEffect(Schema5.toType(pools.GetPoolResponse))(live).pipe(Effect78.mapError(() => new ProxmoxParseError5({
5519
5567
  body: undefined,
5520
5568
  cause: "Pool response does not match its vendor schema"
5521
- })), Effect77.as(live))), Effect77.map((live) => spec4.attributes({ ...live }, props)), Effect77.catchTag("PoolNotFound", () => Effect77.succeed(undefined)), Effect77.catchTag("NotFound", () => Effect77.succeed(undefined)));
5522
- var deletePool2 = (props) => runPve(props.target, "provision", true, pools.deletePool({ poolid: props.poolid })).pipe(Effect77.catchTag("PoolNotFound", () => Effect77.void), Effect77.catchTag("NotFound", () => Effect77.void));
5523
- var ProxmoxPoolProvider = () => Provider25.effect(ProxmoxPool, Effect77.succeed(ProxmoxPool.Provider.of({
5524
- list: () => Effect77.succeed([]),
5569
+ })), Effect78.as(live))), Effect78.map((live) => spec4.attributes({ ...live }, props)), Effect78.catchTag("PoolNotFound", () => Effect78.succeed(undefined)), Effect78.catchTag("NotFound", () => Effect78.succeed(undefined)));
5570
+ var deletePool2 = (props) => runPve(props.target, "provision", true, pools.deletePool({ poolid: props.poolid })).pipe(Effect78.catchTag("PoolNotFound", () => Effect78.void), Effect78.catchTag("NotFound", () => Effect78.void));
5571
+ var ProxmoxPoolProvider = () => Provider25.effect(ProxmoxPool, Effect78.succeed(ProxmoxPool.Provider.of({
5572
+ list: () => Effect78.succeed([]),
5525
5573
  read: ({ olds }) => readPool(olds),
5526
- diff: Effect77.fn(function* ({ news, output }) {
5527
- if (!isResolved23(news))
5574
+ diff: Effect78.fn(function* ({ news, output }) {
5575
+ if (!isResolved24(news))
5528
5576
  return;
5529
5577
  yield* guardCreate9(news, output === undefined);
5530
5578
  yield* guardUpdate9(news);
@@ -5537,7 +5585,7 @@ var ProxmoxPoolProvider = () => Provider25.effect(ProxmoxPool, Effect77.succeed(
5537
5585
  }
5538
5586
  return { action: spec4.matches(live, news) ? "noop" : "update" };
5539
5587
  }),
5540
- reconcile: Effect77.fn(function* ({ news }) {
5588
+ reconcile: Effect78.fn(function* ({ news }) {
5541
5589
  const live = yield* readPool(news);
5542
5590
  yield* guardCreate9(news, live === undefined);
5543
5591
  yield* guardUpdate9(news);
@@ -5553,7 +5601,7 @@ var ProxmoxPoolProvider = () => Provider25.effect(ProxmoxPool, Effect77.succeed(
5553
5601
  }
5554
5602
  const after = yield* readPool(news);
5555
5603
  if (after === undefined)
5556
- return yield* Effect77.fail(new Error(`pools/${news.poolid}: write returned success but the pool is still absent`));
5604
+ return yield* Effect78.fail(new Error(`pools/${news.poolid}: write returned success but the pool is still absent`));
5557
5605
  return after;
5558
5606
  }),
5559
5607
  delete: ({ olds }) => deletePool2(olds)
@@ -5750,14 +5798,14 @@ echo 'provision baseline: done. Next: point the OpenBao proxmox mount at these u
5750
5798
  // src/proxmox/provision-declare.ts
5751
5799
  import { adopt } from "alchemy/AdoptPolicy";
5752
5800
  import * as RemovalPolicy from "alchemy/RemovalPolicy";
5753
- import * as Effect81 from "effect/Effect";
5801
+ import * as Effect82 from "effect/Effect";
5754
5802
 
5755
5803
  // src/proxmox/role.ts
5756
5804
  import { Resource as Resource26 } from "alchemy";
5757
- import { isResolved as isResolved24 } from "alchemy/Diff";
5805
+ import { isResolved as isResolved25 } from "alchemy/Diff";
5758
5806
  import * as Provider26 from "alchemy/Provider";
5759
5807
  import * as access5 from "@distilled.cloud/proxmox/access";
5760
- import * as Effect78 from "effect/Effect";
5808
+ import * as Effect79 from "effect/Effect";
5761
5809
 
5762
5810
  // src/proxmox/role-wire.ts
5763
5811
  var ROLE_CREATE = "pve:POST /access/roles";
@@ -5767,79 +5815,79 @@ var createForm7 = (props) => ({
5767
5815
  privs: canonical2(props.privs).join(","),
5768
5816
  roleid: props.roleid
5769
5817
  });
5770
- var updateForm4 = (props) => ({
5818
+ var updateForm5 = (props) => ({
5771
5819
  privs: canonical2(props.privs).join(","),
5772
5820
  roleid: props.roleid
5773
5821
  });
5774
5822
  var find2 = (rows, roleid) => rows.find((row) => row.roleid === roleid);
5775
- var attributesOf7 = (row, props) => ({
5823
+ var attributesOf8 = (row, props) => ({
5776
5824
  privs: canonical2(row.privs === undefined ? [] : row.privs.split(",")),
5777
5825
  roleid: props.roleid
5778
5826
  });
5779
- var matches7 = (attributes2, props) => canonical2(attributes2.privs).join(",") === canonical2(props.privs).join(",");
5827
+ var matches8 = (attributes2, props) => canonical2(attributes2.privs).join(",") === canonical2(props.privs).join(",");
5780
5828
 
5781
5829
  // src/proxmox/role.ts
5782
5830
  var ProxmoxRole = Resource26("Proxmox.Role");
5783
- var readRole = (props) => readOrUnreadable(runPve(props.target, "read", false, access5.listAccessRoles({}))).pipe(Effect78.map((rows) => {
5831
+ var readRole = (props) => readOrUnreadable(runPve(props.target, "read", false, access5.listAccessRoles({}))).pipe(Effect79.map((rows) => {
5784
5832
  if (rows === UNREADABLE)
5785
5833
  return UNREADABLE;
5786
5834
  const row = find2(rows, props.roleid);
5787
- return row === undefined ? undefined : attributesOf7(row, props);
5835
+ return row === undefined ? undefined : attributesOf8(row, props);
5788
5836
  }));
5789
5837
  var dropUnreadable5 = (live) => live === UNREADABLE ? undefined : live;
5790
- var ProxmoxRoleProvider = () => Provider26.effect(ProxmoxRole, Effect78.succeed(ProxmoxRole.Provider.of({
5791
- list: () => Effect78.succeed([]),
5792
- read: Effect78.fn(function* ({ olds }) {
5838
+ var ProxmoxRoleProvider = () => Provider26.effect(ProxmoxRole, Effect79.succeed(ProxmoxRole.Provider.of({
5839
+ list: () => Effect79.succeed([]),
5840
+ read: Effect79.fn(function* ({ olds }) {
5793
5841
  return dropUnreadable5(yield* readRole(olds));
5794
5842
  }),
5795
- diff: Effect78.fn(function* ({ news, output }) {
5796
- if (!isResolved24(news))
5843
+ diff: Effect79.fn(function* ({ news, output }) {
5844
+ if (!isResolved25(news))
5797
5845
  return;
5798
5846
  yield* guardWrite2(ROLE_CREATE, createForm7(news), output === undefined);
5799
- yield* guardWrite2(ROLE_UPDATE, updateForm4(news), false);
5847
+ yield* guardWrite2(ROLE_UPDATE, updateForm5(news), false);
5800
5848
  if (output === undefined)
5801
5849
  return;
5802
5850
  const live = yield* readRole(news);
5803
5851
  if (live === UNREADABLE) {
5804
- yield* unreadableWarning("Proxmox.Role", news.roleid);
5852
+ yield* unreadableWarning("Proxmox.Role", news.roleid, news.target.mount, mintTier(news.target, "read"));
5805
5853
  return { action: "noop" };
5806
5854
  }
5807
5855
  if (live === undefined) {
5808
5856
  yield* guardWrite2(ROLE_CREATE, createForm7(news), true);
5809
5857
  return { action: "update" };
5810
5858
  }
5811
- return matches7(live, news) ? { action: "noop" } : { action: "update" };
5859
+ return matches8(live, news) ? { action: "noop" } : { action: "update" };
5812
5860
  }),
5813
- reconcile: Effect78.fn(function* ({ news }) {
5861
+ reconcile: Effect79.fn(function* ({ news }) {
5814
5862
  const before = dropUnreadable5(yield* readRole(news));
5815
5863
  yield* guardWrite2(ROLE_CREATE, createForm7(news), before === undefined);
5816
- yield* guardWrite2(ROLE_UPDATE, updateForm4(news), false);
5864
+ yield* guardWrite2(ROLE_UPDATE, updateForm5(news), false);
5817
5865
  if (before === undefined) {
5818
5866
  yield* runPve(news.target, "provision", true, access5.createAccessRole(createForm7(news)));
5819
- } else if (!matches7(before, news)) {
5820
- yield* runPve(news.target, "provision", true, access5.putAccessRole(updateForm4(news)));
5867
+ } else if (!matches8(before, news)) {
5868
+ yield* runPve(news.target, "provision", true, access5.putAccessRole(updateForm5(news)));
5821
5869
  }
5822
5870
  const after = dropUnreadable5(yield* readRole(news));
5823
5871
  if (after === undefined) {
5824
- return yield* Effect78.die(new Error(`access/roles/${news.roleid}: the write returned no error but the role is ` + 'still absent. PVE wraps every answer in {"data":...} and can report success ' + "on a call that did nothing -- read back rather than trusting the status code."));
5872
+ return yield* Effect79.die(new Error(`access/roles/${news.roleid}: the write returned no error but the role is ` + 'still absent. PVE wraps every answer in {"data":...} and can report success ' + "on a call that did nothing -- read back rather than trusting the status code."));
5825
5873
  }
5826
5874
  return after;
5827
5875
  }),
5828
- delete: Effect78.fn(function* ({ olds }) {
5876
+ delete: Effect79.fn(function* ({ olds }) {
5829
5877
  yield* runPve(olds.target, "provision", true, access5.deleteAccessRole({ roleid: olds.roleid }));
5830
5878
  })
5831
5879
  })));
5832
5880
 
5833
5881
  // src/proxmox/user.ts
5834
5882
  import { Resource as Resource27 } from "alchemy";
5835
- import { isResolved as isResolved25 } from "alchemy/Diff";
5883
+ import { isResolved as isResolved26 } from "alchemy/Diff";
5836
5884
  import * as Provider27 from "alchemy/Provider";
5837
5885
  import * as access7 from "@distilled.cloud/proxmox/access";
5838
- import * as Effect80 from "effect/Effect";
5886
+ import * as Effect81 from "effect/Effect";
5839
5887
 
5840
5888
  // src/proxmox/user-wire.ts
5841
5889
  import * as access6 from "@distilled.cloud/proxmox/access";
5842
- import * as Effect79 from "effect/Effect";
5890
+ import * as Effect80 from "effect/Effect";
5843
5891
  var USER_CREATE = "pve:POST /access/users";
5844
5892
  var USER_UPDATE = "pve:PUT /access/users/{userid}";
5845
5893
  var int2 = (value) => {
@@ -5865,11 +5913,11 @@ var createForm8 = (props) => ({
5865
5913
  ...shape8(props),
5866
5914
  userid: props.userid
5867
5915
  });
5868
- var updateForm5 = (props) => ({
5916
+ var updateForm6 = (props) => ({
5869
5917
  ...shape8(props),
5870
5918
  userid: props.userid
5871
5919
  });
5872
- var attributesOf8 = (live, props) => ({
5920
+ var attributesOf9 = (live, props) => ({
5873
5921
  comment: text(live.comment),
5874
5922
  email: text(live.email),
5875
5923
  enable: bool(live.enable, true),
@@ -5880,59 +5928,59 @@ var attributesOf8 = (live, props) => ({
5880
5928
  tokens: tokenNames(live.tokens),
5881
5929
  userid: props.userid
5882
5930
  });
5883
- var matches8 = (attributes2, props) => attributes2.comment === (props.comment ?? "") && attributes2.email === (props.email ?? "") && attributes2.enable === (props.enable !== false) && attributes2.expire === (props.expire ?? 0) && attributes2.firstname === (props.firstname ?? "") && attributes2.lastname === (props.lastname ?? "") && attributes2.groups.join(",") === groupSet(props.groups).join(",");
5884
- var readUserOrFail = (props) => readOrUnreadable(runPve(props.target, "read", false, access6.getAccessUser({ userid: props.userid }))).pipe(Effect79.map((live) => live === UNREADABLE ? UNREADABLE : attributesOf8(live, props)));
5885
- var readUser = (props) => readUserOrFail(props).pipe(Effect79.catchTag("UserNotFound", () => Effect79.succeed(undefined)));
5931
+ var matches9 = (attributes2, props) => attributes2.comment === (props.comment ?? "") && attributes2.email === (props.email ?? "") && attributes2.enable === (props.enable !== false) && attributes2.expire === (props.expire ?? 0) && attributes2.firstname === (props.firstname ?? "") && attributes2.lastname === (props.lastname ?? "") && attributes2.groups.join(",") === groupSet(props.groups).join(",");
5932
+ var readUserOrFail = (props) => readOrUnreadable(runPve(props.target, "read", false, access6.getAccessUser({ userid: props.userid }))).pipe(Effect80.map((live) => live === UNREADABLE ? UNREADABLE : attributesOf9(live, props)));
5933
+ var readUser = (props) => readUserOrFail(props).pipe(Effect80.catchTag("UserNotFound", () => Effect80.succeed(undefined)));
5886
5934
  var dropUnreadable6 = (live) => live === UNREADABLE ? undefined : live;
5887
5935
 
5888
5936
  // src/proxmox/user.ts
5889
5937
  var ProxmoxUser = Resource27("Proxmox.User");
5890
- var ProxmoxUserProvider = () => Provider27.effect(ProxmoxUser, Effect80.succeed(ProxmoxUser.Provider.of({
5891
- list: () => Effect80.succeed([]),
5892
- read: Effect80.fn(function* ({ olds, output }) {
5938
+ var ProxmoxUserProvider = () => Provider27.effect(ProxmoxUser, Effect81.succeed(ProxmoxUser.Provider.of({
5939
+ list: () => Effect81.succeed([]),
5940
+ read: Effect81.fn(function* ({ olds, output }) {
5893
5941
  return dropUnreadable6(yield* output === undefined ? readUser(olds) : readUserOrFail(olds));
5894
5942
  }),
5895
- diff: Effect80.fn(function* ({ news, output }) {
5896
- if (!isResolved25(news))
5943
+ diff: Effect81.fn(function* ({ news, output }) {
5944
+ if (!isResolved26(news))
5897
5945
  return;
5898
5946
  yield* guardWrite2(USER_CREATE, createForm8(news), output === undefined);
5899
- yield* guardWrite2(USER_UPDATE, updateForm5(news), false);
5947
+ yield* guardWrite2(USER_UPDATE, updateForm6(news), false);
5900
5948
  if (output === undefined)
5901
5949
  return;
5902
5950
  const live = yield* readUserOrFail(news);
5903
5951
  if (live === UNREADABLE) {
5904
- yield* unreadableWarning("Proxmox.User", news.userid);
5952
+ yield* unreadableWarning("Proxmox.User", news.userid, news.target.mount, mintTier(news.target, "read"));
5905
5953
  return { action: "noop" };
5906
5954
  }
5907
5955
  if (live === undefined) {
5908
5956
  yield* guardWrite2(USER_CREATE, createForm8(news), true);
5909
5957
  return { action: "update" };
5910
5958
  }
5911
- return matches8(live, news) ? { action: "noop" } : { action: "update" };
5959
+ return matches9(live, news) ? { action: "noop" } : { action: "update" };
5912
5960
  }),
5913
- reconcile: Effect80.fn(function* ({ news }) {
5961
+ reconcile: Effect81.fn(function* ({ news }) {
5914
5962
  const before = dropUnreadable6(yield* readUser(news));
5915
5963
  yield* guardWrite2(USER_CREATE, createForm8(news), before === undefined);
5916
- yield* guardWrite2(USER_UPDATE, updateForm5(news), false);
5964
+ yield* guardWrite2(USER_UPDATE, updateForm6(news), false);
5917
5965
  if (before === undefined) {
5918
5966
  yield* runPve(news.target, "provision", true, access7.createAccessUser(createForm8(news)));
5919
- } else if (!matches8(before, news)) {
5920
- yield* runPve(news.target, "provision", true, access7.putAccessUser(updateForm5(news)));
5967
+ } else if (!matches9(before, news)) {
5968
+ yield* runPve(news.target, "provision", true, access7.putAccessUser(updateForm6(news)));
5921
5969
  }
5922
5970
  const after = dropUnreadable6(yield* readUser(news));
5923
5971
  if (after === undefined) {
5924
- return yield* Effect80.die(new Error(`access/users/${news.userid}: the write returned no error but the account is ` + 'still absent. PVE wraps every answer in {"data":...} and can report success ' + "on a call that did nothing -- read back rather than trusting the status code."));
5972
+ return yield* Effect81.die(new Error(`access/users/${news.userid}: the write returned no error but the account is ` + 'still absent. PVE wraps every answer in {"data":...} and can report success ' + "on a call that did nothing -- read back rather than trusting the status code."));
5925
5973
  }
5926
5974
  return after;
5927
5975
  }),
5928
- delete: Effect80.fn(function* ({ olds }) {
5976
+ delete: Effect81.fn(function* ({ olds }) {
5929
5977
  yield* runPve(olds.target, "provision", true, access7.deleteAccessUser({ userid: olds.userid }));
5930
5978
  })
5931
5979
  })));
5932
5980
 
5933
5981
  // src/proxmox/provision-declare.ts
5934
- var declareProvisionBaseline = (id, target, names2 = {}, options = {}) => Effect81.gen(function* () {
5935
- const baseline = yield* Effect81.try({
5982
+ var declareProvisionBaseline = (id, target, names2 = {}, options = {}) => Effect82.gen(function* () {
5983
+ const baseline = yield* Effect82.try({
5936
5984
  catch: (cause) => cause instanceof Error ? cause : new Error(String(cause)),
5937
5985
  try: () => provisionBaseline(names2)
5938
5986
  });
@@ -5946,13 +5994,13 @@ var declareProvisionBaseline = (id, target, names2 = {}, options = {}) => Effect
5946
5994
  target
5947
5995
  }));
5948
5996
  const group = yield* owned(ProxmoxGroup(`${id}-mint-group`, { ...baseline.group, target }));
5949
- const users = yield* Effect81.all(baseline.users.map((user) => owned(ProxmoxUser(`${id}-${user.lane}-user`, {
5997
+ const users = yield* Effect82.all(baseline.users.map((user) => owned(ProxmoxUser(`${id}-${user.lane}-user`, {
5950
5998
  comment: user.comment,
5951
5999
  groups: [...user.groups],
5952
6000
  target,
5953
6001
  userid: user.userid
5954
6002
  }))));
5955
- const grants = yield* Effect81.all(baseline.grants.map((grant) => owned(ProxmoxAcl(`${id}-${grant.lane}-grant`, {
6003
+ const grants = yield* Effect82.all(baseline.grants.map((grant) => owned(ProxmoxAcl(`${id}-${grant.lane}-grant`, {
5956
6004
  path: "/",
5957
6005
  propagate: true,
5958
6006
  roleid: grant.roleid,
@@ -5965,12 +6013,12 @@ var declareProvisionBaseline = (id, target, names2 = {}, options = {}) => Effect
5965
6013
  // src/proxmox/qemu.ts
5966
6014
  import { Resource as Resource28 } from "alchemy";
5967
6015
  import * as Provider28 from "alchemy/Provider";
5968
- import * as Effect85 from "effect/Effect";
6016
+ import * as Effect86 from "effect/Effect";
5969
6017
 
5970
6018
  // src/proxmox/qemu-lifecycle.ts
5971
- import { isResolved as isResolved26 } from "alchemy/Diff";
6019
+ import { isResolved as isResolved27 } from "alchemy/Diff";
5972
6020
  import * as nodes17 from "@distilled.cloud/proxmox/nodes";
5973
- import * as Effect84 from "effect/Effect";
6021
+ import * as Effect85 from "effect/Effect";
5974
6022
 
5975
6023
  // src/proxmox/qemu-props.ts
5976
6024
  var NOT_CONFIG2 = new Set(["node", "target", "vmid"]);
@@ -6031,7 +6079,7 @@ var createForm9 = (props) => ({
6031
6079
  ...form(props),
6032
6080
  vmid: String(props.vmid)
6033
6081
  });
6034
- var updateForm6 = form;
6082
+ var updateForm7 = form;
6035
6083
 
6036
6084
  // src/proxmox/qemu-errors.ts
6037
6085
  class QemuRefusedError extends Error {
@@ -6126,7 +6174,7 @@ var netPairs = (value) => new Map(value.split(",").map((part) => part.trim()).fi
6126
6174
  const at = part.indexOf("=");
6127
6175
  return at === -1 ? [part, ""] : [part.slice(0, at), part.slice(at + 1)];
6128
6176
  }));
6129
- var modelKey = (map31) => NIC_MODELS.find((model) => map31.has(model));
6177
+ var modelKey = (map32) => NIC_MODELS.find((model) => map32.has(model));
6130
6178
  var netMaps2 = (declared2, live) => {
6131
6179
  const want = netPairs(declared2);
6132
6180
  const have = netPairs(live);
@@ -6197,44 +6245,44 @@ var judge2 = (props, config7) => {
6197
6245
  var identityRefusal = (vmid, was) => was === undefined || vmid === was ? undefined : `vmid: ${String(was)} -> ${String(vmid)} is a different VM. Declare it as a new resource; ` + "this one is retained when its declaration goes.";
6198
6246
 
6199
6247
  // src/proxmox/qemu-read.ts
6200
- import * as cluster10 from "@distilled.cloud/proxmox/cluster";
6248
+ import * as cluster11 from "@distilled.cloud/proxmox/cluster";
6201
6249
  import * as nodes15 from "@distilled.cloud/proxmox/nodes";
6202
- import * as Effect82 from "effect/Effect";
6250
+ import * as Effect83 from "effect/Effect";
6203
6251
  var guestTypes = ["lxc", "qemu"];
6204
- var readVm = (props) => Effect82.gen(function* () {
6252
+ var readVm = (props) => Effect83.gen(function* () {
6205
6253
  const credential = yield* leased(props.target, "read");
6206
- const answer = yield* runPveWith(props.target, credential, false, nodes15.getNodeQemuConfig({ node: props.node, vmid: String(props.vmid) })).pipe(Effect82.map((data) => ({ data, error: undefined })), Effect82.catchTag("QemuConfigNotFound", (error) => Effect82.succeed({ data: undefined, error })));
6254
+ const answer = yield* runPveWith(props.target, credential, false, nodes15.getNodeQemuConfig({ node: props.node, vmid: String(props.vmid) })).pipe(Effect83.map((data) => ({ data, error: undefined })), Effect83.catchTag("QemuConfigNotFound", (error) => Effect83.succeed({ data: undefined, error })));
6207
6255
  if (answer.error === undefined) {
6208
6256
  const live = answer.data;
6209
6257
  if (typeof live.digest !== "string" || live.digest === "") {
6210
- return yield* Effect82.fail(new QemuRefusedError(`VM ${String(props.vmid)}: config read did not return a digest-bearing config.`));
6258
+ return yield* Effect83.fail(new QemuRefusedError(`VM ${String(props.vmid)}: config read did not return a digest-bearing config.`));
6211
6259
  }
6212
6260
  return live;
6213
6261
  }
6214
- const rows = yield* runPveWith(props.target, credential, false, cluster10.listClusterResources({ type: "vm" }));
6262
+ const rows = yield* runPveWith(props.target, credential, false, cluster11.listClusterResources({ type: "vm" }));
6215
6263
  if (!Array.isArray(rows) || rows.some((row) => !Number.isSafeInteger(Number(row?.vmid)) || Number(row?.vmid) <= 0 || typeof row?.node !== "string" || row.node === "" || !guestTypes.includes(row.type))) {
6216
- return yield* Effect82.fail(new QemuRefusedError("The cluster guest index did not identify its rows."));
6264
+ return yield* Effect83.fail(new QemuRefusedError("The cluster guest index did not identify its rows."));
6217
6265
  }
6218
6266
  const found = rows.find((row) => Number(row.vmid) === props.vmid);
6219
6267
  if (found === undefined)
6220
6268
  return;
6221
6269
  if (found.node === props.node && found.type === "qemu")
6222
- return yield* Effect82.fail(answer.error);
6223
- return yield* Effect82.fail(new QemuRefusedError(`vmid ${String(props.vmid)} is a ${text(found.type, "guest")} on ` + `${text(found.node, "?")}, not a VM on ${props.node}. A migration is not an ` + "update and vmids are cluster-wide: declare the node it is on, or pick a free vmid."));
6270
+ return yield* Effect83.fail(answer.error);
6271
+ return yield* Effect83.fail(new QemuRefusedError(`vmid ${String(props.vmid)} is a ${text(found.type, "guest")} on ` + `${text(found.node, "?")}, not a VM on ${props.node}. A migration is not an ` + "update and vmids are cluster-wide: declare the node it is on, or pick a free vmid."));
6224
6272
  });
6225
6273
 
6226
6274
  // src/proxmox/qemu-task.ts
6227
6275
  import * as nodes16 from "@distilled.cloud/proxmox/nodes";
6228
- import * as Effect83 from "effect/Effect";
6229
- var qemuTask = (props, operation, what, polls) => Effect83.gen(function* () {
6276
+ import * as Effect84 from "effect/Effect";
6277
+ var qemuTask = (props, operation, what, polls) => Effect84.gen(function* () {
6230
6278
  const credential = yield* mint(props.target, "provision");
6231
6279
  const upid = text(yield* runPveWith(props.target, credential, true, operation));
6232
6280
  if (upid === "") {
6233
- return yield* Effect83.fail(new QemuRefusedError(`${what}: PVE returned no task id, so the write cannot be confirmed and is not claimed.`));
6281
+ return yield* Effect84.fail(new QemuRefusedError(`${what}: PVE returned no task id, so the write cannot be confirmed and is not claimed.`));
6234
6282
  }
6235
6283
  let exit = "still running when this provider stopped waiting";
6236
6284
  for (let attempt = 0;attempt < polls; attempt++) {
6237
- const status = yield* runPveWith(props.target, credential, false, nodes16.getNodeTaskStatus({ node: props.node, upid })).pipe(Effect83.orElseSucceed(() => {
6285
+ const status = yield* runPveWith(props.target, credential, false, nodes16.getNodeTaskStatus({ node: props.node, upid })).pipe(Effect84.orElseSucceed(() => {
6238
6286
  return;
6239
6287
  }));
6240
6288
  if (status === undefined || status.status === undefined) {
@@ -6245,66 +6293,66 @@ var qemuTask = (props, operation, what, polls) => Effect83.gen(function* () {
6245
6293
  exit = text(status.exitstatus, "stopped with no exitstatus");
6246
6294
  break;
6247
6295
  }
6248
- yield* Effect83.sleep("1 second");
6296
+ yield* Effect84.sleep("1 second");
6249
6297
  }
6250
6298
  if (exit !== "OK") {
6251
- return yield* Effect83.fail(new QemuRefusedError(`${what}: task ${upid} ended "${exit}". Read the task log before running the deploy again.`));
6299
+ return yield* Effect84.fail(new QemuRefusedError(`${what}: task ${upid} ended "${exit}". Read the task log before running the deploy again.`));
6252
6300
  }
6253
6301
  });
6254
6302
 
6255
6303
  // src/proxmox/qemu-lifecycle.ts
6256
6304
  var CREATE_POLLS2 = 180;
6257
6305
  var DELETE_POLLS = 60;
6258
- var attributesOf9 = (live, props) => ({
6306
+ var attributesOf10 = (live, props) => ({
6259
6307
  config: storedConfig2(live),
6260
6308
  node: props.node,
6261
6309
  vmid: props.vmid
6262
6310
  });
6263
- var matches9 = (attributes2, props) => declaredKeys2(props).filter(isManagedKey2).every((key) => attributes2.config[key] === wireValue2(declaredValue2(props, key)));
6311
+ var matches10 = (attributes2, props) => declaredKeys2(props).filter(isManagedKey2).every((key) => attributes2.config[key] === wireValue2(declaredValue2(props, key)));
6264
6312
  var spec5 = {
6265
- attributes: attributesOf9,
6313
+ attributes: attributesOf10,
6266
6314
  collection: (props) => `nodes/${props.node}/qemu`,
6267
6315
  createForm: createForm9,
6268
6316
  endpoint: {
6269
6317
  create: "pve:POST /nodes/{node}/qemu",
6270
6318
  update: "pve:PUT /nodes/{node}/qemu/{vmid}/config"
6271
6319
  },
6272
- matches: matches9,
6320
+ matches: matches10,
6273
6321
  path: (props) => `nodes/${props.node}/qemu/${String(props.vmid)}/config`,
6274
- updateForm: updateForm6
6322
+ updateForm: updateForm7
6275
6323
  };
6276
6324
  var { guardCreate: guardCreate10, guardUpdate: guardUpdate10 } = specGuards(spec5);
6277
- var readQemu = (props) => readVm(props).pipe(Effect84.map((live) => live === undefined ? undefined : attributesOf9(live, props)));
6278
- var deleteQemu = (props) => qemuTask(props, nodes17.deleteNodeQemu({ node: props.node, vmid: String(props.vmid) }), `destroy VM ${String(props.vmid)}`, DELETE_POLLS).pipe(Effect84.catchTag("QemuConfigNotFound", () => Effect84.void));
6325
+ var readQemu = (props) => readVm(props).pipe(Effect85.map((live) => live === undefined ? undefined : attributesOf10(live, props)));
6326
+ var deleteQemu = (props) => qemuTask(props, nodes17.deleteNodeQemu({ node: props.node, vmid: String(props.vmid) }), `destroy VM ${String(props.vmid)}`, DELETE_POLLS).pipe(Effect85.catchTag("QemuConfigNotFound", () => Effect85.void));
6279
6327
  var refuseUnmanaged = (props) => {
6280
6328
  const refused2 = formRefusals(props);
6281
- return refused2.length === 0 ? Effect84.void : Effect84.fail(new QemuRefusedError(refused2.join(`
6329
+ return refused2.length === 0 ? Effect85.void : Effect85.fail(new QemuRefusedError(refused2.join(`
6282
6330
  `)));
6283
6331
  };
6284
- var refuseChange = (change) => change.refuse.length === 0 ? Effect84.void : Effect84.fail(new QemuRefusedError(change.refuse.join(`
6332
+ var refuseChange = (change) => change.refuse.length === 0 ? Effect85.void : Effect85.fail(new QemuRefusedError(change.refuse.join(`
6285
6333
  `)));
6286
6334
  var qemuHandlers = {
6287
- list: () => Effect84.succeed([]),
6288
- read: Effect84.fn(function* ({
6335
+ list: () => Effect85.succeed([]),
6336
+ read: Effect85.fn(function* ({
6289
6337
  fqn,
6290
6338
  instanceId,
6291
6339
  olds,
6292
6340
  output
6293
6341
  }) {
6294
6342
  const found = yield* readQemu(olds);
6295
- const settled2 = Effect84.sync(() => found !== undefined && judge2(olds, found.config).drift.length === 0);
6343
+ const settled2 = Effect85.sync(() => found !== undefined && judge2(olds, found.config).drift.length === 0);
6296
6344
  return yield* ownedRead({ fqn, instanceId, output }, found, settled2);
6297
6345
  }),
6298
- diff: Effect84.fn(function* ({
6346
+ diff: Effect85.fn(function* ({
6299
6347
  news,
6300
6348
  olds,
6301
6349
  output
6302
6350
  }) {
6303
- if (!isResolved26(news))
6351
+ if (!isResolved27(news))
6304
6352
  return;
6305
6353
  const identity2 = identityRefusal(news.vmid, output?.vmid ?? olds.vmid);
6306
6354
  if (identity2 !== undefined)
6307
- return yield* Effect84.fail(new QemuRefusedError(identity2));
6355
+ return yield* Effect85.fail(new QemuRefusedError(identity2));
6308
6356
  yield* refuseUnmanaged(news);
6309
6357
  yield* guardCreate10(news, output === undefined);
6310
6358
  yield* guardUpdate10(news);
@@ -6312,7 +6360,7 @@ var qemuHandlers = {
6312
6360
  return;
6313
6361
  const live = yield* readQemu(news);
6314
6362
  if (live === undefined) {
6315
- yield* Effect84.logWarning(`Proxmox.Vm ${news.node}/${String(news.vmid)}: the cluster lists no VM with this vmid -- ` + "a deploy CREATES it again, with new, empty volumes.");
6363
+ yield* Effect85.logWarning(`Proxmox.Vm ${news.node}/${String(news.vmid)}: the cluster lists no VM with this vmid -- ` + "a deploy CREATES it again, with new, empty volumes.");
6316
6364
  yield* guardCreate10(news, true);
6317
6365
  return { action: "update" };
6318
6366
  }
@@ -6320,7 +6368,7 @@ var qemuHandlers = {
6320
6368
  yield* refuseChange(change);
6321
6369
  return { action: change.drift.length === 0 ? "noop" : "update" };
6322
6370
  }),
6323
- reconcile: Effect84.fn(function* ({
6371
+ reconcile: Effect85.fn(function* ({
6324
6372
  fqn,
6325
6373
  instanceId,
6326
6374
  news,
@@ -6329,7 +6377,7 @@ var qemuHandlers = {
6329
6377
  }) {
6330
6378
  const identity2 = identityRefusal(news.vmid, output?.vmid ?? olds?.vmid);
6331
6379
  if (identity2 !== undefined)
6332
- return yield* Effect84.fail(new QemuRefusedError(identity2));
6380
+ return yield* Effect85.fail(new QemuRefusedError(identity2));
6333
6381
  yield* refuseUnmanaged(news);
6334
6382
  const live = yield* readQemu(news);
6335
6383
  yield* guardCreate10(news, live === undefined);
@@ -6346,11 +6394,11 @@ var qemuHandlers = {
6346
6394
  }
6347
6395
  const after = yield* readQemu(news);
6348
6396
  if (after === undefined) {
6349
- return yield* Effect84.fail(new QemuRefusedError(`${spec5.path(news)}: write returned success but the VM is still absent`));
6397
+ return yield* Effect85.fail(new QemuRefusedError(`${spec5.path(news)}: write returned success but the VM is still absent`));
6350
6398
  }
6351
6399
  const left = judge2(news, after.config);
6352
6400
  if (left.drift.length > 0) {
6353
- return yield* Effect84.fail(new QemuRefusedError(`${spec5.path(news)}: after the write, ${left.drift.join(", ")} still differ from the ` + "declaration. PVE may have normalised the value -- declare what it stores."));
6401
+ return yield* Effect85.fail(new QemuRefusedError(`${spec5.path(news)}: after the write, ${left.drift.join(", ")} still differ from the ` + "declaration. PVE may have normalised the value -- declare what it stores."));
6354
6402
  }
6355
6403
  return after;
6356
6404
  }),
@@ -6359,16 +6407,16 @@ var qemuHandlers = {
6359
6407
 
6360
6408
  // src/proxmox/qemu.ts
6361
6409
  var ProxmoxVm = Resource28("Proxmox.Vm", { defaultRemovalPolicy: "retain" });
6362
- var ProxmoxVmProvider = () => Provider28.effect(ProxmoxVm, Effect85.succeed(ProxmoxVm.Provider.of(qemuHandlers)));
6410
+ var ProxmoxVmProvider = () => Provider28.effect(ProxmoxVm, Effect86.succeed(ProxmoxVm.Provider.of(qemuHandlers)));
6363
6411
  // src/proxmox/storage-download.ts
6364
6412
  import { Resource as Resource29 } from "alchemy";
6365
6413
  import * as Provider29 from "alchemy/Provider";
6366
- import * as Effect88 from "effect/Effect";
6414
+ import * as Effect89 from "effect/Effect";
6367
6415
 
6368
6416
  // src/proxmox/storage-download-lifecycle.ts
6369
- import { isResolved as isResolved27 } from "alchemy/Diff";
6417
+ import { isResolved as isResolved28 } from "alchemy/Diff";
6370
6418
  import * as nodes19 from "@distilled.cloud/proxmox/nodes";
6371
- import * as Effect87 from "effect/Effect";
6419
+ import * as Effect88 from "effect/Effect";
6372
6420
 
6373
6421
  // src/proxmox/storage-download-identity.ts
6374
6422
  var PINNED = [
@@ -6403,16 +6451,16 @@ class StorageDownloadRefusedError extends Error {
6403
6451
 
6404
6452
  // src/proxmox/storage-download-task.ts
6405
6453
  import * as nodes18 from "@distilled.cloud/proxmox/nodes";
6406
- import * as Effect86 from "effect/Effect";
6407
- var storageDownloadTask = (where, operation, what, polls) => Effect86.gen(function* () {
6454
+ import * as Effect87 from "effect/Effect";
6455
+ var storageDownloadTask = (where, operation, what, polls) => Effect87.gen(function* () {
6408
6456
  const credential = yield* mint(where.target, "provision");
6409
6457
  const upid = text(yield* runPveWith(where.target, credential, true, operation));
6410
6458
  if (upid === "") {
6411
- return yield* Effect86.fail(new StorageDownloadRefusedError(`${what}: PVE returned no task id, so the write cannot be confirmed and is not claimed.`));
6459
+ return yield* Effect87.fail(new StorageDownloadRefusedError(`${what}: PVE returned no task id, so the write cannot be confirmed and is not claimed.`));
6412
6460
  }
6413
6461
  let exit = "still running when this provider stopped waiting";
6414
6462
  for (let attempt = 0;attempt < polls; attempt++) {
6415
- const status = yield* runPveWith(where.target, credential, false, nodes18.getNodeTaskStatus({ node: where.node, upid })).pipe(Effect86.orElseSucceed(() => {
6463
+ const status = yield* runPveWith(where.target, credential, false, nodes18.getNodeTaskStatus({ node: where.node, upid })).pipe(Effect87.orElseSucceed(() => {
6416
6464
  return;
6417
6465
  }));
6418
6466
  if (status === undefined || status.status === undefined) {
@@ -6423,10 +6471,10 @@ var storageDownloadTask = (where, operation, what, polls) => Effect86.gen(functi
6423
6471
  exit = text(status.exitstatus, "stopped with no exitstatus");
6424
6472
  break;
6425
6473
  }
6426
- yield* Effect86.sleep("1 second");
6474
+ yield* Effect87.sleep("1 second");
6427
6475
  }
6428
6476
  if (exit !== "OK") {
6429
- return yield* Effect86.fail(new StorageDownloadRefusedError(`${what}: task ${upid} ended "${exit}". Read the task log before running the deploy again.`));
6477
+ return yield* Effect87.fail(new StorageDownloadRefusedError(`${what}: task ${upid} ended "${exit}". Read the task log before running the deploy again.`));
6430
6478
  }
6431
6479
  });
6432
6480
 
@@ -6452,14 +6500,14 @@ var createRefusals2 = (props) => {
6452
6500
  }
6453
6501
  return refuse3.concat(formViolations(DOWNLOAD_ENDPOINT, downloadForm(props), true).map((why) => `${props.filename}: ${why}`));
6454
6502
  };
6455
- var readDownload = (props) => Effect87.gen(function* () {
6503
+ var readDownload = (props) => Effect88.gen(function* () {
6456
6504
  const rows = yield* runPve(props.target, "read", false, nodes19.listNodeStorageContent({
6457
6505
  content: "import",
6458
6506
  node: props.node,
6459
6507
  storage: props.storage
6460
6508
  }));
6461
6509
  if (!Array.isArray(rows)) {
6462
- return yield* Effect87.fail(new StorageDownloadRefusedError(`${props.storage}: the content list did not come back as a list.`));
6510
+ return yield* Effect88.fail(new StorageDownloadRefusedError(`${props.storage}: the content list did not come back as a list.`));
6463
6511
  }
6464
6512
  const found = rows.find((row) => row.volid.endsWith(`/${props.filename}`));
6465
6513
  if (found === undefined)
@@ -6473,7 +6521,7 @@ var readDownload = (props) => Effect87.gen(function* () {
6473
6521
  volid: text(found.volid, "")
6474
6522
  };
6475
6523
  });
6476
- var destroyDownload = (props) => Effect87.gen(function* () {
6524
+ var destroyDownload = (props) => Effect88.gen(function* () {
6477
6525
  const live = yield* readDownload(props);
6478
6526
  if (live === undefined)
6479
6527
  return;
@@ -6484,26 +6532,26 @@ var destroyDownload = (props) => Effect87.gen(function* () {
6484
6532
  }), `delete ${live.volid}`, DELETE_POLLS2);
6485
6533
  });
6486
6534
  var storageDownloadHandlers = {
6487
- list: () => Effect87.succeed([]),
6488
- read: Effect87.fn(function* ({
6535
+ list: () => Effect88.succeed([]),
6536
+ read: Effect88.fn(function* ({
6489
6537
  fqn,
6490
6538
  instanceId,
6491
6539
  olds,
6492
6540
  output
6493
6541
  }) {
6494
6542
  const found = yield* readDownload(olds);
6495
- return yield* ownedRead({ fqn, instanceId, output }, found, Effect87.succeed(true));
6543
+ return yield* ownedRead({ fqn, instanceId, output }, found, Effect88.succeed(true));
6496
6544
  }),
6497
- diff: Effect87.fn(function* ({
6545
+ diff: Effect88.fn(function* ({
6498
6546
  news,
6499
6547
  olds,
6500
6548
  output
6501
6549
  }) {
6502
- if (!isResolved27(news))
6550
+ if (!isResolved28(news))
6503
6551
  return;
6504
6552
  const refused2 = createRefusals2(news);
6505
6553
  if (refused2.length > 0) {
6506
- return yield* Effect87.fail(new StorageDownloadRefusedError(refused2.join(`
6554
+ return yield* Effect88.fail(new StorageDownloadRefusedError(refused2.join(`
6507
6555
  `)));
6508
6556
  }
6509
6557
  if (output === undefined)
@@ -6513,11 +6561,11 @@ var storageDownloadHandlers = {
6513
6561
  return { action: "replace" };
6514
6562
  const live = yield* readDownload(news);
6515
6563
  if (identity2.kind === "pin-changed" && live !== undefined) {
6516
- return yield* Effect87.fail(new StorageDownloadRefusedError(identity2.refuse));
6564
+ return yield* Effect88.fail(new StorageDownloadRefusedError(identity2.refuse));
6517
6565
  }
6518
6566
  return { action: live === undefined ? "update" : "noop" };
6519
6567
  }),
6520
- reconcile: Effect87.fn(function* ({
6568
+ reconcile: Effect88.fn(function* ({
6521
6569
  fqn,
6522
6570
  instanceId,
6523
6571
  news,
@@ -6525,7 +6573,7 @@ var storageDownloadHandlers = {
6525
6573
  }) {
6526
6574
  const refused2 = createRefusals2(news);
6527
6575
  if (refused2.length > 0) {
6528
- return yield* Effect87.fail(new StorageDownloadRefusedError(refused2.join(`
6576
+ return yield* Effect88.fail(new StorageDownloadRefusedError(refused2.join(`
6529
6577
  `)));
6530
6578
  }
6531
6579
  const live = yield* readDownload(news);
@@ -6536,7 +6584,7 @@ var storageDownloadHandlers = {
6536
6584
  }
6537
6585
  const after = yield* readDownload(news);
6538
6586
  if (after === undefined) {
6539
- return yield* Effect87.fail(new StorageDownloadRefusedError(`${news.filename}: the write returned no error but ${news.storage} still has no ` + "matching content — PVE may have normalised the filename; read it back by hand."));
6587
+ return yield* Effect88.fail(new StorageDownloadRefusedError(`${news.filename}: the write returned no error but ${news.storage} still has no ` + "matching content — PVE may have normalised the filename; read it back by hand."));
6540
6588
  }
6541
6589
  return after;
6542
6590
  }),
@@ -6545,17 +6593,17 @@ var storageDownloadHandlers = {
6545
6593
 
6546
6594
  // src/proxmox/storage-download.ts
6547
6595
  var ProxmoxStorageDownload = Resource29("Proxmox.StorageDownload");
6548
- var ProxmoxStorageDownloadProvider = () => Provider29.effect(ProxmoxStorageDownload, Effect88.succeed(ProxmoxStorageDownload.Provider.of(storageDownloadHandlers)));
6596
+ var ProxmoxStorageDownloadProvider = () => Provider29.effect(ProxmoxStorageDownload, Effect89.succeed(ProxmoxStorageDownload.Provider.of(storageDownloadHandlers)));
6549
6597
  // src/proxmox/replication-job.ts
6550
6598
  import { Resource as Resource30 } from "alchemy";
6551
6599
  import * as Provider30 from "alchemy/Provider";
6552
- import * as Effect90 from "effect/Effect";
6600
+ import * as Effect91 from "effect/Effect";
6553
6601
 
6554
6602
  // src/proxmox/replication-job-lifecycle.ts
6555
- import { isResolved as isResolved28 } from "alchemy/Diff";
6556
- import * as cluster11 from "@distilled.cloud/proxmox/cluster";
6603
+ import { isResolved as isResolved29 } from "alchemy/Diff";
6604
+ import * as cluster12 from "@distilled.cloud/proxmox/cluster";
6557
6605
  import { ProxmoxParseError as ProxmoxParseError6 } from "@distilled.cloud/proxmox/Errors";
6558
- import * as Effect89 from "effect/Effect";
6606
+ import * as Effect90 from "effect/Effect";
6559
6607
  import * as Schema6 from "effect/Schema";
6560
6608
 
6561
6609
  // src/proxmox/replication-job-form.ts
@@ -6616,21 +6664,21 @@ var malformed = () => new ProxmoxParseError6({
6616
6664
  body: undefined,
6617
6665
  cause: "Replication job response does not match the requested vendor identity"
6618
6666
  });
6619
- var readReplicationJob = (props) => runPve(props.target, "read", false, cluster11.getClusterReplication({ id: jobId(props) })).pipe(Effect89.flatMap((live) => Schema6.decodeUnknownEffect(Schema6.toType(cluster11.GetClusterReplicationResponse))({
6667
+ var readReplicationJob = (props) => runPve(props.target, "read", false, cluster12.getClusterReplication({ id: jobId(props) })).pipe(Effect90.flatMap((live) => Schema6.decodeUnknownEffect(Schema6.toType(cluster12.GetClusterReplicationResponse))({
6620
6668
  ...live,
6621
6669
  guest: int(live.guest, Number.NaN),
6622
6670
  jobnum: int(live.jobnum, Number.NaN),
6623
6671
  rate: undefined
6624
- }).pipe(Effect89.mapError(malformed), Effect89.as(live))), Effect89.flatMap((live) => live.id === jobId(props) && int(live.guest, Number.NaN) === props.guest && int(live.jobnum, Number.NaN) === props.jobnum ? Effect89.succeed(replicationJobSpec.attributes({ ...live }, props)) : Effect89.fail(malformed())), Effect89.catchTag("ReplicationJobNotFound", () => Effect89.succeed(undefined)));
6625
- var deleteReplicationJob = (props) => runPve(props.target, "provision", true, cluster11.deleteClusterReplication({ id: jobId(props) })).pipe(Effect89.catchTag("ReplicationJobNotFound", () => Effect89.void));
6672
+ }).pipe(Effect90.mapError(malformed), Effect90.as(live))), Effect90.flatMap((live) => live.id === jobId(props) && int(live.guest, Number.NaN) === props.guest && int(live.jobnum, Number.NaN) === props.jobnum ? Effect90.succeed(replicationJobSpec.attributes({ ...live }, props)) : Effect90.fail(malformed())), Effect90.catchTag("ReplicationJobNotFound", () => Effect90.succeed(undefined)));
6673
+ var deleteReplicationJob = (props) => runPve(props.target, "provision", true, cluster12.deleteClusterReplication({ id: jobId(props) })).pipe(Effect90.catchTag("ReplicationJobNotFound", () => Effect90.void));
6626
6674
  var replicationJobHandlers = {
6627
- list: () => Effect89.succeed([]),
6675
+ list: () => Effect90.succeed([]),
6628
6676
  read: ({ olds }) => readReplicationJob(olds),
6629
- diff: Effect89.fn(function* ({
6677
+ diff: Effect90.fn(function* ({
6630
6678
  news,
6631
6679
  output
6632
6680
  }) {
6633
- if (!isResolved28(news))
6681
+ if (!isResolved29(news))
6634
6682
  return;
6635
6683
  yield* guardCreate11(news, output === undefined);
6636
6684
  yield* guardUpdate11(news);
@@ -6643,20 +6691,20 @@ var replicationJobHandlers = {
6643
6691
  }
6644
6692
  return { action: replicationJobSpec.matches(live, news) ? "noop" : "update" };
6645
6693
  }),
6646
- reconcile: Effect89.fn(function* ({ news }) {
6694
+ reconcile: Effect90.fn(function* ({ news }) {
6647
6695
  const live = yield* readReplicationJob(news);
6648
6696
  yield* guardCreate11(news, live === undefined);
6649
6697
  yield* guardUpdate11(news);
6650
6698
  if (live === undefined) {
6651
- yield* runPve(news.target, "provision", true, cluster11.createClusterReplication(replicationJobSpec.createForm(news)));
6699
+ yield* runPve(news.target, "provision", true, cluster12.createClusterReplication(replicationJobSpec.createForm(news)));
6652
6700
  } else {
6653
6701
  const form2 = formToSend(replicationJobSpec.matches, live, news, replicationJobSpec.updateForm(news));
6654
6702
  if (form2 !== undefined)
6655
- yield* runPve(news.target, "provision", true, cluster11.putClusterReplication({ ...form2, id: jobId(news) }));
6703
+ yield* runPve(news.target, "provision", true, cluster12.putClusterReplication({ ...form2, id: jobId(news) }));
6656
6704
  }
6657
6705
  const after = yield* readReplicationJob(news);
6658
6706
  if (after === undefined)
6659
- return yield* Effect89.fail(new Error(`${replicationJobSpec.path(news)}: write returned success but the resource is still absent`));
6707
+ return yield* Effect90.fail(new Error(`${replicationJobSpec.path(news)}: write returned success but the resource is still absent`));
6660
6708
  return after;
6661
6709
  }),
6662
6710
  delete: ({ olds }) => deleteReplicationJob(olds)
@@ -6664,15 +6712,15 @@ var replicationJobHandlers = {
6664
6712
 
6665
6713
  // src/proxmox/replication-job.ts
6666
6714
  var ProxmoxReplicationJob = Resource30("Proxmox.ReplicationJob");
6667
- var ProxmoxReplicationJobProvider = () => Provider30.effect(ProxmoxReplicationJob, Effect90.succeed(ProxmoxReplicationJob.Provider.of(replicationJobHandlers)));
6715
+ var ProxmoxReplicationJobProvider = () => Provider30.effect(ProxmoxReplicationJob, Effect91.succeed(ProxmoxReplicationJob.Provider.of(replicationJobHandlers)));
6668
6716
  // src/proxmox/sdn-apply.ts
6669
6717
  import { Resource as Resource31 } from "alchemy";
6670
- import { isResolved as isResolved29 } from "alchemy/Diff";
6718
+ import { isResolved as isResolved30 } from "alchemy/Diff";
6671
6719
  import * as Provider31 from "alchemy/Provider";
6672
- import * as Effect92 from "effect/Effect";
6720
+ import * as Effect93 from "effect/Effect";
6673
6721
 
6674
6722
  // src/proxmox/sdn-apply-read.ts
6675
- import * as Effect91 from "effect/Effect";
6723
+ import * as Effect92 from "effect/Effect";
6676
6724
  var MARKED = [
6677
6725
  "cluster/sdn/zones",
6678
6726
  "cluster/sdn/vnets",
@@ -6681,7 +6729,7 @@ var MARKED = [
6681
6729
  "cluster/sdn/route-maps"
6682
6730
  ];
6683
6731
  var subsystemAbsent = (error) => error instanceof PveError && error.status === 501;
6684
- var markedPending = (target) => Effect91.all(MARKED.map((collection) => pve(target, "read", "GET", `${collection}?pending=1`).pipe(Effect91.map((rows) => (rows ?? []).filter((row) => row.state !== undefined).length), Effect91.catchIf(subsystemAbsent, () => Effect91.succeed(0)))), { concurrency: "unbounded" }).pipe(Effect91.map((counts) => counts.reduce((total, count2) => total + count2, 0)));
6732
+ var markedPending = (target) => Effect92.all(MARKED.map((collection) => pve(target, "read", "GET", `${collection}?pending=1`).pipe(Effect92.map((rows) => (rows ?? []).filter((row) => row.state !== undefined).length), Effect92.catchIf(subsystemAbsent, () => Effect92.succeed(0)))), { concurrency: "unbounded" }).pipe(Effect92.map((counts) => counts.reduce((total, count2) => total + count2, 0)));
6685
6733
  var fabricStaged = (staged, running) => {
6686
6734
  if (staged === undefined && running === undefined)
6687
6735
  return 0;
@@ -6689,9 +6737,9 @@ var fabricStaged = (staged, running) => {
6689
6737
  return "inconsistent";
6690
6738
  return staged === running ? 0 : 1;
6691
6739
  };
6692
- var fabricPending = (target) => Effect91.all(["pending", "running"].map((view) => pve(target, "read", "GET", `cluster/sdn/fabrics/all?${view}=1`).pipe(Effect91.map(canonical3), Effect91.catchIf(subsystemAbsent, () => Effect91.succeed(undefined)))), { concurrency: "unbounded" }).pipe(Effect91.flatMap(([staged, running]) => {
6740
+ var fabricPending = (target) => Effect92.all(["pending", "running"].map((view) => pve(target, "read", "GET", `cluster/sdn/fabrics/all?${view}=1`).pipe(Effect92.map(canonical3), Effect92.catchIf(subsystemAbsent, () => Effect92.succeed(undefined)))), { concurrency: "unbounded" }).pipe(Effect92.flatMap(([staged, running]) => {
6693
6741
  const verdict = fabricStaged(staged, running);
6694
- return verdict === "inconsistent" ? Effect91.die(new Error("cluster/sdn/fabrics/all answered 501 for one of ?pending=1 and ?running=1 and not " + "the other. Refusing to read that as a staged fabric change.")) : Effect91.succeed(verdict);
6742
+ return verdict === "inconsistent" ? Effect92.die(new Error("cluster/sdn/fabrics/all answered 501 for one of ?pending=1 and ?running=1 and not " + "the other. Refusing to read that as a staged fabric change.")) : Effect92.succeed(verdict);
6695
6743
  }));
6696
6744
  var canonical3 = (value) => JSON.stringify(sortDeep(value));
6697
6745
  var sortDeep = (value) => {
@@ -6704,23 +6752,23 @@ var sortDeep = (value) => {
6704
6752
  }
6705
6753
  return value;
6706
6754
  };
6707
- var sdnPendingCount = (target) => Effect91.all([markedPending(target), fabricPending(target)], { concurrency: "unbounded" }).pipe(Effect91.map(([marked, fabric]) => marked + fabric));
6755
+ var sdnPendingCount = (target) => Effect92.all([markedPending(target), fabricPending(target)], { concurrency: "unbounded" }).pipe(Effect92.map(([marked, fabric]) => marked + fabric));
6708
6756
 
6709
6757
  // src/proxmox/sdn-apply.ts
6710
6758
  var ProxmoxSdnApply = Resource31("Proxmox.SdnApply");
6711
- var read5 = (props) => sdnPendingCount(props.target).pipe(Effect92.map((pending) => ({ pending })));
6712
- var ProxmoxSdnApplyProvider = () => Provider31.effect(ProxmoxSdnApply, Effect92.succeed(ProxmoxSdnApply.Provider.of({
6713
- list: () => Effect92.succeed([]),
6714
- read: Effect92.fn(function* ({ olds }) {
6759
+ var read5 = (props) => sdnPendingCount(props.target).pipe(Effect93.map((pending) => ({ pending })));
6760
+ var ProxmoxSdnApplyProvider = () => Provider31.effect(ProxmoxSdnApply, Effect93.succeed(ProxmoxSdnApply.Provider.of({
6761
+ list: () => Effect93.succeed([]),
6762
+ read: Effect93.fn(function* ({ olds }) {
6715
6763
  return yield* read5(olds);
6716
6764
  }),
6717
- diff: Effect92.fn(function* ({ news }) {
6718
- if (!isResolved29(news))
6765
+ diff: Effect93.fn(function* ({ news }) {
6766
+ if (!isResolved30(news))
6719
6767
  return;
6720
6768
  const { pending } = yield* read5(news);
6721
6769
  return pending === 0 ? { action: "noop" } : { action: "update" };
6722
6770
  }),
6723
- reconcile: Effect92.fn(function* ({ news }) {
6771
+ reconcile: Effect93.fn(function* ({ news }) {
6724
6772
  const staged = yield* read5(news);
6725
6773
  if (staged.pending === 0)
6726
6774
  return staged;
@@ -6728,16 +6776,16 @@ var ProxmoxSdnApplyProvider = () => Provider31.effect(ProxmoxSdnApply, Effect92.
6728
6776
  yield* pve(news.target, "provision", "PUT", "cluster/sdn");
6729
6777
  const after = yield* read5(news);
6730
6778
  if (after.pending !== 0) {
6731
- return yield* Effect92.die(new Error(`PUT /cluster/sdn returned no error but ${String(after.pending)} SDN object(s) ` + "are still staged. The running config does not match the declared one -- check " + "`pvesh get /cluster/sdn/zones --pending 1` for the objects PVE refused."));
6779
+ return yield* Effect93.die(new Error(`PUT /cluster/sdn returned no error but ${String(after.pending)} SDN object(s) ` + "are still staged. The running config does not match the declared one -- check " + "`pvesh get /cluster/sdn/zones --pending 1` for the objects PVE refused."));
6732
6780
  }
6733
6781
  return after;
6734
6782
  }),
6735
- delete: () => Effect92.void
6783
+ delete: () => Effect93.void
6736
6784
  })));
6737
6785
  // src/proxmox/sdn-subnet.ts
6738
6786
  import { Resource as Resource32 } from "alchemy";
6739
6787
  import * as Provider32 from "alchemy/Provider";
6740
- import * as Effect93 from "effect/Effect";
6788
+ import * as Effect94 from "effect/Effect";
6741
6789
 
6742
6790
  // src/proxmox/sdn-subnet-form.ts
6743
6791
  var subnetId = (props) => `${props.zone}-${props.cidr.replace("/", "-")}`;
@@ -6761,14 +6809,14 @@ var createForm10 = (props) => ({
6761
6809
  subnet: props.cidr,
6762
6810
  type: "subnet"
6763
6811
  });
6764
- var updateForm7 = (props) => {
6812
+ var updateForm8 = (props) => {
6765
6813
  const clear = Object.entries(optional3(props)).filter(([, value]) => value === undefined).map(([key]) => key);
6766
6814
  return withClears(body5(props), clear);
6767
6815
  };
6768
6816
 
6769
6817
  // src/proxmox/sdn-subnet.ts
6770
6818
  var ProxmoxSdnSubnet = Resource32("Proxmox.SdnSubnet");
6771
- var handlers13 = pveHandlers({
6819
+ var handlers12 = pveHandlers({
6772
6820
  attributes: (live, props) => {
6773
6821
  const liveVnet = text(live["vnet"]);
6774
6822
  if (liveVnet !== "" && liveVnet !== props.vnet)
@@ -6795,13 +6843,13 @@ var handlers13 = pveHandlers({
6795
6843
  },
6796
6844
  matches: (attributes2, props) => attributes2.gateway === (props.gateway ?? "") && attributes2.snat === (props.snat === true) && attributes2.dnszoneprefix === (props.dnszoneprefix ?? "") && attributes2.dhcpDnsServer === (props.dhcpDnsServer ?? "") && attributes2.dhcpRange === declaredRanges(props.dhcpRange),
6797
6845
  path: (props) => `cluster/sdn/vnets/${props.vnet}/subnets/${subnetId(props)}`,
6798
- updateForm: updateForm7
6846
+ updateForm: updateForm8
6799
6847
  });
6800
- var ProxmoxSdnSubnetProvider = () => Provider32.effect(ProxmoxSdnSubnet, Effect93.succeed(ProxmoxSdnSubnet.Provider.of(handlers13)));
6848
+ var ProxmoxSdnSubnetProvider = () => Provider32.effect(ProxmoxSdnSubnet, Effect94.succeed(ProxmoxSdnSubnet.Provider.of(handlers12)));
6801
6849
  // src/proxmox/sdn-vnet.ts
6802
6850
  import { Resource as Resource33 } from "alchemy";
6803
6851
  import * as Provider33 from "alchemy/Provider";
6804
- import * as Effect94 from "effect/Effect";
6852
+ import * as Effect95 from "effect/Effect";
6805
6853
  var ProxmoxSdnVnet = Resource33("Proxmox.SdnVnet");
6806
6854
  var tagOf = (value) => typeof value === "number" ? value : undefined;
6807
6855
  var shape10 = (props) => {
@@ -6814,14 +6862,14 @@ var shape10 = (props) => {
6814
6862
  ...props.tag === undefined ? {} : { tag: String(props.tag) }
6815
6863
  };
6816
6864
  };
6817
- var updateForm8 = (props) => {
6865
+ var updateForm9 = (props) => {
6818
6866
  const unset2 = [
6819
6867
  ...(props.alias ?? "") === "" ? ["alias"] : [],
6820
6868
  ...props.tag === undefined ? ["tag"] : []
6821
6869
  ];
6822
6870
  return withClears(shape10(props), unset2);
6823
6871
  };
6824
- var handlers14 = pveHandlers({
6872
+ var handlers13 = pveHandlers({
6825
6873
  readRole: "provision",
6826
6874
  attributes: (live, props) => ({
6827
6875
  alias: typeof live["alias"] === "string" ? live["alias"] : "",
@@ -6837,13 +6885,13 @@ var handlers14 = pveHandlers({
6837
6885
  endpoint: { create: "pve:POST /cluster/sdn/vnets", update: "pve:PUT /cluster/sdn/vnets/{vnet}" },
6838
6886
  matches: (attributes2, props) => attributes2.zone === props.zone && attributes2.alias === (props.alias ?? "") && attributes2.tag === props.tag && attributes2.vlanaware === (props.vlanaware === true) && attributes2.isolatePorts === (props.isolatePorts === true),
6839
6887
  path: (props) => `cluster/sdn/vnets/${props.vnet}`,
6840
- updateForm: updateForm8
6888
+ updateForm: updateForm9
6841
6889
  });
6842
- var ProxmoxSdnVnetProvider = () => Provider33.effect(ProxmoxSdnVnet, Effect94.succeed(ProxmoxSdnVnet.Provider.of(handlers14)));
6890
+ var ProxmoxSdnVnetProvider = () => Provider33.effect(ProxmoxSdnVnet, Effect95.succeed(ProxmoxSdnVnet.Provider.of(handlers13)));
6843
6891
  // src/proxmox/sdn-zone.ts
6844
6892
  import { Resource as Resource34 } from "alchemy";
6845
6893
  import * as Provider34 from "alchemy/Provider";
6846
- import * as Effect95 from "effect/Effect";
6894
+ import * as Effect96 from "effect/Effect";
6847
6895
  var ProxmoxSdnZone = Resource34("Proxmox.SdnZone");
6848
6896
  var sameIpam = (live, declared2) => (live === "" ? "pve" : live) === (declared2 === undefined || declared2 === "" ? "pve" : declared2);
6849
6897
  var body6 = (props) => ({
@@ -6864,7 +6912,7 @@ var clearable = {
6864
6912
  vlan: ["dns", "dnszone", "ipam", "mtu", "nodes"],
6865
6913
  vxlan: ["dns", "dnszone", "ipam", "mtu", "nodes"]
6866
6914
  };
6867
- var handlers15 = pveHandlers({
6915
+ var handlers14 = pveHandlers({
6868
6916
  readRole: "provision",
6869
6917
  attributes: (live, props) => {
6870
6918
  const liveType = text(live["type"]);
@@ -6896,13 +6944,13 @@ var handlers15 = pveHandlers({
6896
6944
  return withClears(fields2, clear);
6897
6945
  }
6898
6946
  });
6899
- var ProxmoxSdnZoneProvider = () => Provider34.effect(ProxmoxSdnZone, Effect95.succeed(ProxmoxSdnZone.Provider.of(handlers15)));
6947
+ var ProxmoxSdnZoneProvider = () => Provider34.effect(ProxmoxSdnZone, Effect96.succeed(ProxmoxSdnZone.Provider.of(handlers14)));
6900
6948
  // src/proxmox/storage.ts
6901
6949
  import { Resource as Resource35 } from "alchemy";
6902
- import { isResolved as isResolved30 } from "alchemy/Diff";
6950
+ import { isResolved as isResolved31 } from "alchemy/Diff";
6903
6951
  import * as Provider35 from "alchemy/Provider";
6904
6952
  import * as storage2 from "@distilled.cloud/proxmox/storage";
6905
- import * as Effect97 from "effect/Effect";
6953
+ import * as Effect98 from "effect/Effect";
6906
6954
 
6907
6955
  // src/proxmox/storage-plugin-options.ts
6908
6956
  var SHARED_ACCEPTED_TYPES = new Set(["dir", "lvm", "btrfs", "esxi"]);
@@ -6910,12 +6958,12 @@ var sharedAccepted = (type) => SHARED_ACCEPTED_TYPES.has(type);
6910
6958
 
6911
6959
  // src/proxmox/storage-wire.ts
6912
6960
  import * as storage from "@distilled.cloud/proxmox/storage";
6913
- import * as Effect96 from "effect/Effect";
6961
+ import * as Effect97 from "effect/Effect";
6914
6962
  var str2 = (value, fallback = "") => typeof value === "string" ? value : fallback;
6915
6963
  var tokens = (value) => value.split(",").map((part) => part.trim()).filter((part) => part !== "").sort().join(",");
6916
6964
  var sameList2 = (declared2, live) => declared2 === undefined || tokens(declared2) === tokens(live);
6917
6965
  var same7 = (declared2, live) => declared2 === undefined || declared2 === live;
6918
- var attributesOf10 = (live, props) => {
6966
+ var attributesOf11 = (live, props) => {
6919
6967
  const data = live;
6920
6968
  return {
6921
6969
  comment: str2(data["comment"]),
@@ -6929,8 +6977,8 @@ var attributesOf10 = (live, props) => {
6929
6977
  type: str2(data["type"], props.type)
6930
6978
  };
6931
6979
  };
6932
- var readStorageOrFail = (props) => readOrUnreadable(runPve(props.target, "provision", false, storage.getStorage({ storage: props.storage }))).pipe(Effect96.map((live) => live === UNREADABLE ? UNREADABLE : attributesOf10(live, props)));
6933
- var readStorage = (props) => readStorageOrFail(props).pipe(Effect96.catchTag("StorageNotFound", () => Effect96.succeed(undefined)));
6980
+ var readStorageOrFail = (props) => readOrUnreadable(runPve(props.target, "provision", false, storage.getStorage({ storage: props.storage }))).pipe(Effect97.map((live) => live === UNREADABLE ? UNREADABLE : attributesOf11(live, props)));
6981
+ var readStorage = (props) => readStorageOrFail(props).pipe(Effect97.catchTag("StorageNotFound", () => Effect97.succeed(undefined)));
6934
6982
  var dropUnreadable7 = (live) => live === UNREADABLE ? undefined : live;
6935
6983
  var changedProps = (live, props) => ({
6936
6984
  ...sameList2(props.content, live.content) ? {} : { content: props.content },
@@ -6941,7 +6989,7 @@ var changedProps = (live, props) => ({
6941
6989
  ...same7(props.preallocation, live.preallocation) ? {} : { preallocation: props.preallocation },
6942
6990
  ...same7(props.comment, live.comment) ? {} : { comment: props.comment }
6943
6991
  });
6944
- var matches10 = (attributes2, props) => !sharedAccepted(props.type) && !same7(props.shared, attributes2.shared) ? Effect96.die(new Error(`storage/${props.storage}: declared shared: ${String(props.shared)}, but PVE reports ` + `${String(attributes2.shared)} and '${props.type}' storages never accept a 'shared' ` + "write (storage-plugin-options.ts) -- remove the declared shared or set it to match " + "what PVE already reports; this value can never be applied.")) : Effect96.succeed(Object.keys(changedProps(attributes2, props)).length === 0);
6992
+ var matches11 = (attributes2, props) => !sharedAccepted(props.type) && !same7(props.shared, attributes2.shared) ? Effect97.die(new Error(`storage/${props.storage}: declared shared: ${String(props.shared)}, but PVE reports ` + `${String(attributes2.shared)} and '${props.type}' storages never accept a 'shared' ` + "write (storage-plugin-options.ts) -- remove the declared shared or set it to match " + "what PVE already reports; this value can never be applied.")) : Effect97.succeed(Object.keys(changedProps(attributes2, props)).length === 0);
6945
6993
 
6946
6994
  // src/proxmox/storage-form.ts
6947
6995
  var STORAGE_CREATE = "pve:POST /storage";
@@ -6964,7 +7012,7 @@ var createForm11 = (props) => ({
6964
7012
  storage: props.storage,
6965
7013
  type: props.type
6966
7014
  });
6967
- var updateForm9 = (props, live) => ({
7015
+ var updateForm10 = (props, live) => ({
6968
7016
  ...mutable2(props.type, live === undefined ? props : changedProps(live, props)),
6969
7017
  storage: props.storage
6970
7018
  });
@@ -6975,82 +7023,82 @@ var toDistilledUpdate3 = (form2) => underscored(form2);
6975
7023
  var ProxmoxStorage = Resource35("Proxmox.Storage", {
6976
7024
  defaultRemovalPolicy: "retain"
6977
7025
  });
6978
- var ProxmoxStorageProvider = () => Provider35.effect(ProxmoxStorage, Effect97.succeed(ProxmoxStorage.Provider.of({
6979
- list: () => Effect97.succeed([]),
6980
- read: Effect97.fn(function* ({ olds, output }) {
7026
+ var ProxmoxStorageProvider = () => Provider35.effect(ProxmoxStorage, Effect98.succeed(ProxmoxStorage.Provider.of({
7027
+ list: () => Effect98.succeed([]),
7028
+ read: Effect98.fn(function* ({ olds, output }) {
6981
7029
  return dropUnreadable7(yield* output === undefined ? readStorage(olds) : readStorageOrFail(olds));
6982
7030
  }),
6983
- diff: Effect97.fn(function* ({ news, output }) {
6984
- if (!isResolved30(news))
7031
+ diff: Effect98.fn(function* ({ news, output }) {
7032
+ if (!isResolved31(news))
6985
7033
  return;
6986
7034
  yield* guardWrite2(STORAGE_CREATE, createForm11(news), output === undefined);
6987
- yield* guardWrite2(STORAGE_UPDATE, updateForm9(news, undefined), false);
7035
+ yield* guardWrite2(STORAGE_UPDATE, updateForm10(news, undefined), false);
6988
7036
  if (output === undefined)
6989
7037
  return;
6990
7038
  const live = yield* readStorageOrFail(news);
6991
7039
  if (live === UNREADABLE) {
6992
- yield* unreadableWarning("Proxmox.Storage", news.storage);
7040
+ yield* unreadableWarning("Proxmox.Storage", news.storage, news.target.mount, mintTier(news.target, "provision"));
6993
7041
  return { action: "noop" };
6994
7042
  }
6995
7043
  if (live === undefined) {
6996
7044
  yield* guardWrite2(STORAGE_CREATE, createForm11(news), true);
6997
7045
  return { action: "update" };
6998
7046
  }
6999
- return (yield* matches10(live, news)) ? { action: "noop" } : { action: "update" };
7047
+ return (yield* matches11(live, news)) ? { action: "noop" } : { action: "update" };
7000
7048
  }),
7001
- reconcile: Effect97.fn(function* ({ news }) {
7049
+ reconcile: Effect98.fn(function* ({ news }) {
7002
7050
  const before = dropUnreadable7(yield* readStorage(news));
7003
7051
  yield* guardWrite2(STORAGE_CREATE, createForm11(news), before === undefined);
7004
- const update2 = updateForm9(news, before);
7052
+ const update2 = updateForm10(news, before);
7005
7053
  yield* guardWrite2(STORAGE_UPDATE, update2, false);
7006
7054
  if (before === undefined) {
7007
7055
  yield* runPve(news.target, "provision", true, storage2.createStorage(toDistilledCreate4(news)));
7008
- } else if (!(yield* matches10(before, news))) {
7056
+ } else if (!(yield* matches11(before, news))) {
7009
7057
  yield* runPve(news.target, "provision", true, storage2.putStorage(toDistilledUpdate3(update2)));
7010
7058
  }
7011
7059
  const after = dropUnreadable7(yield* readStorage(news));
7012
7060
  if (after === undefined) {
7013
- return yield* Effect97.die(new Error(`storage/${news.storage}: the write returned no error but the storage is still ` + 'absent. PVE wraps every answer in {"data":...} and can report success on a ' + "call that did nothing -- read back rather than trusting the status code."));
7061
+ return yield* Effect98.die(new Error(`storage/${news.storage}: the write returned no error but the storage is still ` + 'absent. PVE wraps every answer in {"data":...} and can report success on a ' + "call that did nothing -- read back rather than trusting the status code."));
7014
7062
  }
7015
7063
  return after;
7016
7064
  }),
7017
- delete: Effect97.fn(function* ({ olds }) {
7065
+ delete: Effect98.fn(function* ({ olds }) {
7018
7066
  yield* runPve(olds.target, "provision", true, storage2.deleteStorage({ storage: olds.storage }));
7019
7067
  })
7020
7068
  })));
7021
7069
  // src/proxmox/zfs-pool.ts
7022
7070
  import { Resource as Resource36 } from "alchemy";
7023
- import { isResolved as isResolved31 } from "alchemy/Diff";
7071
+ import { isResolved as isResolved32 } from "alchemy/Diff";
7024
7072
  import * as Provider36 from "alchemy/Provider";
7025
- import * as Effect100 from "effect/Effect";
7073
+ import * as Effect101 from "effect/Effect";
7026
7074
 
7027
7075
  // src/proxmox/zfs-pool-wire.ts
7028
7076
  import * as nodes20 from "@distilled.cloud/proxmox/nodes";
7029
- import * as Effect98 from "effect/Effect";
7077
+ import * as Effect99 from "effect/Effect";
7030
7078
  var leafDevices = (children) => Array.isArray(children) ? children.flatMap((entry) => {
7031
7079
  const vdev = entry;
7032
7080
  const nested = leafDevices(vdev.children);
7033
7081
  return nested.length > 0 ? nested : [text(vdev.name)].filter((name) => name !== "");
7034
7082
  }) : [];
7035
- var attributesOf11 = (live, props) => ({
7083
+ var attributesOf12 = (live, props) => ({
7036
7084
  devices: leafDevices(live.children).join(","),
7037
7085
  errors: text(live.errors, "unknown"),
7038
7086
  name: props.name,
7039
7087
  node: props.node,
7040
7088
  state: text(live.state, "unknown")
7041
7089
  });
7042
- var readPoolOrFail = (props) => readOrUnreadable(runPve(props.target, "read", false, nodes20.getNodeDiskZfs({ name: props.name, node: props.node }))).pipe(Effect98.map((live) => {
7090
+ var readPoolOrFail = (props) => readOrUnreadable(runPve(props.target, "read", false, nodes20.getNodeDiskZfs({ name: props.name, node: props.node }))).pipe(Effect99.map((live) => {
7043
7091
  if (live === UNREADABLE)
7044
7092
  return UNREADABLE;
7045
- return text(live.name) === "" ? undefined : attributesOf11(live, props);
7093
+ return text(live.name) === "" ? undefined : attributesOf12(live, props);
7046
7094
  }));
7047
- var readPool2 = (props) => readPoolOrFail(props).pipe(Effect98.orElseSucceed(() => {
7095
+ var readPool2 = (props) => readPoolOrFail(props).pipe(Effect99.orElseSucceed(() => {
7048
7096
  return;
7049
7097
  }));
7050
7098
  var dropUnreadable8 = (live) => live === UNREADABLE ? undefined : live;
7051
7099
 
7052
7100
  // src/proxmox/zfs-pool-form.ts
7053
- import * as Effect99 from "effect/Effect";
7101
+ import * as Effect100 from "effect/Effect";
7054
7102
  import * as nodes21 from "@distilled.cloud/proxmox/nodes";
7055
7103
  var ZFS_POOL_CREATE = "pve:POST /nodes/{node}/disks/zfs";
7056
7104
  var zfsPoolCreateEndpoint = (props) => props.devices === undefined || props.raidlevel === undefined ? undefined : ZFS_POOL_CREATE;
@@ -7071,25 +7119,25 @@ var toDistilledCreate5 = (props) => {
7071
7119
  };
7072
7120
  };
7073
7121
  var SETTLE_ATTEMPTS = 30;
7074
- var createPool2 = (props, read6) => Effect99.gen(function* () {
7122
+ var createPool2 = (props, read6) => Effect100.gen(function* () {
7075
7123
  const existing = yield* read6(props);
7076
7124
  if (existing !== undefined)
7077
7125
  return existing;
7078
7126
  if (props.devices === undefined || props.raidlevel === undefined) {
7079
- return yield* Effect99.die(new Error(`${props.node}/${props.name}: this is an adopt-only declaration (no \`devices\` or ` + "`raidlevel`) and the pool is not there to adopt. An adopt-only Proxmox.ZfsPool never " + "creates -- declare both fields for a pool this resource should build, or point this " + "declaration at a pool that already exists on this node."));
7127
+ return yield* Effect100.die(new Error(`${props.node}/${props.name}: this is an adopt-only declaration (no \`devices\` or ` + "`raidlevel`) and the pool is not there to adopt. An adopt-only Proxmox.ZfsPool never " + "creates -- declare both fields for a pool this resource should build, or point this " + "declaration at a pool that already exists on this node."));
7080
7128
  }
7081
7129
  yield* guardForm(zfsPoolCreateEndpoint(props), asForm2(createForm12(props)), true);
7082
7130
  const upid = yield* runPve(props.target, "provision", true, nodes21.createNodeDiskZfs(toDistilledCreate5(props)));
7083
- const settle3 = (attempts) => Effect99.gen(function* () {
7131
+ const settle3 = (attempts) => Effect100.gen(function* () {
7084
7132
  const live = yield* read6(props);
7085
7133
  if (live !== undefined || attempts <= 0)
7086
7134
  return live;
7087
- yield* Effect99.sleep("2 seconds");
7135
+ yield* Effect100.sleep("2 seconds");
7088
7136
  return yield* settle3(attempts - 1);
7089
7137
  });
7090
7138
  const after = yield* settle3(SETTLE_ATTEMPTS);
7091
7139
  if (after === undefined) {
7092
- return yield* Effect99.die(new Error(`nodes/${props.node}/disks/zfs/${props.name}: POST returned ${text(upid, "(no UPID)")} ` + "but the pool has not appeared. That POST only forks a `zfscreate` worker, so the task " + `holds the real error -- read it with \`pvesh get /nodes/${props.node}/tasks/<upid>/log\`. ` + "NOTHING WAS RETRIED AND NOTHING WAS CLEANED UP: if the worker reached `zpool create`, " + "the declared devices have already been written to. DO NOT RE-RUN THIS DEPLOY BEFORE " + 'READING THAT LOG: `read` cannot tell "the worker is still running" from "the pool is ' + 'genuinely gone", so a re-run this soon can POST a SECOND `zpool create` at the SAME ' + "devices while the first one is still mid-write -- confirm the task finished (one way " + "or the other) before trying again."));
7140
+ return yield* Effect100.die(new Error(`nodes/${props.node}/disks/zfs/${props.name}: POST returned ${text(upid, "(no UPID)")} ` + "but the pool has not appeared. That POST only forks a `zfscreate` worker, so the task " + `holds the real error -- read it with \`pvesh get /nodes/${props.node}/tasks/<upid>/log\`. ` + "NOTHING WAS RETRIED AND NOTHING WAS CLEANED UP: if the worker reached `zpool create`, " + "the declared devices have already been written to. DO NOT RE-RUN THIS DEPLOY BEFORE " + 'READING THAT LOG: `read` cannot tell "the worker is still running" from "the pool is ' + 'genuinely gone", so a re-run this soon can POST a SECOND `zpool create` at the SAME ' + "devices while the first one is still mid-write -- confirm the task finished (one way " + "or the other) before trying again."));
7093
7141
  }
7094
7142
  return after;
7095
7143
  });
@@ -7099,20 +7147,20 @@ var destroyPool = (props) => runPve(props.target, "provision", true, nodes21.del
7099
7147
  var ProxmoxZfsPool = Resource36("Proxmox.ZfsPool", {
7100
7148
  defaultRemovalPolicy: "retain"
7101
7149
  });
7102
- var ProxmoxZfsPoolProvider = () => Provider36.effect(ProxmoxZfsPool, Effect100.succeed(ProxmoxZfsPool.Provider.of({
7103
- list: () => Effect100.succeed([]),
7104
- read: Effect100.fn(function* ({ olds, output }) {
7150
+ var ProxmoxZfsPoolProvider = () => Provider36.effect(ProxmoxZfsPool, Effect101.succeed(ProxmoxZfsPool.Provider.of({
7151
+ list: () => Effect101.succeed([]),
7152
+ read: Effect101.fn(function* ({ olds, output }) {
7105
7153
  return dropUnreadable8(yield* output === undefined ? readPool2(olds) : readPoolOrFail(olds));
7106
7154
  }),
7107
- diff: Effect100.fn(function* ({ news, output }) {
7108
- if (!isResolved31(news))
7155
+ diff: Effect101.fn(function* ({ news, output }) {
7156
+ if (!isResolved32(news))
7109
7157
  return;
7110
7158
  yield* guardForm(zfsPoolCreateEndpoint(news), asForm2(createForm12(news)), output === undefined);
7111
7159
  if (output === undefined)
7112
7160
  return;
7113
7161
  const live = yield* readPoolOrFail(news);
7114
7162
  if (live === UNREADABLE) {
7115
- yield* unreadableWarning("Proxmox.ZfsPool", `${news.node}/${news.name}`);
7163
+ yield* unreadableWarning("Proxmox.ZfsPool", `${news.node}/${news.name}`, news.target.mount, mintTier(news.target, "read"));
7116
7164
  return { action: "noop" };
7117
7165
  }
7118
7166
  if (live === undefined) {
@@ -7121,10 +7169,10 @@ var ProxmoxZfsPoolProvider = () => Provider36.effect(ProxmoxZfsPool, Effect100.s
7121
7169
  }
7122
7170
  return { action: "noop" };
7123
7171
  }),
7124
- reconcile: Effect100.fn(function* ({ news }) {
7125
- return yield* createPool2(news, (props) => readPool2(props).pipe(Effect100.map(dropUnreadable8)));
7172
+ reconcile: Effect101.fn(function* ({ news }) {
7173
+ return yield* createPool2(news, (props) => readPool2(props).pipe(Effect101.map(dropUnreadable8)));
7126
7174
  }),
7127
- delete: Effect100.fn(function* ({ olds }) {
7175
+ delete: Effect101.fn(function* ({ olds }) {
7128
7176
  yield* destroyPool(olds);
7129
7177
  })
7130
7178
  })));
@@ -7207,5 +7255,5 @@ export {
7207
7255
  violations
7208
7256
  };
7209
7257
 
7210
- //# debugId=23CD7F01601D5A3A64756E2164756E21
7258
+ //# debugId=267899A4B122300564756E2164756E21
7211
7259
  //# sourceMappingURL=index.js.map