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

nordisk/gunnar

crates/gunnar-server/src/fed_principals.rs

//! **The principals the installer FEEDS, installed by the primary itself**
//! (edda nordisk-pairing 0.3, 2026-09-25).
//!
//! Until 2026-09-24 the laptop's xtask enrolled the estate's principals over
//! ssh on the front, one `gunnar control user add` per principal, signed with
//! the console key (`private-gunnar-ops` `rebuild.rs` `principal_commands`):
//! the operator (human, gunnar-admin), `monetize` (machine, gunnar-admin) and
//! `gunnar-guest` (machine, NO grant). The installer does the whole install
//! now, so it FEEDS them and the elected primary installs them, the same way
//! it installs the fed `admin_pubkey` ([`crate::pairing::FEED_ADMIN`]) — right
//! after it, because the first identity closes the enrolment window and a
//! table with principals but no admin could never take one.
//!
//! # The feed keys
//!
//! One key per principal, `principal.<id>`, one line:
//!
//! ```text
//! principal.rickard      = "user admin ssh-ed25519 AAAA… rickard@t14s"
//! principal.monetize     = "machine admin ssh-ed25519 AAAA… monetize"
//! principal.gunnar-guest = "machine none ssh-ed25519 AAAA… guest"
//! ```
//!
//! `<kind>` is `user`, `machine` or `deploy`; `<role>` is `admin` (the
//! server-wide gunnar-admin grant) or `none` (no grant at all). The id is the
//! display name too, as `user add <name>` made it. Every step is idempotent:
//! a principal that exists keeps what it has, a key already registered is
//! not registered again, and the admin grant is an upsert — so the loop may
//! run this on every turn until it has taken.

use crate::control_plane::CoreControlPlane;
use crate::stores::ServerStores;
use gunnar_grpc::ControlPlane;
use std::collections::BTreeMap;
use std::sync::Arc;

/// The prefix of a fed principal's key: `principal.<id>`.
pub const FEED_PRINCIPAL_PREFIX: &str = "principal.";

/// What a fed principal is.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FedPrincipal {
    pub id: String,
    pub kind: gunnar_proto::PrincipalKind,
    /// The server-wide gunnar-admin grant.
    pub admin: bool,
    /// **Narrowed to monetize's methods** (role `billing`, f-principal-reach):
    /// no grant at all, and exactly [`gunnar_grpc::BILLING_METHODS`].
    pub narrowed: bool,
    /// The OpenSSH public key line.
    pub key: String,
    /// READ on this namespace (a restore identity), else no namespace grant.
    pub read: Option<String>,
    /// **The offered key REPLACES the one held** ([`REPLACED_BY_OFFER`]): a key
    /// the front mints itself, which a front laid again mints anew.
    pub replaces: bool,
}

/// **The front's principals whose key a front laid again mints ANEW**
/// (estate-box3 life1, R2 after U3: row recharge-twin-certify-stale): the
/// certify key (a fresh installation clears `pairing/certify.key`), the
/// console's and the guest's keys (a front laid on a new /data). The
/// installer's feed — over its own mutual TLS, the operator's word — is the
/// authority for them: the offered key replaces the one held, and the dead
/// front's key stops authenticating. NOT monetize: its identity is restored
/// from its backup, never re-minted, and a second key on it still needs its
/// own attestation (c-dead-front's restore identity is the other way in).
pub const REPLACED_BY_OFFER: [&str; 3] = [
    "gunnar-ui",
    "gunnar-guest",
    gunnar_pairing_door::front::CERTIFY_PRINCIPAL,
];

/// **The principals a VM OFFERS** (nordisk-pairing 0.4): the front's keys
/// are minted on vm1 (the FRONT medium, `gunnar-front`) and reach
/// the primary only as vm1's offer, fed onward as `offer.<vm>.<key>`; the
/// installer feeds only the operator as admin. The primary enrols each of
/// these itself — `(offer key, principal id, "<kind> <role>")`:
pub const OFFERED_PRINCIPALS: [(&str, &str, &str); 4] = [
    // the console on the front (gunnar-front, `console`): it signs gunnar
    // calls for logged-in people, so it is a gunnar-admin — the key the old
    // front OS fed as `admin_pubkey`, which is now the operator's.
    (OFFER_CONSOLE_PUBKEY, "gunnar-ui", "machine admin"),
    // monetize's identity on the front: gunnar-admin, as `rebuild.rs
    // principal_commands` enrolled it over ssh.
    (OFFER_MONETIZE_IDENTITY, "monetize", "machine admin"),
    // the console's guest key: NO grant at all.
    (OFFER_GUEST_PUBKEY, "gunnar-guest", "machine none"),
    // the front's certify key (`gunnar-front`, on vm1): the twin's enrolment
    // and certificate are signed with it.
    (
        gunnar_pairing_door::front::OFFER_CERTIFY_PUBKEY,
        gunnar_pairing_door::front::CERTIFY_PRINCIPAL,
        "machine admin",
    ),
];

/// The offer key of a laid-again front's RESTORE identity (c-dead-front).
pub const OFFER_RESTORE_IDENTITY: &str = "restore_identity";
/// The namespace monetize's backup lives in (`monetize/state-backup`).
pub const RESTORE_NAMESPACE: &str = "monetize";

/// The offer key of monetize's identity (its OpenSSH public key line).
pub const OFFER_MONETIZE_IDENTITY: &str = "monetize_identity";
/// The offer key of the console's guest key (an OpenSSH public key line).
pub const OFFER_GUEST_PUBKEY: &str = "guest_pubkey";
/// The offer key of the console's own key (an OpenSSH public key line).
pub const OFFER_CONSOLE_PUBKEY: &str = "console_pubkey";

/// The offered principals of a feed as `principal.<id>` lines. A principal
/// the installer fed by name (`principal.<id>`) is not taken again from an
/// offer: the plain key wins.
pub fn offered_principals(feed: &BTreeMap<String, String>) -> Vec<(String, String)> {
    OFFERED_PRINCIPALS
        .iter()
        .filter(|(_, id, _)| !feed.contains_key(&format!("{FEED_PRINCIPAL_PREFIX}{id}")))
        .filter_map(|(offer, id, how)| {
            nordisk_pairing::feedbus::offered(feed, offer).map(|key| {
                (
                    format!("{FEED_PRINCIPAL_PREFIX}{id}"),
                    format!("{how} {key}"),
                )
            })
        })
        .collect()
}

/// The roles a fed principal line may name (`<kind> <role> <key>`). The paid
/// build adds `billing` (f-principal-reach); the open build names no such role.
#[cfg(feature = "metered")]
const ROLES: &str = "admin|none|billing|repair";
#[cfg(not(feature = "metered"))]
const ROLES: &str = "admin|none|repair";

/// Every `principal.<id>` in a feed, parsed. A malformed one is refused by
/// name — a feed that lies about a credential must not be half-applied.
pub fn parse(feed: &BTreeMap<String, String>) -> Result<Vec<FedPrincipal>, String> {
    let mut out = Vec::new();
    for (k, v, offered) in feed
        .iter()
        .map(|(k, v)| (k.clone(), v.clone(), false))
        .chain(
            offered_principals(feed)
                .into_iter()
                .map(|(k, v)| (k, v, true)),
        )
    {
        let (k, v) = (k.as_str(), v.as_str());
        let Some(id) = k.strip_prefix(FEED_PRINCIPAL_PREFIX) else {
            continue;
        };
        let bad = |why: &str| {
            Err(format!("REFUSED [fed-principal] `{k}`: {why} — the line is `<user|machine|deploy> <{ROLES}> <openssh public key>`"))
        };
        if id.is_empty() || id.contains('.') || id.contains('/') {
            return bad("the id is empty or not a plain name");
        }
        let mut parts = v.trim().splitn(3, ' ');
        let (Some(kind), Some(role), Some(key)) = (parts.next(), parts.next(), parts.next()) else {
            return bad("fewer than three fields");
        };
        let kind = match kind {
            "user" => gunnar_proto::PrincipalKind::User,
            "machine" => gunnar_proto::PrincipalKind::Machine,
            "deploy" => gunnar_proto::PrincipalKind::Deploy,
            _ => return bad("the kind is not user, machine or deploy"),
        };
        let (admin, narrowed) = match role {
            "admin" => (true, false),
            "none" => (false, false),
            // A CENTRAL monetize serving this estate from elsewhere: its
            // plugin's methods and nothing else (f-principal-reach). The paid
            // build's word only: an open build takes no such principal.
            #[cfg(feature = "metered")]
            "billing" => (false, true),
            // ★ Main rebuild (2026-10-12): the estate's repair key — no grant, narrowed by
            // its name to `gunnar_grpc::REPAIR_METHODS`, and a restore key ([`restore_keys`]).
            // Only under the reserved id: a `repair` role on any other name is refused.
            "repair" if id == gunnar_grpc::REPAIR_PRINCIPAL => (false, false),
            "repair" => {
                return bad(&format!(
                    "the repair role is the principal `{}`'s alone",
                    gunnar_grpc::REPAIR_PRINCIPAL
                ))
            }
            _ => return bad(&format!("the role is not one of {ROLES}")),
        };
        if gunnar_core::auth::parse_public_key(key.trim()).is_err() {
            return bad("the key is not an OpenSSH public key line");
        }
        let replaces = offered && REPLACED_BY_OFFER.contains(&id);
        out.push(FedPrincipal {
            id: id.to_string(),
            kind,
            admin,
            narrowed,
            key: key.trim().to_string(),
            read: None,
            replaces,
        });
    }
    // A laid-again front's RESTORE identity: a principal of its own, named by
    // its key (no attestation owed to anybody), READ on the backup namespace.
    if let Some(key) = nordisk_pairing::feedbus::offered(feed, OFFER_RESTORE_IDENTITY) {
        let parsed = gunnar_core::auth::parse_public_key(key.trim()).map_err(|_| format!("REFUSED [fed-principal] `{OFFER_RESTORE_IDENTITY}`: the key is not an OpenSSH public key line"))?;
        let fp = gunnar_core::Fingerprint::of_key(&parsed);
        let tag: String = fp
            .as_str()
            .trim_start_matches("SHA256:")
            .chars()
            .filter(|c| c.is_ascii_alphanumeric())
            .take(12)
            .collect::<String>()
            .to_ascii_lowercase();
        out.push(FedPrincipal {
            id: format!("monetize-restore-{tag}"),
            kind: gunnar_proto::PrincipalKind::Machine,
            admin: false,
            narrowed: false,
            key: key.trim().to_string(),
            read: Some(RESTORE_NAMESPACE.to_string()),
            replaces: false,
        });
    }
    Ok(out)
}

/// **The feed key the estate's OPERATOR is named under** (2026-10-04): the
/// estate's `[operator] name` (an instance's own `operator`), fed by the
/// installer. The primary claims that account itself on every feed
/// ([`install`]) and `Accounts.ClaimOperator` answers it — the account the
/// first admin's passkey binds to. One plain name; blank is absent.
pub const FEED_OPERATOR: &str = "operator_name";

/// The operator's name in a feed, if the installer named one.
pub fn operator_of(feed: &BTreeMap<String, String>) -> Option<String> {
    feed.get(FEED_OPERATOR)
        .map(|v| v.trim().to_owned())
        .filter(|v| !v.is_empty())
}

/// **The offer key of the console's credential for the estate's OPERATOR**
/// (2026-10-04): an OpenSSH public key line the front (`gunnar-front`,
/// `console/operator`) mints at its first boot and keeps, its private half laid
/// as the console's tenant seed for the operator (`console/seeds/<operator>`).
/// The installer relays it as `offer.<front>.operator_console_pubkey`, and the
/// primary enrols it on the operator's account when it claims it ([`install`])
/// — so the console's credential for the owner exists FROM THE INSTALL, is the
/// account's first key (no attestation owed: the account held none), and the
/// owner's first passkey finds it held: no `awaiting_attestation`, no operator
/// step.
pub const OFFER_OPERATOR_CONSOLE_PUBKEY: &str = "operator_console_pubkey";

