release: v1.14.0#764
Merged
Merged
Conversation
back-merge: main → develop after v1.13.0
The ratified architecture decision record for shipping Pithead through three channels from one release manifest: curl-installed Compose stack, flashable immutable appliance (Debian 13 + Rugix A/B, Podman Quadlet), and git clone. Records the rejected alternatives (bootc, Podman everywhere, apt channel) with evidence, the appliance mechanics (commit gate, migration-deadlock rule, Tor-routed updates, two-tier reset), the phase 0 go/no-go gates, and the risk register. Dev doc only — no behaviour change. Sequencing lives in #394. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add `tari.mode: remote`, mirroring the existing Monero remote-node mode, so operators can merge-mine against an external Tari base node instead of the bundled container — offloading Tari's RAM and ~170 GiB of disk, and letting one node serve several stacks (each with its own wallet; the mining-template gRPC is request-scoped). - config: `tari.remote.host` (required in remote mode) + `tari.remote.grpc_port` (default 18142); `tari.mode` gets an explicit local/remote validation. - render: pithead renders TARI_GRPC_ADDRESS for both modes; `local_tari` compose profile gates the bundled tari container (mirrors monerod's `local_node`). Remote mode skips the Tari mem-limit calc, refuses tari.view_key (payout confirmation is local-only), and drops the Tari/Monero disk budget from doctor/preflight (was demanding the full chain budget on the small-disk hosts remote mode exists for — the Monero side was a pre-existing sibling bug). - compose: p2pool `--merge-mine`, the dashboard, and the (profile-gated) payout wallet all read TARI_GRPC_ADDRESS; p2pool's depends_on is dropped since both nodes can be profiled off in remote mode. - security: charset-guard monero.remote.host / tari.remote.host (and their ports) with the existing is_valid_host/is_valid_port — a comma in the host would otherwise inject socat address options in the p2pool bridge command. The central control-char guard already covered newline .env-injection. - docs: "Remote Tari node" section + trust boundary (plaintext, unauthenticated gRPC — use a trusted/LAN/WireGuard node; a malicious node can redirect Tari rewards, Monero mining unaffected); privacy.md clearnet-egress + DNS notes. Tier-1 coverage in tests/stack/ for render, profile gating, disk budget, the validation guards, and compose resolution with local_tari omitted. Live different-machine e2e folds into the release e2e per the feasibility verdict. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… node values
Follow-up hardening + wiring cleanup on the remote-node path, from an
injection-surface audit of the whole config→sink chain.
- assert_safe_dir: reject ':' in a data dir. It renders unquoted into the
compose bind-mount short syntax (${MONERO_DATA_DIR}:/dest), so a dir ending
':ro' forged a third MODE field — flipping a data mount read-only or breaking
`compose up`. Operator-set but, since #728, also dashboard-committable.
- tari.wallet_address: reject the untouched placeholder and any embedded
whitespace — both cause the silent mine-to-nowhere that monero.wallet_address
already guards against (#250). No exact-format gate: Tari addresses come in
base58 AND emoji forms (RFC-0155), so a strict regex would false-reject valid
addresses; the node rejects a subtler typo at merge-mine time.
- render_env: reuse the parse-time validated remote host/port globals
(MONERO_REMOTE_*, TARI_REMOTE_*) instead of re-reading them from config.json.
Removes six duplicate jq reads and the drift risk of validating one value and
rendering another — the validated value is now the rendered value.
Tier-1 tests for all three. The .env newline-injection vector an earlier review
raised was already closed by the central control-char guard, so no change there.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Internal GitHub #NNN references carry no meaning for an operator reading a warning, an error, the apply preview, or the dashboard — they read as noise. Remove them from user-facing product strings while keeping the explanatory prose intact. Comments and test labels keep their #NNN (developer-facing). - pithead: strip #NNN from log/warn/error/info/echo messages, the --help command descriptions, and describe_change's msg= apply-preview text (which the #33 control channel also renders in the dashboard config editor). Grammar preserved; load-bearing words kept (e.g. "removed in v1.9" stays, only the "#506," goes). Also dropped a stale "v1.6" reference while there. - dashboard: chart.mjs "Avg:" control tooltip. - Regression guard: scripts/lint-operator-strings.sh (wired into `make lint` and CI) fails if a #NNN reaches a pithead message or a dashboard frontend string; it exempts comments and CSS hex colours. Documented in CONTRIBUTING.md. Telegram, webhook, and ntfy message bodies were already clean (issue refs there live only in docstrings). No behaviour change. Stack suite 1622/0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The guard's frontend scanner is non-trivial awk (comment-stripping + CSS hex-colour skip); a silent regression would make it stop catching leaks while still exiting 0. Extract the two scanners into functions and add a `--self-test` mode that drives fixtures through them — planted #NNN must be flagged, hex colours and comments must not. Wired into the stack suite (make test-stack/CI). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…up guard Follow-ups from the PR review pass: - Clear MONERO_REMOTE_*/TARI_REMOTE_* to empty before the mode branch, so the "globals reflect only the current config" invariant holds even if a caller ever parses twice in one process (each real apply is a fresh process, so this is defensive, not a live bug). - Rename TARI_REMOTE_PORT -> TARI_REMOTE_GRPC_PORT to match the config key (tari.remote.grpc_port) and Monero's MONERO_REMOTE_*_PORT convention. - Drop the redundant tari.wallet_address placeholder check — the shared template-placeholder guard right below already covers it; keep only the unique whitespace check. Test updated to assert the shared message. - Scrub the three new operator-facing (#103) strings (the view-key error and the two node-switch preview messages) so they conform to the operator-strings convention #755 enforces, avoiding a straggler once both land. Stack suite 1652/0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…mote-tari feat(tari): remote Tari base-node mode (#103)
…crub-issue-numbers # Conflicts: # pithead
…rub-issue-numbers chore: scrub internal issue/PR numbers from operator-facing text (#755)
The help line dated from when 'git pull' was the only update path; upgrade is also what the extracted release bundle and the dashboard's one-click upgrade run. Say so, and name the re-render step it performs first. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
docs(cli): upgrade help text covers the bundle path
…r, testing plan Three additions to the dual-distribution ADR from the runtime-independence review: - A "Runtime port surface" section: the three engine-neutral contracts (OCI images by digest, four container-API endpoints behind the proxy allowlists, config.json as the only path to runtime files), the four-item engine-specific residue, and the review rule that a PR growing the surface updates the section. - Phase 2: doctor grows engine-aware host checks — its Docker-shaped trio (daemon reachable, docker group, boot persistence) misreports under Podman/systemd, and doctor --json is the appliance commit gate. - A testing plan mapped onto the existing four-tier model: the parity test's derivation mechanics and closed-set lock at tier 1, a Podman lane for the tier-3 mini-stack, the appliance tier-4 matrix additions, and the installer smoke on the release checklist. - One-line manifest note: image ownership is per-service (the Tari node already pins from a foreign registry). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ort-surface docs(dev): plan amendments — runtime port surface, engine-aware doctor, testing plan
#103) With monero.mode or tari.mode set to remote the bundled node container never starts, but torrc still defined its inbound hidden service — so Tor published an onion address that accepted connections into nothing. Each node's HiddenService block moves out of the template and into the tor entrypoint, appended only when that node's compose profile is active. The gate is the profile list itself, passed through to the tor container from pithead's rendered .env, so it cannot drift from which nodes actually run. P2Pool's onion stays unconditional — p2pool always runs. pithead follows suit: provision_tor waits only for the onions that will exist, doctor reports a remote node's missing address as expected rather than a warning, and the "fully provisioned" guard keys off P2Pool's onion instead of Monero's. A stack first set up in remote mode has no address for that node, so provision_node_onions mints and captures it on the apply/upgrade that makes the node local — before the node container starts against it, since monerod templates anonymous-inbound from that value. Covered at tier 1 (torrc gating, provisioning by mode, doctor's report), tier 2 (the profile list reaches the tor service), and tier 3 (the live torrc matches the node mode). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…okup Ponytail review: same behaviour, half the lines. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Both callers take the default; speculative flexibility, cut on the ponytail pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…akhani-1b6564 fix(tor): publish a node's inbound onion only while that node is local (#103)
…_lan_access (#760) The serving side of the remote-node modes. monero.rpc_lan_access existed but published only the RPC — a remote P2Pool needs the ZMQ feed too, and the Tari base node published nothing at all, so serving another stack meant hand-run socat forwards (what the #78 bench setup did on gouda). - monero.zmq_lan_access: publishes monerod's ZMQ (18083); a separate key from rpc_lan_access on purpose — that key's documented use is wallets, and widening it would change existing deployments' exposure. - tari.grpc_lan_access: publishes the bundled Tari base node's gRPC (18142); loopback by default, matching the console-wallet publish's trust boundary. Ignored in remote mode (the service is profiled off). - Both flips to 0.0.0.0 are DEST in describe_change (host-only, like MONERO_RPC_BIND), with the no-auth trust warning in the message. - Docs: config rows + the remote-node sections now name the serving-side switches; CHANGELOG entry. - Tier 1: describe_change direction tests + the #523 black-box render extended for all three binds (default localhost, true → 0.0.0.0). Closes #760. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lan-access feat(config): node LAN exposure switches — monero.zmq_lan_access + tari.grpc_lan_access
VERSION + dashboard package version in lockstep, uv.lock regenerated, CHANGELOG Unreleased rolled to [1.14.0]. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
chore(release): prepare v1.14.0
…#760) The e2e caught this on the bench: monerod's 18083 and the Tari node's 18142 are published from this release, loopback unless the LAN switch is on, so anything already holding either port stops the upgrade at 'docker compose up'. Say so in the CHANGELOG upgrade note and beside both config keys. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sh-note docs(config): note that the node feeds publish a host port either way (#760)
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.
Release merge for v1.14.0 — published at v1.14.0, tag commit
4285d37(= develop HEAD; nothing landed after the cut, so this is a straight develop→main merge).Real merge, never squash — main must stay an ancestor of develop.
In this release
tari.mode: remotemerge-mines against a Tari base node running elsewhere.monero.zmq_lan_access+tari.grpc_lan_access, the serving side of the remote-node modes.upgradehelp text describes the bundle path too (docs(cli): upgrade help text covers the bundle path #757), and config validation rejects adata_dirwith:and a Tari wallet address with whitespace.Pre-cut verification
make testplus the live readiness matrix, both green on the release box.Ponytail review: release merge of already-reviewed commits, no new code — nothing to cut.
🤖 Generated with Claude Code