Skip to content

fix(relay): allow deleting archived channels - #7569

Open
hyein-cbio wants to merge 1 commit into
block:mainfrom
hyein-cbio:hyein-cbio/jawfish
Open

hyein-cbio wants to merge 1 commit into
block:mainfrom
hyein-cbio:hyein-cbio/jawfish

Conversation

@hyein-cbio

@hyein-cbio hyein-cbio commented Sep 10, 2026

Copy link
Copy Markdown

Summary

Archive is a write-lock, not a tombstone. Owners could unarchive a channel (kind:9002 + archived=false) but could not delete it (kind:9008), so the relay rejected delete with invalid: channel is archived.

That left ephemeral huddle backing channels stuck: hang-up and the TTL reaper archive them, and there was no way to remove them afterward.

This change extracts a shared helper, allow_event_on_archived_channel, used by both production gates (ingest and validate_admin_event). The only mutations that remain valid on an archived channel are:

  • unarchive (kind:9002 + archived=false)
  • delete-group (kind:9008)

Everything else stays rejected (messages, membership, rename, kind:9005). Kind 9008 still requires owner (or owner-of-owner-agent) authorization. soft_delete_channel already keys on deleted_at IS NULL, not archived_at, so delete after archive actually lands.

Related issue

Same bug as #2954. Open PRs for it: #2988, #4669. Both last moved 2026-08-19. This is not a new diagnosis.

Compared with #2988 and #4669

All three PRs touch the same three files and the same two archived-channel guards. They are the same fix, restated.

#2988 (July, Fixes #2954) is the original. It inlines is_delete at both gates instead of sharing a helper, so the two exceptions can drift again. It has no unit test. Its ignored e2e is the strongest of the three: archive/unarchive/re-archive with a nonce so duplicate event ids cannot skip side effects; name-edit still hits channel is archived; non-owner 9008 fails with only owner can delete group (auth ran, not the archive guard); owner delete then unarchive fails with channel not found. It still calls get_channel.

#4669 (August) is the shared-helper version of that idea (archived_channel_allows_event) and uses KIND_NIP29_DELETE_GROUP / KIND_NIP29_EDIT_METADATA. Unit tests only cover allow-9008, unarchive vs archive, and reject-9000. E2E is owner archive-then-delete accepted, like this PR. It also still calls get_channel.

This PR keeps the shared helper, on current main (get_channel_for_event_write). The unit table is stricter than #4669: it also rejects name-only 9002, 9005, and kind 1. Comments pin 9008 to huddle hang-up and the TTL reaper. The helper uses 9008 / 9002 literals to match nearby side_effects.rs match arms; #2988 and #4669 are better on that point. The e2e is weaker than #2988: it does not prove non-owner auth, post-delete disappearance, or that a rename still hits the write-lock.

If maintainers want one of these, #2988 has the issue link and the better live-path test; #4669 and this PR have the better gate structure. This one is the rebase onto today's call sites.

Testing

  • Unit table test archived_channel_allows_unarchive_and_delete_group_only binds the production helper: allows 9008 and 9002 archived=false; rejects 9002 archived=true, name-only 9002, 9000, 9005, and kind 1. Ran locally: pass.
  • E2E test_owner_can_delete_archived_channel drives archive then 9008 through ingest. #[ignore] like the rest of e2e_relay.rs (needs a live relay). Weaker than fix(relay): allow owner to delete archived channels #2988's e2e, as above.
  • No UI change, so no screenshots.

Archive is a write-lock, not a tombstone. Owners could unarchive
(kind:9002 archived=false) but not delete (kind:9008), so ephemeral
huddle backing channels archived on hang-up or by the TTL reaper
could not be removed.

Signed-off-by: Hyein Cho <hyein.cho.cbio@gmail.com>
@hyein-cbio
hyein-cbio requested a review from a team as a code owner September 10, 2026 21:03
@github-actions

Copy link
Copy Markdown

🔐 Codex Security Review

Status: review required for the current range.

The current range is 00209076c7a10d9e4a475466c313e8ebecf041f5...a1e4b32cff701f47f51e8e935ce4d1aa4acd50e8.
A new review must complete for this exact range. When manual authorization
is required, a Block organization member must comment exactly
@buzz-security-review a1e4b32cff701f47f51e8e935ce4d1aa4acd50e8 to authorize a new review.
Any previous review applies only to its recorded range.

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.

Deleting an auto-archived huddle channel returns 400 "channel is archived"

1 participant