feat: Implement event rejection #1747

Merged
nex merged 16 commits from nex/feat/rejected-events into main 2026-05-25 17:10:17 +00:00
Owner

Implements event rejection (see: part 3.3 of https://spec.matrix.org/v1.18/rooms/v12/#authorization-rules), which should help resolve some netsplits observed in the continuwuity rooms.

Also un-flags PDUs as soft-failed or rejected when forcing our local state (e.g. when joining via a remote server, or force setting the state, in turn giving us a "clean" slate), and added the !admin users force-join-room-remotely admin command to support forcing a remote join, which may work around local-only issues.

Pull request checklist:

  • This pull request targets the main branch, and the branch is named something other than
    main.
  • I have written an appropriate pull request title and my description is clear.
  • I understand I am responsible for the contents of this pull request.
  • I have followed the contributing guidelines:
Implements event rejection (see: part 3.3 of https://spec.matrix.org/v1.18/rooms/v12/#authorization-rules), which should help resolve some netsplits observed in the continuwuity rooms. Also un-flags PDUs as soft-failed or rejected when forcing our local state (e.g. when joining via a remote server, or force setting the state, in turn giving us a "clean" slate), and added the `!admin users force-join-room-remotely` admin command to support forcing a remote join, which may work around local-only issues. **Pull request checklist:** <!-- You need to complete these before your PR can be considered. If you aren't sure about some, feel free to ask for clarification in #dev:continuwuity.org. --> - [x] This pull request targets the `main` branch, and the branch is named something other than `main`. - [x] I have written an appropriate pull request title and my description is clear. - [x] I understand I am responsible for the contents of this pull request. - I have followed the [contributing guidelines][c1]: - [x] My contribution follows the [code style][c2], if applicable. - [x] I ran [pre-commit checks][c1pc] before opening/drafting this pull request. - [x] I have [tested my contribution][c1t] (or proof-read it for documentation-only changes) myself, if applicable. This includes ensuring code compiles. - [x] My commit messages follow the [commit message format][c1cm] and are descriptive. <!-- Notes on these requirements: - While not required, we encourage you to sign your commits with GPG or SSH to attest the authenticity of your changes. - While we allow LLM-assisted contributions, we do not appreciate contributions that are low quality, which is typical of machine-generated contributions that have not had a lot of love and care from a human. Please do not open a PR if all you have done is asked ChatGPT to tidy up the codebase with a +-100,000 diff. - In the case of code style violations, reviewers may leave review comments/change requests indicating what the ideal change would look like. For example, a reviewer may suggest you lower a log level, or use `match` instead of `if/else` etc. - In the case of code style violations, pre-commit check failures, minor things like typos/spelling errors, and in some cases commit format violations, reviewers may modify your branch directly, typically by making changes and adding a commit. Particularly in the latter case, a reviewer may rebase your commits to squash "spammy" ones (like "fix", "fix", "actually fix"), and reword commit messages that don't satisfy the format. - Pull requests MUST pass the `Checks` CI workflows to be capable of being merged. This can only be bypassed in exceptional circumstances. If your CI flakes, let us know in matrix:r/dev:continuwuity.org. - Pull requests have to be based on the latest `main` commit before being merged. If the main branch changes while you're making your changes, you should make sure you rebase on main before opening a PR. Your branch will be rebased on main before it is merged if it has fallen behind. - We typically only do fast-forward merges, so your entire commit log will be included. Once in main, it's difficult to get out cleanly, so put on your best dress, smile for the cameras! --> [c1]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/CONTRIBUTING.md [c2]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/docs/development/code_style.mdx [c1pc]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/CONTRIBUTING.md#pre-commit-checks [c1t]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/CONTRIBUTING.md#running-tests-locally [c1cm]: https://forgejo.ellis.link/continuwuation/continuwuity/src/branch/main/CONTRIBUTING.md#commit-messages
feat: Implement event rejection
Some checks failed
Auto Labeler / Apply labels based on changed files (pull_request_target) Successful in 3s
Checks / Prek / Check changed files (pull_request) Successful in 5s
Checks / Changelog / Check changelog is added (pull_request_target) Failing after 7s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m28s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m36s
Checks / Prek / Clippy and Cargo Tests (pull_request) Has been cancelled
70a768a711
Co-Authored-By: star <star@nexy7574.co.uk>
nex requested review from Owners 2026-05-08 18:56:13 +00:00
chore: Add news fragment for 1747
All checks were successful
Checks / Prek / Check changed files (pull_request) Successful in 7s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 35s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m22s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m35s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 8m4s
3f3ca53fdd
Co-Authored-By: star <star@nexy7574.co.uk>
ginger approved these changes 2026-05-09 01:47:55 +00:00
Dismissed
@ -124,0 +141,4 @@
}
/// Removes any soft-fail or rejection markers applied to the target PDU
pub(super) fn unmark_pdu(&self, event_id: &EventId) {
Owner

suggested name: clear_pdu_markers

suggested name: `clear_pdu_markers`
nex marked this conversation as resolved
@ -143,0 +163,4 @@
&& !self.db.is_event_soft_failed(event_id).await
}
pub fn unmark_pdu(&self, event_id: &EventId) { self.db.unmark_pdu(event_id); }
Owner

same here

same here
nex marked this conversation as resolved
fix: Mark events as rejected in more places, correct soft-fail extremity behaviour
All checks were successful
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 36s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m19s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m35s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 8m12s
ec76147784
fix: Don't hard fail on events which depend on soft-failed events
All checks were successful
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 35s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m20s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m32s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 8m10s
ab277409bc
feat: Add !admin debug show-auth-chain
Some checks failed
Checks / Prek / Check changed files (pull_request) Successful in 5s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 33s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m20s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m28s
Checks / Prek / Clippy and Cargo Tests (pull_request) Has been cancelled
36cf5b053b
Because why not am I right lads
style: Rename unmark_pdu to clear_pdu_markers
Some checks failed
Checks / Prek / Check changed files (pull_request) Successful in 7s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 34s
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 1m27s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m35s
Checks / Prek / Clippy and Cargo Tests (pull_request) Has been cancelled
d576620953
chore: Update newsfrag
Some checks failed
Checks / Prek / Check changed files (pull_request) Successful in 7s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 35s
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 1m19s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m28s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 8m9s
5a4b8309a7
This prevents future network lookups if we've already rejected an event and see a reference to it again
style: Reformat
All checks were successful
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 37s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m20s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m32s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 8m11s
b884fbd240
@ -48,0 +57,4 @@
}
// If any of the auth events are rejected, this event is also rejected.
for aid in incoming_pdu.auth_events() {
Author
Owner

This check should be moved into handle_incoming_pdu

This check should be moved into `handle_incoming_pdu`
nex marked this conversation as resolved
nex force-pushed nex/feat/rejected-events from b884fbd240
All checks were successful
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 37s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m20s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m32s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 8m11s
to 8d26dcd7a3
All checks were successful
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 34s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m21s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m47s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 8m5s
2026-05-10 17:05:34 +00:00
Compare
@ -70,2 +70,4 @@
}
#[derive(Clone, Copy, Eq, PartialEq)]
enum NodeStatus {
Owner

suggestion:

struct NodeInfo {
    exists_locally: bool,
    status: NodeStatus,
}

enum NodeStatus {
    Accepted, SoftFailed, Rejected
}
suggestion: ```rs struct NodeInfo { exists_locally: bool, status: NodeStatus, } enum NodeStatus { Accepted, SoftFailed, Rejected } ```
Author
Owner

tried this and it was balls

tried this and it was balls
nex marked this conversation as resolved
@ -72,0 +107,4 @@
match status {
| NodeStatus::Rejected(_) => writeln!(graph, "class {node_id} rejected;")?,
| NodeStatus::SoftFailed(_) => writeln!(graph, "class {node_id} soft_failed;")?,
| NodeStatus::Normal(_) => {},
Owner

would be nice if the target event had special styling to make it more obvious in a large graph

would be nice if the target event had special styling to make it more obvious in a large graph
Author
Owner

I did experiment with a few formats but I couldn't really find anything that remained legible. Maybe eventID (eventType), but eventID (eventType, stateKey) and permutations were all too much

I did experiment with a few formats but I couldn't really find anything that remained legible. Maybe `eventID (eventType)`, but `eventID (eventType, stateKey)` and permutations were all too much
nex marked this conversation as resolved
@ -72,0 +141,4 @@
return Err!("Event not found.");
};
let mut graph = String::from(
Owner

perhaps use Askama to build this string?

perhaps use Askama to build this string?
Author
Owner

seems unnecessary

seems unnecessary
nex marked this conversation as resolved
@ -218,0 +220,4 @@
.write()
.insert(room_id.into(), (event_id.to_owned(), start_time));
defer! {{
Owner

space after macro invocation 🤨 what does this macro do anyway

space after macro invocation 🤨 what does this macro _do_ anyway
Author
Owner

space after macro invocation 🤨

idk i copied this from another place :D

defer... defers the call to the end of the function, even if the function returns early. It's like a finally branch of a try/except, it always executes when the function finishes

> space after macro invocation 🤨 idk i copied this from another place :D defer... defers the call to the end of the function, even if the function returns early. It's like a `finally` branch of a try/except, it always executes when the function finishes
nex marked this conversation as resolved
@ -48,0 +59,4 @@
// If any of the auth events are rejected, this event is also rejected.
for aid in incoming_pdu.auth_events() {
if self.services.pdu_metadata.is_event_rejected(aid).await {
// TODO: debug_warn instead of warn
Owner

⚠️todo alert

⚠️todo alert
nex marked this conversation as resolved
@ -147,0 +178,4 @@
if !auth_check {
warn!(
event_id = %incoming_pdu.event_id,
"Event authentication fails based on the current state of the room"
Owner

s/authentication/authorization. also this should probably be a debug_warn

s/authentication/authorization. also this should probably be a debug_warn
Author
Owner

idk our soft-fail log isn't

idk our soft-fail log isn't
nex marked this conversation as resolved
@ -294,6 +296,7 @@ impl Service {
servers: &[OwnedServerName],
state_lock: RoomMutexGuard,
) -> Result {
// public so the admin command force-join-room-remotely works
Owner

we should probably just have one admin command that does local and remote force joins

we should probably just have one admin command that does local and remote force joins
nex marked this conversation as resolved
nex force-pushed nex/feat/rejected-events from 8d26dcd7a3
All checks were successful
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 34s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m21s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m47s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 8m5s
to 57c5aab187
All checks were successful
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 34s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m33s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 2m32s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 9m14s
2026-05-13 19:47:17 +00:00
Compare
Jade approved these changes 2026-05-13 23:07:52 +00:00
Dismissed
Jade approved these changes 2026-05-19 10:07:30 +00:00
nex force-pushed nex/feat/rejected-events from 57c5aab187
All checks were successful
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 34s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m33s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 2m32s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 9m14s
to dd6d61fd2a
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 8s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m20s
Checks / Prek / Check changed files (pull_request) Successful in 7s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m29s
Update flake hashes / update-flake-hashes (pull_request) Successful in 1m33s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 32m8s
2026-05-21 16:12:43 +00:00
Compare
style: Warn -> debug_warn
Some checks failed
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 34s
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 1m29s
Update flake hashes / update-flake-hashes (pull_request) Successful in 1m35s
Documentation / Build and Deploy Documentation (pull_request) Successful in 10m47s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 32m19s
42d6077397
nex force-pushed nex/feat/rejected-events from 42d6077397
Some checks failed
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 34s
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 1m29s
Update flake hashes / update-flake-hashes (pull_request) Successful in 1m35s
Documentation / Build and Deploy Documentation (pull_request) Successful in 10m47s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 32m19s
to 512a96f832
Some checks failed
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 7s
Documentation / Build and Deploy Documentation (pull_request) Successful in 1m16s
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 1m32s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 8m45s
2026-05-25 16:18:32 +00:00
Compare
feat: Combine local & remote force join
Some checks failed
Checks / Prek / Check changed files (pull_request) Successful in 6s
Checks / Prek / Pre-commit & Formatting (pull_request) Successful in 1m33s
Checks / Changelog / Check changelog is added (pull_request_target) Successful in 31s
Checks / Prek / Clippy and Cargo Tests (pull_request) Successful in 8m51s
Checks / Prek / Check changed files (push) Successful in 6s
Checks / Prek / Pre-commit & Formatting (push) Successful in 1m34s
Documentation / Build and Deploy Documentation (pull_request) Successful in 10m53s
Release Docker Image / Build linux-amd64 (release) (push) Failing after 4m36s
Documentation / Build and Deploy Documentation (push) Successful in 10m48s
Release Docker Image / Build linux-arm64 (release) (push) Successful in 11m53s
Release Docker Image / Create Multi-arch Release Manifest (push) Has been skipped
Release Docker Image / Build linux-amd64 (max-perf) (push) Has been skipped
Release Docker Image / Build linux-arm64 (max-perf) (push) Has been skipped
Release Docker Image / Create Max-Perf Manifest (push) Has been skipped
Release Docker Image / Mirror Images (push) Has been skipped
Release Docker Image / Release Binaries (push) Has been skipped
Checks / Prek / Clippy and Cargo Tests (push) Failing after 32m13s
c1a6e649da
ginger approved these changes 2026-05-25 17:05:02 +00:00
nex scheduled this pull request to auto merge when all checks succeed 2026-05-25 17:06:29 +00:00
nex merged commit c1a6e649da into main 2026-05-25 17:10:17 +00:00
nex deleted branch nex/feat/rejected-events 2026-05-25 17:10:17 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
continuwuation/continuwuity!1747
No description provided.