#![allow(clippy::unwrap_used, clippy::expect_used, unsafe_code)]
use super::super::*;
use super::{pubkey_env_value, sample_describe, sign_describe_like_store};
use ed25519_dalek::SigningKey;
#[test]
fn gtxpack_marker_matches_is_case_insensitive_and_fails_safe() {
let dir = tempfile::tempdir().unwrap();
let marker = dir.path().join("router_echo.wasm.gtxpack");
assert!(!gtxpack_marker_matches(&marker, "abc123"));
std::fs::write(&marker, " ABC123\n").unwrap();
assert!(gtxpack_marker_matches(&marker, "abc123"));
assert!(!gtxpack_marker_matches(&marker, "def456"));
}
#[test]
fn gtxpack_marker_path_appends_extension() {
let wasm = std::path::Path::new("/cache/router_echo.wasm");
assert_eq!(
gtxpack_marker_path(wasm),
std::path::Path::new("/cache/router_echo.wasm.gtxpack")
);
assert_ne!(gtxpack_marker_path(wasm), sidecar_path(wasm));
}
#[test]
#[serial_test::serial]
fn verify_describe_signature_round_trips_store_signing() {
let signing = SigningKey::from_bytes(&[3u8; 32]);
let describe = sample_describe();
let signed_bytes = sign_describe_like_store(&describe, &signing);
let signed: serde_json::Value = serde_json::from_slice(&signed_bytes).unwrap();
let trusted = vec![signing.verifying_key()];
verify_describe_signature(&signed, &trusted).expect("valid signature must verify");
}
#[test]
#[serial_test::serial]
fn verify_describe_signature_uses_jcs_canonicalization() {
let describe = serde_json::json!({
"apiVersion": "greentic.ai/v1",
"kind": "ProviderExtension",
"runtime": { "memoryLimitMB": 64.0 },
"metadata": { "id": "router_echo", "version": "1.0.0", "summary": "x" }
});
assert_ne!(
serde_json::to_vec(&describe).unwrap(),
serde_jcs::to_vec(&describe).unwrap(),
"expected serde_json and JCS to diverge on an integer-valued float"
);
let signing = SigningKey::from_bytes(&[9u8; 32]);
let signed_bytes = sign_describe_like_store(&describe, &signing);
let signed: serde_json::Value = serde_json::from_slice(&signed_bytes).unwrap();
verify_describe_signature(&signed, &[signing.verifying_key()])
.expect("store-signed (JCS) describe must verify under the JCS reconstruction");
}
#[test]
#[serial_test::serial]
fn verify_describe_signature_fails_closed_on_empty_allowlist() {
let signing = SigningKey::from_bytes(&[4u8; 32]);
let signed_bytes = sign_describe_like_store(&sample_describe(), &signing);
let signed: serde_json::Value = serde_json::from_slice(&signed_bytes).unwrap();
let err = verify_describe_signature(&signed, &[]).unwrap_err();
assert!(matches!(err, StorePullError::Signature(_)), "got: {err:?}");
}
#[test]
#[serial_test::serial]
fn verify_describe_signature_rejects_untrusted_key() {
let signer = SigningKey::from_bytes(&[5u8; 32]);
let other = SigningKey::from_bytes(&[6u8; 32]);
let signed_bytes = sign_describe_like_store(&sample_describe(), &signer);
let signed: serde_json::Value = serde_json::from_slice(&signed_bytes).unwrap();
let err = verify_describe_signature(&signed, &[other.verifying_key()]).unwrap_err();
assert!(matches!(err, StorePullError::Signature(_)), "got: {err:?}");
}
#[test]
#[serial_test::serial]
fn verify_describe_signature_rejects_tampered_describe() {
let signing = SigningKey::from_bytes(&[7u8; 32]);
let signed_bytes = sign_describe_like_store(&sample_describe(), &signing);
let mut signed: serde_json::Value = serde_json::from_slice(&signed_bytes).unwrap();
signed["metadata"]["summary"] = serde_json::json!("tampered");
let err = verify_describe_signature(&signed, &[signing.verifying_key()]).unwrap_err();
assert!(matches!(err, StorePullError::Signature(_)), "got: {err:?}");
}
#[test]
#[serial_test::serial]
fn trusted_signers_parses_and_rejects_garbage() {
let signing = SigningKey::from_bytes(&[8u8; 32]);
let good = pubkey_env_value(&signing);
unsafe {
std::env::set_var(
TRUSTED_SIGNERS_ENV,
format!("{good}, , rsa:AAAA, not-base64!!"),
)
};
let keys = trusted_signers();
unsafe { std::env::remove_var(TRUSTED_SIGNERS_ENV) };
assert_eq!(keys.len(), 1, "only the one valid ed25519 entry survives");
assert_eq!(keys[0].to_bytes(), signing.verifying_key().to_bytes());
}