Watch
0
0
Fork
You've already forked hyperhive
0

hive-c0re: stop silently dropping errors on credential/marker writes

Add secret_file::write_secret_0600: create the parent dir, write a
sibling temp file opened create_new + mode 0600, sync_all, rename over
the target. Use it for the matrix sender token, the space/chat room-id
files and the forge core token, which previously wrote at the process
umask, then chmod-ed with the error discarded, and dropped the
create_dir_all error. agent_identity::write_identity uses it too
instead of its own open-0600 loop; that loop opened with create +
truncate, so a pre-existing file kept its old mode.

Also log instead of discarding:
- the manager's applied-rev marker write in auto_update
- the knowledge `git remote set-url` scrub (spawn error and non-zero
  exit; the exit status only, since stderr may echo the old URL)
- the parent create_dir_all in paths::move_if_legacy

Closes #5037
This commit is contained in:
atlas 2026-10-09 09:47:54 +02:00 • committed by mara
commit f53ccb2740
8 changed files with 119 additions and 53 deletions

View file

@ -121,13 +121,12 @@ async fn collect(agent: &str, dir: &Path) -> Result<(), Skipped> {
/// Write the two private files, replacing whatever was there.
///
/// `0600` from the moment each file exists rather than after a `chmod`: the
/// key is written through a handle opened with that mode, so there is no
/// instant where it sits on disk world-readable.
/// `0600` from the moment each file exists rather than after a `chmod`
/// ([`crate::secret_file::write_secret_0600`]), so there is no instant where
/// the key sits on disk world-readable.
fn write_identity(dir: &Path, credential: &mtls::Credential) -> anyhow::Result<()> {
use anyhow::Context as _;
use std::io::Write as _;
use std::os::unix::fs::{OpenOptionsExt as _, PermissionsExt as _};
use std::os::unix::fs::PermissionsExt as _;
std::fs::create_dir_all(dir).with_context(|| format!("create {}", dir.display()))?;
// The directory too: its own mode is what stops anything but `hive-core`
@ -139,19 +138,7 @@ fn write_identity(dir: &Path, credential: &mtls::Credential) -> anyhow::Result<(
(CERT_CREDENTIAL, credential.cert.as_bytes()),
(KEY_CREDENTIAL, credential.key.as_bytes()),
] {
let file = dir.join(name);
let mut handle = std::fs::OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.mode(0o600)
.open(&file)
.with_context(|| format!("open {}", file.display()))?;
// The error carries the path and never the bytes — the one line in
// this function where a value could otherwise be interpolated.
handle
.write_all(bytes)
.with_context(|| format!("write {}", file.display()))?;
crate::secret_file::write_secret_0600(&dir.join(name), bytes)?;
}
// Public material, and `0644` says so — it is the same bundle every host