Add post-sync readiness endpoint and bounded ocx ready wait - #569
Add post-sync readiness endpoint and bounded ocx ready wait#569diegocantarero wants to merge 6 commits into
Conversation
|
Warning Review limit reached
Next review available in: 15 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe proxy now tracks startup readiness per server instance, exposes a strict unauthenticated ChangesProxy readiness flow
Estimated code review effort: 4 (Complex) | ~60 minutes Suggested labels: Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant CLI as ocx ready
participant Discovery as findLiveProxy
participant Probe as probeReadiness
participant Proxy as Proxy /readyz
CLI->>Discovery: Discover live proxy within deadline
Discovery-->>CLI: Return pid and port
CLI->>Probe: Probe readiness
Probe->>Proxy: GET /readyz
Proxy-->>Probe: Return status and identity
Probe-->>CLI: Return validated readiness
CLI-->>CLI: Poll, report JSON, and exit
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
Please change the PR to ready for review once you are finished @diegocantarero |
|
NEEDS-SECURITY-REVIEW — the design is sound, the boundary is what needs a reviewer. The separation is the right one. The tests are unusually strong for a PR this size. Why it still needs security review. This deliberately adds a new unauthenticated endpoint. The response is narrowly sanitized to fixed identity and status fields, and The three conflicts all want both sides kept, not a choice:
What happens next: rebase keeping both sides of those three, mark it ready when you are satisfied, run fresh CI, then request security review. |
|
Thanks for putting this together. The separation between process liveness and post-sync readiness is the right design, and it addresses a real startup race. Before maintainer review, please:
The design direction is right and the startup race is real — we want this. |
Document the sanitized HTTP identity separately from the CLI --json shape. Clarify failed-immediate wait behavior and the default 45s timeout. Keep the readiness contract aligned across supported locales. Add real subprocess coverage for terminal failed readiness.
- Rebase the readiness PR onto current dev: adopt the existing deadlineAt
discovery budget in proxy-liveness instead of the duplicate deadlineMs/
probeBudget mechanism, keeping dev's attempts/source discriminator.
- Answer POST /readyz and GET /readyz/ with a deterministic JSON 404 so the
exact-GET contract never depends on whether gui/dist exists (the GUI SPA
fallback previously served index.html with 200 for those paths).
- Re-target the ready docs to reference/cli/lifecycle.md across all locales
and document the 1-300 second --timeout range.
- Fix the deadline test off-by-one and AbortSignal stub ordering; adapt the
catalog-prewarm source-order test to startServer(port, { readinessGate }).
Extract the 750ms per-probe ceiling as DEFAULT_PROBE_TIMEOUT_MS in proxy-liveness and import it from the ready CLI instead of redeclaring IO_TIMEOUT_CAP_MS, so liveness and readiness defaults cannot diverge.
0a1b94f to
55f4937
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 55f493777a
ℹ️ 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".
…tion verifyPidIdentity spawns WMIC/PowerShell (up to seconds on Windows) and is only needed for kill targets. runReady's production discovery now passes verifyPidFn: () => null so no OS command-line check runs outside the wait deadline; the /healthz identity marker and strict /readyz contract validation are unchanged.
[shipping-github] Addressed feedbackfeedback: issue_comment:5154177408 |
[shipping-github] Security review requested@lidge-jun — requesting the deliberate security review you asked for on the unauthenticated Head: This is the last open gate before merge; please review the boundary. |
Summary
GET /healthzas immediate process livenessGET /readyzfor post-sync readinessocx ready [--json] [--wait [--timeout <seconds>]]Problem
The listener can bind before startup catalog/config synchronization finishes. A consumer that treats
/healthzas readiness can therefore connect to a live proxy before model catalog convergence.This closes that portable startup race. It was observed while macOS restored a Codex client during login, but the implementation is platform-neutral and does not include macOS process-management policy.
Behavior
/healthzis unchanged./readyzreturns200only forready.pendingandfailedreturn503withRetry-After: 1.POST /readyzandGET /readyz/return a JSON404(the endpoint matches exact pathname +GETonly, regardless of whethergui/distexists).ok: truewith no nonempty warningocx readyvalidates service identity and HTTP/status consistency--waituses one hard deadline across discovery, probes, polling, and sleep/readyzfail closed as readiness unavailableocx ready --waitinstead of guessing from liveness/readyzunauthenticated response contractExactly these six fields, nothing else:
{ "service": "opencodex", "version": "<string>", "uptime": "<number>", "pid": "<integer>", "port": "<integer>", "status": "pending | ready | failed" }Why this is safe for an unauthenticated caller: every field is already exposed by the existing unauthenticated
/healthz(service,version,uptime,pid,port) or is the readiness state itself (status) that the endpoint exists to report. No sync message, warning text, catalog path, provider output, account data, or diagnostic text is included, and the strict/readyzprobe treats any foreign or malformed body asunreachable.Compatibility and privacy
/healthzclients retain their behaviorstartServer(port)callers remain source-compatible and fail closed as pending unless they own and transition a supplied gateMerge-ready work (rebase + review fixes)
dev(fa51fce54), keeping both sides of the previously conflicting hunks:startServer(port, { readinessGate })withscheduleCatalogPrewarm(), the management-auth imports, anddeadlineAtdiscovery budgeting with thesourcediscriminatordev's existingdeadlineAtdiscovery budget instead of the duplicatedeadlineMs/probeBudgetmechanismdocs-site/.../reference/cli/lifecycle.mdin all locales and documented the 1-300 second--timeoutrangeAbortSignal.timeoutstub ordering/readyzcontract deterministic (JSON404for non-GET/trailing-slash paths)Validation
bun run typecheck: passEPERMtests and acodex-v2-gateassertion that depends on an npm-stylenode_modules/.bin/codex.cmdshim; both reproduce outside this PR); the maintained GitHub CI matrix is the full-suite acceptance gatebun run privacy:scan: passbun run build): pass