Security & data handling
Where data lives
- Application + database — AWS Lightsail in ap-south-1 (Mumbai). Single primary, no replicas yet.
- Document uploads (Paperbrief) — S3 bucket
paperbrief-documents-*, also in ap-south-1, server-side encrypted (AES-256), public access blocked. - Analysis reports (Cloudbrief) — S3 bucket
analyzer-reports-*, same protections. - Secrets — AWS Systems Manager Parameter Store, SecureString (KMS-encrypted) for API keys (Anthropic, OpenAI), DB password, and pgcrypto master key.
What we encrypt at rest
| What | How |
|---|---|
| Document files (Paperbrief) | S3 server-side AES-256 |
| Reports (Cloudbrief) | S3 server-side AES-256 |
| AWS credentials you upload (Cloudbrief) | pgcrypto column-encryption with a key only the application reads |
| User passwords | bcrypt with per-user salt |
| TOTP secrets (2FA) | column-encrypted, same key as AWS credentials |
| Origin TLS cert + key | SSM SecureString, fetched at deploy time |
What we pass to AI providers
- Anthropic (Claude) for chat answers (Paperbrief), document OCR (Paperbrief), and analysis synthesis (Cloudbrief).
- OpenAI (text-embedding-3-small) for embeddings (Paperbrief query + document chunks).
Per provider published policy, API inputs are not used to train models. We do not opt into any training-data programs.
We don't send PII, AWS account IDs, or credentials to AI providers beyond what's strictly needed to answer the question (e.g. Cloudbrief sends Cost Explorer numbers + service names, not your AWS account ID).
Tenant isolation
Every multi-tenant table has an org_id foreign key with a CASCADE delete. Application queries always filter by the caller's org_id; this is enforced at the route handler level and audited by tests.
Specific guarantees:
- A user in org A can never read another org's documents, chunks, conversations, reports, AWS accounts, or runs — DB queries are scoped, not just UI filters.
- Cloudbrief daily email recipients come from the org's account row only. There is intentionally no platform-wide default-recipients fallback (a missing recipient list skips the email rather than emailing the wrong person).
- S3 keys are prefixed by
org_id. Even if an IAM policy somehow broadened, an org's content lives at a distinct key prefix.
The full audit lives in AWS-Connector/docs/SECURITY-TENANCY.md in the product repo.
Auth + session
- JWTs via fastapi-users (opens in a new tab). 24-hour lifetime.
- Optional TOTP-based 2FA (see Accounts). When enabled, the session also requires a fresh TOTP verification per signin.
- Sessions are stored client-side as bearer tokens (
localStorage). No server-side session table; the JWT carries the user id.
Network
- All public traffic terminates at Cloudflare's edge.
- Cloudflare ↔ origin uses
strictSSL — Cloudflare validates the origin cert against Cloudflare's Origin CA root before forwarding. - Origin only listens on 443 (HTTPS), with 80 redirecting to 443.
What we don't have yet
- SOC2 / ISO27001 audit. We're pre-Series-A; not on the immediate roadmap.
- Customer-managed encryption keys (CMK) for the bucket. Single org request would prioritise.
- Per-region data residency. All data is ap-south-1 today.
- Dedicated infrastructure / single-tenant deployment. Available on a custom contract — email us.
Reporting a vulnerability
Email manish.gaud@bhavitech.com with subject SECURITY:. We'll respond within one business day and credit you publicly if you'd like once the issue is fixed.