Security
We're Weft. We're a small team and we're transparent about exactly what we do. No SOC 2 yet — here's what's actually in place today.
Tenant isolation
Every tenant-rooted database table carries an org_id with
a NOT NULL constraint and a leading-org_id
composite index. A SQLAlchemy event hook injects
org_id = current_org_id into every SELECT,
UPDATE, and DELETE; admins can opt out for
cross-org operations behind an explicit unscoped() guard.
Sub-account access is further scoped per shop with the same hook.
Integration tests prove cross-tenant queries return zero rows.
Auth
- Argon2id password hashing (rehash-on-verify when settings change)
- Server-side sessions: cookie carries the token, DB stores SHA-256
- Magic links (single-use, 15-minute TTL)
- TOTP 2FA available; SSO/SAML via WorkOS on Enterprise
- Constant-time login: same path whether the user exists or not
Data
- Postgres in the EU. Daily backups to an off-site bucket.
- Attachments encrypted at rest, per-tenant key prefix
- Pre-signed URLs (15-min TTL); attachments never proxied via the app
- Right-to-delete: 7-day soft delete + 30-day hard delete worker
- Data residency: EU by default. EU-only on Enterprise (audited path)
Hosted mail
- Stalwart (Rust, async) for IMAP/SMTP/JMAP
- SPF + DKIM + DMARC alignment on every outbound message
- Per-domain reputation monitoring (Postmaster Tools, AOL/M365 FBLs)
- Hard-bounce + complaint thresholds rate-limit a tenant before reputation hits other tenants
- SMTP creds stored Argon2-hashed; never displayed to the user
Webhooks
Stripe, Shopify, and Slack webhooks are all HMAC-verified against the raw request body. Replay window of 5 minutes on Slack. Failed verifications never touch the database.
In transit
HTTPS only on app.weftforge.com. HSTS preload. CSP
enforced. CSRF double-submit cookie on every state-changing route
(webhooks exempt; HMAC instead).
Reporting an issue
Email [email protected]. We respond within 1 business day. Coordinated disclosure preferred.