Proof Portal

Project overview

Omarchy

ProbeLabs65 findings · 95 requirements

A 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.

Inbox
ReportR-4512GitHub issuePublicReceived

[Quattro] Sleep monitor keeps the delay inhibitor alive after the lock is secure

Reported by SamCod3 · filed Jul 27, 2026Closed upstream on 2026-07-30 by the merge of PR #6436 (closed by dhh). GitHub close reason: completed.

Received and recorded verbatim. Nothing has been checked yet.

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?
Not yet mapped to any requirement or component.
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?
Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. No decision has been recorded yet.

Original report

[Quattro] Sleep monitor keeps the delay inhibitor alive after the lock is securerevision 1 · captured 2026-10-04 11:56 UTC via poll

System details

Important

This report is specifically for the Quattro branch. It has not been
reproduced on stable Omarchy.

  • Omarchy Quattro dev (c7f7e837)
  • Arch Linux kernel 7.1.5-arch1-1
  • systemd 261
  • Quickshell 0.3.0 (10b439fc)
  • s2idle on an AMD mini PC
  • The shipped InhibitDelayMaxSec=15 drop-in is active
  • Suspend was requested manually from an active, unlocked session
  • The failure was reproduced with the stock omarchy-sleep-lock.service and

omarchy-system-sleep-monitor; the local override described below was
installed only after the failure

What's wrong?

Summary

omarchy-system-sleep-monitor does not release its delay inhibitor when
omarchy-system-sleep-lock has successfully returned. The inhibitor remains
active until logind reaches InhibitDelayMaxSec.

The stock monitor runs this pipeline under systemd-inhibit:

dbus-monitor ... | omarchy-system-sleep-monitor --consume

After PrepareForSleep(true), the consumer runs the lock helper and exits.
However, dbus-monitor is still blocked waiting for another D-Bus event. It
does not notice the closed pipe until it tries to write again, and Bash waits
for the foreground pipeline as a whole. Therefore systemd-inhibit stays
alive even though the lock helper has finished.

On resume, PrepareForSleep(false) gives dbus-monitor another event to
write, the pipeline finally terminates, and the user service restarts. By then
logind has already exhausted the delay inhibitor and suspended the machine.

Security impact observed

In this run, the unnecessary delay became a security failure. The lock was
initially secure, but the lock surface was lost after display blanking while
the inhibitor was still being held. Logind then reached its timeout and
suspended the now-unlocked session.

Timeline from the journal and the Omarchy lock log:

11:19:58  logind receives the suspend request
11:19:59  Omarchy reports lock-requested and secure=true
11:20:05  Omarchy reports secure=false, session-locked=false, and unlocked
11:20:13  Delay lock is active (...) but inhibitor timeout is reached
11:20:13  system enters s2idle
12:26:04  system resumes directly into the unlocked session
12:26:06  omarchy-sleep-lock.service restarts

This is distinct from #6359: that report was retracted after its cause was
identified as a stale hyprlock process. There was no stale lock process in
this reproduction; the lock reached secure=true, and the process retaining
the inhibitor was the dbus-monitor pipeline.

Expected result

As soon as omarchy-system-sleep-lock returns successfully, the monitor side
of the pipeline should terminate and be reaped so that systemd-inhibit
releases the delay inhibitor immediately.

Actual result

The consumer exits, but dbus-monitor and the shell running the pipeline stay
alive. The inhibitor is released only after logind's timeout, not after the
lock becomes secure.

Reproduction

  1. Use the stock omarchy-sleep-lock.service and

omarchy-system-sleep-monitor.
2. Start from an active, unlocked session.
3. Run systemctl suspend.
4. After resuming, inspect the system journal and the Omarchy lock log.
5. Observe that the lock helper reaches secure=true, but logind later logs
inhibitor timeout is reached, and the sleep-lock service does not restart
until after resume.

The producer-lifetime bug can also be reproduced without a real suspend by
replacing dbus-monitor with a test producer that emits a matching
PrepareForSleep(true) event and then blocks. The consumer exits, while the
producer and the inhibited command remain alive.

Tested local fix

I replaced the anonymous pipeline with an explicitly managed dbus-monitor
coprocess. The monitor PID is retained, and an exit trap terminates and waits
for it after the lock helper returns.

The local fix passes:

  • bash -n
  • ShellCheck
  • an isolated regression test whose fake producer emits the sleep event and

then blocks
- systemd-analyze --user verify
- a real suspend/resume cycle

With the fix, the journal contains no inhibitor timeout and the real
suspend/resume cycle returns to the password prompt. I can open a PR with the
tested change and regression test if this approach is acceptable.

View raw text
### System details

> [!IMPORTANT]
> This report is specifically for the **Quattro** branch. It has not been
> reproduced on stable Omarchy.

- Omarchy Quattro `dev (c7f7e837)`
- Arch Linux kernel `7.1.5-arch1-1`
- systemd `261`
- Quickshell `0.3.0` (`10b439fc`)
- `s2idle` on an AMD mini PC
- The shipped `InhibitDelayMaxSec=15` drop-in is active
- Suspend was requested manually from an active, unlocked session
- The failure was reproduced with the stock `omarchy-sleep-lock.service` and
  `omarchy-system-sleep-monitor`; the local override described below was
  installed only after the failure

### What's wrong?

#### Summary

`omarchy-system-sleep-monitor` does not release its delay inhibitor when
`omarchy-system-sleep-lock` has successfully returned. The inhibitor remains
active until logind reaches `InhibitDelayMaxSec`.

The stock monitor runs this pipeline under `systemd-inhibit`:

```bash
dbus-monitor ... | omarchy-system-sleep-monitor --consume
```

After `PrepareForSleep(true)`, the consumer runs the lock helper and exits.
However, `dbus-monitor` is still blocked waiting for another D-Bus event. It
does not notice the closed pipe until it tries to write again, and Bash waits
for the foreground pipeline as a whole. Therefore `systemd-inhibit` stays
alive even though the lock helper has finished.

On resume, `PrepareForSleep(false)` gives `dbus-monitor` another event to
write, the pipeline finally terminates, and the user service restarts. By then
logind has already exhausted the delay inhibitor and suspended the machine.

#### Security impact observed

In this run, the unnecessary delay became a security failure. The lock was
initially secure, but the lock surface was lost after display blanking while
the inhibitor was still being held. Logind then reached its timeout and
suspended the now-unlocked session.

Timeline from the journal and the Omarchy lock log:

```text
11:19:58  logind receives the suspend request
11:19:59  Omarchy reports lock-requested and secure=true
11:20:05  Omarchy reports secure=false, session-locked=false, and unlocked
11:20:13  Delay lock is active (...) but inhibitor timeout is reached
11:20:13  system enters s2idle
12:26:04  system resumes directly into the unlocked session
12:26:06  omarchy-sleep-lock.service restarts
```

This is distinct from #6359: that report was retracted after its cause was
identified as a stale `hyprlock` process. There was no stale lock process in
this reproduction; the lock reached `secure=true`, and the process retaining
the inhibitor was the `dbus-monitor` pipeline.

#### Expected result

As soon as `omarchy-system-sleep-lock` returns successfully, the monitor side
of the pipeline should terminate and be reaped so that `systemd-inhibit`
releases the delay inhibitor immediately.

#### Actual result

The consumer exits, but `dbus-monitor` and the shell running the pipeline stay
alive. The inhibitor is released only after logind's timeout, not after the
lock becomes secure.

#### Reproduction

1. Use the stock `omarchy-sleep-lock.service` and
   `omarchy-system-sleep-monitor`.
2. Start from an active, unlocked session.
3. Run `systemctl suspend`.
4. After resuming, inspect the system journal and the Omarchy lock log.
5. Observe that the lock helper reaches `secure=true`, but logind later logs
   `inhibitor timeout is reached`, and the sleep-lock service does not restart
   until after resume.

The producer-lifetime bug can also be reproduced without a real suspend by
replacing `dbus-monitor` with a test producer that emits a matching
`PrepareForSleep(true)` event and then blocks. The consumer exits, while the
producer and the inhibited command remain alive.

#### Tested local fix

I replaced the anonymous pipeline with an explicitly managed `dbus-monitor`
coprocess. The monitor PID is retained, and an exit trap terminates and waits
for it after the lock helper returns.

The local fix passes:

- `bash -n`
- ShellCheck
- an isolated regression test whose fake producer emits the sleep event and
  then blocks
- `systemd-analyze --user verify`
- a real suspend/resume cycle

With the fix, the journal contains no inhibitor timeout and the real
suspend/resume cycle returns to the password prompt. I can open a PR with the
tested change and regression test if this approach is acceptable.

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.

No decision has been recorded yet.