Data retention
What Foyer stores, how long, and what happens on a STOP or a deletion request. The numbers are deliberately conservative for a portfolio demo; a real engagement would size them against the buyer's actual regulatory posture.
What is hot and what is cold
Hot data is in the live Postgres database, indexed for lookup. Cold data is in S3 as JSON exports under business-keyed prefixes — readable with a restore script, not a query.
| Table | Hot retention | After |
|---|---|---|
messages (text + attachments) | 18 months | Anonymized in place — phone hashed, text scrubbed. Photos deleted from S3. |
conversations | 18 months | Archived to S3, kept 3 years. |
bookings | 3 years | Archived to S3, kept 7 years. |
audit_log | 1 year | Archived to S3, kept 7 years. |
consent_state + consent_changes | Indefinite | Required for TCPA dispute defense. |
STOP-driven suppression
When a customer texts STOP, the consent state for (customer_phone, twilio_number) flips to stoppedand outbound on that pair is permanently suppressed. No marketing follow-up, no “just one more” message, no retry on START except a customer-initiated START reply (which is the only thing that flips the state back).
Suppression applies across channels: a STOP’d phone cannot resume an SMS conversation via the web widget. The widget receives a consent_blocked response and renders a static notice.
Anonymization on deletion request
A documented deletion request triggers the anonymization path:
- Customer phone in
messagesandconversationsis replaced with a per-business salted SHA-256. - Message text in
messagesis replaced with a phase marker. Intents are kept (the structured fields), free text is gone. - Photo S3 objects are deleted; the S3 keys in
messages.attachmentsare nulled out. - Address, lat/lng on
bookingsare truncated to ZIP-3 + city.
Consent records are preserved. TCPA dispute defense requires Foyer to be able to demonstrate when consent was given and when it was withdrawn; anonymizing them would defeat the only protection the business has against a complaint.
Photo storage specifics
Customer-supplied photos (MMS or web upload) are re-encoded to JPEG through Intervention\Image, stripped of EXIF, and uploaded under a UUIDv7 key with a private ACL: s3://foyer-photos/<business_id>/<uuid>.jpg. The owner dashboard displays via pre-signed URLs with a 5-minute TTL. Photos count under the messages.attachments retention clock and are deleted from S3 at anonymization time.
Backups
Nightly Postgres dumps land in the S3 backup bucket, encrypted server-side with AWS-managed KMS. Backup retention is 30 days. A backup is, by definition, a copy of the hot database — anonymization applied to the live row does not retroactively scrub historical backups. The deletion-request runbook says so explicitly so the buyer understands the trade-off: backups can be re-cut after anonymization, but pre-anonymization snapshots are kept until their natural 30-day expiry.
Owner data
Owner accounts, businesses, and scope configuration are kept for the life of the engagement plus 90 days for dispute defense. Owner OAuth refresh tokens are revoked when the engagement ends; the Calendar API side reflects that within hours.
What this page is and is not
This is the floor for a portfolio demo. A real production deployment would size retention against the buyer’s state-level privacy regime (CCPA, CPRA, others), their insurance posture, and any carrier-specific requirements. The numbers above are conservative defaults — not legal advice.