Overview
Mercentia is built as a multi-tenant SaaS. Every merchant's data is isolated at the database layer, encrypted in transit and at rest, and accessed only through the gateway's authenticated API. We never see cardholder data — the payment processor handles that.
This page is the current operational reality. The compliance roadmap at the bottom describes the external attestations in progress.
Authentication
- Better Auth with argon2id password hashing. Passwords are never stored in plaintext; the hash is salted and tuned per OWASP 2025 guidance.
- Session cookies — HttpOnly, Secure, SameSite=Lax, 5-minute liveness receipt with backend revalidation. Refreshing sessions doesn't extend cookie lifetime indefinitely.
- Magic-link sign-in for passwordless flows. Links expire after 15 minutes and are single-use.
- 2FA via TOTP (Google Authenticator, 1Password, Authy) available on every account.
- SAML SSO + SCIM provisioning on Enterprise plans.
- Per-IP rate limiting on every authentication endpoint — 20 attempts / 15 minutes on sign-in; 5 / hour on account creation.
Tenant isolation
Every table containing merchant data carries an org_id column, and PostgreSQL row-level security policies enforce that the current request can only read or write rows where org_id matches the authenticated organisation. The policy is set per-transaction by the gateway middleware — there is no application code path that can bypass it.
Cross-tenant aggregations (peer benchmarks, network insights) require explicit opt-in via the stores.analytics_opt_in flag, are k-anonymised with a minimum cohort size of 5, and never expose individual-store identifiers.
Encryption
- In transit: TLS 1.2+ everywhere; TLS 1.3 preferred. HSTS, modern cipher suites.
- At rest: AES-256 via the managed database (Neon) and object-storage (S3-compatible) providers.
- Secrets: provider-managed (Railway env vars, never committed). API keys are sha256-hashed; only the prefix is stored.
- Database backups: encrypted, point-in-time recovery 7-day window, full restore SLA < 4h.
Payments and PCI scope
Mercentia never touches card data. We use hosted payment elements from Stripe (global), Razorpay (India), and Paystack (West Africa). The merchant's customer enters card details directly into the processor's iframe; we receive a tokenised reference (e.g. pm_*) that lets us charge / refund / authenticate without ever seeing the PAN, CVV, or expiry.
That puts Mercentia in PCI DSS Self-Assessment Questionnaire A scope — the lightest tier, for merchants who fully outsource cardholder data handling. We complete SAQ A annually. Merchants on Mercentia inherit this scope: by using our hosted checkout you stay in SAQ A scope too.
Audit log
Every state-changing API call writes a row to the staff_audit_log table: who did it, when, from which IP, what changed, and (for risky operations) the explicit confirmation token. The log is append-only, retained for 7 years, and searchable from the dashboard.
GDPR data-subject requests (export, erase, consent updates) are recorded the same way and mapped to the relevant GDPR article in the metadata — Article 17, 20, 15, 7.
Infrastructure
- Application hosting: Railway (UK / EU primary regions)
- Database: Neon (managed PostgreSQL, Frankfurt)
- CDN + edge: Cloudflare
- Email: Resend
- AI: Anthropic (Claude); inputs not used for external training
- Dependency hygiene: Renovate-style upgrades, npm audit on every CI run, blocking on high-severity CVEs.
Access controls
- Production access is limited to the engineering team; every console session is logged.
- Database read access in production requires explicit ticketed approval. No standing read access for engineers.
- Customer support staff use a dedicated read-mostly admin role with redacted PII by default.
- Background jobs and webhook handlers run with the minimum scope required for the task.
- Service-account credentials are rotated quarterly or on personnel change, whichever sooner.
Incident response
Detection: synthetic checkout monitoring every 60 seconds, error-rate alerting on the gateway, anomaly detection on auth + payment endpoints.
Response: on-call engineer paged for any severity-1; incident commander + comms lead assigned for severity-1 and -2. Affected merchants notified within 72 hours for any incident involving personal data (GDPR Article 33). Post-mortem published within 14 days on the status page.
Compliance roadmap
| Framework | Status | ETA |
|---|
| GDPR / CCPA / CPRA | Aligned — DSAR endpoints, audit log, consent ledger, sub-processor list, DPA available | Now |
| PCI DSS SAQ A | In scope — Stripe / Razorpay / Paystack hosted elements only | Annual self-assessment |
| SOC 2 Type I | In progress — control framework documented, gap remediation in flight | Q3 2026 |
| SOC 2 Type II | Planned — observation window opens after Type I attestation | Q2 2027 |
| ISO 27001 | Planned — initiated after SOC 2 Type II | 2027–2028 |
We will not claim a SOC 2 / ISO 27001 attestation until we have the signed report. Enterprise prospects under an NDA can request the in-flight gap-remediation document at [email protected].
Reporting a vulnerability
We run a coordinated-disclosure programme. Email [email protected] with reproduction steps. We acknowledge within 48 hours, triage within 5 business days, and fix high-severity issues within 14 days. Researchers who responsibly disclose get credited on this page with permission.