Skip to content

feat(fixture): add an MX Ergo Unifying fixture - #1374

Draft
Chernicharo wants to merge 1 commit into
AprilNEA:masterfrom
Chernicharo:feat/fixture-mx-ergo
Draft

Chernicharo wants to merge 1 commit into
AprilNEA:masterfrom
Chernicharo:feat/fixture-mx-ergo

Conversation

@Chernicharo

Copy link
Copy Markdown

Summary

Adds the first captured fixture to the corpus: an original MX Ergo (wpid 406f, firmware MPM06.03_B0022) on a Unifying receiver, produced with openlogi fixture contribute. It covers a device shape the synthetic corpus does not: a trackball that reports no 0x2201/0x2202 and no 0x2110, so DPI and SmartShift are legitimately unsupported, while 0x1b04 exposes wheel tilt and a precision button.

Changes

  • fixtures/devices/mx-ergo-001/: manifest, semantic profile and eight read-only cassettes (feature table, firmware entities, reprogrammable controls, raw battery, DPI info, SmartShift status, wheel mode, backlight state).

Testing

  • openlogi fixture contribute completed both phases against the hardware; the wizard's own strict verification passed (schema, synthetic identity ledger, profile/case relationships, and replay of all eight cassettes).
  • cargo test -p openlogi-cli fixture on this branch — 48 passed, including fixture::verify, which discovers and strictly verifies every directory in the corpus (this branch has no source changes, so the fixture is validated by unmodified verification code)
  • Identity check by hand: the receiver serial, the device unit id and the receiver-register serial of this unit appear nowhere in the committed files; only the synthetic 4F4C5201 does.

Note

Step 2 of the wizard cannot complete on a Unifying receiver on Linux today (#1349): the receiver's node also carries Logitech DJ reports and the recorder rejects the cassette. This capture was taken with the fix in #1373 applied. The fixture itself does not depend on that fix — it verifies against master as shown above — but it cannot be reproduced on this hardware until the fix lands.

Captured from an original MX Ergo (wpid 406f, fw MPM06.03_B0022) on a
Unifying receiver with `openlogi fixture contribute`: eight read-only
cassettes plus the semantic profile. The device reports no 0x2201/0x2202
and no 0x2110, so it covers a trackball whose pointer and SmartShift
settings are unsupported.
@greptile-apps

greptile-apps Bot commented Sep 12, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 3/5

The PR should not merge until the device-specific firmware extra_version is synthesized and covered by identity verification.

Fix All in CodexFindings

  1. P1 Security Device Identity Remains Unsanitized

Summary

  • Models the MX Ergo as a trackball without adjustable DPI, SmartShift, high-resolution wheel mode, or backlighting.
  • Captures feature discovery, firmware entities, controls, battery state, and unsupported-setting probes.
  • Introduces a privacy concern because firmware extra_version bytes documented as device-specific remain outside the synthetic identity ledger.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    M[manifest.json<br/>cases and identity ledger] --> P[profile.json<br/>MX Ergo semantic model]
    M --> C[Eight replay cassettes]
    C --> F[Feature and setting responses]
    C --> W[Firmware entity responses]
    W --> X[Device-specific extra_version]
    X -. omitted from identity ledger .-> M
Loading

Reviews (1) · Last reviewed commit: "feat(fixture): add an MX Ergo Unifying f..."

{
"request_match": "hidpp20",
"request": "10010210000000",
"response": "1101021001424f5449000001000000cde885f300",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Device Identity Remains Unsanitized

This firmware response, and the response on line 40, retain the captured cd e8 85 f3 00 extra_version. The repository describes this field as device-specific, but the manifest does not declare or synthesize it. Because identity extraction skips DEVICE_INFORMATION function 1, sanitization and strict verification both overlook these bytes, leaving a device-specific hardware value in the committed corpus despite its synthetic-identity guarantee. Remove or deterministically synthesize this field and include it in identity verification.

How this was verified: The response layout places these bytes in extra_version, repository diagnostics describe that field as device-specific, and the fixture identity extractor explicitly skips function 1 responses.

Fix in Codex Fix in Claude Code

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed, and it goes deeper than the capture: the field is not declarable in the current ledger design, so I would rather have your call than guess.

What I verified on this unit: getFwInfo responses end in cd e8 85 f3 00 for both entities, and crates/openlogi-device/src/write/diagnostics.rs describes extra_version as device-specific. ProtocolIdentityExtractor validates the function-1 response framing but claims no field in it, so the bytes ship as captured.

I prototyped the obvious fix — a tagged five-byte synthetic identity for the field, claimed at (DEVICE_INFORMATION, 1) — and it runs into two things:

  1. Self-replay compares the replayed SemanticObservation with the capture, and FirmwareEntities carries extra_version, so rewriting it fails the exact match. Workable: compare against the capture with the audited synthetic value substituted, so every other byte still has to match exactly.
  2. build_profile_ledger derives the ledger only from the profile's device model. extra_version is not in the profile, so verification then rejects the cassette with extra synthetic FirmwareExtraVersion value not declared by the ledger. That is the real blocker, and the two ways out are both design calls:
    • carry the field in the semantic profile's device model (an IPC wire type, so a protocol bump), or
    • let the ledger accept a cassette-derived representation bound to the device principal, which relaxes "the ledger is profile-derived".

Which direction do you want? I have the hardware and the branch, so I can finish either quickly and regenerate this fixture. If you would rather not decide now, I can drop the firmware-entities case from this PR so nothing device-specific ships, and leave the capture gap to a follow-up issue.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drop firmware-entities from this PR and leave the ledger/schema change for a follow-up.

A protocol bump to DeviceModelInfo would put a per-firmware-entity field in the device-model profile, while accepting a cassette-derived representation would weaken the profile-derived identity invariant. Keeping the cassette unchanged is not acceptable because extra_version remains captured device-specific data.

Removing this case is the safest scoped fix: the existing profile-derived unit ID and receiver identities remain covered by the other cassettes, and no unsanitized firmware-specific value ships. The follow-up should introduce an explicit semantic firmware-entity representation plus a dedicated synthetic identity kind, then regenerate this cassette and verify self-replay with the audited replacement.

Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.

@Chernicharo
Chernicharo marked this pull request as draft September 13, 2026 01:09
@Chernicharo

Copy link
Copy Markdown
Author

Marked this a draft until the extra_version question in the review thread is settled — I would rather not land device-specific bytes in the corpus, and the two ways to declare the field in the identity ledger are design calls for you. Everything else in the capture verifies; I can regenerate it in minutes once the direction is clear.

@davidbudnick davidbudnick added type: feature New feature request platform: all Cross-platform issue labels Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

platform: all Cross-platform issue type: feature New feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants