@homeflare/alchemy 0.45.0 → 0.46.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 (78) hide show
  1. package/dist/proxmox/generated/constraints/index.d.ts +1 -1
  2. package/dist/proxmox/generated/constraints/pve-access.d.ts +1 -1
  3. package/dist/proxmox/generated/constraints/pve-cluster-backup.d.ts +1 -1
  4. package/dist/proxmox/generated/constraints/pve-cluster-ceph.d.ts +1 -1
  5. package/dist/proxmox/generated/constraints/pve-cluster-firewall.d.ts +1 -1
  6. package/dist/proxmox/generated/constraints/pve-cluster-ha.d.ts +1 -1
  7. package/dist/proxmox/generated/constraints/pve-cluster-metrics.d.ts +1 -1
  8. package/dist/proxmox/generated/constraints/pve-cluster-notifications.d.ts +1 -1
  9. package/dist/proxmox/generated/constraints/pve-cluster-replication.d.ts +1 -1
  10. package/dist/proxmox/generated/constraints/pve-cluster-sdn.d.ts +1 -1
  11. package/dist/proxmox/generated/constraints/pve-nodes-ceph.d.ts +1 -1
  12. package/dist/proxmox/generated/constraints/pve-nodes-disks.d.ts +1 -1
  13. package/dist/proxmox/generated/constraints/pve-nodes-lxc.d.ts +1 -1
  14. package/dist/proxmox/generated/constraints/pve-nodes-network.d.ts +1 -1
  15. package/dist/proxmox/generated/constraints/pve-nodes-qemu.d.ts +1 -1
  16. package/dist/proxmox/generated/constraints/pve-nodes-qemu.d.ts.map +1 -1
  17. package/dist/proxmox/generated/constraints/pve-nodes-storage.d.ts +1 -1
  18. package/dist/proxmox/generated/constraints/pve-pools.d.ts +1 -1
  19. package/dist/proxmox/generated/constraints/pve-storage.d.ts +1 -1
  20. package/dist/proxmox/index.d.ts +1 -0
  21. package/dist/proxmox/index.d.ts.map +1 -1
  22. package/dist/proxmox/index.js +283 -130
  23. package/dist/proxmox/index.js.map +31 -27
  24. package/dist/proxmox/qemu-dns.d.ts +2 -0
  25. package/dist/proxmox/qemu-dns.d.ts.map +1 -0
  26. package/dist/proxmox/qemu-errors.d.ts +1 -0
  27. package/dist/proxmox/qemu-errors.d.ts.map +1 -1
  28. package/dist/proxmox/qemu-form.d.ts.map +1 -1
  29. package/dist/proxmox/qemu-judge.d.ts.map +1 -1
  30. package/dist/proxmox/qemu-lifecycle.d.ts +15 -10
  31. package/dist/proxmox/qemu-lifecycle.d.ts.map +1 -1
  32. package/dist/proxmox/qemu-props.d.ts +10 -0
  33. package/dist/proxmox/qemu-props.d.ts.map +1 -1
  34. package/dist/proxmox/qemu-resize.d.ts +10 -0
  35. package/dist/proxmox/qemu-resize.d.ts.map +1 -0
  36. package/dist/proxmox/qemu-size.d.ts +20 -0
  37. package/dist/proxmox/qemu-size.d.ts.map +1 -0
  38. package/dist/proxmox/qemu-spec.d.ts +25 -0
  39. package/dist/proxmox/qemu-spec.d.ts.map +1 -0
  40. package/dist/verify/fake-engine.d.ts +4 -2
  41. package/dist/verify/fake-engine.d.ts.map +1 -1
  42. package/docs/proxmox-qemu-resize.md +62 -0
  43. package/package.json +1 -1
  44. package/src/proxmox/generated/constraints/index.ts +1 -1
  45. package/src/proxmox/generated/constraints/pve-access.ts +1 -1
  46. package/src/proxmox/generated/constraints/pve-cluster-backup.ts +1 -1
  47. package/src/proxmox/generated/constraints/pve-cluster-ceph.ts +1 -1
  48. package/src/proxmox/generated/constraints/pve-cluster-firewall.ts +1 -1
  49. package/src/proxmox/generated/constraints/pve-cluster-ha.ts +1 -1
  50. package/src/proxmox/generated/constraints/pve-cluster-metrics.ts +1 -1
  51. package/src/proxmox/generated/constraints/pve-cluster-notifications.ts +1 -1
  52. package/src/proxmox/generated/constraints/pve-cluster-replication.ts +1 -1
  53. package/src/proxmox/generated/constraints/pve-cluster-sdn.ts +1 -1
  54. package/src/proxmox/generated/constraints/pve-nodes-ceph.ts +1 -1
  55. package/src/proxmox/generated/constraints/pve-nodes-disks.ts +1 -1
  56. package/src/proxmox/generated/constraints/pve-nodes-lxc.ts +1 -1
  57. package/src/proxmox/generated/constraints/pve-nodes-network.ts +1 -1
  58. package/src/proxmox/generated/constraints/pve-nodes-qemu.ts +6 -1
  59. package/src/proxmox/generated/constraints/pve-nodes-storage.ts +1 -1
  60. package/src/proxmox/generated/constraints/pve-pools.ts +1 -1
  61. package/src/proxmox/generated/constraints/pve-storage.ts +1 -1
  62. package/src/proxmox/index.ts +1 -0
  63. package/src/proxmox/qemu-dns.test.ts +73 -0
  64. package/src/proxmox/qemu-dns.ts +32 -0
  65. package/src/proxmox/qemu-errors.ts +1 -0
  66. package/src/proxmox/qemu-form.ts +6 -3
  67. package/src/proxmox/qemu-judge.ts +2 -1
  68. package/src/proxmox/qemu-lifecycle.ts +28 -47
  69. package/src/proxmox/qemu-props.ts +14 -2
  70. package/src/proxmox/qemu-resize-lock.test.ts +121 -0
  71. package/src/proxmox/qemu-resize-recovery.test.ts +81 -0
  72. package/src/proxmox/qemu-resize.test.ts +199 -0
  73. package/src/proxmox/qemu-resize.ts +86 -0
  74. package/src/proxmox/qemu-size.test.ts +64 -0
  75. package/src/proxmox/qemu-size.ts +95 -0
  76. package/src/proxmox/qemu-spec.ts +44 -0
  77. package/src/proxmox/qemu-volume.ts +5 -5
  78. package/src/verify/fake-engine.ts +6 -3
