Skip to content

fix(login): tolerate read-only CODEWITH_HOME in auth profile dir setup#284

Merged
andrei-hasna merged 1 commit into
mainfrom
fix/auth-profile
Jul 20, 2026
Merged

fix(login): tolerate read-only CODEWITH_HOME in auth profile dir setup#284
andrei-hasna merged 1 commit into
mainfrom
fix/auth-profile

Conversation

@andrei-hasna

Copy link
Copy Markdown
Contributor

What

Harden auth-profile config-directory setup in codex-login so it no longer
fails when CODEWITH_HOME (~/.codewith) is on a read-only mount.

create_private_dir_all previously ran fs::set_permissions(dir, 0o700)
unconditionally on every ensured directory. On a read-only / bind-mounted
CODEWITH_HOME (as used by OpenLoops auth-profile preflight and bounded
auth-profile health runs) that chmod fails with EROFS even when the
directory is already private and no write is actually required.

The new ensure_private_dir_mode:

  • skips the chmod entirely when the permission bits already equal 0o700
    (the common case), so a read-only filesystem never sees a needless write;
  • if the bits differ, attempts the chmod and tolerates a read-only-filesystem
    error only when the directory is already private (no group/other access) —
    otherwise the error is surfaced so credentials are never silently left
    world-accessible.

This mirrors, at the Rust layer, the JS shim fix already on main
(c30b6dc5c "fix(cli): tolerate read-only codewith home chmod"), which
handles the CODEWITH_HOME root but not the auth-profile subdirectories
ensured inside codex-login.

Why

BUG-PA14 (2d9d931b): "auth profile preflight chmod fails on read-only
CODEWITH_HOME". OpenLoops loops doctor / loops workflows validate --preflight invoke the codewith CLI, which chmods ~/.codewith; on a
read-only worker sandbox this raised EROFS and blocked preflight even
though config was already safely private.

Tests

Adds codex-login regression coverage:

  • ensure_private_dir_mode_leaves_already_private_dir_untouched — the
    already-0o700 early-return path (the read-only-safe case).
  • ensure_private_dir_mode_tightens_permissions_when_writable — still
    locks down an over-permissive dir when the FS is writable.
  • read_only_fs_errors_are_classified_for_tolerance — the
    read-only/permission error classifier.

Verification

E2B (fresh codewith-pr-drain box): check-fast for codex-login +
codex-corePASS (exit 0). Test-mode compilation reached the link
stage successfully; full unit-test execution was blocked by a disk-full
sandbox (environmental, "No space left on device") and runs in CI.

Notes on the related task

BUG-CW-AUTH-ACCOUNT004 (94343851, "auth profile health loop hits usage
limit") is not addressed by this PR: its acceptance is OpenLoops-side
(skip/cooldown a usage-limited profile in the provider/account pool before
bounded health loops burn scheduled runs). The in-repo detection primitive
already exists — codewith usage --json reports Exhausted + resets_at
without burning a model turn, and interactive auto-switch already reroutes
on a usage limit — so the remaining work belongs in the OpenLoops loop
scheduler, out of this repo.

codewith bug-fix fleet

Auth-profile directory setup unconditionally chmod'd every ensured
directory to 0o700, so any auth-profile operation on a read-only
CODEWITH_HOME (sandboxed/bind-mounted config used by OpenLoops
preflight and bounded auth-profile health runs) failed with EROFS even
when the directory was already private.

`create_private_dir_all` now skips the chmod when the permission bits
already match 0o700 (the common case, so a read-only mount never sees a
needless write), and tolerates a read-only-filesystem error only when
the directory is already private (no group/other access); otherwise the
failure is surfaced so credentials are never silently left
world-accessible. This mirrors the JS shim fix (c30b6dc) at the Rust
layer.

Adds regression coverage for the already-private early-return, the
tighten-when-writable path, and the read-only error classifier.

Refs: BUG-PA14 (2d9d931b)
@andrei-hasna
andrei-hasna merged commit 3fb3e84 into main Jul 20, 2026
19 of 20 checks passed
@andrei-hasna
andrei-hasna deleted the fix/auth-profile branch July 20, 2026 13:56
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant