How your data is kept safe
findmynew.work is split into two halves: a client that runs on your own machine and a server we host. The split exists for one reason — your job-board credentials and the cookies proving you're logged in never need to leave your computer, so they don't.
Two halves, one trust line
Think of it as two locked boxes that pass notes through a slot. Each box does what only it should, and the slot is narrow on purpose.
diagram┌─────────────────────────────┐ ┌────────────────────────────────┐ │ YOUR MACHINE │ │ OUR SERVER │ │ │ │ │ │ · LinkedIn / hh.ru cookies │ ──── only ───▶ │ · vacancy text (after parse) │ │ · OS keychain entries │ structured │ · your score / keywords │ │ · Playwright profile dir │ vacancy & │ · your drafted cover letter │ │ · raw scraped HTML │ apply data │ · the resume you uploaded │ │ · the final submit click │ │ · timestamps + status events │ │ │ ◀─── recipes ──│ │ │ ↑ │ & drafted │ │ │ passwords never reach us │ letters │ ↑ │ └─────────────────────────────┘ │ no credentials, no cookies │ └────────────────────────────────┘
What stays on your machine
Everything that could be used to impersonate you on a job board lives on the client side and never travels.
What the server stores
The server only needs to know enough to score vacancies, draft your cover letters, and remember what you've already decided. Here's the full list, per account:
schemaAccount { email string // from Google sign-in createdAt timestamp } Resume { text string // the markdown / text you uploaded uploadedAt timestamp } Vacancy { source "linkedin" | "hh" | "wellfound" | "getmatch" title string description string // parsed text only — no raw HTML url string // public posting URL score number // 0–100, computed by the server coverLetter string? // draft we generated for you tunedResume string? // your resume rephrased for this posting status "new" | "drafted" | "marked_to_send" | "applied" | "archived" decidedAt timestamp? // when you acted on it } ApplyEvent { // append-only audit trail vacancyId ref Vacancy outcome "submitted" | "failed" | "skipped" message string? recordedAt timestamp } ApiKey { prefix string // shown in the UI, e.g. fmwork_a3f2… hash sha256 // we store the hash, never the key itself label string createdAt timestamp lastUsedAt timestamp? }
Everything is scoped to your account at the database level. Other users — even on the same server — cannot read your vacancies, your resume, or your decisions.
What crosses the wire
Two channels go between client and server, both over HTTPS. Here's the full surface area of each.
schema# CLIENT → SERVER (you push to us) search_recipe_request { source } // “give me a search recipe” search_results_upload { rows: VacancyInput[] } // parsed, structured vacancies apply_result_report { vacancyId, outcome } // what happened when you clicked apply # SERVER → CLIENT (you pull from us) search_recipe { url, selectors, pacing } // how to scrape one source apply_queue { vacancy, coverLetter, tunedResume } // for postings you marked health { ok, counters } // is the server reachable # WHAT IS NOT IN ANY MESSAGE ─ no passwords ─ no session cookies ─ no raw browser HTML ─ no screenshots ─ no keystrokes ─ no anything from other tabs or apps
How auth protects you
Two independent secrets gate access to your account. They're kept in different places on purpose so losing one doesn't hand over the other.
schemaSIGN-IN COOKIE (the dashboard you open in a browser) · created by Google OAuth → verified server-side · stored as httpOnly cookie, SameSite=Lax, 14-day rolling · cannot be read by any page’s JavaScript API KEY (the local client you run on your machine) · you create it yourself in Account → API keys · shown to you exactly once — the server only keeps a hash · revoke at any time; the client gets 401 on its next request PER-SESSION USER BINDING · the MCP session id is bound to your account when it’s first issued · replaying someone else’s session id without their API key returns 401 · revoking the API key invalidates every session that used it
Submission is opt-in
The server can draft a cover letter and tune your resume automatically — but actually pressing “Apply” on a job board is a separate, deliberate step:
- You review the draft in the dashboard and mark it to send.
- On its next poll, your local client picks up the marked items and opens your real browser session.
- The final click is yours (or your client's, if you've explicitly enabled live-submit mode). Either way, it happens from your machine, signed in as you.
We never submit on your behalf from our infrastructure, because we can't — we don't have the cookies that would let us.
Export & delete
Your data is yours. You can pull a full JSON snapshot at any time, and account deletion purges every record — vacancies, drafts, audit events, API key hashes — within minutes.
- Export: from Settings, request a JSON dump of everything the server holds about you.
- Delete: the same page has a destructive “close account” action. It cascades: account, resume, vacancies, drafts, audit events, API keys.
- Backups: daily encrypted snapshots are kept for 14 days and then permanently deleted, so a deletion takes effect everywhere within two weeks.
Questions about data handling? Email privacy@findmynew.work.