Extends AsbClient with one-way operation support (`IsOneWay = true`
in IASBIDataV2) plus the KeepAlive and Read operations.
Client API additions:
* `send_envelope_one_way(env)` — frames in SizedEnvelope, writes,
returns immediately. No response read. Mirrors WCF's IsOneWay
semantics for KeepAlive / Disconnect / AuthenticateMe.
* `send_signed_envelope_one_way(action, body, force_hmac)` —
one-way variant that runs the body through F23's authenticator
signing path so the ConnectionValidator header is attached.
* `keep_alive()` — sends an empty `KeepAliveRequest` with default
signing. Used to keep the channel alive past the WCF inactivity
timeout (30s default at `MxAsbDataClient.cs:683`).
* `read(items)` — sends a signed Read envelope, decodes
ReadResponse with both Status and Values arrays.
Operations API additions:
* `build_keep_alive_request_body()` — empty wrapper element +
asb.contracts.messages namespace. Mirror of `AsbContracts.cs:117`
(`public sealed class KeepAlive : ConnectedRequest;`).
* `ReadResponse { status: Vec<ItemStatus>, values: Vec<RuntimeValue> }`
per `AsbContracts.cs:169-179`.
* `decode_read_response(body_tokens)` — pulls both ASBIData
payloads, decodes Status as ItemStatus[], decodes Values via
`decode_runtime_value_array` (4-byte int32 count + per-element
`RuntimeValue::decode` from F24).
5 new tests:
* KeepAlive body shape (empty wrapper, correct namespace).
* ReadResponse decoder round-trip with both Status and Values.
* ReadResponse decoder graceful handling when Values is absent
(returns empty vec).
* End-to-end client::keep_alive — peer drains SizedEnvelope but
doesn't respond; client returns Ok().
* End-to-end client::read — peer responds with synthetic
ReadResponse, client recovers Values[0].timestamp_binary == 1234
and Values[0].status round-trip.
Stubbed for next F25 iterations:
* AsbClient::connect — DH Connect + AuthenticateMe handshake. Needs
ConnectRequest / ConnectResponse builders (regular WCF XML, not
the IAsbCustomSerializableType fast-path).
* Write / PublishWriteComplete / CreateSubscription /
AddMonitoredItems / Publish / Disconnect operation wrappers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
design/ — Rust port architectural plan
This folder is the design contract for the Rust replacement of AVEVA/Wonderware MXAccess. It is the gap between the .NET reference in src/ and the Rust crates that will be written under a sibling rust/ workspace (per CLAUDE.md).
The folder is structured as a small set of focused documents. Read in order; each builds on the previous.
| File | Purpose |
|---|---|
00-overview.md |
Mission, two-layer goal, architectural principles, non-goals |
10-raw-layer.md |
Byte-accurate raw MXAccess layer (codec + transport + session) |
20-async-layer.md |
Idiomatic Tokio async layer on top of the raw layer |
30-crate-topology.md |
Cargo workspace, crates, dependencies, build/test commands |
40-protocol-invariants.md |
Bill of materials: IIDs, opnums, envelope/handle bytes |
50-error-model.md |
MxStatus, error types, panic/cancellation policy |
60-roadmap.md |
Milestones M0..M6, validation strategy |
70-risks-and-open-questions.md |
Parity gaps, unproven flows, cross-platform constraints |
dependencies.md |
Cross- and within-milestone parallelism map; agent budget per phase |
review.md |
Adversarial review log (BLOCKER/MAJOR/MINOR/NIT findings, all resolved) |
prompt.md |
/loop driver prompt for autonomous M2–M6 execution |
followups.md |
Open / resolved deferred work items; auto-triaged by prompt.md Step 0 (created on first /loop run if missing) |
The design is grounded in the .NET reference at src/ and the protocol artifacts in docs/, analysis/, and captures/. Do not introduce protocol behavior in these documents that is not already proven in the reference. When adding a new claim about wire format, cite either:
- a
.csfile path insrc/MxNativeCodec/,src/MxNativeClient/, orsrc/MxAsbClient/, or - a
docs/*.mdspec file, or - a
captures/0NN-frida-*directory oranalysis/frida/*.tsvrow.
This folder is documentation, not code. When the Rust workspace is created, the design here is the contract it must satisfy. When evidence in captures/ invalidates a design decision here, update the design first, then the code.
Reading order
- New contributor: 00 → 30 → 10 → 40 → 20 → 50 → 60 → 70.
- Protocol question: 40 first, then the relevant section of 10.
- API question: 20 first, then 50.
- Planning a milestone: 60 first, cross-reference 70 for blockers.
- Scheduling concurrent work:
dependencies.mdfor the per-phase parallelism map. - Driving M2–M6 autonomously via
/loop:prompt.md(and thefollowups.mdtriage log it maintains).