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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uk8aPxHn3BHCe52L226jdG
This commit is contained in:
Matthew Hodgson
2026-07-14 13:23:26 +01:00
co-authored by Claude Fable 5
parent c24038ff6f
commit 9cea90e6cc
9 changed files with 27 additions and 27 deletions
+2 -2
View File
@@ -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 {
+2 -2
View File
@@ -92,7 +92,7 @@ pub struct PushRuleEvaluator {
/// outlier.
sender_power_level: Option<i64>,
/// 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,
+7 -7
View File
@@ -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;
}
+5 -5
View File
@@ -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.
+4 -4
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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]]: ...
+2 -2
View File
@@ -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()
+3 -3
View File
@@ -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,