sync_power_levels now queries all parent spaces internally via
get_parent_spaces, making the space_id parameter redundant. This also
eliminates redundant work where sync_power_levels_for_children was
calling it once per child per parent space.
Remove redundant assert!(a || b) after assert!(b). Rename tests to
better reflect what they test. Add multi_space_room_has_reqs_in_one_space_only
to cover room with requirements in space A but not space B.
Cover highest-wins PL logic across multiple parent spaces, OR-based
join/kick qualification, edge cases (one space has no PL, neither has
PL, user only in one space, same role different PLs across spaces).
When a room is a child of multiple spaces, sync_power_levels now
computes the maximum power level across ALL parent spaces for each
user, not just the triggering space. validate_pl_change similarly
computes the effective PL as the max across all parents before
rejecting conflicting proposals.
The guard prevented ensure_default_roles from working in the enable
command — it checked the cascading state event which hasn't been
written yet at that point. Callers should gate this themselves.
Remove the else branch that stripped power levels from users not managed
by any space role. This was destroying manually-set PLs for users who
happened to be in space-managed rooms but had no space roles. Space
roles should only SET power levels for managed users, never remove
entries for non-managed users.
Add handle_space_member_leave to kick users from child rooms when they
leave or are banned from a Space. Handle both Join and Leave/Ban
membership transitions in on_pdu_appended dispatch.
Fix enable command to create default roles before sending the cascading
enable event, preventing enforcement from running against empty roles.
- Make cache fields private, add get_user_roles_in_space and
get_room_requirements_in_space accessor methods for admin layer
- Add flush_space_from_cache and call it when cascading is disabled
for a space (prevents stale enforcement data)
- Fix err!(Err("...")) -> err!("...") (redundant variant wrapper)
- Fix variable naming: sender -> server_user in ensure_default_roles
- Fix UFCS turbofish in validate_pl_change to simpler .as_str()
- Import Semaphore instead of inline tokio::sync::Semaphore path
- Add power_level bounds validation in add command (Matrix Int range)
- Add room-is-child-of-space validation in require command
- Handle SPACE_CASCADING_EVENT_TYPE in enforcement dispatch to flush
cache when a space is disabled
Check server.running() at the start of each spawned task to avoid
doing enforcement work during shutdown, matching the codebase's
established pattern for short-lived spawned tasks.
- Fix pending_enforcement cleanup: wrap enforcement body in async block
so removal always runs even on semaphore error or early return
- Fix check_join_allowed: remove is_enabled() guard that blocked
per-space overrides when global flag is false (get_parent_spaces
already filters by is_enabled_for_space)
- Fix kick/join asymmetry: kick_unqualified_from_rooms now checks all
parent spaces before kicking, matching check_join_allowed's OR logic
- Fix lock ordering: validate_pl_change now acquires roles before
user_roles, matching get_user_power_level's order
- Fix ensure_default_roles TOCTOU: move existence check inside state
lock to prevent concurrent duplicate writes
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.
Extract StateEventType constructor helpers to avoid repeated
to_owned() allocations at each call site. Extract
sync_power_levels_for_children to consolidate 3 identical loops.
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.
Run cargo +nightly fmt, add towncrier news fragment, remove plan
documents that served their purpose during development.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>