# 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