Skip to content

fix: preserve ordinary POSIX mode when Code Collab saves text - #604

Merged
Leeeon233 merged 1 commit into
LodyAI:mainfrom
ladydd:fix/preserve-code-collab-save-mode
Sep 22, 2026
Merged

Leeeon233 merged 1 commit into
LodyAI:mainfrom
ladydd:fix/preserve-code-collab-save-mode

Conversation

@ladydd

@ladydd ladydd commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Related issue

Closes #603

Problem / pressure

Code Collab saveText reports success and then replaces the file with a new inode whose mode is 0666 & ~umask. Saving a 0755 script drops +x (EACCES on the next run). A 0600 file is widened to 0664/0644. Digest conflicts already skip the write; the successful path does not keep the ordinary mode.

Summary

writeFileAtomically still writes a temp file and renames it over the original path. On non-Windows it now lstats an existing regular file, chmods the temp path with mode & 0o777 before rename, and leaves conflict / file_deleted returns on the existing no-write paths. Adapter/core gitlinks are unchanged.

Visual explanation

writeFileAtomically(path, bytes)
  mode = lstat(path).mode & 0o777   # skip win32 / missing / non-file
  writeFile(temp, bytes, mode 0666) # still masked by umask
  if mode known: chmod(temp, mode)  # not masked by umask
  rename(temp, path)                # atomic replace

Conflict and deleted-file checks still run in saveText before this helper. A digest mismatch or missing file returns without creating the temp file.

Before / after

Before After
Save 0755 under umask 0022 → 0644, next exec is EACCES Save keeps 0755; script still runs
Save 0600 → 0664/0644 Save keeps 0600
Digest conflict / deleted file Unchanged: no write, no recreate
Windows Unchanged: no chmod (untested)

Test plan

  • apps/cli Vitest src/lib/code-collab/code-collab-v2-service.test.ts: 48 passed on Linux (Node 24.15.0). New coverage: umask 0022 + 0755 remains executable, 0600 stays 0600, 0644 stays 0644, digest conflict leaves 0755, deleted file returns file_deleted and is not recreated. Existing save/conflict tests still pass.
  • oxlint on the two changed TypeScript files: 0 warnings / 0 errors.
  • pnpm run docs check: 0 new errors (pre-existing AGENTS.md size warnings only).
  • check:code-collab-imports, check:platform-boundaries, check:public-boundary: passed.
  • Not run: packaged Electron click-save, macOS, Windows, ACL/xattr/setuid. Isolated profile; the developer's existing Electron instance was not stopped or replaced.

Context handoff

Instructions for reviewing agents

  • Review focus: writeFileAtomically in apps/cli/src/lib/code-collab/code-collab-v2-service.ts and the POSIX save tests; chmod must land on the temp path before rename, and conflict/deleted returns must still skip the write.
  • Decisions to challenge: Copying only mode & 0o777 (dropping setuid/setgid/sticky), skipping Windows chmod, and not restoring ACL/xattr on the new inode.
  • Plausible failures / evidence gaps: Packaged Electron click-save was not run; macOS/Windows untested; a delete between the digest check and rename can still recreate the file (pre-existing TOCTOU).

Authoring context

  • User goal / directives: Fix Code Collab save dropping ordinary POSIX mode, then open a main-repo Issue and PR; do not change adapter/core or fold this into Fix/electron local file browser #38/fix: pin Codex compact-kill waiter rejection #551.
  • Constraints / non-goals: Keep atomic rename and digest/deleted conflict behavior; do not claim ACL, special bits, Windows, macOS, or GUI coverage.
  • Risk-bearing decisions: chmod the temp file with the previous ordinary mode before it becomes visible, so umask cannot strip bits after writeFile.
  • Destructive or irreversible behavior: A successful save still replaces the file inode via rename; failed writes still unlink the temp path. Conflict and deleted-file paths do not write.
  • Deliberately not done or tested: No adapter/core changes; no Electron GUI click-through; no Windows/macOS/ACL/xattr/setuid tests.
  • Unknowns / confidence: Linux service tests pass for 0755/0600/0644 plus conflict/deleted protection. Residual risk is untested desktop GUI and non-Linux permission models.

Original user prompt

Code Collab text save should keep the file's original ordinary POSIX permission bits.

…#603)

writeFileAtomically created the replacement at mode 0666, so rename
left 0666 & ~umask and dropped +x on scripts. chmod the temp file
with the original ordinary bits before rename.
@github-actions github-actions Bot added the status:needs-pr-attention External PR needs contributor attention before review label Sep 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

@ladydd, this pull request needs updates before review.

It is marked status:needs-pr-attention. Address the findings below by 2026-09-28 09:18:44 UTC. The label and this comment are removed automatically after the PR passes validation.

If the PR remains invalid for 7 days, it will be closed and marked status:pr-policy-expired. Continue afterward by opening a new pull request with the current template.

Policy findings
PR does not meet Lody contribution requirements:

- Context handoff must include ### Shared conversation.

See `CONTRIBUTING.md` and `.github/PULL_REQUEST_TEMPLATE.md`.

@Leeeon233

Copy link
Copy Markdown
Contributor

LGTM

@Leeeon233
Leeeon233 merged commit babeacf into LodyAI:main Sep 22, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: cli status:needs-pr-attention External PR needs contributor attention before review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Code Collab save replaces POSIX mode with umask defaults

2 participants