cultmesh-rs: a sink's refusal of a put is a typed write_not_authorized #35

Merged
libby merged 1 commit from libby/cultmesh-rs-typed-refusal into main 2026-11-07 19:31:48 +00:00
Member

A host sink refusal in rudp_document_server.rs reached the peer as an untyped Error (code None). It now sends write_not_authorized with details {field: recordKey, value: <key>}, as C#, TS and Python do. The text is still the fixed variant text (write_not_authorized: the catalog refused the document), never the sink's own. CultMeshRudpApplicationRejection gains record_key: Option<String> (set for put rejections). Other rejections stay untyped; the client-side recognised_refusal strips the new prefix so its quoting still works.

Tests: unit test pins write_refused_message("some:key", "not granted") to the write_not_authorized bytes of error-vectors.json; integration tests assert code, details and text on the wire and that a refused put reaches no sink (receipts == 0). With the typed branch disabled, two integration tests fail. cargo test for the crate: 23 + 12 + 19 pass.

Follow-ups (not in this PR): delete handling (this server has no delete path; ~40 lines + tests); a deny-by-default authority port so a sink refusal is the authority's decision, with a grant-all opt-in as in C#/Py (~120 lines + tests, breaking for embedders).

🤖 Generated with Claude Code

A host sink refusal in `rudp_document_server.rs` reached the peer as an untyped `Error` (code `None`). It now sends `write_not_authorized` with `details {field: recordKey, value: <key>}`, as C#, TS and Python do. The text is still the fixed variant text (`write_not_authorized: the catalog refused the document`), never the sink's own. `CultMeshRudpApplicationRejection` gains `record_key: Option<String>` (set for put rejections). Other rejections stay untyped; the client-side `recognised_refusal` strips the new prefix so its quoting still works. Tests: unit test pins `write_refused_message("some:key", "not granted")` to the `write_not_authorized` bytes of `error-vectors.json`; integration tests assert code, details and text on the wire and that a refused put reaches no sink (`receipts == 0`). With the typed branch disabled, two integration tests fail. `cargo test` for the crate: 23 + 12 + 19 pass. Follow-ups (not in this PR): delete handling (this server has no delete path; ~40 lines + tests); a deny-by-default authority port so a sink refusal is the authority's decision, with a grant-all opt-in as in C#/Py (~120 lines + tests, breaking for embedders). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
cultmesh-rs: a sink's refusal of a put is a typed write_not_authorized
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 5m48s
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (pull_request) Successful in 55s
74ccfaf67a
The RUDP document server sent a host sink's refusal as an untyped Error (code None).
It now sends write_not_authorized with details naming the record, as C#, TS and
Python do; the text stays the fixed variant text, never the sink's. The rejection
carries the put's record_key. Other rejections stay untyped. Unit test pins the
bytes to the error-vectors.json write_not_authorized vector; integration tests
check code/details on the wire and that a refused put reaches no sink.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
libby merged commit 10c1f4dd00 into main 2026-11-07 19:31:48 +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!35
No description provided.