/// **The comment the front's operator credential carries** (its OpenSSH line's
/// third field). It is how the credential a front laid BEFORE held is told
/// apart from the keys the owner added himself: a front laid again offers a
/// new one, and only a key carrying this mark is replaced by it.
pub const OPERATOR_CONSOLE_COMMENT: &str = "gunnar-ui-operator";

/// **The feed key of the operator's first invite** (Stage L, 2026-10-04): the
/// lowercase hex SHA-256 of the break-glass token the installer hands the
/// owner (and feeds vm1's console as `console_admin_token`) — the hash, never
/// the token. The primary records it as the invite for the operator's first
/// passkey (`gunnar_grpc::seam::OPERATOR_INVITE_ID`) when it claims him, so
/// the console's first-admin registration is `Access.WebRegister` with the
/// token as its invite secret, and gunnar decides it.
pub const FEED_OPERATOR_INVITE: &str = "operator_invite_sha256";

/// **The feed key of the first invite's lifetime, in seconds** (2026-10-07,
/// private ownership): a SOLD estate's first invite is the buyer's
/// first-login link, mailed to him by the seller — single use, and short
/// lived. Absent: the invite lives [`gunnar_grpc::seam::OPERATOR_INVITE_TTL_MS`]
/// (the kit's own estates, whose break-glass token is the invite). At least a
/// minute, at most that.
pub const FEED_OPERATOR_INVITE_TTL: &str = "operator_invite_ttl_secs";

/// **The first invite's lifetime, as fed** ([`FEED_OPERATOR_INVITE_TTL`]),
/// milliseconds; absent: [`gunnar_grpc::seam::OPERATOR_INVITE_TTL_MS`]. A
/// value that is no number of seconds, or outside a minute to the most an
/// invite lives, is refused by name.
pub fn invite_ttl_ms(feed: &BTreeMap<String, String>) -> Result<i64, String> {
    let Some(raw) = feed
        .get(FEED_OPERATOR_INVITE_TTL)
        .map(|v| v.trim())
        .filter(|v| !v.is_empty())
    else {
        return Ok(gunnar_grpc::seam::OPERATOR_INVITE_TTL_MS);
    };
    let secs: i64 = raw
        .parse()
        .map_err(|_| format!("`{FEED_OPERATOR_INVITE_TTL}` is {raw:?}, not a number of seconds"))?;
    gunnar_grpc::seam::bootstrap_ttl(secs.saturating_mul(1000))
        .map_err(|e| format!("`{FEED_OPERATOR_INVITE_TTL}` = {raw}: {e}"))
}

/// **The feed key of the buyer's WELCOME** (no-dwarf step 7, the owner 2026-10-08): a sold
/// estate is handed over with ONE repository, `<account>/welcome`, whose README thanks the
/// buyer and says how to start. The shop feeds the README's text; the primary makes the
/// repository and its first commit itself when it claims the account ([`install`]) — no git
/// client anywhere in the sale. Once: a buyer who deletes it is not given it again.
pub const FEED_OPERATOR_WELCOME: &str = "operator_welcome_readme";

/// The welcome repository's name in the buyer's account.
pub const WELCOME_REPO: &str = "welcome";

/// Under the data root: the welcome was made (or the account held repositories already).
pub const WELCOME_MADE_REL: &str = "pairing/welcome.made";

/// **The buyer's welcome repository**, at most once: `<account>/welcome`, private, its first
/// commit the fed README. Not made into an account that already holds a repository, nor
/// twice. The line said, or `None` when it was made before.
fn welcome(
    plane: &CoreControlPlane,
    stores: &Arc<ServerStores>,
    account: &str,
    readme: &str,
) -> Result<Option<String>, String> {
    let made = stores.root().join(WELCOME_MADE_REL);
    if made.exists() {
        return Ok(None);
    }
    let fail =
        |what: &str, e: String| format!("the welcome repository of `{account}`: {what}: {e}");
    let held = plane
        .list_repos(Some(account))
        .map_err(|e| fail("listing the account's repositories", e.to_string()))?;
    let said = if held.is_empty() {
        let path = gunnar_proto::RepoPath::new(account, WELCOME_REPO);
        plane
            .create_repo(gunnar_grpc::NewRepo {
                path: path.clone(),
                hash_kind: gunnar_proto::HashKind::Sha256,
                default_branch: String::new(),
                visibility: gunnar_proto::Visibility::Private,
                description: "Welcome to your own Gunnar".to_owned(),
                adopt: false,
            })
            .map_err(|e| fail("creating it", e.to_string()))?;
        let commit = plane
            .write_first_commit(&path, readme)
            .map_err(|e| fail("its README", e.to_string()))?;
        tracing::info!(target: "gunnar::audit", event = "operator.welcome_repository", account, commit = %commit, "the operator's welcome repository is made: {account}/{WELCOME_REPO}, its README the installer's thanks");
        format!("operator {account}: the welcome repository {account}/{WELCOME_REPO} made, its README the installer's thanks (commit {})", &commit[..commit.len().min(12)])
    } else {
        format!(
            "operator {account}: holds {} repositor(ies) already — no welcome repository",
            held.len()
        )
    };
    if let Some(d) = made.parent() {
        std::fs::create_dir_all(d).map_err(|e| fail("its mark", e.to_string()))?;
    }
    std::fs::write(&made, b"made\n").map_err(|e| fail("its mark", e.to_string()))?;
    Ok(Some(said))
}

/// **The operator's name the installer fed last** — the persisted join reply,
/// `<data>/pairing/joined.toml`. `None` when nothing was fed, or the reply
/// cannot be read (that is logged by `fed_at_rest`): the claim then falls back
/// to the name it was asked for, and never invents one.
pub fn fed_operator(root: &std::path::Path) -> Option<String> {
    let text = crate::fed_at_rest::read(root, crate::pairing::JOINED_REL)?;
    let reply = nordisk_pairing::join::JoinReply::parse(&text).ok()?;
    operator_of(&reply.feed)
}

/// **Install every fed principal** on this (primary) box, after its admin.
/// Returns one line per principal saying what was done; `Err` names the
/// first that could not be installed (the loop asks again).
///
/// And **the estate's operator** when the feed names one ([`FEED_OPERATOR`]):
/// claimed here, at install, so the operator's account exists — gunnar-admin,
/// its namespace reserved — before anything can push into a namespace of that
/// name, and the first admin passkey the console registers binds to it
/// (`Accounts.ClaimOperator`). When the front offered the console's credential
/// for it ([`OFFER_OPERATOR_CONSOLE_PUBKEY`]) that key is enrolled here too, as
/// the account's first key ([`operator_console`]).
pub fn install(
    stores: &Arc<ServerStores>,
    feed: &BTreeMap<String, String>,
) -> Result<Vec<String>, String> {
    let attach = keep_attach_ca(stores.root(), feed)?;
    let mut wanted = parse(feed)?;
    let operator = operator_of(feed);
    if wanted.is_empty() && operator.is_none() {
        return Ok(attach.into_iter().collect());
    }
    // The keys a peer is WAITING on first ([`enrol_order`]).
    wanted.sort_by_key(|p| enrol_order(&p.id));
    note_fed(stores, feed);
    let plane = CoreControlPlane::new(Arc::clone(stores));
    let mut said = Vec::new();
    // **One refusal holds back no other principal** (R3: a front laid again offers a
    // fresh monetize identity until its backup is restored; `monetize` comes before
    // `gunnar-guest`, which must not wait for it). Every principal is tried; the
    // refusals are answered together, and the loop asks again.
    let mut refused = Vec::new();
    for p in &wanted {
        match install_one(&plane, stores, p) {
            Ok(line) => said.push(line),
            Err(e) => refused.push(e),
        }
    }
    // What is enrolled now is no longer awaited; what was refused is not "being enrolled".
    note_fed(stores, feed);
    if let Some(name) = &operator {
        match plane.claim_operator_named(Some(name), "") {
            Ok(claim) => {
                said.push(format!(
                    "operator {}: {}",
                    claim.principal.id,
                    match (claim.created, claim.adopted_namespace) {
                        (true, true) => "created (keyless, gunnar-admin), its account namespace ADOPTED — it existed with no owner",
                        (true, false) => "created (keyless, gunnar-admin) with its account namespace",
                        (false, _) => "already there",
                    }
                ));
                if let Some(offered) =
                    nordisk_pairing::feedbus::offered(feed, OFFER_OPERATOR_CONSOLE_PUBKEY)
                {
                    match operator_console(&plane, stores, &claim.principal.id, &offered) {
                        Ok(line) => said.push(line),
                        Err(e) => refused.push(e),
                    }
                }
                if let Some(text) = feed
                    .get(FEED_OPERATOR_WELCOME)
                    .map(|t| t.trim())
                    .filter(|t| !t.is_empty())
                {
                    match welcome(&plane, stores, &claim.principal.id, text) {
                        Ok(Some(line)) => said.push(line),
                        Ok(None) => {}
                        Err(e) => refused.push(e),
                    }
                }
                if let Some(hash) = feed
                    .get(FEED_OPERATOR_INVITE)
                    .map(|h| h.trim())
                    .filter(|h| !h.is_empty())
                {
                    let invite = invite_ttl_ms(feed).and_then(|ttl| {
                        gunnar_grpc::seam::bootstrap_hash(hash)
                            .and_then(|hash| {
                                plane.operator_bootstrap_invite(
                                    &claim.principal.id,
                                    &hash,
                                    gunnar_core::now_ms(),
                                    ttl,
                                )
                            })
                            .map_err(|e| e.to_string())
                    });
                    match invite {
                        Ok(gunnar_grpc::BootstrapInvite::Spent) => said.push(format!(
                            "operator {}: holds a passkey — the installer's first invite is spent",
                            claim.principal.id
                        )),
                        Ok(done) => said.push(format!(
                            "operator {}: the first invite (the break-glass token's hash) {} — the first passkey registers on this account",
                            claim.principal.id,
                            if done == gunnar_grpc::BootstrapInvite::Recorded { "recorded" } else { "renewed" }
                        )),
                        Err(e) => refused.push(format!("the operator `{}`'s first invite: {e}", claim.principal.id)),
                    }
                }
            }
            Err(e) => refused.push(format!("the operator `{name}`: {e}")),
        }
    }
    if !refused.is_empty() {
        return Err(refused.join("; "));
    }
    said.extend(attach);
    Ok(said)
}

/// **The order fed principals are enrolled in: the keys a peer is WAITING on
/// first** (cov-E r3 2026-10-06, run 3). The front's twin certification
/// calls with its certify key from the moment it is fed the election; the
/// console signs every logged-in person's call; monetize's backup push
/// follows. Enrolled in feed order the certify key came SIXTH (the
/// installer's own principals, then the console, monetize and the guest), and
/// on a starved primary — 4 m 47 s for the whole feed — the twin's
/// certification was refused for five minutes and the install failed its log
/// gate. Each one is a few writes; first in line, the certify key is in after
/// the first of them.
pub fn enrol_order(id: &str) -> u8 {
    match id {
        gunnar_pairing_door::front::CERTIFY_PRINCIPAL => 0,
        "gunnar-ui" => 1,
        "monetize" => 2,
        _ => 3,
    }
}

