release: merge v1.8.0 to main - #623
Merged
Merged
Conversation
Back-merge main into develop after v1.7.0
The config-key reference and the sinks section covered the semantics but not the operator journey (pick a topic, subscribe, apply, test, the Tor reachability gotcha for LAN self-hosted servers). Add that walkthrough to the sinks section and link it from configuration.md's ntfy.url row. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The front-page feature list predated a lot of what shipped. Add the telemetry/history store (#196), the depth of the in-browser config editor (guided form + JSON + upload, per-rig inspect + config-version hashrate correlation, #529/#518/#492), the configurability breadth (~94 keys across 13 sections), the energy/profit calculator (#260), and encrypted backups (#374). House voice, accurate to what ships — no invented features, no banned marketing words. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…tion (#520) (#614) dashboard.energy.tari_price adds Tari merge-mining earnings to the Energy tab's net profit, using the same what-if Tari/day estimate the Tari tab already shows. XvB stays excluded (raffle status, no clean per-day estimate). The net-profit heading and tooltip now say exactly what's included so the figure is never silently P2Pool-only.
Wires a fake monerod (control endpoint to toggle down/busy/synced) into docker-compose.fake.yml and sets LOCAL_MONERO_HOST=fake-monerod so the dashboard actually probes it (else monerod is treated remote and never checked). Adds CI-runnable scenarios: monerod down→reject→readmit (#31/#564), busy/mid-reorg reject, double-outage both-must-recover, and Tari-optional-keeps-mining (#562, its own compose cycle since it's a boot-time flag). Fixes the stale header comment (said monerod, tested Tari). Closes #562 Closes #564 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…-out (#611, #612, #613) (#615) * feat(#611,#612,#613): config form v2 — logical grouping, nested events, host-only grey-out Replaces "one section per top-level config.json key" with a display-layer logical grouping (Wallets & payout, Monero node, Mining, Workers, Dashboard & access, Notifications, Energy, Alerts & thresholds, System / advanced), so a grab-bag key like dashboard.* splits across the sections its fields actually belong to (#611). A path no group claims still renders, in a catch-all Other group, guarded by a frontend test that fails if any config.reference.json path would land there unclaimed. Nests telegram.events (26 toggles), the notification sinks, and healthchecks into their own collapsed sub-groups within Notifications, one level deeper than the existing <details> pattern (#612). Greys out any field the control-channel gate wouldn't actually commit, derived from pithead's CONTROL_DASHBOARD_EDITABLE_KEYS (plus the dashboard.energy special-case, #504) and surfaced to the browser as _editable_keys on GET /api/config — disabled, read-only, with a "Host-only" tooltip, and never wired to enter the edits set (#613). A drift-guard test mirrors #515's shape to keep the surfaced set in lockstep with the gate. config.json, the staged-preview -> closed-schema gate -> commit pipeline, and JSON mode are all unchanged — this is entirely display-layer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor: address ponytail-review findings on config form v2 - control_service.py: generate the 24 TELEGRAM_EVENT_* editable-path entries from a plain tuple of event names instead of hand-typing each dict line (mechanical rename, TELEGRAM_EVENT_<NAME> -> telegram.events.<name>). - configlogic.mjs classifyGroup: drop the longest-prefix-match bookkeeping — every LOGICAL_GROUPS prefix is already specific enough that no two groups ever compete for the same key, so first-match is equivalent and simpler. Replaced the fictitious "longest wins" test with a real invariant test (no two groups' prefixes overlap) that actually exercises the property the simplification depends on. - configview.mjs Field: drop the duplicate `title` attribute on the input/select (identical to the one already on the wrapping `<label>`). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…d fault-injection (#618) * test(tier4): Tor-down + cosign-verify + clock/ENOSPC + per-service uid fault-injection Adds the four real-hardware gaps a coverage audit found at the top tier: a --fault-injection case that stops the tor container and proves both no clearnet egress leak (#563, reuses bench-verify-egress.sh) and that `doctor` flags the outage instead of passing silently; a direct exercise of pithead's own verify_release_images() in release-smoke.sh against a real signed bundle plus a tampered-digest negative case (#376/#459); PATH-shadowed timedatectl and tmpfs-ENOSPC fault-injection cases for doctor's clock-sync and db_healthy verdicts (#383); and a per-service `docker exec <svc> id -u` matrix/--check assertion against each of the 9 services' audited uid (#255/#91). Verified by shellcheck --severity=warning, shfmt -i 4 -d, bash -n, the integration harness self-test (132/132), and manual tracing of the sourced verify_release_images()/clock_sync_status() paths against synthetic bundles — this cannot run against real hardware locally. * test(tier4): simplify the digest-tamper fixture (ponytail-review) Drop the dead pre-existence guard around the bundle extraction (WORK is always a fresh mktemp -d, so the dir can never already exist) and replace the last-hex-char-flip case statement with a fixed all-zero 64-char digest — same effect (a well-formed but mismatched sha256), fewer lines.
…pt, wizard (#617) Closes five tier-1 coverage gaps found in a source-vs-tests audit: - #565 compose depends_on ordering: assert each of the 6 depends_on edges in docker-compose.yml keeps its expected dependency + condition (5x service_healthy, 1x service_started for xmrig-proxy -> p2pool), plus a count guard so a new undocumented edge trips the test too. - audit-log write-side trim (#349): the write-side 512 KiB / ~2000-line trim in control_audit was already exercised by the existing "audit log growth is bounded" test, but only asserted the byte cap. Add the line-count assertion the "newest ~2000 lines" behavior implies. - Tor onion key perms (#343): assert provision_onion_client_auth leaves the hidden-service dir 0700 and the client-auth key file 0600 -- Tor silently refuses a HiddenServiceDir that's group/other-accessible, so a wrong mode is a silent provisioning failure. - control worker-apply ACCEPT path (#185): only the fail-closed reject path was tested. Add a stub-curl-backed test that dials a valid rig, gets a 202 + change_id, polls to a terminal "applied", and checks the audit trail -- mirrors the existing reject-path test's setup. - setup wizard behavioral drive (#502): no test drove the actual `setup` command end-to-end (only the wizard sub-functions directly). Discovered along the way: ensure_config_exists refuses a piped/non-interactive run outright when config.json is missing (by design), so a full black-box Q&A capture isn't possible without faking a tty. Instead: produce config.json the same piped-stdin way the existing wizard tests do, then hand it to the real `setup` command (which skips past that gate once config.json exists) and drive its two remaining prompts. Each new assertion was revert-proofed against the real pithead/ docker-compose.yml source (temporarily broken, confirmed red, restored). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…619) Both privacy checks (egress-firewall-installed, tor-clearnet-egress) skipped with an info line whenever the tor container wasn't running — conflating a clean `down` (rules removed, nothing to guard) with the dangerous state where tor crashed or was stopped individually while monerod/p2pool/xmrig-proxy keep running. In that state the privacy backbone is dead but the stack is live, and doctor reported "all clear." Now: tor down + any revenue container up → dr_fail with a restart-tor / bring-down hint. A clean down still info-skips. Surfaced by the #563 Tor-down tier-4 fault-injection test (its assertion that doctor fails loudly now holds). Also fixes the doctor-test docker stub's name regex ([a-z-] -> [a-z0-9-]) so it matches digit-containing names like p2pool. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
VERSION 1.8.0, dashboard pyproject/uv.lock lockstep (#44), CHANGELOG [Unreleased]→[1.8.0]. Config editor logical grouping + nested event groups + host-only grey-out (#611/#612/#613), Tari revenue in the energy calculator (#520), the failover/privacy coverage push (mini-stack fake monerod + tier-4 fault-injection), and the doctor Tor-down fix. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Real-merge of the v1.8.0 release commit (857626b, tag v1.8.0) into main, keeping main = released-only. Excludes #621 (doctor refactor), which stays on develop for the next release. Back-merge main→develop follows to preserve the main-ancestor-of-develop invariant.
🤖 Generated with Claude Code