@homeflare/alchemy 0.21.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +3 -1
  2. package/dist/launchd/index.d.ts +2 -0
  3. package/dist/launchd/index.d.ts.map +1 -1
  4. package/dist/launchd/index.js +53 -1
  5. package/dist/launchd/index.js.map +4 -3
  6. package/dist/launchd/port-claims.d.ts +31 -0
  7. package/dist/launchd/port-claims.d.ts.map +1 -0
  8. package/dist/proxmox/api-token-form.d.ts +12 -1
  9. package/dist/proxmox/api-token-form.d.ts.map +1 -1
  10. package/dist/proxmox/api-token.d.ts +8 -3
  11. package/dist/proxmox/api-token.d.ts.map +1 -1
  12. package/dist/proxmox/generated/pve/cluster-sdn-fabrics.d.ts +13 -13
  13. package/dist/proxmox/generated/pve/cluster-sdn-fabrics.d.ts.map +1 -1
  14. package/dist/proxmox/index.d.ts +9 -2
  15. package/dist/proxmox/index.d.ts.map +1 -1
  16. package/dist/proxmox/index.js +17 -9
  17. package/dist/proxmox/index.js.map +8 -7
  18. package/dist/proxmox/zfs-pool-spec.d.ts +27 -0
  19. package/dist/proxmox/zfs-pool-spec.d.ts.map +1 -0
  20. package/dist/proxmox/zfs-pool-write.d.ts +48 -7
  21. package/dist/proxmox/zfs-pool-write.d.ts.map +1 -1
  22. package/dist/proxmox/zfs-pool.d.ts +42 -20
  23. package/dist/proxmox/zfs-pool.d.ts.map +1 -1
  24. package/dist/release/catalog.d.ts +37 -0
  25. package/dist/release/catalog.d.ts.map +1 -1
  26. package/dist/release/index.d.ts +2 -1
  27. package/dist/release/index.d.ts.map +1 -1
  28. package/dist/release/index.js +75 -15
  29. package/dist/release/index.js.map +5 -4
  30. package/dist/release/openbao.d.ts +35 -0
  31. package/dist/release/openbao.d.ts.map +1 -0
  32. package/docs/adopted-deploys.md +14 -0
  33. package/docs/launchd-ports.md +109 -0
  34. package/docs/launchd.md +5 -0
  35. package/docs/release-binary-catalogs.md +32 -7
  36. package/docs/release-binary-openbao.md +151 -0
  37. package/docs/release-binary.md +13 -2
  38. package/package.json +1 -1
  39. package/src/launchd/index.ts +2 -0
  40. package/src/launchd/port-claims.test.ts +124 -0
  41. package/src/launchd/port-claims.ts +102 -0
  42. package/src/launchd/providers.test.ts +3 -0
  43. package/src/proxmox/api-token-adopt.test.ts +138 -0
  44. package/src/proxmox/api-token-form.ts +19 -2
  45. package/src/proxmox/api-token.ts +8 -3
  46. package/src/proxmox/generated/pve/cluster-sdn-fabrics.ts +23 -13
  47. package/src/proxmox/index.test.ts +5 -2
  48. package/src/proxmox/index.ts +9 -2
  49. package/src/proxmox/zfs-pool-adopt.test.ts +141 -0
  50. package/src/proxmox/zfs-pool-spec.ts +76 -0
  51. package/src/proxmox/zfs-pool-write.ts +63 -9
  52. package/src/proxmox/zfs-pool.ts +45 -95
  53. package/src/release/catalog.test.ts +71 -0
  54. package/src/release/catalog.ts +68 -5
  55. package/src/release/fixtures/openbao/checksums.txt +83 -0
  56. package/src/release/fixtures/openbao/checksums.txt.gpgsig +0 -0
  57. package/src/release/fixtures/openbao/darwin-assets.txt +12 -0
  58. package/src/release/fixtures/openbao/openbao-gpg-pub-20240618.asc +109 -0
  59. package/src/release/index.ts +3 -0
  60. package/src/release/openbao.test.ts +120 -0
  61. package/src/release/openbao.ts +86 -0
  62. package/src/release/providers.test.ts +1 -0
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The `PveSpec` for `Proxmox.ZfsPool`: where a pool lives, what its GET reports, and the vendor
3
+ * endpoint its create form is checked against.
4
+ *
5
+ * ★ SPLIT OUT OF zfs-pool.ts TO KEEP THAT FILE UNDER THE 250-LINE CAP, and the seam is the same
6
+ * one metric-server-form.ts and zfs-pool-write.ts already cut on: zfs-pool.ts answers "what is
7
+ * a zpool and when has it changed", this file answers "what PVE's own GET/{node}/disks/zfs
8
+ * collection and item say, read into that shape". `leafDevices` moved with `spec` because it
9
+ * exists for exactly one field of `spec.attributes` and nothing else in this package calls it.
10
+ *
11
+ * ⚠️ THE `import type` BACK TO zfs-pool.ts IS A CYCLE ON PAPER ONLY — type-only, erased before
12
+ * anything runs, so the resource's public shape stays in the file that declares the resource.
13
+ * Same reasoning as zfs-pool-write.ts.
14
+ */
15
+ import type { PveSpec } from './resource.ts';
16
+ import type { ZfsPoolAttributes, ZfsPoolProps } from './zfs-pool.ts';
17
+ /**
18
+ * The device paths at the bottom of PVE's vdev tree, in the order ZFS reports them.
19
+ *
20
+ * ⚠️ "NO CHILDREN" IS THE LEAF TEST, AND IT IS NOT A GUESS — MEASURED in the node's `preparetree`,
21
+ * which sets `leaf` to 0 when there are children and 1 otherwise. Reading the flag would work
22
+ * equally well; recursing on `children` needs no second field to be present and is what makes
23
+ * nested sections (mirrors inside a raid10, `spares`, `cache`) flatten correctly.
24
+ */
25
+ export declare const leafDevices: (children: unknown) => string[];
26
+ export declare const spec: PveSpec<ZfsPoolProps, ZfsPoolAttributes>;
27
+ //# sourceMappingURL=zfs-pool-spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zfs-pool-spec.d.ts","sourceRoot":"","sources":["../../src/proxmox/zfs-pool-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAErE;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,aAAc,OAAO,KAAG,MAAM,EAO9C,CAAC;AAET,eAAO,MAAM,IAAI,EAAE,OAAO,CAAC,YAAY,EAAE,iBAAiB,CAuCzD,CAAC"}
@@ -35,15 +35,44 @@ import type { ZfsPoolAttributes, ZfsPoolProps } from './zfs-pool.ts';
35
35
  * declaration asked for, and this is the one call that writes to physical disks.
36
36
  */
37
37
  /**
38
- * The vendor rules the create form is checked against at plan time.
38
+ * The vendor rules a FULL declaration's create form is checked against at plan time.
39
39
  *
40
40
  * ⛔ HERE RATHER THAN INLINE IN zfs-pool.ts BECAUSE THAT FILE IS ALREADY OVER THE 250-LINE CAP,
41
41
  * and a `pve:POST …` literal has to live in a non-test source file for the generator to table
42
- * it at all. The spec imports it on the line it already imports `createForm` from.
42
+ * it at all. zfs-pool-spec.ts imports it on the line it already imports `createForm` from.
43
43
  * ⚠️ NO UPDATE KEY: PVE registers no PUT under `/nodes/{node}/disks/zfs`, which is exactly why
44
44
  * the spec declares no `updateForm` and a changed prop is a REPLACE.
45
+ * ⚠️ `spec.endpoint` DOES NOT RETURN THIS CONSTANT DIRECTLY — see the ★ on `zfsPoolEndpoint`
46
+ * below, and the ⛔ on `devices`/`raidlevel` in zfs-pool.ts (decision 9, 2026-09-23).
45
47
  */
46
48
  export declare const ZFS_POOL_ENDPOINT: EndpointPair;
49
+ /**
50
+ * ★ `PveSpec['endpoint']` AS A FUNCTION OF PROPS, THE WAY notification-target.ts AND
51
+ * ceph-daemon.ts ALREADY DO IT FOR A DIFFERENT REASON (resource-spec.ts's ⚠️ on that field).
52
+ * Here the reason is decision 9's adopt-only mode: `guardCreate` runs on the FIRST plan of
53
+ * ANY declaration (resource.ts `ops.diff`, `output === undefined` branch) and checks the
54
+ * create form's REQUIRED fields whenever `endpoint.create` resolves to a key — and PVE marks
55
+ * both `devices` and `raidlevel` required (measured, codegen/constraints's `pve-nodes-disks`
56
+ * row). An adopt-only declaration deliberately omits both, so returning the real key there
57
+ * would refuse a MATCHING adoption at plan time, before `read` ever ran — exactly the gap
58
+ * `guardCreate`/`guardUpdate` being exported (resource.ts's ★) says this family must not fall
59
+ * through. Returning `{}` (no `create` key) makes `guardCreate` a no-op (`constraint-guard.ts`:
60
+ * `create === undefined ? Effect.void : …`) for an adopt-only declaration, while a FULL one
61
+ * (`devices` and `raidlevel` both present) is checked exactly as before.
62
+ * ⚠️ THE RUNTIME BACKSTOP IS `createPool` BELOW, NOT THIS FUNCTION. Skipping the plan-time guard
63
+ * for an adopt-only declaration does not skip the check that the pool is actually there —
64
+ * `createPool` refuses before any POST when the read comes back absent and either field is
65
+ * undefined, which is what a genuinely absent adopt-only declaration hits at apply time.
66
+ */
67
+ export declare const zfsPoolEndpoint: (props: ZfsPoolProps) => EndpointPair;
68
+ /**
69
+ * ⚠️ EVERY KEY IS OMITTED WHEN ABSENT, `devices` AND `raidlevel` INCLUDED — not just the
70
+ * optional ones. An adopt-only declaration (both undefined, decision 9) must produce a form
71
+ * `createPool`'s own guard can inspect for their absence, and one this function itself does
72
+ * not throw building: `props.devices.join(',')` on an undefined `devices` is exactly the
73
+ * `TypeError` the plan-time guard hit before this change, because `guardCreate` evaluates
74
+ * `spec.createForm(props)` eagerly (resource-guard.ts) — before it even looks at `presence`.
75
+ */
47
76
  export declare const createForm: (props: ZfsPoolProps) => Record<string, string>;
48
77
  /**
49
78
  * Create the pool if it is absent, and otherwise leave it completely alone.
@@ -69,14 +98,26 @@ export declare const createForm: (props: ZfsPoolProps) => Record<string, string>
69
98
  * ⚠️ SHORT POLLS WITH A HARD CAP, NOT ONE LONG WAIT. `read` cannot tell "not yet" from "forbidden"
70
99
  * — both are `undefined` — so the loop gives up with the UPID rather than retrying forever, and
71
100
  * the UPID is the only thing that leads to the worker's real error.
101
+ *
102
+ * ⛔ THE ADOPT-ONLY GUARD, RIGHT AFTER THE READ AND BEFORE ANYTHING ELSE. Decision 9 (2026-09-23):
103
+ * omitting `devices` and `raidlevel` declares a pool this resource may only ADOPT, for a pool
104
+ * PVE's own schema cannot fully describe — n1's `speed` is a stripe, and `raidlevel`'s enum has
105
+ * no stripe (zfs-pool.ts). `zfsPoolEndpoint` above already keeps the vendor constraint guard
106
+ * from refusing such a declaration at PLAN time; this is the matching refusal at APPLY time, for
107
+ * the one case that guard cannot see — the pool genuinely is not there. MEASURED without it: a
108
+ * tolerant `createForm` sends `POST … {name: "rpool"}` with no `devices`/`raidlevel`, which PVE's
109
+ * own schema would 400 on eventually, but only after the request left this process; refusing
110
+ * here is the same `Effect.die` idiom as every other refusal in this package, and it costs
111
+ * nothing this pool did not already lack.
72
112
  */
73
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>;
74
114
  /**
75
- * ⛔ `DELETE /nodes/{node}/disks/zfs/{name}` RUNS `zpool destroy` AND THE DATASETS GO WITH IT.
76
- * It is implemented rather than stubbed, because a `delete` that silently does nothing lies to
77
- * whoever reads the plan. What keeps a deleted line from destroying a pool is the resource's
78
- * `defaultRemovalPolicy: 'retain'` above — an orphaned pool is forgotten, not destroyed, and a
79
- * caller who means it says `.pipe(RemovalPolicy.destroy())`.
115
+ * ⛔ `DELETE /nodes/{node}/disks/zfs/{name}` RUNS `zpool destroy` AND THE DATASETS GO WITH IT. Per
116
+ * S14 (alchemy-provider-standard), it is implemented rather than stubbed — a `delete` that
117
+ * silently does nothing lies to whoever reads the plan — and what keeps an ordinary removed
118
+ * declaration from reaching it is the resource's `defaultRemovalPolicy: 'retain'` (zfs-pool.ts):
119
+ * an orphaned pool is forgotten, not destroyed, unless a caller opts in with
120
+ * `.pipe(RemovalPolicy.destroy())`. See the corrected header in zfs-pool.ts.
80
121
  *
81
122
  * ⚠️ `cleanup-config` IS NOT SENT. It would additionally remove the PVE storage entry pointing
82
123
  * at this pool, which is a different object with its own resource (`Proxmox.Storage`); one
@@ -1 +1 @@
1
- {"version":3,"file":"zfs-pool-write.d.ts","sourceRoot":"","sources":["../../src/proxmox/zfs-pool-write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAErE;;;;;;;;;;;;;GAaG;AACH;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,EAAE,YAA6D,CAAC;AAE9F,eAAO,MAAM,UAAU,UAAW,YAAY,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAOpE,CAAC;AAKH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,CAAC,SACtB,YAAY,cACP,MAAM,QACZ,MAAM,QACN,CAAC,KAAK,EAAE,YAAY,KAAK,MAAM,CAAC,MAAM,CAAC,iBAAiB,GAAG,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,0GAmC/E,CAAC;AAEL;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,SAAU,YAAY,QAAQ,MAAM,wFACb,CAAC"}
1
+ {"version":3,"file":"zfs-pool-write.d.ts","sourceRoot":"","sources":["../../src/proxmox/zfs-pool-write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAErE;;;;;;;;;;;;;GAaG;AACH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,EAAE,YAA6D,CAAC;AAE9F;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,eAAe,UAAW,YAAY,KAAG,YACiC,CAAC;AAExF;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,UAAW,YAAY,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAOpE,CAAC;AAKH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,CAAC,SACtB,YAAY,cACP,MAAM,QACZ,MAAM,QACN,CAAC,KAAK,EAAE,YAAY,KAAK,MAAM,CAAC,MAAM,CAAC,iBAAiB,GAAG,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,0GA8C/E,CAAC;AAEL;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,SAAU,YAAY,QAAQ,MAAM,wFACb,CAAC"}
@@ -6,20 +6,22 @@
6
6
  * moment the worker runs. Every other decision in this file follows from that one sentence, and
7
7
  * each of them is written out below rather than left to be inferred.
8
8
  *
9
- * ⛔ DESTROY IS REFUSED. `delete` MAKES NO API CALL — removing this resource from a stack leaves
10
- * the zpool and its data exactly where they are, and Alchemy simply forgets about them. The
11
- * asymmetry is the whole argument: an ORPHANED pool is recoverable (declare it again, or destroy
12
- * it by hand once a human has looked at which disks are in it), a DESTROYED pool is not. Alchemy
13
- * deletes for reasons that have nothing to do with anybody intending it — a line removed from a
14
- * stack file, a resource renamed so the old id is dropped, a whole stack torn down by the wrong
15
- * command, a replace triggered by a prop nobody meant to touch. Handing `zpool destroy` to any
16
- * of those is not a feature. MEASURED in the node's own source: the DELETE handler forks
17
- * `zfsremove`, which runs `zpool destroy <name>` unconditionally, and with `cleanup-disks` then
18
- * calls `wipe_blockdev` on every member. Neither flag is offered as a prop, because there is no
19
- * call here for them to reach.
20
- * ★ THE OPERATOR'S PATH IS `pvesh delete /nodes/<node>/disks/zfs/<name>`, typed by a person who
21
- * has just looked at the pool. Do not "complete the CRUD" by wiring `delete` to `ops.destroy`:
22
- * that one line turns a text edit into an unrecoverable one.
9
+ * ⛔ ★ CORRECTED 2026-09-23 — THIS PARAGRAPH PREVIOUSLY SAID "DESTROY IS REFUSED" AND "`delete`
10
+ * MAKES NO API CALL". THAT WAS FALSE: MEASURED against this file's own `handlers.delete` below,
11
+ * which calls `destroyPool`, which sends `DELETE /nodes/{node}/disks/zfs/{name}` — the node's
12
+ * own source forks `zfsremove`, which runs `zpool destroy <name>` unconditionally, and with
13
+ * `cleanup-disks` then calls `wipe_blockdev` on every member (neither flag is offered as a prop,
14
+ * because there is no call here for them to reach). `delete` is FULLY IMPLEMENTED, per S14
15
+ * (alchemy-provider-standard): a `delete` that silently does nothing lies to whoever reads the
16
+ * plan. What actually keeps an ordinary removed declaration from reaching it is
17
+ * `defaultRemovalPolicy: 'retain'` below — Alchemy SKIPS `provider.delete` entirely for an
18
+ * orphaned or destroyed resource under `retain`, so the state row drops and the zpool and its
19
+ * data are left exactly where they are. The asymmetry is still the whole argument: an ORPHANED
20
+ * pool is recoverable (declare it again, or destroy it by hand once a human has looked at which
21
+ * disks are in it), a DESTROYED pool is not — which is why `retain` is the default rather than a
22
+ * documented caution, and why `delete` runs only for a caller who opts in by name with
23
+ * `.pipe(RemovalPolicy.destroy())`. See the ★ on `defaultRemovalPolicy` in resource-spec.ts, and
24
+ * zfs-pool-adopt.test.ts's mutation row, which pins exactly one DELETE reaching the fake cluster.
23
25
  *
24
26
  * ⛔ THERE IS NO PUT ON THIS FAMILY AT ALL. MEASURED from the cluster's own published schema
25
27
  * (`/usr/share/pve-docs/api-viewer/apidoc.js`, read on node-b 2026-09-13): `/nodes/{node}/disks/zfs`
@@ -47,7 +49,8 @@
47
49
  * ⚠️ TWO HANDLERS ARE OVERRIDDEN AND THE OTHER THREE COME FROM THE FACTORY — see the ★ above
48
50
  * `handlers`. `delete` is the ⛔ above. `reconcile` is because the create is a FORKED WORKER, so
49
51
  * the factory's immediate read-back would report a successful create as a failure; the measured
50
- * detail is in the ⛔ on `createPool` in zfs-pool-create.ts.
52
+ * detail, and the adopt-only refusal decision 9 adds, are both in `createPool` in
53
+ * zfs-pool-write.ts.
51
54
  *
52
55
  * ⚠️ PRIVILEGES, FROM THE SCHEMA. Read and diff need `Sys.Audit` on `/` — both GETs check it.
53
56
  * Reconcile needs `Sys.Modify` on `/` for the POST. `Datastore.Allocate` on `/storage` is NOT
@@ -56,10 +59,19 @@
56
59
  */
