Make /jobs/:id the canonical application workspace while preserving list state and compatibility links. Replace popup and expandable-row navigation with accessible whole-row routing and richer job details.
Rotate persisted delivery identity only after the matching owner attempt is definitively failed. Keep stale, foreign, pending, sent, and uncertain drafts non-retryable.
Keep follow-up draft generation but remove the direct application SMTP delivery boundary. Route users to the provider-aware Job email flow and return 410 for legacy API callers.
Upgrade React Router to the patched v7 line and refresh transitive js-yaml and nanoid packages. Adapt RouterProvider flags and the Jest jsdom environment without changing application routes.
Keep provider, recipient, subject, thread, and body editable until an app-owned confirmation is accepted. Reuse one request UUID per attempt and block automatic retry when delivery is uncertain.
Gmail and Graph request explicit send consent and classify provider rejection separately from uncertain transport failure. IMAP remains read-only; no send API is exposed.
CV upload now returns 202 with an owner-scoped operation instead of holding the request through parsing. Existing review approval remains required.
BREAKING CHANGE: profile-cv upload responses use the durable operation contract.
Route public health checks to the API, backfill and synchronize job opportunities, stabilize SPA smoke tests, and document operator-only production steps.
- consolidate API ownership and remove dead vendor code
- add Stripe billing, learning paths, and public CV hardening
- add migration, recovery, security, audit, and browser gates
UI-only. No change to APIs, save payloads, extraction behaviour, or data
models. The parent CareerProfilePage still owns loading, state, saving,
and all extraction/import actions; the new sections are presentational
(value + onChange, plus a getMetadata callback for review chips).
Extracted into src/views/career/CareerProfileSections.tsx:
PersonalInformation, ProfessionalSummary, Skills, Interests, Languages,
WorkExperience, Education, OtherSections. FieldReviewNote + confidenceTone
moved there verbatim and shared with the parent. CareerProfilePage went
from 1376 to ~1200 lines.
No Projects/Certifications sections were created -- the editor never had
them (they are not editable structured fields here). Inventing them would
add functionality, which this refactor avoids; noted for a product
decision later.
Hid the duplicate CV concepts behind an "Advanced CV tools" toggle,
collapsed by default: the CV Structure Overview parse block and the
Template-driven CV builder. Both stay mounted and functional (gated with
display:none), so no tested functionality is removed -- the real CV
Builder at /career/builder is the single generation surface. Future
removal plan documented.
Tests: added "editing a field in an extracted section updates parent
state and flows into save" (render -> edit -> PUT /career/profile
{profile,cvText}); existing parse/rewrite tests reveal the advanced tools
first. The increment-1 save-invariant test still pins the payload.
Verified: tsc clean, production build clean, 137 frontend tests pass.
Backend untouched.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>