Skip to main content

systemprompt_cli/commands/admin/
mod.rs

1//! `admin` command tree: privileged platform administration.
2//!
3//! [`AdminCommands`] groups user, agent, configuration, session, bridge,
4//! access-control, and signing-key management plus the setup and bootstrap
5//! flows. On a `--database-url` invocation only the user-management subgroup
6//! is served; the rest require a full profile context.
7//!
8//! Copyright (c) systemprompt.io — Business Source License 1.1.
9//! See <https://systemprompt.io> for licensing details.
10
11pub mod access_control;
12pub mod agents;
13pub mod bootstrap;
14pub mod bridge;
15pub mod config;
16pub mod evals;
17pub mod keys;
18pub mod session;
19pub mod setup;
20pub mod users;
21
22use anyhow::Result;
23use clap::Subcommand;
24
25use crate::context::CommandContext;
26use crate::shared::render_result;
27
28#[derive(Debug, Subcommand)]
29pub enum AdminCommands {
30    #[command(subcommand, about = "User management and IP banning")]
31    Users(users::UsersCommands),
32
33    #[command(subcommand, about = "Agent management")]
34    Agents(agents::AgentsCommands),
35
36    #[command(subcommand, about = "Configuration management and rate limits")]
37    Config(config::ConfigCommands),
38
39    #[command(subcommand, about = "Evaluation runs over production AI traffic")]
40    Evals(evals::EvalsCommands),
41
42    #[command(about = "Interactive setup wizard for local development environment")]
43    Setup(setup::SetupArgs),
44
45    #[command(
46        about = "Idempotently ensure the platform admin user exists with the admin role. Required \
47                 by every install recipe before services start."
48    )]
49    Bootstrap(bootstrap::BootstrapArgs),
50
51    #[command(subcommand, about = "Manage CLI session and profile switching")]
52    Session(session::SessionCommands),
53
54    #[command(
55        subcommand,
56        about = "Bridge helper enrollment (device certs, exchange codes)"
57    )]
58    Bridge(bridge::BridgeCommands),
59
60    #[command(
61        subcommand,
62        name = "access-control",
63        about = "Access-control baseline operations (DB → YAML export)"
64    )]
65    AccessControl(access_control::AccessControlCommands),
66
67    #[command(
68        subcommand,
69        about = "RSA signing-key generation for the federated JWT plane"
70    )]
71    Keys(keys::KeysCommands),
72}
73
74pub async fn execute(cmd: AdminCommands, ctx: &CommandContext) -> Result<()> {
75    if ctx.is_database_scoped() && !matches!(cmd, AdminCommands::Users(_)) {
76        return Err(crate::shared::database_scoped_command_error());
77    }
78
79    match cmd {
80        AdminCommands::Users(cmd) => users::execute(cmd, ctx).await,
81        AdminCommands::Agents(cmd) => Box::pin(agents::execute(cmd, ctx)).await,
82        AdminCommands::Config(cmd) => config::execute(cmd, ctx).await,
83        AdminCommands::Evals(cmd) => Box::pin(evals::execute(cmd, ctx)).await,
84        AdminCommands::Setup(args) => {
85            let result = Box::pin(setup::execute(args, ctx)).await?;
86            render_result(&result, &ctx.cli);
87            Ok(())
88        },
89        AdminCommands::Bootstrap(args) => {
90            let result = bootstrap::execute(args, &ctx.cli).await?;
91            render_result(&result, &ctx.cli);
92            Ok(())
93        },
94        AdminCommands::Session(cmd) => session::execute(cmd, ctx).await,
95        AdminCommands::Bridge(cmd) => bridge::execute(cmd, ctx).await,
96        AdminCommands::AccessControl(cmd) => access_control::execute(cmd, ctx).await,
97        AdminCommands::Keys(cmd) => keys::execute(cmd, ctx).await,
98    }
99}