The health model only knew "wu"/"wslink", so with an Ecowitt setup the
active_protocol / integration_status fell back to "PWS/WU" even while Ecowitt data
was flowing.
- Replace _protocol_name() with _configured_protocol() which returns
wu / wslink / ecowitt (legacy endpoint takes precedence; ecowitt-only -> ecowitt).
- _refresh_summary: treat "ecowitt" as a real accepted protocol (active_protocol and
online_<proto> now track it); the WU-vs-WSLink mismatch -> degraded check is scoped
to the legacy pair so coexisting Ecowitt is never falsely degraded.
- Add the "ecowitt" / "online_ecowitt" entity states to strings/en/cs.
310 passing, 100% coverage; ruff + basedpyright clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Security (from the deep audit):
- S1: health "integration_health" sensor no longer dumps the full snapshot in
extra_state_attributes (readable by any HA user). public_health_snapshot()
strips internal network details (source IP, internal URLs, raw add-on status);
full data stays on the authenticated endpoint and admin-only diagnostics.
- S2: anonymize() now masks the Ecowitt passkey/PASSKEY.
- S3: Windy station id masked before logging the dataset.
- S4: diagnostics redacts internal network fields (source IP, URLs, raw_status).
i18n (Q1/Q2):
- Sync strings.json + en.json with the actual flow: add wslink_port_setup step,
the ecowitt/pocasi/wslink_port_setup menu entries, the pocasi_* and
windy_key_required error keys, the stale_sensors_detected issue; fix wrong data
keys (WSLINK->wslink + legacy_enabled, POCASI_CZ_SEND_INTERVAL->POCASI_SEND_INTERVAL,
pocasi_enabled_checkbox->pocasi_enabled_chcekbox); translate the English ecowitt
options step (was Czech); de-duplicate the legacy-battery issue description.
- Q2: rename wbgt_index -> wbgt_temp to match the entity translation_key.
- cs.json: add windy_key_required and fix the pocasi data/data_description keys.
Tests: 300 passing, 100% coverage maintained; basedpyright clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The /station/health route is registered directly on the aiohttp router, so HA's
auth middleware only flags requests without blocking them - the endpoint was
reachable unauthenticated and returned the full health snapshot.
- health_status now requires HA authentication (bearer token or signed request)
via KEY_AUTHENTICATED and returns 401 otherwise.
- Mask the Ecowitt webhook id (the endpoint's only credential) in last_ingress
paths via _sanitize_path, so it never enters the snapshot exposed by the health
endpoint or the diagnostics download.
- Redact ECOWITT_WEBHOOK_ID in diagnostics.
- Compare the Ecowitt webhook id in constant time (hmac.compare_digest), matching
the WU/WSLink credential checks.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>