Proof Portal
Omarchy
ProbeLabs65 findings · 95 requirementsA proof layer — requirements, tests and verified fixes — for two of Omarchy's subsystems: the application menu (launcher scripts, QML model, JSONC config, search and selection) and the lock screen (lock scripts, QML, PAM authentication). Scope is deliberately limited to those components of omacom/omarchy; the rest of the distribution is not covered.
Network panel: Identity field steals focus from Passphrase on every Wi-Fi scan (WPA-Enterprise)
Reported by benskigomez · filed Aug 27, 2026 · open at source
At a glance
- 1 · What is claimed?
- Only the report text below — no validator has restated it as checkable claims yet.
- 2 · What does it affect?
- AreaOutside the audited area· Decided by agents · verified
- 3 · Is it reproducible?
- No validation has been run yet.
- 4 · What remains unclear?
- Not validated yet: no claims, no reproducer.
- 5 · What happens next?
- Decided by agents and verified by a second, independent agent — see the decision.
Original report
Omarchy 4.0.1-1, Hyprland 0.56.2, quickshell 0.3.1-1, NetworkManager 1.58.1-1.
What happens
Typing a passphrase for a WPA-Enterprise (WPA2 802.1X) network in the network
panel is close to impossible: every second or so the caret jumps out of thePassphrase field and back up into the Identity (user@domain) field above it.
The typed text isn't lost (it lives on the panel root), but the next keystrokes
land in the wrong field, so you end up with fragments of the passphrase inIdentity and have to start over.
It looks random from the user's side. It isn't — it's once per Wi-Fi scan result.
Why
Two things combine, both in shell/plugins/panels/network/Panel.qml.
syncWifiNetworks()reassigns the ListView's array model on every scan result:
wifiNetworks = Model.sortWifiRows(nets) // ~line 606The ListView's model is that plain JS array (~line 1486). Assigning a new
array resets the view, so every delegate is destroyed and recreated — including
the one holding the open credential prompt. scanDone fires this on a 1500ms
timer while the panel is open, and sortWifiRows re-sorts by signal, so an SSID
with several BSSIDs at fluctuating strength churns the list continuously.
- On rebuild,
idFieldunconditionally claims focus (~line 1854):
onVisibleChanged: if (visible) Qt.callLater(forceActiveFocus)
Component.onCompleted: if (visible) Qt.callLater(forceActiveFocus)pwField guards its equivalents with && !row.isEnterprise (~line 1880) so that
identity-first focus works when the prompt opens. But nothing stops idField from
re-grabbing focus on every subsequent rebuild.
This is why the bug is enterprise-only: on a PSK network idField is never visible,
and pwField re-focusing itself after a rebuild is invisible to the user.
The same unguarded onVisibleChanged also defeats failureTimer's explicitpwField.forceActiveFocus() after a wrong-password attempt — clearing the failure
banner makes idField visible again, and its queued callLater runs last.
Repro
- Be in range of a WPA2 802.1X network with several APs advertising the same SSID
(any normal corporate deployment).
2. Open the network panel (SUPER + CTRL + W) and click the enterprise network.
3. Start typing in Passphrase.
4. Roughly every 1.5s the caret jumps up to Identity.
Expected
Once a credential prompt is open, scan churn should not move keyboard focus.
Patch that fixes it locally
Freeze the model while a prompt is open, and stop idField re-claiming focus once
a passphrase has been typed:
- wifiNetworks = Model.sortWifiRows(nets)
+ if (passwordSsid === "") wifiNetworks = Model.sortWifiRows(nets)- onVisibleChanged: if (visible) Qt.callLater(forceActiveFocus)
- Component.onCompleted: if (visible) Qt.callLater(forceActiveFocus)
+ onVisibleChanged: if (visible && root.passwordText.length === 0) Qt.callLater(forceActiveFocus)
+ Component.onCompleted: if (visible && root.passwordText.length === 0) Qt.callLater(forceActiveFocus)Running with this applied via omarchy plugin clone omarchy.network; the prompt is
stable and the caret stays put. Happy to open a PR if the approach looks right —
preserving focus across the rebuild (rather than freezing the list) may be the
better fix if the list is meant to stay live.
Related
#7264 is a different failure in the same prompt (prompt never opens for a saved
network with a stale PSK), not a duplicate.
System
- CPU: 11th Gen Intel Core i5-1145G7
- GPU: Intel TigerLake-LP GT2 [Iris Xe]
- wpa_supplicant 2:2.12-1
View raw text
**Omarchy 4.0.1-1**, Hyprland 0.56.2, quickshell 0.3.1-1, NetworkManager 1.58.1-1. ## What happens Typing a passphrase for a **WPA-Enterprise (WPA2 802.1X)** network in the network panel is close to impossible: every second or so the caret jumps out of the `Passphrase` field and back up into the `Identity (user@domain)` field above it. The typed text isn't lost (it lives on the panel root), but the next keystrokes land in the wrong field, so you end up with fragments of the passphrase in `Identity` and have to start over. It looks random from the user's side. It isn't — it's once per Wi-Fi scan result. ## Why Two things combine, both in `shell/plugins/panels/network/Panel.qml`. 1. `syncWifiNetworks()` reassigns the ListView's array model on every scan result: ```qml wifiNetworks = Model.sortWifiRows(nets) // ~line 606 ``` The ListView's `model` is that plain JS array (`~line 1486`). Assigning a new array resets the view, so **every delegate is destroyed and recreated** — including the one holding the open credential prompt. `scanDone` fires this on a 1500ms timer while the panel is open, and `sortWifiRows` re-sorts by signal, so an SSID with several BSSIDs at fluctuating strength churns the list continuously. 2. On rebuild, `idField` unconditionally claims focus (`~line 1854`): ```qml onVisibleChanged: if (visible) Qt.callLater(forceActiveFocus) Component.onCompleted: if (visible) Qt.callLater(forceActiveFocus) ``` `pwField` guards its equivalents with `&& !row.isEnterprise` (`~line 1880`) so that identity-first focus works when the prompt opens. But nothing stops `idField` from re-grabbing focus on every subsequent rebuild. This is why the bug is enterprise-only: on a PSK network `idField` is never visible, and `pwField` re-focusing itself after a rebuild is invisible to the user. The same unguarded `onVisibleChanged` also defeats `failureTimer`'s explicit `pwField.forceActiveFocus()` after a wrong-password attempt — clearing the failure banner makes `idField` visible again, and its queued `callLater` runs last. ## Repro 1. Be in range of a WPA2 802.1X network with several APs advertising the same SSID (any normal corporate deployment). 2. Open the network panel (`SUPER + CTRL + W`) and click the enterprise network. 3. Start typing in `Passphrase`. 4. Roughly every 1.5s the caret jumps up to `Identity`. ## Expected Once a credential prompt is open, scan churn should not move keyboard focus. ## Patch that fixes it locally Freeze the model while a prompt is open, and stop `idField` re-claiming focus once a passphrase has been typed: ```diff - wifiNetworks = Model.sortWifiRows(nets) + if (passwordSsid === "") wifiNetworks = Model.sortWifiRows(nets) ``` ```diff - onVisibleChanged: if (visible) Qt.callLater(forceActiveFocus) - Component.onCompleted: if (visible) Qt.callLater(forceActiveFocus) + onVisibleChanged: if (visible && root.passwordText.length === 0) Qt.callLater(forceActiveFocus) + Component.onCompleted: if (visible && root.passwordText.length === 0) Qt.callLater(forceActiveFocus) ``` Running with this applied via `omarchy plugin clone omarchy.network`; the prompt is stable and the caret stays put. Happy to open a PR if the approach looks right — preserving focus across the rebuild (rather than freezing the list) may be the better fix if the list is meant to stay live. ## Related #7264 is a different failure in the same prompt (prompt never opens for a saved network with a stale PSK), not a duplicate. ## System - CPU: 11th Gen Intel Core i5-1145G7 - GPU: Intel TigerLake-LP GT2 [Iris Xe] - wpa_supplicant 2:2.12-1
Validation
Not checked yet. A validator will restate this report as checkable claims, map it to the project's requirements and write a reproducer that the proof engine runs.
Linked
Not linked to any known issue, other report or change yet.
Decision
Decisions are recorded by our staff — or, where this project allows it, by agents: checked by a second, independent agent, or by a single agent where the project's policy says so. Any decision reached so far is shown below.
- Out of scopeDecided by agents · verified · 2026-10-09 09:34 UTC