Files
mxaccess/CHANGELOG.md
T
Joseph Doherty 7b15c853d1 [F43] release prep: CHANGELOG + cargo publish --dry-run validation
V1 release prep per M6 DoD bullet 6:

**`CHANGELOG.md`** — V1 release notes covering all 9 workspace crates
(`mxaccess-codec`, `mxaccess-rpc`, `mxaccess-asb-nettcp`,
`mxaccess-asb`, `mxaccess-galaxy`, `mxaccess-callback`,
`mxaccess-nmx`, `mxaccess`, `mxaccess-compat`), the M0 → M6
milestone closeouts, deliberate divergences from the .NET reference
(multi-record DataUpdate codec relaxation per F44; buffered single-
sample stream per R2), and known limitations (F3 cross-domain NTLM,
F45 buffered recovery replay, F46 Suspend/Activate wire instrumentation,
R3/R4 OperationComplete trigger). Documents the dependency-ordered
publish sequence (leaf crates first; dependent crates require their
deps to exist on crates.io before their dry-runs can run).

**`cargo publish --dry-run` validation:**
- Leaf crates (mxaccess-codec, mxaccess-rpc, mxaccess-asb-nettcp):
  dry-run passes — tarball builds, metadata complete, license/
  description/repository/rust-version all present via
  `workspace.package`.
- Dependent crates (mxaccess-asb, mxaccess-galaxy, mxaccess-callback,
  mxaccess-nmx, mxaccess, mxaccess-compat): dry-run fails with
  "no matching package" against crates.io — expected behaviour, the
  registry lookup happens even with `--no-verify`. Validation of
  these crates falls to the build-test-clippy-public_api matrix
  rather than dry-run.

`design/followups.md`: F43 moved to Resolved with a verdict pointing
at this commit + the CHANGELOG.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 05:33:43 -04:00

5.8 KiB
Raw Blame History

Changelog

All notable changes to the mxaccess workspace are documented here. The format follows Keep a Changelog; the workspace as a whole follows SemVer but the 0.0.x line is pre-release / API-unstable.

[Unreleased] — V1 — 2026-05-06

V1 is the first publishable cut. Closes M0 → M6 from design/60-roadmap.md.

