Identity Operations¶
The auths-sdk crate provides orchestration functions for identity lifecycle operations. All functions accept typed config structs and an AuthsContext carrying injected infrastructure adapters. They never prompt for input, print to stdout, or call process::exit().
AuthsContext¶
Every SDK operation requires an AuthsContext, which is built using a typestate builder pattern. The registry, key_storage, and clock fields are compile-time required; omitting any of them is a compile error.
use std::sync::Arc;
use auths_sdk::context::AuthsContext;
let ctx = AuthsContext::builder()
.registry(Arc::new(my_registry))
.key_storage(Arc::new(my_keychain))
.clock(Arc::new(SystemClock))
.identity_storage(Arc::new(my_identity_storage))
.attestation_sink(Arc::new(my_attestation_sink))
.attestation_source(Arc::new(my_attestation_source))
.passphrase_provider(Arc::new(my_passphrase_provider)) // defaults to noop
.event_sink(Arc::new(my_telemetry_sink)) // defaults to noop
.uuid_provider(Arc::new(my_uuid_provider)) // defaults to random v4
.build();
AuthsContext Fields¶
| Field | Type | Required | Default |
|---|---|---|---|
registry |
Arc<dyn RegistryBackend + Send + Sync> |
Yes | -- |
key_storage |
Arc<dyn KeyStorage + Send + Sync> |
Yes | -- |
clock |
Arc<dyn ClockProvider + Send + Sync> |
Yes | -- |
identity_storage |
Arc<dyn IdentityStorage + Send + Sync> |
Yes (runtime) | panics on build |
attestation_sink |
Arc<dyn AttestationSink + Send + Sync> |
Yes (runtime) | panics on build |
attestation_source |
Arc<dyn AttestationSource + Send + Sync> |
Yes (runtime) | panics on build |
passphrase_provider |
Arc<dyn PassphraseProvider + Send + Sync> |
No | NoopPassphraseProvider |
event_sink |
Arc<dyn EventSink> |
No | NoopSink |
uuid_provider |
Arc<dyn UuidProvider + Send + Sync> |
No | SystemUuidProvider |
Developer Identity Setup¶
setup_developer() provisions a new developer identity with device linking, optional platform verification, Git signing configuration, and registry publication.
Function Signature¶
pub fn setup_developer(
config: DeveloperSetupConfig,
ctx: &AuthsContext,
keychain: &(dyn KeyStorage + Send + Sync),
signer: &dyn SecureSigner,
passphrase_provider: &dyn PassphraseProvider,
git_config: Option<&dyn GitConfigProvider>,
) -> Result<SetupResult, SetupError>
Configuration¶
use auths_sdk::types::{
DeveloperSetupConfig, GitSigningScope, IdentityConflictPolicy, PlatformVerification,
};
use auths_core::storage::keychain::KeyAlias;
let config = DeveloperSetupConfig::builder(KeyAlias::new("work-laptop")?)
.with_platform(PlatformVerification::GitHub {
access_token: "ghp_abc123".into(),
})
.with_git_signing_scope(GitSigningScope::Global)
.with_conflict_policy(IdentityConflictPolicy::ReuseExisting)
.with_registration("https://registry.auths.dev")
.with_witness_config(witness_cfg)
.with_metadata(serde_json::json!({"team": "platform"}))
.with_sign_binary_path(PathBuf::from("/usr/local/bin/auths-sign"))
.build();
IdentityConflictPolicy¶
Controls what happens when an identity already exists at the configured path:
| Variant | Behavior |
|---|---|
IdentityConflictPolicy::Error |
Returns SetupError::IdentityAlreadyExists (default) |
IdentityConflictPolicy::ReuseExisting |
Silently reuses the existing identity |
IdentityConflictPolicy::ForceNew |
Overwrites with a new identity |
Result¶
pub struct SetupResult {
pub identity_did: String, // e.g. "did:keri:E..."
pub device_did: String, // e.g. "did:key:z6Mk..."
pub key_alias: KeyAlias,
pub platform_claim: Option<PlatformClaimResult>,
pub git_signing_configured: bool,
pub registered: Option<RegistrationOutcome>,
}
CI/Ephemeral Identity Setup¶
setup_ci() provisions an ephemeral identity for automated CI pipelines. It uses an in-memory keychain and produces environment variable export lines.
Function Signature¶
Configuration¶
use auths_sdk::types::{CiSetupConfig, CiEnvironment};
let config = CiSetupConfig {
ci_environment: CiEnvironment::GitHubActions,
passphrase: std::env::var("AUTHS_PASSPHRASE").unwrap(),
registry_path: PathBuf::from("/tmp/.auths"),
keychain: Box::new(memory_keychain),
};
Supported CiEnvironment variants: GitHubActions, GitLabCi, Custom { name: String }, Unknown.
Result¶
pub struct CiSetupResult {
pub identity_did: String,
pub device_did: String,
pub env_block: Vec<String>, // Shell `export` lines for CI env vars
}
Agent Identity Setup¶
setup_agent() provisions a delegated agent identity with scoped capabilities and optional expiration.
Function Signature¶
pub fn setup_agent(
config: AgentSetupConfig,
ctx: &AuthsContext,
keychain: Box<dyn KeyStorage + Send + Sync>,
passphrase_provider: &dyn PassphraseProvider,
) -> Result<AgentSetupResult, SetupError>
Configuration¶
use auths_sdk::types::AgentSetupConfig;
use auths_core::storage::keychain::KeyAlias;
let config = AgentSetupConfig::builder(
KeyAlias::new("deploy-bot")?,
PathBuf::from("/home/user/.auths"),
)
.with_parent_did("did:keri:Eabc123")
.with_capabilities(vec!["sign-commit".into(), "sign-release".into()])
.with_expiry(86400) // 24 hours
.dry_run(false)
.build();
Result¶
pub struct AgentSetupResult {
pub agent_did: String,
pub parent_did: String,
pub capabilities: Vec<String>,
}
Device Linking¶
link_device() creates a signed attestation that binds a new device key to an existing identity.
Function Signature¶
pub fn link_device(
config: DeviceLinkConfig,
ctx: &AuthsContext,
clock: &dyn ClockProvider,
) -> Result<DeviceLinkResult, DeviceError>
Configuration¶
use auths_sdk::types::DeviceLinkConfig;
let config = DeviceLinkConfig {
identity_key_alias: KeyAlias::new("my-identity")?,
device_key_alias: Some(KeyAlias::new("macbook-pro")?),
device_did: None,
capabilities: vec!["sign-commit".into()],
expires_in: Some(31_536_000),
note: Some("Work laptop".into()),
payload: None,
};
Result¶
Device Revocation¶
revoke_device() creates a signed revocation record that invalidates a device's attestation.
pub fn revoke_device(
device_did: &str,
identity_key_alias: &KeyAlias,
ctx: &AuthsContext,
note: Option<String>,
clock: &dyn ClockProvider,
) -> Result<(), DeviceError>
Device Authorization Extension¶
extend_device_authorization() creates a new attestation with an extended expiry for an existing device.
pub fn extend_device_authorization(
config: DeviceExtensionConfig,
ctx: &AuthsContext,
clock: &dyn ClockProvider,
) -> Result<DeviceExtensionResult, DeviceExtensionError>
Configuration¶
use auths_sdk::types::DeviceExtensionConfig;
let config = DeviceExtensionConfig {
repo_path: PathBuf::from("/home/user/.auths"),
device_did: "did:key:z6Mk...".into(),
days: 365,
identity_key_alias: KeyAlias::new("my-identity")?,
device_key_alias: KeyAlias::new("my-device")?,
};
Key Rotation¶
rotate_identity() performs a KERI key rotation, replacing the current signing key with the pre-committed next key and generating a new forward-looking commitment.
Function Signature¶
pub fn rotate_identity(
config: RotationConfig,
ctx: &AuthsContext,
clock: &dyn ClockProvider,
) -> Result<RotationResult, RotationError>
Configuration¶
use auths_sdk::types::RotationConfig;
let config = RotationConfig {
repo_path: PathBuf::from("/home/user/.auths"),
identity_key_alias: Some(KeyAlias::new("main")?),
next_key_alias: None, // auto-generated as "<alias>-rotated-<timestamp>"
};
Result¶
pub struct RotationResult {
pub controller_did: String,
pub new_key_fingerprint: String, // hex-encoded first 8 bytes
pub previous_key_fingerprint: String, // hex-encoded first 8 bytes
}
Rotation Internals¶
Rotation is a three-phase process:
compute_rotation_event()-- Pure, deterministic construction of the KERIRotEvent. Signs the event with the pre-committed next key.apply_rotation()-- Side-effecting KEL append and keychain write. Non-atomic: if the KEL write succeeds but the keychain write fails, aRotationError::PartialRotationis returned with a recovery path.rotate_identity()-- High-level orchestrator that calls both phases in order.
Clock Injection¶
All SDK functions that involve timestamps accept a ClockProvider or read from AuthsContext.clock. The SDK layer calls clock.now() and passes the value down to domain functions. Utc::now() is banned in auths-core and auths-id source code.