From 558a8bea027dd81abd4563dc108cc25b5ff07e5d Mon Sep 17 00:00:00 2001 From: Ant Somers Date: Mon, 19 Oct 2026 21:47:21 +0300 Subject: [PATCH] chore: pin sponsord to v0.2.0 Moves the decdn/sponsord pin to the line `0.2` and v0.2.0, from `0.1` and v0.1.0: sponsord_version and sponsord_onramp_version, Compose's two image digests (from the release's signed *-image-digest.txt, verified against the vendored KEYS), the commented exact examples and AGENTS.md's pin paragraph. No env var, metric or KEYS change upstream. sponsord-onramp 0.2.0 refuses an ONRAMP_DECDN_RELEASE below v0.2.0 at startup (its installers run `decdn get` without `-o`, which decdn v0.1.x refuses), so the onramp role now checks that floor in preflight, before installing, instead of failing the /healthz gate after; an exact sponsord_onramp_version below 0.2 is exempt. validation-sponsord covers the refusal. Co-Authored-By: Claude Fable 5.1 --- AGENTS.md | 2 +- .../inventory/group_vars/sponsord_hosts.yml | 4 ++-- .../group_vars/sponsord_onramp_hosts.yml | 4 ++-- .../molecule/validation-sponsord/converge.yml | 18 ++++++++++++++++-- ansible/roles/sponsord/defaults/main.yml | 2 +- ansible/roles/sponsord_onramp/README.md | 2 +- .../roles/sponsord_onramp/defaults/main.yml | 2 +- .../sponsord_onramp/tasks/decdn-release.yml | 2 +- ansible/roles/sponsord_onramp/tasks/main.yml | 19 +++++++++++++++++++ compose/.env.example | 4 ++-- .../inventory/group_vars/sponsord_hosts.yml | 4 ++-- .../group_vars/sponsord_onramp_hosts.yml | 4 ++-- 12 files changed, 50 insertions(+), 17 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 6335f0f..279c87d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -143,7 +143,7 @@ lint-alloy` validates and runs it. **Pinned upstream releases.** One decdn/decdn release line (`decdn_node_version`, today `0.2`) and one decdn/sponsord release line (`sponsord_version` = `sponsord_onramp_version`, -today `0.1`; decdn/sponsord tags its whole workspace `vX.Y.Z`, there are no per-crate +today `0.2`; decdn/sponsord tags its whole workspace `vX.Y.Z`, there are no per-crate tags) are pinned across every path. A line, `X.Y`, is what the role defaults, the onramp's installer pin (`sponsord_onramp_decdn_release`, `vX.Y`) and the chart's `appVersion` name: the roles install its newest finished `vX.Y.N` on every run diff --git a/ansible/inventory/group_vars/sponsord_hosts.yml b/ansible/inventory/group_vars/sponsord_hosts.yml index 2a3934e..b59380d 100644 --- a/ansible/inventory/group_vars/sponsord_hosts.yml +++ b/ansible/inventory/group_vars/sponsord_hosts.yml @@ -14,11 +14,11 @@ # The default method, "release", installs the newest release of the decdn/sponsord # line the role pins (sponsord_version "X.Y"), on each deploy; set an exact one only # to hold the host on it, together with sponsord_onramp_version: -# sponsord_version: "0.1.0" +# sponsord_version: "0.2.0" # Or build on the host from a git ref (tag, branch or SHA; sponsord_version is not # checked in this mode): # sponsord_install_method: source -# sponsord_source_ref: v0.1.0 +# sponsord_source_ref: v0.2.0 # Or copy a control-machine build: a decdn/sponsord checkout's target dir # (`cargo build --release -p sponsord`; the role checks the ELF matches the host). # sponsord_install_method: manual diff --git a/ansible/inventory/group_vars/sponsord_onramp_hosts.yml b/ansible/inventory/group_vars/sponsord_onramp_hosts.yml index 8ab8a89..14b6387 100644 --- a/ansible/inventory/group_vars/sponsord_onramp_hosts.yml +++ b/ansible/inventory/group_vars/sponsord_onramp_hosts.yml @@ -12,10 +12,10 @@ # --- Binary ------------------------------------------------------------------------ # The same three methods as sponsord. "release" (default) installs the same release # as the sponsord role; set both versions together to hold the host on another: -# sponsord_onramp_version: "0.1.0" +# sponsord_onramp_version: "0.2.0" # Or build on the host (its own checkout, so it may pin a different ref): # sponsord_onramp_install_method: source -# sponsord_onramp_source_ref: v0.1.0 +# sponsord_onramp_source_ref: v0.2.0 # Or manual, which follows sponsord_release_target_dir (`cargo build --release` in # a decdn/sponsord checkout builds both binaries): # sponsord_onramp_install_method: manual diff --git a/ansible/molecule/validation-sponsord/converge.yml b/ansible/molecule/validation-sponsord/converge.yml index 6ca7a5e..e824fbc 100644 --- a/ansible/molecule/validation-sponsord/converge.yml +++ b/ansible/molecule/validation-sponsord/converge.yml @@ -989,13 +989,27 @@ ansible.builtin.include_role: name: sponsord_onramp vars: - sponsord_onramp_decdn_release: v0.1 + sponsord_onramp_decdn_release: v0.2 rescue: - name: Record onramp-pin-pair rejection (only if its assert failed) ansible.builtin.set_fact: decdn_rejected: "{{ decdn_rejected + ['onramp-pin-pair'] }}" when: ansible_failed_task.name == "Require a SHA256SUMS digest exactly when the release pin is a tag" + - name: "Case onramp-decdn-floor — a decdn release line sponsord-onramp 0.2 refuses" + block: + - name: Run sponsord_onramp with a decdn release line below v0.2 + ansible.builtin.include_role: + name: sponsord_onramp + vars: + sponsord_onramp_decdn_release: v0.1 + sponsord_onramp_decdn_sums_sha256: "" + rescue: + - name: Record onramp-decdn-floor rejection (only if its assert failed) + ansible.builtin.set_fact: + decdn_rejected: "{{ decdn_rejected + ['onramp-decdn-floor'] }}" + when: ansible_failed_task.name == "Refuse a decdn release below the installers' floor" + - name: "Case onramp-pin — an upper-case SHA256SUMS digest" block: - name: Run sponsord_onramp with an upper-case SHA256SUMS digest @@ -1359,7 +1373,7 @@ "onramp-zero-address", "onramp-bind", "onramp-bind", "onramp-proxy", "onramp-domain", "onramp-public-url", "onramp-public-url", "onramp-rpc", "onramp-rpc", "onramp-rpc", "onramp-rpc", "onramp-public-url", "onramp-sitekey", "onramp-pin", - "onramp-pin", "onramp-pin-pair", "onramp-pin-pair", + "onramp-pin", "onramp-pin-pair", "onramp-pin-pair", "onramp-decdn-floor", "onramp-limit", "onramp-ip-header", "onramp-token", "onramp-turnstile", "onramp-turnstile", "onramp-turnstile-empty", "onramp-turnstile-inventory", diff --git a/ansible/roles/sponsord/defaults/main.yml b/ansible/roles/sponsord/defaults/main.yml index 9d1a1c0..5f6bbcf 100644 --- a/ansible/roles/sponsord/defaults/main.yml +++ b/ansible/roles/sponsord/defaults/main.yml @@ -55,7 +55,7 @@ decdn_rustup_sha256: # pins that one release. Keep it equal to sponsord_onramp_version: both come from # one workspace release (README.md, "Bumping the sponsord release"; make # test-scripts checks the defaults agree). -sponsord_version: "0.1" +sponsord_version: "0.2" # Release target triple, derived from the host's gathered architecture (see # vars/main/arch.yml). Set it explicitly only for a play with gather_facts: false. sponsord_target: "{{ _sponsord_arch_targets.get(ansible_facts.get('architecture', ''), '') }}" diff --git a/ansible/roles/sponsord_onramp/README.md b/ansible/roles/sponsord_onramp/README.md index 56b36c7..9b2bfc8 100644 --- a/ansible/roles/sponsord_onramp/README.md +++ b/ansible/roles/sponsord_onramp/README.md @@ -138,7 +138,7 @@ See [`defaults/main.yml`](defaults/main.yml) for the full list with comments. | `sponsord_onramp_turnstile_sitekey` | `""` | **Required.** | | `sponsord_onramp_turnstile_secret` | `""` | **Sensitive.** Leave empty to provision `turnstile-secret` on the host. | | `sponsord_onramp_turnstile_secret_overwrite_host_file` | `false` | Confirm that the inventory secret may replace a file the role did not write. | -| `sponsord_onramp_decdn_release`, `_decdn_sums_sha256` | the `decdn_node` role's default line as a `v` tag, `""` | A decdn/decdn line (`vX.Y`, with no digest: the role reads it from the resolved release) or a tag (`vX.Y.Z`) with its 64-lowercase-hex digest. The default follows the `decdn_node` role's pin; a host override of `decdn_node_version` does not move it. | +| `sponsord_onramp_decdn_release`, `_decdn_sums_sha256` | the `decdn_node` role's default line as a `v` tag, `""` | A decdn/decdn line (`vX.Y`, with no digest: the role reads it from the resolved release) or a tag (`vX.Y.Z`) with its 64-lowercase-hex digest, `v0.2.0` or later (sponsord-onramp 0.2 refuses an older one: its installers rely on decdn 0.2's `get` picking the destination; the role checks this before installing). The default follows the `decdn_node` role's pin; a host override of `decdn_node_version` does not move it. | | `sponsord_onramp_decdn_release_index`, `_decdn_release_base`, `_decdn_keyring` | GitHub's decdn/decdn release list, `/decdn/releases/download`, the vendored KEYS | Where a line is resolved, where its `SHA256SUMS` is read (the installers' own download location), and the keys it must verify against. | | `sponsord_onramp_brand_name`, `_gate_template_src` | `""` | The gate page's name, or your own HTML page (a control-machine file). | | `sponsord_onramp_spending_cap_micro_usdc`, `_ttl_secs` | `""` | Requested per capability. `""` takes the daemon's maximum; more than it fails the deploy. | diff --git a/ansible/roles/sponsord_onramp/defaults/main.yml b/ansible/roles/sponsord_onramp/defaults/main.yml index bbd89a3..f546f66 100644 --- a/ansible/roles/sponsord_onramp/defaults/main.yml +++ b/ansible/roles/sponsord_onramp/defaults/main.yml @@ -50,7 +50,7 @@ decdn_rustup_sha256: # --- Release to install ("release" mode) ---------------------------------------- # The decdn/sponsord release to install, a line ("X.Y", the newest finished vX.Y.N) # or an exact "X.Y.Z": the same one as the sponsord role's sponsord_version. -sponsord_onramp_version: "0.1" +sponsord_onramp_version: "0.2" # Derived from the host's gathered architecture (vars/main/arch.yml). sponsord_onramp_target: "{{ _sponsord_onramp_arch_targets.get(ansible_facts.get('architecture', ''), '') }}" sponsord_onramp_release_base: "https://github.com/decdn/sponsord/releases/download" diff --git a/ansible/roles/sponsord_onramp/tasks/decdn-release.yml b/ansible/roles/sponsord_onramp/tasks/decdn-release.yml index 34e1517..acb01a2 100644 --- a/ansible/roles/sponsord_onramp/tasks/decdn-release.yml +++ b/ansible/roles/sponsord_onramp/tasks/decdn-release.yml @@ -3,7 +3,7 @@ # SHA256SUMS digest the onramp serves (ONRAMP_DECDN_RELEASE, _SUMS_SHA256). # # An exact sponsord_onramp_decdn_release comes with the operator's -# sponsord_onramp_decdn_sums_sha256 and is served as it is. A line ("v0.1") resolves +# sponsord_onramp_decdn_sums_sha256 and is served as it is. A line ("v0.2") resolves # to the newest finished release in it (tasks/resolve-release.yml), and its digest # is taken from that release's SHA256SUMS, fetched from where the installers fetch # it and verified against the decdn/decdn KEYS vendored with this role first: every diff --git a/ansible/roles/sponsord_onramp/tasks/main.yml b/ansible/roles/sponsord_onramp/tasks/main.yml index f7585fe..0f2fa90 100644 --- a/ansible/roles/sponsord_onramp/tasks/main.yml +++ b/ansible/roles/sponsord_onramp/tasks/main.yml @@ -414,6 +414,25 @@ (`sha256sum SHA256SUMS` after verifying its .asc). A tag served with another release's digest fails every installer. +# sponsord-onramp 0.2.0 refuses an ONRAMP_DECDN_RELEASE below v0.2.0 at startup +# (MIN_DECDN_RELEASE in crates/sponsord-onramp/src/config.rs): its installers run +# `decdn get` without `-o`, which v0.1.x's `get` refuses. Caught here, before the +# install, instead of by the fatal /healthz gate after it. An exact +# sponsord_onramp_version below 0.2 keeps the old installers and is exempt. +- name: Refuse a decdn release below the installers' floor + ansible.builtin.assert: + that: + - >- + sponsord_onramp_version | string is not version('0.2', '>=') + or (sponsord_onramp_decdn_release | regex_replace('^v', '')) is version('0.2.0', '>=') + fail_msg: >- + sponsord_onramp_decdn_release={{ sponsord_onramp_decdn_release }} is below v0.2.0, + and sponsord-onramp {{ sponsord_onramp_version }} refuses to serve it: its + installers run `decdn get` without `-o`, which decdn v0.1.x refuses. Move + sponsord_onramp_decdn_release to v0.2 or later (the default follows the + decdn_node role's line), or hold the onramp on an exact sponsord_onramp_version + below 0.2. + - name: Validate the onramp's limits ansible.builtin.assert: that: diff --git a/compose/.env.example b/compose/.env.example index 0739c94..e6ee76c 100644 --- a/compose/.env.example +++ b/compose/.env.example @@ -44,9 +44,9 @@ DECDN_ENV_FILE=/etc/decdn/decdn.env # --- sponsord and onramp ---------------------------------------------------------- # The newest release of the decdn/sponsord line sponsord_version pins: one release # for both images -SPONSORD_IMAGE_DIGEST=sha256:8f82f8f88ce75be0072abc8f72e0462e03c0afba8035fe8671d6ee79ebbc930b +SPONSORD_IMAGE_DIGEST=sha256:8f042a0b2cbad8ee50430d7f7933e3e43b82b84a16370101923a43a2e21edb1f # SPONSORD_IMAGE_REPO=ghcr.io/decdn/sponsord -SPONSORD_ONRAMP_IMAGE_DIGEST=sha256:f0a2701a717c9cdd0ec0969866be30ccbf82773e08c7f25405413f543281a2df +SPONSORD_ONRAMP_IMAGE_DIGEST=sha256:c27bd9542c147c879303ed2e08c086a4aaa918ef2fe0c773e957f9648301f52a # SPONSORD_ONRAMP_IMAGE_REPO=ghcr.io/decdn/sponsord-onramp # uid/gid of the host's dedicated `sponsord` system account, which owns the diff --git a/examples/collection-fleet/inventory/group_vars/sponsord_hosts.yml b/examples/collection-fleet/inventory/group_vars/sponsord_hosts.yml index 2a3934e..b59380d 100644 --- a/examples/collection-fleet/inventory/group_vars/sponsord_hosts.yml +++ b/examples/collection-fleet/inventory/group_vars/sponsord_hosts.yml @@ -14,11 +14,11 @@ # The default method, "release", installs the newest release of the decdn/sponsord # line the role pins (sponsord_version "X.Y"), on each deploy; set an exact one only # to hold the host on it, together with sponsord_onramp_version: -# sponsord_version: "0.1.0" +# sponsord_version: "0.2.0" # Or build on the host from a git ref (tag, branch or SHA; sponsord_version is not # checked in this mode): # sponsord_install_method: source -# sponsord_source_ref: v0.1.0 +# sponsord_source_ref: v0.2.0 # Or copy a control-machine build: a decdn/sponsord checkout's target dir # (`cargo build --release -p sponsord`; the role checks the ELF matches the host). # sponsord_install_method: manual diff --git a/examples/collection-fleet/inventory/group_vars/sponsord_onramp_hosts.yml b/examples/collection-fleet/inventory/group_vars/sponsord_onramp_hosts.yml index 8ab8a89..14b6387 100644 --- a/examples/collection-fleet/inventory/group_vars/sponsord_onramp_hosts.yml +++ b/examples/collection-fleet/inventory/group_vars/sponsord_onramp_hosts.yml @@ -12,10 +12,10 @@ # --- Binary ------------------------------------------------------------------------ # The same three methods as sponsord. "release" (default) installs the same release # as the sponsord role; set both versions together to hold the host on another: -# sponsord_onramp_version: "0.1.0" +# sponsord_onramp_version: "0.2.0" # Or build on the host (its own checkout, so it may pin a different ref): # sponsord_onramp_install_method: source -# sponsord_onramp_source_ref: v0.1.0 +# sponsord_onramp_source_ref: v0.2.0 # Or manual, which follows sponsord_release_target_dir (`cargo build --release` in # a decdn/sponsord checkout builds both binaries): # sponsord_onramp_install_method: manual