first commit
This commit is contained in:
140
PROJECT.md
Normal file
140
PROJECT.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# Design Proposal: Zero-Knowledge Secrets Manager
|
||||
|
||||
## 1. Architectural Overview
|
||||
|
||||
**Philosophy:** "Thick Client, Blind Server."
|
||||
The system relies on a **Zero-Knowledge Architecture**. The server (Node.js/PostgREST) and the database never see unencrypted secrets; they act solely as a synchronization engine for encrypted blobs. All encryption/decryption occurs on the client device (Tauri/Flutter) using keys that never leave the device.
|
||||
|
||||
### High-Level Data Flow
|
||||
|
||||
1. **Client:** Derives Master Key from (Password + Salt). Encrypts data locally.
|
||||
2. **Transport:** Sends encrypted blob (text/bytea) over HTTPS.
|
||||
3. **Gateway:** Nginx/Traefik handles SSL termination and routing.
|
||||
4. **Auth:** Node.js verifies identity (SRP-6a) and issues JWT.
|
||||
5. **Persistence:** PostgREST accepts JWT, enforces Row-Level Security (RLS), and writes blob to PostgreSQL.
|
||||
|
||||
---
|
||||
|
||||
## 2. Component Design
|
||||
|
||||
### A. Database Layer (PostgreSQL v18+)
|
||||
|
||||
* **Role:** Storage and Authorization Engine.
|
||||
* **Logic:** Heavily utilizes Row-Level Security (RLS) policies.
|
||||
* **Schema Strategy:**
|
||||
* `users`: Stores `verifier` (SRP-6a) or hashed credentials (Argon2id).
|
||||
* `secrets`: Stores `encrypted_data` (bytea), `iv`, `auth_tag`, `owner_id`, `type` (manual/rotated).
|
||||
* `access_policies`: Join table mapping users/groups to secrets.
|
||||
* **Security:** RLS policies ensure `SELECT * FROM secrets` only returns rows where `auth.uid() IN (access_policies)`.
|
||||
|
||||
### B. Backend API (Node.js v24 + PostgREST)
|
||||
|
||||
* **Node.js Service:**
|
||||
* **Auth:** Implements SRP-6a (Secure Remote Password) protocol.
|
||||
* **Business Logic:** Handling billing, email alerts, secret rotation jobs, and external webhooks.
|
||||
* **Orchestration:** Manages Redis interactions for ephemeral state.
|
||||
* **PostgREST:**
|
||||
* High-performance CRUD layer.
|
||||
* Directly exposes secure views/tables.
|
||||
* Consumes JWTs issued by the Node.js service for authorization.
|
||||
|
||||
### C. Caching & State (Redis Cluster v8)
|
||||
|
||||
* **Image Source:** Official `redis:alpine` (replacing deprecated Bitnami images).
|
||||
* **Revocation Lists:** Stores revoked JWT JTI claims.
|
||||
* **Rate Limiting:** Distributed counters to block brute-force attacks.
|
||||
* **Pub/Sub:** Real-time event bus to trigger client syncs (e.g., "Vault Updated").
|
||||
|
||||
### D. Clients (Tauri & Flutter)
|
||||
|
||||
* **Desktop (Tauri):**
|
||||
* **Security:** Encryption logic (AES-256-GCM / XChaCha20-Poly1305) runs in the Rust backend to prevent memory dumping attacks via browser dev tools.
|
||||
* **Offline:** Encrypted SQLite local replica.
|
||||
* **Mobile (Flutter):**
|
||||
* **Storage:** Uses `flutter_secure_storage` for session tokens.
|
||||
* **Bio-auth:** Integrates FaceID/Fingerprint to unlock the local vault key.
|
||||
|
||||
---
|
||||
|
||||
## 3. Workflows
|
||||
|
||||
### A. Manual Secret Entry (Core Feature)
|
||||
|
||||
This is the standard workflow for storing static API keys, passwords, or notes.
|
||||
|
||||
1. **User Input:** User enters data (e.g., `API_KEY=12345`) into the client form.
|
||||
2. **Client Encryption:** The App (Tauri/Flutter) generates a random IV and encrypts the payload using the user's Master Key *in memory*.
|
||||
3. **Payload Construction:** Client creates a JSON payload: `{"iv": "...", "data": "encrypted_blob...", "type": "manual"}`.
|
||||
4. **Sync:** Client POSTs the payload to PostgREST.
|
||||
5. **Storage:** Database stores the blob. The server never sees `12345`.
|
||||
|
||||
### B. Automated Rotation (Enhancement)
|
||||
|
||||
1. **Trigger:** Cron job in Node.js wakes up.
|
||||
2. **Execution:** Connects to provider (e.g., AWS), generates new keys.
|
||||
3. **Encryption:** *Note: This requires a separate "Server-Side Vault" mechanism or Public Key encryption if the server needs to write secrets readable by the user.*
|
||||
4. **Update:** Updates the `secrets` row with the new encrypted blob.
|
||||
|
||||
---
|
||||
|
||||
## 4. Cryptography Standards
|
||||
|
||||
* **KDF:** Argon2id (memory-hard) for deriving Master Key.
|
||||
* **Symmetric:** AES-256-GCM or XChaCha20-Poly1305 for vault data.
|
||||
* **Asymmetric:** RSA-4096 or ECC (Curve25519) for sharing secrets between users.
|
||||
* **Transport:** TLS 1.3 only.
|
||||
|
||||
---
|
||||
|
||||
## 5. Infrastructure (Docker Compose Prototype)
|
||||
|
||||
*Note: Switched to official Redis images due to Bitnami Docker Hub deprecation.*
|
||||
|
||||
```yaml
|
||||
version: '3.9'
|
||||
services:
|
||||
# Load Balancer / SSL Termination
|
||||
gateway:
|
||||
image: nginx:alpine
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
depends_on:
|
||||
- api
|
||||
- postgrest
|
||||
|
||||
# The Logic Core
|
||||
api:
|
||||
image: node:24-alpine
|
||||
environment:
|
||||
- DATABASE_URL=postgres://user:pass@db:5432/secrets_db
|
||||
- REDIS_URL=redis://redis:6379
|
||||
- JWT_SECRET=${JWT_SECRET}
|
||||
|
||||
# The Data Interface
|
||||
postgrest:
|
||||
image: postgrest/postgrest:latest
|
||||
environment:
|
||||
- PGRST_DB_URI=postgres://user:pass@db:5432/secrets_db
|
||||
- PGRST_JWT_SECRET=${JWT_SECRET}
|
||||
- PGRST_DB_SCHEMA=api
|
||||
- PGRST_DB_ANON_ROLE=web_anon
|
||||
|
||||
# The Vault
|
||||
db:
|
||||
image: postgres:18
|
||||
volumes:
|
||||
- pg_data:/var/lib/postgresql/data
|
||||
environment:
|
||||
- POSTGRES_DB=secrets_db
|
||||
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
||||
|
||||
# The High-Speed State (Official Image)
|
||||
# For a full cluster in dev, you may need a custom entrypoint or sidecar
|
||||
# to bootstrap the slots. For simplicity here, we use a standalone instance
|
||||
# that mimics the interface.
|
||||
redis:
|
||||
image: redis:alpine
|
||||
command: redis-server --appendonly yes
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
Reference in New Issue
Block a user