48 lines
1.7 KiB
Rust
48 lines
1.7 KiB
Rust
//! `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: crate::util::parse_ident(agent)?,
|
|
token,
|
|
},
|
|
"github",
|
|
)
|
|
.await
|
|
}
|