polkit
The pending polkit authentication request, its progress and the last failure.
The password never reaches Lua: a secure field with
secure_submit = { capability = "polkit", action = "authenticate" } sends it straight to the
Supervisor. The first submit starts polkit’s helper; after that prompt and messages relay its
PAM conversation as on lock, and the same field answers each prompt.
column {
visible = mantle.polkit:map(function(polkit)
return polkit.active
end, false),
spacing = 8,
children = {
text {
content = mantle.polkit:map(function(polkit)
return polkit.message or ""
end, ""),
},
text {
content = mantle.polkit:map(function(polkit)
return polkit.prompt and polkit.prompt.text or "Password"
end, ""),
},
textfield {
width = 280,
height = 24,
masked = mantle.polkit:map(function(polkit)
return not (polkit.prompt and polkit.prompt.echo)
end, true),
secure_submit = { capability = "polkit", action = "authenticate" },
},
text {
foreground = "#F38BA8",
content = mantle.polkit:map(function(polkit)
local last = polkit.messages[#polkit.messages]
return last and last.text or polkit.error or ""
end, ""),
},
list {
direction = "horizontal",
spacing = 8,
items = mantle.polkit:map(function(polkit) return polkit.identities end, {}),
key = function(identity) return tostring(identity.uid) end,
each = function(identity)
return rect {
on_click = function() mantle.polkit:select_identity(identity.uid) end,
children = { text { content = identity.name } },
}
end,
},
rect {
on_click = function() mantle.polkit:cancel() end,
children = { text { content = "Cancel" } },
},
},
}
State
mantle.polkit:get() returns PolkitState, nil before the first push. A field marked ? may be absent.
mantle.polkit’s payload. Every other field is empty while active is false.
| Field | Type | Description |
|---|---|---|
action_id | string | Action being authorized, e.g. org.freedesktop.systemd1.manage-units. |
active | boolean | polkitd is waiting for the user to authenticate. |
authenticating | boolean | An answer is with PAM, or typed before its prompt and held for it. A second submit is refused while true. |
error | string | Drawable reason for the last failure, e.g. "authentication failed". The prompt stays open to retry. |
icon_name | string | Themed icon name, or empty when the caller set none. |
identities | PolkitIdentity[] | The accounts polkit accepts, as it offered them; groups arrive already expanded. |
identity | integer | The uid the next helper authenticates: this session’s user if offered, else the first. |
message | string | The action’s prompt, e.g. "Authentication is required to ...", in en_US: the locale the agent registers with. |
messages | PamNotice[] | The helper’s info and error lines, as on mantle.lock. |
prompt? | PamPrompt | The helper’s pending question, as on mantle.lock. nil until the first submit starts it. |
PamNotice
One line a PAM module showed without asking anything, e.g. a fingerprint hint or a lockout.
| Field | Type | Description |
|---|---|---|
kind | PamNoticeKind | "info" or "error". |
text | string | What the module said, as it said it. |
PamNoticeKind
What a PamNotice reports.
One of "info", "error".
PamPrompt
A question a PAM module asked.
| Field | Type | Description |
|---|---|---|
echo | boolean | The answer is meant to be seen: set the secure field’s masked to not echo. |
id | integer | Unique for this session, so two identical prompts in a row still differ. |
text | string | PAM’s own text, e.g. "Password: " or "Verification code:". |
PolkitIdentity
One account a polkit challenge accepts.
| Field | Type | Description |
|---|---|---|
name | string | Login name, or empty when the uid has no passwd entry. |
uid | integer |
Actions
Call each as mantle.polkit:<action>(arguments...); ? marks an argument you may omit.
| Action | Arguments | Description |
|---|---|---|
cancel | Dismisses the prompt; the requesting program sees the request cancelled. | |
select_identity | uid: integer | Authenticates as uid, one of identities. Clears the prompt and error; the next submit starts PAM for it. After a submit it ends that conversation, which PAM may count as a failure. |
Backend
On first read, registers as the authentication agent for $XDG_SESSION_ID’s session, at
/org/mantle/PolicyKit1/AuthenticationAgent with locale en_US.UTF-8, and again each time polkitd
restarts, cancelling the challenge the old polkitd held. If another agent already answers, it stays
off until polkitd restarts. polkitd accepts an answer only from uid 0, so the
PAM worker hands the password to polkit’s root helper at
/run/polkit/agent-helper.socket. The agent is polkit.rs.
Gotchas
| Trap | Fix |
|---|---|
| A second program’s prompt never shows | One request at a time: a request arriving while another is on screen is cancelled, and its program sees the cancel. Finish or cancel the first |
| Prompts go to another agent | polkit-gnome, hyprpolkitagent or similar registered first. Stop it and restart Mantle |
| The prompt stays open after a wrong password | By design: error says why, and the next submit starts a new helper |
| Another admin should authenticate | List identities and call select_identity(uid) from a click. The default is your own account when polkit offers it. Switching after a submit ends that attempt, which PAM may count |
prompt is nil before anything is typed | polkit’s helper starts on the first submit, because closing a helper that waits on a prompt counts as a failed attempt |
See also: secure fields; FAQ for prompts that never appear.