Move all space roles logic out of append.rs, build.rs, and join.rs
into service methods (on_pdu_appended, validate_pl_change,
check_join_allowed). Existing files now have single-line call sites
instead of inline logic. Extract flush_caches helper to deduplicate
cache clearing.
Add com.continuwuity.space.cascading state event for per-Space override
of the server-wide space_permission_cascading config. Add enable/disable/
status admin commands. Strip superfluous comments throughout.
Critical fixes:
- handle_space_child_change now reads the actual m.space.child state event
and checks if via is empty; removes child from index on removal instead
of unconditionally adding
- Server user is exempted from PL rejection guard so sync_power_levels
can function without being blocked by its own protection
- PL rejection now also checks that space-managed users aren't omitted
from proposed power level events
Important fixes:
- room_to_space changed from 1:1 to 1:many (HashMap<RoomId, HashSet<RoomId>>)
so a room can belong to multiple parent spaces; get_parent_space renamed
to get_parent_spaces; join gating checks all parents (qualify in any)
- All custom event types renamed from m.space.* to com.continuwuity.space.*
to avoid squatting on the Matrix namespace
- Cache cleanup on child removal from space
- Added tokio Semaphore (capacity 4) to limit concurrent enforcement tasks
- Server user membership checked before enforcement in auto_join, kick,
and sync_power_levels to avoid noisy errors
Suggestions:
- Replaced expect() calls with proper error propagation via map_err/?
- Fixed indentation in timeline/mod.rs line 116
- handle_space_child_change now directly joins users to the specific new
child room instead of scanning all children via auto_join_qualifying_rooms
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Checks if user has required Space roles before allowing join to a
child room. Runs after antispam checks, before the actual join path.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This fixes a vulnerability where an attacker with a malicious remote
server and a user on the local server can trick the local server into
signing arbitrary events. The attacker issue a remote leave as the local
user to a room on the malicious server. Without any validation of the
make_leave response, the local server would sign the attacker-controlled
event and pass it back to the malicious server with send_leave.
The join and knock endpoints are also fixed in this commit, but are less
useful for exploitation because the local server replaces the "content"
field returned by the remote server. Remote invites are unaffected
because we already check that the event returned from /invite has the
same event ID as the event passed to it.
Co-authored-by: timedout <git@nexy7574.co.uk>
Co-authored-by: Jade Ellis <jade@ellis.link>
Co-authored-by: Ginger <ginger@gingershaped.computer>
**Does not yet work!** Currently, state resolution does not correctly resolve conflicting states. Everything else appears to work as expected, so stateres will be fixed soon, then we should be clear for takeoff.
Also: a lot of things currently accept a nullable room ID that really just don't need to. This will need tidying up before merge. Some authentication checks have also been disabled temporarily but nothing important.
A lot of things are tagged with `TODO(hydra)`, those need resolving before merge. External contributors should PR to the `hydra/public` branch, *not* ` main`.
---
This PR should be squash merged.
Reviewed-on: https://forgejo.ellis.link/continuwuation/continuwuity/pulls/943
Co-authored-by: nexy7574 <git@nexy7574.co.uk>
Co-committed-by: nexy7574 <git@nexy7574.co.uk>