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
Remove the M5Stack Gray variant from the fleet
The M5Stack Gray is retired (owner-approved): the fleet drops from 9 to 8
device variants. This removes the Gray as a build target / device while
keeping every reusable driver and HAL layer intact.
Removed (Gray-exclusive wiring only):
- variants/m5stack_gray/ (variant.h, ini, sdkconfig, the four envs)
- src/boards/board_gray.cpp (the DEVICE_ID==5 board-registry factory)
- the web installer mockup (gray.svg + screen png) and app.js entry
- docs/hardware/devices/m5stack-gray.md and every fleet-list / inventory
/ identifier / secure-availability row across docs, CI, and instructions
Kept (per owner: preserve tested drivers/HAL even with no current consumer):
- the IP5306 PMIC driver family (src/drivers/power/ip5306*) — Gray was its
only board; still native-validated by test_small_pmic_regmaps
- the classic-ESP32 RTC_CNTL MMIO regmap (rtc_cntl_esp32_regmap.h) — Gray
was the only classic internal-RTC board; still native-validated
- board_gray_log_wrap.cpp renamed to board_log_printf_wrap.cpp: the
__wrap_log_printf stub is fleet-wide (esp32_base defines the gate), not
Gray-specific
DEVICE_ID 5 is retired and left unused so the remaining ids stay stable.
CI covering set rebalanced (Gray was the classic-ESP32 representative):
sticks3, tdeck, cores3_se, m5core_ink, m5stickc_plus2. m5stickc_plus2
(classic ESP32 + ST7789 full-frame polling + 8 MB OTA) replaces the Gray's
classic-ESP32 + OTA + polling coverage. core2_v13 is intentionally not added
to CI: it is an "Initial" WIP board that currently overflows DRAM at link
(pre-existing), so it cannot be a green gate member.
Native tests 2306/2306. Base envs build green for the new CI set
(sticks3, m5stickc_plus2, tdeck, cores3_se, m5core_ink).
Claude-Session: https://claude.ai/code/session_01P6BNTpbgrvnZXSJnNuj8ZJ
Add BM8563 RTC HIL coverage: regmap discovery, VL, alarm, timer
Add qa/tests/hw/test_rtc.py exercising the Phase-3 BM8563/PCF8563 RTC
introspection on real I2C hardware: REGS? chip discovery (0x51, 16 regs),
the raw VL+seconds decode (REGR 0x02), the clock-integrity VL flag via
RTC?, the non-critical alarm value-register round-trip (0x09-0x0C) with an
RTC? alarm_en cross-check, the timer reload round-trip (0x0F) accounting for
the BM8563 read-back-minus-one latch when TE=0, and the critical-register
write blocklist (0x00/0x01/0x0E must refuse a plain REGW, write-back-safe).
Every check is live-discovery driven and skips cleanly when bm8563 is not
registered (boards without a wired BM8563, e.g. sticks3), matching the
Phase-2 convention. The RTC-alarm deep-sleep wake seam is a separate,
slow-marked sub-check board-gated to m5core_ink (RTC_INT_PIN).
Extend test_regmap.py EXPECTED_CHIPS with the bm8563 entry (0x51, 16 regs)
so live discovery asserts the RTC registers fleet-wide.
Verified on hardware (MAC-verified flash): m5stickc_plus2 6 passed /
1 skipped (wake board-gate); sticks3 7 skipped (no BM8563, clean
live-discovery skip).
Claude-Session: https://claude.ai/code/session_01U878bNJtg9bCvAMM8CFKqS
Remove the M5Stack Gray variant from the fleet
The M5Stack Gray is retired (owner-approved): the fleet drops from 9 to 8
device variants. This removes the Gray as a build target / device while
keeping every reusable driver and HAL layer intact.
Removed (Gray-exclusive wiring only):
- variants/m5stack_gray/ (variant.h, ini, sdkconfig, the four envs)
- src/boards/board_gray.cpp (the DEVICE_ID==5 board-registry factory)
- the web installer mockup (gray.svg + screen png) and app.js entry
- docs/hardware/devices/m5stack-gray.md and every fleet-list / inventory
/ identifier / secure-availability row across docs, CI, and instructions
Kept (per owner: preserve tested drivers/HAL even with no current consumer):
- the IP5306 PMIC driver family (src/drivers/power/ip5306*) — Gray was its
only board; still native-validated by test_small_pmic_regmaps
- the classic-ESP32 RTC_CNTL MMIO regmap (rtc_cntl_esp32_regmap.h) — Gray
was the only classic internal-RTC board; still native-validated
- board_gray_log_wrap.cpp renamed to board_log_printf_wrap.cpp: the
__wrap_log_printf stub is fleet-wide (esp32_base defines the gate), not
Gray-specific
DEVICE_ID 5 is retired and left unused so the remaining ids stay stable.
CI covering set rebalanced (Gray was the classic-ESP32 representative):
sticks3, tdeck, cores3_se, m5core_ink, m5stickc_plus2. m5stickc_plus2
(classic ESP32 + ST7789 full-frame polling + 8 MB OTA) replaces the Gray's
classic-ESP32 + OTA + polling coverage. core2_v13 is intentionally not added
to CI: it is an "Initial" WIP board that currently overflows DRAM at link
(pre-existing), so it cannot be a green gate member.
Native tests 2306/2306. Base envs build green for the new CI set
(sticks3, m5stickc_plus2, tdeck, cores3_se, m5core_ink).
Claude-Session: https://claude.ai/code/session_01P6BNTpbgrvnZXSJnNuj8ZJ