Conversation
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Repository: luvs01/opencodex/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 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 |
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. |
|
✅ Deterministic PR hygiene checks passed. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2e8c489bcc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
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".
| if (lockedOwnership.subjectToken !== initialOwnership.subjectToken || !lockedPlan.mayReplacePackage) { | ||
| replacementLease.release(); | ||
| console.error(lockedPlan.notice | ||
| ?? "⚠️ Update stopped because runtime ownership changed before stop authorization; rerun from the beginning."); | ||
| process.exit(1); |
There was a problem hiding this comment.
Restore the tray when locked ownership aborts
On Windows, if ownership changes after the initial observation but before this locked recheck, the updater has already stopped a running tray via handoffWindowsTrayForUpdate, yet this new early-exit path releases the lease and terminates without restarting it. This leaves the user's tray unexpectedly down even though no runtime stop or package replacement occurred; restore it when trayWasRunning is true, as the later replacement-refusal path does, or acquire and validate the lease before the tray handoff.
Useful? React with 👍 / 👎.
| if (lockedOwnership.subjectToken !== initialOwnership.subjectToken || !lockedPlan.mayReplacePackage) { | ||
| replacementLease.release(); | ||
| console.error(lockedPlan.notice | ||
| ?? "⚠️ Update stopped because runtime ownership changed before stop authorization; rerun from the beginning."); | ||
| process.exit(1); |
There was a problem hiding this comment.
🟡 A fenced pre-stop refusal leaves the Windows tray stopped
The updater stops a running Windows tray before acquiring and validating the ownership lease. If ownership changes, this branch exits without restoring the tray, leaving its UI unavailable until manually restarted.
Learn more
The Windows tray handoff occurs before the ownership lease is acquired. A running tray is stopped and recorded in trayWasRunning. The newly added locked-ownership refusal releases the lease and exits directly, unlike the later replacement refusal, which calls startWindowsTray() first. Lease acquisition itself can also throw after the tray has stopped, producing the same stranded-tray outcome.
Example: The tray is running when ocx update begins. The desktop app changes runtime ownership before line 474. The locked subject differs from the initial subject, so the updater exits here; the package and proxy remain untouched, but the tray remains stopped.
Recommended fix: Acquire and validate the ownership lease before tray handoff, or wrap every post-handoff pre-replacement failure—including lease acquisition and this refusal—in shared best-effort tray restoration. Add a behavioral regression test that simulates an ownership change after handoff and verifies the tray restart callback runs.
Was this helpful? React with 👍 or 👎 to provide feedback.
| test("the Bun updater fences and delegates its final stop authorization", () => { | ||
| const leaseAt = bunPath.indexOf("const replacementLease = acquireOwnershipMutationLease"); | ||
| const lockedReadAt = bunPath.indexOf("const lockedOwnership = await resolvedRuntimeOwnership()", leaseAt); | ||
| const stopAt = bunPath.indexOf('selfLaunchArgv(["stop"])', lockedReadAt); | ||
| const releaseAt = bunPath.indexOf("replacementLease.release()", stopAt); | ||
| expect(leaseAt).toBeGreaterThan(-1); | ||
| expect(lockedReadAt).toBeGreaterThan(leaseAt); | ||
| expect(stopAt).toBeGreaterThan(lockedReadAt); | ||
| expect(releaseAt).toBeGreaterThan(stopAt); | ||
| expect(bunPath.slice(lockedReadAt, stopAt)).toContain("lockedOwnership.subjectToken !== initialOwnership.subjectToken"); | ||
| expect(bunPath.slice(lockedReadAt, stopAt)).toContain("ownershipMutationLeaseChildEnvironment"); | ||
| expect(bunPath.slice(stopAt, releaseAt)).toContain("env: stopEnvironment"); | ||
| }); |
There was a problem hiding this comment.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
15237d4 to
5b442bb
Compare
Motivation
ocx stop, which allowed a race where ownership could change (desktop takeover) after observation but before the stop, letting the updater stop a runtime it no longer owned.Description
acquireOwnershipMutationLease(serviceStatePaths())before making the final stop authorization and re-read ownership under that lease to prevent TOCTOU races.ocx stopchild by creating a stop environment withownershipMutationLeaseChildEnvironment(process.env, token)and pass it asenvwhen spawning the stop child, and keep the lease through post-stop liveness checks and package replacement.src/update/index.tsandtests/update/update-desktop-owner.test.ts.Testing
bun run typecheckand it completed successfully.bun test tests/update/update-desktop-owner.test.tsand the focused suite passed (21 pass, 0 fail).bun test tests/ci-workflows/file-size-ratchet.test.tsand it passed (all relevant checks green).bun run structure:checkand it passed.bun test tests/update/update-stop-first.test.tsbut the local Bun (v1.2.14) lacks thenode:zlibzstdDecompressSyncexport required by the checkout; that focused test could not be executed in this environment.bun run test(full suite) but the run was either interrupted or exercised unrelated long-running integration tests (tests/lab/*) and was not used as a validation gate for this focused change.Codex Task
Link to Devin session: https://app.devin.ai/sessions/7af3920bf099491589d8e1176625d373
Open in Devin Desktop: https://app.devin.ai/desktop/session/7af3920bf099491589d8e1176625d373?variant=devin
Link to Devin session: https://app.devin.ai/sessions/7af3920bf099491589d8e1176625d373
Open in Devin Desktop: https://app.devin.ai/desktop/session/7af3920bf099491589d8e1176625d373?variant=devin