use std::fmt;
use super::{
SealCapabilities, SealConformanceLevel, SealCredentialRef, SealEnvelope, SealFormat,
SealIndication, SealMode, SealPort, SealRequest, SealVerification,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConformanceFailure {
pub rule: &'static str,
pub detail: String,
}
#[derive(Debug, Clone, Default)]
pub struct ConformanceReport {
pub failures: Vec<ConformanceFailure>,
pub notes: Vec<String>,
pub combinations_checked: usize,
}
impl ConformanceReport {
#[must_use]
pub fn is_conformant(&self) -> bool {
self.failures.is_empty()
}
fn fail(&mut self, rule: &'static str, detail: impl Into<String>) {
self.failures.push(ConformanceFailure {
rule,
detail: detail.into(),
});
}
}
impl fmt::Display for ConformanceReport {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(
f,
"seal port conformance: {} failure(s), {} note(s), {} combination(s) checked",
self.failures.len(),
self.notes.len(),
self.combinations_checked
)?;
for failure in &self.failures {
writeln!(f, " FAIL [{}] {}", failure.rule, failure.detail)?;
}
for note in &self.notes {
writeln!(f, " note: {note}")?;
}
Ok(())
}
}
fn profiled_request(
format: SealFormat,
mode: SealMode,
conformance_level: SealConformanceLevel,
envelope: SealEnvelope,
) -> SealRequest {
SealRequest {
payload_hash: "ab".repeat(32),
mode,
key_ref: SealCredentialRef {
qtsp_id: "conformance".into(),
credential_id: "conformance".into(),
},
sig_format: format,
conformance_level,
envelope,
}
}
pub async fn check_seal_port<P: SealPort + ?Sized>(adapter: &P) -> ConformanceReport {
let mut report = ConformanceReport::default();
let capabilities = adapter.capabilities();
if capabilities.supported_formats.is_empty() || capabilities.supported_modes.is_empty() {
report.notes.push(
"adapter advertises no formats or no modes; only the refusal rules were exercised"
.to_owned(),
);
}
if !capabilities.can_outlive_certificate_expiry() {
report.notes.push(
"no advertised conformance level survives certificate expiry (B-LT or higher) — \
seals from this adapter stop verifying when the signing certificate does, which \
is inside the retention period of any passport it seals"
.to_owned(),
);
}
check_advertised(adapter, &capabilities, &mut report).await;
check_unadvertised(adapter, &capabilities, &mut report).await;
report
}
async fn check_advertised<P: SealPort + ?Sized>(
adapter: &P,
capabilities: &SealCapabilities,
report: &mut ConformanceReport,
) {
let mut verify_unsupported = false;
for format in &capabilities.supported_formats {
for mode in &capabilities.supported_modes {
report.combinations_checked = report.combinations_checked.saturating_add(1);
let level = capabilities
.supported_levels
.first()
.copied()
.unwrap_or(SealConformanceLevel::BaselineLt);
let Some(packaging) = capabilities
.supported_envelopes
.iter()
.copied()
.find(|e| format.admits(*e))
else {
report.fail(
"capabilities.format_without_envelope",
format!(
"advertises {format:?} but no advertised packaging is one {format:?} \
defines, so no request for it can be well-formed"
),
);
continue;
};
let req = profiled_request(format.clone(), mode.clone(), level, packaging);
let envelope = match adapter.seal(req).await {
Ok(envelope) => envelope,
Err(e) => {
report.fail(
"seal.refused_advertised",
format!("advertised {format:?}/{mode:?} but refused it: {e}"),
);
continue;
}
};
if envelope.format != *format {
report.fail(
"seal.substituted_format",
format!(
"asked for {format:?}, received {:?} — a substituted attestation, \
not the one the caller chose",
envelope.format
),
);
}
match adapter.verify(&envelope).await {
Ok(verification) => audit_verdict(&verification, format, mode, report),
Err(_) => verify_unsupported = true,
}
}
}
if verify_unsupported {
report.notes.push(
"verify() is unsupported for at least one advertised profile — this adapter can \
produce seals it cannot check, including its own"
.to_owned(),
);
}
}
fn audit_verdict(
verification: &SealVerification,
format: &SealFormat,
mode: &SealMode,
report: &mut ConformanceReport,
) {
if !verification.is_coherent() {
report.fail(
"verify.incoherent_verdict",
format!(
"{format:?}/{mode:?} returned {:?} founded on {:?} — a pass over nothing checked",
verification.indication, verification.checks
),
);
}
if verification.placeholder && verification.is_qualified_pass() {
report.fail(
"verify.placeholder_passed",
format!("{format:?}/{mode:?} reported a placeholder envelope as a qualified pass"),
);
}
if let SealIndication::TotalFailed(reason) | SealIndication::Indeterminate(reason) =
&verification.indication
&& reason.trim().is_empty()
{
report.notes.push(format!(
"{format:?}/{mode:?} returned a non-pass verdict with an empty reason; an operator \
cannot act on it"
));
}
}
async fn check_unadvertised<P: SealPort + ?Sized>(
adapter: &P,
capabilities: &SealCapabilities,
report: &mut ConformanceReport,
) {
for format in SealFormat::ALL {
for mode in SealMode::ALL {
for level in SealConformanceLevel::ALL {
for packaging in SealEnvelope::ALL {
let req = profiled_request(format.clone(), mode.clone(), *level, *packaging);
if capabilities.can_produce(&req) {
continue;
}
report.combinations_checked = report.combinations_checked.saturating_add(1);
if let Ok(produced) = adapter.seal(req).await {
report.fail(
"seal.accepted_unadvertised",
format!(
"does not advertise {format:?}/{mode:?}/{level:?}/{packaging:?} \
but produced a {:?} envelope for it",
produced.format
),
);
}
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ports::ghosts::GhostSeal;
use crate::ports::seal::{SealChecks, SealedEnvelope};
use async_trait::async_trait;
use chrono::Utc;
#[tokio::test]
async fn the_ghost_is_conformant() {
let report = check_seal_port(&GhostSeal).await;
assert!(report.is_conformant(), "{report}");
assert!(
report.combinations_checked >= SealFormat::ALL.len(),
"every format must be exercised in one direction or the other: {report}"
);
}
struct SubstitutesFormat;
#[async_trait]
impl SealPort for SubstitutesFormat {
async fn seal(
&self,
_req: SealRequest,
) -> Result<SealedEnvelope, crate::domain::error::DppError> {
Ok(SealedEnvelope {
format: SealFormat::Cades,
seal_value: "synthetic".into(),
signing_cert_ref: None,
sealed_at: Utc::now(),
placeholder: false,
})
}
async fn verify(
&self,
_env: &SealedEnvelope,
) -> Result<SealVerification, crate::domain::error::DppError> {
Ok(SealVerification::passed(SealChecks::FullValidation))
}
fn capabilities(&self) -> SealCapabilities {
SealCapabilities {
supported_formats: vec![SealFormat::Jades, SealFormat::Cades],
supported_modes: vec![SealMode::ProviderSeal],
supported_levels: vec![SealConformanceLevel::BaselineLt],
supported_envelopes: vec![SealEnvelope::Detached],
}
}
}
#[tokio::test]
async fn a_substituted_format_is_caught() {
let report = check_seal_port(&SubstitutesFormat).await;
assert!(!report.is_conformant(), "{report}");
assert!(
report
.failures
.iter()
.any(|f| f.rule == "seal.substituted_format"),
"{report}"
);
assert!(
report
.failures
.iter()
.any(|f| f.rule == "seal.accepted_unadvertised"),
"{report}"
);
}
struct PassesOverNothing;
#[async_trait]
impl SealPort for PassesOverNothing {
async fn seal(
&self,
req: SealRequest,
) -> Result<SealedEnvelope, crate::domain::error::DppError> {
Ok(SealedEnvelope {
format: req.sig_format,
seal_value: "synthetic".into(),
signing_cert_ref: None,
sealed_at: Utc::now(),
placeholder: false,
})
}
async fn verify(
&self,
_env: &SealedEnvelope,
) -> Result<SealVerification, crate::domain::error::DppError> {
Ok(SealVerification {
indication: SealIndication::TotalPassed,
checks: SealChecks::None,
placeholder: false,
})
}
fn capabilities(&self) -> SealCapabilities {
SealCapabilities {
supported_formats: vec![SealFormat::Jades],
supported_modes: vec![SealMode::ProviderSeal],
supported_levels: vec![SealConformanceLevel::BaselineLt],
supported_envelopes: vec![SealEnvelope::Detached],
}
}
}
#[tokio::test]
async fn a_pass_over_nothing_checked_is_caught() {
let report = check_seal_port(&PassesOverNothing).await;
assert!(!report.is_conformant(), "{report}");
assert!(
report
.failures
.iter()
.any(|f| f.rule == "verify.incoherent_verdict"),
"{report}"
);
}
struct ShortLivedOnly;
#[async_trait]
impl SealPort for ShortLivedOnly {
async fn seal(
&self,
req: SealRequest,
) -> Result<SealedEnvelope, crate::domain::error::DppError> {
if !self.capabilities().can_produce(&req) {
return Err(crate::domain::error::DppError::Validation(
crate::domain::field_error::ValidationErrors::message("profile not advertised"),
));
}
Ok(SealedEnvelope {
format: req.sig_format,
seal_value: "synthetic".into(),
signing_cert_ref: None,
sealed_at: Utc::now(),
placeholder: false,
})
}
async fn verify(
&self,
_env: &SealedEnvelope,
) -> Result<SealVerification, crate::domain::error::DppError> {
Ok(SealVerification::passed(SealChecks::FullValidation))
}
fn capabilities(&self) -> SealCapabilities {
SealCapabilities {
supported_formats: vec![SealFormat::Cades],
supported_modes: vec![SealMode::ProviderSeal],
supported_levels: vec![SealConformanceLevel::BaselineB],
supported_envelopes: vec![SealEnvelope::Detached],
}
}
}
#[tokio::test]
async fn an_adapter_that_cannot_outlive_its_certificate_is_noted() {
let report = check_seal_port(&ShortLivedOnly).await;
assert!(
report.is_conformant(),
"offering only B-B is honest, not a contract breach: {report}"
);
assert!(
report
.notes
.iter()
.any(|n| n.contains("certificate expiry")),
"but an operator must be told: {report}"
);
}
#[tokio::test]
async fn a_downgraded_conformance_level_is_refused() {
let caps = ShortLivedOnly.capabilities();
let long_lived = profiled_request(
SealFormat::Cades,
SealMode::ProviderSeal,
SealConformanceLevel::BaselineLt,
SealEnvelope::Detached,
);
assert!(
!caps.can_produce(&long_lived),
"a B-B-only adapter must not claim it can produce B-LT"
);
assert!(!caps.can_outlive_certificate_expiry());
assert!(
ShortLivedOnly.seal(long_lived).await.is_err(),
"and it must refuse rather than quietly hand back B-B"
);
}
struct SealsButCannotVerify;
#[async_trait]
impl SealPort for SealsButCannotVerify {
async fn seal(
&self,
req: SealRequest,
) -> Result<SealedEnvelope, crate::domain::error::DppError> {
if !self.capabilities().can_produce(&req) {
return Err(crate::domain::error::DppError::Validation(
crate::domain::field_error::ValidationErrors::message("profile not advertised"),
));
}
Ok(SealedEnvelope {
format: req.sig_format,
seal_value: "synthetic".into(),
signing_cert_ref: None,
sealed_at: Utc::now(),
placeholder: false,
})
}
async fn verify(
&self,
_env: &SealedEnvelope,
) -> Result<SealVerification, crate::domain::error::DppError> {
Err(crate::domain::error::DppError::Validation(
crate::domain::field_error::ValidationErrors::message("verification unsupported"),
))
}
fn capabilities(&self) -> SealCapabilities {
SealCapabilities {
supported_formats: vec![SealFormat::Cades],
supported_modes: vec![SealMode::ProviderSeal],
supported_levels: vec![SealConformanceLevel::BaselineLt],
supported_envelopes: vec![SealEnvelope::Detached],
}
}
}
#[tokio::test]
async fn an_adapter_that_cannot_verify_is_noted_not_failed() {
let report = check_seal_port(&SealsButCannotVerify).await;
assert!(
report.is_conformant(),
"not implementing verify is permitted by the trait: {report}"
);
assert!(
report.notes.iter().any(|n| n.contains("cannot check")),
"but it must be surfaced: {report}"
);
}
struct FormatWithNoPackaging;
#[async_trait]
impl SealPort for FormatWithNoPackaging {
async fn seal(
&self,
_req: SealRequest,
) -> Result<SealedEnvelope, crate::domain::error::DppError> {
Ok(SealedEnvelope {
format: SealFormat::Pades,
seal_value: "synthetic".into(),
signing_cert_ref: None,
sealed_at: Utc::now(),
placeholder: false,
})
}
async fn verify(
&self,
_env: &SealedEnvelope,
) -> Result<SealVerification, crate::domain::error::DppError> {
Ok(SealVerification::passed(SealChecks::FullValidation))
}
fn capabilities(&self) -> SealCapabilities {
SealCapabilities {
supported_formats: vec![SealFormat::Pades],
supported_modes: vec![SealMode::ProviderSeal],
supported_levels: vec![SealConformanceLevel::BaselineLt],
supported_envelopes: vec![SealEnvelope::Detached, SealEnvelope::Enveloping],
}
}
}
#[tokio::test]
async fn a_format_with_no_advertised_packaging_is_caught() {
let report = check_seal_port(&FormatWithNoPackaging).await;
assert!(!report.is_conformant(), "{report}");
assert!(
report
.failures
.iter()
.any(|f| f.rule == "capabilities.format_without_envelope"),
"an unrequestable format is a defect in the advertisement, not in a request: {report}"
);
}
}