Files
mxaccess/docs/ASB-Native-Integration-Decision.md
T
Joseph Doherty fe2a6db786
rust / build / test / clippy / fmt (push) Has been cancelled
Initial project state: .NET reference, design, Rust port (M0+M1), evidence
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>
2026-05-05 06:21:00 -04:00

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.