57
60
  import { Resource } from 'alchemy';
58
61
  import * as Provider from 'alchemy/Provider';
62
+ import type { NodesNodeDisksZfsPostParams } from './generated/pve.ts';
59
63
  import { type PveRequirements, type WithTarget } from './resource.ts';
60
- /** PVE's layouts. ⚠️ Each has a minimum disk count PVE enforces, and `raid10` needs an even one. */
61
- export type ZfsRaidLevel = 'single' | 'mirror' | 'raid10' | 'raidz' | 'raidz2' | 'raidz3' | 'draid' | 'draid2' | 'draid3';
62
- export type ZfsCompression = 'on' | 'off' | 'gzip' | 'lz4' | 'lzjb' | 'zle' | 'zstd';
64
+ /**
65
+ * PVE's layouts, generated (2026-09-23) from `NodesNodeDisksZfsPostParams['raidlevel']`
66
+ * (`generated/pve.ts`, manifest `pve-apidoc` pve-manager 9.2.11 sha256 9def8f13…) rather than
67
+ * hand-typed, per decision 9. ⚠️ Each has a minimum disk count PVE enforces, and `raid10` needs an
68
+ * even one. ⛔ THERE IS NO `stripe` IN THIS ENUM. n1's `speed` pool is one (decision 14 accepts it
69
+ * as-is): `ZfsPoolProps` below is why a stripe pool is declarable at all — as an ADOPT-ONLY
70
+ * declaration with no `raidlevel`, never as a full one.
71
+ */
72
+ export type ZfsRaidLevel = NonNullable<NodesNodeDisksZfsPostParams['raidlevel']>;
73
+ /** Generated the same way, from `NodesNodeDisksZfsPostParams['compression']`. */
74
+ export type ZfsCompression = NonNullable<NodesNodeDisksZfsPostParams['compression']>;
63
75
  /**
64
76
  * ⛔ THERE IS NO `add_storage`, `cleanup-config` OR `cleanup-disks` PROP, AND THAT IS NOT AN
65
77
  * OVERSIGHT. The last two belong to the DELETE this resource refuses to make. `add_storage=1`
@@ -91,9 +103,19 @@ export interface ZfsPoolProps extends WithTarget {
91
103
  * `csv` sorts, and sorting this list silently re-pairs the mirrors into a different pool.
92
104
  * ⚠️ PVE's only guard is `assert_disk_unused`, i.e. its own `disk_is_used` over the same `used`
93
105
  * column the Disks view shows. A blank disk it considers free is wiped with no confirmation.
106
+ *
107
+ * ⛔ OPTIONAL SINCE DECISION 9 (2026-09-23), AND OMITTING IT MEANS SOMETHING SPECIFIC: leaving
108
+ * both this and `raidlevel` undeclared declares an ADOPT-ONLY pool — one this resource may
109
+ * read and report but never build. That is the only shape available for a pool PVE's own POST
110
+ * schema cannot fully describe, such as n1's `speed`, whose layout is a stripe and whose
111
+ * `raidlevel` enum (above) has no stripe to declare. `createForm` (zfs-pool-write.ts) omits
112
+ * both keys when they are absent, and `createPool` refuses before any POST if the pool it
113
+ * would need to build is not already there — an adopt-only declaration never creates. Declare
114
+ * both fields together for a pool this resource should build from scratch; declaring only one
115
+ * of the two is refused the same way, since PVE's POST requires both.
94
116
  */
