DELETE /v1/rooms: cascade-revoke invites and share link#3
Merged
Conversation
A room was shareable in two ways — hmq_… invites (auto-minted at room create) and the hms_… share link — but DELETE /v1/rooms only flipped revoked_at on the room itself. Every invite and the share link kept working at the auth layer, which surfaced in the website as orphaned "4 live invites" rows on /app/settings for rooms the owner had already revoked. Cascade both: - TenantRegistry.revoke_capabilities_for_room sweeps every live capability whose constraints.room_id matches. Filter is Python-side (constraints is TEXT, not jsonb) so it stays storage-agnostic. - The DELETE handler in api/rooms.py revokes the room first, then best-effort cascades the capabilities and disable_room_share_link. Cascade failures don't undo the room revoke — worst case the owner has to revoke an orphan from /app/settings. Also adds a top-of-file docstring on api/rooms.py describing the two sharing primitives (invite vs share link) side by side so the distinction is obvious from the source, and three regression tests for the capability cascade (targets only matching rooms, idempotent, unknown room is a no-op). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A room was shareable two ways —
hmq_…capability tokens (auto-minted at room create) and thehms_…share link — butDELETE /v1/rooms/{id}only flippedrevoked_aton the room itself. Every invite and the share link kept resolving at the auth layer; only the run path failed. From the owner's seat in the website this surfaced as "4 live invites" on/app/settingslong after the rooms had been revoked, which is the opposite of what revocation should mean.Change
Make
DELETE /v1/rooms/{id}revoke the room and retire every credential pointing at it.TenantRegistry.revoke_capabilities_for_room(tenant_id, room_id) -> int— sweeps every live_capability_tokensrow whoseconstraints.room_idmatches. Filter is Python-side becauseconstraintsisTEXT(JSON-encoded), so we don't introduce ajsonb-only dependency.api/rooms.pyrevokes the room first (primary check still wins), then best-effort cascades:revoke_capabilities_for_roomfor invitesdisable_room_share_link(already existed) for the share link row/app/settings. That's strictly better than leaving the room half-revoked.invites_revokedandshare_link_disabledso clients (the website,hmctl) can surface what got swept.Docs
Top-of-file docstring on
api/rooms.pynow lays out the two sharing primitives in a side-by-side table:…so the distinction is obvious from the source, not just from product context.
Tests
Three regression tests in
tests/test_capability_tokens.py:test_revoke_capabilities_for_room_only_targets_matching_room— confirms we sweep only invites for the named room and leave other rooms' invites live.test_revoke_capabilities_for_room_idempotent— second call returns 0, doesn't double-revoke.test_revoke_capabilities_for_room_unknown_room_returns_zero— guards against accidentally wide queries.Full capability + room test suite green (70 tests, ~89s):
Companion website change
hivemind-website@38ad246already shipped the explanatory UI on both/app/settings(Room invites panel) and the per-room Share link panel, plus per-row room-name resolution and a "room revoked" pill for orphaned invites that exist today. Once this PR merges, new room revokes will auto-clean and the pill won't appear for fresh ones.🤖 Generated with Claude Code