Skip to content

Commit 99159f8

Browse files
committed
fix(matrix): stabilize e2ee qa flows
1 parent 02d266c commit 99159f8

39 files changed

Lines changed: 6355 additions & 931 deletions

docs/channels/matrix.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ Key wizard behaviors:
6868
- Room allowlist entries accept room IDs and aliases directly. Prefer `!room:server` or `#alias:server`; unresolved names are ignored at runtime by allowlist resolution.
6969
- In invite auto-join allowlist mode, use only stable invite targets: `!roomId:server`, `#alias:server`, or `*`. Plain room names are rejected.
7070
- To resolve room names before saving, use `openclaw channels resolve --channel matrix "Project Room"`.
71+
- When setup enables E2EE, OpenClaw writes the encryption config and runs the
72+
same verification bootstrap used by `openclaw matrix encryption setup`.
7173

7274
<Warning>
7375
`channels.matrix.autoJoin` defaults to `off`.
@@ -292,7 +294,32 @@ Use strict room allowlists and mention requirements when enabling bot-to-bot tra
292294

293295
In encrypted (E2EE) rooms, outbound image events use `thumbnail_file` so image previews are encrypted alongside the full attachment. Unencrypted rooms still use plain `thumbnail_url`. No configuration is needed — the plugin detects E2EE state automatically.
294296

295-
Enable encryption:
297+
Recommended setup flow:
298+
299+
```bash
300+
openclaw matrix encryption setup
301+
```
302+
303+
This enables `channels.matrix.encryption`, bootstraps Matrix secret storage and
304+
cross-signing, creates room-key backup state when needed, then prints the
305+
current verification and backup status with next steps.
306+
307+
For a new account, enable E2EE during account creation:
308+
309+
```bash
310+
openclaw matrix account add \
311+
--homeserver https://matrix.example.org \
312+
--access-token syt_xxx \
313+
--enable-e2ee
314+
```
315+
316+
Multi-account setups can target a specific account:
317+
318+
```bash
319+
openclaw matrix encryption setup --account assistant
320+
```
321+
322+
Manual config equivalent:
296323

297324
```json5
298325
{

extensions/matrix/index.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ describe("matrix plugin", () => {
116116

117117
registerMatrixFullRuntime(api);
118118

119+
expect(runtimeMocks.ensureMatrixCryptoRuntime).not.toHaveBeenCalled();
119120
expect(on.mock.calls.map(([hookName]) => hookName)).toEqual([
120121
"subagent_spawning",
121122
"subagent_ended",

extensions/matrix/index.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import {
22
defineBundledChannelEntry,
33
type OpenClawPluginApi,
44
} from "openclaw/plugin-sdk/channel-entry-contract";
5-
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
65
import { registerMatrixCliMetadata } from "./cli-metadata.js";
76
import { registerMatrixSubagentHooks } from "./subagent-hooks-api.js";
87

@@ -16,18 +15,6 @@ function loadMatrixHandlersRuntimeModule() {
1615
}
1716

1817
export function registerMatrixFullRuntime(api: OpenClawPluginApi): void {
19-
void loadMatrixHandlersRuntimeModule()
20-
.then(({ ensureMatrixCryptoRuntime }) =>
21-
ensureMatrixCryptoRuntime({ log: api.logger.info }).catch((err: unknown) => {
22-
const message = formatErrorMessage(err);
23-
api.logger.warn?.(`matrix: crypto runtime bootstrap failed: ${message}`);
24-
}),
25-
)
26-
.catch((err: unknown) => {
27-
const message = formatErrorMessage(err);
28-
api.logger.warn?.(`matrix: failed loading crypto bootstrap runtime: ${message}`);
29-
});
30-
3118
api.registerGatewayMethod("matrix.verify.recoveryKey", async (ctx) => {
3219
const { handleVerifyRecoveryKey } = await loadMatrixHandlersRuntimeModule();
3320
await handleVerifyRecoveryKey(ctx);

extensions/matrix/src/channel.setup.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ describe("matrix setup post-write bootstrap", () => {
138138

139139
expect(verificationMocks.bootstrapMatrixVerification).toHaveBeenCalledWith({
140140
accountId: "default",
141+
cfg: nextCfg,
141142
});
142143
expect(log).toHaveBeenCalledWith('Matrix verification bootstrap: complete for "default".');
143144
expect(log).toHaveBeenCalledWith('Matrix backup version for "default": 7');
@@ -177,6 +178,44 @@ describe("matrix setup post-write bootstrap", () => {
177178
expect(error).not.toHaveBeenCalled();
178179
});
179180

181+
it("bootstraps verification when setup enables encryption for an existing account", async () => {
182+
const previousCfg = {
183+
channels: {
184+
matrix: {
185+
homeserver: "https://matrix.example.org",
186+
userId: "@flurry:example.org",
187+
accessToken: "token",
188+
encryption: false,
189+
},
190+
},
191+
} as CoreConfig;
192+
const nextCfg = {
193+
channels: {
194+
matrix: {
195+
homeserver: "https://matrix.example.org",
196+
userId: "@flurry:example.org",
197+
accessToken: "token",
198+
encryption: true,
199+
},
200+
},
201+
} as CoreConfig;
202+
mockBootstrapResult({ success: true, backupVersion: "8" });
203+
204+
await runAfterAccountConfigWritten({
205+
previousCfg,
206+
nextCfg,
207+
accountId: "default",
208+
input: {},
209+
});
210+
211+
expect(verificationMocks.bootstrapMatrixVerification).toHaveBeenCalledWith({
212+
accountId: "default",
213+
cfg: nextCfg,
214+
});
215+
expect(log).toHaveBeenCalledWith('Matrix verification bootstrap: complete for "default".');
216+
expect(log).toHaveBeenCalledWith('Matrix backup version for "default": 8');
217+
});
218+
180219
it("logs a warning when verification bootstrap fails", async () => {
181220
const { previousCfg, nextCfg, accountId, input } = applyDefaultAccountConfig();
182221
mockBootstrapResult({
@@ -207,6 +246,7 @@ describe("matrix setup post-write bootstrap", () => {
207246

208247
expect(verificationMocks.bootstrapMatrixVerification).toHaveBeenCalledWith({
209248
accountId: "default",
249+
cfg: nextCfg,
210250
});
211251
expect(log).toHaveBeenCalledWith('Matrix verification bootstrap: complete for "default".');
212252
},

0 commit comments

Comments
 (0)