fe2a6db786
rust / build / test / clippy / fmt (push) Has been cancelled
Layout:
- src/ .NET 10 x64 reference: MxNativeCodec, MxNativeClient,
MxAsbClient, probes, tests, harnesses. Executable spec.
- design/ Architectural plan for the Rust port (M0–M6), error
model, protocol invariants, risks (R1–R16), adversarial
review log (review.md).
- rust/ Rust workspace. M0 skeleton + M1 codec parity.
mxaccess-codec: 215 unit tests + 2 cross-implementation
parity tests (byte-identical against .NET reference).
Other crates are M0 stubs awaiting M2+.
- captures/ Frida + netsh + pcap evidence per CLAUDE.md
("captures are evidence, not throwaway logs").
- analysis/ Decompiled C# (frida/proxy/decompiled-*),
Ghidra exports for native DLLs (`exports/` only —
working state at `projects/` and AVEVA's input
binaries at `input/` are gitignored).
- docs/ Reverse-engineering reference docs.
- tools/ Setup-LiveProbeEnv.ps1 (Infisical credential fetcher),
Compute-Crc.ps1 (.NET parity helper).
- .github/workflows/ Rust CI: fmt + build + test + clippy on Windows.
- LICENSE MIT (Joseph Doherty, 2026).
Verified:
- cargo test --workspace → 217 passed (215 unit + 2 .NET parity), 0 failed
- cargo clippy --workspace -- -D warnings → clean
- cargo fmt --all -- --check → clean
- cargo publish --dry-run -p mxaccess-codec → packages cleanly
Excluded from history (see .gitignore):
- **/bin, **/obj, **/target — build artifacts
- analysis/ghidra/projects/ — Ghidra working state (regenerable)
- analysis/ghidra/input/ — AVEVA proprietary DLLs (vendor IP)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
139 lines
7.3 KiB
Markdown
139 lines
7.3 KiB
Markdown
# ASB / Native Integration Decision
|
|
|
|
## Decision
|
|
|
|
Use `MxAsbClient` as the preferred implementation for the regular tag data
|
|
plane. Do not embed ASB inside the current `MxNativeSession` transport. Instead,
|
|
introduce a higher-level compatibility facade that can route each MXAccess-style
|
|
operation to either ASB or native NMX behind a common server/item-handle model.
|
|
|
|
The boundary should be operation-based, not inheritance-based:
|
|
|
|
- ASB owns direct `IASBIDataV2` connect, register, unregister, read, write,
|
|
write-completion polling, publish subscriptions, cleanup, and explicit
|
|
reconnect.
|
|
- Native NMX owns COM/DCOM activation, NMX service registration, callback export,
|
|
Galaxy repository metadata resolution, native subscription callbacks, native
|
|
recovery replay, and MXAccess behaviors whose ASB equivalent is not proven.
|
|
- The existing `MxNativeClient` should remain available as the native fallback
|
|
and diagnostic path. ASB can replace its basic scalar/array read/write and
|
|
simple data-change usage only after a shared facade makes routing explicit.
|
|
|
|
This avoids coupling the WCF ASB channel lifecycle to the DCE/RPC callback
|
|
lifecycle while still letting callers move to the simpler pure-managed x64 ASB
|
|
path where evidence is strongest.
|
|
|
|
## Evidence
|
|
|
|
Current ASB evidence is strong for the normal data path:
|
|
|
|
- The pure .NET 10 x64 ASB client connects to the live `IASBIDataV2` net.tcp
|
|
endpoint, authenticates from local DPAPI-protected solution material, and
|
|
performs register/read/write without AVEVA assembly references.
|
|
- ASB register/read/write is live-proven for deployed scalar and array tags, and
|
|
`PublishWriteComplete` supplies write-handle completion records for basic
|
|
writes.
|
|
- ASB subscriptions can create subscriptions, add monitored items, publish
|
|
values, map quality/status payloads, and raise an MXAccess-like data-change
|
|
event through `MxAsbCompatibilityServer`.
|
|
- ASB now has public option objects for connection, write, write completion,
|
|
subscriptions, monitored items, cleanup, and reconnect.
|
|
|
|
Current native evidence is still required for legacy semantics:
|
|
|
|
- `MxNativeSession` owns NMX service activation, DCE/RPC transport, callback sink
|
|
registration, heartbeat/recovery, Galaxy metadata resolution, NMX write
|
|
message projection, `Write2`, `WriteSecured2`, supervisory advise, buffered
|
|
registration, and callback parsing.
|
|
- `MxNativeCompatibilityServer` models the fuller MXAccess surface:
|
|
`AddItem2`, `AuthenticateUser`, `ArchestrAUserToId`, `Suspend`, `Activate`,
|
|
`AdviseSupervisory`, `OnWriteComplete`, `OperationComplete`, and
|
|
`OnBufferedDataChange`.
|
|
- Direct `IASBIDataV2` exposes no activate, suspend, or generic
|
|
`OperationComplete` operation. It only exposes write-completion polling.
|
|
- ASB buffered monitored items are accepted by the observed provider, but publish
|
|
still returns one current value rather than a native buffered sample batch.
|
|
- Direct system-auth ASB writes did not reproduce the public MXAccess secured
|
|
write rejection path on this VM.
|
|
|
|
## Recommended Boundary
|
|
|
|
Create a routing layer above both clients. It should hold compatibility
|
|
server/item handles and choose a backend per operation:
|
|
|
|
- `Register`, `Unregister`, `AddItem`, `RemoveItem`, `Read`, basic `Write`,
|
|
simple `Advise`, `UnAdvise`, and write-completion polling should default to
|
|
ASB when an ASB endpoint is configured and the tag/value shape is supported.
|
|
- `Write2`, `WriteSecured2`, `AuthenticateUser`, `ArchestrAUserToId`, `Suspend`,
|
|
`Activate`, `AdviseSupervisory`, buffered items, and native callback-only
|
|
events should route to native NMX until direct ASB evidence exists.
|
|
- `OperationComplete` should not be synthesized from ASB write completion. ASB
|
|
write completion can raise a write-complete event, but generic operation
|
|
completion remains native-only until a native trigger and payload mapping are
|
|
proven.
|
|
- The facade should expose which backend handled an item or operation so tests,
|
|
probes, logs, and callers can distinguish ASB behavior from native fallback.
|
|
|
|
## What ASB Should Own
|
|
|
|
- Endpoint discovery/configuration inputs for the direct `IASBIDataV2` route.
|
|
- Connection/authentication, request signing, channel cleanup, reconnect, and
|
|
connection-failure cleanup for ASB.
|
|
- ASB item identity creation, register/unregister/read, variant
|
|
encode/decode, and supported scalar/array writes.
|
|
- `AsbWriteOptions` and `AsbWriteCompletionOptions` driven write completion,
|
|
including delayed readback when requested.
|
|
- ASB subscription creation, monitored item creation/deletion, publish polling,
|
|
quality/status mapping, and basic MXAccess-compatible data-change adaptation.
|
|
- ASB-specific result/status summaries that preserve raw provider status while
|
|
exposing named categories for known cases.
|
|
|
|
## What Native NMX Should Still Own
|
|
|
|
- DCE/RPC, COM object reference handling, NTLM/SSPI authentication, callback
|
|
export, and NMX service registration.
|
|
- Galaxy repository tag resolution and metadata needed for NMX reference handles,
|
|
value-kind projection, and native buffered registration.
|
|
- `Write2` and `WriteSecured2` until ASB timestamped and secured-write parity is
|
|
explicitly proven.
|
|
- `Suspend`, `Activate`, supervisory advise, native recovery replay, heartbeat
|
|
policy, and callback-derived event surfaces.
|
|
- `OnBufferedDataChange` and generic `OperationComplete` until ASB produces
|
|
equivalent runtime evidence.
|
|
- Native diagnostic/probe coverage for payloads that ASB does not expose.
|
|
|
|
## Risks And Unknowns
|
|
|
|
- ASB endpoint discovery/configuration is environment-specific; fallback to NMX
|
|
must be explicit when no usable endpoint is configured.
|
|
- ASB access-denied, no-communication, and other live fault status cases still
|
|
need safe source conditions before they can be treated as complete parity.
|
|
- The exact native completion-only byte-to-status mapping is not fully proven.
|
|
- ASB buffered publish behavior may vary by provider or configuration; the
|
|
observed provider did not produce multi-sample batches.
|
|
- Dual routing can create semantic drift if the facade hides backend choice.
|
|
Backend selection must be visible in diagnostics and test assertions.
|
|
- Mixing ASB and native subscriptions for the same logical item can duplicate
|
|
callbacks or produce ordering differences; route each item to one backend at a
|
|
time.
|
|
|
|
## Staged Migration
|
|
|
|
1. Add a small shared facade project or class that exposes the MXAccess-style
|
|
handle API and delegates to `MxAsbCompatibilityServer` or
|
|
`MxNativeCompatibilityServer`.
|
|
2. Start with opt-in ASB routing for basic register/read/write/simple-advise
|
|
flows. Keep native as the default fallback for unsupported operations.
|
|
3. Add route annotations to events and probe output so every data-change,
|
|
write-complete, and fallback decision identifies `asb` or `native`.
|
|
4. Port basic compatibility tests to run against the facade with ASB-for-data
|
|
enabled and native fallback enabled. Preserve existing ASB-only and
|
|
native-only tests.
|
|
5. Gate any additional replacement on evidence: timestamped ASB write behavior,
|
|
secured-write behavior, buffered sample batches, and native
|
|
operation-complete parity should each require a focused capture or live probe
|
|
before moving from native to ASB.
|
|
6. After the facade is stable, treat `MxNativeClient` as the legacy/native
|
|
adapter and `MxAsbClient` as the primary data adapter. Avoid merging their
|
|
transport internals.
|