Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ per the process in [`docs/releasing.md`](docs/releasing.md).

## [Unreleased]

## [1.5.2] - 2026-07-14

### Fixed

- **Enriched per-rig stats work again when `dashboard.workers[]` is populated (regression from 1.5.1).**
1.5.1's #508 fix kept a worker descriptor whose token is the masked `{"__secret__": true}` sentinel;
the read-probe auth then stringified that dict into the `Authorization: Bearer` header, so every
enriched-feed probe returned HTTP 401 and per-rig stats disappeared. The probe now uses a per-worker
token only when it's a real string, falling through to the fleet auth mode (e.g. `name`) for the
masked sentinel — the host-side runner still uses the real token for the control path.

## [1.5.1] - 2026-07-14

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.5.1
1.5.2
6 changes: 5 additions & 1 deletion build/dashboard/mining_dashboard/client/xmrig_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,11 @@ def _auth_header(self, name_token, override_token=""):
A per-worker token (#172) implies token-auth for that worker only, whatever the
fleet-wide mode says.
"""
if override_token:
# Only a real STRING token overrides the fleet auth. The container reads the MASKED config
# (#440), where a per-worker token is the {"__secret__": true} sentinel — it means "a token
# exists but the container doesn't hold it", so fall through to the fleet auth mode (e.g. name)
# for the read probe. The host-side runner still uses the real token for control (#508/#440).
if isinstance(override_token, str) and override_token:
return {"Authorization": f"Bearer {override_token}"}
mode = XMRIG_API_AUTH
if mode == "name":
Expand Down
2 changes: 1 addition & 1 deletion build/dashboard/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ name = "mining-dashboard"
# Keep in lockstep with the top-level VERSION file — the single source of truth for the stack version
# (#44). A shell test (tests/stack/run.sh) fails if these drift; the dashboard *displays* the version
# from VERSION (baked in as PITHEAD_VERSION, #58), so this is packaging metadata only.
version = "1.5.1"
version = "1.5.2"
description = "Monitoring dashboard and XvB switching engine for Pithead"
readme = "README.md"
requires-python = ">=3.11"
Expand Down
14 changes: 14 additions & 0 deletions build/dashboard/tests/client/test_xmrig_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,20 @@ async def test_override_token_beats_fleet_name_auth(monkeypatch):
assert session.calls[0][1]["Authorization"] == "Bearer per-rig-secret"


async def test_masked_sentinel_token_falls_through_to_fleet_name_auth(monkeypatch):
# The container reads the MASKED config (#440): a per-worker token is the {"__secret__": true}
# sentinel, which must NOT be sent as a bearer (stringifying the dict 401s). It means "a token
# exists but the container doesn't hold it", so the read probe falls through to the fleet auth
# mode; the host-side runner uses the real token for control (#508).
monkeypatch.setattr(xc, "XMRIG_API_AUTH", "name")
_with_overrides(
monkeypatch, [{"name": "rig1", "host": "10.0.0.1", "token": {"__secret__": True}}]
)
session = FakeSession(response=FakeResponse(200, {"ok": True}))
await XMRigWorkerClient(session).get_stats("10.0.0.1", "rig1")
assert session.calls[0][1]["Authorization"] == "Bearer rig1"


async def test_match_is_by_stratum_name_before_plus_suffix(monkeypatch):
_with_overrides(monkeypatch, [{"name": "rig1", "port": 18088}])
session = FakeSession(response=FakeResponse(200, {"ok": True}))
Expand Down
2 changes: 1 addition & 1 deletion build/dashboard/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.