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

117 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog
All notable changes to the `mxaccess` workspace are documented here. The
format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
the workspace as a whole follows [SemVer](https://semver.org/) 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-nmx`** — `INmxService2` client (`RegisterEngine2`,
`TransferData`, `AddSubscriberEngine`, `SetHeartbeatSendInterval`,
etc.) plus auto-resolving `NmxClient::create` factory (F12, gated by
`windows-com`).
- **`mxaccess-galaxy`** — `tiberius`-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-asb`** — `IASBIDataV2` 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-compat`** — `LMXProxyServer`-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).
- **Examples** — `connect-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.
- **Tooling** — `cargo 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.
- **F46** — `LmxProxy.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 / R4** — `OperationComplete` 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.