GenLP Retention Schedule
Version 2026-10-20.
This schedule lists how long GenLP AI LLC keeps each category of data. The windows in bold are the owner's retention decisions of 2026-10-20 (OQ-25, OQ-26, OQ-30). "Implementation" names the code or setting that enforces each period, so the schedule can be checked against the product. Where it says "report-only", the automatic deletion lane exists but only counts rows until ops.killswitch.retention.delete is turned off and the lane is moved to mode: delete (src/config/postgresExpiryRetention.json); until then the period is a commitment carried out by that switch, not yet by code.
A legal hold (Privacy Policy section 9) pauses deletion of the data it covers until the hold is released or expires (at most 1 year per hold).
Accounts and sites
| Data | Retention | Implementation |
|---|---|---|
| Account and profile (email, name, photo, phone, preferences) | Life of the account; erased when the account is deleted | PostgresPrivacyRepository.beginAccount and the deletion effects (Firebase disable, revoke and delete; Stripe cancel and customer delete; database scrub) |
| Sites, drafts, published content and uploads | Life of the site or account; erased with the site or account | Site and account retirement (deleteSite, beginAccount) |
| Saved site versions | Last 20 versions or every version from the last 90 days, whichever is more | Version retention (OQ-30) |
| Unfinished site-building requests, intake forms and drafts never turned into a site | 90 days | Expiry lanes generation-intake, subject-intake, public-intake (report-only; OQ-25) |
| Research cache (web research results) | 7 days | Bucket lifecycle (docs/ops/gcs-required-lifecycle-rules.json) |
| Pipeline artifacts and raw public social-profile archives | 90 days | Bucket lifecycle |
| Expired-trial sites | Paused (offline) at trial end; deleted with the account | Expired-trial sweep (OQ-29) |
| Contact-form messages on customer sites (GenLP as processor) | 540 days by default (site owner may set 365–730) | CONTACT_SUBMISSION_RETENTION_DAYS |
| Deleted-account tombstones (block deleted data from being re-imported) | 30 days | Expiry lane privacy-legal / account_tombstones (report-only) |
| Proof-of-erasure record (operation, hashed email, timestamps) | 395 days after deletion | account_deletions.retain_until |
Billing
| Data | Retention | Implementation |
|---|---|---|
| Subscription, payment and invoice records | Up to 7 years for tax and accounting; the account link is replaced by a pseudonym when the account is deleted | Billing ledger with deleted:<hash> pseudonym; Stripe keeps its own records under its policy |
Communications and preferences
| Data | Retention | Implementation |
|---|---|---|
| Email and job queues, delivery receipts, operational receipts, rate-limit counters | 30 days | Expiry lanes (report-only) |
| Email suppression (unsubscribe) records | As long as needed to honour the unsubscribe: the one-way email hash is kept; IP address and browser data are scrubbed after 90 days | PostgresLegalPublicService.maintain |
| Subprocessor-update subscriptions | Until unsubscribe | app.subprocessor_subscribers |
| Invitation records (a site created for someone) | Invitation expiry plus 30 days | Expiry registry backlog (OQ-25) |
Logs, security and legal records
| Data | Retention | Implementation |
|---|---|---|
| Application, access and audit logs, including the legal audit log | 1 year | Cloud Logging bucket retention; LEGAL_AUDIT_LOG_RETENTION_MONTHS=12 (the code default is 24) |
| Error reports (Sentry) | Sentry plan retention, at most 90 days | Sentry project settings |
| Privacy requests, appeals and their outcomes | 1 year after closure, or longer while needed to defend a claim | Retained legal families (privacyLegalRetirementRepository.ts) |
| Acceptances of the Terms and Privacy Policy (version, time) | Life of the account, then 1 year | app.legal_acceptances (retained legal family) |
| Opt-out records (including GPC) | The opt-out itself as long as needed to honour it; IP address and browser data 1 year | app.privacy_opt_outs |
| Abuse reports and evidence | 1 year after the report is resolved; evidence uploads not attached to a report: 2 hours | Abuse retention (ABUSE_REPORT_LEGAL_HOLD refuses purge while retained) |
| Legal holds | 1 year after release or expiry | app.legal_holds |
Exports, backups and copies
| Data | Retention | Implementation |
|---|---|---|
| Data exports for privacy requests (JSON; media ZIP on request) | 35 days; the download link works for 24 hours | App deletion at 30 days; bucket lifecycle backstop 35 days (dsr-exports/) |
| Site exports | 1 day (lifecycle backstop 2 days) | Bucket lifecycle (site-exports/) |
| Automated database backups and point-in-time recovery log | 7 days, rolling | Cloud SQL backup configuration |
| On-demand database backups | 30 days after creation | Owner-run deletion (OQ-26) |
| Final export of the retired Firestore database | Until 2026-11-17, then deleted | Bucket lifecycle / owner step (OQ-26) |
| Operator laptop captures of production data | Purged | Owner step (OQ-26) |
| Legacy personal data not carried into the current database | Deleted after a dry-run list (OQ-23) | legacyPersonalDataDisposition (owner-run) |
Browser storage
| Item | Retention |
|---|---|
| Cookie and consent choices | Up to 2 years |
Google Analytics cookies (_ga, _ga_*) and event data | Cookies up to 2 years; event data no longer than the property's retention setting (at most 14 months) |
Meta Pixel cookies (_fbp, _fbc, genlp.ai only) | Up to 90 days |
| Sign-in state | Until sign-out or expiry of the sign-in session |