This policy governs how long we keep user data, when we delete it, and what users can do themselves. It's the contract behind every promise on our landing page.
| Category | Retention | Reason |
|---|---|---|
| User account (email, hashed password, tenant, plan) | While account active | Auth, billing, product functionality |
| Profiles (name, role focus, location) | While account active | User-authored; core to the product |
| Resumes (text + parsed sections) | While account active; 10 most recent versions | User-authored; tailoring history enables revert |
| Job queue + applications | While account active | The user's pipeline IS the product |
| Mail inbox + threads | Last 365 days | Storage + UX sanity; older threads prune |
| Cover letters | While account active | Re-use + history |
| Outbound mail attempt log | 1000-entry rolling buffer | Deliverability debugging |
| Event log | 5000-entry rolling buffer | Product analytics |
| Cap-hit log | 2000-entry rolling buffer | Pricing signal |
| Audit log (privileged actions) | 500-entry rolling buffer | Security / incident forensics |
| Bug reports | 500-entry rolling buffer | Product feedback |
| Exit surveys | 1000-entry rolling buffer | Churn analysis |
| Session tokens | 7 days (30 min for impersonation) | Keep users logged in; limit blast radius |
| Stripe customer + subscription IDs | While active + 90 days after cancellation | Refund + billing dispute window |
| Scanner output (global job queue) | Rolling — old jobs prune when no user has them | Dedup across users |
We do NOT store:
When a user clicks Delete My Account and confirms with password:
DELETE /api/account request handles all these in one transaction/opt/incognito/userdata/{userId}/ directory removed recursively30-day guarantee: Lingering references in log files rotate out within 30 days via pm2-logrotate. Residual data after 30 days is a SEV-1 bug.
Single JSON file, downloaded directly: incognito-export-{userId}-{YYYY-MM-DD}.json
{
exportVersion: 1,
generatedAt: "ISO timestamp",
user: { id, email, username, name, role, plan, tenantId, profileId,
activeProfileId, stripeCustomerId, createdAt, updatedAt,
searchOptIn, searchOptInAt },
profiles: [ ... ],
resumes: [ ... ], // full text + sections + keywords
jobs: [ ... ], // entire queue
applications: [ ... ], // entire history
mail: { inbox: [ ... ], preferences: { ... } },
notifications: [ ... ],
scanConfig: { ... }
}
Exports are generated on-demand. We don't cache them server-side. We don't keep a copy.
When a tenant relationship ends:
/api/super/tenants/{id} DELETE'default' tenant; their data stays intactRing-buffered files cap themselves by design. No cron needed. User-data directories rely on active account state — no time-based pruning. A user on parental leave shouldn't lose their pipeline.
Exception: If an email confirms the user is deceased or incapacitated, we preserve the account for next-of-kin access per GDPR Art. 17 and CCPA §1798.105, coordinated through Sara.
| Right | How | SLA |
|---|---|---|
| Export | Settings → Export my data | Instant |
| Delete | Settings → Danger Zone → Delete My Account | < 5s (local) + 30d (logs) |
| Correct / update | In-app edit on profiles, resumes, applications | Instant |
| Restrict processing | Disable all scan-config queries + cancel subscription | Instant |
| Data portability | Same as Export (machine-readable JSON) | Instant |
| Object | Email support@useincognito.com | 30 days |
For rights requests that can't be self-served, response SLA is 30 calendar days per GDPR Art. 12(3).
| Processor | Purpose | Data | Retention |
|---|---|---|---|
| Stripe | Payment processing | Email, name, card (direct to Stripe) | Per Stripe policy |
| Anthropic API | AI drafting | Resume + JD snippets | Zero-retention (API tier) |
| Serper API | Web search for scanner | Queries, role focus | Per Serper policy |
| LeafRelay SMTP | Mail delivery | Email headers + body (outbound) | Logs 7 days |
Each processor is vetted annually against their DPA and security posture.
Material changes are announced via:
Users who don't consent can export + delete within the notice window.