- 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
- The two staging flags in final form at mainnet launch (
NETWORK_IDENTITY.mdNI-R9, amended 2026-11-04). Mainnet launches with each behaviour final; their deadline release is the genesis release (Staging::deadline), andscripts/release/check_staging_deadlines.pyrefuses that cut while either still exists.-
dev-clearnet-encrypt(owner: the Noise flip): deleted at the flip, the encrypted transport the default. -
dev-relay-cover(owner: the cover-traffic lane, TRC-1): promoted or deleted by TRC-1's outcome.
-
- The clearnet reconnect throttle is built, with
NandTmeasured (P2P_TRANSPORT_LAYER.md, "Clearnet reconnect throttle", registered 2026-10-09 by D-S1; owner: the transport layer). Until it exists nothing prices a host's next session, and the past-cap evidence check's forced-rebuild bound is serial builds, not a rate (RANDOMX_CACHE_ACTOR.md§5.9, HA-F11; Rick, 2026-11-11). - 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. On macOS,filesare the Developer ID-signed copies and Tor's own go underupstream: see the macOS step below. 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. - macOS: sign once, then upload (
TB-11; Rick, 2026-10-23). A Developer ID signature carries a secure timestamp, so signing twice gives different bytes: the pair is signed once per re-pin and those files ship in every build. (1) On the signing host, the maintainer who holds the Developer ID unlocks its keychain and signs each target'storandlibevent-2.1.7.dylibtogether, hardened runtime on, with a secure timestamp and no entitlements (the signedtorrefuses alibeventsigned by another team). (2)python3 scripts/release/tor_bundle.py tie --tarball <the GPG-verified tarball> --signed <dir>must exit 0: it proves every byte outside each signature is Tor's and printsfiles(signed) andupstream(Tor's) for the row. (3) Check that each signedtorruns:--versionand--library-versionsexit 0. (4) Upload the four files to a release on this repository namedtor-macos-<bundle_version>-signed, assets<bundle_target>-<file name>(thesigned_urltemplate inconfig/tor_pins.json), marked not latest; download each back and compare its SHA-256 with the row. The digest in the row is the integrity check, not the hosting. The release build'sfetchputs the assets in the sources cache (tor-signed-<bundle_target>-<bundle_version>/).stagereads that directory and no other; it re-checks the tie before packing. The files are never committed and are not a CI artifact. - 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 bootstrap-problem reason the managed Tor's supervisor reads as a clock difference, not a blocked link (
TOR_SUPERVISOR.md§5, "Clock skew"):control_event_bootstrap_problem(warn, "CLOCK_SKEW", …)beside theCLOCK_SKEW SKEW=status event inclock_skew_warning, in the new tor'ssrc/core/mainloop/connection.c(line 6022 attor-0.4.9.14). A renamed reason failsa_clock_skew_bootstrap_problem_is_not_a_blocked_linkonly once its line is re-captured, so read the source. - Re-check the certificate lines the supervisor reads as the clock (
TOR_SUPERVISOR.md§4.2, §5 "Certificates out of date";CERTIFICATE_OUT_OF_DATEinrust/shekyl-tor-control-client/src/supervisor/events.rs) in the new tor's source:ERR("At least one certificate expired.")under"Received a bad CERTS cell: %s"inor_handshake_certs_ed25519_ok,src/feature/relay/torcert.c; and"Certificate %s. Either their clock is set wrong, or your clock is wrong."with"not yet valid"and"already expired"inlog_cert_lifetime/tor_x509_check_cert_lifetime_internal,src/lib/tls/x509_openssl.c(all three attor-0.4.9.14). Also that a closed handshake's bootstrap problem still reportsREASON=DONEwith the relay'sHOSTID(control_event_bootstrap_problem,src/feature/control/control_bootstrap.c). A reword failsthe_certificate_lines_are_tors_own_text; update the constant and that test together. - Re-check the onion-service descriptor upload cadence and lifetime 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), andHS_DESC_DEFAULT_LIFETIMEinsrc/feature/hs/hs_descriptor.h(3 hours attor-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); it also publishes the onion again when no round begins within the lifetime, so a changed lifetime movesDESCRIPTOR_LIFETIMEinshekyl-tor-control-client, whose testthe_descriptor_lifetime_is_tors_three_hourspins it (§4.5, "Overdue"). - 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, Windows and macOS, 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. - Current macOS pin: Expert Bundle 15.0.26 (tor 0.4.9.14) for
macos-aarch64andmacos-x86_64, recorded 2026-10-23 (Rick: pin macOS now). Its Tor files are byte-identical to 15.0.25's; the shipped files are the Developer ID-signed pair in thetor-macos-15.0.26-signedrelease. Not pinned: FreeBSD and riscv64 Linux.
- 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