Gunnar

nordisk/gunnar-ui

gunnar-ui

gunnar

The gunnar console: a passkey-guarded web UI (Leptos, WebAssembly) and its backend-for-frontend, which speaks sshsig-signed gRPC to a gunnar appliance.

Building

git clone ssh://git.gunnar.rs:2222/nordisk/gunnar-ui
cd gunnar-ui
cargo build --release -p gunnar-ui-server

The console itself is a WebAssembly bundle, built by trunk, which is required:

cd crates/gunnar-ui-web
trunk build --release

This page documents gunnar-ui 1.5.0 — the version gunnar-ui-server --version prints.

License: AGPL-3.0-only, © 2026 Vetra Automation AB and Ignalina ApS (Rickard Ernst Björn Lundin). Commercial terms: COMMERCIAL-LICENSING.md.

Routes

The console's pages, routed in the browser. A visitor has no session; signed in is any passkey session; admin is the role a session carries.

pagewho may open it
/reposvisitor
/repo/{namespace}/{name}visitor
/repo/{namespace}/{name}/files · /graph · /diff · /blame · /search · /chainvisitor
/repo/{namespace}/{name}/pulls · /pulls/{n} · /issues · /issues/{n}visitor
/signed in
/storage · /usage · /usage/{namespace} · /eventssigned in
/accountsigned in
/accesssigned in; every mutation on it is admin
/mirrors · /mirrors/importsigned in; every mutation on it is admin

The server's own routes, read off serve.rs. Everything under /api/ that is not listed as a visitor's is refused without a session; the role floor is decided by method and prefix in one place (auth::middleware::role_floor).

route groupwho may open it
/health · /login · /login/repos · /auth/status · /auth/logoutvisitor
/auth/passkey/login/* · /auth/passkey/register/*visitor
/welcome · /auth/signup/status (a metered build that sells)visitor
/signup — the ONE sign-up page: ?plan=private a new private Gunnar, ?plan=10gb an account here (or, signed in, growing it); /private redirects to it · /auth/private/ladder · /auth/private/{quote,start,status} · /auth/signup/{ladder,name,start,rename} (a metered build that sells)visitor; a signed-in buyer's order is theirs (the session's name, locked)
GET /api/reposvisitor
GET /api/repos/{namespace}/{name} and its refs · head · log · browse · diff · blame · search · object · chain leavesvisitor
every other GET/HEAD under /api/, including /api/eventssigned in
/api/account/keys — a person's own keyssigned in
every other mutation under /api/signed in, operator
/api/principals · /api/keys · /api/grants · /api/namespaces · /api/accounts · /api/forges · /api/mirrors, mutatingadmin
/api/namespaces/{name}/increase (a metered build holding a monetize bearer)signed in to read, admin to spend
/auth/passkey/invites · /auth/passkey/credentialssigned in, a fresh ceremony to mint or revoke; gunnar decides who may invite whom and whose passkeys a person may see
/auth/sessions/revoke-alladmin

Passkeys, invites and sessions live in gunnar

The console keeps no passkey, no invite and no key of anybody's. gunnar issues the WebAuthn challenge, verifies every login against the passkey it stores on the person's principal (Access.WebLogin), and enrols a short-lived session key the console minted for that login; everything the session does is signed with that key, as the person, and gunnar's grants decide. Logging out revokes the session key. Registration (Access.WebRegister) redeems an invite gunnar minted (Access.CreateInvite, asked as the person who invites), or is the operator's first passkey through the installer's break-glass token. A passkey this console registered before 2026-10-04 moves to gunnar when the console starts. The console's own store keeps cookie sessions, preferences and caches only.

Thanks

Sponsors

None so far — we would love to have one. Contact gunnar@gunnar.rs.

Files

.cargo/
.github/
.nornir/
LICENSES/
browser/
crates/
deploy/
docs/
proto/
uitest/
xtask/
.gitignore
COMMERCIAL-LICENSING.md
Cargo.lock
Cargo.toml
LICENSE
NOTICE
README.md
THIRD_PARTY_LICENSES.md
TRADEMARKS.md
deny.toml
rust-toolchain.toml

Newest commits

266f41242c11Merge ox-postpub/follow-2026-10-29 into main (lane OX-POSTPUB): the lock follows the siblings (monetize-proto 0.3.3, nornir-xtask-support 0.1.6). Gate on the merged tree (ci4, dwarf): lockcheck green (2 locks), cargo test --workspace --locked 1126/02026-10-29
0d5a83763802lock follows the siblings: monetize-proto 0.3.3, nornir-xtask-support 0.1.6 (lockfollow) (lane OX-POSTPUB)2026-10-29
32609f007c14Merge ghunt19/attested-forge into main (lane GHUNT19): a person approves a pull request in the browser again — the console sends it from her own session, unsigned, and gunnar attests it after a fresh passkey touch2026-10-28
815408123a3bMerge remote-tracking branch 'origin/main' into ghunt19/attested-forge2026-10-28
27bec9732f8dGREEN GHUNT-19: the console sends a person's forge event from her session for gunnar to attest2026-10-28