systemprompt_cli/commands/admin/
mod.rs1pub mod access_control;
12pub mod agents;
13pub mod bootstrap;
14pub mod bridge;
15pub mod config;
16pub mod evals;
17pub mod identity;
18pub mod keys;
19pub mod session;
20pub mod setup;
21pub mod users;
22
23use anyhow::Result;
24use clap::Subcommand;
25
26use crate::context::CommandContext;
27use crate::shared::render_result;
28
29#[derive(Debug, Subcommand)]
30pub enum AdminCommands {
31 #[command(subcommand, about = "User management and IP banning")]
32 Users(users::UsersCommands),
33
34 #[command(subcommand, about = "Agent management")]
35 Agents(agents::AgentsCommands),
36
37 #[command(subcommand, about = "Configuration management and rate limits")]
38 Config(config::ConfigCommands),
39
40 #[command(subcommand, about = "Evaluation runs over production AI traffic")]
41 Evals(evals::EvalsCommands),
42
43 #[command(about = "Interactive setup wizard for local development environment")]
44 Setup(setup::SetupArgs),
45
46 #[command(
47 about = "Idempotently ensure the system admin user exists with the admin role. Required \
48 by every install recipe before services start. Note: the admin ROLE only — \
49 deployments that derive platform admin from organization membership grant that \
50 half themselves (at boot, or via their own tooling)."
51 )]
52 Bootstrap(bootstrap::BootstrapArgs),
53
54 #[command(subcommand, about = "Manage CLI session and profile switching")]
55 Session(session::SessionCommands),
56
57 #[command(
58 subcommand,
59 about = "Bridge helper enrollment (device certs, exchange codes)"
60 )]
61 Bridge(bridge::BridgeCommands),
62
63 #[command(
64 subcommand,
65 name = "access-control",
66 about = "Access-control baseline operations (DB → YAML export)"
67 )]
68 AccessControl(access_control::AccessControlCommands),
69
70 #[command(
71 subcommand,
72 about = "RSA signing-key generation for the federated JWT plane"
73 )]
74 Keys(keys::KeysCommands),
75
76 #[command(
77 subcommand,
78 about = "Replica identity secrets shared by every node of a deployment"
79 )]
80 Identity(identity::IdentityCommands),
81}
82
83pub async fn execute(cmd: AdminCommands, ctx: &CommandContext) -> Result<()> {
84 if ctx.is_database_scoped()
91 && !matches!(cmd, AdminCommands::Users(_) | AdminCommands::Session(_))
92 {
93 return Err(crate::shared::database_scoped_command_error());
94 }
95
96 match cmd {
97 AdminCommands::Users(cmd) => users::execute(cmd, ctx).await,
98 AdminCommands::Agents(cmd) => Box::pin(agents::execute(cmd, ctx)).await,
99 AdminCommands::Config(cmd) => config::execute(cmd, ctx).await,
100 AdminCommands::Evals(cmd) => Box::pin(evals::execute(cmd, ctx)).await,
101 AdminCommands::Setup(args) => {
102 let result = Box::pin(setup::execute(args, ctx)).await?;
103 render_result(&result, &ctx.cli);
104 Ok(())
105 },
106 AdminCommands::Bootstrap(args) => {
107 let result = bootstrap::execute(args, &ctx.cli).await?;
108 render_result(&result, &ctx.cli);
109 Ok(())
110 },
111 AdminCommands::Session(cmd) => session::execute(cmd, ctx).await,
112 AdminCommands::Bridge(cmd) => bridge::execute(cmd, ctx).await,
113 AdminCommands::AccessControl(cmd) => access_control::execute(cmd, ctx).await,
114 AdminCommands::Keys(cmd) => keys::execute(cmd, ctx).await,
115 AdminCommands::Identity(cmd) => identity::execute(cmd, ctx),
116 }
117}