use std::collections::BTreeMap;
use std::sync::Arc;
use ed25519_dalek::{Signer, SigningKey};
use gunnar_common::monetize_key::MonetizePubkey;
use gunnar_core::{
EntitlementState, Level, NewRepo, Principal, PrincipalKind, RepoRef, Visibility,
};
use gunnar_grpc::{ControlError, ControlPlane as _};
use gunnar_proto::{EntitlementFact, EntitlementState as PbState};
use gunnar_server::attest::AttestationLog;
use gunnar_server::control_plane::CoreControlPlane;
use gunnar_server::entitlement::{EntitlementSlot, MeteredConfig};
use gunnar_server::stores::ServerStores;
use gunnar_ssh::command::{GitService, Operation};
use gunnar_ssh::server::{Dispatch, DispatchError};
use gunnar_ssh::PlanGate;
use monetize_embed::{State, TenantId};
const OCT_1_2026: u64 = 1_790_812_800_000;
const BILLING: &str = "https://gunnar.rs/billing/{tenant}";
const ISSUED_AT: u64 = 1_789_000_000_000;
const NO_CACHE: u64 = 1;
const DISK_LINE_PERCENT: u64 = 80;
fn disk_used_percent(dir: &std::path::Path) -> Option<u64> {
let s = rustix::fs::statvfs(dir).ok()?;
let used = s.f_blocks.saturating_sub(s.f_bfree);
let seen = used + s.f_bavail;
(seen > 0).then(|| used * 100 / seen)
}
struct Rig {
_dir: tempfile::TempDir,
stores: Arc<ServerStores>,
key: SigningKey,
forger: SigningKey,
config: MeteredConfig,
minted: std::sync::atomic::AtomicU64,
}
impl Rig {
fn new() -> Rig {
Rig::in_dir(tempfile::tempdir().expect("tempdir"))
}
fn under_the_disk_line() -> Rig {
let tmp = std::env::temp_dir();
let shm = std::path::Path::new("/dev/shm");
let under = |dir: &std::path::Path| {
disk_used_percent(dir).is_some_and(|used| used < DISK_LINE_PERCENT)
};
let dir = if !under(&tmp) && under(shm) {
tempfile::tempdir_in(shm).expect("tempdir in /dev/shm")
} else {
tempfile::tempdir().expect("tempdir")
};
Rig::in_dir(dir)
}
fn in_dir(dir: tempfile::TempDir) -> Rig {
let stores = Arc::new(ServerStores::open(dir.path()).expect("stores"));
let key = SigningKey::from_bytes(&[7u8; 32]);
let forger = SigningKey::from_bytes(&[9u8; 32]);
let pubkey = dir.path().join("monetize.pub");
std::fs::write(&pubkey, key.verifying_key().to_bytes()).expect("write key");
let config =
MeteredConfig::load(&MonetizePubkey::Path(pubkey), Some(BILLING)).expect("config");
Rig {
_dir: dir,
stores,
key,
forger,
config,
minted: std::sync::atomic::AtomicU64::new(0),
}
}
fn slot(&self) -> Arc<EntitlementSlot> {
EntitlementSlot::open(Arc::clone(&self.stores), &self.config).expect("slot")
}
fn plane(&self, slot: &Arc<EntitlementSlot>) -> CoreControlPlane {
CoreControlPlane::new(Arc::clone(&self.stores)).with_entitlement(Arc::clone(slot))
}
fn dispatch(&self, slot: &Arc<EntitlementSlot>) -> Dispatch {
Dispatch::new(
self.stores
.ssh_control()
.with_plan_gate(Arc::clone(slot) as Arc<dyn PlanGate>),
)
}
fn tenant(&self, ns: &str) -> Principal {
let owner = Principal {
id: ns.to_owned(),
name: ns.to_owned(),
kind: PrincipalKind::User,
created: 0,
};
self.stores
.auth()
.add_principal(owner.clone())
.expect("principal");
self.stores
.catalog()
.create_namespace(ns)
.expect("namespace");
let path = RepoRef::new(ns, "proj").expect("legal");
self.stores
.create_repo(NewRepo::new(path.clone()), false)
.expect("repo");
self.stores
.catalog()
.set_visibility(&path, Visibility::Public)
.expect("public");
owner
}
fn signed(
&self,
key: &SigningKey,
ns: &str,
state: State,
caps: &[(&str, u64)],
) -> EntitlementFact {
let issued = ISSUED_AT
+ self
.minted
.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
self.signed_at(key, ns, state, caps, Some(issued))
}
fn signed_at(
&self,
key: &SigningKey,
ns: &str,
state: State,
caps: &[(&str, u64)],
issued: Option<u64>,
) -> EntitlementFact {
let mut fact = monetize_embed::EntitlementFact {
tenant: TenantId(ns.to_owned()),
plan: "10gb".into(),
state,
paid_until_unix_ms: Some(OCT_1_2026),
caps: caps
.iter()
.map(|(k, v)| (k.to_string(), *v))
.collect::<BTreeMap<_, _>>(),
source: "payment:invoice:ocr-42".into(),
signature: vec![],
issued_unix_ms: issued,
issued_signature: vec![],
};
fact.signature = key
.sign(&monetize_embed::signing::fact_message(&fact))
.to_bytes()
.to_vec();
if issued.is_some() {
fact.issued_signature = key
.sign(&monetize_embed::signing::fact_message_issued(&fact))
.to_bytes()
.to_vec();
}
EntitlementFact {
namespace: fact.tenant.0,
plan: fact.plan,
state: match state {
State::Free => PbState::Free,
State::Paid => PbState::Paid,
State::Grace => PbState::Grace,
State::Suspended => PbState::Suspended,
State::Retention => PbState::Retention,
} as i32,
paid_until_unix_ms: fact.paid_until_unix_ms,
caps: fact.caps,
source: fact.source,
signature: fact.signature,
issued_unix_ms: fact.issued_unix_ms,
issued_signature: fact.issued_signature,
}
}
fn log_lines(&self) -> Vec<String> {
std::fs::read_to_string(self.stores.root().join(gunnar_server::ATTESTATION_LOG))
.map(|t| t.lines().map(str::to_owned).collect())
.unwrap_or_default()
}
}
fn repo(ns: &str) -> RepoRef {
RepoRef::new(ns, "proj").expect("legal")
}
#[test]
fn a_forged_fact_is_refused_by_name_and_nothing_moves() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
rig.tenant("team");
let forged = rig.signed(&rig.forger, "team", State::Paid, &[]);
let err = plane
.entitlement_set(forged)
.expect_err("a signature the monetize key did not make must be refused");
assert!(
matches!(err, ControlError::PermissionDenied(_)),
"a forged fact is PERMISSION_DENIED, not a stored fact: {err:?}"
);
assert!(
err.to_string().contains("does not verify") && err.to_string().contains("team"),
"the refusal names the reason and the tenant: {err}"
);
assert!(
rig.log_lines().is_empty(),
"a refused fact must not be logged as accepted: {:?}",
rig.log_lines()
);
assert_eq!(plane.entitlement_get("team").unwrap(), None);
assert!(plane.entitlement_list().unwrap().is_empty());
assert_eq!(slot.counts().paid, 0);
let mut edited = rig.signed(&rig.key, "team", State::Paid, &[]);
edited.state = PbState::Suspended as i32;
let err = plane
.entitlement_set(edited)
.expect_err("edited after signing");
assert!(matches!(err, ControlError::PermissionDenied(_)), "{err:?}");
assert!(rig.log_lines().is_empty());
let (state, seq) = plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[]))
.expect("a genuine fact is accepted");
assert_eq!(state, PbState::Paid);
assert_eq!(seq, 0, "the first line of an empty log is sequence 0");
let lines = rig.log_lines();
assert_eq!(lines.len(), 1, "exactly one attestation line: {lines:?}");
assert!(
lines[0].contains("\"entitlement\"")
&& lines[0].contains("\"tenant\":\"team\"")
&& lines[0].contains("\"source\":\"payment:invoice:ocr-42\"")
&& lines[0].contains("\"state\":\"Paid\""),
"the line carries the fact as monetize signed it: {}",
lines[0]
);
assert_eq!(
plane.entitlement_get("team").unwrap().map(|f| f.state),
Some(PbState::Paid as i32)
);
assert_eq!(slot.counts().paid, 1);
let log = AttestationLog::under(rig.stores.root());
assert!(log.read().expect("the push log still parses").is_empty());
}
#[test]
fn an_accepted_fact_survives_a_reload_and_a_tampered_document_does_not() {
let rig = Rig::new();
rig.tenant("team");
{
let slot = rig.slot();
let plane = rig.plane(&slot);
plane
.entitlement_set(rig.signed(
&rig.key,
"team",
State::Suspended,
&[("cache_bytes", 4096)],
))
.expect("accepted");
assert_eq!(
rig.stores
.catalog()
.namespace_explode_budget("team")
.unwrap(),
Some(NO_CACHE),
"a SUSPENDED fact does not get its plan's cache cap: the door refuses \
this tenant, so the budget is the floor and the 4096 in the fact is \
not applied (see cache_reclaim tests below)"
);
}
let reborn = rig.slot();
let plane = rig.plane(&reborn);
let facts = plane.entitlement_list().unwrap();
assert_eq!(facts.len(), 1, "{facts:?}");
assert_eq!(facts[0].state, PbState::Suspended as i32);
assert_eq!(reborn.counts().suspended, 1);
let dispatch = rig.dispatch(&reborn);
let owner = Principal {
id: "team".into(),
name: "team".into(),
kind: PrincipalKind::User,
created: 0,
};
let err = dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect_err("suspended after reload");
assert!(matches!(err, DispatchError::Plan { .. }), "{err:?}");
let store = gunnar_core::EntitlementStore::new(Arc::clone(rig.stores.control_store())).unwrap();
let mut stored = store.get("team").unwrap().unwrap();
stored.state = EntitlementState::Paid;
store.set(stored).unwrap();
let tampered = rig.slot();
assert_eq!(
tampered.verdict("team", gunnar_ssh::PlanAction::Write),
gunnar_ssh::PlanVerdict::Allow,
"an unverifiable fact is Free (allowed), not the Paid it claims"
);
assert_eq!(
tampered.counts().paid,
0,
"the counts are what is ENFORCED, and nothing is"
);
assert!(
tampered.enforced_state("team").is_none(),
"the cache holds NO fact for it: the tampered fact did not load"
);
}
#[test]
fn list_shows_the_latest_fact_per_namespace() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
rig.tenant("a");
rig.tenant("b");
plane
.entitlement_set(rig.signed(&rig.key, "a", State::Paid, &[]))
.unwrap();
plane
.entitlement_set(rig.signed(&rig.key, "b", State::Grace, &[]))
.unwrap();
let (_, seq) = plane
.entitlement_set(rig.signed(&rig.key, "a", State::Suspended, &[]))
.unwrap();
assert_eq!(seq, 2, "three accepted facts are three lines, 0..=2");
let facts = plane.entitlement_list().unwrap();
assert_eq!(facts.len(), 2, "one row per namespace: {facts:?}");
assert_eq!(
(facts[0].namespace.as_str(), facts[0].state),
("a", PbState::Suspended as i32)
);
assert_eq!(
(facts[1].namespace.as_str(), facts[1].state),
("b", PbState::Grace as i32)
);
let lines = rig.log_lines();
assert_eq!(
lines.len(),
4,
"the log keeps the history; List keeps the latest: {lines:?}"
);
assert_eq!(
lines
.iter()
.filter(|l| l.contains("\"cache_reclaim\""))
.count(),
1,
"one reclaim line, for the one namespace that fell to Suspended: {lines:?}"
);
let counts = slot.counts();
assert_eq!((counts.paid, counts.grace, counts.suspended), (0, 1, 1));
}
#[test]
fn a_plane_without_a_monetize_key_refuses_every_set_by_name() {
let rig = Rig::new();
let plane = CoreControlPlane::new(Arc::clone(&rig.stores));
let err = plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[]))
.expect_err("no key, no verification, no acceptance");
assert!(err.to_string().contains("--monetize-pubkey"), "{err}");
}
#[test]
fn a_suspended_push_is_refused_by_name_and_the_same_push_after_a_paid_fact_succeeds() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
let owner = rig.tenant("team");
let dispatch = rig.dispatch(&slot);
dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect("no fact at all: Free, push allowed");
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Suspended, &[]))
.unwrap();
let err = dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect_err("a Suspended tenant's push is refused");
let DispatchError::Plan { namespace, line } = &err else {
panic!("refused for the wrong reason: {err:?}");
};
assert_eq!(namespace, "team");
assert!(line.contains("expired 2026-10-01"), "the date: {line}");
assert!(
line.contains("writes closed"),
"the state, as what it means: {line}"
);
assert!(
line.ends_with("renew at https://gunnar.rs/billing/team"),
"the URL, naming the tenant: {line}"
);
assert_eq!(
err.client_message().as_deref(),
Some(line.as_str()),
"and the client is told exactly that"
);
let err = dispatch
.authorise_service(
&owner,
None,
GitService::LfsTransfer(Operation::Upload),
repo("team"),
)
.expect_err("LFS upload is a write");
assert!(matches!(err, DispatchError::Plan { .. }), "{err:?}");
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Retention, &[]))
.unwrap();
let err = dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect_err("Retention refuses writes");
let DispatchError::Plan { line, .. } = &err else {
panic!("{err:?}")
};
assert!(line.contains("data kept for export"), "{line}");
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[]))
.unwrap();
let request = dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect("Paid: the same push succeeds");
assert_eq!(request.access, Level::Admin);
assert_eq!(request.plan_notice, None, "Paid carries no warning");
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Grace, &[]))
.unwrap();
let request = dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect("Grace: allowed");
let notice = request.plan_notice.expect("Grace carries the warning line");
assert!(
notice.contains("expired 2026-10-01")
&& notice.ends_with("renew at https://gunnar.rs/billing/team"),
"{notice}"
);
}
#[test]
fn the_owner_always_clones_and_anonymous_is_closed_when_suspended() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
let owner = rig.tenant("team");
let dispatch = rig.dispatch(&slot);
let anonymous = Principal::anonymous();
dispatch
.authorise_service(&anonymous, None, GitService::UploadPack, repo("team"))
.expect("Free: anonymous ls-refs/clone of a Public repo");
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Suspended, &[]))
.unwrap();
let request = dispatch
.authorise_service(&owner, None, GitService::UploadPack, repo("team"))
.expect("the owner clones from a Suspended namespace");
assert_eq!(request.plan_notice, None);
dispatch
.authorise_service(
&owner,
None,
GitService::LfsTransfer(Operation::Download),
repo("team"),
)
.expect("…and downloads their LFS objects");
let err = dispatch
.authorise_service(&anonymous, None, GitService::UploadPack, repo("team"))
.expect_err("anonymous ls-refs on a Suspended public repo is refused");
let DispatchError::Plan { line, .. } = &err else {
panic!("{err:?}")
};
assert!(line.contains("anonymous access closed"), "{line}");
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[]))
.unwrap();
dispatch
.authorise_service(&anonymous, None, GitService::UploadPack, repo("team"))
.expect("Paid: anonymous read allowed again");
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Suspended, &[]))
.unwrap();
let machine = Principal {
id: "replicator".into(),
name: "replicator".into(),
kind: PrincipalKind::Machine,
created: 0,
};
rig.stores.auth().add_principal(machine.clone()).unwrap();
rig.stores
.auth()
.grant(gunnar_core::Grant {
principal: "replicator".into(),
scope: gunnar_core::Scope::Server,
level: Level::Write,
})
.unwrap();
dispatch
.authorise_service(&machine, None, GitService::ReceivePack, repo("team"))
.expect("replication into a Suspended namespace is not a tenant write");
}
#[test]
fn a_push_at_the_pack_quota_is_refused_before_the_bytes_and_under_it_is_not() {
use gunnar_store::conformance::pack::PackBuilder;
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
let owner = rig.tenant("team");
let dispatch = rig.dispatch(&slot);
let repo_row = rig.stores.catalog().get(&repo("team")).unwrap().unwrap();
let handle = rig.stores.repo_store(&repo_row).unwrap();
let mut pb = PackBuilder::new(gix_hash::Kind::Sha256);
pb.object(gix_object::Kind::Blob, vec![b'q'; 200_000]);
handle.serve().put_pack(&pb.build().unwrap().bytes).unwrap();
drop(handle);
rig.stores.close_repo(&repo("team"));
let held = plane.usage(Some("team")).unwrap()[0].pack_bytes;
assert!(held > 200_000, "the fixture is on disk: {held}");
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[("pack_bytes", held - 1)]))
.unwrap();
let err = dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect_err("at the quota: refused before any byte");
let DispatchError::Plan { line, .. } = &err else {
panic!("{err:?}")
};
assert!(
line.contains("pack quota") && line.contains(&format!("{held} of {} bytes", held - 1)),
"{line}"
);
assert!(line.ends_with("https://gunnar.rs/billing/team"), "{line}");
dispatch
.authorise_service(&owner, None, GitService::UploadPack, repo("team"))
.expect("a full tenant still clones");
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[("pack_bytes", held + 1)]))
.unwrap();
dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect("under the cap: allowed");
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[("pack_bytes", 0)]))
.unwrap();
dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect("0 is unlimited");
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Suspended, &[("pack_bytes", 1)]))
.unwrap();
let err = dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.unwrap_err();
let DispatchError::Plan { line, .. } = &err else {
panic!("{err:?}")
};
assert!(
line.contains("writes closed") && !line.contains("quota"),
"{line}"
);
}
#[test]
fn at_a_selling_estate_a_person_with_no_fact_pushes_nothing_until_its_fact_lands() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
let owner = rig.tenant("team");
let dispatch = rig.dispatch(&slot);
dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect("nothing fed: no fact is uncapped, as always");
slot.sells_room_flag()
.store(true, std::sync::atomic::Ordering::Relaxed);
let err = dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect_err("a selling estate: no room yet");
let DispatchError::Plan { line, .. } = &err else {
panic!("{err:?}")
};
assert!(
line.starts_with(gunnar_grpc::selling::NO_ROOM_YET)
&& line.ends_with("https://gunnar.rs/billing/team"),
"{line}"
);
dispatch
.authorise_service(&owner, None, GitService::UploadPack, repo("team"))
.expect("a clone is never refused");
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[("pack_bytes", 10 << 30)]))
.unwrap();
dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect("its fact rules");
let op = rig.tenant("nordisk");
rig.stores
.auth()
.grant(gunnar_core::Grant {
principal: "nordisk".into(),
scope: gunnar_core::Scope::Server,
level: Level::Admin,
})
.unwrap();
dispatch
.authorise_service(&op, None, GitService::ReceivePack, repo("nordisk"))
.expect("the seller's own namespace");
}
#[test]
fn a_capped_tenant_carries_a_byte_ceiling_into_the_transfer() {
use gunnar_server::entitlement::{PACK_CEILING_SLACK_DIVISOR, PACK_CEILING_SLACK_FLOOR_BYTES};
use gunnar_store::conformance::pack::PackBuilder;
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
let owner = rig.tenant("team");
let dispatch = rig.dispatch(&slot);
let repo_row = rig.stores.catalog().get(&repo("team")).unwrap().unwrap();
let handle = rig.stores.repo_store(&repo_row).unwrap();
let mut pb = PackBuilder::new(gix_hash::Kind::Sha256);
pb.object(gix_object::Kind::Blob, vec![b'q'; 200_000]);
handle.serve().put_pack(&pb.build().unwrap().bytes).unwrap();
drop(handle);
rig.stores.close_repo(&repo("team"));
let held = plane.usage(Some("team")).unwrap()[0].pack_bytes;
assert!(held > 200_000, "the fixture is on disk: {held}");
let cap = 10 * 1024 * 1024 * 1024u64; plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[("pack_bytes", cap)]))
.unwrap();
let request = dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect("under the cap: allowed");
let ceiling = request
.pack_ceiling
.expect("a capped tenant's push must carry a ceiling into the transfer");
let slack = cap / PACK_CEILING_SLACK_DIVISOR;
assert!(
slack > PACK_CEILING_SLACK_FLOOR_BYTES,
"this half of the test is about the proportional term winning"
);
assert_eq!(
ceiling.bytes,
(cap - held) + slack,
"the ceiling is the room left under the cap plus its slack"
);
assert_ne!(
ceiling.bytes,
cap - held,
"a ceiling with no slack cuts the push that would have landed exactly at the cap"
);
assert_ne!(
ceiling.bytes,
cap + slack,
"the ceiling ignored what the namespace already holds"
);
assert!(
ceiling.refusal.contains("pack quota")
&& ceiling.refusal.contains(&cap.to_string())
&& ceiling.refusal.contains(&held.to_string()),
"{}",
ceiling.refusal
);
assert!(
ceiling.refusal.ends_with("https://gunnar.rs/billing/team"),
"a refusal that does not say where to pay: {}",
ceiling.refusal
);
let small = 256 * 1024 * 1024u64;
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[("pack_bytes", small)]))
.unwrap();
let request = dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect("allowed");
assert_eq!(
request.pack_ceiling.expect("a ceiling").bytes,
(small - held) + PACK_CEILING_SLACK_FLOOR_BYTES,
"under a small cap the absolute floor is the slack, not cap/{PACK_CEILING_SLACK_DIVISOR}"
);
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[("pack_bytes", 0)]))
.unwrap();
assert_eq!(
dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect("0 is unlimited")
.pack_ceiling,
None,
"an uncapped plan must not carry a ceiling"
);
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[("pack_bytes", cap)]))
.unwrap();
assert_eq!(
dispatch
.authorise_service(&owner, None, GitService::UploadPack, repo("team"))
.expect("a clone")
.pack_ceiling,
None,
"a read carries no byte ceiling: nothing it does grows the tenant's data"
);
}
#[test]
fn admin_stats_counts_the_tenants_by_enforced_state() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
for ns in ["a", "b", "c", "d"] {
rig.tenant(ns);
}
plane
.entitlement_set(rig.signed(&rig.key, "a", State::Paid, &[]))
.unwrap();
plane
.entitlement_set(rig.signed(&rig.key, "b", State::Grace, &[]))
.unwrap();
plane
.entitlement_set(rig.signed(&rig.key, "c", State::Suspended, &[]))
.unwrap();
plane
.entitlement_set(rig.signed(&rig.key, "d", State::Retention, &[]))
.unwrap();
let extras = plane.stats_extras().unwrap();
assert_eq!(
(
extras.tenants_paid,
extras.tenants_grace,
extras.tenants_suspended
),
(1, 1, 2),
"paid 1, grace 1, suspended 2 (Suspended + Retention)"
);
let view = gunnar_server::dashboard::TenantView::new();
let for_band = Arc::clone(&slot);
view.fill(move || for_band.counts());
assert_eq!(
view.counts(),
Some(gunnar_server::dashboard::TenantCounts {
paid: 1,
grace: 1,
suspended: 2
})
);
let bare = CoreControlPlane::new(Arc::clone(&rig.stores))
.stats_extras()
.unwrap();
assert_eq!(
(
bare.tenants_paid,
bare.tenants_grace,
bare.tenants_suspended
),
(0, 0, 0)
);
}
#[test]
fn the_metered_front_door_carries_the_disk_gate_first_and_the_plan_gate_second() {
use gunnar_ssh::{DiskFloor, DiskHeadroomGate};
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
let owner = rig.tenant("team");
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Suspended, &[]))
.unwrap();
let gate = |bytes: u64| {
Arc::new(DiskHeadroomGate::new(
rig.stores.root(),
DiskFloor { percent: 0, bytes },
))
};
let control = gunnar_server::serve::front_control(
&rig.stores,
Default::default(),
gate(u64::MAX),
Some(&slot),
);
assert_eq!(
control
.plan_gates()
.iter()
.map(|g| g.name())
.collect::<Vec<_>>(),
["disk-headroom", "entitlement"],
"two links, disk first: {control:?}"
);
let err = Dispatch::new(control)
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect_err("refused");
let DispatchError::Plan { line, .. } = &err else {
panic!("{err:?}")
};
assert!(
line.starts_with(gunnar_ssh::AT_FLOOR) && !line.contains("renew at"),
"a full disk is told about the disk, not the plan: {line}"
);
let control =
gunnar_server::serve::front_control(&rig.stores, Default::default(), gate(1), Some(&slot));
let err = Dispatch::new(control)
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect_err("still refused — by the plan");
let DispatchError::Plan { line, .. } = &err else {
panic!("{err:?}")
};
assert!(
line.ends_with("renew at https://gunnar.rs/billing/team"),
"with room, the plan's line: {line}"
);
let control =
gunnar_server::serve::front_control(&rig.stores, Default::default(), gate(u64::MAX), None);
assert_eq!(
control
.plan_gates()
.iter()
.map(|g| g.name())
.collect::<Vec<_>>(),
["disk-headroom"]
);
}
#[test]
fn a_key_given_inline_accepts_the_signer_and_refuses_a_forger() {
let dir = tempfile::tempdir().expect("tempdir");
let stores = Arc::new(ServerStores::open(dir.path()).expect("stores"));
let key = SigningKey::from_bytes(&[7u8; 32]);
let forger = SigningKey::from_bytes(&[9u8; 32]);
let hex: String = key
.verifying_key()
.to_bytes()
.iter()
.map(|b| format!("{b:02x}"))
.collect();
assert_eq!(hex.len(), 64, "the cmdline spelling is 64 hex characters");
let inline: MonetizePubkey = hex.parse().expect("the hex key parses");
let config = MeteredConfig::load(&inline, Some(BILLING)).expect("an inline key needs no file");
assert_eq!(
config.monetize_pubkey,
Some(key.verifying_key().to_bytes()),
"the inline key must be the signer's 32 verifying-key bytes"
);
let rig = Rig {
_dir: dir,
stores,
key,
forger,
config,
minted: std::sync::atomic::AtomicU64::new(0),
};
let slot = rig.slot();
let fact = rig.signed(&rig.key, "acme", State::Paid, &[("cache_bytes", 1 << 30)]);
slot.set(fact)
.expect("a fact signed by the inline key is accepted");
assert_eq!(
slot.enforced_state("acme"),
Some(EntitlementState::Paid),
"the plan must have moved — an accepted fact that changes nothing is not acceptance"
);
let forged = rig.signed(&rig.forger, "acme", State::Suspended, &[]);
slot.set(forged)
.expect_err("a fact signed by another key must be refused");
assert_eq!(
slot.enforced_state("acme"),
Some(EntitlementState::Paid),
"the forged fact must not have moved the plan"
);
}
fn usage_read_as(
plane: CoreControlPlane,
principal: &str,
namespace: &str,
) -> Result<gunnar_proto::ReadUsageResponse, tonic::Status> {
use gunnar_proto::usage_server::Usage as _;
let control: Arc<dyn gunnar_grpc::ControlPlane> = Arc::new(plane);
let service = gunnar_grpc::UsageService::new(gunnar_grpc::ServiceContext::new(
control,
Arc::new(gunnar_grpc::EventBus::new(16)),
gunnar_grpc::ServerConfig::default(),
));
let mut request = tonic::Request::new(gunnar_proto::ReadUsageRequest {
namespace: namespace.to_owned(),
});
request.extensions_mut().insert(gunnar_grpc::Caller {
principal_id: principal.to_owned(),
fingerprint: "SHA256:test".to_owned(),
machine: false,
authenticated: true,
});
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.expect("runtime")
.block_on(service.read(request))
.map(tonic::Response::into_inner)
}
#[test]
fn a_tenants_cap_is_on_their_own_usage_read_and_a_tenant_without_a_fact_is_uncapped() {
let rig = Rig::new();
let slot = rig.slot();
rig.tenant("alice");
rig.tenant("bob");
rig.plane(&slot)
.entitlement_set(rig.signed(
&rig.key,
"alice",
State::Paid,
&[("pack_bytes", 7_340_032), ("cache_bytes", 1_572_864)],
))
.expect("alice's fact");
let hers = usage_read_as(rig.plane(&slot), "alice", "alice").expect("alice reads alice");
let allowance = hers.allowance.expect("the allowance is always present");
assert_eq!(allowance.pack_bytes, Some(7_340_032), "pack_bytes cap");
assert_eq!(allowance.cache_bytes, Some(1_572_864), "cache_bytes cap");
for (meter, cap) in [
("cold_bytes", allowance.cold_bytes),
("lfs_bytes", allowance.lfs_bytes),
("tombstoned_bytes", allowance.tombstoned_bytes),
("repos", allowance.repos),
("objects", allowance.objects),
] {
assert!(
cap.is_none(),
"{meter}: the fact names no cap, so none is reported — not {cap:?}"
);
}
assert_eq!(hers.usage.expect("meters").namespace, "alice");
let his = usage_read_as(rig.plane(&slot), "bob", "bob").expect("bob reads bob");
assert_eq!(
his.allowance.expect("present"),
gunnar_proto::Allowance {
enforcement: gunnar_grpc::service::meters::enforcement(),
..gunnar_proto::Allowance::default()
},
"bob has no fact: every cap absent"
);
let refused =
usage_read_as(rig.plane(&slot), "bob", "alice").expect_err("bob may not read alice");
assert_eq!(refused.code(), tonic::Code::PermissionDenied, "{refused:?}");
}
#[test]
fn what_is_left_under_each_cap_is_on_the_tenants_own_usage_read() {
let rig = Rig::new();
let slot = rig.slot();
rig.tenant("alice");
rig.tenant("bob");
rig.plane(&slot)
.entitlement_set(rig.signed(
&rig.key,
"alice",
State::Paid,
&[("pack_bytes", 7_340_032), ("cache_bytes", 1_572_864)],
))
.expect("alice's fact");
let hers = usage_read_as(rig.plane(&slot), "alice", "alice").expect("alice reads alice");
let held = hers.usage.clone().expect("meters");
let left = hers.remaining.expect("remaining is always present");
assert_eq!(left.pack_bytes, Some(7_340_032 - held.pack_bytes));
assert_eq!(left.cache_bytes, Some(1_572_864 - held.cache_bytes));
for (meter, value) in [
("cold_bytes", left.cold_bytes),
("lfs_bytes", left.lfs_bytes),
("tombstoned_bytes", left.tombstoned_bytes),
("repos", left.repos),
("objects", left.objects),
] {
assert!(
value.is_none(),
"{meter} is uncapped, so nothing is 'remaining': {value:?}"
);
}
let his = usage_read_as(rig.plane(&slot), "bob", "bob").expect("bob reads bob");
assert_eq!(his.remaining, Some(gunnar_proto::Remaining::default()));
}
#[test]
fn a_cap_of_zero_is_reported_as_absent_because_the_door_reads_it_as_unlimited() {
let rig = Rig::new();
let slot = rig.slot();
rig.tenant("team");
rig.plane(&slot)
.entitlement_set(rig.signed(
&rig.key,
"team",
State::Paid,
&[("pack_bytes", 0), ("cache_bytes", 4096)],
))
.expect("the fact");
let allowance = usage_read_as(rig.plane(&slot), "team", "team")
.expect("read")
.allowance
.expect("present");
assert_eq!(
allowance.pack_bytes, None,
"a 0 cap is the door's 'unlimited' and must be ABSENT here, not Some(0)"
);
assert_eq!(allowance.cache_bytes, Some(4096));
}
#[test]
fn a_metered_server_without_a_monetize_key_still_answers_usage_read_uncapped() {
let rig = Rig::new();
rig.tenant("team");
let keyless = CoreControlPlane::new(Arc::clone(&rig.stores));
let answer = usage_read_as(keyless, "team", "team")
.expect("a keyless metered server reads meters; it simply holds no caps");
assert_eq!(
answer.allowance.expect("present"),
gunnar_proto::Allowance {
enforcement: gunnar_grpc::service::meters::enforcement(),
..gunnar_proto::Allowance::default()
}
);
assert_eq!(answer.usage.expect("meters").namespace, "team");
}
#[test]
fn a_capped_tenants_lfs_upload_carries_the_rooms_left_into_the_transfer() {
use std::io::Write as _;
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
let owner = rig.tenant("team");
let dispatch = rig.dispatch(&slot);
const PAYLOAD: &[u8] = b"an lfs object that is really on the disk\n";
let repo_row = rig.stores.catalog().get(&repo("team")).unwrap().unwrap();
let handle = rig.stores.repo_store(&repo_row).unwrap();
let lfs = gunnar_lfs::FsLfsStore::open_or_init(handle.git_dir()).unwrap();
let mut hasher = gix_hash::hasher(gix_hash::Kind::Sha256);
hasher.update(PAYLOAD);
let oid = match hasher.try_finalize().unwrap() {
gix_hash::ObjectId::Sha256(d) => gunnar_lfs::Oid::from_digest(d),
other => unreachable!("{other:?}"),
};
use gunnar_lfs::LfsStore as _;
let mut pending = lfs.begin_write(&oid, PAYLOAD.len() as u64).unwrap();
pending.write_all(PAYLOAD).unwrap();
pending.commit().unwrap();
drop(lfs);
drop(handle);
rig.stores.close_repo(&repo("team"));
let held = plane.usage(Some("team")).unwrap()[0].lfs_bytes;
assert!(
held >= PAYLOAD.len() as u64,
"the fixture must be on disk and in the meter: {held}"
);
let cap = 10 * 1024 * 1024 * 1024u64;
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[("lfs_bytes", cap)]))
.unwrap();
let request = dispatch
.authorise_service(
&owner,
None,
GitService::LfsTransfer(Operation::Upload),
repo("team"),
)
.expect("under the cap: allowed");
let namespace_allowance = request
.lfs_allowance
.expect("a capped tenant's lfs upload must carry its room into the transfer");
let allowance = namespace_allowance.allowance();
assert_eq!(
allowance.bytes,
cap - held,
"the room is the cap minus what is held, EXACTLY — an LFS object is \
stored raw and its size is declared before the payload, so there is \
none of the wire-versus-stored uncertainty the pack ceiling adds slack \
for"
);
assert_ne!(allowance.bytes, cap, "the allowance ignored what is held");
assert!(
!allowance.refusal.is_empty()
&& allowance.refusal.contains("lfs room left")
&& allowance.refusal.contains(&cap.to_string())
&& allowance.refusal.contains(&held.to_string()),
"the sentence a tenant reads must name the cap and what is held: {}",
allowance.refusal
);
assert!(
allowance
.refusal
.ends_with("https://gunnar.rs/billing/team"),
"a refusal that does not say where to pay: {}",
allowance.refusal
);
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[("lfs_bytes", 0)]))
.unwrap();
assert!(
dispatch
.authorise_service(
&owner,
None,
GitService::LfsTransfer(Operation::Upload),
repo("team")
)
.expect("0 is unlimited")
.lfs_allowance
.is_none(),
"an uncapped plan must not carry an lfs allowance"
);
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[("lfs_bytes", cap)]))
.unwrap();
assert!(
dispatch
.authorise_service(
&owner,
None,
GitService::LfsTransfer(Operation::Download),
repo("team")
)
.expect("a download")
.lfs_allowance
.is_none(),
"a download carries no allowance: nothing it does grows the tenant's data"
);
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[("pack_bytes", cap)]))
.unwrap();
assert!(
dispatch
.authorise_service(
&owner,
None,
GitService::LfsTransfer(Operation::Upload),
repo("team")
)
.expect("allowed")
.lfs_allowance
.is_none(),
"a pack_bytes cap must not become an lfs_bytes wall behind the tenant's back"
);
}
#[test]
fn a_metered_build_without_a_lapse_url_refuses_at_boot() {
let dir = tempfile::tempdir().expect("tempdir");
let key = SigningKey::from_bytes(&[7u8; 32]);
let pubkey = dir.path().join("monetize.pub");
std::fs::write(&pubkey, key.verifying_key().to_bytes()).expect("write key");
let refusal = MeteredConfig::load(&MonetizePubkey::Path(pubkey.clone()), None)
.expect_err("a metered build with no lapse URL must not start")
.to_string();
assert!(
refusal.contains("--billing-url"),
"the refusal must name the flag the operator has to add: {refusal}"
);
assert!(
refusal.contains("--monetize-pubkey"),
"and the flag whose presence made it required: {refusal}"
);
assert!(
!refusal.contains("gunnar.rs"),
"and it must NOT quietly suggest the URL it just refused to invent: {refusal}"
);
let ok = MeteredConfig::load(&MonetizePubkey::Path(pubkey), Some(BILLING))
.expect("the same key with a URL loads");
assert_eq!(ok.billing_url, BILLING);
}
#[test]
fn the_sites_fed_pay_page_replaces_the_mediums_in_every_refusal() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
let owner = rig.tenant("team");
let dispatch = rig.dispatch(&slot);
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Suspended, &[]))
.unwrap();
let refused = |dispatch: &Dispatch| match dispatch.authorise_service(
&owner,
None,
GitService::ReceivePack,
repo("team"),
) {
Err(DispatchError::Plan { line, .. }) => line,
other => panic!("a Suspended push is refused by the plan: {other:?}"),
};
assert!(
refused(&dispatch).ends_with("renew at https://gunnar.rs/billing/team"),
"the medium's page before any feed"
);
assert_eq!(
slot.set_billing_url("https://test2.gunnar.rs/billing/{tenant}"),
Ok(true),
"a new page is taken"
);
let line = refused(&dispatch);
assert!(
line.ends_with("renew at https://test2.gunnar.rs/billing/team"),
"the site's own page, naming the tenant: {line}"
);
assert_eq!(
slot.set_billing_url("https://test2.gunnar.rs/billing/{tenant}"),
Ok(false),
"the same page: nothing moves"
);
assert_eq!(
slot.set_billing_url("https://test2.gunnar.rs/billing"),
Ok(false),
"`/{{tenant}}` appended, as the flag's: the same page"
);
let err = slot
.set_billing_url("http://test2.gunnar.rs/billing/{tenant}")
.expect_err("not https");
assert!(
err.contains(gunnar_server::feed::FEED_BILLING_URL) && err.contains("https"),
"refused by name: {err}"
);
assert!(
refused(&dispatch).ends_with("https://test2.gunnar.rs/billing/team"),
"a refused page leaves the one in force"
);
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Grace, &[]))
.unwrap();
let request = dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect("Grace: allowed");
assert!(request
.plan_notice
.expect("Grace warns")
.ends_with("renew at https://test2.gunnar.rs/billing/team"));
}
fn reclaim_lines(rig: &Rig, ns: &str) -> Vec<serde_json::Value> {
rig.log_lines()
.iter()
.filter_map(|line| serde_json::from_str::<serde_json::Value>(line).ok())
.filter_map(|value| value.get("cache_reclaim").cloned())
.filter(|record| record.get("namespace").and_then(|n| n.as_str()) == Some(ns))
.collect()
}
#[test]
fn a_suspended_namespaces_budget_is_the_floor_and_never_the_zero_that_means_unlimited() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
rig.tenant("lapsed");
plane
.entitlement_set(rig.signed(&rig.key, "lapsed", State::Paid, &[("cache_bytes", 8 << 30)]))
.expect("paid");
assert_eq!(
rig.stores
.catalog()
.namespace_explode_budget("lapsed")
.unwrap(),
Some(8 << 30),
"a paying tenant is on their plan's number"
);
plane
.entitlement_set(rig.signed(
&rig.key,
"lapsed",
State::Suspended,
&[("cache_bytes", 8 << 30)],
))
.expect("suspended");
let budget = rig
.stores
.catalog()
.namespace_explode_budget("lapsed")
.unwrap();
assert_ne!(
budget,
Some(0),
"0 is UNLIMITED at every layer; a suspended tenant on 0 would hold an \
unbounded cache, which is the opposite of a reclaim"
);
assert_eq!(
budget,
Some(NO_CACHE),
"the floor the type can express, and no more"
);
}
#[test]
fn retention_reclaims_exactly_as_suspended_does() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
rig.tenant("gone");
plane
.entitlement_set(rig.signed(
&rig.key,
"gone",
State::Retention,
&[("cache_bytes", 1 << 30)],
))
.expect("retention");
assert_eq!(
rig.stores
.catalog()
.namespace_explode_budget("gone")
.unwrap(),
Some(NO_CACHE)
);
let records = reclaim_lines(&rig, "gone");
assert_eq!(records.len(), 1, "one reclaim line: {records:?}");
assert_eq!(records[0]["state"], "Retention");
}
#[test]
fn grace_keeps_its_cache_and_journals_no_reclaim() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
rig.tenant("late");
plane
.entitlement_set(rig.signed(&rig.key, "late", State::Grace, &[("cache_bytes", 2 << 30)]))
.expect("grace");
assert_eq!(
rig.stores
.catalog()
.namespace_explode_budget("late")
.unwrap(),
Some(2 << 30),
"a tenant in Grace keeps the plan's cache: they are expected back"
);
assert!(
reclaim_lines(&rig, "late").is_empty(),
"Grace reclaims nothing, so there is nothing to journal: {:?}",
rig.log_lines()
);
plane
.entitlement_set(rig.signed(
&rig.key,
"late",
State::Suspended,
&[("cache_bytes", 2 << 30)],
))
.expect("suspended");
assert_eq!(
rig.stores
.catalog()
.namespace_explode_budget("late")
.unwrap(),
Some(NO_CACHE)
);
assert_eq!(reclaim_lines(&rig, "late").len(), 1);
}
#[test]
fn paying_again_restores_the_budget_from_the_facts_own_caps() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
rig.tenant("back");
rig.tenant("plain");
plane
.entitlement_set(rig.signed(
&rig.key,
"back",
State::Suspended,
&[("cache_bytes", 4 << 30)],
))
.expect("suspended");
assert_eq!(
rig.stores
.catalog()
.namespace_explode_budget("back")
.unwrap(),
Some(NO_CACHE)
);
plane
.entitlement_set(rig.signed(&rig.key, "back", State::Paid, &[("cache_bytes", 3 << 30)]))
.expect("paid again");
assert_eq!(
rig.stores
.catalog()
.namespace_explode_budget("back")
.unwrap(),
Some(3 << 30),
"restored from THIS fact's caps, not from the one before it and not from a constant"
);
plane
.entitlement_set(rig.signed(&rig.key, "plain", State::Suspended, &[]))
.expect("suspended");
assert_eq!(
rig.stores
.catalog()
.namespace_explode_budget("plain")
.unwrap(),
Some(NO_CACHE)
);
plane
.entitlement_set(rig.signed(&rig.key, "plain", State::Paid, &[]))
.expect("paid again");
assert_eq!(
rig.stores
.catalog()
.namespace_explode_budget("plain")
.unwrap(),
None,
"a plan with no cache cap goes back to the server's default, not to our floor"
);
}
#[test]
fn the_restore_does_not_clear_a_quota_the_operator_set_by_hand() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
rig.tenant("hand");
rig.stores
.catalog()
.set_namespace_explode_budget("hand", Some(512 << 20))
.expect("operator quota");
plane
.entitlement_set(rig.signed(&rig.key, "hand", State::Paid, &[]))
.expect("paid");
assert_eq!(
rig.stores
.catalog()
.namespace_explode_budget("hand")
.unwrap(),
Some(512 << 20),
"a plan change with no cache cap is not entitled to clear an operator's quota"
);
}
#[test]
fn the_reclaim_is_journalled_by_namespace_and_the_push_log_still_parses() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
rig.tenant("one");
rig.tenant("two");
plane
.entitlement_set(rig.signed(&rig.key, "one", State::Suspended, &[]))
.expect("suspended");
plane
.entitlement_set(rig.signed(&rig.key, "two", State::Suspended, &[]))
.expect("suspended");
for ns in ["one", "two"] {
let records = reclaim_lines(&rig, ns);
assert_eq!(
records.len(),
1,
"one line per namespace, not one for the box: {records:?}"
);
let record = &records[0];
assert_eq!(record["state"], "Suspended");
assert_eq!(record["budget_bytes"], NO_CACHE);
assert_eq!(
record["repos"], 1,
"the namespace's one repository was looked at: {record}"
);
assert_eq!(
record["bytes_freed"], 0,
"no store is open in this rig, so 0 is the honest number and it is written \
rather than omitted: {record}"
);
}
let log = AttestationLog::under(rig.stores.root());
assert!(
log.read()
.expect("the push log still parses past the reclaim lines")
.is_empty(),
"there were no pushes; the four non-push lines must not become four errors"
);
assert_eq!(rig.log_lines().len(), 4, "two facts and two reclaims");
}
#[test]
fn an_open_store_gives_its_derived_bytes_back_and_the_journal_carries_the_number() {
use gunnar_store::conformance::pack::PackBuilder;
let rig = Rig::under_the_disk_line();
let full = disk_used_percent(rig._dir.path());
assert!(
full.is_some_and(|used| used < DISK_LINE_PERCENT),
"this rig's store sits on a filesystem {full:?} % full, at or past the read cache's \
{DISK_LINE_PERCENT} % disk line: the cache rightly refuses every write-back there"
);
let slot = rig.slot();
let plane = rig.plane(&slot);
rig.tenant("busy");
let path = repo("busy");
let repo_row = rig
.stores
.catalog()
.get(&path)
.expect("row")
.expect("exists");
let handle = rig.stores.repo_store(&repo_row).expect("open");
let mut pb = PackBuilder::new(gix_hash::Kind::Sha256);
for chain in 0..40u32 {
let mut body = vec![b'a' + (chain % 26) as u8; 64 * 1024];
body[..4].copy_from_slice(&chain.to_le_bytes());
let mut at = pb.object(gix_object::Kind::Blob, body.clone());
for link in 0..6u32 {
body[4..8].copy_from_slice(&link.to_le_bytes());
at = pb.delta(at, body.clone());
}
}
let fixture = pb.build().expect("pack");
let oids = fixture.ids();
handle.serve().put_pack(&fixture.bytes).expect("put_pack");
handle.serve().index_now().expect("index");
for _ in 0..2 {
for oid in &oids {
let got = handle
.serve()
.read(oid.as_bytes())
.expect("read")
.expect("present");
assert_eq!(got.1.len(), 64 * 1024);
}
}
let cached = rig
.stores
.engine()
.explode_use()
.into_iter()
.find(|(dir, _)| dir == handle.git_dir())
.map(|(_, band)| band.used())
.unwrap_or(0);
assert!(
cached > 0,
"the reads must have produced a cache, or the reclaim below measures nothing"
);
plane
.entitlement_set(rig.signed(&rig.key, "busy", State::Suspended, &[]))
.expect("suspended");
let records = reclaim_lines(&rig, "busy");
assert_eq!(records.len(), 1, "{records:?}");
let freed = records[0]["bytes_freed"].as_u64().expect("a number");
assert!(
freed > 0,
"an OPEN store's derived cache must come back as bytes, not as an intention: {}",
records[0]
);
assert_eq!(records[0]["repos_reclaimed"], 1);
assert_eq!(
freed, cached,
"every derived byte the store was holding came back: {}",
records[0]
);
let after = rig
.stores
.engine()
.explode_use()
.into_iter()
.find(|(dir, _)| dir == handle.git_dir())
.map(|(_, band)| band.used())
.unwrap_or(0);
assert_eq!(
after, 0,
"and the store is no longer holding it — the reclaim was applied, not reported"
);
for oid in &oids {
let got = handle
.serve()
.read(oid.as_bytes())
.expect("read")
.expect("still present");
assert_eq!(
got.1.len(),
64 * 1024,
"a reclaim that lost an object is a data loss bug"
);
}
}
#[test]
fn a_captured_paid_fact_is_refused_after_the_tenant_lapsed() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
let owner = rig.tenant("team");
let dispatch = rig.dispatch(&slot);
let captured = rig.signed(&rig.key, "team", State::Paid, &[]);
plane
.entitlement_set(captured.clone())
.expect("Paid is accepted");
dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect("Paid: the push goes through");
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Suspended, &[]))
.expect("Suspended is accepted");
dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect_err("Suspended: the push is refused");
let refused = plane
.entitlement_set(captured)
.expect_err("a fact this box has already moved past is not accepted a second time");
let message = format!("{refused:?}");
assert!(
message.contains("team"),
"the refusal names the namespace: {message}"
);
dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect_err("the replay did not restore the write door");
assert_eq!(
slot.enforced_state("team"),
Some(EntitlementState::Suspended),
"the box still enforces the lapse"
);
}
#[test]
fn the_same_fact_pushed_again_is_idempotent_and_is_not_a_replay() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
let owner = rig.tenant("team");
let dispatch = rig.dispatch(&slot);
let fact = rig.signed_at(
&rig.key,
"team",
State::Paid,
&[("pack_bytes", 1 << 30)],
Some(ISSUED_AT),
);
let (first, seq_one) = plane.entitlement_set(fact.clone()).expect("the push");
let (again, seq_two) = plane
.entitlement_set(fact.clone())
.expect("the RETRY of the same push");
assert_eq!(first, again, "the same fact enforces the same state");
assert_ne!(
seq_one, seq_two,
"and the retry is its own attestation line, honestly"
);
assert_eq!(
slot.enforced_state("team"),
Some(EntitlementState::Paid),
"nothing moved, because nothing was different"
);
dispatch
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect("the tenant is still served");
let reopened = rig.slot();
rig.plane(&reopened)
.entitlement_set(fact)
.expect("a retry that arrives after a restart is still not a replay");
let twin = rig.signed_at(&rig.key, "team", State::Suspended, &[], Some(ISSUED_AT));
let err = rig
.plane(&reopened)
.entitlement_set(twin)
.expect_err("same instant, different fact: not newer, so not accepted");
assert!(matches!(err, ControlError::PermissionDenied(_)), "{err:?}");
}
#[test]
fn an_unstamped_fact_is_refused_even_for_a_namespace_that_has_none() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
let old = rig.signed_at(&rig.key, "team", State::Paid, &[], None);
let err = plane
.entitlement_set(old.clone())
.expect_err("an unstamped fact for a fresh namespace");
assert!(matches!(err, ControlError::PermissionDenied(_)), "{err:?}");
assert_eq!(
slot.enforced_state("team"),
None,
"and the refusal moved nothing"
);
let stamped = rig.signed_at(&rig.key, "team", State::Suspended, &[], Some(ISSUED_AT));
plane
.entitlement_set(stamped)
.expect("a stamped fact is accepted");
let err = plane
.entitlement_set(old)
.expect_err("an unstamped fact for a namespace that has one");
assert!(matches!(err, ControlError::PermissionDenied(_)), "{err:?}");
assert_eq!(
slot.enforced_state("team"),
Some(EntitlementState::Suspended),
"and the refusal moved nothing"
);
}
#[test]
fn the_high_water_mark_survives_a_restart_and_the_refusal_says_nothing_extra() {
let rig = Rig::new();
let owner = rig.tenant("team");
let captured = {
let slot = rig.slot();
let plane = rig.plane(&slot);
let captured = rig.signed(&rig.key, "team", State::Paid, &[]);
plane.entitlement_set(captured.clone()).unwrap();
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Suspended, &[]))
.unwrap();
captured
};
let slot = rig.slot();
let plane = rig.plane(&slot);
assert_eq!(
slot.enforced_state("team"),
Some(EntitlementState::Suspended),
"the lapse survived the restart"
);
let err = plane
.entitlement_set(captured)
.expect_err("and so did the high-water mark");
let ControlError::PermissionDenied(words) = &err else {
panic!("{err:?}")
};
assert!(
words.contains("team"),
"the refusal names the namespace: {words}"
);
assert!(
words.contains("replay"),
"and says what it refused it as: {words}"
);
for leak in [
"Suspended",
"Paid",
&ISSUED_AT.to_string(),
&OCT_1_2026.to_string(),
] {
assert!(
!words.contains(leak),
"the refusal must not carry {leak}: a caller who cannot read this namespace's fact \
must not learn it by pushing at it — {words}"
);
}
rig.dispatch(&slot)
.authorise_service(&owner, None, GitService::ReceivePack, repo("team"))
.expect_err("the replay did not restore the write door");
}
#[test]
fn refuse_twin_a_hand_written_issue_time_is_refused_as_forged_and_pins_nothing() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
plane
.entitlement_set(rig.signed_at(&rig.key, "team", State::Paid, &[], Some(ISSUED_AT)))
.expect("a genuine stamped fact");
let mut bumped = rig.signed_at(&rig.key, "team", State::Paid, &[], Some(ISSUED_AT + 1));
bumped.issued_unix_ms = Some(u64::MAX);
let err = plane
.entitlement_set(bumped)
.expect_err("a bumped stamp is not monetize's word");
let ControlError::PermissionDenied(words) = &err else {
panic!("{err:?}")
};
assert!(
words.contains("does not verify"),
"refused as forged, not as stale: {words}"
);
plane
.entitlement_set(rig.signed_at(
&rig.key,
"team",
State::Suspended,
&[],
Some(ISSUED_AT + 2),
))
.expect("the namespace was not wedged by the attempt");
assert_eq!(
slot.enforced_state("team"),
Some(EntitlementState::Suspended)
);
}
#[test]
fn a_box_restored_under_the_wrong_key_reports_no_plan_it_does_not_enforce() {
let rig = Rig::new();
rig.tenant("team");
rig.tenant("acme");
{
let slot = rig.slot();
let plane = rig.plane(&slot);
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[]))
.expect("genuine");
plane
.entitlement_set(rig.signed(&rig.key, "acme", State::Grace, &[]))
.expect("genuine");
assert_eq!(slot.refused_at_boot(), 0);
assert_eq!(plane.entitlement_refused_at_boot().unwrap(), None);
assert!(plane.health_alarms().is_empty());
assert_eq!(plane.entitlement_list().unwrap().len(), 2);
}
let wrong = rig._dir.path().join("wrong.pub");
std::fs::write(&wrong, rig.forger.verifying_key().to_bytes()).expect("write key");
let wrong = MeteredConfig::load(&MonetizePubkey::Path(wrong), Some(BILLING)).expect("config");
let slot =
EntitlementSlot::open(Arc::clone(&rig.stores), &wrong).expect("a wrong key still boots");
let plane = rig.plane(&slot);
assert_eq!(
slot.refused_at_boot(),
2,
"both stored facts were refused, and the box COUNTS them"
);
let refused = plane
.entitlement_refused_at_boot()
.unwrap()
.expect("Entitlement.List must carry the refusal");
assert_eq!(refused.count, 2);
assert_eq!(
refused.namespaces,
vec!["acme".to_string(), "team".to_string()]
);
assert!(
refused.at_unix_ms > 0 && refused.reason.contains("monetize public key"),
"{refused:?}"
);
let alarms = plane.health_alarms();
assert_eq!(alarms.len(), 1, "{alarms:?}");
assert_eq!(
alarms[0].event, "entitlement.key_mismatch",
"--monetize-vital is the default"
);
assert!(
alarms[0].detail.contains("acme, team"),
"the alarm names the namespaces: {}",
alarms[0].detail
);
assert_eq!(alarms[0].count, 2);
assert_eq!(slot.enforced_state("team"), None, "Free at the front door");
assert_eq!(slot.counts().paid, 0);
assert_eq!(
plane.entitlement_get("team").unwrap(),
None,
"Entitlement.Get reported a plan the box does not enforce"
);
assert!(
plane.entitlement_list().unwrap().is_empty(),
"Entitlement.List listed facts the box refused"
);
let err = plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[]))
.expect_err("a fact the configured key did not sign must be refused");
assert!(matches!(err, ControlError::PermissionDenied(_)), "{err:?}");
drop(plane);
drop(slot);
let slot = rig.slot();
let plane = rig.plane(&slot);
assert_eq!(slot.refused_at_boot(), 0);
assert_eq!(slot.enforced_state("team"), Some(EntitlementState::Paid));
assert_eq!(
plane.entitlement_refused_at_boot().unwrap(),
None,
"the right key refuses nothing"
);
assert!(plane.health_alarms().is_empty());
assert_eq!(slot.enforced_state("acme"), Some(EntitlementState::Grace));
assert_eq!(
plane.entitlement_get("team").unwrap().map(|f| f.state),
Some(PbState::Paid as i32)
);
}
fn restored_under_another_key(rig: &Rig, vital: bool) -> Arc<EntitlementSlot> {
rig.tenant("team");
rig.tenant("acme");
{
let slot = rig.slot();
let plane = rig.plane(&slot);
plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[]))
.expect("genuine");
plane
.entitlement_set(rig.signed(&rig.key, "acme", State::Grace, &[]))
.expect("genuine");
assert!(
plane.maintenance_reasons().is_empty(),
"the control: the right key is not maintenance"
);
}
let other = rig._dir.path().join("other.pub");
std::fs::write(&other, rig.forger.verifying_key().to_bytes()).expect("write key");
let mut config =
MeteredConfig::load(&MonetizePubkey::Path(other), Some(BILLING)).expect("config");
config.vital = vital;
EntitlementSlot::open(Arc::clone(&rig.stores), &config)
.expect("a mismatched key still boots and serves")
}
#[test]
fn a_key_mismatch_raises_the_alarm_and_maintenance() {
let rig = Rig::new();
let slot = restored_under_another_key(&rig, true);
let plane = rig.plane(&slot);
assert!(slot.maintenance());
assert_eq!(
plane.maintenance_reasons(),
vec!["entitlement.key_mismatch".to_string()]
);
let alarms = plane.health_alarms();
assert_eq!(alarms.len(), 1, "{alarms:?}");
assert_eq!(alarms[0].event, "entitlement.key_mismatch");
assert_eq!(alarms[0].count, 2);
assert!(
alarms[0].detail.contains("acme, team") && alarms[0].detail.contains("MAINTENANCE"),
"{}",
alarms[0].detail
);
}
#[test]
fn a_new_verifying_fact_clears_the_alarm_and_maintenance() {
let rig = Rig::new();
let slot = restored_under_another_key(&rig, true);
let plane = rig.plane(&slot);
assert!(plane
.entitlement_set(rig.signed(&rig.key, "team", State::Paid, &[]))
.is_err());
assert!(slot.maintenance(), "a refused fact is not a verifying one");
plane
.entitlement_set(rig.signed(&rig.forger, "team", State::Paid, &[]))
.expect("verifies under the box's key");
assert!(!slot.maintenance());
assert!(plane.maintenance_reasons().is_empty());
assert!(
plane.health_alarms().is_empty(),
"{:?}",
plane.health_alarms()
);
assert_eq!(
slot.enforced_state("team"),
Some(gunnar_core::EntitlementState::Paid)
);
}
#[test]
fn with_monetize_vital_false_a_mismatch_only_logs() {
let rig = Rig::new();
let slot = restored_under_another_key(&rig, false);
let plane = rig.plane(&slot);
assert_eq!(
slot.refused_at_boot(),
2,
"still counted and still on Entitlement.List"
);
assert!(plane.entitlement_refused_at_boot().unwrap().is_some());
assert!(!slot.maintenance());
assert!(plane.maintenance_reasons().is_empty());
assert!(
plane.health_alarms().is_empty(),
"{:?}",
plane.health_alarms()
);
}
#[test]
fn monetize_vital_defaults_to_true_and_parses_false() {
use clap::Parser;
let parse = |extra: &[&str]| {
let mut argv = vec![
"gunnar",
"serve",
"--monetize-pubkey",
"1c3663248d60900e2996389fba4efa1d7179d6dbd08627d0426f16f94e44c4e6",
"--billing-url",
BILLING,
];
argv.extend_from_slice(extra);
match gunnar_common::cli::Cli::try_parse_from(argv)
.expect("parses")
.command
{
gunnar_common::cli::Command::Serve(a) => a.monetize_vital,
_ => unreachable!(),
}
};
assert!(parse(&[]));
assert!(!parse(&["--monetize-vital", "false"]));
assert!(parse(&["--monetize-vital", "true"]));
}
#[test]
fn a_fed_monetize_key_applies_in_place_and_a_fact_signed_with_it_is_accepted_without_a_restart() {
let rig = Rig::new();
let keyless =
MeteredConfig::awaiting_feed(Some(BILLING)).expect("a fed medium with a pay page");
assert_eq!(keyless.monetize_pubkey, None);
let slot =
EntitlementSlot::open(Arc::clone(&rig.stores), &keyless).expect("a keyless slot opens");
rig.tenant("acme");
let paid = rig.signed(&rig.key, "acme", State::Suspended, &[]);
let refused = slot
.set(paid.clone())
.expect_err("no key yet: nothing can be verified");
assert!(
refused.to_string().contains("no monetize key yet"),
"{refused}"
);
assert_eq!(
slot.verdict("acme", gunnar_ssh::PlanAction::Write),
gunnar_ssh::PlanVerdict::Allow,
"keyless: Free, as a box with no slot was"
);
gunnar_server::feed::record_monetize_in_force(None);
let taker = Arc::clone(&slot);
gunnar_server::feed::on_monetize_key(
"entitlement slot (test)",
Box::new(move |k| taker.set_key(k).map(|_| ())),
);
let hex: String = rig
.key
.verifying_key()
.to_bytes()
.iter()
.map(|b| format!("{b:02x}"))
.collect();
let arrived = gunnar_server::feed::monetize_arrived(Some(&hex));
assert!(
matches!(
arrived,
Some(gunnar_server::feed::MonetizeArrival::Applied(_))
),
"{arrived:?}"
);
assert_eq!(
gunnar_server::feed::monetize_in_force(),
Some(rig.key.verifying_key().to_bytes())
);
assert_eq!(
gunnar_server::feed::monetize_arrived(Some(&hex)),
None,
"the same key again: nothing to do"
);
let (state, _) = slot
.set(paid)
.expect("a fact signed with the fed key is accepted without a restart");
assert_eq!(state, EntitlementState::Suspended);
assert!(
matches!(
slot.verdict("acme", gunnar_ssh::PlanAction::Write),
gunnar_ssh::PlanVerdict::Refuse(_)
),
"and enforced"
);
assert!(slot
.set(rig.signed(&rig.forger, "acme", State::Paid, &[]))
.is_err());
let other = slot
.set_key(&rig.forger.verifying_key().to_bytes())
.expect_err("a second key is not taken silently");
assert!(other.contains("[pairing.feed_mismatch]"), "{other}");
assert_eq!(
slot.set_key(&rig.key.verifying_key().to_bytes()),
Ok(false),
"the key in force: nothing to do"
);
}
#[test]
fn a_key_applied_in_place_reverifies_the_facts_already_on_disk() {
let rig = Rig::new();
rig.tenant("acme");
rig.slot()
.set(rig.signed(&rig.key, "acme", State::Suspended, &[]))
.expect("stored");
let slot = EntitlementSlot::open(
Arc::clone(&rig.stores),
&MeteredConfig::awaiting_feed(Some(BILLING)).unwrap(),
)
.unwrap();
assert_eq!(
slot.verdict("acme", gunnar_ssh::PlanAction::Write),
gunnar_ssh::PlanVerdict::Allow,
"keyless: Free"
);
assert_eq!(slot.set_key(&rig.key.verifying_key().to_bytes()), Ok(true));
assert!(
matches!(
slot.verdict("acme", gunnar_ssh::PlanAction::Write),
gunnar_ssh::PlanVerdict::Refuse(_)
),
"the stored fact is enforced the moment the key arrives"
);
assert_eq!(slot.refused_at_boot(), 0);
}
fn fact_paid(
key: &SigningKey,
ns: &str,
state: State,
paid_until: u64,
source: &str,
issued: u64,
) -> EntitlementFact {
let mut fact = monetize_embed::EntitlementFact {
tenant: TenantId(ns.to_owned()),
plan: "10gb".into(),
state,
paid_until_unix_ms: Some(paid_until),
caps: BTreeMap::new(),
source: source.into(),
signature: vec![],
issued_unix_ms: Some(issued),
issued_signature: vec![],
};
fact.signature = key
.sign(&monetize_embed::signing::fact_message(&fact))
.to_bytes()
.to_vec();
fact.issued_signature = key
.sign(&monetize_embed::signing::fact_message_issued(&fact))
.to_bytes()
.to_vec();
EntitlementFact {
namespace: fact.tenant.0,
plan: fact.plan,
state: match state {
State::Free => PbState::Free,
State::Paid => PbState::Paid,
State::Grace => PbState::Grace,
State::Suspended => PbState::Suspended,
State::Retention => PbState::Retention,
} as i32,
paid_until_unix_ms: fact.paid_until_unix_ms,
caps: fact.caps,
source: fact.source,
signature: fact.signature,
issued_unix_ms: fact.issued_unix_ms,
issued_signature: fact.issued_signature,
}
}
#[test]
fn a_restored_older_ledger_cannot_suspend_a_tenant_whose_renewal_the_box_holds() {
let rig = Rig::new();
let slot = rig.slot();
let plane = rig.plane(&slot);
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_millis() as u64;
let day = 24 * 3600 * 1000;
plane
.entitlement_set(fact_paid(
&rig.key,
"team",
State::Paid,
now + 60 * day,
"payment:stripe:renewal-2",
ISSUED_AT + 10,
))
.expect("the renewal is taken");
let stale = fact_paid(
&rig.key,
"team",
State::Suspended,
now - day,
"payment:stripe:first",
ISSUED_AT + 20,
);
let refused = plane
.entitlement_set(stale)
.expect_err("a restored ledger that lost the renewal must not suspend a tenant who paid");
let words = format!("{refused}");
assert!(
words.contains("already holds") && words.contains("team"),
"{words}"
);
assert_eq!(
slot.enforced_state("team"),
Some(gunnar_core::EntitlementState::Paid),
"still paid"
);
plane
.entitlement_set(fact_paid(
&rig.key,
"team",
State::Suspended,
now - day,
"payment:stripe:renewal-2",
ISSUED_AT + 30,
))
.expect("a downgrade about the held payment goes through");
assert_eq!(
slot.enforced_state("team"),
Some(gunnar_core::EntitlementState::Suspended)
);
let other = rig.slot();
let p2 = rig.plane(&other);
p2.entitlement_set(fact_paid(
&rig.key,
"lapsed",
State::Paid,
now - 2 * day,
"payment:stripe:a",
ISSUED_AT + 40,
))
.unwrap();
p2.entitlement_set(fact_paid(
&rig.key,
"lapsed",
State::Suspended,
now - 2 * day,
"payment:stripe:older",
ISSUED_AT + 50,
))
.expect("the held paid time is over: a lapse is no regression");
}