Skip to content

Release v0.27.0 - #86

Merged
jdogresorg merged 48 commits into
masterfrom
release/v0.27.0
Nov 1, 2026
Merged

jdogresorg merged 48 commits into
masterfrom
release/v0.27.0

Conversation

@jdogresorg

Copy link
Copy Markdown
Contributor

What this release carries

Added

  • Added coordinated hub checkpoint reset, and reset can now run on a named MariaDB container without the hub push.

Changed

  • Reset can use a root password variable or the stack's own database logins, and moved service ports are now persisted.

Fixed

  • Lifecycle commands now exit non-zero when the in-container command fails or matches nothing, and read-only commands no longer install or restart the hub.
  • A hub answer carrying an error now counts as a failed config push, and the push is capped at three minutes.
  • A failed reset database step is reported with the services left down, and the command lock file is published whole.
  • Autoheal now restarts only running containers, backs off repeated restarts, and keeps going when a container vanishes mid-pass.
  • The bootstrap health gate now ignores halts an operator has cleared and counts a sync halt held only in sync state.
  • Module, explorer and config sidecar handling and the command lock were corrected, and status reports more accurately.

Testnet activation

  • ARCHIVE_ROLLCALL_PRESENCE_ACTIVATION.BTC:testnet on BTC:testnet at height 158396
  • ARCHIVE_ROLLCALL_PRESENCE_ACTIVATION.LTC:testnet on LTC:testnet at height 4946814
  • ARCHIVE_ROLLCALL_PRESENCE_ACTIVATION.DOGE:testnet on DOGE:testnet at height 68033131
  • CHECKPOINT_SUPERSEDE_ACTIVATION.BTC:testnet on BTC:testnet at height 158396
  • CHECKPOINT_SUPERSEDE_ACTIVATION.LTC:testnet on LTC:testnet at height 4946814
  • CHECKPOINT_SUPERSEDE_ACTIVATION.DOGE:testnet on DOGE:testnet at height 68033131
  • ADMIT_CHAIN_MARGIN_ACTIVATION.LTC:testnet on LTC:testnet at height 4946814
  • MATCH_EQUAL_PRICE_OLDEST_FIRST.BTC:testnet on BTC:testnet at height 158396
  • MATCH_EQUAL_PRICE_OLDEST_FIRST.LTC:testnet on LTC:testnet at height 4946814
  • MATCH_EQUAL_PRICE_OLDEST_FIRST.DOGE:testnet on DOGE:testnet at height 68033131
  • DIVIDEND_EMPTY_ALLOW_LIST_DENIES_ACTIVATION.BTC:testnet on BTC:testnet at height 158396
  • DIVIDEND_EMPTY_ALLOW_LIST_DENIES_ACTIVATION.LTC:testnet on LTC:testnet at height 4946814
  • DIVIDEND_EMPTY_ALLOW_LIST_DENIES_ACTIVATION.DOGE:testnet on DOGE:testnet at height 68033131
  • AIRDROP_ZERO_LEGS_OMITTED_ACTIVATION.BTC:testnet on BTC:testnet at height 158396
  • AIRDROP_ZERO_LEGS_OMITTED_ACTIVATION.LTC:testnet on LTC:testnet at height 4946814
  • AIRDROP_ZERO_LEGS_OMITTED_ACTIVATION.DOGE:testnet on DOGE:testnet at height 68033131
  • TICK_NORMALIZE_ACTIVATION.BTC:testnet on BTC:testnet at height 158396
  • TICK_NORMALIZE_ACTIVATION.LTC:testnet on LTC:testnet at height 4946814
  • TICK_NORMALIZE_ACTIVATION.DOGE:testnet on DOGE:testnet at height 68033131
  • SAME_TOKEN_OFFER_REFUSAL_ACTIVATION.BTC:testnet on BTC:testnet at height 158396
  • SAME_TOKEN_OFFER_REFUSAL_ACTIVATION.LTC:testnet on LTC:testnet at height 4946814
  • SAME_TOKEN_OFFER_REFUSAL_ACTIVATION.DOGE:testnet on DOGE:testnet at height 68033131

Release v0.27.0

Base: master at f6c3c4142e40d87c46aacf87ddceb1ed62485bb2
Head: release/v0.27.0 at b5f283b21e6612ab80d74c29e11128fe65a597be

