Skip to content

Comments

feat(vault): add encryption-at-rest vault for environment variables#219

Open
penso wants to merge 2 commits intomainfrom
vault-encryption
Open

feat(vault): add encryption-at-rest vault for environment variables#219
penso wants to merge 2 commits intomainfrom
vault-encryption

Conversation

@penso
Copy link
Collaborator

@penso penso commented Feb 23, 2026

Summary

  • Adds a new moltis-vault crate implementing XChaCha20-Poly1305 encryption-at-rest with Argon2id key derivation
  • Two-layer key hierarchy (Password → KEK → DEK) so password changes only re-wrap the DEK
  • Recovery key support (128-bit random, 32-char alphanumeric encoding) for emergency vault access
  • Integrates with auth flow: vault initializes on setup, unseals on login, re-wraps on password change
  • Vault guard middleware blocks API requests with 423 Locked when sealed (not when uninitialized)
  • Environment variables encrypted with AAD (env:{key}) to prevent ciphertext swapping
  • Plaintext → encrypted migration runs automatically on vault unseal
  • Vault status exposed in gon data (window.__MOLTIS__.vaultStatus) for frontend
  • Full documentation in docs/src/vault.md

Crate structure (crates/vault/)

Module Purpose
vault.rs Core Vault struct with init/unseal/seal/encrypt/decrypt/change_password
kdf.rs Argon2id key derivation with configurable params
xchacha20.rs XChaCha20-Poly1305 AEAD encrypt/decrypt with AAD
key_wrap.rs DEK wrapping/unwrapping with KEK
recovery.rs Recovery key generation, encoding, and verification
migration.rs Plaintext → encrypted env var migration
error.rs VaultError enum via thiserror
traits.rs VaultBackend trait for testing

Integration points

  • auth_routes.rs: Vault init on setup (returns recovery key), unseal on login, re-wrap on password change
  • auth_middleware.rs: Vault guard layer blocks API when sealed
  • credential_store.rs: Encrypt/decrypt env vars via vault
  • state.rs: vault: Option<Arc<Vault>> field on GatewayState
  • server.rs: Vault initialization at startup
  • templates.rs: Vault status in gon data

Validation

Completed

  • cargo check -p moltis-vault — compiles clean
  • cargo test -p moltis-vault — 38 tests pass
  • cargo test -p moltis-auth --features vault — 40 tests pass
  • cargo test -p moltis-gateway — 49 tests pass
  • cargo check -p moltis (full CLI) — compiles clean
  • just format — formatted
  • Clippy clean on vault-affected crates
  • mdbook build — docs build successfully

Remaining

  • E2E tests for vault unlock UI flow
  • KeyStore/TokenStore encryption (blocked on async refactor)
  • local-validate.sh (requires PR number)

Manual QA

  • Verified vault API signatures match integration code
  • Cross-referenced docs against actual source (KDF params, recovery key format, DB schema)
  • Confirmed vault guard only blocks on sealed state, not uninitialized

Add a new `moltis-vault` crate that encrypts sensitive data at rest using
XChaCha20-Poly1305 AEAD with Argon2id-derived keys. The vault integrates
transparently with the authentication flow: it initializes on first
password setup, auto-unseals on login, and rotates keys on password change.

Key hierarchy: Password → Argon2id → KEK → unwrap DEK → encrypt data.
A recovery key (128-bit, shown once at setup) provides emergency access.

Integration points:
- CredentialStore: env vars encrypted when vault is unsealed
- auth_middleware: vault_guard blocks API when sealed (423 Locked)
- auth_routes: vault status/unlock/recovery endpoints + hooks in
  setup/login/change-password handlers
- GonData: vault_status exposed to frontend
- Feature flag: `vault` (default on in gateway + CLI)

Includes 38 vault crate tests, 3 auth integration tests, and
documentation in docs/src/vault.md.
@codspeed-hq
Copy link
Contributor

codspeed-hq bot commented Feb 23, 2026

Merging this PR will not alter performance

✅ 39 untouched benchmarks
⏩ 5 skipped benchmarks1


Comparing vault-encryption (500c14a) with main (7eae997)

Open in CodSpeed

Footnotes

  1. 5 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@codecov
Copy link

codecov bot commented Feb 23, 2026

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