Security
This page details the technical and organizational measures in place to protect your data. It complements the Privacy Policy and the Data Processing Agreement (DPA).
Architecture
Multi-tenant isolation
Each customer company (tenant) is strictly isolated from the others at the database level:
- PostgreSQL Row Level Security enabled on every table containing
tenant_id. Policies use acurrent_tenant_id()function that reads a session variable. - Every server-side query goes through a
withTenant(tenantId, ...)helper that opens a transaction and sets the session variable BEFORE the query. No cross-tenant query is possible. - The API helpers (
withTenantApi) combine session check + role check + tenant scope. It's the mandatory pattern for every business route.
Authentication
- NextAuth.js v5 with Google SSO and single-use magic links for invited new hires.
- No standard Prisma adapter, because our multi-tenant model requires a
tenant_id + emailresolution (email alone is not unique across tenants). - Signed JWT tokens, 30-day rotation.
- Soft delete: a deleted user is anonymized and can no longer sign in, across all auth paths (SSO, Credentials, magic link).
Encryption
In transit
- TLS 1.3 mandatory on all HTTPS connections.
- Strict HSTS.
At rest
- AES-256 native on Supabase and Vercel (disk).
Application level (AI conversations)
Messages exchanged with the AI Companion assistant are encrypted at the application level before being stored in the database:
- AES-256-GCM algorithm with a random 12-byte IV and a 16-byte authentication tag.
- Per-tenant key derived via HKDF-SHA256 from a master key (environment variable, never committed).
- Stored format: base64 of a
[version | iv | authTag | ciphertext]payload. The version byte allows future rotation without a table migration. - Rolling read: older unencrypted (legacy) messages are read as-is until the full backfill is complete.
- Important consequence: losing the master key makes encrypted conversations unrecoverable. That is the strong confidentiality guarantee we provide to our customers.
Audit log
An immutable audit_logs table traces 14 sensitive actions:
- New-hire creation / modification / deletion
- Alert resolution
- AI persona modification
- Journey publishing / modification
- Tenant settings modification
- Badge creation / deletion
- 360° feedback submission
- Offboarding start
- GDPR export (Art. 20) with per-section counters
- GDPR deletion (Art. 17) with an email/role snapshot BEFORE anonymization
Each entry captures: action, entity type, ID, minimal payload, IP, user-agent, timestamp.
Rate limiting
- AI chat: rate-limited per user and per hour (sliding window over the
chat_messagestable). No external Redis — the database naturally enforces the limit with a(conversation_id, created_at)index. - AI journey generation: limited by the plan's Premium quota.
Backups and recovery
- PITR (Point-In-Time Recovery) on Supabase: 7 days.
- Daily snapshots.
- Restore tested quarterly.
GDPR
- Article 15 (access) and Article 20 (portability): full JSON export in one click via the HR interface.
- Article 17 (erasure): soft delete + immediate anonymization of PII. Neighboring data (chat, audit) becomes anonymous by derivation. No recovery possible — this is compliant and intentional.
- Article 33 (breach notification): contractual commitment to notify within 72 hours (see DPA § 6.5).
- Exhaustive list of subprocessors with their DPAs: /en/legal/sous-traitants.
Hosting
- Database: Supabase, EU Central 1 (Frankfurt, Germany) region.
- Web application: Vercel, EU West (Frankfurt) region.
- Transactional emails: Resend (US transit).
- Transfers to AI providers (Anthropic, OpenAI — United States) are governed by Standard Contractual Clauses and our additional clauses.
Reporting and contact
To report a vulnerability: security@weloom.ai. We commit to acknowledging receipt within 48 business hours and coordinating responsible disclosure.
For any security or GDPR question: dpo@weloom.ai.