/// **Say which fed keys this primary will enrol and has not yet** — what the
/// gRPC gate answers `Unavailable [key-enrolling]` (ask again) rather than
/// `Unauthenticated` (`gunnar_grpc::Identity::awaiting_enrolment`). A key
/// counts only when [`install`] WILL take it: its principal holds no key yet,
/// or the offered key replaces the one it holds ([`REPLACED_BY_OFFER`]). A
/// second key that owes an attestation (monetize's fresh identity before its
/// restore) is refused, not enrolled, and is answered as before. The whole set
/// is replaced each time — called when a feed lands and around every install
/// pass — so a key enrolled since, or revoked after, is never "awaited".
pub fn note_fed(stores: &ServerStores, feed: &BTreeMap<String, String>) {
    let Ok(wanted) = parse(feed) else {
        stores.await_enrolment(BTreeMap::new());
        return;
    };
    let auth = stores.auth();
    let mut awaited = BTreeMap::new();
    for p in &wanted {
        let Ok(parsed) = gunnar_core::auth::parse_public_key(&p.key) else {
            continue;
        };
        let fingerprint = gunnar_core::Fingerprint::of_key(&parsed);
        let Ok(held) = auth.keys_of(&p.id) else {
            continue;
        };
        if held
            .iter()
            .any(|k| k.fingerprint_sha256 == fingerprint.as_str())
        {
            continue;
        }
        if held.is_empty() || p.replaces {
            awaited.insert(fingerprint.as_str().to_string(), p.key.clone());
        }
    }
    stores.await_enrolment(awaited);
}

/// ★ **The console's credential for the operator, enrolled at install** — the
/// front's offer ([`OFFER_OPERATOR_CONSOLE_PUBKEY`]) on the account [`install`]
/// just claimed. The line said, or the refusal.
///
/// * already one of the account's keys: nothing to do;
/// * a key carrying [`OPERATOR_CONSOLE_COMMENT`] that is NOT the offered one is
///   the credential a front laid before held — its private half went with that
///   front's disk — and is revoked;
/// * then, if the account holds no other key, the offered one is enrolled: its
///   FIRST key, so no attestation is owed to anybody ("the target holds no key
///   able to sign → nobody to ask", `key_attestation::Requirement::of`);
/// * if it holds keys of the owner's own, it is NOT enrolled over his head:
///   gunnar's rule stands, the console asks for his word
///   (`awaiting_attestation`) as before. Said, not refused — a refusal would
///   make the pairing loop ask again for ever.
fn operator_console(
    plane: &CoreControlPlane,
    stores: &Arc<ServerStores>,
    operator: &str,
    offered: &str,
) -> Result<String, String> {
    let fail = |what: &str, e: String| {
        format!("the console's credential for the operator `{operator}`: {what}: {e}")
    };
    let parsed = gunnar_core::auth::parse_public_key(offered)
        .map_err(|e| fail("the offered key", format!("{e:#}")))?;
    let fingerprint = gunnar_core::Fingerprint::of_key(&parsed);
    let held = stores
        .auth()
        .keys_of(operator)
        .map_err(|e| fail("reading its keys", format!("{e:#}")))?;
    if held
        .iter()
        .any(|k| k.fingerprint_sha256 == fingerprint.as_str())
    {
        return Ok(format!(
            "operator {operator}: the console's credential ({}): already its key",
            fingerprint.as_str()
        ));
    }
    let mut did = Vec::new();
    let stale: Vec<&gunnar_core::PublicKey> = held
        .iter()
        .filter(|k| is_console_credential(&k.openssh))
        .collect();
    for k in &stale {
        plane.revoke_key(&k.fingerprint_sha256).map_err(|e| {
            fail(
                "revoking the credential a front laid before held",
                e.to_string(),
            )
        })?;
    }
    if !stale.is_empty() {
        tracing::info!(operator, replaced = stale.len(), new = %fingerprint.as_str(), "fed principals: the front was laid again — the console's credential for the operator it held before is revoked");
        did.push(format!(
            "replaced the credential a front laid before held ({})",
            stale
                .iter()
                .map(|k| k.fingerprint_sha256.as_str())
                .collect::<Vec<_>>()
                .join(", ")
        ));
    }
    let own = held.len() - stale.len();
    if own > 0 {
        tracing::warn!(
            target: "gunnar::audit",
            event = "operator.console_credential_waits",
            operator,
            fingerprint = %fingerprint.as_str(),
            own,
            "the console's credential for the operator is NOT enrolled at install: the account holds keys of the owner's own, so the console asks for his word"
        );
        did.push(format!("NOT enrolled — the account holds {own} key(s) of his own, so it takes his word (the console asks for it)"));
        return Ok(format!(
            "operator {operator}: the console's credential ({}): {}",
            fingerprint.as_str(),
            did.join(", ")
        ));
    }
    plane
        .add_key(
            operator,
            offered,
            "the console's credential for the operator, offered by the front",
            None,
            gunnar_core::BOOTSTRAP_ADMIN_ID,
            None,
        )
        .map_err(|e| fail("registering it", e.to_string()))?;
    tracing::warn!(
        target: "gunnar::audit",
        event = "operator.console_credential_enrolled",
        operator,
        fingerprint = %fingerprint.as_str(),
        "the console's credential for the operator is enrolled at install as the account's first key: the owner's first passkey finds it held"
    );
    did.push("enrolled as its first key (no attestation owed: it held none)".into());
    Ok(format!(
        "operator {operator}: the console's credential ({}): {}",
        fingerprint.as_str(),
        did.join(", ")
    ))
}

/// A key line that carries the front's mark ([`OPERATOR_CONSOLE_COMMENT`]).
fn is_console_credential(openssh: &str) -> bool {
    openssh.split_whitespace().nth(2) == Some(OPERATOR_CONSOLE_COMMENT)
}

/// One fed principal, as [`install`] takes it: the line said, or the refusal.
fn install_one(
    plane: &CoreControlPlane,
    stores: &Arc<ServerStores>,
    p: &FedPrincipal,
) -> Result<String, String> {
    let auth = stores.auth();
    {
        let fail = |what: &str, e: String| format!("the fed principal `{}`: {what}: {e}", p.id);
        let read_on: String;
        let mut did = Vec::new();
        if auth
            .principal(&p.id)
            .map_err(|e| fail("reading it", format!("{e:#}")))?
            .is_none()
        {
            plane
                .add_principal(&p.id, &p.id, p.kind)
                .map_err(|e| fail("creating it", e.to_string()))?;
            did.push("created");
        }
        let parsed = gunnar_core::auth::parse_public_key(&p.key)
            .map_err(|e| fail("its key", format!("{e:#}")))?;
        let fingerprint = gunnar_core::Fingerprint::of_key(&parsed);
        // **The key LAST** (release-3 test2: `Access.AddPrincipal principal=front-certify
        // decision="deny" reason="no grant"`): a key registered before its grant is a
        // credential that authenticates and is refused — the front's certify thread called in
        // that window. Grants, reads and narrowing first; a grant on a principal nobody can
        // yet sign as is inert.
        if p.admin {
            plane
                .grant(&p.id, "", "", gunnar_proto::GrantLevel::Admin)
                .map_err(|e| fail("the gunnar-admin grant", e.to_string()))?;
            did.push("gunnar-admin");
        }
        if let Some(ns) = &p.read {
            plane
                .grant(&p.id, ns, "", gunnar_proto::GrantLevel::Read)
                .map_err(|e| fail("the read grant", e.to_string()))?;
            read_on = format!("read on {ns}");
            did.push(&read_on);
        }
        #[cfg(feature = "metered")]
        if p.narrowed
            && narrowed_of(stores.root(), &p.id)
                .map_err(|e| fail("reading its narrowing", e))?
                .is_none()
        {
            write_narrowed(stores.root(), &p.id, gunnar_grpc::BILLING_METHODS)
                .map_err(|e| fail("narrowing it", e))?;
            did.push("narrowed to billing");
        }
        let held = auth
            .keys_of(&p.id)
            .map_err(|e| fail("reading its keys", format!("{e:#}")))?;
        if !held
            .iter()
            .any(|k| k.fingerprint_sha256 == fingerprint.as_str())
        {
            if p.replaces && !held.is_empty() {
                // The front was laid again: its new key replaces the dead front's. Revoked
                // first, so the add owes nobody an attestation, and the old key is gone.
                for k in &held {
                    plane.revoke_key(&k.fingerprint_sha256).map_err(|e| {
                        fail("revoking the key the front laid before held", e.to_string())
                    })?;
                }
                tracing::info!(principal = %p.id, replaced = held.len(), new = %fingerprint.as_str(), "fed principals: the front was laid again — its offered key replaces the one it held before");
                did.push("replaced the key the front laid before held");
            }
            plane
                .add_key(
                    &p.id,
                    &p.key,
                    "fed by the installer",
                    None,
                    gunnar_core::BOOTSTRAP_ADMIN_ID,
                    None,
                )
                .map_err(|e| fail("registering its key", e.to_string()))?;
            did.push("key registered");
        }
        Ok(format!(
            "{} ({}): {}",
            p.id,
            fingerprint.as_str(),
            if did.is_empty() {
                "already there".to_string()
            } else {
                did.join(", ")
            }
        ))
    }
}

/// Under the data root: the CENTRAL monetize's attach CA (f-grpc-tls), fed as
/// `attach.ca` to an estate that attached from another cloud.
pub const ATTACH_CA_REL: &str = "attach/ca.pem";
/// The feed key it arrives under.
pub const FEED_ATTACH_CA: &str = "attach.ca";

/// **Keep the fed attach CA** where the gRPC listener reads it; `Ok(None)` when
/// the feed carries none. A value that is not a PEM certificate is refused by
/// name and nothing is written.
pub fn keep_attach_ca(
    root: &std::path::Path,
    feed: &BTreeMap<String, String>,
) -> Result<Option<String>, String> {
    let Some(pem) = feed
        .get(FEED_ATTACH_CA)
        .map(|v| v.trim())
        .filter(|v| !v.is_empty())
    else {
        return Ok(None);
    };
    if !pem.starts_with("-----BEGIN CERTIFICATE-----") {
        return Err(format!(
            "REFUSED [fed-attach-ca] `{FEED_ATTACH_CA}` is not a PEM certificate"
        ));
    }
    let path = root.join(ATTACH_CA_REL);
    if std::fs::read_to_string(&path)
        .map(|t| t.trim() == pem)
        .unwrap_or(false)
    {
        return Ok(Some("the attach CA: already kept".into()));
    }
    let dir = path.parent().expect("a parent");
    std::fs::create_dir_all(dir).map_err(|e| format!("{}: {e}", dir.display()))?;
    let tmp = path.with_extension("staging");
    std::fs::write(&tmp, format!("{pem}\n")).map_err(|e| format!("{}: {e}", tmp.display()))?;
    std::fs::rename(&tmp, &path).map_err(|e| format!("{}: {e}", path.display()))?;
    Ok(Some("the attach CA kept: the central monetize's client identity is trusted at the next start of the gRPC listener".into()))
}

/// **The client CAs the gRPC listener pins**: this box's own issuer, and the
/// central monetize's attach CA when one was fed (f-grpc-tls).
pub fn grpc_client_cas(issuer_pem: &str, root: &std::path::Path) -> String {
    match std::fs::read_to_string(root.join(ATTACH_CA_REL)) {
        Ok(extra) if extra.contains("-----BEGIN CERTIFICATE-----") => format!(
            "{}{}{extra}",
            issuer_pem,
            if issuer_pem.ends_with('\n') { "" } else { "\n" }
        ),
        _ => issuer_pem.to_string(),
    }
}

/// Under the data root: one file per NARROWED principal, its methods one per
/// line (f-principal-reach) — what `CoreControlPlane::narrowed_methods` reads.
pub const NARROWED_REL: &str = "narrowed";

fn narrowed_path(root: &std::path::Path, id: &str) -> Result<std::path::PathBuf, String> {
    // A dot inside is a plain id too (`john.doe`, an SSO employee
    // `acme.bob`): refusing it made EVERY call such a principal signed fail
    // here, as "the identity table could not be read". No leading dot and no
    // `..`, so the name never leaves the directory.
    if id.is_empty()
        || id.starts_with('.')
        || id.contains("..")
        || !id
            .chars()
            .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '.')
    {
        return Err(format!("`{id}` is not a plain principal id"));
    }
    Ok(root.join(NARROWED_REL).join(id))
}

/// **Narrow `id` to `methods`**, written whole (staged, renamed), 0600.
pub fn write_narrowed(root: &std::path::Path, id: &str, methods: &[&str]) -> Result<(), String> {
    let path = narrowed_path(root, id)?;
    let dir = path.parent().expect("a parent");
    std::fs::create_dir_all(dir).map_err(|e| format!("{}: {e}", dir.display()))?;
    let tmp = path.with_extension("staging");
    std::fs::write(&tmp, methods.join("\n") + "\n")
        .map_err(|e| format!("{}: {e}", tmp.display()))?;
    {
        use std::os::unix::fs::PermissionsExt as _;
        let _ = std::fs::set_permissions(&tmp, std::fs::Permissions::from_mode(0o600));
    }
    std::fs::rename(&tmp, &path).map_err(|e| format!("{}: {e}", path.display()))
}

/// **The methods `id` is narrowed to**, or `None` for a principal nobody narrowed.
pub fn narrowed_of(root: &std::path::Path, id: &str) -> Result<Option<Vec<String>>, String> {
    let path = narrowed_path(root, id)?;
    match std::fs::read_to_string(&path) {
        Ok(t) => Ok(Some(
            t.lines()
                .map(str::trim)
                .filter(|l| !l.is_empty())
                .map(str::to_owned)
                .collect(),
        )),
        Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(None),
        Err(e) => Err(format!("{}: {e}", path.display())),
    }
}

/// **The keys a fed box takes a `Bootstrap.Restore` from** (h-v1-6a, 2026-09-28): the fed
/// `admin_pubkey` and every fed or offered principal with the `admin` role — monetize's
/// identity (`monetize_identity`), the console, the operator. Exactly the keys that WILL be
/// the box's server-wide admins once it is enrolled, known to it before anybody could enrol.
/// monetize's restore lane signs its stream with its identity, so on an installer-fed box
/// nothing new has to be fed for the lane to be let in. A `none`-role principal (the
/// console's guest key) is not one of them. A malformed feed contributes nothing: this is
/// who may restore, and a line that does not parse names nobody.
pub fn restore_keys(feed: &BTreeMap<String, String>) -> Vec<String> {
    let mut keys: Vec<String> = feed
        .get(crate::pairing::FEED_ADMIN)
        .map(|k| k.trim().to_owned())
        .filter(|k| gunnar_core::auth::parse_public_key(k).is_ok())
        .into_iter()
        .collect();
    keys.extend(
        parse(feed)
            .unwrap_or_default()
            .into_iter()
            .filter(|p| p.admin || p.id == gunnar_grpc::REPAIR_PRINCIPAL)
            .map(|p| p.key),
    );
    keys
}

/// [`restore_keys`] of what the installer fed this box, out of `<data>/pairing/joined.toml`.
/// No file is no keys; a file that does not parse is an error — a persisted answer that lies
/// must not be read as "nobody".
pub fn restore_keys_at(root: &std::path::Path) -> Result<Vec<String>, String> {
    let path = root.join(crate::pairing::JOINED_REL);
    let Some(text) = crate::fed_at_rest::read_checked(root, crate::pairing::JOINED_REL)
        .map_err(|e| format!("{e:#}"))?
    else {
        return Ok(Vec::new());
    };
    let reply = nordisk_pairing::join::JoinReply::parse(&text)
        .map_err(|e| format!("{}: {e}", path.display()))?;
    Ok(restore_keys(&reply.feed))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn a_restore_is_taken_from_the_fed_admin_keys_and_from_no_other() {
        let (admin, monetize, guest, console) = (a_key(), a_key(), a_key(), a_key());
        let fed = feed(&[
            ("admin_pubkey", admin.as_str()),
            ("principal.monetize", &format!("machine admin {monetize}")),
            ("principal.gunnar-guest", &format!("machine none {guest}")),
            ("offer.vm1.console_pubkey", console.as_str()),
        ]);
        let keys = restore_keys(&fed);
        for k in [&admin, &monetize, &console] {
            assert!(
                keys.contains(k),
                "{k} is fed as an admin, so it may restore: {keys:?}"
            );
        }
        assert!(
            !keys.contains(&guest),
            "a principal with no grant is not one a restore is taken from"
        );
        assert!(
            restore_keys(&feed(&[("admin_pubkey", "not a key")])).is_empty(),
            "a line that does not parse names nobody"
        );
        assert!(
            restore_keys(&BTreeMap::new()).is_empty(),
            "no feed, no keys: the box refuses restores by name"
        );
    }

    fn a_key() -> String {
        let pem = gunnar_core::mint_ed25519().unwrap();
        let k = gunnar_core::ssh_key::PrivateKey::from_openssh(&pem).unwrap();
        k.public_key().to_openssh().unwrap()
    }

    fn feed(pairs: &[(&str, &str)]) -> BTreeMap<String, String> {
        pairs
            .iter()
            .map(|(k, v)| (k.to_string(), v.to_string()))
            .collect()
    }

    /// **c-dead-front**: a front laid again must FETCH monetize's backup before
    /// it holds monetize's identity again (the identity is IN the backup,
    /// sealed), and gunnar never adds a second key to `monetize` without its
    /// attestation. So the new front offers a RESTORE identity, and the primary
    /// enrols it as a principal of its own — a machine, no grant but READ on the
    /// namespace the backup lives in — never admin, never on `monetize`.
    #[test]
    fn a_restore_identity_is_a_machine_of_its_own_that_reads_the_backup_namespace_only() {
        let data = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(data.path()).unwrap());
        stores.auth().bootstrap_admin(&a_key()).unwrap();
        stores
            .catalog()
            .create_namespace(RESTORE_NAMESPACE)
            .unwrap();
        let key = a_key();
        let said = install(
            &stores,
            &feed(&[(&format!("offer.front.{OFFER_RESTORE_IDENTITY}"), &key)]),
        )
        .unwrap();
        let p = parse(&feed(&[(
            &format!("offer.front.{OFFER_RESTORE_IDENTITY}"),
            &key,
        )]))
        .unwrap();
        assert_eq!(p.len(), 1, "{said:?}");
        let id = &p[0].id;
        assert!(
            id.starts_with("monetize-restore-")
                && !p[0].admin
                && p[0].read.as_deref() == Some(RESTORE_NAMESPACE),
            "{p:?}"
        );
        assert!(stores.auth().principal(id).unwrap().is_some(), "{said:?}");
        assert!(
            stores.auth().principal("monetize").unwrap().is_none(),
            "never the monetize principal"
        );
        assert!(
            said.iter().any(|l| l.contains("read on monetize")),
            "{said:?}"
        );
        // A second laid-again front: another key, another principal — no attestation needed.
        let again = install(
            &stores,
            &feed(&[(&format!("offer.front.{OFFER_RESTORE_IDENTITY}"), &a_key())]),
        )
        .unwrap();
        assert!(again.iter().all(|l| l.contains("created")), "{again:?}");
    }

    #[test]
    fn the_three_estate_principals_parse_and_a_bad_line_is_refused_by_name() {
        let key = a_key();
        #[allow(non_snake_case)]
        let KEY = key.as_str();
        let f = feed(&[
            ("principal.rickard", &format!("user admin {KEY}")),
            ("principal.monetize", &format!("machine admin {KEY}")),
            ("principal.gunnar-guest", &format!("machine none {KEY}")),
            ("admin_pubkey", KEY),
            ("monetize_pubkey", "eb16"),
        ]);
        let got = parse(&f).unwrap();
        assert_eq!(got.len(), 3, "only principal.* keys");
        let guest = got.iter().find(|p| p.id == "gunnar-guest").unwrap();
        assert!(
            !guest.admin && guest.kind == gunnar_proto::PrincipalKind::Machine,
            "the guest gets NO grant"
        );
        assert!(got.iter().find(|p| p.id == "rickard").unwrap().admin);
        for bad in [
            format!("robot admin {KEY}"),
            format!("user root {KEY}"),
            "user admin not-a-key".to_string(),
            "user admin".to_string(),
        ] {
            let e = parse(&feed(&[("principal.x", &bad)])).unwrap_err();
            assert!(
                e.starts_with("REFUSED [fed-principal] `principal.x`"),
                "{e}"
            );
        }
        assert!(parse(&feed(&[("principal.", &format!("user admin {KEY}"))])).is_err());
        // The front's offered certify key is a machine admin principal.
        let offered = parse(&feed(&[("offer.front.certify_pubkey", KEY)])).unwrap();
        assert_eq!(offered.len(), 1);
        assert!(
            offered[0].id == "front-certify"
                && offered[0].admin
                && offered[0].kind == gunnar_proto::PrincipalKind::Machine,
            "{offered:?}"
        );
    }

    /// ★ f-grpc-tls: the central monetize's ATTACH CA, fed as `attach.ca`, is
    /// kept where the gRPC listener reads its client CAs, beside the box's own
    /// issuer — the central dials in with a client identity under it.
    #[test]
    fn the_fed_attach_ca_is_kept_and_joins_the_listeners_client_cas() {
        let dir = tempfile::tempdir().unwrap();
        let ca = "-----BEGIN CERTIFICATE-----\nATTACH\n-----END CERTIFICATE-----\n";
        assert!(
            keep_attach_ca(dir.path(), &feed(&[])).unwrap().is_none(),
            "no attach.ca, nothing written"
        );
        assert!(keep_attach_ca(dir.path(), &feed(&[("attach.ca", ca)]))
            .unwrap()
            .is_some());
        let issuer = "-----BEGIN CERTIFICATE-----\nISSUER\n-----END CERTIFICATE-----\n";
        let both = grpc_client_cas(issuer, dir.path());
        assert!(
            both.starts_with(issuer) && both.contains("ATTACH"),
            "{both}"
        );
        assert_eq!(
            grpc_client_cas(issuer, tempfile::tempdir().unwrap().path()),
            issuer,
            "no attach CA: the issuer alone, as before"
        );
        assert!(
            keep_attach_ca(dir.path(), &feed(&[("attach.ca", "not a pem")])).is_err(),
            "refused by name"
        );
    }

    /// ★ f-principal-reach: a CENTRAL monetize is enrolled `machine billing`:
    /// no admin grant, narrowed to the methods monetize's plugin calls; the
    /// narrowing is kept where the control plane reads it.
    /// The open build names no `billing` role: a line that says it is refused
    /// like any unknown role (the_open_sources_say_no_money).
    #[cfg(not(feature = "metered"))]
    #[test]
    fn an_open_build_refuses_a_billing_principal_by_name() {
        let key =
            "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC/NlSHUwzgG2pmW6qZhn0rXR0PFs1Nqgd1rLTUQgj+t";
        let err = parse(&feed(&[(
            "principal.monetize-central",
            &format!("machine billing {key}"),
        )]))
        .unwrap_err();
        assert!(err.contains("the role is not one of admin|none"), "{err}");
    }

    #[cfg(feature = "metered")]
    #[test]
    fn a_billing_principal_holds_no_admin_grant_and_is_narrowed_to_monetizes_methods() {
        let key = a_key();
        let got = parse(&feed(&[(
            "principal.monetize-central",
            &format!("machine billing {key}"),
        )]))
        .unwrap();
        assert_eq!(got.len(), 1);
        assert!(!got[0].admin && got[0].narrowed, "{got:?}");
        let dir = tempfile::tempdir().unwrap();
        write_narrowed(dir.path(), "monetize-central", gunnar_grpc::BILLING_METHODS).unwrap();
        assert_eq!(
            narrowed_of(dir.path(), "monetize-central")
                .unwrap()
                .unwrap(),
            gunnar_grpc::BILLING_METHODS
                .iter()
                .map(|m| m.to_string())
                .collect::<Vec<_>>()
        );
        assert_eq!(
            narrowed_of(dir.path(), "rickard").unwrap(),
            None,
            "a principal nobody narrowed"
        );
        assert!(
            narrowed_of(dir.path(), "../etc").is_err(),
            "a principal id is a plain name"
        );
        assert_eq!(
            narrowed_of(dir.path(), "acme.bob").unwrap(),
            None,
            "a dotted id is a plain name nobody narrowed"
        );
        assert!(
            narrowed_of(dir.path(), ".hidden").is_err() && narrowed_of(dir.path(), "a..b").is_err()
        );
    }
}

