use std::sync::{Arc, Mutex};
use async_trait::async_trait;
use serde_json::Value;
use trust_tasks_rs::{TrustTask, TypeUri};
use vta_sdk::protocols::audit_management::list::AuditLogEntry;
use vti_common::error::AppError;
use crate::policy::SideEffectLevel;
use crate::test_support::{build_signing_test_app_state_with_sink, super_admin_claims};
const NO_AUDIT_BY_DESIGN: &[(&str, &str)] = &[];
const NO_AUDIT_WHEN_NO_OP: &[(&str, &str)] = &[
(
"https://trusttasks.org/spec/auth/revoke-session/0.1",
"The fixture names a session that does not exist, so the handler takes \
its no-session arm: a `tracing` line with outcome=\"no-op\" and no \
sink row. The path that actually deletes a session records both forms, \
and says why they are not redundant.",
),
(
"https://trusttasks.org/spec/consent/revoke/1.0",
"The fixture names a subject with no grant, so the handler returns \
`notFound` as a status before reaching its audit call — deliberately: \
\"a revoke that deleted nothing is not a state change worth a line\".",
),
];
#[derive(Default)]
struct Recording {
seen: Mutex<Vec<AuditLogEntry>>,
}
#[async_trait]
impl vta_audit::AuditSink for Recording {
async fn record(&self, entry: &AuditLogEntry) -> Result<(), AppError> {
self.seen.lock().unwrap().push(entry.clone());
Ok(())
}
}
fn consequential_uris() -> Vec<&'static str> {
super::dispatched_uris()
.into_iter()
.filter(|u| {
super::class_for(u).is_some_and(|class| class.side_effects != SideEffectLevel::None)
})
.collect()
}
fn request_fixture(uri: &str) -> Option<Value> {
super::conformance::request_payload_for(uri)
}
#[tokio::test]
async fn every_consequential_task_records_an_audit_entry() {
let uris = consequential_uris();
assert!(
uris.len() > 40,
"only {} consequential URIs — the dispatch table walk is broken, and a \
census that inspects nothing passes vacuously",
uris.len()
);
let mut silent_on_success: Vec<&str> = Vec::new();
let mut silent_on_failure: Vec<&str> = Vec::new();
let mut unfixtured: Vec<&str> = Vec::new();
let mut failures = 0usize;
let mut checked = 0usize;
for uri in &uris {
let Some(payload) = request_fixture(uri) else {
unfixtured.push(uri);
continue;
};
let sink = Arc::new(Recording::default());
let (state, _dir) = build_signing_test_app_state_with_sink(Some(
sink.clone() as vta_audit::SharedAuditSink
))
.await;
let type_uri: TypeUri = uri.parse().expect("dispatched URI parses");
let mut doc = TrustTask::new(
format!("urn:uuid:{}", uuid::Uuid::new_v4()),
type_uri,
payload,
);
doc.issuer = Some(super_admin_claims().did);
doc.recipient = state.config.read().await.vta_did.clone();
doc.issued_at = Some(chrono::Utc::now());
crate::test_support::sign_as_test_admin(&mut doc);
let body = serde_json::to_vec(&doc).expect("serialize fixture document");
let outcome = super::dispatch_trust_task_core(
&state,
&super_admin_claims(),
&body,
super::transport::TransportConfidentiality::EndToEnd,
)
.await;
checked += 1;
if !outcome.status.is_success() {
failures += 1;
}
let excused = NO_AUDIT_BY_DESIGN.iter().any(|(u, _)| u == uri)
|| NO_AUDIT_WHEN_NO_OP.iter().any(|(u, _)| u == uri);
if sink.seen.lock().unwrap().is_empty() && !excused {
if outcome.status.is_success() {
silent_on_success.push(uri);
} else {
silent_on_failure.push(uri);
}
}
}
assert!(
checked > 30,
"only {checked} tasks were actually driven — too few for this to mean \
anything; check that conformance fixtures still resolve"
);
let succeeded = checked - failures;
assert!(
succeeded >= 5,
"only {succeeded} of {checked} task(s) reached a handler and succeeded. \
The envelope is being refused before dispatch again — check `issuer`, \
`recipient`, `issuedAt` and the proof, and see the module header."
);
let stale: Vec<&str> = NO_AUDIT_BY_DESIGN
.iter()
.chain(NO_AUDIT_WHEN_NO_OP.iter())
.map(|(u, _)| *u)
.filter(|u| !uris.contains(u))
.collect();
assert!(
stale.is_empty(),
"these NO_AUDIT_BY_DESIGN / NO_AUDIT_WHEN_NO_OP entries no longer name \
a consequential dispatched task — remove them, the lists may only \
shrink:\n {}",
stale.join("\n ")
);
let fmt = |v: &[&str]| {
if v.is_empty() {
" (none)".to_string()
} else {
format!(" {}", v.join("\n "))
}
};
assert!(
silent_on_success.is_empty(),
"{} consequential task(s) SUCCEEDED and recorded no audit entry — the \
work happened and left no trace:\n{}\n\nRecord one (see \
`credentials::handle_list` for the handler form, or the `vault_audit` \
arm on the spine for the central one), or add a NO_AUDIT_BY_DESIGN \
entry stating why no trail is correct here.",
silent_on_success.len(),
fmt(&silent_on_success)
);
assert!(
silent_on_failure.is_empty(),
"{} consequential task(s) were REFUSED and recorded nothing. A denied \
privileged attempt is exactly what an incident review looks for, and \
this is the shape that hides it:\n{}\n\nThe spine records every \
refusal (`DispatchAudit::record` in `trust_tasks/mod.rs`), so a task \
reaching here means something returned without passing it.",
silent_on_failure.len(),
fmt(&silent_on_failure)
);
if !unfixtured.is_empty() {
eprintln!(
"audit-coverage census: {} consequential task(s) had no conformance \
fixture and were not driven:\n{}",
unfixtured.len(),
fmt(&unfixtured)
);
}
}