Fix branch-clone, rounding, cast, and remaining long-tail findings
- bugprone-branch-clone (12): fold genuinely identical switch arms
(typing status map, PM1 power levels, wake-cause names, glyph
fallback), merge the duplicated small-panel atlas ladder, rebuild
scaleFor as per-panel constexpr scale tables (lookup-table idiom),
restructure the modal confirm poll around explicit hold/press
predicates (also clears the DeMorgan finding), and NOLINT the one
per-SoC gated ADC calibration switch with rationale.
- bugprone-casting-through-void (13): use direct reinterpret_cast (the
documented pro-type-reinterpret-cast deviation) for byte/sockaddr
views; keep the SPI slot two-step through void* with rationale (it
exists to satisfy -Werror=cast-align next to the static_asserts).
- bugprone-incorrect-roundings (9): std::lroundf instead of +0.5 casts.
- cert-dcl50-cpp (5): rationale NOLINTs on the printf-style formatters
(a parameter pack cannot produce the va_list vsnprintf needs).
- cppcoreguidelines-pro-type-const-cast: const-correct the WordReader
ctx (API + trampoline + tests, const_cast deleted); NOLINT the two
std <cstring>-convention mutable overloads.
- Long tail: explicit void* casts + sizeof(T) rationale in rtos_queue,
range-for loop conversions, 0x80-mask instead of int8_t reinterpret
for the AXP2101 gauge, uint8_t slot subscript, parenthesized -1 pin
macros, extended the __wrap_log_printf ABI suppression to the
reserved-identifier aliases, integer-center tween targets.
Claude-Session: https://claude.ai/code/session_01SV58JXhfxhhc9DC6vdjBo4
Fix all readability-identifier-naming findings and the heal-surfaced defects
Rename every identifier flagged by the .clang-tidy naming policy: file-scope
and function-local statics gain the s_ prefix, static class members of
BleHidManager and AdminPortal move from bare/member-style names to s_ camelBack,
static/constexpr constants take k + PascalCase (kDummies, kNames, kDemos,
kEventNames, kAdvHidUuid, the generated AaFont atlas symbols), snake_case
parameters/locals in secure_allocator become camelBack, the OKLab intermediates
in gradient.cpp get real names, and the mbedtls_aes_context compat alias is
retired in favor of VaultAesContext at every call site. The AaFont symbol
rename is applied in the generator (scripts/fonts/convert_fonts.py) and
mirrored into the generated files. External ABI contracts that cannot be
renamed (app_main, NimBLE C symbols, the __wrap_ linker prefix, the
std-container/std::string API spellings of InplaceVector/InplaceString) are
NOLINT-suppressed with rationale.
Also fix what the healed parse newly surfaced: brace-init the va_list locals
flagged by cppcoreguidelines-init-variables and use auto for the two
static_cast initializers in totp_screen_controller, and rename the s_-prefixed
range-for loop variables in bond_store, name_store_task, and ble_event_bus.
clang-tidy: 239 -> 117 findings; identifier-naming, init-variables, and
use-auto are now at zero.
Claude-Session: https://claude.ai/code/session_01SV58JXhfxhhc9DC6vdjBo4
Fix branch-clone, rounding, cast, and remaining long-tail findings
- bugprone-branch-clone (12): fold genuinely identical switch arms
(typing status map, PM1 power levels, wake-cause names, glyph
fallback), merge the duplicated small-panel atlas ladder, rebuild
scaleFor as per-panel constexpr scale tables (lookup-table idiom),
restructure the modal confirm poll around explicit hold/press
predicates (also clears the DeMorgan finding), and NOLINT the one
per-SoC gated ADC calibration switch with rationale.
- bugprone-casting-through-void (13): use direct reinterpret_cast (the
documented pro-type-reinterpret-cast deviation) for byte/sockaddr
views; keep the SPI slot two-step through void* with rationale (it
exists to satisfy -Werror=cast-align next to the static_asserts).
- bugprone-incorrect-roundings (9): std::lroundf instead of +0.5 casts.
- cert-dcl50-cpp (5): rationale NOLINTs on the printf-style formatters
(a parameter pack cannot produce the va_list vsnprintf needs).
- cppcoreguidelines-pro-type-const-cast: const-correct the WordReader
ctx (API + trampoline + tests, const_cast deleted); NOLINT the two
std <cstring>-convention mutable overloads.
- Long tail: explicit void* casts + sizeof(T) rationale in rtos_queue,
range-for loop conversions, 0x80-mask instead of int8_t reinterpret
for the AXP2101 gauge, uint8_t slot subscript, parenthesized -1 pin
macros, extended the __wrap_log_printf ABI suppression to the
reserved-identifier aliases, integer-center tween targets.
Claude-Session: https://claude.ai/code/session_01SV58JXhfxhhc9DC6vdjBo4
Harden BLE bond lifecycle and land full on-device QA coverage
Defensive BLE audit of src/ble/ (audit dossier: docs/security/audit-ble.md).
The stack was sound; this closes the one actionable finding plus the QA gaps.
BLE-L1 (the finding): BLE bonds survived a vault wipe / factory reset — the
NimBLE keystore (nimble_bond NVS), the kleidos_blnames name blob, and its RTC
mirror all live in NVS, which wipeAll() never touched, so a previous owner's
bonded hosts and the device IRK persisted across a factory reset. Add
BondStore::factoryReset() (erases all three backing stores, radio OFF) exposed
via Facade::factoryResetBonds() and wired into every wipe path (pin_state
brute-force wipe, settings wipe, boot recovery, debug WIPEVAULT/lockout). Clearing
the RTC mirror is essential — reconcile() would otherwise resurrect the bonds
after the post-wipe reboot. Validated on-device. Native regression in
test_bond_store / test_name_store.
QA coverage: implement and validate the eight proposed BLE QA tests —
nc-reject (QA-1), conn-param (QA-2), disconnect (QA-4), factory-reset regression
(QA-5), adv-minimization (QA-7) on the mastodon Linux/BlueZ central; redaction
(QA-6) + UTF-8 robustness (QA-8) in CI; and N4 eviction (QA-3) end-to-end on the
DUT via the ESP32 Plus1 central. New mastodon scenarios (adv-scan,
disconnect-mid-type, conn-param, evict, restore) in ble_attack.sh + ble_probe.py.
Plus1 harness: unify the separate _blehost/_wifihost binaries into one
command-switchable BLE+WiFi binary (m5stickc_plus1_host, MODE BLE|WIFI|NONE).
Add an OWNADDR command that rotates the central's LE random-static identity
(fills the DUT bond table for N4 eviction, no BlueZ). Fix two firmware bugs: the
harness was mute without KLEIDOS_USB_SERIAL_CONSOLE (serial facade compiled to
no-op stubs), and identity rotation broke discovery until OWNADDR/FORGET also
clear the resolving list (ble_hs_resolv_list_clear_all).
CVE maintenance: register CVE-2025-53470/53477 (NimBLE HCI, low-reachability)
and record the advertising-report/Mesh/BlueDroid/BluFi CVEs as not-applicable;
2026 re-check found no new NimBLE CVEs. Plus readability + file:line doc-drift
fixes across ble.md / cve-register.md.
Gates: native 233/233, sticks3 + m5stickc_plus2 + m5stickc_plus1_host build
clean, pio check no defects, clang-format/check_layout/check_variants/typos/
gitleaks/ruff/editorconfig all pass.
Claude-Session: https://claude.ai/code/session_01MyjYtwfLCwUUfGVYuTQqSv
Fix branch-clone, rounding, cast, and remaining long-tail findings
- bugprone-branch-clone (12): fold genuinely identical switch arms
(typing status map, PM1 power levels, wake-cause names, glyph
fallback), merge the duplicated small-panel atlas ladder, rebuild
scaleFor as per-panel constexpr scale tables (lookup-table idiom),
restructure the modal confirm poll around explicit hold/press
predicates (also clears the DeMorgan finding), and NOLINT the one
per-SoC gated ADC calibration switch with rationale.
- bugprone-casting-through-void (13): use direct reinterpret_cast (the
documented pro-type-reinterpret-cast deviation) for byte/sockaddr
views; keep the SPI slot two-step through void* with rationale (it
exists to satisfy -Werror=cast-align next to the static_asserts).
- bugprone-incorrect-roundings (9): std::lroundf instead of +0.5 casts.
- cert-dcl50-cpp (5): rationale NOLINTs on the printf-style formatters
(a parameter pack cannot produce the va_list vsnprintf needs).
- cppcoreguidelines-pro-type-const-cast: const-correct the WordReader
ctx (API + trampoline + tests, const_cast deleted); NOLINT the two
std <cstring>-convention mutable overloads.
- Long tail: explicit void* casts + sizeof(T) rationale in rtos_queue,
range-for loop conversions, 0x80-mask instead of int8_t reinterpret
for the AXP2101 gauge, uint8_t slot subscript, parenthesized -1 pin
macros, extended the __wrap_log_printf ABI suppression to the
reserved-identifier aliases, integer-center tween targets.
Claude-Session: https://claude.ai/code/session_01SV58JXhfxhhc9DC6vdjBo4