From 9cea90e6ccff2ed97d296d0bcf3087e43aef15fa Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Tue, 14 Jul 2026 13:23:26 +0100 Subject: [PATCH] Adopt MSC4506 identifiers for the knock push rule The knock push rules MSC has been published as MSC4506: rename the experimental flag to msc4506_enabled, the rule id to .org.matrix.msc4506.rule.knock and the condition kind to org.matrix.msc4506.recipient_permission per its unstable prefix section. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01Uk8aPxHn3BHCe52L226jdG --- rust/src/push/base_rules.rs | 4 ++-- rust/src/push/evaluator.rs | 4 ++-- rust/src/push/mod.rs | 14 +++++++------- synapse/config/experimental.py | 10 +++++----- synapse/push/bulk_push_rule_evaluator.py | 8 ++++---- synapse/storage/databases/main/push_rule.py | 2 +- synapse/synapse_rust/push.pyi | 2 +- tests/push/test_bulk_push_rule_evaluator.py | 4 ++-- tests/push/test_push_rule_evaluator.py | 6 +++--- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/rust/src/push/base_rules.rs b/rust/src/push/base_rules.rs index 54d26f30e9..3baeb34f76 100644 --- a/rust/src/push/base_rules.rs +++ b/rust/src/push/base_rules.rs @@ -117,12 +117,12 @@ pub const BASE_APPEND_OVERRIDE_RULES: &[PushRule] = &[ default: true, default_enabled: true, }, - // MSCxxxx: notify the members of a room who are able to act on a knock + // MSC4506: notify the members of a room who are able to act on a knock // (i.e. those with a power level sufficient to invite the knocker). Must // come before `.m.rule.member_event`, which suppresses all other member // events. PushRule { - rule_id: Cow::Borrowed("global/override/.org.matrix.mscxxxx.rule.knock"), + rule_id: Cow::Borrowed("global/override/.org.matrix.msc4506.rule.knock"), priority_class: 5, conditions: Cow::Borrowed(&[ Condition::Known(KnownCondition::EventMatch(EventMatchCondition { diff --git a/rust/src/push/evaluator.rs b/rust/src/push/evaluator.rs index 9254c88b46..ed7f2c9f1c 100644 --- a/rust/src/push/evaluator.rs +++ b/rust/src/push/evaluator.rs @@ -92,7 +92,7 @@ pub struct PushRuleEvaluator { /// outlier. sender_power_level: Option, - /// MSCxxxx: the power level required to perform each of the room's + /// MSC4506: the power level required to perform each of the room's /// power-levels actions (e.g. "invite", "kick"), for the /// `recipient_permission` condition. Includes the spec defaults for /// actions absent from the `m.room.power_levels` content. @@ -190,7 +190,7 @@ impl PushRuleEvaluator { /// - `Some(false)` if the event is in a thread and the user does NOT have a subscription for that thread /// /// recipient_power_level: the power level of the user the rules are being - /// evaluated for, used by the MSCxxxx `recipient_permission` condition. + /// evaluated for, used by the MSC4506 `recipient_permission` condition. #[pyo3(signature = (push_rules, user_id=None, display_name=None, msc4306_thread_subscription_state=None, recipient_power_level=None))] pub fn run( &self, diff --git a/rust/src/push/mod.rs b/rust/src/push/mod.rs index 51eb0cdda6..4041331d7f 100644 --- a/rust/src/push/mod.rs +++ b/rust/src/push/mod.rs @@ -369,10 +369,10 @@ pub enum KnownCondition { SenderNotificationPermission { key: Cow<'static, str>, }, - // MSCxxxx (knock push rules): matches if the user the rules are being + // MSC4506 (knock push rules): matches if the user the rules are being // evaluated for has a power level at least that required to perform the // action named by `key` (e.g. "invite"). - #[serde(rename = "org.matrix.mscxxxx.recipient_permission")] + #[serde(rename = "org.matrix.msc4506.recipient_permission")] RecipientPermission { key: Cow<'static, str>, }, @@ -567,7 +567,7 @@ pub struct FilteredPushRules { msc4210_enabled: bool, msc4306_enabled: bool, msc4505_enabled: bool, - mscxxxx_knock_push_rule_enabled: bool, + msc4506_enabled: bool, } #[pymethods] @@ -584,7 +584,7 @@ impl FilteredPushRules { msc4210_enabled: bool, msc4306_enabled: bool, msc4505_enabled: bool, - mscxxxx_knock_push_rule_enabled: bool, + msc4506_enabled: bool, ) -> Self { Self { push_rules, @@ -596,7 +596,7 @@ impl FilteredPushRules { msc4210_enabled, msc4306_enabled, msc4505_enabled, - mscxxxx_knock_push_rule_enabled, + msc4506_enabled, } } @@ -639,8 +639,8 @@ impl FilteredPushRules { return false; } - if !self.mscxxxx_knock_push_rule_enabled - && rule.rule_id.contains("/.org.matrix.mscxxxx.rule.knock") + if !self.msc4506_enabled + && rule.rule_id.contains("/.org.matrix.msc4506.rule.knock") { return false; } diff --git a/synapse/config/experimental.py b/synapse/config/experimental.py index c33c4ad108..695b9f0eee 100644 --- a/synapse/config/experimental.py +++ b/synapse/config/experimental.py @@ -162,12 +162,12 @@ class ExperimentalConfig(Config): # (_one_to_one) / .org.matrix.msc4505.rule.beacon. self.msc4505_enabled: bool = experimental.get("msc4505_enabled", False) - # MSCXXXX (unnumbered draft): default push rule notifying room members + # MSC4506: default push rule notifying room members # who can act on a knock (MSC2403), via the new `recipient_permission` - # push rule condition. Unstable ids: .org.matrix.mscxxxx.rule.knock / - # org.matrix.mscxxxx.recipient_permission. - self.mscxxxx_knock_push_rule_enabled: bool = experimental.get( - "mscxxxx_knock_push_rule_enabled", False + # push rule condition. Unstable ids: .org.matrix.msc4506.rule.knock / + # org.matrix.msc4506.recipient_permission. + self.msc4506_enabled: bool = experimental.get( + "msc4506_enabled", False ) # MSC3912: Relation-based redactions. diff --git a/synapse/push/bulk_push_rule_evaluator.py b/synapse/push/bulk_push_rule_evaluator.py index afd590e862..340724448f 100644 --- a/synapse/push/bulk_push_rule_evaluator.py +++ b/synapse/push/bulk_push_rule_evaluator.py @@ -191,10 +191,10 @@ class BulkPushRuleEvaluator: if target_already_in_room: local_users = [event.state_key] elif ( - self.hs.config.experimental.mscxxxx_knock_push_rule_enabled + self.hs.config.experimental.msc4506_enabled and event.membership == Membership.KNOCK ): - # MSCxxxx: a knock (sender == state_key, so not caught above) + # MSC4506: a knock (sender == state_key, so not caught above) # should notify the members of the room who can act on it, so # we can't take the membership-events-only-notify-their-target # fast path. @@ -480,7 +480,7 @@ class BulkPushRuleEvaluator: except (TypeError, ValueError): del notification_levels[key] - # MSCxxxx (knock push rules): the level required to perform each of the + # MSC4506 (knock push rules): the level required to perform each of the # room's power-levels actions, and the data to compute each recipient's # own level, for the `recipient_permission` condition. As above, # non-integer levels in old room versions are interpreted as integers @@ -558,7 +558,7 @@ class BulkPushRuleEvaluator: if msc4306_thread_subscribers is not None: msc4306_thread_subscription_state = uid in msc4306_thread_subscribers - # MSCxxxx: this user's own power level, for the + # MSC4506: this user's own power level, for the # `recipient_permission` condition. recipient_power_level = _coerce_power_level( user_power_levels.get(uid, users_default_level), users_default_level diff --git a/synapse/storage/databases/main/push_rule.py b/synapse/storage/databases/main/push_rule.py index a8f9b3d77a..71edc44b2c 100644 --- a/synapse/storage/databases/main/push_rule.py +++ b/synapse/storage/databases/main/push_rule.py @@ -108,7 +108,7 @@ def _load_rules( msc4210_enabled=experimental_config.msc4210_enabled, msc4306_enabled=experimental_config.msc4306_enabled, msc4505_enabled=experimental_config.msc4505_enabled, - mscxxxx_knock_push_rule_enabled=experimental_config.mscxxxx_knock_push_rule_enabled, + msc4506_enabled=experimental_config.msc4506_enabled, ) return filtered_rules diff --git a/synapse/synapse_rust/push.pyi b/synapse/synapse_rust/push.pyi index 715ae5df55..ad84ce7cf5 100644 --- a/synapse/synapse_rust/push.pyi +++ b/synapse/synapse_rust/push.pyi @@ -51,7 +51,7 @@ class FilteredPushRules: msc4210_enabled: bool, msc4306_enabled: bool, msc4505_enabled: bool, - mscxxxx_knock_push_rule_enabled: bool, + msc4506_enabled: bool, ): ... def rules(self) -> Collection[tuple[PushRule, bool]]: ... diff --git a/tests/push/test_bulk_push_rule_evaluator.py b/tests/push/test_bulk_push_rule_evaluator.py index e681b3e033..41cf8e341a 100644 --- a/tests/push/test_bulk_push_rule_evaluator.py +++ b/tests/push/test_bulk_push_rule_evaluator.py @@ -653,7 +653,7 @@ class TestBulkPushRuleEvaluator(HomeserverTestCase): class TestKnockPushRules(HomeserverTestCase): - """Tests for the MSCxxxx knock push rule (`.org.matrix.mscxxxx.rule.knock` + """Tests for the MSC4506 knock push rule (`.org.matrix.msc4506.rule.knock` with the `recipient_permission` condition): a knock should notify exactly the members of the room whose power level lets them act on it. """ @@ -714,7 +714,7 @@ class TestKnockPushRules(HomeserverTestCase): ) @override_config( - {"experimental_features": {"mscxxxx_knock_push_rule_enabled": True}} + {"experimental_features": {"msc4506_enabled": True}} ) def test_knock_notifies_only_users_who_can_act(self) -> None: knock_event_id = self._knock_and_get_event_id() diff --git a/tests/push/test_push_rule_evaluator.py b/tests/push/test_push_rule_evaluator.py index b71ea444f3..c3951bde26 100644 --- a/tests/push/test_push_rule_evaluator.py +++ b/tests/push/test_push_rule_evaluator.py @@ -824,14 +824,14 @@ class PushRuleEvaluatorTestCase(unittest.TestCase): def test_recipient_permission(self) -> None: """ - Test the MSCxxxx `recipient_permission` condition (knock push rules). + Test the MSC4506 `recipient_permission` condition (knock push rules). """ evaluator = self._get_evaluator( {"membership": "knock"}, action_power_levels={"invite": 50}, ) condition = { - "kind": "org.matrix.mscxxxx.recipient_permission", + "kind": "org.matrix.msc4506.recipient_permission", "key": "invite", } @@ -854,7 +854,7 @@ class PushRuleEvaluatorTestCase(unittest.TestCase): # An action key with no known level never matches. self.assertFalse( evaluator.matches( - {"kind": "org.matrix.mscxxxx.recipient_permission", "key": "nonsense"}, + {"kind": "org.matrix.msc4506.recipient_permission", "key": "nonsense"}, "@user:test", None, recipient_power_level=100,