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}