Summary
Two related defects in the workflow (kind:30620) deletion path:
-
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.
-
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
- Identity A (channel member) creates a scheduled workflow W:
buzz workflows create --channel <uuid> --yaml <def>.
- 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)
- 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
Summary
Two related defects in the workflow (kind:30620) deletion path:
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 keepsfiring. Cause:
delete_workflow_for_ownermatches rows on owner, deleteszero rows for a non-owner, and the NIP-09 event acceptance is reported
regardless of effect. By contrast, non-owner
workflows triggercorrectlyreturns
forbidden— the authorization surfaces are inconsistent, and thedelete path converts an authorization failure into false completion
evidence.
Owner delete leaves a ghost definition event. A successful owner
deletion removes the workflows DB row (engine-side:
triggerthen returns400 workflow not found) but does NOT remove or tombstone the storedkind:30620 definition event.
workflows list(and any client renderingkind:30620) keeps showing the deleted workflow indefinitely.
Why it matters
accepted:trueon a write that had no effect gives clients false completionevidence. 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
buzz workflows create --channel <uuid> --yaml <def>.buzz workflows trigger --workflow W→forbidden(correct)buzz workflows delete --workflow W→accepted:true; W persists andfires on schedule (defect 1)
buzz workflows delete --workflow W→ engine row deleted(
trigger→400 workflow not found), but the kind:30620 event stillappears in
workflows list(defect 2).Expected
forbidden, matchingtrigger— neveraccepted:truefor a write that will be ignored.listings agree with the engine.
Environment
788b3c0(
crates/buzz-cli/src/commands/workflows.rs::cmd_delete_workflow);engine-side handling in
delete_workflow_for_owner