Electron 41 upgrade, R2 distribution, lazy Chrome launch

2026-04-10
Signal
Jobs-apply desktop hardening day. I upgraded Electron 30 to 41, fixed the OAuth adapter wiring for NextAuth sign-up, moved DMG distribution to Cloudflare R2 (the private-repo GitHub releases were 404ing for users), added lazy Chrome launch to avoid cold-start blocking, and shipped the PDF candidate match report. This is the first of a three-day jobs-apply push (Apr 10 setup -> Apr 11 full tenant isolation -> Apr 13 Lever and Direct pipeline fixes). Yesterday was the vault-engine wiring day, so I deliberately parked that project and pushed the jobs-apply reliability work while the vault ran itself in the background.
Evidence
- Electron 41: bumped electron 30 to 41 plus electron-builder 25 to 26, fixed hoisting issues from the pnpm workspace layout. 11 major versions of deprecation warnings cleaned up in one jump, which will pay dividends on every subsequent build.
- OAuth fix: wired NextAuth adapter to UsersRepository so new OAuth sign-ups get a proper user record written to the Neon Postgres. Without this, sign-ups appeared to work but left no trace in the users table, and every downstream feature silently broke.
- R2 distribution: DMG now hosted on Cloudflare R2 (bucket: jobs-apply-releases), bypassing the private-repo 404. GitHub’s release endpoints return 404 for unauthenticated users hitting a private repo, which made the auto-updater useless. R2 is the right distribution layer for a paid desktop app anyway.
- Lazy Chrome: Chrome only launches when a channel adapter actually needs it, not on app start. Startup time drops noticeably, and users who open the app without running a search never trigger a Chrome window at all.
- PDF match report: candidate match report generation wired into the pipeline. The report PDF is the first artifact a user sees beyond the dashboard, so shipping it unblocks the whole onboarding flow.
- Task tracker: NEXT_WEEK.md created for planning the rest of the launch push. Checklist-driven work is faster than freeform for this kind of multi-day hardening.
So What
The R2 fix is load-bearing. Shipping a desktop app that cannot auto-update because GitHub releases 404 on private repos is shipping a broken update channel, even if the first install works. Cloudflare R2 is the right distribution layer: cheap, fast, and decoupled from the source repo’s visibility. The Electron 30 to 41 jump was long overdue and clears several deprecation warnings that would eventually have forced an emergency migration. Lazy Chrome launch means the app starts faster and does not require Chrome until a user actually runs a job search, which is also the right behavior for users who only want to review past applications or edit their profile. These three changes together move jobs-apply from “a web app that happens to be packaged as desktop” to “a desktop app that happens to use web tech internally,” and that is the distinction that lets the product stop bleeding on LinkedIn restriction windows. Each fix existed because a real failure mode surfaced, which tells me reactive hardening still works but every subsequent day should try to move at least one item from reactive to proactive.
What’s Next
Tomorrow (Apr 11) is the big tenant-isolation push. The OAuth adapter fix today means new users get proper user records, but nothing stops cross-user data leaks yet. UserScopedRepository, ScopedRepos, route audit, and Postgres RLS all land tomorrow. The question for tomorrow is whether the 4-layer defense catches the next incident or whether I am shipping belt-and-suspenders hardening with no real incident pressure behind it.
Log
- jobs-apply (5 commits): Electron 30→41 + electron-builder 25→26 with hoisting fixes; NextAuth adapter wired to UsersRepository for OAuth sign-up; NEXT_WEEK.md task tracker added; DMG distribution moved to Cloudflare R2 (private-repo GH releases were 404ing); lazy Chrome launch + plan enforcement trigger + PDF candidate match report