Owner-only path checks have no migration: 421 pre-existing entries fail boot, one per attempt
Summary
The private-path checks require permissions to be exactly 0o700 for directories and 0o600 for files, but nothing in the upgrade path relaxes or repairs modes written by earlier releases. An ~/.astrid created by an older version fails the check, and because the check aborts on the first offending path, the operator gets one filename per boot attempt with no idea how many remain. On my install that was 421 entries.
Error: Failed to boot Kernel: private directory is not owner-only: /Users/jamie/.astrid/cow
Error: Failed to boot Kernel: private file is not owner-only: /Users/jamie/.astrid/cow/.DS_Store
Error: Failed to boot Kernel: private file is not owner-only: /Users/jamie/.astrid/home/claude-code/.local/log/a2a-capsule/2026-08-29.logMechanism
crates/astrid-core/src/platform_fs.rs:468 tests exact equality, not a permissive mask:
if metadata.permissions().mode() & 0o777 != 0o700 {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
format!("private directory is not owner-only: {}", path.display()),
));
}and platform_fs.rs:520 likewise for files:
if metadata.st_mode & 0o777 != 0o600 {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
format!("private file is not owner-only: {}", path.display()),
));
}The tightening is correct — these hold secrets, keys and principal state, and I am not arguing the check should be loosened. The problem is that it was introduced without a migration, and it is enforced during boot one path at a time. Directories created at 0755 and log files created at 0644 by earlier releases are now fatal, and recovery is a guessing game unless the operator thinks to run find ~/.astrid -perm +077 themselves.
Note the file rule is exactly 0o600, so a file at 0o700 also fails. Anything shipped executable inside the private tree would need care.
Reproduction Steps
- Use an
~/.astridcreated by an earlier release (mine dates to 2026-05-24) where directories are0755and log files are0644. - Upgrade to 2026.9.2 via
astrid update. - Run
astrid start. Boot fails naming one path. - Fix that one path. Run
astrid startagain. Boot fails naming the next path. - Repeat. In my case 421 entries needed fixing before boot progressed.
chmod -R go-rwx ~/.astrid resolves all of them at once, but the operator has to work that out unaided.
Expected Behavior
- Repair modes as part of the upgrade: walk the private tree once and
chmodentries the runtime owns to0700/0600, the same way other layout migrations run at boot. - Failing that, validate the whole tree in one pass and report every offending path, plus the exact remedy (
chmod -R go-rwx ~/.astrid), instead of aborting on the first one. - A pre-flight in
astrid doctorthat reports non-conforming modes would let this be caught before the daemon refuses to start.
Environment
- OS: macOS 15.6 (Darwin 24.6.0), arm64
- Astrid: 2026.9.2, installed via
astrid update - Source: astrid-runtime/astrid @
73661c9b(Cargo version 0.10.4) ~/.astridfirst created 2026-05-24- 421 files/directories failed the owner-only check
Logs / Backtrace
$ find ~/.astrid \( -type f -o -type d \) -perm +077 | wc -l
421
$ find ~/.astrid -type d -not -perm 700
/Users/jamie/.astrid/cow
/Users/jamie/.astrid/secrets/claude-code
/Users/jamie/.astrid/secrets/default
/Users/jamie/.astrid/etc/profiles
/Users/jamie/.astrid/var/update
/Users/jamie/.astrid/var/state.db
...Consecutive boot attempts, each surfacing exactly one path:
Error: Failed to boot Kernel: private directory is not owner-only: /Users/jamie/.astrid/cow
Error: Failed to boot Kernel: private file is not owner-only: /Users/jamie/.astrid/cow/.DS_Store
Error: Failed to boot Kernel: private file is not owner-only: /Users/jamie/.astrid/home/claude-code/.local/log/a2a-capsule/2026-08-29.logSource: astrid-runtime/astrid