Public dry run dryrun-00a47f2c6f21

Source commit: 00a47f2c6f213d43fcef11fdf7926320241da30d

Public tree identity: sha256:c41c788b9938cfa66d0c047c16729942bfe6ba4f884acec7d4cd482da762f81a
This commit is contained in:
Michel Paulissen 2026-07-03 21:08:32 +02:00
parent a40778221a
commit 005b47e4c0
6 changed files with 282 additions and 5 deletions

View file

@ -334,6 +334,34 @@ impl Coordinator {
);
}
pub fn suspend_tenant(&mut self, tenant: TenantId, actor: UserId) -> ServicePolicyRecord {
self.upsert_tenant(tenant.clone());
let name = "tenant:suspended".to_owned();
let digest = Digest::from_parts([
b"tenant-suspension:v1".as_slice(),
tenant.as_str().as_bytes(),
actor.as_str().as_bytes(),
]);
self.upsert_service_policy_record(tenant.clone(), name.clone(), digest);
self.service_policy_record(&tenant, &name)
.expect("tenant suspension record was just inserted")
.clone()
}
pub fn tenant_suspended(&self, tenant: &TenantId) -> bool {
self.service_policy_record(tenant, "tenant:suspended")
.is_some()
}
pub fn ensure_tenant_active(&self, tenant: &TenantId) -> Result<(), CoordinatorError> {
if self.tenant_suspended(tenant) {
return Err(CoordinatorError::Unauthorized(
"tenant is suspended by admin controls".to_owned(),
));
}
Ok(())
}
pub fn grant_project_debug(&mut self, tenant: TenantId, project: ProjectId, user: UserId) {
self.durable.project_permissions.insert(
(tenant.clone(), project.clone(), user.clone()),
@ -870,6 +898,27 @@ mod tests {
assert_eq!(projects[0].id, ProjectId::from("project-a"));
}
#[test]
fn tenant_suspension_is_durable_admin_policy_state() {
let mut store = InMemoryDurableStore::default();
let mut coordinator = Coordinator::boot(&store, 1);
let record =
coordinator.suspend_tenant(TenantId::from("tenant"), UserId::from("admin-user"));
assert_eq!(record.tenant, TenantId::from("tenant"));
assert_eq!(record.name, "tenant:suspended");
assert!(coordinator.tenant_suspended(&TenantId::from("tenant")));
assert!(coordinator
.ensure_tenant_active(&TenantId::from("tenant"))
.unwrap_err()
.to_string()
.contains("suspended"));
coordinator.persist(&mut store);
let restarted = Coordinator::boot(&store, 2);
assert!(restarted.tenant_suspended(&TenantId::from("tenant")));
}
#[test]
fn agent_public_keys_are_project_user_scoped_and_restart_durable() {
let mut store = InMemoryDurableStore::default();