feat(recovery): SSSS recovery key — bridges self-sign on startup #19
No reviewers
Labels
No labels
agent:felinus
agent:human
agent:maximus
priority:p0
priority:p1
priority:p2
priority:p3
status:blocked
status:needs-review
status:wip
type:chore
type:docs
type:feat
type:fix
type:perf
type:refactor
type:test
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
jmz/matrix-bridge!19
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/own-device-recovery"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Stacked on #18 (base =
feat/own-device-cross-signing). This is Option 1 — the durable fix maximus@nas preferred in jmz/pa#20.What
Every bridge instance imports the cross-signing secret from server-side secret storage (SSSS) on startup and self-signs its own device. A new bridge host, or one whose store was lost, self-heals on next launch — no manual signing, and the secret survives any single device's store loss (the exact "no SSSS / unrecoverable secret" hole from jmz/pa#20).
How
enable-recovery [--passphrase]— one-time, run from the device that holds the cross-signing secret (currently the NAS). Requires a complete identity (cross_signing_status().is_complete()), thenrecovery().enable()stores the secret in SSSS and prints a recovery key.recovery_keyfield +resolve_recovery_key()that prefers theMATRIX_BRIDGE_RECOVERY_KEYenv var so the key can be SOPS-injected and never lands inconfig.jsonplaintext.ensure_self_signed()runs after the first sync instart_sync()(the MCP server path): no-op if the self-signing secret is already present, elserecovery().recover(key)imports it. Best-effort — warns and continues (degraded inbound) rather than aborting if no key is configured or import fails.Relationship to #18
verify-own-devices): manual one-shot from the secret-holder to sign other own devices. Immediate unblock, no config/SSSS needed.MATRIX_BRIDGE_RECOVERY_KEYis configured. Durable; the steady state.They compose. #18 unblocks today; this makes it self-sustaining.
Verification
cargo check --all. The new SDK surface (recovery(),Recovery::enable()/Enable::with_passphrase/wait_for_backups_to_upload,recover(),CrossSigningStatus::is_complete) is confirmed against docs.rs (matrix-sdk 0.14):with_passphrase(self, &'a str) -> Self, awaitedEnableyieldsResult<String>(the recovery key).recover()self-signs the current device on import (maximus@nas's option-1 premise). If a device imports the secret but doesn't auto-self-sign, a follow-up would add an explicit own-device sign afterrecover().resolve_recovery_keyis env-dependent (flaky to test), the rest is SDK glue with no mock infra (consistent with the repo).Rollout
matrix-bridge enable-recovery→ capture the recovery key → SOPS.MATRIX_BRIDGE_RECOVERY_KEYon mba / rpi5 / nas bridge launch env.Refs jmz/pa#20