Honor bread.command.lock.unlock via loginctl unlock-session
All checks were successful
Build and publish package / package (push) Successful in 3m15s
All checks were successful
Build and publish package / package (push) Successful in 3m15s
Subscribe the same locker and breadlock listen handlers. Already unlocked is bread.lock.unlock.done; otherwise run loginctl unlock-session and emit done / failed. Do not call compositor unlock() — PAM stays the compositor path (fail-secure). Document in EVENTS.md and README; drop the "Not implemented: unlock" paragraph. pin/blur stay unimplemented.
This commit is contained in:
parent
495fe1aaad
commit
d49df0b5fa
4 changed files with 135 additions and 39 deletions
40
EVENTS.md
40
EVENTS.md
|
|
@ -14,8 +14,8 @@ Commands are received on a `BreadClient::subscribe` background thread
|
|||
(reconnect/backoff) from two places:
|
||||
|
||||
- the locker process itself, while the session is locked
|
||||
- `breadlock listen`, a tiny long-running subscriber so the command
|
||||
works while unlocked
|
||||
- `breadlock listen`, a tiny long-running subscriber so lock/unlock
|
||||
work while unlocked
|
||||
|
||||
`breadgreet` is not wired to the bus. It runs under greetd (typically as
|
||||
the dedicated greeter user, before a user session exists), so breadd is
|
||||
|
|
@ -30,29 +30,38 @@ from session lock/unlock.
|
|||
| `bread.lock.unlocked` | `{}` | PAM authenticated successfully and breadlock sent `unlock` to the compositor. Not emitted on a compositor-ended lock (`finished`), a dispatch-error exit (fail-secure: the session stays locked), or a failed/typo password. |
|
||||
| `bread.lock.lock.done` | `{}` | `bread.command.lock.lock` was honored: the locker was already running, or a locker process was started (same no-args invocation as hypridle's `lock_cmd = breadlock`). This is the command confirmation, not compositor proof — wait on `bread.lock.locked` if you need the session-lock protocol to have completed. |
|
||||
| `bread.lock.lock.failed` | `{ "error": "<message>" }` | `bread.command.lock.lock` was received but the locker could not be started (e.g. this binary is missing from disk). |
|
||||
| `bread.lock.unlock.done` | `{}` | `bread.command.lock.unlock` was honored: no locker was running (already unlocked), or `loginctl unlock-session` was invoked for this session. This is the command confirmation, not compositor proof — wait on `bread.lock.unlocked` if you need PAM + `ext-session-lock-v1` unlock. |
|
||||
| `bread.lock.unlock.failed` | `{ "error": "<message>" }` | `bread.command.lock.unlock` was received but `loginctl unlock-session` could not be run (binary missing, non-zero exit). |
|
||||
|
||||
## Commands honored (`bread.command.lock.*`)
|
||||
|
||||
| Verb | Effect |
|
||||
|------|--------|
|
||||
| `lock` | If a locker is already running, emit `bread.lock.lock.done` and do nothing else. Otherwise start `breadlock` the same way hypridle does (`lock_cmd = breadlock`: this binary, no args) and emit `done` or `failed`. |
|
||||
| `unlock` | If no locker is running, emit `bread.lock.unlock.done` (already unlocked). Otherwise run `loginctl unlock-session` on the caller's session and emit `done` or `failed`. This is session-level (logind), not a passwordless PAM bypass: breadlock does not call compositor `unlock()` for this verb. |
|
||||
|
||||
A Lua workflow that wants the session locked should `bread.wait` /
|
||||
`bread.wait_any` on `bread.lock.lock.done` (or `.failed`) with a timeout.
|
||||
To know the compositor actually locked, wait on `bread.lock.locked`.
|
||||
The same pattern applies to unlock: wait on `bread.lock.unlock.done` /
|
||||
`.failed` for the command, and on `bread.lock.unlocked` for PAM +
|
||||
compositor unlock.
|
||||
|
||||
### Who is listening
|
||||
|
||||
`bread.command.lock.lock` is a silent no-op if nobody is subscribed
|
||||
(bread's usual "no listener, no-op" rule). Two subscribers exist:
|
||||
`bread.command.lock.lock` / `bread.command.lock.unlock` are a silent
|
||||
no-op if nobody is subscribed (bread's usual "no listener, no-op"
|
||||
rule). Two subscribers exist:
|
||||
|
||||
1. **`breadlock listen`** — run this for the unlocked path (Hyprland
|
||||
`exec-once = breadlock listen`, a bread module, or equivalent).
|
||||
Without it, a command sent while the session is unlocked has no
|
||||
process to receive it.
|
||||
process to receive it. Unlock while already unlocked is an
|
||||
idempotent `done`.
|
||||
2. **The locker process** — always subscribes once the lock screen is
|
||||
up, so a command received during an active lock is an idempotent
|
||||
`done`.
|
||||
up, so `lock` during an active lock is an idempotent `done`, and
|
||||
`unlock` runs `loginctl unlock-session` rather than compositor
|
||||
`unlock()`.
|
||||
|
||||
### Session-level equivalent
|
||||
|
||||
|
|
@ -63,13 +72,18 @@ bread command bus. It is the session-level equivalent of
|
|||
same `ext-session-lock-v1` request. Prefer `loginctl lock-session`
|
||||
from a keybind; prefer the bus command from a Lua workflow.
|
||||
|
||||
### Not implemented: `unlock` / `pin` / `blur`
|
||||
`loginctl unlock-session` is the matching session-level unlock. The
|
||||
bus verb invokes that same command. Compositor unlock after a typed
|
||||
password is still PAM on this process (`bread.lock.unlocked`); a
|
||||
dispatch-error or crash path still does **not** call compositor
|
||||
`unlock()` (fail-secure).
|
||||
|
||||
Unlock is PAM on this process only — there is no `bread.command.lock.unlock`
|
||||
and none is stubbed. `background.blur` in `breadlock.toml` remains a
|
||||
documented locker no-op (accepted, warned, surface drawn unblurred).
|
||||
That is appearance config, not a bus command — do not invent
|
||||
`bread.command.lock.blur` for it.
|
||||
### Not implemented: `pin` / `blur`
|
||||
|
||||
`background.blur` in `breadlock.toml` remains a documented locker
|
||||
no-op (accepted, warned, surface drawn unblurred). That is appearance
|
||||
config, not a bus command — do not invent `bread.command.lock.blur`
|
||||
for it.
|
||||
|
||||
## Fail-safe behavior
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue