lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

commit f7f456d906d91aadbb9fac4850afaa8c5723c3e9
parent 59dc0c7f517237f668b4ca1ede9d5cbc511d879d
Author: triesap <tyson@radroots.org>
Date:   Wed,  5 Aug 2026 21:40:47 +0000

test(storage): enforce release coverage gates

Diffstat:
Mcrates/secrets/tests/context_contract.rs | 23+++++++++++++++++++++++
Mcrates/storage/tests/private_artifact.rs | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mcrates/storage_sqlite/src/private_artifact/mod.rs | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mcrates/storage_sqlite/tests/open_options.rs | 7+++++++
4 files changed, 210 insertions(+), 4 deletions(-)

diff --git a/crates/secrets/tests/context_contract.rs b/crates/secrets/tests/context_contract.rs @@ -51,6 +51,29 @@ fn invalid_context_is_rejected_without_echoing_values() { ContextValueError::NonCanonical, ), ( + EnvelopePurpose::parse("not_namespaced").err(), + ContextField::Purpose, + ContextValueError::NonCanonical, + ), + ( + EnvelopePurpose::parse("a".repeat(ENVELOPE_PURPOSE_MAX_BYTES + 1)).err(), + ContextField::Purpose, + ContextValueError::TooLong { + actual_bytes: ENVELOPE_PURPOSE_MAX_BYTES + 1, + max_bytes: ENVELOPE_PURPOSE_MAX_BYTES, + }, + ), + ( + EnvelopePurpose::parse("radroots.café").err(), + ContextField::Purpose, + ContextValueError::NonCanonical, + ), + ( + EnvelopePurpose::parse(" radroots.private_artifact").err(), + ContextField::Purpose, + ContextValueError::NonCanonical, + ), + ( EnvelopeSubject::parse("private artifact", "subject").err(), ContextField::SubjectType, ContextValueError::NonCanonical, diff --git a/crates/storage/tests/private_artifact.rs b/crates/storage/tests/private_artifact.rs @@ -492,14 +492,35 @@ fn reseal_contract_distinguishes_exact_replay_and_conflict() { let store = MemoryStorage::default(); let initial = metadata(RetentionPolicy::indefinite()); block_on(store.put_metadata(initial.clone())).unwrap(); + let reseal_id = PrivateArtifactResealId::new([9; 16]).unwrap(); + let next_reference = DurableSecretReference::new("keyring", "fresh-token", 4).unwrap(); + for (next_commitment, next_size, committed_at) in [ + (initial.commitment(), 640, 200), + (ArtifactCommitment::new([8; 32]), 0, 200), + (ArtifactCommitment::new([8; 32]), 640, 0), + ] { + assert_eq!( + PrivateArtifactResealRequest::new( + reseal_id, + initial.artifact_id(), + initial.revision(), + initial.commitment(), + next_commitment, + next_size, + next_reference.clone(), + committed_at, + ), + Err(Error::InvalidPrivateArtifactResealRequest) + ); + } let request = PrivateArtifactResealRequest::new( - PrivateArtifactResealId::new([9; 16]).unwrap(), + reseal_id, initial.artifact_id(), initial.revision(), initial.commitment(), ArtifactCommitment::new([8; 32]), 640, - DurableSecretReference::new("keyring", "fresh-token", 4).unwrap(), + next_reference, 200, ) .unwrap(); @@ -511,6 +532,86 @@ fn reseal_contract_distinguishes_exact_replay_and_conflict() { assert_eq!(committed.committed_revision().get(), 2); assert_eq!(committed.request_fingerprint(), request.fingerprint()); + let wrong_reseal_id = PrivateArtifactResealRequest::new( + PrivateArtifactResealId::new([7; 16]).unwrap(), + request.artifact_id(), + request.expected_revision(), + request.expected_commitment(), + request.next_commitment(), + request.next_protected_size_bytes(), + request.next_secret_reference().clone(), + request.committed_at_unix_ms(), + ) + .unwrap(); + assert_eq!( + committed.replay(&wrong_reseal_id), + Err(Error::PrivateArtifactResealConflict) + ); + let wrong_artifact = PrivateArtifactResealRequest::new( + request.reseal_id(), + PrivateArtifactId::new([7; 16]).unwrap(), + request.expected_revision(), + request.expected_commitment(), + request.next_commitment(), + request.next_protected_size_bytes(), + request.next_secret_reference().clone(), + request.committed_at_unix_ms(), + ) + .unwrap(); + assert_eq!( + committed.replay(&wrong_artifact), + Err(Error::PrivateArtifactResealConflict) + ); + assert_eq!( + initial.resealed(&wrong_artifact), + Err(Error::PrivateArtifactResealConflict) + ); + let wrong_revision = PrivateArtifactResealRequest::new( + request.reseal_id(), + request.artifact_id(), + PrivateArtifactRevision::new(2).unwrap(), + request.expected_commitment(), + request.next_commitment(), + request.next_protected_size_bytes(), + request.next_secret_reference().clone(), + request.committed_at_unix_ms(), + ) + .unwrap(); + assert_eq!( + initial.resealed(&wrong_revision), + Err(Error::PrivateArtifactResealConflict) + ); + let wrong_commitment = PrivateArtifactResealRequest::new( + request.reseal_id(), + request.artifact_id(), + request.expected_revision(), + ArtifactCommitment::new([6; 32]), + request.next_commitment(), + request.next_protected_size_bytes(), + request.next_secret_reference().clone(), + request.committed_at_unix_ms(), + ) + .unwrap(); + assert_eq!( + initial.resealed(&wrong_commitment), + Err(Error::PrivateArtifactResealConflict) + ); + let stale_timestamp = PrivateArtifactResealRequest::new( + request.reseal_id(), + request.artifact_id(), + request.expected_revision(), + request.expected_commitment(), + request.next_commitment(), + request.next_protected_size_bytes(), + request.next_secret_reference().clone(), + initial.updated_at_unix_ms(), + ) + .unwrap(); + assert_eq!( + initial.resealed(&stale_timestamp), + Err(Error::InvalidPrivateArtifactTimestamp) + ); + let replayed = block_on(store.reseal_metadata(request.clone())).unwrap(); assert_eq!( replayed.disposition(), diff --git a/crates/storage_sqlite/src/private_artifact/mod.rs b/crates/storage_sqlite/src/private_artifact/mod.rs @@ -1084,7 +1084,7 @@ mod tests { opened.expose_secret(|bytes| assert_eq!(bytes, b"private farm coordinates")); let row = sqlx::query( - "SELECT key_version, envelope_version, encrypted_envelope + "SELECT key_version, envelope_version, encrypted_envelope, context_fingerprint FROM radroots_private_artifacts WHERE artifact_id = ?", ) .bind(metadata.artifact_id().as_bytes().as_slice()) @@ -1099,16 +1099,91 @@ mod tests { .windows(24) .any(|bytes| bytes == b"private farm coordinates") ); + assert!(validate_stored_envelope(&metadata, &envelope, &row).is_ok()); let wrong_key_envelope = sealed_envelope(b"private farm coordinates", 8, 1, "farm.location").await; assert_eq!( + validate_stored_envelope(&metadata, &wrong_key_envelope, &row), + Err(Error::CorruptPrivateArtifactMetadata) + ); + assert_eq!( store - .put_encrypted_private_artifact(metadata, &wrong_key_envelope) + .put_encrypted_private_artifact(metadata.clone(), &wrong_key_envelope) .await, Err(Error::InvalidPrivateArtifactMetadata) ); + let stored_validation_metadata = |commitment, protected_size, secret_reference| { + PrivateArtifactMetadata::new( + metadata.artifact_id(), + metadata.kind().clone(), + metadata.schema_id().clone(), + commitment, + protected_size, + secret_reference, + metadata.retention(), + metadata.created_at_unix_ms(), + ) + .expect("structurally valid stored metadata") + }; + for invalid in [ + stored_validation_metadata( + metadata.commitment(), + metadata.protected_size_bytes(), + DurableSecretReference::new( + "memory", + "different-private-artifact-key", + metadata.secret_reference().key_version(), + ) + .expect("different reference"), + ), + stored_validation_metadata( + metadata.commitment(), + metadata.protected_size_bytes() + 1, + metadata.secret_reference().clone(), + ), + stored_validation_metadata( + ArtifactCommitment::new([0; 32]), + metadata.protected_size_bytes(), + metadata.secret_reference().clone(), + ), + ] { + assert_eq!( + validate_stored_envelope(&invalid, &envelope, &row), + Err(Error::CorruptPrivateArtifactMetadata) + ); + } + + let wrong_context_envelope = + sealed_envelope(b"private farm coordinates", 7, 2, "farm.location").await; + let wrong_context_encoded = wrong_context_envelope + .encode() + .expect("wrong context bytes"); + let wrong_context_metadata = stored_validation_metadata( + ArtifactCommitment::new(Sha256::digest(wrong_context_encoded.as_slice()).into()), + u64::try_from(wrong_context_encoded.len()).expect("wrong context length"), + metadata.secret_reference().clone(), + ); + assert_eq!( + validate_stored_envelope(&wrong_context_metadata, &wrong_context_envelope, &row), + Err(Error::CorruptPrivateArtifactMetadata) + ); + let wrong_fingerprint_row = sqlx::query("SELECT X'00' AS context_fingerprint") + .fetch_one(store.private_pool()) + .await + .expect("wrong fingerprint row"); + assert_eq!( + validate_stored_envelope(&metadata, &envelope, &wrong_fingerprint_row), + Err(Error::CorruptPrivateArtifactMetadata) + ); + + let (_, legacy_metadata, legacy_envelope) = migrated_legacy_store().await; + assert_eq!( + validate_new_envelope(&legacy_metadata, &legacy_envelope), + Err(Error::InvalidPrivateArtifactMetadata) + ); + let envelope = sealed_envelope(b"validation matrix", 9, 9, "test.validation_matrix").await; let valid = self::metadata( 9, diff --git a/crates/storage_sqlite/tests/open_options.rs b/crates/storage_sqlite/tests/open_options.rs @@ -114,4 +114,11 @@ fn options_fix_connection_invariants_and_bound_busy_timeout() { .with_source_generation(generation, 0), Err(Error::InvalidSourceGenerationTimestamp { actual: 0 }) )); + let beyond_sqlite_integer = u64::try_from(i64::MAX).expect("positive i64 maximum") + 1; + assert!(matches!( + OpenOptions::new(create.paths().clone(), OpenMode::Create) + .with_source_generation(generation, beyond_sqlite_integer), + Err(Error::InvalidSourceGenerationTimestamp { actual }) + if actual == beyond_sqlite_integer + )); }