# xvault

**xvault is a CLI for keeping secrets _inside_ your real config and notes files, while staying Git-friendly.**

Your files remain readable and reviewable, and only the values you explicitly mark as secret are encrypted.

The core idea is a **single source of truth**: store secrets, notes, and configuration together in a small set of canonical files (.json, .jsonc, .yaml, .env, .md), and let `xvault` handle safe editing, encryption, and export.

From these files, you can **derive/export/resolve** the exact formats your tooling expects (e.g., `.env`, JSON config, certificate files) without duplicating plaintext secrets across multiple files or repositories.

To minimize **cognitive load**, `xvault` keeps the workflow intentionally simple: secure defaults, straightforward commands, and optional OS key caching (no servers to run, no KMS to configure, and no complex policy systems). It’s optimized for **solo developers and small teams** who want a **local-first** vault that integrates cleanly with Git.

---

## Intro

### Motivation: single source of truth for developer secrets
Most developer workflows end up with friction such as:

- a config file plus a separate secrets file
- manual merging before deployment / resolving secrets at runtime
- ugly diffs (whole files encrypted)
- accidental leaks when exporting plaintext

`xvault` is designed to keep your **notes and configs** as the source of truth, with **inline secrets** that stay encrypted on disk.

### Comparison: SOPS and git-crypt
`xvault` overlaps with tools like SOPS and git-crypt, but it targets a slightly different “developer ergonomics” space:

- **SOPS** shines for GitOps/Kubernetes workflows and KMS-backed key management. It’s great when your infra pipeline is already built around SOPS + KMS/PGP/age.  
  `xvault` is not trying to replace that ecosystem; it focuses on **editing arbitrary files (.json, .jsonc, .env, .yml, .md)** with minimal ceremony and clean diffs.

- **git-crypt** is effective for encrypting entire files transparently in Git.  
  `xvault` takes a more explicit approach: secrets are marked with `enc:` and only those values are encrypted, keeping the rest of the document readable.

If your main need is “encrypt a whole directory of files in git”, git-crypt may be enough.  
If your main need is “keep notes/config readable while only encrypting secret values”, `xvault` is a better fit.

### Design philosophy
- **Explicit by default**: only values marked with `enc:` are treated as secrets.
- **Git diffs matter**: keep secrets stored as single-line ciphertext.
- **Stay close to real formats**: work with JSON/JSONC/YAML/.env/Markdown without forcing a rigid schema.
- **Developer UX first**: `edit` is the primary workflow; everything else supports it.
- **Safe defaults**: prefer failing loudly over producing ambiguous output.

---

## Usage

`xvault` is designed for two main workflows. Both rely on the same core idea: **keep secrets inside the files you already use**, encrypt only what you explicitly mark as secret (`enc:`), and derive/export the exact outputs when needed.

### 1) Application config files with embedded secrets

Use `xvault` directly on configuration files that your applications and tooling already understand:

- `.env` files
- JSON / JSONC
- YAML
- md files

You keep the config readable, and only encrypt the values that start with `enc:`.

Example (`dev.env`):
```env
DB_HOST=localhost
DB_USER=enc:admin
DB_PASS=enc:"my password with spaces"
```
Typical workflow:

- `xvault edit ./dev.env` to safely edit secrets and non-secret config together
- `xvault export ./dev.env` to materialize a decrypted output for scripts/CI/runtime
- `xvault get ./dev.env DB_PASS` to extract a decrypted value from file

### 2) Personal vault notes (Markdown)

Use `xvault` as a local-first personal vault where you store notes, runbooks, logs, credentials, and key material inside Markdown files.

A common pattern is:

- one Markdown file per topic (e.g., servers.md, accounts.md, infra.md)
- secrets stored inside standard fenced blocks like ```env

Example (servers.md):

````md
## prod-api-01

Notes and runbook steps in plain text...

```env
SSH_HOST=prod-api-01.example.com
SSH_USER=enc:admin
SSH_PASS=enc:"my password with spaces"
SSH_KEY_PEM_B64=enc:LS0tLS1CRUdJTiBPU...
```
```` 

Guidelines:
- Use enc: for secret values.
- Use *_B64 variables for multi-line or binary material (PEM/PFX/PDF/PNG) encoded as base64.
- Keep everything else (notes, procedures, logs) in plain text for excellent Git diffs and searchability.

---

## Features

- **Formats**: JSON, JSONC, YAML, `.env`, Markdown
- **Inline secret marking**: `enc:` prefix indicates secret values
- **Single-line ciphertext** for clean Git diffs
- **Optional variable substitution**: resolve `${VAR}` placeholders (`xvault get file.json secret_name --resolve`)
- **Key caching (optional)**:
  - `unlock` stores a derived key in the OS key store
  - `lock` removes it
  - `--no-cache-key` disables cache read/write per command
- **Crypto (v1)**:
  - Password-based key derivation: **Argon2id**
  - Encryption: **AES-256-GCM** (authenticated encryption)
- **Rekey support**: rotate secrets to a new password (`xvault rekey`)
- **Validation**: sanity checks for file structure and encrypted markers (`xvault validate`)

---

## Security Model

### What xvault protects against
- Accidental commits of plaintext secrets by keeping secrets **encrypted on disk**
- “Diff leakage”: avoids storing whole plaintext configs; only `enc:` values become ciphertext
- Backup leakage: encrypted vault files are safe to back up as ciphertext
- Tampering detection: AES-GCM provides integrity/authentication for secret values (wrong key or modified ciphertext fails to decrypt)
- By default, xvault edit uses an in-terminal editor and does not write plaintext temp files.

### Threats it does NOT fully solve (limitations)
- **Weak passwords**: your vault is only as strong as the password you choose. Use a strong passphrase (e.g., 12–16+ characters, preferably more).
- **Compromised machine**: if an attacker owns your box while you edit, they can read plaintext.
- **Plaintext exports**: `export` can produce decrypted content. Handle it carefully (gitignore, temporary locations).
- **OS key cache availability**: keyring/credential storage may fail in some contexts (e.g., Windows over SSH). Use `--no-cache-key` or alternative cache strategies.

### Threat mitigations (practical)
- Use a strong, unique password (prefer long passphrases).
- Keep repositories private; avoid cloning vault repos on untrusted machines.
- Prefer `--no-cache-key` in sensitive environments (remote sessions, servers, CI).
- Run `xvault validate` before committing.

### Example file (conceptual)
`xvault` stores a small metadata header (e.g. `_xvault`) and secrets as `enc:` values:

```jsonc
{
  "_xvault": "xvault:<opaque-metadata-blob>",
  "db": {
    "host": "...",
    "user": "enc:...",
    "password": "enc:..."
  }
}
```

```env
_xvault="xvault:<opaque-metadata-blob>"
DB_HOST=...
DB_USER=enc:...
DB_PASSWORD=enc:...
```

## Installation

Install from PyPI:

```bash
pip install xvault
xvault version
```

### Install from source (development)

Clone the repository:

```bash
# clone the repository:
git clone https://github.com/marcdp/xvault.git
# run the CLI:
python -m xvault
# or install as a command:
pip install .
```

---




## Roadmap

Short-term (quality and UX):
- Improve TUI editor UX (colors, navigation, safer save guards, undo-redo)
- Better Markdown conventions for multi-line secrets and binary references
- Safer export modes (explicit confirmations)

Mid-term (developer workflows):
- Export filtering by section/scope in Markdown (e.g., server.var)
- SSH-agent helpers (load selected keys with TTL)
- A "blob store" for large binary secrets (PFX/PDF/PNG) with manifest + encrypted blobs

Long-term:
- VS Code virtual filesystem provider (xvault:/...) backed by xvault (no plaintext temp files)
- Optional policy validation hooks (pre-commit integration)
- Optional alternative key caching backends (more reliable across SSH / WSL)


## License

MIT License

See the LICENSE file for details.