Skip to content

docs(skill): teach ocx the remote hub roles, pairing boundary, and disconnect halves - #3165

Merged
lidge-jun merged 1 commit into
devfrom
codex/ocx-skill-remote-hub
Sep 1, 2026
Merged

lidge-jun merged 1 commit into
devfrom
codex/ocx-skill-remote-hub

Conversation

@lidge-jun

Copy link
Copy Markdown
Owner

Summary

  • Adds skills/ocx/references/05_remote_hub.md and a short inline section in SKILL.md so an agent operating a proxy can answer two remote-hub questions it will be asked, and answer them correctly.
  • Pairing is not hub setup. GET /opencodex-session mints a session on its own for a loopback request, and for a hub reached through the trusted Tailscale ingress when the login is in remoteGui.allowedTailscaleUsers (src/server/gui-session.ts:177-193). A pairing grant is the fallback for a remote browser that neither position nor identity vouches for. The management API is a separate admission ladder again (src/server/management-auth.ts:471-491), which an agent drives with the admin token and never pairs for. Without this written down, the plausible-sounding wrong answer is "yes, you have to pair first."
  • ocx disconnect is only half of leaving a hub. It restores local state and clears the connection, then reports that the hub key is still valid. The reference states both halves and which one applies when the device is gone.
  • Also records the two-step rotation commit and why the ordering is load-bearing, the four disconnect refusals as a safety property rather than an obstacle, and that credentials are stdin-only with no argv form.
  • The reference ends with a short "what to tell a human who asks" list, since these questions arrive as questions rather than as tasks.

Docs and one test-list entry. No runtime change.

Verification

  • bun test tests/skill-ocx.test.ts — 11 pass, 0 fail, 81 expect() calls. That suite is the relevant one: it asserts every ocx <command> named anywhere in the skill exists in the CLI registry, which is what stops a reference from documenting a command nobody can run.
  • REFERENCES in the test grows by one entry, and the "SKILL.md routes to every reference it ships" assertion covers the new file.
  • No full suite, per the no-local-suite policy. No source file is touched, so skill:surface:check and the generated 01_management_surface.md are unaffected.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed (this PR is the documentation).
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults — no code change. The page documents the existing admission boundary and deliberately does not offer a way around it: it states that credentials are stdin-only and that the disconnect refusals must not be routed around.

…sconnect halves

An agent reading skills/ocx had no way to answer two questions it will be asked.

The first is whether configuring a hub requires pairing. It does not.
GET /opencodex-session mints a session on its own for a loopback request, and
for a hub reached through the trusted Tailscale ingress when the login is in
remoteGui.allowedTailscaleUsers (src/server/gui-session.ts:177-193). A pairing
grant is the fallback for a remote browser that neither position nor identity
vouches for, and the management API is a separate admission ladder again
(src/server/management-auth.ts:471-491) which an agent drives with the admin
token and never pairs at all.

The second is that ocx disconnect is only half of leaving a hub. It restores
local state and clears the connection, then reports that the hub key is still
valid -- stopping there leaves a working credential behind. Revocation is the
other half: connect revoke while still connected, or delete the key in the hub
dashboard once the device is gone.

Also records why rotation is a two-step commit (the old key has to outlive the
moment the new one is issued, or a client that has not been updated is
stranded), why the four disconnect refusals are the safety property rather than
an obstacle, and that credentials are stdin-only with no argv form.

references/05_remote_hub.md carries the detail; SKILL.md carries the two
corrections inline so an agent that never opens the reference still answers
correctly. The test's reference list grows by one entry.
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner September 1, 2026 15:37
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 1, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-01T15:42:23.374695Z 4a789b8 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@lidge-jun
lidge-jun merged commit 2f2629f into dev Sep 1, 2026
7 checks passed
@lidge-jun
lidge-jun deleted the codex/ocx-skill-remote-hub branch September 1, 2026 15:38
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Sep 1, 2026

@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: 4a789b8c54

ℹ️ 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 on lines +48 to +49
"runtimeRole": "hub",
"hub": { "managementPublicOrigin": "https://host.ts.net" }

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 Include the data-listener bind in the minimum hub config

On a fresh install where no reverse proxy already forwards the data plane, following this “Minimum hub config” leaves hostname unset; startServer consequently binds the main listener to 127.0.0.1 in src/server/index.ts, so another machine cannot reach the hub or run ocx connect. Include a remotely reachable hostname, or relabel this as role-only configuration and direct agents to the full deployment prerequisites.

AGENTS.md reference: AGENTS.md:L181-L183

