1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// src/vault/vault_structs.rs
//! Core data structures for Vault memory and metadata.
//!
//! These structs define the serialized contents of a `.vault` file, including:
//! - Emotional fingerprinting (tone, intent, REEM™ code)
//! - Cryptographic authorship (CIA™ hash, device fingerprint)
//! - Encrypted memory payload (user reflections or structured logs)
use chrono::Utc;
use serde::{Deserialize, Serialize};
use std::{error::Error, fs};
/// Describes the origin, emotional state, and cryptographic identity of the Vault.
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct VaultMetadata {
/// Name of the user or AI creating the Vault.
#[serde(default)]
pub creator_name: String,
/// UTC timestamp of creation (ISO 8601).
#[serde(default)]
pub created_at: String,
/// Device or system fingerprint for provenance tracking.
#[serde(default)]
pub system_fingerprint: String,
/// Optional tone label (e.g., calm, anxious, confident).
#[serde(default)]
pub tone_classification: Option<String>,
/// Optional intent label (e.g., reflect, confess, create).
#[serde(default)]
pub intent_classification: Option<String>,
/// Optional REEM™ emotional code for memory encoding.
#[serde(default)]
pub reem_code: Option<String>,
/// Optional CIA™ hash for authorship verification.
#[serde(default)]
pub cia_hash: Option<String>,
}
/// Represents a decrypted Vault, containing emotional metadata and raw memory content.
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct VaultPayload {
/// Authorship + emotional context for the Vault.
pub metadata: VaultMetadata,
/// User-generated content (plaintext memory, script, or reflection).
pub content: String,
/// Top-level author field for backward compatibility with older payloads.
/// This is `#[serde(default)]` so legacy fixtures without it still deserialize.
#[serde(default)]
pub creator_name: String,
}
impl VaultPayload {
/// Load a `.echo` file and generate a VaultPayload with auto-filled metadata.
pub fn from_echo_file(path: &str) -> Result<Self, Box<dyn Error>> {
let content = fs::read_to_string(path)?;
let who = whoami::realname();
let created = Utc::now().to_rfc3339();
let fingerprint = whoami::fallible::hostname().unwrap_or_default();
let metadata = VaultMetadata {
creator_name: who.clone(),
created_at: created,
system_fingerprint: fingerprint,
..Default::default()
};
Ok(Self {
metadata,
content,
// mirror into legacy top-level for compatibility
creator_name: who,
})
}
/// Generate a canonical Vault filename from the creation timestamp.
pub fn generate_vault_filename(&self) -> String {
let ts = if !self.metadata.created_at.is_empty() {
self.metadata.created_at.clone()
} else {
Utc::now().to_rfc3339()
};
let safe_ts = ts.replace(':', "-");
format!("vault_{safe_ts}.vault")
}
}