The previous commit on this branch copied cuprated's raw
--generate-config defaults (stdout=info, file=debug, max_log_files=7)
verbatim. Turns out that's the wrong reference: compared against
ssmithx@archy-dev-pa:/home/ssmithx/cuprate/Cuprated.toml — the actual
dev config this app was built and tested against — file logging is
meant to run at "info" with 14 rotated files, not the binary's raw
"debug"/7. Confirmed live on amishparadise: podman logs (stdout) was
already clean at info, but the on-disk file log
(.local/share/cuprate/logs/<date>) was flooding with per-peer DEBUG
gossip (~400KB in 2 minutes) because it inherited the binary default
instead of the intended one.
Left the resource-tuning knobs in the reference config (8GB
target_max_memory, tokio/rayon thread counts, P2P connection counts,
explicit reader_threads) out of this file — those were sized for
ssmithx's dev box and don't apply here; this manifest's
target_max_memory already stays deliberately under the container's
4Gi memory_limit.
Regenerated releases/app-catalog.json (still unsigned).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ga6N8Jk1YdCTMMX1LjDpAr
apps/cuprate/manifest.yml only ever wrote network/target_max_memory/
rpc.restricted.enable into Cuprated.toml, so the [tracing.stdout] and
[tracing.file] tables were silently absent — cuprated still applied
its built-in info/debug/7 defaults, but nothing on disk showed it.
Verified live on amishparadise 2026-09-01: the deployed 5-line file
had no [tracing] section at all, and the level was only discoverable
by running `cuprated --generate-config` and diffing.
Add both tables to the manifest's files[].content with the same
values cuprated already defaults to, so every new install ships a
Cuprated.toml an operator can actually read and tune. overwrite:false
means already-deployed nodes (amishparadise included) keep their
existing file untouched — this only changes what fresh installs get.
Regenerated releases/app-catalog.json (unsigned) to embed the updated
manifest; needs scripts/sign-catalog.sh before it's authoritative for
the fleet.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ga6N8Jk1YdCTMMX1LjDpAr
Flags the app update policy already noted as unresolved in
app-developer-guide.md, adds a section for SSH access strategy, and
starts an app wishlist (Cashu wallet, phoenixd) for packaging.
The federation fallback in the plain content-inline path wasn't enough —
mesh.transport-advice recommended the "resource-mesh" tier purely from our
own device being Reticulum-capable, without checking that THIS peer
actually has a radio route. For a federation-only contact (no radio twin)
that steered the frontend into send-content-inline's Reticulum
resource-transfer path, which has no dest_prefix to send to and fails with
"Peer is federation-only (no radio twin)" — reproduced after deploying the
first fix on a live node.
Adds MeshService::has_radio_route(contact_id), and gates both the
"resource-mesh" tier in mesh.transport-advice and the resource-transfer
branch in mesh.send-content-inline on it. Federation-only peers now fall
through to the has_tor branches, which route the frontend to
mesh.send-content (already correctly federation-aware) instead.
Landed from PR #133 (re-committed to drop private host details from the
original message; content identical).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
mesh.send-content-inline always called send_typed_wire (the LoRa/radio
path), which fails with "Peer is federation-only (no radio twin)" for
any contact reachable only via Tor federation — reproduced sending a
picture from the companion app to a federation-only peer. mesh.send-content
already resolves the peer's federation onion and falls back to
send_typed_wire_via_federation; mirror that same lookup here.
Landed from PR #133 (re-committed to drop private host details from the
original message; content identical).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Full-node daemon: P2P + Monero's own restricted RPC (the safe-for-public
subset wallets use as a "remote node") are auth:none like bitcoin/electrumx's
equivalents; unrestricted RPC (full node control) stays gated auth:local.
readonly_root works cleanly since the upstream image is FROM scratch with
ownership fixed at build time — no runtime chown/setuid needed, unlike
bitcoin-knots/core.
Verified locally end-to-end before committing: built the upstream Dockerfile,
confirmed the generated Cuprated.toml against `cuprated --generate-config`/
`--dry-run`, and ran the real image with the manifest's exact ports/volumes —
including discovering that cuprated's own 127.0.0.1-default RPC bind is
unreachable through a published host port and needs to bind 0.0.0.0
internally with ports[].bind:127.0.0.1 doing the actual restriction, the
same pattern bitcoin-knots' RPC port already uses in this repo.
Bumps the unauthenticated_ports_are_all_accounted_for canary (26 -> 28) for
cuprate's two auth:none ports, per that test's own review-before-updating
contract.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>