fix(service): bake the stable ocx launcher into the launchd plist - #3554
fix(service): bake the stable ocx launcher into the launchd plist#3554lidge-jun wants to merge 5 commits into
Conversation
After a mise/asdf upgrade the installed CLI was 2.42.0 while the launchd proxy kept serving 2.10.1-preview: buildPlist baked the package-local Bun + CLI pair, so launchd never saw the new package until someone restarted the service by hand (#3464). systemd had already moved to stableLauncherEntry() for exactly this failure (#2898 / #2909); launchd is the macOS counterpart. - buildPlist takes the same { launcher, runtime } deps as buildUnit; with a launcher the job execs that path and omits the OCX_BUN_RUNTIME_* provenance pair, keeping only a proof-bound OPENCODEX_BUN_PATH override. Without one the plist is byte-identical. - installLaunchd resolves the launcher once, passes the same value to the plist and to install state (launcherPath), so the stale-path diagnostic judges what launchd runs. - startLaunchd and serviceStatusReport compared the live job against the Bun + CLI command; a launcher-backed job would have read as "an OLDER plist" on every healthy start. expectedLaunchdCommand(port) follows the recorded launcherPath (never re-walks PATH) and both callers use the installed port. This fixes which build the next launchd start runs. It does not replace an already running proxy after an external upgrade — that remains a restart / repair step, noted in the docs — so the issue stays open for that half. Refs #3464
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (2)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Team Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. |
리뷰 · 우선순위 70 / 80이 PR은 Linux systemd가 이미 쓰는 라인 expectedLaunchdCommand / launchdStart - 기대 명령을 기록된 메인테이너의 판단이 필요한 지점
너의 추천 이 댓글은 grok-bot이 작성했습니다 |
Ingwannu
left a comment
There was a problem hiding this comment.
The launchd design is consistent with the existing systemd launcher boundary on this stacked head. installLaunchd resolves one stable launcher and records the same path in both the plist and install state; start/status derive the expected command from that recorded path instead of re-walking PATH. Launcher mode drops stale package-local Bun provenance, preserves only a proof-bound Bun override, keeps the API token file-backed, and shell/XML quoting is covered. The scope also correctly leaves already-running proxy replacement open in #3464.
I am requesting changes because this executable-selection/security-boundary PR currently targets codex/3462-mihomo-ipv6-fakeip, whose parent chain includes blocked #3551 and #3547. It cannot receive a final security approval or be merged on a temporary stack base.
After the parents land, retarget/rebase this layer onto the then-current dev, ensure its final diff contains only the launchd/service/docs changes, and run exact-head CI including macOS. I will then re-review the final launcher command, install-state provenance, and live-status comparison. Do not merge it into the temporary parent branch.
Summary
After a
miseupgrade the installed CLI was 2.42.0 while the launchd proxy kept serving 2.10.1-preview:buildPlistbaked the package-local Bun + CLI pair, so launchd never saw the new package until someone restarted the service by hand (#3464). systemd already moved tostableLauncherEntry()for exactly this failure (#2898 / #2909, which explicitly left launchd untouched); this is the macOS counterpart.buildPlisttakes the same{ launcher, runtime }deps asbuildUnit. With a launcher the job execs that absolute path and omits theOCX_BUN_RUNTIME_*provenance pair, keeping only a proof-boundOPENCODEX_BUN_PATHoverride (same rule as systemd). Without one the plist is byte-identical to today, so source checkouts and existing tests are unaffected.installLaunchdresolves the launcher once and passes the same value to the plist and to install state (launcherPath), so the existing launcher-aware stale-path diagnostic judges what launchd actually runs.startLaunchdandserviceStatusReportcompared the live job against the Bun + CLI command string; a launcher-backed job would have read as "launchd is running an OLDER plist" on every healthyocx service start. NewexpectedLaunchdCommand(port)follows the recordedlauncherPath(never re-walks PATH) and both callers now use the installed port.lifecycle.mdlauncher paragraph generalised to macOS + Linux;structure/04section renamed and extended.Scope note — this does not close #3464. Launcher parity fixes which build the next launchd start runs. It cannot replace an already-running proxy after an external upgrade; that stays a restart /
ocx service repairstep (now stated in the docs) and the auto-repair-vs-refuse decision stays open on the issue.Security review (MAINTAINERS.md): changes durable executable selection for the service.
stableLauncherEntryis unchanged: absolute PATH entries only, regular file +X_OK, lexical (no symlink resolution), shell-quoted into the plist so/bin/sh -lcdoes not re-resolve it. The launcher's own#!/usr/bin/env nodeshebang still resolvesnodethrough the baked PATH — the same assumption systemd already makes. No credential or token handling change; the API token stays file-backed and read only by the service shell at start.Stack (260905 bug triage, position 3 of 5; base is #3551's head — retarget to
devafter the parents land):devUnit:
devlog/_plan/260905_bug_triage_stack/(000, 005, 030).Verification
bun run typecheck— exit 0.bun test tests/service/service.test.ts— 199 pass / 0 fail. RED-before: withsrc/service.tsstashed the new assertions fail (expectedLaunchdCommandmissing, launcher plist tests fail); GREEN-after.launcher: nullkeeps the legacy shape; proof-bound override preserved vs ambient dropped; metacharacter launcher path stays quoted andlaunchdListenPortstill parses;expectedLaunchdCommandfor recorded launcher / v1 legacy state / missing state (Bun + CLI fallback, no PATH walk).bun run privacy:scan— passed.launchctlround-trip on this machine.Refs #3464
Checklist
devafter it landsbun run typecheckpassesbun run privacy:scanpasseslifecycle.md,structure/04)