Skip to content

refactor: land the standards-audit findings in batches#381

Merged
AprilNEA merged 17 commits into
masterfrom
refactor/standards-audit
Jul 18, 2026
Merged

refactor: land the standards-audit findings in batches#381
AprilNEA merged 17 commits into
masterfrom
refactor/standards-audit

Conversation

@AprilNEA

@AprilNEA AprilNEA commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Summary

Lands the findings of a workspace-wide audit against the newly codified agent-guide standards (AGENTS.md, #379): silent wire-value drops, boundary-validation gaps, hand-rolled logic with mature in-tree replacements, and module-structure debt. Seventeen focused commits, one batch each, ordered fixes-first — intended for rebase-merge (every commit is release-quality conventional).

Changes

Behavior fixes

  • hidpp: receiver/feature listeners no longer silently drop events carrying unknown wire values. Unifying/Bolt 0x41 connection events fold an unrecognised kind nibble to Unknown (num_enum(default)) instead of hiding the device — on the Unifying path arrival notifications are the only device source. Bolt 0x54 unknown pairing-error codes carry the raw byte (catch_all Other(u8)) instead of degenerating into a session timeout; same for the 0x4e press type. The 0x1d4b reconnection broadcast decodes infallibly. smartshift_enhanced reports UnsupportedResponse for an unknown wheel mode instead of silently claiming Ratchet, matching 0x2110/hires_wheel.
  • hid, agent-core: the Bolt passkey is decoded once at the notification boundary (NUL-trimmed, digit-validated, numeric value alongside); a malformed passkey fails the pairing session explicitly instead of rendering an all-Left click sequence via parse().unwrap_or(0). Out-of-range DPI writes are rejected as OutOfRange (awaitable path) or logged-and-skipped (fire-and-forget path) instead of clamping u16::MAX onto the device.
  • core, gui, agent, cli: the lighting color is a validated Rgb newtype serialized as the same hex string — the two divergent hand-rolled parsers (agent fell back to black, GUI to white) are gone. The pinned bytes in wire_format.rs are unchanged, proving IPC compatibility.

Dependency replacements

  • core: config persistence via atomic-write-file (adds the directory fsync and randomized temp name the hand-rolled writer lacked; 0600 preserved). $HOME resolution via the etcetera-backed paths::home_dir().
  • assets, gui (tests): hand-rolled env::temp_dir()+pid test dirs → tempfile::tempdir().

Structure (pure code motion)

  • inject: the three inline platform backends move to inject/{macos,linux,windows}.rs (1691 → 682 lines), matching the hook crate's layout.
  • gui: app.rs splits along its three seams into app/{home,detail,widgets}.rs (1909 → 683); asset/mod.rsasset.rs, windows/mod.rswindows.rs per the module-layout rule; the ipc_client pacing module and the asset-sync orchestration get their own files; Load/LazyDeviceDatastate/load.rs; duplicated file_url collapsed; NaN-tolerant sorts → total_cmp.
  • core: swipe machinery → binding/swipe.rs; cmd/diag/mod.rsdiag.rs (cli).

Docs & hygiene

  • core: #![deny(missing_docs)] (parity with openlogi-hid) after documenting 140 flagged items.
  • Every remaining lint suppression carries a reason; the last section-banner comments are gone; the updater fails fast on an impossible invalid embedded version.

Testing

  • devenv tasks run openlogi:check (fmt --check, workspace clippy -D warnings, full workspace tests incl. doc-tests) — green on the final tree; each commit was additionally verified with targeted clippy + tests before landing.
  • cargo clippy --target x86_64-pc-windows-gnu cross-lint on the touched cfg-shared crates (core, inject) — clean; Linux paths rely on CI as the authoritative check.
  • Wire compatibility: the bincode golden tests (wire_format.rs) pass with unchanged pinned bytes; no PROTOCOL_VERSION bump needed.
  • Not runtime-tested on hardware: receiver event tolerance (unknown-kind devices, unknown pairing errors) and the passkey failure path need a physical Bolt/Unifying setup; the GUI was not exercised beyond its unit tests. Suggested spot-check: pair a device (passkey flow), toggle lighting color/brightness, and confirm devices still enumerate after sleep.

Follow-ups (tracked separately, out of scope here)

@greptile-apps

greptile-apps Bot commented Jul 13, 2026

Copy link
Copy Markdown

Greptile Summary

This PR lands a broad standards-audit cleanup across the workspace. The main changes are:

  • More tolerant HID++ event and pairing notification decoding.
  • Validated lighting colors through a shared Rgb type.
  • Rejected out-of-range DPI writes instead of clamping them.
  • Atomic config writes and safer temporary test directories.
  • Module splits for gesture, GUI, diagnostics, assets, and platform code.

Confidence Score: 4/5

This is close, but the pairing flow should be fixed before merging.

  • Hash-prefixed lighting colors now load and save through the config path correctly.
  • Malformed passkey notifications now fail the session and cancel the Bolt pairing phase.
  • Valid keyboard passkeys can still be shown as pointer clicks when the auth bit is absent, leaving the pairing workflow broken for that device state.

crates/openlogi-hid/src/pairing.rs

Important Files Changed

Filename Overview
crates/openlogi-core/src/color.rs Adds the shared validated Rgb type for lighting colors.
crates/openlogi-core/src/config/settings.rs Updates lighting config deserialization to accept hash-prefixed colors and save canonical hex.
crates/openlogi-hid/src/pairing.rs Adds pairing phase tracking and stricter passkey handling, but valid keyboard passkeys can still be routed to the pointer UI.
crates/openlogi-hid/src/pairing/notification.rs Parses passkey notifications into validated digit strings and numeric values.
crates/openlogi-agent-core/src/ipc.rs Maps malformed pairing notifications onto the existing pairing failure wire shape.

Fix All in Codex Fix All in Claude Code

Reviews (2): Last reviewed commit: "fix(hid): cancel failed Bolt pairing ses..." | Re-trigger Greptile

Comment thread crates/openlogi-core/src/config.rs Outdated
Comment thread crates/openlogi-hid/src/pairing.rs
AprilNEA added 17 commits July 18, 2026 16:28
…ners

Every allow/expect in the workspace now states its reason inline (the
four stragglers had it in a loose comment or not at all), and the one
remaining dashed section banner is reduced to plain prose.
CARGO_PKG_VERSION is cargo-provided and always valid semver; falling
back to 0.0.0 would silently make every release look like an upgrade.
Panic with a reasoned expect instead of hiding the impossible case.
Expose the etcetera-backed home_dir from openlogi-core and use it for
the launchd plist location instead of reading $HOME by hand — one home
resolution policy for the whole workspace.
The receiver and feature listeners run in a void callback with no error
channel, so every unrecognised byte used to degenerate into a silent
return — losing whole events over an identity-only field:

- Unifying/Bolt 0x41 device-connection: an unknown kind nibble dropped
  the event entirely; on the Unifying path arrival notifications are
  the only device source, so the device never appeared at all. Kind now
  folds to Unknown via num_enum(default) (identity-only by policy).
- Pairing-info register reads no longer fail the whole read over the
  kind nibble either, matching the listener policy.
- Bolt 0x54 pairing status: an unknown error code turned a failure into
  a session timeout; PairingError now carries the raw code in a
  num_enum(catch_all) Other variant. Same treatment for the 0x4e
  passkey press type.
- Bolt 0x4d passkey: trim the NUL padding before decoding.
- 0x1d4b WirelessDeviceStatus broadcast: the (re)connection signal was
  dropped if any of its three bytes was unrecognised; all fields now
  decode infallibly with catch_all Other variants.
- smartshift_enhanced: an unknown wheel mode silently reported Ratchet;
  it is now Hidpp20Error::UnsupportedResponse, matching 0x2110 and
  hires_wheel (the pinned fallback test asserts the error instead).

openlogi-hid's discovery kind mapping is simplified to the now-
infallible From.
A corrupt Bolt passkey notification used to flow through from_utf8_lossy
and parse().unwrap_or(0), rendering an all-Left click sequence that can
never authenticate — with no diagnostic anywhere. The 0x4d decoder now
NUL-trims and validates ASCII digits once, producing the digits and
their numeric value together; a malformed payload fails the pairing
session explicitly (surfaced over IPC as the generic transport-failure
message, so the wire format is unchanged).

The DPI write path clamped an out-of-range u32 to u16::MAX and wrote
that to the device. The awaitable path now rejects it as the same
OutOfRange feature error the device itself would return; the
fire-and-forget path logs and skips the write.
The lighting color was a raw String parsed independently in two places
with divergent silent fallbacks: the agent's parse_hex fell back to
black (lights off) while the GUI's fell back to white and didn't strip
a '#' prefix. A hand-edited config degraded differently on each side of
the IPC with no diagnostic.

openlogi-core now owns a validated Rgb newtype (exactly 6 hex digits)
that serializes as the same hex string the field used to hold, so TOML
files and the bincode wire format are unchanged — the pinned wire bytes
in wire_format.rs prove it. Config load folds an unparseable value to
white with the same documented per-field tolerance as the brightness
clamp (failing the load would discard the whole user config). Every
consumer — agent write path, GUI swatches and keyboard glow, CLI diag —
now uses the typed components; both hand-rolled hex parsers are gone.
The hand-rolled temp-file writer used a fixed .toml.tmp name (a
concurrent-save collision surface) and never fsynced the directory, so
the rename could vanish on a crash. atomic-write-file — already the
asset cache's writer — covers both; the 0600 mode on every save is
preserved.
asset/mod.rs, windows/mod.rs, and cmd/diag/mod.rs all carry real logic
(the asset resolver, the window registry, the diag device-selection
policy) — per the module-layout rule they are foo.rs files with their
children in the sibling directory. Pure renames.
The ipc_client's inline pacing module (with its own tests) becomes a
file; the duplicated file_url helper collapses to one copy; two
one-line single-caller wrappers in app.rs are inlined; the hotspot
geometry sorts with total_cmp instead of NaN-tolerant unwrap_or.
The hand-rolled env::temp_dir()+pid directories leaked on assertion
failure; tempfile::tempdir cleans up on drop, as the core and xtask
tests already do.
…oad.rs

The lazy load-state types have no AppState dependency; state.rs keeps
the state itself.
SyncOutcome/AssetControl/run_asset_sync are a self-contained subsystem;
main.rs keeps startup wiring only.
detect_swipe and SwipeAccumulator are input-processing runtime, not
part of the Action vocabulary the rest of binding.rs defines.
The hand-rolled env::temp_dir()+pid directories leaked on assertion
failure; tempfile::tempdir cleans up on drop.
Brings openlogi-core to parity with openlogi-hid, which already
enforces rustdoc coverage at compile time.
@AprilNEA
AprilNEA force-pushed the refactor/standards-audit branch from 6d78dd6 to 16e8d27 Compare July 18, 2026 08:29
Comment thread crates/openlogi-hid/src/pairing.rs
@AprilNEA
AprilNEA merged commit 994a84f into master Jul 18, 2026
12 checks passed
@AprilNEA
AprilNEA deleted the refactor/standards-audit branch July 18, 2026 08:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant