Skip to content

Try to modify MSC4311 test to meet new proposal#796

Draft
turt2live wants to merge 20 commits into
mainfrom
travis/msc4311-v2
Draft

Try to modify MSC4311 test to meet new proposal#796
turt2live wants to merge 20 commits into
mainfrom
travis/msc4311-v2

Conversation

@turt2live
Copy link
Copy Markdown
Member

@turt2live turt2live commented Aug 15, 2025

Update MSC4311 tests to conform to the spec.

"I have no idea what I'm doing" disclaimer goes here taken over by @MadLittleMods

For element-hq/synapse#18822 element-hq/synapse#19723

Dev notes

COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh -run TestMSC4311StrippedStateClientAPI

COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh -run TestMSC4311FullEventsOnStrippedStateFederation

Comment thread tests/v12_test.go Outdated
must.MatchGJSON(t, ev,
match.JSONKeyPresent("origin_server_ts"),
)
srv.Mux().HandleFunc("/_matrix/federation/v2/invite/{roomID}/{eventID}", srv.ValidFederationRequest(t, func(fr *fclient.FederationRequest, pathParams map[string]string) util.JSONResponse {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to alternatively use:

	srv := federation.NewServer(t, deployment,
		federation.HandleInviteRequests(func(p gomatrixserverlib.PDU) {
			// checks here
		}),
		federation.HandleKeyRequests(),
		federation.HandleMakeSendJoinRequests(),
		federation.HandleTransactionRequests(nil, nil),
	)

Copy link
Copy Markdown
Collaborator

@MadLittleMods MadLittleMods May 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went down this route but the problem is that federation.HandleInviteRequests(...) doesn't allow you to inspect the invite_room_state yet. It would have to be updated to pass in the full invite request to the callback.

And gomatrixserverlib needs to be updated to handle the new world where invite_room_state can be stripped state or full PDUs.

We could have an infallible InviteV2Request.StrippedInviteRoomState() that would give a view of stripped state regardless of whether we were passed stripped or full PDU's (we can derive stripped state from the full PDU's). And then a fallible InviteV2Request.FullInviteRoomState() that would return an error if the homeserver didn't pass us full PDUs.

We would also need to update IRoomVersion to add new fields like CreateEventRequiredInInviteRoomState and FullPDUInviteRoomState (full PDU's can happen in any room version) so we can conditionally apply this behavior. Or maybe the flags could be combined as MSC4311InviteRoomState

If any of the events are not a PDU, not for the room ID specified, or fail signature checks, or the m.room.create event is missing, the receiving server MAY respond to invites with a 400 M_MISSING_PARAM standard Matrix error (new to the endpoint). For invites to room version 12+ rooms, servers SHOULD rather than MAY respond to such requests with 400 M_MISSING_PARAM.

-- matrix-org/matrix-spec-proposals#4311

Comment thread tests/v12_test.go Outdated
Comment on lines +1389 to +1393
match.JSONArrayEach("invite_room_state", func(event gjson.Result) error {
// Each event should have extra fields `origin_server_ts` that indicate we're
// seeing a full PDU and not just a "stripped state event"
return should.MatchGJSON(event, match.JSONKeyPresent("origin_server_ts"))
}),
Copy link
Copy Markdown
Collaborator

@MadLittleMods MadLittleMods May 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This currently fails in Synapse because it just pulls invite_room_state from the the unsigned part of the PDU which will be the stripped state client version, see synapse/federation/federation_client.py#L1361

Example flawed /_matrix/federation/v2/invite/{roomID}/{eventID} request body from Synapse
{
  "event": {
    "auth_events": [
      "$3-FVPb1HO_ZyxolbnthZ8qTVEMXyZ6px4qUdrL0exII",
      "$hRMnmEtlMElF2pqbd23ccVSfAIUq-Dqo9kxORAbs2Pk",
      "$luBrxrHgZcSqpdm5UMAXtGKxCvmOwGAHJrZ0iMeWrdw"
    ],
    "content": {
      "membership": "invite"
    },
    "depth": 6,
    "hashes": {
      "sha256": "xBOaaPtS1jAtu/qsWiBIXFZqDdOm6zI8R+RVgXfhm00"
    },
    "origin_server_ts": 1777676386564,
    "prev_events": [
      "$VoTAQZqsV4zWnRi3Uh9n42ioJ4J74UvwMoZuHNiHWU4"
    ],
    "room_id": "!gvlLh8tsK9LSCdF8y56dVfErfUiw7lZnLQ8JTB_kih4",
    "sender": "@user-1-alice:hs1",
    "signatures": {
      "hs1": {
        "ed25519:a_NKNg": "xS/15iTHLn3I65oaTdVRMFBrs+ASbKp9Lm9GM8oLoKlD3ZUwtuBP2pyN/tdUXgraKnRNDU1b3PLxpXYzsLGkCQ"
      }
    },
    "state_key": "@bob:host.docker.internal:44453",
    "type": "m.room.member",
    "unsigned": {
      "age": 11,
      "invite_room_state": [
        {
          "auth_events": [],
          "content": {
            "room_version": "12"
          },
          "depth": 1,
          "hashes": {
            "sha256": "vVkUaUxHUum571Kj4D0vo85iS2dssrPpILSm3XnELpc"
          },
          "origin_server_ts": 1777676385521,
          "prev_events": [],
          "sender": "@user-1-alice:hs1",
          "signatures": {
            "hs1": {
              "ed25519:a_NKNg": "m7pf3WIpaGZEgTR85+L+ewSY88eBXJSGecOXXJmLudEFq4mGxR4MBw6/x9+xMTz4byo+z0a+0h4IcvvSyYhiAA"
            }
          },
          "state_key": "",
          "type": "m.room.create",
          "unsigned": {
            "age_ts": 1777676385521
          }
        },
        {
          "content": {
            "join_rule": "public"
          },
          "sender": "@user-1-alice:hs1",
          "state_key": "",
          "type": "m.room.join_rules"
        },
        {
          "content": {
            "displayname": "user-1-alice",
            "membership": "join"
          },
          "sender": "@user-1-alice:hs1",
          "state_key": "@user-1-alice:hs1",
          "type": "m.room.member"
        }
      ]
    }
  },
  "invite_room_state": [
    {
      "auth_events": [],
      "content": {
        "room_version": "12"
      },
      "depth": 1,
      "hashes": {
        "sha256": "vVkUaUxHUum571Kj4D0vo85iS2dssrPpILSm3XnELpc"
      },
      "origin_server_ts": 1777676385521,
      "prev_events": [],
      "sender": "@user-1-alice:hs1",
      "signatures": {
        "hs1": {
          "ed25519:a_NKNg": "m7pf3WIpaGZEgTR85+L+ewSY88eBXJSGecOXXJmLudEFq4mGxR4MBw6/x9+xMTz4byo+z0a+0h4IcvvSyYhiAA"
        }
      },
      "state_key": "",
      "type": "m.room.create",
      "unsigned": {
        "age_ts": 1777676385521
      }
    },
    {
      "content": {
        "join_rule": "public"
      },
      "sender": "@user-1-alice:hs1",
      "state_key": "",
      "type": "m.room.join_rules"
    },
    {
      "content": {
        "displayname": "user-1-alice",
        "membership": "join"
      },
      "sender": "@user-1-alice:hs1",
      "state_key": "@user-1-alice:hs1",
      "type": "m.room.member"
    }
  ],
  "room_version": "12"
}

Copy link
Copy Markdown
Collaborator

@MadLittleMods MadLittleMods May 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test passes with Synapse with the changes from element-hq/synapse#19723

COMPLEMENT_DIR=../complement ./scripts-dev/complement.sh -run TestMSC4311FullEventsOnStrippedStateFederation

Comment thread tests/v12_test.go Outdated
Comment thread tests/v12_test.go Outdated
Comment on lines +1402 to +1404
var roomVersion gomatrixserverlib.RoomVersion
if err := json.Unmarshal([]byte(rawRoomVersion), &roomVersion); err != nil {
t.Fatalf("failed to parse room version: %s", err)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better way to get a gomatrixserverlib.RoomVersion from a room version string?

Comment thread tests/v12_test.go
Comment thread tests/v12_test.go
Comment on lines +1646 to +1650
// TODO: Test events not full PDU's

// TODO: Test events not from the same room

// TODO: Test invalid signatures/hashes
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something for future PRs

Comment thread tests/v12_test.go
// > error (new to the endpoint). For invites to room version 12+ rooms, servers
// > SHOULD rather than MAY respond to such requests with `400 M_MISSING_PARAM`.
func TestMSC4311RejectInvalidStrippedStateFederation(t *testing.T) {
runtime.SkipIf(t, runtime.Synapse) // FIXME: Run these tests after 2027-06-01
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also cross-linked this in the Synapse codebase (see element-hq/synapse#19723)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants