Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
e0abb66
ci: add develop to push triggers + guard the release gate against a m…
VijitSingh97 Jun 16, 2026
6d24b54
chore(v1.1): Wave 1 cleanup — dead known_workers, tar xattrs, fail-cl…
VijitSingh97 Jun 16, 2026
fec2831
feat(p2pool): route outbound sidechain P2P through Tor by default (#1…
VijitSingh97 Jun 17, 2026
851e8a9
feat(xvb): route XvB donation mining through Tor by default (#166) (#…
VijitSingh97 Jun 17, 2026
3244625
feat(privacy): enforce Tor-only egress fail-closed via a host firewal…
VijitSingh97 Jun 17, 2026
87ee875
fix(privacy): install Tor-egress firewall before containers start — c…
VijitSingh97 Jun 17, 2026
5509c78
fix(privacy): route Tari clearnet peer dials through Tor SOCKS — genu…
VijitSingh97 Jun 17, 2026
7d3cae6
fix(#272): e2e deploys via `pithead upgrade` so it rebuilds the branc…
VijitSingh97 Jun 17, 2026
0f495ab
feat(#274): standing no-clearnet-leak egress gate in the harness (#288)
VijitSingh97 Jun 17, 2026
cb172e8
fix(#273): fail-loud when a stale p2pool image drops the Tor flags (c…
VijitSingh97 Jun 17, 2026
ed84823
fix(#278): keep p2pool's monerod RPC/ZMQ direct under Tor (loopback b…
VijitSingh97 Jun 17, 2026
9f79215
tooling(#280): ruff lint + format for all repo Python (+ .editorconfi…
VijitSingh97 Jun 18, 2026
96b6ad5
build(#283): reproducible Python builds with uv + uv.lock (#297)
VijitSingh97 Jun 18, 2026
631e6fa
build(#282): supply-chain & secrets hardening (gitleaks, Trivy, Depen…
VijitSingh97 Jun 18, 2026
fbd641d
build(#281): round out per-surface lint/format (shfmt, Biome, yamllin…
VijitSingh97 Jun 18, 2026
fbbfe52
build(deps): bump GitHub Actions to v6 (checkout/setup-python/setup-n…
dependabot[bot] Jun 18, 2026
ef29e3c
build(#282): scope Dependabot to safe updates (docker digest-only, pi…
VijitSingh97 Jun 18, 2026
7d24418
build(deps): bump base-image digests (python:3.11-slim, alpine) (#304)
dependabot[bot] Jun 18, 2026
c48cc48
build(deps): bump the python group (requests + transitive) (#305)
dependabot[bot] Jun 18, 2026
fc85b28
build(#286): adopt RigForge CI best practices — diff-cover patch cove…
VijitSingh97 Jun 18, 2026
67d3027
test(#284): hypothesis property tests for the money/numeric logic (#307)
VijitSingh97 Jun 18, 2026
5f54909
build(deps): bump actions/checkout in the actions group (#309)
dependabot[bot] Jun 25, 2026
1a835e1
build(deps): bump the python group in /build/dashboard with 3 updates…
dependabot[bot] Jun 25, 2026
59d089f
feat(#256): autonomous Tor-vs-clearnet benchmark harness + finalized …
VijitSingh97 Jun 28, 2026
895b6c5
feat(#170): Stack Topology panel — full wiring map (ingress/egress/in…
VijitSingh97 Jun 28, 2026
128331b
fix(#313): route Tari merge-mine gRPC over loopback under Tor (extend…
VijitSingh97 Jun 28, 2026
a4796b7
test(#170): end-to-end coverage for Stack Topology & Egress (#312)
VijitSingh97 Jun 28, 2026
09e0ba2
feat(#171,#172): one config-driven worker-API probe, default no-auth …
VijitSingh97 Jun 28, 2026
5570255
fix(#291): apply Tor-egress firewall BEFORE compose in stack_upgrade …
VijitSingh97 Jun 28, 2026
ce01d20
feat(#263): auto-register miners with the XvB raffle (no manual signu…
VijitSingh97 Jun 28, 2026
e79f704
test(#295): confirm effective Tari status is surfaced; lock in build_…
VijitSingh97 Jun 28, 2026
e005666
docs(#259): attribute bundled third-party components + GPLv3 source p…
VijitSingh97 Jun 28, 2026
a9ef228
feat(#255,#91): run all containers as non-root + security follow-ups …
VijitSingh97 Jun 28, 2026
9f9b311
test(#206): close the deferred tier-1/4 live-validation gaps for secu…
VijitSingh97 Jun 28, 2026
8a5ac93
test: resync drifted frontend fixture + make regen deterministic (#323)
VijitSingh97 Jun 28, 2026
b3d0ff6
fix(#311): guard XvB controller against a stale/frozen stats fetch + …
VijitSingh97 Jun 28, 2026
e3750e1
refactor: pre-v1.1 conservative code + test cleanup (#324)
VijitSingh97 Jun 28, 2026
d8189c0
docs: rewrite for voice consistency (#325)
VijitSingh97 Jun 29, 2026
6d91132
build(deps): bump python (#327)
dependabot[bot] Jul 1, 2026
d2301de
build(deps): bump actions/setup-python in the actions group (#328)
dependabot[bot] Jul 1, 2026
4e1b05c
build(deps): bump ruff in /build/dashboard in the python group (#329)
dependabot[bot] Jul 1, 2026
8d90490
chore: rename config files for clarity (minimal + reference) (#326)
VijitSingh97 Jul 1, 2026
f1e6db2
test: cover flagged edge cases + fix snapshot persistence-health bug …
VijitSingh97 Jul 1, 2026
78404e4
release: v1.1.0
VijitSingh97 Jul 1, 2026
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
24 changes: 24 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# EditorConfig — whitespace/EOL baseline across every file surface (Wave 7 tooling, #280).
# https://editorconfig.org · Mirrors the formatters: ruff (Python), and the per-surface
# tools landing in #281 (shfmt -i 4 for shell, Biome 2-space for JS/CSS/JSON).
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 4

# Web/config surfaces conventionally use 2-space indent.
[*.{js,mjs,cjs,css,json,jsonc,yml,yaml,toml,proto}]
indent_size = 2

# Markdown uses two trailing spaces for a hard line break — don't strip them.
[*.md]
trim_trailing_whitespace = false

# Makefiles require real tabs.
[Makefile]
indent_style = tab
49 changes: 49 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Dependabot (Wave 7 tooling, #282): automated dependency + CVE update PRs across every
# supply-chain surface. Grouped + weekly to keep PR volume sane.
version: 2
updates:
# GitHub Actions — keep the SHA-pinned actions (#282) fresh. Dependabot rewrites the SHA and the
# `# vX.Y.Z` comment together.
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
groups:
actions:
patterns: ["*"]

# Dashboard Python deps — bumps the hashed uv.lock + pyproject floors (#283).
- package-ecosystem: "uv"
directory: "/build/dashboard"
schedule:
interval: "weekly"
groups:
python:
patterns: ["*"]
ignore:
# protobuf/grpcio are pinned to what the vendored Tari gRPC stubs assert at import time
# (see build/dashboard/pyproject.toml); a major bump needs the stubs regenerated first.
- dependency-name: "protobuf"
update-types: ["version-update:semver-major"]
- dependency-name: "grpcio"
update-types: ["version-update:semver-major"]

# Base-image digests across every build/* Dockerfile (incl. the uv build image). This is the
# mechanism that clears base-distro CVEs — e.g. the openssl point-release accepted in .trivyignore.
- package-ecosystem: "docker"
directories:
- "/build/dashboard"
- "/build/monero"
- "/build/p2pool"
- "/build/tor"
- "/build/xmrig-proxy"
schedule:
interval: "weekly"
groups:
docker:
patterns: ["*"]
ignore:
# Major/minor base bumps (e.g. python 3.11->3.14, ubuntu 24.04->26.04) are deliberate
# migrations, not security updates — keep Dependabot to digest + patch within the pinned tag.
- dependency-name: "*"
update-types: ["version-update:semver-major", "version-update:semver-minor"]
190 changes: 162 additions & 28 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,53 @@ name: CI

on:
push:
branches: [main]
branches: [main, develop]
pull_request:

# Least privilege (#282): every job here only reads the repo — none push commits, comment, or
# publish packages. Narrowing the default GITHUB_TOKEN limits the blast radius of a compromised step.
permissions:
contents: read

jobs:
dashboard:
name: Dashboard tests (pytest + coverage)
runs-on: ubuntu-latest
env:
UV_PYTHON_DOWNLOADS: never # use the setup-python 3.11; don't fetch another interpreter
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
fetch-depth: 0 # full history so diff-cover can diff the PR against origin/develop (#286)
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.11"
- name: Install dashboard with test extras
run: pip install -e "build/dashboard[test]"
- name: Run pytest with coverage gate
working-directory: build/dashboard
run: python -m pytest --cov=mining_dashboard --cov-report=term-missing --cov-fail-under=80
- name: "Install uv (pinned — reproducible, hash-locked installs, #283)"
# Curl the pinned installer (same posture as hadolint below); avoids a mutable-tag action.
run: |
export UV_INSTALL_DIR="$HOME/.local/bin" # deterministic install dir (runners may set CARGO_HOME)
curl -LsSf https://astral.sh/uv/0.10.10/install.sh | sh
echo "$UV_INSTALL_DIR" >> "$GITHUB_PATH"
- name: Dashboard tests + coverage gate (emits coverage.xml)
run: make test-dashboard
- name: "Patch-coverage gate — changed lines >=90% (diff-cover vs origin/develop, #286)"
run: |
git fetch --no-tags origin develop
make test-patch-coverage
- name: Fake-daemon contract test (real clients vs controllable fakes)
# Points the real Monero/Tari clients at the integration fakes and asserts they parse
# every state (synced/syncing/down). Docker-free, so it runs on every PR (issue #54).
run: PYTHONPATH=build/dashboard python -m pytest tests/integration/fakes -q
run: make test-fakes

frontend:
name: Frontend logic tests (node --test)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "20"
# Pure client logic (worker sort, tooltip formatting) lives in static/logic.mjs and is
Expand All @@ -42,7 +61,9 @@ jobs:
name: Dashboard image (Docker test stage)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Build the dashboard test stage (installs package + runs the suite in-container)
run: docker build --target test ./build/dashboard

Expand All @@ -59,38 +80,125 @@ jobs:
matrix:
service: [monero, p2pool, tor, xmrig-proxy, dashboard]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: docker build ./build/${{ matrix.service }}
run: docker build -t "pithead-${{ matrix.service }}:ci" "./build/${{ matrix.service }}"
- name: Scan image for CVEs (Trivy)
# Gate on actionable (fixable) HIGH/CRITICAL only; accepted findings live in .trivyignore.
# Must stay green before v1.1 images publish (#282).
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
image-ref: pithead-${{ matrix.service }}:ci
scanners: vuln
severity: HIGH,CRITICAL
ignore-unfixed: true
exit-code: "1"
trivyignores: .trivyignore

hadolint:
name: Dockerfile lint (hadolint)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install hadolint
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: "Install hadolint (pinned + sha256-verified, #286)"
run: |
sudo curl -fsSL -o /usr/local/bin/hadolint \
curl -fsSL -o /tmp/hadolint \
https://github.com/hadolint/hadolint/releases/download/v2.12.0/hadolint-Linux-x86_64
sudo chmod +x /usr/local/bin/hadolint
echo "56de6d5e5ec427e17b74fa48d51271c7fc0d61244bf5c90e828aab8362d55010 /tmp/hadolint" | sha256sum -c -
sudo install -m 0755 /tmp/hadolint /usr/local/bin/hadolint
- name: Lint all build/* Dockerfiles (config in .hadolint.yaml)
run: hadolint build/*/Dockerfile

python-lint:
name: Python lint + format (ruff)
runs-on: ubuntu-latest
env:
UV_PYTHON_DOWNLOADS: never
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.11"
- name: Install uv (pinned)
run: |
export UV_INSTALL_DIR="$HOME/.local/bin" # deterministic install dir (runners may set CARGO_HOME)
curl -LsSf https://astral.sh/uv/0.10.10/install.sh | sh
echo "$UV_INSTALL_DIR" >> "$GITHUB_PATH"
- name: ruff check + format --check (config in build/dashboard/pyproject.toml + root ruff.toml)
# Single source of truth: the Makefile `lint-py` target, which runs ruff via uv from the
# locked `dev` extra — one pinned ruff for CI, pre-commit, and local devs.
run: make lint-py

gitleaks:
name: Secret scan (gitleaks)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
fetch-depth: 0 # full history so the scan covers every commit, not just the tip
- name: Scan git history for secrets (gitleaks, pinned by digest)
# Run the binary via its pinned image (the gitleaks-action requires a license for org repos).
# Accepted false positives live in .gitleaks.toml.
run: |
docker run --rm -v "$PWD":/repo \
ghcr.io/gitleaks/gitleaks:v8.30.1@sha256:c00b6bd0aeb3071cbcb79009cb16a60dd9e0a7c60e2be9ab65d25e6bc8abbb7f \
git /repo --no-banner --redact --config /repo/.gitleaks.toml

zizmor:
name: Workflow audit (zizmor)
runs-on: ubuntu-latest
env:
UV_PYTHON_DOWNLOADS: never
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.11"
- name: Install uv (pinned)
run: |
export UV_INSTALL_DIR="$HOME/.local/bin"
curl -LsSf https://astral.sh/uv/0.10.10/install.sh | sh
echo "$UV_INSTALL_DIR" >> "$GITHUB_PATH"
- name: Audit workflows (injection, token scope, self-hosted-runner risks)
run: uvx zizmor@1.25.2 --offline .github/workflows/

shell:
name: Shell tests (shellcheck + pithead suite)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# shellcheck is preinstalled on ubuntu-* runners, so we invoke it directly.
# Avoid `apt-get update`, which refreshes every configured source (incl.
# unrelated third-party mirrors like dl.google.com) and intermittently fails
# the job when one is briefly out of sync — see issue #64.
- name: Lint pithead, build/* container scripts, and test scripts
# Single source of truth: the Makefile `lint` target (so the file list can't drift between
# here and `make lint`). Now also covers build/*/*.sh — the entrypoints + healthchecks that
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: "Install shellcheck + shfmt (pinned + sha256-verified, #286)"
# Direct upstream-release downloads with a sha256 check (RigForge convention) instead of the
# runner's preinstalled shellcheck / apt — reproducible, and immune to the apt-mirror
# flakiness of #64. Keep these pins in sync with the local-dev tooling.
run: |
curl -fsSL -o /tmp/shfmt \
https://github.com/mvdan/sh/releases/download/v3.13.1/shfmt_v3.13.1_linux_amd64
echo "fb096c5d1ac6beabbdbaa2874d025badb03ee07929f0c9ff67563ce8c75398b1 /tmp/shfmt" | sha256sum -c -
sudo install -m 0755 /tmp/shfmt /usr/local/bin/shfmt
curl -fsSL -o /tmp/sc.tar.xz \
https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.x86_64.tar.xz
echo "8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198 /tmp/sc.tar.xz" | sha256sum -c -
tar -xJf /tmp/sc.tar.xz -C /tmp
sudo install -m 0755 /tmp/shellcheck-v0.11.0/shellcheck /usr/local/bin/shellcheck
- name: Lint pithead, build/* container scripts, and test scripts (shellcheck + shfmt)
# Single source of truth: the Makefile `lint-sh` target (so the file list can't drift
# between here and the Makefile). Covers build/*/*.sh — the entrypoints + healthchecks that
# run in every container (#124). Gate on warnings+errors; info-level style nits vary by
# shellcheck version.
run: make lint
# shellcheck version. Python lint runs in its own `python-lint` job (ruff isn't on this
# runner; `make lint` runs both for local devs).
run: make lint-sh
- name: Run pithead test suite
run: bash tests/stack/run.sh
- name: Run integration harness self-test
Expand All @@ -107,6 +215,32 @@ jobs:
name: Compose config + security hardening
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Validate docker-compose.yml interpolation + hardening invariants (#90)
run: bash tests/stack/test_compose.sh

lint-surfaces:
name: Lint per-surface (biome, yaml, markdown, proto, toml)
runs-on: ubuntu-latest
env:
UV_PYTHON_DOWNLOADS: never
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "20"
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.11"
- name: Install uv (pinned)
run: |
export UV_INSTALL_DIR="$HOME/.local/bin"
curl -LsSf https://astral.sh/uv/0.10.10/install.sh | sh
echo "$UV_INSTALL_DIR" >> "$GITHUB_PATH"
- name: Lint JS/CSS (Biome), YAML, Markdown, proto (buf), TOML (taplo)
# Single source of truth: the Makefile targets. Tools run via npx/uvx/docker (preinstalled).
run: make lint-js lint-yaml lint-md lint-proto lint-toml
7 changes: 6 additions & 1 deletion .github/workflows/integration-mini-stack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,17 @@ on:
- "build/dashboard/**"
- ".github/workflows/integration-mini-stack.yml"

permissions:
contents: read

jobs:
mini-stack:
name: Fake-daemon mini-stack (docker)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
# ubuntu-latest ships Docker with the Compose v2 plugin — no setup needed.
- name: Run the fake-daemon mini-stack
run: bash tests/integration/mini-stack/run-mini-stack.sh
Expand Down
27 changes: 27 additions & 0 deletions .github/workflows/lychee.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Link check (lychee)

# Scheduled (not per-PR) so flaky external links never redden a PR (#281). The run goes red in the
# Actions tab if a link breaks; trigger on demand with workflow_dispatch. Ignored URLs: .lycheeignore.
on:
schedule:
- cron: "0 6 * * 1" # Mondays 06:00 UTC
workflow_dispatch:

permissions:
contents: read

jobs:
lychee:
name: Check Markdown links
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Check links in Markdown
uses: lycheeverse/lychee-action@8646ba30535128ac92d33dfc9133794bfdd9b411 # v2.8.0
with:
args: "--no-progress './**/*.md'"
fail: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # higher github.com rate limit for repo links
Loading