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
Doxygen polish B+C+D+E1/E4+G2: group descriptions, FSM diagrams, mainpage rewrite, UML look, platform-abstraction input
- B: Expand top-level group descriptions with @dot diagrams:
- hal: board hierarchy diagram (hal_common -> M5/TDeck -> drivers)
- ui: describe direct-draw vs LVGL-backed rendering paths
- diag: clarify scope vs platform_diag (G2)
- platform_diag: cross-ref to diag (G2)
- D: Rewrite mainpage.dox with FSM @dot, orientation table, power budget
table, security constraints, and @ref-based module listing
- C: Add docs/platform-abstraction.md to Doxyfile INPUT
- E1: Add UML_LOOK=YES to Doxyfile
- E4: Add REFERENCED_BY_RELATION=YES + REFERENCES_RELATION=YES (trial)
Raise DOT_GRAPH_MAX_NODES from 80 to 100
- fix: Filter 'ignoring \dot command' advisory from coverage probe
(HAVE_DOT=NO in probe mode, dots are only advisory not undoc warnings)
Gate: doxygen Doxyfile EXIT=0, check_doc_coverage.py [PASS]
Remediate WiFi audit findings, add resource telemetry and PMIC current
Implement the WiFi subsystem defensive-audit remediations (dossier in
docs/research/wifi-audit-dossier.md) plus a resource-consumption monitor and
per-chip power telemetry.
Security (audit findings):
- OTA: real semver anti-downgrade (running vs candidate partition), rollback
enabled on shipping open/_release builds, size/BLE-state guards.
- Lifecycle: keyboard variants run the real goToSleep() teardown+wipe (LIFEC-001);
exit() always tears down the portal (LIFEC-003); loop task subscribed to the
TWDT (LIFEC-004); symmetric BLE/WiFi start guard (LIFEC-002); master key wiped
before the handover reboot (LIFEC-008); on-device idle warning + panel dimming.
- HTTP: DNS-rebinding Host guard with captive-portal exemption (HTTP-003, incl.
the 403 reason-phrase fix found on hardware); idle-based session TTL (HTTP-001);
sliding-window rate limiter (HTTP-006, native test); /stream token no longer
logged (HTTP-005).
- Radio: H2E-only SAE, TX-power cap, stack wifi_config_t scrub, WPA2 fail-closed,
bootloader-random AP password, DHCP-DNS offer.
- Web UI: stored-XSS removal via safe DOM builders, autocomplete controls, CSP
meta, deterministic gzip; SPA gz regenerated.
- Optimization: nothrow HTTP body alloc, std::move export responses, CPU boost
around the export KDF, ~1 Hz AP snapshot poll, early never-connected AP shutdown.
Telemetry / consumption:
- Per-tick UI-loop latency gauge (loop_dt_us / loop_max_us) via diag helpers.
- RES? extended with heap fragmentation, SoC die temperature, battery mV/%/current
and VBUS (USB) mV/current.
- PowerManager / IPmic gain optional current + VBUS readouts; implemented for the
AXP192 (validated on a Plus1: batt 4.1 V, VBUS ~5.0 V, ~81 mA USB draw) and
"n/a" on the M5PM1 / AXP2101 fleet. See docs/research/pmic-consumption-telemetry.md.
QA harness (mastodon SSH rig):
- portal_checks.py adds Host-guard / security-header / idle plumbing / Core-0
stress-flood checks; wifi_net.sh requests SAE H2E; run.py forwards the stress
env; new pytest tests for admin lifecycle, WiFi stress-resource monitoring and
AXP192 current.
Verified: native 1472/1472; -Werror builds for sticks3, cardputer, sticks3_debug
and m5stickc_plus1_debug; clang-format, check_variants and check_conditionals
clean; HIL passes on sticks3 (via mastodon) and the AXP192 current path on the
Plus1. Known limitation in plan/plus1-softap-nomem.md: the admin SoftAP hits
ESP_ERR_NO_MEM on the no-PSRAM Plus1 (pre-existing DRAM exhaustion).
Claude-Session: https://claude.ai/code/session_01NYGJirRyAokBs9idYmGLxi
Add multi-variant support, HAL reorganization, and per-variant vault limits
- Reorganize HAL into common/, m5/, tdeck/ subdirectories
- Add M5Stack Gray (DEVICE_ID=5) and T-Deck (DEVICE_ID=3) board support
- Add Plus 1.1 (DEVICE_ID=4) variant with 4MB partition table
- Add 16MB partition table for Gray and T-Deck
- Make MAX_CREDENTIALS/MAX_TOTP configurable per variant:
Plus1: 100/30, Plus2/StickS3: 150/40, Gray/T-Deck: 200/50
- Replace PBKDF2 with HMAC-SHA256 for WiFi admin sub-key derivation
- Add T-Deck HAL: keyboard, trackball, touch, TFT display, power manager
- Add LVGL UI framework for T-Deck (screens, themes, input)
- Add OnDeviceMenu, DevicePanel, PassphraseEntryUI components
- Add capture_all_screens.py screenshot utility
- Add docs/variants.md with full variant comparison
- Add SonarQube, clang-format, clang-tidy, editorconfig configs
- Update .gitignore to exclude __pycache__, *.log, screenshots/
Add variant-config consistency and editorconfig gates
Add scripts/check_variants.py, a pure-stdlib validator that enforces device
variant consistency: extra_configs registration (no orphans), required keys
on base variants, sdkconfig/partition reference integrity, the shared
sdkconfig.defaults.kleidos_ble include, -I variants/<dir> include paths,
flash-size agreement, unique env names, and KLEIDOS_BRANDS_* presence/ranges.
CoreInk is allowlisted as intentionally unregistered.
Add .ecrc to drive editorconfig-checker: disable the noisy IndentSize rule
(clang-format already governs C/C++ indentation) and exclude generated,
vendored, and binary trees. Normalize the tree to satisfy the remaining
checks: convert leading tabs to spaces in platformio.ini, six variant .ini
files, src/CMakeLists.txt, and scripts/run_include_cleaner.sh, and add final
newlines to .markdownlint.json, the CAD bounding-boxes JSON, and
AudioFeedbackSpeaker.cpp.
Wire both as blocking gates: variant-config-guard and editorconfig-checker
pre-commit hooks (ec pinned to 3.0.3) plus editorconfig and variants CI jobs.
No functional changes; sticks3 build and 428 native tests pass.
Add per-variant _release targets and Secure Boot upload guard
Give every device variant the full four-tier target set: base, _debug,
_release, and _secure. Previously only sticks3 had an explicit _release
env; the other variants jumped from the unsuffixed base build straight to
_secure, leaving no re-flashable open-production target.
- Add [env:<variant>_release] to cardputer, core2_v13, cores3_se,
m5core_ink, m5stack_gray, m5stickc_plus1, m5stickc_plus2, and tdeck.
Each extends its base env, unflags CORE_DEBUG_LEVEL=1, and sets
KLEIDOS_RELEASE=1 + CORE_DEBUG_LEVEL=0 (the proven _secure build_flags
minus the eFuse-burning secure partitions/cmake/guard). Partitions are
inherited from each variant's base env.
- The 4 MB / no-OTA boards (m5stickc_plus1, m5core_ink) get _release but
intentionally keep NO _secure target: Secure Boot v2 + Flash Encryption
needs 8 MB+ flash and these boards update by full re-flash.
- Add secure partition tables (partitions_8mb_secure.csv,
partitions_16mb_secure.csv) and scripts/secure_upload_guard.py, an
interactive PlatformIO pre-upload guard that forces explicit human
confirmation before flashing any irreversible *_secure image.
- Refresh sign_firmware.sh notes and the espsecure.py invocation; align
sdkconfig.release.defaults.opt-in.
Validated: scripts/check_variants.py reports 37 environments; building
m5stickc_plus2_release succeeds.
Add per-variant _release targets and Secure Boot upload guard
Give every device variant the full four-tier target set: base, _debug,
_release, and _secure. Previously only sticks3 had an explicit _release
env; the other variants jumped from the unsuffixed base build straight to
_secure, leaving no re-flashable open-production target.
- Add [env:<variant>_release] to cardputer, core2_v13, cores3_se,
m5core_ink, m5stack_gray, m5stickc_plus1, m5stickc_plus2, and tdeck.
Each extends its base env, unflags CORE_DEBUG_LEVEL=1, and sets
KLEIDOS_RELEASE=1 + CORE_DEBUG_LEVEL=0 (the proven _secure build_flags
minus the eFuse-burning secure partitions/cmake/guard). Partitions are
inherited from each variant's base env.
- The 4 MB / no-OTA boards (m5stickc_plus1, m5core_ink) get _release but
intentionally keep NO _secure target: Secure Boot v2 + Flash Encryption
needs 8 MB+ flash and these boards update by full re-flash.
- Add secure partition tables (partitions_8mb_secure.csv,
partitions_16mb_secure.csv) and scripts/secure_upload_guard.py, an
interactive PlatformIO pre-upload guard that forces explicit human
confirmation before flashing any irreversible *_secure image.
- Refresh sign_firmware.sh notes and the espsecure.py invocation; align
sdkconfig.release.defaults.opt-in.
Validated: scripts/check_variants.py reports 37 environments; building
m5stickc_plus2_release succeeds.
Fix LVGL/Xtensa build under IDF 6 GCC 15.2 toolchain
The T-Deck env (the only HAS_LVGL target) failed to build under the official
espressif32 7.0.1 platform (ESP-IDF 6.0.1 / GCC 15.2) for two toolchain reasons,
both confined to PlatformIO-built lib_deps (LVGL); the IDF's own sources, built
by CMake, are unaffected.
1. C++-only flags on C sources. The platform merges the IDF C++ compile options
into the shared SCons CCFLAGS; LVGL's C files then receive -fuse-cxa-atexit,
which the C frontend rejects under -Werror ("valid for C++/ObjC++ but not for
C"). New post-script scripts/strip_cxx_only_cflags.py relocates the known
C++-only flags from CCFLAGS/CFLAGS to CXXFLAGS on the project env and every
lib-builder env, so C++ TUs keep RTTI/atexit behavior and C ones build.
2. ARM SIMD assembly assembled for Xtensa. LVGL 9.x ships
draw/sw/blend/{helium,neon}/*.S, whose #include of lv_conf_internal.h pulls in
IDF-6/picolibc system headers with __ASSEMBLY__-unguarded typedefs; the Xtensa
assembler aborts ("unknown opcode 'typedef'"). The bodies are ARM-only
(__ARM_FEATURE_MVE) and dead on Xtensa, but the LDF assembles them anyway. The
same post-script neutralizes the two .S files in the resolved lib_deps tree
with an idempotent empty stub (reinstated by Library Manager on reinstall).
Also pin lvgl/lvgl to exactly 9.2.2 (was floating ^9.2.2, which now resolves to
9.5.0 under the new core) as the tested known-good version, and refresh
dependencies.lock.esp32 to IDF 6.0.1 for the classic-ESP32 (PICO) targets.
Verified: pio run -e tdeck SUCCESS (RAM 28.3%, Flash 32.9%). Full device fleet
(sticks3, m5stickc_plus2/plus1, m5stack_gray, m5core_ink, cardputer, tdeck,
cores3_se, core2_v13) builds SUCCESS under IDF 6.0.1 -Werror. Variant /
conditional / layout guards OK.