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/tests/delete_retention_is_said.rs

//! **A client says "it can be restored for N days" with the server's N** (2026-10-28).
//!
//! The console's delete is a soft `Repos.Delete` with no window of its own, so the bytes
//! stay for the server's default retention. The console's confirm step names that number
//! before the person deletes anything, and it must be the server's number, not one the
//! console keeps: `Repos.ListDeleted` answers it beside the rows.

use std::sync::Arc;

use gunnar_core::{Principal, PrincipalKind};
use gunnar_grpc::{Caller, EventBus, ServerConfig, ServiceContext};
use gunnar_proto::repos_server::Repos as _;
use gunnar_proto::ListDeletedRequest;
use gunnar_server::stores::{ServerStores, DEFAULT_DELETE_RETENTION_DAYS};
use gunnar_server::CoreControlPlane;
use tonic::Request;

const NS: &str = "alice";

#[test]
fn list_deleted_names_the_default_retention_window() {
    let dir = tempfile::tempdir().expect("tempdir");
    let stores = Arc::new(ServerStores::open(dir.path()).expect("stores"));
    stores.catalog().create_namespace(NS).expect("namespace");
    stores
        .auth()
        .add_principal(Principal::new(NS, NS, PrincipalKind::User).expect("id"))
        .expect("alice");
    let plane: Arc<dyn gunnar_grpc::ControlPlane> =
        Arc::new(CoreControlPlane::new(Arc::clone(&stores)));
    let ctx = ServiceContext::new(plane, Arc::new(EventBus::new(16)), ServerConfig::default());
    let repos = gunnar_grpc::ReposService::new(ctx);
    let mut request = Request::new(ListDeletedRequest {
        namespace: NS.to_owned(),
    });
    request.extensions_mut().insert(Caller {
        principal_id: NS.to_owned(),
        fingerprint: "SHA256:test".to_owned(),
        machine: false,
        authenticated: true,
    });
    let rt = tokio::runtime::Builder::new_current_thread()
        .enable_all()
        .build()
        .expect("runtime");
    let answer = rt
        .block_on(repos.list_deleted(request))
        .expect("ListDeleted")
        .into_inner();
    assert!(answer.repos.is_empty());
    assert_eq!(
        answer.default_retention_days, DEFAULT_DELETE_RETENTION_DAYS,
        "ListDeleted does not say how long a delete keeps the bytes"
    );
    assert_eq!(DEFAULT_DELETE_RETENTION_DAYS, 30);
}