mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:50:42 +00:00
fix(matrix): accept recovery keys from stdin
This commit is contained in:
@@ -93,16 +93,20 @@ If your old installation had local-only encrypted history that was never backed
|
||||
openclaw matrix verify backup status
|
||||
```
|
||||
|
||||
5. If OpenClaw tells you a recovery key is needed, run:
|
||||
5. Put the recovery key for the Matrix account you are repairing in an account-specific environment variable. For a single default account, `MATRIX_RECOVERY_KEY` is fine. For multiple accounts, use one variable per account, for example `MATRIX_RECOVERY_KEY_ASSISTANT`, and add `--account assistant` to the command.
|
||||
|
||||
6. If OpenClaw tells you a recovery key is needed, run the command for the matching account:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify backup restore --recovery-key "<your-recovery-key>"
|
||||
printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify backup restore --recovery-key-stdin
|
||||
printf '%s\n' "$MATRIX_RECOVERY_KEY_ASSISTANT" | openclaw matrix verify backup restore --recovery-key-stdin --account assistant
|
||||
```
|
||||
|
||||
6. If this device is still unverified, run:
|
||||
7. If this device is still unverified, run the command for the matching account:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify device "<your-recovery-key>"
|
||||
printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify device --recovery-key-stdin
|
||||
printf '%s\n' "$MATRIX_RECOVERY_KEY_ASSISTANT" | openclaw matrix verify device --recovery-key-stdin --account assistant
|
||||
```
|
||||
|
||||
If the recovery key is accepted and backup is usable, but `Cross-signing verified`
|
||||
@@ -116,13 +120,13 @@ If your old installation had local-only encrypted history that was never backed
|
||||
and type `yes` only when they match. The command exits successfully only
|
||||
after `Cross-signing verified` becomes `yes`.
|
||||
|
||||
7. If you are intentionally abandoning unrecoverable old history and want a fresh backup baseline for future messages, run:
|
||||
8. If you are intentionally abandoning unrecoverable old history and want a fresh backup baseline for future messages, run:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify backup reset --yes
|
||||
```
|
||||
|
||||
8. If no server-side key backup exists yet, create one for future recoveries:
|
||||
9. If no server-side key backup exists yet, create one for future recoveries:
|
||||
|
||||
```bash
|
||||
openclaw matrix verify bootstrap
|
||||
@@ -242,15 +246,15 @@ If the old store reports room keys that were never backed up, OpenClaw warns ins
|
||||
- Meaning: some old room keys existed only in the old local store and had never been uploaded to Matrix backup.
|
||||
- What to do: expect some old encrypted history to remain unavailable unless you can recover those keys manually from another verified client.
|
||||
|
||||
`Legacy Matrix encrypted state for account "..." has backed-up room keys, but no local backup decryption key was found. Ask the operator to run "openclaw matrix verify backup restore --recovery-key <key>" after upgrade if they have the recovery key.`
|
||||
`Legacy Matrix encrypted state for account "..." has backed-up room keys, but no local backup decryption key was found. Ask the operator to run "openclaw matrix verify backup restore --recovery-key-stdin" after upgrade if they have the recovery key.`
|
||||
|
||||
- Meaning: backup exists, but OpenClaw could not recover the recovery key automatically.
|
||||
- What to do: run `openclaw matrix verify backup restore --recovery-key "<your-recovery-key>"`.
|
||||
- What to do: run `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify backup restore --recovery-key-stdin`.
|
||||
|
||||
`Failed inspecting legacy Matrix encrypted state for account "..." (...): ...`
|
||||
|
||||
- Meaning: OpenClaw found the old encrypted store, but it could not inspect it safely enough to prepare recovery.
|
||||
- What to do: rerun `openclaw doctor --fix`. If it repeats, keep the old state directory intact and recover using another verified Matrix client plus `openclaw matrix verify backup restore --recovery-key "<your-recovery-key>"`.
|
||||
- What to do: rerun `openclaw doctor --fix`. If it repeats, keep the old state directory intact and recover using another verified Matrix client plus `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify backup restore --recovery-key-stdin`.
|
||||
|
||||
`Legacy Matrix backup key was found for account "...", but .../recovery-key.json already contains a different recovery key. Leaving the existing file unchanged.`
|
||||
|
||||
@@ -265,39 +269,39 @@ If the old store reports room keys that were never backed up, OpenClaw warns ins
|
||||
`matrix: failed restoring room keys from legacy encrypted-state backup: ...`
|
||||
|
||||
- Meaning: the new plugin attempted restore but Matrix returned an error.
|
||||
- What to do: run `openclaw matrix verify backup status`, then retry with `openclaw matrix verify backup restore --recovery-key "<your-recovery-key>"` if needed.
|
||||
- What to do: run `openclaw matrix verify backup status`, then retry with `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify backup restore --recovery-key-stdin` if needed.
|
||||
|
||||
### Manual recovery messages
|
||||
|
||||
`Backup key is not loaded on this device. Run 'openclaw matrix verify backup restore' to load it and restore old room keys.`
|
||||
|
||||
- Meaning: OpenClaw knows you should have a backup key, but it is not active on this device.
|
||||
- What to do: run `openclaw matrix verify backup restore`, or pass `--recovery-key` if needed.
|
||||
- What to do: run `openclaw matrix verify backup restore`, or set `MATRIX_RECOVERY_KEY` and run `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify backup restore --recovery-key-stdin` if needed.
|
||||
|
||||
`Store a recovery key with 'openclaw matrix verify device <key>', then run 'openclaw matrix verify backup restore'.`
|
||||
`Store a recovery key with 'openclaw matrix verify device --recovery-key-stdin', then run 'openclaw matrix verify backup restore'.`
|
||||
|
||||
- Meaning: this device does not currently have the recovery key stored.
|
||||
- What to do: verify the device with your recovery key first, then restore the backup.
|
||||
- What to do: set `MATRIX_RECOVERY_KEY`, run `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify device --recovery-key-stdin`, then restore the backup.
|
||||
|
||||
`Backup key mismatch on this device. Re-run 'openclaw matrix verify device <key>' with the matching recovery key.`
|
||||
`Backup key mismatch on this device. Re-run 'openclaw matrix verify device --recovery-key-stdin' with the matching recovery key.`
|
||||
|
||||
- Meaning: the stored key does not match the active Matrix backup.
|
||||
- What to do: rerun `openclaw matrix verify device "<your-recovery-key>"` with the correct key.
|
||||
- What to do: set `MATRIX_RECOVERY_KEY` to the correct key and run `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify device --recovery-key-stdin`.
|
||||
|
||||
If you accept losing unrecoverable old encrypted history, you can instead reset the
|
||||
current backup baseline with `openclaw matrix verify backup reset --yes`. When the
|
||||
stored backup secret is broken, that reset may also recreate secret storage so the
|
||||
new backup key can load correctly after restart.
|
||||
|
||||
`Backup trust chain is not verified on this device. Re-run 'openclaw matrix verify device <key>'.`
|
||||
`Backup trust chain is not verified on this device. Re-run 'openclaw matrix verify device --recovery-key-stdin'.`
|
||||
|
||||
- Meaning: the backup exists, but this device does not trust the cross-signing chain strongly enough yet.
|
||||
- What to do: rerun `openclaw matrix verify device "<your-recovery-key>"`.
|
||||
- What to do: set `MATRIX_RECOVERY_KEY` and run `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify device --recovery-key-stdin`.
|
||||
|
||||
`Matrix recovery key is required`
|
||||
|
||||
- Meaning: you tried a recovery step without supplying a recovery key when one was required.
|
||||
- What to do: rerun the command with your recovery key.
|
||||
- What to do: rerun the command with `--recovery-key-stdin`, for example `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify device --recovery-key-stdin`.
|
||||
|
||||
`Invalid Matrix recovery key: ...`
|
||||
|
||||
@@ -313,7 +317,7 @@ new backup key can load correctly after restart.
|
||||
- What to do: run `openclaw matrix verify self`, accept the request in another
|
||||
Matrix client, compare the SAS, and type `yes` only when it matches. The
|
||||
command waits for full Matrix identity trust before reporting success. Use
|
||||
`openclaw matrix verify bootstrap --recovery-key "<your-recovery-key>" --force-reset-cross-signing`
|
||||
`printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify bootstrap --recovery-key-stdin --force-reset-cross-signing`
|
||||
only when you intentionally want to replace the current cross-signing identity.
|
||||
|
||||
`Matrix key backup is not active on this device after loading from secret storage.`
|
||||
@@ -321,10 +325,10 @@ new backup key can load correctly after restart.
|
||||
- Meaning: secret storage did not produce an active backup session on this device.
|
||||
- What to do: verify the device first, then recheck with `openclaw matrix verify backup status`.
|
||||
|
||||
`Matrix crypto backend cannot load backup keys from secret storage. Verify this device with 'openclaw matrix verify device <key>' first.`
|
||||
`Matrix crypto backend cannot load backup keys from secret storage. Verify this device with 'openclaw matrix verify device --recovery-key-stdin' first.`
|
||||
|
||||
- Meaning: this device cannot restore from secret storage until device verification is complete.
|
||||
- What to do: run `openclaw matrix verify device "<your-recovery-key>"` first.
|
||||
- What to do: run `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify device --recovery-key-stdin` first.
|
||||
|
||||
### Custom plugin install messages
|
||||
|
||||
@@ -340,7 +344,7 @@ Run these checks in order:
|
||||
```bash
|
||||
openclaw matrix verify status --verbose
|
||||
openclaw matrix verify backup status --verbose
|
||||
openclaw matrix verify backup restore --recovery-key "<your-recovery-key>" --verbose
|
||||
printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify backup restore --recovery-key-stdin --verbose
|
||||
```
|
||||
|
||||
If the backup restores successfully but some old rooms are still missing history, those missing keys were probably never backed up by the previous plugin.
|
||||
|
||||
@@ -34,6 +34,15 @@ const consoleLogMock = vi.fn();
|
||||
const consoleErrorMock = vi.fn();
|
||||
const stdoutWriteMock = vi.fn();
|
||||
|
||||
function mockRecoveryKeyStdin(value: string): void {
|
||||
vi.spyOn(process.stdin, Symbol.asyncIterator).mockReturnValue(
|
||||
(async function* (): AsyncGenerator<Buffer, undefined, unknown> {
|
||||
yield Buffer.from(value);
|
||||
return undefined;
|
||||
})(),
|
||||
);
|
||||
}
|
||||
|
||||
vi.mock("./matrix/actions/verification.js", () => ({
|
||||
acceptMatrixVerification: (...args: unknown[]) => acceptMatrixVerificationMock(...args),
|
||||
bootstrapMatrixVerification: (...args: unknown[]) => bootstrapMatrixVerificationMock(...args),
|
||||
@@ -291,7 +300,7 @@ describe("matrix CLI verification commands", () => {
|
||||
"- Recovery key can unlock the room-key backup, but full Matrix identity trust is still incomplete. Run openclaw matrix verify self, accept the request in another verified Matrix client, and confirm the SAS only if it matches.",
|
||||
);
|
||||
expect(consoleLogMock).toHaveBeenCalledWith(
|
||||
"- If you intend to replace the current cross-signing identity, run openclaw matrix verify bootstrap --recovery-key '<key>' --force-reset-cross-signing.",
|
||||
"- If you intend to replace the current cross-signing identity, run the shown printf pipeline with the Matrix recovery key env var for this account: printf '%s\\n' \"$MATRIX_RECOVERY_KEY\" | openclaw matrix verify bootstrap --recovery-key-stdin --force-reset-cross-signing.",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -748,6 +757,35 @@ describe("matrix CLI verification commands", () => {
|
||||
expect(process.exitCode).toBe(1);
|
||||
});
|
||||
|
||||
it("reads backup restore recovery key from stdin", async () => {
|
||||
restoreMatrixRoomKeyBackupMock.mockResolvedValue({
|
||||
success: true,
|
||||
backupVersion: "1",
|
||||
imported: 1,
|
||||
total: 1,
|
||||
loadedFromSecretStorage: false,
|
||||
backup: {
|
||||
serverVersion: "1",
|
||||
activeVersion: "1",
|
||||
trusted: true,
|
||||
matchesDecryptionKey: true,
|
||||
decryptionKeyCached: true,
|
||||
},
|
||||
});
|
||||
mockRecoveryKeyStdin("stdin-recovery-key\n");
|
||||
const program = buildProgram();
|
||||
|
||||
await program.parseAsync(["matrix", "verify", "backup", "restore", "--recovery-key-stdin"], {
|
||||
from: "user",
|
||||
});
|
||||
|
||||
expect(restoreMatrixRoomKeyBackupMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
recoveryKey: "stdin-recovery-key",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("sets non-zero exit code for backup reset failures in JSON mode", async () => {
|
||||
resetMatrixRoomKeyBackupMock.mockResolvedValue({
|
||||
success: false,
|
||||
@@ -1432,7 +1470,7 @@ describe("matrix CLI verification commands", () => {
|
||||
"Backup issue: backup decryption key is not loaded on this device (secret storage did not return a key)",
|
||||
);
|
||||
expect(console.log).toHaveBeenCalledWith(
|
||||
"- Backup key is not loaded on this device. Run openclaw matrix verify backup restore to load it and restore old room keys. If restore still cannot load the key, run openclaw matrix verify backup restore --recovery-key '<key>' with the Matrix recovery key.",
|
||||
"- Backup key is not loaded on this device. Run openclaw matrix verify backup restore to load it and restore old room keys. If restore still cannot load the key, run the shown printf pipeline with the Matrix recovery key env var for this account: printf '%s\\n' \"$MATRIX_RECOVERY_KEY\" | openclaw matrix verify backup restore --recovery-key-stdin.",
|
||||
);
|
||||
expect(console.log).not.toHaveBeenCalledWith(
|
||||
"- Backup is present but not trusted for this device. Re-run 'openclaw matrix verify device <key>'.",
|
||||
@@ -1632,7 +1670,7 @@ describe("matrix CLI verification commands", () => {
|
||||
});
|
||||
expect(console.log).toHaveBeenCalledWith("Account: assistant");
|
||||
expect(console.log).toHaveBeenCalledWith(
|
||||
"- Run openclaw matrix verify device '<key>' --account assistant with your Matrix recovery key. If you do not have the recovery key but still have another verified Matrix client, run openclaw matrix verify self --account assistant instead.",
|
||||
"- Run the shown printf pipeline with the Matrix recovery key env var for this account: printf '%s\\n' \"$MATRIX_RECOVERY_KEY_ASSISTANT\" | openclaw matrix verify device --recovery-key-stdin --account assistant. If you do not have the recovery key but still have another verified Matrix client, run openclaw matrix verify self --account assistant instead.",
|
||||
);
|
||||
expect(console.log).toHaveBeenCalledWith(
|
||||
"- Run openclaw matrix verify bootstrap --account assistant to create a room key backup.",
|
||||
|
||||
@@ -74,6 +74,44 @@ function markCliFailure(): void {
|
||||
process.exitCode = 1;
|
||||
}
|
||||
|
||||
async function readMatrixCliRecoveryKeyFromStdin(): Promise<string> {
|
||||
const chunks: Buffer[] = [];
|
||||
for await (const chunk of process.stdin) {
|
||||
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
|
||||
}
|
||||
const recoveryKey = Buffer.concat(chunks).toString("utf8").trim();
|
||||
if (!recoveryKey) {
|
||||
throw new Error("Matrix recovery key was requested from stdin, but stdin was empty.");
|
||||
}
|
||||
return recoveryKey;
|
||||
}
|
||||
|
||||
async function resolveMatrixCliRecoveryKeyInput(options: {
|
||||
recoveryKey?: string;
|
||||
recoveryKeyStdin?: boolean;
|
||||
}): Promise<string | undefined> {
|
||||
if (options.recoveryKey && options.recoveryKeyStdin === true) {
|
||||
throw new Error("Use either --recovery-key or --recovery-key-stdin, not both.");
|
||||
}
|
||||
if (options.recoveryKeyStdin === true) {
|
||||
return await readMatrixCliRecoveryKeyFromStdin();
|
||||
}
|
||||
return options.recoveryKey;
|
||||
}
|
||||
|
||||
async function requireMatrixCliRecoveryKeyInput(options: {
|
||||
recoveryKey?: string;
|
||||
recoveryKeyStdin?: boolean;
|
||||
}): Promise<string> {
|
||||
const recoveryKey = await resolveMatrixCliRecoveryKeyInput(options);
|
||||
if (!recoveryKey) {
|
||||
throw new Error(
|
||||
"Matrix recovery key is required. Pass --recovery-key-stdin to read it from stdin.",
|
||||
);
|
||||
}
|
||||
return recoveryKey;
|
||||
}
|
||||
|
||||
function toErrorMessage(err: unknown): string {
|
||||
return formatMatrixErrorMessage(err);
|
||||
}
|
||||
@@ -123,6 +161,15 @@ function formatMatrixCliCommand(command: string, accountId?: string): string {
|
||||
return formatMatrixCliCommandParts(command.split(" "), accountId);
|
||||
}
|
||||
|
||||
function formatMatrixCliRecoveryKeyStdinCommand(command: string, accountId?: string): string {
|
||||
const normalizedAccountId = normalizeAccountId(accountId);
|
||||
const envName =
|
||||
normalizedAccountId === "default"
|
||||
? "MATRIX_RECOVERY_KEY"
|
||||
: `MATRIX_RECOVERY_KEY_${normalizedAccountId.replace(/[^A-Za-z0-9]/g, "_").toUpperCase()}`;
|
||||
return `printf '%s\\n' "$${envName}" | ${formatMatrixCliCommand(command, accountId)}`;
|
||||
}
|
||||
|
||||
function formatMatrixCliCommandParts(parts: string[], accountId?: string): string {
|
||||
const normalizedAccountId = normalizeAccountId(accountId);
|
||||
const command = ["openclaw", "matrix", ...parts];
|
||||
@@ -1068,11 +1115,11 @@ function buildVerificationGuidance(
|
||||
`Recovery key can unlock the room-key backup, but full Matrix identity trust is still incomplete. Run ${formatMatrixCliCommand("verify self", accountId)}, accept the request in another verified Matrix client, and confirm the SAS only if it matches.`,
|
||||
);
|
||||
nextSteps.add(
|
||||
`If you intend to replace the current cross-signing identity, run ${formatMatrixCliCommand("verify bootstrap --recovery-key <key> --force-reset-cross-signing", accountId)}.`,
|
||||
`If you intend to replace the current cross-signing identity, run the shown printf pipeline with the Matrix recovery key env var for this account: ${formatMatrixCliRecoveryKeyStdinCommand("verify bootstrap --recovery-key-stdin --force-reset-cross-signing", accountId)}.`,
|
||||
);
|
||||
} else {
|
||||
nextSteps.add(
|
||||
`Run ${formatMatrixCliCommand("verify device <key>", accountId)} with your Matrix recovery key. If you do not have the recovery key but still have another verified Matrix client, run ${formatMatrixCliCommand("verify self", accountId)} instead.`,
|
||||
`Run the shown printf pipeline with the Matrix recovery key env var for this account: ${formatMatrixCliRecoveryKeyStdinCommand("verify device --recovery-key-stdin", accountId)}. If you do not have the recovery key but still have another verified Matrix client, run ${formatMatrixCliCommand("verify self", accountId)} instead.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1112,23 +1159,23 @@ function buildBackupGuidance(
|
||||
) {
|
||||
if (options.recoveryKeyStored) {
|
||||
nextSteps.add(
|
||||
`Backup key is not loaded on this device. Run ${formatMatrixCliCommand("verify backup restore", accountId)} to load it and restore old room keys. If restore still cannot load the key, run ${formatMatrixCliCommand("verify backup restore --recovery-key <key>", accountId)} with the Matrix recovery key.`,
|
||||
`Backup key is not loaded on this device. Run ${formatMatrixCliCommand("verify backup restore", accountId)} to load it and restore old room keys. If restore still cannot load the key, run the shown printf pipeline with the Matrix recovery key env var for this account: ${formatMatrixCliRecoveryKeyStdinCommand("verify backup restore --recovery-key-stdin", accountId)}.`,
|
||||
);
|
||||
} else {
|
||||
nextSteps.add(
|
||||
`Run ${formatMatrixCliCommand("verify backup restore --recovery-key <key>", accountId)} with the Matrix recovery key to load the server backup and store the key for future restores.`,
|
||||
`Run the shown printf pipeline with the Matrix recovery key env var for this account: ${formatMatrixCliRecoveryKeyStdinCommand("verify backup restore --recovery-key-stdin", accountId)} to load the server backup and store the key for future restores.`,
|
||||
);
|
||||
}
|
||||
} else if (backupIssue.code === "key-mismatch") {
|
||||
nextSteps.add(
|
||||
`Backup key mismatch on this device. Run ${formatMatrixCliCommand("verify backup restore --recovery-key <key>", accountId)} with the recovery key for the active server backup.`,
|
||||
`Backup key mismatch on this device. Run the shown printf pipeline with the active server backup recovery key env var for this account: ${formatMatrixCliRecoveryKeyStdinCommand("verify backup restore --recovery-key-stdin", accountId)}.`,
|
||||
);
|
||||
nextSteps.add(
|
||||
`If you want a fresh backup baseline and accept losing unrecoverable history, run ${formatMatrixCliCommand("verify backup reset --yes", accountId)}. Add --rotate-recovery-key only when the old recovery key should stop unlocking the fresh backup.`,
|
||||
);
|
||||
} else if (backupIssue.code === "untrusted-signature") {
|
||||
nextSteps.add(
|
||||
`Backup trust chain is not verified on this device. Re-run ${formatMatrixCliCommand("verify device <key>", accountId)} if you have the correct recovery key.`,
|
||||
`Backup trust chain is not verified on this device. Run the shown printf pipeline with the correct recovery key env var for this account: ${formatMatrixCliRecoveryKeyStdinCommand("verify device --recovery-key-stdin", accountId)}.`,
|
||||
);
|
||||
nextSteps.add(
|
||||
`If device identity trust remains incomplete after that, run ${formatMatrixCliCommand("verify self", accountId)} from another verified Matrix client.`,
|
||||
@@ -1795,13 +1842,18 @@ export function registerMatrixCli(params: { program: Command }): void {
|
||||
.command("restore")
|
||||
.description("Restore encrypted room keys from server backup")
|
||||
.option("--account <id>", "Account ID (for multi-account setups)")
|
||||
.option("--recovery-key <key>", "Optional recovery key to load before restoring")
|
||||
.option(
|
||||
"--recovery-key <key>",
|
||||
"Optional recovery key to load before restoring (prefer --recovery-key-stdin)",
|
||||
)
|
||||
.option("--recovery-key-stdin", "Read the Matrix recovery key from stdin")
|
||||
.option("--verbose", "Show detailed diagnostics")
|
||||
.option("--json", "Output as JSON")
|
||||
.action(
|
||||
async (options: {
|
||||
account?: string;
|
||||
recoveryKey?: string;
|
||||
recoveryKeyStdin?: boolean;
|
||||
verbose?: boolean;
|
||||
json?: boolean;
|
||||
}) => {
|
||||
@@ -1813,7 +1865,7 @@ export function registerMatrixCli(params: { program: Command }): void {
|
||||
await restoreMatrixRoomKeyBackup({
|
||||
accountId,
|
||||
cfg,
|
||||
recoveryKey: options.recoveryKey,
|
||||
recoveryKey: await resolveMatrixCliRecoveryKeyInput(options),
|
||||
}),
|
||||
onText: (result, verbose) => {
|
||||
printAccountLabel(accountId);
|
||||
@@ -1846,7 +1898,11 @@ export function registerMatrixCli(params: { program: Command }): void {
|
||||
.command("bootstrap")
|
||||
.description("Bootstrap Matrix cross-signing and device verification state")
|
||||
.option("--account <id>", "Account ID (for multi-account setups)")
|
||||
.option("--recovery-key <key>", "Recovery key to apply before bootstrap")
|
||||
.option(
|
||||
"--recovery-key <key>",
|
||||
"Recovery key to apply before bootstrap (prefer --recovery-key-stdin)",
|
||||
)
|
||||
.option("--recovery-key-stdin", "Read the Matrix recovery key from stdin")
|
||||
.option("--force-reset-cross-signing", "Force reset cross-signing identity before bootstrap")
|
||||
.option("--verbose", "Show detailed diagnostics")
|
||||
.option("--json", "Output as JSON")
|
||||
@@ -1854,6 +1910,7 @@ export function registerMatrixCli(params: { program: Command }): void {
|
||||
async (options: {
|
||||
account?: string;
|
||||
recoveryKey?: string;
|
||||
recoveryKeyStdin?: boolean;
|
||||
forceResetCrossSigning?: boolean;
|
||||
verbose?: boolean;
|
||||
json?: boolean;
|
||||
@@ -1866,7 +1923,7 @@ export function registerMatrixCli(params: { program: Command }): void {
|
||||
await bootstrapMatrixVerification({
|
||||
accountId,
|
||||
cfg,
|
||||
recoveryKey: options.recoveryKey,
|
||||
recoveryKey: await resolveMatrixCliRecoveryKeyInput(options),
|
||||
forceResetCrossSigning: options.forceResetCrossSigning === true,
|
||||
}),
|
||||
onText: (result, verbose) => {
|
||||
@@ -1907,18 +1964,34 @@ export function registerMatrixCli(params: { program: Command }): void {
|
||||
);
|
||||
|
||||
verify
|
||||
.command("device <key>")
|
||||
.command("device [key]")
|
||||
.description("Verify device using a Matrix recovery key")
|
||||
.option("--account <id>", "Account ID (for multi-account setups)")
|
||||
.option("--recovery-key-stdin", "Read the Matrix recovery key from stdin")
|
||||
.option("--verbose", "Show detailed diagnostics")
|
||||
.option("--json", "Output as JSON")
|
||||
.action(
|
||||
async (key: string, options: { account?: string; verbose?: boolean; json?: boolean }) => {
|
||||
async (
|
||||
key: string | undefined,
|
||||
options: {
|
||||
account?: string;
|
||||
recoveryKeyStdin?: boolean;
|
||||
verbose?: boolean;
|
||||
json?: boolean;
|
||||
},
|
||||
) => {
|
||||
const { accountId, cfg } = resolveMatrixCliAccountContext(options.account);
|
||||
await runMatrixCliCommand({
|
||||
verbose: options.verbose === true,
|
||||
json: options.json === true,
|
||||
run: async () => await verifyMatrixRecoveryKey(key, { accountId, cfg }),
|
||||
run: async () =>
|
||||
await verifyMatrixRecoveryKey(
|
||||
await requireMatrixCliRecoveryKeyInput({
|
||||
recoveryKey: key,
|
||||
recoveryKeyStdin: options.recoveryKeyStdin,
|
||||
}),
|
||||
{ accountId, cfg },
|
||||
),
|
||||
onText: (result, verbose) => {
|
||||
printAccountLabel(accountId);
|
||||
if (!result.success) {
|
||||
|
||||
Reference in New Issue
Block a user