C#: a put or delete with an empty or blank schemaId or recordKey is refused message_invalid (as an unreadable frame, like the Rust server) and not applied
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 31s

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Libby 2026-11-08 19:46:45 +00:00
commit 1a228349f1
2 changed files with 57 additions and 0 deletions

View file

@ -391,6 +391,14 @@ namespace GameCult.Networking
}
// A refusal: error.v1 carrying the write's id for a receipt-capable connection, the v0 error for any other.
// An empty or blank schemaId or recordKey names no record: refused as a frame that does not read, exactly as the Rust
// server's decoder refuses it (write-receipt.md, "Required fields"), never handed to the store.
private static bool IsUnreadableWriteTarget(string? schemaId, string? recordKey) =>
string.IsNullOrWhiteSpace(schemaId) || string.IsNullOrWhiteSpace(recordKey);
private static CultNetErrorMessage UnreadableWriteTarget() =>
CultNetErrorMessage.ForMessageInvalid("message", "the message could not be read");
private static void Refuse(CultNetServerPeer peer, CultNetReceiptedWrite? write, CultNetErrorMessage error)
{
if (write != null) write.Refused(error);
@ -431,6 +439,12 @@ namespace GameCult.Networking
return;
}
if (IsUnreadableWriteTarget(message.Document!.SchemaId, message.Document.RecordKey))
{
Refuse(peer, write, UnreadableWriteTarget());
return;
}
if (write != null && !write.Begin()) return;
var authorize = Authorize(peer, CultNetRemoteWriteOperation.Put, message.ShardId, message.ShardEpoch);
@ -506,6 +520,12 @@ namespace GameCult.Networking
return;
}
if (IsUnreadableWriteTarget(message.SchemaId, message.RecordKey))
{
Refuse(peer, write, UnreadableWriteTarget());
return;
}
if (write != null && !write.Begin()) return;
var authorize = Authorize(peer, CultNetRemoteWriteOperation.Delete, message.ShardId, message.ShardEpoch);