mirror of https://github.com/openclaw/openclaw.git
fix(matrix): harden health probe storage metadata
This commit is contained in:
parent
92e802da93
commit
8a7eb2329a
|
|
@ -67,7 +67,7 @@ describe("matrix account path propagation", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("forwards accountId to matrix probes", async () => {
|
||||
it("forwards accountId and deviceId to matrix probes", async () => {
|
||||
await matrixPlugin.status!.probeAccount?.({
|
||||
cfg: {} as never,
|
||||
timeoutMs: 500,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const ensureMatrixSdkLoggingConfiguredMock = vi.hoisted(() => vi.fn());
|
||||
const resolveValidatedMatrixHomeserverUrlMock = vi.hoisted(() => vi.fn());
|
||||
const maybeMigrateLegacyStorageMock = vi.hoisted(() => vi.fn(async () => undefined));
|
||||
const resolveMatrixStoragePathsMock = vi.hoisted(() => vi.fn());
|
||||
const writeStorageMetaMock = vi.hoisted(() => vi.fn());
|
||||
const MatrixClientMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock("./logging.js", () => ({
|
||||
ensureMatrixSdkLoggingConfigured: ensureMatrixSdkLoggingConfiguredMock,
|
||||
}));
|
||||
|
||||
vi.mock("./config.js", () => ({
|
||||
resolveValidatedMatrixHomeserverUrl: resolveValidatedMatrixHomeserverUrlMock,
|
||||
}));
|
||||
|
||||
vi.mock("./storage.js", () => ({
|
||||
maybeMigrateLegacyStorage: maybeMigrateLegacyStorageMock,
|
||||
resolveMatrixStoragePaths: resolveMatrixStoragePathsMock,
|
||||
writeStorageMeta: writeStorageMetaMock,
|
||||
}));
|
||||
|
||||
vi.mock("../sdk.js", () => ({
|
||||
MatrixClient: MatrixClientMock,
|
||||
}));
|
||||
|
||||
let createMatrixClient: typeof import("./create-client.js").createMatrixClient;
|
||||
|
||||
describe("createMatrixClient", () => {
|
||||
const storagePaths = {
|
||||
rootDir: "/tmp/openclaw-matrix-create-client-test",
|
||||
storagePath: "/tmp/openclaw-matrix-create-client-test/storage.json",
|
||||
recoveryKeyPath: "/tmp/openclaw-matrix-create-client-test/recovery.key",
|
||||
idbSnapshotPath: "/tmp/openclaw-matrix-create-client-test/idb.snapshot",
|
||||
metaPath: "/tmp/openclaw-matrix-create-client-test/storage-meta.json",
|
||||
accountKey: "default",
|
||||
tokenHash: "token-hash",
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
({ createMatrixClient } = await import("./create-client.js"));
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
ensureMatrixSdkLoggingConfiguredMock.mockReturnValue(undefined);
|
||||
resolveValidatedMatrixHomeserverUrlMock.mockResolvedValue("https://matrix.example.org");
|
||||
resolveMatrixStoragePathsMock.mockReturnValue(storagePaths);
|
||||
MatrixClientMock.mockImplementation(function MockMatrixClient() {
|
||||
return {
|
||||
stop: vi.fn(),
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
it("persists storage metadata by default", async () => {
|
||||
await createMatrixClient({
|
||||
homeserver: "https://matrix.example.org",
|
||||
userId: "@bot:example.org",
|
||||
accessToken: "tok",
|
||||
});
|
||||
|
||||
expect(writeStorageMetaMock).toHaveBeenCalledWith({
|
||||
storagePaths,
|
||||
homeserver: "https://matrix.example.org",
|
||||
userId: "@bot:example.org",
|
||||
accountId: undefined,
|
||||
deviceId: undefined,
|
||||
});
|
||||
expect(MatrixClientMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("skips storage metadata writes when persistence is disabled", async () => {
|
||||
await createMatrixClient({
|
||||
homeserver: "https://matrix.example.org",
|
||||
userId: "@bot:example.org",
|
||||
accessToken: "tok",
|
||||
persistStorageMeta: false,
|
||||
});
|
||||
|
||||
expect(writeStorageMetaMock).not.toHaveBeenCalled();
|
||||
expect(MatrixClientMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
|
@ -33,6 +33,7 @@ export async function createMatrixClient(params: {
|
|||
accessToken: string;
|
||||
password?: string;
|
||||
deviceId?: string;
|
||||
persistStorageMeta?: boolean;
|
||||
encryption?: boolean;
|
||||
localTimeoutMs?: number;
|
||||
initialSyncLimit?: number;
|
||||
|
|
@ -66,13 +67,16 @@ export async function createMatrixClient(params: {
|
|||
});
|
||||
fs.mkdirSync(storagePaths.rootDir, { recursive: true });
|
||||
|
||||
writeStorageMeta({
|
||||
storagePaths,
|
||||
homeserver,
|
||||
userId,
|
||||
accountId: params.accountId,
|
||||
deviceId: params.deviceId,
|
||||
});
|
||||
// Health probes still need validated paths, but they must not rewrite durable identity metadata.
|
||||
if (params.persistStorageMeta !== false) {
|
||||
writeStorageMeta({
|
||||
storagePaths,
|
||||
homeserver,
|
||||
userId,
|
||||
accountId: params.accountId,
|
||||
deviceId: params.deviceId,
|
||||
});
|
||||
}
|
||||
|
||||
const cryptoDatabasePrefix = `openclaw-matrix-${storagePaths.accountKey}-${storagePaths.tokenHash}`;
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ describe("probeMatrix", () => {
|
|||
homeserver: "https://matrix.example.org",
|
||||
userId: undefined,
|
||||
accessToken: "tok",
|
||||
persistStorageMeta: false,
|
||||
localTimeoutMs: 1234,
|
||||
});
|
||||
});
|
||||
|
|
@ -50,6 +51,7 @@ describe("probeMatrix", () => {
|
|||
homeserver: "https://matrix.example.org",
|
||||
userId: "@bot:example.org",
|
||||
accessToken: "tok",
|
||||
persistStorageMeta: false,
|
||||
localTimeoutMs: 500,
|
||||
});
|
||||
});
|
||||
|
|
@ -67,6 +69,7 @@ describe("probeMatrix", () => {
|
|||
homeserver: "https://matrix.example.org",
|
||||
userId: "@bot:example.org",
|
||||
accessToken: "tok",
|
||||
persistStorageMeta: false,
|
||||
localTimeoutMs: 500,
|
||||
accountId: "ops",
|
||||
});
|
||||
|
|
@ -87,6 +90,7 @@ describe("probeMatrix", () => {
|
|||
homeserver: "https://matrix.example.org",
|
||||
userId: undefined,
|
||||
accessToken: "tok",
|
||||
persistStorageMeta: false,
|
||||
localTimeoutMs: 500,
|
||||
dispatcherPolicy: {
|
||||
mode: "explicit-proxy",
|
||||
|
|
@ -105,11 +109,15 @@ describe("probeMatrix", () => {
|
|||
accountId: "ops",
|
||||
});
|
||||
|
||||
expect(createMatrixClientMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
deviceId: "ABCDEF",
|
||||
}),
|
||||
);
|
||||
expect(createMatrixClientMock).toHaveBeenCalledWith({
|
||||
homeserver: "https://matrix.example.org",
|
||||
userId: "@bot:example.org",
|
||||
accessToken: "tok",
|
||||
deviceId: "ABCDEF",
|
||||
persistStorageMeta: false,
|
||||
localTimeoutMs: 500,
|
||||
accountId: "ops",
|
||||
});
|
||||
});
|
||||
|
||||
it("omits deviceId when not provided", async () => {
|
||||
|
|
@ -119,11 +127,14 @@ describe("probeMatrix", () => {
|
|||
timeoutMs: 500,
|
||||
});
|
||||
|
||||
expect(createMatrixClientMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
deviceId: undefined,
|
||||
}),
|
||||
);
|
||||
expect(createMatrixClientMock).toHaveBeenCalledWith({
|
||||
homeserver: "https://matrix.example.org",
|
||||
userId: undefined,
|
||||
accessToken: "tok",
|
||||
deviceId: undefined,
|
||||
persistStorageMeta: false,
|
||||
localTimeoutMs: 500,
|
||||
});
|
||||
});
|
||||
|
||||
it("returns client validation errors for insecure public http homeservers", async () => {
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ export async function probeMatrix(params: {
|
|||
userId: inputUserId,
|
||||
accessToken: params.accessToken,
|
||||
deviceId: params.deviceId,
|
||||
persistStorageMeta: false,
|
||||
localTimeoutMs: params.timeoutMs,
|
||||
accountId: params.accountId,
|
||||
allowPrivateNetwork: params.allowPrivateNetwork,
|
||||
|
|
|
|||
Loading…
Reference in New Issue