Security

Security as a feature, not an afterthought.

Every tenant table runs Postgres row-level security with FORCE and WITH CHECK. Webhooks are signed and replay-resistant. The runtime database role cannot bypass RLS. We document everything at /trust.

Multi-tenant RLS. Stripe-grade webhook verification. Two-role Postgres separation.

live
Security
3 modules · part of Rekomi
By the numbers

What this surface delivers.

Security at a glance

Multi-tenant RLS. Stripe-grade webhook verification. Two-role Postgres separation.

3
Modules in scope

Built into Security

100%
Audit-log coverage

Every mutation, every actor

300s
Webhook replay window

HMAC-SHA256 verified

RLS
Tenant isolation

Enforced at the database

Impossible by design

Cross-tenant data leak isn't a bug we patch. The database refuses to allow it.

Every tenant-scoped table has a Postgres row-level security policy keyed to the current organization. The runtime role is NOSUPERUSER NOBYPASSRLS, so even if a query is malformed, no row from another tenant is returned. We test cross-tenant isolation in CI with Testcontainers.

  • FORCE ROW LEVEL SECURITY on every tenant table (15+ today)
  • WITH CHECK clause prevents cross-tenant inserts
  • Two-role Postgres: rekomi (superuser, migrations) and rekomi_app (runtime, NOSUPERUSER NOBYPASSRLS)
  • Cross-tenant isolation enforced by Testcontainers integration tests in CI
Module 01 of 03
Postgres RLS · tenant isolationenforced
-- enforced on every tenant table
ALTER TABLE programs FORCE ROW LEVEL SECURITY;
CREATE POLICY tenant_iso ON programs
USING (organization_id = current_setting('app.org')::uuid)
WITH CHECK (organization_id = current_setting('app.org')::uuid);
-- runtime role
SET ROLE rekomi_app; -- NOSUPERUSER NOBYPASSRLS
Protected tables
15+ · every tenant row
Isolation tests
verified in CI
Database-level enforcement · not app-layerNOSUPERUSER · NOBYPASSRLS
Webhooks that can't be forged or replayed

No one can fake a webhook or replay an old one.

Every webhook from Stripe and Clerk is verified by HMAC-SHA256 signature with a 300-second replay tolerance. We track every processed event ID per organization in billing_events with a UNIQUE index, so replays are no-ops. Failed signature checks return 401 silently and never reveal why.

  • Stripe webhooks: HMAC-SHA256 signature with 300s replay window
  • Clerk webhooks: Svix signature verification
  • Every event recorded to billing_events for idempotency and audit
  • Failed signature returns 401, never reveals which check failed
Module 02 of 03
Webhook verification · Stripe + Clerkverified
Incoming webhook
POST /api/stripe with signed payload
HMAC-SHA256 verified
Stripe-Signature header matches secret
300s replay window
Timestamp within tolerance
billing_events idempotency
UNIQUE event_id · replay is no-op
Failure mode
Bad signature → 401, no reason
Clerk webhooks
Same flow · Svix verified
HMAC-SHA256 · 300s toleranceIdempotent · audit-logged
Append-only, mutation-by-mutation

Every state change logged. Forever.

Audit log entries are written for every campaign create, affiliate invite, payout dispatch, billing event, AI co-pilot action, and admin override. The log is append-only, scoped to the organization, captures actor and action and target and timestamp and the request origin as seen at our edge, and is searchable from the admin app.

  • Append-only audit_log table per organization
  • Captures actor, action, target, timestamp, and the request origin as seen at our edge
  • Searchable from the admin app
  • Kept indefinitely for compliance review
Module 03 of 03
Audit log · org_acmeappend-only
program.createdbysam@acme.com
id=prog_4c2 · summer-2026
14:32:08 UTC
payout.dispatchedbysam@acme.com
8 affiliates · $24,917.00
14:35:21 UTC
affiliate.invitedbyai-copilot
kenji.sato@northwind.io
14:38:02 UTC
commission.adjustedbysam@acme.com
tier=gold · 35% → 28%
14:42:11 UTC
billing_event.recordedbystripe.webhook
evt_1Q… · charge.succeeded
14:44:53 UTC
Captured per entry
actor · action · target · request origin
Retention
Kept indefinitely
Append-only · cryptographically orderedExportable as CSV
FAQ

Common questions.

Where is data stored?

Postgres on a managed provider (production); the app and click-tracking API run on managed regional infrastructure. US region only today. EU hosting is on the roadmap.

Is data encrypted at rest?

Yes. AES-256 at rest, TLS 1.3 in transit. API key signing secrets are encrypted at rest via ASP.NET Core Data Protection. Field-level encryption of tax form identifying fields is a planned hardening step.

Do you have a SOC 2 report I can read?

Not yet. We do not claim a certification we do not yet hold. Our security model is documented in detail at /security and /trust. When an independent third-party audit completes, we will send the report under NDA on request.

What happens to my data if I cancel?

You can export your data at any time, before or after cancelling. On cancellation your data is retained so you can reactivate, and it is deleted on request or when you delete the account. Audit log entries about your organization are kept indefinitely for legal compliance.

Can I bring my own AWS / GCP / Azure?

Not currently. BYO-cloud is on the enterprise roadmap. We use a managed Postgres provider and Cloudflare for the edge. Both meet enterprise security baselines.

Is there a public bug bounty?

Not yet. A formal program is on the roadmap. Until then, please report security issues to support@rekomi.com and we will acknowledge within one business day.

Do you support SAML SSO?

Not yet. SAML SSO is on the enterprise roadmap. Today, Clerk handles authentication with email + password, magic link, and OAuth providers.

Also worth a look

Other parts of Rekomi.

Security is one of eight surfaces. Each is built on the same primitives - Stripe, Postgres with RLS, Clerk, Anthropic - and ships with the same audit and security bar.

Ready when you are

Ten minutes to first click.

14-day free trial. Native Stripe, Paddle, Braintree, and more. No card. Live this afternoon.

  • 14-day free trial
  • Cancel anytime, $0 charged