Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/gunnar

crates/gunnar-front/src/lib.rs

//! # gunnar-front — vm1's one program, the FRONT medium's PID 1
//!
//! The estate is ALWAYS three VMs — vm1 the front, vm2 main, vm3 the twin —
//! and it has TWO media (owner 2026-09-25): main and twin boot the gunnar
//! medium, byte for byte the same; vm1 boots the FRONT medium,
//! `gunnar-front-installer-open`, whose payload is this binary. Like every
//! box, it reaches the installer over the installer's WireGuard link, is fed,
//! and then carries on by itself:
//!
//! * [`vm::FrontVm`] — the installer's view of this box: it presents kind
//!   **`front`**, keeps what it is fed in `<data>/pairing/joined.toml`, reports
//!   PAIRED once the fed reply lists every box of the estate, and OFFERS the
//!   front's public keys ([`vm::FrontVm::offer`]);
//! * [`role`] — the front's role from the fed reply, for the life of the
//!   process: the estate's WireGuard relay on udp/51820 keyed with this box's
//!   own tunnel key, and the twin's certification against the primary, signed
//!   with the certify key minted here ([`keys`]);
//! * [`forward`] — the forge's public door: tcp/2222 forwarded to the PRIMARY's
//!   utility address, following the fed verdict, re-targeted live;
//! * [`clock`] — the estate's root of time: this box keeps its own clock from
//!   the site's sources and serves signed time on its utility address;
//!   its key and address are offered, so the boxes are fed them.
//!
//! **What the installer feeds and what the front makes itself.** The installer
//! feeds only the operator key, the CA and the estate identity (the seed on
//! the medium + the reply). Everything the front OWNS it mints at first boot
//! and offers: the certify key (`certify_pubkey` → the primary's
//! `front-certify`), the clock key and peer (`clock_key`, `clock_peer` → every
//! box's clock), and the build it runs (`version`). The primary enrols the
//! principals itself (gunnar-server `fed_principals`).
//!
//! The console (gunnar-ui) is here (`console`; `metered` adds its paid half and
//! the operator's door). **No monetize** — not open, not metered, not on a sold
//! estate: the ONE monetize (monetize.ignalina.dk) holds every ledger, and the
//! estate's boxes call its Fleet door (owner 13:35Z 2026-10-10).

/// **A re-laid main filled from its twin by the front** (main rebuild, 2026-10-12) — see the module.
#[cfg(feature = "metered")]
pub mod autofill;
pub mod clock;
#[cfg(feature = "console")]
pub mod console;
pub mod downloads;
/// The egress door's gate (AIRGAP B2): built (`egress-door`) and switched on.
pub mod egress_door;
pub mod forward;
pub mod keys;
/// The operator's verbs on vm1's door: the forge's history for an off-site copy, the twin's health, a fed credential rotated in place.
#[cfg(feature = "metered")]
pub mod operator_door;
/// The front's PID 1 (`src/main.rs` runs it).
pub mod pid1;
/// vm1's mTLS door for the operator's kit (the paid front).
#[cfg(feature = "metered")]
pub mod plugin_door;
/// The front re-admits a sold estate's lost box itself (F4, 2026-10-09).
#[cfg(feature = "metered")]
pub mod recharge;
pub mod role;
/// The thin SoldEstate client (F4 under ONE monetize): the front CALLS the ONE
/// monetize in over monetize-proto and verifies its signature — no embedded
/// server, no self-registration.
#[cfg(feature = "metered")]
pub mod shop_door;
/// The front's clean stop: the power button heard (release-3 test2).
pub mod stop;
/// The update its shop opened, done by the front box by box (owner 2026-10-14).
pub mod update;
pub mod vm;
pub mod web;

/// The pairing files a fresh installation of the FRONT clears
/// (`installer_listener::reset_if_fresh_install_of`): what the installer fed,
/// the box's own certificate, the signal, the closed marker — the gunnar box's
/// list. **Every identity key the front mints is KEPT where its disk survives**
/// (a keep-upgrade, a recharge onto the same /data): the certify key and its
/// record, the console and guest keys, the clock key — as a gunnar box keeps `wg0.key`. A new key after a keep-upgrade
/// was refused by main (upgrade-front-certify-reminted); a front on a NEW disk
/// mints anew and main takes the fed keys (gunnar-server fed_principals
/// REPLACED_BY_OFFER).
pub const PAIRING_STATE: [&str; 5] = [
    gunnar_server::pairing::JOINED_REL,
    gunnar_server::pairing::OWN_CERT_REL,
    gunnar_server::pairing::OWN_KEY_REL,
    gunnar_server::pairing::SIGNAL_REL,
    gunnar_server::installer_listener::CLOSED_REL,
];

/// The interface the front's utility address is on — the second entry of the
/// medium's `korp.env.GUNNAR_NET=eth0:dhcp,eth1:dhcp`, the same `eth1` the
/// gunnar medium's control plane binds (`gunnar_recipe::PRIVATE_INTERFACE`).
pub const UTILITY_INTERFACE: &str = "eth1";

/// **The front proves the tunnel is the only path** (WireGuard-only).
pub mod mesh_probe;

/// **The primary's overlay address, by the verdict** (WireGuard-only, owner
/// 2026-10-04): the door's own `primary_overlay`, else the peer with role
/// primary. Every box-to-box connection the front makes goes here (or to a
/// peer's `overlay`), through the front's own tun on the relay — never to a
/// utility address, which a `--wg-only` box refuses.
pub fn primary_overlay(reply: &nordisk_pairing::join::JoinReply) -> Option<std::net::Ipv4Addr> {
    reply.primary_overlay.or_else(|| {
        reply
            .peers
            .iter()
            .find(|p| p.role == nordisk_pairing::Role::Primary)
            .map(|p| p.overlay)
    })
}

/// The twin's overlay address, when a twin is fed.
pub fn twin_overlay(reply: &nordisk_pairing::join::JoinReply) -> Option<std::net::Ipv4Addr> {
    reply
        .peers
        .iter()
        .find(|p| p.role == nordisk_pairing::Role::Twin)
        .map(|p| p.overlay)
}