diff --git a/packages/overlays/matrix-synapse/patches/0007-Expose-tombstone-in-room-admin-api.patch b/packages/overlays/matrix-synapse/patches/0007-Expose-tombstone-in-room-admin-api.patch
new file mode 100644
index 0000000..719705e
--- /dev/null
+++ b/packages/overlays/matrix-synapse/patches/0007-Expose-tombstone-in-room-admin-api.patch
@@ -0,0 +1,114 @@
+From d3edb4aa9a225f521fdbc406c187fd40343b3963 Mon Sep 17 00:00:00 2001
+From: Rory& <root@rory.gay>
+Date: Tue, 27 May 2025 06:37:52 +0200
+Subject: [PATCH 07/11] Expose tombstone in room admin api
+
+---
+ synapse/rest/admin/rooms.py | 5 ++++
+ synapse/rest/client/room.py | 1 -
+ synapse/storage/databases/main/room.py | 36 +++++++++++++++++++++++++-
+ 3 files changed, 40 insertions(+), 2 deletions(-)
+
+diff --git a/synapse/rest/admin/rooms.py b/synapse/rest/admin/rooms.py
+index f8c5bf18d4..adac1f0362 100644
+--- a/synapse/rest/admin/rooms.py
++++ b/synapse/rest/admin/rooms.py
+@@ -251,6 +251,10 @@ class ListRoomRestServlet(RestServlet):
+ direction = parse_enum(request, "dir", Direction, default=Direction.FORWARDS)
+ reverse_order = True if direction == Direction.BACKWARDS else False
+
++ emma_include_tombstone = parse_boolean(
++ request, "emma_include_tombstone", default=False
++ )
++
+ # Return list of rooms according to parameters
+ rooms, total_rooms = await self.store.get_rooms_paginate(
+ start,
+@@ -260,6 +264,7 @@ class ListRoomRestServlet(RestServlet):
+ search_term,
+ public_rooms,
+ empty_rooms,
++ emma_include_tombstone = emma_include_tombstone
+ )
+
+ response = {
+diff --git a/synapse/rest/client/room.py b/synapse/rest/client/room.py
+index e838341fde..f61152c35b 100644
+--- a/synapse/rest/client/room.py
++++ b/synapse/rest/client/room.py
+@@ -919,7 +919,6 @@ class RoomEventServlet(RestServlet):
+ request,
+ "fi.mau.msc2815.include_unredacted_content"
+ )
+- == "true"
+ )
+ if include_unredacted_content and not await self.auth.is_server_admin(
+ requester
+diff --git a/synapse/storage/databases/main/room.py b/synapse/storage/databases/main/room.py
+index 58451d3ff1..66b79db4ed 100644
+--- a/synapse/storage/databases/main/room.py
++++ b/synapse/storage/databases/main/room.py
+@@ -610,6 +610,7 @@ class RoomWorkerStore(CacheInvalidationWorkerStore):
+ search_term: Optional[str],
+ public_rooms: Optional[bool],
+ empty_rooms: Optional[bool],
++ emma_include_tombstone: bool = False,
+ ) -> Tuple[List[Dict[str, Any]], int]:
+ """Function to retrieve a paginated list of rooms as json.
+
+@@ -629,6 +630,7 @@ class RoomWorkerStore(CacheInvalidationWorkerStore):
+ If true, empty rooms are queried.
+ if false, empty rooms are excluded from the query. When it is
+ none (the default), both empty rooms and none-empty rooms are queried.
++ emma_include_tombstone: If true, include tombstone events in the results.
+ Returns:
+ A list of room dicts and an integer representing the total number of
+ rooms that exist given this query
+@@ -797,11 +799,43 @@ class RoomWorkerStore(CacheInvalidationWorkerStore):
+ room_count = cast(Tuple[int], txn.fetchone())
+ return rooms, room_count[0]
+
+- return await self.db_pool.runInteraction(
++ result = await self.db_pool.runInteraction(
+ "get_rooms_paginate",
+ _get_rooms_paginate_txn,
+ )
+
++ if emma_include_tombstone:
++ room_id_sql, room_id_args = make_in_list_sql_clause(
++ self.database_engine, "cse.room_id", [r["room_id"] for r in result[0]]
++ )
++
++ tombstone_sql = """
++ SELECT cse.room_id, cse.event_id, ej.json
++ FROM current_state_events cse
++ JOIN event_json ej USING (event_id)
++ WHERE cse.type = 'm.room.tombstone'
++ AND {room_id_sql}
++ """.format(
++ room_id_sql=room_id_sql
++ )
++
++ def _get_tombstones_txn(
++ txn: LoggingTransaction,
++ ) -> Dict[str, JsonDict]:
++ txn.execute(tombstone_sql, room_id_args)
++ for room_id, event_id, json in txn:
++ for result_room in result[0]:
++ if result_room["room_id"] == room_id:
++ result_room["gay.rory.synapse_admin_extensions.tombstone"] = db_to_json(json)
++ break
++ return result[0], result[1]
++
++ result = await self.db_pool.runInteraction(
++ "get_rooms_tombstones", _get_tombstones_txn,
++ )
++
++ return result
++
+ @cached(max_entries=10000)
+ async def get_ratelimit_for_user(self, user_id: str) -> Optional[RatelimitOverride]:
+ """Check if there are any overrides for ratelimiting for the given user
+--
+2.49.0
+
|