Landed refs

  • b5f283b Release v0.27.0
  • 7c5860d Merge develop into release/v0.27.0
  • 7cea7af fix: land verified review-round fixes
  • ed0e4c9 fix: land verified review-round fixes
  • 6cf273f Merge develop into release/v0.27.0
  • bcb9b14 fix: land verified review-round fixes
  • e701585 Merge develop into release/v0.27.0
  • 65bead2 fix: land verified review-round fixes
  • 27e7f9b Merge develop into release/v0.27.0
  • c0dd550 fix: land verified review-round fixes
  • 87494ed Expect named refusals in the regression, fuzz and e2e suites
  • 7ce159c Note the lifecycle exit and explorer scope fixes in the changelog
  • 8c3fe10 Fail lifecycle commands that match nothing and keep the explorer out of a one-chain stop
  • 20ab027 fix(exec): exit non-zero when the in-container command fails or matches nothing
  • b9a387d fix(precheck): keep read-only commands from installing or restarting the hub
  • f3bf037 fix(hub-push): treat a hub answer carrying an error as a failed config push
  • 9f16136 fix(hub-push): cap the hub config push at three minutes of wall time
  • 8fa8bdf fix(cli): reject an unknown chain or network before building the service list
  • 28f1362 fix(autoheal): stamp a restart when it finishes, not at pass start
  • 83b0402 fix(reset): report a failed database step and name the services left down
  • d45c2ec fix(cli): name an unknown chain or network in clear-reorg-halt
  • dcae229 fix(command-lock): publish the lock file complete so a live creator's lock is never reclaimed
  • c551b5c Merge: Keep bootstrap capture logs on work volume
  • 8bee1f5 Keep bootstrap capture logs on work volume
  • bd3b91f Read service database logins from container config so a stopped stack can be reset
  • 6579f14 Let a named-container reset run as the stack's own database users when no root logs in
  • 2dc1701 Let a named-container reset take its root from XCHAIN_NODE_DB_CONTAINER_ROOT_PASSWORD and add --check
  • 13b923d Let reset run its database steps on a named MariaDB container without the hub push
  • 974cb41 Merge: Keep checkpoint reset within structure boundaries
  • c01a625 Keep checkpoint reset within structure boundaries
  • 6521e25 Add coordinated hub checkpoint reset
  • ff8515c Move the workflow Node pin to 22.23.4
  • 1092916 Merge: Persist automatically moved service ports
  • 33ea04d Persist automatically moved service ports
  • a87e151 Honour a forced bootstrap on an installed module, wait out a cold MariaDB, and move a second install off busy host ports
  • 3d78754 Override zod to the patched release and refresh body-parser
  • c933f6e Wait for a recreated hub to open its API before giving up the config push
  • f955b59 Merge master (v0.26.3 release) back into develop
  • 09f5fd5 Merge: Split nightly workflow contract checks
  • 84f201e Split nightly workflow contract checks
  • eec8cbf sync trunk
  • ddd8d66 Defer regtest validator seeding until stack readiness
  • 850fc0f Record the v0.23.3 maintenance release in the changelog
  • 7344a8b Merge master (v0.26.2 release) back into develop
  • 3db1372 Merge master (v0.26.1 release) back into develop

Recreate the shared hub after both bridge rails are installed so its first seeded capability snapshot cannot precede the bitcoin rail. Cover the gate, ordering, exported environment, and recreate invocation in the workflow contract.
Extract workflow environment runners and group validator assertions into focused registration helpers so each test function remains within the structure limit.
…push

A recreated hub takes 40 to 60 s to open its API, while the post-deploy
config push gave up after about 27 s, so every hub update reported failure
and the pushed config never applied. The push now tries for three minutes,
and a push that succeeds on its final attempt is no longer reported as a
failure.
zod below 4.6.6 (GHSA-mrhx-c7xc-m3w5) and body-parser 2.3.0 (GHSA-27r3-jxmh-p828) failed the production audit at high. zod is overridden to ^4.6.6 (resolves 4.6.7) and body-parser moves to 2.4.0 within express's range, so npm audit --omit=dev --audit-level=high passes.
…iaDB, and move a second install off busy host ports

