Data encryption
In transit
All data is encrypted in transit using TLS 1.2+. API endpoints enforce HTTPS. WebSocket connections use WSS with JWT authentication.At rest
- Files are stored in AWS S3 with AES-256 server-side encryption (SSE-S3)
- Database is PostgreSQL with encrypted connections
- Sensitive fields (refresh tokens) are stored as SHA-256 hashes
Passwords
- All passwords are hashed with bcrypt (cost factor 12)
- Minimum password length: 12 characters
- Plaintext passwords are never stored, logged, or transmitted
- 3-layer password detection system prevents accidental upload of files containing raw passwords
Tenant isolation
ORCA enforces strict multi-tenant data isolation:- Every database query includes an
org_idfilter — no exceptions - S3 keys are namespaced under
{prefix}/{org_id}/— cross-tenant access is architecturally impossible - API endpoints verify org membership before returning any data
- Admin endpoints additionally verify
role='admin'
There is no mechanism to query, access, or download another organisation’s data, even with a valid session token.
Authentication
JWT tokens
- Access tokens are short-lived JWTs
- Refresh tokens are stored as SHA-256 hashes in the database
- JWT secrets are minimum 64 characters
- Session invalidation on logout is mandatory
Two-factor authentication (2FA)
- TOTP-based 2FA using authenticator apps (Google Authenticator, Authy, etc.)
- Backup codes provided at setup
- Cannot be bypassed — if enabled, 2FA is required for every login
Single sign-on (SSO)
- SAML 2.0 and OIDC support
- SSO enforcement option (disables password login for the org)
- JIT user provisioning from IdP attributes
Rate limiting
Authentication endpoints are rate-limited to prevent brute-force attacks:| Endpoint | Rate limit |
|---|---|
/auth/login | Strict per-IP limiting |
/auth/register | Strict per-IP limiting |
/auth/verify-email | Strict per-IP limiting |
/auth/2fa/complete | Strict per-IP limiting |
/files/prescan | Per-user limiting |
| WebSocket connections | 30/min per IP, 10-min timeout |
GDPR compliance
PII detection
ORCA automatically detects GDPR-sensitive columns across 14+ categories:- Email addresses, phone numbers, names, addresses
- National IDs (SSN, Swedish personnummer)
- Financial data (IBAN, credit card numbers)
- Health data, dates of birth, IP addresses
Data masking
Sample values sent to the AI classification engine are masked for GDPR-sensitive columns. The masking layer (pii_masker.py) is mandatory and cannot be bypassed.
Data retention
- Default retention policy:
analysis_only(results kept, raw data available for re-analysis) - GDPR toggle defaults to ON for PII detection
- File deletion from S3 is synchronous and confirmed
- Data subject access and deletion requests can be fulfilled via the API
Password detection
A 3-layer system prevents accidental upload of files containing raw passwords:Audit logging
All security-relevant events are logged to an append-only audit log:login,logout,login_failedregister,email_verified2fa_enabled,2fa_disabledfile_uploaded,job_created,job_completed,job_startedfiles_deleted,file_rejected_raw_passwordgdpr_check_disabledcredits_addedcertificate_issued,remediation_applied
Audit logs cannot be modified or deleted. Each entry includes timestamp, user ID, org ID, IP address, and event-specific metadata.
Infrastructure
| Component | Provider | Purpose |
|---|---|---|
| Application | Railway | Backend hosting, auto-scaling |
| Database | Supabase (PostgreSQL) | Primary data store |
| Cache | Redis | Session cache, rate limiting |
| File storage | AWS S3 | Encrypted file storage |
| AI engine | Google Gemini | Semantic classification |
| Payments | Stripe | Billing and subscriptions |
Security headers
All API responses include:X-Content-Type-Options: nosniffX-Frame-Options: DENYStrict-Transport-Security(HSTS)- CORS configured for allowed origins only
- WebSocket origin validation