block / block/buzz

Archived agent identities leave orphaned repos/projects that only a DB admin can remove

Open
#4,547 2 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

# Archived agent identities leave orphaned repos/projects that only a DB admin can remove

## Summary

Every time an agent is (re-)added in Buzz Desktop, a new keypair is generated and the previous identity is orphaned. Any NIP-34 repo announcement (kind `30617`) or NIP-MP project (kind `30621`) that the old identity published outlives it: the signing key is destroyed with the identity, and deletion is author-scoped, so no in-product path can remove those entries — not the workspace owner, not another agent, not the Desktop Projects panel. The Projects list accumulates duplicate and dead rows.

We hit this on a self-hosted workspace, and the **only** way we could clean it up was deleting the events directly from the relay's database by hand. That works if you self-host; it is not available to anyone else.

## Impact

On our workspace, 5 of 7 Projects entries were signed by an identity that had been archived. One of them was a stale duplicate of a live repo — same display name, same bound channel, no clone URL, so nobody could even clone it. Two more had no repo binding at all. The remaining orphans point at real repositories that are still in use, but they can no longer be edited, rebound, or removed by anyone.

This is a one-way ratchet: every agent re-add adds more rows that no product surface can remove. On a hosted relay, they would be permanent.

## Steps to reproduce

1. In Buzz Desktop, have an agent announce a repo: `buzz repos create --id demo-repo --name "Demo" --channel `.
2. Remove and re-add that agent in the Agents panel (this generates a new keypair; the old identity is orphaned).
3. Archive the old identity.
4. Open the Projects panel and try to delete the `demo-repo` entry.

## Expected

The workspace owner can remove a project/repo entry published by an identity they own — through the Projects panel or a CLI command — without touching the database.

## Actual

Every in-product path fails. Confirmed on our workspace:

| Attempt | Result |
|---|---|
| Desktop Projects panel, as workspace owner | Entry could not be removed (reported by the workspace owner) |
| `buzz repos delete` | Subcommand does not exist (`buzz repos` has only `create`, `get`, `list`, `bind`, `protect`) |
| `buzz messages delete --event ` | `event has no h-tag — cannot determine channel` |
| `buzz projects delete ` | Only handles kind `30621`, and only for the current identity |
| Re-announcing under a live identity with the same `d`-tag | Does not replace the old entry. Addressable events are keyed by `(kind, pubkey, d-tag)`, so a different pubkey produces a *second* entry and the orphan remains |
| Hand-signed NIP-09 kind `5` delete from another identity, POSTed to `/events` | Rejected by design — NIP-09 honors only the original author's signature |
| **Manual `DELETE` against the relay database** | **Worked. This was the only thing that worked.** |

The archived identity's private key is genuinely unrecoverable: it is not in the OS keychain (the `buzz-desktop` entry holds keys only for currently configured agents), not in `agents/managed-agents.json` (the entry is deleted along with the agent), and not in the agent logs. So "just sign a NIP-09 delete as the original author" is not an option once the identity is gone.

## Why the DB workaround isn't a fix

- It requires shell/DB access to the relay. Anyone on a hosted or shared relay has no recourse at all.
- It bypasses the event log entirely — no tombstone, no audit trail, and any client that cached the event keeps showing it.
- It is trivially easy to delete the wrong row; the operator is hand-matching event IDs with no safety net.

## Suggested fixes

Any one of these would close the hole; the first two are the most valuable.

1. **Owner-level tombstone.** Let the workspace owner/admin publish a moderation tombstone over a repo/project entry authored by any identity in their workspace, and have the Projects panel expose it as a normal "Remove project" action. The relay already has a moderation event family (kinds `9040`–`9044`), so this fits the existing model and keeps an audit trail — unlike a raw DB delete.
2. **Don't orphan identities on re-add.** Reuse the existing keypair when an agent is re-added under the same name/slug, or offer an explicit "rotate identity" flow that carries ownership of published events across the rotation (NIP-IA already has a `replaced_by` rotation pointer — honor it for authorship of addressable events).
3. **Transfer on archive.** When an identity is archived, prompt to reassign or tombstone the repos/projects it authored, instead of silently stranding them.
4. **Stopgap:** add `buzz repos delete ` so at least an author can retract their own announcement. This does not fix the orphan case, but today even a live agent cannot delete an entry it published itself.

## Environment

- macOS 26.x
- Buzz Desktop with a self-hosted relay
- `buzz` CLI installed at `~/.local/bin/buzz` (no `--version` flag available, so the exact build cannot be reported)
- Observed 2026-08-03

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.