fix: route forge_admin through hive-priv; auto-recover matrix passwords

forge_admin() spawned nixos-container run hive-forge directly from the
hive-core process. nixos-container run uses nsenter to enter the container
namespaces, which requires root. hive-core is unprivileged, so every call
failed with: nsenter: stat of /proc/<pid>/ns/user failed: Permission denied

Fix: add RunForgeAdmin { args } to PrivRequest. hive-priv (root) handles
it by spawning nixos-container run hive-forge -- runuser -u forgejo --
forgejo --work-path /var/lib/forgejo admin <args>. forge_admin() now calls
priv_client::run_forge_admin().

matrix: ensure_user_for hit M_USER_IN_USE then failed when the stored
password file was missing (state dirs wiped but homeserver kept accounts).
Previously required manual hivectl matrix reset-password <name>.

Fix: add auto_reset_password() — calls the admin API (PUT
/_synapse/admin/v2/users/@<name>:<server> with the hive admin token) to
set a new random password, then proceeds with login. Falls back to the
existing manual-recovery error if the admin token is unavailable.

Closes #1234
This commit is contained in:
atlas 2026-06-03 23:17:39 +02:00
commit 34bc4c0b06
5 changed files with 147 additions and 47 deletions

View file

@ -248,6 +248,14 @@ pub async fn chmod_socket_dir(agent_name: &str, mode: u32) -> Result<()> {
.await?)
}
/// Run `forgejo admin <args>` inside the `hive-forge` container via
/// hive-priv (which runs as root and can nsenter into the container).
/// Returns `(stdout, stderr)` on success.
pub async fn run_forge_admin(args: &[&str]) -> Result<(String, String)> {
let owned: Vec<String> = args.iter().map(|s| (*s).to_owned()).collect();
check(call(&PrivRequest::RunForgeAdmin { args: owned }).await?)
}
fn check(resp: PrivResponse) -> Result<(String, String)> {
if resp.ok {
Ok((resp.stdout, resp.stderr))