ad1cf2351c
Three M6 sub-followups landed in this wave (sub-agent worktrees +
manual reconciliation in main):
**F36 — Session::subscribe_buffered (NMX) per R2 single-sample**
- `BufferedOptions::rounded_update_interval_ms()` — 100ms rounding
helper mirroring MxNativeCompatibilityServer.cs:638
((updateInterval + 99) / 100) * 100, saturating on overflow.
- `Session::subscribe_buffered` (public, lib.rs:604) delegates to
the new private `subscribe_buffered_nmx` which uses the buffered
RegisterReference path: item_definition suffixed with
`.property(buffer)`, subscribe=true (no separate
AdviseSupervisory follow-up — verified against capture 082).
- Per R2 verified at wwtools/mxaccesscli/docs/api-notes.md the wire
semantic is single-sample-per-event with a server-side cadence
knob; rounded_ms is held client-side only (native MXAccess does
not emit a separate SetBufferedUpdateInterval RPC, verified by
absence in 079/082 captures).
- New crates/mxaccess/examples/subscribe-buffered.rs.
- New crates/mxaccess-codec/tests/buffered_register_reference_parity.rs:
4 tests (capture 079/082 round-trip, suffix helper, constructive
forward-build vs capture 082).
**F40 — Optional metrics feature**
- New crates/mxaccess/src/metrics.rs (275 lines): `pub(crate)`
thin wrappers (`record_write_latency`, `record_read_latency`,
`inc_writes`, `inc_reads`, `inc_advises`, `inc_recovery_*`,
`set_active_subscriptions`, etc.) that compile to no-ops under
`#[cfg(not(feature = "metrics"))]`. Call sites in session.rs +
asb_session.rs invoke them unconditionally; the gate is inside
the wrapper.
- `metrics = { version = "0.24", optional = true }` added to
workspace + mxaccess crate Cargo.toml.
- Default build: zero metrics dep, zero runtime cost.
**F44 — Buffered batch + suspend capture decode evidence**
- New docs/M6-buffered-evidence.md: per-capture summary for
077, 079, 080, 081, 082, 094 — call sequence, key wire bytes,
R2/R5 verdict.
- R2 confirmed silently as "not a real risk" — single-sample
observed across 079/080/082/094.
- R5 trigger conditions documented from capture 077: AdviseSupervisory
+ Suspend pair, 1-second intervals, succeeds on enum attributes.
- design/70-risks-and-open-questions.md R2/R5 status updated.
Workspace: 759 → 792 tests, clippy clean, rustdoc -D warnings clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
88 lines
3.1 KiB
TOML
88 lines
3.1 KiB
TOML
[workspace]
|
|
resolver = "3"
|
|
members = [
|
|
"crates/mxaccess-codec",
|
|
"crates/mxaccess-galaxy",
|
|
"crates/mxaccess-rpc",
|
|
"crates/mxaccess-callback",
|
|
"crates/mxaccess-nmx",
|
|
"crates/mxaccess-asb-nettcp",
|
|
"crates/mxaccess-asb",
|
|
"crates/mxaccess",
|
|
"crates/mxaccess-compat",
|
|
]
|
|
|
|
[workspace.package]
|
|
version = "0.0.0"
|
|
edition = "2024"
|
|
license = "MIT"
|
|
repository = "https://github.com/<org>/mxaccess"
|
|
rust-version = "1.85"
|
|
authors = ["Joseph Doherty <dohejw01@gmail.com>"]
|
|
|
|
# Workspace-level dependency pins. Crates opt in via `dep = { workspace = true }`.
|
|
# M0 stubs use minimal deps; the full pinned set per design/30-crate-topology.md
|
|
# will be uncommented as M1+ implementation lands.
|
|
[workspace.dependencies]
|
|
thiserror = "2"
|
|
tracing = "0.1"
|
|
async-trait = "0.1"
|
|
futures-util = "0.3"
|
|
bytes = "1"
|
|
byteorder = "1"
|
|
tokio = { version = "1", features = ["net", "io-util", "rt-multi-thread", "sync", "time", "macros"] }
|
|
# M5 ASB transport (F19). Crypto crates target the digest 0.10 / cipher 0.4
|
|
# generation (the line that hmac 0.12, md-5 0.10, sha1 0.10, sha2 0.10,
|
|
# aes 0.8, cbc 0.1, pbkdf2 0.12 all share). mxaccess-rpc is already on this
|
|
# generation (crates/mxaccess-rpc/Cargo.toml:13-18); M5 sticks with it for
|
|
# resolved-graph coherence. The design doc at design/30-crate-topology.md:251-289
|
|
# prescribed the 0.11/0.5 generation but the rpc crate landed earlier on the
|
|
# 0.10/0.4 line — when those two diverge, the implementation is canonical.
|
|
hmac = "0.12"
|
|
md-5 = "0.10"
|
|
sha1 = "0.10"
|
|
sha2 = "0.10"
|
|
aes = "0.8"
|
|
cbc = { version = "0.1", features = ["std"] }
|
|
pbkdf2 = { version = "0.12", default-features = false, features = ["hmac"] }
|
|
flate2 = "1"
|
|
rand = "0.8"
|
|
# DH bigint. F27 (closed): constant-time `mod_exp` lives in
|
|
# `crypto-bigint::DynResidue`; we keep `num-bigint` for decimal parsing
|
|
# + .NET-LE byte conversion (crypto-bigint has no decimal-string parser
|
|
# and no built-in .NET `BigInteger.ToByteArray()` ordering). The
|
|
# `auth.rs::constant_time_mod_exp` wrapper bridges both: parse via
|
|
# num-bigint, compute via crypto-bigint Uint<32> + DynResidue, return
|
|
# back through num-bigint for downstream byte slicing. Wire bytes
|
|
# stay identical so existing fixtures pin parity.
|
|
num-bigint = "0.4"
|
|
num-traits = "0.2"
|
|
num-integer = "0.1"
|
|
crypto-bigint = "0.5"
|
|
quick-xml = "0.36"
|
|
tokio-util = { version = "0.7", features = ["codec"] }
|
|
zeroize = { version = "1", features = ["zeroize_derive"] }
|
|
# F40 — optional `mxaccess` feature `metrics`. Pin to 0.24.x (current
|
|
# stable line). The dep is only pulled in when the consumer enables
|
|
# `mxaccess/metrics`; the default build resolves without it.
|
|
metrics = "0.24"
|
|
|
|
[workspace.lints.rust]
|
|
unsafe_op_in_unsafe_fn = "warn"
|
|
|
|
[workspace.lints.clippy]
|
|
unwrap_used = "deny"
|
|
expect_used = "deny"
|
|
panic = "deny"
|
|
todo = "warn" # warn during M0 stubs; will tighten to deny post-M1
|
|
unreachable = "deny"
|
|
indexing_slicing = "deny"
|
|
|
|
[profile.release]
|
|
opt-level = 3
|
|
lto = "thin"
|
|
codegen-units = 1
|
|
|
|
[profile.dev]
|
|
opt-level = 0
|