diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a3542d..8bc0e59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,26 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased +## 0.17.3 — 2026-06-02 + +### Fixed — clawmes couldn't reach the Clawnch backend in production + +The Clawnch apex host `clawn.ch` 307-redirects to the `www.clawn.ch` canonical +host, but (a) `www.clawn.ch` was not on the network allowlist and (b) the HTTP +client deliberately does not follow cross-host redirects (an allowlisted host +redirecting to a non-allowlisted one would otherwise bypass the allowlist). The +combination meant every Clawnch API call — agent registration, token deploys, +`leaderboard` / `my_launches` reads — failed with either a 307 error or a +`NetworkAllowlistError`. + +- `lib/http.py`: added `www.clawn.ch` to `_DEFAULT_ALLOWLIST` alongside the + apex. +- `services/clawnch.py`: the default base URL is now `https://www.clawn.ch` + (the canonical host, no redirect). `CLAWNCH_BASE_URL` still overrides for + staging / local dev. + +No config change is needed; existing installs pick this up on update. + ## 0.17.2 — 2026-06-02 ### Reverted — no bundled WalletConnect project ID (security) diff --git a/clawmes/_version.py b/clawmes/_version.py index 70a63d5..4cdfc46 100644 --- a/clawmes/_version.py +++ b/clawmes/_version.py @@ -7,4 +7,4 @@ * Tooling that does not want to incur a full package import """ -__version__ = "0.17.2" +__version__ = "0.17.3" diff --git a/clawmes/lib/http.py b/clawmes/lib/http.py index f5f4f31..1b107f3 100644 --- a/clawmes/lib/http.py +++ b/clawmes/lib/http.py @@ -98,7 +98,10 @@ "bv7x.ai", # Clawnch launchpad HTTP API — see services.clawnch for the deploy / # agent-registration flow used by /launch and clawnch_launch tool. + # The apex 307-redirects to the www canonical host, so both must be + # allowed (the client doesn't follow cross-host redirects by design). "clawn.ch", + "www.clawn.ch", # Simulation "api.tenderly.co", # Fiat ramps diff --git a/clawmes/plugin.yaml b/clawmes/plugin.yaml index 0827073..e226a51 100644 --- a/clawmes/plugin.yaml +++ b/clawmes/plugin.yaml @@ -1,5 +1,5 @@ name: clawmes -version: 0.17.2 +version: 0.17.3 description: Hermes Agent for crypto. Wallet, swaps, DeFi, launches, automation. author: Clawnch kind: standalone diff --git a/clawmes/services/clawnch.py b/clawmes/services/clawnch.py index d0e2aa5..88163c5 100644 --- a/clawmes/services/clawnch.py +++ b/clawmes/services/clawnch.py @@ -48,7 +48,10 @@ #: Base URL of the Clawnch HTTP API. Override via ``CLAWNCH_BASE_URL`` for #: staging / local dev. The service uses ``/api/...`` paths underneath. -_BASE_URL = os.environ.get("CLAWNCH_BASE_URL", "https://clawn.ch") +#: Defaults to the ``www`` canonical host: the apex ``clawn.ch`` 307-redirects +#: to ``www.clawn.ch`` and our HTTP client doesn't follow cross-host redirects, +#: so targeting the apex would fail every request. +_BASE_URL = os.environ.get("CLAWNCH_BASE_URL", "https://www.clawn.ch") #: Source tag attached to every deploy made through clawmes. Lets the #: launchpad render a "launched via clawmes" badge on launch detail pages. diff --git a/plugin.yaml b/plugin.yaml index 0827073..e226a51 100644 --- a/plugin.yaml +++ b/plugin.yaml @@ -1,5 +1,5 @@ name: clawmes -version: 0.17.2 +version: 0.17.3 description: Hermes Agent for crypto. Wallet, swaps, DeFi, launches, automation. author: Clawnch kind: standalone diff --git a/pyproject.toml b/pyproject.toml index a95b4a6..34e693f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "clawmes" -version = "0.17.2" +version = "0.17.3" description = "Hermes Agent plugin for crypto: wallets, DEX trading, lending and staking, governance, on-chain automation." readme = "README.md" license = { text = "MIT" } diff --git a/tests/lib/test_http.py b/tests/lib/test_http.py index 231d9ee..dad5dd0 100644 --- a/tests/lib/test_http.py +++ b/tests/lib/test_http.py @@ -24,6 +24,12 @@ def test_allows_known_host(self): _check_allowlist("https://api.coingecko.com/api/v3/simple/price") _check_allowlist("https://api.basescan.org/api") + def test_allows_clawnch_apex_and_www(self): + # The apex 307-redirects to the www canonical host; both must be + # allowed since the client doesn't follow cross-host redirects. + _check_allowlist("https://clawn.ch/api/agents/register") + _check_allowlist("https://www.clawn.ch/api/agents/register") + def test_rejects_unknown_host(self): with pytest.raises(NetworkAllowlistError, match="not on the clawmes network allowlist"): _check_allowlist("https://evil.example.com/whatever") diff --git a/tests/services/test_clawnch.py b/tests/services/test_clawnch.py index 6920193..936690e 100644 --- a/tests/services/test_clawnch.py +++ b/tests/services/test_clawnch.py @@ -51,6 +51,12 @@ def test_start_authenticated(self, monkeypatch, svc): svc.start() assert svc.health()["status"] == "authenticated" + def test_base_url_defaults_to_www(self, svc): + # Apex clawn.ch 307-redirects to www; the client doesn't follow + # cross-host redirects, so the default targets the www host directly. + svc.start() + assert svc.health()["base_url"] == "https://www.clawn.ch" + def test_base_url_override(self, monkeypatch, svc): monkeypatch.setenv("CLAWNCH_BASE_URL", "https://staging.clawn.ch/") svc.start()