Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
b6c483e
fix(node): roll-call wiring refusal names the public explorer read wi…
jdogresorg Sep 23, 2026
a6f188a
Write fresh sidecar credentials under safe secret names
jdogresorg Sep 24, 2026
068874c
Publish the hub peer port in validator mode
jdogresorg Sep 24, 2026
9d6acdc
Split preferred sidecar tests into named groups
jdogresorg Sep 24, 2026
de0d189
Enforce c8 --all coverage and re-baseline floors to measured values
jdogresorg Sep 24, 2026
6522857
Merge origin/master (v0.20.1 release) into develop
jdogresorg Sep 24, 2026
ec0a008
test information schema SQL builders
jdogresorg Sep 24, 2026
a091e9f
Merge: test information schema SQL builders
jdogresorg Sep 24, 2026
b29acdb
Test price fence SQL builders
jdogresorg Sep 24, 2026
d14f0a7
Merge: Test price fence SQL builders
jdogresorg Sep 24, 2026
b57c855
Require siblings in coverage tier
jdogresorg Sep 24, 2026
14d9dae
Merge: Require siblings in coverage tier
jdogresorg Sep 24, 2026
f4a4454
Install prototype mixins as non-enumerable methods
jdogresorg Sep 24, 2026
35b3d1e
Merge: Install prototype mixins as non-enumerable methods
jdogresorg Sep 24, 2026
1da68a0
Add scheduled Stryker mutation workflow
jdogresorg Sep 24, 2026
9f33061
fix(test): isolate config fixtures and surface benchmark failures
jdogresorg Sep 24, 2026
8699e42
Bring integration tier to the current service contracts
jdogresorg Sep 24, 2026
162990d
Merge: Add scheduled Stryker mutation workflow
jdogresorg Sep 25, 2026
c58195c
Merge: fix(test): isolate config fixtures and surface benchmark failures
jdogresorg Sep 25, 2026
26dc99f
Merge: Bring integration tier to the current service contracts
jdogresorg Sep 25, 2026
9969063
Repoint node to the renamed SDK encoder helper
jdogresorg Sep 25, 2026
29f2613
fix(node): report cross-coin credential update outcomes
jdogresorg Sep 25, 2026
e29504f
build: time each ci:full tier
jdogresorg Sep 25, 2026
ad1eb77
Merge: Repoint node to the renamed SDK encoder helper
jdogresorg Sep 25, 2026
789e163
test: stabilize the Stryker dry run over the full suite
jdogresorg Sep 25, 2026
e453c0b
fix(node): validate the running indexer migrate CLI status
jdogresorg Sep 25, 2026
85de032
fix(validator): use regtest namespaces in validator links and encoder…
jdogresorg Sep 26, 2026
4d12a8b
Isolate unit test config writes
jdogresorg Sep 26, 2026
8fcfe43
Merge: Isolate unit test config writes
jdogresorg Sep 26, 2026
933d2cb
fix(module-service): clone detached local module sources at their che…
jdogresorg Sep 26, 2026
177ff96
fix(node): start module containers with --init and bound healthcheck …
jdogresorg Sep 26, 2026
ffac298
fix(node): check BuildKit availability before clone and database setup
jdogresorg Sep 26, 2026
1127268
ci(node): check out coverage siblings through the shared action
jdogresorg Sep 26, 2026
e4c0c9f
test(ci): require the shared sibling checkout in the coverage job
jdogresorg Sep 26, 2026
830b2f2
Refresh CI sibling dispatcher wording
jdogresorg Sep 27, 2026
53fd827
Align config and network chaos contracts
jdogresorg Sep 27, 2026
8f9e146
test: wire service delivery and privacy coverage
jdogresorg Sep 27, 2026
398fdd0
fix(update): require explicit node data directory
jdogresorg Sep 27, 2026
1348808
Merge: Refresh CI sibling dispatcher wording
jdogresorg Sep 27, 2026
a36504a
test(boundary): align cases with v2 contracts
jdogresorg Sep 27, 2026
cd25e5c
Document hub result-presence contract
jdogresorg Sep 27, 2026
d6c20c7
Merge: Document hub result-presence contract
jdogresorg Sep 27, 2026
419818d
Merge: test: wire service delivery and privacy coverage
jdogresorg Sep 27, 2026
c34ad99
Merge: test(boundary): align cases with v2 contracts
jdogresorg Sep 27, 2026
7143fbc
sync trunk
jdogresorg Sep 27, 2026
4b1715f
test: keep update preflight suite within limits
jdogresorg Sep 27, 2026
a66f891
Narrow the fast CI test selection
jdogresorg Sep 27, 2026
611e6cd
Merge: Narrow the fast CI test selection
jdogresorg Sep 27, 2026
127ce19
Guard migrate status probe by source contract
jdogresorg Sep 27, 2026
3662038
Support both SDK encoder accessors
jdogresorg Sep 27, 2026
bf7d365
Merge: Guard migrate status probe by source contract
jdogresorg Sep 27, 2026
ee9be79
Merge: Support both SDK encoder accessors
jdogresorg Sep 27, 2026
29f714e
Pass the anchor fold arming variable to regtest indexer and hub
jdogresorg Sep 28, 2026
a81b602
Merge: Pass the anchor fold arming variable to regtest indexer and hub
jdogresorg Sep 28, 2026
2f6db9f
sync trunk
jdogresorg Sep 29, 2026
96faf9c
Merge: sync trunk
jdogresorg Sep 29, 2026
cab0f99
test: provide data dir for module updates
jdogresorg Sep 29, 2026
3180818
Merge: test: provide data dir for module updates
jdogresorg Sep 29, 2026
8371b5d
Fix 27 issues found in a code review round
jdogresorg Sep 29, 2026
3b8a9c3
chore(release): v0.21.0
jdogresorg Sep 29, 2026
4443e32
Pin CI Node to 22.22.3, the fleet's consensus runtime
jdogresorg Sep 29, 2026
688ba64
Give the matrix stack boot the job token for GitHub API reads
jdogresorg Sep 29, 2026
8b47116
Give every matrix shard step the job token for GitHub API reads
jdogresorg Sep 29, 2026
666aa23
Pin CI Node to 22.22.3, the fleet's consensus runtime
jdogresorg Sep 29, 2026
ecb6e36
Merge develop into release/v0.21.0
jdogresorg Sep 29, 2026
daed528
Give the matrix stack boot the job token for GitHub API reads
jdogresorg Sep 29, 2026
4a74ba2
Give every matrix shard step the job token for GitHub API reads
jdogresorg Sep 29, 2026
6de78f0
Run nightly attest-mirror legs on hosted runners
jdogresorg Sep 29, 2026
765ba68
Merge develop into release/v0.21.0
jdogresorg Sep 29, 2026
35b2bca
Generalize workflow venue comments
jdogresorg Sep 29, 2026
1df1373
Add selector replay analysis
jdogresorg Sep 29, 2026
15794d0
Validate the attest-mirror drive script
jdogresorg Sep 29, 2026
55da8e4
Merge: Add selector replay analysis
jdogresorg Sep 29, 2026
1058fd0
Merge: Validate the attest-mirror drive script
jdogresorg Sep 29, 2026
a403bfa
Merge develop into release/v0.21.0
jdogresorg Sep 29, 2026
eaaa84a
Revert "Merge develop into release/v0.21.0"
jdogresorg Sep 29, 2026
71255cb
Release v0.21.0 manifest
jdogresorg Sep 30, 2026
94f8ed8
Merge pull request #52 from XChain-Platform/release-manifest-v0.21.0
jdogresorg Sep 30, 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
10 changes: 7 additions & 3 deletions .ci-siblings
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
# checks against it. An undeclared sibling is not a neutral omission - the gate
# would fail loud (bin/ci-full.sh need_sib) rather than silently skip.
#
# ci-dispatch.sh ships each of these at its origin/master (falling back to local
# HEAD) and REFUSES the push if one is not a checkout beside this repo, so a
# declared sibling can never be silently absent.
# ci-dispatch.sh ships each of these at its canonical origin head (falling back
# to local HEAD) and REFUSES the push if one is not a checkout beside this repo,
# so a declared sibling can never be silently absent.

# Vendored coins-registry byte-identity: BTC/LTC/DOGE/index/consensus_pin.
xchain-hub
Expand All @@ -18,3 +18,7 @@ xchain-hub
# src/rollcall_activation.js). Both guards throw under XCHAIN_REQUIRE_SIBLINGS=1
# when this checkout is absent, which is exactly what CI run 35020607785 did.
xchain-indexer
# The migrationMode parity guard (migration_precondition_service.test) holds
# this tool's copy to the decoder runner's src/db/migration_statements.js, and
# throws under XCHAIN_REQUIRE_SIBLINGS=1 when this checkout is absent.
xchain-decoder
39 changes: 7 additions & 32 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ on:
jobs:
ci:
uses: XChain-Platform/.github/.github/workflows/ci-reusable.yml@fd9160695d677f0538e959460ba5d8dfbb7f3c8e # pin: XChain-Platform/.github @ master 2026-08-31; bump deliberately
# Override the Node version for a repo if ever needed:
# with:
# node-version: "20"
with:
# The fleet's consensus runtime; a floating "22" now resolves 22.23.3, which the VM runtime gate refuses.
node-version: "22.22.3"

# Cross-repo drift guards: this repo vendors the canonical
# coin registry from xchain-hub, and per-repo CI cannot see sibling repos, so
Expand All @@ -49,7 +49,7 @@ jobs:
- name: Use Node.js 22
uses: actions/setup-node@v4
with:
node-version: "22"
node-version: "22.22.3"

- name: Coin-registry byte-identity vs canonical
run: xchain-hub/bin/sync-coins.sh --check --only xchain-node
Expand Down Expand Up @@ -89,40 +89,15 @@ jobs:
steps:
- uses: actions/checkout@v4

# Re-runs the same suite the `ci` job runs, so it needs the same
# sibling checkout that job's shared workflow does elsewhere.
# Mirrored verbatim (same roster, same clone) so they cannot drift.
# Re-runs the same suite the `ci` job runs, so it needs the same siblings.
- name: Check out declared sibling repositories
id: siblings
env:
SIBLINGS_REF: ${{ github.ref == 'refs/heads/master' && 'master' || 'develop' }}
OWNER: ${{ github.repository_owner }}
run: |
set -euo pipefail
if [ ! -f .ci-siblings ]; then
echo "no .ci-siblings in this repo; single-repo layout"
exit 0
fi
repos=$(sed 's/#.*//' .ci-siblings | tr -d '\r' | awk 'NF')
cd "$GITHUB_WORKSPACE/.."
for repo in $repos; do
rm -rf "$repo"
url="https://github.com/$OWNER/$repo.git"
git clone --quiet --depth 1 --branch "$SIBLINGS_REF" "$url" "$repo" 2>/dev/null \
|| git clone --quiet --depth 1 "$url" "$repo"
echo "sibling $repo @ $(git -C "$repo" rev-parse --abbrev-ref HEAD) $(git -C "$repo" rev-parse --short HEAD)"
if [ -f "$repo/package.json" ]; then
( cd "$repo" && npm ci --omit=dev --ignore-scripts --no-audit --no-fund >/dev/null 2>&1 ) \
|| ( cd "$repo" && npm install --omit=dev --ignore-scripts --no-audit --no-fund >/dev/null 2>&1 ) \
|| echo "sibling $repo: dependency install failed, guards needing its modules will say so"
fi
done
echo "checked-out=1" >> "$GITHUB_OUTPUT"
uses: XChain-Platform/.github/actions/checkout-siblings@master # one definition for every call site; see the action for why this tracks master

- name: Use Node.js 22
uses: actions/setup-node@v4
with:
node-version: "22"
node-version: "22.22.3"
cache: npm

- name: Install dependencies
Expand Down
41 changes: 41 additions & 0 deletions .github/workflows/mutation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Scheduled Stryker mutation run over the modules listed in stryker.config.json.
# Too slow for the push gate, so it runs weekly and on demand. The report is
# uploaded even when the break threshold fails the run, so a score drop can be
# inspected from the artifact.
name: mutation

permissions:
contents: read

on:
schedule:
- cron: "0 3 * * 0"
workflow_dispatch:

jobs:
stryker:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v4

- name: Use Node.js 22
uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm

- name: Install dependencies
run: npm ci

- name: Run Stryker
run: npm run test:mutation

- name: Upload mutation report
if: always()
uses: actions/upload-artifact@v4
with:
name: mutation-report
path: reports/mutation/
if-no-files-found: warn
retention-days: 30
10 changes: 7 additions & 3 deletions .github/workflows/nightly-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: '22'
node-version: "22.22.3"

# WHY THE COIN LIST IS EVENT-DEPENDENT. A scheduled run carries NO inputs, so
# without this it would silently test bitcoin alone and the nightly would be
Expand Down Expand Up @@ -245,6 +245,10 @@ jobs:
COIN: ${{ matrix.coin }}
SHARD: ${{ matrix.shard }}
PLAN_JSON: ${{ needs.plan.outputs.plan }}
# Every node src/index.js call below (validator init, install, e2etest) reads
# api.github.com; anonymous reads share 60 per hour per runner IP, which a busy
# day exhausts, and the job token raises that to 5000.
GITHUB_TOKEN: ${{ github.token }}
# The anchor-reward attestation barrier holds each block until the hub-mirror
# stream watermark is 120s past that block's own timestamp. On a shared ledger
# that is free, because blocks are ten minutes apart and the watermark is long
Expand Down Expand Up @@ -357,7 +361,7 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: '22'
node-version: "22.22.3"

- name: Reclaim runner disk (coin daemon + per-service images are large)
run: |
Expand Down Expand Up @@ -773,7 +777,7 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: '22'
node-version: "22.22.3"

# A shard that never uploaded simply has no artifact here; the merge names
# it as missing, so a failed download is not allowed to stop the job first.
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.21.0] - 2026-09-29

### Added
- Published the hub peer port in validator mode.

### Changed
- Validated the running indexer's migration status before service use.
- Passed the anchor fold arming variable to the regtest indexer and hub.

### Fixed
- Used regtest namespaces and the correct encoder URL in validator links.
- Started module containers under an init process and bounded health-check requests.

## [0.20.1] - 2026-09-23

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# XChain Platform Node

<p align="center">
<img src="https://img.shields.io/badge/version-0.20.1-blue" alt="Version">
<img src="https://img.shields.io/badge/version-0.21.0-blue" alt="Version">
<img src="https://img.shields.io/badge/tests-3%2C387%2B%20passing-brightgreen" alt="Tests">
<img src="https://img.shields.io/badge/node-%3E%3D22-green" alt="Node">
<img src="https://img.shields.io/badge/license-AGPL--3.0--or--later-blue" alt="License">
Expand Down
72 changes: 61 additions & 11 deletions bin/ci-full.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,29 @@ ci_tier_deferred() {
return 1
}
# <<< ci-tier <<<
fast_defer() {
DEFERRED="$DEFERRED [$1]"
echo; echo "ci:full ===== $1 DEFERRED (CI_TIER=fast, runs in the full sweep) ====="
}

# >>> ci-tier timer (generated block; re-run the tier wirer to update) >>>
run_tier() {
ci_tier_deferred "$1" && return 0 # ci-tier guard (generated)
local name="$1"; shift
local __ci_tier_t0=$SECONDS
echo; echo "ci:full ===== $name ====="
if "$@"; then
echo "ci:full ----- $name PASS"
local root
root="$(mktemp -d "${TMPDIR:-/tmp}/xchain-node-ci-full.XXXXXX")"
mkdir -p "$root/config" "$root/data"
if ( export XCHAIN_NODE_CONFIG_DIR="$root/config" XCHAIN_NODE_DATA_DIR="$root/data"; "$@" ); then
echo "ci:full ----- $name PASS ($(( SECONDS - __ci_tier_t0 ))s)"
else
FAILED="$FAILED [$name]"
echo "ci:full ----- $name FAIL"
echo "ci:full ----- $name FAIL ($(( SECONDS - __ci_tier_t0 ))s)"
fi
rm -rf -- "$root"
}
# <<< ci-tier timer <<<
need_sib() {
local s
for s in "$@"; do
Expand Down Expand Up @@ -104,14 +116,52 @@ if [ "${#DECLARED_SIBLINGS[@]}" -gt 0 ]; then
need_sib "${DECLARED_SIBLINGS[@]}"
fi

FAST_SELECTOR_MODE="full"
if [ "${CI_TIER:-full}" = "fast" ]; then
FAST_PLAN=""
FAST_SELECTOR_REASON=""
if [ ! -f bin/ci_fast_select.js ]; then
FAST_SELECTOR_REASON="helper missing"
elif FAST_PLAN="$(node bin/ci_fast_select.js --plan 2>&1)"; then
FAST_PLAN_HEADER="${FAST_PLAN%%$'\n'*}"
case "$FAST_PLAN_HEADER" in
"consensus 0") FAST_SELECTOR_MODE="changed" ;;
"consensus 1") FAST_SELECTOR_MODE="consensus" ;;
*) FAST_SELECTOR_REASON="selector returned no consensus decision" ;;
esac
if [ -z "$FAST_SELECTOR_REASON" ]; then
printf '%s\n' "$FAST_PLAN"
fi
else
FAST_SELECTOR_STATUS=$?
FAST_SELECTOR_REASON="exit $FAST_SELECTOR_STATUS: ${FAST_PLAN//$'\n'/; }"
fi
if [ -n "$FAST_SELECTOR_REASON" ]; then
echo "ci:full: fast selector unavailable ($FAST_SELECTOR_REASON); running the full unit tier"
fi
fi

# --- job: ci (XChain-Platform/.github ci-reusable.yml -> npm run ci) -------
# ci-reusable.yml arms XCHAIN_REQUIRE_SIBLINGS whenever it checked
# siblings out, so every sibling guard fails loud on a miss instead of
# skipping; match that here for a true local twin.
if [ "${#DECLARED_SIBLINGS[@]}" -gt 0 ]; then
run_tier "ci" env XCHAIN_REQUIRE_SIBLINGS=1 npm run ci
if [ "${CI_TIER:-full}" != "fast" ] || [ "$FAST_SELECTOR_MODE" != "changed" ]; then
if [ "${#DECLARED_SIBLINGS[@]}" -gt 0 ]; then
run_tier "ci" env XCHAIN_REQUIRE_SIBLINGS=1 npm run ci
else
run_tier "ci" npm run ci
fi
else
run_tier "ci" npm run ci
if [ "${#DECLARED_SIBLINGS[@]}" -gt 0 ]; then
run_tier "ci (changed tests)" env XCHAIN_REQUIRE_SIBLINGS=1 node bin/ci_fast_select.js --run
else
run_tier "ci (changed tests)" node bin/ci_fast_select.js --run
fi
fast_defer "ci"
fi

if [ "${CI_TIER:-full}" = "fast" ]; then
run_tier "fast-tier selector self-test" ./node_modules/.bin/mocha --no-config --timeout 20000 --exit bin/test/ci_fast_select.test.js
fi

# --- job: drift-guards -------------------------------------------------------
Expand All @@ -128,14 +178,14 @@ run_tier "drift: coin consensus-pin conformance" node -e '
console.log("consensus pin conformance OK (testnet, regtest)");
'

# --- identity pin (this gate only; no ci.yml job runs it) --------------------
# bin/pins/identity.json holds the sha256 of every vendored coin file. Nothing
# else reads it, so this tier re-hashes the tree against it and fails on any
# moved, missing or unreadable file instead of letting the pin go stale.
# --- identity pin (also the drift-guards job's identity pin step) ------------
# bin/pins/identity.json holds the sha256 of every vendored coin file. This
# tier re-hashes the tree against it and fails on any moved, missing or
# unreadable file instead of letting the pin go stale.
run_tier "identity pin (vendored coin bytes)" node bin/pin_identity.js --compare bin/pins/identity.json

# --- job: coverage -----------------------------------------------------------
run_tier "coverage ratchet (coverage:check)" npm run coverage:check
run_tier "coverage ratchet (coverage:check)" env XCHAIN_REQUIRE_SIBLINGS=1 npm run coverage:check

echo
# >>> ci-tier summary (generated) >>>
Expand Down
Loading
Loading