SystemdLauncher::stop_all runs one synchronous systemctl stop over the
instance's mind-self and mind-persona units (stop_args, built from the same
templates as start and alive). cli::run gains a stop_units parameter that only
brake hold calls, after the write whatever its outcome. The window probe uses
dial set instead of brake hold, since a real hold now runs systemctl.
Builds not yet verified on the stopgap at this commit.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
clippy.toml lists the std::env readers (var, var_os, vars, vars_os,
set_var, remove_var, args, args_os, current_exe, temp_dir, home_dir) and
libc::getenv as disallowed methods, and lib.rs forbids allowing them back.
main.rs and the self-spawning integration test carry the only allows.
The forge probe's environment sweep and its 22 guessed variable names go:
the lint covers a variable of any name, so the list was a second, weaker
path for the same rule.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
read_effective(instance) reads CONTROL_ROOT/<instance>/control.cc. The root override is a thread-local under cfg(test) inside the crate; the reader tests and the Grant launch tests move in-crate to use it. The operator CLI's show derives its display line from the store it already read. An external forge probe and compile_fail examples pin the rule; the instance gate is pinned with same-length, prefix and extension forgeries, and the Persona refusal with a claim of every kind.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Grant carries the instance whose store was read; read_effective(root, instance)
derives the store path itself and no caller supplies a path or a source. The
launch refuses a Grant of another instance and a Persona request with claims,
both typed refusals that name no input. Launcher drops its dead label: liveness
is keyed by unit (instance, turn). Tests pin Persona step 0, the Operator-run
exclusion, the fiftieth ended run and the same-batch boundary.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The run cap and cadence leave the control reader only inside a Grant with
private fields, so a cap cannot exist without a released brake and an
in-bounds dial. effective() is private; its one caller is read_effective.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rust-toolchain.toml owns which rustc and clippy judge the tree. View in
HuginnMindResponse is boxed so the large_enum_variant allow on the wire
type is deleted; the PipelineDocument allow keeps a sharpened reason.
Type aliases, is_multiple_of, slice::from_ref and a literal refused()
clear the rest. Wire bytes and schemas are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Soul s3: the window probe wrote a window-probe-<pid> instance under the real
/etc/gamecult/minds. A leading --root argv flag (argv, because sudo -E carries
the environment) replaces the default root; the probe points the real binary at
a tempdir, whose drop removes whatever a failed assert leaves. No test names
/etc/gamecult any more; the path-derivation test uses CONTROL_ROOT.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Under the binary's umask 077 a first write would have left /etc/gamecult/minds
0700 and unreadable by the units. The attacker reports how much it swept.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Soul s2: under a permissive umask the store was group/world-writable between
CultCache's rename and the chmod, and an fd opened there survived it. The
mind-control binary now sets umask 077 first (the library never touches the
umask). The writer refuses to write through an existing directory, lock or store
that is not root's or is group/world-writable, with the typed UnsafeStore error
naming path, mode and owner. Tests: a non-root open-for-write probe against the
real binary under umask 000; refusals for 0777/0775 directories, 0666/0664
locks and stores, and a non-root-owned directory; accepted root installs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Modes under umask 000/022/077 via a re-executed test child; a non-root user
(setpriv uid 65534, skipped with a message when not root) cannot write the store
but can read it; an undecodable or NaN dial reads Held(Undecodable) whatever the
brake says, which kills the fail-open default-dial mutant.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>