Add field correctness diagnostics: store invariant audit, drop and bounds proofs

ConversationStore.auditInvariants() verifies the per-conversation and
store-level message-ID indexes, caps, timestamp ordering, unread-set
membership, and selection validity - wired to the existing read-receipt
cleanup cadence, loud (.error) on violation, sampled heartbeat when
healthy (~2.8ms per audit at 5k messages, benchmarked and floored).
Router drops log both outcomes (marked failed / skipped by no-downgrade
guard); relay cap evictions, age sweeps, and jittered reconnect delays
log their counts; mirrored republishes get a sampled proof line. 11 new
invariant tests corrupt store state through DEBUG-only hooks since the
single-writer lockdown makes those states unreachable via intents.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jack
2026-06-11 19:28:47 +02:00
co-authored by Claude Fable 5
parent 22be3d6392
commit 8899cb7f9e
8 changed files with 504 additions and 9 deletions
@@ -496,6 +496,34 @@ final class PerformanceBaselineTests: XCTestCase {
reportThroughput("store.append", samples: samples, operations: messageCount, unit: "messages")
}
// MARK: - 8. ConversationStore invariant audit (field observability)
/// `ConversationStore.auditInvariants()` over a realistic 5k-message
/// corpus (mesh + geohash + 75 private chats). The audit runs in the
/// field on the read-receipt cleanup cadence
/// (`ChatViewModel.auditConversationStore`), so this measures the
/// per-audit cost that piggybacks on peer-list updates it must stay
/// trivially cheap relative to that cadence.
func testConversationStoreAudit() {
let context = PerfDeliveryContext.makeCorpus(publicCount: 2000, peerCount: 75, messagesPerPeer: 40)
let store = context.store
XCTAssertEqual(store.totalMessageCount, 5000)
let repsPerPass = 20
var samples: [TimeInterval] = []
measure {
let start = Date()
var violationCount = 0
for _ in 0..<repsPerPass {
violationCount += store.auditInvariants().count
}
samples.append(Date().timeIntervalSince(start))
XCTAssertEqual(violationCount, 0, "healthy corpus must audit clean")
}
reportThroughput("store.audit", samples: samples, operations: repsPerPass, unit: "audits")
}
/// Spins the main run loop in small slices (draining main-queue tasks and
/// timers) until `condition` holds or `timeout` elapses.
private func spinMainRunLoop(timeout: TimeInterval, until condition: () -> Bool) -> Bool {
+4 -2
View File
@@ -24,7 +24,8 @@
"formatting.formatMessage": 12261,
"pipeline.privateIngest": 24848,
"pipeline.publicIngest": 13102,
"store.append": 213201
"store.append": 213201,
"store.audit": 362
},
"floors": {
"nostrInbound.fresh": 530,
@@ -36,6 +37,7 @@
"formatting.formatMessage": 3000,
"pipeline.privateIngest": 6000,
"pipeline.publicIngest": 3200,
"store.append": 53000
"store.append": 53000,
"store.audit": 90
}
}