Initial project state: .NET reference, design, Rust port (M0+M1), evidence
rust / build / test / clippy / fmt (push) Has been cancelled
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>
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user