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

nordisk/gunnar

crates/gunnar-cli/tests/account_push_door.rs

#![cfg(feature = "server")]

//! **The first push names a repository too** (the owner's enterprise list,
//! 2026-10-05): a customer creates repositories in their own account with
//! `git push` as well as with `Repos.Create`, so the name filter stands at
//! the push door, and the creation is in the account's audit log. Stock
//! `git`, a real SSH connection, the account's own key.

mod common;

use common::{local_repo, tools_present, Harness};
use gunnar_core::account_audit::AuditQuery;
use gunnar_core::{HashKind, Principal, PrincipalKind};

/// `acme`, a person with an account, and an ssh command that signs as acme.
fn acme(harness: &Harness) -> String {
    harness
        .stores
        .auth()
        .add_principal(Principal::new("acme", "acme", PrincipalKind::User).expect("a person"))
        .expect("acme");
    harness
        .stores
        .catalog()
        .create_namespace("acme")
        .expect("acme's account namespace");
    let private = gunnar_core::mint_ed25519().expect("a key");
    let parsed = gunnar_core::ssh_key::PrivateKey::from_openssh(&private).expect("parses");
    let public = parsed.public_key().to_openssh().expect("openssh");
    harness
        .stores
        .auth()
        .register_key("acme", &public, None)
        .expect("acme's key");
    let path = harness.dir.path().join("acme_ed25519");
    std::fs::write(&path, &private).expect("write acme's key");
    #[cfg(unix)]
    {
        use std::os::unix::fs::PermissionsExt as _;
        std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o600)).expect("0600");
    }
    format!(
        "ssh -i {} -o IdentitiesOnly=yes -o IdentityAgent=none -o StrictHostKeyChecking=no \
         -o UserKnownHostsFile=/dev/null -o BatchMode=yes -o LogLevel=ERROR",
        path.display()
    )
}

#[test]
fn a_first_push_meets_the_name_filter_and_its_creation_is_in_the_accounts_log() {
    assert!(
        tools_present(),
        "this test requires `git` and `ssh` on PATH"
    );
    let harness = Harness::start_appliance_bootstrap();
    let as_acme = acme(&harness);
    let work = harness.dir.path().join("work");
    local_repo(&harness, &work, HashKind::Sha1, "acme's first bytes\n");

    // An offensive name: refused with gunnar's sentence, nothing made.
    let refused = harness.git_with_ssh(
        &work,
        &as_acme,
        &[
            "push",
            &harness.url("acme", "fuck-this"),
            "HEAD:refs/heads/main",
        ],
    );
    assert!(
        !refused.ok,
        "the push of an offensive name went through: {}",
        refused.stdout
    );
    assert!(
        refused.stderr.contains("is refused") && refused.stderr.contains("Choose another name"),
        "the pusher is not told why: {}",
        refused.stderr
    );
    assert!(
        harness
            .stores
            .catalog()
            .open(&gunnar_core::RepoRef::new("acme", "fuck-this").unwrap())
            .is_err(),
        "a repository was made under the refused name"
    );

    // A clean name: made, and in acme's log as acme's own act.
    harness
        .git_with_ssh(
            &work,
            &as_acme,
            &["push", &harness.url("acme", "site"), "HEAD:refs/heads/main"],
        )
        .expect_ok("acme's first push of a clean name");
    let log = harness
        .stores
        .account_audit()
        .query(
            "acme",
            &AuditQuery {
                limit: 50,
                ..AuditQuery::default()
            },
        )
        .expect("acme's log");
    let seen: Vec<String> = log
        .entries
        .iter()
        .map(|e| format!("{}:{}:{}:{}", e.kind, e.actor, e.actor_role, e.target))
        .collect();
    assert_eq!(
        seen,
        vec![
            "repo.created:acme:admin:acme/site",
            "name.refused:acme:admin:fuck-this"
        ],
        "{seen:#?}"
    );
    let queue = harness
        .stores
        .names()
        .reviews("acme")
        .expect("acme's queue");
    assert_eq!(
        queue.len(),
        1,
        "the refusal is noted for acme's admin: {queue:?}"
    );
}