Request authentication
Every order-scoring request is authenticated by an API key plus an HMAC-SHA256 signature over a canonical string built from the timestamp, a nonce, and the body.
canonical = "{timestamp}.{nonce}.{body}"
signature = hmac_sha256(hmac_secret, canonical).hexdigest()- API keys are hashed (bcrypt) in storage; only an 8-char prefix is recoverable.
- HMAC secrets are shown once at creation. Rotation issues a fresh secret without disrupting in-flight requests.
- Timestamp skew beyond 300 s rejects with 401.
- Nonces are stored in Redis with atomic
SET NX EX; replays return 401. - Bad-signature requests release the nonce so legitimate retries aren't blocked.
Tenant isolation
Every row in every table is keyed on store_id or merchant_id. The API enforces this at the dependency layer — handlers receive a pre-scoped query factory; cross-tenant access requires an explicit superadmin path with audit logging.
AI scoring never shares context across tenants. Each store's data — including rule wording — stays in that tenant's isolated workspace and is never used as training data for other tenants.
Dashboard authentication
The dashboard uses short-lived JWTs in HttpOnly cookies, with refresh-token rotation:
- Access token — 15 min, in the
fcc_accesscookie. - Refresh token — 7 days, single-use, in the
fcc_refreshcookie. Reuse revokes the entire token family. - Cookies scoped to
.fraudcommandcenter.comsologin.*andmcp.*share session.
Multi-factor authentication
TOTP-based MFA is available on every account. Enable it in Settings → Security. Once enabled, login is a two-step flow: password → MFA challenge token → TOTP code. Recovery codes are issued at enrolment and stored as bcrypt hashes.
Reset and verification tokens
Password reset, email verification, and MFA challenge tokens are stored as SHA-256(jti) — never raw. Every token is single-use, with explicit TTLs (1 h reset, 24 h email verify, 10 min MFA challenge). A DB dump is useless on its own.
User-enumeration protection
Login and signup endpoints respond uniformly whether or not the account exists. The login path runs a dummy bcrypt verify on misses to keep timing constant. The signup path emails the existing owner a notice on duplicate attempts instead of revealing the account exists to the attempted signup.
Audit logging
Every privileged action — auth events, settings changes, impersonation, rule mutations, review decisions — writes to an append-only audit_logs table. Visible to merchant admins in Settings → Audit log.
Data retention
- Shadow: 90 days.
- Starter: 1 year.
- Growth: 2 years.
- Pro / Enterprise: unlimited.
Beyond the retention window, transaction payloads are deleted; aggregated scoring metrics are kept indefinitely for the dashboard's historical trend charts.
Reporting a vulnerability
Please email [email protected]. We respond within one business day. Please don't publicly disclose until we've shipped a fix.