#[test]
fn test_unknown_schema() {
let dir = tempfile::tempdir().unwrap();
let rules = test_rules();
let mut writer = LogWriter::open(dir.path(), &rules).unwrap();
let mut state = State::default();
let bogus_schema = sha256_utf8("bogus.schema.v99");
let data = encode(&RequestData {
objective: "test".into(),
scope: SCOPE,
attachments: vec![],
parent_request_id: None,
})
.unwrap();
let proposal = Proposal {
space: SPACE,
thread: THREAD,
author: human_author(),
kind: Kind::Request,
schema: bogus_schema,
data,
refs: vec![],
};
let (_, verdict) = writer.commit(proposal, &rules, &mut state).unwrap();
assert_eq!(verdict.result, VerdictResult::Reject);
assert_eq!(verdict.reason, Some(ReasonCode::UnknownSchema));
}
#[test]
fn test_kind_schema_mismatch() {
let dir = tempfile::tempdir().unwrap();
let rules = test_rules();
let mut writer = LogWriter::open(dir.path(), &rules).unwrap();
let mut state = State::default();
let data = encode(&RequestData {
objective: "test".into(),
scope: SCOPE,
attachments: vec![],
parent_request_id: None,
})
.unwrap();
let proposal = Proposal {
space: SPACE,
thread: THREAD,
author: human_author(),
kind: Kind::Action, schema: schema_id(SCHEMA_REQUEST),
data,
refs: vec![],
};
let (_, verdict) = writer.commit(proposal, &rules, &mut state).unwrap();
assert_eq!(verdict.result, VerdictResult::Reject);
assert_eq!(verdict.reason, Some(ReasonCode::KindSchemaMismatch));
}
#[test]
fn test_ref_unresolved() {
let dir = tempfile::tempdir().unwrap();
let rules = test_rules();
let mut writer = LogWriter::open(dir.path(), &rules).unwrap();
let mut state = State::default();
let nonexistent_id = [99u8; 32];
let data = encode(&RequestData {
objective: "test".into(),
scope: SCOPE,
attachments: vec![],
parent_request_id: None,
})
.unwrap();
let proposal = Proposal {
space: SPACE,
thread: THREAD,
author: human_author(),
kind: Kind::Request,
schema: schema_id(SCHEMA_REQUEST),
data,
refs: vec![Ref {
type_: RefType::Cause,
target: nonexistent_id,
}],
};
let (_, verdict) = writer.commit(proposal, &rules, &mut state).unwrap();
assert_eq!(verdict.result, VerdictResult::Reject);
assert_eq!(verdict.reason, Some(ReasonCode::RefUnresolved));
}
#[test]
fn test_ref_cross_space() {
let dir = tempfile::tempdir().unwrap();
let rules = test_rules();
let mut writer = LogWriter::open(dir.path(), &rules).unwrap();
let mut state = State::default();
let (_request_id, _) = writer
.commit(request_proposal(), &rules, &mut state)
.unwrap();
let other_space = [77u8; 32];
let other_rules = VerifierRules::new(other_space, 200);
let dir2 = tempfile::tempdir().unwrap();
let mut writer2 = LogWriter::open(dir2.path(), &other_rules).unwrap();
let mut state2 = State::default();
let data = encode(&RequestData {
objective: "other space".into(),
scope: SCOPE,
attachments: vec![],
parent_request_id: None,
})
.unwrap();
let (_other_id, _) = writer2
.commit(
Proposal {
space: other_space,
thread: THREAD,
author: human_author(),
kind: Kind::Request,
schema: schema_id(SCHEMA_REQUEST),
data,
refs: vec![],
},
&other_rules,
&mut state2,
)
.unwrap();
let data = encode(&RequestData {
objective: "test".into(),
scope: SCOPE,
attachments: vec![],
parent_request_id: None,
})
.unwrap();
let foreign_record = Record {
id: [0u8; 32],
space: other_space,
thread: THREAD,
time: 100,
author: human_author(),
kind: Kind::Request,
schema: schema_id(SCHEMA_REQUEST),
data: data.clone(),
refs: vec![],
evidence: Evidence::Reported,
}
.with_computed_id()
.unwrap();
let test_record = Record {
id: [0u8; 32],
space: SPACE,
thread: THREAD,
time: 101,
author: human_author(),
kind: Kind::Request,
schema: schema_id(SCHEMA_REQUEST),
data,
refs: vec![Ref {
type_: RefType::Cause,
target: foreign_record.id,
}],
evidence: Evidence::Reported, };
let ref_evidences: Vec<Evidence> = vec![foreign_record.evidence];
let evidence = derive_evidence(&test_record.schema, &ref_evidences);
let test_record = Record {
evidence,
..test_record
}
.with_computed_id()
.unwrap();
let prior = vec![foreign_record];
let verdict = verify_record(&test_record, &prior, &rules, &State::default());
assert_eq!(verdict.result, VerdictResult::Reject);
assert_eq!(verdict.reason, Some(ReasonCode::RefCrossSpace));
}
#[test]
fn test_request_missing() {
let dir = tempfile::tempdir().unwrap();
let rules = test_rules();
let mut writer = LogWriter::open(dir.path(), &rules).unwrap();
let mut state = State::default();
let (_cap_id, v) = writer
.commit(
capability_proposal(ACTOR, "shell", CapabilityMode::Auto),
&rules,
&mut state,
)
.unwrap();
assert_eq!(v.result, VerdictResult::Accept);
let bogus_request = [88u8; 32];
let (_, verdict) = writer
.commit(action_proposal(bogus_request, "shell"), &rules, &mut state)
.unwrap();
assert_eq!(verdict.result, VerdictResult::Reject);
assert_eq!(verdict.reason, Some(ReasonCode::RequestMissing));
}
#[test]
fn test_capability_missing() {
let dir = tempfile::tempdir().unwrap();
let rules = test_rules();
let mut writer = LogWriter::open(dir.path(), &rules).unwrap();
let mut state = State::default();
let (request_id, _) = writer
.commit(request_proposal(), &rules, &mut state)
.unwrap();
let (_, verdict) = writer
.commit(action_proposal(request_id, "shell"), &rules, &mut state)
.unwrap();
assert_eq!(verdict.result, VerdictResult::Reject);
assert_eq!(verdict.reason, Some(ReasonCode::CapabilityMissing));
}
#[test]
fn test_capability_denied() {
let dir = tempfile::tempdir().unwrap();
let rules = test_rules();
let mut writer = LogWriter::open(dir.path(), &rules).unwrap();
let mut state = State::default();
let (request_id, _) = writer
.commit(request_proposal(), &rules, &mut state)
.unwrap();
let (cap_id, v) = writer
.commit(
capability_proposal(ACTOR, "shell", CapabilityMode::Deny),
&rules,
&mut state,
)
.unwrap();
assert_eq!(v.result, VerdictResult::Accept);
let (_, verdict) = writer
.commit(
action_proposal_with_authority(request_id, "shell", &[cap_id]),
&rules,
&mut state,
)
.unwrap();
assert_eq!(verdict.result, VerdictResult::Reject);
assert_eq!(verdict.reason, Some(ReasonCode::CapabilityDenied));
}