95
- devices: readonly string[];
96
- raidlevel: ZfsRaidLevel;
117
+ devices?: readonly string[];
118
+ raidlevel?: ZfsRaidLevel;
97
119
  /**
98
120
  * Sector size exponent, 9–16, PVE default 12.
99
121
  *
@@ -1 +1 @@
1
- {"version":3,"file":"zfs-pool.d.ts","sourceRoot":"","sources":["../../src/proxmox/zfs-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,UAAU,EAGhB,MAAM,eAAe,CAAC;AAIvB,oGAAoG;AACpG,MAAM,MAAM,YAAY,GACpB,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,QAAQ,CAAC;AAEb,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAErF;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,+FAA+F;IAC/F,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;;;;;OAYG;IACH,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,SAAS,EAAE,YAAY,CAAC;IACxB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,cAAc,CAAC;IAC7B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAe,SAAQ,QAAQ,CAC9C,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,mGAAmG;AACnG,eAAO,MAAM,cAAc,iDAEzB,CAAC;AA8EH,eAAO,MAAM,sBAAsB,oIACoD,CAAC"}
1
+ {"version":3,"file":"zfs-pool.d.ts","sourceRoot":"","sources":["../../src/proxmox/zfs-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAA8B,MAAM,eAAe,CAAC;AAIlG;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,2BAA2B,CAAC,WAAW,CAAC,CAAC,CAAC;AAEjF,iFAAiF;AACjF,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,2BAA2B,CAAC,aAAa,CAAC,CAAC,CAAC;AAErF;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,+FAA+F;IAC/F,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,cAAc,CAAC;IAC7B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAe,SAAQ,QAAQ,CAC9C,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,KAAK,EACL,eAAe,CAChB;CAAG;AAEJ,mGAAmG;AACnG,eAAO,MAAM,cAAc,iDAEzB,CAAC;AAqBH,eAAO,MAAM,sBAAsB,oIACoD,CAAC"}
@@ -13,17 +13,54 @@
13
13
  * ⛔ ADD A VENDOR ONLY AFTER ITS OWN WALK-DOWN (docs/release-binary-catalogs.md): its checksum
14
14
  * format read byte-exact, and its binary's linkage measured (`otool -L`). Vendor binaries were
15
15
  * measured self-contained ONLY for the five Victoria ones; that is not a property of "Go".
16
+ * ★ `computed` IS A SECOND, LESSER OWNER OF A MEMBER'S DIGEST — never the vendor's, always ours,
17
+ * for a checksum file that never lists the member at all (OpenBao: archives and SBOMs only,
18
+ * never `bao`; docs/release-binary-openbao.md is the walk-down). `checksums.signature` records
19
+ * how the checksum file's OWN authorship was checked, if a vendor publishes one to check.
16
20
  */
17
21
  import type { ReleaseArchive, ReleaseBinaryProps } from './binary-form.ts';
22
+ /**
23
+ * A member digest WE computed, because the vendor's checksum file never lists it — read
24
+ * checksums.ts's header before adding one: most vendors list archives only.
25
+ */
26
+ export interface ComputedDigest {
27
+ readonly sha256: string;
28
+ /** The date it was computed, from the archive whose pinned SHA-256 matched that day. */
29
+ readonly recorded: string;
30
+ }
31
+ /** How the checksum file itself was checked, beyond its own SHA-256 — openpgp today. */
32
+ export interface ChecksumSignature {
33
+ readonly kind: 'openpgp';
34
+ /** The detached signature asset's URL. */
35
+ readonly url: string;
36
+ readonly sha256: string;
37
+ /** The public key it was checked against. */
38
+ readonly key: {
39
+ readonly url: string;
40
+ readonly sha256: string;
41
+ readonly fingerprint: string;
42
+ };
43
+ /** The date `gpgv` was run, recorded once — never re-run at apply or by CI. */
44
+ readonly verified: string;
45
+ }
18
46
  /** One release archive as a catalog records it: the pin, plus where every digest came from. */
19
47
  export interface PinnedArchive extends ReleaseArchive {
20
48
  /** Archive member → its SHA-256. Every member the vendor's checksum file lists, not just ours. */
21
49
  readonly members: Readonly<Record<string, string>>;
50
+ /**
51
+ * Archive member → a digest WE computed, for a checksum file that never lists it (OpenBao's
52
+ * lists archives and SBOMs, never `bao`). ⛔ NOT A VENDOR FACT: computed from the bytes of an
53
+ * archive whose own SHA-256 already matched the pin, never filed beside `members`. A member in
54
+ * both is refused (catalogProblems) — two owners of one pin is a data-set bug, not a choice.
55
+ */
56
+ readonly computed?: Readonly<Record<string, ComputedDigest>>;
22
57
  /** The checksum file the digests were copied from, its own SHA-256, and when. Never fetched. */
23
58
  readonly checksums: {
24
59
  readonly url: string;
25
60
  readonly sha256: string;
26
61
  readonly recorded: string;
62
+ /** How the checksum file's own authorship was checked, if at all. Optional: not every vendor publishes one. */
63
+ readonly signature?: ChecksumSignature;
27
64
  };
28
65
  }
29
66
  /** One package (one archive per version and platform) of a vendor. */
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/release/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAG3E,+FAA+F;AAC/F,MAAM,WAAW,aAAc,SAAQ,cAAc;IACnD,kGAAkG;IAClG,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,gGAAgG;IAChG,QAAQ,CAAC,SAAS,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAClG;AAED,sEAAsE;AACtE,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpD,uFAAuF;IACvF,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;CACtF;AAED,kCAAkC;AAClC,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;CAC7D;AAED,+CAA+C;AAC/C,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,+FAA+F;AAC/F,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC;AAO9F,iFAAiF;AACjF,eAAO,MAAM,eAAe,YAAa,cAAc,WAAW,cAAc,KAAG,MAAM,EA2CxF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,YAAa,cAAc,WAAW,cAAc,KAAG,YA0BhF,CAAC;AAEF,4FAA4F;AAC5F,eAAO,MAAM,gBAAgB,SACrB,MAAM,WACH,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,SAAS,CAAC,KACnD,MAAyD,CAAC;AAE7D,8EAA8E;AAC9E,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5E;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,aACf,SAAS,cAAc,EAAE,UAC3B,MAAM,KACb,gBAAgB,GAAG,SAerB,CAAC"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/release/catalog.ts"],"names":[],"mappings":"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"}
@@ -14,8 +14,9 @@
14
14
  export type { PinnedDownload, ReleaseArchive, ReleaseBinaryAttributes, ReleaseBinaryProps, } from './binary-form.ts';
15
15
  export { releaseBinaryPath, releaseUrl } from './binary-form.ts';
16
16
  export { ReleaseBinary, ReleaseBinaryProvider } from './binary.ts';
17
- export type { CatalogPackage, CatalogRequest, IdentifiedBinary, PinnedArchive, PinnedBinary, ReleaseCatalog, } from './catalog.ts';
17
+ export type { CatalogPackage, CatalogRequest, ChecksumSignature, ComputedDigest, IdentifiedBinary, PinnedArchive, PinnedBinary, ReleaseCatalog, } from './catalog.ts';
18
18
  export { catalogBinary, catalogDirectory, catalogProblems, identifyBinary } from './catalog.ts';
19
+ export { OPENBAO_RELEASES } from './openbao.ts';
19
20
  export { releaseProviders } from './providers.ts';
20
21
  export { ArchiveRefused, BinaryRefused, ChecksumMismatch, DownloadFailed } from './refused.ts';
21
22
  export { VICTORIA_RELEASES } from './victoria.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/release/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,YAAY,EACV,cAAc,EACd,cAAc,EACd,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACnE,YAAY,EACV,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAChG,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC/F,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EACV,UAAU,EACV,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,YAAY,GACb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/release/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,YAAY,EACV,cAAc,EACd,cAAc,EACd,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACnE,YAAY,EACV,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAChG,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC/F,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EACV,UAAU,EACV,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,YAAY,GACb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1162,6 +1162,13 @@ var ReleaseBinaryProvider = () => makeReleaseBinaryProvider();
1162
1162
  // src/release/catalog.ts
1163
1163
  var quoted = (names) => [...names].map((n) => `"${n}"`).join(", ");
1164
1164
  var has = (record, key) => Object.hasOwn(record, key);
