Skip to content

feat(sandbox-manager): provision per-developer Paseo daemons - #150

Draft
tee8z wants to merge 5 commits into
mainfrom
tee8z/paseo-provisioning
Draft

tee8z wants to merge 5 commits into
mainfrom
tee8z/paseo-provisioning

Conversation

@tee8z

@tee8z tee8z commented Nov 10, 2026 •

Copy link
Copy Markdown
Collaborator

Problem and behavior

Each developer needs an always-on Paseo daemon that delegates work through Buzz. The daemon receives a narrow Kubernetes Secret, without the developer's GitHub, signing key, 1Password, or AWS access.

Pairing credentials and the generated gateway key live only in paseo-daemon-<id> in namespace buzz-paseo. They never enter the profile that Sandboxes read. Existing profiles and Sandbox images require no schema changes.

Operation Behavior
First enroll Generate absent password, server ID, NaCl keypair, and secp256k1 gateway key. Store the Secret before the profile.
Re-enroll Read and preserve existing identities. Update the agent list and selected model tokens.
Failed Secret read Return paseo_store_failed; preserve the existing Secret and profile.
Failed Secret write Return paseo_store_failed before writing the profile.
enroll / profile reply Return password, server ID, TLS pairing offer, and gateway_pubkey. Never return either private key.
Registering deploy Refresh only BUZZ_PASEO_AGENTS in an existing Secret. A failed refresh propagates for retry.

The feature remains off unless manager configuration enables paseo_daemons. Offers target buzz.voltage.cloud:443 by default, with TLS required. The provider list contains channel-bound agents registered on the manager's own relay.

The Secret holds PASEO_PASSWORD, PASEO_SERVER_ID, PASEO_DAEMON_KEYPAIR, BUZZ_PRIVATE_KEY, BUZZ_PASEO_AGENTS, and optional CLAUDE_CODE_OAUTH_TOKEN / CODEX_ACCESS_TOKEN. Other credentials are refused. Rotation requires deleting this Secret, re-enrolling, revoking the old gateway grant, and pairing the apps again.

Validation

  • cargo fmt --all --check: passed.
  • cargo clippy -p buzz-sandbox-reaper -p buzz-backend-kubernetes -p buzz-session-control --all-targets -- -D warnings: passed.
  • cargo test -p buzz-sandbox-reaper -p buzz-backend-kubernetes -p buzz-session-control: 396 passed, 4 ignored.
  • The enrollment journey exercises real enrollment and Kubernetes client code against external fakes. It covers failed creation, failed reading, re-enrollment, gateway public-key derivation, token allowlisting, and reply/profile redaction.
  • Removing gateway preservation, disabling the Secret key allowlist, or inserting pairing data into the profile each makes its regression test fail.
  • Pairing key and offer encodings retain vectors from the pinned upstream Paseo image.

A live staging deployment and app pairing have not been exercised. Repository-wide just ci has not run for this follow-up.

Rollout and human validation

Deploy the Terraform daemon namespace/RBAC and image configuration, then the manager image. Enroll again to create the narrow Secret. Grant the returned gateway public key before using remote agents; the gateway authorization PR is a separate dependency.

For a local reproduction, run the targeted enrollment journey:

. ./bin/activate-hermit
cargo test -p buzz-sandbox-reaper paseo_pairing_is_kept_only_in_the_daemon_secret_and_returned -- --nocapture

Working behavior preserves identity across enrollment, returns only public keys, and leaves the profile unchanged after failed Secret operations. Final human confirmation must also cover actual enrollment and Paseo pairing after the dependent images are available.

This PR stays draft pending independent review and human workflow confirmation. It has no `` attestation.

The profile reply includes paseo_enabled, even when the profile or daemon Secret is absent. Onboarding can distinguish disabled provisioning from a missing Secret and re-enroll idempotently. This additive field does not change the stored developer profile.

Capability validation: all 11 enrollment tests and reaper clippy pass. The tests cover enabled provisioning before a Secret exists, disabled provisioning, pairing identity preservation, and credential redaction. Human acceptance should also enable Paseo for an existing profile, rerun onboarding without new credentials, then repeat after deliberate Secret rotation.

With `paseo_daemons` in the manager config, enrollment generates a Paseo
pairing (password, server ID, tweetnacl box keypair) into the profile's
`paseo` section when absent and keeps it on re-enrollment. The manager
creates or replaces the narrow Secret `paseo-daemon-<id>` in `buzz-paseo`
with the pairing, the developer's registered agents (`BUZZ_PASEO_AGENTS`),
only the Claude subscription or Codex access token, and the reserved
gateway key. The `enroll` and `profile` replies return the password and
the `https://app.paseo.sh/#offer=` pairing URL for the configured relay
endpoint (default `buzz.voltage.cloud:443`, always TLS).

A registering desktop deploy records its channel-thread channel as a
registration annotation and refreshes the agent list in an existing daemon
Secret. Write failures are refused as `paseo_store_failed`.

Signed-off-by: Tee8z <tee8z@protonmail.com>
@tee8z tee8z self-assigned this Nov 10, 2026
@coderabbitai

coderabbitai Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

A paseo_store_failed refusal came after the profile was already stored.
A client that sees a refusal keeps what it sent for the retry, so the
GPUI app skipped registering a new agent signing key with GitHub while
the manager had stored it; the retry then found the key on file and
never registered it, leaving agent commits unverified.

Write the daemon Secret after validation and the GitHub check, before
the profile write, so a refusal always leaves the profile unchanged. A
Secret written for a profile that then fails to store holds only what
the request carried, and the retried enroll rewrites it.

Signed-off-by: Tee8z <tee8z@protonmail.com>
@tee8z
tee8z marked this pull request as ready for review November 10, 2026 13:34
@tee8z
tee8z marked this pull request as draft November 10, 2026 18:06
Signed-off-by: Tee8z <tee8z@protonmail.com>
@tee8z

tee8z commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator Author

Independent agent review of the current Secret-only provisioning change, including follow-up 22ea65069.

No remaining blockers found. I checked the product vision and the remote-agent relay-only contract, then traced enrollment admission, Secret reads and writes, identity preservation, provider-list refresh, profile writes, and reply redaction. Pairing and gateway keys stay outside sandbox profiles; failed Secret reads propagate without regeneration, and optimistic-concurrency conflicts retry at most three times.

The review found one concrete integration defect: a remote agent named Cursor received provider ID cursor, which the daemon image rejects as reserved. The follow-up reserves that ID, extends the existing regression table, and removes the stale image/profile rollout prerequisite. I verified that fix against the image wrapper.

Validation: cargo test -p buzz-sandbox-reaper paseo -- --nocapture passed all nine matching tests, including the production enrollment and registration journeys. I did not deploy to a cluster or pair a client. Human enrollment and pairing confirmation remains outstanding.

Scores: minimalism 9/10, elegance 9/10, correctness 9/10. This comment is agent review evidence; it does not attest human testing or deployment readiness.

This branch has not been deployed

No deployments
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.

1 participant