From f50c7b2e82c1823fb445b94aad9ce5adbab62ff0 Mon Sep 17 00:00:00 2001 From: michael Date: Sun, 26 Apr 2026 16:53:11 -0700 Subject: [PATCH] Rename project: ubuntu-fido -> authforge Renames the package and all artifacts to authforge to drop the distro-specific prefix, since the roadmap targets Ubuntu + Debian + KDE + eventually Fedora (option C in the design). - deb packages: authforge, authforge-{daemon,pam,cli,gui,gnome-integration} - binaries: authforged, authforgectl, authforge (GUI) - D-Bus name: io.dangerousthings.AuthForge - PAM module: pam_authforge_pending.so - Paths: /etc/authforge/, /var/lib/authforge/, /usr/share/pam-configs/authforge - PPA: ppa:dangerousthings/authforge Filesystem path /home/work/VSCodeProjects/ubuntu_fido/ left as-is for historical reference; can rename later via git mv at the dir level. Verified: cargo build/test/clippy/fmt clean, pam builds, gui builds, all 5 debs produced. --- .github/workflows/ci.yml | 4 +- .gitignore | 4 +- Cargo.lock | 2148 +++++++++++++++++ Cargo.toml | 4 +- README.md | 12 +- cli/Cargo.toml | 6 +- cli/src/main.rs | 6 +- common/Cargo.toml | 2 +- daemon/Cargo.toml | 6 +- daemon/src/main.rs | 2 +- debian/changelog | 4 +- debian/control | 46 +- debian/copyright | 4 +- debian/rules | 22 +- docs/BUILDING.md | 24 +- ...sign.md => 2026-04-26-authforge-design.md} | 76 +- ...=> 2026-04-26-authforge-implementation.md} | 328 +-- gui/Cargo.toml | 6 +- ...p => io.dangerousthings.AuthForge.desktop} | 4 +- ...o.svg => io.dangerousthings.AuthForge.svg} | 0 gui/src/main.rs | 2 +- pam/Makefile | 8 +- ...fido_pending.c => pam_authforge_pending.c} | 2 +- 23 files changed, 2431 insertions(+), 289 deletions(-) create mode 100644 Cargo.lock rename docs/plans/{2026-04-26-ubuntu-fido-design.md => 2026-04-26-authforge-design.md} (76%) rename docs/plans/{2026-04-26-ubuntu-fido-implementation.md => 2026-04-26-authforge-implementation.md} (76%) rename gui/data/{io.dangerousthings.UbuntuFido.desktop => io.dangerousthings.AuthForge.desktop} (82%) rename gui/data/{io.dangerousthings.UbuntuFido.svg => io.dangerousthings.AuthForge.svg} (100%) rename pam/{pam_ubuntu_fido_pending.c => pam_authforge_pending.c} (88%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f80a215..93d6af5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,8 +41,8 @@ jobs: cargo rustc - run: debuild -us -uc -b - name: Run lintian (warnings allowed in Phase 0) - run: lintian --info --display-info ../ubuntu-fido*.changes || true + run: lintian --info --display-info ../authforge*.changes || true - uses: actions/upload-artifact@v4 with: name: deb-packages - path: ../ubuntu-fido*.deb + path: ../authforge*.deb diff --git a/.gitignore b/.gitignore index 19bb20f..a5b10f9 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,9 @@ debian/.debhelper/ debian/files debian/*.substvars debian/*.debhelper.log -debian/ubuntu-fido*/ +debian/authforge*/ +debian/debhelper-build-stamp +pam/*.so build/ .vscode/ *.swp diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..6311db4 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2148 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-signal" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "authforge-cli" +version = "0.1.0" +dependencies = [ + "anyhow", + "authforge-common", + "clap", + "tokio", + "zbus", +] + +[[package]] +name = "authforge-common" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", + "thiserror", + "toml", +] + +[[package]] +name = "authforge-daemon" +version = "0.1.0" +dependencies = [ + "anyhow", + "authforge-common", + "tokio", + "tracing", + "tracing-subscriber", + "zbus", +] + +[[package]] +name = "authforge-gui" +version = "0.1.0" +dependencies = [ + "anyhow", + "authforge-common", + "gtk4", + "libadwaita", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "cairo-rs" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ac2a4d0e69036cf0062976f6efcba1aaee3e448594e6514bb2ddf87acce562" +dependencies = [ + "bitflags", + "cairo-sys-rs", + "glib", + "libc", + "thiserror", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3bb3119664efbd78b5e6c93957447944f16bdbced84c17a9f41c7829b81e64" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "clap" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624eaba126021103c7339b2e179ae4ee8cdab842daab419040710f38ed9f8699" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4efa05a4f83c8cc50eb4d883787b919b85e5f1d8dd10b5a1df53bf5689782379" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk4" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db265c9dd42d6a371e09e52deab3a84808427198b86ac792d75fd35c07990a07" +dependencies = [ + "cairo-rs", + "gdk-pixbuf", + "gdk4-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk4-sys" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9418fb4e8a67074919fe7604429c45aa74eb9df82e7ca529767c6d4e9dc66dd" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + +[[package]] +name = "gio" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c49f117d373ffcc98a35d114db5478bc223341cff53e39a5d6feced9e2ddffe" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "pin-project-lite", + "smallvec", + "thiserror", +] + +[[package]] +name = "gio-sys" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cd743ba4714d671ad6b6234e8ab2a13b42304d0e13ab7eba1dcdd78a7d6d4ef" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "windows-sys 0.52.0", +] + +[[package]] +name = "glib" +version = "0.19.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39650279f135469465018daae0ba53357942a5212137515777d5fdca74984a44" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "smallvec", + "thiserror", +] + +[[package]] +name = "glib-macros" +version = "0.19.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4429b0277a14ae9751350ad9b658b1be0abb5b54faa5bcdf6e74a3372582fad7" +dependencies = [ + "heck", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glib-sys" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2dc18d3a82b0006d470b13304fbbb3e0a9bd4884cf985a60a7ed733ac2c4a5" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "gobject-sys" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e697e252d6e0416fd1d9e169bda51c0f1c926026c39ca21fbe8b1bb5c3b8b9e" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "graphene-rs" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fb86031d24d9ec0a2a15978fc7a65d545a2549642cf1eb7c3dda358da42bcf" +dependencies = [ + "glib", + "graphene-sys", + "libc", +] + +[[package]] +name = "graphene-sys" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f530e0944bccba4b55065e9c69f4975ad691609191ebac16e13ab8e1f27af05" +dependencies = [ + "glib-sys", + "libc", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gsk4" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7563884bf6939f4468e5d94654945bdd9afcaf8c3ba4c5dd17b5342b747221be" +dependencies = [ + "cairo-rs", + "gdk4", + "glib", + "graphene-rs", + "gsk4-sys", + "libc", + "pango", +] + +[[package]] +name = "gsk4-sys" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23024bf2636c38bbd1f822f58acc9d1c25b28da896ff0f291a1a232d4272b3dc" +dependencies = [ + "cairo-sys-rs", + "gdk4-sys", + "glib-sys", + "gobject-sys", + "graphene-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk4" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b04e11319b08af11358ab543105a9e49b0c491faca35e2b8e7e36bfba8b671ab" +dependencies = [ + "cairo-rs", + "field-offset", + "futures-channel", + "gdk-pixbuf", + "gdk4", + "gio", + "glib", + "graphene-rs", + "gsk4", + "gtk4-macros", + "gtk4-sys", + "libc", + "pango", +] + +[[package]] +name = "gtk4-macros" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec655a7ef88d8ce9592899deb8b2d0fa50bab1e6dd69182deb764e643c522408" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "gtk4-sys" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c8aa86b7f85ea71d66ea88c1d4bae1cfacf51ca4856274565133838d77e57b5" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk4-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "graphene-sys", + "gsk4-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.0", + "serde", + "serde_core", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libadwaita" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91b4990248b9e1ec5e72094a2ccaea70ec3809f88f6fd52192f2af306b87c5d9" +dependencies = [ + "gdk-pixbuf", + "gdk4", + "gio", + "glib", + "gtk4", + "libadwaita-sys", + "libc", + "pango", +] + +[[package]] +name = "libadwaita-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23a748e4e92be1265cd9e93d569c0b5dfc7814107985aa6743d670ab281ea1a8" +dependencies = [ + "gdk4-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk4-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "pango" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f0d328648058085cfd6897c9ae4272884098a926f3a833cd50c8c73e6eccecd" +dependencies = [ + "gio", + "glib", + "libc", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff03da4fa086c0b244d4a4587d3e20622a3ecdb21daea9edf66597224c634ba0" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.11+spec-1.1.0", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tokio" +version = "1.52.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" +dependencies = [ + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime 0.6.11", + "toml_write", + "winnow 0.7.15", +] + +[[package]] +name = "toml_edit" +version = "0.25.11+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +dependencies = [ + "indexmap", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.2", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.2", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "typenum" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys 0.61.2", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version-compare" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "xdg-home" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "zbus" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" +dependencies = [ + "async-broadcast", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix", + "ordered-stream", + "rand", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tracing", + "uds_windows", + "windows-sys 0.52.0", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zvariant" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" +dependencies = [ + "endi", + "enumflags2", + "serde", + "static_assertions", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index f6f7b40..fe160d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ resolver = "2" members = ["common", "daemon", "cli", "gui"] # GUI excluded from default builds because it requires libgtk-4-dev + libadwaita-1-dev -# at link time. Build it explicitly with `cargo build -p ubuntu-fido-gui`. +# at link time. Build it explicitly with `cargo build -p authforge-gui`. default-members = ["common", "daemon", "cli"] [workspace.package] @@ -10,7 +10,7 @@ version = "0.1.0" edition = "2021" license = "Apache-2.0" authors = ["Dangerous Things "] -repository = "https://github.com/dangerousthings/ubuntu-fido" +repository = "https://github.com/dangerousthings/authforge" rust-version = "1.78" [workspace.dependencies] diff --git a/README.md b/README.md index c6a9fb0..a25d2eb 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,18 @@ -# ubuntu-fido +# authforge -Turnkey U2F / FIDO2 passkey / TOTP MFA for Ubuntu desktops. +Turnkey U2F / FIDO2 passkey / TOTP MFA for Linux desktops. v1 ships on Ubuntu LTS + GNOME; Debian and KDE Plasma are on the roadmap. ## Install (end users) - sudo add-apt-repository ppa:dangerousthings/ubuntu-fido - sudo apt install ubuntu-fido + sudo add-apt-repository ppa:dangerousthings/authforge + sudo apt install authforge ## Build from source -See `docs/BUILDING.md`. +See [docs/BUILDING.md](docs/BUILDING.md). ## Status -Pre-alpha. See `docs/plans/` for design and roadmap. +Pre-alpha. See [docs/plans/](docs/plans/) for design and roadmap. Copyright 2026 Dangerous Things, LLC. Licensed under the Apache License, Version 2.0. diff --git a/cli/Cargo.toml b/cli/Cargo.toml index e6aef0c..a702b38 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "ubuntu-fidoctl" +name = "authforge-cli" version.workspace = true edition.workspace = true license.workspace = true [[bin]] -name = "ubuntu-fidoctl" +name = "authforgectl" path = "src/main.rs" [dependencies] -ubuntu-fido-common = { path = "../common" } +authforge-common = { path = "../common" } clap = { workspace = true } anyhow = { workspace = true } zbus = { workspace = true } diff --git a/cli/src/main.rs b/cli/src/main.rs index e01c0a7..52837d2 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -3,9 +3,9 @@ use clap::Parser; #[derive(Parser)] #[command( - name = "ubuntu-fidoctl", + name = "authforgectl", version, - about = "Manage ubuntu-fido configuration" + about = "Manage authforge configuration" )] struct Cli { #[command(subcommand)] @@ -21,7 +21,7 @@ enum Cmd { async fn main() -> Result<()> { let args = Cli::parse(); match args.cmd { - Cmd::Status => println!("ubuntu-fidoctl: not yet implemented"), + Cmd::Status => println!("authforgectl: not yet implemented"), } Ok(()) } diff --git a/common/Cargo.toml b/common/Cargo.toml index 9b448a6..8e4c43c 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "ubuntu-fido-common" +name = "authforge-common" version.workspace = true edition.workspace = true license.workspace = true diff --git a/daemon/Cargo.toml b/daemon/Cargo.toml index d36b65b..adaaff3 100644 --- a/daemon/Cargo.toml +++ b/daemon/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "ubuntu-fidod" +name = "authforge-daemon" version.workspace = true edition.workspace = true license.workspace = true [[bin]] -name = "ubuntu-fidod" +name = "authforged" path = "src/main.rs" [dependencies] -ubuntu-fido-common = { path = "../common" } +authforge-common = { path = "../common" } zbus = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } diff --git a/daemon/src/main.rs b/daemon/src/main.rs index f4bd4c4..014748b 100644 --- a/daemon/src/main.rs +++ b/daemon/src/main.rs @@ -6,7 +6,7 @@ async fn main() -> Result<()> { tracing_subscriber::fmt() .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) .init(); - info!("ubuntu-fidod {} starting", env!("CARGO_PKG_VERSION")); + info!("authforged {} starting", env!("CARGO_PKG_VERSION")); // D-Bus service registration in Phase 1. Ok(()) } diff --git a/debian/changelog b/debian/changelog index f8ecdd8..9b2e3b5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -ubuntu-fido (0.1.0-1) UNRELEASED; urgency=low +authforge (0.1.0-1) UNRELEASED; urgency=low - * Initial packaging skeleton. + * Initial packaging skeleton (renamed from ubuntu-fido). -- Dangerous Things Sun, 26 Apr 2026 12:00:00 +0000 diff --git a/debian/control b/debian/control index 2afb247..eab2089 100644 --- a/debian/control +++ b/debian/control @@ -1,4 +1,4 @@ -Source: ubuntu-fido +Source: authforge Section: admin Priority: optional Maintainer: Dangerous Things @@ -12,44 +12,44 @@ Build-Depends: libfido2-dev, pkg-config Standards-Version: 4.6.2 -Homepage: https://github.com/dangerousthings/ubuntu-fido -Vcs-Browser: https://github.com/dangerousthings/ubuntu-fido -Vcs-Git: https://github.com/dangerousthings/ubuntu-fido.git +Homepage: https://github.com/dangerousthings/authforge +Vcs-Browser: https://github.com/dangerousthings/authforge +Vcs-Git: https://github.com/dangerousthings/authforge.git -Package: ubuntu-fido +Package: authforge Architecture: any -Depends: ubuntu-fido-daemon (= ${binary:Version}), - ubuntu-fido-pam (= ${binary:Version}), - ubuntu-fido-cli (= ${binary:Version}), +Depends: authforge-daemon (= ${binary:Version}), + authforge-pam (= ${binary:Version}), + authforge-cli (= ${binary:Version}), ${misc:Depends} -Recommends: ubuntu-fido-gui (= ${binary:Version}) -Suggests: ubuntu-fido-gnome-integration -Description: Turnkey FIDO2/U2F/TOTP MFA for Ubuntu (metapackage) - Installs the full ubuntu-fido stack: daemon, PAM module, CLI, and +Recommends: authforge-gui (= ${binary:Version}) +Suggests: authforge-gnome-integration +Description: Turnkey FIDO2/U2F/TOTP MFA for Linux desktops (metapackage) + Installs the full authforge stack: daemon, PAM module, CLI, and (if recommended) GUI. -Package: ubuntu-fido-daemon +Package: authforge-daemon Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, libpam-u2f, libfido2-1 -Description: System daemon for ubuntu-fido MFA management +Description: System daemon for authforge MFA management Provides the privileged D-Bus service that orchestrates enrollment, policy edits, and lockout-prevention checks. -Package: ubuntu-fido-pam +Package: authforge-pam Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, libpam-runtime -Description: PAM module backstopping ubuntu-fido first-login enrollment - Refuses authentication when /var/lib/ubuntu-fido/pending/ exists +Description: PAM module backstopping authforge first-login enrollment + Refuses authentication when /var/lib/authforge/pending/ exists and the user has not completed first-login MFA setup. -Package: ubuntu-fido-cli +Package: authforge-cli Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, ubuntu-fido-daemon -Description: CLI for ubuntu-fido (admin and fleet) +Depends: ${shlibs:Depends}, ${misc:Depends}, authforge-daemon +Description: CLI for authforge (admin and fleet) Configure policy, enroll on behalf of users, generate recovery codes. -Package: ubuntu-fido-gui +Package: authforge-gui Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, ubuntu-fido-daemon -Description: GTK4/libadwaita UI for ubuntu-fido +Depends: ${shlibs:Depends}, ${misc:Depends}, authforge-daemon +Description: GTK4/libadwaita UI for authforge End-user-facing settings panel for enrollment and policy. diff --git a/debian/copyright b/debian/copyright index 30362e6..abd206f 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,7 +1,7 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: ubuntu-fido +Upstream-Name: authforge Upstream-Contact: Dangerous Things -Source: https://github.com/dangerousthings/ubuntu-fido +Source: https://github.com/dangerousthings/authforge Files: * Copyright: 2026 Dangerous Things, LLC diff --git a/debian/rules b/debian/rules index 83fd121..cb5b695 100755 --- a/debian/rules +++ b/debian/rules @@ -11,20 +11,20 @@ override_dh_auto_build: override_dh_auto_install: # Daemon - install -D -m 0755 target/release/ubuntu-fidod \ - debian/ubuntu-fido-daemon/usr/sbin/ubuntu-fidod + install -D -m 0755 target/release/authforged \ + debian/authforge-daemon/usr/sbin/authforged # CLI - install -D -m 0755 target/release/ubuntu-fidoctl \ - debian/ubuntu-fido-cli/usr/bin/ubuntu-fidoctl + install -D -m 0755 target/release/authforgectl \ + debian/authforge-cli/usr/bin/authforgectl # GUI - install -D -m 0755 target/release/ubuntu-fido \ - debian/ubuntu-fido-gui/usr/bin/ubuntu-fido - install -D -m 0644 gui/data/io.dangerousthings.UbuntuFido.desktop \ - debian/ubuntu-fido-gui/usr/share/applications/io.dangerousthings.UbuntuFido.desktop - install -D -m 0644 gui/data/io.dangerousthings.UbuntuFido.svg \ - debian/ubuntu-fido-gui/usr/share/icons/hicolor/scalable/apps/io.dangerousthings.UbuntuFido.svg + install -D -m 0755 target/release/authforge \ + debian/authforge-gui/usr/bin/authforge + install -D -m 0644 gui/data/io.dangerousthings.AuthForge.desktop \ + debian/authforge-gui/usr/share/applications/io.dangerousthings.AuthForge.desktop + install -D -m 0644 gui/data/io.dangerousthings.AuthForge.svg \ + debian/authforge-gui/usr/share/icons/hicolor/scalable/apps/io.dangerousthings.AuthForge.svg # PAM - $(MAKE) -C pam install DESTDIR=$(CURDIR)/debian/ubuntu-fido-pam + $(MAKE) -C pam install DESTDIR=$(CURDIR)/debian/authforge-pam override_dh_auto_test: cargo test --workspace --release diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 09633a6..3c8dda5 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -1,4 +1,4 @@ -# Building ubuntu-fido from source +# Building authforge from source ## System dependencies @@ -19,32 +19,24 @@ Rust toolchain: stable (1.78 minimum). Install via [rustup](https://rustup.rs). cargo build --release # GUI (requires libgtk-4-dev + libadwaita-1-dev) -cargo build -p ubuntu-fido-gui --release +cargo build -p authforge-gui --release # PAM module (requires libpam0g-dev) make -C pam -# Full deb build (requires all of the above) -debuild -us -uc -b -# Output: ../ubuntu-fido*.deb +# Full deb build (requires all of the above + debhelper) +dpkg-buildpackage -us -uc -b +# Output: ../authforge*.deb ``` ## Tests ```bash -cargo test --workspace --exclude ubuntu-fido-gui +cargo test --workspace --exclude authforge-gui ``` -The GUI crate has no automated tests in v1; manual smoke tests are documented in [docs/plans/2026-04-26-ubuntu-fido-design.md](plans/2026-04-26-ubuntu-fido-design.md#testing-strategy). +The GUI crate has no automated tests in v1; manual smoke tests are documented in [docs/plans/2026-04-26-authforge-design.md](plans/2026-04-26-authforge-design.md#testing-strategy). ## Phase 0 status -Repository scaffolding is complete (tag `v0.1.0-scaffolding`). Subsequent phases per [docs/plans/2026-04-26-ubuntu-fido-implementation.md](plans/2026-04-26-ubuntu-fido-implementation.md). - -Build verifications NOT yet run on this machine (require `sudo apt install libpam0g-dev libgtk-4-dev libadwaita-1-dev libfido2-dev`): - -- `make -C pam` — PAM module compile -- `cargo build -p ubuntu-fido-gui --release` — GUI link -- `debuild -us -uc -b` — full deb build - -Once those packages are installed, run the three commands above to complete the Phase 0 acceptance gate. +Repository scaffolding is complete (tag `v0.1.0-scaffolding`, then renamed `ubuntu-fido` → `authforge`). Subsequent phases per [docs/plans/2026-04-26-authforge-implementation.md](plans/2026-04-26-authforge-implementation.md). diff --git a/docs/plans/2026-04-26-ubuntu-fido-design.md b/docs/plans/2026-04-26-authforge-design.md similarity index 76% rename from docs/plans/2026-04-26-ubuntu-fido-design.md rename to docs/plans/2026-04-26-authforge-design.md index 329ad7e..ef034f3 100644 --- a/docs/plans/2026-04-26-ubuntu-fido-design.md +++ b/docs/plans/2026-04-26-authforge-design.md @@ -1,4 +1,4 @@ -# ubuntu-fido — Design Document +# authforge — Design Document **Date:** 2026-04-26 **Status:** Draft (brainstorm complete, validated through Section 2 with stakeholder) @@ -22,21 +22,21 @@ This project ships a single deb package that gives end users and admins a turnke | 2 | **v1 target: Ubuntu LTS + GNOME.** Ultimate target: Ubuntu + Debian × GNOME + KDE Plasma. | ~25–30% of Linux desktop on day one, ~50–60% at target state. v1 ships in months not years. | | 3 | **GUI: standalone GTK4/libadwaita app + optional gnome-control-center Users-panel shortcut deb.** | gnome-control-center has no stable plugin API. Standalone app is forward-compatible; shortcut deb adds discoverability without coupling to GNOME release cycle. | | 4 | **Authenticators: U2F + FIDO2 passkey + TOTP.** TOTP behind a build-time feature flag. | Full scope as written; flag lets us ship a beta without TOTP if the QR/recovery-code UX slips schedule. | -| 5 | **Policy contexts: 3 in main GUI (gdm-password, sudo, sshd) with Disabled / Optional / Required modes.** Full list (polkit, su, login, plus auto-detected stacks) under pkexec admin gate or via `/etc/ubuntu-fido/policy.d/*.conf`. | 95% case stays simple; advanced/fleet path unrestricted. Mandatory pre-commit lockout simulation. | -| 6 | **First-login enrollment: `chage -d 0` + autostart enrollment app + small `pam_ubuntu_fido_pending.so` blocking module.** | Belt-and-suspenders: leverages existing forced-password-change, adds enrollment via autostart, PAM module ensures user can't bypass by killing the modal. | +| 5 | **Policy contexts: 3 in main GUI (gdm-password, sudo, sshd) with Disabled / Optional / Required modes.** Full list (polkit, su, login, plus auto-detected stacks) under pkexec admin gate or via `/etc/authforge/policy.d/*.conf`. | 95% case stays simple; advanced/fleet path unrestricted. Mandatory pre-commit lockout simulation. | +| 6 | **First-login enrollment: `chage -d 0` + autostart enrollment app + small `pam_authforge_pending.so` blocking module.** | Belt-and-suspenders: leverages existing forced-password-change, adds enrollment via autostart, PAM module ensures user can't bypass by killing the modal. | ## Architecture ``` ┌─────────────────────────┐ ┌──────────────────────────┐ ┌──────────────┐ -│ ubuntu-fido GTK app │ │ ubuntu-fidoctl (CLI) │ │ Future KDE │ +│ authforge GTK app │ │ authforgectl (CLI) │ │ Future KDE │ │ (libadwaita panel) │ │ (admin/fleet scripting) │ │ KCM module │ └─────────────┬───────────┘ └────────────┬─────────────┘ └──────┬───────┘ - │ D-Bus (org.dt.UbuntuFido) │ │ + │ D-Bus (io.dangerousthings.AuthForge) │ │ └─────────────┬─────────────┴────────────────────────┘ ▼ ┌────────────────────────────────────┐ - │ ubuntu-fidod (system daemon) │ ← polkit-mediated + │ authforged (system daemon) │ ← polkit-mediated │ - enrollment orchestration │ │ - policy read/write + lockout │ │ safety simulation │ @@ -47,7 +47,7 @@ This project ships a single deb package that gives end users and admins a turnke ▼ ┌─────────────────┬───────┴────────┬──────────────────────┐ ▼ ▼ ▼ ▼ -/etc/pam.d/* /etc/ubuntu-fido/ ~/.config/Yubico/ /var/lib/ubuntu-fido/ +/etc/pam.d/* /etc/authforge/ ~/.config/Yubico/ /var/lib/authforge/ (stack edits policy.d/*.conf u2f_keys (per-user) pending/ via pam-auth- (admin/fleet /etc/u2f_mappings (first-login flag) update) drop-ins) (central override) @@ -55,7 +55,7 @@ update) drop-ins) (central override) ### Trust boundary -The daemon owns all writes to `/etc/pam.d/`, `/etc/ubuntu-fido/`, and `/var/lib/ubuntu-fido/`. GUIs never write these directly. polkit policies decide who can call which method: +The daemon owns all writes to `/etc/pam.d/`, `/etc/authforge/`, and `/var/lib/authforge/`. GUIs never write these directly. polkit policies decide who can call which method: | D-Bus method | Default polkit action | |---|---| @@ -74,18 +74,18 @@ The daemon owns all writes to `/etc/pam.d/`, `/etc/ubuntu-fido/`, and `/var/lib/ | Package | Contents | Type | |---|---|---| -| `ubuntu-fido` | Empty metapackage. | Depends | -| `ubuntu-fido-daemon` | `/usr/sbin/ubuntu-fidod`, systemd unit (`ubuntu-fido.service`), D-Bus service file, polkit rules under `/usr/share/polkit-1/actions/` | Hard dep of metapackage | -| `ubuntu-fido-pam` | `/usr/lib/$DEB_HOST_MULTIARCH/security/pam_ubuntu_fido_pending.so`, pam-auth-update profile at `/usr/share/pam-configs/ubuntu-fido` | Hard dep | -| `ubuntu-fido-cli` | `/usr/bin/ubuntu-fidoctl` (Rust binary, talks D-Bus) | Hard dep | -| `ubuntu-fido-gui` | `/usr/bin/ubuntu-fido` (GTK4/libadwaita), `.desktop` file with `Categories=Settings;Security;`, app icon | **Recommends** (so headless servers can skip) | -| `ubuntu-fido-gnome-integration` | Tiny shim that adds a "Configure security…" launcher button to gnome-control-center's Users panel via overlay `.desktop` extension | **Suggests** (not auto-installed) | +| `authforge` | Empty metapackage. | Depends | +| `authforge-daemon` | `/usr/sbin/authforged`, systemd unit (`authforge.service`), D-Bus service file, polkit rules under `/usr/share/polkit-1/actions/` | Hard dep of metapackage | +| `authforge-pam` | `/usr/lib/$DEB_HOST_MULTIARCH/security/pam_authforge_pending.so`, pam-auth-update profile at `/usr/share/pam-configs/authforge` | Hard dep | +| `authforge-cli` | `/usr/bin/authforgectl` (Rust binary, talks D-Bus) | Hard dep | +| `authforge-gui` | `/usr/bin/authforge` (GTK4/libadwaita), `.desktop` file with `Categories=Settings;Security;`, app icon | **Recommends** (so headless servers can skip) | +| `authforge-gnome-integration` | Tiny shim that adds a "Configure security…" launcher button to gnome-control-center's Users panel via overlay `.desktop` extension | **Suggests** (not auto-installed) | ### Headline install ```bash -sudo add-apt-repository ppa:dangerousthings/ubuntu-fido -sudo apt install ubuntu-fido +sudo add-apt-repository ppa:dangerousthings/authforge +sudo apt install authforge ``` Two commands. After install: @@ -97,20 +97,20 @@ Two commands. After install: ### Headless / fleet install ```bash -apt install ubuntu-fido-daemon ubuntu-fido-pam ubuntu-fido-cli +apt install authforge-daemon authforge-pam authforge-cli ``` -Skips the GUI metadata. Configure via `/etc/ubuntu-fido/policy.d/90-fleet.conf` or `ubuntu-fidoctl`. We additionally publish: +Skips the GUI metadata. Configure via `/etc/authforge/policy.d/90-fleet.conf` or `authforgectl`. We additionally publish: -- An **Ansible role** `dangerousthings.ubuntu_fido` on Galaxy wrapping `apt + debconf + drop-in config`. +- An **Ansible role** `dangerousthings.authforge` on Galaxy wrapping `apt + debconf + drop-in config`. - A **debconf preseed schema** so `debian-installer`/cloud-init can answer questions at install time. ### Clean uninstall -`apt purge ubuntu-fido*` runs `pam-auth-update --remove` (cleanly retracts our PAM hooks), stops and disables the systemd unit, removes `/etc/ubuntu-fido/` only on `purge` (not `remove`), and leaves `~/.config/Yubico/u2f_keys` files alone (so reinstall is painless). +`apt purge authforge*` runs `pam-auth-update --remove` (cleanly retracts our PAM hooks), stops and disables the systemd unit, removes `/etc/authforge/` only on `purge` (not `remove`), and leaves `~/.config/Yubico/u2f_keys` files alone (so reinstall is painless). ## GUI design -### App: `ubuntu-fido` +### App: `authforge` GTK4 + libadwaita. Single-window adaptive layout, looks like a stock Settings panel. Top-level navigation via libadwaita `AdwViewStack`: @@ -138,23 +138,23 @@ GTK4 + libadwaita. Single-window adaptive layout, looks like a stock Settings pa ### App: gnome-control-center Users panel shortcut -Optional `ubuntu-fido-gnome-integration` package ships an overlay file under `/usr/share/gnome-control-center/users/` (or whatever the current GNOME version uses) that adds an additional row labeled **"Authentication & Security Keys…"** to each user's detail view. Clicking launches `ubuntu-fido --user ` with elevated D-Bus permissions if the launching user is in `sudo`/`admin` group. +Optional `authforge-gnome-integration` package ships an overlay file under `/usr/share/gnome-control-center/users/` (or whatever the current GNOME version uses) that adds an additional row labeled **"Authentication & Security Keys…"** to each user's detail view. Clicking launches `authforge --user ` with elevated D-Bus permissions if the launching user is in `sudo`/`admin` group. The overlay is shipped separately precisely because gnome-control-center has no stable plugin API — this package may need re-tuning every GNOME release. If it ever breaks, the standalone app keeps working; only the discoverability shortcut is lost. ### Add User flow extension -When `ubuntu-fido-gnome-integration` is installed, the **gnome-control-center Users → Add User** dialog gains a new section: **Configure security**, with three radio options: +When `authforge-gnome-integration` is installed, the **gnome-control-center Users → Add User** dialog gains a new section: **Configure security**, with three radio options: 1. **Enroll security credential now** — opens enrollment modal, admin must have the user's key/implant present. Sets a real password (admin-supplied). -2. **Require user to set up at first login** — admin sets a temp password (or accepts a generated one). We run `chage -d 0 ` and create `/var/lib/ubuntu-fido/pending/`. +2. **Require user to set up at first login** — admin sets a temp password (or accepts a generated one). We run `chage -d 0 ` and create `/var/lib/authforge/pending/`. 3. **No MFA** — only available if local policy permits ("Required" stacks would block this option with a tooltip). ## Enrollment flows ### Flow A: User self-enrollment (the common case) -1. User opens `ubuntu-fido` from Activities. +1. User opens `authforge` from Activities. 2. Clicks "+ Add Security Key". 3. Modal: "Plug in your key now or tap your NFC implant to a reader." Daemon polls `libfido2` for new device. 4. Device detected → optional PIN/UV prompt for FIDO2 → daemon emits `pamu2fcfg`-equivalent registration line. @@ -178,49 +178,49 @@ polkit asks admin password. **At account creation (admin side):** 1. Admin picks "Require user to set up at first login", enters/accepts temp password. 2. Daemon runs `chage -d 0 ` (built-in Linux mechanism: forces password change at next login). -3. Daemon writes flag file `/var/lib/ubuntu-fido/pending/` containing JSON: `{"required_methods": ["fido2"], "created": "...", "deadline": null}`. +3. Daemon writes flag file `/var/lib/authforge/pending/` containing JSON: `{"required_methods": ["fido2"], "created": "...", "deadline": null}`. **First login (user side):** 1. User logs into GDM with temp password. 2. PAM `passwd` module forces password change (existing Ubuntu behavior, no work for us). 3. GNOME session starts. -4. Our autostart entry `/etc/xdg/autostart/ubuntu-fido-firstrun.desktop` runs `ubuntu-fido --first-run`. +4. Our autostart entry `/etc/xdg/autostart/authforge-firstrun.desktop` runs `authforge --first-run`. 5. Detects pending flag, takes over the screen with a fullscreen modal: "Welcome. Before you continue, please enroll a security key." 6. User enrolls (Flow A inside the modal). 7. On success, daemon clears pending flag. 8. Modal closes, user lands on a normal desktop. **Backstop (the PAM module):** -- If user kills `ubuntu-fido --first-run` and tries to do anything sudo/login-related, `pam_ubuntu_fido_pending.so` is in their auth stack; it sees the pending flag and denies auth with a friendly message: "Account setup incomplete. Please complete enrollment in the Authentication app." -- A watchdog inside `ubuntu-fido --first-run` calls `gnome-session-quit --logout --no-prompt` after 60 seconds of inactivity in the modal. +- If user kills `authforge --first-run` and tries to do anything sudo/login-related, `pam_authforge_pending.so` is in their auth stack; it sees the pending flag and denies auth with a friendly message: "Account setup incomplete. Please complete enrollment in the Authentication app." +- A watchdog inside `authforge --first-run` calls `gnome-session-quit --logout --no-prompt` after 60 seconds of inactivity in the modal. ### Flow D: Lost key recovery 1. User can't authenticate. 2. User contacts admin. -3. Admin runs `ubuntu-fidoctl recovery generate ` (or clicks button in GUI). Outputs an 8-digit one-time code valid 24 h. -4. User enters code at GDM password prompt — `pam_ubuntu_fido_pending.so` recognizes recovery code prefix, lets them through with a forced re-enrollment flag set. +3. Admin runs `authforgectl recovery generate ` (or clicks button in GUI). Outputs an 8-digit one-time code valid 24 h. +4. User enters code at GDM password prompt — `pam_authforge_pending.so` recognizes recovery code prefix, lets them through with a forced re-enrollment flag set. 5. User logs in, immediately sees first-login-style modal forcing them to enroll a new key before doing anything else. ## PAM and policy details ### pam-auth-update profile -`/usr/share/pam-configs/ubuntu-fido`: +`/usr/share/pam-configs/authforge`: ``` -Name: Dangerous Things ubuntu-fido MFA +Name: Dangerous Things authforge MFA Default: no Priority: 192 Auth-Type: Additional Auth: [success=ok default=1 ignore=ignore] pam_u2f.so cue authfile=/etc/u2f_mappings - [success=ok default=die] pam_ubuntu_fido_pending.so + [success=ok default=die] pam_authforge_pending.so ``` Default `no` means the package install does not enable enforcement — admins / GUI explicitly turn it on per stack. -### Policy file format (`/etc/ubuntu-fido/policy.d/*.conf`) +### Policy file format (`/etc/authforge/policy.d/*.conf`) TOML, parsed in lexical order, last-key-wins: @@ -252,7 +252,7 @@ Daemon reloads on `SIGHUP` or when a watched file changes (uses `inotify`). Before applying any policy change, daemon simulates the new policy against: - The currently logged-in interactive user (resolved via `loginctl`). -- Every user listed in `/var/lib/ubuntu-fido/users.db` (cached enrollment registry). +- Every user listed in `/var/lib/authforge/users.db` (cached enrollment registry). For each user, it runs the new policy through a dry-run PAM check. If the result would deny login *without* a way to recover (no enrolled credentials of any required method), the daemon refuses the change and returns an actionable error: "Applying this policy would lock out user `alice` from `gdm-password` (no fido2 credentials enrolled). Enroll a credential for alice or set this stack to 'optional'." @@ -283,7 +283,7 @@ The architecture is designed so each step here is additive — no refactor of v1 |---|---|---| | **v1.0** | Ubuntu LTS + GNOME, U2F + FIDO2 passkey + TOTP. | Reference. | | **v1.1** | Debian stable packaging (same source, second build target). | ~2 weeks. | -| **v1.2** | KDE Plasma front-end as a KCM module (`kcm_ubuntu_fido`). Reuses the same daemon over D-Bus. Built with KF6/Qt6. | ~6–8 weeks (mostly Qt port of GUI). | +| **v1.2** | KDE Plasma front-end as a KCM module (`kcm_authforge`). Reuses the same daemon over D-Bus. Built with KF6/Qt6. | ~6–8 weeks (mostly Qt port of GUI). | | **v1.3** | Fedora/RHEL spec file. PAM module and daemon already work; needs `.rpm` packaging and SELinux policy. GNOME GUI works as-is. | ~3–4 weeks. | | **v2.0** | Optional: organization-wide credential sync via FreeIPA / LDAP integration. Pure backend feature. | Out of scope for now. | @@ -307,4 +307,4 @@ The architecture is designed so each step here is additive — no refactor of v1 --- -*This design was developed via guided brainstorming on 2026-04-26. The next artifact is a detailed implementation plan in `2026-04-26-ubuntu-fido-implementation-plan.md`.* +*This design was developed via guided brainstorming on 2026-04-26. The next artifact is a detailed implementation plan in `2026-04-26-authforge-implementation-plan.md`.* diff --git a/docs/plans/2026-04-26-ubuntu-fido-implementation.md b/docs/plans/2026-04-26-authforge-implementation.md similarity index 76% rename from docs/plans/2026-04-26-ubuntu-fido-implementation.md rename to docs/plans/2026-04-26-authforge-implementation.md index dbf1aed..678b2cf 100644 --- a/docs/plans/2026-04-26-ubuntu-fido-implementation.md +++ b/docs/plans/2026-04-26-authforge-implementation.md @@ -1,16 +1,16 @@ -# ubuntu-fido Implementation Plan +# authforge Implementation Plan > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. > > **Note on plan structure:** This is a multi-month project. Phase 0 is fully detailed at step granularity. Phases 1–18 are specified with goals, deliverables, file targets, and task lists at sufficient detail to begin implementation. Each subsequent phase should re-invoke `superpowers:writing-plans` to expand its tasks to step-level granularity at the moment that phase begins (state from prior phases informs the expansion). -**Goal:** Ship `ubuntu-fido` as an apt package on a PPA that turns U2F / FIDO2 passkey / TOTP MFA on Ubuntu desktops into a two-command install with a polished libadwaita GUI, sane policy, and a first-login enrollment flow. +**Goal:** Ship `authforge` as an apt package on a PPA that turns U2F / FIDO2 passkey / TOTP MFA on Ubuntu desktops into a two-command install with a polished libadwaita GUI, sane policy, and a first-login enrollment flow. -**Architecture:** Rust system daemon (`ubuntu-fidod`) exposes a D-Bus interface. A GTK4 / libadwaita app and a CLI are thin clients. A small C PAM module (`pam_ubuntu_fido_pending.so`) backstops first-login enrollment. PAM stack edits go through `pam-auth-update`. Policy is drop-in TOML in `/etc/ubuntu-fido/policy.d/`. Full design in `docs/plans/2026-04-26-ubuntu-fido-design.md`. +**Architecture:** Rust system daemon (`authforged`) exposes a D-Bus interface. A GTK4 / libadwaita app and a CLI are thin clients. A small C PAM module (`pam_authforge_pending.so`) backstops first-login enrollment. PAM stack edits go through `pam-auth-update`. Policy is drop-in TOML in `/etc/authforge/policy.d/`. Full design in `docs/plans/2026-04-26-authforge-design.md`. **Tech Stack:** Rust 2021 edition (daemon, CLI), GTK4 + libadwaita via `gtk4-rs` and `libadwaita-rs` (GUI), C (PAM module), `libfido2` via `ctap-hid-fido2` crate, D-Bus via `zbus`, polkit, debhelper-compat 13 packaging, sbuild for clean builds, GitHub Actions CI, Launchpad PPA for distribution. -**Reference design:** [docs/plans/2026-04-26-ubuntu-fido-design.md](2026-04-26-ubuntu-fido-design.md) +**Reference design:** [docs/plans/2026-04-26-authforge-design.md](2026-04-26-authforge-design.md) --- @@ -24,8 +24,8 @@ | 3 | Daemon: FIDO2 enrollment backend via `ctap-hid-fido2` | 5–7 days | Spec'd | | 4 | Daemon: policy apply via pam-auth-update wrapper | 4 days | Spec'd | | 5 | Daemon: lockout simulator | 3 days | Spec'd | -| 6 | PAM module: `pam_ubuntu_fido_pending.so` (C) | 3 days | Spec'd | -| 7 | CLI: `ubuntu-fidoctl` | 4 days | Spec'd | +| 6 | PAM module: `pam_authforge_pending.so` (C) | 3 days | Spec'd | +| 7 | CLI: `authforgectl` | 4 days | Spec'd | | 8 | GUI: app shell + Security Keys tab | 6–8 days | Spec'd | | 9 | GUI: Policy tab + lockout-warning UX | 4 days | Spec'd | | 10 | First-login flow: autostart entry + fullscreen modal | 4 days | Spec'd | @@ -33,8 +33,8 @@ | 12 | Recovery flow (codes + emergency unlock) | 4 days | Spec'd | | 13 | Debian packaging finalization (postinst, debconf, purge) | 4 days | Spec'd | | 14 | Launchpad PPA build setup | 2 days | Spec'd | -| 15 | `ubuntu-fido-gnome-integration` (Users panel shortcut) | 3 days | Spec'd | -| 16 | Ansible role `dangerousthings.ubuntu_fido` | 2 days | Spec'd | +| 15 | `authforge-gnome-integration` (Users panel shortcut) | 3 days | Spec'd | +| 16 | Ansible role `dangerousthings.authforge` | 2 days | Spec'd | | 17 | Integration test harness (Multipass / LXD VM) | 4 days | Spec'd | | 18 | User docs + onboarding site | 3 days | Spec'd | | **R** | **v1.0 release** | 1 day | — | @@ -82,7 +82,7 @@ debian/.debhelper/ debian/files debian/*.substvars debian/*.debhelper.log -debian/ubuntu-fido*/ +debian/authforge*/ build/ .vscode/ *.swp @@ -93,14 +93,14 @@ build/ **Step 4:** Write minimal `README.md`: ```markdown -# ubuntu-fido +# authforge Turnkey U2F / FIDO2 passkey / TOTP MFA for Ubuntu desktops. ## Install (end users) - sudo add-apt-repository ppa:dangerousthings/ubuntu-fido - sudo apt install ubuntu-fido + sudo add-apt-repository ppa:dangerousthings/authforge + sudo apt install authforge ## Build from source @@ -137,7 +137,7 @@ version = "0.1.0" edition = "2021" license = "Apache-2.0" authors = ["Dangerous Things "] -repository = "https://github.com/dangerousthings/ubuntu-fido" +repository = "https://github.com/dangerousthings/authforge" rust-version = "1.78" [workspace.dependencies] @@ -185,7 +185,7 @@ rustflags = ["-D", "warnings"] ```toml [package] -name = "ubuntu-fido-common" +name = "authforge-common" version.workspace = true edition.workspace = true license.workspace = true @@ -248,7 +248,7 @@ mod tests { This needs `serde_json` as a dev-dep; add `[dev-dependencies] serde_json = { workspace = true }` to `common/Cargo.toml`. -**Step 6:** Run `cargo test -p ubuntu-fido-common`. Expected: PASS. +**Step 6:** Run `cargo test -p authforge-common`. Expected: PASS. **Step 7:** Commit. @@ -267,17 +267,17 @@ git commit -m "Add common crate with shared Mode and Method types" ```toml [package] -name = "ubuntu-fidod" +name = "authforged" version.workspace = true edition.workspace = true license.workspace = true [[bin]] -name = "ubuntu-fidod" +name = "authforged" path = "src/main.rs" [dependencies] -ubuntu-fido-common = { path = "../common" } +authforge-common = { path = "../common" } zbus = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } @@ -296,13 +296,13 @@ async fn main() -> Result<()> { tracing_subscriber::fmt() .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) .init(); - info!("ubuntu-fidod {} starting", env!("CARGO_PKG_VERSION")); + info!("authforged {} starting", env!("CARGO_PKG_VERSION")); // D-Bus service registration in Phase 1. Ok(()) } ``` -**Step 3:** `cargo build -p ubuntu-fidod`. Expected: success. +**Step 3:** `cargo build -p authforged`. Expected: success. **Step 4:** Commit. @@ -321,17 +321,17 @@ git commit -m "Add daemon crate skeleton" ```toml [package] -name = "ubuntu-fidoctl" +name = "authforgectl" version.workspace = true edition.workspace = true license.workspace = true [[bin]] -name = "ubuntu-fidoctl" +name = "authforgectl" path = "src/main.rs" [dependencies] -ubuntu-fido-common = { path = "../common" } +authforge-common = { path = "../common" } clap = { workspace = true } anyhow = { workspace = true } zbus = { workspace = true } @@ -345,7 +345,7 @@ use anyhow::Result; use clap::Parser; #[derive(Parser)] -#[command(name = "ubuntu-fidoctl", version, about = "Manage ubuntu-fido configuration")] +#[command(name = "authforgectl", version, about = "Manage authforge configuration")] struct Cli { #[command(subcommand)] cmd: Cmd, @@ -360,7 +360,7 @@ enum Cmd { async fn main() -> Result<()> { let args = Cli::parse(); match args.cmd { - Cmd::Status => println!("ubuntu-fidoctl: not yet implemented"), + Cmd::Status => println!("authforgectl: not yet implemented"), } Ok(()) } @@ -379,9 +379,9 @@ git commit -m "Add cli crate skeleton" **Files:** - Create: `pam/Makefile` -- Create: `pam/pam_ubuntu_fido_pending.c` +- Create: `pam/pam_authforge_pending.c` -**Step 1:** `pam/pam_ubuntu_fido_pending.c`: +**Step 1:** `pam/pam_authforge_pending.c`: ```c #define PAM_SM_AUTH @@ -392,7 +392,7 @@ git commit -m "Add cli crate skeleton" PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { (void)flags; (void)argc; (void)argv; - pam_syslog(pamh, LOG_INFO, "ubuntu_fido_pending: stub - allowing"); + pam_syslog(pamh, LOG_INFO, "authforge_pending: stub - allowing"); return PAM_IGNORE; /* implemented in Phase 6 */ } @@ -409,14 +409,14 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, CFLAGS ?= -Wall -Wextra -Werror -fPIC -O2 LIBDIR ?= /usr/lib/$(shell dpkg-architecture -qDEB_HOST_MULTIARCH)/security -pam_ubuntu_fido_pending.so: pam_ubuntu_fido_pending.c +pam_authforge_pending.so: pam_authforge_pending.c $(CC) $(CFLAGS) -shared -o $@ $< -lpam -install: pam_ubuntu_fido_pending.so - install -D -m 0644 pam_ubuntu_fido_pending.so $(DESTDIR)$(LIBDIR)/pam_ubuntu_fido_pending.so +install: pam_authforge_pending.so + install -D -m 0644 pam_authforge_pending.so $(DESTDIR)$(LIBDIR)/pam_authforge_pending.so clean: - rm -f pam_ubuntu_fido_pending.so + rm -f pam_authforge_pending.so .PHONY: install clean ``` @@ -427,7 +427,7 @@ clean: cd pam && make && cd .. ``` -Expected: produces `pam/pam_ubuntu_fido_pending.so` (~10 KB). Requires `libpam0g-dev` (will be in build-deps). +Expected: produces `pam/pam_authforge_pending.so` (~10 KB). Requires `libpam0g-dev` (will be in build-deps). **Step 4:** Commit. @@ -441,8 +441,8 @@ git commit -m "Add PAM module stub" **Files:** - Create: `gui/Cargo.toml` - Create: `gui/src/main.rs` -- Create: `gui/data/io.dangerousthings.UbuntuFido.desktop` -- Create: `gui/data/io.dangerousthings.UbuntuFido.svg` (1KB placeholder icon) +- Create: `gui/data/io.dangerousthings.AuthForge.desktop` +- Create: `gui/data/io.dangerousthings.AuthForge.svg` (1KB placeholder icon) **Step 1:** Add `gui` to workspace members in root `Cargo.toml`. @@ -450,19 +450,19 @@ git commit -m "Add PAM module stub" ```toml [package] -name = "ubuntu-fido-gui" +name = "authforge-gui" version.workspace = true edition.workspace = true license.workspace = true [[bin]] -name = "ubuntu-fido" +name = "authforge" path = "src/main.rs" [dependencies] gtk = { package = "gtk4", version = "0.8" } adw = { package = "libadwaita", version = "0.6" } -ubuntu-fido-common = { path = "../common" } +authforge-common = { path = "../common" } anyhow = { workspace = true } ``` @@ -472,7 +472,7 @@ anyhow = { workspace = true } use adw::prelude::*; use gtk::glib; -const APP_ID: &str = "io.dangerousthings.UbuntuFido"; +const APP_ID: &str = "io.dangerousthings.AuthForge"; fn main() -> glib::ExitCode { let app = adw::Application::builder().application_id(APP_ID).build(); @@ -499,15 +499,15 @@ fn main() -> glib::ExitCode { } ``` -**Step 4:** `.desktop` file at `gui/data/io.dangerousthings.UbuntuFido.desktop`: +**Step 4:** `.desktop` file at `gui/data/io.dangerousthings.AuthForge.desktop`: ```desktop [Desktop Entry] Name=Authentication GenericName=Security Keys & MFA Comment=Manage U2F/FIDO2 keys and authentication policy -Exec=ubuntu-fido -Icon=io.dangerousthings.UbuntuFido +Exec=authforge +Icon=io.dangerousthings.AuthForge Terminal=false Type=Application Categories=Settings;Security; @@ -515,12 +515,12 @@ Keywords=mfa;u2f;fido2;passkey;totp;security; StartupNotify=true ``` -**Step 5:** Placeholder SVG icon — a simple gray key glyph; sourced from any open icon set under a compatible license. Save at `gui/data/io.dangerousthings.UbuntuFido.svg`. +**Step 5:** Placeholder SVG icon — a simple gray key glyph; sourced from any open icon set under a compatible license. Save at `gui/data/io.dangerousthings.AuthForge.svg`. **Step 6:** Build (assumes GTK4 / libadwaita dev packages installed: `libgtk-4-dev`, `libadwaita-1-dev`). ```bash -cargo build -p ubuntu-fido-gui +cargo build -p authforge-gui ``` Expected: success. @@ -541,17 +541,17 @@ git commit -m "Add GUI crate skeleton with libadwaita placeholder window" - Create: `debian/rules` - Create: `debian/source/format` - Create: `debian/compat` (or use `debhelper-compat (= 13)` in control) -- Create: `debian/ubuntu-fido.install` -- Create: `debian/ubuntu-fido-daemon.install` -- Create: `debian/ubuntu-fido-daemon.service` -- Create: `debian/ubuntu-fido-pam.install` -- Create: `debian/ubuntu-fido-cli.install` -- Create: `debian/ubuntu-fido-gui.install` +- Create: `debian/authforge.install` +- Create: `debian/authforge-daemon.install` +- Create: `debian/authforge-daemon.service` +- Create: `debian/authforge-pam.install` +- Create: `debian/authforge-cli.install` +- Create: `debian/authforge-gui.install` **Step 1:** `debian/changelog`: ``` -ubuntu-fido (0.1.0-1) UNRELEASED; urgency=low +authforge (0.1.0-1) UNRELEASED; urgency=low * Initial packaging skeleton. @@ -567,7 +567,7 @@ ubuntu-fido (0.1.0-1) UNRELEASED; urgency=low **Step 3:** `debian/control` — declares all 5 binary packages and their relationships: ``` -Source: ubuntu-fido +Source: authforge Section: admin Priority: optional Maintainer: Dangerous Things @@ -581,46 +581,46 @@ Build-Depends: libfido2-dev, pkg-config Standards-Version: 4.6.2 -Homepage: https://github.com/dangerousthings/ubuntu-fido -Vcs-Browser: https://github.com/dangerousthings/ubuntu-fido -Vcs-Git: https://github.com/dangerousthings/ubuntu-fido.git +Homepage: https://github.com/dangerousthings/authforge +Vcs-Browser: https://github.com/dangerousthings/authforge +Vcs-Git: https://github.com/dangerousthings/authforge.git -Package: ubuntu-fido +Package: authforge Architecture: any -Depends: ubuntu-fido-daemon (= ${binary:Version}), - ubuntu-fido-pam (= ${binary:Version}), - ubuntu-fido-cli (= ${binary:Version}), +Depends: authforge-daemon (= ${binary:Version}), + authforge-pam (= ${binary:Version}), + authforge-cli (= ${binary:Version}), ${misc:Depends} -Recommends: ubuntu-fido-gui (= ${binary:Version}) -Suggests: ubuntu-fido-gnome-integration +Recommends: authforge-gui (= ${binary:Version}) +Suggests: authforge-gnome-integration Description: Turnkey FIDO2/U2F/TOTP MFA for Ubuntu (metapackage) - Installs the full ubuntu-fido stack: daemon, PAM module, CLI, and + Installs the full authforge stack: daemon, PAM module, CLI, and (if recommended) GUI. -Package: ubuntu-fido-daemon +Package: authforge-daemon Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, libpam-u2f, libfido2-1 -Description: System daemon for ubuntu-fido MFA management +Description: System daemon for authforge MFA management Provides the privileged D-Bus service that orchestrates enrollment, policy edits, and lockout-prevention checks. -Package: ubuntu-fido-pam +Package: authforge-pam Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, libpam-runtime -Description: PAM module backstopping ubuntu-fido first-login enrollment - Refuses authentication when /var/lib/ubuntu-fido/pending/ exists +Description: PAM module backstopping authforge first-login enrollment + Refuses authentication when /var/lib/authforge/pending/ exists and the user has not completed first-login MFA setup. -Package: ubuntu-fido-cli +Package: authforge-cli Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, ubuntu-fido-daemon -Description: CLI for ubuntu-fido (admin and fleet) +Depends: ${shlibs:Depends}, ${misc:Depends}, authforge-daemon +Description: CLI for authforge (admin and fleet) Configure policy, enroll on behalf of users, generate recovery codes. -Package: ubuntu-fido-gui +Package: authforge-gui Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, ubuntu-fido-daemon -Description: GTK4/libadwaita UI for ubuntu-fido +Depends: ${shlibs:Depends}, ${misc:Depends}, authforge-daemon +Description: GTK4/libadwaita UI for authforge End-user-facing settings panel for enrollment and policy. ``` @@ -640,20 +640,20 @@ override_dh_auto_build: override_dh_auto_install: # Daemon - install -D -m 0755 target/release/ubuntu-fidod \ - debian/ubuntu-fido-daemon/usr/sbin/ubuntu-fidod + install -D -m 0755 target/release/authforged \ + debian/authforge-daemon/usr/sbin/authforged # CLI - install -D -m 0755 target/release/ubuntu-fidoctl \ - debian/ubuntu-fido-cli/usr/bin/ubuntu-fidoctl + install -D -m 0755 target/release/authforgectl \ + debian/authforge-cli/usr/bin/authforgectl # GUI - install -D -m 0755 target/release/ubuntu-fido \ - debian/ubuntu-fido-gui/usr/bin/ubuntu-fido - install -D -m 0644 gui/data/io.dangerousthings.UbuntuFido.desktop \ - debian/ubuntu-fido-gui/usr/share/applications/io.dangerousthings.UbuntuFido.desktop - install -D -m 0644 gui/data/io.dangerousthings.UbuntuFido.svg \ - debian/ubuntu-fido-gui/usr/share/icons/hicolor/scalable/apps/io.dangerousthings.UbuntuFido.svg + install -D -m 0755 target/release/authforge \ + debian/authforge-gui/usr/bin/authforge + install -D -m 0644 gui/data/io.dangerousthings.AuthForge.desktop \ + debian/authforge-gui/usr/share/applications/io.dangerousthings.AuthForge.desktop + install -D -m 0644 gui/data/io.dangerousthings.AuthForge.svg \ + debian/authforge-gui/usr/share/icons/hicolor/scalable/apps/io.dangerousthings.AuthForge.svg # PAM - $(MAKE) -C pam install DESTDIR=$(CURDIR)/debian/ubuntu-fido-pam + $(MAKE) -C pam install DESTDIR=$(CURDIR)/debian/authforge-pam override_dh_auto_test: cargo test --workspace --release @@ -680,9 +680,9 @@ Expected: produces 5 `.deb` files in the parent directory. Lintian may complain **Step 8:** Verify install + remove on a throwaway VM (Multipass shell or LXD container). ```bash -sudo dpkg -i ../ubuntu-fido*.deb || sudo apt -f install -sudo systemctl status ubuntu-fido.service # will fail until Phase 1 ships unit -sudo apt purge ubuntu-fido* +sudo dpkg -i ../authforge*.deb || sudo apt -f install +sudo systemctl status authforge.service # will fail until Phase 1 ships unit +sudo apt purge authforge* ``` **Step 9:** Commit. @@ -721,7 +721,7 @@ jobs: - uses: actions/checkout@v4 - run: sudo apt-get update && sudo apt-get install -y debhelper devscripts lintian libpam0g-dev libgtk-4-dev libadwaita-1-dev libfido2-dev pkg-config cargo rustc - run: debuild -us -uc -b - - run: lintian --info --display-info ../ubuntu-fido*.changes || true # warnings allowed in Phase 0 + - run: lintian --info --display-info ../authforge*.changes || true # warnings allowed in Phase 0 ``` **Step 2:** Push and verify both jobs go green. @@ -740,9 +740,9 @@ Verify all of the following before declaring Phase 0 complete: - [ ] `cargo build --workspace --release` succeeds. - [ ] `cargo test --workspace` succeeds (1 test in `common`). - [ ] `cargo clippy --workspace -- -D warnings` is clean. -- [ ] `make -C pam` produces `pam_ubuntu_fido_pending.so`. +- [ ] `make -C pam` produces `pam_authforge_pending.so`. - [ ] `debuild -us -uc -b` produces 5 `.deb` files. -- [ ] On an Ubuntu 24.04 LXD container: `sudo dpkg -i ../ubuntu-fido*.deb` succeeds, `sudo apt purge ubuntu-fido*` cleanly removes. +- [ ] On an Ubuntu 24.04 LXD container: `sudo dpkg -i ../authforge*.deb` succeeds, `sudo apt purge authforge*` cleanly removes. - [ ] CI is green on `main`. If all check, tag `v0.1.0-scaffolding`: @@ -755,24 +755,24 @@ git tag -a v0.1.0-scaffolding -m "Phase 0: repository scaffolding complete" # Phase 1: Daemon — D-Bus Interface, systemd, polkit -**Goal:** `ubuntu-fidod` registers on the system bus as `io.dangerousthings.UbuntuFido`, gets started by systemd, and enforces polkit-mediated method-level authorization. Methods are stubs returning sensible test data. +**Goal:** `authforged` registers on the system bus as `io.dangerousthings.AuthForge`, gets started by systemd, and enforces polkit-mediated method-level authorization. Methods are stubs returning sensible test data. **Re-invoke `superpowers:writing-plans` at start of this phase to expand to step granularity.** **Files to create:** - `daemon/src/dbus.rs` — zbus `interface` definition - `daemon/src/state.rs` — in-memory state shell -- `debian/ubuntu-fido-daemon.service` — systemd unit -- `debian/io.dangerousthings.UbuntuFido.conf` — D-Bus policy -- `debian/io.dangerousthings.UbuntuFido.service` — D-Bus activation file -- `debian/io.dangerousthings.UbuntuFido.policy` — polkit actions -- `debian/ubuntu-fido-daemon.postinst` — enable + start unit +- `debian/authforge-daemon.service` — systemd unit +- `debian/io.dangerousthings.AuthForge.conf` — D-Bus policy +- `debian/io.dangerousthings.AuthForge.service` — D-Bus activation file +- `debian/io.dangerousthings.AuthForge.policy` — polkit actions +- `debian/authforge-daemon.postinst` — enable + start unit **D-Bus interface skeleton:** ```rust -#[zbus::interface(name = "io.dangerousthings.UbuntuFido1")] -impl UbuntuFido { +#[zbus::interface(name = "io.dangerousthings.AuthForge1")] +impl AuthForge { async fn list_credentials(&self, user: String) -> zbus::fdo::Result> { ... } async fn enroll_own(&self, user: String, nickname: String) -> zbus::fdo::Result { ... } async fn remove_own(&self, user: String, cred_id: String) -> zbus::fdo::Result<()> { ... } @@ -785,26 +785,26 @@ impl UbuntuFido { } ``` -**polkit actions** (XML in `io.dangerousthings.UbuntuFido.policy`): +**polkit actions** (XML in `io.dangerousthings.AuthForge.policy`): | Action | Default for active session | |---|---| -| `io.dangerousthings.UbuntuFido.enroll-own` | `auth_self_keep` | -| `io.dangerousthings.UbuntuFido.remove-own` | `auth_self_keep` | -| `io.dangerousthings.UbuntuFido.enroll-other` | `auth_admin_keep` | -| `io.dangerousthings.UbuntuFido.set-policy` | `auth_admin_keep` | -| `io.dangerousthings.UbuntuFido.set-pending` | `auth_admin_keep` | -| `io.dangerousthings.UbuntuFido.clear-pending` | `auth_admin_keep` | -| `io.dangerousthings.UbuntuFido.generate-recovery` | `auth_admin_keep` | +| `io.dangerousthings.AuthForge.enroll-own` | `auth_self_keep` | +| `io.dangerousthings.AuthForge.remove-own` | `auth_self_keep` | +| `io.dangerousthings.AuthForge.enroll-other` | `auth_admin_keep` | +| `io.dangerousthings.AuthForge.set-policy` | `auth_admin_keep` | +| `io.dangerousthings.AuthForge.set-pending` | `auth_admin_keep` | +| `io.dangerousthings.AuthForge.clear-pending` | `auth_admin_keep` | +| `io.dangerousthings.AuthForge.generate-recovery` | `auth_admin_keep` | **Tasks:** 1. Add zbus interface module with stubs returning fixture data. -2. Wire up `connection.request_name("io.dangerousthings.UbuntuFido")`. -3. Write systemd unit (`Type=dbus`, `BusName=io.dangerousthings.UbuntuFido`, `User=root`). +2. Wire up `connection.request_name("io.dangerousthings.AuthForge")`. +3. Write systemd unit (`Type=dbus`, `BusName=io.dangerousthings.AuthForge`, `User=root`). 4. Write D-Bus system policy (allow root to own; allow `at_console` to call read methods; restrict write methods). 5. Write polkit policy XML; daemon checks each method against polkit before executing. -6. Wire postinst: `systemctl daemon-reload && systemctl enable --now ubuntu-fido.service`. -7. Test: `busctl call io.dangerousthings.UbuntuFido /io/dangerousthings/UbuntuFido io.dangerousthings.UbuntuFido1 ListCredentials s "$USER"` returns the fixture data. +6. Wire postinst: `systemctl daemon-reload && systemctl enable --now authforge.service`. +7. Test: `busctl call io.dangerousthings.AuthForge /io/dangerousthings/AuthForge io.dangerousthings.AuthForge1 ListCredentials s "$USER"` returns the fixture data. 8. Test: as non-root, `SetPolicy` triggers polkit prompt. **Acceptance:** D-Bus introspection works (`busctl introspect ...`), all 9 methods are callable as stubs, polkit prompts appear at correct times. @@ -813,14 +813,14 @@ impl UbuntuFido { # Phase 2: Daemon — Storage Layer -**Goal:** Real I/O to `/etc/ubuntu-fido/policy.d/`, `/var/lib/ubuntu-fido/pending/`, and `~/.config/Yubico/u2f_keys` (or `/etc/u2f_mappings`). Replaces fixtures from Phase 1. +**Goal:** Real I/O to `/etc/authforge/policy.d/`, `/var/lib/authforge/pending/`, and `~/.config/Yubico/u2f_keys` (or `/etc/u2f_mappings`). Replaces fixtures from Phase 1. **Files:** - `common/src/policy.rs` — fully implemented TOML parser with last-key-wins merge - `daemon/src/storage/policy.rs` — read/write policy.d/ dir, inotify watcher - `daemon/src/storage/pending.rs` — read/write pending flags - `daemon/src/storage/credentials.rs` — manipulate u2f_keys files (per-user vs central) -- `daemon/src/storage/userdb.rs` — `/var/lib/ubuntu-fido/users.db` cache (sqlite via `rusqlite`) +- `daemon/src/storage/userdb.rs` — `/var/lib/authforge/users.db` cache (sqlite via `rusqlite`) **Tasks:** 1. Implement `Policy::load_from_dir(path)` with merge semantics. TDD: write 3 test fixture dirs, assert merge order. @@ -864,10 +864,10 @@ impl UbuntuFido { **Files:** - `daemon/src/policy_apply/mod.rs` - `daemon/src/policy_apply/profile.rs` — generates the pam-configs file dynamically -- `debian/ubuntu-fido-pam.install` — ships the static pam-configs profile -- `debian/ubuntu-fido-daemon.postinst` — runs `pam-auth-update --package` on install +- `debian/authforge-pam.install` — ships the static pam-configs profile +- `debian/authforge-daemon.postinst` — runs `pam-auth-update --package` on install -**Approach:** The pam-configs profile is templated. Daemon writes the appropriate variant to `/usr/share/pam-configs/ubuntu-fido` based on which stacks are required, then invokes `pam-auth-update --package`. (Alternative: ship multiple profiles, enable/disable each. The first approach is simpler.) +**Approach:** The pam-configs profile is templated. Daemon writes the appropriate variant to `/usr/share/pam-configs/authforge` based on which stacks are required, then invokes `pam-auth-update --package`. (Alternative: ship multiple profiles, enable/disable each. The first approach is simpler.) **Tasks:** 1. Write template renderer. @@ -904,20 +904,20 @@ Returns a list of (user, stack, reason) violations. --- -# Phase 6: PAM Module — `pam_ubuntu_fido_pending.so` +# Phase 6: PAM Module — `pam_authforge_pending.so` **Goal:** The C module that backstops first-login enrollment. Replaces the Phase 0 stub. **Files:** -- `pam/pam_ubuntu_fido_pending.c` — full implementation +- `pam/pam_authforge_pending.c` — full implementation - `pam/Makefile` — already exists from Phase 0 **Behavior:** - `pam_sm_authenticate`: 1. Get `PAM_USER`. - 2. Check for `/var/lib/ubuntu-fido/pending/` (use `stat()`, root-owned, mode 0644, no setuid surprises). + 2. Check for `/var/lib/authforge/pending/` (use `stat()`, root-owned, mode 0644, no setuid surprises). 3. If exists: - a. If recovery code provided and matches `/var/lib/ubuntu-fido/recovery/` (8-digit, 24h validity), accept and re-flag for re-enrollment. + a. If recovery code provided and matches `/var/lib/authforge/recovery/` (8-digit, 24h validity), accept and re-flag for re-enrollment. b. Otherwise return `PAM_AUTH_ERR` with conv message: "Account setup incomplete. Please complete enrollment in the Authentication app." 4. If no flag: return `PAM_IGNORE`. - `pam_sm_setcred`: `PAM_SUCCESS`. @@ -928,11 +928,11 @@ Returns a list of (user, stack, reason) violations. 3. Add structured logging via `pam_syslog`. 4. Test with `pamtester`: ``` - sudo touch /var/lib/ubuntu-fido/pending/alice - pamtester ubuntu-fido alice authenticate + sudo touch /var/lib/authforge/pending/alice + pamtester authforge alice authenticate # expect: failure with our message - sudo rm /var/lib/ubuntu-fido/pending/alice - pamtester ubuntu-fido alice authenticate + sudo rm /var/lib/authforge/pending/alice + pamtester authforge alice authenticate # expect: success (PAM_IGNORE → other modules carry it) ``` @@ -940,7 +940,7 @@ Returns a list of (user, stack, reason) violations. --- -# Phase 7: CLI — `ubuntu-fidoctl` +# Phase 7: CLI — `authforgectl` **Goal:** Full admin/fleet CLI. Talks D-Bus to the daemon. No magic — every command is a thin wrapper around a D-Bus call. @@ -951,19 +951,19 @@ Returns a list of (user, stack, reason) violations. **Subcommands:** ``` -ubuntu-fidoctl status -ubuntu-fidoctl enroll [--user USER] [--nickname NAME] -ubuntu-fidoctl list [--user USER] -ubuntu-fidoctl remove [--user USER] CRED_ID -ubuntu-fidoctl policy show -ubuntu-fidoctl policy set [--methods METHOD,...] -ubuntu-fidoctl policy apply [--force-i-know-what-im-doing] -ubuntu-fidoctl policy validate -ubuntu-fidoctl pending set USER [--methods METHOD,...] -ubuntu-fidoctl pending clear USER -ubuntu-fidoctl pending list -ubuntu-fidoctl recovery generate USER -ubuntu-fidoctl recovery list USER +authforgectl status +authforgectl enroll [--user USER] [--nickname NAME] +authforgectl list [--user USER] +authforgectl remove [--user USER] CRED_ID +authforgectl policy show +authforgectl policy set [--methods METHOD,...] +authforgectl policy apply [--force-i-know-what-im-doing] +authforgectl policy validate +authforgectl pending set USER [--methods METHOD,...] +authforgectl pending clear USER +authforgectl pending list +authforgectl recovery generate USER +authforgectl recovery list USER ``` **Output:** human-readable by default; `--json` flag for machine-parseable output (essential for Ansible integration). @@ -1023,12 +1023,12 @@ ubuntu-fidoctl recovery list USER **Files:** - `gui/src/views/firstrun.rs` — fullscreen modal mode -- `gui/data/ubuntu-fido-firstrun.desktop` — autostart entry -- `debian/ubuntu-fido-gui.install` — install autostart entry to `/etc/xdg/autostart/` +- `gui/data/authforge-firstrun.desktop` — autostart entry +- `debian/authforge-gui.install` — install autostart entry to `/etc/xdg/autostart/` - `gui/src/main.rs` — handle `--first-run` CLI flag **Tasks:** -1. Add `--first-run` flag to `ubuntu-fido` binary; alters startup to fullscreen modal mode (no header bar, no decorations, sticky-on-top). +1. Add `--first-run` flag to `authforge` binary; alters startup to fullscreen modal mode (no header bar, no decorations, sticky-on-top). 2. On startup in first-run mode, query daemon for `pending_flag(current_user)`; if absent, exit immediately. 3. Show welcome page + run enrollment flow. 4. On successful enrollment, call `clear_pending_flag` via D-Bus, exit cleanly. @@ -1037,9 +1037,9 @@ ubuntu-fidoctl recovery list USER **Test (manual, in VM):** 1. `useradd -m testuser`, `passwd testuser` (set tempPW), `chage -d 0 testuser`. -2. `sudo ubuntu-fidoctl pending set testuser --methods fido2`. +2. `sudo authforgectl pending set testuser --methods fido2`. 3. Log out, log in as testuser → forced password change → enrollment modal appears → enroll Yubikey → modal closes → desktop usable. -4. Verify: subsequent SSH-as-testuser-without-key is blocked by `pam_ubuntu_fido_pending.so` if pending wasn't cleared. +4. Verify: subsequent SSH-as-testuser-without-key is blocked by `pam_authforge_pending.so` if pending wasn't cleared. **Acceptance:** End-to-end flow C works in a VM smoke test. @@ -1053,7 +1053,7 @@ ubuntu-fidoctl recovery list USER - `daemon/Cargo.toml` — add `totp` feature - `daemon/src/totp/mod.rs` — secret generation, recovery codes - `gui/src/views/totp.rs` — QR code display, secret enrollment -- `debian/ubuntu-fido-daemon.install` — conditionally install pam-configs entry for TOTP +- `debian/authforge-daemon.install` — conditionally install pam-configs entry for TOTP - `debian/control` — `Recommends: libpam-google-authenticator` when feature enabled **Tasks:** @@ -1077,9 +1077,9 @@ ubuntu-fidoctl recovery list USER - `gui/src/views/recovery.rs` **Tasks:** -1. `generate_recovery_code(user)` writes `/var/lib/ubuntu-fido/recovery/` (root-owned, 0600) containing Argon2id hash + expiry timestamp. -2. PAM module checks recovery code at password prompt (already added in Phase 6); on success, removes recovery file and writes a `/var/lib/ubuntu-fido/pending/` flag with `re_enroll = true`. -3. CLI: `ubuntu-fidoctl recovery generate alice` outputs the 8-digit code. +1. `generate_recovery_code(user)` writes `/var/lib/authforge/recovery/` (root-owned, 0600) containing Argon2id hash + expiry timestamp. +2. PAM module checks recovery code at password prompt (already added in Phase 6); on success, removes recovery file and writes a `/var/lib/authforge/pending/` flag with `re_enroll = true`. +3. CLI: `authforgectl recovery generate alice` outputs the 8-digit code. 4. GUI: "Recovery" tab shows generate / list / revoke. 5. Print-PDF feature: `gtk_print_unix_dialog` with template containing user's TOTP secret (opt-in only) and recovery codes. @@ -1092,32 +1092,32 @@ ubuntu-fidoctl recovery list USER **Goal:** All packages install cleanly, postinst/prerm/postrm scripts handle every state transition correctly, debconf preseed works. **Files:** -- `debian/ubuntu-fido-daemon.{postinst,prerm,postrm}` -- `debian/ubuntu-fido-pam.{postinst,prerm,postrm}` -- `debian/ubuntu-fido.config` — debconf script -- `debian/ubuntu-fido.templates` — debconf templates +- `debian/authforge-daemon.{postinst,prerm,postrm}` +- `debian/authforge-pam.{postinst,prerm,postrm}` +- `debian/authforge.config` — debconf script +- `debian/authforge.templates` — debconf templates **Tasks:** -1. postinst: enable + start daemon; run `pam-auth-update --package`; if first-time install and debconf provided answers, write initial `/etc/ubuntu-fido/policy.d/00-debconf.conf`. +1. postinst: enable + start daemon; run `pam-auth-update --package`; if first-time install and debconf provided answers, write initial `/etc/authforge/policy.d/00-debconf.conf`. 2. prerm: disable PAM enforcement (`pam-auth-update --package --remove`) so removal can't lock anyone out. -3. postrm purge: rm `/etc/ubuntu-fido/`, `/var/lib/ubuntu-fido/`. +3. postrm purge: rm `/etc/authforge/`, `/var/lib/authforge/`. 4. debconf templates: ask "Default policy? (None / Optional everywhere / Required for sudo)". 5. lintian: get all warnings down to zero or explicitly overridden with rationale. 6. Test matrix: install → upgrade (from 0.0.x → 0.1.0) → remove → purge → reinstall, on Ubuntu 22.04 and 24.04. -**Acceptance:** `piuparts ubuntu-fido_0.1.0-1_amd64.deb` passes. +**Acceptance:** `piuparts authforge_0.1.0-1_amd64.deb` passes. --- # Phase 14: Launchpad PPA Setup -**Goal:** End users can `sudo add-apt-repository ppa:dangerousthings/ubuntu-fido`. +**Goal:** End users can `sudo add-apt-repository ppa:dangerousthings/authforge`. **Tasks:** 1. Create Launchpad team `dangerousthings` (or use existing). -2. Create PPA `ubuntu-fido`. +2. Create PPA `authforge`. 3. Generate signing key (gpg, store passphrase in 1Password / vault). -4. `dput ppa:dangerousthings/ubuntu-fido ubuntu-fido_0.1.0-1_source.changes` (note: Launchpad builds from source). +4. `dput ppa:dangerousthings/authforge authforge_0.1.0-1_source.changes` (note: Launchpad builds from source). 5. Wait for build, verify install on a fresh VM. 6. Document signing key fingerprint in README. @@ -1125,13 +1125,13 @@ ubuntu-fidoctl recovery list USER --- -# Phase 15: `ubuntu-fido-gnome-integration` +# Phase 15: `authforge-gnome-integration` -**Goal:** Optional shortcut deb that makes ubuntu-fido discoverable from `gnome-control-center` Users panel. +**Goal:** Optional shortcut deb that makes authforge discoverable from `gnome-control-center` Users panel. **Files:** - New source tree under `gnome-integration/` (separate Cargo workspace member or pure-data deb) -- `debian/ubuntu-fido-gnome-integration.install` +- `debian/authforge-gnome-integration.install` **Approach (research required during this phase):** GNOME 46+ allows panel extensions via dbus-activated services. Ship a small JS/GJS extension or a dynamic library loaded by gnome-control-center. If neither stable approach exists, ship a `.desktop` file under `/usr/share/applications/` tagged with `X-GNOME-Settings-Panel=user-accounts` or similar — exact mechanism is GNOME-version-dependent. @@ -1141,13 +1141,13 @@ ubuntu-fidoctl recovery list USER 3. Test against current Ubuntu LTS GNOME version. 4. Pin Recommends to specific gnome-control-center major version range. -**Acceptance:** Opening Settings → Users → some-user shows a "Configure security…" link that launches `ubuntu-fido --user some-user` with proper polkit context. +**Acceptance:** Opening Settings → Users → some-user shows a "Configure security…" link that launches `authforge --user some-user` with proper polkit context. --- # Phase 16: Ansible Role -**Goal:** `dangerousthings.ubuntu_fido` role on Ansible Galaxy that handles install, policy, and enrollment for fleet deployments. +**Goal:** `dangerousthings.authforge` role on Ansible Galaxy that handles install, policy, and enrollment for fleet deployments. **Files (in a separate `ansible-role` tree, possibly its own repo):** - `ansible-role/tasks/main.yml` @@ -1156,7 +1156,7 @@ ubuntu-fidoctl recovery list USER - `ansible-role/meta/main.yml` **Tasks:** -1. Role tasks: add PPA, install packages, drop policy file at `/etc/ubuntu-fido/policy.d/90-fleet.conf`, restart daemon. +1. Role tasks: add PPA, install packages, drop policy file at `/etc/authforge/policy.d/90-fleet.conf`, restart daemon. 2. Variables for: enabled stacks, modes per stack, central credential storage on/off, default firstrun methods. 3. Examples in `examples/playbook.yml`. 4. Publish to Galaxy. @@ -1196,7 +1196,7 @@ Use `umockdev` to simulate USB devices in CI; require real hardware for nightly - `docs/user/fleet-deployment.md` - `docs/user/recovery.md` - `docs/user/troubleshooting.md` -- Optional: small static site (mdBook or Docusaurus) at `https://ubuntu-fido.dangerousthings.com` +- Optional: small static site (mdBook or Docusaurus) at `https://authforge.dangerousthings.com` **Tasks:** 1. Getting started: end-user view of "install + enroll my Yubikey + require it for sudo". @@ -1247,7 +1247,7 @@ Use `umockdev` to simulate USB devices in CI; require real hardware for nightly When the user returns: -> Plan complete and saved to `docs/plans/2026-04-26-ubuntu-fido-implementation.md`. The companion design doc is at `docs/plans/2026-04-26-ubuntu-fido-design.md`. Phase 0 is fully detailed; phases 1–18 are spec'd to a level sufficient to begin work. Each later phase should re-invoke `superpowers:writing-plans` for step-level expansion as it begins. +> Plan complete and saved to `docs/plans/2026-04-26-authforge-implementation.md`. The companion design doc is at `docs/plans/2026-04-26-authforge-design.md`. Phase 0 is fully detailed; phases 1–18 are spec'd to a level sufficient to begin work. Each later phase should re-invoke `superpowers:writing-plans` for step-level expansion as it begins. > > Two execution options: > diff --git a/gui/Cargo.toml b/gui/Cargo.toml index 7ccc430..4bb6294 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "ubuntu-fido-gui" +name = "authforge-gui" version.workspace = true edition.workspace = true license.workspace = true [[bin]] -name = "ubuntu-fido" +name = "authforge" path = "src/main.rs" [dependencies] gtk = { package = "gtk4", version = "0.8" } adw = { package = "libadwaita", version = "0.6" } -ubuntu-fido-common = { path = "../common" } +authforge-common = { path = "../common" } anyhow = { workspace = true } diff --git a/gui/data/io.dangerousthings.UbuntuFido.desktop b/gui/data/io.dangerousthings.AuthForge.desktop similarity index 82% rename from gui/data/io.dangerousthings.UbuntuFido.desktop rename to gui/data/io.dangerousthings.AuthForge.desktop index 2744654..ac8b16f 100644 --- a/gui/data/io.dangerousthings.UbuntuFido.desktop +++ b/gui/data/io.dangerousthings.AuthForge.desktop @@ -2,8 +2,8 @@ Name=Authentication GenericName=Security Keys & MFA Comment=Manage U2F/FIDO2 keys and authentication policy -Exec=ubuntu-fido -Icon=io.dangerousthings.UbuntuFido +Exec=authforge +Icon=io.dangerousthings.AuthForge Terminal=false Type=Application Categories=Settings;Security; diff --git a/gui/data/io.dangerousthings.UbuntuFido.svg b/gui/data/io.dangerousthings.AuthForge.svg similarity index 100% rename from gui/data/io.dangerousthings.UbuntuFido.svg rename to gui/data/io.dangerousthings.AuthForge.svg diff --git a/gui/src/main.rs b/gui/src/main.rs index ea9a813..7aa2497 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -1,7 +1,7 @@ use adw::prelude::*; use gtk::glib; -const APP_ID: &str = "io.dangerousthings.UbuntuFido"; +const APP_ID: &str = "io.dangerousthings.AuthForge"; fn main() -> glib::ExitCode { let app = adw::Application::builder().application_id(APP_ID).build(); diff --git a/pam/Makefile b/pam/Makefile index 81bfe2f..39fd1f5 100644 --- a/pam/Makefile +++ b/pam/Makefile @@ -1,13 +1,13 @@ CFLAGS ?= -Wall -Wextra -Werror -fPIC -O2 LIBDIR ?= /usr/lib/$(shell dpkg-architecture -qDEB_HOST_MULTIARCH)/security -pam_ubuntu_fido_pending.so: pam_ubuntu_fido_pending.c +pam_authforge_pending.so: pam_authforge_pending.c $(CC) $(CFLAGS) -shared -o $@ $< -lpam -install: pam_ubuntu_fido_pending.so - install -D -m 0644 pam_ubuntu_fido_pending.so $(DESTDIR)$(LIBDIR)/pam_ubuntu_fido_pending.so +install: pam_authforge_pending.so + install -D -m 0644 pam_authforge_pending.so $(DESTDIR)$(LIBDIR)/pam_authforge_pending.so clean: - rm -f pam_ubuntu_fido_pending.so + rm -f pam_authforge_pending.so .PHONY: install clean diff --git a/pam/pam_ubuntu_fido_pending.c b/pam/pam_authforge_pending.c similarity index 88% rename from pam/pam_ubuntu_fido_pending.c rename to pam/pam_authforge_pending.c index 054d3ed..ae2835e 100644 --- a/pam/pam_ubuntu_fido_pending.c +++ b/pam/pam_authforge_pending.c @@ -7,7 +7,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { (void)flags; (void)argc; (void)argv; - pam_syslog(pamh, LOG_INFO, "ubuntu_fido_pending: stub - allowing"); + pam_syslog(pamh, LOG_INFO, "authforge_pending: stub - allowing"); return PAM_IGNORE; /* implemented in Phase 6 */ }