block / block/buzz

feat(cli): add owner-approved scoped managed-agent signing for local integrations

Open
#5,381 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

**Motivation**

A local companion UI may need to send a human-reviewed message under a dedicated Buzz managed-agent identity without receiving or copying that identity's private key.

Concrete case: a localhost Mission Control dashboard transcribes speech locally, displays the exact editable text, invalidates approval after edits, requires a deliberate send action, limits sends to one channel, rate-limits mutations, records a durable nonce before transport, and reconciles ambiguous outcomes. The final safe transport boundary is missing.

Generating a standalone Nostr key is insufficient on a membership-gated relay: profile publication and direct channel join are rejected with `403 relay_membership_required`, even after the owner adds the public identity to the channel. Reusing the owner key or exporting a managed-agent nsec into the browser/local integration would violate least authority.

Buzz Desktop already has the correct signing and authorization path in `send_managed_agent_channel_message` (`desktop/src-tauri/src/commands/messages.rs`): it loads the managed-agent record, verifies the stored key matches the pubkey, applies the stored/legacy NIP-OA auth tag, supports idempotency markers, and returns the published event ID. That path is currently available only to the Desktop webview through Tauri IPC.

**Proposed solution**

Add an owner-approved, revocable managed-agent signing capability for local integrations, backed by Buzz Desktop rather than exported key material.

A grant should bind all of:

- exact managed-agent pubkey;
- allowed channel UUID(s);
- allowed operation (`send_channel_message` only initially);
- top-level vs. thread policy;
- local client identity/origin;
- short expiry or explicit revocation;
- rate limit;
- single-use nonce/idempotency marker.

Expose the capability through an authenticated Desktop-local IPC surface or a CLI command that delegates to the running Desktop signer. The caller supplies exact content plus nonce and receives the event ID (or an explicit unknown outcome that can be reconciled by nonce). Private key and persistent NIP-OA auth material never leave Desktop storage.

Suggested first API shape (names illustrative):

```text
buzz agents grants create --agent --channel --operation send-message
buzz messages send --as-managed-agent --grant \
--channel --content - --nonce
buzz messages send-status --nonce
```

Grant creation/revocation must be owner-reviewed in Desktop. `send` should fail closed if Desktop is unavailable, the grant is expired/revoked, the channel differs, or the nonce was already consumed.

A smaller first milestone could be a Desktop deep link that opens an exact-text "Send as managed agent" review draft and requires the owner to click Send. That would unblock safe integrations without adding unattended signing, though it adds a second review action.

**Alternatives considered**

- **Read `managed-agents.json` from the CLI/local broker:** rejected because it turns an integration into a durable key reader and bypasses Desktop-owned capability review.
- **Copy a managed-agent nsec into a local broker:** rejected because provisioning and revocation become manual secret distribution.
- **Generate a standalone identity and add it to the channel:** tested; relay membership remains missing and publication is rejected.
- **Send as the owner's identity or an existing agent:** rejected because attribution and authority are broader than the integration requires.
- **Add a generic localhost HTTP signer without grants:** rejected; loopback is containment, not authorization, and arbitrary websites can reach localhost mutation endpoints.

**Additional context**

Relevant existing code:

- `desktop/src-tauri/src/commands/messages.rs` — `send_managed_agent_channel_message`, marker lookup, stored auth tag, key/pubkey verification.
- `desktop/src/shared/api/tauriManagedAgentMessages.ts` — current webview-only adapter.
- `crates/buzz-cli/src/commands/messages.rs` — current agent-facing message commands.

Security acceptance should cover origin/client authentication, channel mismatch, expired/revoked grant, replay, rate limit, crash-after-submit ambiguity, nonce reconciliation, and proof that key material never appears in CLI output or browser assets.

Duplicate search: no matching open or closed issue/PR found for `managed agent message CLI`, `scoped signer`, or `external dashboard sender`.

Contributor guide

Open the contributing guide

Research direction

Start with desktop/src-tauri/src/commands/messages.rs and the send_managed_agent_channel_message path, then read desktop/src/shared/api/tauriManagedAgentMessages.ts and crates/buzz-cli/src/commands/messages.rs. Trace the existing marker, auth-tag, key verification, and event-ID behavior before choosing the local integration boundary. Done means owner-reviewed scoped grants, fail-closed send and revocation checks, nonce reconciliation, rate limiting, and security coverage for the listed acceptance cases without exposing key material.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, typescript
Domain
authentication, authorization, cli, desktop, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.