Skip to content

State/logging/input robustness: atomic manifest, rename retries, rotation recovery, WithAttrs, distro-name validation #93

Description

@zcsizmadia

Batch of state/logging/input robustness findings from the independent v0.2.0 review. All LOW; one PR's worth together.

  • writeManifest is the one non-atomic state write (provision): bare os.WriteFile — a crash mid-write corrupts manifest.json and the supervisor exits "no install found" until repair. Use the tmp+rename pattern every other state file already uses.
  • Rename-over-existing can hit sharing violations (state.go, config): Go opens without FILE_SHARE_DELETE, so a rename racing a concurrent reader (supervisor tick reads every 3s) can fail spuriously; also the tmp name is a constant, so two concurrent writers can collide. Retry the rename once on sharing violation; use os.CreateTemp in the state dir.
  • Log rotation reopen failure leaves a dead logger (rotate.go, found by two reviewers): after Close+rename, if reopen fails, w.f is a closed handle, every Write errors, slog discards handler errors, and the next rotation aborts at Close — supervisor runs logless until restart. Treat Close errors as non-fatal, nil the handle on reopen failure, retry open() in Write.
  • consoleHandler.WithAttrs/WithGroup silently drop attributes (cmd/hawser/console.go): a future log.With() loses context invisibly. Implement or document.
  • Validate distro names at the Options boundary (provision): names reach sh -c scripts as positional args (safe) but also path-ish contexts — the unshare cleanup does rm -rf "$(dirname "$1")", and integrate writes the name into a profile script line. All self-inflicted-only today; a [A-Za-z0-9._-]+ gate closes the class.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Small; batch or document during v0.3bugSomething isn't workingreview-findingFrom the 2026-09 independent 4-agent review of v0.2.0

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions