What we do — and what we don't.
Honest overview. No 'bank-grade' theatre.
Tenant isolation
Every domain document carries org_id. All read/write paths go through a shared FastAPI dependency (require_org) that resolves the caller's org from the JWT — the client never supplies its own. We include cross-tenant tests in the backend suite.
Authentication
Bcrypt password hashing (12 rounds). Sessions use a short-lived access token delivered as a Secure, HttpOnly cookie (not readable by JavaScript) plus a readable CSRF token for double-submit protection on state-changing requests. Rate limits on /api/auth/login (10 attempts / 5 min per IP) and /api/auth/signup. Optional TOTP-based MFA with 8 one-time backup codes (sha256-hashed); MFA fails closed in production.
Impersonation
Founder support access requires a written reason (min 6 chars), returns a short-lived 30-min JWT scoped to the target org, is audited on start / end / every mutating action, and shows a persistent banner in the tenant UI.
Portal tokens & webhooks
Booking / quote / invoice portal tokens are 24-byte URL-safe secrets, compared in constant time. Outbound webhooks are HMAC-SHA256 signed with a 5-minute replay window.
Data export & deletion
Owners can download a full org-scoped JSON ZIP export any time, or schedule a soft-delete with a 30-day grace window.