@@ -0,0 +1,2 @@
1
+ export declare const dnsRefusals: (nameserver: unknown) => string[];
2
+ //# sourceMappingURL=qemu-dns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qemu-dns.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-dns.ts"],"names":[],"mappings":"AAuBA,eAAO,MAAM,WAAW,eAAgB,OAAO,KAAG,MAAM,EAQvD,CAAC"}
@@ -1,5 +1,6 @@
1
1
  /** A QEMU write or observation this provider will not turn into a create or a delete. */
2
2
  export declare class QemuRefusedError extends Error {
3
+ readonly _tag = "QemuRefusedError";
3
4
  constructor(message: string);
4
5
  }
5
6
  //# sourceMappingURL=qemu-errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"qemu-errors.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-errors.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF"}
1
+ {"version":3,"file":"qemu-errors.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-errors.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,IAAI,sBAAsB;IACnC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"qemu-form.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-form.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,KAAK,OAAO,EAKb,MAAM,iBAAiB,CAAC;AAEzB;;;;GAIG;AACH,eAAO,MAAM,YAAY,UAAW,OAAO,KAAG,MAAM,EAG6C,CAAC;AAElG,2FAA2F;AAC3F,eAAO,MAAM,IAAI,UAAW,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAO1D,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,UAAW,OAAO;;CAGvC,CAAC;AAEH,qGAAqG;AACrG,eAAO,MAAM,UAAU,aAAO,CAAC"}
1
+ {"version":3,"file":"qemu-form.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-form.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,KAAK,OAAO,EAKb,MAAM,iBAAiB,CAAC;AAGzB;;;;GAIG;AACH,eAAO,MAAM,YAAY,UAAW,OAAO,KAAG,MAAM,EAKnD,CAAC;AAEF,2FAA2F;AAC3F,eAAO,MAAM,IAAI,UAAW,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAO1D,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,UAAW,OAAO;;CAGvC,CAAC;AAEH,qGAAqG;AACrG,eAAO,MAAM,UAAU,aAAO,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"qemu-judge.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-judge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,KAAK,OAAO,EAAsD,MAAM,iBAAiB,CAAC;AAInG,MAAM,MAAM,QAAQ,GAAG;IACrB,mFAAmF;IACnF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC,CAAC;AAEF,eAAO,MAAM,KAAK,UAAW,OAAO,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,QA8CtE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,SAAU,MAAM,OAAO,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SAI1B,CAAC"}
1
+ {"version":3,"file":"qemu-judge.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-judge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,KAAK,OAAO,EAAsD,MAAM,iBAAiB,CAAC;AAKnG,MAAM,MAAM,QAAQ,GAAG;IACrB,mFAAmF;IACnF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC,CAAC;AAEF,eAAO,MAAM,KAAK,UAAW,OAAO,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,QA8CtE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,SAAU,MAAM,OAAO,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SAI1B,CAAC"}
@@ -1,40 +1,45 @@
1
1
  import type { Input } from 'alchemy/Input';
2
2
  import * as nodes from '@distilled.cloud/proxmox/nodes';
3
3
  import * as Effect from 'effect/Effect';
4
- import { type VmAttributes, type VmProps } from './qemu-props.ts';
5
- export declare const readQemu: (props: VmProps) => Effect.Effect<VmAttributes | undefined, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
4
+ import type * as HttpClient from 'effect/unstable/http/HttpClient';
5
+ import { QemuRefusedError } from './qemu-errors.ts';
6
+ import type { VmAttributes, VmProps } from './qemu-props.ts';
7
+ import { type QemuDiskResizeRefused } from './qemu-size.ts';
8
+ type QemuLifecycleError = Effect.Error<ReturnType<typeof readQemu>> | nodes.PutNodeQemuResizeError | QemuRefusedError | QemuDiskResizeRefused;
9
+ export declare const readQemu: (props: VmProps) => Effect.Effect<VmAttributes | undefined, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, HttpClient.HttpClient>;
6
10
  /** No purge, no skiplock, no destroy-unreferenced-disks. A missing config is already gone. */
7
- export declare const deleteQemu: (props: VmProps) => Effect.Effect<void | undefined, Error | import("./credential-errors.ts").PveCredentialDenied | nodes.ProxmoxOpError, import("effect/unstable/http/HttpClient").HttpClient>;
11
+ export declare const deleteQemu: (props: VmProps) => Effect.Effect<void | undefined, Error | import("./credential-errors.ts").PveCredentialDenied | nodes.ProxmoxOpError, HttpClient.HttpClient>;
8
12
  export declare const qemuHandlers: {
9
13
  list: () => Effect.Effect<never[], never, never>;
10
14
  /**
11
15
  * ⛔ `Unowned` UNLESS STATE ALREADY VOUCHES FOR IT (C2). With no attributes this is Alchemy's
12
16
  * adoption probe or the recovery read for an interrupted create (ownership/probe.ts); `settled`
13
- * is the same `judge` reconcile uses, so "proven ours" and "reconcile would write nothing" are
14
- * the same question asked once.
17
+ * uses the same config comparison as reconcile. Disk growth is a post-create step, so its
18
+ * drift cannot disown a VM after an interrupted/failed resize (measured 2026-10-05).
15
19
  */
16
20
  read: (args_0: {
17
21
  fqn: string;
18
22
  instanceId: string;
19
23
  olds: VmProps;
20
24
  output: VmAttributes | undefined;
21
- }) => Effect.Effect<VmAttributes | undefined, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
25
+ }) => Effect.Effect<VmAttributes | undefined, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, HttpClient.HttpClient>;
22
26
  diff: (args_0: {
23
27
  news: Input<VmProps>;
24
28
  olds: VmProps;
25
29
  output: VmAttributes | undefined;
26
30
  }) => Effect.Effect<{
27
- readonly action: "noop" | "update";
28
- } | undefined, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
31
+ readonly action: 'noop' | 'update';
32
+ } | undefined, QemuLifecycleError, HttpClient.HttpClient>;
29
33
  reconcile: (args_0: {
30
34
  fqn: string;
31
35
  instanceId: string;
32
36
  news: VmProps;
33
37
  olds: VmProps | undefined;
34
38
  output: VmAttributes | undefined;
35
- }) => Effect.Effect<VmAttributes, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
39
+ }) => Effect.Effect<VmAttributes, QemuLifecycleError, HttpClient.HttpClient>;
36
40
  delete: ({ olds }: {
37
41
  olds: VmProps;
38
- }) => Effect.Effect<void | undefined, Error | import("./credential-errors.ts").PveCredentialDenied | nodes.ProxmoxOpError, import("effect/unstable/http/HttpClient").HttpClient>;
42
+ }) => Effect.Effect<void | undefined, Error | import("./credential-errors.ts").PveCredentialDenied | nodes.ProxmoxOpError, HttpClient.HttpClient>;
39
43
  };
44
+ export {};
40
45
  //# sourceMappingURL=qemu-lifecycle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"qemu-lifecycle.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-lifecycle.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,KAAK,MAAM,gCAAgC,CAAC;AACxD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAOxC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,OAAO,EAMb,MAAM,iBAAiB,CAAC;AAwCzB,eAAO,MAAM,QAAQ,UAAW,OAAO,iOAapC,CAAC;AAEJ,8FAA8F;AAC9F,eAAO,MAAM,UAAU,UAAW,OAAO,+KAMyB,CAAC;AAmBnE,eAAO,MAAM,YAAY;IACvB,IAAI;IACJ;;;;;OAKG;IACH,IAAI;aAMG,MAAM;oBACC,MAAM;cACZ,OAAO;gBACL,YAAY,GAAG,SAAS;;IAQlC,IAAI;cAKI,KAAK,CAAC,OAAO,CAAC;cACd,OAAO;gBACL,YAAY,GAAG,SAAS;;;;IAwBlC,SAAS;aAOF,MAAM;oBACC,MAAM;cACZ,OAAO;cACP,OAAO,GAAG,SAAS;gBACjB,YAAY,GAAG,SAAS;;IAoDlC,MAAM,aAAa;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE;CACrC,CAAC"}
1
+ {"version":3,"file":"qemu-lifecycle.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-lifecycle.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,KAAK,MAAM,gCAAgC,CAAC;AACxD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,UAAU,MAAM,iCAAiC,CAAC;AAKnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAI7D,OAAO,EAAE,KAAK,qBAAqB,EAAyC,MAAM,gBAAgB,CAAC;AAOnG,KAAK,kBAAkB,GACnB,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,GACzC,KAAK,CAAC,sBAAsB,GAC5B,gBAAgB,GAChB,qBAAqB,CAAC;AAE1B,eAAO,MAAM,QAAQ,UAAW,OAAO,kMAapC,CAAC;AAEJ,8FAA8F;AAC9F,eAAO,MAAM,UAAU,UAAW,OAAO,gJAMyB,CAAC;AAmBnE,eAAO,MAAM,YAAY;IACvB,IAAI;IACJ;;;;;OAKG;IACH,IAAI;aAMG,MAAM;oBACC,MAAM;cACZ,OAAO;gBACL,YAAY,GAAG,SAAS;;IAUlC,IAAI;cAKI,KAAK,CAAC,OAAO,CAAC;cACd,OAAO;gBACL,YAAY,GAAG,SAAS;;yBAEb,MAAM,GAAG,QAAQ;;IA4BtC,SAAS;aAOF,MAAM;oBACC,MAAM;cACZ,OAAO;cACP,OAAO,GAAG,SAAS;gBACjB,YAAY,GAAG,SAAS;;IAuDlC,MAAM,aAAa;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE;CACrC,CAAC"}
@@ -46,6 +46,16 @@ export interface VmProps extends WithTarget {
46
46
  boot?: string;
47
47
  /** e.g. `virtio-scsi-single`. */
48
48
  scsihw?: string;
49
+ /** Cloud-init DNS servers: PVE's `address-list` (IP addresses or DNS names). */
50
+ nameserver?: string;
51
+ /** Cloud-init DNS search domains, in PVE's wire spelling. */
52
+ searchdomain?: string;
53
+ /**
54
+ * Minimum disk sizes in GiB, e.g. `{ scsi0: 64 }`, grown after import completes.
55
+ * Existing larger disks are left alone. Lowering a previously declared target is refused.
56
+ * These are resize targets, never config fields; declare the corresponding disk slot too.
57
+ */
58
+ diskSizesGiB?: Partial<Record<`scsi${number}` | `ide${number}`, number>>;
49
59
  /**
50
60
  * `local-zfs:32` to create a new volume, or the live volume string as adopted —
51
61
  * `cephtb4:vm-101-disk-0,size=32G` (n is 0 to 30, pve-qemu-server's own `$MAX_SCSI_DISKS`).
@@ -1 +1 @@
1
- {"version":3,"file":"qemu-props.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-props.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,kGAAkG;AAClG,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;AAEtC,MAAM,WAAW,OAAQ,SAAQ,UAAU;IACzC,uFAAuF;IACvF,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,yFAAyF;IACzF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,CAAC,IAAI,EAAE,OAAO,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;IAC5C;;;OAGG;IACH,CAAC,GAAG,EAAE,MAAM,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;IAC1C;;;;OAIG;IACH,CAAC,SAAS,EAAE,MAAM,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;IAChD,mFAAmF;IACnF,CAAC,QAAQ,EAAE,WAAW,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;IACpD,gFAAgF;IAChF,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;IAChD,kCAAkC;IAClC,UAAU,CAAC,EAAE,KAAK,CAAC;IACnB,wCAAwC;IACxC,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,2FAA2F;IAC3F,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAKD,8FAA8F;AAC9F,eAAO,MAAM,OAAO;aAClB,GAAG,EAAE,CAAC;aACN,QAAQ,EAAE,EAAE;aACZ,GAAG,EAAE,EAAE;aACP,IAAI,EAAE,EAAE;aACR,MAAM,EAAE,CAAC;CACD,CAAC;AACX,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,OAAO,CAAC;AAEjD,4FAA4F;AAC5F,eAAO,MAAM,UAAU,QAAS,MAAM,KAAG,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC,GAAG,SAM3E,CAAC;AAeF;;;;;GAKG;AACH,eAAO,MAAM,YAAY,QAAS,MAAM,KAAG,OACY,CAAC;AAExD,6GAA6G;AAC7G,eAAO,MAAM,aAAa,UAAW,OAAO,OAAO,MAAM,KAAG,OACR,CAAC;AAErD,wFAAwF;AACxF,eAAO,MAAM,YAAY,UAAW,OAAO,KAAG,MAAM,EAGzC,CAAC;AAEZ,iGAAiG;AACjG,eAAO,MAAM,SAAS,UAAW,OAAO,KAAG,MACmB,CAAC;AAE/D;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,SAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAQjF,CAAC"}
1
+ {"version":3,"file":"qemu-props.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-props.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import * as Effect from 'effect/Effect';
2
+ import { type VmProps } from './qemu-props.ts';
3
+ /**
4
+ * ⛔ Observe the unlocked, allocated disk before each resize, including recovery after import.
5
+ * Absolute targets make retries safe; `+60G` would grow again after interrupted state writes.
6
+ * This resource never starts a guest. Its caller can power on only after reconcile returns.
7
+ * SDK failures retain their generated tags; provider refusals are QemuDiskResizeRefused.
8
+ */
9
+ export declare const resizeDisks: (props: VmProps) => Effect.Effect<undefined, Error | import("effect/unstable/http/HttpClientError").HttpClientError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
10
+ //# sourceMappingURL=qemu-resize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qemu-resize.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-resize.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,KAAK,OAAO,EAAgB,MAAM,iBAAiB,CAAC;AAqC7D;;;;;GAKG;AACH,eAAO,MAAM,WAAW,UAAW,OAAO,kNAuCtC,CAAC"}
@@ -0,0 +1,20 @@
1
+ import * as Effect from 'effect/Effect';
2
+ import { type VmProps } from './qemu-props.ts';
3
+ declare const QemuDiskResizeRefused_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
4
+ readonly _tag: "QemuDiskResizeRefused";
5
+ } & Readonly<A>;
6
+ export declare class QemuDiskResizeRefused extends QemuDiskResizeRefused_base<{
7
+ readonly disk: string;
8
+ readonly message: string;
9
+ }> {
10
+ }
11
+ /** PVE config reports binary sizes, including fractional G and integer M/K for imported images. */
12
+ export declare const diskBytes: (config: string | undefined) => number | undefined;
13
+ /** Validate the whole declaration before any write, including a later attempted target decrease. */
14
+ export declare const validateDiskSizes: (props: VmProps, olds?: VmProps) => Effect.Effect<undefined, QemuDiskResizeRefused, never>;
15
+ /** Capacity drift drives reconcile; recovery ownership ignores it because resize follows create. */
16
+ export declare const diskSizeDrift: (props: VmProps, config: Record<string, string>) => string[];
17
+ /** Missing slots may be imported by the upcoming config write; unreadable existing sizes fail closed. */
18
+ export declare const checkLiveDiskSizes: (props: VmProps, config: Record<string, string>, allowMissing?: boolean) => Effect.Effect<undefined, QemuDiskResizeRefused, never>;
19
+ export {};
20
+ //# sourceMappingURL=qemu-size.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qemu-size.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-size.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,KAAK,OAAO,EAA6B,MAAM,iBAAiB,CAAC;;;;AAG1E,qBAAa,qBAAsB,SAAQ,2BAA0C;IACnF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;AAEL,mGAAmG;AACnG,eAAO,MAAM,SAAS,WAAY,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SAO/D,CAAC;AAEF,oGAAoG;AACpG,eAAO,MAAM,iBAAiB,UAAW,OAAO,SAAS,OAAO,2DAwC5D,CAAC;AAEL,oGAAoG;AACpG,eAAO,MAAM,aAAa,UAAW,OAAO,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,MAAM,EAKzC,CAAC;AAE7C,yGAAyG;AACzG,eAAO,MAAM,kBAAkB,UACtB,OAAO,UACN,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,mFAmB5B,CAAC"}
@@ -0,0 +1,25 @@
1
+ /** QEMU config forms and vendor guards, separated from lifecycle to keep both reviewable. */
2
+ import { createForm } from './qemu-form.ts';
3
+ import { type VmAttributes, type VmProps } from './qemu-props.ts';
4
+ export declare const attributesOf: (live: Record<string, unknown>, props: VmProps) => VmAttributes;
5
+ /**
6
+ * ⚠️ KEPT ONLY TO SATISFY `PveSpec`'S REQUIRED FIELD — `qemu-judge.ts`'s `judge` is what diff and
7
+ * reconcile actually decide by, since a plain string compare is exactly the bug C1 found (it
8
+ * never matches the "new disk" or MAC-less spellings a declaration may use).
9
+ */
10
+ declare const matches: (attributes: VmAttributes, props: VmProps) => boolean;
11
+ export declare const spec: {
12
+ attributes: typeof attributesOf;
13
+ collection: (props: VmProps) => string;
14
+ createForm: typeof createForm;
15
+ endpoint: {
16
+ create: string;
17
+ update: string;
18
+ };
19
+ matches: typeof matches;
20
+ path: (props: VmProps) => string;
21
+ updateForm: typeof import("./qemu-form.ts").form;
22
+ };
23
+ export declare const guardCreate: (props: VmProps, presence: boolean) => import("effect/Effect").Effect<void>, guardUpdate: (props: VmProps) => import("effect/Effect").Effect<void>;
24
+ export {};
25
+ //# sourceMappingURL=qemu-spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qemu-spec.d.ts","sourceRoot":"","sources":["../../src/proxmox/qemu-spec.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,OAAO,EAAE,UAAU,EAAc,MAAM,gBAAgB,CAAC;AACxD,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,OAAO,EAMb,MAAM,iBAAiB,CAAC;AAIzB,eAAO,MAAM,YAAY,SAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,OAAO,KAAG,YAI3E,CAAC;AAEH;;;;GAIG;AACH,QAAA,MAAM,OAAO,eAAgB,YAAY,SAAS,OAAO,YAG2B,CAAC;AAErF,eAAO,MAAM,IAAI;;wBAEK,OAAO;;;QAGzB,MAAM;QACN,MAAM;;;kBAGM,OAAO;;CAEmB,CAAC;AAE3C,eAAO,MAAQ,WAAW,+EAAE,WAAW,0DAAqB,CAAC"}
@@ -53,7 +53,7 @@ export type DriftRow = {
53
53
  readonly action: string;
54
54
  };
55
55
  export interface FakeEngine {
56
- /** Plan and apply `body`, as `alchemy deploy --adopt` would; resolves to the planned actions. */
56
+ /** Plan and apply `body` with the configured adoption policy; resolves to planned actions. */
57
57
  readonly deploy: (body: Body) => Promise<Record<string, string>>;
58
58
  /** Verify `body` against what the earlier deploys recorded. */
59
59
  readonly verify: (body: Body, options?: VerifyOptions) => Promise<AdoptReport>;
@@ -78,7 +78,9 @@ export interface FakeEngine {
78
78
  * hands in its real provider over a fake transport (proxmox/ceph-pool-adopt.test.ts).
79
79
  * ⚠️ THE CASTS ARE AT THE ENGINE'S TYPED BOUNDARY — openbao/fake-stack.ts has the reasoning.
80
80
  */
81
- export declare const engineOver: <ROut, E, RIn>(layer: Layer.Layer<ROut, E, RIn>) => FakeEngine;
81
+ export declare const engineOver: <ROut, E, RIn>(layer: Layer.Layer<ROut, E, RIn>, options?: {
82
+ readonly adopt?: boolean;
83
+ }) => FakeEngine;
82
84
  /** The fake family over `cloud`. */
83
85
  export declare const fakeEngine: (cloud: Cloud) => FakeEngine;
84
86
  //# sourceMappingURL=fake-engine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fake-engine.d.ts","sourceRoot":"","sources":["../../src/verify/fake-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAKnC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAiB,MAAM,aAAa,CAAC;AAElF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,KAAM,SAAQ,OAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AAC7F,eAAO,MAAM,KAAK,8BAAwC,CAAC;AAE3D,4EAA4E;AAC5E,MAAM,WAAW,KAAM,SAAQ,OAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AAC7F,eAAO,MAAM,KAAK,8BAAwC,CAAC;AAE3D;;;;GAIG;AACH,MAAM,WAAW,QAAS,SAAQ,OAAO,CAAC,QAAQ,CAAC,eAAe,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AACnG,eAAO,MAAM,QAAQ,iCAA8C,CAAC;AAEpE,gGAAgG;AAChG,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,eAAO,MAAM,OAAO,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAQ,KAI1D,CAAC;AAEH,8CAA8C;AAC9C,eAAO,MAAM,QAAQ,UAAW,KAAK,KAAG,MAAM,EAC2C,CAAC;AAyB1F,4FAA4F;AAC5F,eAAO,MAAM,cAAc,UAAW,KAAK,8GAmCxC,CAAC;AAEJ,oFAAoF;AACpF,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAK5D,gGAAgG;AAChG,MAAM,MAAM,QAAQ,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,MAAM,WAAW,UAAU;IACzB,iGAAiG;IACjG,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACjE,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/E;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAClE;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC;CAC/B;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,IAAI,EAAE,CAAC,EAAE,GAAG,SAAS,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,KAAG,UAmD3E,CAAC;AAEF,oCAAoC;AACpC,eAAO,MAAM,UAAU,UAAW,KAAK,KAAG,UAA+C,CAAC"}
1
+ {"version":3,"file":"fake-engine.d.ts","sourceRoot":"","sources":["../../src/verify/fake-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AAKnC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAiB,MAAM,aAAa,CAAC;AAElF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,KAAM,SAAQ,OAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AAC7F,eAAO,MAAM,KAAK,8BAAwC,CAAC;AAE3D,4EAA4E;AAC5E,MAAM,WAAW,KAAM,SAAQ,OAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AAC7F,eAAO,MAAM,KAAK,8BAAwC,CAAC;AAE3D;;;;GAIG;AACH,MAAM,WAAW,QAAS,SAAQ,OAAO,CAAC,QAAQ,CAAC,eAAe,EAAE,UAAU,EAAE,eAAe,CAAC;CAAG;AACnG,eAAO,MAAM,QAAQ,iCAA8C,CAAC;AAEpE,gGAAgG;AAChG,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,eAAO,MAAM,OAAO,UAAU,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAQ,KAI1D,CAAC;AAEH,8CAA8C;AAC9C,eAAO,MAAM,QAAQ,UAAW,KAAK,KAAG,MAAM,EAC2C,CAAC;AAyB1F,4FAA4F;AAC5F,eAAO,MAAM,cAAc,UAAW,KAAK,8GAmCxC,CAAC;AAEJ,oFAAoF;AACpF,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAK5D,gGAAgG;AAChG,MAAM,MAAM,QAAQ,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,MAAM,WAAW,UAAU;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACjE,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/E;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAClE;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC;CAC/B;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,IAAI,EAAE,CAAC,EAAE,GAAG,SAC9B,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,YACvB;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,KACpC,UAmDF,CAAC;AAEF,oCAAoC;AACpC,eAAO,MAAM,UAAU,UAAW,KAAK,KAAG,UAA+C,CAAC"}
@@ -0,0 +1,62 @@
1
+ # Cloud-init DNS and imported disk growth
2
+
3
+ ```ts
4
+ Proxmox.Vm('talos', {
5
+ target,
6
+ node: 'n2',
7
+ vmid: 10000,
8
+ scsi0: 'cephtb4:0,import-from=cephfs-tb4:import/talos.raw',
9
+ diskSizesGiB: { scsi0: 64 },
10
+ ide2: 'cephtb4:cloudinit',
11
+ ipconfig0: 'ip=10.20.16.20/24,gw=10.20.16.254',
12
+ nameserver: '10.20.16.254',
13
+ searchdomain: 'example.internal',
14
+ });
15
+ ```
16
+
17
+ `diskSizesGiB` declares minimum capacity in positive integer GiB. Declare the disk
18
+ slot alongside its target. Equal or larger live disks need no resize; lowering a
19
+ previously declared target is refused with `QemuDiskResizeRefused`, which callers
20
+ can handle with `Effect.catchTag`. Removing a target leaves capacity unmanaged.
21
+ Unsupported slots, CD-ROM/cloud-init drives and unreadable live sizes are refused.
22
+
23
+ The provider waits for import, reads the allocated disk, sends an absolute target
24
+ through the generated `putNodeQemuResize` operation, waits for its task, and verifies
25
+ the resulting capacity. An interrupted create resumes without `--adopt` when its
26
+ config matches, even if disk growth remains unfinished. Each resize checks the raw
27
+ VM lock first; lock waits and resize task polling share a 60-observation budget per
28
+ disk. A persistent lock raises `QemuDiskResizeRefused` without a resize write.
29
+ Absolute targets let retries finish growth without adding capacity twice.
30
+ `size=` in a volume config string is still observed metadata: omit it when
31
+ using a resize target. An unrelated update never resends the import source.
32
+
33
+ This resource never starts a VM. Complete its reconciliation before the separate
34
+ power-on step. Resizing an existing guest does not grow its partitions/filesystems.
35
+
36
+ DNS keys use the same declared-key comparison as `ipconfig0`: omitted keys remain
37
+ unmanaged. `nameserver` enforces the generated `address-list` constraint; PVE permits
38
+ IP addresses or DNS names, separated by whitespace, commas or semicolons. The provider
39
+ preserves the supplied spelling. `searchdomain` has no extra schema constraint.
40
+
41
+ Schema provenance: `codegen/manifest.json`, pve-manager **9.2.11/f6997e698c7933ea**,
42
+ SHA-256 `9def8f13611184ee1c7d0399713130dfc4a065701d0d91a69b9c03df929344e9`.
43
+ QEMU resize already exists in both generated surfaces: distilled's `nodes.ts` and
44
+ the legacy generator's packed `nodes-node-qemu-vmid-mtunnel.ts`. A filename search
45
+ for `qemu-vmid-resize.ts` misses the latter; neither output needs hand editing.
46
+ Both caches were recovered byte-for-byte from public vendor sources, then
47
+ `bun codegen/constraints.ts` generated the resize guard. The existing type generator
48
+ already supports the operation. No generated file was edited by hand.
49
+
50
+ Recovery used the vendor Makefile's concatenation order: `api-viewer/apidata.js`
51
+ and `api-viewer/PVEAPI.js` from proxmox/pve-docs
52
+ `4e7ff22c70eb35c63e65b0ba65c98980cb4d7bf5`, then `src/api-viewer/APIViewer.js`
53
+ from proxmox/proxmox-widget-toolkit `9204a77880eb31aff6ffc8bcf65ca48539685ab1`.
54
+ The result is exactly 4,337,847 bytes and the manifest SHA-256 above. PBS's 1,508,860
55
+ bytes were recovered from the public `proxmox-backup-docs_4.2.3-1_all.deb`, matching
56
+ the manifest's full SHA-256 (the recorded server version is 4.2.6-1, running 4.2.3).
57
+ No host was contacted. Tests cover generated constraints/types and fake SDK transport.
58
+
59
+ The named format's semantics come from
60
+ [PVE::JSONSchema](https://github.com/proxmox/pve-common/blob/defd246f31f327463f901a2daaf8dc52efcc5a97/src/PVE/JSONSchema.pm)
61
+ and `PVE::ParseUtils` at the same commit, inspected 2026-10-05. This is vendor-source
62
+ and fake-transport evidence; no live PVE call or Talos boot was performed.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homeflare/alchemy",
3
- "version": "0.45.0",
3
+ "version": "0.46.0",
4
4
  "description": "Custom Alchemy providers for Cloudflare, Proxmox, OpenBao, Forgejo, Talos, launchd and Caddy, and a verifier that proves adoptions are no-ops.",
5
5
  "homepage": "https://github.com/taslabs-net/homeflare-kit/tree/main/packages/alchemy#readme",
6
6
  "bugs": "https://github.com/taslabs-net/homeflare-kit/issues",
@@ -54,4 +54,4 @@ export const PROXMOX_CONSTRAINTS: Readonly<Record<string, EndpointConstraints>>
54
54
  * ★ A DIGEST OF THE DATA, NOT OF THE FILE TEXT, so reformatting is not a stale generation while
55
55
  * changing a 128 to a 129 by hand is. `tests/schema-manifest.test.ts` recomputes it.
56
56
  */
57
- export const PROXMOX_CONSTRAINTS_DIGEST = '8b6745a471839974';
57
+ export const PROXMOX_CONSTRAINTS_DIGEST = 'cbf63b7bac0500ef';
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -122,4 +122,9 @@ export const PVE_NODES_QEMU_CONSTRAINTS: Readonly<Record<string, EndpointConstra
122
122
  "vmstatestorage": {"format":"pve-storage-id","type":"string"},
123
123
  "watchdog": {"format":"pve-qm-watchdog","type":"string"},
124
124
  },
125
+ "pve:PUT /nodes/{node}/qemu/{vmid}/resize": {
126
+ "digest": {"maxLength":40,"type":"string"},
127
+ "disk": {"enum":["ide0","ide1","ide2","ide3","scsi0","scsi1","scsi2","scsi3","scsi4","scsi5","scsi6","scsi7","scsi8","scsi9","scsi10","scsi11","scsi12","scsi13","scsi14","scsi15","scsi16","scsi17","scsi18","scsi19","scsi20","scsi21","scsi22","scsi23","scsi24","scsi25","scsi26","scsi27","scsi28","scsi29","scsi30","virtio0","virtio1","virtio2","virtio3","virtio4","virtio5","virtio6","virtio7","virtio8","virtio9","virtio10","virtio11","virtio12","virtio13","virtio14","virtio15","sata0","sata1","sata2","sata3","sata4","sata5","efidisk0","tpmstate0"],"required":true,"type":"string"},
128
+ "size": {"pattern":"^\\+?\\d+(\\.\\d+)?[KMGT]?\\n?$","patternSource":"\\+?\\d+(\\.\\d+)?[KMGT]?","required":true,"type":"string"},
129
+ },
125
130
  };
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -6,7 +6,7 @@
6
6
  * sha256 9def8f13611184ee, read on a PVE cluster node from
7
7
  * /usr/share/pve-docs/api-viewer/apidoc.js
8
8
  *
9
- * 59 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
9
+ * 60 of this product's 258 POST/PUT endpoints are tabled across all areas: the ones
10
10
  * this package writes to, named in its own source. Every other vendor write endpoint is UNTABLED
11
11
  * and therefore unchecked at plan time.
12
12
  *
@@ -113,6 +113,7 @@ export {
113
113
  export { provisionBootstrap } from './provision-bootstrap.ts';
114
114
  export { type DeclareProvisionOptions, declareProvisionBaseline } from './provision-declare.ts';
115
115
  export { ProxmoxVm, ProxmoxVmProvider, type VmAttributes, type VmProps } from './qemu.ts';
116
+ export { QemuDiskResizeRefused } from './qemu-size.ts';
116
117
  export {
117
118
  ProxmoxStorageDownload,
118
119
  ProxmoxStorageDownloadProvider,
@@ -0,0 +1,73 @@
1
+ import { expect, test } from 'bun:test';
2
+ import * as Effect from 'effect/Effect';
3
+ import { FAKE_TARGET, fakePve, withoutBao } from './fake-pve.ts';
4
+ import { createForm, formRefusals, updateForm } from './qemu-form.ts';
5
+ import { judge } from './qemu-judge.ts';
6
+ import { qemuHandlers } from './qemu-lifecycle.ts';
7
+ import { storedConfig } from './qemu-props.ts';
8
+
9
+ const base = { target: FAKE_TARGET, node: 'n2', vmid: 10000 };
10
+ const props = { ...base, nameserver: '10.20.16.254', searchdomain: 'example.internal' };
11
+
12
+ test('cloud-init DNS survives form rendering, stored attributes and per-key diff', () => {
13
+ const config = { nameserver: props.nameserver, searchdomain: props.searchdomain };
14
+ expect(createForm(props)).toEqual({ ...config, vmid: '10000' });
15
+ expect(updateForm(props)).toEqual(config);
16
+ expect(storedConfig(config)).toEqual(config);
17
+ expect(judge(props, config)).toEqual({ drift: [], put: {}, refuse: [] });
18
+ expect(judge({ ...props, nameserver: '10.20.16.1' }, config)).toEqual({
19
+ drift: ['nameserver'],
20
+ put: { nameserver: '10.20.16.1' },
21
+ refuse: [],
22
+ });
23
+ expect(judge({ ...props, searchdomain: 'new.internal' }, config).put).toEqual({
24
+ searchdomain: 'new.internal',
25
+ });
26
+ expect(judge(base, config).drift).toEqual([]);
27
+ });
28
+
29
+ test('address-list follows PVE: IPs, DNS names, separators and empty lists', () => {
30
+ for (const nameserver of [
31
+ '',
32
+ '10.20.16.254',
33
+ '2001:db8::53',
34
+ 'dns.example.internal',
35
+ '10.20.16.254, 2001:db8::53;dns.example.internal',
36
+ '10.20.16.254\0dns.example.internal',
37
+ ]) {
38
+ expect(formRefusals({ ...base, nameserver }), nameserver).toEqual([]);
39
+ }
40
+ for (const nameserver of [
41
+ 'https://dns.example',
42
+ '10.20.16.254/24',
43
+ '[2001:db8::53]',
44
+ '-bad.example',
45
+ 'bad_.example',
46
+ '2001:db8::broken',
47
+ 'dns.example.',
48
+ ]) {
49
+ expect(formRefusals({ ...base, nameserver })[0], nameserver).toContain('address-list');
50
+ }
51
+ });
52
+
53
+ test('invalid DNS fails with a typed refusal before any live read or write', async () => {
54
+ const fake = fakePve(() => {
55
+ throw new Error('unexpected API call');
56
+ });
57
+ await withoutBao(async () => {
58
+ const refusal = await Effect.runPromise(
59
+ qemuHandlers
60
+ .diff({
61
+ news: { ...props, nameserver: 'dns://invalid' },
62
+ olds: base,
63
+ output: undefined,
64
+ })
65
+ .pipe(
66
+ Effect.catchTag('QemuRefusedError', (error) => Effect.succeed(error.message)),
67
+ Effect.provide(fake.layer),
68
+ ),
69
+ );
70
+ expect(refusal).toBe('nameserver: must satisfy the vendor address-list format');
71
+ });
72
+ expect(fake.calls).toEqual([]);
73
+ });