Skip to content

Try to modify MSC4311 test to meet new proposal#796

Draft
turt2live wants to merge 13 commits intomainfrom
travis/msc4311-v2
Draft

Try to modify MSC4311 test to meet new proposal#796
turt2live wants to merge 13 commits intomainfrom
travis/msc4311-v2

Conversation

@turt2live
Copy link
Copy Markdown
Member

@turt2live turt2live commented Aug 15, 2025

"I have no idea what I'm doing" disclaimer goes here

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

Comment thread tests/v12_test.go
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 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
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
Comment on lines +1426 to +1431
// JSONArraySome returns a matcher which will check that `wantKey` is an array then
// loops over each item calling `fn`. If `fn` returns nil, the matcher is satisifed,
// iterating stops and we return.
//
// Will fail if the array is empty and the check never runs
func JSONArraySome(wantKey string, fn func(gjson.Result) error) match.JSON {
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.

Opinions on whether this is suitable to add to match/json.go. Seems general and good enough to me.

Comment thread tests/v12_test.go
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
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