corteq_onepassword/lib.rs
1//! # corteq-onepassword
2//!
3//! Secure 1Password SDK wrapper for Rust applications.
4//!
5//! This crate provides a safe, ergonomic interface to 1Password secrets
6//! using FFI bindings to the official 1Password SDK Core library.
7//!
8//! ## Features
9//!
10//! - **Secure by default** - Secrets are wrapped in [`SecretString`] with automatic
11//! memory zeroization
12//! - **Simple API** - Retrieve secrets with a single function call
13//! - **Thread-safe** - Client is `Send + Sync` for use in async applications
14//! - **Builder pattern** - Flexible configuration with sensible defaults
15//!
16//! ## Quick Start
17//!
18//! ```no_run
19//! use corteq_onepassword::{OnePassword, ExposeSecret};
20//!
21//! #[tokio::main]
22//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
23//! // Create client from OP_SERVICE_ACCOUNT_TOKEN environment variable
24//! let client = OnePassword::from_env()?
25//! .integration("my-app", "1.0.0")
26//! .connect()
27//! .await?;
28//!
29//! // Resolve a secret
30//! let api_key = client.secret("op://vault/item/api-key").await?;
31//!
32//! // Use the secret (expose only when needed)
33//! println!("API key length: {}", api_key.expose_secret().len());
34//!
35//! Ok(())
36//! }
37//! ```
38//!
39//! ## Authentication
40//!
41//! This crate uses 1Password service account tokens for authentication.
42//! Personal account tokens are not supported.
43//!
44//! ### Environment Variable (Recommended)
45//!
46//! Set the `OP_SERVICE_ACCOUNT_TOKEN` environment variable:
47//!
48//! ```bash
49//! export OP_SERVICE_ACCOUNT_TOKEN="ops_..."
50//! ```
51//!
52//! Then use [`OnePassword::from_env()`]:
53//!
54//! ```no_run
55//! use corteq_onepassword::OnePassword;
56//!
57//! #[tokio::main]
58//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
59//! let client = OnePassword::from_env()?.connect().await?;
60//! Ok(())
61//! }
62//! ```
63//!
64//! ### Explicit Token
65//!
66//! For testing or special deployments, use [`OnePassword::from_token()`]:
67//!
68//! ```no_run
69//! use corteq_onepassword::OnePassword;
70//!
71//! #[tokio::main]
72//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
73//! let token = std::env::var("MY_TOKEN")?;
74//! let client = OnePassword::from_token(&token)?
75//! .connect()
76//! .await?;
77//! Ok(())
78//! }
79//! ```
80//!
81//! ## Secret References
82//!
83//! Secrets are referenced using the `op://vault/item/field` format:
84//!
85//! - `op://Production/Database/password` - Simple reference
86//! - `op://Production/Database/admin/password` - Section-scoped reference
87//!
88//! ## Batch Operations
89//!
90//! Resolve multiple secrets efficiently:
91//!
92//! ```no_run
93//! use corteq_onepassword::{OnePassword, ExposeSecret};
94//!
95//! #[tokio::main]
96//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
97//! let client = OnePassword::from_env()?.connect().await?;
98//!
99//! // Batch resolution (returns Vec)
100//! let secrets = client.secrets(&[
101//! "op://prod/db/host",
102//! "op://prod/db/user",
103//! "op://prod/db/pass",
104//! ]).await?;
105//!
106//! // Named resolution (returns SecretMap)
107//! let secrets = client.secrets_named(&[
108//! ("host", "op://prod/db/host"),
109//! ("user", "op://prod/db/user"),
110//! ("pass", "op://prod/db/pass"),
111//! ]).await?;
112//!
113//! let host = secrets.get("host").expect("host secret").expose_secret();
114//! Ok(())
115//! }
116//! ```
117//!
118//! ## Sharing the Client
119//!
120//! The client is thread-safe and can be shared via `Arc`:
121//!
122//! ```no_run
123//! use std::sync::Arc;
124//! use corteq_onepassword::OnePassword;
125//!
126//! #[tokio::main]
127//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
128//! let client = Arc::new(OnePassword::from_env()?.connect().await?);
129//!
130//! let client1 = Arc::clone(&client);
131//! let client2 = Arc::clone(&client);
132//!
133//! tokio::join!(
134//! async move { client1.secret("op://vault/item/field1").await },
135//! async move { client2.secret("op://vault/item/field2").await },
136//! );
137//! Ok(())
138//! }
139//! ```
140//!
141//! ## Feature Flags
142//!
143//! - `blocking` - Enable synchronous API via [`OnePasswordBuilder::connect_blocking()`]
144//! - `tracing` - Enable tracing spans for observability
145//!
146//! ## Security
147//!
148//! This crate is designed with security as a primary concern:
149//!
150//! - **Tokens** are wrapped in [`SecretString`] and zeroized on drop
151//! - **Secrets** are never logged or included in error messages
152//! - **Debug** implementations redact sensitive data
153//! - **Native library** is verified via SHA256 checksum at build time
154//!
155//! ## Platform Support
156//!
157//! | Platform | Architecture | Status |
158//! |----------|--------------|--------|
159//! | Linux | x86_64 | ✅ Supported |
160//! | Linux | aarch64 | ✅ Supported |
161//! | macOS | x86_64 | ✅ Supported |
162//! | macOS | aarch64 | ✅ Supported |
163//! | Windows | - | ❌ Not supported |
164//! | Alpine | - | ❌ Not supported (musl) |
165
166#![warn(missing_docs)]
167#![warn(clippy::all)]
168#![deny(unsafe_op_in_unsafe_fn)]
169
170mod client;
171mod error;
172mod ffi;
173mod secret;
174
175// Public API
176pub use client::{OnePassword, OnePasswordBuilder};
177pub use error::{Error, Result};
178pub use secret::{SecretMap, SecretReference};
179
180// Re-export secrecy types for user convenience
181// This allows users to import everything they need from this crate
182pub use secrecy::{ExposeSecret, SecretString};