@homeflare/alchemy 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/caddy/admin-guard.d.ts +1 -1
- package/dist/caddy/index.js.map +2 -2
- package/dist/cloudflare/client.d.ts +1 -1
- package/dist/cloudflare/index.js.map +2 -2
- package/dist/cloudflare/lock-rules.d.ts +1 -1
- package/dist/forgejo/branch-protection-form.d.ts +1 -1
- package/dist/forgejo/branch-protection.d.ts +1 -1
- package/dist/forgejo/index.js.map +10 -10
- package/dist/forgejo/org-actions-secrets.d.ts +1 -1
- package/dist/forgejo/org-label.d.ts +1 -1
- package/dist/forgejo/org-team.d.ts +1 -1
- package/dist/forgejo/repo-webhook.d.ts +1 -1
- package/dist/forgejo/repository.d.ts +2 -2
- package/dist/forgejo/repository.d.ts.map +1 -1
- package/dist/forgejo/resource.d.ts +2 -2
- package/dist/forgejo/team-member.d.ts +1 -1
- package/dist/openbao/auth-role.d.ts +1 -1
- package/dist/openbao/bao-http.d.ts +4 -4
- package/dist/openbao/cloudflare-permission-groups.d.ts +1 -1
- package/dist/openbao/cloudflare-role-form.d.ts +2 -2
- package/dist/openbao/cloudflare-role-form.d.ts.map +1 -1
- package/dist/openbao/cloudflare-roles-expand.d.ts +1 -1
- package/dist/openbao/digest.d.ts +1 -1
- package/dist/openbao/forgejo-bootstrap-parse.d.ts +2 -2
- package/dist/openbao/forgejo-bootstrap-parse.d.ts.map +1 -1
- package/dist/openbao/forgejo-bootstrap.d.ts +1 -1
- package/dist/openbao/index.js.map +14 -14
- package/dist/openbao/mount.d.ts +1 -1
- package/dist/openbao/pki-role.d.ts +1 -1
- package/dist/openbao/policy.d.ts +2 -2
- package/dist/openbao/proxmox-role-form.d.ts +2 -2
- package/dist/openbao/proxmox-role-form.d.ts.map +1 -1
- package/dist/openbao/proxmox-role.d.ts +10 -10
- package/dist/openbao/ssh-role.d.ts +3 -3
- package/dist/proxmox/acl.d.ts +2 -2
- package/dist/proxmox/acl.d.ts.map +1 -1
- package/dist/proxmox/alertmanager-body.d.ts +54 -0
- package/dist/proxmox/alertmanager-body.d.ts.map +1 -0
- package/dist/proxmox/api-token-form.d.ts +2 -2
- package/dist/proxmox/api-token.d.ts +11 -11
- package/dist/proxmox/ceph-daemon-form.d.ts +3 -3
- package/dist/proxmox/ceph-daemon.d.ts +19 -19
- package/dist/proxmox/ceph-daemon.d.ts.map +1 -1
- package/dist/proxmox/ceph-flag.d.ts +5 -5
- package/dist/proxmox/ceph-fs-wire.d.ts +5 -5
- package/dist/proxmox/ceph-fs.d.ts +16 -16
- package/dist/proxmox/ceph-osd-tree.d.ts +16 -16
- package/dist/proxmox/ceph-osd.d.ts +5 -5
- package/dist/proxmox/ceph-pool-form.d.ts +13 -13
- package/dist/proxmox/ceph-pool-form.d.ts.map +1 -1
- package/dist/proxmox/ceph-pool.d.ts +3 -3
- package/dist/proxmox/client.d.ts +2 -2
- package/dist/proxmox/credential-literals.d.ts +36 -0
- package/dist/proxmox/credential-literals.d.ts.map +1 -0
- package/dist/proxmox/credentials.d.ts +8 -8
- package/dist/proxmox/credentials.d.ts.map +1 -1
- package/dist/proxmox/fake-pbs-notify.d.ts +23 -0
- package/dist/proxmox/fake-pbs-notify.d.ts.map +1 -0
- package/dist/proxmox/fake-pve.d.ts +5 -0
- package/dist/proxmox/fake-pve.d.ts.map +1 -1
- package/dist/proxmox/firewall-alias-form.d.ts +1 -1
- package/dist/proxmox/firewall-alias.d.ts +1 -1
- package/dist/proxmox/generated/pbs.d.ts +279 -1
- package/dist/proxmox/generated/pbs.d.ts.map +1 -1
- package/dist/proxmox/generated/pve.d.ts +58 -1
- package/dist/proxmox/generated/pve.d.ts.map +1 -1
- package/dist/proxmox/group.d.ts +8 -8
- package/dist/proxmox/ha-resource.d.ts +3 -2
- package/dist/proxmox/ha-resource.d.ts.map +1 -1
- package/dist/proxmox/ha-rule-form.d.ts +5 -5
- package/dist/proxmox/ha-rule.d.ts +3 -3
- package/dist/proxmox/index.d.ts +14 -0
- package/dist/proxmox/index.d.ts.map +1 -1
- package/dist/proxmox/index.js +935 -223
- package/dist/proxmox/index.js.map +69 -56
- package/dist/proxmox/lease-cache.d.ts +4 -4
- package/dist/proxmox/lxc-harness.d.ts +1 -1
- package/dist/proxmox/lxc-props.d.ts +2 -2
- package/dist/proxmox/lxc.d.ts +3 -3
- package/dist/proxmox/members.d.ts +3 -3
- package/dist/proxmox/network-apply-read.d.ts +5 -5
- package/dist/proxmox/network-apply.d.ts +9 -9
- package/dist/proxmox/node-network-form.d.ts +6 -6
- package/dist/proxmox/node-network.d.ts +17 -17
- package/dist/proxmox/node-network.d.ts.map +1 -1
- package/dist/proxmox/notification-matcher-form.d.ts +100 -0
- package/dist/proxmox/notification-matcher-form.d.ts.map +1 -0
- package/dist/proxmox/notification-matcher.d.ts +46 -0
- package/dist/proxmox/notification-matcher.d.ts.map +1 -0
- package/dist/proxmox/notification-target.d.ts +3 -2
- package/dist/proxmox/notification-target.d.ts.map +1 -1
- package/dist/proxmox/pbs-datastore-guard.d.ts +1 -1
- package/dist/proxmox/pbs-datastore.d.ts +10 -10
- package/dist/proxmox/pbs-notification-matcher.d.ts +53 -0
- package/dist/proxmox/pbs-notification-matcher.d.ts.map +1 -0
- package/dist/proxmox/pbs-notification-target-form.d.ts +63 -0
- package/dist/proxmox/pbs-notification-target-form.d.ts.map +1 -0
- package/dist/proxmox/pbs-notification-target-lifecycle.d.ts +100 -0
- package/dist/proxmox/pbs-notification-target-lifecycle.d.ts.map +1 -0
- package/dist/proxmox/pbs-notification-target-wire.d.ts +30 -0
- package/dist/proxmox/pbs-notification-target-wire.d.ts.map +1 -0
- package/dist/proxmox/pbs-notification-target.d.ts +123 -0
- package/dist/proxmox/pbs-notification-target.d.ts.map +1 -0
- package/dist/proxmox/pbs-prune-job.d.ts +2 -2
- package/dist/proxmox/pbs-sync-job.d.ts +4 -4
- package/dist/proxmox/pbs-verify-job.d.ts +1 -1
- package/dist/proxmox/pool.d.ts +4 -4
- package/dist/proxmox/provision-baseline.d.ts +74 -0
- package/dist/proxmox/provision-baseline.d.ts.map +1 -0
- package/dist/proxmox/provision-bootstrap.d.ts +33 -0
- package/dist/proxmox/provision-bootstrap.d.ts.map +1 -0
- package/dist/proxmox/provision-cli-fake.d.ts +38 -0
- package/dist/proxmox/provision-cli-fake.d.ts.map +1 -0
- package/dist/proxmox/provision-declare.d.ts +25 -0
- package/dist/proxmox/provision-declare.d.ts.map +1 -0
- package/dist/proxmox/replication-job.d.ts +9 -8
- package/dist/proxmox/replication-job.d.ts.map +1 -1
- package/dist/proxmox/resource.d.ts +6 -5
- package/dist/proxmox/resource.d.ts.map +1 -1
- package/dist/proxmox/sdn-apply-read.d.ts +7 -7
- package/dist/proxmox/sdn-apply.d.ts +1 -1
- package/dist/proxmox/sdn-subnet-form.d.ts +1 -1
- package/dist/proxmox/sdn-subnet.d.ts +5 -5
- package/dist/proxmox/sdn-vnet.d.ts +5 -6
- package/dist/proxmox/sdn-vnet.d.ts.map +1 -1
- package/dist/proxmox/storage.d.ts +4 -3
- package/dist/proxmox/storage.d.ts.map +1 -1
- package/dist/proxmox/user.d.ts +3 -2
- package/dist/proxmox/user.d.ts.map +1 -1
- package/dist/proxmox/values.d.ts +1 -1
- package/dist/proxmox/write-only.d.ts +35 -0
- package/dist/proxmox/write-only.d.ts.map +1 -0
- package/dist/proxmox/zfs-pool-write.d.ts +1 -1
- package/dist/proxmox/zfs-pool.d.ts +5 -5
- package/dist/talos/credentials.d.ts +1 -1
- package/dist/talos/credentials.d.ts.map +1 -1
- package/dist/talos/index.js.map +1 -1
- package/dist/verify/fake-engine.d.ts +5 -0
- package/dist/verify/fake-engine.d.ts.map +1 -1
- package/docs/adopt-verify.md +21 -5
- package/docs/adopted-deploys.md +9 -1
- package/docs/ownership.md +26 -1
- package/docs/pbs-alertmanager-body.md +73 -0
- package/docs/pbs-notifications.md +163 -0
- package/docs/provision-baseline.md +106 -0
- package/docs/proxmox-lxc-adopt.md +2 -2
- package/docs/proxmox-lxc.md +5 -4
- package/docs/proxmox.md +9 -0
- package/package.json +1 -1
- package/src/caddy/admin-guard.ts +1 -1
- package/src/caddy/local-admin.ts +1 -1
- package/src/cloudflare/client.ts +1 -1
- package/src/cloudflare/lock-rules.ts +1 -1
- package/src/forgejo/branch-protection-form.ts +1 -1
- package/src/forgejo/branch-protection.ts +1 -1
- package/src/forgejo/client.ts +1 -1
- package/src/forgejo/org-actions-secrets.ts +1 -1
- package/src/forgejo/org-label.ts +1 -1
- package/src/forgejo/org-team.ts +1 -1
- package/src/forgejo/repo-webhook.ts +1 -1
- package/src/forgejo/repository.ts +2 -2
- package/src/forgejo/resource.ts +2 -2
- package/src/forgejo/team-member.ts +1 -1
- package/src/openbao/README.md +4 -4
- package/src/openbao/auth-role.ts +1 -1
- package/src/openbao/bao-http.test.ts +2 -2
- package/src/openbao/bao-http.ts +6 -6
- package/src/openbao/bao-status.test.ts +1 -1
- package/src/openbao/bao-status.ts +1 -1
- package/src/openbao/cloudflare-group-scope.test.ts +1 -1
- package/src/openbao/cloudflare-permission-groups.test.ts +1 -1
- package/src/openbao/cloudflare-permission-groups.ts +3 -3
- package/src/openbao/cloudflare-policy.ts +1 -1
- package/src/openbao/cloudflare-role-form.ts +2 -2
- package/src/openbao/cloudflare-roles-expand.ts +1 -1
- package/src/openbao/digest.ts +1 -1
- package/src/openbao/forgejo-bootstrap-parse.test.ts +3 -3
- package/src/openbao/forgejo-bootstrap-parse.ts +2 -2
- package/src/openbao/forgejo-bootstrap.ts +4 -4
- package/src/openbao/kubernetes-role-form.test.ts +5 -5
- package/src/openbao/mount.ts +1 -1
- package/src/openbao/pki-role.ts +1 -1
- package/src/openbao/policy-wire.test.ts +3 -3
- package/src/openbao/policy.ts +2 -2
- package/src/openbao/proxmox-role-form.ts +5 -5
- package/src/openbao/proxmox-role.ts +11 -11
- package/src/openbao/ssh-role.ts +3 -3
- package/src/proxmox/acl.ts +4 -4
- package/src/proxmox/adopt-noop.test.ts +6 -6
- package/src/proxmox/alertmanager-body.ts +125 -0
- package/src/proxmox/api-token-form.ts +4 -4
- package/src/proxmox/api-token.ts +13 -13
- package/src/proxmox/ceph-daemon-form.ts +3 -3
- package/src/proxmox/ceph-daemon.ts +20 -20
- package/src/proxmox/ceph-flag.ts +7 -7
- package/src/proxmox/ceph-fs-wire.ts +7 -7
- package/src/proxmox/ceph-fs.ts +18 -18
- package/src/proxmox/ceph-osd-tree.ts +16 -16
- package/src/proxmox/ceph-osd.ts +6 -6
- package/src/proxmox/ceph-pool-adopt.test.ts +14 -14
- package/src/proxmox/ceph-pool-form.ts +13 -13
- package/src/proxmox/ceph-pool.ts +6 -6
- package/src/proxmox/client.test.ts +3 -3
- package/src/proxmox/client.ts +3 -3
- package/src/proxmox/credential-literals.test.ts +148 -0
- package/src/proxmox/credential-literals.ts +74 -0
- package/src/proxmox/credentials.test.ts +6 -8
- package/src/proxmox/credentials.ts +8 -8
- package/src/proxmox/fake-pbs-notify.ts +108 -0
- package/src/proxmox/fake-pve.ts +12 -2
- package/src/proxmox/firewall-alias-form.ts +1 -1
- package/src/proxmox/firewall-alias.ts +1 -1
- package/src/proxmox/generated/pbs.ts +330 -1
- package/src/proxmox/generated/pve.ts +63 -1
- package/src/proxmox/group.ts +10 -10
- package/src/proxmox/ha-resource.ts +3 -2
- package/src/proxmox/ha-rule-form.ts +5 -5
- package/src/proxmox/ha-rule.ts +3 -3
- package/src/proxmox/index.test.ts +10 -0
- package/src/proxmox/index.ts +32 -0
- package/src/proxmox/lease-cache.test.ts +19 -19
- package/src/proxmox/lease-cache.ts +4 -4
- package/src/proxmox/lxc-adopt.test.ts +3 -3
- package/src/proxmox/lxc-create-form.ts +1 -1
- package/src/proxmox/lxc-guards.test.ts +4 -4
- package/src/proxmox/lxc-harness.ts +3 -3
- package/src/proxmox/lxc-judge.test.ts +5 -5
- package/src/proxmox/lxc-lifecycle.ts +1 -1
- package/src/proxmox/lxc-props.ts +2 -2
- package/src/proxmox/lxc-read.test.ts +3 -3
- package/src/proxmox/lxc-strict-adopt.test.ts +1 -1
- package/src/proxmox/lxc-volume.test.ts +9 -9
- package/src/proxmox/lxc-volume.ts +1 -1
- package/src/proxmox/lxc-wire.ts +1 -1
- package/src/proxmox/lxc.ts +3 -3
- package/src/proxmox/members.test.ts +1 -1
- package/src/proxmox/members.ts +3 -3
- package/src/proxmox/metric-server-otel.ts +2 -2
- package/src/proxmox/network-apply-read.ts +10 -10
- package/src/proxmox/network-apply.ts +10 -10
- package/src/proxmox/node-network-form.ts +7 -7
- package/src/proxmox/node-network.ts +18 -18
- package/src/proxmox/notification-matcher-form.ts +221 -0
- package/src/proxmox/notification-matcher.test.ts +234 -0
- package/src/proxmox/notification-matcher.ts +76 -0
- package/src/proxmox/notification-target.ts +3 -2
- package/src/proxmox/pbs-datastore-guard.ts +1 -1
- package/src/proxmox/pbs-datastore.ts +10 -10
- package/src/proxmox/pbs-notification-matcher.ts +81 -0
- package/src/proxmox/pbs-notification-target-drift.test.ts +83 -0
- package/src/proxmox/pbs-notification-target-form.ts +229 -0
- package/src/proxmox/pbs-notification-target-lifecycle.ts +177 -0
- package/src/proxmox/pbs-notification-target-state.test.ts +191 -0
- package/src/proxmox/pbs-notification-target-wire.ts +112 -0
- package/src/proxmox/pbs-notification-target.test.ts +226 -0
- package/src/proxmox/pbs-notification-target.ts +139 -0
- package/src/proxmox/pbs-notifications-stack.test.ts +94 -0
- package/src/proxmox/pbs-prune-job.ts +2 -2
- package/src/proxmox/pbs-sync-job.ts +4 -4
- package/src/proxmox/pbs-verify-job.ts +1 -1
- package/src/proxmox/pool.test.ts +2 -2
- package/src/proxmox/pool.ts +4 -4
- package/src/proxmox/provision-baseline.test.ts +87 -0
- package/src/proxmox/provision-baseline.ts +162 -0
- package/src/proxmox/provision-bootstrap.test.ts +132 -0
- package/src/proxmox/provision-bootstrap.ts +135 -0
- package/src/proxmox/provision-cli-fake.ts +217 -0
- package/src/proxmox/provision-declare.test.ts +111 -0
- package/src/proxmox/provision-declare.ts +103 -0
- package/src/proxmox/replication-job.ts +9 -8
- package/src/proxmox/resource.ts +9 -9
- package/src/proxmox/sdn-apply-read.test.ts +16 -16
- package/src/proxmox/sdn-apply-read.ts +7 -7
- package/src/proxmox/sdn-apply.ts +3 -3
- package/src/proxmox/sdn-subnet-form.ts +1 -1
- package/src/proxmox/sdn-subnet.ts +5 -5
- package/src/proxmox/sdn-vnet.ts +5 -6
- package/src/proxmox/storage.ts +4 -3
- package/src/proxmox/user.ts +3 -2
- package/src/proxmox/values.test.ts +2 -2
- package/src/proxmox/values.ts +1 -1
- package/src/proxmox/write-only.test.ts +75 -0
- package/src/proxmox/write-only.ts +106 -0
- package/src/proxmox/zfs-pool-write.ts +1 -1
- package/src/proxmox/zfs-pool.ts +6 -6
- package/src/talos/credentials.ts +3 -3
- package/src/talos/values.test.ts +9 -9
- package/src/verify/cli.test.ts +1 -1
- package/src/verify/fake-engine.ts +8 -1
|
@@ -29,9 +29,9 @@ const { Bun } = globalThis as unknown as {
|
|
|
29
29
|
|
|
30
30
|
const TOKEN = 'hvs.FAKE-sentinel-never-a-real-token';
|
|
31
31
|
const SECRET = 'fake-pve-secret-0000';
|
|
32
|
-
const
|
|
32
|
+
const C1: PveTarget = {
|
|
33
33
|
members: ['pve.example'],
|
|
34
|
-
mount: 'proxmox-
|
|
34
|
+
mount: 'proxmox-c1',
|
|
35
35
|
scheme: 'pve',
|
|
36
36
|
};
|
|
37
37
|
|
|
@@ -59,11 +59,9 @@ const withFake = async (
|
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
const minted = (env: BaoEnvironment) =>
|
|
62
|
-
Effect.runPromise(mint(
|
|
62
|
+
Effect.runPromise(mint(C1, 'read', env).pipe(Effect.provide(FetchHttpClient.layer)));
|
|
63
63
|
const refused = (env: BaoEnvironment) =>
|
|
64
|
-
Effect.runPromise(
|
|
65
|
-
mint(TB4, 'read', env).pipe(Effect.flip, Effect.provide(FetchHttpClient.layer)),
|
|
66
|
-
);
|
|
64
|
+
Effect.runPromise(mint(C1, 'read', env).pipe(Effect.flip, Effect.provide(FetchHttpClient.layer)));
|
|
67
65
|
|
|
68
66
|
const CREDENTIAL = {
|
|
69
67
|
json: { data: { secret: SECRET, token_id: 'hf-read@pve!hf-read-1' }, lease_duration: 3600 },
|
|
@@ -79,7 +77,7 @@ describe('mint', () => {
|
|
|
79
77
|
secret: SECRET,
|
|
80
78
|
tokenId: 'hf-read@pve!hf-read-1',
|
|
81
79
|
});
|
|
82
|
-
assert.equal(seen[0]?.path, '/v1/proxmox-
|
|
80
|
+
assert.equal(seen[0]?.path, '/v1/proxmox-c1/creds/read');
|
|
83
81
|
assert.equal(seen[0]?.headers.get('x-vault-token'), TOKEN);
|
|
84
82
|
assert.equal(seen[0]?.headers.get('x-vault-namespace'), 'homeflare');
|
|
85
83
|
assert.equal(seen[0]?.headers.get('x-vault-request'), 'true');
|
|
@@ -135,7 +133,7 @@ describe('mint', () => {
|
|
|
135
133
|
CREDENTIAL,
|
|
136
134
|
async (address, seen) => {
|
|
137
135
|
assert.equal((await minted({ BAO_ADDR: address })).leaseSeconds, 3600);
|
|
138
|
-
assert.equal(seen[0]?.path, '/v1/proxmox-
|
|
136
|
+
assert.equal(seen[0]?.path, '/v1/proxmox-c1/creds/read');
|
|
139
137
|
},
|
|
140
138
|
socket,
|
|
141
139
|
);
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* The PVE credential a reconcile runs with: minted from OpenBao, alive for five minutes.
|
|
3
3
|
*
|
|
4
4
|
* ⛔ THERE IS NO STATIC WRITE TOKEN IN THIS ESTATE, AND THAT IS DELIBERATE. Every PVE token stored
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* on the estate's static KV shelf is read-only — PVEAuditor on each cluster, Audit on PBS, all
|
|
6
|
+
* as one metrics user. The MCP proxmox client says why in its own header: the auditor token bounds
|
|
7
7
|
* what a BUG can do, independently of what the code bounds. Adding a long-lived write token to
|
|
8
8
|
* that shelf would delete the outer lock for every reader of the shelf, not just for this
|
|
9
9
|
* provider.
|
|
10
10
|
*
|
|
11
|
-
* ★ SO WRITES COME FROM A DYNAMIC MOUNT INSTEAD, which the estate already built: `proxmox-
|
|
11
|
+
* ★ SO WRITES COME FROM A DYNAMIC MOUNT INSTEAD, which the estate already built: `proxmox-c1/`
|
|
12
12
|
* exposes two roles — `read` (ttl 3600s) and `provision` (ttl 300s, max 1800s, NOT renewable).
|
|
13
13
|
* A mint returns a PVE API token of its own, `hf-provision@pve!hf-provision-…-<timestamp>-<id>`,
|
|
14
14
|
* which expires on its own whether or not anything cleans up. Same shape as
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
*
|
|
25
25
|
* ⛔ THE SECRET NEVER TOUCHES DISK, A LOG, OR ALCHEMY STATE. Alchemy persists resource attributes
|
|
26
26
|
* WITHOUT encryption — StateEncoding.ts writes `Redacted` as `{"@redacted": <plaintext>}` — and
|
|
27
|
-
* this estate's state store is the `alchemy` Postgres, which
|
|
27
|
+
* this estate's state store is the `alchemy` Postgres, which a nightly job dumps. A PVE
|
|
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
|
*/
|
|
@@ -60,10 +60,10 @@ export type PveRole = 'read' | 'provision';
|
|
|
60
60
|
* use this file unchanged; that is the whole difference between a provider and a script.
|
|
61
61
|
*/
|
|
62
62
|
export type PveTarget = {
|
|
63
|
-
/** OpenBao mount that vends API tokens for this host, e.g. `proxmox-
|
|
63
|
+
/** OpenBao mount that vends API tokens for this host, e.g. `proxmox-c1`. */
|
|
64
64
|
readonly mount: string;
|
|
65
65
|
/**
|
|
66
|
-
* mgmt hostnames for cluster members, e.g. `
|
|
66
|
+
* mgmt hostnames for cluster members, e.g. `node-b.mgmt.example.com`. Any member's :8006 API
|
|
67
67
|
* manages the whole cluster; `client.ts` failovers across them.
|
|
68
68
|
*/
|
|
69
69
|
readonly members: readonly string[];
|
|
@@ -133,14 +133,14 @@ const baoVariable = (env: BaoEnvironment, name: string) =>
|
|
|
133
133
|
* Mint one credential for `role`: `GET /v1/<mount>/creds/<role>` on OpenBao's HTTP API.
|
|
134
134
|
*
|
|
135
135
|
* 🔴 IT SHELLED OUT TO `bao read -format=json` UNTIL 2026-09-14. The case for the CLI was that one
|
|
136
|
-
* client could not disagree with `bao kv get` about what this machine may do.
|
|
136
|
+
* client could not disagree with `bao kv get` about what this machine may do. <estate>/openbao then
|
|
137
137
|
* learned twice what deciding by stderr costs — every failure read as absent, and two commands
|
|
138
138
|
* said "absent" in different words — so this reads STATUS CODES: 2xx is a credential, and 403
|
|
139
139
|
* (denied), 404 (no such role or mount — a mint has no "absent"), 503 (sealed) all fail.
|
|
140
140
|
* ★ THE ENVIRONMENT CONTRACT IS STILL THE CLI's, READ THE CLI's WAY, which keeps the case above
|
|
141
141
|
* true (openbao v2.6.2 api/client.go:34-66, 370, 503-507, 761-762, 776-785): BAO_AGENT_ADDR over
|
|
142
142
|
* BAO_ADDR over https://127.0.0.1:8200; BAO_NAMESPACE as X-Vault-Namespace; BAO_TOKEN as
|
|
143
|
-
* X-Vault-Token; X-Vault-Request always.
|
|
143
|
+
* X-Vault-Token; X-Vault-Request always. <estate>/openbao/src/bao-address.ts has the long form.
|
|
144
144
|
* ★ AGENT MODE IS NO BAO_TOKEN AND NO TOKEN HEADER. An Agent or Proxy listener with
|
|
145
145
|
* `api_proxy { use_auto_auth_token = true }` (or the older `cache { … }`) substitutes its
|
|
146
146
|
* auto-auth token exactly when a request carries none — command/agentproxyshared/cache/handler.go
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A PBS (or PVE) notification config that remembers writes — enough of proxmox-notify's CRUD for
|
|
3
|
+
* a family's REAL provider to create, drift, rotate and adopt through Alchemy's engine.
|
|
4
|
+
*
|
|
5
|
+
* ★ STATEFUL, UNLIKE `fakePve`'s bare answer function, because the questions here are about the
|
|
6
|
+
* SECOND deploy: whether a rotated secret is written, whether an unchanged one is not. That needs
|
|
7
|
+
* a server that holds what the first deploy wrote.
|
|
8
|
+
* ★ IT KEEPS proxmox-notify's TWO RULES THAT MATTER HERE (api/webhook.rs, read at HEAD 2026-09-22):
|
|
9
|
+
* 1. a read returns secret NAMES only; values live in a separate private store;
|
|
10
|
+
* 2. a PUT that carries `secret` REPLACES the list, a name without a value keeping the old
|
|
11
|
+
* one; a PUT without `secret` leaves the list alone. `delete` entries clear a field.
|
|
12
|
+
* Repeated form keys arrive as arrays, as the real urlencoded decoder builds them.
|
|
13
|
+
* ⛔ TEST-ONLY. No provider imports this file.
|
|
14
|
+
*/
|
|
15
|
+
import { type FakePve, type PveCall, fakePve } from './fake-pve.ts';
|
|
16
|
+
import { keyAndValue } from './pbs-notification-target-wire.ts';
|
|
17
|
+
|
|
18
|
+
/** Keys the servers take as `type: array`. Everything else is a scalar. */
|
|
19
|
+
const LISTS = new Set([
|
|
20
|
+
'header',
|
|
21
|
+
'mailto',
|
|
22
|
+
'mailto-user',
|
|
23
|
+
'match-calendar',
|
|
24
|
+
'match-field',
|
|
25
|
+
'match-severity',
|
|
26
|
+
'secret',
|
|
27
|
+
'target',
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
export interface FakeNotify extends FakePve {
|
|
31
|
+
/** Public config by path, as a GET would see it apart from secrets. Mutable, for drift. */
|
|
32
|
+
readonly objects: Map<string, Record<string, unknown>>;
|
|
33
|
+
/** Secret items with values (`name=…,value=<base64>`), by path — the root-only file. */
|
|
34
|
+
readonly secrets: Map<string, string[]>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const body = (call: PveCall) => {
|
|
38
|
+
const fields: Record<string, unknown> = {};
|
|
39
|
+
const deletes: string[] = [];
|
|
40
|
+
for (const [key, value] of call.pairs) {
|
|
41
|
+
if (key === 'delete') deletes.push(value);
|
|
42
|
+
else if (LISTS.has(key))
|
|
43
|
+
fields[key] = [...((fields[key] as string[] | undefined) ?? []), value];
|
|
44
|
+
// ⚠️ Scalars as the server's JSON reads them back: a flag as a boolean, a port as a number.
|
|
45
|
+
else if (key === 'disable' || key === 'invert-match') fields[key] = value === '1';
|
|
46
|
+
else if (key === 'port') fields[key] = Number(value);
|
|
47
|
+
else fields[key] = value;
|
|
48
|
+
}
|
|
49
|
+
return { deletes, fields };
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const withSecretsBlanked = (
|
|
53
|
+
path: string,
|
|
54
|
+
object: Record<string, unknown>,
|
|
55
|
+
secrets: FakeNotify['secrets'],
|
|
56
|
+
) => {
|
|
57
|
+
const held = secrets.get(path);
|
|
58
|
+
return held === undefined || held.length === 0
|
|
59
|
+
? object
|
|
60
|
+
: { ...object, secret: held.map((item) => `name=${keyAndValue(item).name}`) };
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const fakeNotify = (
|
|
64
|
+
seed: Readonly<Record<string, Record<string, unknown>>> = {},
|
|
65
|
+
): FakeNotify => {
|
|
66
|
+
const objects = new Map(Object.entries(seed).map(([path, object]) => [path, { ...object }]));
|
|
67
|
+
const secrets = new Map<string, string[]>();
|
|
68
|
+
|
|
69
|
+
const putSecrets = (path: string, items: readonly string[]) => {
|
|
70
|
+
const old = secrets.get(path) ?? [];
|
|
71
|
+
const next = items.map((item) => {
|
|
72
|
+
const { name, value } = keyAndValue(item);
|
|
73
|
+
if (value !== undefined) return item;
|
|
74
|
+
const kept = old.find((existing) => keyAndValue(existing).name === name);
|
|
75
|
+
if (kept === undefined) throw new Error(`secret '${name}' not known`);
|
|
76
|
+
return kept;
|
|
77
|
+
});
|
|
78
|
+
secrets.set(path, next);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const fake = fakePve((call) => {
|
|
82
|
+
const path = call.path.split('?')[0] ?? call.path;
|
|
83
|
+
const { deletes, fields } = body(call);
|
|
84
|
+
if (call.method === 'GET') {
|
|
85
|
+
const object = objects.get(path);
|
|
86
|
+
return object === undefined ? undefined : withSecretsBlanked(path, object, secrets);
|
|
87
|
+
}
|
|
88
|
+
if (call.method === 'DELETE') {
|
|
89
|
+
objects.delete(path);
|
|
90
|
+
secrets.delete(path);
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
const target = call.method === 'POST' ? `${path}/${String(fields['name'])}` : path;
|
|
94
|
+
const { secret, ...rest } = fields as { secret?: string[] } & Record<string, unknown>;
|
|
95
|
+
const next: Record<string, unknown> = {
|
|
96
|
+
...(call.method === 'PUT' ? objects.get(target) : {}),
|
|
97
|
+
...rest,
|
|
98
|
+
};
|
|
99
|
+
for (const key of deletes) {
|
|
100
|
+
if (key === 'secret') secrets.delete(target);
|
|
101
|
+
else delete next[key];
|
|
102
|
+
}
|
|
103
|
+
objects.set(target, next);
|
|
104
|
+
if (secret !== undefined) putSecrets(target, secret);
|
|
105
|
+
return undefined;
|
|
106
|
+
});
|
|
107
|
+
return { ...fake, objects, secrets };
|
|
108
|
+
};
|
package/src/proxmox/fake-pve.ts
CHANGED
|
@@ -28,6 +28,11 @@ export interface PveCall {
|
|
|
28
28
|
/** Relative to `/api2/json/`, query included — the string a family passes to `pve()`. */
|
|
29
29
|
readonly path: string;
|
|
30
30
|
readonly form: Readonly<Record<string, string>>;
|
|
31
|
+
/**
|
|
32
|
+
* Every key/value pair in wire order. ⚠️ `form` keeps only the LAST value of a repeated key, and
|
|
33
|
+
* a PBS list IS a repeated key (client.ts `encode`) — assert a list on `pairs`, never `form`.
|
|
34
|
+
*/
|
|
35
|
+
readonly pairs: readonly (readonly [string, string])[];
|
|
31
36
|
}
|
|
32
37
|
|
|
33
38
|
/** Answers one call with its `data`; `undefined` is PVE's `{"data": null}`. */
|
|
@@ -56,8 +61,13 @@ export const fakePve = (answer: PveAnswer): FakePve => {
|
|
|
56
61
|
return Response.json({ data, lease_duration: 0 });
|
|
57
62
|
}
|
|
58
63
|
const path = `${url.pathname.replace(/^\/api2\/json\//, '')}${url.search}`;
|
|
59
|
-
const
|
|
60
|
-
const call = {
|
|
64
|
+
const params = new URLSearchParams(await request.text());
|
|
65
|
+
const call = {
|
|
66
|
+
form: Object.fromEntries(params),
|
|
67
|
+
method: request.method,
|
|
68
|
+
pairs: [...params],
|
|
69
|
+
path,
|
|
70
|
+
};
|
|
61
71
|
calls.push(call);
|
|
62
72
|
return Response.json({ data: answer(call) ?? null });
|
|
63
73
|
};
|
|
@@ -36,7 +36,7 @@ export const fold = (name: string) => name.trim().toLowerCase();
|
|
|
36
36
|
/**
|
|
37
37
|
* A CIDR reduced to the one form PVE will hand back.
|
|
38
38
|
*
|
|
39
|
-
* ⛔ MEASURED by running the cluster's own `PVE::Firewall::parse_alias` on
|
|
39
|
+
* ⛔ MEASURED by running the cluster's own `PVE::Firewall::parse_alias` on node-b (pve-manager 9.2.11,
|
|
40
40
|
* 2026-09-13) — a pure function over a string, no config read and none written:
|
|
41
41
|
* `10.1.1.5/32` -> `10.1.1.5` a /32 host suffix is STRIPPED
|
|
42
42
|
* `2001:0DB8::1/128`-> `2001:0DB8::1` a /128 is stripped, and the case is NOT folded
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
* ⚠️ PRIVILEGES, AND FOR ONCE NOTHING NEEDS WIDENING. MEASURED 2026-09-13 from the cluster's own
|
|
62
62
|
* schema and its live ACL: the item GET checks `["perm","/",["Sys.Audit"]]`, POST/PUT/DELETE
|
|
63
63
|
* check `["perm","/",["Sys.Modify"]]`, `hf-read@pve` holds `PVEAuditor` at `/` with propagate and
|
|
64
|
-
* `hf-provision@pve` holds
|
|
64
|
+
* `hf-provision@pve` holds the provision role (provision-baseline.ts) at `/` with propagate. Both privileges are already
|
|
65
65
|
* held, so `readRole` stays the default `read` lane — unlike storage/sdn-zone/sdn-vnet, whose
|
|
66
66
|
* ITEM reads are gated on an allocate privilege the auditor cannot have.
|
|
67
67
|
* ⚠️ `Sys.Modify` ON `/` IS STILL A BIG HAMMER — it is the same grant `metric-server.ts` warns
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Generated PBS API types — DO NOT EDIT BY HAND.
|
|
3
3
|
*
|
|
4
4
|
* Run: bun codegen/generate.ts
|
|
5
|
-
* Source:
|
|
5
|
+
* Source: the cluster's own `apidoc.js` (pve-docs), extracted outside this repo.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
/** GET /config/datastore — `data` payload after client unwrap. */
|
|
@@ -141,6 +141,335 @@ export type ConfigDatastoreNameDeleteParams = {
|
|
|
141
141
|
/** DELETE /config/datastore/{name} — `data` payload after client unwrap. */
|
|
142
142
|
export type ConfigDatastoreNameDeleteReturn = string;
|
|
143
143
|
|
|
144
|
+
/** GET /config/notifications/endpoints — `data` payload after client unwrap. */
|
|
145
|
+
export type ConfigNotificationsEndpointsGetReturn = null;
|
|
146
|
+
|
|
147
|
+
/** GET /config/notifications/endpoints/gotify — `data` payload after client unwrap. */
|
|
148
|
+
export type ConfigNotificationsEndpointsGotifyGetReturn = readonly {
|
|
149
|
+
comment?: string;
|
|
150
|
+
disable?: boolean | 0 | 1;
|
|
151
|
+
filter?: string;
|
|
152
|
+
name: string;
|
|
153
|
+
origin?: 'user-created' | 'builtin' | 'modified-builtin';
|
|
154
|
+
server: string;
|
|
155
|
+
}[];
|
|
156
|
+
|
|
157
|
+
/** POST /config/notifications/endpoints/gotify — form/query parameters (path segments omitted). */
|
|
158
|
+
export type ConfigNotificationsEndpointsGotifyPostParams = {
|
|
159
|
+
comment?: string;
|
|
160
|
+
disable?: '0' | '1';
|
|
161
|
+
filter?: string;
|
|
162
|
+
name: string;
|
|
163
|
+
origin?: 'user-created' | 'builtin' | 'modified-builtin';
|
|
164
|
+
server: string;
|
|
165
|
+
token: string;
|
|
166
|
+
};
|
|
167
|
+
/** POST /config/notifications/endpoints/gotify — `data` payload after client unwrap. */
|
|
168
|
+
export type ConfigNotificationsEndpointsGotifyPostReturn = null;
|
|
169
|
+
|
|
170
|
+
/** GET /config/notifications/endpoints/gotify/{name} — `data` payload after client unwrap. */
|
|
171
|
+
export type ConfigNotificationsEndpointsGotifyNameGetReturn = {
|
|
172
|
+
comment?: string;
|
|
173
|
+
disable?: boolean | 0 | 1;
|
|
174
|
+
filter?: string;
|
|
175
|
+
name: string;
|
|
176
|
+
origin?: 'user-created' | 'builtin' | 'modified-builtin';
|
|
177
|
+
server: string;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/** PUT /config/notifications/endpoints/gotify/{name} — form/query parameters (path segments omitted). */
|
|
181
|
+
export type ConfigNotificationsEndpointsGotifyNamePutParams = {
|
|
182
|
+
comment?: string;
|
|
183
|
+
delete?: readonly ('comment' | 'disable')[];
|
|
184
|
+
digest?: string;
|
|
185
|
+
disable?: '0' | '1';
|
|
186
|
+
server?: string;
|
|
187
|
+
token?: string;
|
|
188
|
+
};
|
|
189
|
+
/** PUT /config/notifications/endpoints/gotify/{name} — `data` payload after client unwrap. */
|
|
190
|
+
export type ConfigNotificationsEndpointsGotifyNamePutReturn = null;
|
|
191
|
+
|
|
192
|
+
/** DELETE /config/notifications/endpoints/gotify/{name} — `data` payload after client unwrap. */
|
|
193
|
+
export type ConfigNotificationsEndpointsGotifyNameDeleteReturn = null;
|
|
194
|
+
|
|
195
|
+
/** GET /config/notifications/endpoints/sendmail — `data` payload after client unwrap. */
|
|
196
|
+
export type ConfigNotificationsEndpointsSendmailGetReturn = readonly {
|
|
197
|
+
author?: string;
|
|
198
|
+
comment?: string;
|
|
199
|
+
disable?: boolean | 0 | 1;
|
|
200
|
+
filter?: string;
|
|
201
|
+
'from-address'?: string;
|
|
202
|
+
mailto?: readonly string[];
|
|
203
|
+
'mailto-user'?: readonly string[];
|
|
204
|
+
name: string;
|
|
205
|
+
origin?: 'user-created' | 'builtin' | 'modified-builtin';
|
|
206
|
+
}[];
|
|
207
|
+
|
|
208
|
+
/** POST /config/notifications/endpoints/sendmail — form/query parameters (path segments omitted). */
|
|
209
|
+
export type ConfigNotificationsEndpointsSendmailPostParams = {
|
|
210
|
+
author?: string;
|
|
211
|
+
comment?: string;
|
|
212
|
+
disable?: '0' | '1';
|
|
213
|
+
filter?: string;
|
|
214
|
+
'from-address'?: string;
|
|
215
|
+
mailto?: readonly string[];
|
|
216
|
+
'mailto-user'?: readonly string[];
|
|
217
|
+
name: string;
|
|
218
|
+
origin?: 'user-created' | 'builtin' | 'modified-builtin';
|
|
219
|
+
};
|
|
220
|
+
/** POST /config/notifications/endpoints/sendmail — `data` payload after client unwrap. */
|
|
221
|
+
export type ConfigNotificationsEndpointsSendmailPostReturn = null;
|
|
222
|
+
|
|
223
|
+
/** GET /config/notifications/endpoints/sendmail/{name} — `data` payload after client unwrap. */
|
|
224
|
+
export type ConfigNotificationsEndpointsSendmailNameGetReturn = {
|
|
225
|
+
author?: string;
|
|
226
|
+
comment?: string;
|
|
227
|
+
disable?: boolean | 0 | 1;
|
|
228
|
+
filter?: string;
|
|
229
|
+
'from-address'?: string;
|
|
230
|
+
mailto?: readonly string[];
|
|
231
|
+
'mailto-user'?: readonly string[];
|
|
232
|
+
name: string;
|
|
233
|
+
origin?: 'user-created' | 'builtin' | 'modified-builtin';
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
/** PUT /config/notifications/endpoints/sendmail/{name} — form/query parameters (path segments omitted). */
|
|
237
|
+
export type ConfigNotificationsEndpointsSendmailNamePutParams = {
|
|
238
|
+
author?: string;
|
|
239
|
+
comment?: string;
|
|
240
|
+
delete?: readonly (
|
|
241
|
+
| 'author'
|
|
242
|
+
| 'comment'
|
|
243
|
+
| 'disable'
|
|
244
|
+
| 'from-address'
|
|
245
|
+
| 'mailto'
|
|
246
|
+
| 'mailto-user'
|
|
247
|
+
)[];
|
|
248
|
+
digest?: string;
|
|
249
|
+
disable?: '0' | '1';
|
|
250
|
+
'from-address'?: string;
|
|
251
|
+
mailto?: readonly string[];
|
|
252
|
+
'mailto-user'?: readonly string[];
|
|
253
|
+
};
|
|
254
|
+
/** PUT /config/notifications/endpoints/sendmail/{name} — `data` payload after client unwrap. */
|
|
255
|
+
export type ConfigNotificationsEndpointsSendmailNamePutReturn = null;
|
|
256
|
+
|
|
257
|
+
/** DELETE /config/notifications/endpoints/sendmail/{name} — `data` payload after client unwrap. */
|
|
258
|
+
export type ConfigNotificationsEndpointsSendmailNameDeleteReturn = null;
|
|
259
|
+
|
|
260
|
+
/** GET /config/notifications/endpoints/smtp — `data` payload after client unwrap. */
|
|
261
|
+
export type ConfigNotificationsEndpointsSmtpGetReturn = readonly {
|
|
262
|
+
author?: string;
|
|
263
|
+
comment?: string;
|
|
264
|
+
disable?: boolean | 0 | 1;
|
|
265
|
+
'from-address': string;
|
|
266
|
+
mailto?: readonly string[];
|
|
267
|
+
'mailto-user'?: readonly string[];
|
|
268
|
+
mode?: 'insecure' | 'starttls' | 'tls';
|
|
269
|
+
name: string;
|
|
270
|
+
origin?: 'user-created' | 'builtin' | 'modified-builtin';
|
|
271
|
+
port?: number;
|
|
272
|
+
server: string;
|
|
273
|
+
username?: string;
|
|
274
|
+
}[];
|
|
275
|
+
|
|
276
|
+
/** POST /config/notifications/endpoints/smtp — form/query parameters (path segments omitted). */
|
|
277
|
+
export type ConfigNotificationsEndpointsSmtpPostParams = {
|
|
278
|
+
author?: string;
|
|
279
|
+
comment?: string;
|
|
280
|
+
disable?: '0' | '1';
|
|
281
|
+
'from-address': string;
|
|
282
|
+
mailto?: readonly string[];
|
|
283
|
+
'mailto-user'?: readonly string[];
|
|
284
|
+
mode?: 'insecure' | 'starttls' | 'tls';
|
|
285
|
+
name: string;
|
|
286
|
+
origin?: 'user-created' | 'builtin' | 'modified-builtin';
|
|
287
|
+
password?: string;
|
|
288
|
+
port?: string;
|
|
289
|
+
server: string;
|
|
290
|
+
username?: string;
|
|
291
|
+
};
|
|
292
|
+
/** POST /config/notifications/endpoints/smtp — `data` payload after client unwrap. */
|
|
293
|
+
export type ConfigNotificationsEndpointsSmtpPostReturn = null;
|
|
294
|
+
|
|
295
|
+
/** GET /config/notifications/endpoints/smtp/{name} — `data` payload after client unwrap. */
|
|
296
|
+
export type ConfigNotificationsEndpointsSmtpNameGetReturn = {
|
|
297
|
+
author?: string;
|
|
298
|
+
comment?: string;
|
|
299
|
+
disable?: boolean | 0 | 1;
|
|
300
|
+
'from-address': string;
|
|
301
|
+
mailto?: readonly string[];
|
|
302
|
+
'mailto-user'?: readonly string[];
|
|
303
|
+
mode?: 'insecure' | 'starttls' | 'tls';
|
|
304
|
+
name: string;
|
|
305
|
+
origin?: 'user-created' | 'builtin' | 'modified-builtin';
|
|
306
|
+
port?: number;
|
|
307
|
+
server: string;
|
|
308
|
+
username?: string;
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
/** PUT /config/notifications/endpoints/smtp/{name} — form/query parameters (path segments omitted). */
|
|
312
|
+
export type ConfigNotificationsEndpointsSmtpNamePutParams = {
|
|
313
|
+
author?: string;
|
|
314
|
+
comment?: string;
|
|
315
|
+
delete?: readonly (
|
|
316
|
+
| 'author'
|
|
317
|
+
| 'comment'
|
|
318
|
+
| 'disable'
|
|
319
|
+
| 'mailto'
|
|
320
|
+
| 'mailto-user'
|
|
321
|
+
| 'password'
|
|
322
|
+
| 'port'
|
|
323
|
+
| 'username'
|
|
324
|
+
)[];
|
|
325
|
+
digest?: string;
|
|
326
|
+
disable?: '0' | '1';
|
|
327
|
+
'from-address'?: string;
|
|
328
|
+
mailto?: readonly string[];
|
|
329
|
+
'mailto-user'?: readonly string[];
|
|
330
|
+
mode?: 'insecure' | 'starttls' | 'tls';
|
|
331
|
+
password?: string;
|
|
332
|
+
port?: string;
|
|
333
|
+
server?: string;
|
|
334
|
+
username?: string;
|
|
335
|
+
};
|
|
336
|
+
/** PUT /config/notifications/endpoints/smtp/{name} — `data` payload after client unwrap. */
|
|
337
|
+
export type ConfigNotificationsEndpointsSmtpNamePutReturn = null;
|
|
338
|
+
|
|
339
|
+
/** DELETE /config/notifications/endpoints/smtp/{name} — `data` payload after client unwrap. */
|
|
340
|
+
export type ConfigNotificationsEndpointsSmtpNameDeleteReturn = null;
|
|
341
|
+
|
|
342
|
+
/** GET /config/notifications/endpoints/webhook — `data` payload after client unwrap. */
|
|
343
|
+
export type ConfigNotificationsEndpointsWebhookGetReturn = readonly {
|
|
344
|
+
body?: string;
|
|
345
|
+
comment?: string;
|
|
346
|
+
disable?: boolean | 0 | 1;
|
|
347
|
+
header?: readonly string[];
|
|
348
|
+
method: 'post' | 'put' | 'get';
|
|
349
|
+
name: string;
|
|
350
|
+
origin?: 'user-created' | 'builtin' | 'modified-builtin';
|
|
351
|
+
secret?: readonly string[];
|
|
352
|
+
url: string;
|
|
353
|
+
}[];
|
|
354
|
+
|
|
355
|
+
/** POST /config/notifications/endpoints/webhook — form/query parameters (path segments omitted). */
|
|
356
|
+
export type ConfigNotificationsEndpointsWebhookPostParams = {
|
|
357
|
+
body?: string;
|
|
358
|
+
comment?: string;
|
|
359
|
+
disable?: '0' | '1';
|
|
360
|
+
header?: readonly string[];
|
|
361
|
+
method: 'post' | 'put' | 'get';
|
|
362
|
+
name: string;
|
|
363
|
+
origin?: 'user-created' | 'builtin' | 'modified-builtin';
|
|
364
|
+
secret?: readonly string[];
|
|
365
|
+
url: string;
|
|
366
|
+
};
|
|
367
|
+
/** POST /config/notifications/endpoints/webhook — `data` payload after client unwrap. */
|
|
368
|
+
export type ConfigNotificationsEndpointsWebhookPostReturn = null;
|
|
369
|
+
|
|
370
|
+
/** GET /config/notifications/endpoints/webhook/{name} — `data` payload after client unwrap. */
|
|
371
|
+
export type ConfigNotificationsEndpointsWebhookNameGetReturn = {
|
|
372
|
+
body?: string;
|
|
373
|
+
comment?: string;
|
|
374
|
+
disable?: boolean | 0 | 1;
|
|
375
|
+
header?: readonly string[];
|
|
376
|
+
method: 'post' | 'put' | 'get';
|
|
377
|
+
name: string;
|
|
378
|
+
origin?: 'user-created' | 'builtin' | 'modified-builtin';
|
|
379
|
+
secret?: readonly string[];
|
|
380
|
+
url: string;
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
/** PUT /config/notifications/endpoints/webhook/{name} — form/query parameters (path segments omitted). */
|
|
384
|
+
export type ConfigNotificationsEndpointsWebhookNamePutParams = {
|
|
385
|
+
body?: string;
|
|
386
|
+
comment?: string;
|
|
387
|
+
delete?: readonly ('comment' | 'disable' | 'header' | 'body' | 'secret')[];
|
|
388
|
+
digest?: string;
|
|
389
|
+
disable?: '0' | '1';
|
|
390
|
+
header?: readonly string[];
|
|
391
|
+
method?: 'post' | 'put' | 'get';
|
|
392
|
+
secret?: readonly string[];
|
|
393
|
+
url?: string;
|
|
394
|
+
};
|
|
395
|
+
/** PUT /config/notifications/endpoints/webhook/{name} — `data` payload after client unwrap. */
|
|
396
|
+
export type ConfigNotificationsEndpointsWebhookNamePutReturn = null;
|
|
397
|
+
|
|
398
|
+
/** DELETE /config/notifications/endpoints/webhook/{name} — `data` payload after client unwrap. */
|
|
399
|
+
export type ConfigNotificationsEndpointsWebhookNameDeleteReturn = null;
|
|
400
|
+
|
|
401
|
+
/** GET /config/notifications/matchers — `data` payload after client unwrap. */
|
|
402
|
+
export type ConfigNotificationsMatchersGetReturn = readonly {
|
|
403
|
+
comment?: string;
|
|
404
|
+
disable?: boolean | 0 | 1;
|
|
405
|
+
'invert-match'?: boolean | 0 | 1;
|
|
406
|
+
'match-calendar'?: readonly string[];
|
|
407
|
+
'match-field'?: readonly string[];
|
|
408
|
+
'match-severity'?: readonly string[];
|
|
409
|
+
mode?: 'all' | 'any';
|
|
410
|
+
name: string;
|
|
411
|
+
origin?: 'user-created' | 'builtin' | 'modified-builtin';
|
|
412
|
+
target?: readonly string[];
|
|
413
|
+
}[];
|
|
414
|
+
|
|
415
|
+
/** POST /config/notifications/matchers — form/query parameters (path segments omitted). */
|
|
416
|
+
export type ConfigNotificationsMatchersPostParams = {
|
|
417
|
+
comment?: string;
|
|
418
|
+
disable?: '0' | '1';
|
|
419
|
+
'invert-match'?: '0' | '1';
|
|
420
|
+
'match-calendar'?: readonly string[];
|
|
421
|
+
'match-field'?: readonly string[];
|
|
422
|
+
'match-severity'?: readonly string[];
|
|
423
|
+
mode?: 'all' | 'any';
|
|
424
|
+
name: string;
|
|
425
|
+
origin?: 'user-created' | 'builtin' | 'modified-builtin';
|
|
426
|
+
target?: readonly string[];
|
|
427
|
+
};
|
|
428
|
+
/** POST /config/notifications/matchers — `data` payload after client unwrap. */
|
|
429
|
+
export type ConfigNotificationsMatchersPostReturn = null;
|
|
430
|
+
|
|
431
|
+
/** GET /config/notifications/matchers/{name} — `data` payload after client unwrap. */
|
|
432
|
+
export type ConfigNotificationsMatchersNameGetReturn = {
|
|
433
|
+
comment?: string;
|
|
434
|
+
disable?: boolean | 0 | 1;
|
|
435
|
+
'invert-match'?: boolean | 0 | 1;
|
|
436
|
+
'match-calendar'?: readonly string[];
|
|
437
|
+
'match-field'?: readonly string[];
|
|
438
|
+
'match-severity'?: readonly string[];
|
|
439
|
+
mode?: 'all' | 'any';
|
|
440
|
+
name: string;
|
|
441
|
+
origin?: 'user-created' | 'builtin' | 'modified-builtin';
|
|
442
|
+
target?: readonly string[];
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
/** PUT /config/notifications/matchers/{name} — form/query parameters (path segments omitted). */
|
|
446
|
+
export type ConfigNotificationsMatchersNamePutParams = {
|
|
447
|
+
comment?: string;
|
|
448
|
+
delete?: readonly (
|
|
449
|
+
| 'comment'
|
|
450
|
+
| 'disable'
|
|
451
|
+
| 'invert-match'
|
|
452
|
+
| 'match-calendar'
|
|
453
|
+
| 'match-field'
|
|
454
|
+
| 'match-severity'
|
|
455
|
+
| 'mode'
|
|
456
|
+
| 'target'
|
|
457
|
+
)[];
|
|
458
|
+
digest?: string;
|
|
459
|
+
disable?: '0' | '1';
|
|
460
|
+
'invert-match'?: '0' | '1';
|
|
461
|
+
'match-calendar'?: readonly string[];
|
|
462
|
+
'match-field'?: readonly string[];
|
|
463
|
+
'match-severity'?: readonly string[];
|
|
464
|
+
mode?: 'all' | 'any';
|
|
465
|
+
target?: readonly string[];
|
|
466
|
+
};
|
|
467
|
+
/** PUT /config/notifications/matchers/{name} — `data` payload after client unwrap. */
|
|
468
|
+
export type ConfigNotificationsMatchersNamePutReturn = null;
|
|
469
|
+
|
|
470
|
+
/** DELETE /config/notifications/matchers/{name} — `data` payload after client unwrap. */
|
|
471
|
+
export type ConfigNotificationsMatchersNameDeleteReturn = null;
|
|
472
|
+
|
|
144
473
|
/** GET /config/prune — `data` payload after client unwrap. */
|
|
145
474
|
export type ConfigPruneGetReturn = readonly {
|
|
146
475
|
comment?: string;
|