use gunnar_proto::PushAttestation;
pub fn attestation_json_line(attestation: &PushAttestation) -> Result<String, serde_json::Error> {
serde_json::to_string(attestation)
}
#[cfg(test)]
mod tests {
use super::*;
use gunnar_proto::{HashKind, RefUpdate, RepoPath};
fn sample() -> PushAttestation {
PushAttestation {
attestation_id: "att-1".into(),
repo: Some(RepoPath::new("nordisk", "gunnar")),
principal_id: "principal-00000001".into(),
principal_name: "alice".into(),
key_fingerprint: "SHA256:abc".into(),
credential: "key:SHA256:abc".into(),
hash_kind: HashKind::Sha256 as i32,
ref_updates: vec![RefUpdate {
ref_name: "refs/heads/main".into(),
old_oid: "a".repeat(64),
new_oid: "b".repeat(64),
}],
new_object_oids: vec!["c".repeat(64)],
new_object_count: 1,
new_object_oids_unknown: String::new(),
new_object_bytes: 4096,
pack_hash: "d".repeat(64),
received_at_unix_ms: 1_700_000_000_000,
server_agent: gunnar_proto::AGENT.into(),
transport: "ssh".into(),
}
}
#[test]
fn renders_exactly_one_line() {
let line = attestation_json_line(&sample()).expect("serialises");
assert!(
!line.contains('\n'),
"a JSONL record must not contain a newline: {line}"
);
assert_eq!(line.lines().count(), 1);
}
#[test]
fn carries_the_facts_receive_pack_already_had() {
let line = attestation_json_line(&sample()).expect("serialises");
for expected in [
"\"namespace\":\"nordisk\"",
"\"repo\":\"gunnar\"",
"\"principal_name\":\"alice\"",
"\"key_fingerprint\":\"SHA256:abc\"",
"\"ref_name\":\"refs/heads/main\"",
"\"new_object_count\":1",
"\"transport\":\"ssh\"",
] {
assert!(line.contains(expected), "missing {expected} in {line}");
}
}
#[test]
fn an_unenumerated_record_says_so_on_the_line_rather_than_showing_an_empty_list() {
let mut att = sample();
att.new_object_oids.clear();
att.new_object_oids_unknown =
"the policy has no gate over objects, so the object set was not enumerated".to_owned();
att.new_object_count = 3;
let line = attestation_json_line(&att).expect("serialises");
assert!(
line.contains("\"new_object_oids\":[]")
&& line.contains("\"new_object_count\":3")
&& line.contains("was not enumerated"),
"the line must carry the empty list, the count that is still true and the reason \
the two disagree: {line}"
);
let enumerated = attestation_json_line(&sample()).expect("serialises");
assert!(
enumerated.contains("\"new_object_oids_unknown\":\"\""),
"an enumerated set must leave the reason EMPTY, or every reader is told the list \
is untrustworthy: {enumerated}"
);
}
}