Repository navigation
fix: keep fenced proxies restartable and failed Windows updates recoverable (#5496, #5624) - #5643
Conversation
…ested identity (#5496) A proxy whose installed package tree was replaced fences /healthz, /readyz and /v1/* with 503 package_tree_changed. Liveness treated any non-200 /healthz as "no proxy", so ocx restart reported the proxy as not running and fell back to a start that could not bind, and ocx stop's orphan fallback missed it too. The fence now withholds readiness but not identity. The fenced /healthz answers the local attestation challenge and reports restartCapability plus the installedVersion now on disk. Liveness accepts the 503 only for callers that opt in (restart discovery, ocx stop and uninstall orphan fallbacks, service stop) and only after this home's runtime record names the same pid and port and the listener proves that record's secret; the pid in the body alone is never identity. The bound restart client admits exactly that fenced body, compares the CLI with installedVersion because the in-place respawn runs the replaced files at the same path, and refuses while that version is unreadable. The invariant is recorded as INV-FENCE-01 in structure/overview.md and in the package-tree fence section of structure/ops/docs-and-release.md.
…p on failure (#5624) A Windows update that failed during the staging npm install kept the previous version and restored the service, but its cleanup was a silent best-effort rmSync: a locked bunx.exe left the staging tree behind with nothing marking it, nothing ever swept it, and the dashboard job only recorded "update command failed (1)". Staging directories are now created exclusively under a unique name and carry an ownership marker. Cleanup removes everything but the marker first, so a partly locked stage stays provably owned, and the next update removes marked stages older than an in-flight floor. Unmarked stages from older updaters, npm's own .<name>-<random> rename-asides, other packages' stages and links are reported and never deleted. A post-swap verification failure moves the rejected tree into the owned stage instead of deleting it in place, so a locked file there cannot turn a rollback into a double fault. After a failed npm update the launcher prints a phase-specific next step (retry, then stop + reinstall + service restart; or the recovery marker after a double fault) in place of the old "Try manually" line, and the dashboard job points at the terminal for it. The ENOTDIR root cause in the report is not established by this change.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Warning Review limit reachedNext included review available in 3 minutes. View limit detailsLimit details: You’ve used all 10 included reviews currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Repository: lidge-jun/opencodex/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (29)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
|
✅ Deterministic PR hygiene checks passed. |
💡 Codex Reviewopencodex/src/cli/system-restart-client.ts Lines 140 to 145 in 9d80cc6 When an out-of-band npm install has written a valid opencodex/src/update/transactional-install.mjs Lines 296 to 297 in 9d80cc6 For a user-scoped npm prefix, AGENTS.md reference: AGENTS.md:L454-L455 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
… by position The uninstall orphan fallback was outside the audited opt-in set for fenced identity and is pinned by its own source test, so it keeps plain liveness. The stop-path ordering test now locates the orphan probe by its call rather than its exact empty argument list, which the fenced opt-in changed.
…cement settles; log leftover names only A readable package.json is not an install-completion signal: npm can write the manifest while it is still extracting the rest of the tree. The fenced /healthz now reports installedVersion only after the guard's stability debounce has seen the same replacement identity for the full interval, and withdraws it whenever the tree moves again, so a manual restart cannot respawn from a partial tree. Leftover and staging log lines name the folder only; the full path under a user-scoped npm prefix carries the account name.
리뷰 · 우선순위 64 / 80이 PR은 업데이트 중에 프록시가 끊기는 두 구멍을 막아요. 베이스는 패키지 파일이 돌아가는 프록시 밑에서 바뀌면, 프록시는 윈도우에서 npm 업데이트가 실패해도 다음 시도가 막히지 않게 해요. 임시 폴더는 매번 새 이름이고, 우리가 만들었다는 표식을 넣어요. 지울 때는 표식을 맨 마지막에 지워요. 파일이 잠겨 있으면 다음 업데이트가 반시간보다 오래된 우리 폴더만 치워요. 남이 만든 폴더와 npm이 이름을 바꿔 둔 폴더는 이름만 알려 주고 지우지 않아요. 실패한 단계에 따라 다음에 칠 명령을 터미널에 찍어요. 대시보드는 터미널을 보라고만 해요. src/cli/index.ts:1586 - src/lib/package-tree-integrity.ts:66 - 설치가 끝났다는 신호는 src/update/update-failure-guidance.mjs:28 - 이전 버전이 남아 있으면 메인테이너의 판단이 필요한 지점
우리 것이 아닌 임시 폴더는 업데이트할 때마다 다시 출력돼요. 사용자가 지우기 전까지 같은 줄이 반복돼요. 한 번만 알릴지 매번 알릴지 정해 주셔야 해요. 너의 추천 제거의 고아 프록시 찾기에 이 댓글은 grok-bot이 작성했습니다 |
Summary
Two continuity gaps for an installed proxy whose package is updated or replaced.
#5496: a package-tree fenced proxy stays discoverable. When the installed package tree is replaced under a live proxy, the guard answers
/healthz,/readyzand/v1/*with 503package_tree_changed. Liveness treated any non-200/healthzas "no proxy", soocx restartreported that no proxy was running and started one that could not bind, andocx stop's orphan fallback missed it. The automatic drain and restart already ondev(src/server/index/package-tree-guard.ts) is unchanged. This PR closes the manual path:/healthzwithholds readiness but keeps identity. It answers the local attestation challenge and reportsrestartCapability, plus theinstalledVersionon disk once the replacement has held for the guard's full stability interval (a readable manifest alone does not mean npm finished extracting).ocx restartdiscovery, theocx stopand uninstall orphan fallbacks, service stop) and only after this home's runtime record names the same pid and port and the listener proves that record's secret. The pid in the body is never trusted on its own. Ensure, update health waits and replacement waits stay opted out.installedVersion, because the in-place respawn runs the replaced files at the same path, and refuses with a clear message while that version is unreadable.INV-FENCE-01(structure/overview.md) and in the package-tree fence section ofstructure/ops/docs-and-release.md.#5624: a failed Windows update leaves nothing that blocks the next one and says what to do.
bunx.exestays provably owned, and a later update removes marked stages older than a floor set well above the install timeout. Unmarked stages from older updaters, npm's own.opencodex-<random>rename-asides, other packages' stages and links are reported by folder name (no account-bearing paths) and never deleted.ocx stop, reinstall,ocx service restart; or the recovery marker after a double fault) in place of the old "Try manually" line. The dashboard job points at the terminal.troubleshooting/update-failed(English; the sidebar label is translated, other locales fall back to the English page) for users on 2.64.0 and earlier whose update fails this way.reference/cli/lifecycle.mdlinks to it.Established vs not: our updater never creates
@bitkyc08/.opencodex-*(that is npm's rename-aside during a direct global install), and theENOTDIRonmkdirin the report is not explained by this code. The job log withholds the path, so which component was a file is unknown. This PR does not claim to fix that root cause. It makes the failure recoverable and non-blocking.Plan and audit record:
devlog/_plan/260923_p2_update_continuity/.Closes #5496
Closes #5624
Verification
tests/ci-workflows/package-tree-fenced-restart.test.ts: realstartServer, in order: boot 200, replace the observed tree, fenced 503 withoutinstalledVersionuntil the replacement settles, automatic admission, manual discovery through the realfindLiveProxyand realrequestBoundSystemRestartjoining the pending restart, exactly one handoff; a service child that lost its service home keeps the fence and never hands off.tests/server/proxy-liveness-package-tree-fence.test.ts: opt-in only; wrong secret, unsigned listener, missing or mismatched record, expected-pid mismatch and non-fence 503 bodies are all refused.tests/cli/system-restart-client-package-tree.test.ts: fenced restart accepted when the installed version matches; skew, unsettled tree, missing proof and other non-OK responses refused.tests/update/update-transactional-leftovers.test.ts: an injected failure at each updater step (stage mkdirENOTDIR, npm failure after partial write, staged verify, live move-asideEXDEV, stage placement, post-swap verify, double fault) keeps or restores the previous version, leads to service restore throughplanStoppedRuntimeRecovery, and names the next command; a locked leftover survives while recent and is removed once stale; unowned trees are left intact.Checklist