Useful? React with 👍 / 👎.

|---|---|
| `Token file` | `owned` is nominal. `changed` means another process overwrote the token, and `disconnect` will refuse until that is resolved. |
| `Key rotation` | `recovery-required` means a rotation was interrupted. Re-run `connect rotate` to commit or abort it. |
| `Catalog` | `unsafe` means the catalog bytes are not the ones this connection wrote. |

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 Stop claiming status verifies catalog ownership

When a user or another process replaces the catalog bytes with any regular file, collectClientConnectionStatus still reports present: it only checks lstatSync(...).isFile(), while unsafe is reserved for a symlink, non-file, or stat failure. An agent relying on this table will therefore miss catalog drift until disconnect refuses it; describe unsafe accurately and state that status does not hash-check ownership, or compare the file against the saved catalogFingerprint.

AGENTS.md reference: AGENTS.md:L181-L183

Useful? React with 👍 / 👎.

Comment thread skills/ocx/SKILL.md
Comment on lines +128 to +130
When `disconnect` refuses, do not route around it. Each refusal means the unwind cannot be
proven safe: another process owns the token, no journal records the pre-connect state, a
different client key owns the journal, or the restore was only partial.

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 Cover the other disconnect refusal paths

For a connected client whose service token is missing or whose catalog bytes changed, disconnectClient refuses with errors not represented by this exhaustive “each refusal ... or” list; it can also refuse if the token changes during removal or client state races the final commit (src/client/connect.ts). Agents following the operating reference will have no safe guidance for these common drift cases, so include the omitted classes and remedies or clearly label the four listed cases as examples and instruct agents to preserve state and report the exact error.

AGENTS.md reference: AGENTS.md:L181-L183

Useful? React with 👍 / 👎.

tarunravi pushed a commit to tarunravi/opencodex that referenced this pull request Sep 14, 2026
…sconnect halves (lidge-jun#3165)

An agent reading skills/ocx had no way to answer two questions it will be asked.

The first is whether configuring a hub requires pairing. It does not.
GET /opencodex-session mints a session on its own for a loopback request, and
for a hub reached through the trusted Tailscale ingress when the login is in
remoteGui.allowedTailscaleUsers (src/server/gui-session.ts:177-193). A pairing
grant is the fallback for a remote browser that neither position nor identity
vouches for, and the management API is a separate admission ladder again
(src/server/management-auth.ts:471-491) which an agent drives with the admin
token and never pairs at all.

The second is that ocx disconnect is only half of leaving a hub. It restores
local state and clears the connection, then reports that the hub key is still
valid -- stopping there leaves a working credential behind. Revocation is the
other half: connect revoke while still connected, or delete the key in the hub
dashboard once the device is gone.

Also records why rotation is a two-step commit (the old key has to outlive the
moment the new one is issued, or a client that has not been updated is
stranded), why the four disconnect refusals are the safety property rather than
an obstacle, and that credentials are stdin-only with no argv form.

references/05_remote_hub.md carries the detail; SKILL.md carries the two
corrections inline so an agent that never opens the reference still answers
correctly. The test's reference list grows by one entry.

Co-authored-by: jun <jun@lidge.dev>
agentHits pushed a commit to agentHits/opencodex that referenced this pull request Sep 17, 2026
…sconnect halves (lidge-jun#3165)

An agent reading skills/ocx had no way to answer two questions it will be asked.

The first is whether configuring a hub requires pairing. It does not.
GET /opencodex-session mints a session on its own for a loopback request, and
for a hub reached through the trusted Tailscale ingress when the login is in
remoteGui.allowedTailscaleUsers (src/server/gui-session.ts:177-193). A pairing
grant is the fallback for a remote browser that neither position nor identity
vouches for, and the management API is a separate admission ladder again
(src/server/management-auth.ts:471-491) which an agent drives with the admin
token and never pairs at all.

The second is that ocx disconnect is only half of leaving a hub. It restores
local state and clears the connection, then reports that the hub key is still
valid -- stopping there leaves a working credential behind. Revocation is the
other half: connect revoke while still connected, or delete the key in the hub
dashboard once the device is gone.

Also records why rotation is a two-step commit (the old key has to outlive the
moment the new one is issued, or a client that has not been updated is
stranded), why the four disconnect refusals are the safety property rather than
an obstacle, and that credentials are stdin-only with no argv form.

references/05_remote_hub.md carries the detail; SKILL.md carries the two
corrections inline so an agent that never opens the reference still answers
correctly. The test's reference list grows by one entry.

Co-authored-by: jun <jun@lidge.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant