- Stressnet stable for 4 consecutive weeks (Phase 7.7)
-
Prerequisite of stressnet ENTRY:RETIRED 2026-07-19 (K_COVERsealeddocs/completed/ARCHIVAL_REWARD_GATE_M1.md§13): the gate and the collective reward-withholding concept are retired by ruling — reward withholding is individually-caused only (slash, onset, holdings shape, claim expiry). No seal act remains; the machinery-removal implementation PR is tracked indocs/FOLLOWUPS.md. The stressnet-entry prerequisite this row guarded is dissolved (the gate has only ever run as thek_cover = 0identity, so no activation boundary exists to exercise). - All stressnet acceptance criteria met (see
tests/stressnet/README.md) - Zero tree root divergences for full 4-week run
- Block validation p95 < 500ms sustained
- Verification cache hit rate > 95% sustained
- Stressnet summary report archived
- Stressnet artifact links recorded in release notes (metrics dashboards, logs, and report commit hash)
-
- 4-scalar leaf circuit audit completed (Phase 9)
- Audit engagement initiated after stressnet gate
- No critical or high findings in final report
- All findings remediated and re-verified
- Written security assessment report archived (see
docs/AUDIT_SCOPE.md) - Audit artifact links recorded in release notes (report URL or digest, remediation PRs)
- Security audit
- Code audit
- Genesis address format: PQ signing anchor (address v2) — CLOSED 2026-08-16. Fork (ii) SELECTED by SM-R-8 (2026-08-08); freeze-window signed 2026-08-13; layout + vectors landed 2026-08-15 (in-place
0x01,ADDRESS_DERIVATION_V2); R6-a verify gate lifted. See child rows.- 192f UX gate (owner: R. Dawson, release owner) — CLOSED 2026-08-13 by release-owner ruling: 192s stands. Closed by decision, not by test: no floor-hardware UX test was run and none is planned. The ~4.3 s session figure was accepted deliberately at SM-R-8 ratification for a rare, deliberate operation ("4 seconds feels like something important is being done"); 192f was only ever pre-priced as a fallback if pre-freeze UX testing found 4 s intolerable, and no such testing exists. Reopen: only if pre-freeze UX testing is actually run and comes back bad. After the freeze the s→f swap stays foreclosed as stated (same length, different scheme — a format change no later round can make). Fallback record retained: 192f = 171 ms floor signing at ~47.7 KB armored.
- Genesis-lane freeze-window sign-off on the v2 layout — SIGNED 2026-08-13 (R. Dawson, release owner). The 48-byte SLH-DSA-192s public-key fourth field in the classical segment is the committed frozen wire field, exactly as SM-R-8 ratified it. This row records the ratified position; it decided nothing new.
- Address v2 layout + test vectors landed (
ADDRESS_DERIVATION_V1successor) — 2026-08-15. Applied as an IN-PLACE correction by ruling: version byte stays0x01, the classical segment isversion ‖ spend ‖ view ‖ msg_sign_pk(48)(113 B; bound form 129 B), and the 65-byte draft layout is deleted everywhere (multisigMULTISIG_ADDRESS_VERSIONprecedent — never deployed beyond the pre-genesis test estate). Successor corpusADDRESS_DERIVATION_V2regenerated + freeze-hash re-pinned; the persisted wallet-envelope field keeps the 65-byteversion‖spend‖viewPREFIX so every existing wallet file stays openable. A persona has no address and derives no SLH-DSA key: the seventh archival-P label (shekyl-archival-p-msg-sign-slh-dsa-192s-v1) and its registry row are deleted (2026-10-18,FND-25; decision log 2026-10-18). The SM-R-6 R6-a verify gate is LIFTED:verify_messageis live end to end and the interim-29803code was retired unused - Message-signing round unblocked — 2026-08-13, by the sign-off above. PR-SM-2's address-integrated verify freezes against the signed-off layout; the SM-R-6 R6-a type-gate lifts in code once the v2 layout row above lands.
- Release-asset manifest signed by the release owner on a real release (CBOM §6, SA-6; owner: R. Dawson, release owner; this row was titled "wired into the gitian job" until 2026-10-06, which the token-held subkey makes impossible — the gitian job publishes, the release owner signs) — the policy is NOT open:
docs/SIGNING.mdrules it (GPG; the Shekyl Foundation institutional key — certification-only primary stored offline with thesec#stub check as a verifiable invariant, hardware-token-held signing subkey requiring physical possession + PIN, personal-key fallback documented; the primary/subkey split means a lost token never compromises the identity). The earlier three-way scheme framing (2026-08-14) overstated the gap. What remains is the wiring half, which tag-signing does not close:SIGNING.mdgoverns the release tag (authenticating the commit the release was cut from), while the gitian job publishes assets that carry no signature — a user who downloadsshekyldand runs it has verified nothing. Owed before the first non-RC release tag: the signedSHA256SUMSmanifest ceremony — the Foundation signing subkey signs one manifest of asset hashes (same key, same hardware-token ceremony as tags; composes with reproducible builds). The ceremony is scripted:scripts/release/sign_release_assets.py(seedocs/SIGNING.md§Release assets) — it enforces the key-hygiene invariants before signing, round-trip-verifies before upload, and doubles as the downstream verifier (--verify-only). Because the subkey is token-held the ceremony is the release owner's local act, not a CI step; this row checks when it has been exercised on a real release. Cutting a release with this row unchecked is the failure the row exists to prevent (docs/CRYPTOGRAPHIC_INVENTORY.md§6). EXERCISED 2026-10-06 onv3.1.0-alpha.9: the release owner ran the ceremony with the token;SHA256SUMSandSHA256SUMS.ascare on the release, and an independent--download --verify-onlyfrom a clean directory reported the signature good under the signing subkey with all 12 hashes matching and no unlisted assets. The gitian job publishes an unsignedSHA256SUMSfirst, so the ceremony's upload takes--clobber(docs/SIGNING.md). The row stays a per-release duty: it is checked here because the mechanism has now run on a real release, not because later releases are covered. - PQC specification frozen
-
docs/POST_QUANTUM_CRYPTOGRAPHY.mdmatches implementation — updated in PR-SA-2 to the nested combiner (v2, 64-byte domain-separated preimage),Result<()>verify, and the v2/frozen-v1 test-vector split - canonical transaction/signature serialization documented
- signed payload definition documented
- V4 PQC Privacy Roadmap published
- Hybrid signature construction frozen (SA-2,
SIGNATURE_ALIGNMENT.md): the nested combiner (HYBRID_SIG_VERSION = 2, PQ-inner / Ed25519-outer over a domain-separated preimage) and the per-surfaceSCHEME_DOMAIN_*strings are consensus-visible on bonded/settlement surfaces (bond-post auth, attestation witness, emission auth). After genesis a change here is a hard fork; the version byte is the security boundary. Landed pre-genesis in PR-SA-2. - Bond-preimage reconciliation closed (SA-2b,
SIGNATURE_ALIGNMENT.md§2.2): the P-role replay analysis found the surface-A whole-tx hash (which binds the vin type tag) forecloses cross-role replay, so generic won. The bond vin'spqc_authsslot signs the generic surface-A payload hash; S1 +signature_preimage+SCHEME_DOMAIN_BOND_POSTdeleted. No wire change. Landed pre-genesis in PR-SA-2b. -
fn-dsaat 1.0 or later (genesis gate). Hybrid scheme 3 (Ed25519 + FN-DSA-1024) rests on a pre-standard crate whose keys and signatures change when FIPS 206 is final.scripts/ci/check_fn_dsa_genesis_gate.pyrefuses a tag with no pre-release suffix while the lockedfn-dsapackages are below 1.0; pre-release tags pass. This row checks when the crate is updated and every scheme-3 vector is regenerated (docs/design/FN_DSA_HYBRID.md§4, and its FOLLOWUPS row).
-
- PQC crypto review
- hybrid sign/verify implementation reviewed (external audit pending)
- FFI ownership / zeroization reviewed (external audit pending)
- test vectors generated and archived (
PQC_HYBRID_V2_KAT.json: 6 pinned positives, one per signing surface — bond-post's dropped in SA-2b, §2.2 — with cross-surface rejection; frozen v1 parse-rejection fixture; 3 negative vector integration tests)
- PQC interoperability verification
- wallet sign/daemon verify path tested
- malformed hybrid signature rejection tested (3 negative vector integration tests)
- encoded transaction size impact measured (5389 bytes
pqc_authper input viapqc_auth_weight()) - payload limit guidance documented in V3_ROLLOUT.md
- Ledger integration — deleted 2026-10-01 (
docs/HARDWARE_WALLETS.md). There is no in-tree backend to finish. Reopen only when a device ships the V4 primitives that doc names. - Trezor integration — deleted 2026-08-18 (
docs/HARDWARE_WALLETS.md). Same reopen criterion. The software device is the key helper the daemon calls, and it does not carry FCMP offload hooks.
Software wallets only. Hardware support reopens against the Rust wallet when a device ships the V4 primitives docs/HARDWARE_WALLETS.md names.
- Fork height set (rebooted chain: all features at HF 1 from genesis)
- Shekyl announcement mailer / notice
- Twitter announcement
- Reddit announcement
- Project website announcement
- Notify wallets (placeholder -- replace with actual Shekyl-compatible wallets pre-launch)
- Shekyl GUI Wallet (first-party)
- Shekyl CLI (first-party)
- (third-party wallet integrations TBD)
- Notify exchanges (placeholder -- replace with actual exchange partners pre-launch)
- (exchange integrations TBD)
- Notify 3rd party payment processors (placeholder)
- (payment gateway integrations TBD)
- Notify mining pools (placeholder)
- (mining pool partnerships TBD)
- Release tagged
- Update src/version.cpp.in with new version AND new name (if necessary)
- Update Gitian YML files in contrib/gitian/ to the new version number
- Update README.md with new fork table entry (or recommended Shekyl version)
- Update contrib/gitian/README.md so that the instructions reflect the current version
- Update src/checkpoints/checkpoints.cpp with a recent hardcoded checkpoint
- Testnet forked
- Testnet testing/verification
- Run deterministic tuple check across seed nodes:
python3 scripts/check_testnet_genesis_consensus.py --rpc http://SEED_EAST:12029 --rpc http://SEED_WEST:12029 --rpc http://SEED_EU:12029 --check-economy
- Follow rehearsal runbook:
shekyl-dev/docs/TESTNET_MINER.md - Follow rehearsal gates:
shekyl-dev/docs/TESTNET_REHEARSAL_CHECKLIST.md - Ledger
- Trezor
- Release-specific testing
- RPC testing/update RPC documentation
- PQC transaction validation testing
- PQC wallet send/receive testing
- PQC multisig group creation (2-of-3, 3-of-5)
- PQC multisig signing flow (export request, partial sign, import, broadcast)
- PQC multisig scheme downgrade rejection verified
- PQC multisig fuzz targets run (5 harnesses, 10M iterations each)
- PQC multisig test vectors validated against docs/PQC_TEST_VECTOR_002_MULTISIG.json
- FCMP++ proof verification tested (prove/verify round-trip)
- Curve tree operations tested (grow/trim/root/path)
- FCMP++/staking/PQC fuzz targets run (11 harnesses total, 10M iterations each)
- CI fuzz smoke gate passed (required harness inventory check in
.github/workflows/build.yml) - Per-output PQC key derivation tested
- Bech32m address encoding/decoding tested
- Block header
curve_tree_rootcommitment validated - RPC consumer regression testing for larger transactions
- Run deterministic tuple check across seed nodes:
- CLI reproducible builds validated
- Rust/PQC reproducible build inputs documented
- Bundled Tor pin current (2d-2 archival firewall, SP-T0c;
TOR_BUNDLE_DISTRIBUTION.mdTB-6…TB-10— the pin of record isconfig/tor_pins.json)- Every managed tor launch, the daemon's and the wallet's, is gated on the pin:
rust/shekyl-tor-control-client/src/binary.rsmints theVerifiedTorBinarywitness a launch requires only when tor's directory holds exactly the pinned files and each hashes to its pin. Release artifacts carry that bundle. A stale or unverified pin is a mission-#1 (security-precondition) gap, so this is a recurring duty, not a one-time step. - Watch https://www.torproject.org/download/tor/ for a new stable Tor Expert Bundle or a security advisory since the recorded pin (and the alpha line, for
linux-aarch64). - Ensure the signing key is in your keyring (fresh machine):
gpg --auto-key-locate nodefault,wkd --locate-keys [email protected], then confirm the primary fingerprint isEF6E286DDA85EA2A4BA7DE684E2C6E8793298290(signing_key_fingerprintinconfig/tor_pins.json, compiled asTOR_SIGNING_KEY_FPR). - On a new stable / advisory, per pinned target: download the Expert Bundle tarball and its
.asc, thengpg --status-fd 1 --verify <file>.asc <file>— require aVALIDSIGline whose last field, the primary key, is that fingerprint;GOODSIGalone matches any key the keyring happens to hold (the durable pin is this key, not any single hash). - Record, in that target's row of
config/tor_pins.json:bundle_version,tor_version, the tarball'ssha256sumastarball_sha256, and thesha256sumof each file Shekyl ships from the tarball'stor/directory underfiles(on Linuxtor,libevent-2.1.so.7,libssl.so.3,libcrypto.so.3; on Windowstor.exe). On Windows also re-deriveimportsfrom the newtor.exeitself, never from the old list: theDLL Namelines ofobjdump -p tor.exe, and itsDelay Import Directorymust be empty.tor_bundle.pyrefuses a DLL the list does not name and any delay-load import, so a changed set is a stop: say what changed and why it is safe before recording it. If the new bundle'storneeds a library the old one did not ship, it is a newfilesentry: the daemon refuses a tor directory that holds anything unlisted, and one that lacks anything listed. Nothing else in the tree carries a digest —build.rscompiles the row andscripts/release/tor_bundle.pypackages from it. - Update the two prose records that point at the pin: the "Current pin" paragraphs in
docs/design/ARCHIVAL_BOND_2D2_SP_T0_TOR.md(move the old pin to its "Superseded pins" note with its tarball hash) and the "Current pin" lines below.scripts/ci/check_tor_pin_targets.pyfails until the lines below name the new versions. - Re-verify locally:
python3 scripts/release/tor_bundle.py stage --host <gitian-host> --sources <dir holding the verified tarball> --dest <fresh>/tor --licenses <fresh>/tor-licenses, thenSHEKYL_TEST_PINNED_TOR_BINARY=<fresh>/tor/tor cargo test -p shekyl-tor-control-client --lib binary -- --ignored—bundled_tor_matches_recorded_pinmust pass. (The test is notcfg-gated: on a target with no pin it fails loudly instead of reporting a vacuous 0-test green. Pointing it at the raw extracted bundle fails by design: that directory carriespluggable_transports/.) - Re-check the onion-service descriptor upload cadence in the new tor's source:
HS_SERVICE_NEXT_UPLOAD_TIME_MINandHS_SERVICE_NEXT_UPLOAD_TIME_MAXinsrc/feature/hs/hs_service.h(60 and 120 minutes attor-0.4.9.13andtor-0.4.9.14). The daemon's reachability probe runs once per upload round, so a changed cadence changes how long an unnoticed failure can last (TOR_SUPERVISOR.mdTSR-Q5). - Dispatch the
tor-pin-verifyworkflow (.github/workflows/tor-pin-verify.yml). It takes no version input — it reads the pin file — and for each pinned target, Linux and Windows, runs fetch → GPG-verify → stage → pin-match, then the SP-T0--liblive lifecycle tests against the staged bundle. - Current pin: Expert Bundle 15.0.25 (tor 0.4.9.14) for
linux-x86_64andwindows-x86_64, verified and recorded 2026-10-17 (seeconfig/tor_pins.jsonfor the gate values — the file is canonical; this line is a pointer, not a second source of truth). - Current
linux-aarch64pin: Expert Bundle 16.0a14 (tor 0.4.9.14), verified and recorded 2026-10-17. This is an alpha, and it is pinned on purpose. The stable line publishes onlylinux-i686andlinux-x86_64(the aarch64 builds areandroid-andmacos-), so the alpha line is the onlylinux-aarch64build there is, and the rule-76 floor device needs aVerifiedTorBinaryto run the managed posture at all. Verified the same way as the stable pin: aVALIDSIGunder the key above. Reopen: re-pin to the first stable bundle that shipslinux-aarch64, and until then the alpha-line advisories are part of the watch above — seedocs/design/ARCHIVAL_BOND_2D2_SP_T0_TOR.md. - Not pinned: macOS (its digests are verified in
TOR_BUNDLE_DISTRIBUTION.md§4 and adopted with its launch test,TB-11), FreeBSD and riscv64 Linux. Each has anunavailablerow with its reason; a target with no row does not compile.
- Every managed tor launch, the daemon's and the wallet's, is gated on the pin:
- CLI released
- Project downloads page updated
- Update hashes.txt on website
- Update downloads.yml on website
- Update auto-update DNS records on all 5 TLDs (see
shekyl-dev/docs/DNS_CONFIG.md) - Update redirects on downloads box
- Update seed nodes
- GUI released (if applicable)
- Project downloads page updated
- Update hashes.txt on website
- Update hashes.txt.sig on website
- Update downloads.yml on website
- Update auto-update DNS records on all 5 TLDs (see
shekyl-dev/docs/DNS_CONFIG.md) - Update redirects on downloads box
- Release Announcements
- Shekyl announcement mailer notice
- Twitter announcement
- Reddit announcement
- Project website announcement