split hivectl main.rs into per-domain modules (#2509)

This commit is contained in:
damocles 2026-07-16 11:17:50 +02:00
commit fc7720572b
16 changed files with 1922 additions and 1771 deletions

48
hivectl/src/github.rs Normal file
View file

@ -0,0 +1,48 @@
//! `hivectl github set-token <agent>` — write an operator-supplied GitHub PAT
//! into an agent's `github-token` state file via the daemon's privileged
//! helper, so the agent's `gh` wrapper + git credential helper authenticate.
use std::path::Path;
use anyhow::{Result, bail};
use crate::util::daemon_request;
/// `hivectl github set-token <agent>`: write an operator-supplied GitHub PAT
/// into the agent's `github-token` state file (0600, agent-owned) via
/// hive-priv, so the agent's `gh` wrapper + git credential helper can
/// authenticate. Read live at invocation, so no rebuild/restart is needed.
pub(crate) async fn github_set_token(
socket: &Path,
agent: &str,
token: Option<String>,
token_stdin: bool,
) -> Result<()> {
// Resolve + validate the token client-side (inline flag or stdin read);
// the daemon never touches this process's stdin. Persistence happens
// daemon-side via the privileged helper.
let token = match (token, token_stdin) {
(Some(t), _) => t,
(None, true) => {
let mut s = String::new();
std::io::Read::read_to_string(&mut std::io::stdin(), &mut s)?;
s.trim_end_matches(['\n', '\r']).to_owned()
}
(None, false) => bail!(
"provide the PAT via --token <pat> or --token-stdin (stdin preferred — \
an inline token is visible in shell history + process listings)"
),
};
if token.is_empty() {
bail!("refusing to write an empty GitHub token for agent '{agent}'");
}
daemon_request(
socket,
hive_host_sock::HostRequest::SetAgentGithubToken {
agent: agent.to_owned(),
token,
},
"github",
)
.await
}