Security · last updated May 15, 2026
The most damaging thing a thief could steal from us is a list of email addresses.
Bribe was built so that even if every server we run got compromised, there's nothing a bank would want back. No card numbers. No passwords. No bank logins. Here's why.
Card numbers never touch us
When a customer links a card, the actual card number stays inside the card company's vault. We receive a token — a useless string of letters that only works for matching transactions at the specific venues that opted in to our program. The token is meaningless outside that closed loop. There is no card data on our infrastructure to steal, ever.
PCI-DSS out of scope, by design
We never receive, store, process, or transmit cardholder data. The Fidel SDK handles that side of the wall — their PCI-DSS Level 1 environment is certified and audited. Our role is to match the resulting tokens to merchant locations and issue rewards. We maintain a PCI-DSS SAQ A self-assessment to confirm we remain out of scope.
We don't have your password
Sign-in is delegated to Firebase Auth, which handles password hashing, two-factor authentication, account recovery, and session management. Our servers receive a customer UUID; the password never appears in our logs, our database, or our memory.
PII at rest, encrypted
Email and phone are encrypted with AES-256-GCM. Encryption keys are envelope-encrypted under AWS KMS root keys — a fresh Data Encryption Key is generated per tenant, the DEK is encrypted with KMS, and only the encrypted DEK is stored alongside the ciphertext. Decryption goes through KMS with full audit logging. DEKs rotate on a regular cadence.
Multi-tenant isolation in the database, not the application
Every tenant-scoped table is protected by PostgreSQL Row-Level Security
policies. The FastAPI role used in production is not a superuser. On every
request, the application sets app.current_tenant_id for the
transaction, and the database refuses to return rows from any other tenant
— even if a SQL-injection bug somewhere asked it to. The wall is in
Postgres, not in our application logic.
Webhooks: signed, deduplicated, idempotent
Every inbound Fidel webhook is signature-verified using double HMAC-SHA256 before we read the body. Every transaction is deduplicated by its Fidel transaction ID with a unique constraint at the database level — replays are no-ops. The webhook endpoint persists the event before returning 200, so a network blip can never lose a transaction.
Right to delete
One button in the app. Your encrypted PII columns are nulled, your linked cards are detached, your transactions are anonymized, and the row is marked deleted — all inside the same database transaction. A minimal compliance audit log of the deletion event itself is retained.
Compliance
- PCI-DSS SAQ A. Self-assessed and maintained.
- CCPA-ready. Right to know, right to delete, right to opt out of sale (we don't sell).
- GDPR-ready. Lawful basis tracked at signup, right to access, right to erasure.
- CAN-SPAM. Every marketing email has a working one-click unsubscribe.
Reporting a vulnerability? security@bribe.app. We respond within one business day. We don't sue researchers acting in good faith.