Skip to main content

Data handling & PII

What user data lives in the marketplace DB

DataTablePurpose
Email, name, imageuserAuth + display
Hashed passworduser (via better-auth)Auth — bcrypt cost ≥ 12
Session tokenssessionHttpOnly cookies, no client access
OAuth refresh tokensaccount (better-auth)Cross-agent SSO
Subscription metadatauser_agent_subscriptionsBilling
ReviewsreviewsPublic on agent detail page
Waitlist emailagent_waitlistMarketing
Interaction emailsinteractionsMarketing notification fan-out
Audit log (PostHog)externalRequest metadata, no bodies

The marketplace does not store:

  • Card numbers (Stripe holds them).
  • Conversation transcripts (the agent service holds them).
  • Agent-side runtime data (KBs, files, sessions).

What's in the audit log

AuditLogMiddleware records request metadata only:

  • requestId, userId, userRole, orgId
  • method, path, statusCode, errorCode, duration_ms
  • userAgent, ip

It does not record request bodies, response bodies, or query parameters. That's intentional — query params can carry sensitive data (?token=...), so logging them is risky.

If you add a new event source (e.g. business-level events), filter PII before logging.

PropertyValue
HttpOnlytrue (always)
Securetrue in production
SameSiteLax in dev, None cross-origin in prod
Path/
Max-Age30 days (better-auth default; configurable)

CORS

app.enableCors({
origin: config.frontendUrl.split(',').map(s => s.trim()),
credentials: true,
});

Explicit allow-list. No wildcards. credentials: true is required for cookie auth.

Deletion / right to be forgotten

Currently no built-in user-deletion endpoint. To honor a deletion request:

BEGIN;
DELETE FROM "session" WHERE user_id = '<id>';
DELETE FROM "account" WHERE user_id = '<id>';
UPDATE reviews SET user_id = NULL WHERE user_id = '<id>';
DELETE FROM user_agent_subscriptions WHERE user_id = '<id>';
DELETE FROM "user" WHERE id = '<id>';
COMMIT;

Cancel any active Stripe subscriptions separately:

stripe subscriptions list --customer <cus_...> | jq -r '.[].id' | xargs -I{} stripe subscriptions cancel {}

Build this into a self-service flow when GDPR / DPDP / CCPA pressure demands it. Until then, manual.

Encryption

  • In transit: TLS 1.2+ between every hop (browser ↔ ALB, ALB ↔ task, task ↔ RDS, task ↔ Stripe, task ↔ PostHog).
  • At rest: RDS storage encryption on; Secrets Manager KMS-encrypted; S3 buckets server-side encrypted.

Backup & retention

DataRetention
RDS PITR7 days
RDS snapshots30 days
CloudWatch logs30 days (set explicitly; default is forever)
PostHog eventsProject default (configurable per project)
Stripe eventsindefinite (Stripe side)

Adjust to match your compliance posture.

What agents are responsible for

Each agent service owns its own runtime data (knowledge bases, conversations, files). The marketplace explicitly does not see this. Each agent must publish its own privacy policy and handle its own data deletion.