Write path online. GalaxyDriver implements IWritable; routes by
SecurityClassification — SecuredWrite / VerifiedWrite tags go through
MxCommandKind.WriteSecured, everything else through MxGatewaySession.
WriteAsync. Per-tag classifications are captured during ITagDiscovery via a
SecurityCapturingBuilder wrapper that intercepts Variable() calls without
the discoverer needing to know about the driver's internal state.
Files:
- Runtime/MxValueEncoder.cs — boxed CLR value → MxValue. Covers seven Galaxy
scalar types (bool/int8-32/uint8-32 → Int32, int64/uint64 → Int64, float,
double, string, DateTime/DateTimeOffset → Timestamp) and 1-D array
variants. Inverse of MxValueDecoder; round-trip pinned by tests.
DateTime.Local converts to UTC; unsupported types throw ArgumentException.
- Runtime/IGalaxyDataWriter.cs — driver-side seam. Tests inject a fake to
capture routing decisions; production path uses GatewayGalaxyDataWriter.
- Runtime/GatewayGalaxyDataWriter.cs — production. Lazy-AddItem caches
itemHandles, encodes value, routes Write vs WriteSecured, translates
MxCommandReply (ProtocolStatus → BadCommunicationError; first
MxStatusProxy in statuses[] via StatusCodeMap.FromMxStatus). Per-tag
exception isolation: one bad write doesn't fail the batch.
- GalaxyDriver: now implements IWritable. Discovery wraps the supplied
IAddressSpaceBuilder in SecurityCapturingBuilder which records each
attribute's SecurityClass into _securityByFullRef before delegating.
WriteAsync resolves classification per tag (FreeAccess default for
unknown tags — matches the legacy backend), routes through the injected
writer. Throws NotSupportedException with PR 4.4 pointer when no writer
is wired (production path requires GalaxyMxSession.Connect from PR 4.4).
Tests (32 new, 94 Galaxy total):
- MxValueEncoder: every scalar type, narrowing checks (sbyte/short/byte/
ushort fit Int32; uint within Int32 range; ulong within Int64),
DateTime.Local → UTC conversion, array variants for bool/double/string/
DateTime, Dimensions populated, unsupported-type throws ArgumentException,
encoder/decoder round-trip pin.
- GalaxyDriverWriteTests: WriteAsync routes through fake writer with
values intact; theory exercises every SecurityClassification value through
the discovery-then-write path; unknown-tag defaults to FreeAccess; empty-
request short-circuit; no-writer fail-loud; post-dispose throws.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>