Added

  • mxaccess-codec — pure protocol codec covering MxReferenceHandle, NmxTransferEnvelope, NmxItemControlMessage, NmxWriteMessage (scalar
    • array, normal + timestamped), NmxSecuredWrite2Message, NmxSubscriptionMessage (single + multi-record DataUpdate per F44), NmxReferenceRegistrationMessage, NmxMetadataQueryMessage, NmxOperationStatusMessage, ObservedWriteBodyTemplate, ASB Variant + AsbStatus + RuntimeValue, MxStatus, MxValueKind, MxDataType, MxValue. Counting-allocator bench harness in benches/alloc_count.rs (F38) reports 14 allocs per write across the proven matrix, well under the R12 < 5/write target.
  • mxaccess-rpc — DCE/RPC PDU codec, NTLMv2 client + server-direction packet-integrity verify (F2 with subtle::ConstantTimeEq), TCP transport, OBJREF parser + Win32 CoMarshalInterface emitter (F6), IObjectExporter::ResolveOxid + ResolveOxid2 (F10), IRemUnknown::RemQueryInterface + RemAddRef/RemRelease (F11).
  • mxaccess-callback — RPC server hosting INmxSvcCallback + IRemUnknown for inbound DataReceived / StatusReceived frames.
  • mxaccess-nmxINmxService2 client (RegisterEngine2, TransferData, AddSubscriberEngine, SetHeartbeatSendInterval, etc.) plus auto-resolving NmxClient::create factory (F12, gated by windows-com).
  • mxaccess-galaxytiberius-backed Resolver + UserResolver (F14, gated by galaxy-resolver).
  • mxaccess-asb-nettcp[MS-NMF] framing + [MC-NBFX] binary-XML
    • [MC-NBFS] static dictionary + DH/HMAC/AES auth crypto with constant-time mod_exp via crypto-bigint::DynResidue (F27).
  • mxaccess-asbIASBIDataV2 client (Connect, RegisterItems, Read, Write, PublishWriteComplete, CreateSubscription, AddMonitoredItems, Publish, DeleteMonitoredItems, DeleteSubscription, Disconnect) with canonical-XML HMAC signing for all 13 ConnectedRequest shapes (F28) and DataContract field-suffix names on the binary MonitoredItem body (F34).
  • mxaccess — async Tokio façade exposing Session, AsbSession, Subscription (Stream<Item = Result<DataChange, Error>>), subscribe_buffered per R2 single-sample-with-cadence-knob semantics (F36), recover_connection reconnect loop (F16), recovery events (RecoveryEvent::Started/Recovered/Failed), and a typed Error taxonomy. Optional metrics feature emits per-op counters, latency histograms, and connection-state gauges (F40).
  • mxaccess-compatLMXProxyServer-shaped Rust facade exposing the 18-method ILMXProxyServer5 surface as async fns over mxaccess::Session / AsbSession with a Mutex<HashMap<i32, ItemRef>> handle table and Stream-based event channels (F35).
  • Examplesconnect-write-read.rs, subscribe.rs, subscribe-buffered.rs, asb-subscribe.rs, multi-tag.rs, recovery.rs, secured-write.rs, plus diagnostic asb-relay.rs. Live-probe DoD verified end-to-end against the AVEVA install.
  • Toolingcargo public-api baselines under design/public-api/{crate}.txt with CI drift check (F41). design/M6-bench-baseline.md records the alloc-count baseline.

Changed (vs the .NET reference)

  • NmxSubscriptionMessage::parse_data_update accepts record_count >= 1; the .NET reference hard-throws on record_count != 1. F44 evidence walk against captures/094-frida-buffered-separate-writer/ documents the multi-record observation that drove the divergence.
  • subscribe_buffered returns a Stream<Item = DataChange> (single-sample-per-event); per R2 verification the cadence is a server-side delivery rate knob, not a multi-sample payload.

Known limitations

  • F3 — cross-domain NTLM Type1/2/3 fixture is permanently out-of-scope on the dev host (single-domain). Single-domain wire parity is verified; cross-domain is documented but not regression- tested.
  • F45 — recovery replay for buffered subscriptions falls through to plain AdviseSupervisory, losing the .property(buffer) registration. Filed as a follow-up.
  • F46LmxProxy.dll!CLMXProxyServer.Suspend/.Activate wire emission was not instrumented; the compatibility-server's client-side gating is documented but the underlying ORPC call shape is unconfirmed.
  • R3 / R4OperationComplete trigger conditions and completion-only byte mappings are unmapped in both the .NET reference and the Rust port. Frame bytes are preserved verbatim via Session::operation_status_events().

Publish order

Workspace crates form a dependency DAG; cargo publish requires already-published deps to exist on crates.io, so the order matters. For V1 cut:

  1. mxaccess-codec (no internal deps)
  2. mxaccess-rpc (no internal deps)
  3. mxaccess-asb-nettcp (no internal deps)
  4. mxaccess-galaxy (depends on codec)
  5. mxaccess-callback (depends on rpc + codec)
  6. mxaccess-asb (depends on codec + asb-nettcp)
  7. mxaccess-nmx (depends on codec + galaxy + rpc + callback)
  8. mxaccess (depends on all the above)
  9. mxaccess-compat (depends on mxaccess)

cargo publish --dry-run validates each crate's metadata + tarball in isolation; the dependent crates' dry-runs require the leaf crates to actually exist on crates.io (the registry lookup happens regardless of --no-verify). For pre-publish verification: leaf crates dry-run in CI; dependent crates are validated by the public-api baseline + build-test-clippy matrix.