diff --git a/assets/secrets-lifecycle.svg b/assets/secrets-lifecycle.svg
new file mode 100644
index 0000000..6cc65de
--- /dev/null
+++ b/assets/secrets-lifecycle.svg
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/docs/secrets-and-pki.md b/docs/secrets-and-pki.md
index 8fb8d67..8ec2340 100644
--- a/docs/secrets-and-pki.md
+++ b/docs/secrets-and-pki.md
@@ -23,18 +23,7 @@ A managed secrets service (a cloud provider's KMS/Secrets Manager) was a real al
## Why it's built this way
-```mermaid
-flowchart LR
- Before["Before: plaintext secrets in git-tracked .env files readable by anyone with repo access, permanent in git history"] -->|replaced| After
-
- subgraph After["Now"]
- direction TB
- T["Git-tracked template placeholder syntax only"]
- V["Vault real value, one place"]
- R["Rendered file gitignored, 0600, root-owned"]
- V -->|renders| R
- end
-```
+Before this system existed, every stack's secrets sat in plaintext inside git-tracked `.env` files — readable by anyone with repo access, and permanently baked into git history even after being "fixed." SecureVault replaces that:
- The real secret value lives in exactly one place: Vault.
- What's git-tracked is a template with placeholder syntax, never a real value.
@@ -46,25 +35,20 @@ flowchart LR
## Architecture
-```mermaid
-flowchart TD
- Vault["Vault PKI (public + internal mounts) + KV v2 store TLS listener, cert-verified · audit log"]
- Proxy["Internal app-to-app reverse-proxy zone see docs/dns-naming.md"]
- A1["Vault Agent — App Host ~12 stacks' secrets + internal CA cert"]
- A2["Vault Agent — Automation Host ~10 stacks' secrets"]
- A3["Vault Agent — Monitoring Host admin credentials + OIDC secret"]
- A4["Vault Agent — Edge Proxy Host mTLS zone certs"]
- A5["Vault Agent — DNS Host admin UI cert"]
- A6["Vault Agent — Security Monitoring Host manager/indexer/dashboard secrets"]
+Every Vault Agent reaches Vault through the internal app-to-app proxy zone described in [`docs/dns-naming.md`](dns-naming.md) — never directly. It's the one hop in that entire zone where the proxy actually verifies the backend's certificate instead of skipping it, which is exactly the asymmetric-trust decision explained below.
- Vault -->|HTTPS, cert-verified| Proxy
- Proxy --> A1
- Proxy --> A2
- Proxy --> A3
- Proxy --> A4
- Proxy --> A5
- Proxy --> A6
-```
+| Consumer | What it gets from Vault |
+|---|---|
+| App Host | 12 stacks' worth of application secrets, an internal CA cert to verify Vault's own listener, plus a shared registry-token render |
+| Automation Host | 10 stacks' worth of application secrets, plus a shared registry-token render |
+| Monitoring Host | Grafana's admin password and the Authentik OIDC secret, plus Hawser's application secret, plus a shared registry-token render |
+| User-Facing Proxy | Server + client certs for the mTLS-enforced browser zone, plus a shared registry-token render and Hawser's application secret |
+| Internal DNS | Server cert for its own admin UI/API only |
+| Security Monitoring | Its manager and dashboard services' shared secrets (indexer, API, dashboard passwords), plus Hawser's application secret, plus a shared registry-token render |
+
+None of these ever call the Vault API themselves — every one of them goes through the same local-render sequence:
+
+
**Two authentication flows, not one:**
@@ -81,10 +65,10 @@ flowchart TD
| Layer | Protection |
|---|---|
| Transport | Every Vault Agent ↔ Vault connection is TLS, certificate-verified |
-| Secrets at rest | KV v2, encrypted by Vault's storage layer; rendered files tightly permissioned, root-owned, gitignored |
-| Audit trail | Every request/response logged; secret values HMAC-hashed, not plaintext — what's visible is metadata: which token, which path, when |
+| Secrets at rest | KV v2, encrypted by Vault's storage layer; rendered files are `0600`, root-owned, gitignored |
+| Audit trail | Every request/response logged to a file audit device; secret values HMAC-hashed, not plaintext — what's visible is metadata: which token, which path, when. Rotated weekly, 8 generations kept. |
| Alerting | Root-token use or permission-denied bursts trigger an alert through [`docs/notifications.md`](notifications.md)'s pipeline |
-| Cert renewal reliability | A dependent service's TLS bundle auto-rebuilds when its cert re-issues, guarded to skip unless under a week from expiry |
+| Cert renewal reliability | Technitium's DNS-over-TLS/DoH cert bundle auto-rebuilds whenever Vault Agent re-renders its certs, guarded to skip unless under 7 days from expiry. This closed a real prior gap: the rebuild never used to happen automatically, and an expired cert was silently served for 19 days before anyone caught it. |
## Known gaps, ranked by actual risk — not a flat list