Security
Real claims, sourced.
We do not do "bank-grade" hand-waves. Every claim on this page links to a document or commit you can read. If we have not built something yet, you will find it in the roadmap with a date.
Identity Platform + TOTP 2FA
Sign-in goes through Google Identity Platform — the same identity service GCP uses internally. Customers can enroll a time-based authenticator code (Google Authenticator, 1Password, Authy) in Settings; once enrolled, sign-in requires the code.
Source: DEPLOYMENT.md §12
Database-level tenant isolation (Postgres RLS)
The application connects to Postgres as a least-privilege role (keobooks_api), and every client-scoped table has a row-level security policy keyed by client_id. Cross-tenant reads and writes are blocked by the database itself, not just the application code. A dedicated test asserts the negative case as part of every CI run.
Source: DEPLOYMENT.md §13
Direct-to-storage uploads (signed URLs)
Customer documents are uploaded directly to Google Cloud Storage using short-lived signed URLs. Bytes never pass through our API, the path is scoped by tenant, and the object name includes a SHA-256 hash for deduplication.
Source: DEPLOYMENT.md §14
Append-only audit trail
Every mutating request writes a row to an append-only audit_event table. The application role has SELECT and INSERT on this table; UPDATE and DELETE are explicitly revoked at the database layer, so an audit row cannot be altered or removed even with a SQL-injection foothold.
Source: 0001_init.sql
Encryption at rest, TLS in transit
Cloud SQL and Cloud Storage use Google-managed encryption at rest. All traffic to the API and web app is HTTPS-only. Customer-managed encryption keys (CMEK) are on the roadmap.
Source: Roadmap §Open questions
Secret management
Database credentials, API keys, and signing material live in Google Secret Manager and are mounted into Cloud Run at runtime — never committed to the repository. CI uses Workload Identity Federation for keyless deploys.
Source: DEPLOYMENT.md §4
Continuous secret scanning + dependency review
gitleaks runs on every push, CodeQL runs on every PR, and pnpm audit fails CI on high-severity findings. Every commit to main passes the integration suite as the non-owner database role, so authorization regressions surface immediately.
Source: ci.yml
Reporting a vulnerability
Found a security issue? Email security@keobooks.com with reproduction steps. We acknowledge within 24 hours and coordinate a fix and disclosure timeline with you.