@homeflare/alchemy 0.37.1 → 0.37.3

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 (195) hide show
  1. package/dist/proxmox/backup-job-config.d.ts +95 -0
  2. package/dist/proxmox/backup-job-config.d.ts.map +1 -0
  3. package/dist/proxmox/backup-job-distilled.d.ts +46 -0
  4. package/dist/proxmox/backup-job-distilled.d.ts.map +1 -0
  5. package/dist/proxmox/backup-job.d.ts +9 -26
  6. package/dist/proxmox/backup-job.d.ts.map +1 -1
  7. package/dist/proxmox/ceph-fs-distilled.d.ts +17 -10
  8. package/dist/proxmox/ceph-fs-distilled.d.ts.map +1 -1
  9. package/dist/proxmox/ceph-fs-wire.d.ts +5 -22
  10. package/dist/proxmox/ceph-fs-wire.d.ts.map +1 -1
  11. package/dist/proxmox/ceph-fs.d.ts +3 -3
  12. package/dist/proxmox/distilled-pbs.d.ts +12 -0
  13. package/dist/proxmox/distilled-pbs.d.ts.map +1 -0
  14. package/dist/proxmox/fake-pbs-jobs.d.ts +23 -0
  15. package/dist/proxmox/fake-pbs-jobs.d.ts.map +1 -0
  16. package/dist/proxmox/fake-pbs-notify.d.ts.map +1 -1
  17. package/dist/proxmox/fake-pve.d.ts +1 -1
  18. package/dist/proxmox/fake-pve.d.ts.map +1 -1
  19. package/dist/proxmox/group-wire.d.ts +2 -2
  20. package/dist/proxmox/group-wire.d.ts.map +1 -1
  21. package/dist/proxmox/index.js +1382 -506
  22. package/dist/proxmox/index.js.map +51 -27
  23. package/dist/proxmox/live-core-fixtures.d.ts +40 -0
  24. package/dist/proxmox/live-core-fixtures.d.ts.map +1 -0
  25. package/dist/proxmox/metric-server-config.d.ts +49 -0
  26. package/dist/proxmox/metric-server-config.d.ts.map +1 -0
  27. package/dist/proxmox/metric-server-distilled.d.ts +43 -0
  28. package/dist/proxmox/metric-server-distilled.d.ts.map +1 -0
  29. package/dist/proxmox/metric-server.d.ts +2 -10
  30. package/dist/proxmox/metric-server.d.ts.map +1 -1
  31. package/dist/proxmox/node-network-wire.d.ts +1 -1
  32. package/dist/proxmox/node-network-wire.d.ts.map +1 -1
  33. package/dist/proxmox/notification-matcher-distilled.d.ts +9 -0
  34. package/dist/proxmox/notification-matcher-distilled.d.ts.map +1 -0
  35. package/dist/proxmox/notification-matcher-lifecycle.d.ts +27 -0
  36. package/dist/proxmox/notification-matcher-lifecycle.d.ts.map +1 -0
  37. package/dist/proxmox/notification-matcher.d.ts +5 -5
  38. package/dist/proxmox/notification-matcher.d.ts.map +1 -1
  39. package/dist/proxmox/notification-sdk-input.d.ts +22 -0
  40. package/dist/proxmox/notification-sdk-input.d.ts.map +1 -0
  41. package/dist/proxmox/notification-target-distilled.d.ts +12 -0
  42. package/dist/proxmox/notification-target-distilled.d.ts.map +1 -0
  43. package/dist/proxmox/notification-target-form.d.ts +2 -0
  44. package/dist/proxmox/notification-target-form.d.ts.map +1 -1
  45. package/dist/proxmox/notification-target-lifecycle.d.ts +29 -0
  46. package/dist/proxmox/notification-target-lifecycle.d.ts.map +1 -0
  47. package/dist/proxmox/notification-target-spec.d.ts +5 -0
  48. package/dist/proxmox/notification-target-spec.d.ts.map +1 -0
  49. package/dist/proxmox/notification-target.d.ts +4 -5
  50. package/dist/proxmox/notification-target.d.ts.map +1 -1
  51. package/dist/proxmox/pbs-datastore-endpoint.d.ts +1 -1
  52. package/dist/proxmox/pbs-datastore-form.d.ts +18 -42
  53. package/dist/proxmox/pbs-datastore-form.d.ts.map +1 -1
  54. package/dist/proxmox/pbs-datastore-guard.d.ts +7 -4
  55. package/dist/proxmox/pbs-datastore-guard.d.ts.map +1 -1
  56. package/dist/proxmox/pbs-datastore-lifecycle.d.ts +56 -0
  57. package/dist/proxmox/pbs-datastore-lifecycle.d.ts.map +1 -0
  58. package/dist/proxmox/pbs-datastore-wire.d.ts +21 -0
  59. package/dist/proxmox/pbs-datastore-wire.d.ts.map +1 -0
  60. package/dist/proxmox/pbs-datastore.d.ts +5 -6
  61. package/dist/proxmox/pbs-datastore.d.ts.map +1 -1
  62. package/dist/proxmox/pbs-notification-input.d.ts +18 -0
  63. package/dist/proxmox/pbs-notification-input.d.ts.map +1 -0
  64. package/dist/proxmox/pbs-notification-matcher-distilled.d.ts +11 -0
  65. package/dist/proxmox/pbs-notification-matcher-distilled.d.ts.map +1 -0
  66. package/dist/proxmox/pbs-notification-matcher.d.ts +4 -3
  67. package/dist/proxmox/pbs-notification-matcher.d.ts.map +1 -1
  68. package/dist/proxmox/pbs-notification-target-distilled.d.ts +20 -0
  69. package/dist/proxmox/pbs-notification-target-distilled.d.ts.map +1 -0
  70. package/dist/proxmox/pbs-notification-target-lifecycle.d.ts +4 -4
  71. package/dist/proxmox/pbs-notification-target-lifecycle.d.ts.map +1 -1
  72. package/dist/proxmox/pbs-notification-target.d.ts +1 -1
  73. package/dist/proxmox/pbs-prune-job-lifecycle.d.ts +22 -0
  74. package/dist/proxmox/pbs-prune-job-lifecycle.d.ts.map +1 -0
  75. package/dist/proxmox/pbs-prune-job-spec.d.ts +5 -0
  76. package/dist/proxmox/pbs-prune-job-spec.d.ts.map +1 -0
  77. package/dist/proxmox/pbs-prune-job-wire.d.ts +11 -0
  78. package/dist/proxmox/pbs-prune-job-wire.d.ts.map +1 -0
  79. package/dist/proxmox/pbs-prune-job.d.ts +9 -8
  80. package/dist/proxmox/pbs-prune-job.d.ts.map +1 -1
  81. package/dist/proxmox/pbs-sync-job-attributes.d.ts +34 -0
  82. package/dist/proxmox/pbs-sync-job-attributes.d.ts.map +1 -0
  83. package/dist/proxmox/pbs-sync-job-form.d.ts +21 -22
  84. package/dist/proxmox/pbs-sync-job-form.d.ts.map +1 -1
  85. package/dist/proxmox/pbs-sync-job-lifecycle.d.ts +22 -0
  86. package/dist/proxmox/pbs-sync-job-lifecycle.d.ts.map +1 -0
  87. package/dist/proxmox/pbs-sync-job-wire.d.ts +11 -0
  88. package/dist/proxmox/pbs-sync-job-wire.d.ts.map +1 -0
  89. package/dist/proxmox/pbs-sync-job.d.ts +9 -39
  90. package/dist/proxmox/pbs-sync-job.d.ts.map +1 -1
  91. package/dist/proxmox/pbs-verify-job-lifecycle.d.ts +22 -0
  92. package/dist/proxmox/pbs-verify-job-lifecycle.d.ts.map +1 -0
  93. package/dist/proxmox/pbs-verify-job-spec.d.ts +16 -0
  94. package/dist/proxmox/pbs-verify-job-spec.d.ts.map +1 -0
  95. package/dist/proxmox/pbs-verify-job-wire.d.ts +11 -0
  96. package/dist/proxmox/pbs-verify-job-wire.d.ts.map +1 -0
  97. package/dist/proxmox/pbs-verify-job.d.ts +12 -12
  98. package/dist/proxmox/pbs-verify-job.d.ts.map +1 -1
  99. package/dist/proxmox/pool.d.ts +10 -1
  100. package/dist/proxmox/pool.d.ts.map +1 -1
  101. package/dist/proxmox/storage-wire.d.ts +2 -2
  102. package/dist/proxmox/storage-wire.d.ts.map +1 -1
  103. package/dist/proxmox/user-wire.d.ts +2 -2
  104. package/dist/proxmox/user-wire.d.ts.map +1 -1
  105. package/dist/proxmox/zfs-pool-wire.d.ts +1 -1
  106. package/dist/proxmox/zfs-pool-wire.d.ts.map +1 -1
  107. package/docs/changelog/README.md +22 -0
  108. package/docs/changelog/archive-01.md +176 -0
  109. package/docs/changelog/archive-02.md +180 -0
  110. package/docs/changelog/archive-03.md +179 -0
  111. package/docs/changelog/archive-04.md +178 -0
  112. package/docs/changelog/archive-05.md +177 -0
  113. package/docs/changelog/archive-06.md +180 -0
  114. package/docs/changelog/archive-07.md +180 -0
  115. package/docs/changelog/archive-08.md +178 -0
  116. package/docs/changelog/archive-09.md +181 -0
  117. package/docs/changelog/archive-10.md +182 -0
  118. package/docs/changelog/archive-11.md +182 -0
  119. package/docs/changelog/archive-12.md +183 -0
  120. package/docs/changelog/archive-13.md +180 -0
  121. package/docs/changelog/archive-14.md +178 -0
  122. package/docs/changelog/archive-15.md +181 -0
  123. package/docs/changelog/archive-16.md +182 -0
  124. package/docs/changelog/archive-17.md +183 -0
  125. package/docs/changelog/archive-18.md +55 -0
  126. package/docs/pbs-distilled-jobs.md +31 -0
  127. package/docs/pbs-notifications.md +8 -2
  128. package/docs/proxmox-notification-sdk.md +28 -0
  129. package/docs/proxmox-sdk-migration.md +60 -0
  130. package/docs/proxmox.md +9 -3
  131. package/docs/upstream-conformance-families.md +6 -2
  132. package/package.json +3 -3
  133. package/src/proxmox/adopt-noop.test.ts +4 -5
  134. package/src/proxmox/backup-job-config.ts +95 -0
  135. package/src/proxmox/backup-job-distilled.ts +86 -0
  136. package/src/proxmox/backup-job.ts +78 -116
  137. package/src/proxmox/ceph-fs-delete.test.ts +5 -8
  138. package/src/proxmox/ceph-fs-destroy-sdk.test.ts +98 -0
  139. package/src/proxmox/ceph-fs-distilled.ts +41 -13
  140. package/src/proxmox/ceph-fs-wire.ts +5 -93
  141. package/src/proxmox/ceph-fs.ts +7 -7
  142. package/src/proxmox/constraints.test.ts +9 -8
  143. package/src/proxmox/distilled-pbs.test.ts +87 -0
  144. package/src/proxmox/distilled-pbs.ts +50 -0
  145. package/src/proxmox/fake-pbs-jobs.ts +99 -0
  146. package/src/proxmox/fake-pbs-notify.ts +4 -1
  147. package/src/proxmox/fake-pve.ts +3 -2
  148. package/src/proxmox/live-core-fixtures.ts +126 -0
  149. package/src/proxmox/live-core-lifecycle.test.ts +115 -0
  150. package/src/proxmox/live-core-wire.test.ts +190 -0
  151. package/src/proxmox/metric-server-config.ts +87 -0
  152. package/src/proxmox/metric-server-distilled.ts +81 -0
  153. package/src/proxmox/metric-server.ts +77 -88
  154. package/src/proxmox/notification-distilled.test.ts +162 -0
  155. package/src/proxmox/notification-matcher-distilled.ts +60 -0
  156. package/src/proxmox/notification-matcher-lifecycle.ts +71 -0
  157. package/src/proxmox/notification-matcher.ts +9 -26
  158. package/src/proxmox/notification-replacement.test.ts +190 -0
  159. package/src/proxmox/notification-sdk-input.ts +39 -0
  160. package/src/proxmox/notification-target-distilled.ts +160 -0
  161. package/src/proxmox/notification-target-form.ts +2 -0
  162. package/src/proxmox/notification-target-lifecycle.ts +75 -0
  163. package/src/proxmox/notification-target-spec.ts +68 -0
  164. package/src/proxmox/notification-target.ts +6 -68
  165. package/src/proxmox/pbs-datastore-endpoint.ts +1 -1
  166. package/src/proxmox/pbs-datastore-form.ts +18 -49
  167. package/src/proxmox/pbs-datastore-guard.ts +7 -4
  168. package/src/proxmox/pbs-datastore-lifecycle.ts +114 -0
  169. package/src/proxmox/pbs-datastore-wire.ts +94 -0
  170. package/src/proxmox/pbs-datastore.ts +7 -133
  171. package/src/proxmox/pbs-jobs-delete.test.ts +40 -0
  172. package/src/proxmox/pbs-jobs-sdk.test.ts +215 -0
  173. package/src/proxmox/pbs-notification-errors.test.ts +93 -0
  174. package/src/proxmox/pbs-notification-input.ts +25 -0
  175. package/src/proxmox/pbs-notification-mail.test.ts +64 -0
  176. package/src/proxmox/pbs-notification-matcher-distilled.ts +65 -0
  177. package/src/proxmox/pbs-notification-matcher.ts +70 -17
  178. package/src/proxmox/pbs-notification-target-distilled.ts +124 -0
  179. package/src/proxmox/pbs-notification-target-lifecycle.ts +26 -17
  180. package/src/proxmox/pbs-notification-target.ts +1 -1
  181. package/src/proxmox/pbs-notifications-stack.test.ts +25 -0
  182. package/src/proxmox/pbs-prune-job-lifecycle.ts +52 -0
  183. package/src/proxmox/pbs-prune-job-spec.ts +53 -0
  184. package/src/proxmox/pbs-prune-job-wire.ts +68 -0
  185. package/src/proxmox/pbs-prune-job.ts +10 -58
  186. package/src/proxmox/pbs-sync-job-attributes.ts +33 -0
  187. package/src/proxmox/pbs-sync-job-form.ts +7 -6
  188. package/src/proxmox/pbs-sync-job-lifecycle.ts +46 -0
  189. package/src/proxmox/pbs-sync-job-wire.ts +71 -0
  190. package/src/proxmox/pbs-sync-job.ts +10 -41
  191. package/src/proxmox/pbs-verify-job-lifecycle.ts +52 -0
  192. package/src/proxmox/pbs-verify-job-spec.ts +76 -0
  193. package/src/proxmox/pbs-verify-job-wire.ts +58 -0
  194. package/src/proxmox/pbs-verify-job.ts +13 -85
  195. package/src/proxmox/pool.ts +92 -10
