silicon-remind-cli 0.1.2

Silicon Remind command line interface
use clap::{Args, Parser, Subcommand, ValueEnum};
use uuid::Uuid;

#[derive(Parser)]
#[command(
    name = "remind",
    version,
    about = "Create and manage Silicon reminders through Silicon IAM.",
    long_about = "Silicon Remind schedules one-time or recurring reminders using five-field Linux cron. Silicons manage their own reminders; Carbons and Silicons can read their organization's reminders.\n\nStart with: remind login <slt>\nOptionally subscribe a receiver: remind webhook subscribe <url>\nCreate a reminder: remind create --text 'Check the build' --cron '*/5 * * * *'\nUse any command in a saved sandbox: remind --test <test_id> <command>.",
    after_help = "Authentication:\n  remind iam --json                 Discover the IAM app_id before obtaining an SLT\n  remind login <slt>                Exchange your IAM short-lived token\n  remind login status --json        Verify the saved Carbon or Silicon identity\n\nLocal state defaults to $SILICON_HOME/.remind when SILICON_HOME is set, otherwise ~/.remind. Use remind config home <directory> to select an existing directory.\n\nRun remind <command> --help for command-specific options and examples.",
    subcommand_required = true,
    arg_required_else_help = true
)]
pub struct Cli {
    /// Override the server origin for this invocation (credentials stay scoped to that origin).
    #[arg(long, global = true, env = "REMIND_URL")]
    pub url: Option<String>,
    /// Select the organization for this invocation.
    #[arg(long, global = true, env = "REMIND_ORG")]
    pub org: Option<String>,
    /// Run the same command in a saved test environment, using its isolated session.
    #[arg(long, global = true)]
    pub test: Option<Uuid>,
    /// Print machine-readable JSON; suggestions go to stderr only in human mode.
    #[arg(long, global = true)]
    pub json: bool,
    /// Skip this invocation's automatic registry check.
    #[arg(long, global = true)]
    pub no_update: bool,
    /// Reuse a mutation key when retrying the exact same create, edit or status operation.
    #[arg(long, global = true)]
    pub idempotency_key: Option<String>,
    #[command(subcommand)]
    pub command: Command,
}
#[derive(Subcommand)]
pub enum Command {
    /// Log in with an IAM short-lived token, or inspect live authentication status.
    #[command(args_conflicts_with_subcommands = true, arg_required_else_help = true)]
    Login {
        #[arg(value_name = "SLT")]
        slt: Option<String>,
        #[command(subcommand)]
        command: Option<Login>,
    },
    /// Show public IAM application information, including the app_id needed for an SLT.
    Iam,
    /// Log in using an IAM short-lived token; inspect or revoke the current session.
    Auth {
        #[command(subcommand)]
        command: Auth,
    },
    /// Create a reminder owned by the signed-in Silicon.
    #[command(
        after_help = "Examples:\n  remind create --text 'Daily standup' --cron '0 9 * * MON-FRI' --timezone Asia/Kolkata\n  remind create --text 'One reminder' --cron '30 16 * * *' --kind one-time\n\nAdd optional receivers with remind webhook subscribe <url>."
    )]
    Create {
        #[arg(long)]
        text: String,
        #[arg(long)]
        cron: String,
        #[arg(long, default_value = "UTC")]
        timezone: String,
        #[arg(long, value_enum, default_value = "recurring")]
        kind: Kind,
    },
    /// List current reminders; use --archived for the 45-day archive.
    List {
        #[arg(long)]
        silicon: Option<String>,
        #[arg(long)]
        archived: bool,
        #[arg(long, value_enum)]
        status: Option<Status>,
        #[command(flatten)]
        page: Page,
    },
    /// Show one reminder, including its next trigger and archive deadline.
    Get { id: Uuid },
    /// Change reminder text, cron, timezone or kind. Archived reminders are immutable.
    Edit {
        id: Uuid,
        #[arg(long)]
        text: Option<String>,
        #[arg(long)]
        cron: Option<String>,
        #[arg(long)]
        timezone: Option<String>,
        #[arg(long, value_enum)]
        kind: Option<Kind>,
    },
    /// Atomically pause one or up to 100 owned reminders without archiving them.
    Pause {
        #[arg(required=true,num_args=1..=100)]
        ids: Vec<Uuid>,
    },
    /// Atomically resume owned reminders and calculate their next future occurrences.
    Resume {
        #[arg(required=true,num_args=1..=100)]
        ids: Vec<Uuid>,
    },
    /// Archive one owned reminder. It remains readable for 45 days.
    Archive { id: Uuid },
    /// Inspect delivery attempts, failures and webhook ingress receipt IDs.
    Executions {
        id: Uuid,
        #[command(flatten)]
        page: Page,
    },
    /// List registered Silicons in the current organization.
    Silicons {
        #[arg(long)]
        after: Option<Uuid>,
        #[arg(long,default_value_t=50,value_parser=clap::value_parser!(u32).range(1..=100))]
        limit: u32,
    },
    /// Add, inspect or remove the signed-in Silicon's webhook subscriptions.
    Webhook {
        #[command(subcommand)]
        command: Webhook,
    },
    /// Manage organization-owned test environments using the production session.
    Env {
        #[command(subcommand)]
        command: Environment,
    },
    /// Inspect the selected sandbox; requires --test <id>.
    TestInfo,
    /// Configure this sandbox's test-only IAM Application secret (requires --test).
    ConfigureIam {
        #[arg(long)]
        iam_app_secret_file: Option<std::path::PathBuf>,
    },
    /// Erase all data in the selected sandbox while retaining its key and IAM binding.
    #[command(
        after_help = "Requires --test <id>. This erases reminders, delivery history, webhook configuration and sandbox logs. It does not clean the linked IAM environment."
    )]
    Clean,
    /// Show or set local server and updater preferences.
    Config {
        #[command(subcommand)]
        command: Config,
    },
    /// Check crates.io or explicitly update this CLI after the command completes.
    Update {
        #[arg(long)]
        check: bool,
    },
    /// Probe API liveness or database readiness.
    Health {
        #[arg(long)]
        ready: bool,
    },
}
#[derive(Subcommand)]
pub enum Login {
    /// Verify the saved session with IAM and report the Carbon or Silicon identity.
    Status,
}
#[derive(Subcommand)]
pub enum Auth {
    /// Exchange an IAM SLT; prompt securely, or read it from standard input.
    Login {
        #[arg(long)]
        slt_stdin: bool,
    },
    /// Show current live IAM identity and organization permissions.
    Whoami,
    /// Explicitly rotate the current refresh token.
    Refresh,
    /// Revoke the IAM session, then remove the saved credentials.
    Logout,
}
#[derive(Subcommand)]
pub enum Webhook {
    /// Register any HTTP(S) URL and optional HMAC signing secret.
    Set {
        #[arg(value_name = "URL")]
        endpoint_url: String,
        #[arg(long)]
        secret_stdin: bool,
        /// Send without an HMAC signing secret.
        #[arg(long, conflicts_with = "secret_stdin")]
        unsigned: bool,
    },
    /// Add another independent webhook subscription.
    Subscribe {
        #[arg(value_name = "URL")]
        endpoint_url: String,
        #[arg(long)]
        secret_stdin: bool,
        /// Send without an HMAC signing secret.
        #[arg(long, conflicts_with = "secret_stdin")]
        unsigned: bool,
    },
    /// Show the configured endpoint; the signing secret is never returned.
    Get,
    /// List every active webhook subscription.
    List,
    /// Disable one subscription by its UUID.
    Unsubscribe { id: Uuid },
    /// Disable delivery configuration until it is set again.
    Disable,
}
#[derive(Subcommand)]
pub enum Environment {
    /// Create an empty Remind environment bound to an existing IAM test environment.
    Create {
        name: String,
        #[arg(long)]
        description: Option<String>,
        #[arg(long)]
        iam_key_file: Option<std::path::PathBuf>,
        #[arg(long)]
        iam_app_secret_file: Option<std::path::PathBuf>,
    },
    /// List active environments, optionally including recoverable deleted ones.
    List {
        #[arg(long)]
        include_deleted: bool,
        #[arg(long)]
        after: Option<Uuid>,
        #[arg(long,default_value_t=50,value_parser=clap::value_parser!(u32).range(1..=100))]
        limit: u32,
    },
    /// Inspect one environment's metadata and retention deadlines.
    Get { id: Uuid },
    /// Retrieve and print an environment key; also save it locally.
    Key { id: Uuid },
    /// Rotate an environment key and save the successor locally.
    Rotate { id: Uuid },
    /// Retire an environment; recover it within 30 days using env restore.
    Delete { id: Uuid },
    /// Restore a retired environment with a fresh root key.
    Restore { id: Uuid },
    /// Save a shared root key locally; no production session is needed.
    Import {
        id: Uuid,
        #[arg(long)]
        key_stdin: bool,
    },
    /// Forget a saved key and session on this computer; leaves the server untouched.
    Forget { id: Uuid },
}
#[derive(Subcommand)]
pub enum Config {
    Show,
    SetUrl {
        #[arg(value_name = "URL")]
        service_url: String,
    },
    /// Set the parent directory used for the local Remind state directory.
    Home {
        #[arg(value_name = "DIRECTORY")]
        location: std::path::PathBuf,
    },
    AutoUpdate {
        #[arg(value_enum)]
        value: Toggle,
    },
}
#[derive(Clone, Copy, ValueEnum)]
pub enum Toggle {
    On,
    Off,
}
#[derive(Clone, Copy, ValueEnum)]
pub enum Kind {
    OneTime,
    Recurring,
}
#[derive(Clone, Copy, ValueEnum)]
pub enum Status {
    Active,
    Paused,
    Completed,
}
#[derive(Args)]
pub struct Page {
    #[arg(long)]
    cursor: Option<String>,
    #[arg(long,default_value_t=50,value_parser=clap::value_parser!(u32).range(1..=100))]
    limit: u32,
}
impl Page {
    pub fn cursor(&self) -> Option<String> {
        self.cursor.clone()
    }
    pub fn limit(&self) -> u32 {
        self.limit
    }
}
impl From<Kind> for silicon_remind_client::models::ScheduleKind {
    fn from(v: Kind) -> Self {
        match v {
            Kind::OneTime => Self::OneTime,
            Kind::Recurring => Self::Recurring,
        }
    }
}
impl From<Status> for silicon_remind_client::models::ScheduleStatus {
    fn from(v: Status) -> Self {
        match v {
            Status::Active => Self::Active,
            Status::Paused => Self::Paused,
            Status::Completed => Self::Completed,
        }
    }
}