Encryption and cryptographic erasure¶
PEART encrypts sensitive data at the file level using age, a modern, community-reviewed construction, implemented in pure Go with no CGO so the binaries stay statically and cross-compilable (ADR 0004). This is file encryption, not database encryption, and the distinction is deliberate and documented.
What is encrypted, and what is not¶
Encrypted by default: evidence (the screenshots and captures that carry credentials, tokens and PII, the highest-value asset) and backup artifacts. Turning this off requires explicit configuration and a warning.
Not encrypted, by architectural necessity: renditions and generated reports. Both are
client-facing artifacts served directly by the portal, and the portal never holds the master identity
by design (see the portal boundary). Encrypting them against an
identity the serving surface does not possess would make them unrecoverable by the very surface that
must deliver them. This is a constraint, not a gap, and docs/security.md states it explicitly.
Not encrypted, by deliberate decision: the SQLite database (ADR 0008). Encrypting SQLite with the mature options requires CGO, which would break the static, cross-compiled distribution model. Instead, full-disk encryption on the host (LUKS) is the documented, recommended control for the database at rest. The consequence is stated plainly: finding titles, technical descriptions and exploitation steps are readable to anyone with access to the database file. The project declares this rather than implying otherwise, because a declared limitation is worth more than a vague promise.
The key hierarchy¶
There are two levels of key.
The installation master identity is generated on first boot, as an age key, into a file with mode
0600. It never leaves the internal surface, and it is never included in a backup; the backup command
refuses to add it, because a master key in the same archive as the data it protects would make the
encryption theatre.
Each engagement has its own identity, whose private key is encrypted with the master identity and stored in the database. Encrypting a given engagement's evidence uses that engagement's key.
Cryptographic erasure¶
The per-engagement key is what makes true erasure possible. Destroying an engagement's key renders its material illegible even in old backups the consultancy no longer controls, which no row deletion can achieve. This is the basis of the retention-purge mechanism, and it is the strongest part of the privacy story: it is erasure by key destruction, which reaches copies that a delete statement never could. For a DPO weighing the right to erasure, this is the mechanism that answers "and the backups?".
Operational consequences¶
Losing the master identity means losing all evidence, with no recovery. There is an explicit export command, and first boot instructs the operator to keep a readable copy somewhere separate from the data backup:
peart export-key -key /etc/peart/master.key -confirm
Key rotation is out of scope for v1, and this is declared in the project rather than left implicit.