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>
- PL omission check now allows omitting a space-managed user if the
proposed users_default equals their space-granted PL
- Semaphore acquire errors cause early return instead of silent proceed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix doc comment referencing room_to_space instead of space_to_rooms
- Add space_to_rooms forward index to design doc index table
- Use Err! consistently for validation errors in admin commands
- Rename test to follow deserialize_ prefix convention
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Convert all log statements in space roles code to use structured
key-value fields instead of string interpolation, matching the project
code style. Fix import ordering (serde_json moved after conduwuit_core),
move a misplaced `use futures::StreamExt` from function body to
file-level imports, add lock ordering comments to prevent deadlocks,
fix populate_space to acquire locks in the same order as
handle_space_child_change, add diagnostic debug_warn before PL
rejection errors, and document the nested cascade limitation on
get_parent_spaces.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix all clippy warnings in space roles files: dangerous `as` casts,
`to_string()` on &str, format string inlining, items-after-statements,
needless borrows, large futures, semicolons outside blocks, and
let-else patterns.
Extract `compute_user_power_level` and `roles_satisfy_requirements` as
pure free functions so the core logic can be unit-tested without async
service dependencies. Update all tests in tests.rs and
integration_tests.rs to call the real extracted functions instead of
reimplementing the logic inline.
Add negative deserialization tests for RoleDefinition,
SpaceRoleMemberEventContent, and SpaceRoleRoomEventContent. Improve
doc comments on handle_* methods and add module-level documentation to
cache_tests.rs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add per-space dedup set to prevent concurrent enforcement tasks from
competing when multiple role events fire rapidly for the same space
- Add space_roles_cache_capacity config (default 1000) to bound cache
growth, clearing all caches when exceeded
- Add PartialEq/Eq derives to all space role event content types
- Skip server user in auto_join_qualifying_rooms and handle_space_member_join
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract event type string literals as constants in space_roles.rs and
replace all occurrences across service and admin code. Add a forward
index (space_to_rooms) for O(1) child room lookups instead of scanning
the reverse index. Introduce resolve_space! macro to deduplicate the
repeated enabled-check + alias-resolve + space-type-guard pattern in
all 9 admin command handlers. Flatten deeply nested if-let chains in
append.rs using let-chains syntax.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove redundant StdHashSet import alias in cache_tests.rs
- Add type alias SpaceEnforcementData for readability in build.rs
- Fix formatting of for-loop closing brace in PL check
- Move BTreeMap and RoleDefinition imports to file-level in build.rs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
- Gate memory_usage() and clear_cache() with is_enabled()
- Gate populate_space() and get_parent_space() as defense-in-depth
- All admin commands now refuse when feature is disabled with
a clear message pointing to the config option
- Prefix memory labels with space_ for disambiguation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add spawn_enforcement methods (handle_state_event_change,
handle_space_child_change, handle_space_member_join) that run
enforcement as background tasks to avoid recursive Send issues
- Expand append_pdu hook to trigger enforcement on role events,
space child changes, and space member joins
- Fix deadlock risk in get_user_power_level and user_qualifies_for_room
by dropping read guards before acquiring new ones
- Batch room_to_space writes in populate_space with a single write lock
- Add space type validation to all admin commands
- Fix PL rejection check to reject any change (!=) not just lowering (<)
- Fix sync_power_levels to also lower PLs for users who lost their roles
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Checks proposed m.room.power_levels events against Space-granted power
levels. Rejects if any user's proposed PL is below their Space role PL.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add ensure_default_roles() to check if a Space has m.space.roles state
event and create default admin/mod roles if missing. Add worker() to
rebuild the space roles cache on startup by iterating all rooms and
populating cache for spaces.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Updates the space roles cache when m.space.roles, m.space.role.member,
or m.space.role.room state events are appended. Adds roles service as
a dependency of the timeline service.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- sync_power_levels(): Overrides child room PLs with Space role PLs
- auto_join_qualifying_rooms(): Joins user to all rooms they qualify for
- kick_unqualified_from_rooms(): Kicks user from rooms they no longer qualify for
- Adds globals dep for server_user access
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>
Adds is_enabled(), populate_space(), get_user_power_level(),
user_qualifies_for_room(), and get_parent_space() methods.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create rooms::roles::Service with in-memory caches for role definitions,
user-role assignments, room requirements, and room-to-space mappings.
Register the service in the service stack alongside other room services.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Define serde content types for m.space.roles, m.space.role.member,
and m.space.role.room custom state events used by space permission
cascading.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Only the server user can now remove the #admins alias, matching the
existing check for setting the alias. This prevents users from
accidentally breaking the admin room functionality.
fixes#1408
- Disabled first-run mode when running Complement tests
- Updated logging config under complement to be a bit less verbose
- Changed test result and log output locations