lib

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

commit 8e4b381e7f9b3ae5e166fe20abaa7c3a57c8d61f
parent e082385ed7a2eb6bdd5e002fbfb6bee22407e58a
Author: triesap <tyson@radroots.org>
Date:   Sun,  2 Aug 2026 18:51:19 +0000

test(core): add public redaction assertions

- scan public snapshot and safe-error debug representations
- inspect representative SQLite schema and durable records
- reject known secret hex nsec and secret-prefix fixtures
- document the reusable pre-command redaction guard lane

Diffstat:
Acrates/studio_application/tests/redaction.rs | 47+++++++++++++++++++++++++++++++++++++++++++++++
Acrates/studio_storage/tests/redaction.rs | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 100 insertions(+), 0 deletions(-)

diff --git a/crates/studio_application/tests/redaction.rs b/crates/studio_application/tests/redaction.rs @@ -0,0 +1,47 @@ +use radroots_studio_application::{ + AppSnapshot, RelayConfiguration, SessionState, SnapshotRevision, +}; +use radroots_studio_domain::{ + AccountCreatedAt, AccountSummary, KeyAvailability, Npub, PublicKey, SafeError, SafeErrorCode, + SafeMessage, SignerKind, UnixTimestamp, +}; + +const SECRET_HEX: &str = "1111111111111111111111111111111111111111111111111111111111111111"; +const SECRET_NSEC: &str = "nsec1vl029mgpspedva04g90vltkh6fvh240zqtv9k0t9af8935ke9laqsnlfe5"; +const NPUB: &str = "npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg"; + +fn assert_redacted(text: &str) { + assert!(!text.contains(SECRET_HEX)); + assert!(!text.contains(SECRET_NSEC)); + assert!(!text.contains("nsec1")); +} + +#[test] +fn redaction_guards_public_snapshot_and_safe_error_debug() { + let account = AccountSummary::new( + PublicKey::from_bytes([2; 32]), + Npub::from_encoded(NPUB.to_owned()).expect("npub"), + SignerKind::LocalSecret, + KeyAvailability::Available, + None, + AccountCreatedAt::new(UnixTimestamp::from_seconds(1).expect("time")), + None, + ); + let snapshot = AppSnapshot::ready( + SnapshotRevision::from_value(1), + RelayConfiguration::default(), + vec![account.clone()], + Some(account.public_key()), + SessionState::SignedOut, + None, + None, + ) + .expect("snapshot"); + let error = SafeError::new( + SafeErrorCode::KeyringUnavailable, + SafeMessage::new("The operating system credential store is unavailable."), + ); + + assert_redacted(&format!("{snapshot:?}")); + assert_redacted(&format!("{error:?} {error}")); +} diff --git a/crates/studio_storage/tests/redaction.rs b/crates/studio_storage/tests/redaction.rs @@ -0,0 +1,53 @@ +use std::fs; + +use radroots_studio_application::{AccountOperationKind, AccountRepository, OperationJournal}; +use radroots_studio_domain::{ + AccountCreatedAt, AccountSummary, KeyAvailability, Npub, PublicKey, SignerKind, UnixTimestamp, +}; +use radroots_studio_storage::Database; +use tempfile::tempdir; + +const SECRET_HEX: &str = "1111111111111111111111111111111111111111111111111111111111111111"; +const SECRET_NSEC: &str = "nsec1vl029mgpspedva04g90vltkh6fvh240zqtv9k0t9af8935ke9laqsnlfe5"; +const NPUB: &str = "npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg"; + +fn assert_redacted(bytes: &[u8]) { + assert!( + !bytes + .windows(SECRET_HEX.len()) + .any(|value| value == SECRET_HEX.as_bytes()) + ); + assert!( + !bytes + .windows(SECRET_NSEC.len()) + .any(|value| value == SECRET_NSEC.as_bytes()) + ); + assert!(!bytes.windows(5).any(|value| value == b"nsec1")); +} + +#[test] +fn redaction_guards_sqlite_schema_and_non_secret_records() { + let directory = tempdir().expect("directory"); + let path = directory.path().join("studio.sqlite3"); + { + let database = Database::open(&path).expect("database"); + let account = AccountSummary::new( + PublicKey::from_bytes([2; 32]), + Npub::from_encoded(NPUB.to_owned()).expect("npub"), + SignerKind::LocalSecret, + KeyAvailability::Available, + None, + AccountCreatedAt::new(UnixTimestamp::from_seconds(1).expect("time")), + None, + ); + database.insert_account(&account).expect("account"); + database + .begin_operation( + AccountOperationKind::Add, + account.public_key(), + UnixTimestamp::from_seconds(2).expect("time"), + ) + .expect("journal"); + } + assert_redacted(&fs::read(path).expect("database bytes")); +}