Add Matrix QA coverage for MXID-prefixed commands

Add a qa-matrix contract scenario that sends a Matrix self MXID-prefixed
control command from an observer and expects no SUT reply. This captures the
regression fixed by the Matrix command precheck change.
This commit is contained in:
Gustavo Madeira Santana
2026-04-19 16:46:49 -04:00
parent 8fbf0972e7
commit efc19f0ddb
3 changed files with 67 additions and 0 deletions

View File

@@ -44,6 +44,7 @@ export type MatrixQaScenarioId =
| "matrix-room-membership-loss"
| "matrix-homeserver-restart-resume"
| "matrix-mention-gating"
| "matrix-mxid-prefixed-command-block"
| "matrix-mention-metadata-spoof-block"
| "matrix-observer-allowlist-override"
| "matrix-allowlist-block"
@@ -449,6 +450,14 @@ export const MATRIX_QA_SCENARIOS: MatrixQaScenarioDefinition[] = [
timeoutMs: 8_000,
title: "Matrix room message without mention does not trigger",
},
{
id: "matrix-mxid-prefixed-command-block",
timeoutMs: 8_000,
title: "Matrix MXID-prefixed control commands stay gated",
configOverrides: {
groupPolicy: "open",
},
},
{
id: "matrix-mention-metadata-spoof-block",
timeoutMs: 8_000,

View File

@@ -247,6 +247,18 @@ export async function runMatrixQaScenario(
token,
});
}
case "matrix-mxid-prefixed-command-block": {
const token = buildMatrixQaToken("MATRIX_QA_MXID_COMMAND");
return await runNoReplyScenario({
accessToken: context.observerAccessToken,
actorId: "observer",
actorUserId: context.observerUserId,
body: `${context.sutUserId} /new`,
mentionUserIds: [context.sutUserId],
context,
token,
});
}
case "matrix-mention-metadata-spoof-block": {
const token = buildMatrixQaToken("MATRIX_QA_METADATA_SPOOF");
return await runNoReplyScenario({

View File

@@ -106,6 +106,7 @@ describe("matrix live qa scenarios", () => {
"matrix-room-membership-loss",
"matrix-homeserver-restart-resume",
"matrix-mention-gating",
"matrix-mxid-prefixed-command-block",
"matrix-mention-metadata-spoof-block",
"matrix-observer-allowlist-override",
"matrix-allowlist-block",
@@ -516,6 +517,51 @@ describe("matrix live qa scenarios", () => {
});
});
it("blocks MXID-prefixed Matrix control commands from non-allowlisted observers", async () => {
const primeRoom = vi.fn().mockResolvedValue("observer-sync-start");
const sendTextMessage = vi.fn().mockResolvedValue("$observer-command-trigger");
const waitForOptionalRoomEvent = vi.fn().mockImplementation(async (params) => {
expect(params.since).toBe("observer-sync-start");
return {
matched: false,
since: "observer-sync-next",
};
});
createMatrixQaClient.mockReturnValue({
primeRoom,
sendTextMessage,
waitForOptionalRoomEvent,
});
const scenario = MATRIX_QA_SCENARIOS.find(
(entry) => entry.id === "matrix-mxid-prefixed-command-block",
);
expect(scenario).toBeDefined();
await expect(runMatrixQaScenario(scenario!, matrixQaScenarioContext())).resolves.toMatchObject({
artifacts: {
actorUserId: "@observer:matrix-qa.test",
driverEventId: "$observer-command-trigger",
},
});
expect(createMatrixQaClient).toHaveBeenCalledWith({
accessToken: "observer-token",
baseUrl: "http://127.0.0.1:28008/",
});
expect(sendTextMessage).toHaveBeenCalledWith({
body: "@sut:matrix-qa.test /new",
mentionUserIds: ["@sut:matrix-qa.test"],
roomId: "!main:matrix-qa.test",
});
expect(waitForOptionalRoomEvent).toHaveBeenCalledWith(
expect.objectContaining({
roomId: "!main:matrix-qa.test",
}),
);
});
it("queues a Matrix trigger during restart before proving incremental sync continues", async () => {
const callOrder: string[] = [];
const primeRoom = vi.fn().mockResolvedValue("driver-sync-start");