Skip to content

chore(secrets): create the disaster-recovery escrow, which had never existed - #1002

Merged
mlorentedev merged 2 commits into
mainfrom
chore/dr-escrow-refresh
Aug 15, 2026
Merged

chore(secrets): create the disaster-recovery escrow, which had never existed#1002
mlorentedev merged 2 commits into
mainfrom
chore/dr-escrow-refresh

Conversation

@mlorentedev

Copy link
Copy Markdown
Owner

The first sensitive/dr/bitwarden-export.age this repository has ever contained.

Why this is not routine

ADR-028 §5 specifies a disaster-recovery escrow: bw sync + bw export piped in memory into age, encrypted to the operator's own recipient, round-trip verified, written 0600, and committed — the directory's .gitignore un-ignores *.age precisely so the encrypted blob rides in git and is therefore offsite by construction.

It had never run. dotf secrets backup fails with bw export: Vault is locked because the export shells out to the bw CLI, which authenticates from BW_SESSION, while every read path moved to the bw serve daemon in #975. That is #993, and the escrow is its most expensive consequence.

Two facts made the absence serious rather than untidy:

What was done

$ BW_SESSION="$(bw unlock --raw)" dotf secrets backup
escrow written and verified: …/sensitive/dr/bitwarden-export.age

$ ls -l sensitive/dr/bitwarden-export.age
-rw------- 141K
$ head -c 21 sensitive/dr/bitwarden-export.age
age-encryption.org/v1

141 KB, mode 0600, genuine age ciphertext, and dotf secrets backup decrypts it back and byte-compares before it will report success — a corrupt escrow is removed rather than committed.

The other half, not in this PR

An escrow is worthless if its key has a single point of failure, and this one did: the age identity's only off-machine copy lived inside Bitwarden, the vault the escrow exists to survive the loss of. That circular dependency is now broken — the key is on a separate USB, so recovery is USB key + git clone with two independent failure modes. Tracked in #1000, where what remains is verification rather than exposure: the registry still does not declare the key (#937), nothing checks the two copies still match, and the recovery chain has never been executed end to end.

Note on the commit

Committed directly to main first, in error, and moved onto this branch before pushing. Everything in this repository goes through a PR; the escrow is not an exception just because it is a binary blob.

@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

💤 Files selected but had no reviewable changes (1)
  • sensitive/dr/bitwarden-export.age
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b6501f3b-fd3f-4c37-b8c1-4b3566134247

📥 Commits

Reviewing files that changed from the base of the PR and between 69f4bb5 and 03913fb.

📒 Files selected for processing (1)
  • sensitive/dr/bitwarden-export.age

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mlorentedev
mlorentedev merged commit 5e79333 into main Aug 15, 2026
8 checks passed
@mlorentedev
mlorentedev deleted the chore/dr-escrow-refresh branch August 15, 2026 08:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant