Architecture Review

Architecture Review — April 2026

Comprehensive security review of the vault’s design, encryption layers, operational patterns, and threat model.

Strengths

Area Assessment

Encryption choice

Age (ChaCha20-Poly1305) over GPG — no key server dependency, no trust model complexity, no expiry dance. Simplicity is the security.

Opaque domain IDs

d000/d001 with encrypted registry prevents infrastructure name exposure from directory structure.

Shell history protection

HISTORY_IGNORE patterns + leading-space dsec-load + clear-sensitive-history + audit-history-security covers all four shell history leak vectors. Three-shell coverage (zsh/bash/fish) eliminates gaps.

Temp file handling

/dev/shm (RAM-backed tmpfs) for all plaintext — never touches persistent storage during edit operations.

LUKS header backups

Backs up encryption metadata (not just data) — recoverable from header corruption without exposing secrets.

Git redundancy

4 independent remotes (GitHub, GitLab, Gitea, Codeberg) with gh-repo-create for simultaneous multi-remote creation.

Offline backup depth

M2 SSD + 2x Seagate offsite + Borg = 4 independent copies including at least 2 offsite.

Template-driven consistency

12 .env.example files prevent missing-field errors when adding new domains/tiers.

Findings

1. Commit messages leak tool names (High)

Opaque domain IDs are undermined by descriptive commit messages:

feat: Add Wazuh SIEM variables to d000/dev/network
feat(d000/dev): Add k3s Infrastructure Monitoring credentials
[CHORE] wazuh pass rotation

An attacker reading git log learns the full technology stack despite opaque directory names.

Recommendation: Generic messages only — chore: rotate d000/dev/network, feat: add d000/lab tier. Never name tools (Wazuh, K3s, ISE) in commit messages.

2. shred on SSD (Low — accepted risk)

shred -n 10 cannot target specific NAND cells due to SSD wear leveling. However, plaintext only exists in /dev/shm (RAM) and LUKS encrypts all persistent storage. Both layers render `shred’s SSD limitation irrelevant in practice.

Status: Accepted risk. The two encryption layers (Age + LUKS) provide the actual protection.

3. No commit signing (Medium)

202 commits across 4 remotes with no GPG or SSH signing. An attacker with push access to any remote could inject a modified encrypted file.

Recommendation: Enable git config commit.gpgsign true or SSH signing.

4. gitleaks enforcement unclear (Medium)

.gitleaks.toml is well-configured (5.6KB) but enforcement as a pre-commit hook should be verified. Config without enforcement is documentation, not protection.

5. No rotation tracking (Medium)

177 encrypted files with no systematic metadata about credential expiry or last-rotated dates. Rotation happens (visible in commit history) but relies on memory rather than tooling.

Recommendation: Add dsec stale command or rotation-schedule.yaml.age with expiry tracking.

6. documents/ scope (Low)

114 encrypted documents (personal, professional, communications) have different lifecycle needs than secrets. Secrets need rotation; documents need retention. Operationally simple as one repo — but should be acknowledged in README.

7. No automated dsec testing (Low)

dsec handles encryption, decryption, sourcing, and editing with no test suite. A regression could silently fail to encrypt or corrupt during edit.

8. Commit convention inconsistency (Low)

Four different commit styles in history. Conventional commits recommended: chore: rotate d000/dev/network.

9. No tags for recovery anchors (Low)

Single branch, no tags. Tags at milestones would simplify point-in-time recovery.