Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.

FieldTypeDescription
action_idstringAction being authorized, e.g. org.freedesktop.systemd1.manage-units.
activebooleanpolkitd is waiting for the user to authenticate.
authenticatingbooleanAn answer is with PAM, or typed before its prompt and held for it. A second submit is refused while true.
errorstringDrawable reason for the last failure, e.g. "authentication failed". The prompt stays open to retry.
icon_namestringThemed icon name, or empty when the caller set none.
identitiesPolkitIdentity[]The accounts polkit accepts, as it offered them; groups arrive already expanded.
identityintegerThe uid the next helper authenticates: this session’s user if offered, else the first.
messagestringThe action’s prompt, e.g. "Authentication is required to ...", in en_US: the locale the agent registers with.
messagesPamNotice[]The helper’s info and error lines, as on mantle.lock.
prompt?PamPromptThe 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.

FieldTypeDescription
kindPamNoticeKind"info" or "error".
textstringWhat the module said, as it said it.

PamNoticeKind

What a PamNotice reports.

One of "info", "error".

PamPrompt

A question a PAM module asked.

FieldTypeDescription
echobooleanThe answer is meant to be seen: set the secure field’s masked to not echo.
idintegerUnique for this session, so two identical prompts in a row still differ.
textstringPAM’s own text, e.g. "Password: " or "Verification code:".

PolkitIdentity

One account a polkit challenge accepts.

FieldTypeDescription
namestringLogin name, or empty when the uid has no passwd entry.
uidinteger

Actions

Call each as mantle.polkit:<action>(arguments...); ? marks an argument you may omit.

ActionArgumentsDescription
cancelDismisses the prompt; the requesting program sees the request cancelled.
select_identityuid: integerAuthenticates 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

TrapFix
A second program’s prompt never showsOne 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 agentpolkit-gnome, hyprpolkitagent or similar registered first. Stop it and restart Mantle
The prompt stays open after a wrong passwordBy design: error says why, and the next submit starts a new helper
Another admin should authenticateList 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 typedpolkit’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.

Source: supervisor/src/capabilities/polkit.rs