Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions skills/ocx/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ replacement, and report only confirmation plus non-secret key/rotation IDs.
Never ask for the plaintext key in chat or offer a pipe, redirection, or API
workaround to perform the secret-returning step inside the agent session.

`ocx hub invite` has the same boundary: text and JSON output expose a plaintext pairing
grant or a command embedding it. Use the human-operated terminal handoff in
[recipe 10](references/03_recipes.md#10-invite-one-more-machine-onto-a-hub); never ask for
the grant or generated command in chat. Continue non-secret setup and verification normally.

Configuration confirmation is not approval to revoke the existing credential.
Identify the existing key ID and obtain separate explicit revocation approval
before committing an in-place rotation or removing an old, separately replaced key.
Expand Down Expand Up @@ -132,10 +137,10 @@ cannot.
**A hub is one port, and `ocx hub invite` writes the join command for you.** Remote machines dial
`hostname:port` with their own per-client key; the hub's own processes dial `127.0.0.1:<the same
port>` with no credential, through the loopback companion listener
(`unauthenticatedLoopbackListener: {"enabled": true}`, no port). Run `ocx hub invite` on the hub
rather than assembling an `ocx connect` line: it mints a single-use code and prints the exact
(`unauthenticatedLoopbackListener: {"enabled": true}`, no port). Have the operator run `ocx hub invite`
on the hub outside the agent session rather than assembling an `ocx connect` line: it mints a single-use code and prints the exact
command, with both origins already filled in. Its `--management-url` is a confirmation of
`hub.managementPublicOrigin`, not an override. Do not persist the code it prints.
`hub.managementPublicOrigin`, not an override. The operator transfers the command directly to the joining machine; keep it out of the transcript.

Two consequences that look like bugs and are not. `ocx status` on a hub prints a `Hub:` block —
read it before asking the operator anything about ports or tokens. And a hub does not rewrite its
Expand Down
15 changes: 7 additions & 8 deletions skills/ocx/references/03_recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,20 +263,19 @@ decision, not a broken connection.

## 10. Invite one more machine onto a hub

Run on the **hub**. This is the whole flow; do not assemble an `ocx connect` line by hand.
Inspect non-secret state on the **hub** first:

```bash
ocx status # read the Hub: block first -- origins, listener, token source
ocx hub invite --json
```

`--json` gives `{ code, expiresAt, dataUrl, managementUrl, command }` on stdout. Hand the
operator `command` to run on the other machine; it already carries the data origin, the
management origin and `--pairing-code-stdin`. The code is a secret with a five-minute TTL and
one use: do not persist it, do not put it in a file, and prefer letting the operator copy it
rather than keeping it in a transcript.
Have the operator run `ocx hub invite` in a human-operated terminal outside the agent session.
Both output modes expose a plaintext pairing grant or the command embedding it; `--json`
is not a safe agent-output alternative. The operator transfers the generated command directly
to the other machine. It already carries both origins and `--pairing-code-stdin`, so do not
assemble it by hand or ask for it in chat. The code is secret, single-use, and expires in five minutes.

**Also relay the `Bound browser origin:` line from stderr.** It is not in the JSON envelope,
**Ask only for non-secret confirmation, such as expiry and the `Bound browser origin:` line.** That line is on stderr rather than in the JSON envelope,
and when the bound origin is not `http://localhost:10100` the joining machine has to already
be running on that port or the exchange is refused and the code is spent.

Expand Down
12 changes: 6 additions & 6 deletions skills/ocx/references/05_remote_hub.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,11 @@ stored as digests, and rate-capped at 8/min. They are secrets: do not persist on

## Inviting a machine (`ocx hub invite`)

Run on the **hub**. It prints the command for the other machine:

```bash
ocx hub invite
```
Have the operator run `ocx hub invite` on the **hub** in a human-operated terminal outside
the agent session, then transfer the generated command directly to the joining machine.
Both text and JSON output contain a plaintext pairing grant or a command embedding it;
do not run either mode through an agent tool or ask for its secret-bearing output in chat.
The placeholder below illustrates the operator's command, not a request to relay a live grant:

```text
# Run on the other machine:
Expand All @@ -224,7 +224,7 @@ other machine to dial itself and spends the code for nothing, so `invite` refuse
the `hub.dataPublicOrigin` fix. An explicit override is never second-guessed: a loopback data
origin is legitimate over an SSH tunnel.

Every successful invite prints a `Bound browser origin:` line on stderr. A grant is bound to
Every successful invite prints a non-secret `Bound browser origin:` line on stderr. The operator may report that line and the expiry for verification. A grant is bound to
one origin and a remote `ocx connect` presents `Origin: http://localhost:<its own configured
port>`, so when the bound origin is not the default the other machine must already be running
on that port. Relay that line; it is the difference between a working exchange and a spent
Expand Down
Loading