187 files

This commit is contained in:
Home Assistant Version Control
2026-10-09 11:57:31 +00:00
parent 28fa34d78a
commit 1e1b12d52b
187 changed files with 40899 additions and 32654 deletions
+31 -2
View File
@@ -56,13 +56,26 @@ _SENSITIVE_KEYS = {
"switch_entity",
"energy_price_entity",
"energy_sensor",
# The active-cycle snapshot's meter entity (kept in `failed_restore`).
"energy_meter_source",
}
# A record that names a setting in a field instead of using it as the dict key -
# a settings-changelog row is `{"key": "power_sensor", "old": ..., "new": ...}` -
# carries the sensitive value under these generic names, which slipped past the
# key-based redaction: entity ids, person.* and notify targets (audit PLATFORM-08).
_VALUE_FIELDS = ("old", "new", "value")
def _redact(obj: Any) -> Any:
if isinstance(obj, dict):
named = obj.get("key")
names_sensitive = isinstance(named, str) and named in _SENSITIVE_KEYS
return {
k: "**REDACTED**" if k in _SENSITIVE_KEYS else _redact(v)
k: "**REDACTED**"
if k in _SENSITIVE_KEYS or (names_sensitive and k in _VALUE_FIELDS)
else _redact(v)
for k, v in obj.items()
}
if isinstance(obj, list):
@@ -70,11 +83,23 @@ def _redact(obj: Any) -> Any:
return obj
async def _failed_restore(manager: WashDataManager) -> Any:
"""The kept failed-restore record, redacted; None on any problem reading it."""
try:
return _redact(await manager.profile_store.async_get_failed_restore())
except Exception: # noqa: BLE001 - the download must never fail on this
return None
async def async_get_config_entry_diagnostics(
hass: HomeAssistant, entry: ConfigEntry
) -> dict[str, Any]:
"""Return diagnostics for a config entry."""
manager: WashDataManager = hass.data[DOMAIN][entry.entry_id]
manager: WashDataManager | None = hass.data.get(DOMAIN, {}).get(entry.entry_id)
if manager is None:
# Setup failed or the entry is unloaded: the download must still work - it
# is how such a failure gets reported (audit PLATFORM-14).
return {"entry": _redact(entry.as_dict()), "manager_state": None}
# Full store export - same payload as the export_config service, but the
# entry_data / entry_options pass through the redactor to strip personal keys.
@@ -138,4 +163,8 @@ async def async_get_config_entry_diagnostics(
# state_history: [{ts, from, to, program}, ...] - detector state changes
# logs: [{ts, lvl}, ...] - log timestamps and levels (msg removed)
"live_diagnostics": manager.diag_buffer.redacted_snapshot(),
# The last active-cycle snapshot that failed to restore, with the error and
# its age (register item 266 follow-up); None when none ever has. A download,
# not a bus event, so the 32 KB event-data limit does not apply.
"failed_restore": await _failed_restore(manager),
}