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 keys;
17pub mod session;
18pub mod setup;
19pub mod users;
20
21use anyhow::Result;
22use clap::Subcommand;
23
24use crate::context::CommandContext;
25use crate::shared::render_result;
26
27#[derive(Debug, Subcommand)]
28pub enum AdminCommands {
29    #[command(subcommand, about = "User management and IP banning")]
30    Users(users::UsersCommands),
31
32    #[command(subcommand, about = "Agent management")]
33    Agents(agents::AgentsCommands),
34
35    #[command(subcommand, about = "Configuration management and rate limits")]
36    Config(config::ConfigCommands),
37
38    #[command(about = "Interactive setup wizard for local development environment")]
39    Setup(setup::SetupArgs),
40
41    #[command(
42        about = "Idempotently ensure the platform admin user exists with the admin role. Required \
43                 by every install recipe before services start."
44    )]
45    Bootstrap(bootstrap::BootstrapArgs),
46
47    #[command(subcommand, about = "Manage CLI session and profile switching")]
48    Session(session::SessionCommands),
49
50    #[command(
51        subcommand,
52        about = "Bridge helper enrollment (device certs, exchange codes)"
53    )]
54    Bridge(bridge::BridgeCommands),
55
56    #[command(
57        subcommand,
58        name = "access-control",
59        about = "Access-control baseline operations (DB → YAML export)"
60    )]
61    AccessControl(access_control::AccessControlCommands),
62
63    #[command(
64        subcommand,
65        about = "RSA signing-key generation for the federated JWT plane"
66    )]
67    Keys(keys::KeysCommands),
68}
69
70pub async fn execute(cmd: AdminCommands, ctx: &CommandContext) -> Result<()> {
71    if ctx.is_database_scoped() && !matches!(cmd, AdminCommands::Users(_)) {
72        return Err(crate::shared::database_scoped_command_error());
73    }
74
75    match cmd {
76        AdminCommands::Users(cmd) => users::execute(cmd, ctx).await,
77        AdminCommands::Agents(cmd) => Box::pin(agents::execute(cmd, ctx)).await,
78        AdminCommands::Config(cmd) => config::execute(cmd, ctx).await,
79        AdminCommands::Setup(args) => {
80            let result = Box::pin(setup::execute(args, ctx)).await?;
81            render_result(&result, &ctx.cli);
82            Ok(())
83        },
84        AdminCommands::Bootstrap(args) => {
85            let result = bootstrap::execute(args, &ctx.cli).await?;
86            render_result(&result, &ctx.cli);
87            Ok(())
88        },
89        AdminCommands::Session(cmd) => session::execute(cmd, ctx).await,
90        AdminCommands::Bridge(cmd) => bridge::execute(cmd, ctx).await,
91        AdminCommands::AccessControl(cmd) => access_control::execute(cmd, ctx).await,
92        AdminCommands::Keys(cmd) => keys::execute(cmd, ctx).await,
93    }
94}