Skip to content

fix(init): explain configuration publication recovery - #3896

Closed
parkjs101 wants to merge 1 commit into
lidge-jun:devfrom
parkjs101:codex/init-publication-guidance
Closed

fix(init): explain configuration publication recovery#3896
parkjs101 wants to merge 1 commit into
lidge-jun:devfrom
parkjs101:codex/init-publication-guidance

Conversation

@parkjs101

@parkjs101 parkjs101 commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #3893.

When first-run configuration cannot be secured or published, ocx init now distinguishes permission-hardening failure from denied hard-link publication and directs the user to a supported OPENCODEX_HOME location. The quickstart explains inspection before retry, preserving existing configuration, and choosing a fresh location on Windows or Unix.

The existing write order, private permissions, complete-file publication, no-replacement behavior, and cleanup remain unchanged. CLI integration tests cover permission, link, and cleanup faults, including privacy-safe messages, uncertain-publication warnings, backup preservation, and stopping subsequent setup prompts.

Verification

Windows, Bun 1.4.0; independent branch from dev at 522ce5f8c8527d1e6c479a0090af14e390214bcb.

  • bun test tests/config/config-mutation-lock.test.ts tests/service/init-eof.test.ts --test-name-pattern 'failed hardening|unsupported/denied link|publication recovery guidance': 9 passed. These cases failed before the diagnostic change.
  • bun test tests/config/config-mutation-lock.test.ts tests/service/init-eof.test.ts: 38 passed, 3 skipped, 2 failed. Both failures also occur on unchanged 522ce5f8c: Windows denies file-symlink creation in init refuses a directory and a dangling symlink without following either; a swapped temporary symlink is neither written through nor removed as our inode then lacks the expected residue. No skips or weakened assertions were added.
  • bun run typecheck: passed.
  • bun run privacy:scan: passed.
  • In docs-site: bun install --frozen-lockfile and bun run build: passed, 425 pages. Lockfiles unchanged; translated quickstarts checked for conflicting instructions.

Physical unsupported-filesystem compatibility is not claimed; the fault tests exercise the existing injected I/O boundary. This draft does not attest full local CI or maintainer security approval. Plan and evidence: devlog/_plan/260907_init_publication_guidance/010_implementation.md.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Maintainer review of the initial-config boundary remains pending.

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

Summary by CodeRabbit

  • Bug Fixes

    • Improved setup failure diagnostics to distinguish private-permission issues from hard-link publication failures.
    • Error messages now provide safer, clearer recovery guidance without exposing sensitive filesystem details.
  • Documentation

    • Added troubleshooting guidance for inspecting existing configuration files and retrying setup.
    • Documented using OPENCODEX_HOME to select a fresh, writable configuration location on Windows, macOS, and Linux.
    • Clarified that changing the configuration location does not migrate an existing installation.

@coderabbitai

coderabbitai Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Team

Run ID: 836ca615-c197-4a00-883e-701736986572

📥 Commits

Reviewing files that changed from the base of the PR and between 522ce5f and fc78bc3.

📒 Files selected for processing (6)
  • devlog/_plan/260907_init_publication_guidance/010_implementation.md
  • docs-site/src/content/docs/getting-started/quickstart.md
  • src/config/initialize.ts
  • structure/02_config-and-codex-home.md
  • tests/config/config-mutation-lock.test.ts
  • tests/service/init-eof.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Changes

Initial publication diagnostics

Layer / File(s) Summary
Permission-aware publication diagnostics
src/config/initialize.ts
InitialConfigPublicationError accepts hardeningFailed. publishInitialConfigNoReplace sets this flag around permission hardening and reports a privacy-safe permission diagnostic when hardening fails.
Publication failure coverage
tests/config/config-mutation-lock.test.ts, tests/service/init-eof.test.ts
Tests cover hardening, hard-link, cleanup, and partial-write failures. They verify recovery guidance, redaction of raw errors and secrets, exit status, and preservation of existing files.
Supported-location recovery guidance
docs-site/src/content/docs/getting-started/quickstart.md, structure/02_config-and-codex-home.md, devlog/_plan/260907_init_publication_guidance/010_implementation.md
Documentation distinguishes permission-hardening failures from hard-link failures and describes fresh OPENCODEX_HOME locations, inspection before retry, and the absence of direct-write or replacing-rename fallbacks.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to fc78b

Initial configuration setup now provides distinct, privacy-safe recovery guidance for permission hardening and hard-link publication failures while retaining the existing no-replacement, complete-file publication behavior. The covered failure paths preserve existing configuration and are ready to merge.

Sequence Diagram(s)

sequenceDiagram
  participant Operator
  participant InitWizard
  participant ConfigPublication
  participant ConfigFilesystem
  participant CLI
  Operator->>InitWizard: run ocx init
  InitWizard->>ConfigPublication: publish initial configuration
  ConfigPublication->>ConfigFilesystem: harden temporary file
  ConfigFilesystem-->>ConfigPublication: permission or hard-link failure
  ConfigPublication-->>CLI: privacy-safe publication diagnostic
  CLI-->>Operator: OPENCODEX_HOME recovery guidance
Loading

Suggested reviewers: invalid-email-address

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: improved recovery guidance for configuration publication failures during initialization.
Linked Issues check ✅ Passed The changes satisfy issue #3893. They distinguish hardening failures from hard-link publication failures, provide supported OPENCODEX_HOME recovery guidance, preserve privacy and existing configuratio…
Out of Scope Changes check ✅ Passed All changes are related to issue #3893. The implementation, tests, quickstart updates, configuration documentation, and implementation plan support the requested diagnostics, recovery workflow, securi…
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 3 files. (3 skipped: 3 …
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Sep 7, 2026
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • review readiness checklist open (0/4 boxes ticked).

What to do

  • Tick all four boxes in the PR description once you're done (currently 0/4).

Review readiness checklist

  • ⬜ All CI tests are green on my local testing.
  • ⬜ I pushed my PR to the latest dev commit.
  • ⬜ I resolved all correct Codex and CodeRabbit findings.
  • ⬜ My PR is ready for review.

0/4 boxes ticked.

This PR stays in draft until every box above is ticked.

Hygiene

Deterministic PR hygiene checks passed.

@parkjs101
parkjs101 marked this pull request as ready for review September 7, 2026 11:54
@github-actions
github-actions Bot marked this pull request as draft September 7, 2026 11:54
@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 54 / 80

이 PR은 #3893을 닫습니다. ocx init이 첫 설정을 쓸 때 hard-link 발행이나 권한 강화가 실패하면, 예전에는 “hard-link가 거부됐다” 정도의 짧은 말만 나왔습니다. 사용자는 무엇을 검사하고, 어디에 OPENCODEX_HOME을 두면 되는지 알기 어려웠습니다. 이번 변경은 권한 강화 실패와 hard-link 거부를 나누고, 둘 다 지원되는 위치 선택 안내를 붙입니다. 쓰기 순서·비공개 권한·완전한 파일 발행·덮어쓰기 금지·정리 규칙은 그대로입니다. 직접 쓰기나 rename 폴백은 일부러 넣지 않았습니다.

src/config/initialize.tsInitialConfigPublicationErrorhardeningFailed 옵션을 받습니다. harden 호출 직전에 플래그를 켜고, 성공하면 끕니다. harden이 던지면 메시지는 “permissions could not be secured… OPENCODEX_HOME…”이고, hard-link 거부는 기존 문구에 검사·OPENCODEX_HOME 안내를 덧붙입니다. raw cause 문자열은 메시지에 넣지 않습니다. quickstart와 structure/02_config-and-codex-home.md에 권한 실패 vs link 실패, 재시도 전 검사, Windows/Unix OPENCODEX_HOME 예, 위치 변경이 마이그레이션이 아님을 적었습니다. 단위·CLI 통합 테스트로 메시지·잔여 파일 경고·백업 보존·후속 프롬프트 중단을 검증합니다. docs-site 빌드 425페이지 통과를 보고했습니다. 같은 Windows 호스트의 symlink EPERM 2건은 베이스라인에도 있던 실패라고 했고, 새 assertion을 약하게 만들지 않았습니다.

src/config/initialize.ts · InitialConfigPublicationError - hardeningFailed를 먼저 보고, 그다음 hardLinkUnavailable, 아니면 일반 “did not finish”입니다. partial write는 권한 실패로 오인되지 않게 테스트했습니다.

src/config/initialize.ts · publishInitialConfigNoReplace - harden 전후에만 hardeningFailed를 토글합니다. open 실패나 write/link 실패는 권한 메시지로 위장되지 않습니다. I/O 순서 변경 없음이 핵심입니다.

docs-site/.../quickstart.md - 재시도 전 config 디렉터리 검사, 기존 config.json 삭제 금지, 새 위치는 hard link+private permission을 지원해야 한다는 안내가 초보에게도 읽힙니다.

tests/service/init-eof.test.ts - 실제 CLI wizard 경로로 permissions/link/link-residue를 주입해 exit 1·OPENCODEX_HOME·비밀 문자열 비노출·백업 보존을 봅니다.

메인테이너의 판단이 필요한 지점

  • 메시지/문서만으로 #3893을 닫을지, 아니면 비지원 파일시스템 폴백을 나중에 따로 둘지
  • Windows symlink EPERM 베이스라인 실패를 이 PR과 무관하게 둘지
  • draft checklist를 머지 전에 채울지

너의 추천
발행 보장을 약화하지 않은 UX/docs 수정이라 mid로 머지 후보입니다. checklist 정리 후 넣고 #3893을 닫으세요. 폴백 쓰기 경로는 넣지 않은 결정을 유지하는 편이 안전합니다.

이 댓글은 grok-bot이 작성했습니다

@lidge-jun

Copy link
Copy Markdown
Owner

Carried into #3941 as the top layer of a manual stack, cherry-picked with -x so the commit keeps you as the git author, plus a Co-authored-by: Joonsuh Park <trckstr4422@gmail.com> trailer that survives the squash.

The stack puts one change underneath yours: src/config/initialize.ts still opened its temp file with the numeric O_WRONLY | O_CREAT | O_EXCL combination that Bun on Windows misreads, so first-run ocx init could fail with ENOENT before reaching any of the diagnostics this PR improves. That line is now openSync(temp, "wx", 0o600).

That produced exactly one conflict, the adjacent hunk where your hardeningFailed = true sits directly after the openSync line. The resolution keeps both. An independent read-only review compared the result byte-for-byte against this PR's pinned head fc78bc37d and confirmed it equals your file with only that one substitution, that hardeningFailed is still set immediately before hardenInitialConfig and cleared immediately after it returns, and that your other five files are byte-identical.

Leaving this open until #3941 lands on dev; it will be closed then with the merge commit named. Thanks for the fix.

lidge-jun added a commit that referenced this pull request Sep 7, 2026
ea8265a is @parkjs101's work from #3896, cherry-picked with -x onto the
portable exclusive-open change. The one conflict was the adjacent hunk this
stack was ordered to resolve once: the carried commit inserts hardeningFailed
directly after the openSync line that the layer below rewrote. Both survive.

A squash landing keeps only the squash message, so the trailer lives here.

Co-authored-by: Joonsuh Park <trckstr4422@gmail.com>
lidge-jun added a commit that referenced this pull request Sep 7, 2026
… init publication recovery (#3941)

Bun on Windows misreads the numeric `O_WRONLY | O_CREAT | O_EXCL` combination and drops the creation bit, so every private config temp write failed with ENOENT: the pid file, config.json, the Codex runtime cache, and the OAuth credential store all route through the two atomic writers, and publishInitialConfigNoReplace hit the same wall before first-run `ocx init` could publish anything. All three call sites now use the portable `openSync(path, "wx", 0o600)` spelling.

"wx" maps to O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, so it is behaviorally equivalent here rather than bit-identical: exclusive creation rejects an existing name, including a symlink planted at the temp path, so the added O_TRUNC can never truncate anything. The 0o600 mode, Windows ACL hardening order, identity verification, the single hard-link publication, and descriptor-owned cleanup are unchanged.

`ocx init` also now separates a required permission-hardening failure from denied hard-link publication, and both messages name OPENCODEX_HOME as the recovery path. Previously a hardening failure fell into the generic "publication did not finish" message with no direction.

Landed as a three-layer manual stack through this tip: #3900 carried, the same spelling applied to initialize.ts, then #3896 carried on top. The one conflict was the adjacent hunk where #3896 inserts hardeningFailed directly after the rewritten openSync line; both survive.

Closes #3893. Supersedes #3900 and #3896.

Co-authored-by: x3M3x <amroeid1999@gmail.com>
Co-authored-by: Joonsuh Park <trckstr4422@gmail.com>
@lidge-jun

Copy link
Copy Markdown
Owner

Landed on dev in 6188458 via #3941. Closing as delivered, and #3893 is closed with it.

All six of your files are on dev, each hashing identical to this PR's pinned head fc78bc37d except src/config/initialize.ts, which differs only by the two substitutions from the layer underneath: the constants import is gone and the temp open is now openSync(temp, "wx", 0o600). Your hardeningFailed flag still sets immediately before hardenInitialConfig and clears immediately after it returns, so the diagnostic still distinguishes exactly what you intended. The squash message carries Co-authored-by: Joonsuh Park <trckstr4422@gmail.com>.

CI on the integration head passed all 25 jobs with no reruns.

Thanks — the recovery guidance is a real improvement over a message that told users only that publication had stopped.

@lidge-jun

Copy link
Copy Markdown
Owner

Correction to my closure comment above: I wrote "passed all 25 jobs", which overstates it. The accurate figure for run 34153124187 is 19 successful jobs and 2 skipped, with zero failures or cancellations on the first attempt — 24 successful check runs across that head counting the separate PR-gate workflows.

The two skips are the conditional macos control and Windows shard lanes, which are dispatch-only. Windows packaging and keyring smoke passed; the Windows test suite itself did not run. That does not change the outcome, but "all 25 jobs passed" is not what the run says.

@lidge-jun

Copy link
Copy Markdown
Owner

Landed via #3941 at 6188458ae3f4fd84ef57344b60cf3ceeed80aa6f

@lidge-jun lidge-jun added the landed-via-maintainer Original PR closed after landing via a maintainer merge train label Sep 7, 2026
@kkwanmoo621-crypto kkwanmoo621-crypto mentioned this pull request Sep 7, 2026
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working landed-via-maintainer Original PR closed after landing via a maintainer merge train

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants