Commit graph

30 commits

Author SHA1 Message Date
4df2fe2923 fix(spaces): remove is_enabled_for_space guard from ensure_default_roles
Some checks failed
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 5s
Update flake hashes / update-flake-hashes (pull_request) Failing after 5s
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 4s
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.
2026-03-19 19:55:44 +01:00
5787f38906 fix(spaces): don't reset manual PL overrides in sync_power_levels
Some checks failed
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Update flake hashes / update-flake-hashes (pull_request) Failing after 5s
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 5s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 4s
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.
2026-03-19 19:49:04 +01:00
528c1c501e feat(spaces): handle space leave/ban, fix enable ordering
Some checks failed
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 5s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 6s
Update flake hashes / update-flake-hashes (pull_request) Failing after 5s
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.
2026-03-19 19:46:40 +01:00
8494d1d65b fix(spaces): fix clippy semicolon_outside_block, add type alias for complex type
Some checks failed
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 5s
Update flake hashes / update-flake-hashes (pull_request) Failing after 6s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 6s
2026-03-19 19:37:28 +01:00
5cc90faa42 fix(spaces): address 10-agent review findings
Some checks failed
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 4s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 5s
Update flake hashes / update-flake-hashes (pull_request) Failing after 5s
- 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
2026-03-19 19:31:27 +01:00
2fbbf76692 fix(spaces): add server.running() guards to spawned enforcement tasks
Some checks failed
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 5s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 5s
Update flake hashes / update-flake-hashes (pull_request) Failing after 4s
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.
2026-03-19 19:16:04 +01:00
89074c9741 fix(spaces): address critical review findings
Some checks failed
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 6s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 6s
Update flake hashes / update-flake-hashes (pull_request) Failing after 5s
- 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
2026-03-19 18:41:54 +01:00
5740f72b4d refactor(spaces): extract hooks into service methods, minimize touchpoints
Some checks failed
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 5s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 5s
Update flake hashes / update-flake-hashes (pull_request) Failing after 5s
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.
2026-03-19 18:32:05 +01:00
07c38c3339 refactor(spaces): extract event type helpers and PL sync loop
Some checks failed
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 5s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 5s
Update flake hashes / update-flake-hashes (pull_request) Failing after 5s
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.
2026-03-19 18:17:33 +01:00
482f9145e6 refactor(spaces): consolidate duplicated code, delete redundant tests
Some checks failed
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 5s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 5s
Update flake hashes / update-flake-hashes (pull_request) Failing after 5s
- Delete cache_tests.rs and integration_tests.rs (only tested same two
  free functions already covered in tests.rs via MockCache indirection)
- Extract invite_and_join_user helper, eliminating duplicate invite+join
  PDU pattern in auto_join and handle_space_child_change
- Extract send_space_state! macro, eliminating 8 repeated lock+send
  blocks in admin commands
- Extract resolve_room_as_space! macro for enable/disable/status
- Remove redundant user_qualifies check in SPACE_ROLE_ROOM handler
  (kick_unqualified_from_rooms already checks)
- Add parent_spaces.is_empty() short-circuit in build.rs PL enforcement
- Hoist Arc::clone in append.rs to single binding
- Rename space_roles_cache_capacity -> space_roles_cache_flush_threshold
- Remove remaining trivial serde tests
2026-03-19 18:11:08 +01:00
f5ab4da12d fix(spaces): add early is_enabled() check in join path, use err! macro
Some checks failed
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 4s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 5s
Update flake hashes / update-flake-hashes (pull_request) Failing after 5s
Skip lock acquisition on every join when feature is globally disabled.
Use conduwuit::err! macro instead of manual Error::Err construction.
2026-03-19 16:47:28 +01:00
5b56a8b6ed feat(spaces): add per-Space cascading toggle with server-wide default
Some checks failed
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 4s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 5s
Update flake hashes / update-flake-hashes (pull_request) Failing after 14s
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.
2026-03-19 16:33:15 +01:00
53d4fb892c chore(spaces): fix formatting, add changelog, remove design docs
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>
2026-03-19 16:10:53 +01:00
78d7c56e6f fix(spaces): allow PL omission when users_default matches, handle semaphore errors
Some checks failed
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 5s
Update flake hashes / update-flake-hashes (pull_request) Failing after 4s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 13s
- 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>
2026-03-18 12:51:19 +01:00
cee5aa476c chore(spaces): fix doc comments, design doc accuracy, consistent error style
- 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>
2026-03-18 12:35:35 +01:00
d569ef2e40 style(spaces): convert to structured logging, fix import ordering, add lock docs
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>
2026-03-18 12:17:14 +01:00
dd1e9f0979 refactor(spaces): fix clippy, extract testable functions, improve test coverage
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>
2026-03-18 11:53:11 +01:00
b14889176e fix(spaces): add enforcement dedup, cache bounds, PartialEq derives, skip server user
- 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>
2026-03-18 11:30:19 +01:00
aa610b055a fix(spaces): cascade role removal, validate role names, gate on Space type
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 11:19:44 +01:00
898f4a470c refactor(spaces): extract constants, add forward index, reduce duplication
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>
2026-03-18 11:06:58 +01:00
4c0ec5f7a0 fix(spaces): address fourth review - stale cache, PL membership check, multi-space safety
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:46:30 +01:00
939f7e3d72 fix(spaces): address third review - event loops, PL guards, namespace, concurrency
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>
2026-03-18 10:33:18 +01:00
6fa67ed489 fix(spaces): improve feature flag isolation for disabled state
- 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>
2026-03-18 10:19:53 +01:00
40646eb4ba fix(spaces): wire up enforcement hooks, fix deadlocks, validate spaces
- 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>
2026-03-18 10:13:47 +01:00
c8f39ca6ff feat(spaces): add default roles init and startup cache rebuild
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>
2026-03-18 09:52:10 +01:00
0a52a928dc test(spaces): add comprehensive unit and integration tests
- 12 event content type serde tests (all pass)
- Service lookup unit tests (power level calc, role qualification)
- Enforcement scenario integration tests (access lifecycle, cross-space isolation)
- Cache consistency tests (populate, invalidate, clear)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 09:27:22 +01:00
f143248636 feat(spaces): add power level sync, auto-join, and auto-kick methods
- 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>
2026-03-17 17:13:59 +01:00
83eea18f3e feat(spaces): add cache population and lookup methods for space roles
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>
2026-03-17 17:03:47 +01:00
aae610b3d2 fix(spaces): use RoleDefinition from core instead of local duplicate
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 16:56:11 +01:00
053bdf00da feat(spaces): add space roles service for permission cascading
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>
2026-03-17 16:54:19 +01:00