Skip to content

0.61.4#22

Merged
tmunzer-AIDE merged 4 commits intomainfrom
0.61.4
Apr 1, 2026
Merged

0.61.4#22
tmunzer-AIDE merged 4 commits intomainfrom
0.61.4

Conversation

@tmunzer-AIDE
Copy link
Copy Markdown
Collaborator

@tmunzer-AIDE tmunzer-AIDE commented Apr 1, 2026

Version 0.61.4 (April 2026)

Released: April 1, 2026

This release improves WebSocket reconnection, hardens credential handling, and fixes the two-factor authentication flow.


1. NEW FEATURES

Capped Reconnect Backoff (max_reconnect_backoff)

The _MistWebsocket client now supports a max_reconnect_backoff parameter to cap the exponential backoff delay during reconnection attempts:

ws = mistapi.websockets.sites.DeviceStatsEvents(
    apisession,
    site_ids=["<site_id>"],
    auto_reconnect=True,
    max_reconnect_backoff=60.0  # Cap backoff at 60 seconds
)

Unlimited Reconnect Attempts

Setting max_reconnect_attempts=0 now enables unlimited reconnection attempts:

ws = mistapi.websockets.sites.DeviceStatsEvents(
    apisession,
    site_ids=["<site_id>"],
    auto_reconnect=True,
    max_reconnect_attempts=0  # Reconnect indefinitely
)

2. IMPROVEMENTS

Credential Override Logging

APISession now logs INFO-level messages when credentials (host, email, password, API token) are overridden by:

  • Constructor parameters overriding environment variables
  • Vault secrets overriding previously loaded values
  • Keyring credentials overriding previously loaded values

Security: Password Cleared After Login

The stored password is now cleared from memory immediately after successful login authentication.

User Attribute Handling

_get_self() now only sets known user attributes (first_name, last_name, email, enable_two_factor, two_factor_verified, no_tracking, password_expiry, password_modified_time) instead of setting arbitrary response keys as object attributes.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Bumps mistapi to 0.61.4 and ships updates around WebSocket reconnection behavior plus APISession authentication hardening (including 2FA flow adjustments), along with corresponding release notes.

Changes:

  • Add max_reconnect_backoff and allow max_reconnect_attempts=0 (unlimited) across WebSocket wrappers and core reconnect loop.
  • Harden APISession behavior: log credential overrides, clear stored password after successful login, adjust 2FA flow endpoint usage, and restrict _getself() attribute assignment.
  • Release housekeeping: version bumps (pyproject.toml, __version.py, uv.lock), changelog entry, and submodule tracking update.

Reviewed changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/mistapi/websockets/__ws_client.py Implements capped exponential backoff + unlimited reconnect attempts semantics in reconnect loop.
src/mistapi/websockets/sites.py Propagates new reconnect parameter through site websocket wrappers.
src/mistapi/websockets/orgs.py Propagates new reconnect parameter through org websocket wrappers.
src/mistapi/websockets/location.py Propagates new reconnect parameter through location websocket wrappers.
src/mistapi/websockets/session.py Adds new reconnect parameter to SessionWithUrl.
tests/unit/test_websocket_client.py Minor formatting change to an existing unit test signature.
src/mistapi/__api_session.py Adds override logging, clears password on successful login, revises 2FA flow, and restricts _getself() attribute setting.
src/mistapi/api/v1/sites/sle.py Updates deprecation current_version fields to 0.61.4.
src/mistapi/__version.py Version bump to 0.61.4.
pyproject.toml Project version bump to 0.61.4.
uv.lock Lockfile version bump to 0.61.4.
CHANGELOG.md Adds 0.61.4 release notes describing websocket + auth changes.
.gitmodules Changes mist_openapi submodule branch from a pinned version branch to master.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 69 to +80
auto_reconnect: bool = False,
max_reconnect_attempts: int = 5,
reconnect_backoff: float = 2.0,
max_reconnect_backoff: float | None = None,
queue_maxsize: int = 0,
) -> None:
if max_reconnect_attempts < 0:
raise ValueError("max_reconnect_attempts must be >= 0")
raise ValueError("max_reconnect_attempts must be >= 0 (0 = unlimited)")
if reconnect_backoff <= 0:
raise ValueError("reconnect_backoff must be > 0")
if max_reconnect_backoff is not None and max_reconnect_backoff <= 0:
raise ValueError("max_reconnect_backoff must be > 0")
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New reconnect behavior (unlimited attempts when max_reconnect_attempts=0 and capped delay via max_reconnect_backoff) is introduced here, but the unit tests don’t cover either case. Add tests that (1) verify the attempt limit is not enforced when max_reconnect_attempts=0 and (2) verify delay is capped when max_reconnect_backoff is set (e.g., by patching Event.wait / logger to observe the computed timeout).

Copilot uses AI. Check for mistakes.
Comment on lines 86 to 90
auto_reconnect: bool = False,
max_reconnect_attempts: int = 5,
reconnect_backoff: float = 2.0,
max_reconnect_backoff: float | None = None,
queue_maxsize: int = 0,
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constructor docstring documents max_reconnect_attempts/reconnect_backoff but doesn’t mention the newly added max_reconnect_backoff parameter (or that max_reconnect_attempts=0 means unlimited). Please update the parameter docs to match the signature so users discover the new option via help()/docs.

Copilot uses AI. Check for mistakes.
Comment on lines 75 to 82
ping_interval: int = 30,
ping_timeout: int = 10,
auto_reconnect: bool = False,
max_reconnect_attempts: int = 5,
reconnect_backoff: float = 2.0,
max_reconnect_backoff: float | None = None,
queue_maxsize: int = 0,
) -> None:
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wrapper exposes the new max_reconnect_backoff parameter, but its docstring parameter list doesn’t document it (and also doesn’t note the updated semantics where max_reconnect_attempts=0 means unlimited). Please update the docstring for this class (and the other websocket wrappers updated similarly) so the public API docs stay accurate.

Copilot uses AI. Check for mistakes.
"two_factor_verified",
"no_tracking",
"password_expiry",
"password_modified_time",
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_getself() now only sets a small whitelist of keys via setattr(). This drops fields that the class already models/prints elsewhere (e.g., via_sso/phone/session_expiry in str), so those values will no longer reflect the /api/v1/self response. Either expand the whitelist to include the supported APISession attributes (at least those referenced by str/public API), or update str/attribute model to remove fields you no longer intend to populate.

Suggested change
"password_modified_time",
"password_modified_time",
"via_sso",
"phone",
"session_expiry",

Copilot uses AI. Check for mistakes.
Comment on lines 740 to 745
resp = self._session.post(self._url(uri), json=body)
if resp.status_code == 200:
LOGGER.info("apisession:_process_login:authentication successful!")
CONSOLE.info("Authentication successful!")
self._password = None
self._set_authenticated(True)
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Password clearing after successful login is a security-sensitive behavior change and should be covered by unit tests. Add tests that ensure (a) _password is cleared after a successful /api/v1/login, and (b) the 2FA flow (login_with_return with two_factor) still succeeds using the new /api/v1/login/two_factor endpoint after the password has been cleared.

Copilot uses AI. Check for mistakes.
path = mist_openapi
url = https://github.com/mistsys/mist_openapi.git
branch = 2602.1.8 No newline at end of file
branch = master No newline at end of file
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching the mist_openapi submodule tracking from a versioned branch to master makes builds non-reproducible and can unexpectedly pull breaking API spec changes. Consider keeping this pinned to a specific release branch/tag/commit (or document why master is required) and reflect the spec version change in the changelog/release notes if it’s intentional.

Suggested change
branch = master
branch = v1.0.0

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

tmunzer-AIDE and others added 2 commits April 1, 2026 11:03
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@tmunzer-AIDE tmunzer-AIDE merged commit 652cf60 into main Apr 1, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants