Skip to content

Improve ocx init compatibility and recovery guidance when hard-link publication is unavailable #3893

Closed

Description

@parkjs101

Area

CLI

What are you trying to accomplish?

Complete first-run setup with ocx init when the configuration filesystem refuses hard-link publication, while preserving the existing confidentiality and complete-file publication guarantees. If those guarantees cannot be provided on that filesystem, users need actionable guidance for choosing a supported configuration location.

What prevents this today?

Reviewed at dev commit 76436a3ee221d577cc94d6c10544c03bb1f9d9db.

publishInitialConfigNoReplace hardens a private temporary file, writes the complete configuration, then publishes it with one hard-link operation. Unsupported or denied links fail explicitly; this is intentional behavior introduced by #3796 and documented in the quickstart, rather than an unhandled exception.

The error identifies the hard-link requirement and warns that configuration may already exist, but does not explain how to select a supported location or distinguish a link restriction from a permission-hardening failure.

The temporary file is a sibling of the target. Merely placing OPENCODEX_HOME on another drive does not create a cross-device link.

What should OpenCodex do?

Provide a documented recovery path when initial publication is unavailable:

  • Explain the filesystem/permission requirements and how to select a configuration location that satisfies them.
  • Preserve the warning to inspect the destination before retrying when publication is uncertain.
  • Distinguish a failure to secure the temporary file from a failure to publish it.
  • Consider an alternative publication strategy only if it preserves all existing guarantees: permission hardening before secret bytes are written, complete-file visibility, no replacement of any existing destination, and cleanup that cannot damage an existing or concurrently published file.

An actionable diagnostic/documentation improvement is a useful first step. Alternative filesystem support should require evidence that these guarantees hold; this proposal does not require an unconditional fallback.

Example usage or interface

For a fresh installation whose current location rejects publication:

  1. Run ocx init.
  2. Receive an explanation of the failed prerequisite and instructions to inspect any existing config or temporary residue.
  3. Select a supported OPENCODEX_HOME location and retry setup, without hand-writing a configuration containing credentials.

Existing configuration must remain preserved throughout this workflow.

Alternatives or workarounds

Opening the destination with O_CREAT | O_EXCL prevents replacement, but writing its contents afterward exposes an empty or partial config. It is not equivalent to publishing a fully written private file.

Ordinary rename/replacement is also not an acceptable fallback if it can replace a concurrent winner. On Windows, a fallback must account for required ACL hardening as well as hard-link support.

Additional context

Verification used Windows with Bun 1.4.0 and the implementation's injected I/O seam. For each of EOPNOTSUPP, ENOTSUP, ENOSYS, EXDEV, and EPERM, an injected link failure produced:

{
  "name": "InitialConfigPublicationError",
  "publication": "uncertain",
  "hardLinkUnavailable": true,
  "residualTemp": false,
  "targetExists": false
}

The isolated probe used nonsensitive fixture bytes and bypassed ACL hardening solely to reach the link fault boundary. This verifies error handling, not successful operation on an actual non-NTFS/FUSE/network filesystem. No physical-filesystem reproduction is claimed.

Existing regression coverage includes partial-write cleanup and denied-link behavior in tests/config/config-mutation-lock.test.ts. That whole test file could not run in this fresh checkout because zod/v4 was unavailable; the standalone publication probe did run.

Checks

  • I searched existing issues and documentation.
  • This request describes a concrete OpenCodex workflow rather than merely naming a desired technology.
  • I removed secrets and personal data.

Activity

  1. lidge-jun commented on Sep 7, 2026

    @lidge-jun
    Owner

    리뷰 · 우선순위 47 / 80

    이 이슈는 ocx init이 설정 파일시스템에 hard-link 발행을 거부당할 때, 사용자가 다음에 뭘 해야 하는지 안내가 부족하다는 요청입니다. 지금 dev의 publishInitialConfigNoReplace(src/config/initialize.ts)는 임시 파일을 권한 강화 → 전체 설정 기록 → hard-link 한 번으로 발행합니다. #3796이 넣은 의도된 실패이고 quickstart에도 요구사항이 있습니다. src/cli/init.ts 진단은 hard-link 필요와 “설정이 이미 있을 수 있음”은 말하지만, 지원되는 OPENCODEX_HOME을 고르는 법이나 “임시 파일 보안 실패 vs 발행 실패” 구분은 약합니다. 임시 파일이 대상의 형제가 되므로, 홈만 다른 드라이브로 옮긴다고 cross-device link가 해결되지 않는다는 지적도 맞습니다.

    원하는 1차는 문서/진단 개선입니다. 대체 발행 전략은 기존 보장(기록 전 권한 강화, 완전 파일만 노출, 기존 대상 교체 없음, 동시 발행 파일 손상 없는 정리)을 깨지 않을 때만 검토하라고 해서 안전합니다. Windows에서 EOPNOTSUPP/ENOTSUP/ENOSYS/EXDEV/EPERM 주입 재현도 적혀 있습니다.

    src/cli/init.ts (InitialConfigPublicationError 분기) - hardLinkUnavailable / residualTemp / targetExists를 구분해 “지원 FS로 OPENCODEX_HOME 옮기고 재시도” 문장을 넣으면 이슈의 최소 해결에 가깝습니다.

    docs-site/.../quickstart.md - 요구사항만 있고 실패 후 복구 절차가 빈약하면 여기와 CLI 메시지를 같이 고치세요.

    대체 publish 전략 - O_CREAT|O_EXCL 후 쓰기나 일반 rename은 부분 노출·동시 승자 교체 위험이 있어 기본 폴백으로 쓰면 안 됩니다. 본문 경고를 유지하세요.

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

    너의 추천
    문서/CLI 진단 개선 PR을 help wanted로 받으세요. hard-link 보장 완화나 무조건 rename 폴백은 받지 마세요.

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

  2. added a commit that references this issue on Sep 7, 2026
    6188458
  3. lidge-jun commented on Sep 7, 2026

    @lidge-jun
    Owner

    Fixed on dev in 6188458 via #3941, which carried @parkjs101's #3896.

    ocx init now separates a required permission-hardening failure from denied hard-link publication instead of reporting both as "Initial config publication did not finish.", and both messages name OPENCODEX_HOME as the place to move to. The quickstart explains inspecting the directory before retrying, that an existing config.json is preserved, and how to pick a fresh location on Windows or Unix.

    One thing the same change fixed underneath: publishInitialConfigNoReplace built its exclusive-create flags numerically, which Bun on Windows misreads as ENOENT. On an affected setup ocx init could fail before it produced any diagnostic at all. That call site now uses the portable spelling, so the improved guidance is reachable rather than pre-empted.

    This does not add a fallback for a filesystem that cannot support hard links or private permissions — the no-replace publication guarantee is unchanged. It tells you which requirement was not met and where to go instead.

    Closing manually: pull requests here target dev, and GitHub only auto-closes linked issues on the default branch.

  4. added a commit that references this issue on Sep 17, 2026
    b06243d
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

    cliCLI, config inject, packaging flagsenhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions