Skip to main content

cairn_cli/cli/
identity.rs

1use clap::{Args, Subcommand};
2use serde_json::json;
3
4use crate::client::BackpacClient;
5use crate::errors::CairnError;
6
7use super::{output_json, Cli};
8
9#[derive(Args, Debug)]
10pub struct IdentityArgs {
11    #[command(subcommand)]
12    pub command: IdentityCommands,
13}
14
15#[derive(Subcommand, Debug)]
16pub enum IdentityCommands {
17    /// Register a new DID identity anchored to a wallet.
18    Register {
19        /// DID identifier (e.g., did:key:z6Mk...)
20        #[arg(long)]
21        did: String,
22
23        /// Wallet address for the identity
24        #[arg(long)]
25        wallet: String,
26
27        /// Ed25519 public key (base64 or hex)
28        #[arg(long)]
29        public_key: String,
30
31        /// Human-readable display name
32        #[arg(long)]
33        display_name: Option<String>,
34    },
35
36    /// Rotate the signing key for a registered DID.
37    Rotate {
38        /// DID identifier to rotate
39        #[arg(long)]
40        did: String,
41
42        /// Current public key (for verification)
43        #[arg(long)]
44        current_key: String,
45
46        /// New public key to replace the current one
47        #[arg(long)]
48        new_key: String,
49    },
50
51    /// Get the current state of a registered DID.
52    Get {
53        /// DID identifier to look up
54        did: String,
55    },
56}
57
58impl IdentityArgs {
59    pub async fn execute(&self, cli: &Cli) -> Result<(), CairnError> {
60        let client = BackpacClient::new(cli.jwt.as_deref(), cli.api_url.as_deref(), cli.worker_url.as_deref());
61
62        match &self.command {
63            IdentityCommands::Register {
64                did,
65                wallet,
66                public_key,
67                display_name,
68            } => {
69                let mut body = json!({
70                    "did": did,
71                    "wallet_address": wallet,
72                    "public_key": public_key,
73                });
74                if let Some(name) = display_name {
75                    body["display_name"] = json!(name);
76                }
77                let result = client.post("/v1/agents/identity", &body).await?;
78                output_json(&result, &cli.output);
79                Ok(())
80            }
81
82            IdentityCommands::Rotate {
83                did,
84                current_key,
85                new_key,
86            } => {
87                let body = json!({
88                    "did": did,
89                    "current_public_key": current_key,
90                    "new_public_key": new_key,
91                });
92                let result = client.put("/v1/agents/identity/rotate", &body).await?;
93                output_json(&result, &cli.output);
94                Ok(())
95            }
96
97            IdentityCommands::Get { did } => {
98                let path = format!("/v1/agents/identity/{}", urlencoding::encode(did));
99                let result = client.get(&path).await?;
100                output_json(&result, &cli.output);
101                Ok(())
102            }
103        }
104    }
105}