vios_app 0.1.1

Small JSON vaults: Argon2id + AES-GCM, with optional AAD binding.
Documentation
use std::fs;
use std::path::PathBuf;
use std::collections::HashMap;
use serde::{Serialize, Deserialize};
use crate::vault_crypto::decrypt_vault_payload;
use crate::vault::vault_types::VaultMetadata;

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct VaultLink {
    pub source: String,
    pub target: String,
    pub similarity_score: f32,
}

pub fn link_vaults_by_emotion(vault_dir: &str) -> Vec<VaultLink> {
    let mut links = Vec::new();
    let mut vaults: HashMap<String, VaultMetadata> = HashMap::new();

    for entry in fs::read_dir(vault_dir).unwrap() {
        let entry = entry.unwrap();
        let path = entry.path();
        if path.extension().unwrap_or_default() == "vault" {
            if let Ok((_, meta)) = decrypt_vault_payload(&path) {
                vaults.insert(path.to_string_lossy().to_string(), meta);
            }
        }
    }

    let vault_paths: Vec<String> = vaults.keys().cloned().collect();
    for i in 0..vault_paths.len() {
        for j in (i + 1)..vault_paths.len() {
            let a = &vaults[&vault_paths[i]];
            let b = &vaults[&vault_paths[j]];

            let score = emotional_similarity_score(a, b);
            if score > 0.5 {
                links.push(VaultLink {
                    source: vault_paths[i].clone(),
                    target: vault_paths[j].clone(),
                    similarity_score: score,
                });
            }
        }
    }

    links
}

fn emotional_similarity_score(a: &VaultMetadata, b: &VaultMetadata) -> f32 {
    let mut score = 0.0;

    if a.tone == b.tone {
        score += 0.4;
    }

    if a.intent == b.intent {
        score += 0.4;
    }

    if a.reem_code == b.reem_code {
        score += 0.2;
    }

    score
}