@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.
- package/dist/proxmox/acl-wire.d.ts +26 -0
- package/dist/proxmox/acl-wire.d.ts.map +1 -0
- package/dist/proxmox/acl.d.ts.map +1 -1
- package/dist/proxmox/api-token-form.d.ts +28 -26
- package/dist/proxmox/api-token-form.d.ts.map +1 -1
- package/dist/proxmox/api-token.d.ts +48 -89
- package/dist/proxmox/api-token.d.ts.map +1 -1
- package/dist/proxmox/ceph-fs-wire.d.ts +2 -2
- package/dist/proxmox/ceph-fs-wire.d.ts.map +1 -1
- package/dist/proxmox/ceph-osd-tree.d.ts +1 -1
- package/dist/proxmox/ceph-osd-tree.d.ts.map +1 -1
- package/dist/proxmox/ceph-osd-write.d.ts +2 -2
- package/dist/proxmox/ceph-osd-write.d.ts.map +1 -1
- package/dist/proxmox/ceph-pool-settle.d.ts +1 -1
- package/dist/proxmox/ceph-pool-settle.d.ts.map +1 -1
- package/dist/proxmox/client.d.ts +2 -2
- package/dist/proxmox/client.d.ts.map +1 -1
- package/dist/proxmox/credential-errors.d.ts +27 -0
- package/dist/proxmox/credential-errors.d.ts.map +1 -0
- package/dist/proxmox/credentials.d.ts +0 -38
- package/dist/proxmox/credentials.d.ts.map +1 -1
- package/dist/proxmox/distilled-guard.d.ts +31 -0
- package/dist/proxmox/distilled-guard.d.ts.map +1 -0
- package/dist/proxmox/distilled-pve.d.ts +11 -4
- package/dist/proxmox/distilled-pve.d.ts.map +1 -1
- package/dist/proxmox/generated/constraints/index.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-access.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-access.d.ts.map +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-backup.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-ceph.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-firewall.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-ha.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-metrics.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-notifications.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-replication.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-cluster-sdn.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-ceph.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-disks.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-lxc.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-network.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-nodes-qemu.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-pools.d.ts +1 -1
- package/dist/proxmox/generated/constraints/pve-storage.d.ts +1 -1
- package/dist/proxmox/group-wire.d.ts +29 -0
- package/dist/proxmox/group-wire.d.ts.map +1 -0
- package/dist/proxmox/group.d.ts +20 -24
- package/dist/proxmox/group.d.ts.map +1 -1
- package/dist/proxmox/index.js +725 -509
- package/dist/proxmox/index.js.map +40 -33
- package/dist/proxmox/lease-cache.d.ts +1 -1
- package/dist/proxmox/lease-cache.d.ts.map +1 -1
- package/dist/proxmox/lxc-lifecycle.d.ts +5 -5
- package/dist/proxmox/lxc-lifecycle.d.ts.map +1 -1
- package/dist/proxmox/mint.d.ts +50 -0
- package/dist/proxmox/mint.d.ts.map +1 -0
- package/dist/proxmox/network-apply-read.d.ts +2 -2
- package/dist/proxmox/network-apply-read.d.ts.map +1 -1
- package/dist/proxmox/pbs-notification-target-lifecycle.d.ts +2 -2
- package/dist/proxmox/pbs-sync-job-form.d.ts +2 -2
- package/dist/proxmox/provision-cli-fake.d.ts.map +1 -1
- package/dist/proxmox/resource.d.ts +4 -4
- package/dist/proxmox/role-wire.d.ts +28 -0
- package/dist/proxmox/role-wire.d.ts.map +1 -0
- package/dist/proxmox/role.d.ts +36 -52
- package/dist/proxmox/role.d.ts.map +1 -1
- package/dist/proxmox/sdn-apply-read.d.ts +1 -1
- package/dist/proxmox/sdn-apply-read.d.ts.map +1 -1
- package/dist/proxmox/unreadable-read.d.ts +50 -0
- package/dist/proxmox/unreadable-read.d.ts.map +1 -0
- package/dist/proxmox/user-wire.d.ts +18 -0
- package/dist/proxmox/user-wire.d.ts.map +1 -0
- package/dist/proxmox/user.d.ts +25 -32
- package/dist/proxmox/user.d.ts.map +1 -1
- package/dist/proxmox/zfs-pool-write.d.ts +2 -2
- package/dist/proxmox/zfs-pool-write.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/proxmox/acl-wire.ts +83 -0
- package/src/proxmox/acl.ts +29 -82
- package/src/proxmox/adopt-noop.test.ts +18 -0
- package/src/proxmox/api-token-adopt.test.ts +28 -12
- package/src/proxmox/api-token-form.ts +50 -93
- package/src/proxmox/api-token.ts +149 -135
- package/src/proxmox/client.ts +2 -7
- package/src/proxmox/constraints-forms.test.ts +7 -27
- package/src/proxmox/credential-errors.ts +33 -0
- package/src/proxmox/credentials.test.ts +29 -3
- package/src/proxmox/credentials.ts +4 -134
- package/src/proxmox/distilled-guard.ts +42 -0
- package/src/proxmox/distilled-pve.ts +15 -4
- package/src/proxmox/generated/constraints/index.ts +1 -1
- package/src/proxmox/generated/constraints/pve-access.ts +1 -4
- package/src/proxmox/generated/constraints/pve-cluster-backup.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-ceph.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-firewall.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-ha.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-metrics.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-notifications.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-replication.ts +1 -1
- package/src/proxmox/generated/constraints/pve-cluster-sdn.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-ceph.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-disks.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-lxc.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-network.ts +1 -1
- package/src/proxmox/generated/constraints/pve-nodes-qemu.ts +1 -1
- package/src/proxmox/generated/constraints/pve-pools.ts +1 -1
- package/src/proxmox/generated/constraints/pve-storage.ts +1 -1
- package/src/proxmox/group-wire.ts +63 -0
- package/src/proxmox/group.test.ts +110 -0
- package/src/proxmox/group.ts +135 -105
- package/src/proxmox/lease-cache.ts +2 -1
- package/src/proxmox/lxc-lifecycle.ts +2 -1
- package/src/proxmox/mint.ts +158 -0
- package/src/proxmox/network-apply.ts +1 -1
- package/src/proxmox/provision-cli-fake.ts +11 -0
- package/src/proxmox/provision-declare.test.ts +6 -1
- package/src/proxmox/role-wire.ts +49 -0
- package/src/proxmox/role.test.ts +89 -0
- package/src/proxmox/role.ts +147 -106
- package/src/proxmox/unreadable-read.test.ts +83 -0
- package/src/proxmox/unreadable-read.ts +60 -0
- package/src/proxmox/user-wire.ts +112 -0
- package/src/proxmox/user.test.ts +142 -0
- package/src/proxmox/user.ts +132 -129
|
@@ -94,5 +94,5 @@ export declare const makeLeases: <E, R>(mintFor: (key: LeaseKey) => Effect.Effec
|
|
|
94
94
|
* ★ client.ts is the one place that decides to use the cache. `mint` stays exported and unchanged
|
|
95
95
|
* for the caller that reasons about identity rather than cost — network-apply.ts.
|
|
96
96
|
*/
|
|
97
|
-
export declare const leased: (target: ApiTarget, role: PveRole) => Effect.Effect<PveCredential, Error, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
97
|
+
export declare const leased: (target: ApiTarget, role: PveRole) => Effect.Effect<PveCredential, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
98
98
|
//# sourceMappingURL=lease-cache.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lease-cache.d.ts","sourceRoot":"","sources":["../../src/proxmox/lease-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,IAAI,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,KAAK,OAAO,
|
|
1
|
+
{"version":3,"file":"lease-cache.d.ts","sourceRoot":"","sources":["../../src/proxmox/lease-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,IAAI,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAgBpF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;CACtC,CAAC;AAQF;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,SAAU,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,KAAG,QAAQ,CAAC,QAG3D,CAAC;AAEpB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,QAAQ,KAAK,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC,CAAC,4EACX,CAAC;AASrF;;;;;;GAMG;AACH,eAAO,MAAM,MAAM,WAAY,SAAS,QAAQ,OAAO,qJAA2C,CAAC"}
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* a cached lease can be handed out with 60s left (lease-cache.ts).
|
|
25
25
|
*/
|
|
26
26
|
import * as Effect from 'effect/Effect';
|
|
27
|
-
import {
|
|
27
|
+
import type { PveTarget } from './credentials.ts';
|
|
28
28
|
import { type LxcChange } from './lxc-judge.ts';
|
|
29
29
|
import type { LxcAttributes, LxcProps } from './lxc-props.ts';
|
|
30
30
|
/** A plan-time or apply-time refusal. Nothing was written when one of these is raised. */
|
|
@@ -39,10 +39,10 @@ export type LxcWhere = {
|
|
|
39
39
|
};
|
|
40
40
|
export declare const guestPath: (where: LxcWhere) => string;
|
|
41
41
|
/** The live config, or undefined when no guest holds this vmid anywhere in the cluster. */
|
|
42
|
-
export declare const readLive: (where: LxcWhere) => Effect.Effect<Record<string, unknown> | undefined, Error | LxcRefusedError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
42
|
+
export declare const readLive: (where: LxcWhere) => Effect.Effect<Record<string, unknown> | undefined, Error | LxcRefusedError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
43
43
|
export declare const attributesOf: (where: LxcWhere, live: Record<string, unknown>) => LxcAttributes;
|
|
44
44
|
/** POST the create and wait for the template to unpack. ⛔ Refusals are the caller's to check. */
|
|
45
|
-
export declare const createGuest: (props: LxcProps) => Effect.Effect<undefined, Error | LxcRefusedError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
45
|
+
export declare const createGuest: (props: LxcProps) => Effect.Effect<undefined, Error | LxcRefusedError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
46
46
|
/**
|
|
47
47
|
* Apply a judged change: the config PUT first, then each resize.
|
|
48
48
|
* ⚠️ IN THAT ORDER BECAUSE A MOUNT POINT'S PUT CARRIES ITS LIVE `size=`, and the resize rewrites it.
|
|
@@ -53,7 +53,7 @@ export declare const createGuest: (props: LxcProps) => Effect.Effect<undefined,
|
|
|
53
53
|
* seen by reconcile's fresh judge instead: a declared key edited meanwhile is written back to the
|
|
54
54
|
* declaration (even after a plan that warned of nothing), an undeclared one is left alone.
|
|
55
55
|
*/
|
|
56
|
-
export declare const updateGuest: (props: LxcProps, change: LxcChange, digest: string) => Effect.Effect<void, Error | LxcRefusedError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
56
|
+
export declare const updateGuest: (props: LxcProps, change: LxcChange, digest: string) => Effect.Effect<void, Error | LxcRefusedError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
57
57
|
/**
|
|
58
58
|
* ⛔ NO `force`, NO `purge`, NO STOP FIRST. PVE refuses to destroy a running or protected guest,
|
|
59
59
|
* and that refusal is kept: stopping a guest so a delete can proceed is an operator's decision.
|
|
@@ -64,5 +64,5 @@ export declare const updateGuest: (props: LxcProps, change: LxcChange, digest: s
|
|
|
64
64
|
* first; one that no longer matches is refused with the keys that differ, and deleting it (or
|
|
65
65
|
* declaring it again) is the operator's call.
|
|
66
66
|
*/
|
|
67
|
-
export declare const destroyGuest: (where: LxcWhere, declared: LxcProps) => Effect.Effect<undefined, Error | LxcRefusedError, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
67
|
+
export declare const destroyGuest: (where: LxcWhere, declared: LxcProps) => Effect.Effect<undefined, Error | LxcRefusedError | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
68
68
|
//# sourceMappingURL=lxc-lifecycle.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lxc-lifecycle.d.ts","sourceRoot":"","sources":["../../src/proxmox/lxc-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAIxC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"lxc-lifecycle.d.ts","sourceRoot":"","sources":["../../src/proxmox/lxc-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAIxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGlD,OAAO,EAAE,KAAK,SAAS,EAAS,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAK9D,0FAA0F;AAC1F,qBAAa,eAAgB,SAAQ,KAAK;IACxC,SAAkB,IAAI,qBAAqB;CAC5C;AAED,6DAA6D;AAC7D,MAAM,MAAM,QAAQ,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpG,eAAO,MAAM,SAAS,UAAW,QAAQ,WAAoD,CAAC;AAgC9F,2FAA2F;AAC3F,eAAO,MAAM,QAAQ,UAAW,QAAQ,6LAqCpC,CAAC;AAEL,eAAO,MAAM,YAAY,UAAW,QAAQ,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,aAK5E,CAAC;AAgCH,iGAAiG;AACjG,eAAO,MAAM,WAAW,UAAW,QAAQ,mKAmBvC,CAAC;AAEL;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,UAAW,QAAQ,UAAU,SAAS,UAAU,MAAM,8JAyB1E,CAAC;AAEL;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,UAAW,QAAQ,YAAY,QAAQ,mKAe5D,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minting one PVE/PBS credential from OpenBao: `GET /v1/<mount>/creds/<role>`, alive for five
|
|
3
|
+
* minutes. Split out of `credentials.ts` (2026-09-24) to keep that file's TYPES under the
|
|
4
|
+
* 250-line cap once `PveCredentialDenied`'s catchers needed a real header there; the reasoning
|
|
5
|
+
* for WHY the estate mints rather than stores a token is still credentials.ts's own header.
|
|
6
|
+
*
|
|
7
|
+
* ⛔ THE SECRET NEVER TOUCHES DISK, A LOG, OR ALCHEMY STATE — see credentials.ts's ⛔. Nothing
|
|
8
|
+
* here returns it to a resource; it is used to build a header and then dropped.
|
|
9
|
+
*/
|
|
10
|
+
import * as Effect from 'effect/Effect';
|
|
11
|
+
import * as HttpClient from 'effect/unstable/http/HttpClient';
|
|
12
|
+
import { PveCredentialDenied } from './credential-errors.ts';
|
|
13
|
+
import type { ApiTarget, BaoEnvironment, PveCredential, PveRole } from './credentials.ts';
|
|
14
|
+
/**
|
|
15
|
+
* Mint one credential for `role`: `GET /v1/<mount>/creds/<role>` on OpenBao's HTTP API.
|
|
16
|
+
*
|
|
17
|
+
* 🔴 IT SHELLED OUT TO `bao read -format=json` UNTIL 2026-09-14. The case for the CLI was that one
|
|
18
|
+
* client could not disagree with `bao kv get` about what this machine may do. <estate>/openbao then
|
|
19
|
+
* learned twice what deciding by stderr costs — every failure read as absent, and two commands
|
|
20
|
+
* said "absent" in different words — so this reads STATUS CODES: 2xx is a credential, and 403
|
|
21
|
+
* (denied), 404 (no such role or mount — a mint has no "absent"), 503 (sealed) all fail.
|
|
22
|
+
* ★ THE ENVIRONMENT CONTRACT IS STILL THE CLI's, READ THE CLI's WAY, which keeps the case above
|
|
23
|
+
* true (openbao v2.6.2 api/client.go:34-66, 370, 503-507, 761-762, 776-785): BAO_AGENT_ADDR over
|
|
24
|
+
* BAO_ADDR over https://127.0.0.1:8200; BAO_NAMESPACE as X-Vault-Namespace; BAO_TOKEN as
|
|
25
|
+
* X-Vault-Token; X-Vault-Request always. <estate>/openbao/src/bao-address.ts has the long form.
|
|
26
|
+
* ★ AGENT MODE IS NO BAO_TOKEN AND NO TOKEN HEADER. An Agent or Proxy listener with
|
|
27
|
+
* `api_proxy { use_auto_auth_token = true }` (or the older `cache { … }`) substitutes its
|
|
28
|
+
* auto-auth token exactly when a request carries none — command/agentproxyshared/cache/handler.go
|
|
29
|
+
* :29-38, command/agent.go:517-541, command/agent/config/config.go:288-292, and
|
|
30
|
+
* website/content/docs/agent-and-proxy/agent/apiproxy.mdx:57-62. The CLI's token-file fallback
|
|
31
|
+
* is deliberately not read. ⚠️ So an unset BAO_TOKEN aimed at a SERVER rather than an agent is a
|
|
32
|
+
* 403, which reads like a missing grant rather than a missing variable.
|
|
33
|
+
* ★ UNIX SOCKETS: `unix:///path` is plain HTTP to `localhost` over that socket, as the CLI does it
|
|
34
|
+
* (api/client.go:654-667). Bun's fetch takes a `unix` option; `FetchHttpClient.RequestInit` is
|
|
35
|
+
* Effect's documented way to pass fetch options, read from the calling fiber (effect
|
|
36
|
+
* FetchHttpClient.ts:59-72). Off Bun it REFUSES, rather than reach http://localhost:80.
|
|
37
|
+
*/
|
|
38
|
+
export declare const mint: (target: ApiTarget, role: PveRole, env?: BaoEnvironment) => Effect.Effect<{
|
|
39
|
+
leaseSeconds: number;
|
|
40
|
+
secret: string;
|
|
41
|
+
tokenId: string;
|
|
42
|
+
}, Error | PveCredentialDenied, HttpClient.HttpClient>;
|
|
43
|
+
/**
|
|
44
|
+
* The header PVE wants. `PVEAPIToken=<tokenid>=<secret>`.
|
|
45
|
+
*
|
|
46
|
+
* ⚠️ THE SEPARATOR IS `=`, NOT `:`. Proxmox rejects the colon form with a 401 that says only
|
|
47
|
+
* "authentication failure", which reads as a bad credential rather than as a malformed header.
|
|
48
|
+
*/
|
|
49
|
+
export declare const authorization: (credential: PveCredential, target: ApiTarget) => string;
|
|
50
|
+
//# sourceMappingURL=mint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mint.d.ts","sourceRoot":"","sources":["../../src/proxmox/mint.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAIxC,OAAO,KAAK,UAAU,MAAM,iCAAiC,CAAC;AAE9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAM1F;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,IAAI,WAAY,SAAS,QAAQ,OAAO,QAAO,cAAc;;;;sDAoGtE,CAAC;AAEL;;;;;GAKG;AACH,eAAO,MAAM,aAAa,eAAgB,aAAa,UAAU,SAAS,KAAG,MAGf,CAAC"}
|
|
@@ -54,7 +54,7 @@ export type ClusterHealth = {
|
|
|
54
54
|
*/
|
|
55
55
|
export declare const pendingLines: (diff: string) => number;
|
|
56
56
|
/** How many staged lines this node is carrying. Zero is the only settled value. */
|
|
57
|
-
export declare const pendingCount: (target: PveTarget, node: string) => Effect.Effect<number, Error, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
57
|
+
export declare const pendingCount: (target: PveTarget, node: string) => Effect.Effect<number, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
58
58
|
/**
|
|
59
59
|
* Why the cluster is not healthy, or `undefined` when it is.
|
|
60
60
|
*
|
|
@@ -69,7 +69,7 @@ export declare const pendingCount: (target: PveTarget, node: string) => Effect.E
|
|
|
69
69
|
* pools losing min_size; reloading another node's networking while it is out is the move that
|
|
70
70
|
* completes the outage. Bring it back, or apply by hand with the cluster in front of you.
|
|
71
71
|
*/
|
|
72
|
-
export declare const degradedReason: (target: PveTarget) => Effect.Effect<string | undefined, Error, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
72
|
+
export declare const degradedReason: (target: PveTarget) => Effect.Effect<string | undefined, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
73
73
|
/**
|
|
74
74
|
* ⛔ NOT AN EXITSTATUS PVE CAN RETURN, AND THAT IS THE POINT. The caller compares against `'OK'`;
|
|
75
75
|
* these two say WHY the answer is not OK without needing a second branch for "we do not know".
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network-apply-read.d.ts","sourceRoot":"","sources":["../../src/proxmox/network-apply-read.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAatE,oGAAoG;AACpG,MAAM,MAAM,aAAa,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AA0B7E;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,SAAU,MAAM,WAWxC,CAAC;AAEF,mFAAmF;AACnF,eAAO,MAAM,YAAY,WAAY,SAAS,QAAQ,MAAM,
|
|
1
|
+
{"version":3,"file":"network-apply-read.d.ts","sourceRoot":"","sources":["../../src/proxmox/network-apply-read.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAatE,oGAAoG;AACpG,MAAM,MAAM,aAAa,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AA0B7E;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,SAAU,MAAM,WAWxC,CAAC;AAEF,mFAAmF;AACnF,eAAO,MAAM,YAAY,WAAY,SAAS,QAAQ,MAAM,8IACH,CAAC;AAiC1D;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,WAAY,SAAS,0JAO7C,CAAC;AAEJ;;;GAGG;AACH,eAAO,MAAM,WAAW,0FACiE,CAAC;AAY1F;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,SAAS,WACZ,SAAS,cACL,aAAa,QACnB,MAAM,QACN,MAAM,aAEF,MAAM,uFAgCd,CAAC"}
|
|
@@ -91,10 +91,10 @@ export declare const handlers: {
|
|
|
91
91
|
header: string;
|
|
92
92
|
headerDigest: string;
|
|
93
93
|
secret: string;
|
|
94
|
-
}, Error, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
94
|
+
}, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
95
95
|
delete: ({ olds }: {
|
|
96
96
|
olds: Props;
|
|
97
|
-
}) => Effect.Effect<unknown, Error, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
97
|
+
}) => Effect.Effect<unknown, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
98
98
|
};
|
|
99
99
|
export {};
|
|
100
100
|
//# sourceMappingURL=pbs-notification-target-lifecycle.d.ts.map
|
|
@@ -75,9 +75,9 @@ export declare const handlers: {
|
|
|
75
75
|
} | undefined, never, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
76
76
|
reconcile: ({ news }: {
|
|
77
77
|
news: SyncJobProps;
|
|
78
|
-
}) => import("effect/Effect").Effect<SyncJobAttributes, Error, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
78
|
+
}) => import("effect/Effect").Effect<SyncJobAttributes, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
79
79
|
delete: ({ olds }: {
|
|
80
80
|
olds: SyncJobProps;
|
|
81
|
-
}) => import("effect/Effect").Effect<unknown, Error, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
81
|
+
}) => import("effect/Effect").Effect<unknown, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
82
82
|
};
|
|
83
83
|
//# sourceMappingURL=pbs-sync-job-form.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provision-cli-fake.d.ts","sourceRoot":"","sources":["../../src/proxmox/provision-cli-fake.ts"],"names":[],"mappings":"AAkBA,MAAM,MAAM,OAAO,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AACF,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AACF,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,GAAG,EAAE,QAAQ,EAAE,CAAC;CACjB,CAAC;AAEF,4FAA4F;AAC5F,eAAO,MAAM,YAAY,QAAO,QAc9B,CAAC;AAIH,mGAAmG;AACnG,eAAO,MAAM,OAAO,UAAW,QAAQ,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"provision-cli-fake.d.ts","sourceRoot":"","sources":["../../src/proxmox/provision-cli-fake.ts"],"names":[],"mappings":"AAkBA,MAAM,MAAM,OAAO,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AACF,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AACF,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,GAAG,EAAE,QAAQ,EAAE,CAAC;CACjB,CAAC;AAEF,4FAA4F;AAC5F,eAAO,MAAM,YAAY,QAAO,QAc9B,CAAC;AAIH,mGAAmG;AACnG,eAAO,MAAM,OAAO,UAAW,QAAQ,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAiC/D,CAAC;AA0FF,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,QAAQ,CAAC;CACjB,CAAC;AAEF,6EAA6E;AAC7E,eAAO,MAAM,SAAS,WAAkB,MAAM,SAAS,QAAQ,KAAG,OAAO,CAAC,SAAS,CAkClF,CAAC"}
|
|
@@ -19,13 +19,13 @@ export declare const pveOperations: <Props extends WithApiTarget, Attributes>(sp
|
|
|
19
19
|
} | {
|
|
20
20
|
readonly action: 'replace';
|
|
21
21
|
} | undefined, never, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
22
|
-
reconcile: (news: Props) => Effect.Effect<Attributes & ({} | null), Error, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
22
|
+
reconcile: (news: Props) => Effect.Effect<Attributes & ({} | null), Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
23
23
|
/**
|
|
24
24
|
* ⚠️ PVE REFUSES TO DELETE THINGS THAT ARE STILL IN USE — a pool holding guests, a storage with
|
|
25
25
|
* volumes. That refusal is the cluster declining to orphan something because a line left a
|
|
26
26
|
* file, so it is surfaced as-is rather than retried with a force flag.
|
|
27
27
|
*/
|
|
28
|
-
destroy: (olds: Props) => Effect.Effect<unknown, Error, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
28
|
+
destroy: (olds: Props) => Effect.Effect<unknown, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
29
29
|
};
|
|
30
30
|
/**
|
|
31
31
|
* The five provider handlers for a spec'd PVE object, wired once.
|
|
@@ -77,9 +77,9 @@ export declare const pveHandlers: <Props extends WithApiTarget, Attributes exten
|
|
|
77
77
|
} | undefined, never, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
78
78
|
reconcile: ({ news }: {
|
|
79
79
|
news: Props;
|
|
80
|
-
}) => Effect.Effect<Attributes, Error, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
80
|
+
}) => Effect.Effect<Attributes, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
81
81
|
delete: ({ olds }: {
|
|
82
82
|
olds: Props;
|
|
83
|
-
}) => Effect.Effect<unknown, Error, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
83
|
+
}) => Effect.Effect<unknown, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
84
84
|
};
|
|
85
85
|
//# sourceMappingURL=resource.d.ts.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Proxmox.Role`'s wire shape: PVE's create/update forms and how a live list row becomes
|
|
3
|
+
* attributes. Split out of role.ts (2026-09-24, the distilled migration) to keep that file
|
|
4
|
+
* under the 250-line cap — the api-token.ts/api-token-form.ts seam.
|
|
5
|
+
*/
|
|
6
|
+
import type * as access from '@distilled.cloud/proxmox/access';
|
|
7
|
+
import type { RoleAttributes, RoleProps } from './role.ts';
|
|
8
|
+
export declare const ROLE_CREATE = "pve:POST /access/roles";
|
|
9
|
+
export declare const ROLE_UPDATE = "pve:PUT /access/roles/{roleid}";
|
|
10
|
+
/**
|
|
11
|
+
* The only shape two privilege sets may be compared in: sorted, de-duplicated, blanks dropped.
|
|
12
|
+
*
|
|
13
|
+
* ⚠️ THE TRIM AND THE EMPTY FILTER ARE NOT DECORATION. `'A,B,'.split(',')` yields a trailing `''`,
|
|
14
|
+
* and a hand-written list is quite likely to carry a stray space after a comma. Either one turns
|
|
15
|
+
* into a phantom member that no live answer can contain, so `matches` would be false on every
|
|
16
|
+
* plan and the deploy would rewrite the role to exactly what it already was.
|
|
17
|
+
*/
|
|
18
|
+
export declare const canonical: (privs: readonly string[]) => string[];
|
|
19
|
+
export declare const createForm: (props: RoleProps) => access.CreateAccessRoleRequest;
|
|
20
|
+
/**
|
|
21
|
+
* ⚠️ NO `append` FIELD, DELIBERATELY. Sending `append=1` would make every update additive, so a
|
|
22
|
+
* privilege could be granted from here but never taken away — see role.ts's own header.
|
|
23
|
+
*/
|
|
24
|
+
export declare const updateForm: (props: RoleProps) => access.PutAccessRoleRequest;
|
|
25
|
+
export declare const find: (rows: readonly access.ListAccessRolesResponseBodyItem[], roleid: string) => access.ListAccessRolesResponseBodyItem | undefined;
|
|
26
|
+
export declare const attributesOf: (row: access.ListAccessRolesResponseBodyItem, props: RoleProps) => RoleAttributes;
|
|
27
|
+
export declare const matches: (attributes: RoleAttributes, props: RoleProps) => boolean;
|
|
28
|
+
//# sourceMappingURL=role-wire.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"role-wire.d.ts","sourceRoot":"","sources":["../../src/proxmox/role-wire.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,KAAK,MAAM,MAAM,iCAAiC,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3D,eAAO,MAAM,WAAW,2BAA2B,CAAC;AACpD,eAAO,MAAM,WAAW,mCAAmC,CAAC;AAE5D;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,UAAW,SAAS,MAAM,EAAE,KAAG,MAAM,EAC8B,CAAC;AAE1F,eAAO,MAAM,UAAU,UAAW,SAAS,KAAG,MAAM,CAAC,uBAGnD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,UAAU,UAAW,SAAS,KAAG,MAAM,CAAC,oBAGnD,CAAC;AAEH,eAAO,MAAM,IAAI,SAAU,SAAS,MAAM,CAAC,+BAA+B,EAAE,UAAU,MAAM,uDACjD,CAAC;AAE5C,eAAO,MAAM,YAAY,QAClB,MAAM,CAAC,+BAA+B,SACpC,SAAS,KACf,cAGD,CAAC;AAEH,eAAO,MAAM,OAAO,eAAgB,cAAc,SAAS,SAAS,YACQ,CAAC"}
|
package/dist/proxmox/role.d.ts
CHANGED
|
@@ -2,53 +2,54 @@
|
|
|
2
2
|
* `Proxmox.Role` — a PVE role: one name, one set of privileges. The object every other resource
|
|
3
3
|
* in this package stands on, because a role is what the provision credential actually holds.
|
|
4
4
|
*
|
|
5
|
-
* ★ THIS IS WHERE pool.ts's ⚠️ STOPS BEING A MEMORY.
|
|
6
|
-
*
|
|
7
|
-
* that a human widened the role over SSH with `pveum role modify`. Prose cannot be planned
|
|
8
|
-
* against: it goes stale the first time somebody edits the role in the UI and tells nobody.
|
|
9
|
-
* Declared here, the same fact is a diff — the privileges the role is SUPPOSED to hold are read
|
|
10
|
-
* off the cluster on every plan, and a hand edit shows up as `1 to update` rather than as a 403
|
|
11
|
-
* six weeks later in the middle of something else.
|
|
12
|
-
*
|
|
13
|
-
* ⛔ THE INDEX AND THE ITEM DISAGREE ABOUT WHAT `privs` IS, AND MISSING THAT COSTS A DIFF THAT
|
|
14
|
-
* NEVER CONVERGES. `GET /access/roles` (the index) reports each role's privileges as a COMMA
|
|
15
|
-
* STRING. `GET /access/roles/{roleid}` — the path this resource reads — returns a privilege MAP
|
|
16
|
-
* instead, `{"VM.Allocate":1,"Sys.Audit":1,…}`, and its key order is a Perl hash's order, so it
|
|
17
|
-
* is not stable between two calls to the same endpoint. Compare the raw string, or the raw
|
|
18
|
-
* object, or the keys in the order they arrived, and every plan reports an update forever.
|
|
19
|
-
* `canonical` below is the whole answer: both sides become a sorted, de-duplicated set before
|
|
20
|
-
* anything is compared, and `attributes` STORES the sorted form so Alchemy's state does not
|
|
21
|
-
* churn either.
|
|
5
|
+
* ★ THIS IS WHERE pool.ts's ⚠️ STOPS BEING A MEMORY. Declared here, a hand edit shows up as
|
|
6
|
+
* `1 to update` rather than as a 403 six weeks later in the middle of something else.
|
|
22
7
|
*
|
|
23
8
|
* ⚠️ A DECLARATION REPLACES THE PRIVILEGE SET; IT DOES NOT ADD TO IT. `PUT /access/roles/{roleid}`
|
|
24
|
-
* accepts an `append` flag and this resource deliberately never sends it — with
|
|
25
|
-
* could only ever grow,
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* type it from memory.
|
|
9
|
+
* accepts an `append` flag and this resource deliberately never sends it (role-wire.ts) — with
|
|
10
|
+
* append a role could only ever grow, the same perpetual diff by a different road. The
|
|
11
|
+
* consequence: anything a human added by hand is REVOKED on the next deploy unless it is in
|
|
12
|
+
* `privs`. Copy the live set out of `pveum role list` before declaring a role that already
|
|
13
|
+
* exists; do not type it from memory.
|
|
30
14
|
*
|
|
31
15
|
* ⛔ A ROLE CAN LOCK ITS OWN PROVIDER OUT, AND NOTHING IN THIS PACKAGE CAN UNDO IT. Reconcile runs
|
|
32
16
|
* as the provision credential, and that credential holds a role. Declare THAT role without the
|
|
33
17
|
* privileges the provider needs — `Sys.Modify` on `/access` above all — and the write succeeds,
|
|
34
18
|
* after which every later plan reads 403 and the repair has to happen out of band as `root@pam`
|
|
35
|
-
* over SSH.
|
|
36
|
-
* down at the bottom of this comment rather than left to be rediscovered from an error message.
|
|
19
|
+
* over SSH.
|
|
37
20
|
*
|
|
38
21
|
* ⚠️ PVE REFUSES TO EDIT ITS OWN BUILT-IN ROLES (`Administrator`, `NoAccess`, the `PVE*` set), and
|
|
39
|
-
* the
|
|
40
|
-
*
|
|
41
|
-
*
|
|
22
|
+
* the LIST read (below) DOES carry the `special` flag that marks them, unlike the item endpoint
|
|
23
|
+
* this file used before the distilled migration — `role-wire.ts`'s `attributesOf` does not use
|
|
24
|
+
* it, but a caller reading `list`'s own answer could. A declaration aimed at a built-in role
|
|
25
|
+
* still reads back cleanly and fails at write time. Declare roles you own.
|
|
42
26
|
*
|
|
43
27
|
* ★ PRIVILEGES A RECONCILE NEEDS: `Sys.Audit` on `/access` to read and diff, `Sys.Modify` on
|
|
44
|
-
* `/access` to create, update or delete. Not `Permissions.Modify` —
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
28
|
+
* `/access` to create, update or delete. Not `Permissions.Modify` — that is a different object.
|
|
29
|
+
*
|
|
30
|
+
* ★ READ VIA THE LIST, NOT THE ITEM — A DELIBERATE CHANGE FROM THE PRE-MIGRATION CODE, AND THE
|
|
31
|
+
* REASON IS THE ITEM'S OWN GENERATED SCHEMA. `access.getAccessRole`'s response
|
|
32
|
+
* (`GetAccessRoleResponse`) enumerates a FIXED list of ~47 known privilege field names
|
|
33
|
+
* (`Sys_Modify`, `VM_Allocate`, …), each its own optional property — MEASURED in
|
|
34
|
+
* `@distilled.cloud/proxmox`'s generated `access.ts`. A privilege this package's generator did
|
|
35
|
+
* not know about would silently not appear as a field at all, and this file's old `privs: []`
|
|
36
|
+
* reconstruction would drop it from state without a diff ever seeing the loss. The LIST read
|
|
37
|
+
* (`access.listAccessRoles`) answers `privs` as the SAME plain comma string PVE's item read
|
|
38
|
+
* also disagreed with the index about pre-migration — a shape with no fixed enumeration to fall
|
|
39
|
+
* behind. `find` below (role-wire.ts) does the item-read's old job client-side.
|
|
40
|
+
* ⚠️ REASONED, NOT MEASURED, THAT THE LIST READ NEEDS NO MORE THAN `read`'s AUDITOR SHAPE. The
|
|
41
|
+
* item read's own privilege check (`Sys.Audit` on `/access`) was measured; the list's was not
|
|
42
|
+
* separately checked, but PVE's own convention is that an index read is never MORE restrictive
|
|
43
|
+
* than its item. `readRole` stays at the default `read` on that basis, same as before.
|
|
44
|
+
*
|
|
45
|
+
* ★ MIGRATED OFF `client.ts`'s generic `pve()`/`pveHandlers` ONTO `@distilled.cloud/proxmox`'s
|
|
46
|
+
* typed `access.listAccessRoles`/`createAccessRole`/`putAccessRole`/`deleteAccessRole`
|
|
47
|
+
* (2026-09-24, decision 43's proxmox walk-down). `distilled-pve.ts`'s `runPve` replaces
|
|
48
|
+
* `pve()`; the cries-wolf fix is wired the same way as acl.ts, group.ts and user.ts.
|
|
48
49
|
*/
|
|
49
50
|
import { Resource } from 'alchemy';
|
|
50
51
|
import * as Provider from 'alchemy/Provider';
|
|
51
|
-
import {
|
|
52
|
+
import type { PveRequirements, WithTarget } from './resource-spec.ts';
|
|
52
53
|
export interface RoleProps extends WithTarget {
|
|
53
54
|
/**
|
|
54
55
|
* PVE's primary key for a role.
|
|
@@ -60,13 +61,11 @@ export interface RoleProps extends WithTarget {
|
|
|
60
61
|
roleid: string;
|
|
61
62
|
/**
|
|
62
63
|
* The COMPLETE privilege set, e.g. `['VM.Allocate', 'VM.Audit', 'Sys.Audit']`. Order and
|
|
63
|
-
* duplicates do not matter — see the
|
|
64
|
+
* duplicates do not matter — see the header — but completeness does: this list is the
|
|
64
65
|
* role, not an addition to it.
|
|
65
66
|
*
|
|
66
67
|
* ⚠️ DECLARE AT LEAST ONE. A role with no privileges grants nothing and reads back as an empty
|
|
67
|
-
* document, which
|
|
68
|
-
* there — reconcile would then refuse with its "the write returned no error but the object is
|
|
69
|
-
* still absent" message, which is true of the read and misleading about the cause.
|
|
68
|
+
* document, which reconcile cannot tell apart from an object that is not there.
|
|
70
69
|
*/
|
|
71
70
|
privs: string[];
|
|
72
71
|
}
|
|
@@ -78,20 +77,5 @@ export interface RoleAttributes {
|
|
|
78
77
|
export interface ProxmoxRole extends Resource<'Proxmox.Role', RoleProps, RoleAttributes, never, PveRequirements> {
|
|
79
78
|
}
|
|
80
79
|
export declare const ProxmoxRole: import("alchemy").ResourceClass<ProxmoxRole>;
|
|
81
|
-
/**
|
|
82
|
-
* ⛔ AN EMPTY LIST, AND NOWHERE DOES IT MATTER MORE. `GET /access/roles` returns every
|
|
83
|
-
* role on the cluster, PVE's own built-ins included. Returning them would invite Alchemy
|
|
84
|
-
* to adopt `Administrator` — and therefore one day to narrow or delete it. Adoption is
|
|
85
|
-
* an explicit act, here as everywhere else in this package.
|
|
86
|
-
|
|
87
|
-
*
|
|
88
|
-
* ⛔ DO NOT CARRY THE FACTORY'S REASSURANCE OVER TO THIS ONE. `destroy` there notes that
|
|
89
|
-
* PVE refuses to delete things still in use — a pool holding guests, a storage with
|
|
90
|
-
* volumes — and a role is NOT protected that way. Whoever is bound to the role loses
|
|
91
|
-
* those privileges the moment it goes, and the credential this provider runs with is
|
|
92
|
-
* bound through exactly such a binding. Checking who holds a role before removing it is
|
|
93
|
-
* an operator's job, and it is not done here on their behalf while they read a diff.
|
|
94
|
-
|
|
95
|
-
*/
|
|
96
80
|
export declare const ProxmoxRoleProvider: () => import("effect/Layer").Layer<Provider.Provider<ProxmoxRole>, never, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
97
81
|
//# sourceMappingURL=role.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"role.d.ts","sourceRoot":"","sources":["../../src/proxmox/role.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"role.d.ts","sourceRoot":"","sources":["../../src/proxmox/role.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAa7C,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAStE,MAAM,WAAW,SAAU,SAAQ,UAAU;IAC3C;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,4FAA4F;IAC5F,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ,CAC3C,cAAc,EACd,SAAS,EACT,cAAc,EACd,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,eAAO,MAAM,WAAW,8CAAwC,CAAC;AAiBjE,eAAO,MAAM,mBAAmB,iIA+E7B,CAAC"}
|
|
@@ -76,5 +76,5 @@ export declare const canonical: (value: unknown) => string;
|
|
|
76
76
|
* Alchemy always calls it the first time a resource appears — and `PUT /cluster/sdn` regenerates
|
|
77
77
|
* `/etc/network/interfaces.d/sdn` on every node. On C1 that file carries Ceph's cluster network.
|
|
78
78
|
*/
|
|
79
|
-
export declare const sdnPendingCount: (target: PveTarget) => Effect.Effect<number, Error, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
79
|
+
export declare const sdnPendingCount: (target: PveTarget) => Effect.Effect<number, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
80
80
|
//# sourceMappingURL=sdn-apply-read.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdn-apply-read.d.ts","sourceRoot":"","sources":["../../src/proxmox/sdn-apply-read.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAwBlD;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,YAAI,mBAAmB,EAAE,iBAAiB,CAAU,CAAC;AAE5E;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe,UAAW,OAAO,KAAG,OACE,CAAC;AAqBpD;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,WACf,MAAM,GAAG,SAAS,WACjB,MAAM,GAAG,SAAS,KAC1B,MAAM,GAAG,cAIX,CAAC;AAuCF,+FAA+F;AAC/F,eAAO,MAAM,SAAS,UAAW,OAAO,KAAG,MAAyC,CAAC;AAiBrF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,WAAY,SAAS,
|
|
1
|
+
{"version":3,"file":"sdn-apply-read.d.ts","sourceRoot":"","sources":["../../src/proxmox/sdn-apply-read.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAwBlD;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,YAAI,mBAAmB,EAAE,iBAAiB,CAAU,CAAC;AAE5E;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe,UAAW,OAAO,KAAG,OACE,CAAC;AAqBpD;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,WACf,MAAM,GAAG,SAAS,WACjB,MAAM,GAAG,SAAS,KAC1B,MAAM,GAAG,cAIX,CAAC;AAuCF,+FAA+F;AAC/F,eAAO,MAAM,SAAS,UAAW,OAAO,KAAG,MAAyC,CAAC;AAiBrF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,WAAY,SAAS,8IAG9C,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The "unreadable" outcome a refused read produces — distinct from `undefined` (genuinely
|
|
3
|
+
* absent) and from a real attributes object (present) — so `diff` stops treating a REFUSED read
|
|
4
|
+
* the same as a confirmed-gone one. Fixes the "cries wolf" bug (measured 2026-09-24): on a lane
|
|
5
|
+
* whose credential cannot mint `provision`, every already-correct ACL and storage row read back
|
|
6
|
+
* as absent, and `diff` forced `update` for every one of them without comparing a single field,
|
|
7
|
+
* because `.pipe(Effect.orElseSucceed(() => undefined))` folds every failure — a genuine 404, a
|
|
8
|
+
* network blip, AND a permission refusal — into the one "absent" value `diff` cannot tell apart.
|
|
9
|
+
*
|
|
10
|
+
* ★ WHY A SENTINEL, NOT A FAILED `diff`. Upstream's `Diff` type is exactly
|
|
11
|
+
* `NoopDiff | UpdateDiff | ReplaceDiff` (`packages/alchemy/src/Diff.ts@v2.0.0-beta.79`) — there
|
|
12
|
+
* is no fourth "unreadable" action to return. And `Plan.ts`'s resource pass runs every
|
|
13
|
+
* resource's `diff` under `Effect.exit`, then FAILS THE WHOLE PLAN if even one failed
|
|
14
|
+
* (`diffFailures.length > 0` -> `Effect.failCause`, `Plan.ts@v2.0.0-beta.79` ~lines 1711-1731).
|
|
15
|
+
* So making `diff` FAIL on a refused read would not report one honest row — it would abort
|
|
16
|
+
* `bun run plan` for every OTHER resource in the stack too, worse than today's false "update".
|
|
17
|
+
* `{ action: 'noop' }` plus a logged warning is the only outcome that (a) never forces a write
|
|
18
|
+
* on a lane that cannot prove one is needed and (b) never takes the rest of the plan down with
|
|
19
|
+
* it — the "noop-with-warning" reading of the fix, over the alternative of a typed plan error.
|
|
20
|
+
*
|
|
21
|
+
* ⛔ ONLY THE CREDENTIAL DENIAL IS CAUGHT HERE. Every other read failure (a genuine
|
|
22
|
+
* `Cause.TimeoutError`, `PveClusterExhausted`, a network error) keeps folding into `undefined`
|
|
23
|
+
* exactly as it always has — this narrows ONE typed tag out of that fold, via `catchTag`, and
|
|
24
|
+
* changes nothing else about it. See credential-errors.ts's own ⛔ for why 403 alone qualifies.
|
|
25
|
+
*/
|
|
26
|
+
import * as Effect from 'effect/Effect';
|
|
27
|
+
import type { PveCredentialDenied } from './credential-errors.ts';
|
|
28
|
+
/** Distinct from `undefined` (absent) and from a real attributes object (present). */
|
|
29
|
+
export declare const UNREADABLE: unique symbol;
|
|
30
|
+
export type Unreadable = typeof UNREADABLE;
|
|
31
|
+
/**
|
|
32
|
+
* Catches ONLY `PveCredentialDenied` and turns it into the sentinel, so a caller that also
|
|
33
|
+
* `.pipe(Effect.orElseSucceed(() => undefined))` for every OTHER failure never conflates a
|
|
34
|
+
* refusal with a genuine absence. Compose this INSIDE that fold, never after it.
|
|
35
|
+
*
|
|
36
|
+
* ⚠️ `E | PveCredentialDenied` IN, `E` OUT — not a generic `E` narrowed by `Exclude`. `catchTag`
|
|
37
|
+
* needs the tag to be STATICALLY present in the error union to typecheck at all; a bare
|
|
38
|
+
* unconstrained `E` gives it nothing to match against. Every caller's `runPve` already carries
|
|
39
|
+
* `PveCredentialDenied` explicitly (distilled-pve.ts's own ★ on why), so this signature costs
|
|
40
|
+
* nothing at the call site.
|
|
41
|
+
*/
|
|
42
|
+
export declare const readOrUnreadable: <A, E, R>(effect: Effect.Effect<A, E | PveCredentialDenied, R>) => Effect.Effect<A | Unreadable, E, R>;
|
|
43
|
+
/**
|
|
44
|
+
* The warning `diff` logs when it reports `noop` for a row it could not actually read — visible
|
|
45
|
+
* in `bun run plan`'s own output (Effect's default logger), even though the Diff type has
|
|
46
|
+
* nowhere to carry the distinction through to the printed action. See the header for why a log
|
|
47
|
+
* line, not a failed diff or a fourth Diff action, is what "the plan reports" means here.
|
|
48
|
+
*/
|
|
49
|
+
export declare const unreadableWarning: (type: string, identity: string) => Effect.Effect<void>;
|
|
50
|
+
//# sourceMappingURL=unreadable-read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unreadable-read.d.ts","sourceRoot":"","sources":["../../src/proxmox/unreadable-read.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAElE,sFAAsF;AACtF,eAAO,MAAM,UAAU,eAA2B,CAAC;AACnD,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC;AAE3C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,UAC9B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,mBAAmB,EAAE,CAAC,CAAC,KACnD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,CAAC,CACkD,CAAC;AAExF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,SAAU,MAAM,YAAY,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAKlF,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Proxmox.User`'s wire shape: PVE's create/update forms and how a live item becomes
|
|
3
|
+
* attributes. Split out of user.ts (2026-09-24, the distilled migration) to keep that file
|
|
4
|
+
* under the 250-line cap — the api-token.ts/api-token-form.ts seam.
|
|
5
|
+
*/
|
|
6
|
+
import type * as access from '@distilled.cloud/proxmox/access';
|
|
7
|
+
import type { UserAttributes, UserProps } from './user.ts';
|
|
8
|
+
export declare const USER_CREATE = "pve:POST /access/users";
|
|
9
|
+
export declare const USER_UPDATE = "pve:PUT /access/users/{userid}";
|
|
10
|
+
export declare const createForm: (props: UserProps) => access.CreateAccessUserRequest;
|
|
11
|
+
export declare const updateForm: (props: UserProps) => access.PutAccessUserRequest;
|
|
12
|
+
export declare const attributesOf: (live: access.GetAccessUserResponse, props: UserProps) => UserAttributes;
|
|
13
|
+
/**
|
|
14
|
+
* ⚠️ `tokens` IS NOT COMPARED, and neither is anything create-only. What is compared is exactly
|
|
15
|
+
* what a PUT can put back; a field PVE reports but will not accept is drift nobody can fix.
|
|
16
|
+
*/
|
|
17
|
+
export declare const matches: (attributes: UserAttributes, props: UserProps) => boolean;
|
|
18
|
+
//# sourceMappingURL=user-wire.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-wire.d.ts","sourceRoot":"","sources":["../../src/proxmox/user-wire.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,KAAK,MAAM,MAAM,iCAAiC,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3D,eAAO,MAAM,WAAW,2BAA2B,CAAC;AACpD,eAAO,MAAM,WAAW,mCAAmC,CAAC;AA2D5D,eAAO,MAAM,UAAU,UAAW,SAAS,KAAG,MAAM,CAAC,uBAGnD,CAAC;AAEH,eAAO,MAAM,UAAU,UAAW,SAAS,KAAG,MAAM,CAAC,oBAGnD,CAAC;AAEH,eAAO,MAAM,YAAY,SACjB,MAAM,CAAC,qBAAqB,SAC3B,SAAS,KACf,cAgBD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,OAAO,eAAgB,cAAc,SAAS,SAAS,YAOF,CAAC"}
|
package/dist/proxmox/user.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* `Proxmox.User` — a PVE account. The identity every other resource in this package borrows.
|
|
3
3
|
*
|
|
4
4
|
* ★ THIS IS THE ONE OBJECT THAT CAN CUT THE BRANCH IT SITS ON. The user the credential mount vends
|
|
5
|
-
* tokens for, and the group whose members are allowed to mint, are what `
|
|
5
|
+
* tokens for, and the group whose members are allowed to mint, are what `credentials.ts`
|
|
6
6
|
* ultimately asks OpenBao for. A cluster rebuilt without them cannot plan ANY resource here —
|
|
7
7
|
* including the plan that would recreate them, which needs a credential to run. So this resource
|
|
8
8
|
* is drift repair for an account that already exists (comment, email, enable, expire, groups),
|
|
@@ -18,37 +18,43 @@
|
|
|
18
18
|
*
|
|
19
19
|
* ⚠️ `groups` COMES BACK AS AN ARRAY AND GOES OUT AS A COMMA STRING, and the asymmetry is the whole
|
|
20
20
|
* trap. GET answers `["a","b"]`, POST/PUT want `a,b`, and PVE returns the list in ITS order, not
|
|
21
|
-
* the declared one.
|
|
22
|
-
* the rest of time says "1 to update". Both sides are normalised to a sorted, deduplicated set
|
|
23
|
-
* below. Joining is a safe comparison precisely because a group id cannot contain a comma — the
|
|
24
|
-
* wire format is comma-separated, so PVE refuses one.
|
|
21
|
+
* the declared one. Both sides are normalised to a sorted, deduplicated set — see user-wire.ts.
|
|
25
22
|
*
|
|
26
23
|
* ⚠️ `tokens` IS NESTED AND IS NOT SETTABLE THROUGH THIS ENDPOINT. The read hands back a map of the
|
|
27
24
|
* account's API tokens; `PUT /access/users/{userid}` has no parameter for them, because they are
|
|
28
|
-
* their own objects under `.../token/{tokenid}
|
|
29
|
-
*
|
|
30
|
-
* `pool.members`. Reported, never declared.
|
|
25
|
+
* their own objects under `.../token/{tokenid}` (api-token.ts). So they are reported as an
|
|
26
|
+
* attribute and kept OUT of `matches`, exactly like `pool.members`. Reported, never declared.
|
|
31
27
|
*
|
|
32
28
|
* ⚠️ RECONCILE NEEDS PRIVILEGES A GUEST-ONLY ROLE DOES NOT HOLD, so they are stated rather than met
|
|
33
|
-
* as a 403 in the middle of a deploy (
|
|
34
|
-
* `PROVISION_PRIVILEGES` (provision-baseline.ts) carries every one of them:
|
|
29
|
+
* as a 403 in the middle of a deploy. `PROVISION_PRIVILEGES` (provision-baseline.ts) carries:
|
|
35
30
|
* · `Realm.AllocateUser` on `/access/realm/<realm>` — create and delete.
|
|
36
31
|
* · `User.Modify` on `/access/groups`, and on `/access/groups/<group>` for EVERY group named in
|
|
37
32
|
* `groups` — create, update and delete. PVE checks the groups you are granting, not just the
|
|
38
|
-
* user, so a role wide enough to edit the account can still be refused for one group
|
|
39
|
-
* list.
|
|
33
|
+
* user, so a role wide enough to edit the account can still be refused for one group.
|
|
40
34
|
* · `Sys.Audit` (or `User.Modify`) for the read, which the `read` role's auditor already has.
|
|
41
|
-
* `Permissions.Modify` is NOT on this list: that governs ACL entries, which are a different PVE
|
|
42
|
-
* object and would be a different resource here.
|
|
43
35
|
*
|
|
44
|
-
* ⚠️ A MISSING USER IS A 500, NOT A 404 — "no such user ('x@pve')"
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
36
|
+
* ⚠️ A MISSING USER IS A 500, NOT A 404 — "no such user ('x@pve')". distilled turns that into an
|
|
37
|
+
* `UnknownProxmoxError` (protocol.ts), and `readOrUnreadable`'s own `orElseSucceed` folds it
|
|
38
|
+
* into "absent" same as the old hand-rolled client did. A 403 therefore also reads as absent
|
|
39
|
+
* UNLESS it is the one refusal `readOrUnreadable` catches (unreadable-read.ts): a REFUSED
|
|
40
|
+
* `provision` mint, the cries-wolf case. Any other refusal still reads as absent, and the
|
|
41
|
+
* honest error arrives one step later, from the create.
|
|
42
|
+
*
|
|
43
|
+
* ⚠️ THE WIRE URL FOR THIS FAMILY CHANGED, THOUGH NOTHING A CALLER SEES DID. MEASURED
|
|
44
|
+
* (user.test.ts): distilled's `{userid}` label substitution percent-encodes it —
|
|
45
|
+
* `iac@pve` -> `.../access/users/iac%40pve` — where `client.ts`'s plain string concatenation
|
|
46
|
+
* sent the `@` literally. A real PVE (any HTTP server) decodes both the same way, so this is
|
|
47
|
+
* not a behaviour change a stack observes; a fake in a test has to decode it, `client.ts`'s
|
|
48
|
+
* own fixtures never had to.
|
|
49
|
+
*
|
|
50
|
+
* ★ MIGRATED OFF `client.ts`'s generic `pve()`/`pveHandlers` ONTO `@distilled.cloud/proxmox`'s
|
|
51
|
+
* typed `access.getAccessUser`/`createAccessUser`/`putAccessUser`/`deleteAccessUser`
|
|
52
|
+
* (2026-09-24, decision 43's proxmox walk-down, access sub-area). `distilled-pve.ts`'s `runPve`
|
|
53
|
+
* replaces `pve()` as in acl.ts and group.ts; the cries-wolf fix is wired the same way.
|
|
48
54
|
*/
|
|
49
55
|
import { Resource } from 'alchemy';
|
|
50
56
|
import * as Provider from 'alchemy/Provider';
|
|
51
|
-
import {
|
|
57
|
+
import type { PveRequirements, WithTarget } from './resource-spec.ts';
|
|
52
58
|
export interface UserProps extends WithTarget {
|
|
53
59
|
/**
|
|
54
60
|
* ⛔ REALM-QUALIFIED, ALWAYS: `someone@pve`, `someone@pam`. The realm is part of PVE's primary
|
|
@@ -91,18 +97,5 @@ export interface UserAttributes {
|
|
|
91
97
|
export interface ProxmoxUser extends Resource<'Proxmox.User', UserProps, UserAttributes, never, PveRequirements> {
|
|
92
98
|
}
|
|
93
99
|
export declare const ProxmoxUser: import("alchemy").ResourceClass<ProxmoxUser>;
|
|
94
|
-
/**
|
|
95
|
-
* ⛔ EMPTY, AND MORE POINTEDLY SO HERE THAN ANYWHERE ELSE. `GET /access/users` answers with
|
|
96
|
-
* every account on the cluster: `root@pam`, every human who logs in, every service
|
|
97
|
-
* identity someone made years ago. Handing that list to Alchemy would invite it to adopt
|
|
98
|
-
* — and therefore one day DELETE — people. Adoption is an explicit act.
|
|
99
|
-
|
|
100
|
-
*
|
|
101
|
-
* ⛔ DELETING A USER TAKES ITS API TOKENS AND ITS ACL ENTRIES WITH IT, in one call and
|
|
102
|
-
* without a confirmation. For the identity a credential mount vends from, that revokes
|
|
103
|
-
* every outstanding lease at once and every plan in this package stops working — this one
|
|
104
|
-
* included. PVE refuses only for `root@pam`; for everyone else it simply obeys.
|
|
105
|
-
|
|
106
|
-
*/
|
|
107
100
|
export declare const ProxmoxUserProvider: () => import("effect/Layer").Layer<Provider.Provider<ProxmoxUser>, never, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
108
101
|
//# sourceMappingURL=user.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/proxmox/user.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/proxmox/user.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;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;AAiBtE,MAAM,WAAW,SAAU,SAAQ,UAAU;IAC3C;;;;;;;OAOG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mGAAmG;IACnG,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,WAAY,SAAQ,QAAQ,CAC3C,cAAc,EACd,SAAS,EACT,cAAc,EACd,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,eAAO,MAAM,WAAW,8CAAwC,CAAC;AAajE,eAAO,MAAM,mBAAmB,iIAgF7B,CAAC"}
|
|
@@ -110,7 +110,7 @@ export declare const createForm: (props: ZfsPoolProps) => Record<string, string>
|
|
|
110
110
|
* here is the same `Effect.die` idiom as every other refusal in this package, and it costs
|
|
111
111
|
* nothing this pool did not already lack.
|
|
112
112
|
*/
|
|
113
|
-
export declare const createPool: <E, R>(props: ZfsPoolProps, collection: string, path: string, read: (props: ZfsPoolProps) => Effect.Effect<ZfsPoolAttributes | undefined, E, R>) => Effect.Effect<ZfsPoolAttributes, E | Error, R | import("effect/unstable/http/HttpClient").HttpClient>;
|
|
113
|
+
export declare const createPool: <E, R>(props: ZfsPoolProps, collection: string, path: string, read: (props: ZfsPoolProps) => Effect.Effect<ZfsPoolAttributes | undefined, E, R>) => Effect.Effect<ZfsPoolAttributes, E | Error | import("./credential-errors.ts").PveCredentialDenied, R | import("effect/unstable/http/HttpClient").HttpClient>;
|
|
114
114
|
/**
|
|
115
115
|
* ⛔ `DELETE /nodes/{node}/disks/zfs/{name}` RUNS `zpool destroy` AND THE DATASETS GO WITH IT. Per
|
|
116
116
|
* S14 (alchemy-provider-standard), it is implemented rather than stubbed — a `delete` that
|
|
@@ -124,5 +124,5 @@ export declare const createPool: <E, R>(props: ZfsPoolProps, collection: string,
|
|
|
124
124
|
* resource reaching over to delete another's is how a stack ends up with state describing
|
|
125
125
|
* something that is gone.
|
|
126
126
|
*/
|
|
127
|
-
export declare const destroyPool: (olds: ZfsPoolProps, path: string) => Effect.Effect<unknown, Error, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
127
|
+
export declare const destroyPool: (olds: ZfsPoolProps, path: string) => Effect.Effect<unknown, Error | import("./credential-errors.ts").PveCredentialDenied, import("effect/unstable/http/HttpClient").HttpClient>;
|
|
128
128
|
//# sourceMappingURL=zfs-pool-write.d.ts.map
|