install returned early for any installed module, so the printed remedy 're-run install with XCHAIN_NODE_FORCE_BOOTSTRAP=1' did nothing; an installed utxo-tracker, decoder or indexer now reinstalls and takes the restore again, stopping the running container gracefully, while other modules still return. The MariaDB readiness probe looks the container up on every attempt, and a fresh datadir waits up to 5 min for its first root login before anything else touches it. A second install whose default on-request host port is already published now takes the same port 100 higher (3001 to 3101) instead of stopping on a conflict; the hub and explorer ports still refuse. Unit tests cover each.
Record auto-selected host ports in the per-network sidecar so later config reads and hub updates use the published port. Refuse conflicts for operator-selected ports from either config file and exercise the installed production wrapper.
The consensus runtime re-pins to Node 22.23.4 (V8 12.4.254.21-node.57, ICU 78.3), so CI jobs that load the VM must run that build.
Discover Docker rail stacks, stop hub and mirror services before mutation, recreate checkpoint-owned hub tables, purge local mirrors, and restart cleanly. Add command-level coverage for ordering, stop refusal, and table scope.
Run the coordinated repair from the CLI recovery surface and rebuild tables through schema-only database dumps. Restore the reset operations module to its prior size and keep the command tests focused on database tool calls.
Create publisher output captures under the configured temporary directory so restricted host temp locations do not erase source-health diagnostics. Exercise the refusal path with an unavailable host TMPDIR.
… lock is never reclaimed

Creating the lock with an exclusive open followed by a write left a window where the file existed empty, and a contender treated that empty file as a crashed creator's lock and reclaimed it, letting two mutating commands run at once. The lock payload is now written to a private temp file and hard-linked into place, so the lock path only ever appears with its full contents.
A mistyped chain or network fell through to the decoder container lookup, so clear-reorg-halt reported that no decoder container was installed instead of saying the value was unknown. The command now checks both against the known coins and networks first and exits with a message naming the bad value and the accepted ones.
…down

When the database wipe failed after the services were stopped, the rejection escaped the reset, skipped the restart pass and left the indexer silently stopped with no message. The database step failure is now caught and reported like any other started wipe, naming what was already cleared and every stopped service left down for a re-run.
Autoheal recorded each restart with the clock taken when the pass began, so the restart cooldown and the recovery probation both started before the container was stopped, up to the full stop budget early and earlier still for later containers in the same pass. The stamp now advances the pass clock by the real time the restart consumed, so both windows run from the finished restart.
…ice list

A typo in the chain or network of a command such as stop all still produced the shared explorer entry, so the command stopped the explorer, matched no chain container and exited 0. Unknown chains and networks are now rejected up front with an error naming the bad value, before any service is touched.
A paused or hung hub accepts the connection and never answers, so each of the 60 push attempts waited out the 60 s connector timeout and a mutating command held the command lock for about an hour. The retry loop now also stops once three minutes of wall time have passed, whatever each attempt costs.
…g push

The hub reports a refused config push, such as a PBFT "Not the leader" refusal, as a normal JSON-RPC result holding an error field, and the connector read any non-null result as delivered, so the lifecycle command exited 0 with the config never applied. The connector now returns false for such a result and records the hub's error text, so the retry loop retries and finally surfaces the real cause.
…the hub

The precheck ran the hub install for every command, and that install restarts a hub whose state is exited, so a read-only ps started a hub the operator had stopped and then printed its stale exited status. The hub install now runs only for state-changing commands, so ps, tail, logs and monitor leave every container's run state as they found it.
…es nothing

exec printed the raw error object when the command failed inside a container and exited 0, and it also exited 0 when the selection matched no installed service, so scripts chaining on exec carried on after a failure. It now prints the command output, exit code and stderr as a short reason and exits 1 when any run fails or nothing matched.
…of a one-chain stop

start, stop and restart now exit 1 with the unmatched service, chain and
network when a selection matches no installed container, as exec already
does; an "all" selection with some services not installed still succeeds.
An unknown chain or network fails inside the same exit path.

start, stop, restart and uninstall leave the shared explorer out of an
"all" selection scoped to one chain, since that explorer serves every
chain; with no chain named they still include it. install, update and
recreate keep including it so a per-chain install still gets an explorer.
Lifecycle commands now fail when nothing selected is installed, and an
unknown chain or network is refused by name. Three suites outside the
unit run still asserted the old silent success: the precheck regression
case, the filterCommandParameters fuzz cases and the empty-registry e2e
scenarios. They now assert the named error and that no container is
touched; an empty chain or network still means all.
Applies the adversarially verified fixes from the 2026-10-30 review
round for this repo (21 files).
Applies the adversarially verified fixes from the 2026-10-31 review
round for this repo (31 files).
Applies the adversarially verified fixes from the 2026-10-31 review
round for this repo (3 files).
Applies the adversarially verified fixes from the 2026-10-31 review
round for this repo (5 files).
Applies the adversarially verified fixes from the 2026-10-31 review
round for this repo (7 files).
@jdogresorg
jdogresorg merged commit 8bc677a into master Nov 1, 2026
9 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