@@ -0,0 +1,11 @@
1
+ /** PBS 4.2.6-1 operations through @distilled.cloud/proxmox-backup. */
2
+ import * as config from '@distilled.cloud/proxmox-backup/config';
3
+ import * as Effect from 'effect/Effect';
4
+ import type { SyncJobProps } from './pbs-sync-job.ts';
5
+ /** ⛔ Only the SDK SyncJobNotFound is absence; permission, transport and malformed replies propagate. */
6
+ export declare const readOne: (props: SyncJobProps) => Effect.Effect<import("./pbs-sync-job-attributes.ts").SyncJobAttributes | undefined, Error | import("./credential-errors.ts").PveCredentialDenied | import("effect/Cause").TimeoutError | config.ProxmoxBackupOpError, import("effect/unstable/http/HttpClient").HttpClient>;
7
+ export declare const createOne: (props: SyncJobProps) => Effect.Effect<config.SyncConfigResponse, Error | import("./credential-errors.ts").PveCredentialDenied | import("effect/Cause").TimeoutError | config.ProxmoxBackupOpError, import("effect/unstable/http/HttpClient").HttpClient>;
8
+ export declare const updateOne: (props: SyncJobProps) => Effect.Effect<config.PutConfigSyncResponse, Error | import("./credential-errors.ts").PveCredentialDenied | import("effect/Cause").TimeoutError | config.ProxmoxBackupOpError, import("effect/unstable/http/HttpClient").HttpClient>;
9
+ /** Deleting the schedule never deletes backups; already missing is a successful deletion. */
10
+ export declare const deleteOne: (props: SyncJobProps) => Effect.Effect<config.DeleteConfigSyncResponse | undefined, Error | import("./credential-errors.ts").PveCredentialDenied | import("effect/Cause").TimeoutError | config.ProxmoxBackupOpError, import("effect/unstable/http/HttpClient").HttpClient>;
11
+ //# sourceMappingURL=pbs-sync-job-wire.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pbs-sync-job-wire.d.ts","sourceRoot":"","sources":["../../src/proxmox/pbs-sync-job-wire.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,OAAO,KAAK,MAAM,MAAM,wCAAwC,CAAC;AACjE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AA+CtD,wGAAwG;AACxG,eAAO,MAAM,OAAO,UAAW,YAAY,gRAIxC,CAAC;AAEJ,eAAO,MAAM,SAAS,UAAW,YAAY,qOAC+B,CAAC;AAE7E,eAAO,MAAM,SAAS,UAAW,YAAY,wOACkC,CAAC;AAEhF,6FAA6F;AAC7F,eAAO,MAAM,SAAS,UAAW,YAAY,uPAKzC,CAAC"}
@@ -35,8 +35,8 @@
35
35
  * `/api2/json/config/sync` is not even evidence that the endpoint exists. THE FIRST PLAN
36
36
  * AGAINST A LIVE PBS IS THE MEASUREMENT. Read it; do not deploy it unseen.
37
37
  * ⚠️ AN ERROR BODY IS NOT WRAPPED: the 401 body is the bare text `authentication failed`, not
38
- * JSON. `pve()` checks `response.ok` before it parses, so a `pbs()` copied from it is safe —
39
- * provided the check stays in that order.
38
+ * JSON. The original `pve()` checked status before decoding success data. The distilled PBS
39
+ * protocol preserves this distinction and classifies error text through SDK patches.
40
40
  *
41
41
  * ⚠️ `Proxmox.BackupJob` AND `Pbs.SyncJob` ARE NOT THE SAME FAMILY AND THE NAMES NEARLY COLLIDE.
42
42
  * The first is a PVE vzdump schedule; this is a Proxmox Backup SERVER sync job, on a different
@@ -54,6 +54,8 @@
54
54
  */
55
55
  import { Resource } from 'alchemy';
56
56
  import * as Provider from 'alchemy/Provider';
57
+ import type { SyncJobAttributes } from './pbs-sync-job-attributes.ts';
58
+ export type { SyncJobAttributes } from './pbs-sync-job-attributes.ts';
57
59
  import type { PveRequirements } from './resource.ts';
58
60
  import type { WithPbsTarget } from './resource.ts';
