workspace: add bread-app crate and first-cut bread-polkit agent
Some checks failed
dev bread-theme / build (push) Successful in 17s
dev bakery / build (push) Successful in 43s
beta (rc) bakery / build (push) Has been skipped
beta (rc) bread-theme / build (push) Has been skipped
Build and publish package / package (push) Successful in 1m46s
release bakery / build (push) Failing after 52s
release bread-theme / build (push) Failing after 14s

bread-app is the GTK bootstrap new tools should use instead of another
copied main.rs: com.breadway.* app id, singleton lock, optional
gtk_popup re-export, optional bread.command.<app>.** listen loop.
Tests cover app-id helpers and command-verb parse. Existing apps are
not migrated.

bread-polkit is an own PolicyKit1 session authentication agent with a
bread-theme GTK4 password prompt (not a polkit-gnome wrapper).
Autostart via contrib/bread-polkit.desktop or exec-once. Not a bakery
product; not added to the BOS ISO lockfile.
This commit is contained in:
Breadway 2026-08-16 00:34:12 +08:00
parent c296d26408
commit 11c0e844e5
19 changed files with 2049 additions and 32 deletions

94
bread-polkit/src/main.rs Normal file
View file

@ -0,0 +1,94 @@
//! bread-polkit — themed PolicyKit authentication agent.
//!
//! Registers on the `org.freedesktop.PolicyKit1.AuthenticationAgent`
//! interface and shows a bread-theme GTK4 password prompt. This is an
//! agent, not a wrapper that execs `polkit-gnome`.
//!
//! Autostart: copy `contrib/bread-polkit.desktop` to
//! `~/.config/autostart/`, or add `exec-once = bread-polkit` to Hyprland.
mod agent;
mod auth;
mod ui;
use bread_app::singleton::Acquire;
use gtk4::prelude::*;
const APP_NAME: &str = "bread-polkit";
fn main() {
let arg = std::env::args().nth(1);
match arg.as_deref() {
Some("-h") | Some("--help") => {
print_help();
return;
}
Some("-V") | Some("--version") => {
println!("bread-polkit {}", env!("CARGO_PKG_VERSION"));
return;
}
Some(other) => {
eprintln!("bread-polkit: unknown argument '{other}'");
print_help();
std::process::exit(2);
}
None => {}
}
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")),
)
.with_target(false)
.init();
let _guard = match bread_app::try_acquire(APP_NAME) {
Ok(Acquire::Acquired(g)) => Some(g),
Ok(Acquire::HeldByOther(pid)) => {
eprintln!("bread-polkit: already running (pid {pid:?})");
std::process::exit(0);
}
Err(e) => {
eprintln!("bread-polkit: singleton lock unavailable ({e}); continuing");
None
}
};
let app_id = bread_app::application_id(APP_NAME).expect("static app name");
let app = gtk4::Application::builder().application_id(&app_id).build();
app.connect_activate(|app| {
bread_theme::gtk::apply_shared();
bread_theme::gtk::apply_app_css(ui::app_css);
// No window until polkit asks; hold so GApplication stays alive.
std::mem::forget(app.hold());
if let Err(e) = agent::spawn() {
eprintln!("bread-polkit: {e:#}");
app.quit();
}
});
app.run();
}
fn print_help() {
print!(
"\
bread-polkit themed PolicyKit authentication agent
Usage:
bread-polkit
bread-polkit --help
bread-polkit --version
Autostart (pick one):
cp contrib/bread-polkit.desktop ~/.config/autostart/
exec-once = bread-polkit # Hyprland
The agent talks to the polkit1 AuthenticationAgent API and prompts for
a password. It does not exec polkit-gnome. Not a bakery product; not
on the BOS ISO lockfile.
"
);
}