diff --git a/docs/agent-lifecycle/persistence.md b/docs/agent-lifecycle/persistence.md index ac536424..3f64dd44 100644 --- a/docs/agent-lifecycle/persistence.md +++ b/docs/agent-lifecycle/persistence.md @@ -535,8 +535,8 @@ container lifetime: 2. **Migrate any leftover `/root/.claude` content into `${homeDir}/.claude`** — legacy `claude` wrote to root's empty home; the bind mount didn't exist yet. Marker - (`/var/lib/hive-agent-user-migrated`) guards single-shot; it is - only written once there is nothing left to migrate, so a `cp` + (`/var/lib/hive-agent-user-migrated`) guards single-shot; it's + only written once there's nothing left to migrate, so a `cp` failure leaves it absent and the next boot retries. `cp -an` (no-clobber) so any pre-existing files at the new location win — never blow over data already there, and so a diff --git a/nix/host-modules/lib/atomic-write-secret.nix b/nix/host-modules/lib/atomic-write-secret.nix index 1456775c..6c6cb5a7 100644 --- a/nix/host-modules/lib/atomic-write-secret.nix +++ b/nix/host-modules/lib/atomic-write-secret.nix @@ -9,34 +9,25 @@ # # The value is a function ARGUMENT, not piped in on stdin: a producer that # exits non-zero partway through a pipe still leaves `cat` a clean EOF, so -# `atomic_write_secret`'s own writer has no way to tell a truncated read from -# an intentionally short one — the partial content would still land at the -# live path, `mv` and all, with only `pipefail` reporting the failure -# afterwards. A caller that computes the value with a command captures it -# into a variable first (`value=$(cmd)`, which fails under `set -e` before -# this function is ever called) and passes the finished value in. -# -# `$4` is never handed to an external program — it's a shell function -# argument, not a process's `argv`/environment, so it never appears in that -# process's own `/proc//cmdline`; the write inside uses `printf`, a -# shell builtin, for the same reason. +# a truncated read is indistinguishable from an intentionally short one, +# and the partial content would still land at the live path via `mv`. A +# caller that computes the value with a command captures it into a +# variable first (`value=$(cmd)`, which fails under `set -e` before this +# function is ever called) and passes the finished value in — never handed +# to an external program, so it never appears in a process's own +# `/proc//cmdline`, and written with `printf`, a shell builtin. # # Pure function — NOT a NixOS module. Call it from a module's `let`: # # atomicWriteSecret = import ./lib/atomic-write-secret.nix { }; -# ... # script = '' # ${atomicWriteSecret} # atomic_write_secret 0600 "" "$path" "$secret" -# atomic_write_secret 0400 "grafana:0" "$path" "$secret" # ''; # -# Args: mode, an owner for `chown` (`user:group` or a bare uid, or "" to -# leave the mktemp-created root:root ownership as it is), the target path, -# and the value. The value is written followed by a trailing newline (every -# call site's prior `printf '%s\n' "$value"` behaviour) — a caller building -# a multi-field value (e.g. `KEY=$value`) assembles the whole string first -# and passes that. Requires `coreutils` on the caller's `path`. +# Args: mode, an owner for `chown` ("" to keep mktemp's root:root), target +# path, value — written with a trailing newline like every call site's +# prior `printf '%s\n'`. Requires `coreutils` on the caller's `path`. { }: '' atomic_write_secret() {