Skip to content

[WRONG BRANCH] CI mirror for upstream PR 5896 (do not merge) - #1

Closed
halysondev wants to merge 6 commits into
ci-base-devfrom
feat/local-plugins
Closed

halysondev wants to merge 6 commits into
ci-base-devfrom
feat/local-plugins

Conversation

@halysondev

Copy link
Copy Markdown
Owner

Runs the upstream pull_request workflows (Cross-platform CI, Service lifecycle, React Doctor) against the exact head of lidge-jun/opencodex PR 5896, because the upstream runs are waiting for maintainer approval. Not for merge; closed once the results are reported upstream.

halysondev and others added 6 commits September 25, 2026 23:20
`ocx start` now imports `$OPENCODEX_HOME/plugins/*.{ts,js,mjs}` before the
server binds. A plugin default-exports `{ name?, setup(context) }` and can
register an upstream rewriter that runs synchronously at the physical send:
fetchWithHeaderTimeout, fetchWithAttemptDeadline and the CodexWsSession dial.
This lets a local sidecar (for example a compression proxy) sit in front of
providers without editing the core.

- upstream-hooks.ts imports nothing; with no plugin the send is untouched.
- A throwing rewriter is disabled and the send continues unmodified.
- The loader refuses files owned by other users or writable by group/others,
  bounds setup to 5s, removes hooks from a failed setup, and honours
  OCX_PLUGINS=0.
- Documented in structure/ops/plugins.md and docs-site guides/local-plugins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Addresses the CodeRabbit review on lidge-jun#5896.

- Move the HTTP rewrite from fetchWithHeaderTimeout/fetchWithAttemptDeadline
  into sendWithConnectionPolicy. Rewriting before the transport choice hid the
  chatgpt.com origin from the Codex WebSocket selection and pushed Codex turns
  onto HTTP; egress now also follows the rewritten destination. Nested passes
  rewrite once via an init mark, like EGRESS_DECIDED.
- WebSocket dials redirected to loopback drop the caller's proxy, which was
  chosen for the original destination and cannot reach local loopback.
- Undo a rewriter's edits to the target when it throws.
- Report plugin directory read failures other than ENOENT.
- Key shutdown hooks by plugin file, not display name.
- Close a plugin's context when setup fails or times out, so a setup that
  resumes later cannot register; state that the deadline only bounds setup
  that yields.
- Guide example keeps the upstream query string.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… trust

Addresses the maintainer review and the second CodeRabbit pass on lidge-jun#5896.

- HTTP sends rewritten onto loopback now dial directly (`proxy: false`,
  egress marked decided), matching the Codex WebSocket; provider proxies and
  HTTP_PROXY cannot reach a local sidecar.
- The Codex WebSocket rewrite moved from the CodexWsSession constructor to
  codexWsUpstreamFetch, before the pool lookup, and the dialled destination
  joins codexWsReuseIdentity. Every exchange, including one on a pooled
  socket, now passes the plugin, and a socket is never reused for another
  destination. CodexWsSession is back to its dev shape.
- Request inputs are rewritten too; the rewritten mark is only set after a
  rewrite pass actually ran.
- The loader uses lstat: symbolic links are refused, and the plugins
  directory itself must be owned by the user and not group/other-writable.
- Each onShutdown call gets its own key (plugin:<file>#<n>), so a plugin
  can register several teardowns.
- Docs: per-rewriter rollback, Windows skips owner/mode checks, a timed-out
  setup keeps running, loopback sends bypass proxies, WS rewrite per turn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Addresses the third CodeRabbit pass on lidge-jun#5896.

- Every ancestor of the resolved plugin directory up to `/` must be owned
  by the user or root and not group/other-writable unless sticky, so no
  other user can swap a checked path before import (OpenSSH StrictModes
  rule). Plugins are imported through the resolved directory.
- The Codex WebSocket reuse identity hashes the rewritten headers, so a
  pooled socket is never reused with stale plugin headers.
- A non-loopback WebSocket rewrite resolves its own proxy route (scheme,
  NO_PROXY), falling back to SSE when that route requires it, via the new
  planCodexWsDial helper.
- Loader tests drop group write on the runner's own nested temp roots,
  which inherit umask 002 on user-private-group systems.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Addresses the fourth CodeRabbit pass on lidge-jun#5896.

x-codex-turn-state and x-codex-turn-metadata ride in each WebSocket
frame's client_metadata, prepared before the plugin rewrite and
authoritative per exchange; the pool deliberately leaves them out of the
reuse identity. planCodexWsDial now restores their original values after
the rewrite, so a rewriter cannot make the upgrade headers disagree with
the frame, and socket reuse keeps working. The header list is exported
once as CODEX_WS_FRAME_HEADERS and shared by the frame builder and pool.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

✅ Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the chore label Sep 26, 2026
@github-actions github-actions Bot changed the title CI mirror for upstream PR 5896 (do not merge) [WRONG BRANCH] CI mirror for upstream PR 5896 (do not merge) Sep 26, 2026
@github-actions

Copy link
Copy Markdown

⏳ DRAFT

  • wrong target branch (ci-base-dev); retarget to dev. PR description needs work (thin).

What to do

  • Retarget this PR to dev — all contributions go to dev.
  • Add a real Summary and Test plan to the PR description.

Its title has been prefixed with [WRONG BRANCH].
This pull request was already a draft. Its draft status will be preserved after every issue above is resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant