Skip to content

feat: add companion pairing API - #146

Open
ttupper92618 wants to merge 17 commits into
mainfrom
codex/companion-pairing
Open

feat: add companion pairing API#146
ttupper92618 wants to merge 17 commits into
mainfrom
codex/companion-pairing

Conversation

@ttupper92618

Copy link
Copy Markdown
Collaborator

Summary

Adds the Skulk-side native companion pairing surface for SkulkOps Pair and Observe.

  • Adds short-lived companion pairing sessions with QR payload metadata
  • Exchanges single-use nonces for scoped read-only bearer credentials
  • Stores only hashed companion credentials and persists them across Skulk restarts
  • Adds an Ed25519 cluster public key for cluster binding
  • Adds a companion-safe read-only overview endpoint

Security Notes

  • QR payloads do not contain bearer credentials
  • Tailscale/LAN remains reachability only; companion bearer credentials are the authorization boundary
  • V1 credentials are scoped to read-only observation
  • Credential hashes and cluster key material are stored under Skulk config with 0600 permissions
  • Destructive operations are not exposed through the companion API

Validation

  • uv run ruff check src/exo/api/companion.py src/exo/api/main.py src/exo/api/tests/test_companion_api.py src/exo/shared/constants.py
  • uv run pytest src/exo/api/tests/test_companion_api.py src/exo/api/tests/test_connectivity_api.py
  • uv run basedpyright src/exo/api/main.py src/exo/api/companion.py src/exo/api/tests/test_companion_api.py

Copilot AI review requested due to automatic review settings May 5, 2026 15:03

@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: 12f09dd620

ℹ️ 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/exo/api/main.py

Copilot AI 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.

Pull request overview

Adds a Skulk-side “Companion” API surface that supports QR-based pairing, nonce exchange into revocable read-only bearer credentials, and a companion-safe cluster overview endpoint.

Changes:

  • Introduces CompanionPairingManager + Pydantic contracts to create short-lived pairing sessions, exchange nonces for scoped bearer tokens, and persist hashed credentials.
  • Wires new /v1/companion/* endpoints into the main FastAPI app, including bearer-token authentication for the overview endpoint.
  • Adds cryptography dependency and a test suite covering pairing/session expiry, single-use nonces, credential persistence, and auth enforcement.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
uv.lock Locks updated dependency graph including cryptography wheels/markers.
pyproject.toml Adds cryptography>=46.0.0 to runtime dependencies.
src/exo/shared/constants.py Adds config paths for companion cluster key + credential store (and EXO_* aliases).
src/exo/api/companion.py New companion pairing/credential store implementation + overview response builder.
src/exo/api/main.py Registers Companion routes and integrates pairing manager + auth enforcement.
src/exo/api/tests/test_companion_api.py New tests validating pairing session creation, nonce exchange rules, auth, revocation, and persistence.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/companion.py
Comment thread src/exo/api/companion.py
Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/companion.py Outdated

@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: 8af05a407f

ℹ️ 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/exo/api/companion.py Outdated
Copilot AI review requested due to automatic review settings May 5, 2026 17:58

@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: a106ff13f4

ℹ️ 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/exo/api/main.py Outdated
Comment thread src/exo/api/companion.py Outdated

Copilot AI 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.

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/exo/api/main.py
Comment thread dashboard-react/src/components/observability/PairingTab.tsx
Comment thread src/exo/api/companion.py
Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/companion.py Outdated

@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: 882a61e2c5

ℹ️ 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/exo/api/companion.py Outdated
Copilot AI review requested due to automatic review settings May 5, 2026 18:26

@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: a19a19e8a0

ℹ️ 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 dashboard-react/src/components/observability/PairingTab.tsx Outdated
Comment thread src/exo/api/main.py Outdated

Copilot AI 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.

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/main.py Outdated
Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/companion.py Outdated

@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: 55b7c325a1

ℹ️ 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/exo/api/main.py Outdated
Copilot AI review requested due to automatic review settings May 5, 2026 21:33

Copilot AI 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.

Pull request overview

Copilot reviewed 11 out of 13 changed files in this pull request and generated 8 comments.

Files not reviewed (1)
  • dashboard-react/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/main.py Outdated
Comment thread dashboard-react/src/components/observability/PairingTab.tsx
Comment thread dashboard-react/src/components/observability/PairingTab.tsx Outdated
Comment thread dashboard-react/src/components/observability/PairingTab.tsx

@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: d17d9ac1f2

ℹ️ 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/exo/api/companion.py

@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: 57ad192083

ℹ️ 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/exo/api/main.py Outdated
Copilot AI review requested due to automatic review settings May 6, 2026 02:37

@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: 9511d36df8

ℹ️ 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/exo/api/main.py Outdated

Copilot AI 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.

Pull request overview

Copilot reviewed 11 out of 13 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • dashboard-react/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/exo/api/main.py Outdated
Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/companion.py Outdated
Copilot AI review requested due to automatic review settings May 6, 2026 03:19

Copilot AI 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.

Pull request overview

Copilot reviewed 11 out of 13 changed files in this pull request and generated 4 comments.

Files not reviewed (1)
  • dashboard-react/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/companion.py Outdated
Comment thread src/exo/api/main.py
Comment thread dashboard-react/src/components/observability/PairingTab.tsx Outdated
Copilot AI review requested due to automatic review settings May 6, 2026 14:11

Copilot AI 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.

Pull request overview

Copilot reviewed 11 out of 13 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • dashboard-react/package-lock.json: Language not supported

Comment thread src/exo/api/main.py Outdated
Comment thread src/exo/api/companion.py Outdated
Copilot AI review requested due to automatic review settings May 6, 2026 14:37

@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: 1ed98c92e3

ℹ️ 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/exo/api/companion.py Outdated

Copilot AI 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.

Pull request overview

Copilot reviewed 11 out of 13 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • dashboard-react/package-lock.json: Language not supported

Comment thread src/exo/api/main.py
@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

Skulk/src/exo/api/main.py

Lines 529 to 530 in 1e8105f

host = request.client.host if request.client else ""
if not _is_loopback_host(host):

P2 Badge Handle missing client info in loopback authorization

_is_loopback_client assumes request.client is always present, but Starlette allows it to be None (for example, common Uvicorn deployments behind a UNIX domain socket). In that case host becomes "", this check returns False, and _require_companion_pairing_operator rejects otherwise local operator requests unless an explicit token header is configured. This causes companion QR creation to fail in valid local proxy setups that should pass loopback auth.

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

Copilot AI review requested due to automatic review settings May 12, 2026 05:42

Copilot AI 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.

Pull request overview

Copilot reviewed 11 out of 14 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • dashboard-react/package-lock.json: Language not supported

Comment thread src/exo/api/companion.py
return {}
try:
store = CompanionCredentialStore.model_validate_json(
self._credentials_path.read_text()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants