@homeflare/alchemy 0.31.0 → 0.31.1

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 (123) hide show
  1. package/dist/proxmox/acl-wire.d.ts +26 -0
  2. package/dist/proxmox/acl-wire.d.ts.map +1 -0
  3. package/dist/proxmox/acl.d.ts.map +1 -1
  4. package/dist/proxmox/api-token-form.d.ts +28 -26
  5. package/dist/proxmox/api-token-form.d.ts.map +1 -1
  6. package/dist/proxmox/api-token.d.ts +48 -89
  7. package/dist/proxmox/api-token.d.ts.map +1 -1
  8. package/dist/proxmox/ceph-fs-wire.d.ts +2 -2
  9. package/dist/proxmox/ceph-fs-wire.d.ts.map +1 -1
  10. package/dist/proxmox/ceph-osd-tree.d.ts +1 -1
  11. package/dist/proxmox/ceph-osd-tree.d.ts.map +1 -1
  12. package/dist/proxmox/ceph-osd-write.d.ts +2 -2
  13. package/dist/proxmox/ceph-osd-write.d.ts.map +1 -1
  14. package/dist/proxmox/ceph-pool-settle.d.ts +1 -1
  15. package/dist/proxmox/ceph-pool-settle.d.ts.map +1 -1
  16. package/dist/proxmox/client.d.ts +2 -2
  17. package/dist/proxmox/client.d.ts.map +1 -1
  18. package/dist/proxmox/credential-errors.d.ts +27 -0
  19. package/dist/proxmox/credential-errors.d.ts.map +1 -0
  20. package/dist/proxmox/credentials.d.ts +0 -38
  21. package/dist/proxmox/credentials.d.ts.map +1 -1
  22. package/dist/proxmox/distilled-guard.d.ts +31 -0
  23. package/dist/proxmox/distilled-guard.d.ts.map +1 -0
  24. package/dist/proxmox/distilled-pve.d.ts +11 -4
  25. package/dist/proxmox/distilled-pve.d.ts.map +1 -1
  26. package/dist/proxmox/generated/constraints/index.d.ts +1 -1
  27. package/dist/proxmox/generated/constraints/pve-access.d.ts +1 -1
  28. package/dist/proxmox/generated/constraints/pve-access.d.ts.map +1 -1
  29. package/dist/proxmox/generated/constraints/pve-cluster-backup.d.ts +1 -1
  30. package/dist/proxmox/generated/constraints/pve-cluster-ceph.d.ts +1 -1
  31. package/dist/proxmox/generated/constraints/pve-cluster-firewall.d.ts +1 -1
  32. package/dist/proxmox/generated/constraints/pve-cluster-ha.d.ts +1 -1
  33. package/dist/proxmox/generated/constraints/pve-cluster-metrics.d.ts +1 -1
  34. package/dist/proxmox/generated/constraints/pve-cluster-notifications.d.ts +1 -1
  35. package/dist/proxmox/generated/constraints/pve-cluster-replication.d.ts +1 -1
  36. package/dist/proxmox/generated/constraints/pve-cluster-sdn.d.ts +1 -1
  37. package/dist/proxmox/generated/constraints/pve-nodes-ceph.d.ts +1 -1
  38. package/dist/proxmox/generated/constraints/pve-nodes-disks.d.ts +1 -1
  39. package/dist/proxmox/generated/constraints/pve-nodes-lxc.d.ts +1 -1
  40. package/dist/proxmox/generated/constraints/pve-nodes-network.d.ts +1 -1
  41. package/dist/proxmox/generated/constraints/pve-nodes-qemu.d.ts +1 -1
  42. package/dist/proxmox/generated/constraints/pve-pools.d.ts +1 -1
  43. package/dist/proxmox/generated/constraints/pve-storage.d.ts +1 -1
  44. package/dist/proxmox/group-wire.d.ts +29 -0
  45. package/dist/proxmox/group-wire.d.ts.map +1 -0
  46. package/dist/proxmox/group.d.ts +20 -24
  47. package/dist/proxmox/group.d.ts.map +1 -1
  48. package/dist/proxmox/index.js +725 -509
  49. package/dist/proxmox/index.js.map +40 -33
  50. package/dist/proxmox/lease-cache.d.ts +1 -1
  51. package/dist/proxmox/lease-cache.d.ts.map +1 -1
  52. package/dist/proxmox/lxc-lifecycle.d.ts +5 -5
  53. package/dist/proxmox/lxc-lifecycle.d.ts.map +1 -1
  54. package/dist/proxmox/mint.d.ts +50 -0
  55. package/dist/proxmox/mint.d.ts.map +1 -0
  56. package/dist/proxmox/network-apply-read.d.ts +2 -2
  57. package/dist/proxmox/network-apply-read.d.ts.map +1 -1
  58. package/dist/proxmox/pbs-notification-target-lifecycle.d.ts +2 -2
  59. package/dist/proxmox/pbs-sync-job-form.d.ts +2 -2
  60. package/dist/proxmox/provision-cli-fake.d.ts.map +1 -1
  61. package/dist/proxmox/resource.d.ts +4 -4
  62. package/dist/proxmox/role-wire.d.ts +28 -0
  63. package/dist/proxmox/role-wire.d.ts.map +1 -0
  64. package/dist/proxmox/role.d.ts +36 -52
  65. package/dist/proxmox/role.d.ts.map +1 -1
  66. package/dist/proxmox/sdn-apply-read.d.ts +1 -1
  67. package/dist/proxmox/sdn-apply-read.d.ts.map +1 -1
  68. package/dist/proxmox/unreadable-read.d.ts +50 -0
  69. package/dist/proxmox/unreadable-read.d.ts.map +1 -0
  70. package/dist/proxmox/user-wire.d.ts +18 -0
  71. package/dist/proxmox/user-wire.d.ts.map +1 -0
  72. package/dist/proxmox/user.d.ts +25 -32
  73. package/dist/proxmox/user.d.ts.map +1 -1
  74. package/dist/proxmox/zfs-pool-write.d.ts +2 -2
  75. package/dist/proxmox/zfs-pool-write.d.ts.map +1 -1
  76. package/package.json +1 -1
  77. package/src/proxmox/acl-wire.ts +83 -0
  78. package/src/proxmox/acl.ts +29 -82
  79. package/src/proxmox/adopt-noop.test.ts +18 -0
  80. package/src/proxmox/api-token-adopt.test.ts +28 -12
  81. package/src/proxmox/api-token-form.ts +50 -93
  82. package/src/proxmox/api-token.ts +149 -135
  83. package/src/proxmox/client.ts +2 -7
  84. package/src/proxmox/constraints-forms.test.ts +7 -27
  85. package/src/proxmox/credential-errors.ts +33 -0
  86. package/src/proxmox/credentials.test.ts +29 -3
  87. package/src/proxmox/credentials.ts +4 -134
  88. package/src/proxmox/distilled-guard.ts +42 -0
  89. package/src/proxmox/distilled-pve.ts +15 -4
  90. package/src/proxmox/generated/constraints/index.ts +1 -1
  91. package/src/proxmox/generated/constraints/pve-access.ts +1 -4
  92. package/src/proxmox/generated/constraints/pve-cluster-backup.ts +1 -1
  93. package/src/proxmox/generated/constraints/pve-cluster-ceph.ts +1 -1
  94. package/src/proxmox/generated/constraints/pve-cluster-firewall.ts +1 -1
  95. package/src/proxmox/generated/constraints/pve-cluster-ha.ts +1 -1
  96. package/src/proxmox/generated/constraints/pve-cluster-metrics.ts +1 -1
  97. package/src/proxmox/generated/constraints/pve-cluster-notifications.ts +1 -1
  98. package/src/proxmox/generated/constraints/pve-cluster-replication.ts +1 -1
  99. package/src/proxmox/generated/constraints/pve-cluster-sdn.ts +1 -1
  100. package/src/proxmox/generated/constraints/pve-nodes-ceph.ts +1 -1
  101. package/src/proxmox/generated/constraints/pve-nodes-disks.ts +1 -1
  102. package/src/proxmox/generated/constraints/pve-nodes-lxc.ts +1 -1
  103. package/src/proxmox/generated/constraints/pve-nodes-network.ts +1 -1
  104. package/src/proxmox/generated/constraints/pve-nodes-qemu.ts +1 -1
  105. package/src/proxmox/generated/constraints/pve-pools.ts +1 -1
  106. package/src/proxmox/generated/constraints/pve-storage.ts +1 -1
  107. package/src/proxmox/group-wire.ts +63 -0
  108. package/src/proxmox/group.test.ts +110 -0
  109. package/src/proxmox/group.ts +135 -105
  110. package/src/proxmox/lease-cache.ts +2 -1
  111. package/src/proxmox/lxc-lifecycle.ts +2 -1
  112. package/src/proxmox/mint.ts +158 -0
  113. package/src/proxmox/network-apply.ts +1 -1
  114. package/src/proxmox/provision-cli-fake.ts +11 -0
  115. package/src/proxmox/provision-declare.test.ts +6 -1
  116. package/src/proxmox/role-wire.ts +49 -0
  117. package/src/proxmox/role.test.ts +89 -0
  118. package/src/proxmox/role.ts +147 -106
  119. package/src/proxmox/unreadable-read.test.ts +83 -0
  120. package/src/proxmox/unreadable-read.ts +60 -0
  121. package/src/proxmox/user-wire.ts +112 -0
  122. package/src/proxmox/user.test.ts +142 -0
  123. package/src/proxmox/user.ts +132 -129
