Skip to main content

revault_api/
lib.rs

1#![deny(missing_docs)]
2//! Complete source-native Rust API for reVault `Lockbox` archives and `Vault`s.
3//!
4//! Use [`lockbox`] for portable encrypted archives and [`vault`] for local key,
5//! contact, form, platform-keyring, and session-agent operations. This package
6//! re-exports the native core directly; transport framing exists only at the
7//! foreign-language boundary. Rust links the implementation at build time, so
8//! there is no runtime library path or `REVAULT_LIBRARY` setting.
9//!
10//! See the [reVault repository README](https://github.com/onepub-dev/reVault#readme)
11//! for installation, security guidance, and examples.
12
13/// Portable encrypted archive API.
14pub mod lockbox {
15    pub use revault_lockbox_api::{
16        ArtifactKind, CacheLimit, CacheStats, ContactKeyPair, ContactPublicKey, ContentChunk,
17        ContentStreamOptions, ContentStreamOrder, Error, ExtractPolicy, FormDefinition,
18        FormFieldDefinition, FormFieldKind, FormFieldValue, FormRecord, FormTypeId, FormValue,
19        ImportStats, ListOptions, Lockbox, LockboxEntry, LockboxEntryKind, LockboxFileInspection,
20        LockboxFileMut, LockboxFileReader, LockboxId, LockboxInspector, LockboxKeySlot,
21        LockboxKeySlotAlgorithm, LockboxKeySlotProtection, LockboxOpen, LockboxOptions,
22        LockboxOwnerInspection, LockboxPath, LockboxProtection, MirrorMissingFilePolicy,
23        MirrorProject, OpenFileOptions, PageInspection, PageObjectInspection, ReadOnly,
24        RecoveryReport, RecoveryReportOptions, RecoveryScanner, Result, SecretString, SecretVec,
25        VariableName, VariableNamePattern, VariableSensitivity, VariableValueRef, WorkerPolicy,
26        WorkloadProfile, Writable, WritableLockboxState,
27    };
28
29    /// A profile's signing identity. The owner role is assigned only when the
30    /// key is attached to a [`Lockbox`].
31    pub type ProfileSigningKeyPair = revault_lockbox_api::OwnerSigningKeyPair;
32
33    /// The shareable verification half of a profile signing identity.
34    pub type ProfileSigningPublicKey = revault_lockbox_api::OwnerSigningPublicKey;
35
36    /// A contact-encrypted content-key envelope.
37    pub type WrappedContactKey = revault_lockbox_api::ContactWrappedKey;
38}
39
40/// Local vault, keyring, and session-agent API.
41pub mod vault {
42    use revault_lockbox_api::{ContactKeyPair, ContactPublicKey};
43
44    pub use revault_vault_api::{
45        backup_default_vault, decode_fingerprint_crockford_96, decode_fingerprint_hex,
46        default_vault_dir, default_vault_path, disable_platform_secret_store,
47        enable_platform_secret_store, encode_hex, export_private_key, export_public_key, forget,
48        forget_all, forget_platform_vault_password, forget_vault_unlock_key,
49        format_fingerprint_crockford_96, format_fingerprint_crockford_96_reading,
50        format_fingerprint_hex_pairs, get, get_platform_vault_password, get_vault_unlock_key,
51        import_private_key, import_private_key_file, import_public_key, is_running, list,
52        platform_secret_store_disabled, platform_secret_store_status, public_key_fingerprint, put,
53        put_platform_vault_password, put_vault_unlock_key, restore_default_vault, serve_agent,
54        set_auto_open_scope, start, stop, verify_agent_transport_security, AccessSlotLabel,
55        AgentSleepSupport, AutoOpenScope, CachedLockbox, ContentKeyStore, KeyFormat, KnownLockbox,
56        NoopStore, PlatformSecretStoreStatus, ProfileGeneration, ProfileGenerationStatus,
57        ProfileHistory, SecretActivityGuard, SecretActivityKind, SecretString, SecretVec,
58        StoredContact, VaultBackupManifest, CURRENT_VAULT_STRUCTURE_VERSION,
59        FINGERPRINT_CODE_96_LEN,
60    };
61
62    /// Persistent encrypted local store for profiles, keys, contacts, and
63    /// remembered lockbox metadata.
64    ///
65    /// The implementation handle is private: callers see the reviewed
66    /// `Vault` name and cannot depend on the core storage type.
67    #[derive(Debug)]
68    pub struct Vault(revault_vault_api::VaultDirectory);
69
70    impl Vault {
71        /// Opens the default persistent store.
72        pub fn open_default(password: &SecretString) -> revault_lockbox_api::Result<Self> {
73            let path = revault_vault_api::default_vault_path()?;
74            revault_vault_api::VaultDirectory::open_file(path, password).map(Self)
75        }
76        /// Opens or creates the default persistent store.
77        pub fn open_or_create_default(
78            password: &SecretString,
79        ) -> revault_lockbox_api::Result<Self> {
80            revault_vault_api::VaultDirectory::open_or_create_default(password).map(Self)
81        }
82        /// Creates a new store at an explicit file path.
83        pub fn create_file(
84            path: impl AsRef<std::path::Path>,
85            password: &SecretString,
86        ) -> revault_lockbox_api::Result<Self> {
87            revault_vault_api::VaultDirectory::create_file(path, password).map(Self)
88        }
89        /// Opens an existing store at an explicit file path.
90        pub fn open_file(
91            path: impl AsRef<std::path::Path>,
92            password: &SecretString,
93        ) -> revault_lockbox_api::Result<Self> {
94            revault_vault_api::VaultDirectory::open_file(path, password).map(Self)
95        }
96        /// Opens or creates a store below `root`.
97        pub fn open_or_create(
98            root: impl AsRef<std::path::Path>,
99            password: &SecretString,
100        ) -> revault_lockbox_api::Result<Self> {
101            revault_vault_api::VaultDirectory::open_or_create(root, password).map(Self)
102        }
103        /// Replaces the store below `root`.
104        pub fn replace(
105            root: impl AsRef<std::path::Path>,
106            password: &SecretString,
107        ) -> revault_lockbox_api::Result<Self> {
108            revault_vault_api::VaultDirectory::replace(root, password).map(Self)
109        }
110        /// Returns the structure version without opening the store for writes.
111        pub fn probe_structure_version(
112            root: impl AsRef<std::path::Path>,
113            password: &SecretString,
114        ) -> revault_lockbox_api::Result<u32> {
115            revault_vault_api::VaultDirectory::probe_structure_version(root, password)
116        }
117        /// Returns the store's containing directory.
118        pub fn root(&self) -> &std::path::Path {
119            self.0.root()
120        }
121        /// Returns the encrypted store file path.
122        pub fn path(&self) -> &std::path::Path {
123            self.0.path()
124        }
125        /// Returns the on-disk structure version.
126        pub fn structure_version(&self) -> revault_lockbox_api::Result<u32> {
127            self.0.structure_version()
128        }
129        /// Stores a contact private key under a profile name.
130        pub fn store_private_key(
131            &self,
132            name: &str,
133            key: &ContactKeyPair,
134        ) -> revault_lockbox_api::Result<()> {
135            self.0.store_private_key(name, key)
136        }
137        /// Loads a contact private key for a profile.
138        pub fn load_private_key(&self, name: &str) -> revault_lockbox_api::Result<ContactKeyPair> {
139            self.0.load_private_key(name)
140        }
141        /// Reports whether a profile private key exists.
142        pub fn private_key_exists(&self, name: &str) -> revault_lockbox_api::Result<bool> {
143            self.0.private_key_exists(name)
144        }
145        /// Lists profile names with private keys.
146        pub fn list_private_keys(&self) -> revault_lockbox_api::Result<Vec<String>> {
147            self.0.list_private_keys()
148        }
149        /// Deletes a profile private key and its metadata.
150        pub fn delete_private_key(&self, name: &str) -> revault_lockbox_api::Result<()> {
151            self.0.delete_private_key(name)
152        }
153        /// Stores a profile's non-secret email metadata.
154        pub fn store_profile_email(
155            &self,
156            name: &str,
157            email: &str,
158        ) -> revault_lockbox_api::Result<()> {
159            self.0.store_profile_email(name, email)
160        }
161        /// Reads a profile's email metadata.
162        pub fn profile_email(&self, name: &str) -> revault_lockbox_api::Result<Option<String>> {
163            self.0.profile_email(name)
164        }
165        /// Lists profile key generations.
166        pub fn list_profile_generations(
167            &self,
168            name: &str,
169        ) -> revault_lockbox_api::Result<ProfileHistory> {
170            self.0.list_profile_generations(name)
171        }
172        /// Rotates a profile's private key.
173        pub fn rotate_private_key(
174            &self,
175            name: &str,
176        ) -> revault_lockbox_api::Result<ProfileHistory> {
177            self.0.rotate_private_key(name)
178        }
179        /// Loads the current profile signing identity.
180        pub fn load_profile_signing_key(
181            &self,
182            name: &str,
183        ) -> revault_lockbox_api::Result<super::ProfileSigningKeyPair> {
184            self.0.load_owner_signing_key(name)
185        }
186        /// Loads a historical profile signing identity.
187        pub fn load_profile_signing_key_generation(
188            &self,
189            name: &str,
190            index: u16,
191        ) -> revault_lockbox_api::Result<super::ProfileSigningKeyPair> {
192            self.0.load_owner_signing_key_generation(name, index)
193        }
194        /// Stores a contact's public key.
195        pub fn store_contact(
196            &self,
197            name: &str,
198            key: &ContactPublicKey,
199        ) -> revault_lockbox_api::Result<()> {
200            self.0.store_contact(name, key)
201        }
202        /// Loads a contact's public key.
203        pub fn load_contact(&self, name: &str) -> revault_lockbox_api::Result<ContactPublicKey> {
204            self.0.load_contact(name)
205        }
206        /// Reports whether a contact exists.
207        pub fn contact_exists(&self, name: &str) -> revault_lockbox_api::Result<bool> {
208            self.0.contact_exists(name)
209        }
210        /// Deletes a contact's public key.
211        pub fn delete_contact(&self, name: &str) -> revault_lockbox_api::Result<()> {
212            self.0.delete_contact(name)
213        }
214        /// Lists stored contacts.
215        pub fn list_contacts(&self) -> revault_lockbox_api::Result<Vec<StoredContact>> {
216            self.0.list_contacts()
217        }
218        /// Stores a contact signing public key.
219        pub fn store_contact_signing_key(
220            &self,
221            name: &str,
222            key: &super::ProfileSigningPublicKey,
223        ) -> revault_lockbox_api::Result<()> {
224            self.0.store_contact_signing_key(name, key)
225        }
226        /// Loads a contact signing public key.
227        pub fn load_contact_signing_key(
228            &self,
229            name: &str,
230        ) -> revault_lockbox_api::Result<super::ProfileSigningPublicKey> {
231            self.0.load_contact_signing_key(name)
232        }
233    }
234
235    /// Read-only view of a persistent [`Vault`].
236    #[derive(Debug)]
237    pub struct ReadOnlyVault(revault_vault_api::ReadOnlyVaultDirectory);
238
239    impl ReadOnlyVault {
240        /// Opens the default store without loading private signing material.
241        pub fn open_default(password: &SecretString) -> revault_lockbox_api::Result<Self> {
242            revault_vault_api::ReadOnlyVaultDirectory::open_default(password).map(Self)
243        }
244        /// Opens a store below `root` without loading private signing material.
245        pub fn open(
246            root: impl AsRef<std::path::Path>,
247            password: &SecretString,
248        ) -> revault_lockbox_api::Result<Self> {
249            revault_vault_api::ReadOnlyVaultDirectory::open(root, password).map(Self)
250        }
251        /// Lists profile names without loading private keys.
252        pub fn list_private_key_names(&self) -> revault_lockbox_api::Result<Vec<String>> {
253            self.0.list_private_key_names()
254        }
255        /// Lists contact names without loading contact key material.
256        pub fn list_contact_names(&self) -> revault_lockbox_api::Result<Vec<String>> {
257            self.0.list_contact_names()
258        }
259        /// Lists form aliases stored in the encrypted metadata.
260        pub fn list_form_aliases(&self) -> revault_lockbox_api::Result<Vec<String>> {
261            self.0.list_form_aliases()
262        }
263        /// Lists remembered Lockbox paths.
264        pub fn list_known_lockboxes(&self) -> revault_lockbox_api::Result<Vec<KnownLockbox>> {
265            self.0.list_known_lockboxes()
266        }
267    }
268
269    /// Explicit controller for the optional session agent. It caches selected
270    /// content keys only when asked and never represents persistent Vault data.
271    #[derive(Debug, Clone, Copy, Default)]
272    pub struct AgentSession;
273
274    impl AgentSession {
275        /// Returns the process-local session controller.
276        pub const fn instance() -> Self {
277            Self
278        }
279        /// Starts the optional session-agent process.
280        pub fn start(&self) -> std::io::Result<()> {
281            revault_vault_api::start()
282        }
283        /// Stops the optional session-agent process.
284        pub fn stop(&self) -> std::io::Result<()> {
285            revault_vault_api::stop()
286        }
287        /// Forgets every cached lockbox and profile key.
288        pub fn close_all(&self) -> std::io::Result<()> {
289            revault_vault_api::forget_all()
290        }
291        /// Reads a cached profile signing identity, if one is present.
292        ///
293        /// The private key remains in the session agent; callers should drop
294        /// the returned value as soon as signing is complete.
295        pub fn profile_signing_key(
296            &self,
297            vault_id: &str,
298            profile: &str,
299        ) -> std::io::Result<Option<super::ProfileSigningKeyPair>> {
300            revault_vault_api::get_owner_signing_key(vault_id, profile)
301        }
302        /// Caches a profile signing identity for the requested session TTL.
303        pub fn cache_profile_signing_key(
304            &self,
305            vault_id: &str,
306            profile: &str,
307            key: super::ProfileSigningKeyPair,
308            ttl_seconds: Option<u64>,
309        ) -> std::io::Result<()> {
310            revault_vault_api::put_owner_signing_key(vault_id, profile, key, ttl_seconds)
311        }
312        /// Removes one cached profile signing identity.
313        pub fn forget_profile_signing_key(
314            &self,
315            vault_id: &str,
316            profile: &str,
317        ) -> std::io::Result<()> {
318            revault_vault_api::forget_owner_signing_key(vault_id, profile)
319        }
320        /// Reports whether the session-agent process is running.
321        pub fn is_running(&self) -> bool {
322            revault_vault_api::is_running()
323        }
324        /// Serves the session-agent protocol in the current process.
325        pub fn serve(&self) -> std::io::Result<()> {
326            revault_vault_api::serve_agent()
327        }
328    }
329}
330
331pub use lockbox::{ProfileSigningKeyPair, ProfileSigningPublicKey, WrappedContactKey};
332pub use revault_lockbox_api::{ContactKeyPair, ContactPublicKey, Lockbox};
333pub use vault::{AgentSession, ReadOnlyVault, Vault};
334
335/// Source-native runtime entry point.
336///
337/// Rust links the implementation when the crate is built, therefore loading
338/// is a no-op. The explicit entry point keeps startup discoverable without
339/// introducing a library-path escape hatch.
340#[derive(Debug, Clone, Copy, Default)]
341pub struct Revault;
342
343impl Revault {
344    /// Returns the linked runtime entry point.
345    ///
346    /// ```rust
347    /// let _runtime = revault_api::Revault::load();
348    /// # let _ = _runtime;
349    /// ```
350    pub const fn load() -> Self {
351        Self
352    }
353}
354
355#[cfg(test)]
356mod tests {
357    use super::{AgentSession, ProfileSigningKeyPair, ReadOnlyVault, Revault, Vault};
358
359    #[test]
360    fn reviewed_runtime_and_profile_identity_are_process_local() {
361        let _runtime = Revault::load();
362        let session = AgentSession::instance();
363        let _running = session.is_running();
364        let signing_key = ProfileSigningKeyPair::generate().expect("generate profile key");
365        let public_key = signing_key.public_key();
366        assert!(!public_key.to_bytes().is_empty());
367
368        let root = std::env::temp_dir().join(format!(
369            "revault-api-facade-{}-{}",
370            std::process::id(),
371            public_key.to_bytes()[0]
372        ));
373        let passphrase = super::vault::SecretString::try_from_slice(b"facade test passphrase")
374            .expect("construct vault passphrase");
375        let vault = Vault::replace(&root, &passphrase).expect("replace test Vault");
376        assert!(vault.structure_version().expect("read structure version") > 0);
377        drop(vault);
378        let readonly = ReadOnlyVault::open(&root, &passphrase).expect("open read-only Vault");
379        assert!(readonly
380            .list_private_key_names()
381            .expect("list profile names")
382            .is_empty());
383        let _ = std::fs::remove_dir_all(root);
384    }
385}