Data lifecycle
How data enters Sophia, where it lives, and how removal works today versus what is only planned.
Storage
- MongoDB — All application entities (organizations through notes). Tenants share one database; queries scope by
organizationId. - Amazon S3 — Resume files (private bucket, server-side encryption). Staging keys under
resume-uploads/…; permanent keys underresumes/{org}/{candidate}/….
How data enters
| Source | What gets created or updated |
|---|---|
| Signup | Organization + founder user; Firebase auth; trial credits on the ledger |
| Team invites | User row with hashed invite token (expires after ~7 days) |
| API | Positions, candidates, interviews, notes, profile changes |
| Resume upload | Presigned S3 upload → parse (optional LLM) → candidate row + promoted S3 object + extracted text on the candidate |
| Schedule interview | Interview with frozen snapshot (name, email, resume text copied from candidate) |
| Live interview | Runtime, timing, room, recording metadata on the interview document |
| Settlement | Credit consume/release; retentionExpiresAt set (~60 days after terminal outcome); report job enqueued |
| AI report worker | InterviewReport (transcript, scores, analysis) |
| Stripe webhooks | CreditLedger + CreditLot for purchases |
Join links send a plaintext token to the candidate; only a hash is stored. Optional interview passwords are stored hashed.
Changes and “deletion”
- Soft delete —
deletedAton organization, user, position, candidate, interview, and note. Reads ignore non-null values. Today only interview and note deletes set it. Deactivating a user setsstatus, notdeletedAt. Blacklisting a candidate keeps all data. - Position archive — Sets
status: archived; row stays in the database. - Hard delete — Signup rollback, revoking never-accepted invites, replacing or cleaning up S3 resume objects. No general API to purge candidates, reports, or transcripts.
- Credit ledger — Append-only; lots can expire when expiry logic runs.
Retention
Settled interviews and reports get retentionExpiresAt (~60 days from terminal settlement). The field is indexed for future purge jobs.
Nothing in production yet purges expired rows, sends pre-purge email, or applies S3 lifecycle rules on resumes. Soft-deleted documents and interview evidence stay until a job or manual process removes them.