Skip to content

feat(deploy): phase 5 — hub management ingress, deployment recipes, oracle dogfood fixes - #2786

Open
lidge-jun wants to merge 8 commits into
codex/remote-hub-p4from
codex/remote-hub-p5
Open

feat(deploy): phase 5 — hub management ingress, deployment recipes, oracle dogfood fixes#2786
lidge-jun wants to merge 8 commits into
codex/remote-hub-p4from
codex/remote-hub-p5

Conversation

@lidge-jun

Copy link
Copy Markdown
Owner

Summary

  • Phase 5 of the remote-hub stack (plan: devlog/_plan/260827_remote_hub/070_phase5_deploy.md) plus the live clisu-oracle dogfood it prescribed.
  • Adds the optional hub loopback management ingress (hub.managementIngress): a second 127.0.0.1-only listener serving GUI + /api + the pairing exchange, default-404 allowlist, no /v1/*, startup rollback when the bind fails, three-listener shutdown covered by real-socket tests. Defaults byte-identical when unconfigured.
  • Adds the remote-hub deployment guide (systemd/launchd via the existing service installer, Docker with a persistent home volume and OCX_API_TOKEN_FILE secret, tailscale serve + ts.net cert walkthrough, headless OAuth via oauthOpenBrowser:false + manual code submit).
  • Dogfood on clisu-oracle found and fixed three live defects, each with a regression test: runtimeRole=hub refused ocx start; the hub role ran local Codex/Grok/Claude client syncs on startup (marking /readyz failed and rewriting ~/.grok/config.toml on a server box); ocx connect refused its final commit on a fresh machine with no config.json.
  • Full dogfood record: devlog/_plan/260827_remote_hub/090_dogfood_record.md — pairing grant → per-client key auto-issue → injected client → real routed HUB_OK completion over the tailnet → per-apiKeyId usage attribution on the hub → byte-identical disconnect restore.

Verification

Run on lidge-ai (remote CI host) at f98081f, per the no-local-suite policy:

  • bun run typecheck — clean.
  • bun test tests/server-live.test.ts tests/server-management-auth.test.ts tests/client-machine-listener.test.ts tests/client-connect.test.ts tests/codex-desired-state.test.ts tests/loopback-listener-integration.test.ts tests/core-lab-boundary.test.ts tests/service-install.test.ts — 156 pass, 0 fail.
  • Live dogfood on clisu-oracle (evidence in 090): ready /readyz with protocol metadata over the tailnet, authenticated /v1/catalog, HTTPS-only admin refusal, pairing-code connect, routed completion, usage slice, offline-restore disconnect.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed (deployment guide added; locale sync is Phase 6).
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults (ingress loopback-only allowlist; hub role never rewrites host client configs; admin-over-HTTPS rule proven live).

@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner August 27, 2026 19:42
@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (2)
  • ^dev$
  • ^preview$

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7f359376-d68a-4660-91bc-efbf67d09b21

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the enhancement New feature or request label Aug 27, 2026
@lidge-jun

Copy link
Copy Markdown
Owner Author

리뷰 · 우선순위 64 / 80

이 PR은 remote-hub phase 5입니다. 베이스는 codex/remote-hub-p4(PR #2781)입니다. Draft가 아닙니다. hub 전용 loopback management ingress와 배포 가이드, 그리고 clisu-oracle dogfood에서 찾은 세 결함을 고칩니다.

hub.managementIngress가 켜지면 127.0.0.1에 GUI·/api·페어링만 여는 두 번째 리스너를 띄웁니다. /v1/*·health·readyz·WS는 막고, 바인드 실패 시 이미 연 리스너를 롤백합니다. 기본값(미설정)은 바이트 동일입니다. 배포 문서는 systemd/launchd·Docker 홈 볼륨·OCX_API_TOKEN_FILE·Tailscale Serve·oauthOpenBrowser:false 수동 코드를 다룹니다.

Dogfood 수정 세 가지가 실사용 가치가 큽니다. (1) runtimeRole=hubocx start를 거절하던 것. (2) hub가 기동 때 로컬 Codex/Grok/Claude 클라이언트 sync를 돌려 /readyz를 실패시키고 서버 박스의 ~/.grok/config.toml을 고치던 것. (3) 새 머신에 config.json이 없으면 ocx connect 최종 커밋을 거절하던 것. 각각 회귀 테스트가 있습니다.

지금 dev에는 hub ingress 필드가 없고, oauthOpenBrowser는 config L889에 이미 있습니다. types/config에 managementIngress가 더해지므로 분할 캠페인 면적은 조금 늘어납니다. CI gates/test가 이 시각 기준 빨갛습니다. p4 draft 위라 dev 단독 머지 불가입니다.

라인 src/server/index.ts managementIngress - 127.0.0.1 전용, allowlist 404, 바인드 실패 롤백, stop에 세 리스너.

라인 src/types/config.ts / src/config.ts - hub.managementIngress 스키마. enabled:false | {enabled:true,port}.

라인 src/cli/claude-agent-startup-sync.ts / desired-state - hub 역할은 호스트 클라이언트 설정을 다시 쓰지 않습니다.

라인 src/client/state.ts - hub에 client state가 없으면 mismatch가 아니라 disconnected.

라인 tests/loopback-listener-*.ts / server-management-auth.test.ts - ingress 경계·실소켓 종료를 잠급니다.

경로 base - #2781(draft) 위. p4 ready 전이면 이 PR도 대기입니다.

메인테이너의 판단이 필요한 지점

  • p4를 먼저 ready·머지한 뒤 이어서 올릴지
  • CI 빨강을 dogfood 회귀와 분리해 볼지
  • managementIngress 기본 포트를 문서에 고정할지

너의 추천
p4가 ready·초록이 된 뒤 이 PR을 올리세요. dogfood 세 수정은 가치가 커서 phase 5와 같이 가는 편이 맞습니다. 미설정 시 동작 동일 보증은 유지하세요.

이 댓글은 grok-bot이 작성했습니다

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a62c8eba20

ℹ️ 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".

Comment thread src/client/state.ts
// A hub is a server role, not a broken client: without client state it simply is not
// connected, and refusing here blocked `ocx start` on every hub (found on the first
// clisu-oracle dogfood boot). Hub role WITH client state remains mismatched below.
if (!hasClient && role === "hub") return { kind: "disconnected" };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep hub role out of disconnected client state

When a hub has no client block, classifying it as disconnected lets connectClient() pass its state.kind === "disconnected" preflight and later makes commitClientConnection() replace runtimeRole: "hub" with "client". Thus, on a hub without a service-token file, running ocx connect silently converts the installation into a client and disables hub behavior on restart. Preserve the hub/client mismatch for connection operations and special-case hub startup in handleStart() instead, or add an explicit hub-role rejection to the connect preflight.

Useful? React with 👍 / 👎.

Comment thread src/client/state.ts
Comment on lines +82 to +85
const seeded = getDefaultConfig();
seeded.runtimeRole = "client";
seeded.client = structuredClone(state);
saveConfig(seeded);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make missing-config bootstrap conditional

When mutatePersistedConfig() reports missing, it returns before acquiring the mutation lock; another first-run command can therefore create a valid config.json before this unconditional whole-config saveConfig(seeded) runs. The seeded defaults then overwrite the newly created providers, credentials, and settings. Bootstrap creation needs to acquire the coordinator lock and confirm the file is still absent before writing, otherwise it should retry the field-scoped mutation or report a conflict.

Useful? React with 👍 / 👎.

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes on exact head a62c8eba20ec1ecc7531f2ce8eb2310004052dde. It is 203 commits behind current dev@ae356a3cf, and exact-head CI is failing on product contracts, not only infrastructure noise: tests/cli-headless-parity.test.ts:287 exposes seven undeclared /api/machine/* routes; tests/update-stop-first.test.ts:225, tests/loopback-listener-admission.test.ts:196, and tests/release-version-line.test.ts:108 also fail on macOS, while the privacy gate fails. Please rebuild the deployment phase on current dev, explicitly declare or remove every machine management route from the CLI/headless surface, restore the stop-first and role-admission contracts, and keep the privacy/release gates intact. Re-request review only on a clean exact head with green CI.

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants