feat(antd): live network health on /health — write_ready, peer counts, last-store age (V2-1027) - #241
Conversation
…, last-store age (V2-1027) Both health surfaces (REST /health, gRPC HealthService.Check) were static snapshots of startup state: a daemon with zero peers reported status:ok while every store failed (ant-sdk#232). They now report: - write_ready: max(routing_table_size, connected_peers) >= threshold — best-effort write-path floor; the max() is load-bearing (client-mode routing tables under-report, see V2-1036) - connected_peers / routing_table_size / rebootstrap_threshold - last_store_ok_secs_ago, stamped on every successful store-type operation across all 7 REST + 7 gRPC write paths (null until the first success this process) All fields additive on both wire surfaces; status:ok semantics are untouched so existing liveness probes keep working. antd-rust models updated in the same change (it regenerates from the shared proto and cannot lag); the other 15 SDKs are V2-1040. MERGE GATE: do not merge before the matching saorsa-core recovery fix lands (WithAutonomi/saorsa-core#153 / V2-1036). Without it a degraded client can report write_ready:false indefinitely with no runtime remedy (the repair path could never heal), and REBOOTSTRAP_THRESHOLD in state.rs mirrors the saorsa-core const that #153 makes public. Verified live: peerless daemon (write_ready:false, rt 0), mainnet (write_ready:true, 5 peers), and a full devnet decay reproduction of the reporter's incident — timeline and evidence on V2-1027. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…th-write-readiness
…e re-bootstrap recovery The merge gate for this PR: saorsa-core#153 (V2-1036) shipped in saorsa-core 0.27.2, reaching antd through ant-protocol 2.3.4 / ant-core 0.8.0. With it in the graph, a client below the rebootstrap threshold heals at runtime and write_ready can recover instead of sticking false. REBOOTSTRAP_THRESHOLD stays mirrored: saorsa-core 0.27.3 marks the upstream const pub, but its module is pub(crate) and nothing re-exports it, so it is still unreachable for consumers. antd: cargo test 63/63, clippy -D warnings clean against the new graph. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
dirvine
left a comment
There was a problem hiding this comment.
Requesting changes for one runtime blocker found in review.
P1 — the locked dependency does not contain the recovery this PR claims to pick up. antd/Cargo.lock resolves saorsa-core to 0.27.2. The client-mode runtime re-bootstrap change from WithAutonomi/saorsa-core#153 was released in 0.27.3, not 0.27.2. Because daemon CI/builds use --locked, this head still produces an antd binary without that recovery while exposing readiness as if the corresponding runtime behaviour were present. Please update the lock to 0.27.3 and re-run the locked checks. I verified cargo update -p saorsa-core --precise 0.27.3 --dry-run resolves cleanly.
Two non-runtime contract issues should be addressed in the same pass:
ant-core0.8.0 already exportsNetwork::health(),NetworkHealth, andREBOOTSTRAP_THRESHOLD, explicitly to keep one readiness formula forantd, FFI, GUI, etc.antd/src/state.rsduplicates that implementation and constant. Delegate the peer/routing snapshot toself.client.network().health().await, then add only the daemon-locallast_store_ok_secs_ago, so the advertised threshold cannot drift from the implementation.- The public contract rollout is incomplete:
antd/openapi.yaml,llms-full.txt, and the vendored/generated health surfaces in the other SDKs still stop atpayment_vault_address(the Kotlin proto copy is already inconsistent withantd/proto/antd/v1/health.proto). At minimum, update the canonical OpenAPI/reference docs and either synchronise generated clients or clearly scope a tracked compatibility follow-up. Add REST assertions for the new fields and daemon-level tests for readiness/last-store transitions; current Rust client tests cover gRPC fields but do not exercise those server transitions.
Verification at this exact head: all three GitHub checks pass; locally cargo fmt --check, cargo test --locked, and clippy with -D warnings pass for both antd and antd-rust. The additive protobuf numbering and serde defaults are wire-compatible.
| [[package]] | ||
| name = "saorsa-core" | ||
| version = "0.27.0" | ||
| version = "0.27.2" |
There was a problem hiding this comment.
P1 (blocking): this locks the daemon to saorsa-core 0.27.2, but the client-mode runtime re-bootstrap recovery from WithAutonomi/saorsa-core#153 is in 0.27.3. With --locked, this PR's advertised recovery is therefore absent. Please resolve the lock to 0.27.3 and rerun locked CI.
| /// auto-re-bootstraps. v0.27.3 marked it `pub`, but its module is | ||
| /// `pub(crate)` and nothing re-exports it, so it remains unreachable for | ||
| /// consumers. Keep in sync until saorsa-core exports it at crate root. | ||
| pub const REBOOTSTRAP_THRESHOLD: usize = 3; |
There was a problem hiding this comment.
P2: ant-core 0.8.0 already exports REBOOTSTRAP_THRESHOLD, NetworkHealth, and Network::health() specifically as the shared implementation for antd and other embedded clients. Mirroring the constant and formula here creates two sources of truth. Please reuse self.client.network().health().await and layer only last_store_ok_secs_ago in AppState.
…core (review) P1: the lock resolved saorsa-core 0.27.2, which does NOT contain the runtime re-bootstrap recovery (saorsa-core#153) — v0.27.2 was cut before the merge despite its later tag date; 0.27.3 is the first release carrying it. With --locked builds the daemon would have advertised recovery semantics its binary lacked. Lock now pins 0.27.3. P2: drop antd's mirrored REBOOTSTRAP_THRESHOLD and duplicated readiness formula; the peer/routing snapshot now comes from ant-core's Network::health() (the shared implementation), with only the daemon-local last_store_ok_secs_ago layered on via a StoreMarker newtype. Daemon-level tests cover the store-marker transition, the compose layering, and degraded -> recovered readiness. Contract rollout: openapi.yaml HealthResponse and llms-full.txt (REST + gRPC sections) now document all five fields; the Kotlin proto source copy is synced with antd/proto/antd/v1/health.proto. Wider generated-SDK fan-out stays tracked as V2-1040. antd: cargo test 66/66, fmt + clippy -D warnings clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
dirvine
left a comment
There was a problem hiding this comment.
Re-reviewed at f5e2a394dd0249da93b886fef1bc3853b877836c. The blocking dependency mismatch is resolved: antd/Cargo.lock now pins saorsa-core 0.27.3, and readiness delegates to ant_core::Network::health(). OpenAPI/proto surfaces and daemon transition coverage are updated; the remaining SDK fan-out is tracked separately. Local fmt, full locked tests, and clippy pass for antd and antd-rust; GitHub checks and security audit are green.
Non-blocking: a positive REST-client assertion for the five new fields would complement the existing old-daemon compatibility fixture, server JSON assertions, and gRPC coverage.
Important
Gate cleared (2026-09-03). saorsa-core#153 (V2-1036) merged 2026-08-28 and is first contained in saorsa-core v0.27.3 (v0.27.2 was cut before the merge despite its later tag date); the lock now pins 0.27.3 via the ant-core
ant-cli-v0.3.5(0.8.0) bump, so the repair path heals at runtime andwrite_readycan recover. The peer/routing snapshot and readiness formula are delegated to ant-core'sNetwork::health()(one source of truth); antd layers only the daemon-locallast_store_ok_secs_ago. Generated-SDK health surfaces beyond the Kotlin proto copy are tracked as V2-1040.What
Both health surfaces (REST
/health, gRPCHealthService.Check) were static snapshots of startup state: a daemon with zero peers reportedstatus:okwhile every store failed (#232). They now report live network state:write_ready:max(routing_table_size, connected_peers) >= threshold— best-effort write-path floor; themax()is load-bearing (client-mode routing tables under-report, see V2-1036)connected_peers/routing_table_size/rebootstrap_thresholdlast_store_ok_secs_ago: stamped on every successful store-type operation across all 7 REST + 7 gRPC write paths (nulluntil the first success this process)All fields are additive on both wire surfaces;
status:oksemantics are untouched so existing liveness probes keep working. antd-rust models are updated in the same change (it regenerates from the shared proto and cannot lag); the other 15 SDKs are V2-1040.Verification
write_ready:false, rt 0), mainnet (write_ready:true, 5 peers), and a full devnet decay reproduction of the reporter's incident — timeline and evidence on V2-1027Follow-ups
network_health()becomes a pass-through and drops the mirrored const🤖 Generated with Claude Code
Closes #232.