59
61
  /**
@@ -155,10 +157,10 @@ export interface SyncJobProps extends WithPbsTarget {
155
157
  'transfer-last'?: number;
156
158
  /**
157
159
  * ⛔ NOT DECLARABLE, AND A COMPILE ERROR RATHER THAN A PROP THAT HALF WORKS — the storage.ts
158
- * `password` idiom, for two independent reasons, either of which alone would be enough.
160
+ * `password` idiom. Two barriers originally applied; the second remains unresolved.
159
161
  * 1. THE WIRE FORM IS AN ARRAY. PBS takes `group-filter` as a repeated parameter
160
- * (`group-filter=type:ct&group-filter=regex:^web`), and `pve()`'s form is
161
- * `Record<string, string>` — one value per key — so a list cannot be expressed at all.
162
+ * (`group-filter=type:ct&group-filter=regex:^web`). The old single-value form could not
163
+ * express it; the distilled PBS protocol now supports repeated keys.
162
164
  * 2. NARROWING A FILTER MAY BE A DELETE. Whether `remove-vanished` skips the groups a filter
163
165
  * excludes is NOT something I could measure without a credential. If it does not, then
164
166
  * editing this field on a job with `remove-vanished` set removes every local group the new
@@ -166,8 +168,8 @@ export interface SyncJobProps extends WithPbsTarget {
166
168
  * half-working prop.
167
169
  * ★ IT IS STILL REPORTED in the attributes, so a plan shows the filters a hand-made job carries
168
170
  * and this resource never strips them: undeclared is unmanaged, and PBS's update assigns only
169
- * what it was sent. To make it declarable, fix both halves — a form type that can repeat a
170
- * key, and a MEASURED answer to (2) — in that order.
171
+ * what it was sent. Making it declarable still needs a MEASURED answer to (2), even though
172
+ * the SDK now supplies the necessary repeated-key transport.
171
173
  */
172
174
  'group-filter'?: never;
173
175
  /**
@@ -192,38 +194,6 @@ export interface SyncJobProps extends WithPbsTarget {
192
194
  */
193
195
  'verified-only'?: boolean;
194
196
  }
195
- export interface SyncJobAttributes {
196
- /** From the props — it is the path this object was read by. */
197
- id: string;
198
- store: string;
199
- /** `''` is the root namespace, which is also how PBS spells it. */
200
- ns: string;
201
- /** `''` means a LOCAL sync — datastore to datastore on this PBS. */
202
- remote: string;
203
- 'remote-store': string;
204
- 'remote-ns': string;
205
- /** `''` means the job runs only when somebody starts it. */
206
- schedule: string;
207
- comment: string;
208
- 'remove-vanished': boolean;
209
- /** ⚠️ Absent on the wire means `false`, PBS's own default. */
210
- 'verified-only': boolean;
211
- /** `''` means no owner in the config, i.e. `root@pam` at runtime. An identifier, never a secret. */
212
- owner: string;
213
- /** Bytes per second, or `UNSET` (-1). See `bytes()`. */
214
- 'rate-in': number;
215
- /** `UNSET` (-1) means unset, which means full recursion. `0` is a real value meaning none. */
216
- 'max-depth': number;
217
- /** `UNSET` (-1) means all snapshots. */
218
- 'transfer-last': number;
219
- /**
220
- * ⚠️ REPORTED, NEVER SENT, NEVER COMPARED — the live filter list joined for display only. See the
221
- * ⛔ on the prop for why it is not declarable.
222
- */
223
- 'group-filter': string;
224
- /** `pull` or `push`. Reported, never compared — create-only here. */
225
- 'sync-direction': string;
226
- }
227
197
  export interface PbsSyncJob extends Resource<'Pbs.SyncJob', SyncJobProps, SyncJobAttributes, never, PveRequirements> {
228
198
  }