#[cfg(test)]
mod install_tests {
    use super::*;

    fn a_key() -> String {
        let pem = gunnar_core::mint_ed25519().unwrap();
        gunnar_core::ssh_key::PrivateKey::from_openssh(&pem)
            .unwrap()
            .public_key()
            .to_openssh()
            .unwrap()
    }

    #[test]
    fn the_primary_installs_the_fed_principals_after_its_admin_and_again_changes_nothing() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        stores.auth().bootstrap_admin(&a_key()).unwrap();
        let (op, mon, guest) = (a_key(), a_key(), a_key());
        let feed: BTreeMap<String, String> = [
            ("principal.rickard".to_string(), format!("user admin {op}")),
            (
                "principal.monetize".to_string(),
                format!("machine admin {mon}"),
            ),
            (
                "principal.gunnar-guest".to_string(),
                format!("machine none {guest}"),
            ),
        ]
        .into_iter()
        .collect();
        let said = install(&stores, &feed).unwrap();
        assert_eq!(said.len(), 3, "{said:?}");
        assert!(
            said.iter()
                .all(|l| l.contains("created") && l.contains("key registered")),
            "{said:?}"
        );
        let auth = stores.auth();
        assert_eq!(
            auth.principal("monetize").unwrap().unwrap().kind,
            gunnar_core::PrincipalKind::Machine
        );
        assert_eq!(auth.keys_of("rickard").unwrap().len(), 1);
        assert!(
            !auth.grants(Some("rickard")).unwrap().is_empty(),
            "the operator is gunnar-admin"
        );
        assert!(
            auth.grants(Some("gunnar-guest")).unwrap().is_empty(),
            "the guest has NO grant"
        );
        let again = install(&stores, &feed).unwrap();
        assert!(
            again
                .iter()
                .all(|l| !l.contains("created") && !l.contains("key registered")),
            "{again:?}"
        );
        assert_eq!(
            auth.keys_of("rickard").unwrap().len(),
            1,
            "not registered twice"
        );
    }

    /// ★ **The buyer's welcome repository is made by the primary, once** (no-dwarf step 7,
    /// 2026-10-08): fed `operator_welcome_readme`, the claimed account gets `<account>/welcome`,
    /// private, its first commit the README — the only repository; a second feed makes nothing,
    /// and a buyer who deletes it is not given it again.
    #[test]
    fn the_buyers_welcome_repository_is_made_once_with_the_sellers_readme() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        stores.auth().bootstrap_admin(&a_key()).unwrap();
        let text = "# Welcome to your own Gunnar\n\nThank you for buying it.\n";
        let feed: BTreeMap<String, String> = [
            (FEED_OPERATOR.to_string(), "acme-owner".to_string()),
            (FEED_OPERATOR_WELCOME.to_string(), text.to_string()),
        ]
        .into_iter()
        .collect();
        let said = install(&stores, &feed).unwrap();
        assert!(
            said.iter().any(|l| l.contains("acme-owner/welcome made")),
            "{said:?}"
        );
        let plane = CoreControlPlane::new(Arc::clone(&stores));
        let repos = plane.list_repos(Some("acme-owner")).unwrap();
        assert_eq!(
            repos
                .iter()
                .map(|r| r.path.as_ref().map(|p| p.repo.clone()).unwrap_or_default())
                .collect::<Vec<_>>(),
            vec![WELCOME_REPO.to_string()],
            "the only repository"
        );
        assert_eq!(
            repos[0].visibility,
            gunnar_proto::Visibility::Private as i32,
            "the buyer's, private"
        );
        let again = install(&stores, &feed).unwrap();
        assert!(
            !again.iter().any(|l| l.contains("welcome")),
            "made once: {again:?}"
        );
        assert_eq!(plane.list_repos(Some("acme-owner")).unwrap().len(), 1);
    }

    /// **A namespace says whose account it is** (`Namespace.owner_kind`), so
    /// monetize's gunnar plugin bills people and never the estate's machines.
    #[test]
    fn every_listed_namespace_names_the_kind_of_the_principal_whose_account_it_is() {
        use gunnar_grpc::ControlPlane as _;
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        stores.auth().bootstrap_admin(&a_key()).unwrap();
        let feed: BTreeMap<String, String> = [
            (
                "principal.rickard".to_string(),
                format!("user admin {}", a_key()),
            ),
            (
                "principal.monetize".to_string(),
                format!("machine admin {}", a_key()),
            ),
            (
                "principal.dwarves-oden".to_string(),
                format!("machine none {}", a_key()),
            ),
        ]
        .into_iter()
        .collect();
        install(&stores, &feed).unwrap();
        let plane = CoreControlPlane::new(Arc::clone(&stores));
        // A principal's account is made with it; a namespace of no principal on its own.
        plane.create_namespace("team", "").unwrap();
        let kinds: BTreeMap<String, i32> = plane
            .list_namespaces()
            .unwrap()
            .into_iter()
            .map(|n| (n.name, n.owner_kind))
            .collect();
        assert_eq!(kinds["rickard"], gunnar_proto::PrincipalKind::User as i32);
        assert_eq!(
            kinds["monetize"],
            gunnar_proto::PrincipalKind::Machine as i32
        );
        assert_eq!(
            kinds["dwarves-oden"],
            gunnar_proto::PrincipalKind::Machine as i32
        );
        assert_eq!(
            kinds["team"],
            gunnar_proto::PrincipalKind::Unspecified as i32,
            "no principal of that id"
        );

        // **A group of machines is the estate's own too** (MEASURED on the
        // mock 2026-09-29: the `twin` group — the twin's log readers, member
        // `gunnar-twin` — was listed as a tenant): a group whose every member
        // is a machine is answered MACHINE; a group with a person in it stays
        // a group (a team's account).
        use gunnar_core::{Principal, PrincipalKind as K};
        let auth = stores.auth();
        auth.add_principal(Principal::new("gunnar-twin", "gunnar-twin", K::Machine).unwrap())
            .unwrap();
        auth.add_principal(Principal::new("twin", "twin", K::Group).unwrap())
            .unwrap();
        auth.add_to_group("twin", "gunnar-twin").unwrap();
        auth.add_principal(Principal::new("crew", "crew", K::Group).unwrap())
            .unwrap();
        auth.add_to_group("crew", "rickard").unwrap();
        auth.add_to_group("crew", "monetize").unwrap();
        auth.add_principal(Principal::new("empty", "empty", K::Group).unwrap())
            .unwrap();
        for ns in ["twin", "crew", "empty"] {
            plane.create_namespace(ns, "").unwrap();
        }
        let kinds: BTreeMap<String, i32> = plane
            .list_namespaces()
            .unwrap()
            .into_iter()
            .map(|n| (n.name, n.owner_kind))
            .collect();
        assert_eq!(
            kinds["twin"],
            gunnar_proto::PrincipalKind::Machine as i32,
            "a group of machines only"
        );
        assert_eq!(
            kinds["crew"],
            gunnar_proto::PrincipalKind::Group as i32,
            "a person in it: a team"
        );
        assert_eq!(
            kinds["empty"],
            gunnar_proto::PrincipalKind::Group as i32,
            "no member: nobody said it is a machine"
        );
    }

    /// Since 0.4 the installer feeds only the operator as admin; monetize,
    /// the guest and the front's certify key reach the primary as vm1's
    /// OFFERS (`offer.front.<key>`), and the primary enrols them itself.
    #[test]
    fn the_primary_enrols_monetize_the_guest_and_the_front_from_vm1s_offers() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let (op, mon, guest, certify) = (a_key(), a_key(), a_key(), a_key());
        stores.auth().bootstrap_admin(&op).unwrap();
        let feed: BTreeMap<String, String> = [
            ("admin_pubkey".to_string(), op.clone()),
            (
                format!("offer.front.{OFFER_MONETIZE_IDENTITY}"),
                mon.clone(),
            ),
            (format!("offer.front.{OFFER_GUEST_PUBKEY}"), guest.clone()),
            (
                format!(
                    "offer.front.{}",
                    gunnar_pairing_door::front::OFFER_CERTIFY_PUBKEY
                ),
                certify,
            ),
            ("offer.main.ticket_pubkey".to_string(), "ab".repeat(32)),
        ]
        .into_iter()
        .collect();
        let said = install(&stores, &feed).unwrap();
        assert_eq!(said.len(), 3, "{said:?}");
        let auth = stores.auth();
        assert_eq!(
            auth.principal("monetize").unwrap().unwrap().kind,
            gunnar_core::PrincipalKind::Machine
        );
        assert!(
            !auth.grants(Some("monetize")).unwrap().is_empty(),
            "monetize is gunnar-admin"
        );
        assert_eq!(auth.keys_of("gunnar-guest").unwrap().len(), 1);
        assert!(
            auth.grants(Some("gunnar-guest")).unwrap().is_empty(),
            "the guest has NO grant"
        );
        assert!(
            !auth.grants(Some("front-certify")).unwrap().is_empty(),
            "the front certifies with an admin key"
        );
        assert!(
            install(&stores, &feed)
                .unwrap()
                .iter()
                .all(|l| !l.contains("created") && !l.contains("key registered")),
            "idempotent"
        );
        // A principal the installer fed by name wins over the offer.
        let mut named = feed.clone();
        named.insert("principal.monetize".into(), format!("machine none {mon}"));
        assert!(
            !parse(&named)
                .unwrap()
                .iter()
                .find(|p| p.id == "monetize")
                .unwrap()
                .admin
        );
        assert_eq!(
            parse(&named)
                .unwrap()
                .iter()
                .filter(|p| p.id == "monetize")
                .count(),
            1
        );
    }

    /// **A front laid again REPLACES the keys it mints itself** (estate-box3 life1, R2 after
    /// U3: row recharge-twin-certify-stale). U3 laid vm1 again on its kept /data: a fresh
    /// installation clears `pairing/certify.key`, so the new front offers a NEW certify key.
    /// The primary already held the old one, and a second key needs the holder's attestation
    /// — so main WARNed "a fed principal could not be installed yet" for ever, kept the DEAD
    /// front's certify key, and refused every enrol the new front signed ("the credential did
    /// not verify against any registered key"): the recharged twin was never certified. The
    /// installer's feed is the authority for the keys the front mints (certify, console,
    /// guest): the offered key replaces the one held, the old one no longer authenticates.
    /// monetize's identity is NOT one of them (it is restored from its backup, never re-minted).
    #[test]
    fn a_front_laid_again_replaces_the_keys_it_mints_and_the_old_ones_stop_authenticating() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let op = a_key();
        stores.auth().bootstrap_admin(&op).unwrap();
        let certify_offer = format!(
            "offer.front.{}",
            gunnar_pairing_door::front::OFFER_CERTIFY_PUBKEY
        );
        let fed =
            |certify: &str, console: &str, guest: &str, mon: &str| -> BTreeMap<String, String> {
                [
                    ("admin_pubkey".to_string(), op.clone()),
                    (certify_offer.clone(), certify.to_string()),
                    (
                        format!("offer.front.{OFFER_CONSOLE_PUBKEY}"),
                        console.to_string(),
                    ),
                    (
                        format!("offer.front.{OFFER_GUEST_PUBKEY}"),
                        guest.to_string(),
                    ),
                    (
                        format!("offer.front.{OFFER_MONETIZE_IDENTITY}"),
                        mon.to_string(),
                    ),
                ]
                .into_iter()
                .collect()
            };
        let (c1, k1, g1, mon) = (a_key(), a_key(), a_key(), a_key());
        install(&stores, &fed(&c1, &k1, &g1, &mon)).unwrap();
        let fp = |k: &str| {
            gunnar_core::Fingerprint::of_key(&gunnar_core::auth::parse_public_key(k).unwrap())
        };
        let auth = stores.auth();
        // U3: the same front slot, a fresh installation — new certify, console and guest keys.
        let (c2, k2, g2) = (a_key(), a_key(), a_key());
        let said = install(&stores, &fed(&c2, &k2, &g2, &mon))
            .expect("the new front's keys are installed, not refused for an attestation");
        for (id, old, new) in [
            ("front-certify", &c1, &c2),
            ("gunnar-ui", &k1, &k2),
            ("gunnar-guest", &g1, &g2),
        ] {
            let held: Vec<String> = auth
                .keys_of(id)
                .unwrap()
                .into_iter()
                .map(|k| k.fingerprint_sha256)
                .collect();
            assert_eq!(
                held,
                vec![fp(new).as_str().to_string()],
                "{id} holds the new front's key only: {said:?}"
            );
            assert!(
                auth.principal_by_fingerprint(&fp(old)).unwrap().is_none(),
                "{id}: the dead front's key no longer authenticates"
            );
            assert!(
                said.iter()
                    .any(|l| l.starts_with(id) && l.contains("replaced")),
                "{id}: said: {said:?}"
            );
        }
        assert!(
            !auth.grants(Some("front-certify")).unwrap().is_empty(),
            "the certify key keeps its gunnar-admin grant"
        );
        // Fed again: nothing changes.
        assert!(
            install(&stores, &fed(&c2, &k2, &g2, &mon))
                .unwrap()
                .iter()
                .all(|l| !l.contains("created")
                    && !l.contains("key registered")
                    && !l.contains("replaced")),
            "idempotent"
        );
        // monetize's identity is never replaced by an offer: a different key is refused by name.
        let e = install(&stores, &fed(&c2, &k2, &g2, &a_key())).unwrap_err();
        assert!(e.contains("monetize") && e.contains("attestation"), "{e}");
        assert_eq!(auth.keys_of("monetize").unwrap().len(), 1);
    }

    /// The installer's feed as a primary is fed it: the installer's own
    /// principals by name, then the front's offers.
    fn a_full_feed(
        op: &str,
        certify: &str,
        console: &str,
        mon: &str,
        guest: &str,
    ) -> BTreeMap<String, String> {
        [
            ("admin_pubkey".to_string(), op.to_string()),
            (
                "principal.dwarves-oden".to_string(),
                format!("machine admin {}", a_key()),
            ),
            (
                "principal.installer-seed".to_string(),
                format!("machine admin {}", a_key()),
            ),
            (
                format!(
                    "offer.front.{}",
                    gunnar_pairing_door::front::OFFER_CERTIFY_PUBKEY
                ),
                certify.to_string(),
            ),
            (
                format!("offer.front.{OFFER_CONSOLE_PUBKEY}"),
                console.to_string(),
            ),
            (
                format!("offer.front.{OFFER_MONETIZE_IDENTITY}"),
                mon.to_string(),
            ),
            (
                format!("offer.front.{OFFER_GUEST_PUBKEY}"),
                guest.to_string(),
            ),
        ]
        .into_iter()
        .collect()
    }

    /// ★ **The front's certify key is enrolled FIRST** (cov-E r3 2026-10-06,
    /// run 3): in feed order it came sixth — the installer's own principals,
    /// then the console, monetize, the guest — and a starved primary took
    /// 4 m 47 s over the whole feed while the front's twin certification,
    /// calling with that key since the election, was refused. The keys a peer
    /// is waiting on go first: the certify key, the console, monetize.
    #[test]
    fn the_fronts_certify_key_is_enrolled_first_then_the_console_then_monetize() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let op = a_key();
        stores.auth().bootstrap_admin(&op).unwrap();
        let said = install(
            &stores,
            &a_full_feed(&op, &a_key(), &a_key(), &a_key(), &a_key()),
        )
        .unwrap();
        let order: Vec<&str> = said
            .iter()
            .map(|l| l.split(' ').next().unwrap_or(""))
            .collect();
        assert_eq!(
            &order[..3],
            &[
                gunnar_pairing_door::front::CERTIFY_PRINCIPAL,
                "gunnar-ui",
                "monetize"
            ],
            "{said:#?}"
        );
        assert_eq!(
            order.len(),
            6,
            "every fed principal is still enrolled: {said:#?}"
        );
    }

    /// ★ **A key the installer fed and the primary has not enrolled yet is
    /// AWAITED** (cov-E r3 2026-10-06, run 3): its holder is told
    /// `Unavailable [key-enrolling]` — ask again — not that it is unknown.
    /// Only a key the install WILL take: monetize's second key (owing an
    /// attestation) is refused, not enrolled, and is answered as before; and
    /// once enrolled, nothing is awaited any more.
    #[test]
    fn a_fed_key_not_enrolled_yet_is_awaited_and_its_holder_told_to_ask_again() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let op = a_key();
        stores.auth().bootstrap_admin(&op).unwrap();
        let certify_pem = gunnar_core::mint_ed25519().unwrap();
        let certify = gunnar_core::ssh_key::PrivateKey::from_openssh(&certify_pem).unwrap();
        let certify_line = certify.public_key().to_openssh().unwrap();
        let fp = |k: &str| {
            gunnar_core::Fingerprint::of_key(&gunnar_core::auth::parse_public_key(k).unwrap())
                .as_str()
                .to_string()
        };
        let mon = a_key();
        let feed = a_full_feed(&op, &certify_line, &a_key(), &mon, &a_key());
        let plane: Arc<dyn gunnar_grpc::ControlPlane> =
            Arc::new(CoreControlPlane::new(Arc::clone(&stores)));
        let gate = gunnar_grpc::AuthGate::new(Arc::clone(&plane), gunnar_grpc::AuthMode::Required);
        let presented = |nonce: &str| {
            let now = gunnar_core::now_ms() as i64;
            let credential =
                gunnar_grpc::sign_credential_for(&certify, now, nonce, "Admin.Health").unwrap();
            let mut md = tonic::metadata::MetadataMap::new();
            md.insert(
                gunnar_grpc::CREDENTIAL_METADATA_KEY,
                credential.to_header_value().parse().unwrap(),
            );
            gate.authenticate_bound(&md, now, Some("Admin.Health"))
        };

        // The feed landed; the pairing loop has not enrolled anything yet.
        assert_eq!(
            presented("nonce-before-the-feed"),
            Err(gunnar_grpc::AuthFailure::NotVerified),
            "nothing fed yet: unknown"
        );
        note_fed(&stores, &feed);
        assert_eq!(
            plane.awaiting_enrolment(&fp(&certify_line)),
            Some(certify_line.clone())
        );
        assert_eq!(
            presented("nonce-fed-and-awaited"),
            Err(gunnar_grpc::AuthFailure::Enrolling),
            "the front's certify key, fed and not enrolled yet"
        );

        // Enrolled: a caller, and nothing awaited.
        install(&stores, &feed).unwrap();
        assert_eq!(plane.awaiting_enrolment(&fp(&certify_line)), None);
        assert_eq!(
            presented("nonce-once-enrolled-01").map(|c| c.principal_id),
            Ok(gunnar_pairing_door::front::CERTIFY_PRINCIPAL.to_string())
        );

        // A second monetize key owes an attestation: refused, never "being enrolled".
        let second = a_key();
        let refeed = a_full_feed(&op, &certify_line, &a_key(), &second, &a_key());
        note_fed(&stores, &refeed);
        assert_eq!(
            plane.awaiting_enrolment(&fp(&second)),
            None,
            "monetize's second key is refused by install, not awaited"
        );
        assert!(install(&stores, &refeed).is_err());
        assert_eq!(plane.awaiting_enrolment(&fp(&second)), None);
        assert_eq!(plane.awaiting_enrolment(&fp(&mon)), None);
    }

    /// **One principal that cannot be installed yet does not hold back the others**
    /// (R3, a front laid again on a NEW disk): it offers a freshly minted monetize
    /// identity until monetize's backup is restored (the old identity is IN the backup),
    /// and the primary rightly refuses that second key on `monetize`. `install` stopped
    /// at the first refusal — and `monetize` comes before `gunnar-guest` and
    /// `front-certify` — so the new front's certify key waited on monetize's restore and
    /// the twin could not be certified meanwhile. Every other principal is installed;
    /// the refusal is still an `Err` naming it (the loop asks again).
    #[test]
    fn a_principal_refused_for_now_does_not_hold_back_the_front_certify_key() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let op = a_key();
        stores.auth().bootstrap_admin(&op).unwrap();
        let certify_offer = format!(
            "offer.front.{}",
            gunnar_pairing_door::front::OFFER_CERTIFY_PUBKEY
        );
        let fed = |certify: &str, mon: &str| -> BTreeMap<String, String> {
            [
                ("admin_pubkey".to_string(), op.clone()),
                (certify_offer.clone(), certify.to_string()),
                (
                    format!("offer.front.{OFFER_MONETIZE_IDENTITY}"),
                    mon.to_string(),
                ),
            ]
            .into_iter()
            .collect()
        };
        let (c1, mon) = (a_key(), a_key());
        install(&stores, &fed(&c1, &mon)).unwrap();
        // R3: the new front, before monetize's restore: a new monetize identity AND a new certify key.
        let c2 = a_key();
        let e = install(&stores, &fed(&c2, &a_key())).unwrap_err();
        assert!(e.contains("`monetize`"), "the refusal is named: {e}");
        let fp =
            gunnar_core::Fingerprint::of_key(&gunnar_core::auth::parse_public_key(&c2).unwrap());
        let held: Vec<String> = stores
            .auth()
            .keys_of("front-certify")
            .unwrap()
            .into_iter()
            .map(|k| k.fingerprint_sha256)
            .collect();
        assert_eq!(
            held,
            vec![fp.as_str().to_string()],
            "the new front's certify key is in, whatever monetize waits for"
        );
        // After the restore the front offers monetize's OLD identity again: all taken.
        assert!(install(&stores, &fed(&c2, &mon)).is_ok());
    }

    /// **No fed admin key authenticates before its grant exists** (release-3 test2 mock:
    /// main logged `Access.AddPrincipal principal=front-certify decision="deny" reason="no
    /// grant"` once at pairing — a machine of the estate DENIED, which fails the receipt).
    /// `install` registered each principal's KEY and then its grant, two commits: the front's
    /// certify thread, retrying since the election, called in between and was refused. The
    /// key is registered LAST, so the key is never valid without its grant. Watched from
    /// another thread while the install runs, keys read before grants (a new-order install
    /// can never look key-without-grant that way), on fresh stores many times.
    #[test]
    fn a_fed_admin_key_never_authenticates_before_its_admin_grant_exists() {
        let mut seen = Vec::new();
        for round in 0..30 {
            let dir = tempfile::tempdir().unwrap();
            let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
            let op = a_key();
            stores.auth().bootstrap_admin(&op).unwrap();
            let feed: BTreeMap<String, String> = [
                ("admin_pubkey".to_string(), op),
                (
                    format!(
                        "offer.front.{}",
                        gunnar_pairing_door::front::OFFER_CERTIFY_PUBKEY
                    ),
                    a_key(),
                ),
            ]
            .into_iter()
            .collect();
            let done = Arc::new(std::sync::atomic::AtomicBool::new(false));
            let (s2, d2) = (Arc::clone(&stores), Arc::clone(&done));
            let watcher = std::thread::spawn(move || {
                let mut bad = 0u32;
                while !d2.load(std::sync::atomic::Ordering::SeqCst) {
                    let keys = s2
                        .auth()
                        .keys_of("front-certify")
                        .map(|k| k.len())
                        .unwrap_or(0);
                    if keys > 0
                        && s2
                            .auth()
                            .grants(Some("front-certify"))
                            .map(|g| g.is_empty())
                            .unwrap_or(false)
                    {
                        bad += 1;
                    }
                }
                bad
            });
            install(&stores, &feed).unwrap();
            done.store(true, std::sync::atomic::Ordering::SeqCst);
            let bad = watcher.join().unwrap();
            if bad > 0 {
                seen.push(format!(
                    "round {round}: {bad} look(s) saw front-certify's key with no grant"
                ));
            }
        }
        assert!(
            seen.is_empty(),
            "the certify key authenticated with no grant: {seen:?}"
        );
    }

    // ── the estate's operator (2026-10-04) ────────────────────────────────

    fn operator_feed(op: &str) -> BTreeMap<String, String> {
        [
            ("admin_pubkey".to_string(), op.to_string()),
            (FEED_OPERATOR.to_string(), "rickard".to_string()),
        ]
        .into_iter()
        .collect()
    }

    /// ★ **The installer's `operator_name` makes the operator's account AT
    /// INSTALL**: a person, keyless, gunnar-admin, its namespace reserved —
    /// before anything can push into `rickard/…` and conjure an ownerless
    /// namespace (test2 2026-10-04), and before the first passkey binds to it.
    /// Keyless is the point: the console's credential is its FIRST key, which
    /// owes nobody an attestation, so a fresh estate never shows
    /// `awaiting_attestation`.
    #[test]
    fn the_fed_operator_is_claimed_at_install_keyless_gunnar_admin_with_its_account() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let op = a_key();
        stores.auth().bootstrap_admin(&op).unwrap();
        let said = install(&stores, &operator_feed(&op)).unwrap();
        assert!(
            said.iter()
                .any(|l| l.starts_with("operator rickard: created")),
            "{said:?}"
        );
        let auth = stores.auth();
        let rickard = auth
            .principal("rickard")
            .unwrap()
            .expect("the operator exists after the install");
        assert_eq!(rickard.kind, gunnar_core::PrincipalKind::User);
        assert!(
            auth.keys_of("rickard").unwrap().is_empty(),
            "the operator must be KEYLESS: the console's key is its first"
        );
        assert!(
            auth.grants(Some("rickard"))
                .unwrap()
                .iter()
                .any(|g| matches!(g.scope, gunnar_core::Scope::Server)
                    && g.level == gunnar_core::Level::Admin),
            "the operator is the estate's admin"
        );
        assert!(
            stores.catalog().namespace("rickard").unwrap().is_some(),
            "its account namespace"
        );
        // The fed admin key stays the bootstrap admin's; nothing moved it.
        assert_eq!(
            auth.keys_of(gunnar_core::BOOTSTRAP_ADMIN_ID).unwrap().len(),
            1
        );
        // Every feed after it: nothing new.
        let again = install(&stores, &operator_feed(&op)).unwrap();
        assert!(
            again.iter().any(|l| l == "operator rickard: already there"),
            "{again:?}"
        );
    }

    /// ★ **test2, 2026-10-04: the namespace a first push conjured is ADOPTED.**
    /// `rickard/t2-scratch` was pushed with the installer's admin key before any
    /// operator existed; `AddPrincipal rickard` was refused from then on, and
    /// the owner's passkey bound to nothing. The claim takes the namespace — and
    /// what is in it — as the operator's account.
    #[test]
    fn a_namespace_a_first_push_conjured_for_the_operator_is_adopted_with_its_repositories() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let op = a_key();
        stores.auth().bootstrap_admin(&op).unwrap();
        let plane = CoreControlPlane::new(Arc::clone(&stores));
        plane.create_namespace("rickard", "").unwrap();
        plane
            .create_repo(gunnar_grpc::NewRepo {
                path: gunnar_proto::RepoPath::new("rickard", "t2-scratch"),
                hash_kind: gunnar_proto::HashKind::Sha256,
                default_branch: String::new(),
                visibility: gunnar_proto::Visibility::Private,
                description: String::new(),
                adopt: false,
            })
            .unwrap();
        // RED on release-3: exactly the refusal test2 logged.
        let refused = plane
            .add_principal("rickard", "rickard", gunnar_proto::PrincipalKind::User)
            .unwrap_err();
        assert!(
            refused.to_string().contains("namespace already exists"),
            "{refused}"
        );

        let said = install(&stores, &operator_feed(&op)).unwrap();
        assert!(said.iter().any(|l| l.contains("ADOPTED")), "{said:?}");
        assert!(stores.auth().principal("rickard").unwrap().is_some());
        assert!(gunnar_core::AuthTable::owns_account("rickard", "rickard"));
        assert!(
            plane
                .get_repo(&gunnar_proto::RepoPath::new("rickard", "t2-scratch"))
                .is_ok(),
            "the adopted account keeps what was pushed into it"
        );
    }

    /// **`Accounts.ClaimOperator` answers the FED operator, whatever it was
    /// asked** — the console sends the name the first passkey was registered
    /// under, and gunnar decides. The fed name is read from the persisted join
    /// reply, so a restart changes nothing.
    #[test]
    fn the_claim_answers_the_fed_operator_whatever_it_was_asked() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        stores.auth().bootstrap_admin(&a_key()).unwrap();
        std::fs::create_dir_all(dir.path().join("pairing")).unwrap();
        std::fs::write(
            dir.path().join(crate::pairing::JOINED_REL),
            "estate = \"operator-claim-test\"\nrole = \"primary\"\npeers = []\n\n[me]\nname = \"main\"\noverlay = \"10.13.0.2\"\n\n[feed]\noperator_name = \"rickard\"\n",
        )
        .unwrap();
        assert_eq!(fed_operator(dir.path()).as_deref(), Some("rickard"));
        let plane = CoreControlPlane::new(Arc::clone(&stores));
        let claim =
            gunnar_grpc::ControlPlane::claim_operator(&plane, "Rickard-typed-something-else")
                .unwrap();
        assert_eq!(claim.principal.id, "rickard");
        assert_eq!(claim.named_by, "fed");
        assert!(claim.created);
        let again = gunnar_grpc::ControlPlane::claim_operator(&plane, "").unwrap();
        assert!(!again.created);
        assert_eq!(
            again.principal, claim.principal,
            "the same row and the same stamp"
        );
    }

    /// No `operator_name` in the feed: the install claims nobody, and a claim
    /// that names nobody either is refused rather than guessed.
    #[test]
    fn a_feed_without_an_operator_claims_nobody() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let op = a_key();
        stores.auth().bootstrap_admin(&op).unwrap();
        let feed: BTreeMap<String, String> =
            [("admin_pubkey".to_string(), op)].into_iter().collect();
        install(&stores, &feed).unwrap();
        assert!(stores.auth().principal("rickard").unwrap().is_none());
        let plane = CoreControlPlane::new(Arc::clone(&stores));
        let refused = gunnar_grpc::ControlPlane::claim_operator(&plane, "").unwrap_err();
        assert!(
            matches!(refused, gunnar_grpc::ControlError::FailedPrecondition(_)),
            "{refused}"
        );
    }

    // ── the console's credential for the operator, enrolled at install ────

    /// The front's operator credential as it offers it: an OpenSSH line that
    /// carries [`OPERATOR_CONSOLE_COMMENT`].
    fn a_console_credential() -> String {
        format!("{} {OPERATOR_CONSOLE_COMMENT}", a_key())
    }

    fn fingerprint(line: &str) -> String {
        gunnar_core::Fingerprint::of_key(&gunnar_core::auth::parse_public_key(line).unwrap())
            .as_str()
            .to_owned()
    }

    fn held(stores: &ServerStores, id: &str) -> Vec<String> {
        stores
            .auth()
            .keys_of(id)
            .unwrap()
            .into_iter()
            .map(|k| k.fingerprint_sha256)
            .collect()
    }

    /// ★ **The console's credential for the operator is enrolled AT INSTALL, as
    /// the account's first key** (2026-10-04): the front offers it
    /// (`offer.front.operator_console_pubkey`, the installer relays it) and the
    /// primary enrols it on the account it claims — so when the owner registers
    /// his YubiKey the console's credential is already held, it owed nobody an
    /// attestation, and the console shows no `awaiting_attestation` and asks for
    /// no operator step. On test2 that morning the console had to mint one at
    /// the first read, and an account with any key of its own refused it.
    #[test]
    fn the_fronts_operator_credential_is_the_operators_first_key_from_the_install() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let op = a_key();
        stores.auth().bootstrap_admin(&op).unwrap();
        let credential = a_console_credential();
        let mut feed = operator_feed(&op);
        feed.insert(
            format!("offer.front.{OFFER_OPERATOR_CONSOLE_PUBKEY}"),
            credential.clone(),
        );
        let said = install(&stores, &feed).unwrap();
        assert_eq!(
            held(&stores, "rickard"),
            vec![fingerprint(&credential)],
            "the operator's ONLY key is the console's credential: {said:?}"
        );
        assert!(
            said.iter()
                .any(|l| l.contains("console's credential") && l.contains("first key")),
            "{said:?}"
        );
        let kept = stores.auth().keys_of("rickard").unwrap();
        assert_eq!(
            kept[0].openssh.split_whitespace().nth(2),
            Some(OPERATOR_CONSOLE_COMMENT),
            "the mark is kept with the key: {}",
            kept[0].openssh
        );
        // Every later feed: nothing new, nothing refused.
        let again = install(&stores, &feed).unwrap();
        assert!(
            again
                .iter()
                .any(|l| l.contains("console's credential") && l.contains("already")),
            "{again:?}"
        );
        assert_eq!(held(&stores, "rickard").len(), 1, "not registered twice");
        // The installer's admin key stays the bootstrap admin's.
        assert_eq!(held(&stores, gunnar_core::BOOTSTRAP_ADMIN_ID).len(), 1);
    }

    /// ★ **Over the namespace a first push conjured too** (test2 2026-10-04):
    /// the account is adopted and the console's credential is its first key.
    #[test]
    fn over_a_conjured_namespace_the_adopted_account_takes_the_consoles_credential() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let op = a_key();
        stores.auth().bootstrap_admin(&op).unwrap();
        CoreControlPlane::new(Arc::clone(&stores))
            .create_namespace("rickard", "")
            .unwrap();
        let credential = a_console_credential();
        let mut feed = operator_feed(&op);
        feed.insert(
            format!("offer.front.{OFFER_OPERATOR_CONSOLE_PUBKEY}"),
            credential.clone(),
        );
        let said = install(&stores, &feed).unwrap();
        assert!(said.iter().any(|l| l.contains("ADOPTED")), "{said:?}");
        assert_eq!(
            held(&stores, "rickard"),
            vec![fingerprint(&credential)],
            "{said:?}"
        );
    }

    /// **A front laid again offers a NEW credential**: it replaces the one the
    /// dead front held (that key's private half is gone with its disk), and
    /// the keys the owner added himself are his and stay. Here he holds none
    /// yet, so the new one is again the account's first key.
    #[test]
    fn a_front_laid_again_replaces_the_credential_the_dead_front_held() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let op = a_key();
        stores.auth().bootstrap_admin(&op).unwrap();
        let (first, second) = (a_console_credential(), a_console_credential());
        let mut feed = operator_feed(&op);
        feed.insert(
            format!("offer.front.{OFFER_OPERATOR_CONSOLE_PUBKEY}"),
            first.clone(),
        );
        install(&stores, &feed).unwrap();
        feed.insert(
            format!("offer.front.{OFFER_OPERATOR_CONSOLE_PUBKEY}"),
            second.clone(),
        );
        let said = install(&stores, &feed).unwrap();
        assert_eq!(
            held(&stores, "rickard"),
            vec![fingerprint(&second)],
            "the dead front's credential must be gone and the new one held: {said:?}"
        );
        assert!(said.iter().any(|l| l.contains("replaced")), "{said:?}");
    }

    /// **The owner's own keys are never touched, and never jumped**: on an
    /// account that already holds a key of the owner's (an estate installed
    /// before this, or a front laid again after he added his SSH keys), the
    /// dead front's credential is still replaced — but the new one is NOT
    /// enrolled over his head. gunnar's rule stands: a second key takes the
    /// account's own word, and the console asks for it. Said, not refused —
    /// the loop must not ask again for ever.
    #[test]
    fn an_account_holding_the_owners_own_key_is_not_given_a_credential_over_his_head() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let op = a_key();
        stores.auth().bootstrap_admin(&op).unwrap();
        let (first, second, his) = (a_console_credential(), a_console_credential(), a_key());
        let mut feed = operator_feed(&op);
        feed.insert(
            format!("offer.front.{OFFER_OPERATOR_CONSOLE_PUBKEY}"),
            first.clone(),
        );
        install(&stores, &feed).unwrap();
        // He adds his laptop's key — signed by the account itself (the console's
        // credential vouches for it).
        CoreControlPlane::new(Arc::clone(&stores))
            .add_key("rickard", &his, "laptop", None, "rickard", None)
            .unwrap();
        feed.insert(
            format!("offer.front.{OFFER_OPERATOR_CONSOLE_PUBKEY}"),
            second.clone(),
        );
        let said = install(&stores, &feed).unwrap();
        assert_eq!(held(&stores, "rickard"), vec![fingerprint(&his)], "his key stays, the dead front's credential goes, the new one waits for his word: {said:?}");
        assert!(
            said.iter()
                .any(|l| l.contains("NOT enrolled") && l.contains("of his own")),
            "{said:?}"
        );
    }

    /// No operator named: an offered credential has nobody to go to, and
    /// nothing is made for it.
    #[test]
    fn an_offered_credential_with_no_operator_named_goes_nowhere() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let op = a_key();
        stores.auth().bootstrap_admin(&op).unwrap();
        let feed: BTreeMap<String, String> = [
            ("admin_pubkey".to_string(), op),
            (
                format!("offer.front.{OFFER_OPERATOR_CONSOLE_PUBKEY}"),
                a_console_credential(),
            ),
        ]
        .into_iter()
        .collect();
        install(&stores, &feed).unwrap();
        assert!(stores.auth().principal("rickard").unwrap().is_none());
        assert_eq!(
            stores.auth().keys().unwrap().len(),
            1,
            "only the bootstrap admin's key"
        );
    }

    // ── the operator's first invite: the break-glass token, by its hash ───

    /// The break-glass token as the installer hands it over, and the hash it
    /// feeds (`webauthn::sha256_hex`, what an invite row keeps).
    const BREAK_GLASS: &str = "uitest-break-glass-0000000000000000000000000001";

    fn hash_of(secret: &str) -> String {
        gunnar_grpc::webauthn::sha256_hex(secret.as_bytes())
    }

    /// The operator's first invite as the plane holds it (the core reads it as a fed invite).
    fn first_invite(stores: &ServerStores) -> Option<gunnar_core::model::FirstInviteRow> {
        stores
            .auth()
            .first_invite(gunnar_grpc::seam::OPERATOR_INVITE_ID)
            .unwrap()
    }

    /// The box's identity core over `stores`, as `serve` builds it.
    fn core(
        dir: &std::path::Path,
        stores: &Arc<ServerStores>,
    ) -> Arc<gunnar_grpc::identity::GunnarIdentity> {
        let control: Arc<dyn gunnar_grpc::ControlPlane> =
            Arc::new(CoreControlPlane::new(Arc::clone(stores)));
        crate::identity::build(dir, control, &gunnar_grpc::ServerConfig::default(), false)
    }

    /// A passkey registered with `secret` through the core (the console's relay).
    fn register(
        identity: &gunnar_grpc::identity::GunnarIdentity,
        secret: &str,
        seed: u8,
    ) -> Result<String, nornir_identity::Refused> {
        let relay = nornir_identity::Relay {
            rp_id: "console.example".into(),
            origin: "https://console.example".into(),
            client: None,
        };
        let c = identity.redeem_start(secret, "", &relay)?;
        let made = identity.redeem_finish(
            nornir_identity::test_host::SoftPasskey::new(seed)
                .register(&c, "https://console.example"),
        )?;
        Ok(made.session.user_id)
    }

    /// ★ **The installer's break-glass token is the operator's FIRST invite**
    /// (Stage L, 2026-10-04: passkeys are gunnar's, and "the UI never creates
    /// users or decides anything"). The feed carries its hash
    /// (`operator_invite_sha256`); the primary records it as the invite
    /// `operator-bootstrap` on the operator it claims — no server grant: he
    /// already is gunnar-admin — and the owner's first passkey, registered
    /// with the token through the identity core (which reads the row as a fed
    /// invite onto him), lands on his account. Over test2's conjured
    /// `rickard/` too. Once he holds a passkey the bootstrap is spent: a later
    /// feed records nothing, and the token registers nothing more.
    #[test]
    fn the_installers_bootstrap_invite_puts_the_first_passkey_on_the_operator_and_is_then_spent() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let op = a_key();
        stores.auth().bootstrap_admin(&op).unwrap();
        CoreControlPlane::new(Arc::clone(&stores))
            .create_namespace("rickard", "")
            .unwrap();
        let mut feed = operator_feed(&op);
        feed.insert(FEED_OPERATOR_INVITE.to_string(), hash_of(BREAK_GLASS));
        let said = install(&stores, &feed).unwrap();
        assert!(
            said.iter()
                .any(|l| l.contains("first invite") && l.contains("recorded")),
            "{said:?}"
        );
        let invite = first_invite(&stores).expect("the first invite");
        assert_eq!(invite.principal_id, "rickard");
        assert_eq!(
            invite.secret_hash,
            hash_of(BREAK_GLASS),
            "the hash, never the token"
        );
        assert_eq!(
            invite.server_level, None,
            "an invite never makes an admin; the claim already did"
        );
        // Every later feed before his first passkey: renewed, still one.
        let again = install(&stores, &feed).unwrap();
        assert!(
            again
                .iter()
                .any(|l| l.contains("first invite") && l.contains("renewed")),
            "{again:?}"
        );
        assert!(first_invite(&stores).is_some());

        // His YubiKey, registered with the token: on HIS account, by gunnar's word.
        let identity = core(dir.path(), &stores);
        let owner = register(&identity, BREAK_GLASS, 0x37)
            .expect("the break-glass token registers the operator's first passkey");
        assert_eq!(owner, "rickard");
        assert_eq!(
            stores
                .auth()
                .web_credentials(Some("rickard"))
                .unwrap()
                .len(),
            1,
            "on his account"
        );
        assert!(first_invite(&stores).is_none(), "redeemed once");

        // Spent: the next feed records nothing, and the token registers nothing more.
        let spent = install(&stores, &feed).unwrap();
        assert!(spent.iter().any(|l| l.contains("spent")), "{spent:?}");
        assert!(
            first_invite(&stores).is_none(),
            "no second bootstrap once he holds a passkey"
        );
        assert!(register(&identity, BREAK_GLASS, 0x38).is_err());
    }

    /// A token fed where its hash belongs is refused by name, and nothing is
    /// recorded: the feed must never carry the secret to the primary.
    #[test]
    fn a_token_fed_in_place_of_its_hash_is_refused_and_nothing_is_recorded() {
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let op = a_key();
        stores.auth().bootstrap_admin(&op).unwrap();
        let mut feed = operator_feed(&op);
        feed.insert(FEED_OPERATOR_INVITE.to_string(), BREAK_GLASS.to_string());
        let refused = install(&stores, &feed).unwrap_err();
        assert!(
            refused.contains("SHA-256") && refused.contains("never the token"),
            "{refused}"
        );
        assert!(first_invite(&stores).is_none());
    }
    /// ★ **A SOLD estate's first invite is the buyer's first-login link**
    /// (private ownership, 2026-10-07): the feed names the buyer's account as
    /// the operator, the hash of the invite the seller mails him, and how long
    /// it lives (`operator_invite_ttl_secs`). The primary records it with THAT
    /// lifetime; it registers exactly one passkey, on the buyer's account; it
    /// is then spent.
    #[test]
    fn a_sold_estates_first_login_invite_lives_as_the_feed_says_registers_once_and_is_then_spent() {
        const FIRST_LOGIN: &str =
            "first-login-0000000000000000000000000000000000000000000000000001";
        let week_secs: i64 = 7 * 24 * 60 * 60;
        let dir = tempfile::tempdir().unwrap();
        let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
        let op = a_key();
        stores.auth().bootstrap_admin(&op).unwrap();
        let mut feed: BTreeMap<String, String> = [
            ("admin_pubkey".to_string(), op.clone()),
            (FEED_OPERATOR.to_string(), "acmebuyer".to_string()),
            (FEED_OPERATOR_INVITE.to_string(), hash_of(FIRST_LOGIN)),
            (FEED_OPERATOR_INVITE_TTL.to_string(), week_secs.to_string()),
        ]
        .into_iter()
        .collect();
        let before = gunnar_core::now_ms();
        let said = install(&stores, &feed).unwrap();
        let after = gunnar_core::now_ms();
        assert!(
            said.iter().any(|l| l.contains("operator acmebuyer")),
            "the buyer is the operator: {said:?}"
        );
        let invite = first_invite(&stores).expect("the first-login invite");
        assert_eq!(invite.principal_id, "acmebuyer");
        let lives = invite.expires - invite.created;
        assert_eq!(
            lives,
            week_secs * 1000,
            "the invite lives as long as the feed says, not {} days",
            lives / 86_400_000
        );
        assert!(
            invite.expires >= before + week_secs * 1000
                && invite.expires <= after + week_secs * 1000
        );

        // Within it: exactly one passkey, on the buyer's account.
        let identity = core(dir.path(), &stores);
        let buyer = register(&identity, FIRST_LOGIN, 0x41)
            .expect("the first-login link registers the buyer's first passkey");
        assert_eq!(buyer, "acmebuyer");
        assert!(first_invite(&stores).is_none(), "redeemed once");
        assert!(
            register(&identity, FIRST_LOGIN, 0x42).is_err(),
            "a link used once registers nothing more"
        );
        // A later feed (an upgrade) records nothing once he holds a passkey.
        let spent = install(&stores, &feed).unwrap();
        assert!(spent.iter().any(|l| l.contains("spent")), "{spent:?}");
        assert!(first_invite(&stores).is_none());

        // A lifetime that is no number, under a minute or over the most an
        // invite lives is refused by name, and nothing is recorded.
        for bad in [
            "soon",
            "0",
            "59",
            &((gunnar_grpc::seam::OPERATOR_INVITE_TTL_MS / 1000) + 1).to_string(),
        ] {
            let dir = tempfile::tempdir().unwrap();
            let stores = Arc::new(ServerStores::open(dir.path()).unwrap());
            stores.auth().bootstrap_admin(&op).unwrap();
            feed.insert(FEED_OPERATOR_INVITE_TTL.to_string(), bad.to_string());
            let refused = install(&stores, &feed).unwrap_err();
            assert!(
                refused.contains(FEED_OPERATOR_INVITE_TTL),
                "{bad:?}: {refused}"
            );
            assert!(first_invite(&stores).is_none(), "{bad:?}");
        }
    }
}