Security

Built for operational trust.

What we protect, how we protect it, and, honestly, what we don't have yet. Updated as the posture evolves.

Encrypted credentials

Your Stripe secret key never sits in plaintext at rest. AES-256 envelope encryption with a per-deployment master key, TraceTxn operators can't read your Stripe key from the database, full stop.

  • Per-org `gateway_credentials` row, your key never mingles with another tenant's
  • Webhook signing-secret captured at registration time + stored encrypted
  • Decryption only at request scope, never logged
  • Loss of the master key locks all encrypted rows, rotation is documented

Hashed evidence chain

Every state change on every order appends a SHA-256-linked event. The chain is append-only at the model layer, service-layer bugs can't silently rewrite history.

  • Each event hash includes the previous event's hash (Merkle-style)
  • Update hooks throw on any `findOneAndUpdate` against evidence
  • Chain verification surfaced in-product on every order detail
  • Tamper-evident exports the cardholder's bank can re-verify

Tenant isolation

Every business-data row carries `orgId`. Lookup-by-id pins both `_id` AND `orgId` at the query layer, so a Tenant-A actor holding a guessed Tenant-B id gets a clean 404, not a real document.

  • 18 business-data collections carry orgId at the schema layer
  • Child models (disputes, evidence, consent, drafts, outbox) all carry orgId
  • Cross-tenant tests in CI prove id-guesses fail
  • Per-tenant indexes on every business collection

Auth + access control

Firebase Auth for sign-in (Google + email/password), short-lived signed JWT cookie for the session. Every protected route runs through a proxy that verifies the JWT signature, role, and org membership before the handler sees the request.

  • Firebase ID-token → server-verified → minted JWT (jose, HS256, 12h)
  • Strict same-site cookies, HttpOnly, Secure in prod
  • RBAC: SUPER_ADMIN → ADMIN → STAFF, granted via the permission matrix
  • Tenant-aware: every request resolves the actor's active org before the handler runs

Webhook integrity

Stripe webhooks are verified against your per-org signing secret BEFORE the handler runs. Replays + double-deliveries dedupe against a durable `processed_webhook_events` collection, not the order doc.

  • Per-org signing secret captured at Stripe connect, encrypted at rest
  • Idempotent on three axes: event id, processed-marker, and status guard
  • Concurrent webhook + reconcile races collapse at the unique index
  • Webhook health check + repair surfaced in the admin Gateways page

Bot protection + abuse defense

Cloudflare Turnstile gates every public form (login, signup, quotation, contact). Rate-limits at the request layer protect the auth + payment-exchange endpoints from credential-stuffing.

  • Turnstile-required on login + signup + waitlist forms
  • Per-route rate limits with IP-derived keys
  • Session-cookie hash mixed into rate-limit keys for finer-grained control
  • CSP locked down to `self` + explicitly whitelisted third parties

What we don't have yet

Honest about the gaps.

Most startup security pages claim certifications they don't have. We'd rather just tell you.

  • Not SOC 2 certified yet

    We're early. We don't have a SOC 2 Type II report, and we won't claim we do. Compliance pursuit starts when we have the customer volume to justify the audit cost.

  • Single-region deployment

    Today we run in one DigitalOcean region with daily Mongo Atlas snapshots. Multi-region failover is on the roadmap when paying tenant density crosses the threshold that justifies the operational overhead.

  • No third-party pentest yet

    We've done internal threat modelling + code review. A formal third-party penetration test is scheduled before we open the Scale tier to enterprise customers.

  • PCI scope: we never touch card data

    TraceTxn is BYOS-Stripe, Stripe takes the card data, not us. We never see, store, or process card numbers. PCI scope sits with Stripe and your business directly, not TraceTxn.

Responsible disclosure

Found something? Tell us first.

If you believe you've found a security vulnerability in TraceTxn, please email us before disclosing publicly. We acknowledge within 48 hours and ship the fix as soon as it's validated. We don't run a paid bug-bounty yet - public hall-of-fame credit is the recognition path today.

  • Acknowledgement within 48h
  • No legal action against good-faith research
  • Coordinated public disclosure once the fix ships
Email security
[email protected]

PGP key on request. Include reproduction steps, affected endpoint, and your preferred name for disclosure credit.

Open mail client →

Open a workspace in 3 minutes

Build bulletproof payment operations.

Connect your core stack, eliminate fragmented tracking gaps, and protect your merchant processing pipeline. No call required. No engineer required.