229
199
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"pbs-sync-job.d.ts","sourceRoot":"","sources":["../../src/proxmox/pbs-sync-job.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAG7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD;;;;GAIG;AACH,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD;;;;;;;OAOG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,cAAc,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;;;;OAeG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;;;;;;;;OAeG;IACH,cAAc,CAAC,EAAE,KAAK,CAAC;IACvB;;;;;;;;;OASG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,EAAE,EAAE,MAAM,CAAC;IACX,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,8DAA8D;IAC9D,eAAe,EAAE,OAAO,CAAC;IACzB,oGAAoG;IACpG,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;IAClB,8FAA8F;IAC9F,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,eAAe,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,UAAW,SAAQ,QAAQ,CAC1C,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,UAAU,6CAAsC,CAAC;AAE9D;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,gIACgD,CAAC"}
1
+ {"version":3,"file":"pbs-sync-job.d.ts","sourceRoot":"","sources":["../../src/proxmox/pbs-sync-job.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAG7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtE,YAAY,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD;;;;GAIG;AACH,MAAM,WAAW,YAAa,SAAQ,aAAa;IACjD;;;;;;;OAOG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,cAAc,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;;;;OAeG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;;;;;;;;OAeG;IACH,cAAc,CAAC,EAAE,KAAK,CAAC;IACvB;;;;;;;;;OASG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,UAAW,SAAQ,QAAQ,CAC1C,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,UAAU,6CAAsC,CAAC;AAE9D;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,gIACgD,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { Input } from 'alchemy/Input';
2
+ import * as Effect from 'effect/Effect';
3
+ import type { PbsVerifyJobAttributes, PbsVerifyJobProps } from './pbs-verify-job.ts';
4
+ export declare const handlers: {
5
+ list: () => Effect.Effect<never[], never, never>;
6
+ read: ({ olds }: {
7
+ olds: PbsVerifyJobProps;
8
+ }) => Effect.Effect<PbsVerifyJobAttributes | undefined, Error | import("./credential-errors.ts").PveCredentialDenied | import("effect/Cause").TimeoutError | import("@distilled.cloud/proxmox-backup/Protocol").ProxmoxBackupOpError, import("effect/unstable/http/HttpClient").HttpClient>;
9
+ diff: ({ news, output, }: {
10
+ news: Input<PbsVerifyJobProps>;
11
+ output: PbsVerifyJobAttributes | undefined;
12
+ }) => Effect.Effect<{
13
+ readonly action: "noop" | "update";
14
+ } | undefined, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
15
+ reconcile: ({ news }: {
16
+ news: PbsVerifyJobProps;
17
+ }) => Effect.Effect<PbsVerifyJobAttributes, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
18
+ delete: ({ olds }: {
19
+ olds: PbsVerifyJobProps;
20
+ }) => Effect.Effect<import("@distilled.cloud/proxmox-backup/config").DeleteConfigVerifyResponse | undefined, Error | import("./credential-errors.ts").PveCredentialDenied | import("effect/Cause").TimeoutError | import("@distilled.cloud/proxmox-backup/Protocol").ProxmoxBackupOpError, import("effect/unstable/http/HttpClient").HttpClient>;
21
+ };
22
+ //# sourceMappingURL=pbs-verify-job-lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pbs-verify-job-lifecycle.d.ts","sourceRoot":"","sources":["../../src/proxmox/pbs-verify-job-lifecycle.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAMrF,eAAO,MAAM,QAAQ;IAEnB,IAAI;IACJ,IAAI,aAAa;QAAE,IAAI,EAAE,iBAAiB,CAAA;KAAE;IAC5C,IAAI,sBAGD;QACD,IAAI,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC/B,MAAM,EAAE,sBAAsB,GAAG,SAAS,CAAC;KAC5C;;;IAaD,SAAS,aAAa;QAAE,IAAI,EAAE,iBAAiB,CAAA;KAAE;IAgBjD,MAAM,aAAa;QAAE,IAAI,EAAE,iBAAiB,CAAA;KAAE;CAC/C,CAAC"}
@@ -0,0 +1,16 @@
1
+ /** PBS 4.2.6-1 values and vendor form guards; SDK transport is in pbs-verify-job-wire.ts. */
2
+ import type { PbsVerifyJobAttributes, PbsVerifyJobProps } from './pbs-verify-job.ts';
3
+ import type { PveSpec } from './resource-spec.ts';
4
+ /**
5
+ * ⚠️ EVERY FIELD IS READ THROUGH `values.ts` THOUGH PBS RETURNS REAL JSON TYPES. Unlike PVE's
6
+ * SectionConfig round-trip, `GET /config/verify/{id}` serialises a Rust struct, so
7
+ * `ignore-verified` arrives as a JSON boolean and `max-depth` as a JSON number. `bool` and `int`
8
+ * accept both spellings, and using them costs nothing while covering the version that does not.
9
+ * ⚠️ `digest` IS NOT AN ATTRIBUTE AND CANNOT BECOME ONE BY ACCIDENT. PBS puts it on the rpcenv, and
10
+ * the JSON formatter adds rpcenv attributes as SIBLINGS of `data` — `{"data":{…},"digest":"…"}` —
11
+ * so both the old client and the SDK expose only the resource data. Attributes deliberately
12
+ * exclude it: the digest covers verification.cfg as a FILE, so keeping it would churn state
13
+ * whenever an unrelated verify job was edited.
14
+ */
15
+ export declare const spec: PveSpec<PbsVerifyJobProps, PbsVerifyJobAttributes>;
16
+ //# sourceMappingURL=pbs-verify-job-spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pbs-verify-job-spec.d.ts","sourceRoot":"","sources":["../../src/proxmox/pbs-verify-job-spec.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,OAAO,KAAK,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACrF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAIlD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,IAAI,EAAE,OAAO,CAAC,iBAAiB,EAAE,sBAAsB,CA0DnE,CAAC"}
@@ -0,0 +1,11 @@
1
+ /** PBS 4.2.6-1 operations through @distilled.cloud/proxmox-backup. */
2
+ import * as config from '@distilled.cloud/proxmox-backup/config';
3
+ import * as Effect from 'effect/Effect';
4
+ import type { PbsVerifyJobProps } from './pbs-verify-job.ts';
5
+ /** ⛔ Only the SDK VerifyJobNotFound is absence; permission, transport and malformed replies propagate. */
6
+ export declare const readOne: (props: PbsVerifyJobProps) => Effect.Effect<import("./pbs-verify-job.ts").PbsVerifyJobAttributes | undefined, Error | import("./credential-errors.ts").PveCredentialDenied | import("effect/Cause").TimeoutError | config.ProxmoxBackupOpError, import("effect/unstable/http/HttpClient").HttpClient>;
7
+ export declare const createOne: (props: PbsVerifyJobProps) => Effect.Effect<config.VerifyConfigResponse, Error | import("./credential-errors.ts").PveCredentialDenied | import("effect/Cause").TimeoutError | config.ProxmoxBackupOpError, import("effect/unstable/http/HttpClient").HttpClient>;
8
+ export declare const updateOne: (props: PbsVerifyJobProps) => Effect.Effect<config.PutConfigVerifyResponse, Error | import("./credential-errors.ts").PveCredentialDenied | import("effect/Cause").TimeoutError | config.ProxmoxBackupOpError, import("effect/unstable/http/HttpClient").HttpClient>;
9
+ /** Deleting the schedule never deletes backups; already missing is a successful deletion. */
10
+ export declare const deleteOne: (props: PbsVerifyJobProps) => Effect.Effect<config.DeleteConfigVerifyResponse | undefined, Error | import("./credential-errors.ts").PveCredentialDenied | import("effect/Cause").TimeoutError | config.ProxmoxBackupOpError, import("effect/unstable/http/HttpClient").HttpClient>;
11
+ //# sourceMappingURL=pbs-verify-job-wire.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pbs-verify-job-wire.d.ts","sourceRoot":"","sources":["../../src/proxmox/pbs-verify-job-wire.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,OAAO,KAAK,MAAM,MAAM,wCAAwC,CAAC;AACjE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAkC7D,0GAA0G;AAC1G,eAAO,MAAM,OAAO,UAAW,iBAAiB,4QAI7C,CAAC;AAEJ,eAAO,MAAM,SAAS,UAAW,iBAAiB,uOAC4B,CAAC;AAE/E,eAAO,MAAM,SAAS,UAAW,iBAAiB,0OAC+B,CAAC;AAElF,6FAA6F;AAC7F,eAAO,MAAM,SAAS,UAAW,iBAAiB,yPAK9C,CAAC"}
@@ -9,22 +9,22 @@
9
9
  * green `Proxmox.BackupJob` makes it worse rather than better, because a vzdump job that says
10
10
  * "OK" every night is exactly the evidence people stop at.
11
11
  *
12
- * ⛔ THIS FILE CANNOT AUTHENTICATE UNTIL TWO THINGS OUTSIDE IT CHANGE, AND IT IS SHIPPED SAYING SO
13
- * RATHER THAN SHIPPED LOOKING FINISHED. Both are recorded on `PbsTarget` below:
12
+ * ⚠️ HISTORICAL BOOTSTRAP BLOCKER, 2026-09-13: TWO THINGS OUTSIDE THIS FILE WERE MISSING
13
+ * before PBS could authenticate. Both are now resolved by the PBS lane and SDK:
14
14
  * 1. `credentials.ts` has no PBS mint. MEASURED 2026-09-13 from this Mac: the agent's
15
15
  * approle is refused `sys/mounts`, `kv/infra/proxmox` and `proxmox-pbs/creds/read` alike —
16
16
  * 403 permission denied on all three — so there is no mount to name and none is invented.
17
17
  * 2. `client.ts`'s `authorization()` builds a PVE header, and PBS will not accept it. See the
18
18
  * ⛔ on `PbsTarget`.
19
- * Until both land, every call 401s, `pveOperations.read` folds that into "absent", and the plan
20
- * reports `create` for a job that is plainly there. The deploy then FAILS at the POST rather
19
+ * Before both landed, every call 401'd, `pveOperations.read` folded that into "absent", and the plan
20
+ * reported `create` for a job that was plainly there. The deploy then FAILED at the POST rather
21
21
  * than clobbering anything — an unauthenticated POST 401s, and an authenticated one is refused
22
22
  * because PBS will not take a duplicate section id — so the cost is a LYING PLAN and a broken
23
23
  * run, not a lost job. That is still reason enough not to wire it into a stack yet: a plan
24
24
  * nobody can trust is its own outage.
25
25
  *
26
- * ⚠️ THE SHAPES BELOW ARE READ FROM PUBLISHED SOURCE, NOT MEASURED ON THIS ESTATE. Everything is
27
- * taken from `pbs-api-types/src/jobs.rs`, `src/api2/config/verify.rs`, `src/server/verify_job.rs`
26
+ * ⚠️ THE ORIGINAL SHAPES WERE READ FROM PUBLISHED SOURCE, NOT MEASURED ON THIS ESTATE. Everything is
27
+ * originally taken from `pbs-api-types/src/jobs.rs`, `src/api2/config/verify.rs`, `src/server/verify_job.rs`
28
28
  * and `src/backup/verify.rs` at HEAD of the Proxmox git mirrors on 2026-09-13. What WAS measured
29
29
  * here: `pbs.example.com:8007` and `pbs.mgmt.example.com:8007` both answer HTTP 401 under
30
30
  * STRICT TLS (curl `ssl_verify_result=0`), so no `-k` is needed and `client.ts`'s plain `fetch`
@@ -34,7 +34,7 @@
34
34
  import { Resource } from 'alchemy';
35
35
  import * as Provider from 'alchemy/Provider';
36
36
  import type { PbsTarget } from './credentials.ts';
37
- import { type PveRequirements } from './resource.ts';
37
+ import type { PveRequirements } from './resource-spec.ts';
38
38
  export interface PbsVerifyJobProps {
39
39
  /** ⛔ A PBS host, never a PVE cluster. See `PbsTarget`. */
40
40
  target: PbsTarget;
@@ -128,7 +128,7 @@ export interface PbsVerifyJob extends Resource<'Pbs.VerifyJob', PbsVerifyJobProp
128
128
  */
129
129
  export declare const PbsVerifyJob: import("alchemy").ResourceClass<PbsVerifyJob>;
130
130
  /**
131
- * ⛔ `list` IS EMPTY, INHERITED FROM `pveHandlers`, AND THE REASON IS SHARPER HERE THAN ELSEWHERE.
131
+ * ⛔ `list` STAYS EXPLICITLY EMPTY, AND THE REASON IS SHARPER HERE THAN ELSEWHERE.
132
132
  * `GET /config/verify` returns every verification job the caller can see, including the
133
133
  * ones the PBS installer and a human made. Adopting those would put Alchemy one dropped line
134
134
  * away from DELETING a datastore's only verification schedule — and deleting it destroys nothing
@@ -136,10 +136,10 @@ export declare const PbsVerifyJob: import("alchemy").ResourceClass<PbsVerifyJob>
136
136
  * to say when the rot started. Adoption stays explicit: declare the existing id.
137
137
  *
138
138
  * ⚠️ NO `digest` IS SENT ON UPDATE OR DELETE, SO THIS IS LAST-WRITER-WINS. PBS accepts an optional
139
- * `digest` on both and would refuse a write made against a stale read. Sending one would need a
140
- * read-then-write window this provider does not have — `pveOperations` reads and writes in two
141
- * separate calls with two separate mints — so a concurrent edit from the PBS UI is overwritten
142
- * rather than refused. Same behaviour as every PVE family here; stated because PBS offers better.
139
+ * `digest` on both and would refuse a write made against a stale read. This migration preserves
140
+ * the existing forms, which omit it; the SDK runner reuses leased credentials but does not add
141
+ * an optimistic-lock check. A concurrent edit from the PBS UI may therefore be overwritten
142
+ * rather than refused. PBS offers that stronger guarantee as a separate provider change.
143
143
  */
144
144
  export declare const PbsVerifyJobProvider: () => import("effect/Layer").Layer<Provider.Provider<PbsVerifyJob>, never, import("effect/unstable/http/HttpClient").HttpClient>;
145
145
  //# sourceMappingURL=pbs-verify-job.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pbs-verify-job.d.ts","sourceRoot":"","sources":["../../src/proxmox/pbs-verify-job.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,KAAK,eAAe,EAAe,MAAM,eAAe,CAAC;AAGlE,MAAM,WAAW,iBAAiB;IAChC,0DAA0D;IAC1D,MAAM,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;;;OAMG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,0FAA0F;IAC1F,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,+FAA+F;IAC/F,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,2EAA2E;IAC3E,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAa,SAAQ,QAAQ,CAC5C,eAAe,EACf,iBAAiB,EACjB,sBAAsB,EACtB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,+CAA0C,CAAC;AAyEpE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oBAAoB,kIACkD,CAAC"}
1
+ {"version":3,"file":"pbs-verify-job.d.ts","sourceRoot":"","sources":["../../src/proxmox/pbs-verify-job.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAG7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,WAAW,iBAAiB;IAChC,0DAA0D;IAC1D,MAAM,EAAE,SAAS,CAAC;IAClB;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;;;OAMG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,0FAA0F;IAC1F,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,+FAA+F;IAC/F,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,2EAA2E;IAC3E,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAa,SAAQ,QAAQ,CAC5C,eAAe,EACf,iBAAiB,EACjB,sBAAsB,EACtB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,+CAA0C,CAAC;AAEpE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oBAAoB,kIACkD,CAAC"}
@@ -17,8 +17,10 @@
17
17
  */
18
18
  import { Resource } from 'alchemy';
19
19
  import * as Provider from 'alchemy/Provider';
20
+ import * as pools from '@distilled.cloud/proxmox/pools';
21
+ import * as Effect from 'effect/Effect';
20
22
  import type { PoolsPoolidPutParams, PoolsPostParams } from './generated/pve.ts';
21
- import { type PveRequirements, type WithTarget } from './resource.ts';
23
+ import type { PveRequirements, WithTarget } from './resource-spec.ts';
22
24
  export interface PoolProps extends WithTarget {
23
25
  /** PVE's primary key for a pool. Changing it is a replace, not an update. */
24
26
  poolid: string;
@@ -38,5 +40,12 @@ export declare const ProxmoxPool: import("alchemy").ResourceClass<ProxmoxPool>;
38
40
  export declare const poolCreateForm: (props: PoolProps) => PoolsPostParams;
39
41
  /** PUT body — only `comment`; path carries `poolid`. Matches deprecated `/pools/{poolid}`. */
40
42
  export declare const poolUpdateForm: (props: PoolProps) => Pick<PoolsPoolidPutParams, 'comment'>;
43
+ /** Pool absence is PVE's typed 500, not a catch-all; pve-manager 9.2.11. */
44
+ export declare const readPool: (props: PoolProps) => Effect.Effect<{
45
+ comment: string;
46
+ members: number;
47
+ poolid: string;
48
+ } | undefined, import("@distilled.cloud/caddy").BadGateway | import("@distilled.cloud/caddy").BadRequest | import("@distilled.cloud/caddy").ConfigError | import("@distilled.cloud/caddy").Conflict | Error | import("@distilled.cloud/caddy").Forbidden | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | import("@distilled.cloud/caddy").Locked | import("@distilled.cloud/proxmox/Errors").ParameterVerificationFailed | import("./distilled-pve.ts").PveClusterExhausted | import("./credential-errors.ts").PveCredentialDenied | import("@distilled.cloud/caddy").ServiceUnavailable | import("effect/Cause").TimeoutError | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/caddy").UnprocessableEntity | import("@distilled.cloud/proxmox/Errors").ClientErrors, import("effect/unstable/http/HttpClient").HttpClient>;
49
+ export declare const deletePool: (props: PoolProps) => Effect.Effect<void | pools.DeletePoolResponse, import("@distilled.cloud/caddy").BadGateway | import("@distilled.cloud/caddy").BadRequest | import("@distilled.cloud/caddy").ConfigError | import("@distilled.cloud/caddy").Conflict | Error | import("@distilled.cloud/caddy").Forbidden | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | import("@distilled.cloud/caddy").Locked | import("@distilled.cloud/proxmox/Errors").ParameterVerificationFailed | import("./distilled-pve.ts").PveClusterExhausted | import("./credential-errors.ts").PveCredentialDenied | import("@distilled.cloud/caddy").ServiceUnavailable | import("effect/Cause").TimeoutError | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/caddy").UnprocessableEntity | import("@distilled.cloud/proxmox/Errors").ClientErrors, import("effect/unstable/http/HttpClient").HttpClient>;
41
50
  export declare const ProxmoxPoolProvider: () => import("effect/Layer").Layer<Provider.Provider<ProxmoxPool>, never, import("effect/unstable/http/HttpClient").HttpClient>;
42
51
  //# sourceMappingURL=pool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../src/proxmox/pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAEV,oBAAoB,EACpB,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAe,MAAM,eAAe,CAAC;AAEnF,MAAM,WAAW,SAAU,SAAQ,UAAU;IAC3C,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,4FAA4F;IAC5F,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ,CAC3C,cAAc,EACd,SAAS,EACT,cAAc,EACd,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,eAAO,MAAM,WAAW,8CAAwC,CAAC;AAEjE,mFAAmF;AACnF,eAAO,MAAM,cAAc,UAAW,SAAS,KAAG,eAGhD,CAAC;AAEH,8FAA8F;AAC9F,eAAO,MAAM,cAAc,UAAW,SAAS,KAAG,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAEpF,CAAC;AAoBH,eAAO,MAAM,mBAAmB,iIACiD,CAAC"}
1
+ {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../../src/proxmox/pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,KAAK,MAAM,gCAAgC,CAAC;AAGxD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,KAAK,EAAE,eAAe,EAAW,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAK/E,MAAM,WAAW,SAAU,SAAQ,UAAU;IAC3C,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,4FAA4F;IAC5F,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ,CAC3C,cAAc,EACd,SAAS,EACT,cAAc,EACd,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,eAAO,MAAM,WAAW,8CAAwC,CAAC;AAEjE,mFAAmF;AACnF,eAAO,MAAM,cAAc,UAAW,SAAS,KAAG,eAGhD,CAAC;AAEH,8FAA8F;AAC9F,eAAO,MAAM,cAAc,UAAW,SAAS,KAAG,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAEpF,CAAC;AAsBH,4EAA4E;AAC5E,eAAO,MAAM,QAAQ,UAAW,SAAS;;;;o+BAiBtC,CAAC;AAEJ,eAAO,MAAM,UAAU,UAAW,SAAS,ygCAIxC,CAAC;AAEJ,eAAO,MAAM,mBAAmB,iIAoD7B,CAAC"}
@@ -40,7 +40,7 @@ export declare const same: <T>(declared: T | undefined, live: T) => boolean;
40
40
  * `readUser`/`readGroup` do, so a brand-new declaration can still be created; `readStorageOrFail`
41
41
  * (used by `diff`) does not.
42
42
  */
43
- export declare const readStorageOrFail: (props: StorageProps) => Effect.Effect<typeof UNREADABLE | StorageAttributes, import("@distilled.cloud/caddy").BadGateway | import("@distilled.cloud/caddy").BadRequest | import("@distilled.cloud/caddy").ConfigError | Error | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | import("@distilled.cloud/proxmox/Errors").ParameterVerificationFailed | import("@distilled.cloud/proxmox/Errors").ProxmoxParseError | import("./distilled-pve.ts").PveClusterExhausted | import("@distilled.cloud/caddy").ServiceUnavailable | storage.StorageNotFound | import("effect/Cause").TimeoutError | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/proxmox/Errors").UnknownProxmoxError, import("effect/unstable/http/HttpClient").HttpClient>;
43
+ export declare const readStorageOrFail: (props: StorageProps) => Effect.Effect<typeof UNREADABLE | StorageAttributes, import("@distilled.cloud/caddy").BadGateway | import("@distilled.cloud/caddy").BadRequest | import("@distilled.cloud/caddy").ConfigError | import("@distilled.cloud/caddy").Conflict | Error | import("@distilled.cloud/caddy").Forbidden | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | import("@distilled.cloud/caddy").Locked | import("@distilled.cloud/caddy").NotFound | import("@distilled.cloud/proxmox/Errors").ParameterVerificationFailed | import("@distilled.cloud/proxmox/Errors").ProxmoxParseError | import("./distilled-pve.ts").PveClusterExhausted | import("@distilled.cloud/caddy").ServiceUnavailable | storage.StorageNotFound | import("effect/Cause").TimeoutError | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/proxmox/Errors").UnknownProxmoxError | import("@distilled.cloud/caddy").UnprocessableEntity, import("effect/unstable/http/HttpClient").HttpClient>;
44
44
  /**
45
45
  * ⛔ ONLY `StorageNotFound` MEANS ABSENT. The initial distilled transport swap preserved a
46
46
  * catch-all fold because PVE reports missing objects as HTTP 500. SDK PR 265 now types that
@@ -49,7 +49,7 @@ export declare const readStorageOrFail: (props: StorageProps) => Effect.Effect<t
49
49
  * ★ `readStorageOrFail` remains the strict path used for an already-confirmed state row. This
50
50
  * change narrows cold reads/reconcile without changing that existing drift/diff contract.
51
51
  */
52
- export declare const readStorage: (props: StorageProps) => Effect.Effect<typeof UNREADABLE | StorageAttributes | undefined, import("@distilled.cloud/caddy").BadGateway | import("@distilled.cloud/caddy").BadRequest | import("@distilled.cloud/caddy").ConfigError | Error | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | import("@distilled.cloud/proxmox/Errors").ParameterVerificationFailed | import("@distilled.cloud/proxmox/Errors").ProxmoxParseError | import("./distilled-pve.ts").PveClusterExhausted | import("@distilled.cloud/caddy").ServiceUnavailable | import("effect/Cause").TimeoutError | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/proxmox/Errors").UnknownProxmoxError, import("effect/unstable/http/HttpClient").HttpClient>;
52
+ export declare const readStorage: (props: StorageProps) => Effect.Effect<typeof UNREADABLE | StorageAttributes | undefined, import("@distilled.cloud/caddy").BadGateway | import("@distilled.cloud/caddy").BadRequest | import("@distilled.cloud/caddy").ConfigError | import("@distilled.cloud/caddy").Conflict | Error | import("@distilled.cloud/caddy").Forbidden | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | import("@distilled.cloud/caddy").Locked | import("@distilled.cloud/caddy").NotFound | import("@distilled.cloud/proxmox/Errors").ParameterVerificationFailed | import("@distilled.cloud/proxmox/Errors").ProxmoxParseError | import("./distilled-pve.ts").PveClusterExhausted | import("@distilled.cloud/caddy").ServiceUnavailable | import("effect/Cause").TimeoutError | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/proxmox/Errors").UnknownProxmoxError | import("@distilled.cloud/caddy").UnprocessableEntity, import("effect/unstable/http/HttpClient").HttpClient>;
53
53
  /** `read`/`reconcile` return `Attributes | undefined`; only `diff` tells `UNREADABLE` apart. */
54
54
  export declare const dropUnreadable: (live: StorageAttributes | Unreadable | undefined) => StorageAttributes | undefined;
55
55
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"storage-wire.d.ts","sourceRoot":"","sources":["../../src/proxmox/storage-wire.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,OAAO,MAAM,kCAAkC,CAAC;AAC5D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAoB,MAAM,sBAAsB,CAAC;AAGrF,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,6FAA6F;IAC7F,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAmBD,eAAO,MAAM,QAAQ,aAAc,MAAM,GAAG,SAAS,QAAQ,MAAM,YACN,CAAC;AAE9D,eAAO,MAAM,IAAI,GAAI,CAAC,YAAY,CAAC,GAAG,SAAS,QAAQ,CAAC,YACX,CAAC;AAwB9C;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,iBAAiB,UAAW,YAAY,63BAGyC,CAAC;AAE/F;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,UAAW,YAAY,+2BAG5C,CAAC;AAEJ,gGAAgG;AAChG,eAAO,MAAM,cAAc,SAAU,iBAAiB,GAAG,UAAU,GAAG,SAAS,kCACvC,CAAC;AAEzC;;;GAGG;AACH,eAAO,MAAM,OAAO,eAAgB,iBAAiB,SAAS,YAAY,YAOjC,CAAC"}
1
+ {"version":3,"file":"storage-wire.d.ts","sourceRoot":"","sources":["../../src/proxmox/storage-wire.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,OAAO,MAAM,kCAAkC,CAAC;AAC5D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAoB,MAAM,sBAAsB,CAAC;AAGrF,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,6FAA6F;IAC7F,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAmBD,eAAO,MAAM,QAAQ,aAAc,MAAM,GAAG,SAAS,QAAQ,MAAM,YACN,CAAC;AAE9D,eAAO,MAAM,IAAI,GAAI,CAAC,YAAY,CAAC,GAAG,SAAS,QAAQ,CAAC,YACX,CAAC;AAwB9C;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,iBAAiB,UAAW,YAAY,mmCAGyC,CAAC;AAE/F;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,UAAW,YAAY,qlCAG5C,CAAC;AAEJ,gGAAgG;AAChG,eAAO,MAAM,cAAc,SAAU,iBAAiB,GAAG,UAAU,GAAG,SAAS,kCACvC,CAAC;AAEzC;;;GAGG;AACH,eAAO,MAAM,OAAO,eAAgB,iBAAiB,SAAS,YAAY,YAOjC,CAAC"}
@@ -29,7 +29,7 @@ export declare const matches: (attributes: UserAttributes, props: UserProps) =>
29
29
  * `PveClusterExhausted`, then silently folded to "absent" by the old `orElseSucceed`, forcing a
30
30
  * false `update` on every account.
31
31
  */
32
- export declare const readUserOrFail: (props: UserProps) => Effect.Effect<typeof UNREADABLE | UserAttributes, import("@distilled.cloud/caddy").BadGateway | import("@distilled.cloud/caddy").BadRequest | import("@distilled.cloud/caddy").ConfigError | Error | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | import("@distilled.cloud/proxmox/Errors").ParameterVerificationFailed | import("@distilled.cloud/proxmox/Errors").ProxmoxParseError | import("./distilled-pve.ts").PveClusterExhausted | import("@distilled.cloud/caddy").ServiceUnavailable | import("effect/Cause").TimeoutError | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/proxmox/Errors").UnknownProxmoxError | access.UserNotFound, import("effect/unstable/http/HttpClient").HttpClient>;
32
+ export declare const readUserOrFail: (props: UserProps) => Effect.Effect<typeof UNREADABLE | UserAttributes, import("@distilled.cloud/caddy").BadGateway | import("@distilled.cloud/caddy").BadRequest | import("@distilled.cloud/caddy").ConfigError | import("@distilled.cloud/caddy").Conflict | Error | import("@distilled.cloud/caddy").Forbidden | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | import("@distilled.cloud/caddy").Locked | import("@distilled.cloud/caddy").NotFound | import("@distilled.cloud/proxmox/Errors").ParameterVerificationFailed | import("@distilled.cloud/proxmox/Errors").ProxmoxParseError | import("./distilled-pve.ts").PveClusterExhausted | import("@distilled.cloud/caddy").ServiceUnavailable | import("effect/Cause").TimeoutError | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/proxmox/Errors").UnknownProxmoxError | import("@distilled.cloud/caddy").UnprocessableEntity | access.UserNotFound, import("effect/unstable/http/HttpClient").HttpClient>;
33
33
  /**
34
34
  * ⛔ ONLY `UserNotFound` MEANS ABSENT. The initial distilled transport swap preserved a
35
35
  * catch-all fold because PVE reports missing objects as HTTP 500. SDK PR 265 now types that
@@ -38,7 +38,7 @@ export declare const readUserOrFail: (props: UserProps) => Effect.Effect<typeof
38
38
  * ★ `readUserOrFail` remains the strict path used for an already-confirmed state row. This
39
39
  * change narrows cold reads/reconcile without changing that existing drift/diff contract.
40
40
  */
41
- export declare const readUser: (props: UserProps) => Effect.Effect<typeof UNREADABLE | UserAttributes | undefined, import("@distilled.cloud/caddy").BadGateway | import("@distilled.cloud/caddy").BadRequest | import("@distilled.cloud/caddy").ConfigError | Error | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | import("@distilled.cloud/proxmox/Errors").ParameterVerificationFailed | import("@distilled.cloud/proxmox/Errors").ProxmoxParseError | import("./distilled-pve.ts").PveClusterExhausted | import("@distilled.cloud/caddy").ServiceUnavailable | import("effect/Cause").TimeoutError | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/proxmox/Errors").UnknownProxmoxError, import("effect/unstable/http/HttpClient").HttpClient>;
41
+ export declare const readUser: (props: UserProps) => Effect.Effect<typeof UNREADABLE | UserAttributes | undefined, import("@distilled.cloud/caddy").BadGateway | import("@distilled.cloud/caddy").BadRequest | import("@distilled.cloud/caddy").ConfigError | import("@distilled.cloud/caddy").Conflict | Error | import("@distilled.cloud/caddy").Forbidden | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | import("@distilled.cloud/caddy").Locked | import("@distilled.cloud/caddy").NotFound | import("@distilled.cloud/proxmox/Errors").ParameterVerificationFailed | import("@distilled.cloud/proxmox/Errors").ProxmoxParseError | import("./distilled-pve.ts").PveClusterExhausted | import("@distilled.cloud/caddy").ServiceUnavailable | import("effect/Cause").TimeoutError | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/proxmox/Errors").UnknownProxmoxError | import("@distilled.cloud/caddy").UnprocessableEntity, import("effect/unstable/http/HttpClient").HttpClient>;
42
42
  /** `read`/`reconcile` return `Attributes | undefined`; only `diff` tells `UNREADABLE` apart. */
43
43
  export declare const dropUnreadable: (live: UserAttributes | Unreadable | undefined) => UserAttributes | undefined;
44
44
  //# sourceMappingURL=user-wire.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"user-wire.d.ts","sourceRoot":"","sources":["../../src/proxmox/user-wire.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,MAAM,MAAM,iCAAiC,CAAC;AAC1D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAoB,MAAM,sBAAsB,CAAC;AAGrF,eAAO,MAAM,WAAW,2BAA2B,CAAC;AACpD,eAAO,MAAM,WAAW,mCAAmC,CAAC;AA2D5D,eAAO,MAAM,UAAU,UAAW,SAAS,KAAG,MAAM,CAAC,uBAGnD,CAAC;AAEH,eAAO,MAAM,UAAU,UAAW,SAAS,KAAG,MAAM,CAAC,oBAGnD,CAAC;AAoBH;;;GAGG;AACH,eAAO,MAAM,OAAO,eAAgB,cAAc,SAAS,SAAS,YAOF,CAAC;AAEnE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,UAAW,SAAS,s3BAG+C,CAAC;AAE/F;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,UAAW,SAAS,42BACqD,CAAC;AAE/F,gGAAgG;AAChG,eAAO,MAAM,cAAc,SAAU,cAAc,GAAG,UAAU,GAAG,SAAS,+BACpC,CAAC"}
1
+ {"version":3,"file":"user-wire.d.ts","sourceRoot":"","sources":["../../src/proxmox/user-wire.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,MAAM,MAAM,iCAAiC,CAAC;AAC1D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAoB,MAAM,sBAAsB,CAAC;AAGrF,eAAO,MAAM,WAAW,2BAA2B,CAAC;AACpD,eAAO,MAAM,WAAW,mCAAmC,CAAC;AA2D5D,eAAO,MAAM,UAAU,UAAW,SAAS,KAAG,MAAM,CAAC,uBAGnD,CAAC;AAEH,eAAO,MAAM,UAAU,UAAW,SAAS,KAAG,MAAM,CAAC,oBAGnD,CAAC;AAoBH;;;GAGG;AACH,eAAO,MAAM,OAAO,eAAgB,cAAc,SAAS,SAAS,YAOF,CAAC;AAEnE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,UAAW,SAAS,4lCAG+C,CAAC;AAE/F;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,UAAW,SAAS,klCACqD,CAAC;AAE/F,gGAAgG;AAChG,eAAO,MAAM,cAAc,SAAU,cAAc,GAAG,UAAU,GAAG,SAAS,+BACpC,CAAC"}
@@ -51,7 +51,7 @@ export declare const leafDevices: (children: unknown) => string[];
51
51
  * `SETTLE_ATTEMPTS` (zfs-pool-form.ts's own ⚠️ on that); `readPoolOrFail` (used by `diff`) does
52
52
  * not fold it, so a genuine transient failure there propagates and fails the plan loudly instead.
53
53
  */
54
- export declare const readPoolOrFail: (props: ZfsPoolProps) => Effect.Effect<typeof UNREADABLE | ZfsPoolAttributes | undefined, import("@distilled.cloud/caddy").BadGateway | import("@distilled.cloud/caddy").BadRequest | import("@distilled.cloud/caddy").ConfigError | Error | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | import("@distilled.cloud/proxmox/Errors").ParameterVerificationFailed | import("@distilled.cloud/proxmox/Errors").ProxmoxParseError | import("./distilled-pve.ts").PveClusterExhausted | import("@distilled.cloud/caddy").ServiceUnavailable | import("effect/Cause").TimeoutError | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/proxmox/Errors").UnknownProxmoxError, import("effect/unstable/http/HttpClient").HttpClient>;
54
+ export declare const readPoolOrFail: (props: ZfsPoolProps) => Effect.Effect<typeof UNREADABLE | ZfsPoolAttributes | undefined, import("@distilled.cloud/caddy").BadGateway | import("@distilled.cloud/caddy").BadRequest | import("@distilled.cloud/caddy").ConfigError | import("@distilled.cloud/caddy").Conflict | Error | import("@distilled.cloud/caddy").Forbidden | import("@distilled.cloud/caddy").GatewayTimeout | import("effect/unstable/http/HttpClientError").HttpClientError | import("@distilled.cloud/caddy").InternalServerError | import("@distilled.cloud/caddy").Locked | import("@distilled.cloud/caddy").NotFound | import("@distilled.cloud/proxmox/Errors").ParameterVerificationFailed | import("@distilled.cloud/proxmox/Errors").ProxmoxParseError | import("./distilled-pve.ts").PveClusterExhausted | import("@distilled.cloud/caddy").ServiceUnavailable | import("effect/Cause").TimeoutError | import("@distilled.cloud/caddy").TooManyRequests | import("@distilled.cloud/caddy").Unauthorized | import("@distilled.cloud/proxmox/Errors").UnknownProxmoxError | import("@distilled.cloud/caddy").UnprocessableEntity, import("effect/unstable/http/HttpClient").HttpClient>;
55
55
  /**
56
56
  * ⛔ FOLDS A GENUINE READ FAILURE TO `undefined` TOO, AND ONLY `createPool`'s settle-poll AND
57
57
  * `read`/`reconcile` MAY USE IT — user.ts's `readUser` has the full reasoning. Safe here because
@@ -1 +1 @@
1
- {"version":3,"file":"zfs-pool-wire.d.ts","sourceRoot":"","sources":["../../src/proxmox/zfs-pool-wire.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAoB,MAAM,sBAAsB,CAAC;AAGrF;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,aAAc,OAAO,KAAG,MAAM,EAO9C,CAAC;AAmBT;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,cAAc,UAAW,YAAY,+2BAe/C,CAAC;AAEJ;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ,UAAW,YAAY,kIACuB,CAAC;AAEpE,sGAAsG;AACtG,eAAO,MAAM,cAAc,SAAU,iBAAiB,GAAG,UAAU,GAAG,SAAS,kCACvC,CAAC;AAEzC;;;;;;;;GAQG"}
1
+ {"version":3,"file":"zfs-pool-wire.d.ts","sourceRoot":"","sources":["../../src/proxmox/zfs-pool-wire.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAoB,MAAM,sBAAsB,CAAC;AAGrF;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,aAAc,OAAO,KAAG,MAAM,EAO9C,CAAC;AAmBT;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,cAAc,UAAW,YAAY,qlCAe/C,CAAC;AAEJ;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ,UAAW,YAAY,kIACuB,CAAC;AAEpE,sGAAsG;AACtG,eAAO,MAAM,cAAc,SAAU,iBAAiB,GAAG,UAAU,GAAG,SAAS,kCACvC,CAAC;AAEzC;;;;;;;;GAQG"}
@@ -0,0 +1,22 @@
1
+ # Alchemy changelog archive
2
+
3
+ Release history before 0.37.1, preserved in order. See the [current changelog](../../CHANGELOG.md).
4
+
5
+ - [0.37.0](./archive-01.md)
6
+ - [0.37.0 to 0.35.0](./archive-02.md)
7
+ - [0.35.0 to 0.34.0](./archive-03.md)
8
+ - [0.34.0 to 0.33.0](./archive-04.md)
9
+ - [0.33.0 to 0.32.0](./archive-05.md)
10
+ - [0.32.0 to 0.31.1](./archive-06.md)
11
+ - [0.31.1 to 0.29.1](./archive-07.md)
12
+ - [0.29.1 to 0.29.0](./archive-08.md)
13
+ - [0.29.0 to 0.27.3](./archive-09.md)
14
+ - [0.27.3 to 0.24.0](./archive-10.md)
15
+ - [0.24.0 to 0.20.0](./archive-11.md)
16
+ - [0.20.0 to 0.16.1](./archive-12.md)
17
+ - [0.16.1 to 0.15.0](./archive-13.md)
18
+ - [0.15.0 to 0.14.0](./archive-14.md)
19
+ - [0.14.0 to 0.10.0](./archive-15.md)
20
+ - [0.10.0 to 0.6.0](./archive-16.md)
21
+ - [0.6.0 to 0.1.1](./archive-17.md)
22
+ - [0.1.1 to 0.1.0](./archive-18.md)
@@ -0,0 +1,176 @@
1
+ # Alchemy changelog archive 1
2
+
3
+ [Current changelog](../../CHANGELOG.md) · [Archive index](./README.md)
4
+
5
+ ## 0.37.0
6
+
7
+ ### Minor Changes
8
+
9
+ - [#262](https://github.com/taslabs-net/homeflare-kit/pull/262) [`ca1a558`](https://github.com/taslabs-net/homeflare-kit/commit/ca1a558db9101a8381dff57ba80f4aafcd01ae61) Thanks [@taslabs-net](https://github.com/taslabs-net)! - New `argocd/*` family — `Argocd.Repository`, `Argocd.RepoCreds` and `Argocd.Cluster`, on
10
+ `@distilled.cloud/argocd@1.0.0-rc.12` (measured published, matching the kit's own `effect`/core
11
+ pins — added as a direct peer dependency, the same shape as `forgejo`/`discord`). Built ahead of
12
+ need, per Tim's "we are using talos on pve once we get things settled ... i thought we are using
13
+ argocd, i wanted it on the radar" and "even if we don't use it yet but we know we will" — **no
14
+ Talos-on-PVE cluster and no Argo CD instance exist on the estate yet**; every test runs against a
15
+ fake, never a real server.
16
+
17
+ **Upstream check first (decision 49).** `alchemy-run/alchemy` v2.0.0-beta.79 ships no ArgoCD
18
+ provider at all — the only two `argocd` hits in the whole repo are an unrelated AWS EKS add-on
19
+ capability name in a JSDoc example. So there is nothing upstream to duplicate.
20
+
21
+ **The REST-vs-CRD split is the actual design decision, and it is why `Application`/`AppProject`
22
+ are deliberately NOT in this family.** Both are real Kubernetes CRDs (`argoproj.io/v1alpha1`,
23
+ their own versioned OpenAPI schema, listable with plain `kubectl`) — the upstream-correct owner is
24
+ Alchemy's own `Kubernetes.Manifest` (`src/Kubernetes/Manifest.ts`, which already documents a
25
+ "Custom resource (CRD)" example), not a house REST wrapper around the same object. Repository,
26
+ RepoCreds and Cluster are different: Argo CD's own storage for them is a `Secret` labeled with its
27
+ own private convention (`argocd.argoproj.io/secret-type: repository|repo-creds|cluster`) — not a
28
+ published Kubernetes API type, so the REST SDK is the only correct owner. Full reasoning, citations
29
+ and worked `Kubernetes.Manifest` examples for `Application`/`AppProject`:
30
+ `packages/alchemy/docs/argocd.md` and `docs/argocd-kubernetes.md`.
31
+
32
+ **A real, measured SDK-gap check that came back clean, unlike Discord's.** No `patches/` directory
33
+ exists for `packages/argocd` in distilled (homeflare/base) — every generated operation's own
34
+ declared `errors` array is just `[UnknownArgocdError]`. That looks like Discord's documented gap
35
+ (`docs/discord.md#sdk-gaps`) at first read. It is not: `protocol.ts` types every operation's shared
36
+ error channel from `API_ERRORS` (the full `HTTP_STATUS_MAP` set, not the narrower
37
+ `DEFAULT_ERRORS` Discord's channel is built from), and `core/protocol-rest.ts#decode` maps any
38
+ 4xx status through `HTTP_STATUS_MAP` unconditionally after the per-op typed matchers, regardless
39
+ of what the operation itself declared. `catchTag('NotFound', ...)` works correctly today — proven
40
+ against the real protocol and a fake 404/401/403 in `repository.test.ts`, `repo-creds.test.ts` and
41
+ `cluster.test.ts`, not asserted by reading the source alone. No distilled patch was needed.
42
+
43
+ **Secrets never in state.** Every credential field (a repo's password/SSH key/bearer token/TLS
44
+ client key, a cluster's password/bearer token/TLS client key) is a prop typed `FromEnv`
45
+ (`../secrets/write-only.ts`), resolved from the deploying process's own environment at call time
46
+ and refused with a typed domain error when unset — never a literal value on a stack file, an
47
+ attribute, or in Alchemy's state store. No drift detection on those fields, the same
48
+ simplification `forgejo/org-actions-secrets.ts` already makes for the identical problem (Argo CD's
49
+ `Get`/`List` never returns them back): written once on create, rotated by destroy-then-create.
50
+
51
+ **Shape.** One shared engine (`resource.ts`) — a near-verbatim copy of `forgejo/resource.ts`, since
52
+ both SDKs are plain bearer-REST with a genuine typed `NotFound`. `reconcile` is a single upsert
53
+ call (every `Create*` operation this family calls takes `upsert: true` as a query parameter,
54
+ converging create-or-update in one request — no separate `Update*` path to wire). No `adopt(true)`/
55
+ `Unowned` wrapping, mirroring forgejo's own choice rather than discord's/netbox's marker.
56
+
57
+ **Tests**: 20 cases across the three resources, covering a live decode, a 404 folding to absent, a
58
+ 401/403 propagating (never folded), idempotent delete (no DELETE call against an already-absent
59
+ object), and the write-only credential refusal/resolution path — all against `fake-argocd.ts`, a
60
+ loopback fake exercising the real distilled protocol, never a real Argo CD server.
61
+
62
+ ### Patch Changes
63
+
64
+ - [#259](https://github.com/taslabs-net/homeflare-kit/pull/259) [`4302d28`](https://github.com/taslabs-net/homeflare-kit/commit/4302d28be200a04aa7b367a8a579134f864cd414) Thanks [@taslabs-net](https://github.com/taslabs-net)! - The `proxmox/*` family's Ceph sub-area, second of two PRs for 2c (decision 43's walk-down): migrates
65
+ `Proxmox.CephDaemon` (mon/mgr/mds) and `Proxmox.CephOsd` fully onto `@distilled.cloud/proxmox`.
66
+ Neither family had a forked-worker settle loop or an envelope-stripping dependency, so unlike
67
+ `Proxmox.NetworkApply`/`Proxmox.CephFs`'s delete, there is no protocol-level reason to leave either
68
+ on `client.ts` — both move completely.
69
+
70
+ **`Proxmox.CephDaemon`** replaces the generic `pveOperations`/`pveHandlers` factory (which cannot
71
+ run a distilled typed operation) with hand-written `read`/`diff`/`reconcile`/`delete`, matching the
72
+ factory's own pre-migration shape exactly: `matches` was always `() => true` and there is no PUT
73
+ for any of the three kinds, so a live daemon is always `noop` and drift is always `update`, never a
74
+ diff no write could satisfy. `nodes.updateNodeCephMon`/`Mgr`/`Mds` are distilled's generator
75
+ misnaming the create a POST "update" (checked against each one's `T.Http` annotation before
76
+ trusting the name); `nodes.listNodeCephMon`/`Mgr`/`Mds` and `nodes.deleteNodeCephMon`/`Mgr`/`Mds`
77
+ are the read and delete. One field rename: mon's `mon-address` maps to distilled's `mon_address`
78
+ (`T.Body("mon-address")`, confirmed against the schema) — the same one-key pattern
79
+ node-network-form.ts's `RENAMED` table carries for three fields.
80
+
81
+ **`Proxmox.CephOsd`** keeps its own pre-migration read behaviour exactly: `readOsd` (ceph-osd-tree.ts)
82
+ still has NO `Effect.orElseSucceed` — the tree endpoint is a collection that always exists while
83
+ Ceph is installed, so a read failure is never "the OSD is gone" and must propagate, never fold. This
84
+ is the one migrated Ceph family that does NOT match the single-fold shape `Proxmox.CephPool`/
85
+ `Proxmox.CephDaemon` carry, because it never had it before this PR either. `nodes.getNodeCephOsd`
86
+ (the tree), `nodes.createNodeCephOsd` and `nodes.deleteNodeCephOsd` map 1:1 to the existing forms.
87
+
88
+ **Both families keep every existing refusal byte-for-byte.** `Proxmox.CephOsd`'s create and delete
89
+ remain unreachable through this package's own credential — PVE registers `createosd`/`destroyosd`
90
+ with NO permissions block at all (root@pam only), confirmed again against distilled's own generated
91
+ schema, which changes nothing about that restriction. `Proxmox.CephDaemon`'s destroy still runs
92
+ against the daemon's own id path, never the collection `read` uses, avoiding the 501-that-looks-
93
+ like-a-permission-problem the pre-migration header already warned about.
94
+
95
+ **One pre-existing, out-of-scope finding, carried forward exactly rather than fixed here:**
96
+ `Proxmox.CephOsd`'s `destroyOsd` sends its `cleanup` flag as a request BODY on a DELETE, on
97
+ `client.ts` before this PR and on distilled after it alike — `client.ts`'s own `buildRequest` puts
98
+ `form` in the body for every HTTP method, and distilled's generated `DeleteNodeCephOsdRequest`
99
+ carries no `T.Query()` annotation on `cleanup` either, so it defaults to the same place. PVE's own
100
+ server (measured from `AnyEvent.pm`, the same fact `Proxmox.CephFs`'s delete was kept off distilled
101
+ for) never reads a body on DELETE — so `cleanup=1` was ALREADY silently ignored by the live cluster
102
+ before this migration. This is not a new regression, so it is not a reason to keep `destroyOsd` off
103
+ distilled the way `Proxmox.CephFs`'s delete was — but it is a real bug, unrelated to this PR, flagged
104
+ separately for its own fix (move `cleanup` into the query string, the way `destroyPath` in
105
+ ceph-fs-wire.ts already does for CephFs's own flags). It has zero live impact today either way,
106
+ since the whole DELETE 403s for this package's credential regardless of `cleanup`.
107
+
108
+ **One adversarial-review finding, fixed.** The hand-written `reconcile` returned early on
109
+ `if (live !== undefined) return live;` BEFORE calling `guardWrite` — the pre-migration factory
110
+ (`pveOperations.reconcile`, resource.ts) ran its create/update guard unconditionally right after
111
+ the read, because `reconcile` also runs for an ADOPTED row with no fresh `diff` first (Plan.ts
112
+ forces it after the probe even when `diff` said noop). Inert today, since `diff` guards every
113
+ normal plan — but a real gap for any caller that invokes `reconcile` directly (a resumed apply
114
+ from persisted state, a verify/adopt harness). Fixed to match `node-network.ts`'s own `reconcile`:
115
+ `guardWrite` now runs immediately after the read, unconditionally. `reconcileDaemon` is exported
116
+ so a test can call it directly, bypassing `diff` the same way the gap would have been reached.
117
+
118
+ **A related, separate finding, NOT fixed here — recorded to `decisions.md`'s open items.** Proving
119
+ the guard fix with an actual refused value turned up that `constraints.ts`'s `violations()` never
120
+ checks a bare `format` rule: `mon-address`'s own vendor entry is `{"format":"ip-list",
121
+ "type":"string"}` with no `pattern`, and checked directly, `formViolations` returns `[]` for a
122
+ malformed address. `mds`/`mgr`'s create endpoints carry EMPTY constraint tables too. About 105
123
+ parameters across this whole package declare a `format`; none are enforced. This is a real,
124
+ pre-existing gap unrelated to distilled or this migration — the new test instead proves the
125
+ STRUCTURAL property (`guardWrite`, and the `createForm` it must evaluate, still run on the
126
+ adopted-row path, via a field getter that only `createForm` reads on that path), confirmed to fail
127
+ without the ordering fix by temporarily reverting it and re-running.
128
+
129
+ **New tests**, proven against a deliberately broken implementation before landing:
130
+ `ceph-daemon-write.test.ts` (a new mon POSTs `mon-address` as `mon_address` and reads the collection
131
+ back; a new mds POSTs `hotstandby`; `RemovalPolicy.destroy()` then undeclaring a mgr sends exactly
132
+ one DELETE — confirmed to fail without the real `deleteDaemon` call by temporarily stubbing it out)
133
+ and `ceph-osd-write.test.ts` (a new OSD POSTs `dev` and `crush-device-class` correctly and reads the
134
+ new leaf back by id — this test can never run against the real cluster, since the write it drives is
135
+ root-only, but it is the only way to catch a wire-translation bug a real deploy would never reach far
136
+ enough to expose).
137
+
138
+ **Expected after this releases and the consumer bumps:** no live plan change for either family — C1's
139
+ read-role lease could always read the live Ceph daemons and OSDs cleanly, so this is a transport
140
+ migration on tested paths, not a behaviour change.
141
+
142
+ - [#257](https://github.com/taslabs-net/homeflare-kit/pull/257) [`5e1e1b7`](https://github.com/taslabs-net/homeflare-kit/commit/5e1e1b7dfd51cff7664c74284287e44e9caa9f3c) Thanks [@taslabs-net](https://github.com/taslabs-net)! - The `proxmox/*` family's Ceph sub-area, first PR of two (decision 43's serial proxmox walk-down,
143
+ 2c — the four Ceph families, split pool+fs first, daemon+osd after): migrates `Proxmox.CephPool`
144
+ fully onto `@distilled.cloud/proxmox`, and migrates `Proxmox.CephFs`'s READ and CREATE onto it
145
+ while its DELETE stays on `client.ts` for a measured protocol reason.
146
+
147
+ **Every existing refusal and guard survives byte-for-byte — this is a transport swap, not a
148
+ redesign.** Both families keep the exact single-fold read shape they always had
149
+ (`Effect.orElseSucceed` after every failure, no `output`-branching): that is NOT the newer
150
+ dual-path pattern `Proxmox.NodeNetwork`/`Proxmox.ZfsPool`/`Proxmox.Storage` carry, and it is not
151
+ upgraded to it here — this PR's own rule is behaviour surviving unchanged, not gaining the newer
152
+ pattern along the way. Both `ceph-pool-wire.ts` and `ceph-fs-distilled.ts` say so in their own
153
+ headers, including the same-day latent gap this leaves (a refused OpenBao mint still folds to
154
+ "absent" on both families, the cries-wolf class already fixed elsewhere) — noted, not fixed, since
155
+ fixing it is a behaviour change this PR's rules do not ask for.
156
+
157
+ **`Proxmox.CephPool`: the PG-merge guard, and the absence signal, both measured live.** `GET
158
+ /nodes/{node}/ceph/pool/{name}/status` on a name with no pool answers a generic HTTP 500 (measured
159
+ against TB4 `n2`, 2026-09-24, read-role, read-only probe:
160
+ `{"data":null,"message":"error with 'osd pool get': mon_cmd failed - unrecognized pool
161
+ '<name>'\n"}`) — not a parsed field like `Proxmox.NodeNetwork`'s 400, so `confirmAbsent`
162
+ (ceph-pool-settle.ts) still asks the SECOND question — does the index list this name — before a
163
+ create is allowed to run, exactly as before. `confirmAbsent` now calls distilled's
164
+ `listNodeCephPool`; the settle loop (waiting out a forked worker) never used PVE's task-status
165
+ endpoint at all — it re-polls the pool's own status, so it needed no `Task.awaitTask` and carries
166
+ no NEW protocol risk. `createNodeCephPool`/`putNodeCephPool`/`deleteNodeCephPool` map 1:1 to the
167
+ existing form (no field renames this family needed).
168
+
169
+ **`Proxmox.CephFs`: reads and create move; delete does not, for a measured reason.** Distilled
170
+ types `DeleteNodeCephFsRequest`'s `remove_pools`/`remove_storages` as request-BODY fields
171
+ (`T.Body`) — checked directly against its generated schema. This family's own header already
172
+ carries the measured fact (from PVE's own `AnyEvent.pm`) that PVE's server reads a request body
173
+ only on PUT/POST; a DELETE's body is silently discarded, no error raised anywhere. Sending those
174
+ two safety flags through distilled's generated delete op as-is would silently drop them — the same
175
+ class of protocol gap `Proxmox.NetworkApply` was kept off distilled for. `destroyFs` therefore
176
+ stays on `client.ts`, unmigrated, in `ceph-fs-wire.ts`.