Rework the M5 design doc data model and add manual-testing surface:
- Two-layer model: rename energy_meters/energy_readings -> generic
modbus_device + modbus_reading; readings become a JSON payload blob
instead of a wide fixed-column table (aggregation via SQLite
json_extract, generated-column index as a future lever).
- Protocol knowledge moves to read-only YAML profiles (data+functions,
no OOP inheritance); deployment/config (friendly_name, unit_id, host)
stays on the device row; multiple devices share one profile.
- UUID = stable internal identity, also anchors HA discovery unique_id
(Z2M rename model); device metadata for HA derived from the profile.
- Naming scheme C: modbus_* / /api/modbus/devices at the data+API layer,
'Energy' as the first domain view in the frontend.
- New task M5-T01B: ConfigPage Accordion sectioning (avoids a second
in-page side nav conflicting with the T01 app sidebar).
- Manual testing: read-only modbus_cli 'probe' subcommand (FC03/04 only,
no register writes); mqtt/test now publishes a test message viewable
in MQTT Explorer; no MQTT CLI (manual verification via UI + HA).
- README: add 前端 v2 (React SPA) section (dev/build/codegen/hosting/gates),
update directory listing, drop stale Jinja descriptions
- architecture-overview: retire '不引入前后端分离' constraint; reflect SPA + JSON API
- roadmap: mark M2 done
- remove orphaned jinja2 dependency (recompile requirements*.txt; no other churn)
- delete empty tests/test_auth.py stub; drop dead _extract_csrf_token in test_api_data
- verified image still builds and app imports with the slimmer deps
Record the decisions reached in planning into docs/design/m2-frontend-v2.md:
component library = Mantine; map = Leaflet (react-leaflet + leaflet.heat +
markercluster, isolated behind a component seam for a future MapLibre swap);
OpenAPI typed client committed + CI-checked; CSRF simplified to SameSite=Lax +
a custom write header (no per-session token); heatmap-first map as the home
view with a required time-range picker and an auxiliary paginated list;
record CRUD edits non-PK fields and deletes single rows (no UI create); bare
ingestion endpoints stay until M3; trips optional. Wireframes intentionally
skipped for this milestone.