From cdf2ec77d1e5426c87dd2c0a1716e597b4bd242b Mon Sep 17 00:00:00 2001 From: Alexander Miller Date: Thu, 22 Oct 2026 11:14:08 -0400 Subject: [PATCH 1/3] 3.0.x: version 3.0.0 and its release notes (#557) 3.0.0 is 3.0.0-rc.6 plus #770 (#765) and #760 (#759), the two fixes #772 prepared as 3.0.0-rc.7, which was never tagged. The 3.0.x branch starts at #770's merge, 4c134913, before 3.x.x took the 3.1 dual writer. - VERSION, [workspace.package].version and the workspace-member entries of both Cargo.lock files move to 3.0.0. - doc/release-notes-3.0.0.md becomes the 3.0.0 notes: #772's rc.7 notes as the changes since rc.6, then the D5 recovery contract it held. - The development-line note and the migration guide name 3.0.0. Co-Authored-By: Claude Opus 5.5 --- Cargo.lock | 10 +- Cargo.toml | 2 +- VERSION | 2 +- crates/qbit-prism-server/fuzz/Cargo.lock | 6 +- doc/release-notes-3.0.0.md | 274 +++++++++++++++++++- doc/release-notes-3.x.x-development-line.md | 18 +- docs/prism-rust-migration.md | 11 +- 7 files changed, 293 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 13074e70d..8d5a3e49f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1376,7 +1376,7 @@ dependencies = [ [[package]] name = "qbit-pool-builder" -version = "3.0.0-rc.6" +version = "3.0.0" dependencies = [ "ed25519-dalek", "hex", @@ -1388,7 +1388,7 @@ dependencies = [ [[package]] name = "qbit-prism" -version = "3.0.0-rc.6" +version = "3.0.0" dependencies = [ "hex", "qbit-pool-builder", @@ -1401,7 +1401,7 @@ dependencies = [ [[package]] name = "qbit-prism-load" -version = "3.0.0-rc.6" +version = "3.0.0" dependencies = [ "anyhow", "axum", @@ -1428,7 +1428,7 @@ dependencies = [ [[package]] name = "qbit-prism-server" -version = "3.0.0-rc.6" +version = "3.0.0" dependencies = [ "anyhow", "axum", @@ -1466,7 +1466,7 @@ dependencies = [ [[package]] name = "qbit-prism-test-gate" -version = "3.0.0-rc.6" +version = "3.0.0" [[package]] name = "quinn" diff --git a/Cargo.toml b/Cargo.toml index c95628bce..045eb224c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ members = [ ] [workspace.package] -version = "3.0.0-rc.6" +version = "3.0.0" # Pinned to the toolchain in rust-toolchain.toml; scripts/check_toolchain_pin.py # fails when they differ. rust-version = "1.98.1" diff --git a/VERSION b/VERSION index c84a56c89..4a36342fc 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.0-rc.6 +3.0.0 diff --git a/crates/qbit-prism-server/fuzz/Cargo.lock b/crates/qbit-prism-server/fuzz/Cargo.lock index a52ddb703..e1fa40108 100644 --- a/crates/qbit-prism-server/fuzz/Cargo.lock +++ b/crates/qbit-prism-server/fuzz/Cargo.lock @@ -1372,7 +1372,7 @@ dependencies = [ [[package]] name = "qbit-pool-builder" -version = "3.0.0-rc.6" +version = "3.0.0" dependencies = [ "ed25519-dalek", "hex", @@ -1384,7 +1384,7 @@ dependencies = [ [[package]] name = "qbit-prism" -version = "3.0.0-rc.6" +version = "3.0.0" dependencies = [ "hex", "qbit-pool-builder", @@ -1396,7 +1396,7 @@ dependencies = [ [[package]] name = "qbit-prism-server" -version = "3.0.0-rc.6" +version = "3.0.0" dependencies = [ "anyhow", "axum", diff --git a/doc/release-notes-3.0.0.md b/doc/release-notes-3.0.0.md index cab9d8b68..c0897da16 100644 --- a/doc/release-notes-3.0.0.md +++ b/doc/release-notes-3.0.0.md @@ -1,16 +1,272 @@ -# qbit-mining-bootstrap 3.0.0 — unreleased recovery contract - -**UNRELEASED. NOT PRODUCTION-READY.** These partial release notes record the -migration decision required by #287. #291 must complete the release notes and -rehearse the cutover and isolated restore on production-sized history, including -restore and `import-audits` timings, before approving a production rollout. -See [development-line status](release-notes-3.x.x-development-line.md) and -the release candidates' notes, [3.0.0-rc.1](release-notes-3.0.0-rc.1.md), +# qbit-mining-bootstrap 3.0.0 Release Notes + +Release date: 2026-10-22 (tag `v3.0.0`, cut from the `3.0.x` branch). + +3.0.0 is 3.0.0-rc.6 plus #770's fix for #765, in which `import-audits` held +`SETTLEMENT_LOCK` while it sent and stored each legacy audit body, so a large +body stalled settlement and template refresh on the frontends serving beside +it, and #760's fix for #759, in which the node RPC client reused an idle +connection past qbitd's own idle close. Those two pull requests were prepared +as 3.0.0-rc.7 (#772), which was never tagged. `3.0.x` branches from `3.x.x` +at #770's merge, `4c134913`. `3.x.x` continues as 3.1 from 3.1.0-rc.1, which +adds the dual writer and migrations 027, 028 and 031; 3.0.0 has none of them. +#291 records the cutover qualification and the go/no-go for the production +rollout. + +Everything in the [3.0.0-rc.1](release-notes-3.0.0-rc.1.md), [3.0.0-rc.2](release-notes-3.0.0-rc.2.md), [3.0.0-rc.3](release-notes-3.0.0-rc.3.md), [3.0.0-rc.4](release-notes-3.0.0-rc.4.md), [3.0.0-rc.5](release-notes-3.0.0-rc.5.md) and -[3.0.0-rc.6](release-notes-3.0.0-rc.6.md). +[3.0.0-rc.6](release-notes-3.0.0-rc.6.md) notes applies, with the changes +below; see also the +[development-line status](release-notes-3.x.x-development-line.md). Like +rc.6, an upgrade from the previous candidate replaces the binary only: 3.0.0 +adds no migration ([Upgrading](#upgrading)). + +## Changes since 3.0.0-rc.6 + +- #770 (#765): `import-audits` writes each legacy audit before it takes + `SETTLEMENT_LOCK`, holds the lock only to check the write guard and + commit, and bounds every phase of a row's transaction. + - **Before:** for each row, rc.6 took `SETTLEMENT_LOCK`, checked the write + guard, and only then encoded the row's UPDATE and sent it: the canonical + body as `bytea`, beside the audit's commitment and witness Merkle leaves + as JSON. The lock was held while the client encoded and sent the + statement and while the server stored it. Nothing bounded the send: the + session's `statement_timeout` (`PRISM_DATABASE_STATEMENT_TIMEOUT_MS`, + 15 s by default) starts only once the whole statement has arrived. In + #765, a legacy audit with a ~112 MB canonical body held the lock for + about 90 s, until it was killed, while the server waited for the rest + of the statement (`idle in transaction`, waiting on `ClientRead`). + Every other `SETTLEMENT_LOCK` user waited behind it: the frontends' + advisory-lock waits timed out, template refresh was deferred, and + settlement would have waited too. `docker stop` didn't stop it either: + in a container the command runs as PID 1, which ignores a SIGTERM it + has no handler for. + - **Now, per row:** the body is loaded, verified and canonicalized, and all + nine UPDATE parameters are encoded, on one blocking thread before any + transaction opens. The UPDATE is then sent and run on the row's own + connection, holding only that row's lock. Only then does the importer + poll for `SETTLEMENT_LOCK` with `pg_try_advisory_xact_lock`, every 25 ms + and never queued, check the write guard again under it, and commit. + Every other `SETTLEMENT_LOCK` holder still sees a row committed before + it took the lock, or not at all. The write guard also runs before the + write, so a halted cluster or a live legacy writer is refused before + anything is sent. + - **A lock holder that needs the row goes first.** A poll that misses the + lock also walks the lock holder's blockers (`pg_blocking_pids`, then + theirs in turn). If the holder waits on this row, directly or through + another session, the row is rolled back so the holder can proceed, and + the command fails naming the row. Other sessions waiting on the row, + such as a second import, just wait. + - **Bounds:** two new settings, read by `import-audits` only. + - `PRISM_IMPORT_AUDITS_WRITE_TIMEOUT_MS` (60000; 1000 to 600000) is the + write's transaction-local `idle_in_transaction_session_timeout`, + `statement_timeout` and `lock_timeout`. So the server ends a session + that stops sending mid-statement, and cancels an UPDATE that runs, or + waits for the row, that long. + - `PRISM_IMPORT_AUDITS_LOCK_TIMEOUT_MS` (5000; 100 to 600000) bounds the + wait for `SETTLEMENT_LOCK`. Once the lock is held, it is also the + transaction's idle and statement timeout, so a client or statement + that stalls under the lock loses its session, and the lock, within + that long. + - The row's connection also sets `client_connection_check_interval` to + 1 s where the server supports it (PostgreSQL 14 or later, on Linux). + An abandoned row is then rolled back within about a second, even while + the server is storing it. + - **A row that exceeds a bound** is rolled back, and the command exits 1 + with an error naming the row, `importing legacy audit `, and + its cause, such as `SETTLEMENT_LOCK stayed busy for 2000 ms; the row is + rolled back and nothing was stored`. Rows imported before it stay + imported, and a re-run resumes from it. + - **SIGTERM or SIGINT stops the command.** It stops before the next row, + or rolls back a row that has not been granted the lock, and exits 1 with + `import-audits stopped on request after importing audit bodies; …`. + A row that holds the lock finishes its commit first, and a stop that + lands once the last row is in ends as a finished import. A second signal + exits at once. + - **Each row it writes prints one line on stderr,** `imported`, or + `unchanged` for a row that changed after it was read, for example + `import-audits: block_hash= imported + parameter_bytes=block_hash:64,…,canonical_audit_bytes: + total_parameter_bytes= prepare_ms=… write_ms=… lock_wait_ms=… + lock_held_ms=… total_ms=…`. stdout keeps the completeness counts and + `Imported audit bodies`. + - **Measured** in a release build, over TLS through a TCP proxy, on a + synthetic legacy row with a 112.2 MB canonical body and a 37.5 MB + witness-leaves array. rc.6's order held `SETTLEMENT_LOCK` for 3.145 s: + 0.10 s encoding the statement, 3.01 s sending it and the server storing + it, about 0.15 s of that the send, and 28 ms for the guard and the + commit. 3.0.0 holds it for 13 ms. With the client's send + slowed to 16 MiB/s, the hold was 14.9 s against 16 ms. A session taking + the lock every 20 ms waited at most 3.13 s and 14.9 s beside rc.6's + order, and 3 ms and 17 ms beside 3.0.0's. + - **Why #765's send took so long is not proven:** it did not reproduce + here. The likely cause is #771, below. 3.0.0's `import-audits` + doesn't depend on it: whatever slows or stops the send now happens + before the lock and within the write timeout. The client also polls the + statement every 100 ms, which un-sticks #771's lost wakeup if it occurs. + - It changes `import-audits` only: the command, its transaction and two + setting names. There is no migration or schema change, and nothing the + frontends or the `public-api` service run changes. +- #760 (#759): every node RPC client keeps an idle connection for at most + 20 s. + - **Before:** the frontends' qbitd RPC client kept an idle kept-alive + connection for 60 s, and the public API's node client for reqwest's + default 90 s, while qbitd closes one after its `-rpcservertimeout`, 30 s + by default. A request written into a connection just as the node closes + it is never read, and fails after the connection existed: the plain + `transport failed` error, which nothing retries. On `submitblock` that + is an unknown outcome, and the block is never offered again. One + deployment, with `PRISM_CTV_BROADCASTER_POLL_SECONDS=30` (the default is + 10), logged the error from the CTV broadcaster, whose passes ran in step + with the 2 s refresh, on about one pass in eight to fifteen. + - **Now** every node client is built by `node_client_builder()`: the + frontends', the public API's and the load harness's. It keeps an idle + connection for at most 20 s (`POOL_IDLE_TIMEOUT`), so the client drops + it before the node can. A compile-time assert keeps the bound below + qbitd's 30 s default. Relay calls, `submitblock` included, share the + bounded pool as before. + - **Operator rule:** keep qbitd's `-rpcservertimeout`, and the idle + timeout of any proxy between a PRISM process and its node, above 20 s. + qbitd's default, 30 s, is. + +## Upgrading + +- **From 2.0.x, or from 3.0.0-rc.4:** as in the + [rc.5 notes](release-notes-3.0.0-rc.5.md#upgrading), with 3.0.0 + in rc.5's place. That covers `migrate` for 026, which every start of + 3.0.0 requires, as rc.5's does; the cutover's + `migrate --defer-share-hashes --offline-indexes`, and finishing the + backfill after go-live with `backfill-share-hashes`; rolling back to rc.4 + at fence 2; and the operating rules still in force: #737's statement + timeout for rc.4's tools, #738's snapshot rule and + `fatal-state clear --timeout-seconds`. From an earlier candidate, the + upgrade sections of each later candidate's notes apply in turn. +- **From 3.0.0-rc.5:** replace the binary, as the + [rc.6 notes](release-notes-3.0.0-rc.6.md#upgrading) describe for rc.6; + everything below about rc.6 applies too. +- **From 3.0.0-rc.6: no migration; replace the binary on every frontend and + tool, and on the `public-api` service.** 3.0.0 requires the same + native schema migrations as rc.6, 2 to 26, declares the same capabilities + and understands the same share-hash fence values, 1 and 2. The same + settings give its frontends the same configuration fingerprint, so they + can replace rc.6's one at a time. It changes no evidence or admission-gate + script. + - **The two new settings are accepted by 3.0.0 binaries only.** rc.6's + `run` and `check-config` refuse a `PRISM_*` name they don't know in + production mode (`QBIT_CHAIN` main or mainnet, `QBIT_PRODUCTION` or + `QBIT_TOOLS_PRODUCTION`), and warn about it otherwise. So pass them only + to a 3.0.0 `import-audits` run, never through an environment that an + rc.6 frontend reads. + - **#760's node rule:** check that qbitd's `-rpcservertimeout`, and the + idle timeout of any proxy between a PRISM process (a frontend, a tool or + the `public-api` service) and its node, are above 20 s. + - **`import-audits` beside serving frontends** no longer needs the guard + #765 describes, one that kills it with SIGKILL once a settlement waiter + has waited a few seconds. Its hold is now the guard read and the commit, + and `docker stop` stops it. +- **Rolling back to rc.6:** first remove the two settings from every + environment an rc.6 binary will read, then replace the binary; nothing + else changes. With rc.6, #765 returns: run its `import-audits` beside + serving frontends only under the guard #765 describes. #759 returns too: + the node clients keep an idle connection for 60 s again, 90 s on the + public API. + +## Verification + +The runtime changes between rc.6 and 3.0.0 are in `import-audits` +and in how long the node clients keep an idle connection: +- #770, merged as `4c134913`: `import-audits` only, in + `ledger/migration.rs` (`Ledger::import_legacy_audits_with` and its per-row + transaction) and `tools.rs` (the command, its two settings, its stop + signal and its stderr line), with the two names in + `config/native-settings.txt` and a re-export in `ledger.rs`. It adds + `tests/import_audits_settlement_lock.rs` and its entries in + `test/prism-gated-tests.txt`, and updates the server's README, the ledger + runbook and the pool-acquire census. +- #760, merged as `12f1ae8e`: the node client's idle bound in `rpc.rs`, used + by the public API's node client (`api.rs`) and the load harness's, with + the node requirement in the migration guide. + +Neither touches a migration, a capability, the share append +(`ledger/window.rs`), the order lock or settlement. #760 changes only how +long each node client keeps an idle connection. So the serving evidence +rc.3's notes cite still applies: the D1 peak-second gate, the 750/s ceiling +and the failover drill under load, run 1, all measured on #719's build. + +In CI, the changes are proved by their tests: +- #770 by `import_audits_settlement_lock`'s 13 gated tests. They put the + importer's connections behind a relay that slows or stalls what the client + sends, which leaves the server in #765's state, and check: + - that a session taking `SETTLEMENT_LOCK` every 20 ms beside the import of + a 107 MB body with a 37.5 MB witness-leaves array waits less than 3 s, + while the throttled write takes longer than that (rc.6's order fails + it); + - that a stall mid-send and a stall under the lock each end within their + bound, and that a busy lock fails the row within its bound; + - that a lock holder waiting on the row goes first, directly or behind + another session; + - that a stop mid-send, mid-execution, before the grant, between rows and + after the last row each behaves as above; + - and, on the real command, its SIGTERM exit and its busy-lock output. +- #760 by `rpc_idle_close`: the real client against a loopback node that + drops a request arriving after its idle limit, as the race does. With a + bound below the node's, the next call opens a new connection and is + answered; with a bound past it, the call fails with the production error. + +Otherwise the evidence is the same set as rc.6's (#557): +- CI on the version-bump pull request, and dispatched on the tag; +- the L3 production-window matrix (`l3-full`) on the `v3.0.0` tag push. The + version-bump pull request targets `3.0.x`, where the matrix doesn't run + on pull requests, so the tag runs it rather than promoting a pull + request's run (#608); +- the targeted nightly batch: `short-plan-fake-node`, `short-plan-real-node`, + `soak-smoke`, `faults-short-real-node` and `faults-failover-fake-node`; +- the live regtest weekly scenarios. + +rc.1's full nightly set and 5.5 h soak carry over. The evidence bundle on the +`v3.0.0` GitHub release lists every run, and #291 links to it. + +## Known issues + +As in the rc.6 notes, with these changes: + +- **Fixed since rc.6:** + - **#765, by #770:** rc.6's `import-audits` held `SETTLEMENT_LOCK` while + it sent and stored each body, with nothing bounding the send, and ignored + `docker stop` (above). + - **#759, by #760:** the node clients kept an idle connection past qbitd's + idle close, so a call could fail in the close (above). +- **Open since rc.6, not fixed in 3.0.0:** + - **#771:** sqlx 0.8.6's rustls stream can lose the wakeup of a large write. + A large statement sent over TLS can then stall, with the server waiting + for the rest of it, until something closes the connection. It is the + likely cause of #765's hold. 3.0.0's `import-audits` works + around it (above), but other large statements from the serving binary + don't. The fix is upstream, launchbadge/sqlx#4251, which no 0.8.x + release carries; #771 tracks backporting it. + - **#762:** a `submitblock` whose deadline, + `PRISM_BLOCK_SUBMIT_RPC_TIMEOUT_SECONDS` (1 s by default), passes while + its connection is still opening is recorded as an unknown offer, not an + unsent one, so that block is never offered again. It needs no free + pooled connection when the call starts and a connect slower than the + deadline, which the 2 s refresh calls make unlikely. #760 leaves relay + calls on the bounded pool for this reason. + - **#757:** five alert-rule UIDs in `docs/prism-native-alert-rules.json` + exceed Grafana's 40-character limit, so provisioning the rule set as + published stops Grafana from starting. Until it's fixed, map the five + to short forms when rendering the rules; #757 lists them. + - **#758:** the two accepted-block revision-work warnings, + `PrismAcceptedRevisionWorkPending` and + `PrismAcceptedRevisionWorkTrackingUnknown`, fire after every pool block + on a frontend that has no miners and doesn't commit the settlements, a + backup frontend say, and the second latches until that frontend + restarts. Until it's fixed, silence the two on idle frontends. +- **Still open from rc.6,** as the rc.6 notes describe them: #752, #738, + #739, #724's other answer, #737's open part, #741, #731, #734, #716's open + part, #711 and #712. ## Migration and recovery (D5) diff --git a/doc/release-notes-3.x.x-development-line.md b/doc/release-notes-3.x.x-development-line.md index ea666e9f1..876762d3e 100644 --- a/doc/release-notes-3.x.x-development-line.md +++ b/doc/release-notes-3.x.x-development-line.md @@ -47,8 +47,8 @@ carries a banner with the same statement. submodules, `ledger/candidates.rs`, `ledger/jobs.rs`, `ledger/window.rs`, and `ledger/connect.rs`, with no behaviour change and no signature change, so parallel workstream pull requests stop colliding on one file. -- One release identity per #284, currently `3.0.0-rc.6`, the sixth release - candidate of `3.0.0` (#557). The single source is +- One release identity per #284, currently `3.0.0` on the `3.0.x` branch, + after six release candidates (#557). The single source is `[workspace.package].version` in the root `Cargo.toml`, which every crate inherits with `version.workspace = true`, plus the `VERSION` file; bump the two together. `scripts/check_version_skew.py` (also `make @@ -120,16 +120,14 @@ they fixed or configured no longer exists on this line: - There is no production release of the Rust server. The Postgres-backed and live-regtest Rust suites need a PostgreSQL server and a `qbitd` binary; see `test/prism-native-tests.sh`. They are not part of this note's verification. -- Final release notes are #291. The tree reads 3.0.0-rc.6, the sixth release - candidate ([its notes](release-notes-3.0.0-rc.6.md); the earlier ones are - [3.0.0-rc.1](release-notes-3.0.0-rc.1.md), +- The tree reads 3.0.0 ([its notes](release-notes-3.0.0.md); the release + candidates' are [3.0.0-rc.1](release-notes-3.0.0-rc.1.md), [3.0.0-rc.2](release-notes-3.0.0-rc.2.md), [3.0.0-rc.3](release-notes-3.0.0-rc.3.md), - [3.0.0-rc.4](release-notes-3.0.0-rc.4.md) and - [3.0.0-rc.5](release-notes-3.0.0-rc.5.md)), and nothing on this line has - been released as 3.0.0; `doc/release-notes-3.0.0.md` currently - records only the unreleased D5 recovery contract. #291 completes those - notes and the rollout record. + [3.0.0-rc.4](release-notes-3.0.0-rc.4.md), + [3.0.0-rc.5](release-notes-3.0.0-rc.5.md) and + [3.0.0-rc.6](release-notes-3.0.0-rc.6.md)). #291 keeps the rollout + record: the cutover qualification and the go/no-go. - Native candidate recovery (#268) landed with #439. ## Upgrade and rollback diff --git a/docs/prism-rust-migration.md b/docs/prism-rust-migration.md index 9eb2dab1f..4f413df54 100644 --- a/docs/prism-rust-migration.md +++ b/docs/prism-rust-migration.md @@ -91,7 +91,16 @@ qbit-prism-server import-audits --root /var/lib/qbit-prism/audit reconstructed body. Require the exact SHA and matching ETag, as below. Nothing on the serving path reads a legacy row's canonical bytes. So -frontends can admit traffic before `import-audits` finishes. Until it does, +frontends can admit traffic before `import-audits` finishes. From 3.0.0 an +import beside them holds `SETTLEMENT_LOCK` only to check the write guard and +commit each row. It sends and stores the row first, within +`PRISM_IMPORT_AUDITS_WRITE_TIMEOUT_MS`; `PRISM_IMPORT_AUDITS_LOCK_TIMEOUT_MS` +bounds its wait for the lock and its hold. SIGTERM stops it (#765). Through +rc.6 it held the lock while it sent and stored each body, which stalls +settlement and template refresh for as long, so run an earlier candidate's +import beside serving frontends only under a guard that kills it with +SIGKILL once a settlement waiter has waited a few seconds: as a container's +PID 1 it ignores SIGTERM. Until `import-audits` finishes, production `self-check` fails at audit completeness and skips its other checks (#734). `scripts/prism_legacy_import_admission_gate.sh` checks every other fact `self-check` checks, against the frontend's own environment on each host. It From f7ad277377f069a46904a6bb26d44598e8662d66 Mon Sep 17 00:00:00 2001 From: Alexander Miller Date: Thu, 22 Oct 2026 11:27:28 -0400 Subject: [PATCH 2/3] 3.0.x: update rustls, rustls-webpki and webpki-roots for six RustSec advisories cargo deny fails on rc.6's lockfile with RUSTSEC-2026-0346, -0347, -0348 and -0349 (rustls < 0.23.46), RUSTSEC-2026-0382 (rustls-webpki < 0.103.16) and RUSTSEC-2026-0381 (webpki-roots < 1.0.10). Move each to its first fixed patch release with cargo update --precise, in the root and fuzz lockfiles, as #354 did for RUSTSEC-2026-0285. No other dependency changes. Co-Authored-By: Claude Opus 5.5 --- Cargo.lock | 18 +++++++++--------- crates/qbit-prism-server/fuzz/Cargo.lock | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8d5a3e49f..5a2f431f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -845,7 +845,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", - "webpki-roots 1.0.9", + "webpki-roots 1.0.10", ] [[package]] @@ -1709,7 +1709,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 1.0.9", + "webpki-roots 1.0.10", ] [[package]] @@ -1776,9 +1776,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.45" +version = "0.23.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" +checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" dependencies = [ "once_cell", "ring", @@ -1800,9 +1800,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.15" +version = "0.103.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" +checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281" dependencies = [ "ring", "rustls-pki-types", @@ -2739,14 +2739,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.9", + "webpki-roots 1.0.10", ] [[package]] name = "webpki-roots" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" +checksum = "1c1c8e20c8a38fc7d65abfe74eb7280e4aa667e8eec8bc84996d2874810748d9" dependencies = [ "rustls-pki-types", ] diff --git a/crates/qbit-prism-server/fuzz/Cargo.lock b/crates/qbit-prism-server/fuzz/Cargo.lock index e1fa40108..e1e9102fc 100644 --- a/crates/qbit-prism-server/fuzz/Cargo.lock +++ b/crates/qbit-prism-server/fuzz/Cargo.lock @@ -841,7 +841,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", - "webpki-roots 1.0.9", + "webpki-roots 1.0.10", ] [[package]] @@ -1639,7 +1639,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 1.0.9", + "webpki-roots 1.0.10", ] [[package]] @@ -1693,9 +1693,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.45" +version = "0.23.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" +checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" dependencies = [ "once_cell", "ring", @@ -1717,9 +1717,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.15" +version = "0.103.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" +checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281" dependencies = [ "ring", "rustls-pki-types", @@ -2620,14 +2620,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.9", + "webpki-roots 1.0.10", ] [[package]] name = "webpki-roots" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" +checksum = "1c1c8e20c8a38fc7d65abfe74eb7280e4aa667e8eec8bc84996d2874810748d9" dependencies = [ "rustls-pki-types", ] From def1fa0dcdc85fb2e16489ba8a9c2b6c51190191 Mon Sep 17 00:00:00 2001 From: Alexander Miller Date: Thu, 22 Oct 2026 11:27:32 -0400 Subject: [PATCH 3/3] 3.0.x: describe 3.0.0 as this line's production release The development-line note's status, not-done and upgrade sections, and the README banner, said no production release of the Rust server existed. With the coordinator's go-ahead for 3.0.0 they now point to 3.0.0 on 3.0.x and its notes, and say 3.x.x continues as 3.1. The 3.0.0 notes list the TLS dependency update. Co-Authored-By: Claude Opus 5.5 --- README.md | 11 ++++---- doc/release-notes-3.0.0.md | 12 ++++++-- doc/release-notes-3.x.x-development-line.md | 31 +++++++++++---------- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index ff270bbae..7784431b1 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ -> **WARNING: `3.x.x` is a development line and is not production-ready.** -> The production line is `2.x.x`. This branch carries the Rust PRISM server -> rewrite ([#244](https://github.com/Qbit-Org/qbit-mining-bootstrap/pull/244)), -> which has not been through a production release. Do not deploy it and do not -> point a production database at it. See -> [#283](https://github.com/Qbit-Org/qbit-mining-bootstrap/issues/283). +> **This is the `3.0.x` release branch: version 3.0.0 of the Rust PRISM server +> ([#244](https://github.com/Qbit-Org/qbit-mining-bootstrap/pull/244)).** +> Deploy it from the `v3.0.0` tag, and upgrade from `2.x.x` only as the +> [3.0.0 release notes](doc/release-notes-3.0.0.md#upgrading) describe: native +> migration is one-way. `3.x.x` continues as 3.1 and is not this release. # qbit-mining-bootstrap diff --git a/doc/release-notes-3.0.0.md b/doc/release-notes-3.0.0.md index c0897da16..cb2fda758 100644 --- a/doc/release-notes-3.0.0.md +++ b/doc/release-notes-3.0.0.md @@ -131,6 +131,13 @@ adds no migration ([Upgrading](#upgrading)). - **Operator rule:** keep qbitd's `-rpcservertimeout`, and the idle timeout of any proxy between a PRISM process and its node, above 20 s. qbitd's default, 30 s, is. +- TLS dependencies, for the RustSec advisories `cargo deny` reports against + rc.6's lockfile: rustls 0.23.45 to 0.23.46 (RUSTSEC-2026-0346, -0347, + -0348 and -0349), rustls-webpki 0.103.15 to 0.103.16 (RUSTSEC-2026-0382) + and webpki-roots 1.0.9 to 1.0.10 (RUSTSEC-2026-0381), in the root and fuzz + lockfiles. They are patch releases within the versions rc.6 already + resolved, with no other dependency change. The serving binary's + PostgreSQL (sqlx) and HTTPS (reqwest) clients use them. ## Upgrading @@ -176,8 +183,9 @@ adds no migration ([Upgrading](#upgrading)). ## Verification -The runtime changes between rc.6 and 3.0.0 are in `import-audits` -and in how long the node clients keep an idle connection: +The runtime changes between rc.6 and 3.0.0 are in `import-audits`, in how +long the node clients keep an idle connection, and in the TLS crates' patch +releases above: - #770, merged as `4c134913`: `import-audits` only, in `ledger/migration.rs` (`Ledger::import_legacy_audits_with` and its per-row transaction) and `tools.rs` (the command, its two settings, its stop diff --git a/doc/release-notes-3.x.x-development-line.md b/doc/release-notes-3.x.x-development-line.md index 876762d3e..7e568223f 100644 --- a/doc/release-notes-3.x.x-development-line.md +++ b/doc/release-notes-3.x.x-development-line.md @@ -1,13 +1,15 @@ # qbit-mining-bootstrap 3.x.x development line -Release date: none. This is a development line, not a release. +Release date: none. This is a development line, not a release. Its first +release is [3.0.0](release-notes-3.0.0.md), cut on the `3.0.x` branch. ## Status -The `3.x.x` branch is not production-ready. The production line is `2.x.x`; -its tip is version 2.0.2 (see `release-notes-2.0.2.md`, whose release date is still pending). Nothing on this -branch has been through a production release, and no production deployment -should run it or point a production database at it. +3.0.0 is the production release of this line, from the `3.0.x` branch, which +starts at `4c134913`. Deploy 3.0.0 from its tag, not from `3.x.x`: `3.x.x` +continues as 3.1 (3.1.0-rc.1 onwards), which 3.0.0 doesn't include. The +previous production line is `2.x.x`, whose tip is version 2.0.2 (see +`release-notes-2.0.2.md`); the upgrade from it is in the 3.0.0 notes. This line exists so that three engineers can work in parallel on the native Rust PRISM server without sharing one open pull request. Work is split into @@ -117,8 +119,7 @@ they fixed or configured no longer exists on this line: ## Not done yet -- There is no production release of the Rust server. The Postgres-backed and - live-regtest Rust suites need a PostgreSQL server and a `qbitd` binary; see +- The Postgres-backed and live-regtest Rust suites need a PostgreSQL server and a `qbitd` binary; see `test/prism-native-tests.sh`. They are not part of this note's verification. - The tree reads 3.0.0 ([its notes](release-notes-3.0.0.md); the release candidates' are [3.0.0-rc.1](release-notes-3.0.0-rc.1.md), @@ -132,19 +133,19 @@ they fixed or configured no longer exists on this line: ## Upgrade and rollback -No production cutover is supported yet. Do not point a production database at this line. The Rust -migrator refuses to start against a live legacy Python writer lease and -against an undrained legacy block outbox, but that is a guard against -accidental cutover, not release approval. +The supported production cutover is to 3.0.0, as its +[notes](release-notes-3.0.0.md#upgrading) and `docs/prism-rust-migration.md` +describe. The Rust migrator refuses to start against a live legacy Python +writer lease and against an undrained legacy block outbox, as a guard against +an accidental cutover. Decision D5 in #260 declares one-way native migration with forward repair and isolated-restore reconciliation, without down-migrations. #287 supplies the numbered procedures and exact queries in `docs/prism-rust-migration.md` and `docs/prism-ledger-ops.md`, and enforces audit import through production -`self-check`. #291 must rehearse the procedure on production-sized history, -record restore/import timings, and include the following identical data-loss -boundary already recorded in the [unreleased 3.0.0 notes](release-notes-3.0.0.md) -when preparing the actual release: +`self-check`. #291 records the rehearsal on production-sized history and its +restore and import timings. The [3.0.0 notes](release-notes-3.0.0.md) record +the same data-loss boundary: > Before the first native share is acknowledged, restore the complete > pre-migration database and artifact backup and restart the pinned old image