cultmesh-rs: RUDP document server answers writes with write_admitted / error.v1 #60

Merged
libby merged 11 commits from libby/rs-write-receipt-server into main 2026-11-08 19:49:50 +00:00
Member

Rust server side of the write-receipt spec (#59, not yet merged; this PR branches from main and pins the spec's hashes in its own tests). Scope: cultnet-rs frames and CultMeshRudpDocumentServer; no other runtime, no TS/C#/Python server.

  • cultnet-rs: CultNetMessage::WriteAdmitted (cultnet.write_admitted.v0), CultNetMessage::ErrorV1 (cultnet.error.v1, v0 + messageId), write_content_hash (SHA-256 of [operation, schemaId, recordKey, payload]). tests/write_receipt.rs pins the four worked hashes from write-receipt-vectors.json and round-trips both frames.
  • Server: a session is receipt-capable only when its hello lists both new frames (framing only; the sink's admission is unchanged). On such a session an admitted put is answered with write_admitted after the sink accepts it (best effort: a receipt that cannot be queued is dropped, never turned into a refusal); a refusal is an error.v1 carrying the write's id; a resend of the same id and content is re-receipted without reaching the sink; the same id with other content is refused message_invalid (details messageId), never re-receipted. Other sessions are answered exactly as before.
  • Failing then green: 6 new tests in tests/rudp_document_server.rs (5 failed before the server change; the no-capability test passed because it pins today's behaviour). Mutants killed: reuse-with-other-content treated as resend, capability needing one frame instead of both (needed a new test), v0 error always, error without id, no dedupe memory. cultmesh-rs 32+28+12 and cultnet-rs suites pass.
  • Deviations from #59, stated: this server has no authenticated actor beyond the RUDP session, so the dedupe key is (session, messageId) and the table lives as long as the session (the spec's 10-minute retention is not met for sessions that expire sooner); a session remembers at most 1024 admitted writes and refuses new ones with PayloadBudgetFull rather than forget an id. Deletes are still refused (DeleteNotSupported) and now carry their id on a receipt-capable session.

🤖 Generated with Claude Code

Rust server side of the write-receipt spec (#59, not yet merged; this PR branches from main and pins the spec's hashes in its own tests). Scope: `cultnet-rs` frames and `CultMeshRudpDocumentServer`; no other runtime, no TS/C#/Python server. - **cultnet-rs**: `CultNetMessage::WriteAdmitted` (`cultnet.write_admitted.v0`), `CultNetMessage::ErrorV1` (`cultnet.error.v1`, v0 + `messageId`), `write_content_hash` (SHA-256 of `[operation, schemaId, recordKey, payload]`). `tests/write_receipt.rs` pins the four worked hashes from `write-receipt-vectors.json` and round-trips both frames. - **Server**: a session is receipt-capable only when its hello lists both new frames (framing only; the sink's admission is unchanged). On such a session an admitted put is answered with `write_admitted` after the sink accepts it (best effort: a receipt that cannot be queued is dropped, never turned into a refusal); a refusal is an `error.v1` carrying the write's id; a resend of the same id and content is re-receipted without reaching the sink; the same id with other content is refused `message_invalid` (details `messageId`), never re-receipted. Other sessions are answered exactly as before. - **Failing then green**: 6 new tests in `tests/rudp_document_server.rs` (5 failed before the server change; the no-capability test passed because it pins today's behaviour). Mutants killed: reuse-with-other-content treated as resend, capability needing one frame instead of both (needed a new test), v0 error always, error without id, no dedupe memory. cultmesh-rs 32+28+12 and cultnet-rs suites pass. - **Deviations from #59, stated**: this server has no authenticated actor beyond the RUDP session, so the dedupe key is `(session, messageId)` and the table lives as long as the session (the spec's 10-minute retention is not met for sessions that expire sooner); a session remembers at most 1024 admitted writes and refuses new ones with `PayloadBudgetFull` rather than forget an id. Deletes are still refused (`DeleteNotSupported`) and now carry their id on a receipt-capable session. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
cultmesh-rs: RUDP document server answers writes with write_admitted / error.v1 (write-receipt spec)
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Has been cancelled
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Has been cancelled
9f73047c29
cultnet-rs gains cultnet.write_admitted.v0, cultnet.error.v1 (v0 + messageId) and
write_content_hash. The server opts a session in only when its hello lists both frames
(framing only; admission rules are unchanged). On an opted-in session an admitted put is
answered with a receipt carrying its id after the sink accepts it, a refusal is an error.v1
naming the id, a resend of the same content is re-receipted without reaching the sink, and the
same id with other content is refused message_invalid (never the old receipt). Other sessions
are answered exactly as before.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
cultmesh-rs: receipt server follows Heimdall's review of #60
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Failing after 7m11s
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Successful in 26s
8bd31a5d4a
A refused put, a full dedupe table and a reused id refuse the write, not the
session; only a protocol violation ends one. A frame that does not decode but
holds a messageId is refused with that id. The server answers a receipt-capable
hello with its own, listing both frames. The sink's authorization (new
authorize_raw_document, default admit) runs before the session's remembered
writes are consulted. A second hello does not change the capability: it is set
once, by the first hello or the first write. A receipt that cannot be queued, and
a write the payload budget would drop silently, end the session instead of
leaving the write unanswered. Refusals to a receipt-capable session are queued
reliably.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
cultmesh-rs: receipt server looks the id up first, remembers refusals, answers deletes and unqueueable refusals
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Failing after 4m47s
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Has been cancelled
d4f440ac7c
Follows Heimdall's second review of #60: replay by (session,id) before any
authorization; refusals stored with their hash; delete shares the dedupe
table and settles capability; a refusal the queue cannot take ends the
session; a peer's refusal frames and a receipt session's refused deletes are
not violations; the write limit has its own fixed text; the sink trait says
Ok means committed and visible.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
cultmesh-rs: a put reusing a delete's id is refused (mutant-driven test)
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Has been cancelled
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Has been cancelled
5f699c27fa
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
cultnet-rs, cultmesh-rs: remembered-write cap refusal is error.v1 limit_reached; pin authorize-once with a counting sink
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Failing after 5m19s
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Successful in 41s
0182a6d40b
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
cultnet-rs, cultmesh-rs: write_admitted in spec field order; server-wide remembered-write budget over digest entries; id size limit; limit refusals remembered; unreliable writes refused; local failure is its own goodbye
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Failing after 5m14s
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Successful in 46s
1447ccd8dd
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
cultmesh-rs: pin limit-refusal memory bound and legacy unreliable drop (mutant-driven tests)
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Has been cancelled
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Has been cancelled
d7b36416c6
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
cultnet-rs, cultmesh-rs: null or missing document/schemaId refused naming the field; budget tests use literal bytes; unreliable-refusal local failure test
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Failing after 5m33s
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Successful in 26s
c8f869e54e
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
cultmesh-rs: server-wide remembered-write budget is a maintained counter; a session whose refusal set overflowed refuses unseen ids after the budget frees
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Failing after 5m35s
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Successful in 1m1s
1a05df2524
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
cultmesh-rs: a receipt session accepts writes only on a reliable, non-sequenced channel; a test pins that a reconnect starts a fresh session
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Failing after 10m5s
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Successful in 1m8s
e4b67a9e0b
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
cultmesh-rs: a refused reliable-sequenced write is received and acknowledged first, and a refused write counts as session activity
Some checks failed
CultMesh QUIC native / Build win32-x64 (pull_request) Has been skipped
CultMesh QUIC native / Build linux-x64 (pull_request) Has been skipped
CultMesh QUIC native / Release native binaries (pull_request) Has been skipped
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (pull_request) Failing after 6m11s
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Successful in 52s
90d252735f
Refusing before session.receive left the packet unacknowledged: the client resent it forever and every later ordered write stalled. The test now uses the same peer and proves a later ordered write is admitted.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
libby merged commit 36494dafb9 into main 2026-11-08 19:49:50 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
GameCult/CultLib!60
No description provided.