@homeflare/alchemy 0.7.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -45
- package/dist/caddy/config-lifecycle.d.ts +49 -3
- package/dist/caddy/config-lifecycle.d.ts.map +1 -1
- package/dist/caddy/config.d.ts +6 -2
- package/dist/caddy/config.d.ts.map +1 -1
- package/dist/caddy/fake-caddy.d.ts +11 -0
- package/dist/caddy/fake-caddy.d.ts.map +1 -1
- package/dist/caddy/index.d.ts +2 -1
- package/dist/caddy/index.d.ts.map +1 -1
- package/dist/caddy/index.js +270 -44
- package/dist/caddy/index.js.map +15 -11
- package/dist/caddy/with-file.d.ts +7 -3
- package/dist/caddy/with-file.d.ts.map +1 -1
- package/dist/launchd/fake-runner.d.ts +1 -0
- package/dist/launchd/fake-runner.d.ts.map +1 -1
- package/dist/launchd/fake-sudo.d.ts +51 -0
- package/dist/launchd/fake-sudo.d.ts.map +1 -0
- package/dist/launchd/host-effect.d.ts +1 -1
- package/dist/launchd/host-file-form.d.ts +5 -0
- package/dist/launchd/host-file-form.d.ts.map +1 -1
- package/dist/launchd/host-file-lifecycle.d.ts +14 -1
- package/dist/launchd/host-file-lifecycle.d.ts.map +1 -1
- package/dist/launchd/host-file.d.ts +2 -1
- package/dist/launchd/host-file.d.ts.map +1 -1
- package/dist/launchd/index.d.ts +2 -0
- package/dist/launchd/index.d.ts.map +1 -1
- package/dist/launchd/index.js +642 -49
- package/dist/launchd/index.js.map +24 -14
- package/dist/launchd/job-lifecycle.d.ts +8 -1
- package/dist/launchd/job-lifecycle.d.ts.map +1 -1
- package/dist/launchd/job-preflight.d.ts +13 -1
- package/dist/launchd/job-preflight.d.ts.map +1 -1
- package/dist/launchd/job-validate.d.ts +2 -0
- package/dist/launchd/job-validate.d.ts.map +1 -1
- package/dist/launchd/job.d.ts +2 -1
- package/dist/launchd/job.d.ts.map +1 -1
- package/dist/launchd/local-runner.d.ts +2 -0
- package/dist/launchd/local-runner.d.ts.map +1 -1
- package/dist/launchd/providers.d.ts +2 -1
- package/dist/launchd/providers.d.ts.map +1 -1
- package/dist/launchd/runner.d.ts +14 -5
- package/dist/launchd/runner.d.ts.map +1 -1
- package/dist/launchd/sudo-acl.d.ts +25 -0
- package/dist/launchd/sudo-acl.d.ts.map +1 -0
- package/dist/launchd/sudo-allowlist.d.ts +47 -0
- package/dist/launchd/sudo-allowlist.d.ts.map +1 -0
- package/dist/launchd/sudo-guard.d.ts +83 -0
- package/dist/launchd/sudo-guard.d.ts.map +1 -0
- package/dist/launchd/sudo-runner.d.ts +60 -0
- package/dist/launchd/sudo-runner.d.ts.map +1 -0
- package/dist/launchd/sudo-said.d.ts +10 -0
- package/dist/launchd/sudo-said.d.ts.map +1 -0
- package/dist/launchd/sudo-stage.d.ts +7 -0
- package/dist/launchd/sudo-stage.d.ts.map +1 -0
- package/dist/openbao/auth-method-reconcile.d.ts +6 -2
- package/dist/openbao/auth-method-reconcile.d.ts.map +1 -1
- package/dist/openbao/auth-method.d.ts.map +1 -1
- package/dist/openbao/auth-role-form.d.ts +0 -9
- package/dist/openbao/auth-role-form.d.ts.map +1 -1
- package/dist/openbao/auth-role.d.ts +3 -2
- package/dist/openbao/auth-role.d.ts.map +1 -1
- package/dist/openbao/cloudflare-role.d.ts.map +1 -1
- package/dist/openbao/fake-bao.d.ts +18 -0
- package/dist/openbao/fake-bao.d.ts.map +1 -1
- package/dist/openbao/fake-core.d.ts +39 -0
- package/dist/openbao/fake-core.d.ts.map +1 -0
- package/dist/openbao/fake-engines-roles.d.ts +32 -0
- package/dist/openbao/fake-engines-roles.d.ts.map +1 -0
- package/dist/openbao/fake-engines.d.ts +8 -2
- package/dist/openbao/fake-engines.d.ts.map +1 -1
- package/dist/openbao/fake-families.d.ts +52 -0
- package/dist/openbao/fake-families.d.ts.map +1 -0
- package/dist/openbao/fake-mounts.d.ts +16 -0
- package/dist/openbao/fake-mounts.d.ts.map +1 -0
- package/dist/openbao/fake-stack.d.ts +5 -1
- package/dist/openbao/fake-stack.d.ts.map +1 -1
- package/dist/openbao/host-approles.d.ts.map +1 -1
- package/dist/openbao/index.js +709 -359
- package/dist/openbao/index.js.map +32 -25
- package/dist/openbao/jwt-config.d.ts +5 -0
- package/dist/openbao/jwt-config.d.ts.map +1 -1
- package/dist/openbao/jwt-role.d.ts +2 -1
- package/dist/openbao/jwt-role.d.ts.map +1 -1
- package/dist/openbao/kubernetes-role.d.ts +2 -1
- package/dist/openbao/kubernetes-role.d.ts.map +1 -1
- package/dist/openbao/mfa-enforcement.d.ts +12 -5
- package/dist/openbao/mfa-enforcement.d.ts.map +1 -1
- package/dist/openbao/mfa-totp.d.ts +6 -2
- package/dist/openbao/mfa-totp.d.ts.map +1 -1
- package/dist/openbao/mount-reconcile.d.ts +5 -1
- package/dist/openbao/mount-reconcile.d.ts.map +1 -1
- package/dist/openbao/mount.d.ts.map +1 -1
- package/dist/openbao/pki-role.d.ts.map +1 -1
- package/dist/openbao/plugin-reconcile.d.ts +6 -2
- package/dist/openbao/plugin-reconcile.d.ts.map +1 -1
- package/dist/openbao/plugin.d.ts.map +1 -1
- package/dist/openbao/policy.d.ts.map +1 -1
- package/dist/openbao/proxmox-role.d.ts.map +1 -1
- package/dist/openbao/rename-identity.d.ts +69 -0
- package/dist/openbao/rename-identity.d.ts.map +1 -0
- package/dist/openbao/rename.d.ts +13 -12
- package/dist/openbao/rename.d.ts.map +1 -1
- package/dist/openbao/role-reconcile.d.ts +11 -1
- package/dist/openbao/role-reconcile.d.ts.map +1 -1
- package/dist/openbao/ssh-role-erase.d.ts +11 -0
- package/dist/openbao/ssh-role-erase.d.ts.map +1 -0
- package/dist/openbao/ssh-role.d.ts.map +1 -1
- package/dist/ownership/adopt.d.ts +52 -0
- package/dist/ownership/adopt.d.ts.map +1 -0
- package/dist/ownership/probe.d.ts +13 -0
- package/dist/ownership/probe.d.ts.map +1 -0
- package/dist/ownership/resume.d.ts +40 -0
- package/dist/ownership/resume.d.ts.map +1 -0
- package/dist/ownership/rows.d.ts +33 -0
- package/dist/ownership/rows.d.ts.map +1 -0
- package/dist/ownership/whole.d.ts +14 -0
- package/dist/ownership/whole.d.ts.map +1 -0
- package/dist/proxmox/ceph-pool-form.d.ts +3 -3
- package/dist/proxmox/ceph-pool.d.ts.map +1 -1
- package/dist/proxmox/fake-bao-env.d.ts +3 -0
- package/dist/proxmox/fake-bao-env.d.ts.map +1 -0
- package/dist/proxmox/fake-pve-lxc.d.ts +42 -0
- package/dist/proxmox/fake-pve-lxc.d.ts.map +1 -0
- package/dist/proxmox/fake-pve.d.ts +38 -0
- package/dist/proxmox/fake-pve.d.ts.map +1 -0
- package/dist/proxmox/index.d.ts +6 -2
- package/dist/proxmox/index.d.ts.map +1 -1
- package/dist/proxmox/index.js +970 -186
- package/dist/proxmox/index.js.map +22 -9
- package/dist/proxmox/lxc-create-form.d.ts +6 -0
- package/dist/proxmox/lxc-create-form.d.ts.map +1 -0
- package/dist/proxmox/lxc-harness.d.ts +34 -0
- package/dist/proxmox/lxc-harness.d.ts.map +1 -0
- package/dist/proxmox/lxc-identity.d.ts +18 -0
- package/dist/proxmox/lxc-identity.d.ts.map +1 -0
- package/dist/proxmox/lxc-judge.d.ts +46 -0
- package/dist/proxmox/lxc-judge.d.ts.map +1 -0
- package/dist/proxmox/lxc-lifecycle.d.ts +68 -0
- package/dist/proxmox/lxc-lifecycle.d.ts.map +1 -0
- package/dist/proxmox/lxc-props.d.ts +139 -0
- package/dist/proxmox/lxc-props.d.ts.map +1 -0
- package/dist/proxmox/lxc-volume.d.ts +29 -0
- package/dist/proxmox/lxc-volume.d.ts.map +1 -0
- package/dist/proxmox/lxc-wire.d.ts +51 -0
- package/dist/proxmox/lxc-wire.d.ts.map +1 -0
- package/dist/proxmox/lxc.d.ts +27 -47
- package/dist/proxmox/lxc.d.ts.map +1 -1
- package/dist/proxmox/network-apply-read.d.ts +1 -1
- package/dist/proxmox/network-apply-read.d.ts.map +1 -1
- package/dist/proxmox/pbs-datastore.d.ts.map +1 -1
- package/dist/proxmox/resource.d.ts.map +1 -1
- package/dist/proxmox/update-guard.d.ts +27 -0
- package/dist/proxmox/update-guard.d.ts.map +1 -0
- package/dist/verify/args.d.ts +16 -0
- package/dist/verify/args.d.ts.map +1 -0
- package/dist/verify/cli.d.ts +3 -0
- package/dist/verify/cli.d.ts.map +1 -0
- package/dist/verify/cli.js +320 -0
- package/dist/verify/cli.js.map +15 -0
- package/dist/verify/fake-engine.d.ts +57 -0
- package/dist/verify/fake-engine.d.ts.map +1 -0
- package/dist/verify/index.d.ts +16 -0
- package/dist/verify/index.d.ts.map +1 -0
- package/dist/verify/index.js +297 -0
- package/dist/verify/index.js.map +14 -0
- package/dist/verify/report.d.ts +6 -0
- package/dist/verify/report.d.ts.map +1 -0
- package/dist/verify/rows.d.ts +57 -0
- package/dist/verify/rows.d.ts.map +1 -0
- package/dist/verify/spy.d.ts +31 -0
- package/dist/verify/spy.d.ts.map +1 -0
- package/dist/verify/verify.d.ts +43 -0
- package/dist/verify/verify.d.ts.map +1 -0
- package/docs/adopt-verify.md +108 -0
- package/docs/adopted-deploys.md +85 -0
- package/docs/caddy-admin.md +24 -0
- package/docs/caddy.md +73 -54
- package/docs/credentials.md +15 -0
- package/docs/launchd-sudo.md +147 -0
- package/docs/launchd.md +14 -7
- package/docs/ownership.md +113 -0
- package/docs/peers.md +39 -0
- package/docs/proxmox-lxc.md +196 -0
- package/docs/proxmox.md +12 -0
- package/package.json +9 -2
- package/src/caddy/adopt-scope.test.ts +82 -0
- package/src/caddy/config-adopt.test.ts +235 -0
- package/src/caddy/config-lifecycle.test.ts +31 -53
- package/src/caddy/config-lifecycle.ts +98 -7
- package/src/caddy/config.ts +48 -10
- package/src/caddy/fake-caddy.ts +19 -0
- package/src/caddy/index.ts +2 -1
- package/src/caddy/providers.test.ts +8 -23
- package/src/caddy/with-file.ts +7 -3
- package/src/launchd/adopt-apply.test.ts +166 -0
- package/src/launchd/fake-runner.ts +26 -4
- package/src/launchd/fake-sudo.ts +136 -0
- package/src/launchd/host-effect.ts +1 -1
- package/src/launchd/host-file-form.ts +10 -2
- package/src/launchd/host-file-lifecycle.ts +41 -15
- package/src/launchd/host-file.ts +13 -4
- package/src/launchd/index.ts +2 -0
- package/src/launchd/job-lifecycle.ts +22 -14
- package/src/launchd/job-preflight.ts +21 -3
- package/src/launchd/job-validate.ts +1 -1
- package/src/launchd/job.ts +13 -4
- package/src/launchd/local-runner.ts +6 -3
- package/src/launchd/providers.test.ts +3 -0
- package/src/launchd/providers.ts +2 -1
- package/src/launchd/runner.ts +14 -5
- package/src/launchd/sudo-acl.ts +68 -0
- package/src/launchd/sudo-allowlist.test.ts +191 -0
- package/src/launchd/sudo-allowlist.ts +213 -0
- package/src/launchd/sudo-chain.test.ts +121 -0
- package/src/launchd/sudo-guard.test.ts +100 -0
- package/src/launchd/sudo-guard.ts +230 -0
- package/src/launchd/sudo-lifecycle.test.ts +172 -0
- package/src/launchd/sudo-modes.test.ts +135 -0
- package/src/launchd/sudo-runner-files.test.ts +240 -0
- package/src/launchd/sudo-runner.test.ts +126 -0
- package/src/launchd/sudo-runner.ts +216 -0
- package/src/launchd/sudo-said.ts +58 -0
- package/src/launchd/sudo-stage.ts +28 -0
- package/src/openbao/README.md +11 -2
- package/src/openbao/REPLACE.md +67 -37
- package/src/openbao/adopt-core.test.ts +119 -0
- package/src/openbao/adopt-families.test.ts +97 -0
- package/src/openbao/adopt-holes.test.ts +168 -0
- package/src/openbao/adopt-recovery.test.ts +71 -0
- package/src/openbao/auth-method-reconcile.ts +15 -3
- package/src/openbao/auth-method.ts +15 -6
- package/src/openbao/auth-role-form.test.ts +2 -16
- package/src/openbao/auth-role-form.ts +0 -11
- package/src/openbao/auth-role.ts +48 -17
- package/src/openbao/cloudflare-role.ts +23 -18
- package/src/openbao/fake-bao.ts +52 -0
- package/src/openbao/fake-core.ts +141 -0
- package/src/openbao/fake-engines-roles.ts +114 -0
- package/src/openbao/fake-engines.ts +18 -11
- package/src/openbao/fake-families.ts +188 -0
- package/src/openbao/fake-mounts.ts +74 -0
- package/src/openbao/fake-stack.ts +17 -4
- package/src/openbao/host-approles.test.ts +15 -2
- package/src/openbao/host-approles.ts +19 -4
- package/src/openbao/jwt-config.ts +35 -11
- package/src/openbao/jwt-role.ts +33 -14
- package/src/openbao/kubernetes-role.ts +32 -14
- package/src/openbao/mfa-enforcement.ts +42 -13
- package/src/openbao/mfa-totp.ts +42 -14
- package/src/openbao/mount-move.test.ts +2 -35
- package/src/openbao/mount-reconcile.ts +13 -2
- package/src/openbao/mount.ts +15 -6
- package/src/openbao/pki-role.ts +33 -10
- package/src/openbao/plugin-reconcile.ts +16 -5
- package/src/openbao/plugin.ts +57 -20
- package/src/openbao/policy.ts +24 -11
- package/src/openbao/proxmox-role.ts +20 -20
- package/src/openbao/rename-adoption.test.ts +95 -0
- package/src/openbao/rename-families.test.ts +122 -0
- package/src/openbao/rename-identity.test.ts +129 -0
- package/src/openbao/rename-identity.ts +117 -0
- package/src/openbao/rename.ts +19 -15
- package/src/openbao/role-reconcile.ts +23 -0
- package/src/openbao/ssh-role-erase.ts +50 -0
- package/src/openbao/ssh-role.ts +29 -57
- package/src/ownership/adopt.ts +122 -0
- package/src/ownership/ownership.test.ts +200 -0
- package/src/ownership/probe.ts +65 -0
- package/src/ownership/resume.ts +118 -0
- package/src/ownership/rows.ts +117 -0
- package/src/ownership/whole.test.ts +39 -0
- package/src/ownership/whole.ts +60 -0
- package/src/proxmox/adopt-noop.test.ts +112 -0
- package/src/proxmox/ceph-pool-adopt.test.ts +88 -0
- package/src/proxmox/ceph-pool-form.ts +3 -3
- package/src/proxmox/ceph-pool.ts +10 -3
- package/src/proxmox/fake-bao-env.ts +28 -0
- package/src/proxmox/fake-pve-lxc.ts +210 -0
- package/src/proxmox/fake-pve.ts +75 -0
- package/src/proxmox/index.test.ts +6 -6
- package/src/proxmox/index.ts +6 -2
- package/src/proxmox/lxc-adopt.test.ts +170 -0
- package/src/proxmox/lxc-create-form.ts +76 -0
- package/src/proxmox/lxc-create.test.ts +126 -0
- package/src/proxmox/lxc-guards.test.ts +158 -0
- package/src/proxmox/lxc-harness.ts +150 -0
- package/src/proxmox/lxc-identity.ts +43 -0
- package/src/proxmox/lxc-judge.test.ts +175 -0
- package/src/proxmox/lxc-judge.ts +196 -0
- package/src/proxmox/lxc-lifecycle.ts +200 -0
- package/src/proxmox/lxc-ownership.test.ts +159 -0
- package/src/proxmox/lxc-props.ts +215 -0
- package/src/proxmox/lxc-read.test.ts +60 -0
- package/src/proxmox/lxc-volume.test.ts +96 -0
- package/src/proxmox/lxc-volume.ts +153 -0
- package/src/proxmox/lxc-wire.ts +210 -0
- package/src/proxmox/lxc.ts +216 -93
- package/src/proxmox/network-apply-read.ts +3 -1
- package/src/proxmox/pbs-datastore.ts +4 -3
- package/src/proxmox/resource.ts +7 -7
- package/src/proxmox/update-guard.ts +31 -0
- package/src/verify/args.ts +82 -0
- package/src/verify/cli.test.ts +86 -0
- package/src/verify/cli.ts +49 -0
- package/src/verify/fake-engine.ts +158 -0
- package/src/verify/index.ts +36 -0
- package/src/verify/report.ts +52 -0
- package/src/verify/rows.ts +169 -0
- package/src/verify/spy.test.ts +141 -0
- package/src/verify/spy.ts +149 -0
- package/src/verify/verify.test.ts +124 -0
- package/src/verify/verify.ts +172 -0
package/README.md
CHANGED
|
@@ -104,6 +104,11 @@ Cloudflare and Proxmox roles, plugins — plus `assertBaoIdentity` (call it firs
|
|
|
104
104
|
⛔ **Metadata only.** Alchemy stores props and attributes unencrypted, so no secret, CA key,
|
|
105
105
|
plugin `env` or OIDC client secret is declarable. Every family defaults to `retain` on destroy.
|
|
106
106
|
|
|
107
|
+
⛔ **Nothing is adopted without `--adopt`** (0.9.0), for every family and even when the live object
|
|
108
|
+
is identical to the declaration; an interrupted create of this stack's own resumes when its row
|
|
109
|
+
can prove it (one killed while a prop was an `Output` needs `--adopt`). The same rule holds for
|
|
110
|
+
`HostFile`, `LaunchdJob`, `CaddyConfig` and `ProxmoxLxc`: [docs/ownership.md](./docs/ownership.md).
|
|
111
|
+
|
|
107
112
|
★ **Usage lives beside the code**, so it ships in the tarball with it:
|
|
108
113
|
[src/openbao/README.md](./src/openbao/README.md). What each resource does on a rename is in
|
|
109
114
|
[src/openbao/REPLACE.md](./src/openbao/REPLACE.md) — read it before changing a path or name.
|
|
@@ -119,36 +124,56 @@ delete-first.
|
|
|
119
124
|
- ⛔ **No silent sudo:** the system domain needs a deploy started as root, or a `privileged` runner.
|
|
120
125
|
- ⚠️ `org.nixos.*` jobs are never adopted. Guide and nix-darwin cutover: [docs/launchd.md](./docs/launchd.md).
|
|
121
126
|
|
|
127
|
+
### Deploying as yourself — `sudoRunner()`
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
launchdProviders(sudoRunner({ prefixes: ['/Library/LaunchDaemons', '/opt/example'] }));
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The deploy runs as you. Only `launchctl bootstrap | bootout | kickstart` in the system domain, and
|
|
134
|
+
`install` / `rm` of a file under a declared prefix, go through `sudo -n`, in exact argv shapes. Each
|
|
135
|
+
one is logged (argv only, never content) before it runs. A plan never calls sudo.
|
|
136
|
+
|
|
137
|
+
- ⛔ **Opt-in, never a fallback**, and it never prompts: if sudo needs a password, the call fails at
|
|
138
|
+
once and says to run `sudo -v`, or to grant exactly these commands `NOPASSWD`.
|
|
139
|
+
- ⚠️ Refused before sudo is asked: any other argv, a prefix — or any directory below it on the way
|
|
140
|
+
to the file — that is not a real directory only root may write, a root-owned file that would be
|
|
141
|
+
group/world-writable, setuid or setgid, a path outside every prefix that needs root, a file you
|
|
142
|
+
could not read back, and another user's `gui/<uid>`. A plan that will write runs the same checks.
|
|
143
|
+
- Full list, sudoers cautions and limits: [docs/launchd-sudo.md](./docs/launchd-sudo.md).
|
|
144
|
+
|
|
122
145
|
## Caddy — `@homeflare/alchemy/caddy`
|
|
123
146
|
|
|
124
147
|
`CaddyConfig` declares a running Caddy's config as Caddyfile text, applied through Caddy's own admin
|
|
125
148
|
API: `POST /load` (graceful reload; Caddy keeps the old config if it refuses the new one, and the
|
|
126
|
-
deploy says why), `GET /config/` for drift.
|
|
127
|
-
`
|
|
128
|
-
the transport, `http://127.0.0.1:2019` by default.
|
|
149
|
+
deploy says why), `GET /config/` for drift. `caddyWithFile()` also writes the file Caddy starts from,
|
|
150
|
+
with `HostFile`; `caddyProviders()` provides the transport, `http://127.0.0.1:2019` by default.
|
|
129
151
|
|
|
152
|
+
- ⛔ **Nothing is adopted silently:** a running Caddy whose config is not the declared one plans as
|
|
153
|
+
`Unowned`, and the deploy needs `--adopt`.
|
|
130
154
|
- ⛔ **No secrets in the Caddyfile** (state is unencrypted): `{env.NAME}` / `{file./path}` placeholders.
|
|
131
155
|
- ⛔ **The admin API stays on loopback or a unix socket**, and a Caddyfile that would move it is refused.
|
|
132
|
-
- ⛔ **Delete never unloads or stops Caddy.** Order of file and load
|
|
156
|
+
- ⛔ **Delete never unloads or stops Caddy.** Order of file and load: [docs/caddy.md](./docs/caddy.md).
|
|
157
|
+
- ★ **Managed Caddies run `--resume` with their own `XDG_CONFIG_HOME`**, so a restart runs the last
|
|
158
|
+
config Caddy accepted — and after one, SIGUSR1 has no file to reload. Why, and the rest: same doc.
|
|
133
159
|
|
|
134
|
-
##
|
|
160
|
+
## Proxmox — `@homeflare/alchemy/proxmox`
|
|
135
161
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
(an Alchemy profile, or `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID` in CI).
|
|
162
|
+
PVE and PBS objects over the PVE API, and `ProxmoxLxc` for containers. What the subpath never does
|
|
163
|
+
to a guest, and why: [docs/proxmox.md](./docs/proxmox.md).
|
|
139
164
|
|
|
140
|
-
|
|
141
|
-
API Key. An empty value fails closed with a message saying so, because an empty render is
|
|
142
|
-
a denied grant rather than a missing file, and `Bearer ` + nothing 401s in a way that reads
|
|
143
|
-
like a bad credential.
|
|
165
|
+
## Adopt verifier — `hf-adopt-verify` / `@homeflare/alchemy/verify`
|
|
144
166
|
|
|
145
|
-
|
|
167
|
+
⛔ A plan prints `adopted` for a match and for a drift alike. Before a gated deploy run
|
|
168
|
+
`bunx --bun hf-adopt-verify --config alchemy.run.ts --stage live`: Alchemy's planner, no writes,
|
|
169
|
+
each row's own diff, exit 0 only when all are no-ops. [docs/adopt-verify.md](./docs/adopt-verify.md)
|
|
146
170
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
171
|
+
## Credentials
|
|
172
|
+
|
|
173
|
+
⛔ **Mint a short-lived, scoped token** — never a long-lived one, never a Global API Key. How each
|
|
174
|
+
subpath reads its credential, and why an empty one fails closed: [docs/credentials.md](./docs/credentials.md).
|
|
175
|
+
|
|
176
|
+
## Peers — and one override you need
|
|
152
177
|
|
|
153
178
|
⚠️ Peers, not dependencies: Alchemy's resource registry and Effect's context both break if
|
|
154
179
|
two copies load in one process.
|
|
@@ -167,33 +192,8 @@ two copies load in one process.
|
|
|
167
192
|
}
|
|
168
193
|
```
|
|
169
194
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
`effect >= 4.0.0-rc.115`; an unlocked `@effect/platform-node-shared` still floats to the
|
|
173
|
-
next rc and breaks at import. Pin the whole set.
|
|
174
|
-
|
|
175
|
-
| what resolves | what happens |
|
|
176
|
-
| ------------------------------------------------------------- | ------------------------------------------------------ |
|
|
177
|
-
| Alchemy 77 + `effect` → rc.115 (measured 2026-09-16) | `TypeError: Config.string is not a function` at import |
|
|
178
|
-
| `@effect/platform-node-shared` newer than the pinned `effect` | `Cannot find module 'effect/ByteSize'` |
|
|
179
|
-
| `rolldown` → 1.2.9 via vite's `~1.2.6` (measured 2026-09-16) | `GET …/rolldown-1.2.9.tgz - 404` at `bun add` |
|
|
180
|
-
| no `mime` (measured 2026-09-17 against Alchemy 78) | `Cannot find package 'mime'` from cloudflare-runtime |
|
|
181
|
-
|
|
182
|
-
Alchemy 78 adapted to rc.115 — that first row is why we used to pin 112, not a reason to
|
|
183
|
-
stay there. The override is still the only thing that holds the set together.
|
|
184
|
-
|
|
185
|
-
⚠️ `@effect/platform-node` is **required, not optional**: Alchemy's module graph reaches
|
|
186
|
-
`Cloudflare/Workers/WorkerBridge → @effect/platform-node/NodeServices` even when you only
|
|
187
|
-
import the Proxmox subpath.
|
|
188
|
-
|
|
189
|
-
⚠️ So is `mime`. Alchemy 78's `@alchemy.run/cloudflare-runtime` imported it without
|
|
190
|
-
declaring it (measured 2026-09-17). 79 declares it; the peer stays so a consumer
|
|
191
|
-
that followed the 78 README does not drop a required line.
|
|
192
|
-
|
|
193
|
-
⚠️ So is `cloudflare`. It was marked optional in 0.1.1, which claimed the `/cloudflare`
|
|
194
|
-
subpath would degrade without it — measured 2026-09-16, the subpath does not load at all:
|
|
195
|
-
`Cannot find package 'cloudflare'`. An optional peer should mean a feature is absent, not
|
|
196
|
-
that an import fails.
|
|
195
|
+
Why each peer is required and each pin exists — the measurements, and the error a missing one
|
|
196
|
+
produces: [docs/peers.md](./docs/peers.md).
|
|
197
197
|
|
|
198
198
|
## License
|
|
199
199
|
|
|
@@ -9,9 +9,11 @@
|
|
|
9
9
|
* · live ≠ stored — DRIFT: a hand `curl` to the API, or a restart that loaded a different file
|
|
10
10
|
* (or an `autosave.json` holding someone else's change, under `--resume`).
|
|
11
11
|
* · declared = live — nothing to load, whatever the state says.
|
|
12
|
+
* With NO state there is no stored digest, and the question is whose config is running: see
|
|
13
|
+
* `claimable` below, which both the adoption probe and the apply ask.
|
|
12
14
|
*/
|
|
13
15
|
import type { Diff } from 'alchemy/Diff';
|
|
14
|
-
import type
|
|
16
|
+
import { type CaddyAdmin } from './admin.ts';
|
|
15
17
|
import { type CaddyConfigAttributes, type CaddyConfigProps } from './config-form.ts';
|
|
16
18
|
type Desired = {
|
|
17
19
|
readonly digest: string;
|
|
@@ -26,6 +28,31 @@ type Desired = {
|
|
|
26
28
|
export declare const desiredConfig: (admin: CaddyAdmin, props: CaddyConfigProps) => Promise<Desired>;
|
|
27
29
|
/** What is running now, as attributes. `sourceFile` is carried over, never discovered. */
|
|
28
30
|
export declare const readLive: (admin: CaddyAdmin, sourceFile?: string) => Promise<CaddyConfigAttributes>;
|
|
31
|
+
/**
|
|
32
|
+
* ⛔ WITH NO STATE, A RUNNING CONFIG IS THIS STACK'S ONLY IF IT IS THE DECLARED ONE (decision,
|
|
33
|
+
* 2026-09-21: CaddyConfig must not adopt silently — the house rule HostFile and LaunchdJob keep).
|
|
34
|
+
* Anything else was put there by a person, another tool or another stack, and loading over it
|
|
35
|
+
* replaces every site it serves. ★ A config that serves nothing (`null`, or no apps) is claimable
|
|
36
|
+
* too: there is nothing to take over, as an empty R2 lock rule set reads as no lock.
|
|
37
|
+
*/
|
|
38
|
+
export declare const claimable: (running: unknown, declaredDigest: string) => boolean;
|
|
39
|
+
export type Probe = {
|
|
40
|
+
readonly attributes: CaddyConfigAttributes;
|
|
41
|
+
/** The live config IS the declared one: adopting it changes nothing. */
|
|
42
|
+
readonly ours: boolean;
|
|
43
|
+
/** Why the declaration could not be compared, when it could not — the Caddy is then not ours. */
|
|
44
|
+
readonly unchecked?: string;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* The adoption probe — `read` with no state: `undefined` when Caddy serves nothing (plan a create),
|
|
48
|
+
* else the live attributes and whether they are provably ours (the provider brands the rest
|
|
49
|
+
* `Unowned`, and the plan refuses them without `--adopt`).
|
|
50
|
+
* ⛔ IT NEVER THROWS OVER THE DECLARATION. The engine also runs this read to recover an interrupted
|
|
51
|
+
* create, with THAT deploy's props (Plan.ts, `status: "creating"`) — so a Caddyfile that failed to
|
|
52
|
+
* adapt then would fail every later plan, the one carrying the fix included. What cannot be
|
|
53
|
+
* compared is "not proven ours", with the reason; the next diff or apply validates the Caddyfile.
|
|
54
|
+
*/
|
|
55
|
+
export declare const probeLive: (admin: CaddyAdmin, caddyfile: string | undefined, sourceFile?: string) => Promise<Probe | undefined>;
|
|
29
56
|
/**
|
|
30
57
|
* ★ NEVER `replace`. Nothing in the props names a different object: a new Caddyfile is a reload of
|
|
31
58
|
* the same Caddy, and `sourceFile` is a header. (Which Caddy is the transport's business — see
|
|
@@ -39,7 +66,26 @@ export type Applied = {
|
|
|
39
66
|
/** Whether a `POST /load` was sent (false when Caddy already ran this config). */
|
|
40
67
|
readonly loaded: boolean;
|
|
41
68
|
};
|
|
42
|
-
/**
|
|
43
|
-
|
|
69
|
+
/**
|
|
70
|
+
* What this apply may load over — config.ts decides from the state and the adopt setting:
|
|
71
|
+
* · `takeOver` — any running config: the state was applied to THIS Caddy (an update, drift
|
|
72
|
+
* correction, or a create the engine adopted), or adoption is on (`--adopt`, or the
|
|
73
|
+
* resource's own `adopt(true)` — ownership/adopt.ts adoptEnabled).
|
|
74
|
+
* · otherwise only a claimable one — plus, as `stored`, the digest the state last recorded: a
|
|
75
|
+
* Caddy reached at a NEW endpoint that runs exactly that is the same config under another name.
|
|
76
|
+
*/
|
|
77
|
+
export type Authority = {
|
|
78
|
+
readonly takeOver: boolean;
|
|
79
|
+
readonly stored?: string;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Load the Caddyfile unless Caddy already runs it, then read it back and insist it matches.
|
|
83
|
+
* ⛔ WITHOUT `takeOver`, A CONFIG THE STACK CANNOT CLAIM IS NEVER LOADED OVER. The engine's adoption
|
|
84
|
+
* probe cannot guard every create: it is skipped while `news` holds an Output — ALWAYS on
|
|
85
|
+
* caddyWithFile's first deploy (`sourceFile` is its HostFile's path) — and a Caddy that was down at
|
|
86
|
+
* plan time read as nothing. Nor does state vouch for a Caddy the transport NOW reaches at another
|
|
87
|
+
* endpoint (diff plans that as an update). Refused here, before any `/load`, like HostFile's.
|
|
88
|
+
*/
|
|
89
|
+
export declare const reconcileConfig: (admin: CaddyAdmin, props: CaddyConfigProps, authority: Authority) => Promise<Applied>;
|
|
44
90
|
export {};
|
|
45
91
|
//# sourceMappingURL=config-lifecycle.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-lifecycle.d.ts","sourceRoot":"","sources":["../../src/caddy/config-lifecycle.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"config-lifecycle.d.ts","sourceRoot":"","sources":["../../src/caddy/config-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,KAAK,UAAU,EAAyB,MAAM,YAAY,CAAC;AAQpE,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EAEtB,MAAM,kBAAkB,CAAC;AAQ1B,KAAK,OAAO,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAcjF;;;;;GAKG;AACH,eAAO,MAAM,aAAa,UACjB,UAAU,SACV,gBAAgB,KACtB,OAAO,CAAC,OAAO,CAUjB,CAAC;AAYF,0FAA0F;AAC1F,eAAO,MAAM,QAAQ,UACZ,UAAU,eACJ,MAAM,KAClB,OAAO,CAAC,qBAAqB,CACiC,CAAC;AAElE;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,YAAa,OAAO,kBAAkB,MAAM,KAAG,OACD,CAAC;AAErE,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC;IAC3C,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,iGAAiG;IACjG,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,SAAS,UACb,UAAU,aACN,MAAM,GAAG,SAAS,eAChB,MAAM,KAClB,OAAO,CAAC,KAAK,GAAG,SAAS,CAmB3B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,UACd,UAAU,QACX,gBAAgB,UACd,qBAAqB,KAC5B,OAAO,CAAC,IAAI,CAYd,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC;IAC3C,iGAAiG;IACjG,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjF;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,UACnB,UAAU,SACV,gBAAgB,aACZ,SAAS,KACnB,OAAO,CAAC,OAAO,CA8CjB,CAAC"}
|
package/dist/caddy/config.d.ts
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
* - create / update — `POST /adapt` (validate), `POST /load` with `text/caddyfile` (a graceful
|
|
6
6
|
* reload; Caddy keeps the old config if it refuses the new one, and the error names why), then
|
|
7
7
|
* `GET /config/` and insist it matches. Skipped when Caddy already runs this config.
|
|
8
|
-
* - read — the digest of `GET /config/`.
|
|
9
|
-
* config becomes the starting point, and the deploy's forced update loads the declared one.
|
|
8
|
+
* - read — the digest of `GET /config/`. With no state it is the adoption probe (below).
|
|
10
9
|
* - diff — declared, live and stored digests (config-lifecycle.ts). Never `replace`.
|
|
11
10
|
* - delete — ⛔ NOTHING. See below.
|
|
12
11
|
*
|
|
@@ -15,6 +14,11 @@
|
|
|
15
14
|
* servers. `retain` is the default (the engine never calls delete); with `destroy` the handler
|
|
16
15
|
* still only forgets. It never calls `/stop` (which exits the process) or `DELETE /config/`.
|
|
17
16
|
* To empty a Caddy, do it by hand at its admin API.
|
|
17
|
+
* ⛔ NOTHING IS ADOPTED SILENTLY (decision, 2026-09-21 — the house rule HostFile and LaunchdJob
|
|
18
|
+
* keep). With no state, a running Caddy whose live config IS the declared one reads as ours (the
|
|
19
|
+
* adoption changes nothing); any other config reads as `Unowned`, and the plan refuses it unless
|
|
20
|
+
* the deploy runs with `--adopt`. A Caddy serving nothing reads as absent: a create. Where the
|
|
21
|
+
* engine skips that probe, reconcile refuses the same takeover (config-lifecycle.ts).
|
|
18
22
|
* ⛔ `caddyfile` IS NEVER A SECRET — see config-form.ts; refused before anything is sent.
|
|
19
23
|
* ⚠️ WHICH CADDY is the transport's (providers.ts), not a prop: one CaddyAdmin per stack.
|
|
20
24
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/caddy/config.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/caddy/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGnC,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAI7C,OAAO,EAAE,iBAAiB,EAAyB,MAAM,YAAY,CAAC;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGhF,YAAY,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEhF,MAAM,WAAW,WAAY,SAAQ,QAAQ,CAC3C,cAAc,EACd,gBAAgB,EAChB,qBAAqB,CACtB;CAAG;AAEJ,eAAO,MAAM,WAAW,8CAEtB,CAAC;AAsBH,eAAO,MAAM,mBAAmB,8FAsF7B,CAAC"}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* ★ `listenPort` is the port Caddy BELIEVES it listens on — its Host check uses it — while the
|
|
18
18
|
* fake really listens on an ephemeral one: a Caddy on its default :2019 behind a forward.
|
|
19
19
|
*/
|
|
20
|
+
import type { CaddyAdmin } from './admin.ts';
|
|
20
21
|
export type Seen = {
|
|
21
22
|
readonly method: string;
|
|
22
23
|
readonly path: string;
|
|
@@ -40,4 +41,14 @@ export declare const fakeCaddy: (options?: {
|
|
|
40
41
|
origins?: string[];
|
|
41
42
|
listenPort?: number;
|
|
42
43
|
}) => FakeCaddy;
|
|
44
|
+
/**
|
|
45
|
+
* A fake Caddy on its DEFAULT :2019 behind a forward (`hostHeader`), and the transport to it.
|
|
46
|
+
* ★ Addressed that way so a Caddyfile with no `admin` line — the common case — passes the guard.
|
|
47
|
+
* A Caddy reached on any other port needs `admin <address>` declared, or the first load would
|
|
48
|
+
* move it (admin-guard.ts).
|
|
49
|
+
*/
|
|
50
|
+
export declare const fakeDefaultCaddy: (running?: unknown) => {
|
|
51
|
+
admin: CaddyAdmin;
|
|
52
|
+
caddy: FakeCaddy;
|
|
53
|
+
};
|
|
43
54
|
//# sourceMappingURL=fake-caddy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fake-caddy.d.ts","sourceRoot":"","sources":["../../src/caddy/fake-caddy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,0CAA0C;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IACtB,+DAA+D;IAC/D,OAAO,EAAE,OAAO,CAAC;IACjB,+EAA+E;IAC/E,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,IAAI,IAAI,IAAI,CAAC;CACd,CAAC;AAqDF,eAAO,MAAM,SAAS,aACX;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,KACrF,SAoEF,CAAC"}
|
|
1
|
+
{"version":3,"file":"fake-caddy.d.ts","sourceRoot":"","sources":["../../src/caddy/fake-caddy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C,MAAM,MAAM,IAAI,GAAG;IACjB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,0CAA0C;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IACtB,+DAA+D;IAC/D,OAAO,EAAE,OAAO,CAAC;IACjB,+EAA+E;IAC/E,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,IAAI,IAAI,IAAI,CAAC;CACd,CAAC;AAqDF,eAAO,MAAM,SAAS,aACX;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,KACrF,SAoEF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,aAAc,OAAO,KAAG;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAQzF,CAAC"}
|
package/dist/caddy/index.d.ts
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* the digest, the guards and the admin calls are internals; an `export *` would publish them.
|
|
7
7
|
* ⛔ THE ADMIN API STAYS ON LOOPBACK OR A UNIX SOCKET. It has no authentication; localCaddyAdmin()
|
|
8
8
|
* refuses any other address, and a Caddyfile that would move or expose it is refused before load.
|
|
9
|
-
*
|
|
9
|
+
* ⛔ NOTHING IS ADOPTED SILENTLY: a running config that is not the declared one needs `--adopt`.
|
|
10
|
+
* Guide, order of file and load, adoption, `--resume` and secrets: docs/caddy.md.
|
|
10
11
|
*/
|
|
11
12
|
export type { CaddyAdmin, CaddyAdminListener, CaddyAdminRequest, CaddyAdminResponse, } from './admin.ts';
|
|
12
13
|
export { CaddyAdminService, CaddyUnreachableError, caddyAdminLayer } from './admin.ts';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/caddy/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/caddy/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,YAAY,EACV,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACvF,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,YAAY,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC/D,YAAY,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
|