Release v2.3 — Critical fixes & improvements - #1
Merged
Merged
Conversation
- clean up HonClient lifecycle failures and setup/unload cancellation paths - route command entities through their owning config-entry client - fail closed on missing sessions, appliance-list failures, partial updates, auth/reauth failures, and typed timeouts - classify auth vs retryable server errors in config flow, setup, and coordinator refresh - surface select/switch/climate command failures as HomeAssistantError - validate and roll back climate settings parameter assignment before sending - force post-command refresh through direct coordinator refresh and fail on stored refresh errors - add focused unittest coverage with Home Assistant stubs
- add explicit start/stop button entities for physical program actions - remove the misleading start/stop power switch - only expose program select for safe non-start program commands - stop using washer-only static program labels for dryer-capable selects - cover button platform forwarding, routing, and no-startProgram select regressions
tis24dev
added a commit
that referenced
this pull request
Jun 23, 2026
…t refresh Audit findings #1 (HIGH) and #14, plus the concurrent-refresh race. _check_headers refreshed the OAuth token before EVERY request whenever a refresh_token was present (#1): with several appliances and the asyncio.gather in load_commands, that is dozens of POST /services/oauth2/token per coordinator cycle (token is valid 8h), risking cloud rate-limit/block. A single 401 also cascaded into 3 refreshes (#14: pre-refresh + loop0 + recursion). Refresh only when there is no usable in-RAM token (first request / restart with a persisted refresh_token) or the token is near expiry; the 401 recovery in _intercept is unchanged, and since refresh() resets _expires the recursive _check_headers no longer fires a second time. An asyncio.Lock (on the connection, not the create()-replaced HonAuth) with a re-check collapses a concurrent burst into a single refresh, so a rotating IdP cannot invalidate the shared token mid-flight. Tests: no pre-refresh when fresh (#1), single refresh on 401 (#14), refresh on expires-soon, restart-with-token refreshes not logins, concurrent burst -> 1 refresh (lock).
tis24dev
added a commit
that referenced
this pull request
Jun 23, 2026
…t refresh Audit findings #1 (HIGH) and #14, plus the concurrent-refresh race. _check_headers refreshed the OAuth token before EVERY request whenever a refresh_token was present (#1): with several appliances and the asyncio.gather in load_commands, that is dozens of POST /services/oauth2/token per coordinator cycle (token is valid 8h), risking cloud rate-limit/block. A single 401 also cascaded into 3 refreshes (#14: pre-refresh + loop0 + recursion). Refresh only when there is no usable in-RAM token (first request / restart with a persisted refresh_token) or the token is near expiry; the 401 recovery in _intercept is unchanged, and since refresh() resets _expires the recursive _check_headers no longer fires a second time. An asyncio.Lock (on the connection, not the create()-replaced HonAuth) with a re-check collapses a concurrent burst into a single refresh, so a rotating IdP cannot invalidate the shared token mid-flight. Tests: no pre-refresh when fresh (#1), single refresh on 401 (#14), refresh on expires-soon, restart-with-token refreshes not logins, concurrent burst -> 1 refresh (lock).
tis24dev
added a commit
that referenced
this pull request
Jun 23, 2026
…t refresh Audit findings #1 (HIGH) and #14, plus the concurrent-refresh race. _check_headers refreshed the OAuth token before EVERY request whenever a refresh_token was present (#1): with several appliances and the asyncio.gather in load_commands, that is dozens of POST /services/oauth2/token per coordinator cycle (token is valid 8h), risking cloud rate-limit/block. A single 401 also cascaded into 3 refreshes (#14: pre-refresh + loop0 + recursion). Refresh only when there is no usable in-RAM token (first request / restart with a persisted refresh_token) or the token is near expiry; the 401 recovery in _intercept is unchanged, and since refresh() resets _expires the recursive _check_headers no longer fires a second time. An asyncio.Lock (on the connection, not the create()-replaced HonAuth) with a re-check collapses a concurrent burst into a single refresh, so a rotating IdP cannot invalidate the shared token mid-flight. Tests: no pre-refresh when fresh (#1), single refresh on 401 (#14), refresh on expires-soon, restart-with-token refreshes not logins, concurrent burst -> 1 refresh (lock).
tis24dev
added a commit
that referenced
this pull request
Jun 25, 2026
#2, #5) - _persist_refresh_token: update the config entry only when the live refresh token actually rotated (at setup and on each coordinator poll), so a rotated token survives a restart instead of replaying a stale one (#2). - HonClient: re-seed the stored refresh token after setup, after MFA verify, and after each poll, so a mid-life rotation is not lost on the next refresh (#1, #5). - tests: change-guarded persist (AST-checked call sites), mid-life rotation seed-sync, and the reauth re-seed handoff.
This was referenced Jul 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Critical Fixes
Major Fixes
Minor Fixes
Testing
Requirements