1165
+ var memberDigest = (archive, member) => {
1166
+ const vendor = has(archive.members, member) ? archive.members[member] : undefined;
1167
+ const computed = archive.computed !== undefined && has(archive.computed, member) ? archive.computed[member]?.sha256 : undefined;
1168
+ if (vendor !== undefined && computed !== undefined)
1169
+ return "both";
1170
+ return vendor ?? computed;
1171
+ };
1165
1172
  var catalogProblems = (catalog, request) => {
1166
1173
  const entry = has(catalog.packages, request.package) ? catalog.packages[request.package] : undefined;
1167
1174
  if (entry === undefined) {
@@ -1185,8 +1192,11 @@ var catalogProblems = (catalog, request) => {
1185
1192
  found.push(`${request.package} ${request.version} is not pinned for platform "${request.platform}" (${quoted(Object.keys(platforms))})`);
1186
1193
  } else if (found.length === 0) {
1187
1194
  const member = entry.binaries[request.binary] ?? "";
1188
- if (!has(archive.members, member)) {
1189
- found.push(`${request.package} ${request.version}'s checksum file lists no member "${member}"`);
1195
+ const digest = memberDigest(archive, member);
1196
+ if (digest === "both") {
1197
+ found.push(`${request.package} ${request.version}'s member "${member}" is pinned twice — once as a ` + "vendor digest and once as a computed one; a member has exactly one owner");
1198
+ } else if (digest === undefined) {
1199
+ found.push(`${request.package} ${request.version} pins no digest for member "${member}" (checked ` + "the vendor checksum file and any computed record)");
1190
1200
  }
1191
1201
  }
1192
1202
  return found;
@@ -1197,7 +1207,8 @@ var catalogBinary = (catalog, request) => {
1197
1207
  const entry = own(catalog.packages, request.package);
1198
1208
  const archive = own(own(entry?.versions, request.version), request.platform);
1199
1209
  const member = own(entry?.binaries, request.binary);
1200
- const sha256 = member === undefined ? undefined : own(archive?.members, member);
1210
+ const digest = member === undefined || archive === undefined ? undefined : memberDigest(archive, member);
1211
+ const sha256 = digest === "both" ? undefined : digest;
1201
1212
  if (problems.length > 0 || archive === undefined || member === undefined || sha256 === undefined) {
1202
1213
  throw new BinaryRefused({
1203
1214
  message: `Release.Binary ${request.binary}: ${problems.join("; ")}. Nothing was fetched.`
@@ -1218,7 +1229,8 @@ var identifyBinary = (catalogs, sha256) => {
1218
1229
  for (const [version, platforms] of Object.entries(entry.versions)) {
1219
1230
  for (const [platform, archive] of Object.entries(platforms)) {
1220
1231
  for (const [binary, member] of Object.entries(entry.binaries)) {
1221
- if (archive.members[member] === sha256) {
1232
+ const digest = memberDigest(archive, member);
1233
+ if (digest !== "both" && digest === sha256) {
1222
1234
  return { binary, package: pkg, platform, vendor: catalog.vendor, version };
1223
1235
  }
1224
1236
  }
@@ -1228,13 +1240,60 @@ var identifyBinary = (catalogs, sha256) => {
1228
1240
  }
1229
1241
  return;
1230
1242
  };
1243
+ // src/release/openbao.ts
1244
+ var RECORDED = "2026-09-23";
1245
+ var REPO2 = "openbao/openbao";
1246
+ var TAG = "v2.6.2";
1247
+ var DOWNLOAD = `https://github.com/${REPO2}/releases/download/${TAG}`;
1248
+ var OPENBAO_RELEASES = {
1249
+ packages: {
1250
+ openbao: {
1251
+ binaries: { bao: "bao" },
1252
+ versions: {
1253
+ "2.6.2": {
1254
+ darwin_arm64: {
1255
+ asset: "openbao_2.6.2_darwin_arm64.tar.gz",
1256
+ checksums: {
1257
+ recorded: RECORDED,
1258
+ sha256: "3d4a19fdc54a86fd94ce59ea91316dbf4304180bb27ae818e78e85c7f2164645",
1259
+ signature: {
1260
+ kind: "openpgp",
1261
+ key: {
1262
+ fingerprint: "66D15FDD87287219C8E15478D200CD702853E6D0",
1263
+ sha256: "1862a196422947124282e026ea4e09d6f7c5d383b628d90c17906936e6e5a8e0",
1264
+ url: "https://openbao.org/assets/openbao-gpg-pub-20240618.asc"
1265
+ },
1266
+ sha256: "40f294d642a2b4e9adac766ca6b8b2633e15b3dbfdf63969dedbf46d94df53e8",
1267
+ url: `${DOWNLOAD}/checksums.txt.gpgsig`,
1268
+ verified: RECORDED
1269
+ },
1270
+ url: `${DOWNLOAD}/checksums.txt`
1271
+ },
1272
+ computed: {
1273
+ bao: {
1274
+ recorded: RECORDED,
1275
+ sha256: "d476d17e81a35e6d70dd7e86a8ab2a3664313525118f1f1cfe0130e7a2b95f3a"
1276
+ }
1277
+ },
1278
+ members: {},
1279
+ repo: REPO2,
1280
+ sha256: "4e495376174accc0e014d31e9901f518a974f966850c839f626347eaac05fd52",
1281
+ size: 76833570,
1282
+ tag: TAG
1283
+ }
1284
+ }
1285
+ }
1286
+ }
1287
+ },
1288
+ vendor: "OpenBao"
1289
+ };
1231
1290
  // src/release/providers.ts
1232
1291
  import * as Layer2 from "effect/Layer";
1233
1292
  import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
1234
1293
  var releaseProviders = (runner) => ReleaseBinaryProvider().pipe(Layer2.provide(Layer2.mergeAll(hostRunnerLayer(runner), FetchHttpClient.layer)));
1235
1294
  // src/release/victoria.ts
1236
- var RECORDED = "2026-09-22";
1237
- var DOWNLOAD = "https://github.com/VictoriaMetrics";
1295
+ var RECORDED2 = "2026-09-22";
1296
+ var DOWNLOAD2 = "https://github.com/VictoriaMetrics";
1238
1297
  var VICTORIA_RELEASES = {
1239
1298
  packages: {
1240
1299
  "victoria-logs": {
@@ -1244,9 +1303,9 @@ var VICTORIA_RELEASES = {
1244
1303
  "darwin-arm64": {
1245
1304
  asset: "victoria-logs-darwin-arm64-v1.52.0.tar.gz",
1246
1305
  checksums: {
1247
- recorded: RECORDED,
1306
+ recorded: RECORDED2,
1248
1307
  sha256: "d4ca686c3cceec78a0f4e733ef9ab3f857549131ea48cd6f89f701cda406ac4b",
1249
- url: `${DOWNLOAD}/VictoriaLogs/releases/download/v1.52.0/victoria-logs-darwin-arm64-v1.52.0_checksums.txt`
1308
+ url: `${DOWNLOAD2}/VictoriaLogs/releases/download/v1.52.0/victoria-logs-darwin-arm64-v1.52.0_checksums.txt`
1250
1309
  },
1251
1310
  members: {
1252
1311
  "victoria-logs-prod": "9e48809e314902782959b3a4e683a3087476759d0293791a0564921c676ca7be"
@@ -1266,9 +1325,9 @@ var VICTORIA_RELEASES = {
1266
1325
  "darwin-arm64": {
1267
1326
  asset: "victoria-metrics-darwin-arm64-v1.151.0.tar.gz",
1268
1327
  checksums: {
1269
- recorded: RECORDED,
1328
+ recorded: RECORDED2,
1270
1329
  sha256: "735745ee0e7b2d5b8118883f2d0ed124c2a12d70261c16380128f5e362566d1e",
1271
- url: `${DOWNLOAD}/VictoriaMetrics/releases/download/v1.151.0/victoria-metrics-darwin-arm64-v1.151.0_checksums.txt`
1330
+ url: `${DOWNLOAD2}/VictoriaMetrics/releases/download/v1.151.0/victoria-metrics-darwin-arm64-v1.151.0_checksums.txt`
1272
1331
  },
1273
1332
  members: {
1274
1333
  "victoria-metrics-prod": "3c493a95ac1e9034a3261b230c4d62f3b186a04aafcdbacc99bfc110dc5de6a1"
@@ -1288,9 +1347,9 @@ var VICTORIA_RELEASES = {
1288
1347
  "darwin-arm64": {
1289
1348
  asset: "victoria-traces-darwin-arm64-v0.10.0.tar.gz",
1290
1349
  checksums: {
1291
- recorded: RECORDED,
1350
+ recorded: RECORDED2,
1292
1351
  sha256: "cd32bfc21900b48ba543124e43827a1d13d735e45d50dbfd742c0ca6640e1aae",
1293
- url: `${DOWNLOAD}/VictoriaTraces/releases/download/v0.10.0/victoria-traces-darwin-arm64-v0.10.0_checksums.txt`
1352
+ url: `${DOWNLOAD2}/VictoriaTraces/releases/download/v0.10.0/victoria-traces-darwin-arm64-v0.10.0_checksums.txt`
1294
1353
  },
1295
1354
  members: {
1296
1355
  "victoria-traces-prod": "4759ec89a466129b9eefc22244a111e1f489739340747805fd93b58fd0f7b2dd"
@@ -1318,9 +1377,9 @@ var VICTORIA_RELEASES = {
1318
1377
  "darwin-arm64": {
1319
1378
  asset: "vmutils-darwin-arm64-v1.151.0.tar.gz",
1320
1379
  checksums: {
1321
- recorded: RECORDED,
1380
+ recorded: RECORDED2,
1322
1381
  sha256: "fda5a64fce9022bee7614c3fda27271c0826f1d7b90f8b162e1f48c77c0df04b",
1323
- url: `${DOWNLOAD}/VictoriaMetrics/releases/download/v1.151.0/vmutils-darwin-arm64-v1.151.0_checksums.txt`
1382
+ url: `${DOWNLOAD2}/VictoriaMetrics/releases/download/v1.151.0/vmutils-darwin-arm64-v1.151.0_checksums.txt`
1324
1383
  },
1325
1384
  members: {
1326
1385
  "vmagent-prod": "d3b6fa1f71ef48beac619f15f8adfa7610e76605caf37db1ebfbb379b6692329",
@@ -1348,6 +1407,7 @@ export {
1348
1407
  ChecksumMismatch,
1349
1408
  DownloadFailed,
1350
1409
  HostRunnerService,
1410
+ OPENBAO_RELEASES,
1351
1411
  ReleaseBinary,
1352
1412
  ReleaseBinaryProvider,
1353
1413
  VICTORIA_RELEASES,
@@ -1361,5 +1421,5 @@ export {
1361
1421
  releaseUrl
1362
1422
  };
1363
1423
 
1364
- //# debugId=F5F53F961865973E64756E2164756E21
1424
+ //# debugId=95AC8419C10B267864756E2164756E21
1365
1425
  //# sourceMappingURL=index.js.map