recover

command
v1.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Command recover is the offline account-recovery tool. Given the recovery PRIVATE key and a database DSN, it reads the append-only recovery escrow log, decrypts each record, and prints the recoverable details as JSON lines so an operator can restore deleted users from backup.

The running server never has the private key — it can only WRITE escrow records. This tool is meant to run on a trusted offline host where the key is available.

Usage:

DATABASE_URL="postgres://user:pass@host:5432/vault?sslmode=require" \
	recover --key /path/to/recovery_private.pem --out recovered.jsonl

The DSN belongs in DATABASE_URL rather than in --dsn: every argument of a running process is readable by every other process on the host through /proc/<pid>/cmdline, and a shell keeps it in history afterwards. --dsn still works, and says so on stderr when the value it was given carries a password.

--out writes the recovered records to a file the tool creates itself, mode 0600, refusing to overwrite an existing file or to follow a symlink. Without it the records go to stdout, and a `> file` redirect creates that file with the operator's umask, which on a stock login is world-readable. This output is the personal data an erasure removed, so it is worth the extra flag.

Escrow formats

A payload is sealed to the row it lives in: the record's primary key and its subject pseudonym are the RSA-OAEP label and the AES-GCM AAD, and the payload names its own subject. That binding is what stops a payload being moved between rows and reported under another erasure's deleted_at, deleted_by and reason. This tool rebuilds it from the columns it reads, which is why it needs no HMAC secret to do so.

Records written before the binding existed are still readable, because they are the only recoverable copy of the accounts they describe. Every output line carries escrow_format, "bound" or "legacy", so a restore can tell a verified attribution from an unverified one without reading stderr, and every legacy read is announced there as well. --allow-legacy=false refuses them outright; once the retention horizon has aged the last one out, the legacy path here and in internal/crypto can be deleted.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL