Files
Joseph Doherty 9e57bfd451 [F41 + F44 reconciliation] cargo public-api baselines + multi-record DataUpdate codec
**F41 — public-api baselines (M6 DoD bullet 5)**

`design/public-api/{crate}.txt` for all 9 workspace crates, generated
via `cargo +nightly public-api --simplified -p <crate>`. Per-crate
baseline sizes:
- mxaccess-codec: 2516 lines
- mxaccess-asb:   1258 lines
- mxaccess-rpc:   1273 lines
- mxaccess-asb-nettcp: 708 lines
- mxaccess: 542 lines
- mxaccess-galaxy: 374 lines
- mxaccess-callback: 170 lines
- mxaccess-compat: 123 lines
- mxaccess-nmx: 118 lines

`design/public-api/README.md` documents the update procedure
(install nightly + cargo-public-api, regenerate the affected baseline
on intentional API changes, commit alongside).

`.github/workflows/rust.yml` gains a `public-api` job that runs the
same diff against the committed baseline; drift fails CI with a
unified diff in the log so the PR author can either revert or
update the baseline.

**F44 reconciliation — multi-record DataUpdate codec**

Cherry-picked from the F44 sub-agent's worktree (commit `aec6a0c`):
`subscription_message.rs::parse_data_update` now loops over
`record_count` like `parse_subscription_status` does, accepting any
positive count. The .NET reference still hard-throws on
`record_count != 1`; the Rust codec deliberately diverges per the F44
evidence walk against `captures/094-frida-buffered-separate-writer/
frida-events.tsv:145` (a `0x33` DataUpdate body with `record_count = 2`,
inner_length = 23 (preamble) + 2 * 19 (records) = 61, post a
separate-session writer triggering two value changes inside one
`SetBufferedUpdateInterval(1000)` window).

Two new round-trip tests:
- `data_update_multi_record_round_trip` — synthesises a 2-record body,
  parses, asserts both records decode to expected Int32 values.
- `data_update_capture_094_truncated_record_errors` — truncates the
  capture-094 fixture mid-second-record, asserts CodecError::Decode.

New wire-byte fixtures under `crates/mxaccess-codec/tests/fixtures/m6-buffered/`:
- `094-line145-dataupdate-recordcount2.bin` (57 bytes, `0x33` multi-record)
- `094-line48-substatus-recordcount2.bin` (101 bytes, `0x32` multi-record)

R2 in `design/70-risks-and-open-questions.md` updated from
"single-sample (settled silently)" to "settled per option (a) — codec
relaxed; multi-record observed in production-stack tracing."

`design/followups.md`: F44's verdict updated to reflect the
contradiction-then-relaxation, with reference to the new tests +
fixtures.

Workspace 792 → 794 tests pass; clippy clean; rustdoc clean.

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

124 lines
11 KiB
Plaintext

pub mod mxaccess_compat
pub struct mxaccess_compat::BufferedDataChangeEvent
pub mxaccess_compat::BufferedDataChangeEvent::is_during_recovery: bool
pub mxaccess_compat::BufferedDataChangeEvent::item_handle: i32
pub mxaccess_compat::BufferedDataChangeEvent::mx_data_type: i16
pub mxaccess_compat::BufferedDataChangeEvent::qualities: alloc::vec::Vec<u16>
pub mxaccess_compat::BufferedDataChangeEvent::server_handle: i32
pub mxaccess_compat::BufferedDataChangeEvent::statuses: alloc::vec::Vec<mxaccess_codec::status::MxStatus>
pub mxaccess_compat::BufferedDataChangeEvent::timestamps: alloc::vec::Vec<std::time::SystemTime>
pub mxaccess_compat::BufferedDataChangeEvent::values: alloc::vec::Vec<mxaccess_codec::value::MxValue>
impl core::clone::Clone for mxaccess_compat::BufferedDataChangeEvent
pub fn mxaccess_compat::BufferedDataChangeEvent::clone(&self) -> mxaccess_compat::BufferedDataChangeEvent
impl core::fmt::Debug for mxaccess_compat::BufferedDataChangeEvent
pub fn mxaccess_compat::BufferedDataChangeEvent::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
impl core::marker::Freeze for mxaccess_compat::BufferedDataChangeEvent
impl core::marker::Send for mxaccess_compat::BufferedDataChangeEvent
impl core::marker::Sync for mxaccess_compat::BufferedDataChangeEvent
impl core::marker::Unpin for mxaccess_compat::BufferedDataChangeEvent
impl core::marker::UnsafeUnpin for mxaccess_compat::BufferedDataChangeEvent
impl core::panic::unwind_safe::RefUnwindSafe for mxaccess_compat::BufferedDataChangeEvent
impl core::panic::unwind_safe::UnwindSafe for mxaccess_compat::BufferedDataChangeEvent
pub struct mxaccess_compat::DataChangeEvent
pub mxaccess_compat::DataChangeEvent::is_during_recovery: bool
pub mxaccess_compat::DataChangeEvent::item_handle: i32
pub mxaccess_compat::DataChangeEvent::quality: u16
pub mxaccess_compat::DataChangeEvent::server_handle: i32
pub mxaccess_compat::DataChangeEvent::status: mxaccess_codec::status::MxStatus
pub mxaccess_compat::DataChangeEvent::timestamp: std::time::SystemTime
pub mxaccess_compat::DataChangeEvent::value: mxaccess_codec::value::MxValue
impl core::clone::Clone for mxaccess_compat::DataChangeEvent
pub fn mxaccess_compat::DataChangeEvent::clone(&self) -> mxaccess_compat::DataChangeEvent
impl core::fmt::Debug for mxaccess_compat::DataChangeEvent
pub fn mxaccess_compat::DataChangeEvent::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
impl core::marker::Freeze for mxaccess_compat::DataChangeEvent
impl core::marker::Send for mxaccess_compat::DataChangeEvent
impl core::marker::Sync for mxaccess_compat::DataChangeEvent
impl core::marker::Unpin for mxaccess_compat::DataChangeEvent
impl core::marker::UnsafeUnpin for mxaccess_compat::DataChangeEvent
impl core::panic::unwind_safe::RefUnwindSafe for mxaccess_compat::DataChangeEvent
impl core::panic::unwind_safe::UnwindSafe for mxaccess_compat::DataChangeEvent
pub struct mxaccess_compat::EventStream<T: core::clone::Clone + core::marker::Send + core::marker::Unpin + 'static>
impl<T: core::clone::Clone + core::marker::Send + core::marker::Unpin + 'static> futures_core::stream::Stream for mxaccess_compat::EventStream<T>
pub type mxaccess_compat::EventStream<T>::Item = T
pub fn mxaccess_compat::EventStream<T>::poll_next(self: core::pin::Pin<&mut Self>, cx: &mut core::task::wake::Context<'_>) -> core::task::poll::Poll<core::option::Option<Self::Item>>
impl<T> core::marker::Freeze for mxaccess_compat::EventStream<T>
impl<T> core::marker::Send for mxaccess_compat::EventStream<T>
impl<T> core::marker::Sync for mxaccess_compat::EventStream<T> where T: core::marker::Sync
impl<T> core::marker::Unpin for mxaccess_compat::EventStream<T>
impl<T> core::marker::UnsafeUnpin for mxaccess_compat::EventStream<T>
impl<T> !core::panic::unwind_safe::RefUnwindSafe for mxaccess_compat::EventStream<T>
impl<T> !core::panic::unwind_safe::UnwindSafe for mxaccess_compat::EventStream<T>
pub struct mxaccess_compat::LmxClient
impl mxaccess_compat::LmxClient
pub async fn mxaccess_compat::LmxClient::activate(&self, h_server: i32, h_item: i32) -> core::result::Result<mxaccess_codec::status::MxStatus, mxaccess::Error>
pub async fn mxaccess_compat::LmxClient::add_buffered_item(&self, h_server: i32, item_def: &str, context: &str) -> core::result::Result<i32, mxaccess::Error>
pub async fn mxaccess_compat::LmxClient::add_item(&self, h_server: i32, item_def: &str) -> core::result::Result<i32, mxaccess::Error>
pub async fn mxaccess_compat::LmxClient::add_item_2(&self, h_server: i32, item_def: &str, context: &str) -> core::result::Result<i32, mxaccess::Error>
pub async fn mxaccess_compat::LmxClient::advise(&self, h_server: i32, h_item: i32) -> core::result::Result<(), mxaccess::Error>
pub async fn mxaccess_compat::LmxClient::advise_supervisory(&self, h_server: i32, h_item: i32) -> core::result::Result<(), mxaccess::Error>
pub async fn mxaccess_compat::LmxClient::archestra_user_to_id(&self, h_server: i32, user_guid: &str) -> core::result::Result<i32, mxaccess::Error>
pub async fn mxaccess_compat::LmxClient::authenticate_user(&self, h_server: i32, _user: &str, _password: &str) -> core::result::Result<i32, mxaccess::Error>
pub fn mxaccess_compat::LmxClient::buffered_update_interval_ms(&self) -> i32
pub async fn mxaccess_compat::LmxClient::is_advised(&self, h_item: i32) -> bool
pub async fn mxaccess_compat::LmxClient::item_count(&self) -> usize
pub fn mxaccess_compat::LmxClient::on_buffered_data_change(&self) -> mxaccess_compat::EventStream<mxaccess_compat::BufferedDataChangeEvent>
pub fn mxaccess_compat::LmxClient::on_data_change(&self) -> mxaccess_compat::EventStream<mxaccess_compat::DataChangeEvent>
pub fn mxaccess_compat::LmxClient::on_operation_complete(&self) -> mxaccess_compat::EventStream<mxaccess_compat::OperationCompleteEvent>
pub fn mxaccess_compat::LmxClient::on_write_complete(&self) -> mxaccess_compat::EventStream<mxaccess_compat::WriteCompleteEvent>
pub fn mxaccess_compat::LmxClient::register(_client_name: &str, session: mxaccess::Session) -> Self
pub fn mxaccess_compat::LmxClient::register_asb(_client_name: &str, session: mxaccess::asb_session::AsbSession) -> Self
pub async fn mxaccess_compat::LmxClient::remove_item(&self, h_server: i32, h_item: i32) -> core::result::Result<(), mxaccess::Error>
pub fn mxaccess_compat::LmxClient::server_handle(&self) -> i32
pub async fn mxaccess_compat::LmxClient::set_buffered_update_interval(&self, h_server: i32, interval_ms: i32) -> core::result::Result<(), mxaccess::Error>
pub async fn mxaccess_compat::LmxClient::suspend(&self, h_server: i32, h_item: i32) -> core::result::Result<mxaccess_codec::status::MxStatus, mxaccess::Error>
pub async fn mxaccess_compat::LmxClient::un_advise(&self, h_server: i32, h_item: i32) -> core::result::Result<(), mxaccess::Error>
pub async fn mxaccess_compat::LmxClient::unregister(&self, h_server: i32) -> core::result::Result<(), mxaccess::Error>
pub async fn mxaccess_compat::LmxClient::write(&self, h_server: i32, h_item: i32, value: mxaccess_codec::value::MxValue, _user_id: i32) -> core::result::Result<(), mxaccess::Error>
pub async fn mxaccess_compat::LmxClient::write_2(&self, h_server: i32, h_item: i32, value: mxaccess_codec::value::MxValue, timestamp: std::time::SystemTime, _user_id: i32) -> core::result::Result<(), mxaccess::Error>
pub async fn mxaccess_compat::LmxClient::write_secured(&self, h_server: i32, h_item: i32, current_user_id: i32, verifier_user_id: i32, value: mxaccess_codec::value::MxValue) -> core::result::Result<(), mxaccess::Error>
pub async fn mxaccess_compat::LmxClient::write_secured_2(&self, h_server: i32, h_item: i32, current_user_id: i32, verifier_user_id: i32, value: mxaccess_codec::value::MxValue, timestamp: std::time::SystemTime) -> core::result::Result<(), mxaccess::Error>
impl core::clone::Clone for mxaccess_compat::LmxClient
pub fn mxaccess_compat::LmxClient::clone(&self) -> Self
impl core::fmt::Debug for mxaccess_compat::LmxClient
pub fn mxaccess_compat::LmxClient::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
impl core::marker::Freeze for mxaccess_compat::LmxClient
impl core::marker::Send for mxaccess_compat::LmxClient
impl core::marker::Sync for mxaccess_compat::LmxClient
impl core::marker::Unpin for mxaccess_compat::LmxClient
impl core::marker::UnsafeUnpin for mxaccess_compat::LmxClient
impl !core::panic::unwind_safe::RefUnwindSafe for mxaccess_compat::LmxClient
impl !core::panic::unwind_safe::UnwindSafe for mxaccess_compat::LmxClient
pub struct mxaccess_compat::OperationCompleteEvent
pub mxaccess_compat::OperationCompleteEvent::is_during_recovery: bool
pub mxaccess_compat::OperationCompleteEvent::item_handle: i32
pub mxaccess_compat::OperationCompleteEvent::server_handle: i32
pub mxaccess_compat::OperationCompleteEvent::statuses: alloc::vec::Vec<mxaccess_codec::status::MxStatus>
impl core::clone::Clone for mxaccess_compat::OperationCompleteEvent
pub fn mxaccess_compat::OperationCompleteEvent::clone(&self) -> mxaccess_compat::OperationCompleteEvent
impl core::fmt::Debug for mxaccess_compat::OperationCompleteEvent
pub fn mxaccess_compat::OperationCompleteEvent::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
impl core::marker::Freeze for mxaccess_compat::OperationCompleteEvent
impl core::marker::Send for mxaccess_compat::OperationCompleteEvent
impl core::marker::Sync for mxaccess_compat::OperationCompleteEvent
impl core::marker::Unpin for mxaccess_compat::OperationCompleteEvent
impl core::marker::UnsafeUnpin for mxaccess_compat::OperationCompleteEvent
impl core::panic::unwind_safe::RefUnwindSafe for mxaccess_compat::OperationCompleteEvent
impl core::panic::unwind_safe::UnwindSafe for mxaccess_compat::OperationCompleteEvent
pub struct mxaccess_compat::WriteCompleteEvent
pub mxaccess_compat::WriteCompleteEvent::is_during_recovery: bool
pub mxaccess_compat::WriteCompleteEvent::item_handle: i32
pub mxaccess_compat::WriteCompleteEvent::server_handle: i32
pub mxaccess_compat::WriteCompleteEvent::statuses: alloc::vec::Vec<mxaccess_codec::status::MxStatus>
impl core::clone::Clone for mxaccess_compat::WriteCompleteEvent
pub fn mxaccess_compat::WriteCompleteEvent::clone(&self) -> mxaccess_compat::WriteCompleteEvent
impl core::fmt::Debug for mxaccess_compat::WriteCompleteEvent
pub fn mxaccess_compat::WriteCompleteEvent::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
impl core::marker::Freeze for mxaccess_compat::WriteCompleteEvent
impl core::marker::Send for mxaccess_compat::WriteCompleteEvent
impl core::marker::Sync for mxaccess_compat::WriteCompleteEvent
impl core::marker::Unpin for mxaccess_compat::WriteCompleteEvent
impl core::marker::UnsafeUnpin for mxaccess_compat::WriteCompleteEvent
impl core::panic::unwind_safe::RefUnwindSafe for mxaccess_compat::WriteCompleteEvent
impl core::panic::unwind_safe::UnwindSafe for mxaccess_compat::WriteCompleteEvent