use spacedb_access::{
gate, AccessPolicy, AccessRequest, AuditDecision, Capability, CapabilityChain, Decision,
DenyReason, Did, Identity, MemKeyDirectory, Ops, RevocationSet, Scope, SignedCapability,
};
const NOW: u64 = 1_000_000_000;
const FAR: u64 = 9_000_000_000;
#[test]
fn end_to_end_consent_flow_is_fully_audited() {
let owner = Identity::generate("did:mata:owner").unwrap();
let node = Identity::generate("did:mata:node").unwrap();
let dir = MemKeyDirectory::new();
dir.publish(&owner).unwrap();
let agent = Did::from("did:agent:assistant");
let scope = Scope::Collection("journal".into());
let policy = AccessPolicy::new()
.with_roster_member(owner.did().clone())
.requiring_accountable_agents();
let mut log = spacedb_access::AuditLog::new();
let mut revocations = RevocationSet::new();
let cap = Capability::grant(owner.did().clone(), agent.clone(), scope.clone(), Ops::READ | Ops::COMPUTE)
.unwrap()
.with_expiry(FAR)
.with_budget(10_000);
let cap_id = cap.id;
let chain = CapabilityChain::single(SignedCapability::sign(cap, &owner).unwrap());
let read = AccessRequest { bearer: &agent, scope: &scope, op: Ops::READ };
let d1 = gate(&policy, Some(&chain), &read, &dir, NOW, &revocations).unwrap();
assert_eq!(d1, Decision::Allow);
log.record(&node, NOW, &agent, &scope, Ops::READ, Some(cap_id), AuditDecision::of(&d1)).unwrap();
let compute = AccessRequest { bearer: &agent, scope: &scope, op: Ops::COMPUTE };
let d2 = gate(&policy, Some(&chain), &compute, &dir, NOW + 1, &revocations).unwrap();
assert_eq!(d2, Decision::Allow);
log.record(&node, NOW + 1, &agent, &scope, Ops::COMPUTE, Some(cap_id), AuditDecision::of(&d2)).unwrap();
revocations.revoke(cap_id);
let d3 = gate(&policy, Some(&chain), &read, &dir, NOW + 2, &revocations).unwrap();
assert_eq!(d3, Decision::Deny(DenyReason::Revoked));
log.record(&node, NOW + 2, &agent, &scope, Ops::READ, Some(cap_id), AuditDecision::of(&d3)).unwrap();
let stranger = Did::from("did:agent:stranger");
let read2 = AccessRequest { bearer: &stranger, scope: &scope, op: Ops::READ };
let d4 = gate(&policy, None, &read2, &dir, NOW + 3, &revocations).unwrap();
assert_eq!(d4, Decision::Deny(DenyReason::NoCapability));
log.record(&node, NOW + 3, &stranger, &scope, Ops::READ, None, AuditDecision::of(&d4)).unwrap();
assert_eq!(log.len(), 4);
log.verify(node.public_key()).unwrap();
assert_eq!(log.entries()[0].decision, AuditDecision::Allowed);
assert_eq!(log.entries()[1].decision, AuditDecision::Allowed);
assert_eq!(log.entries()[2].decision, AuditDecision::Denied(DenyReason::Revoked));
assert_eq!(log.entries()[3].decision, AuditDecision::Denied(DenyReason::NoCapability));
}