app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

package_boundary.rs (10204B)


      1 use std::{fs, path::Path};
      2 
      3 fn read(path: &Path) -> String {
      4     fs::read_to_string(path).unwrap_or_else(|error| panic!("{}: {error}", path.display()))
      5 }
      6 
      7 #[test]
      8 fn storage_package_keeps_one_sqlite_authority_and_a_sealed_public_surface() {
      9     let crate_root = Path::new(env!("CARGO_MANIFEST_DIR"));
     10     let workspace_root = crate_root.join("../..");
     11     let manifest = read(&crate_root.join("Cargo.toml"));
     12     let workspace_manifest = read(&workspace_root.join("Cargo.toml"));
     13     let lock = read(&workspace_root.join("Cargo.lock"));
     14     let root_source = read(&crate_root.join("src/lib.rs"));
     15     let contract_source = read(&crate_root.join("src/contract.rs"));
     16     let database_source = read(&crate_root.join("src/db.rs"));
     17     let evidence_source = read(&crate_root.join("src/availability_evidence.rs"));
     18     let journal_source = read(&crate_root.join("src/journal.rs"));
     19     let keyring_source = read(&crate_root.join("src/os_keyring.rs"));
     20     let api = read(&workspace_root.join("compatibility/harvestcircle-storage-api-v3.txt"));
     21 
     22     for forbidden in ["rusqlite", "refinery", "hmac", "rustix"] {
     23         assert!(
     24             !manifest.contains(forbidden),
     25             "storage manifest reintroduced direct {forbidden} authority"
     26         );
     27     }
     28     assert!(manifest.contains("radroots_service_sqlite.workspace = true"));
     29     assert!(manifest.contains("radroots_event = { workspace = true, features = [\"std\"] }"));
     30     assert!(
     31         manifest.contains(
     32             "radroots_event_codec = { workspace = true, features = [\"std\", \"json\"] }"
     33         )
     34     );
     35     assert!(manifest.contains("sqlx.workspace = true"));
     36     assert!(!manifest.contains("\nkeyring ="));
     37     assert!(manifest.contains(
     38         "secret-service = { version = \"=5.1.0\", features = [\"rt-tokio-crypto-rust\"] }"
     39     ));
     40     assert!(!manifest.contains("features = [\"crypto-rust\"]"));
     41     assert!(manifest.contains("security-framework = \"=3.7.0\""));
     42     assert!(manifest.contains("security-framework-sys = \"=2.17.0\""));
     43     assert!(workspace_manifest.contains("sqlx = { version = \"=0.9.0\""));
     44     for forbidden_package in ["rusqlite", "refinery"] {
     45         assert!(
     46             !lock.contains(&format!("\nname = \"{forbidden_package}\"\n")),
     47             "lock contains forbidden SQLite package {forbidden_package}"
     48         );
     49     }
     50 
     51     for module in [
     52         "availability_evidence",
     53         "backup",
     54         "contract",
     55         "db",
     56         "identities",
     57         "identity_namespace",
     58         "installation",
     59         "journal",
     60         "os_keyring",
     61         "profiles",
     62     ] {
     63         assert!(root_source.contains(&format!("mod {module};")));
     64         assert!(!root_source.contains(&format!("pub mod {module};")));
     65     }
     66     assert!(!root_source.contains("harvestcircle_initial_schema_sql"));
     67     assert!(!keyring_source.contains("PoisonError::into_inner"));
     68     assert!(!keyring_source.contains("set_password"));
     69     assert!(keyring_source.contains("add_generic_password"));
     70     assert!(keyring_source.contains("CREDENTIAL_OPERATION_ATTRIBUTE"));
     71     assert!(keyring_source.contains("false,\n            \"application/octet-stream\""));
     72     let readonly_verification = keyring_source
     73         .split_once("    fn verify<'a>(")
     74         .and_then(|(_, source)| source.split_once("\n    fn load("))
     75         .map(|(body, _)| body)
     76         .expect("request-bound read-only verification method");
     77     for required in [
     78         "request_id: &'a DurableRequestId",
     79         "public_key: PublicKey",
     80         "secret: SecretKeyInput",
     81         "self.operation()?",
     82         "Zeroizing::new(platform_read(&account).map_err(map_read_error)?)",
     83         "verify_replay_binding(request_id, &secret, encoded.as_slice())",
     84     ] {
     85         assert!(
     86             readonly_verification.contains(required),
     87             "read-only custody boundary is missing {required}"
     88         );
     89     }
     90     for forbidden in ["platform_create(", "platform_delete(", ".put(", ".delete("] {
     91         assert!(
     92             !readonly_verification.contains(forbidden),
     93             "verification mutates custody through {forbidden}"
     94         );
     95     }
     96     assert!(keyring_source.contains("verify_existing_replay(request_id, secret, encoded).map_err"));
     97     assert!(keyring_source.contains("SafeErrorCode::InvalidApplicationState"));
     98     let envelope_comparison = keyring_source
     99         .split_once("fn verify_existing_replay(")
    100         .and_then(|(_, source)| source.split_once("\nfn verify_replay_binding("))
    101         .map(|(body, _)| body)
    102         .expect("shared complete envelope comparison");
    103     for required in [
    104         "decode_credential(encoded)?",
    105         "existing_request == *request_id",
    106         "existing_secret",
    107         "secret.with_exposed_secret(|expected| value == expected)",
    108         "Err(credential_exists())",
    109     ] {
    110         assert!(
    111             envelope_comparison.contains(required),
    112             "complete custody binding is missing {required}"
    113         );
    114     }
    115     assert!(!database_source.contains("pub fn host"));
    116     assert!(!database_source.contains("pub const fn host"));
    117     for forbidden in [
    118         "SqlitePool",
    119         "SqliteConnection",
    120         "DELETE FROM availability_versions",
    121         "DELETE FROM public_payload_usage",
    122         "SecretKey",
    123         "OsKeyringSecretStore",
    124         "account_identities",
    125         "local_signer_bindings",
    126         "profile_cache",
    127     ] {
    128         assert!(
    129             !evidence_source.contains(forbidden),
    130             "public evidence crossed authority through {forbidden}"
    131         );
    132     }
    133     assert!(evidence_source.contains("verify_nip01_event("));
    134     assert!(evidence_source.contains("Nip01EventWire::parse_json_unverified("));
    135 
    136     for required in [
    137         "pub struct harvestcircle_storage::Database",
    138         "pub async fn harvestcircle_storage::Database::open",
    139         "pub async fn harvestcircle_storage::Database::close",
    140         "pub async fn harvestcircle_storage::Database::retain_availability_version",
    141         "pub async fn harvestcircle_storage::Database::load_availability_version",
    142         "pub async fn harvestcircle_storage::Database::capture_online_backup",
    143         "pub async fn harvestcircle_storage::Database::restore_verified_backup",
    144         "pub struct harvestcircle_storage::VerifiedHarvestCircleBackup",
    145         "pub fn harvestcircle_storage::verify_harvestcircle_backup",
    146         "impl harvestcircle_application::ports::DurableOperationRepository for harvestcircle_storage::Database",
    147         "harvestcircle_application::ports::BoxFuture",
    148         "pub fn harvestcircle_storage::OsKeyringSecretStore::contains(&self, harvestcircle_domain::key::PublicKey) -> harvestcircle_application::ports::BoxFuture",
    149         "pub fn harvestcircle_storage::OsKeyringSecretStore::put<'a>(&'a self, &'a harvestcircle_application::ports::DurableRequestId, harvestcircle_domain::key::PublicKey, harvestcircle_domain::key::SecretKeyInput) -> harvestcircle_application::ports::BoxFuture<'a",
    150         "pub fn harvestcircle_storage::OsKeyringSecretStore::verify<'a>(&'a self, &'a harvestcircle_application::ports::DurableRequestId, harvestcircle_domain::key::PublicKey, harvestcircle_domain::key::SecretKeyInput) -> harvestcircle_application::ports::BoxFuture<'a",
    151         "pub fn harvestcircle_storage::OsKeyringSecretStore::delete<'a>(&'a self, &'a harvestcircle_application::ports::DurableRequestId, harvestcircle_domain::key::PublicKey) -> harvestcircle_application::ports::BoxFuture<'a",
    152         "pub fn harvestcircle_storage::harvestcircle_migration_catalog()",
    153         "pub fn harvestcircle_storage::harvestcircle_schema_catalog()",
    154         "pub const harvestcircle_storage::HARVESTCIRCLE_DURABLE_OPERATION_CAPACITY: usize",
    155         "pub const harvestcircle_storage::HARVESTCIRCLE_DURABLE_OPERATION_CLEANUP_BATCH: usize",
    156         "pub const harvestcircle_storage::HARVESTCIRCLE_TERMINAL_RECEIPT_RETENTION_SECONDS: i64",
    157     ] {
    158         assert!(api.contains(required), "API baseline is missing {required}");
    159     }
    160     for forbidden in [
    161         "rusqlite::",
    162         "refinery::",
    163         "sqlx::",
    164         "OperationJournal",
    165         "harvestcircle_initial_schema_sql",
    166         "SELECT_AVAILABILITY_VERSION_SQL",
    167         "decode_availability_row",
    168         "retain_availability_version_on",
    169         "ServiceSqliteTransaction",
    170         "VerifiedServiceBackup",
    171         "StagedServiceRestore",
    172         "verify_backup_bundle",
    173         "stage_verified_restore",
    174         "finalize_staged_restore",
    175         "repair",
    176         "preflight",
    177     ] {
    178         assert!(
    179             !api.contains(forbidden),
    180             "API baseline exposes forbidden surface {forbidden}"
    181         );
    182     }
    183 
    184     for required in [
    185         "pub const HARVESTCIRCLE_STATE_SCHEMA_VERSION: u32 = 3;",
    186         "pub const HARVESTCIRCLE_UNFINISHED_DURABLE_OPERATION_CAPACITY: usize = 1_024;",
    187         "pub const HARVESTCIRCLE_DURABLE_OPERATION_CAPACITY: usize = 4_096;",
    188         "pub const HARVESTCIRCLE_DURABLE_OPERATION_CLEANUP_BATCH: usize = 256;",
    189         "pub const HARVESTCIRCLE_TERMINAL_RECEIPT_RETENTION_SECONDS: i64 = 7 * 24 * 60 * 60;",
    190         "bound_durable_operation_receipts",
    191         "completed_at_unix_s",
    192         "durable_operations_receipt_insert_guard",
    193         "durable_operations_receipt_update_guard",
    194         "add_verified_listing_evidence",
    195         "CREATE TABLE availability_versions",
    196         "CREATE TABLE public_payload_usage",
    197     ] {
    198         assert!(
    199             contract_source.contains(required),
    200             "storage contract is missing {required}"
    201         );
    202     }
    203     for required in [
    204         "LIMIT 1025",
    205         "LIMIT 4097",
    206         "LIMIT 256",
    207         "completed_at_unix_s < ?",
    208         "completed_at_unix_s = ?",
    209     ] {
    210         assert!(
    211             journal_source.contains(required),
    212             "journal enforcement is missing {required}"
    213         );
    214     }
    215     for forbidden in [
    216         "DELETE FROM durable_operations WHERE terminal_outcome IS NOT NULL",
    217         "DELETE FROM durable_operations WHERE completed_at_unix_s IS NOT NULL;",
    218         "ORDER BY completed_at_unix_s DESC",
    219     ] {
    220         assert!(
    221             !journal_source.contains(forbidden),
    222             "journal reintroduced unbounded or in-window eviction: {forbidden}"
    223         );
    224     }
    225 }