@@ -0,0 +1,26 @@
1
+ /**
2
+ * `Proxmox.Acl`'s wire shape: PVE's PUT form, identity, and how a live row becomes attributes.
3
+ * Split out of acl.ts (2026-09-24) to keep that file under the 250-line cap once the cries-wolf
4
+ * fix needed real space — the api-token.ts/api-token-form.ts seam, same reasoning: this file
5
+ * answers "what does PVE store", acl.ts answers "when has it changed" and drives the provider.
6
+ */
7
+ import type * as access from '@distilled.cloud/proxmox/access';
8
+ import type { AclAttributes, AclProps } from './acl.ts';
9
+ /** ⚠️ PVE normalises ACL paths (collapses repeated slashes, strips the trailing one, adds a leading one). */
10
+ export declare const normalize: (raw: string) => string;
11
+ /** The tuple PVE keys a grant by, as PUT's fields. */
12
+ export declare const tuple: (props: AclProps) => access.PutAccessAclRequest;
13
+ /** Create and update are one call: the tuple plus the single mutable field. */
14
+ export declare const bind: (props: AclProps) => access.PutAccessAclRequest;
15
+ /**
16
+ * ⚠️ ALWAYS PRESENCE-CHECKED. `bind`'s output IS the create form (there is no separate,
17
+ * narrower update form for this family — see acl.ts's header), so the vendor's
18
+ * required-parameter check is never wrong to run; the two separate create/update passes the
19
+ * generic factory ran elsewhere collapse to one call here without losing coverage.
20
+ */
21
+ export declare const guardWrite: (props: AclProps) => import("effect/Effect").Effect<void, never, never>;
22
+ /** What a change of this string means: not an edit, a different grant. */
23
+ export declare const identity: (grant: Pick<AclAttributes, 'path' | 'roleid' | 'type' | 'ugid'>) => string;
24
+ export declare const attributesOf: (rows: readonly access.ListAccessAclResponseBodyItem[], props: AclProps) => AclAttributes;
25
+ export declare const matches: (attributes: AclAttributes, props: AclProps) => boolean;
26
+ //# sourceMappingURL=acl-wire.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acl-wire.d.ts","sourceRoot":"","sources":["../../src/proxmox/acl-wire.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,KAAK,MAAM,MAAM,iCAAiC,CAAC;AAE/D,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAExD,6GAA6G;AAC7G,eAAO,MAAM,SAAS,QAAS,MAAM,WAAmD,CAAC;AAQzF,sDAAsD;AACtD,eAAO,MAAM,KAAK,UAAW,QAAQ,KAAG,MAAM,CAAC,mBAI7C,CAAC;AAEH,+EAA+E;AAC/E,eAAO,MAAM,IAAI,UAAW,QAAQ,KAAG,MAAM,CAAC,mBAG5C,CAAC;AAMH;;;;;GAKG;AACH,eAAO,MAAM,UAAU,UAAW,QAAQ,uDAAmD,CAAC;AAE9F,0EAA0E;AAC1E,eAAO,MAAM,QAAQ,UAAW,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC,WACf,CAAC;AAoB1E,eAAO,MAAM,YAAY,SACjB,SAAS,MAAM,CAAC,6BAA6B,EAAE,SAC9C,QAAQ,KACd,aAUF,CAAC;AAEF,eAAO,MAAM,OAAO,eAAgB,aAAa,SAAS,QAAQ,YACQ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"acl.d.ts","sourceRoot":"","sources":["../../src/proxmox/acl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAI7C,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGtE,4FAA4F;AAC5F,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAExD,MAAM,WAAW,QAAS,SAAQ,UAAU;IAC1C;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,sFAAsF;IACtF,IAAI,EAAE,cAAc,CAAC;IACrB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,gGAAgG;IAChG,MAAM,EAAE,MAAM,CAAC;IACf,8FAA8F;IAC9F,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,+FAA+F;IAC/F,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,UAAW,SAAQ,QAAQ,CAC1C,aAAa,EACb,QAAQ,EACR,aAAa,EACb,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,eAAO,MAAM,UAAU,6CAAsC,CAAC;AAuF9D,eAAO,MAAM,kBAAkB,gIAoE5B,CAAC"}
1
+ {"version":3,"file":"acl.d.ts","sourceRoot":"","sources":["../../src/proxmox/acl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAI7C,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAStE,4FAA4F;AAC5F,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAExD,MAAM,WAAW,QAAS,SAAQ,UAAU;IAC1C;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,sFAAsF;IACtF,IAAI,EAAE,cAAc,CAAC;IACrB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,gGAAgG;IAChG,MAAM,EAAE,MAAM,CAAC;IACf,8FAA8F;IAC9F,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,+FAA+F;IAC/F,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,UAAW,SAAQ,QAAQ,CAC1C,aAAa,EACb,QAAQ,EACR,aAAa,EACb,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,eAAO,MAAM,UAAU,6CAAsC,CAAC;AAmB9D,eAAO,MAAM,kBAAkB,gIA6E5B,CAAC"}
@@ -15,9 +15,14 @@ import type { ApiTokenAttributes, ApiTokenProps } from './api-token.ts';
15
15
  * `update_token_info`, read over SSH on node-b on 2026-09-13. The two disagree in exactly the place
16
16
  * that costs a forever-diff: the schema gives `expire` the default "same as user", and the code
17
17
  * never implements it. api-token.ts records what that means.
18
+ *
19
+ * ★ MIGRATED OFF THE GENERATED `generated/pve.ts` PARAM TYPES ONTO `@distilled.cloud/proxmox`'s
20
+ * typed `access.PutAccessUserTokenRequest`/`access.GetAccessUserTokenResponse` (2026-09-24) —
21
+ * the same three fields, still form-urlencoded strings on the wire; distilled's generator
22
+ * reads the identical vendor schema `generated/pve.ts` came from.
18
23
  */
19
- import type { AccessUsersUseridTokenTokenidPostParams, AccessUsersUseridTokenTokenidPutParams } from './generated/pve.ts';
20
- import type { PveSpec } from './resource.ts';
24
+ import type * as access from '@distilled.cloud/proxmox/access';
25
+ export declare const API_TOKEN_UPDATE = "pve:PUT /access/users/{userid}/token/{tokenid}";
21
26
  /**
22
27
  * `<userid>!<tokenid>` — the name the rest of PVE calls this object by.
23
28
  *
@@ -32,12 +37,8 @@ import type { PveSpec } from './resource.ts';
32
37
  */
33
38
  export declare const fullTokenid: (props: ApiTokenProps) => string;
34
39
  /**
35
- * Everything a token has, in the form PVE wants. Create and update send exactly this.
36
- *
37
- * ⛔ `userid` AND `tokenid` ARE NOT IN IT, and that is not an omission. Both are path segments of
38
- * `access/users/{userid}/token/{tokenid}` — which is the path the POST goes to as well as the
39
- * PUT — so a second copy in the body can only ever disagree with the path it was sent to.
40
- * metric-server.ts omits its `id` for the same reason and says so there.
40
+ * Everything a token has, in the form PVE wants. Update sends exactly this (this family never
41
+ * creates — see api-token.ts's header).
41
42
  *
42
43
  * ⚠️ EVERY FIELD IS SENT ON EVERY WRITE, THE EMPTY COMMENT INCLUDED, BECAUSE A PUT MERGES.
43
44
  * MEASURED in `update_token_info`: `$token->{comment} = $param->{comment} if defined(...)`
@@ -48,23 +49,24 @@ export declare const fullTokenid: (props: ApiTokenProps) => string;
48
49
  * literally `my $deletable = { comment => 1 };`, and anything else answers
49
50
  * "unknown option '<k>'" — so `expire` and `privsep` have no clear path at all, which is the
50
51
  * other half of why both are required props rather than optional ones.
51
- *
52
- * ⚠️ `flag()` FROM values.ts IS DELIBERATELY NOT USED FOR `privsep`. Its entire job is turning an
53
- * UNDECLARED boolean into `undefined` so the field is omitted from the form; `privsep` is a
54
- * required prop precisely so that it is never undeclared, so there is nothing for it to do and
55
- * its `string | undefined` return would have to be asserted away to fit `Record<string,string>`.
56
- * An assertion here would be a claim about the prop that the type already makes properly.
57
- *
58
- * ★ TYPED AGAINST THE GENERATED PUT AND POST PARAMS, NOT `Record<string, string>`, since
59
- * 2026-09-23 — the `notification-matcher-form.ts` pattern: `Pick` rather than the whole type,
60
- * because neither `AccessUsersUseridTokenTokenidPutParams` nor …`PostParams` (generated/pve.ts)
61
- * carries `userid`/`tokenid` (they are path segments — see the ⛔ above) and Put alone also
62
- * carries `delete`/`regenerate`, which this family never sends. A schema drift on any of the
63
- * three fields this function DOES send fails `tsc` here rather than surfacing as a 400 on a live
64
- * cluster; api-token.test.ts pins the assignment both ways (Put and Post) without a cast.
65
- * `expire` is written as a template literal, not `String(...)`, because the generated type is
66
- * `` `${number}` ``, not `string` — `String(n)` widens to plain `string` and would not typecheck.
67
52
  */
68
- export declare const shape: (props: ApiTokenProps) => Pick<AccessUsersUseridTokenTokenidPutParams, 'comment' | 'expire' | 'privsep'> & Pick<AccessUsersUseridTokenTokenidPostParams, 'comment' | 'expire' | 'privsep'>;
69
- export declare const apiTokenSpec: PveSpec<ApiTokenProps, ApiTokenAttributes>;
53
+ export declare const shape: (props: ApiTokenProps) => access.PutAccessUserTokenRequest;
54
+ /**
55
+ * ★ NOTHING PVE REPORTS HERE IS UNWRITABLE, WHICH IS UNUSUAL IN THIS PACKAGE. The GET returns
56
+ * exactly `comment`, `expire` and `privsep`; PUT accepts exactly those three.
57
+ * ⛔ `undefined` WHEN NEITHER FLAG IS THERE, BECAUSE BOTH ARE ALWAYS THERE FOR A REAL TOKEN.
58
+ * `user.cfg` materialises `expire` and `privsep` for every token it stores, so an answer
59
+ * carrying neither is not a token — the same "distilled unwraps a missing object's `{"data":
60
+ * null}` to `{}`" trap group.ts's header measures, checked here the way this guard already was
61
+ * before the distilled migration (api-token.ts's ⛔ on the create refusal cites the same
62
+ * MEASURED schema). Without this guard `bool`/`int` would invent one out of their fallbacks and
63
+ * the read-back guard in `reconcile` could never fire.
64
+ */
65
+ export declare const attributesOf: (live: access.GetAccessUserTokenResponse, props: ApiTokenProps) => ApiTokenAttributes | undefined;
66
+ /**
67
+ * ⚠️ EXACTLY THE THREE FIELDS A PUT CAN PUT BACK, WHICH IS ALSO EXACTLY WHAT THE GET REPORTS.
68
+ * MEASURED (pre-migration, replaying against four live token shapes — see the old PR): all
69
+ * answer noop; flipping `privsep` answers update; an empty body answers absent.
70
+ */
71
+ export declare const matches: (attributes: ApiTokenAttributes, props: ApiTokenProps) => boolean;
70
72
  //# sourceMappingURL=api-token-form.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-token-form.d.ts","sourceRoot":"","sources":["../../src/proxmox/api-token-form.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACxE;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EACV,uCAAuC,EACvC,sCAAsC,EACvC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,UAAW,aAAa,WAAuC,CAAC;AAExF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,KAAK,UACT,aAAa,KACnB,IAAI,CAAC,sCAAsC,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC,GAC/E,IAAI,CAAC,uCAAuC,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,CAI9E,CAAC;AAEH,eAAO,MAAM,YAAY,EAAE,OAAO,CAAC,aAAa,EAAE,kBAAkB,CA6DnE,CAAC"}
1
+ {"version":3,"file":"api-token-form.d.ts","sourceRoot":"","sources":["../../src/proxmox/api-token-form.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACxE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,KAAK,MAAM,MAAM,iCAAiC,CAAC;AAG/D,eAAO,MAAM,gBAAgB,mDAAmD,CAAC;AAEjF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,UAAW,aAAa,WAAuC,CAAC;AAExF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,KAAK,UAAW,aAAa,KAAG,MAAM,CAAC,yBAMlD,CAAC;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,SACjB,MAAM,CAAC,0BAA0B,SAChC,aAAa,KACnB,kBAAkB,GAAG,SAYvB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,OAAO,eAAgB,kBAAkB,SAAS,aAAa,YAGtC,CAAC"}
@@ -2,17 +2,15 @@
2
2
  * `Proxmox.ApiToken` — a PVE API token: the thing a service actually authenticates as.
3
3
  *
4
4
  * ⛔ THE SECRET EXISTS FOR ONE HTTP RESPONSE AND THEN NOWHERE. MEASURED from the cluster's own
5
- * schema (`/usr/share/pve-docs/api-viewer/apidoc.js` on node-b, 2026-09-13): POST returns
6
- * `["full-tokenid","info","value"]`; PUT returns `["comment","expire","full-tokenid","privsep",
7
- * "value"]` with `value` present ONLY when `regenerate` was set; GET returns
8
- * `["comment","expire","privsep"]` and never the secret. A live token agrees —
9
- * `GET /access/users/metrics@pve/token/exporter` answers `{"expire":0,"privsep":0}`. PVE says
10
- * it plainly on the POST: the value "needs to be stored as it cannot be retrieved afterwards".
5
+ * schema: POST returns `["full-tokenid","info","value"]`; PUT returns `["comment","expire",
6
+ * "full-tokenid","privsep","value"]` with `value` present ONLY when `regenerate` was set; GET
7
+ * returns `["comment","expire","privsep"]` and never the secret. PVE says it plainly on the
8
+ * POST: the value "needs to be stored as it cannot be retrieved afterwards".
11
9
  *
12
10
  * ⛔ SO A TOKEN THIS RESOURCE CREATES IS UNUSABLE, AND SAYING SO IS THE POINT OF THIS BLOCK. The
13
11
  * secret may not become an attribute: Alchemy persists attributes UNENCRYPTED, and this estate's
14
- * state store is a Postgres dumped nightly (the ⛔ in credentials.ts). So `reconcile` drops the
15
- * value on the floor, and what lands is a live credential in `/etc/pve/user.cfg` whose secret
12
+ * state store is a Postgres dumped nightly (the ⛔ in credentials.ts). So `reconcile` refuses
13
+ * before any POST, and what would land is a live credential in `/etc/pve/user.cfg` whose secret
16
14
  * nobody holds. No `regenerate` rescues it, because a regenerated value is discarded the same
17
15
  * way. The only escape is an operator who captured the value out of band — which this provider
18
16
  * gives them no way to do.
@@ -20,48 +18,37 @@
20
18
  * whole of a token's policy, and declaring them is real work: it is how `expire` stops being
21
19
  * whatever somebody typed in 2024. Mint NEW tokens where the secret can be caught — OpenBao's
22
20
  * `proxmox-c1` mount, or a human at `pveum user token add`.
23
- * ⛔ ★ CORRECTED 2026-09-23 — THIS PARAGRAPH PREVIOUSLY SAID "THE CREATE PATH IS LEFT REACHABLE
24
- * RATHER THAN STUBBED… the honest arrangement is a create that works". THAT CONTRADICTED THE
25
- * `reconcile` BELOW, WHICH REFUSES: `handlers.reconcile` calls `Effect.die` by name when `read`
26
- * answers absent, before any POST — metadata-only per decision 9 (2026-09-23), exported on the
27
- * barrel as an adopt-and-manage-only Resource. A create that silently did nothing WOULD be the
28
- * lie resource.ts's ★ describes for a stubbed delete; refusing loudly, by name, with the two
29
- * ways to get a usable token, is the honest arrangement instead — see the ★ further down and
30
- * api-token-adopt.test.ts's absent-token row, which pins the refusal and zero writes.
31
21
  *
32
22
  * ⛔ THERE IS NO `regenerate` PROP, AND IT IS NOT AN OVERSIGHT. PVE's own description: "All users
33
23
  * of the previous secret will lose access after this operation." A prop for it would revoke a
34
24
  * live credential during a deploy whose plan said `update`, and hand back a replacement this
35
- * provider is obliged to throw away — breakage with no recovery. Rotation belongs to the mount
36
- * that owns the lease, or to a human who is watching.
25
+ * provider is obliged to throw away — breakage with no recovery.
37
26
  *
38
27
  * ⚠️ THERE IS A SECOND WRITER TO THESE OBJECTS AND IT IS THE ONE THIS PROVIDER RUNS ON. OpenBao's
39
- * `proxmox-c1` engine mints PVE tokens under `hf-read@pve` and `hf-provision@pve` — read from
40
- * `<estate>/platform/secrets/vault/plugin-proxmox/proxmox/`: `privsep=0` (client.go), `expire` set
41
- * to the lease deadline, and an id the plugin CHOOSES,
42
- * `hf-<role>-<actor>-<entity6>-<stamp>-<nonce>` (tokenname.go). Revocation and WAL rollback look
43
- * up that one exact id (wal.go); neither sweeps a prefix. So the two systems cannot collide on
44
- * one object by accident — but they share the USER: `hf-read@pve` held three live leases when
45
- * this was written, and `Proxmox.User` deleting that account takes every one of them with it.
46
- * ⛔ DO NOT DECLARE A TOKEN UNDER A MINT USER. `expire` is what makes that dangerous rather than
47
- * untidy: point this resource at a lease token with the wrong expire and a 300-second
48
- * credential becomes a permanent one — and on `hf-provision@pve` that credential carries
49
- * `Permissions.Modify` at `/`. docs/privileges.md records what those 27 privileges buy.
28
+ * `proxmox-c1` engine mints PVE tokens under `hf-read@pve` and `hf-provision@pve` with an id it
29
+ * CHOOSES (`hf-<role>-<actor>-<entity6>-<stamp>-<nonce>`), so the two systems cannot collide on
30
+ * one object by accident — but they share the USER, and `Proxmox.User` deleting that account
31
+ * takes every one of its tokens with it. ⛔ DO NOT DECLARE A TOKEN UNDER A MINT USER: `expire`
32
+ * is what makes that dangerous — a 300-second lease token becomes a permanent one.
50
33
  *
51
34
  * ⚠️ PRIVILEGES, AND THE READ LANE CANNOT DO IT. MEASURED: all four methods on this path check
52
35
  * `['or', ['userid-param','self'], ['userid-group', ['User.Modify']]]` — with no `Sys.Audit`
53
- * alternative, unlike `GET /access/users/{userid}`, which has one. And
54
- * `pvesh get /access/permissions --userid hf-read@pve --path /access/groups` answers the seven
55
- * PVEAuditor audit privileges and no `User.Modify`, while `hf-provision@pve` has it. So the
56
- * 3600s read lease reaches at most its OWN account's tokens and is refused for every other
57
- * userid — which `read` in resource.ts folds into "absent", so the plan says create and the POST
58
- * then fails with "Token already exists". Hence `readRole: 'provision'` below, for the same
59
- * reason storage.ts, sdn-zone.ts and sdn-vnet.ts set it, at the same cost: every plan mints a
60
- * 300s non-renewable provision lease just to read.
36
+ * alternative — so the 3600s read lease reaches at most its OWN account's tokens and is refused
37
+ * for every other userid. `readRole: 'provision'` below, for the same reason storage.ts,
38
+ * sdn-zone.ts and sdn-vnet.ts set it, at the same cost: every plan mints a 300s non-renewable
39
+ * provision lease just to read.
40
+ *
41
+ * ★ MIGRATED OFF `client.ts`'s generic `pve()`/`pveHandlers`/`pveOperations` ONTO
42
+ * `@distilled.cloud/proxmox`'s typed `access.getAccessUserToken`/`putAccessUserToken`/
43
+ * `deleteAccessUserToken` (2026-09-24, decision 43's proxmox walk-down, the last access-family
44
+ * resource). There is no `createAccessUserToken` call anywhere in this file — the create branch
45
+ * was already provably unreachable before the migration (`reconcile` dies on an absent read
46
+ * before any create path runs), so nothing calls distilled's POST-shaped `updateAccessUserToken`
47
+ * operation either; see api-token-form.ts for why the generator gave it that name.
61
48
  */
62
49
  import { Resource } from 'alchemy';
63
50
  import * as Provider from 'alchemy/Provider';
64
- import { type PveRequirements, type WithTarget } from './resource.ts';
51
+ import type { PveRequirements, WithTarget } from './resource-spec.ts';
65
52
  export interface ApiTokenProps extends WithTarget {
66
53
  /**
67
54
  * The account that owns the token, realm-qualified: `iac@pve`, `root@pam`. Identity.
@@ -75,57 +62,36 @@ export interface ApiTokenProps extends WithTarget {
75
62
  /**
76
63
  * The token's own name, unique within the account. Identity.
77
64
  *
78
- * ⚠️ PVE HAS NO RENAME, AND HERE THAT COSTS MORE THAN IT DOES FOR A USER. Editing this prop (or
79
- * `userid`) points `path` at a DIFFERENT token, which reads as absent and is then created —
80
- * leaving the old token LIVE, with its secret still working, invisible to the plan, while the
81
- * new one is the unusable kind described at the top. Rename by declaring a delete and a
82
- * create, the way user.ts says for an account.
83
- * ⛔ `diff` IS NOT OVERRIDDEN TO SAY `replace` THE WAY acl.ts DOES, AND THE DIFFERENCE IS THE
84
- * OBJECT. There, replace removes a grant that can be rebuilt from its own tuple; here it
85
- * would DELETE a live token — destroying an irrecoverable secret, and everything using it —
86
- * to tidy up a name. Leaving the old token standing is the lesser harm, and saying so here
87
- * is what keeps it from looking like an omission.
88
- * ⚠️ PATTERN `[A-Za-z][A-Za-z0-9.\-_]+`: a letter first, two characters minimum. The schema
89
- * declares no maxLength; the OpenBao plugin assumes a conservative 64 rather than finding the
90
- * real limit in production, and so should anything else.
65
+ * ⚠️ PVE HAS NO RENAME. Editing this prop (or `userid`) points `path` at a DIFFERENT token,
66
+ * which reads as absent and is then created — leaving the old token LIVE, invisible to the
67
+ * plan, while the new one is the unusable kind described at the top. Rename by declaring a
68
+ * delete and a create.
69
+ * ⛔ `diff` IS NOT OVERRIDDEN TO SAY `replace` THE WAY acl.ts DOES: there, replace removes a
70
+ * grant that can be rebuilt from its own tuple; here it would DELETE a live token —
71
+ * destroying an irrecoverable secret — to tidy up a name. Leaving the old token standing is
72
+ * the lesser harm.
73
+ * ⚠️ PATTERN `[A-Za-z][A-Za-z0-9.\-_]+`: a letter first, two characters minimum.
91
74
  */
92
75
  tokenid: string;
93
- /**
94
- * Free text in `pveum user token list` and the UI. Empty is how it is cleared — see `shape`.
95
- * ⚠️ ANY CHARACTER IS SAFE HERE, MEASURED, and it was worth checking: `user.cfg` is a
96
- * colon-delimited line, so a comment holding a colon or a newline is the obvious place for a
97
- * round-trip to lose a character and diff forever. PVE escapes it — `encode_text` turns
98
- * `a:b\nc%d` into `a%3Ab%0Ac%25d` and `decode_text` gives it back byte for byte.
99
- */
76
+ /** Free text in `pveum user token list` and the UI. Empty is how it is cleared — see `shape`. */
100
77
  comment?: string;
101
78
  /**
102
79
  * Seconds since the epoch, or 0 for "never expires".
103
80
  *
104
81
  * ⛔ REQUIRED, AND THE SCHEMA WILL TELL YOU IT NEED NOT BE. It declares the default "same as
105
82
  * user", and the code never implements it: `generate_token` writes `expire` only when the
106
- * parameter is defined, `user.cfg` stores a token as `token:<id>:<expire>:<privsep>:<comment>:`
107
- * with no absent state, and the parser does `$expire = 0 if !$expire` (AccessControl.pm:1624).
108
- * MEASURED end to end: every token on this cluster that was created without an expire reads
109
- * back `"expire":0`. So "same as user" is documentation of an intention, not behaviour.
110
- * ⛔ WHICH IS WHY IT IS NOT OPTIONAL-DEFAULTING-TO-0. That spelling reads identically and is far
111
- * worse: an omitted `expire` would then quietly WRITE 0 over a live deadline, turning an
112
- * expiring credential into a permanent one, and the plan would call it an update. Requiring
113
- * the field makes "this token never expires" a sentence somebody had to type.
83
+ * parameter is defined, and the parser does `$expire = 0 if !$expire`. Required, so "this
84
+ * token never expires" is a sentence somebody had to type, rather than an omission that would
85
+ * quietly WRITE 0 over a live deadline.
114
86
  */
115
87
  expire: number;
116
88
  /**
117
89
  * True keeps the token's privileges separate from its owner's — it gets NOTHING until an ACL
118
90
  * names `fullTokenid`. False gives it the owner's privileges entire.
119
91
  *
120
- * ⛔ REQUIRED FOR THE SAME REASON AS `expire`, AND THE BLAST RADIUS IS LARGER. PVE's API default
121
- * is 1, every token on this cluster is 0 (measured), and `user.cfg` materialises it either way
122
- * — `$privsep = $privsep ? 1 : 0` (AccessControl.pm:1622), so there is no unset state to
123
- * preserve. Were this optional, adopting a live token without mentioning `privsep` would plan
124
- * an update to 1 and STRIP a working credential of every privilege it has, silently: PVE
125
- * returns 401/403 to the service, nothing errors here, and `iac@pve!apply` simply stops
126
- * working. Required, so adopting a token is a sentence that states what it is.
127
- * ⚠️ AND `false` IS NOT A SHRUG. It is a token with its owner's whole privilege set; under a
128
- * provisioning account that is the account's full authority with a separate secret.
92
+ * ⛔ REQUIRED FOR THE SAME REASON AS `expire`, AND THE BLAST RADIUS IS LARGER. Were this
93
+ * optional, adopting a live token without mentioning `privsep` would plan an update to 1 and
94
+ * STRIP a working credential of every privilege it has, silently.
129
95
  */
130
96
  privsep: boolean;
131
97
  }
@@ -142,23 +108,16 @@ export interface ProxmoxApiToken extends Resource<'Proxmox.ApiToken', ApiTokenPr
142
108
  }
143
109
  /**
144
110
  * ★ `retain` BY DEFAULT, AND THIS IS THE PLAINEST CASE FOR IT IN THE PACKAGE. A token's contents
145
- * are one irreplaceable secret: delete it and the value is gone, a replacement is a DIFFERENT
146
- * value, and every holder loses access the instant `cfs_write_file` returns — with no error
147
- * raised anywhere near them. The live cluster's tokens are `metrics@pve!exporter` (the PVE
148
- * exporter feeding VictoriaMetrics), `agent@pve!executor`, `iac@pve!apply`, `iac@pve!ro`,
149
- * `app@pve!app` and `mint@pve!engine` — the last being the parent credential the
150
- * OpenBao mount itself authenticates with, so orphaning that one would stop every plan in this
151
- * package, this resource included. `delete` is FULLY IMPLEMENTED (DELETE is a real method on
152
- * this path, measured) and runs the moment a caller opts in with `.pipe(RemovalPolicy.destroy())`.
153
- * See the ★ in resource.ts, which explains the convention once.
111
+ * are one irreplaceable secret: delete it and the value is gone, and every holder loses access
112
+ * the instant `cfs_write_file` returns — with no error raised anywhere near them. `delete` is
113
+ * FULLY IMPLEMENTED and runs the moment a caller opts in with `.pipe(RemovalPolicy.destroy())`.
154
114
  */
155
115
  export declare const ProxmoxApiToken: import("alchemy").ResourceClass<ProxmoxApiToken>;
156
116
  /**
157
- * ⛔ `list` IS EMPTY, AND FOR THIS FAMILY THAT MATTERS MORE THAN THE GENERIC ARGUMENT IN
158
- * resource.ts. A token index handed to Alchemy would offer up `mint@pve!engine` and every
159
- * live OpenBao lease for adoption — and adoption is what makes a later plan willing to delete.
160
- * The mount's leases in particular appear and vanish on their own; anything that adopted one
161
- * would report drift against a credential that was never its to hold.
117
+ * ⛔ THIS FAMILY ADOPTS AND MANAGES TOKENS; IT REFUSES TO MINT ONE — see the header. `reconcile`
118
+ * refuses by name before any write when the read finds nothing, so the create path this
119
+ * family's spec would otherwise need never runs, and no `createAccessUserToken`-shaped call
120
+ * exists in this file at all.
162
121
  */
163
122
  export declare const ProxmoxApiTokenProvider: () => import("effect/Layer").Layer<Provider.Provider<ProxmoxApiToken>, never, import("effect/unstable/http/HttpClient").HttpClient>;
164
123
  //# sourceMappingURL=api-token.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-token.d.ts","sourceRoot":"","sources":["../../src/proxmox/api-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAG7C,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAA8B,MAAM,eAAe,CAAC;AAElG,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC/C;;;;;;;OAOG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;;OAaG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;OAaG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAOlB;AAED,MAAM,WAAW,eAAgB,SAAQ,QAAQ,CAC/C,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,kDAE1B,CAAC;AA6CH;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,qIACqD,CAAC"}
1
+ {"version":3,"file":"api-token.d.ts","sourceRoot":"","sources":["../../src/proxmox/api-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAK7C,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAStE,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC/C;;;;;;;OAOG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;OAYG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,iGAAiG;IACjG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;OAQG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAKlB;AAED,MAAM,WAAW,eAAgB,SAAQ,QAAQ,CAC/C,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,eAAe,kDAE1B,CAAC;AAaH;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,qIAgFjC,CAAC"}
@@ -80,7 +80,7 @@ export declare const createForm: (props: CephFsProps) => Record<string, string>;
80
80
  * ⚠️ BOTH WRITES CHECK `Sys.Modify` ON `/` -- the root, with the breadth metric-server.ts warns
81
81
  * about: granting it buys datacenter options and every other cluster-wide config write too.
82
82
  */
83
- export declare const createFs: (props: CephFsProps) => Effect.Effect<undefined, Error, import("effect/unstable/http/HttpClient").HttpClient>;
83
+ export declare const createFs: (props: CephFsProps) => Effect.Effect<undefined, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
84
84
  /**
85
85
  * DELETE the filesystem, then wait for the worker.
86
86
  *
@@ -91,7 +91,7 @@ export declare const createFs: (props: CephFsProps) => Effect.Effect<undefined,
91
91
  * fails with "ceph pools '<name>_data' and/or '<name>_metadata' already exist" -- that refusal is
92
92
  * a BRAKE, not a bug, and it is the last thing standing between a mis-typed rename and the data.
93
93
  */
94
- export declare const destroyFs: (props: CephFsProps) => Effect.Effect<void, Error, import("effect/unstable/http/HttpClient").HttpClient>;
94
+ export declare const destroyFs: (props: CephFsProps) => Effect.Effect<void, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
95
95
  /**
96
96
  * The two read-back failures, as messages rather than as guesses.
97
97
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ceph-fs-wire.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-fs-wire.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKlE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,SACZ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SACtB,WAAW,KACjB,gBAAgB,GAAG,SAkBrB,CAAC;AAaF,6FAA6F;AAC7F,eAAO,MAAM,UAAU,UAAW,WAAW,WAAgD,CAAC;AAM9F;;;GAGG;AACH,eAAO,MAAM,UAAU,UAAW,WAAW,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAGnE,CAAC;AA2DH;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ,UAAW,WAAW,0FAiBvC,CAAC;AAEL;;;;;;;;;GASG;AACH,eAAO,MAAM,SAAS,UAAW,WAAW,qFAQxC,CAAC;AAEL;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,UAAW,WAAW,UAK1C,CAAC;AAEJ,eAAO,MAAM,YAAY,UAAW,WAAW,UAK5C,CAAC"}
1
+ {"version":3,"file":"ceph-fs-wire.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-fs-wire.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKlE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO,SACZ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,SACtB,WAAW,KACjB,gBAAgB,GAAG,SAkBrB,CAAC;AAaF,6FAA6F;AAC7F,eAAO,MAAM,UAAU,UAAW,WAAW,WAAgD,CAAC;AAM9F;;;GAGG;AACH,eAAO,MAAM,UAAU,UAAW,WAAW,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAGnE,CAAC;AA2DH;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ,UAAW,WAAW,iJAiBvC,CAAC;AAEL;;;;;;;;;GASG;AACH,eAAO,MAAM,SAAS,UAAW,WAAW,4IAQxC,CAAC;AAEL;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,UAAW,WAAW,UAK1C,CAAC;AAEJ,eAAO,MAAM,YAAY,UAAW,WAAW,UAK5C,CAAC"}
@@ -149,6 +149,6 @@ export declare const osdAttributes: (leaf: CrushNode, props: CephOsdProps) => Ce
149
149
  * added. ⚠️ A 404 or a 403 both arrive here as `undefined`: see the ⛔ on `readRole` in
150
150
  * resource.ts for why that distinction is invisible and what it costs.
151
151
  */
152
- export declare const readOsd: (props: CephOsdProps) => Effect.Effect<CephOsdAttributes | undefined, Error, import("effect/unstable/http/HttpClient").HttpClient>;
152
+ export declare const readOsd: (props: CephOsdProps) => Effect.Effect<CephOsdAttributes | undefined, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
153
153
  export {};
154
154
  //# sourceMappingURL=ceph-osd-tree.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ceph-osd-tree.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-osd-tree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAIlD,iFAAiF;AACjF,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAOzC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,SAAS,SAAU,SAAS,KAAG,SAAS,EAQpD,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,OAAO,SAAU,SAAS,SAAS,MAAM,0BACiB,CAAC;AAExE,MAAM,WAAW,iBAAiB;IAChC,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,EAAE,EAAE,OAAO,CAAC;IACZ,8FAA8F;IAC9F,YAAY,EAAE,MAAM,CAAC;IACrB,kGAAkG;IAClG,QAAQ,EAAE,MAAM,CAAC;IACjB,4FAA4F;IAC5F,GAAG,EAAE,MAAM,CAAC;IACZ,iGAAiG;IACjG,WAAW,EAAE,MAAM,CAAC;IACpB,uFAAuF;IACvF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,SAAU,SAAS,SAAS,YAAY,KAAG,iBAanE,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,UAAW,YAAY,8GAMxC,CAAC"}
1
+ {"version":3,"file":"ceph-osd-tree.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-osd-tree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAIlD,iFAAiF;AACjF,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAOzC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,SAAS,SAAU,SAAS,KAAG,SAAS,EAQpD,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,OAAO,SAAU,SAAS,SAAS,MAAM,0BACiB,CAAC;AAExE,MAAM,WAAW,iBAAiB;IAChC,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;IACf,iGAAiG;IACjG,EAAE,EAAE,OAAO,CAAC;IACZ,8FAA8F;IAC9F,YAAY,EAAE,MAAM,CAAC;IACrB,kGAAkG;IAClG,QAAQ,EAAE,MAAM,CAAC;IACjB,4FAA4F;IAC5F,GAAG,EAAE,MAAM,CAAC;IACZ,iGAAiG;IACjG,WAAW,EAAE,MAAM,CAAC;IACpB,uFAAuF;IACvF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,SAAU,SAAS,SAAS,YAAY,KAAG,iBAanE,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,UAAW,YAAY,qKAMxC,CAAC"}
@@ -32,7 +32,7 @@ export declare const OSD_CREATE_ENDPOINT: EndpointKey;
32
32
  * ⚠️ `dev` is `string | undefined` on the props and non-optional here: `createOsd` refuses first.
33
33
  */
34
34
  export declare const createOsdForm: (props: CephOsdProps, dev: string) => Record<string, string>;
35
- export declare const createOsd: (news: CephOsdProps) => Effect.Effect<import("./ceph-osd-tree.ts").CephOsdAttributes, Error, import("effect/unstable/http/HttpClient").HttpClient>;
35
+ export declare const createOsd: (news: CephOsdProps) => Effect.Effect<import("./ceph-osd-tree.ts").CephOsdAttributes, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
36
36
  /**
37
37
  * ⛔ REMOVING THE DECLARATION REMOVES THE ASSERTION, NOT THE REPLICA, AND THAT ASYMMETRY IS THE
38
38
  * POINT. `DELETE /nodes/{node}/ceph/osd/{osdid}` takes a replica out of a live pool — with
@@ -51,5 +51,5 @@ export declare const createOsd: (news: CephOsdProps) => Effect.Effect<import("./
51
51
  * ⚠️ `cleanup` DEFAULTS TO FALSE, so the logical volumes survive and the disk can be re-added
52
52
  * without a rebuild. Ceph still starts backfilling the missing copies the moment the OSD goes.
53
53
  */
54
- export declare const destroyOsd: (olds: CephOsdProps) => Effect.Effect<unknown, Error, import("effect/unstable/http/HttpClient").HttpClient>;
54
+ export declare const destroyOsd: (olds: CephOsdProps) => Effect.Effect<unknown, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
55
55
  //# sourceMappingURL=ceph-osd-write.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ceph-osd-write.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-osd-write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAA+C,CAAC;AAIlF;;;GAGG;AACH,eAAO,MAAM,aAAa,UAAW,YAAY,OAAO,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAGpF,CAAC;AAEH,eAAO,MAAM,SAAS,oJA6BpB,CAAC;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,SAAU,YAAY,wFAO1C,CAAC"}
1
+ {"version":3,"file":"ceph-osd-write.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-osd-write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAA+C,CAAC;AAIlF;;;GAGG;AACH,eAAO,MAAM,aAAa,UAAW,YAAY,OAAO,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAGpF,CAAC;AAEH,eAAO,MAAM,SAAS,2MA6BpB,CAAC;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,SAAU,YAAY,+IAO1C,CAAC"}
@@ -24,7 +24,7 @@ export type PoolRead = (props: CephPoolProps) => Effect.Effect<CephPoolAttribute
24
24
  * An empty list is trusted: the collection 403s when the role is too narrow rather than
25
25
  * filtering, so `[]` really does mean a cluster with no pools.
26
26
  */
27
- export declare const confirmAbsent: (props: CephPoolProps, collection: string, describe: string) => Effect.Effect<void, Error, import("effect/unstable/http/HttpClient").HttpClient>;
27
+ export declare const confirmAbsent: (props: CephPoolProps, collection: string, describe: string) => Effect.Effect<void, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
28
28
  /**
29
29
  * Wait for the cluster to agree, then answer the last thing it said.
30
30
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ceph-pool-settle.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-pool-settle.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,CACrB,KAAK,EAAE,aAAa,KACjB,MAAM,CAAC,MAAM,CAAC,kBAAkB,GAAG,SAAS,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;AAE3E;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,UAAW,aAAa,cAAc,MAAM,YAAY,MAAM,qFAcrF,CAAC;AAEJ;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM,UACV,aAAa,QACd,QAAQ,QACR,CAAC,IAAI,EAAE,kBAAkB,GAAG,SAAS,KAAK,OAAO,+GASrD,CAAC"}
1
+ {"version":3,"file":"ceph-pool-settle.d.ts","sourceRoot":"","sources":["../../src/proxmox/ceph-pool-settle.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,CACrB,KAAK,EAAE,aAAa,KACjB,MAAM,CAAC,MAAM,CAAC,kBAAkB,GAAG,SAAS,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;AAE3E;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,UAAW,aAAa,cAAc,MAAM,YAAY,MAAM,4IAcrF,CAAC;AAEJ;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM,UACV,aAAa,QACd,QAAQ,QACR,CAAC,IAAI,EAAE,kBAAkB,GAAG,SAAS,KAAK,OAAO,+GASrD,CAAC"}
@@ -14,7 +14,7 @@
14
14
  */
15
15
  import * as Effect from 'effect/Effect';
16
16
  import * as HttpClient from 'effect/unstable/http/HttpClient';
17
- import { type ApiTarget, type PveCredential, type PveRole, type PveTarget } from './credentials.ts';
17
+ import type { ApiTarget, PveCredential, PveRole, PveTarget } from './credentials.ts';
18
18
  export declare class PveError extends Error {
19
19
  readonly status: number;
20
20
  readonly method: string;
@@ -60,5 +60,5 @@ export declare const pveEnvelopeWith: (target: PveTarget, credential: PveCredent
60
60
  * node that received the PUT. Any member serves any task path; the privilege skip is keyed on
61
61
  * whether the caller IS the task's owner.
62
62
  */
63
- export declare const pve: <T>(target: ApiTarget, role: PveRole, method: 'GET' | 'POST' | 'PUT' | 'DELETE', path: string, form?: PveForm) => Effect.Effect<T | undefined, Error, HttpClient.HttpClient>;
63
+ export declare const pve: <T>(target: ApiTarget, role: PveRole, method: 'GET' | 'POST' | 'PUT' | 'DELETE', path: string, form?: PveForm) => Effect.Effect<T | undefined, Error | import("./credential-errors.ts").PveCredentialDenied, HttpClient.HttpClient>;
64
64
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/proxmox/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,UAAU,MAAM,iCAAiC,CAAC;AAE9D,OAAO,EACL,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,OAAO,EACZ,KAAK,SAAS,EAEf,MAAM,kBAAkB,CAAC;AAI1B,qBAAa,QAAS,SAAQ,KAAK;IAE/B,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM;IAHvB,YACW,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EAIf;CACF;AAcD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC;AA8FjE,uFAAuF;AACvF,eAAO,MAAM,OAAO,GAAI,CAAC,UACf,SAAS,cACL,aAAa,UACjB,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,QACnC,MAAM,SACL,OAAO,kEAgBZ,CAAC;AAEL;;;;;GAKG;AACH,eAAO,MAAM,eAAe,WAClB,SAAS,cACL,aAAa,UACjB,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,QACnC,MAAM,4EAmBV,CAAC;AAEL;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,UACX,SAAS,QACX,OAAO,UACL,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,QACnC,MAAM,SACL,OAAO,+DAKZ,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/proxmox/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,UAAU,MAAM,iCAAiC,CAAC;AAE9D,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAKrF,qBAAa,QAAS,SAAQ,KAAK;IAE/B,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM;IAHvB,YACW,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EAIf;CACF;AAcD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC;AA8FjE,uFAAuF;AACvF,eAAO,MAAM,OAAO,GAAI,CAAC,UACf,SAAS,cACL,aAAa,UACjB,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,QACnC,MAAM,SACL,OAAO,kEAgBZ,CAAC;AAEL;;;;;GAKG;AACH,eAAO,MAAM,eAAe,WAClB,SAAS,cACL,aAAa,UACjB,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,QACnC,MAAM,4EAmBV,CAAC;AAEL;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,UACX,SAAS,QACX,OAAO,UACL,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,QACnC,MAAM,SACL,OAAO,sHAKZ,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { PveRole } from './credentials.ts';
2
+ declare const PveCredentialDenied_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 & {
3
+ readonly _tag: "PveCredentialDenied";
4
+ } & Readonly<A>;
5
+ /**
6
+ * OpenBao answered 403 to `GET /v1/<mount>/creds/<role>`: this identity's AppRole has no grant
7
+ * for `role` on `mount` — measured 2026-09-24 as "the agent lane cannot mint `provision`" (the
8
+ * lane's policy grants `read` but not `provision`). A TYPED tag, not the plain `Error` every
9
+ * other mint failure still is (404 no such role/mount, 503 sealed, a network failure), because
10
+ * this ONE case means "refused, not evidence of anything about the object" — a family's
11
+ * `readOrUnreadable` (unreadable-read.ts) `catchTag`s exactly this, never any other mint
12
+ * failure, which stays a hard error precisely because it is NOT a scoped refusal.
13
+ *
14
+ * ⛔ WHY NOT EVERY NON-2xx: A 503 (sealed) or a 404 (misconfigured mount/role) is the estate
15
+ * BROKEN, not this identity being narrowly scoped — folding those into "unreadable, report
16
+ * noop" would hide a real outage behind a quiet, misleadingly reassuring plan. Only 403 is
17
+ * "this identity, this role, denied" and safe to read as "cannot see, not evidence of absence".
18
+ */
19
+ export declare class PveCredentialDenied extends PveCredentialDenied_base<{
20
+ readonly mount: string;
21
+ readonly role: PveRole;
22
+ readonly detail: string;
23
+ }> {
24
+ get message(): string;
25
+ }
26
+ export {};
27
+ //# sourceMappingURL=credential-errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-errors.d.ts","sourceRoot":"","sources":["../../src/proxmox/credential-errors.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;;;;AAEhD;;;;;;;;;;;;;GAaG;AACH,qBAAa,mBAAoB,SAAQ,yBAAwC;IAC/E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;IACA,IAAa,OAAO,IAAI,MAAM,CAK7B;CACF"}
@@ -28,8 +28,6 @@
28
28
  * secret that reached an attribute would outlive its 300s lease by months, in four places.
29
29
  * Nothing here returns it to a resource; it is used to build a header and then dropped.
30
30
  */
31
- import * as Effect from 'effect/Effect';
32
- import * as HttpClient from 'effect/unstable/http/HttpClient';
33
31
  /**
34
32
  * ★ NO SESSION, ON PURPOSE, AND THIS IS WHAT UNBLOCKED `wip/bao-policy`.
35
33
  * `CommandExecutor.run` requires a `ScopedPlanStatusSession`, and Alchemy gives one to
@@ -114,40 +112,4 @@ export type PveCredential = {
114
112
  };
115
113
  /** The environment `mint` resolves OpenBao from — `process.env` unless a test passes its own. */
116
114
  export type BaoEnvironment = Readonly<Record<string, string | undefined>>;
117
- /**
118
- * Mint one credential for `role`: `GET /v1/<mount>/creds/<role>` on OpenBao's HTTP API.
119
- *
120
- * 🔴 IT SHELLED OUT TO `bao read -format=json` UNTIL 2026-09-14. The case for the CLI was that one
121
- * client could not disagree with `bao kv get` about what this machine may do. <estate>/openbao then
122
- * learned twice what deciding by stderr costs — every failure read as absent, and two commands
123
- * said "absent" in different words — so this reads STATUS CODES: 2xx is a credential, and 403
124
- * (denied), 404 (no such role or mount — a mint has no "absent"), 503 (sealed) all fail.
125
- * ★ THE ENVIRONMENT CONTRACT IS STILL THE CLI's, READ THE CLI's WAY, which keeps the case above
126
- * true (openbao v2.6.2 api/client.go:34-66, 370, 503-507, 761-762, 776-785): BAO_AGENT_ADDR over
127
- * BAO_ADDR over https://127.0.0.1:8200; BAO_NAMESPACE as X-Vault-Namespace; BAO_TOKEN as
128
- * X-Vault-Token; X-Vault-Request always. <estate>/openbao/src/bao-address.ts has the long form.
129
- * ★ AGENT MODE IS NO BAO_TOKEN AND NO TOKEN HEADER. An Agent or Proxy listener with
130
- * `api_proxy { use_auto_auth_token = true }` (or the older `cache { … }`) substitutes its
131
- * auto-auth token exactly when a request carries none — command/agentproxyshared/cache/handler.go
132
- * :29-38, command/agent.go:517-541, command/agent/config/config.go:288-292, and
133
- * website/content/docs/agent-and-proxy/agent/apiproxy.mdx:57-62. The CLI's token-file fallback
134
- * is deliberately not read. ⚠️ So an unset BAO_TOKEN aimed at a SERVER rather than an agent is a
135
- * 403, which reads like a missing grant rather than a missing variable.
136
- * ★ UNIX SOCKETS: `unix:///path` is plain HTTP to `localhost` over that socket, as the CLI does it
137
- * (api/client.go:654-667). Bun's fetch takes a `unix` option; `FetchHttpClient.RequestInit` is
138
- * Effect's documented way to pass fetch options, read from the calling fiber (effect
139
- * FetchHttpClient.ts:59-72). Off Bun it REFUSES, rather than reach http://localhost:80.
140
- */
141
- export declare const mint: (target: ApiTarget, role: PveRole, env?: BaoEnvironment) => Effect.Effect<{
142
- leaseSeconds: number;
143
- secret: string;
144
- tokenId: string;
145
- }, Error, HttpClient.HttpClient>;
146
- /**
147
- * The header PVE wants. `PVEAPIToken=<tokenid>=<secret>`.
148
- *
149
- * ⚠️ THE SEPARATOR IS `=`, NOT `:`. Proxmox rejects the colon form with a 401 that says only
150
- * "authentication failure", which reads as a bad credential rather than as a malformed header.
151
- */
152
- export declare const authorization: (credential: PveCredential, target: ApiTarget) => string;
153
115
  //# sourceMappingURL=credentials.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/proxmox/credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAIxC,OAAO,KAAK,UAAU,MAAM,iCAAiC,CAAC;AAG9D;;;;;;;;;;;;GAYG;AACH,uFAAuF;AACvF,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,WAAW,CAAC;AAE3C;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;CACxB,CAAC;AAEF,oFAAoF;AACpF,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;CACxB,CAAC;AAEF,oGAAoG;AACpG,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAE9C;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iEAAiE;IACjE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF,iGAAiG;AACjG,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AAM1E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,IAAI,WAAY,SAAS,QAAQ,OAAO,QAAO,cAAc;;;;gCAuFtE,CAAC;AAEL;;;;;GAKG;AACH,eAAO,MAAM,aAAa,eAAgB,aAAa,UAAU,SAAS,KAAG,MAGf,CAAC"}
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/proxmox/credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH;;;;;;;;;;;;GAYG;AACH,uFAAuF;AACvF,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,WAAW,CAAC;AAE3C;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;CACxB,CAAC;AAEF,oFAAoF;AACpF,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;CACxB,CAAC;AAEF,oGAAoG;AACpG,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAE9C;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iEAAiE;IACjE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B,CAAC;AAEF,iGAAiG;AACjG,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Vendor-constraint guards (constraint-guard.ts) for a distilled-backed family — the seam
3
+ * acl.ts's own local `guardWrite` established (acl-wire.ts), generalized once a second family
4
+ * (Group) needed the SAME create/update split `resource.ts`'s `specGuards` (resource-guard.ts)
5
+ * gives every family still on `client.ts`. `codegen/constraints.ts` scans this package's SOURCE
6
+ * TEXT for the endpoint-key strings a caller passes here, so a family switching to this helper
7
+ * changes nothing about which vendor rules apply — same keys, same generated tables.
8
+ *
9
+ * ★ WHY `asForm` IS THE ONLY TRANSLATION NEEDED. Distilled's generated request types for every
10
+ * PVE form-urlencoded operation are already `Record<string, string | undefined>` — the SAME
11
+ * shape `PveForm`/`guardForm` want, minus the `?`. There is no JSON vs form-encoding gap to
12
+ * bridge here the way client.ts's `pve()` had to.
13
+ */
14
+ import type * as Effect from 'effect/Effect';
15
+ import type { EndpointKey } from './constraints.ts';
16
+ /**
17
+ * Drops non-string fields — distilled's request type carries `?`, `guardForm` wants a plain
18
+ * form. ⚠️ `body: object`, NOT `Record<string, string | undefined>`: distilled's generated
19
+ * request types are `interface`s with no index signature, so TypeScript refuses that stricter
20
+ * parameter type for every one of them ("index signature ... is missing") even though every
21
+ * field they declare fits it. `object` accepts any of them; the cast below is where the shape
22
+ * is actually asserted, once, rather than at every call site.
23
+ */
24
+ export declare const asForm: (body: object) => Record<string, string>;
25
+ /**
26
+ * `presence`: whether a CREATE is really about to happen (required fields are enforced) or the
27
+ * form is only being value-checked in passing — see resource-guard.ts's own header on why this
28
+ * is not "this is the create form" but "a create is really about to happen".
29
+ */
30
+ export declare const guardWrite: (endpoint: EndpointKey, body: object, presence: boolean) => Effect.Effect<void>;
31
+ //# sourceMappingURL=distilled-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distilled-guard.d.ts","sourceRoot":"","sources":["../../src/proxmox/distilled-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAC;AAE7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,SAAU,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAKxD,CAAC;AAEJ;;;;GAIG;AACH,eAAO,MAAM,UAAU,aACX,WAAW,QACf,MAAM,YACF,OAAO,KAChB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAgD,CAAC"}