@homeflare/alchemy 0.37.1 → 0.37.3
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/backup-job-config.d.ts +95 -0
- package/dist/proxmox/backup-job-config.d.ts.map +1 -0
- package/dist/proxmox/backup-job-distilled.d.ts +46 -0
- package/dist/proxmox/backup-job-distilled.d.ts.map +1 -0
- package/dist/proxmox/backup-job.d.ts +9 -26
- package/dist/proxmox/backup-job.d.ts.map +1 -1
- package/dist/proxmox/ceph-fs-distilled.d.ts +17 -10
- package/dist/proxmox/ceph-fs-distilled.d.ts.map +1 -1
- package/dist/proxmox/ceph-fs-wire.d.ts +5 -22
- package/dist/proxmox/ceph-fs-wire.d.ts.map +1 -1
- package/dist/proxmox/ceph-fs.d.ts +3 -3
- package/dist/proxmox/distilled-pbs.d.ts +12 -0
- package/dist/proxmox/distilled-pbs.d.ts.map +1 -0
- package/dist/proxmox/fake-pbs-jobs.d.ts +23 -0
- package/dist/proxmox/fake-pbs-jobs.d.ts.map +1 -0
- package/dist/proxmox/fake-pbs-notify.d.ts.map +1 -1
- package/dist/proxmox/fake-pve.d.ts +1 -1
- package/dist/proxmox/fake-pve.d.ts.map +1 -1
- package/dist/proxmox/group-wire.d.ts +2 -2
- package/dist/proxmox/group-wire.d.ts.map +1 -1
- package/dist/proxmox/index.js +1382 -506
- package/dist/proxmox/index.js.map +51 -27
- package/dist/proxmox/live-core-fixtures.d.ts +40 -0
- package/dist/proxmox/live-core-fixtures.d.ts.map +1 -0
- package/dist/proxmox/metric-server-config.d.ts +49 -0
- package/dist/proxmox/metric-server-config.d.ts.map +1 -0
- package/dist/proxmox/metric-server-distilled.d.ts +43 -0
- package/dist/proxmox/metric-server-distilled.d.ts.map +1 -0
- package/dist/proxmox/metric-server.d.ts +2 -10
- package/dist/proxmox/metric-server.d.ts.map +1 -1
- package/dist/proxmox/node-network-wire.d.ts +1 -1
- package/dist/proxmox/node-network-wire.d.ts.map +1 -1
- package/dist/proxmox/notification-matcher-distilled.d.ts +9 -0
- package/dist/proxmox/notification-matcher-distilled.d.ts.map +1 -0
- package/dist/proxmox/notification-matcher-lifecycle.d.ts +27 -0
- package/dist/proxmox/notification-matcher-lifecycle.d.ts.map +1 -0
- package/dist/proxmox/notification-matcher.d.ts +5 -5
- package/dist/proxmox/notification-matcher.d.ts.map +1 -1
- package/dist/proxmox/notification-sdk-input.d.ts +22 -0
- package/dist/proxmox/notification-sdk-input.d.ts.map +1 -0
- package/dist/proxmox/notification-target-distilled.d.ts +12 -0
- package/dist/proxmox/notification-target-distilled.d.ts.map +1 -0
- package/dist/proxmox/notification-target-form.d.ts +2 -0
- package/dist/proxmox/notification-target-form.d.ts.map +1 -1
- package/dist/proxmox/notification-target-lifecycle.d.ts +29 -0
- package/dist/proxmox/notification-target-lifecycle.d.ts.map +1 -0
- package/dist/proxmox/notification-target-spec.d.ts +5 -0
- package/dist/proxmox/notification-target-spec.d.ts.map +1 -0
- package/dist/proxmox/notification-target.d.ts +4 -5
- package/dist/proxmox/notification-target.d.ts.map +1 -1
- package/dist/proxmox/pbs-datastore-endpoint.d.ts +1 -1
- package/dist/proxmox/pbs-datastore-form.d.ts +18 -42
- package/dist/proxmox/pbs-datastore-form.d.ts.map +1 -1
- package/dist/proxmox/pbs-datastore-guard.d.ts +7 -4
- package/dist/proxmox/pbs-datastore-guard.d.ts.map +1 -1
- package/dist/proxmox/pbs-datastore-lifecycle.d.ts +56 -0
- package/dist/proxmox/pbs-datastore-lifecycle.d.ts.map +1 -0
- package/dist/proxmox/pbs-datastore-wire.d.ts +21 -0
- package/dist/proxmox/pbs-datastore-wire.d.ts.map +1 -0
- package/dist/proxmox/pbs-datastore.d.ts +5 -6
- package/dist/proxmox/pbs-datastore.d.ts.map +1 -1
- package/dist/proxmox/pbs-notification-input.d.ts +18 -0
- package/dist/proxmox/pbs-notification-input.d.ts.map +1 -0
- package/dist/proxmox/pbs-notification-matcher-distilled.d.ts +11 -0
- package/dist/proxmox/pbs-notification-matcher-distilled.d.ts.map +1 -0
- package/dist/proxmox/pbs-notification-matcher.d.ts +4 -3
- package/dist/proxmox/pbs-notification-matcher.d.ts.map +1 -1
- package/dist/proxmox/pbs-notification-target-distilled.d.ts +20 -0
- package/dist/proxmox/pbs-notification-target-distilled.d.ts.map +1 -0
- package/dist/proxmox/pbs-notification-target-lifecycle.d.ts +4 -4
- package/dist/proxmox/pbs-notification-target-lifecycle.d.ts.map +1 -1
- package/dist/proxmox/pbs-notification-target.d.ts +1 -1
- package/dist/proxmox/pbs-prune-job-lifecycle.d.ts +22 -0
- package/dist/proxmox/pbs-prune-job-lifecycle.d.ts.map +1 -0
- package/dist/proxmox/pbs-prune-job-spec.d.ts +5 -0
- package/dist/proxmox/pbs-prune-job-spec.d.ts.map +1 -0
- package/dist/proxmox/pbs-prune-job-wire.d.ts +11 -0
- package/dist/proxmox/pbs-prune-job-wire.d.ts.map +1 -0
- package/dist/proxmox/pbs-prune-job.d.ts +9 -8
- package/dist/proxmox/pbs-prune-job.d.ts.map +1 -1
- package/dist/proxmox/pbs-sync-job-attributes.d.ts +34 -0
- package/dist/proxmox/pbs-sync-job-attributes.d.ts.map +1 -0
- package/dist/proxmox/pbs-sync-job-form.d.ts +21 -22
- package/dist/proxmox/pbs-sync-job-form.d.ts.map +1 -1
- package/dist/proxmox/pbs-sync-job-lifecycle.d.ts +22 -0
- package/dist/proxmox/pbs-sync-job-lifecycle.d.ts.map +1 -0
- package/dist/proxmox/pbs-sync-job-wire.d.ts +11 -0
- package/dist/proxmox/pbs-sync-job-wire.d.ts.map +1 -0
- package/dist/proxmox/pbs-sync-job.d.ts +9 -39
- package/dist/proxmox/pbs-sync-job.d.ts.map +1 -1
- package/dist/proxmox/pbs-verify-job-lifecycle.d.ts +22 -0
- package/dist/proxmox/pbs-verify-job-lifecycle.d.ts.map +1 -0
- package/dist/proxmox/pbs-verify-job-spec.d.ts +16 -0
- package/dist/proxmox/pbs-verify-job-spec.d.ts.map +1 -0
- package/dist/proxmox/pbs-verify-job-wire.d.ts +11 -0
- package/dist/proxmox/pbs-verify-job-wire.d.ts.map +1 -0
- package/dist/proxmox/pbs-verify-job.d.ts +12 -12
- package/dist/proxmox/pbs-verify-job.d.ts.map +1 -1
- package/dist/proxmox/pool.d.ts +10 -1
- package/dist/proxmox/pool.d.ts.map +1 -1
- package/dist/proxmox/storage-wire.d.ts +2 -2
- package/dist/proxmox/storage-wire.d.ts.map +1 -1
- package/dist/proxmox/user-wire.d.ts +2 -2
- package/dist/proxmox/user-wire.d.ts.map +1 -1
- package/dist/proxmox/zfs-pool-wire.d.ts +1 -1
- package/dist/proxmox/zfs-pool-wire.d.ts.map +1 -1
- package/docs/changelog/README.md +22 -0
- package/docs/changelog/archive-01.md +176 -0
- package/docs/changelog/archive-02.md +180 -0
- package/docs/changelog/archive-03.md +179 -0
- package/docs/changelog/archive-04.md +178 -0
- package/docs/changelog/archive-05.md +177 -0
- package/docs/changelog/archive-06.md +180 -0
- package/docs/changelog/archive-07.md +180 -0
- package/docs/changelog/archive-08.md +178 -0
- package/docs/changelog/archive-09.md +181 -0
- package/docs/changelog/archive-10.md +182 -0
- package/docs/changelog/archive-11.md +182 -0
- package/docs/changelog/archive-12.md +183 -0
- package/docs/changelog/archive-13.md +180 -0
- package/docs/changelog/archive-14.md +178 -0
- package/docs/changelog/archive-15.md +181 -0
- package/docs/changelog/archive-16.md +182 -0
- package/docs/changelog/archive-17.md +183 -0
- package/docs/changelog/archive-18.md +55 -0
- package/docs/pbs-distilled-jobs.md +31 -0
- package/docs/pbs-notifications.md +8 -2
- package/docs/proxmox-notification-sdk.md +28 -0
- package/docs/proxmox-sdk-migration.md +60 -0
- package/docs/proxmox.md +9 -3
- package/docs/upstream-conformance-families.md +6 -2
- package/package.json +3 -3
- package/src/proxmox/adopt-noop.test.ts +4 -5
- package/src/proxmox/backup-job-config.ts +95 -0
- package/src/proxmox/backup-job-distilled.ts +86 -0
- package/src/proxmox/backup-job.ts +78 -116
- package/src/proxmox/ceph-fs-delete.test.ts +5 -8
- package/src/proxmox/ceph-fs-destroy-sdk.test.ts +98 -0
- package/src/proxmox/ceph-fs-distilled.ts +41 -13
- package/src/proxmox/ceph-fs-wire.ts +5 -93
- package/src/proxmox/ceph-fs.ts +7 -7
- package/src/proxmox/constraints.test.ts +9 -8
- package/src/proxmox/distilled-pbs.test.ts +87 -0
- package/src/proxmox/distilled-pbs.ts +50 -0
- package/src/proxmox/fake-pbs-jobs.ts +99 -0
- package/src/proxmox/fake-pbs-notify.ts +4 -1
- package/src/proxmox/fake-pve.ts +3 -2
- package/src/proxmox/live-core-fixtures.ts +126 -0
- package/src/proxmox/live-core-lifecycle.test.ts +115 -0
- package/src/proxmox/live-core-wire.test.ts +190 -0
- package/src/proxmox/metric-server-config.ts +87 -0
- package/src/proxmox/metric-server-distilled.ts +81 -0
- package/src/proxmox/metric-server.ts +77 -88
- package/src/proxmox/notification-distilled.test.ts +162 -0
- package/src/proxmox/notification-matcher-distilled.ts +60 -0
- package/src/proxmox/notification-matcher-lifecycle.ts +71 -0
- package/src/proxmox/notification-matcher.ts +9 -26
- package/src/proxmox/notification-replacement.test.ts +190 -0
- package/src/proxmox/notification-sdk-input.ts +39 -0
- package/src/proxmox/notification-target-distilled.ts +160 -0
- package/src/proxmox/notification-target-form.ts +2 -0
- package/src/proxmox/notification-target-lifecycle.ts +75 -0
- package/src/proxmox/notification-target-spec.ts +68 -0
- package/src/proxmox/notification-target.ts +6 -68
- package/src/proxmox/pbs-datastore-endpoint.ts +1 -1
- package/src/proxmox/pbs-datastore-form.ts +18 -49
- package/src/proxmox/pbs-datastore-guard.ts +7 -4
- package/src/proxmox/pbs-datastore-lifecycle.ts +114 -0
- package/src/proxmox/pbs-datastore-wire.ts +94 -0
- package/src/proxmox/pbs-datastore.ts +7 -133
- package/src/proxmox/pbs-jobs-delete.test.ts +40 -0
- package/src/proxmox/pbs-jobs-sdk.test.ts +215 -0
- package/src/proxmox/pbs-notification-errors.test.ts +93 -0
- package/src/proxmox/pbs-notification-input.ts +25 -0
- package/src/proxmox/pbs-notification-mail.test.ts +64 -0
- package/src/proxmox/pbs-notification-matcher-distilled.ts +65 -0
- package/src/proxmox/pbs-notification-matcher.ts +70 -17
- package/src/proxmox/pbs-notification-target-distilled.ts +124 -0
- package/src/proxmox/pbs-notification-target-lifecycle.ts +26 -17
- package/src/proxmox/pbs-notification-target.ts +1 -1
- package/src/proxmox/pbs-notifications-stack.test.ts +25 -0
- package/src/proxmox/pbs-prune-job-lifecycle.ts +52 -0
- package/src/proxmox/pbs-prune-job-spec.ts +53 -0
- package/src/proxmox/pbs-prune-job-wire.ts +68 -0
- package/src/proxmox/pbs-prune-job.ts +10 -58
- package/src/proxmox/pbs-sync-job-attributes.ts +33 -0
- package/src/proxmox/pbs-sync-job-form.ts +7 -6
- package/src/proxmox/pbs-sync-job-lifecycle.ts +46 -0
- package/src/proxmox/pbs-sync-job-wire.ts +71 -0
- package/src/proxmox/pbs-sync-job.ts +10 -41
- package/src/proxmox/pbs-verify-job-lifecycle.ts +52 -0
- package/src/proxmox/pbs-verify-job-spec.ts +76 -0
- package/src/proxmox/pbs-verify-job-wire.ts +58 -0
- package/src/proxmox/pbs-verify-job.ts +13 -85
- package/src/proxmox/pool.ts +92 -10
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Alchemy changelog archive 8
|
|
2
|
+
|
|
3
|
+
[Current changelog](../../CHANGELOG.md) · [Archive index](./README.md)
|
|
4
|
+
|
|
5
|
+
Known trade-off (found by adversarial review, 2026-09-24): forcing the ruleset first only helps
|
|
6
|
+
once the repository already exists. A repo and its ruleset created together for the FIRST time,
|
|
7
|
+
with `checks` non-empty from day one, now fails clearly instead of racing — GitHub's own ruleset
|
|
8
|
+
API 404s on a repository that does not exist yet, and the engine now guarantees that order rather
|
|
9
|
+
than leaving it to chance. Both `declareRepoBaseline` and `declareRepoPolicy` document this and a
|
|
10
|
+
new test proves the failure is explicit, not a silent fail-open; the fix is for an ALREADY-LIVE
|
|
11
|
+
repo moving from no checks to some, which is K5's own scenario and the documented use of both
|
|
12
|
+
functions.
|
|
13
|
+
|
|
14
|
+
## 0.29.0
|
|
15
|
+
|
|
16
|
+
### Minor Changes
|
|
17
|
+
|
|
18
|
+
- [#222](https://github.com/taslabs-net/homeflare-kit/pull/222) [`1e6285f`](https://github.com/taslabs-net/homeflare-kit/commit/1e6285fb229dca7455afa5b52e1c79ca3286dc26) Thanks [@taslabs-net](https://github.com/taslabs-net)! - Declare `@distilled.cloud/discord`, `@distilled.cloud/google-workspace` and `@distilled.cloud/grafana` (1.0.0-rc.12) as exact-pinned peers, ahead of the Discord, Google Workspace and Grafana provider families. Per the peer contract they are required, and they appear in the README install line and the smoke install.
|
|
19
|
+
|
|
20
|
+
- [#208](https://github.com/taslabs-net/homeflare-kit/pull/208) [`2d28264`](https://github.com/taslabs-net/homeflare-kit/commit/2d28264e71d9f141ff0771f57dab49d6daa79904) Thanks [@taslabs-net](https://github.com/taslabs-net)! - `GitHub.RepositoryRuleset`'s `rules.pullRequest.extraApprovalForUnattributedChanges` now accepts
|
|
21
|
+
`true`, not only `false`. Re-read live 2026-09-23, 8 rulesets carry
|
|
22
|
+
`require_extra_approval_for_unattributed_changes: true` (aop, cloudflareforms,
|
|
23
|
+
doesthishelp-workeropen, homeflare-anyauth, homeflare-desktop, loggarr, magictransit,
|
|
24
|
+
proxmox-tb4), so this resource could not declare their exact shape before: it would either omit
|
|
25
|
+
the field (leaving it unmanaged, refused once a caller also carries a `bypassActors`/rule
|
|
26
|
+
declaration for the same ruleset) or send `false`, which is real drift against a live `true` on
|
|
27
|
+
every plan.
|
|
28
|
+
|
|
29
|
+
The wire builder now sends whatever is declared instead of hardcoding `false`; `undefined` still
|
|
30
|
+
means "no opinion" (GitHub defaults an absent key to `true`). `repoBaselineRuleset()` in
|
|
31
|
+
repo-baseline-data.ts is unchanged — the house baseline still pins `false` for the repos that
|
|
32
|
+
fit it; a caller with a live `true` declares `RepositoryRuleset` directly with the live value,
|
|
33
|
+
the same pattern kit PR 205 established for `bypassActors` and rule presence.
|
|
34
|
+
|
|
35
|
+
Tested against aop's full live shape (`gh api repos/taslabs-net/aop/rulesets/14572279`,
|
|
36
|
+
re-read 2026-09-23): declaring the live value (including `true`) is now a genuine zero-write
|
|
37
|
+
adopt, and declaring `false` against a live `true` is still real drift, never a silent noop.
|
|
38
|
+
|
|
39
|
+
- [#214](https://github.com/taslabs-net/homeflare-kit/pull/214) [`9af4441`](https://github.com/taslabs-net/homeflare-kit/commit/9af4441462743476da58ee06af877ec0b346aa1f) Thanks [@taslabs-net](https://github.com/taslabs-net)! - `GitHub.RepositoryRuleset`'s "never-reported context" guard (`refuseUnreportedContexts` /
|
|
40
|
+
`hasContextReportedSuccess`) checked only the default branch's current tip. The house's rendered
|
|
41
|
+
CI (`packages/config/src/repo-shape/ci.ts`) triggers on `pull_request` only, deliberately (no
|
|
42
|
+
`push: [main]` — a squash-merged commit re-testing an already-green PR was ~41% of the mini's CI
|
|
43
|
+
load, measured 2026-09-15..22), so `ci`, `secret scan` and `CodeQL` never report on the tip
|
|
44
|
+
itself. The guard refused adding any of them everywhere, including homeflare-builds' pending
|
|
45
|
+
first ruleset.
|
|
46
|
+
|
|
47
|
+
`hasContextReportedSuccess` now falls back to up to `RECENT_MERGED_PR_LIMIT` (10) recent merged
|
|
48
|
+
pull requests' head SHAs — one bounded list call, never the repo's full PR history — checked only
|
|
49
|
+
if the tip itself has no reported success. A context that has never reported success ANYWHERE
|
|
50
|
+
(not the tip, not any recent merged head) is still refused: the guard's whole purpose is
|
|
51
|
+
unchanged, only where it is willing to look for evidence widened.
|
|
52
|
+
|
|
53
|
+
The core logic (`contextReportedSuccess`, `hasRefReportedSuccess`, `recentMergedHeadShas`) is now
|
|
54
|
+
exported as plain functions over a real `OctokitClient`, not only reachable through the
|
|
55
|
+
`GitHubCredentials`-gated `RulesetOctokit` — the same pure-function seam `desiredWireRuleset`
|
|
56
|
+
already uses — so `repository-ruleset-octokit.test.ts` measures it against a real `@octokit/rest`
|
|
57
|
+
instance with a fetch shim (no network), mirroring the H15 wire test: accepting a context that
|
|
58
|
+
reports only on a recent merged head, refusing one that reports nowhere, and refusing one whose
|
|
59
|
+
only success is older than the bound (the limit is real, not decorative).
|
|
60
|
+
|
|
61
|
+
### Patch Changes
|
|
62
|
+
|
|
63
|
+
- [#219](https://github.com/taslabs-net/homeflare-kit/pull/219) [`40c08eb`](https://github.com/taslabs-net/homeflare-kit/commit/40c08ebfc3ca04de7338deb95b217fbdce6c50d7) Thanks [@taslabs-net](https://github.com/taslabs-net)! - The `caddy/*` family (`Caddy.Config`, `caddyWithFile`, `localCaddyAdmin`) now calls
|
|
64
|
+
`@distilled.cloud/caddy`'s typed `admin` operations (`adaptConfig`, `loadConfig`,
|
|
65
|
+
`getConfig`) instead of a hand-rolled promise-based `CaddyAdmin.request()` interface.
|
|
66
|
+
Every operation's error channel is `catchTag`-able (`Caddy.CaddyOpError`); `isUnreachable`
|
|
67
|
+
(caddy-http-client.ts) is a type guard over the SDK's own `HttpClientError`, replacing the
|
|
68
|
+
old `CaddyUnreachableError` class, and gates the same "plan without Caddy" escape hatch
|
|
69
|
+
config.ts always had.
|
|
70
|
+
|
|
71
|
+
The measured local transport survives unchanged in shape: loopback TCP or a unix socket,
|
|
72
|
+
Host/Origin headers as the Caddy CLI sends them, retrying only a connection nothing
|
|
73
|
+
accepted (`ECONNREFUSED`/`ENOENT`) — now built as an Effect `HttpClient.HttpClient` layer
|
|
74
|
+
(`caddy-http-client.ts`) the SDK's protocol runs over, over `node:http` (not
|
|
75
|
+
`FetchHttpClient`: only `node:http` dials a unix socket on both Bun and Node). The
|
|
76
|
+
`LoadRefused` 200-trap (a refused `/load` that still answers 200 with the error appended
|
|
77
|
+
after the adapter's warnings) is first-class in the SDK's own `protocol.ts`, not
|
|
78
|
+
re-detected here.
|
|
79
|
+
|
|
80
|
+
Two real gaps this migration found and fixed at the source, never worked around in the
|
|
81
|
+
resource:
|
|
82
|
+
|
|
83
|
+
- `@distilled.cloud/caddy`'s `AdaptConfig`/`LoadConfig` JSON-encoded the Caddyfile TEXT and
|
|
84
|
+
overwrote the caller's `Content-Type` — fixed in the distilled clone's `protocol.ts` and
|
|
85
|
+
shipped as `@homeflare/distilled-caddy@0.2.1` (sibling changeset).
|
|
86
|
+
- The SDK's own default retry policy treats any transport-level `HttpClientError` as
|
|
87
|
+
retryable, including a `POST /load` that was already accepted before the connection
|
|
88
|
+
reset — `local-admin.ts` now disables it (`Caddy.Retry.Retry`) so caddy-http-client.ts's
|
|
89
|
+
own narrower ECONNREFUSED/ENOENT-only retry is the only one in play.
|
|
90
|
+
|
|
91
|
+
`providers.ts`'s `caddyProviders()` (and this family's own tests) also fix a wiring bug the
|
|
92
|
+
migration surfaced: `CaddyConfigProvider().pipe(Layer.provide(caddyAdminLayer(...)))`
|
|
93
|
+
seals `caddyAdminLayer`'s services away from the provider's `read`/`diff`/`reconcile`
|
|
94
|
+
handlers once they are built, so the engine's later call to any of them died with "Service
|
|
95
|
+
not found". `Layer.provideMerge` keeps those services live for every later call.
|
|
96
|
+
|
|
97
|
+
State did not move: props and attributes stay byte-identical (`configSha256`, `endpoint`,
|
|
98
|
+
`sourceFile`) — proven by the family's existing tests (updated only where the typed-error
|
|
99
|
+
message text itself changed, from the old ad hoc `method path -> status` strings to the
|
|
100
|
+
SDK's own tagged errors) plus fake-caddy.ts, a real HTTP server, so every test already
|
|
101
|
+
drives the real distilled wire protocol, not a re-implementation of it.
|
|
102
|
+
|
|
103
|
+
- [#209](https://github.com/taslabs-net/homeflare-kit/pull/209) [`1eaf80f`](https://github.com/taslabs-net/homeflare-kit/commit/1eaf80f9ef2ad5e616f1a459ed6396819be15e6c) Thanks [@taslabs-net](https://github.com/taslabs-net)! - The `proxmox/*` family's `Proxmox.Acl` (the first resource in the PVE
|
|
104
|
+
`access/ACL` sub-area, per decision 43's serial proxmox walk-down) now calls
|
|
105
|
+
`@distilled.cloud/proxmox`'s typed `access.listAccessAcl`/`access.putAccessAcl`
|
|
106
|
+
operations instead of `client.ts`'s hand-rolled, generic `pve()` call. A new
|
|
107
|
+
`distilled-pve.ts` module (`runPve`/`runPveWith`) replaces `pve()`/`pveWith`
|
|
108
|
+
for a migrated family: the same OpenBao lease reuse (`lease-cache.ts`,
|
|
109
|
+
unchanged) and the same cluster-member failover safety rule (`members.ts`,
|
|
110
|
+
unchanged — a write may repeat only on a provably pre-send transport
|
|
111
|
+
failure, never on an HTTP answer or a post-connect timeout), now re-running
|
|
112
|
+
the whole typed operation per member instead of retrying one already-built
|
|
113
|
+
request. `client.ts`/`pveOperations` are untouched and still serve every
|
|
114
|
+
other PVE family; `Proxmox.Acl` is the first to move off them, chosen
|
|
115
|
+
because it was already the one family that didn't fit the generic
|
|
116
|
+
path+form shape (no create/delete verb — PVE has only GET/PUT on
|
|
117
|
+
`/access/acl`).
|
|
118
|
+
|
|
119
|
+
One dead branch is removed, not preserved: the old code's generic factory
|
|
120
|
+
POSTed on a "live read undefined" case that its own comments called
|
|
121
|
+
unreachable on a healthy cluster and documented as actively misleading (PVE
|
|
122
|
+
has no POST here, so the 501 it got back said nothing about the real
|
|
123
|
+
failure). `@distilled.cloud/proxmox` has no `createAccessAcl` at all — the
|
|
124
|
+
vendor schema has no POST for the generator to make one from — so there is
|
|
125
|
+
nothing to call that way any more. `reconcile` now always PUTs, the only
|
|
126
|
+
write PVE actually implements for this path, so a read that genuinely fails
|
|
127
|
+
surfaces its real cause instead of a confusing 501.
|
|
128
|
+
|
|
129
|
+
A trap found while writing the member-failover test: `@distilled.cloud/core`'s
|
|
130
|
+
default retry policy retries transport failures automatically (not just
|
|
131
|
+
5xx answers), which could have resent a write to the same member several
|
|
132
|
+
times before this file's own cluster failover ever saw a result to
|
|
133
|
+
classify — the hand-rolled client never auto-retried anything. `distilled-pve.ts`
|
|
134
|
+
disables the SDK's retry (`Retry.none`) on every attempt, keeping
|
|
135
|
+
member failover the only place a request repeats, matching the original
|
|
136
|
+
behavior exactly.
|
|
137
|
+
|
|
138
|
+
State did not move: `AclProps`/`AclAttributes` are unchanged, and the
|
|
139
|
+
existing cross-family `adopt-noop.test.ts` case for `Proxmox.Acl` (an
|
|
140
|
+
already-matching grant is read-only) passes unmodified against the new
|
|
141
|
+
code. New tests (`acl.test.ts`, `distilled-pve.test.ts`) drive a fake PVE
|
|
142
|
+
server through the real distilled protocol — real path assembly, real
|
|
143
|
+
form-urlencoded PUT bodies, real `{"data": ...}` envelope — covering
|
|
144
|
+
create, drift-correction, delete, identity-replace, the read-back guard,
|
|
145
|
+
and cluster-member failover for both a read and a write.
|
|
146
|
+
|
|
147
|
+
This is PR 1 of a serial, sub-area-by-sub-area migration
|
|
148
|
+
(access/ACL, then nodes/storage, then notifications, then PBS, …) of the
|
|
149
|
+
~98-resource PVE family plus the PBS resources onto
|
|
150
|
+
`@distilled.cloud/proxmox`/`@distilled.cloud/proxmox-backup`. The other PVE
|
|
151
|
+
and PBS resources still call `client.ts`'s `pve()`, unchanged; `client.ts`
|
|
152
|
+
is deleted only once nothing imports it.
|
|
153
|
+
|
|
154
|
+
- [#215](https://github.com/taslabs-net/homeflare-kit/pull/215) [`72c448d`](https://github.com/taslabs-net/homeflare-kit/commit/72c448dbaec8f2acb7b5109aa7387a4409185fe8) Thanks [@taslabs-net](https://github.com/taslabs-net)! - Fix a review finding on the `litellm/*` distilled migration (`@homeflare/distilled-litellm`'s
|
|
155
|
+
`CredentialsFromEnv`, S20): a missing or misspelled `LITELLM_PROXY_URL`/`LITELLM_PROXY_API_KEY`
|
|
156
|
+
used to die as an unrecoverable Effect defect and crash the whole engine, instead of the typed
|
|
157
|
+
`ConfigError` `LitellmOpError` already declared — a regression this migration made newly
|
|
158
|
+
reachable from `LiteLLM.PassThroughEndpoint`'s `read`/`reconcile`/`delete` (the retired
|
|
159
|
+
hand-rolled `credentials.ts` failed typed). Fixed at the source, per house rule: the distilled
|
|
160
|
+
`litellm` package's own `credentials.ts` no longer ends in `Effect.orDie`, copied forward into
|
|
161
|
+
`@homeflare/distilled-litellm` unchanged. No prop, attribute or public API changed.
|
|
162
|
+
|
|
163
|
+
`netbox/*`'s `CredentialsFromEnv` has the identical shape and is not fixed by this changeset —
|
|
164
|
+
tracked separately (`docs/upstream-conformance.md` finding 9).
|
|
165
|
+
|
|
166
|
+
- [#210](https://github.com/taslabs-net/homeflare-kit/pull/210) [`2002713`](https://github.com/taslabs-net/homeflare-kit/commit/20027131b716058de035bd1d8423054f3e9dbff0) Thanks [@taslabs-net](https://github.com/taslabs-net)! - The `litellm/*` family (`LiteLLM.PassThroughEndpoint`) now calls `@distilled.cloud/litellm`'s
|
|
167
|
+
typed `misc` operations instead of a hand-rolled `Effect HttpClient` client. The old
|
|
168
|
+
status-carrying `LitellmBadRequestError`/`LitellmUnauthorizedError`/`LitellmHttpError`/
|
|
169
|
+
`LitellmTransportError` are gone: every failure the SDK's four operations declare (`BadRequest`,
|
|
170
|
+
`NotFound` on update, `UnprocessableEntity`, plus the shared default HTTP errors) is the SDK's own
|
|
171
|
+
typed error, `catchTag`'d. `deletePassThroughEndpoint`'s re-list-on-ambiguous-delete trick is
|
|
172
|
+
unchanged, now keyed on the `BadRequest` tag instead of a status code. The per-base-URL write
|
|
173
|
+
semaphore LiteLLM's whole-list storage forces is unchanged, moved into the new `operations.ts`.
|
|
174
|
+
`client.ts` and the kit's own hand-generated `generated/pass-through.ts` are both deleted — the
|
|
175
|
+
SDK's `misc.PassThroughGenericEndpoint` is the same shape, generated from the same LiteLLM 1.100.0
|
|
176
|
+
OpenAPI document. The `codegen/litellm.ts` generator and `tests/litellm-manifest.test.ts` that
|
|
177
|
+
kept that file current are retired with it; the `litellm-openapi` manifest entry stays, recorded
|
|
178
|
+
as consumed by nothing, the same pattern the two UniFi entries already establish.
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# Alchemy changelog archive 9
|
|
2
|
+
|
|
3
|
+
[Current changelog](../../CHANGELOG.md) · [Archive index](./README.md)
|
|
4
|
+
|
|
5
|
+
Not published upstream yet, so aliased onto `@homeflare/distilled-litellm@0.2.0` as a plain
|
|
6
|
+
`dependencies` entry, not a peer — see `docs/distilled-interim.md`. Credentials still resolve
|
|
7
|
+
from `LITELLM_PROXY_URL` / `LITELLM_PROXY_API_KEY` at call time, now through the package's own
|
|
8
|
+
`CredentialsFromEnv` layer. Props and attributes are unchanged — an adopted pass-through endpoint
|
|
9
|
+
still plans noop.
|
|
10
|
+
|
|
11
|
+
- [#212](https://github.com/taslabs-net/homeflare-kit/pull/212) [`e419a44`](https://github.com/taslabs-net/homeflare-kit/commit/e419a44f45e3332eb9ae7c3b196d203309668f26) Thanks [@taslabs-net](https://github.com/taslabs-net)! - The `paperless/*` family (`Tag`, `DocumentType`, `StoragePath`, `CustomField`) now calls
|
|
12
|
+
`@distilled.cloud/paperless-ngx`'s typed operations instead of a hand-rolled `Effect HttpClient`
|
|
13
|
+
client. `client.ts`, `errors.ts` and `credentials.ts` are gone; every status check
|
|
14
|
+
(`statusToError`, the status-carrying `PaperlessError` union) is replaced by
|
|
15
|
+
`Effect.catchTag('NotFound', …)` at each resource file's own `getById` call, the same rule
|
|
16
|
+
`forgejo/*` and `netbox/*` follow — a LIST call is never folded to absent at all, since an empty
|
|
17
|
+
page is a normal 200 (measured live, kit PR 194). The shared `matching.ts`/`matching-locate.ts`
|
|
18
|
+
engine (locate-by-name before there is state, by the stored `output.id` after — PR 163) is
|
|
19
|
+
unchanged in shape, generalized only over the SDK's typed `Live` row and each family's own
|
|
20
|
+
distilled error union instead of an untyped `PaperlessRow`.
|
|
21
|
+
|
|
22
|
+
`@distilled.cloud/paperless-ngx` is not published upstream yet, so this package was already
|
|
23
|
+
aliased onto `@homeflare/distilled-paperless-ngx@0.3.0` (kit PR 188/194/206 — built the distilled
|
|
24
|
+
way and shipped from this monorepo, see `docs/distilled-interim.md`); this PR is the first thing
|
|
25
|
+
that actually imports it. `packages/alchemy`'s own `build:interim-deps` now builds it too, and
|
|
26
|
+
picks up a pre-existing bug in the same line while doing so: `bun --cwd <dir> run <script>`
|
|
27
|
+
(space-separated) silently no-ops instead of building — `bun --cwd=<dir> run <script>` is the form
|
|
28
|
+
that actually works. Fixed for all three interim deps this script already named (netbox, proxmox,
|
|
29
|
+
paperless-ngx); the root-level `scripts/build-interim-packages.ts` was never affected, since it
|
|
30
|
+
spawns `bun run build` with an explicit `cwd` option rather than a shell string.
|
|
31
|
+
|
|
32
|
+
Credentials still resolve from `PAPERLESS_URL` / `PAPERLESS_TOKEN` at call time, now through the
|
|
33
|
+
SDK's own `CredentialsFromEnv`, baked directly into each of the four `xxxProvider()`s the same way
|
|
34
|
+
`netboxHandlers`/`forgejoHandlers` do — `providers.ts`'s `paperlessProviders()` no longer takes a
|
|
35
|
+
credentials-layer override (nothing in this estate called it with one: measured 2026-09-24, no
|
|
36
|
+
tray repo under `homeflare-landscape` declares a Paperless resource at all). Props and attributes
|
|
37
|
+
are unchanged — an adopted tag, document type, storage path or custom field still plans noop.
|
|
38
|
+
|
|
39
|
+
- [#220](https://github.com/taslabs-net/homeflare-kit/pull/220) [`4da7ecc`](https://github.com/taslabs-net/homeflare-kit/commit/4da7ecc7d5dd59e0c9aab3a4a13dee148f9a14a9) Thanks [@taslabs-net](https://github.com/taslabs-net)! - `client.ts`'s `executeOnCluster` and `distilled-pve.ts`'s `runPveWith`
|
|
40
|
+
(`members.ts`, shared by both) now bound a single cluster-member attempt with
|
|
41
|
+
a new `MEMBER_TIMEOUT` (20 seconds). Previously nothing did: a PVE member
|
|
42
|
+
that accepted the TCP connection but never answered hung the whole call
|
|
43
|
+
forever, because the cluster-failover loop never got a failure to classify
|
|
44
|
+
and so never reached a healthy member — this affected every PVE resource,
|
|
45
|
+
migrated or not, since both codepaths funnel through `executeOnCluster`. A
|
|
46
|
+
bounded timeout now fails a read over to the next member (no side effect to
|
|
47
|
+
duplicate) and fails a write outright without resending it, matching the
|
|
48
|
+
existing rule that a post-connect failure is never pre-send. Found on review
|
|
49
|
+
of `Proxmox.Acl`'s migration (PR 209); fixed once, shared by every PVE
|
|
50
|
+
family.
|
|
51
|
+
|
|
52
|
+
- [#216](https://github.com/taslabs-net/homeflare-kit/pull/216) [`eaa12e5`](https://github.com/taslabs-net/homeflare-kit/commit/eaa12e532fc420a74efd8df717e1fe080f1e3840) Thanks [@taslabs-net](https://github.com/taslabs-net)! - `repoBaselineSettings` (repo-baseline-data.ts) no longer turns `allowAutoMerge` on
|
|
53
|
+
unconditionally — it now follows `checks.length > 0`, the same as the sibling `repoPolicy` path
|
|
54
|
+
already refuses to do (`repo-policy-guards.ts`'s `assertAutoMergeWaits`). With zero required
|
|
55
|
+
status checks, `gh pr merge --auto` (and the ruleset's own auto-merge) has nothing to wait for:
|
|
56
|
+
GitHub merges a CLEAN pull request on the spot, with no review and no green run required. A repo
|
|
57
|
+
declared through `declareRepoBaseline` with an empty `checks` list (homeflare-anyauth today, for
|
|
58
|
+
example — no workflows, so no checks to name) would otherwise get auto-merge turned on with
|
|
59
|
+
nothing gating it.
|
|
60
|
+
|
|
61
|
+
This baseline has no `autoMerge` opt-out prop the way `repoPolicy` does, so the fix is
|
|
62
|
+
unconditional rather than a thrown refusal: a repo with checks keeps `allowAutoMerge: true`
|
|
63
|
+
exactly as before; one without simply never gets it turned on by this baseline.
|
|
64
|
+
|
|
65
|
+
- [#217](https://github.com/taslabs-net/homeflare-kit/pull/217) [`ad397ea`](https://github.com/taslabs-net/homeflare-kit/commit/ad397eadbff8c20fef5c9634980b99ce65203758) Thanks [@taslabs-net](https://github.com/taslabs-net)! - `GitHub.RepositoryRuleset`'s `Resource<>` declaration put `GitHubCredentials` in its 5th
|
|
66
|
+
(`Providers`) type parameter, which puts that credential requirement on every `yield*
|
|
67
|
+
RepositoryRuleset(...)` call site — including inside `declareRepoPolicy`/`declareRepoBaseline`.
|
|
68
|
+
A stack body cannot supply `GitHubCredentials` itself (`Alchemy.Stack`'s own `ProviderServices`
|
|
69
|
+
type is a closed union `GitHubCredentials` does not structurally match), so any consumer whose
|
|
70
|
+
stack body calls `declareRepoPolicy`/`declareRepoBaseline` — or declares `RepositoryRuleset`
|
|
71
|
+
directly — failed `tsc` (measured 2026-09-24: homeflare-builds bumping to 0.27.4, TS2345).
|
|
72
|
+
|
|
73
|
+
Verified against upstream `alchemy@2.0.0-beta.79`'s own `GitHub.Ruleset`
|
|
74
|
+
(`node_modules/alchemy/src/GitHub/Ruleset.ts`): its 5th slot is `GitHub.Providers`, the
|
|
75
|
+
`ProviderCollection` tag `GitHub.providers()` outputs — never the raw `GitHubCredentials`
|
|
76
|
+
service its own provider handlers pull in via `octokitFor`. `RepositoryRuleset` now omits the
|
|
77
|
+
5th parameter, defaulting its declaration requirement to `Provider<RepositoryRuleset>` instead —
|
|
78
|
+
a real `ProviderServices` member, matching the pattern a standalone (non-collection) resource
|
|
79
|
+
needs.
|
|
80
|
+
|
|
81
|
+
Fixing only the declaration was not enough on its own: `GitHub.providers()` and
|
|
82
|
+
`RepositoryRulesetProvider()` written side by side as a stack's `providers` still fails to
|
|
83
|
+
typecheck, because `RepositoryRulesetProvider()`'s handlers need `GitHubCredentials` fed in, and
|
|
84
|
+
merging two layers does not thread one's output into the other's requirement. New export
|
|
85
|
+
`repoPolicyProviders()` (`repository-ruleset-providers.ts`) composes the two correctly —
|
|
86
|
+
`RepositoryRulesetProvider().pipe(Layer.provideMerge(GitHub.providers()))` merged with
|
|
87
|
+
`GitHub.providers()` itself — and is now the documented wiring in `docs/repo-policy.md`,
|
|
88
|
+
`docs/repository-ruleset.md`, `repo-policy.ts` and `declare-repo-baseline.ts`.
|
|
89
|
+
|
|
90
|
+
Added a type-level test (`repo-policy-stack.test.ts`): a real `Alchemy.Stack(...)` whose body
|
|
91
|
+
calls `declareRepoPolicy` and `declareRepoBaseline` with `repoPolicyProviders()`, built (never
|
|
92
|
+
run) so `tsc` checks it on every `bun run check` — the test that would have caught this before
|
|
93
|
+
it reached a consumer's bump PR.
|
|
94
|
+
|
|
95
|
+
No runtime behavior changes: every CRUD handler (`read`/`diff`/`reconcile`/`delete`) and its own
|
|
96
|
+
`GitHubCredentials` requirement is unchanged — only the type surface a stack body sees when
|
|
97
|
+
declaring the resource, and how the two providers compose, is fixed.
|
|
98
|
+
|
|
99
|
+
## 0.28.0
|
|
100
|
+
|
|
101
|
+
### Minor Changes
|
|
102
|
+
|
|
103
|
+
- [#206](https://github.com/taslabs-net/homeflare-kit/pull/206) [`06591c9`](https://github.com/taslabs-net/homeflare-kit/commit/06591c91d622178fdf1b09d8ac2f455bafa70107) Thanks [@taslabs-net](https://github.com/taslabs-net)! - Aliases four more distilled interim SDKs onto `@homeflare/alchemy`'s
|
|
104
|
+
`dependencies`, following `docs/distilled-interim.md`'s step 5:
|
|
105
|
+
`@distilled.cloud/proxmox-backup`, `@distilled.cloud/paperless-ngx`,
|
|
106
|
+
`@distilled.cloud/litellm` and `@distilled.cloud/caddy`, each aliased onto
|
|
107
|
+
its published `@homeflare/distilled-<vendor>` interim copy (kit PRs [#200](https://github.com/taslabs-net/homeflare-kit/issues/200),
|
|
108
|
+
[#194](https://github.com/taslabs-net/homeflare-kit/issues/194)/[#195](https://github.com/taslabs-net/homeflare-kit/issues/195), [#201](https://github.com/taslabs-net/homeflare-kit/issues/201), [#202](https://github.com/taslabs-net/homeflare-kit/issues/202)) at its current workspace version — not opnsense or
|
|
109
|
+
unifi-network, neither of which is aliased anywhere yet. No resource in this
|
|
110
|
+
package imports any of the four yet; that migration is each family's own
|
|
111
|
+
later PR, per `distilled-interim.md`'s "what NOT to do".
|
|
112
|
+
|
|
113
|
+
The root `build:interim-packages` script (kept root-level and non-nested,
|
|
114
|
+
the CI-race fix from kit PR [#193](https://github.com/taslabs-net/homeflare-kit/issues/193)) is now generic: it discovers which
|
|
115
|
+
`packages/distilled-*` copies to build by scanning every workspace
|
|
116
|
+
manifest's `dependencies` for a `"@distilled.cloud/<vendor>":
|
|
117
|
+
"npm:@homeflare/distilled-<vendor>@<version>"` alias, instead of a
|
|
118
|
+
hard-coded netbox/proxmox list — a new alias needs no edit to this script.
|
|
119
|
+
`tests/catalog.test.ts`'s `EXACT_PEERS` table is now derived the same way
|
|
120
|
+
for every `distilled-*` interim copy (`effect` alone, one reasoning comment
|
|
121
|
+
kept in one place) instead of one hand-added entry and comment per vendor,
|
|
122
|
+
which had become a recurring merge-conflict hot spot across concurrent
|
|
123
|
+
interim-package PRs landing the same night.
|
|
124
|
+
|
|
125
|
+
This is a `minor`, not a `patch`: `@homeflare/alchemy`'s own `dependencies`
|
|
126
|
+
gained four new runtime entries, even though no exported code changed.
|
|
127
|
+
|
|
128
|
+
- [#205](https://github.com/taslabs-net/homeflare-kit/pull/205) [`3ab881e`](https://github.com/taslabs-net/homeflare-kit/commit/3ab881ecd53108050b1d23db39d955e82a07c322) Thanks [@taslabs-net](https://github.com/taslabs-net)! - `GitHub.RepositoryRuleset` now expresses a live ruleset's exact shape when that shape is
|
|
129
|
+
narrower than the house baseline: a `rules.pullRequest: false` declares its deliberate absence
|
|
130
|
+
(matching the `requiredStatusChecks: false` pattern that already existed), and `bypassActors`
|
|
131
|
+
already carried an arbitrary `actor_id`/`actor_type`/`bypass_mode` list — the gap was never the
|
|
132
|
+
prop shape, it was that nothing stopped a declaration from silently narrowing what is live.
|
|
133
|
+
|
|
134
|
+
Two new guards close that: `bypassNarrowingRefusal` refuses a declared `bypassActors` that drops
|
|
135
|
+
a live actor, and `ruleNarrowingRefusal` refuses a declared `false` (any modeled rule) that drops
|
|
136
|
+
a rule the live ruleset still has — both unless the declaration also carries the matching new
|
|
137
|
+
prop, `acknowledgeBypassNarrowing: { reason: string }` or `acknowledgeRuleNarrowing: { reason:
|
|
138
|
+
string }`, a reasoned, explicit sign-off. The two acknowledgements are deliberately separate
|
|
139
|
+
props, not one shared flag: an adversarial review found that a single shared
|
|
140
|
+
`acknowledgeNarrowing` let a reason worded for one kind of drop silently also excuse the other
|
|
141
|
+
kind in the same declaration, so each guard now reads only the prop scoped to what it checks.
|
|
142
|
+
Widening bypass stays refused unconditionally, as before — this only ever loosens the NARROWING
|
|
143
|
+
side, and only with a recorded, correctly-scoped reason.
|
|
144
|
+
|
|
145
|
+
Prompted by a red-team finding against a design for declaring ~88 `taslabs-net` repos' GitHub
|
|
146
|
+
settings in Alchemy: 5 live repos (`taslabs-net`, `aop`, `magictransit`, `loggarr`,
|
|
147
|
+
`doesthishelp-workeropen`) carry a non-empty live `bypass_actors`, and `taslabs-net` itself has
|
|
148
|
+
no live `pull_request` rule — the exact combination `repoBaselineRuleset()`'s hardcoded
|
|
149
|
+
`bypassActors: []` and always-on `pullRequest` rule could not adopt without silently stripping
|
|
150
|
+
protection. `repoBaselineRuleset()` itself is unchanged — it keeps its baseline defaults, for
|
|
151
|
+
repos the baseline shape actually fits; a caller with a narrower live ruleset now declares
|
|
152
|
+
`RepositoryRuleset` directly with the live shape instead.
|
|
153
|
+
|
|
154
|
+
Tested against all 5 live shapes, re-read via `gh api repos/taslabs-net/<repo>/rulesets/<id>`
|
|
155
|
+
2026-09-23 (not copied from an earlier paraphrase — `doesthishelp-workeropen`'s two bypass
|
|
156
|
+
actors' `bypass_mode`s differ from how an earlier design doc described them).
|
|
157
|
+
|
|
158
|
+
## 0.27.4
|
|
159
|
+
|
|
160
|
+
### Patch Changes
|
|
161
|
+
|
|
162
|
+
- [#193](https://github.com/taslabs-net/homeflare-kit/pull/193) [`41bdc5d`](https://github.com/taslabs-net/homeflare-kit/commit/41bdc5d8f32fca92d60ee667b85306c77cea2442) Thanks [@taslabs-net](https://github.com/taslabs-net)! - The `netbox/*` family (`Netbox.Prefix`) now calls `@distilled.cloud/netbox`'s
|
|
163
|
+
typed `ipam` operations instead of a hand-rolled `Effect HttpClient` client.
|
|
164
|
+
The old status-carrying `NetboxError` and its `cause.status === 404` check
|
|
165
|
+
are gone: `Netbox.Prefix` locates by a server-side list filter, which
|
|
166
|
+
`@distilled.cloud/netbox` never answers with a 404 (an empty page is a
|
|
167
|
+
normal 200), so nothing here checks a status code at all — a stronger
|
|
168
|
+
version of the same rule `catchTag('NotFound', …)` enforces for a
|
|
169
|
+
distilled-backed family that reads by direct key, like `forgejo/*`.
|
|
170
|
+
`client.ts` is gone; nothing else in this package imported it. The real
|
|
171
|
+
`@distilled.cloud/netbox` is not published upstream yet, so this package
|
|
172
|
+
aliases it onto `@homeflare/distilled-netbox@0.2.0` (built the distilled way
|
|
173
|
+
and shipped from this monorepo — see `docs/distilled-interim.md`) as a plain
|
|
174
|
+
`dependencies` entry, not a peer — nothing changes for a consumer's install.
|
|
175
|
+
Credentials still resolve from `NETBOX_URL` / `NETBOX_TOKEN` at call time,
|
|
176
|
+
now through the package's own `CredentialsFromEnv` layer. Props and
|
|
177
|
+
attributes are unchanged — an adopted prefix still plans noop.
|
|
178
|
+
|
|
179
|
+
## 0.27.3
|
|
180
|
+
|
|
181
|
+
### Patch Changes
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Alchemy changelog archive 10
|
|
2
|
+
|
|
3
|
+
[Current changelog](../../CHANGELOG.md) · [Archive index](./README.md)
|
|
4
|
+
|
|
5
|
+
- [#191](https://github.com/taslabs-net/homeflare-kit/pull/191) [`e991225`](https://github.com/taslabs-net/homeflare-kit/commit/e9912254041b1f15195f8a4cf2917e00a1194d43) Thanks [@taslabs-net](https://github.com/taslabs-net)! - `packages/alchemy` now depends on `@distilled.cloud/proxmox`, aliased per
|
|
6
|
+
`packages/alchemy/docs/distilled-interim.md`'s interim-package route onto
|
|
7
|
+
the published `@homeflare/distilled-proxmox@0.2.0`
|
|
8
|
+
(`"npm:@homeflare/distilled-proxmox@0.2.0"` in `dependencies`, not
|
|
9
|
+
`peerDependencies` — the package needs it resolved, not left to whoever
|
|
10
|
+
installs it). This is the follow-up PR `distilled-proxmox-interim.md`
|
|
11
|
+
called out: the alias, plus `src/proxmox/distilled-task-await.test.ts`
|
|
12
|
+
(ported off draft PR 182's dev-only `link:` dependency onto the real alias,
|
|
13
|
+
assertions unchanged) proving `awaitTask`'s poll-until-exitstatus loop
|
|
14
|
+
against a fake PVE — success only on `exitstatus` exactly `"OK"`,
|
|
15
|
+
`"OK (warnings)"` fails, and a bare 400 is the non-retryable `BadRequest`
|
|
16
|
+
(that last case already lives in `packages/distilled-proxmox/src/protocol.test.ts`,
|
|
17
|
+
merged with the package itself).
|
|
18
|
+
|
|
19
|
+
No existing `packages/alchemy/src/proxmox/*` resource is touched or moved
|
|
20
|
+
onto the distilled package — that migration is still a separate, later PR.
|
|
21
|
+
Because `@homeflare/distilled-proxmox` is also a sibling workspace package,
|
|
22
|
+
bun resolves the alias to the local workspace copy rather than fetching the
|
|
23
|
+
npm tarball (same unmodified code either way); that local copy has no
|
|
24
|
+
prebuilt `dist` by default, and `tsc`'s `moduleResolution: "bundler"`
|
|
25
|
+
follows the alias's `exports["."].types` straight to `dist/index.d.ts` when
|
|
26
|
+
typechecking the new test file — `bun test` itself needs no such build
|
|
27
|
+
(it resolves the package's own `bun` export condition straight to `src`).
|
|
28
|
+
`packages/alchemy/package.json` gets a `pretypes` script
|
|
29
|
+
(`bun run --filter '@homeflare/distilled-proxmox' build`) so `bun run
|
|
30
|
+
types` — and therefore `bun run check` — builds that one dependency first;
|
|
31
|
+
nothing else changes.
|
|
32
|
+
|
|
33
|
+
## 0.27.2
|
|
34
|
+
|
|
35
|
+
### Patch Changes
|
|
36
|
+
|
|
37
|
+
- [#180](https://github.com/taslabs-net/homeflare-kit/pull/180) [`1a85198`](https://github.com/taslabs-net/homeflare-kit/commit/1a85198349981e04f475c0e08b0aa2a995719ef4) Thanks [@taslabs-net](https://github.com/taslabs-net)! - The `forgejo/*` family (`Forgejo.Repository`, `Forgejo.BranchProtection`,
|
|
38
|
+
`Forgejo.OrgLabel`, `Forgejo.OrgTeam`, `Forgejo.RepoWebhook`,
|
|
39
|
+
`Forgejo.OrgSecret`, `Forgejo.TeamMember`) now calls
|
|
40
|
+
`@distilled.cloud/forgejo@1.0.0-rc.12`'s typed operations instead of a
|
|
41
|
+
hand-rolled `Effect HttpClient` client — `catchTag('NotFound', …)` in place
|
|
42
|
+
of a status-carrying `ForgejoError`. `client.ts` is gone; nothing else in
|
|
43
|
+
this package imported it. Credentials still resolve from `FORGEJO_URL` /
|
|
44
|
+
`FORGEJO_TOKEN` at call time, now through the package's own
|
|
45
|
+
`CredentialsFromEnv` layer. Every operation this family calls exists in the
|
|
46
|
+
package and every error it handles carries a tag, so no distilled patch was
|
|
47
|
+
needed. Props and attributes are unchanged — an adopted repository, label,
|
|
48
|
+
team, webhook, branch protection rule, org secret or team membership still
|
|
49
|
+
plans noop.
|
|
50
|
+
|
|
51
|
+
- [#179](https://github.com/taslabs-net/homeflare-kit/pull/179) [`0419d30`](https://github.com/taslabs-net/homeflare-kit/commit/0419d30860e4f6ffbf42e0e1257bd5845a00a418) Thanks [@taslabs-net](https://github.com/taslabs-net)! - `Cloudflare.R2BucketLock` now calls `@distilled.cloud/cloudflare/r2`
|
|
52
|
+
(`getBucketLock`/`putBucketLock`) instead of the `cloudflare` npm SDK, the same
|
|
53
|
+
distilled package `MeshNode` already used — `catchTag('NoSuchBucket', …)` in
|
|
54
|
+
place of an `instanceof NotFoundError` status check. The `cloudflare` peer
|
|
55
|
+
dependency and `client.ts` are gone; nothing else in this package imported
|
|
56
|
+
them. Props, attributes and the wire body are unchanged — an adopted lock
|
|
57
|
+
still plans noop.
|
|
58
|
+
|
|
59
|
+
## 0.27.1
|
|
60
|
+
|
|
61
|
+
### Patch Changes
|
|
62
|
+
|
|
63
|
+
- [#177](https://github.com/taslabs-net/homeflare-kit/pull/177) [`615d7f0`](https://github.com/taslabs-net/homeflare-kit/commit/615d7f0f081828a64f2c334ce423324f10e13921) Thanks [@taslabs-net](https://github.com/taslabs-net)! - `launchd-ports.md` and `port-claims.ts`'s header comment no longer cite the
|
|
64
|
+
house monorepo's path and a pinned commit as the source of the port-collision
|
|
65
|
+
rule; both now state it as the kit's own rule, matching the estate's existing
|
|
66
|
+
port-collision strictness on its own terms. No behavior change.
|
|
67
|
+
|
|
68
|
+
## 0.27.0
|
|
69
|
+
|
|
70
|
+
### Minor Changes
|
|
71
|
+
|
|
72
|
+
- [#175](https://github.com/taslabs-net/homeflare-kit/pull/175) [`7767e82`](https://github.com/taslabs-net/homeflare-kit/commit/7767e82d18e74af203ccae108b8e4f3de99be724) Thanks [@taslabs-net](https://github.com/taslabs-net)! - Add `GitHub.RepositoryRuleset`, a bridge resource under `@homeflare/alchemy/github` that
|
|
73
|
+
probes for an existing same-named ruleset by name before creating one (closing the
|
|
74
|
+
duplicate-ruleset hazard in upstream `alchemy@2.0.0-beta.79`'s `GitHub.Ruleset`) and
|
|
75
|
+
normalizes before comparing so a matching live ruleset is a true noop. Also adds
|
|
76
|
+
`declareRepoBaseline`, and rewires `declareRepoPolicy`'s ruleset half onto the new
|
|
77
|
+
resource — `builds` is the only caller, and its ruleset has never been created, so this
|
|
78
|
+
changes no live resource's identity.
|
|
79
|
+
|
|
80
|
+
Versions this was walked against: `alchemy@2.0.0-beta.79`, `@octokit/rest@22.0.1`,
|
|
81
|
+
`@octokit/openapi-types@27.0.0` (the version the REST method parameter types actually
|
|
82
|
+
resolve through — see `repository-ruleset-constraints.ts` for the version-chain note).
|
|
83
|
+
|
|
84
|
+
## 0.26.0
|
|
85
|
+
|
|
86
|
+
### Minor Changes
|
|
87
|
+
|
|
88
|
+
- [#171](https://github.com/taslabs-net/homeflare-kit/pull/171) [`66e6e03`](https://github.com/taslabs-net/homeflare-kit/commit/66e6e03060b0cebbf0e326e6f2880f196735fba7) Thanks [@taslabs-net](https://github.com/taslabs-net)! - Add `sshSudoRunner()` to `@homeflare/alchemy/linux` — the Linux twin of the launchd subpath's
|
|
89
|
+
`sudoRunner()`, for a host stack whose ssh user is not root but has passwordless sudo
|
|
90
|
+
(`(ALL) NOPASSWD: ALL`). The deploy runs as the operator, and only a fixed allowlist of absolute
|
|
91
|
+
`sudo -n` calls elevates: `install`→`mv` (GNU `install` writes through its destination, so this
|
|
92
|
+
runner stages, installs into a derived temp file, then `mv`s it into place — a rename(2), atomic
|
|
93
|
+
by construction), `rm`, `mkdir`/`chmod`/`chown`/`rmdir` for `Host.Directory`, and
|
|
94
|
+
`daemon-reload`/`enable`/`disable`/`start`/`stop`/`restart` for `Systemd.Unit` and
|
|
95
|
+
`Systemd.Timer` (gated by each unit's own `FragmentPath`, so a vendor unit like
|
|
96
|
+
`pveproxy.service` stays unreachable). Every privileged argv is logged before it runs; a plan
|
|
97
|
+
never elevates (`checkWrite` and every read stay on the operator); the host guard reads the whole
|
|
98
|
+
directory chain from `/` down to the target in one `ls -ldn` call, refusing anything not
|
|
99
|
+
root-owned, group/other-writable, ACL-flagged, or the wrong kind. See
|
|
100
|
+
`packages/alchemy/docs/linux-sudo.md` for the full argv table and what is measured versus
|
|
101
|
+
reasoned — write paths are reasoned, not run live; construction and `checkWrite` were exercised
|
|
102
|
+
read-only against a real Debian 13 / trixie host (systemd 257.13-1~deb13u1, coreutils 9.7-3),
|
|
103
|
+
confirming nothing is elevated by a plan.
|
|
104
|
+
|
|
105
|
+
homeflare-proxmox's first consumer: a script, systemd service and timer declared per Proxmox
|
|
106
|
+
node with `sshSudoRunner({ host, prefixes: ['/usr/local/bin', '/etc/systemd/system'] })`.
|
|
107
|
+
Groundwork from PR 132 (`src/linux/sudo-listing.ts`, the `ls -ldn` chain reader) is now used
|
|
108
|
+
directly by the new guard rather than left unreferenced.
|
|
109
|
+
|
|
110
|
+
## 0.25.1
|
|
111
|
+
|
|
112
|
+
### Patch Changes
|
|
113
|
+
|
|
114
|
+
- [#168](https://github.com/taslabs-net/homeflare-kit/pull/168) [`f5b8dcf`](https://github.com/taslabs-net/homeflare-kit/commit/f5b8dcf7e5875f1f5f589a73139fa58d8d886a43) Thanks [@taslabs-net](https://github.com/taslabs-net)! - Fix `Systemd.Unit`: for a unit declared `started: false`, `ActiveState=activating` no longer
|
|
115
|
+
reads as drift. A timer-driven `Type=oneshot` service (no `[Install]`; its `.timer` starts it)
|
|
116
|
+
reports `activating` for the whole duration of its run, not an instant — so a plan taken
|
|
117
|
+
mid-run used to show `update`, and a deploy would `systemctl stop` a check that was already
|
|
118
|
+
running. Now only `ActiveState=active` counts as drift for `started: false`; `started: true`
|
|
119
|
+
(the default) is unchanged. `activating` with `SubState=auto-restart`/`auto-restart-queued` —
|
|
120
|
+
systemd's crash-restart backoff, not a fresh start — is excluded from that exemption and still
|
|
121
|
+
counts as drift, so a crash-looping unit declared `started: false` is still stopped. Both
|
|
122
|
+
`diffUnit` (unit-lifecycle.ts) and `settle` (unit-settle.ts) now share one predicate,
|
|
123
|
+
`isUnitRunning` (unit-form.ts), so they can never disagree about it.
|
|
124
|
+
|
|
125
|
+
## 0.25.0
|
|
126
|
+
|
|
127
|
+
### Minor Changes
|
|
128
|
+
|
|
129
|
+
- [#163](https://github.com/taslabs-net/homeflare-kit/pull/163) [`cf301fb`](https://github.com/taslabs-net/homeflare-kit/commit/cf301fba5196056938419140e80754dc7bf34991) Thanks [@taslabs-net](https://github.com/taslabs-net)! - Add `@homeflare/alchemy/paperless`: `Tag`, `DocumentType`, `StoragePath` and `CustomField` —
|
|
130
|
+
Paperless-ngx's taxonomy, create-or-update and never deleted by default — generated from
|
|
131
|
+
Paperless-ngx **3.1.1**'s own served OpenAPI document (API version **10**, sha256 `d0fe550d…`).
|
|
132
|
+
Types (`generated/types/*.ts`) and constraint tables (`generated/constraints/*.ts`) are both
|
|
133
|
+
generated by the new `bun codegen/paperless.ts`, which also introduces
|
|
134
|
+
`codegen/openapi-types.ts` (a component-to-TypeScript emitter over `openapi.ts`'s `JsonSchema`)
|
|
135
|
+
and `codegen/dialects.ts` (the regex-dialect-plus-anchoring table `codegen/netbox.ts` now reads
|
|
136
|
+
too, unchanged).
|
|
137
|
+
|
|
138
|
+
Every create sends `owner` (null when undeclared) — Paperless-ngx's `OwnedObjectSerializer`
|
|
139
|
+
defaults an absent `owner` to the token user, so omitting it the way an undeclared NetBox
|
|
140
|
+
foreign key is omitted would create a second, invisible row on every deploy. `read` answers
|
|
141
|
+
`Unowned` on every match rather than adopting silently (H1). A `CustomField.dataType` change is
|
|
142
|
+
refused at plan time — never a PATCH, never a replace — because either one deletes that field's
|
|
143
|
+
value on every document.
|
|
144
|
+
|
|
145
|
+
## 0.24.0
|
|
146
|
+
|
|
147
|
+
### Minor Changes
|
|
148
|
+
|
|
149
|
+
- [#157](https://github.com/taslabs-net/homeflare-kit/pull/157) [`2a69523`](https://github.com/taslabs-net/homeflare-kit/commit/2a69523410521f8373d2c216070f788df0ca2a64) Thanks [@taslabs-net](https://github.com/taslabs-net)! - Add `LiteLLM.PassThroughEndpoint` to `@homeflare/alchemy/litellm`, the kit's first LiteLLM
|
|
150
|
+
resource: one row of LiteLLM's `/config/pass_through_endpoint` family, a route on the proxy that
|
|
151
|
+
forwards requests to an upstream target. Types are generated from LiteLLM **1.100.0**'s own
|
|
152
|
+
OpenAPI document (tag `v1.100.0`, commit `e4f25265704e2b2c6cf6e81be2e4c5cffff896f4`), dumped the
|
|
153
|
+
way the vendor's own CI dumps it — `prisma generate` against `litellm/proxy/schema.prisma`, then
|
|
154
|
+
the `dumpSpec` program embedded in `ui/litellm-dashboard/scripts/gen-api-types.mjs`, run with
|
|
155
|
+
`app.routes`' `include_in_schema` forced `True` the way the dashboard's generator does — because
|
|
156
|
+
the reference proxy's `/openapi.json` could not be reached when this was walked (jetsam restart
|
|
157
|
+
loop). Cross-checked byte-identically: regenerating with `openapi-typescript@7.13.0` reproduces
|
|
158
|
+
the tag's committed `ui/litellm-dashboard/src/lib/http/schema.d.ts` exactly, sha256
|
|
159
|
+
`8bc5d9c9…40b83f9`, 2,334,248 bytes on both sides. The dump itself is sha256
|
|
160
|
+
`1b3e4d23…4b006399f` (`codegen/manifest.json`'s `litellm-openapi` entry).
|
|
161
|
+
|
|
162
|
+
Every pass-through endpoint lives in one `general_settings.pass_through_endpoints` field — every
|
|
163
|
+
create, update and delete is a read-modify-write of the whole list — so every mutating call is
|
|
164
|
+
wrapped in a per-base-URL `Effect` semaphore, and `reconcile` reads back after writing rather
|
|
165
|
+
than trusting the call that just returned. A path already held by a `config.yaml` entry
|
|
166
|
+
(`is_from_config: true`) is refused at plan rather than silently overridden; a foreign DB row on
|
|
167
|
+
the same path is `Unowned` and needs `--adopt`; a literal secret in a forwarded `Authorization`,
|
|
168
|
+
`x-api-key` or `cf-aig-authorization` header is refused unless it carries LiteLLM's own
|
|
169
|
+
`os.environ/NAME` reference form. Clearing `timeout`, `methods` or `guardrails` is planned as a
|
|
170
|
+
replace (delete then create), because LiteLLM's update route merges with `exclude_none` and can
|
|
171
|
+
never clear an already-set field. Credentials (`LITELLM_PROXY_URL`, `LITELLM_PROXY_API_KEY` —
|
|
172
|
+
LiteLLM's own variable names) are read fresh from the environment on every call, never a prop.
|
|
173
|
+
|
|
174
|
+
Deferred: the Claude OAuth model, key and team slice, which needs estate answers only Tim can
|
|
175
|
+
give. See `docs/litellm.md`.
|
|
176
|
+
|
|
177
|
+
- [#156](https://github.com/taslabs-net/homeflare-kit/pull/156) [`6b4b58c`](https://github.com/taslabs-net/homeflare-kit/commit/6b4b58c9a207dd4351d80e514ee4b7d09cc74ea0) Thanks [@taslabs-net](https://github.com/taslabs-net)! - Create-and-assert a database on a self-hosted cluster: `Postgres.Database` in the new
|
|
178
|
+
`@homeflare/alchemy/postgres` subpath. Walked against PostgreSQL 18.6 (`REL_18_6`, commit
|
|
179
|
+
`724edf9b`) — upstream `alchemy@2.0.0-beta.79` has vendor-API Postgres resources (Planetscale,
|
|
180
|
+
Neon, Prisma, Fly, Railway) and a runtime binding over `@effect/sql-pg`, but nothing for a
|
|
181
|
+
database you run yourself, so this builds on that same `@effect/sql-pg` `PgClient` upstream's
|
|
182
|
+
own `alchemy/SQL/Postgres` uses (new optional peer, `@effect/sql-pg@4.0.0-rc.115`).
|