Releases: FilipNowakowicz/info-kierowca-notifier
Release list
v2.3.1
What's new
v2.3.1 is a focused fix for the automatic Profil Zaufany relogin flow: it no longer retries forever after repeated failures, and the dashboard now tells you clearly when it's given up and is waiting on you.
Profil Zaufany relogin
- Consecutive-failure cap: an automatic Profil Zaufany login submits a real saved password and, on a rejected SMS code, a real failed one-time-code attempt. Retrying that unattended forever — the previous behavior, on an hourly-capped backoff — risked tripping a temporary lockout on the identity provider's own side. Automatic attempts now stop outright after 3 consecutive failures instead of continuing to retry; a manual retry (Settings → "Get new session now") still always works and clears the counter on success.
- Dashboard indicator: when automatic retries are paused this way, the dashboard now shows "Session expired — manual retry required" with a pointer to Settings, instead of looking identical to the ordinary "still retrying on its own" state. Previously the only sign was a single notification that was easy to miss.
- One-time alert: a desktop + phone notification fires the moment the cap is first crossed, on top of the per-failure alert already sent.
QR-wording fixes
Every place that could trigger or describe a relogin — Settings' "Get new session now", the login screen, restart flows — was hardcoded to say "QR login"/"scan the QR" regardless of the configured method. These now correctly say "Profil Zaufany login" for accounts using that method, since it authenticates with a saved username/password and an SMS code, not a QR code.
Validation
- 367 automated tests passed locally, with 3 OpenSSL-dependent tests skipped.
- CI passed on Python 3.9, 3.11, and 3.13, including the installed-wheel smoke test.
- PyInstaller builds succeeded for Windows, macOS, and Linux.
v2.3.0
What's new
v2.3.0 is a security-hardening and correctness pass across the local dashboard, the booking automation, and the Windows QR-login flow, plus a few smaller UX fixes.
Security fixes
- CSRF: every state-changing endpoint (setup, reset account, pause, relogin, quit, ...) now requires a matching Host/Origin and JSON content type, closing a gap where any web page open in the same browser could silently POST to the local dashboard.
- Stored XSS: the notification-topic field was interpolated unescaped into the Settings page; it's now delivered the same safe way every other field already was.
- DNS rebinding:
/settingsand/status.jsonnow validate the request's Host header too, not just the GET-vs-POST split. - Session cookie leak: the info-kierowca.pl session cookie could be forwarded across an HTTP redirect to a different origin; redirects now strip credential headers whenever the target origin differs.
- Assorted hardening: PZ login credential-typing TOCTOU window closed, host-suffix matching fixed against a look-alike-domain edge case,
tools/diagnose.py's page-capture now redacts PKK/PESEL/OTP-shaped text instead of a since-broken code path silently skipping the redaction it claimed to do, and every state file/log/directory this app writes is now consistently locked to owner-only permissions.
Booking automation correctness (auto_select_slot / auto_confirm_reschedule)
These flags are still off by default and still experimental, but several real correctness bugs in the matching/confirmation logic are fixed:
- Slot matching is now scoped to both the correct exam centre and the correct date — previously a same-time/type slot at the wrong centre or wrong date group could be selected.
- The pre-confirm summary check is now scoped to the actual modal instead of the whole page behind it.
- The final confirm click can no longer double-submit on a slow/lost network response.
- A single transient error no longer permanently disables post-booking verification.
- Accounts with more than one active booking (e.g. theory + practical) can now verify a successful reschedule correctly.
Not yet re-verified against the live site — the DOM-dependent parts of this pass (row/date-group scoping, the modal selector, the new centre-match rule) are logic-verified and covered by 50+ new tests, but watch the first live auto_confirm_reschedule run closely before trusting it unattended. The new centre-match rule fails closed (refuses rather than guesses) if it can't confirm a match.
Windows QR-login
Re-diagnosed a reported stall where Chrome opened the login page but never clicked through. The initial --lang=pl-PL fix turned out not to be the cause; this release adds real diagnostics (viewport size, DPI, registration acknowledgement) instead of guessing again, and separately fixes a confirmed bug where backing out of the login flow past an origin boundary could re-trigger auto-clicking forward against the user's own navigation.
Other
- PKK number/license category now prefill on the Settings page too (previously only on first run), with a read-only masked display for a single profile and a partially-masked picker for multiple.
- Session-expiry countdown is hidden for Profil Zaufany accounts, since that session renews itself proactively; the manual "get new session" action moved into Settings.
- Added a favicon.
Validation
- 350 automated tests passed locally, with 3 OpenSSL-dependent tests skipped.
- CI passed on Python 3.9, 3.11, and 3.13, including the installed-wheel smoke test.
- PyInstaller builds, packaged TLS policy checks, verified HTTPS smoke tests, and packaged keyring discovery smoke tests passed on Windows, macOS, and Linux.
v2.2.0
What's new
v2.2.0 adds an opt-in headless mode for automatic Profil Zaufany session renewal. Once Profil Zaufany and Google Messages Web are configured, the app can refresh an expiring info-kierowca.pl session without opening a visible browser window.
Highlights
- Adds a Run automatic Profil Zaufany login in the background option in Settings.
- Runs the dedicated renewal browser with modern Chrome headless mode when enabled.
- Keeps visible browser mode as the default, so existing installations behave as before.
- Keeps mObywatel QR login visible because it still requires a manual scan.
- Preserves the same secure credential-vault, Google Messages OTP, session-capture, and retry safeguards in both visible and headless modes.
Documentation and downloads
- Refreshes the English and Polish READMEs around one-time login, notifications, and optional automatic rescheduling.
- Adds direct Windows, macOS, and Linux download links plus clearer Polish search terminology.
Validation
- Completed a live end-to-end headless Profil Zaufany renewal with refreshed session cookies.
- 244 automated tests passed locally, with 3 OpenSSL-dependent tests skipped.
- CI passed on Python 3.9, 3.11, and 3.13, including the installed-wheel smoke test.
- PyInstaller builds, packaged TLS policy checks, verified HTTPS smoke tests, and packaged keyring discovery smoke tests passed on Windows, macOS, and Linux.
v2.1.0
What's new
v2.1.0 reorganizes the application into an installable src package and separates shared browser, authentication, booking, client, and notifier infrastructure without changing the notifier’s intended behavior.
Highlights
- Provides a conventional installable package and console entry point.
- Extracts shared browser interaction and Chrome lifecycle infrastructure.
- Separates authentication and booking launch flows from the core notifier.
- Adds installed-wheel smoke coverage alongside Python 3.9, 3.11, and 3.13 tests.
- Ensures manual release-workflow runs build and test artifacts without publishing a release.
Validation
- 242 automated tests passed locally, with 3 skipped.
- CI passed on Python 3.9, 3.11, and 3.13, including the installed-wheel smoke test.
- PyInstaller builds, packaged TLS policy checks, verified HTTPS smoke tests, and packaged keyring discovery smoke tests passed on Windows, macOS, and Linux.
v2.0.1
What's new
v2.0.1 is a focused reliability and security update for automatic Profil Zaufany authentication. It preserves the working v2.0.0 login flow, mObywatel support, Google Messages integration, localization, and existing release behavior.
Highlights
- Makes OTP discovery resilient when PZePUAP timestamps a valid SMS shortly before the challenge form appears, while retaining preexisting-code and maximum-age protections.
- Interprets PZePUAP timestamps explicitly in the Europe/Warsaw timezone, independent of the computer's configured timezone.
- Safely cleans up the previous OS-keyring credential after switching PZ usernames without risking loss of the new or old credential during a failed save.
- Waits for an attached Chrome CDP endpoint to actually stop before considering browser shutdown complete.
- Rejects retained Google Messages tabs that have navigated away from the exact HTTPS Messages origin.
- Avoids guessing when multiple Profil Zaufany chooser controls are equally plausible.
- Strengthens packaged secure-keyring validation without writing test credentials.
- Allows Reset Account to clear local state when the OS keyring is unavailable and reports an accurate warning.
- Restricts the persistent Chrome profile to owner-only permissions on POSIX and binds remote debugging explicitly to loopback.
Validation
- 190 automated tests passed on Python 3.9, 3.11, and 3.13.
- Clean Linux PyInstaller build passed.
- Packaged TLS and keyring smoke tests passed locally.
- Release artifacts are built separately for Windows, macOS, and Linux by the tag-triggered workflow.
Live verification recommended
After upgrading, verify one complete automatic Profil Zaufany login and, if applicable, Google Messages pairing/profile reuse on the target desktop platform.
v2.0.0
What's new
Automatic Profil Zaufany login
- The notifier can now refresh an expired session by signing in through Profil Zaufany instead of requiring a fresh QR scan each time.
- Choose Profil Zaufany in setup or Settings, save the username and password, and pair Google Messages for Web so the app can collect the fresh PZePUAP SMS code during login.
- Passwords stay in the operating system credential store. Passwords and one-time codes are not written to config, logs, notifications, command lines, or control files.
- Authentication is bounded, target-scoped, and fails closed if the browser reaches an unexpected origin or ambiguous page. mObywatel QR login remains available.
Safer, more resilient browser automation
- Browser work is pinned to the exact tab created for the operation instead of falling back to another open tab.
- Login and rescheduling clicks now reject hidden, ambiguous, unrelated, or sensitive controls and keep diagnostics redacted.
- Automatic relogin uses persisted exponential backoff, while manual retry remains available. A deliberately confirmed restart can cooperatively replace a stuck relogin without trusting a stale PID or starting a second browser too early.
- Cross-platform process checks, restart tokens, lock ownership, and concurrent state writes have been hardened.
Search and notification improvements
- Added an optional earliest acceptable exam date, enforced both in the API request and against returned slots.
- The existing-booking reminder can now be dismissed and remains separate from account configuration.
- ntfy test pushes and runtime notifications now report real delivery outcomes instead of silently treating failures as success.
Cross-platform security and packaging
- HTTPS now uses verified native OS trust with a verified certifi fallback only for certificate-chain discovery failures; explicit CA configuration remains authoritative and fail-closed.
- CI now discovers the full test suite and systemd units support common portable uv and Nix/NixOS paths.
- Linux, macOS, and Windows packages are built with verified HTTPS and credential-store discovery smoke tests.
v1.3.0
What's new
English & Polish interface
- The setup flow, Settings, dashboard status, dialogs, validation messages, calendar, and accessibility labels are now available in Polish as well as English.
- Use the
EN · PLswitch in the setup/Settings header. The choice takes effect immediately and is remembered on this device without becoming part of your account or session data. - Added a complete Polish README, linked alongside the English documentation.
Clearer rescheduling setup
- Setup now makes the prerequisite explicit: you need an existing confirmed booking because the app changes the date of that booking; it cannot create a new booking.
- The booking-date field and documentation now describe it as the date of the booking to reschedule.
Reliability fixes
- Fixed Settings initialization so existing saved configuration reliably appears when the page opens.
- Fixed QR-login helper launches to preserve the app's runtime home and state paths, so isolated or alternate profiles can observe the login session they create.
v1.2.2
What's new
Automatic slot-selection fix
- Automatic slot selection:
auto_select_slotcould silently fail because the booking portal's slot picker does not reliably render a radio input; its clickable target is the whole slot row. The selector now finds the most specific row matching both the exam type and time, then clicks its clickable ancestor. - This repairs the slot-picking stage of the experimental autonomous rebooking flow, allowing it to reach the reservation summary screen when a matching slot is found.
- Safety note: automatic final confirmation (
auto_confirm_reschedule) remains off by default and is still unverified end-to-end. Leave it disabled until the full flow has been confirmed with a real booking.
v1.2.1
What's new
Windows login-automation fixes
- Chrome detection:
find_chrome()only searched PATH names likegoogle-chrome— a Linux/Mac convention Windows Chrome installs never register under — so it silently fell back to Edge even when Chrome was installed. Now also checks the standard Windows "App Paths" registry key (the same mechanism Windows itself uses to resolvechrome.exe), so it finds Chrome regardless of install location. - QR code not rendering: the login window was launched too narrow (460px, then 600px — both confirmed too small live), which put the login page below a responsive breakpoint that swaps the real QR image for a plain text backup code. Widened to 900x850.
- Diagnostics: added a standalone diagnostic tool (
diagnose.py, built via a new manually-triggeredDiagnosticActions workflow) that reports Chrome/Edge resolution details, orphaned browser processes, profile lock state, and runs a live bounded login-flow test — all in one plain-text report, no cookies/secrets included.
macOS (untested — no Mac available to verify against)
- Added a Spotlight (
mdfind) lookup for Chrome by bundle identifier, so it's found regardless of install location instead of only checking the common/Applicationspath. - Desktop notifications (separate from the ntfy phone push) previously only worked on Linux via
notify-sendand silently did nothing on macOS; now falls back toosascriptthere.
These two macOS changes are marked unverified in the code and CLAUDE.md — worst case they behave exactly as before (existing fallback path / silent no-op).
v1.2.0
What's new
Added
- Preferred time-of-day window: a dual-handle time slider in Settings (and
earliest_slot_hour/latest_slot_hourinconfig.json) so only slots within your chosen hours count as matches. A slot outside the window is ignored entirely — no push, no dashboard entry. - Experimental reschedule automation (opt-in, off by default, under Settings → Automation) — extends the existing reschedule assist past the date picker:
- Auto-select the matching slot (
auto_select_slot): after opening the reschedule date picker for your booking, selects the exact matching slot (right exam type + time) and advances to the summary/review screen. - Auto-confirm the reservation change (
auto_confirm_reschedule): goes one step further and clicks the final confirm — actually submitting the reservation change — but only after re-verifying the summary screen matches the intended slot. Requires auto-select, is gated behind a browser confirm dialog, and is UNVERIFIED against the live site (written from screenshots). Read docs/ADVANCED.md and confirm auto-select works reliably before ever enabling it. - Supporting safety around the above: automation output is logged to
reschedule.log, critical outcomes send a phone push, a 15-minute cooldown blocks repeat confirm attempts, andcurrent_slot_dateis auto-updated after a verified reschedule.
- Auto-select the matching slot (
Changed
- Urgency is now exclusive: a found slot only counts as urgent (red dashboard / phone push / auto-open browser) if it's on a strictly earlier date than your booked slot — a different time on the same day no longer triggers.
- The WORD exam-center dropdown now closes after each selection instead of staying open.
- Internal cleanup: split
app.py's HTML/JS intotemplates.py; deduplicated repeated plumbing (browser poll loops, the empty-status shape, browser-trigger outcome constants, the session-expired handler); cached the static exam-center list; the dashboard page is assembled once at startup.
Documentation
- Documented the session-expiry countdown and three previously-undocumented config keys (
poll_interval_seconds,earliest_slot_hour/latest_slot_hour); fixed the stale "checks every 60 seconds" note now that the interval is user-configurable (15–1800s). - Trimmed changelog-style narration from code comments and
CLAUDE.md, keeping rationale and live-verification notes.