fix(gateway): resolve 2026-06-18 array-write review findings
- Server-057: extend []-suffix normalization to AddItemBulk/AddBufferedItem so bulk-added array tags bind write-capable handles (authz check, worker bind, and registration kept consistent); update gateway.md + client READMEs. Tests: AddItemBulk/AddBufferedItem wiring. - Server-058: assert []-fallback-resolved bare array names are still denied when out of read/write scope and that MaxWriteClassification is enforced on suffixed array registrations. - Contracts-023/024/025: round-trip + field-19 descriptor pin for MxSparseArray; document MxSparseArray in docs/Contracts.md; enumerate it in the protocol-version-3 test summary. - Tests-040: add wiring tests for the six uncovered sparse-write arms (WriteSecured, Write2, WriteSecured2, Write2Bulk, WriteSecuredBulk, WriteSecured2Bulk). dotnet build + targeted tests green (184 passed).
This commit is contained in:
@@ -987,6 +987,19 @@ public sealed class GatewaySession
|
||||
break;
|
||||
case MxCommand.PayloadOneofCase.AddItem2:
|
||||
command.AddItem2.ItemDefinition = NormalizeAddress(command.AddItem2.ItemDefinition);
|
||||
break;
|
||||
case MxCommand.PayloadOneofCase.AddBufferedItem:
|
||||
command.AddBufferedItem.ItemDefinition = NormalizeAddress(command.AddBufferedItem.ItemDefinition);
|
||||
break;
|
||||
case MxCommand.PayloadOneofCase.AddItemBulk:
|
||||
// Normalize each bare array address in place so the worker binds a write-capable handle
|
||||
// for every array tag in the batch (the same IsArray-gated rewrite the single-add path
|
||||
// applies). Scalar addresses pass through unchanged.
|
||||
for (int i = 0; i < command.AddItemBulk.TagAddresses.Count; i++)
|
||||
{
|
||||
command.AddItemBulk.TagAddresses[i] = NormalizeAddress(command.AddItemBulk.TagAddresses[i]);
|
||||
}
|
||||
|
||||
break;
|
||||
case MxCommand.PayloadOneofCase.Write:
|
||||
ExpandValue(command.Write.Value);
|
||||
@@ -1089,9 +1102,16 @@ public sealed class GatewaySession
|
||||
TrackItem(command.AddItem2.ServerHandle, reply.AddItem2.ItemHandle, NormalizeAddress(command.AddItem2.ItemDefinition));
|
||||
break;
|
||||
case MxCommandKind.AddBufferedItem when reply.AddBufferedItem is not null:
|
||||
TrackItem(command.AddBufferedItem.ServerHandle, reply.AddBufferedItem.ItemHandle, command.AddBufferedItem.ItemDefinition);
|
||||
// The reply carries no address, so tracking keys off the command's ItemDefinition;
|
||||
// re-apply the array-suffix normalization (the tracking copy is a separate, un-mutated
|
||||
// instance from the one forwarded at the InvokeAsync choke point) so the registration
|
||||
// matches the write-capable handle the worker bound.
|
||||
TrackItem(command.AddBufferedItem.ServerHandle, reply.AddBufferedItem.ItemHandle, NormalizeAddress(command.AddBufferedItem.ItemDefinition));
|
||||
break;
|
||||
case MxCommandKind.AddItemBulk when reply.AddItemBulk is not null:
|
||||
// The worker echoes back the (already-normalized) address it bound in each
|
||||
// SubscribeResult.TagAddress, so TrackBulkItems stores the suffixed array address
|
||||
// without re-normalizing here.
|
||||
TrackBulkItems(reply.AddItemBulk);
|
||||
break;
|
||||
case MxCommandKind.SubscribeBulk when reply.SubscribeBulk is not null:
|
||||
|
||||
Reference in New Issue
Block a user