Skip to content

release: merge v1.8.0 to main - #623

Merged
VijitSingh97 merged 10 commits into
mainfrom
release/main-v1.8.0
Jul 18, 2026
Merged

release: merge v1.8.0 to main#623
VijitSingh97 merged 10 commits into
mainfrom
release/main-v1.8.0

Conversation

@VijitSingh97

Copy link
Copy Markdown
Collaborator

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

VijitSingh97 and others added 10 commits July 17, 2026 16:44
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>
@VijitSingh97
VijitSingh97 merged commit b061ea0 into main Jul 18, 2026
32 checks passed
@VijitSingh97
VijitSingh97 deleted the release/main-v1.8.0 branch July 18, 2026 00:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant