Skip to content

v0.6.0: Workflow B and offline keys, QR transfer, and the scratch-test fixes - #21

Merged
abhijitkrm merged 9 commits into
mainfrom
feat/workflow-b-offline
Oct 13, 2026
Merged

abhijitkrm merged 9 commits into
mainfrom
feat/workflow-b-offline

Conversation

@abhijitkrm

@abhijitkrm abhijitkrm commented Oct 12, 2026 •

Copy link
Copy Markdown
Owner

Everything for v0.6.0: Workflow B, offline keys, QR transfer, and the fixes from a full scratch test on four wiped hosts. The report is at docs/reports/v0.6.0-scratch-test.md.

Workflow B and offline keys

  • genesis join, base, gentx, collect and install launch a network with validators the coordinator can't reach.
    • Keys and gentxs are made in containers with no network, and mnemonics go to 0600 files on the key machine.
    • Every hand-off file is checksummed, and every gentx is checked against the kit.
  • host prepare --offline_ready (with --save_image / --image_tar) readies a machine for offline keys. join and gentx refuse a connected machine unless --allow-online.
  • qr show / qr read move join and gentx files off an offline machine as QR codes, in any order, verified by checksum. Files with key material are refused.
  • network remove wipes a test network, but only homes whose genesis is for that chain.

Scratch test (4 hosts wiped to bare OS, rebuilt with cometcli only)

area result
Bare-host setup, image builds, genesis with 2 validators, 3rd validator joining, archive node ✓
Governance (text and params), governed upgrade v0.7.2 → v0.7.3 ✓
Jail and unjail, stop/revive, all nodes down at once ✓
Config, memory, docker, port, network, image incidents; replaying through a past upgrade ✓, fixed locally
Prompts answered without a model 93%

13 findings, all fixed here:

  • upgrade build naming and repo on fresh and running hosts.
  • Added upgrade handlers are recorded per tag and reused, so a rebuild is the same binary.
  • upgrade switch picks its image itself; upgrade proposals get a default title and summary.
  • val operator-key for validators joining after genesis.
  • While a node is down, chain queries go to another node of the same chain.
  • Triage fixes for low memory limits, missing containers or images, and replaying through a past upgrade.
  • Critical: shell and file guards now refuse deleting *.db, upgrade-info.json and cs.wal, and --unsafe-skip-upgrades anywhere. With bash allowed, a model run destroyed an archive's state.

🤖 Generated with Claude Code

abhijitkrm and others added 3 commits October 12, 2026 14:54
A launch where other organisations run validators: they make keys on
their own machines, ideally offline, and only public, checksummed files
change hands.

- genesis join (validator): node, consensus and operator keys made in a
  container with --network none; a new mnemonic goes to a 0600 file on
  that machine, never to the screen; --recover-from a mnemonic file
  there; writes <moniker>.join.json (account, node id, consensus pubkey)
- genesis base (coordinator): base genesis funding every joined
  validator and your --own ones (keys made on their hosts), written as a
  kit: base genesis, spec, kit.json, README, SHA256SUMS
- genesis gentx (validator): verifies the kit, checks the home is the
  node the kit lists, signs offline with the peer address in the memo
- genesis collect (coordinator): checks every gentx against the kit
  (same kit, validator in it, agreed stake, funded account, consensus
  key from the join, node id, signed), signs your own on their hosts,
  collect + strict validate, one package per validator with every peer,
  installs and starts your own
- genesis install (validator): verifies the package, installs the final
  genesis, renders configs and starts the node
- offline: join and gentx refuse a connected machine (default route or a
  connected interface; docker bridges don't count) unless --allow-online,
  which is recorded in the files; host prepare --offline_ready loads and
  checks the image with no network, --save_image/--image_tar carry it over
- network remove: stops a network's nodes and deletes their homes, only
  where the home's genesis is that chain's; builder files and profiles
  too; reports free disk
- a failed join removes the home it made, so it can be rerun

Tested live on the four SSH hosts as primium-3 beside primium-2: offline
gate, key recovery, tampered kit and edited gentx refused, launch with
two outside and two own validators, network check PASS, stop/revive of
one validator with catch-up, then everything removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…odes

cometcli qr show <file> compresses the file and shows it as a few QR
codes (one per Enter, or --png images to show full screen); cometcli qr
read on a connected machine takes the scanned text or photos of the
codes, in any order, and writes the file only when every part is in and
it matches the checksum each part carries. Parts of another file,
damaged parts and repeats are handled; files with key material are
refused, so only public files leave this way. Codes fit an 80-column
terminal and use medium error correction for photos of a screen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bare hosts rebuilt with cometcli only: host prepare, image builds, a new
chain from genesis, a validator joining later, an archive node,
governance, a governed upgrade, jailing, outages and docker incidents.
Report: docs/reports/v0.6.0-scratch-test.md.

- upgrade build on a fresh host takes the image naming and repo from the
  network spec; on a running node too (it named primium-v0.7.2:v0.7.3)
- a consensus-breaking release always asks only where a node runs
- added upgrade handlers are recorded per tag in the network spec and
  reused, so a rebuild (lost image, new node) is the same binary
- upgrade switch picks the image whose binary registers the halted plan,
  preferring the spec's naming; upgrade proposals default title/summary
- val operator-key: a joining validator's key in its node's keyring, the
  mnemonic in a 0600 file on that host, the profile set to sign there
- chain queries fall back to another node of the same chain while a node
  is down (jail status, upgrade plans)
- triage: a memory limit under 1 GB is the root on its own; a missing
  container's image is read from its compose file; image-missing explains
  container-missing; playbooks recreate from the compose file and
  node.recreate works without a container; a node replaying through a
  past upgrade switches to the image built for it
- shell and file guards refuse deleting *.db stores, cs.wal,
  upgrade-info.json and wasm/ in a node's data, and --unsafe-skip-upgrades
  anywhere — a model with bash allowed did the first two on the archive
- network remove handles root-owned files (passwordless sudo)
- fleet status shows profiles not set up yet; short fact output of
  playbook steps is shown (who holds a port); model rounds audit tokens

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@abhijitkrm abhijitkrm changed the title Genesis with validators you don't run (Workflow B), and offline keys v0.6.0: Workflow B and offline keys, QR transfer, and the scratch-test fixes Oct 12, 2026
abhijitkrm and others added 6 commits October 12, 2026 22:45
Container names default to <chain id>-<role> instead of a fixed
primium-validator, so two chains on one host never collide. upgrade build
looks for any Dockerfile beside the node's compose project instead of
searching the home dir for Dockerfile.primium, writes its built-in one as
Dockerfile.evmd, and drops the name=primium image label. The env importer
reads HOST_HOME or any <NAME>_HOST_HOME. Help text, docs and examples use
generic names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
val edit and val create send commission as the scaled integer on every SDK
version: cosmos.Dec tx fields are gogoproto LegacyDec on v0.54 too, and a
plain 0.06 failed live with "cannot unmarshal into a *big.Int". val edit
says when the chain's one-change-per-24h rule allows the next change.

A node with no new block for 30s reads the consensus state: who has voted
at this height, and with how much power. Under 2/3 is a new case,
chain-halted-validators-offline, naming the absent validators by moniker
and their share; the fleet's CHAIN HALT line says the same instead of
guessing at an upgrade or consensus failure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s image

network check warns when an archive or RPC node turns pex off or takes no
inbound peers, and provision renders pex on for them (and CometBFT's 40
inbound when it was 0). provision --reconfigure keeps the image the node
runs instead of the spec's genesis tag: after a governed upgrade that
would have started it on the old binary. /incident's evidence is what
triage saw, not what still matches after the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The shell guard refuses, in every mode, copying a node's whole config or
data dir (from one, or recursively into one) and unpacking an archive
into a node's home: both move a consensus key or signing state without
its file name. A single file such as genesis.json into config/ is fine.

sec doublesign reads a docker node's container state (it asked systemd
and said "unknown"), checks the signing state against the node's height,
and reports double_sign_check_height. Node homes get owner-only config
and data dirs at init and on reconfigure, as sec perms expects.

upgrade build never replaces the handler recorded for a tag: a build
with another handler needs its own image name and isn't recorded, so a
later rebuild still reproduces the binary the chain ran.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…self

gov propose --kind cancel-upgrade cancels the plan on chain: refused when
none is scheduled or when the vote can't pass before its height (with the
expedited period as the way out), and the approval names the plan it
cancels. upgrade ready defaults to the scheduled plan and the local image
whose binary registers it, and says "not ready — build it" when there is
none, as upgrade switch already picked its image.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e-sign, Workflow B)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@abhijitkrm
abhijitkrm merged commit 5cd13d0 into main Oct 13, 2026
2 checks passed
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