Data Handling Policy
Conduit is designed as a governance proxy — MLS listing data transits through the system but is never persisted. This document describes how each data category is classified, stored, encrypted, and deleted.
Data classification
| Category | Examples | Storage | Sensitivity |
|---|---|---|---|
| Transit data | MLS listing records, property details, agent info | Never stored — transits through proxy only | High |
| Audit metadata | Request counts, latency, status codes, field filter actions | Supabase PostgreSQL (append-only) | Medium |
| Revenue records | Query costs, MLS/Conduit share, billing periods | Supabase PostgreSQL | Medium |
| Organization data | Org name, plan, MLS/vendor profiles, policies | Supabase PostgreSQL | Medium |
| Auth credentials | API key hashes, OAuth tokens, session data | Supabase PostgreSQL + Cloudflare KV (cache) | High |
| Billing data | Stripe customer IDs, subscription status, payout records | Stripe (primary) + Supabase (references) | High |
What Conduit does NOT store
Conduit is a governance proxy, not a data warehouse. The following are never persisted:
- MLS listing data (property records, photos, agent details)
- Upstream MLS API responses (request bodies or response bodies)
- Plaintext API keys (only SHA-256 hashes are stored)
- User passwords (authentication is delegated to Supabase Auth / GitHub OAuth)
- Credit card numbers or payment details (handled entirely by Stripe)
- Vendor query content or search parameters
Encryption
At rest — All data stored in Supabase PostgreSQL is encrypted at rest using AES-256, managed by Supabase's infrastructure. Stripe stores billing data with PCI DSS Level 1 encryption.
In transit — All connections use TLS 1.2 or higher. This applies to: client → Cloudflare (proxy), client → Vercel (web app), proxy → Supabase (database lookups), proxy → MLS upstream server, web app → Stripe API.
API keys — Hashed with SHA-256 before storage. The original key is shown once at creation and cannot be retrieved.
Data deletion
Organization deletion — When an organization is deleted, all associated data is cascade-deleted: users, API keys, MCP servers, billing periods, usage events, and webhook configurations. Audit logs in mls_audit_log are retained for compliance (append-only, no delete).
Vendor suspension — When an MLS suspends a vendor via the kill switch, the vendor's access is revoked but data is preserved for audit purposes. The vendor can be reinstated.
API key revocation — Revoking a key sets its status to revoked and the key hash is invalidated in KV cache. The key record is retained for audit.
Third-party data processors
| Processor | Purpose | Data accessed | Certifications |
|---|---|---|---|
| Supabase | Database, authentication | Org data, auth, audit logs, revenue records | SOC 2 Type II, HIPAA |
| Cloudflare | Gateway proxy, KV store, edge compute | Request metadata, rate limit counters, API key cache | SOC 2 Type II, ISO 27001 |
| Vercel | Web application hosting, serverless functions | Application code, session cookies | SOC 2 Type II |
| Stripe | Payment processing, MLS payouts | Customer IDs, subscription status, payout amounts | PCI DSS Level 1, SOC 2 Type II |
Known improvement areas
[i]Honest disclosure
Upstream MLS auth configuration
The upstream_auth_config field in the MCP servers table stores upstream MLS credentials in plaintext JSON. This should be migrated to an encrypted secrets manager (e.g., Supabase Vault or AWS Secrets Manager). Current mitigation: RLS restricts access to the owning organization, and the proxy reads credentials server-side only.
Audit log retention policy
Audit logs are currently retained indefinitely. A formal retention schedule with automated archival to cold storage should be implemented before the audit log grows beyond practical query performance limits.
Rate limit counter durability
KV-based rate limit counters may lose accuracy during Cloudflare edge propagation delays. Current mitigation: on KV failure, the system defaults to allowing the request and classifying it as included (preventing phantom billing). This is a deliberate fail-open for availability, documented in the system design.