Workflow deletion: non-owner delete is accepted then silently ignored, and owner delete leaves a ghost kind:30620 definition event
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
## Summary
Two related defects in the workflow (kind:30620) deletion path:
1. **Non-owner delete is silently ignored but acknowledged.** A non-owner
submitting the CLI's kind:5 deletion for another author's workflow receives
`{"accepted":true, "event_id":"…"}` — but the workflow persists and keeps
firing. Cause: `delete_workflow_for_owner` matches rows on owner, deletes
zero rows for a non-owner, and the NIP-09 event acceptance is reported
regardless of effect. By contrast, non-owner `workflows trigger` correctly
returns `forbidden` — the authorization surfaces are inconsistent, and the
delete path converts an authorization failure into false completion
evidence.
2. **Owner delete leaves a ghost definition event.** A successful owner
deletion removes the workflows DB row (engine-side: `trigger` then returns
`400 workflow not found`) but does NOT remove or tombstone the stored
kind:30620 definition event. `workflows list` (and any client rendering
kind:30620) keeps showing the deleted workflow indefinitely.
## Why it matters
`accepted:true` on a write that had no effect gives clients false completion
evidence. In a multi-agent channel this caused a real coordination fault: an
agent believed a scheduled workflow was deleted and provisioned a replacement,
risking duplicate scheduled runs. The ghost event then makes listings disagree
with the engine about what exists. Accepted-but-ignored writes are the same
failure shape as the announcement-update timestamp defect (#4509).
## Reproduction
1. Identity A (channel member) creates a scheduled workflow W:
`buzz workflows create --channel --yaml `.
2. Identity B (same channel, not owner):
- `buzz workflows trigger --workflow W` → `forbidden` (correct)
- `buzz workflows delete --workflow W` → `accepted:true`; W persists and
fires on schedule (defect 1)
3. Identity A: `buzz workflows delete --workflow W` → engine row deleted
(`trigger` → `400 workflow not found`), but the kind:30620 event still
appears in `workflows list` (defect 2).
## Expected
- Non-owner delete: explicit `forbidden`, matching `trigger` — never
`accepted:true` for a write that will be ignored.
- Owner delete: the kind:30620 definition event is deleted or tombstoned so
listings agree with the engine.
## Environment
- Self-hosted Buzz relay (Railway), deployed commit `788b3c0`
- Deletion via CLI kind:5 path
(`crates/buzz-cli/src/commands/workflows.rs::cmd_delete_workflow`);
engine-side handling in `delete_workflow_for_owner`
Contributor guide
Research direction
Start with crates/buzz-cli/src/commands/workflows.rs::cmd_delete_workflow and the engine-side delete_workflow_for_owner path. Reproduce both deletion cases from the issue, then trace how kind:5 acceptance and kind:30620 storage are handled. Done means non-owners receive forbidden, owners remove or tombstone the definition event, and listings agree with the engine.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend-api-design, cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 58/100