Skip to main content

auths_sdk/
types.rs

1use auths_core::storage::keychain::{KeyAlias, KeyStorage};
2use auths_verifier::Capability;
3use std::path::PathBuf;
4
5/// Policy for handling an existing identity during developer setup.
6///
7/// Replaces interactive CLI prompts with a typed enum that headless consumers
8/// can set programmatically.
9///
10/// Usage:
11/// ```ignore
12/// let config = DeveloperSetupConfig::builder("my-key")
13///     .with_conflict_policy(IdentityConflictPolicy::ReuseExisting)
14///     .build();
15/// ```
16#[derive(Debug, Clone, Default)]
17pub enum IdentityConflictPolicy {
18    /// Return an error if an identity already exists (default).
19    #[default]
20    Error,
21    /// Reuse the existing identity silently.
22    ReuseExisting,
23    /// Overwrite the existing identity with a new one.
24    ForceNew,
25}
26
27/// How to verify a platform identity.
28///
29/// The CLI obtains tokens interactively (OAuth device flow, browser open).
30/// The SDK accepts the resulting token — it never opens a browser.
31///
32/// Usage:
33/// ```ignore
34/// let platform = PlatformVerification::GitHub {
35///     access_token: "ghp_abc123".into(),
36/// };
37/// ```
38#[derive(Debug, Clone)]
39pub enum PlatformVerification {
40    /// Verify via GitHub using a personal access token.
41    GitHub {
42        /// The GitHub personal access token.
43        access_token: String,
44    },
45    /// Verify via GitLab using a personal access token.
46    GitLab {
47        /// The GitLab personal access token.
48        access_token: String,
49    },
50    /// Skip platform verification.
51    Skip,
52}
53
54/// Whether and how to configure Git commit signing.
55///
56/// Usage:
57/// ```ignore
58/// let scope = GitSigningScope::Global;
59/// ```
60#[derive(Debug, Clone, Default)]
61pub enum GitSigningScope {
62    /// Configure signing for a specific repository only.
63    Local {
64        /// Path to the repository to configure.
65        repo_path: PathBuf,
66    },
67    /// Configure signing globally for all repositories (default).
68    #[default]
69    Global,
70    /// Do not configure git signing.
71    Skip,
72}
73
74/// CI platform environment.
75///
76/// Usage:
77/// ```ignore
78/// let env = CiEnvironment::GitHubActions;
79/// ```
80#[derive(Debug, Clone)]
81pub enum CiEnvironment {
82    /// GitHub Actions CI environment.
83    GitHubActions,
84    /// GitLab CI/CD environment.
85    GitLabCi,
86    /// A custom CI platform with a user-provided name.
87    Custom {
88        /// The name of the custom CI platform.
89        name: String,
90    },
91    /// The CI platform could not be detected.
92    Unknown,
93}
94
95/// Configuration for provisioning a new developer identity.
96///
97/// Use [`DeveloperSetupConfigBuilder`] to construct this with optional fields.
98/// The registry backend is injected via [`crate::context::AuthsContext`] — this
99/// struct carries only serializable configuration values.
100///
101/// Args:
102/// * `key_alias`: Human-readable name for the key (e.g. "work-laptop").
103///
104/// Usage:
105/// ```ignore
106/// let config = DeveloperSetupConfig::builder("work-laptop")
107///     .with_platform(PlatformVerification::GitHub { access_token: "ghp_abc".into() })
108///     .with_git_signing_scope(GitSigningScope::Global)
109///     .build();
110/// ```
111#[derive(Debug)]
112pub struct DeveloperSetupConfig {
113    /// Human-readable name for the key (e.g. "work-laptop").
114    pub key_alias: KeyAlias,
115    /// Optional platform verification configuration.
116    pub platform: Option<PlatformVerification>,
117    /// How to configure git commit signing.
118    pub git_signing_scope: GitSigningScope,
119    /// Whether to register the identity on a remote registry.
120    pub register_on_registry: bool,
121    /// Remote registry URL, if registration is enabled.
122    pub registry_url: Option<String>,
123    /// What to do if an identity already exists.
124    pub conflict_policy: IdentityConflictPolicy,
125    /// Optional KERI witness configuration for the inception event.
126    pub witness_config: Option<auths_id::witness_config::WitnessConfig>,
127    /// Optional JSON metadata to attach to the identity.
128    pub metadata: Option<serde_json::Value>,
129    /// Path to the `auths-sign` binary, required when git signing is configured.
130    /// The CLI resolves this via `which::which("auths-sign")`.
131    pub sign_binary_path: Option<PathBuf>,
132}
133
134impl DeveloperSetupConfig {
135    /// Creates a builder with the required key alias.
136    ///
137    /// Args:
138    /// * `key_alias`: Human-readable name for the key.
139    ///
140    /// Usage:
141    /// ```ignore
142    /// let builder = DeveloperSetupConfig::builder("my-key");
143    /// ```
144    pub fn builder(key_alias: KeyAlias) -> DeveloperSetupConfigBuilder {
145        DeveloperSetupConfigBuilder {
146            key_alias,
147            platform: None,
148            git_signing_scope: GitSigningScope::Global,
149            register_on_registry: false,
150            registry_url: None,
151            conflict_policy: IdentityConflictPolicy::Error,
152            witness_config: None,
153            metadata: None,
154            sign_binary_path: None,
155        }
156    }
157}
158
159/// Builder for [`DeveloperSetupConfig`].
160#[derive(Debug)]
161pub struct DeveloperSetupConfigBuilder {
162    key_alias: KeyAlias,
163    platform: Option<PlatformVerification>,
164    git_signing_scope: GitSigningScope,
165    register_on_registry: bool,
166    registry_url: Option<String>,
167    conflict_policy: IdentityConflictPolicy,
168    witness_config: Option<auths_id::witness_config::WitnessConfig>,
169    metadata: Option<serde_json::Value>,
170    sign_binary_path: Option<PathBuf>,
171}
172
173impl DeveloperSetupConfigBuilder {
174    /// Configures platform identity verification for the new identity.
175    ///
176    /// The SDK never opens a browser or runs OAuth flows. The caller must
177    /// obtain the access token beforehand and pass it here.
178    ///
179    /// Args:
180    /// * `platform`: The platform and access token to verify against.
181    ///
182    /// Usage:
183    /// ```ignore
184    /// let config = DeveloperSetupConfig::builder("my-key")
185    ///     .with_platform(PlatformVerification::GitHub {
186    ///         access_token: "ghp_abc123".into(),
187    ///     })
188    ///     .build();
189    /// ```
190    pub fn with_platform(mut self, platform: PlatformVerification) -> Self {
191        self.platform = Some(platform);
192        self
193    }
194
195    /// Sets the Git signing scope (local, global, or skip).
196    ///
197    /// Args:
198    /// * `scope`: How to configure `git config` for commit signing.
199    ///
200    /// Usage:
201    /// ```ignore
202    /// let config = DeveloperSetupConfig::builder("my-key")
203    ///     .with_git_signing_scope(GitSigningScope::Local {
204    ///         repo_path: PathBuf::from("/path/to/repo"),
205    ///     })
206    ///     .build();
207    /// ```
208    pub fn with_git_signing_scope(mut self, scope: GitSigningScope) -> Self {
209        self.git_signing_scope = scope;
210        self
211    }
212
213    /// Enables registration on a remote auths registry after identity creation.
214    ///
215    /// Args:
216    /// * `url`: The registry URL to register with.
217    ///
218    /// Usage:
219    /// ```ignore
220    /// let config = DeveloperSetupConfig::builder("my-key")
221    ///     .with_registration("https://registry.auths.dev")
222    ///     .build();
223    /// ```
224    pub fn with_registration(mut self, url: impl Into<String>) -> Self {
225        self.register_on_registry = true;
226        self.registry_url = Some(url.into());
227        self
228    }
229
230    /// Sets the policy for handling an existing identity at the registry path.
231    ///
232    /// Args:
233    /// * `policy`: What to do if an identity already exists.
234    ///
235    /// Usage:
236    /// ```ignore
237    /// let config = DeveloperSetupConfig::builder("my-key")
238    ///     .with_conflict_policy(IdentityConflictPolicy::ReuseExisting)
239    ///     .build();
240    /// ```
241    pub fn with_conflict_policy(mut self, policy: IdentityConflictPolicy) -> Self {
242        self.conflict_policy = policy;
243        self
244    }
245
246    /// Sets the witness configuration for the KERI inception event.
247    ///
248    /// Args:
249    /// * `config`: Witness endpoints and thresholds.
250    ///
251    /// Usage:
252    /// ```ignore
253    /// let config = DeveloperSetupConfig::builder("my-key")
254    ///     .with_witness_config(witness_cfg)
255    ///     .build();
256    /// ```
257    pub fn with_witness_config(mut self, config: auths_id::witness_config::WitnessConfig) -> Self {
258        self.witness_config = Some(config);
259        self
260    }
261
262    /// Attaches custom metadata to the identity (e.g. `created_at`, `setup_profile`).
263    ///
264    /// Args:
265    /// * `metadata`: Arbitrary JSON metadata.
266    ///
267    /// Usage:
268    /// ```ignore
269    /// let config = DeveloperSetupConfig::builder("my-key")
270    ///     .with_metadata(serde_json::json!({"team": "platform"}))
271    ///     .build();
272    /// ```
273    pub fn with_metadata(mut self, metadata: serde_json::Value) -> Self {
274        self.metadata = Some(metadata);
275        self
276    }
277
278    /// Sets the path to the `auths-sign` binary used for git signing configuration.
279    ///
280    /// Required when `git_signing_scope` is not `Skip`. The CLI resolves this via
281    /// `which::which("auths-sign")`.
282    ///
283    /// Args:
284    /// * `path`: Absolute path to the `auths-sign` binary.
285    ///
286    /// Usage:
287    /// ```ignore
288    /// let config = DeveloperSetupConfig::builder("my-key")
289    ///     .with_sign_binary_path(PathBuf::from("/usr/local/bin/auths-sign"))
290    ///     .build();
291    /// ```
292    pub fn with_sign_binary_path(mut self, path: PathBuf) -> Self {
293        self.sign_binary_path = Some(path);
294        self
295    }
296
297    /// Builds the final [`DeveloperSetupConfig`].
298    ///
299    /// Usage:
300    /// ```ignore
301    /// let config = DeveloperSetupConfig::builder("my-key").build();
302    /// ```
303    pub fn build(self) -> DeveloperSetupConfig {
304        DeveloperSetupConfig {
305            key_alias: self.key_alias,
306            platform: self.platform,
307            git_signing_scope: self.git_signing_scope,
308            register_on_registry: self.register_on_registry,
309            registry_url: self.registry_url,
310            conflict_policy: self.conflict_policy,
311            witness_config: self.witness_config,
312            metadata: self.metadata,
313            sign_binary_path: self.sign_binary_path,
314        }
315    }
316}
317
318/// Configuration for CI/ephemeral identity.
319///
320/// Args:
321/// * `ci_environment`: The detected or specified CI platform.
322/// * `passphrase`: Passphrase for key encryption (typically from env var).
323/// * `registry_path`: Path to the ephemeral auths registry.
324/// * `keychain`: The key storage backend (use `MemoryKeyStorage` for CI).
325///
326/// Usage:
327/// ```ignore
328/// let config = CiSetupConfig {
329///     ci_environment: CiEnvironment::GitHubActions,
330///     passphrase: std::env::var("AUTHS_PASSPHRASE").unwrap(),
331///     registry_path: PathBuf::from("/tmp/.auths"),
332///     keychain: Box::new(memory_keychain),
333/// };
334/// ```
335pub struct CiSetupConfig {
336    /// The detected or specified CI platform.
337    pub ci_environment: CiEnvironment,
338    /// Passphrase for key encryption (typically from an environment variable).
339    pub passphrase: String,
340    /// Path to the ephemeral auths registry directory.
341    pub registry_path: PathBuf,
342    /// Key storage backend (typically `MemoryKeyStorage` for CI).
343    pub keychain: Box<dyn KeyStorage + Send + Sync>,
344}
345
346impl std::fmt::Debug for CiSetupConfig {
347    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
348        f.debug_struct("CiSetupConfig")
349            .field("ci_environment", &self.ci_environment)
350            .field("registry_path", &self.registry_path)
351            .field("passphrase", &"[REDACTED]")
352            .finish()
353    }
354}
355
356/// Configuration for agent identity.
357///
358/// Use [`AgentSetupConfigBuilder`] to construct this with optional fields.
359///
360/// Args:
361/// * `alias`: Human-readable name for the agent.
362/// * `parent_identity_did`: The DID of the identity that owns this agent.
363/// * `registry_path`: Path to the auths registry.
364///
365/// Usage:
366/// ```ignore
367/// let config = AgentSetupConfig::builder("deploy-bot", "did:keri:abc123", path)
368///     .with_capabilities(vec!["sign-commit".into()])
369///     .build();
370/// ```
371#[derive(Debug)]
372pub struct AgentSetupConfig {
373    /// Human-readable name for the agent.
374    pub alias: KeyAlias,
375    /// Capabilities granted to the agent.
376    pub capabilities: Vec<Capability>,
377    /// DID of the parent identity that delegates authority.
378    pub parent_identity_did: Option<String>,
379    /// Path to the auths registry directory.
380    pub registry_path: PathBuf,
381    /// Optional agent key expiration time in seconds.
382    pub expires_in_secs: Option<u64>,
383    /// If true, construct state without persisting.
384    pub dry_run: bool,
385}
386
387impl AgentSetupConfig {
388    /// Creates a builder with alias and registry path.
389    ///
390    /// Args:
391    /// * `alias`: Human-readable name for the agent.
392    /// * `registry_path`: Path to the auths registry directory.
393    ///
394    /// Usage:
395    /// ```ignore
396    /// let builder = AgentSetupConfig::builder("deploy-bot", path);
397    /// ```
398    pub fn builder(alias: KeyAlias, registry_path: impl Into<PathBuf>) -> AgentSetupConfigBuilder {
399        AgentSetupConfigBuilder {
400            alias,
401            capabilities: Vec::new(),
402            parent_identity_did: None,
403            registry_path: registry_path.into(),
404            expires_in_secs: None,
405            dry_run: false,
406        }
407    }
408}
409
410/// Builder for [`AgentSetupConfig`].
411#[derive(Debug)]
412pub struct AgentSetupConfigBuilder {
413    alias: KeyAlias,
414    capabilities: Vec<Capability>,
415    parent_identity_did: Option<String>,
416    registry_path: PathBuf,
417    expires_in_secs: Option<u64>,
418    dry_run: bool,
419}
420
421impl AgentSetupConfigBuilder {
422    /// Sets the parent identity DID that delegates authority to this agent.
423    ///
424    /// Args:
425    /// * `did`: The DID of the owning identity.
426    ///
427    /// Usage:
428    /// ```ignore
429    /// let config = AgentSetupConfig::builder("bot", path)
430    ///     .with_parent_did("did:keri:abc123")
431    ///     .build();
432    /// ```
433    pub fn with_parent_did(mut self, did: impl Into<String>) -> Self {
434        self.parent_identity_did = Some(did.into());
435        self
436    }
437
438    /// Sets the capabilities granted to the agent.
439    ///
440    /// Args:
441    /// * `capabilities`: List of capabilities.
442    ///
443    /// Usage:
444    /// ```ignore
445    /// let config = AgentSetupConfig::builder("bot", path)
446    ///     .with_capabilities(vec![Capability::sign_commit()])
447    ///     .build();
448    /// ```
449    pub fn with_capabilities(mut self, capabilities: Vec<Capability>) -> Self {
450        self.capabilities = capabilities;
451        self
452    }
453
454    /// Sets the agent key expiration time in seconds.
455    ///
456    /// Args:
457    /// * `secs`: Seconds until the agent identity expires.
458    ///
459    /// Usage:
460    /// ```ignore
461    /// let config = AgentSetupConfig::builder("bot", path)
462    ///     .with_expiry(86400) // 24 hours
463    ///     .build();
464    /// ```
465    pub fn with_expiry(mut self, secs: u64) -> Self {
466        self.expires_in_secs = Some(secs);
467        self
468    }
469
470    /// Enables dry-run mode (constructs state without persisting).
471    ///
472    /// Usage:
473    /// ```ignore
474    /// let config = AgentSetupConfig::builder("bot", path)
475    ///     .dry_run(true)
476    ///     .build();
477    /// ```
478    pub fn dry_run(mut self, enabled: bool) -> Self {
479        self.dry_run = enabled;
480        self
481    }
482
483    /// Builds the final [`AgentSetupConfig`].
484    ///
485    /// Usage:
486    /// ```ignore
487    /// let config = AgentSetupConfig::builder("bot", path).build();
488    /// ```
489    pub fn build(self) -> AgentSetupConfig {
490        AgentSetupConfig {
491            alias: self.alias,
492            capabilities: self.capabilities,
493            parent_identity_did: self.parent_identity_did,
494            registry_path: self.registry_path,
495            expires_in_secs: self.expires_in_secs,
496            dry_run: self.dry_run,
497        }
498    }
499}
500
501/// Configuration for extending a device authorization's expiration.
502///
503/// Args:
504/// * `repo_path`: Path to the auths registry.
505/// * `device_did`: The DID of the device whose authorization to extend.
506/// * `days`: Number of days from now for the new expiration.
507/// * `identity_key_alias`: Keychain alias for the identity key (for re-signing).
508/// * `device_key_alias`: Keychain alias for the device key (for re-signing).
509///
510/// Usage:
511/// ```ignore
512/// let config = DeviceExtensionConfig {
513///     repo_path: PathBuf::from("/home/user/.auths"),
514///     device_did: "did:key:z6Mk...".into(),
515///     days: 365,
516///     identity_key_alias: "my-identity".into(),
517///     device_key_alias: "my-device".into(),
518/// };
519/// ```
520#[derive(Debug)]
521pub struct DeviceExtensionConfig {
522    /// Path to the auths registry.
523    pub repo_path: PathBuf,
524    /// DID of the device whose authorization to extend.
525    pub device_did: String,
526    /// Number of days from now for the new expiration.
527    pub days: u32,
528    /// Keychain alias for the identity signing key.
529    pub identity_key_alias: KeyAlias,
530    /// Keychain alias for the device signing key.
531    pub device_key_alias: KeyAlias,
532}
533
534/// Configuration for rotating an identity's signing keys.
535///
536/// Args:
537/// * `repo_path`: Path to the auths registry (typically `~/.auths`).
538/// * `identity_key_alias`: Keychain alias of the current signing key.
539///   If `None`, the first non-next alias for the identity is used.
540/// * `next_key_alias`: Keychain alias to store the new key under.
541///   Defaults to `<identity_key_alias>-rotated-<timestamp>`.
542///
543/// Usage:
544/// ```ignore
545/// let config = RotationConfig {
546///     repo_path: PathBuf::from("/home/user/.auths"),
547///     identity_key_alias: Some("main".into()),
548///     next_key_alias: None,
549/// };
550/// ```
551#[derive(Debug)]
552pub struct RotationConfig {
553    /// Path to the auths registry (typically `~/.auths`).
554    pub repo_path: PathBuf,
555    /// Keychain alias of the current signing key (auto-detected if `None`).
556    pub identity_key_alias: Option<KeyAlias>,
557    /// Keychain alias for the new rotated key (auto-generated if `None`).
558    pub next_key_alias: Option<KeyAlias>,
559}
560
561/// Configuration for linking a device to an existing identity.
562///
563/// Args:
564/// * `identity_key_alias`: Alias of the identity key in the keychain.
565///
566/// Usage:
567/// ```ignore
568/// let config = DeviceLinkConfig {
569///     identity_key_alias: "my-identity".into(),
570///     device_key_alias: Some("macbook-pro".into()),
571///     device_did: None,
572///     capabilities: vec!["sign-commit".into()],
573///     expires_in_days: Some(365),
574///     note: Some("Work laptop".into()),
575///     payload: None,
576/// };
577/// ```
578#[derive(Debug)]
579pub struct DeviceLinkConfig {
580    /// Alias of the identity key in the keychain.
581    pub identity_key_alias: KeyAlias,
582    /// Optional alias for the device key (defaults to identity alias).
583    pub device_key_alias: Option<KeyAlias>,
584    /// Optional pre-existing device DID (not yet supported).
585    pub device_did: Option<String>,
586    /// Capabilities to grant to the linked device.
587    pub capabilities: Vec<Capability>,
588    /// Optional expiration period in days.
589    pub expires_in_days: Option<u32>,
590    /// Optional human-readable note for the attestation.
591    pub note: Option<String>,
592    /// Optional JSON payload to embed in the attestation.
593    pub payload: Option<serde_json::Value>,
594}