From efc9d83c25b0de5b8f8f0121eb228f7d0b4b08f4 Mon Sep 17 00:00:00 2001 From: cesnimda Date: Thu, 30 Jul 2026 23:34:42 +0200 Subject: [PATCH] fix: finish prospect workflow safeguards --- JobTrackerApi/Program.cs | 19 ++++++------------- docs/implementation-roadmap.md | 12 ++++++------ job-tracker-ui/src/components/AddJobModal.tsx | 2 +- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/JobTrackerApi/Program.cs b/JobTrackerApi/Program.cs index 61eb0bc..0e8cdbf 100644 --- a/JobTrackerApi/Program.cs +++ b/JobTrackerApi/Program.cs @@ -105,19 +105,12 @@ builder.Services.AddCors(options => } if (origins.Any(x => x.Trim() == "*")) - { - policy.SetIsOriginAllowed(_ => true) - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials(); - } - else - { - policy.WithOrigins(origins.Select(x => x.Trim()).Where(x => x.Length > 0).ToArray()) - .AllowAnyMethod() - .AllowAnyHeader() - .AllowCredentials(); - } + throw new InvalidOperationException("Cors:Origins cannot contain wildcard when credentialed requests are enabled."); + + policy.WithOrigins(origins.Select(x => x.Trim()).Where(x => x.Length > 0).ToArray()) + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials(); }); }); diff --git a/docs/implementation-roadmap.md b/docs/implementation-roadmap.md index 0039fa4..3f1c4ff 100644 --- a/docs/implementation-roadmap.md +++ b/docs/implementation-roadmap.md @@ -35,14 +35,14 @@ Goal: finish surfacing the pre-application workflow in the UI, and close the sec | # | Task | Priority | Difficulty | Dependencies | Expected value | |---|---|---|---|---|---| -| 1.1 | **Surface prospect stages in the UI** — add `Saved`/`Interested`/`Preparing` to `src/pipeline.ts` (`PIPELINE_STATUSES`), the Kanban columns, the status filter and the status menus. | **P0** | **M** | Phase 0 | **The backend supports the workflow; the UI does not yet expose it.** Phase 0 deliberately changed no UI behaviour. Until this lands, users still cannot save an unapplied job. Note the Kanban already has 6 columns — 9 stages needs a layout decision. | -| 1.2 | **Point the add-job wizard at `Saved`/`Preparing`** | **P0** | **XS** | 1.1 | Completes the workflow end to end. The 6-step wizard already exists (`components/AddJobModal.tsx:368`); this is a default-value change once 1.1 makes the stage selectable. | +| 1.1 | ✅ **DONE** — `Saved`, `Interested`, and `Preparing` are exposed through the shared pipeline model, grouped Kanban, filters, and status menus. | **P0** | **M** | Phase 0 | Prospect workflow is visible end to end. | +| 1.2 | ✅ **DONE (2026-07-30)** — new jobs default to `Saved`; users can choose any later stage in the wizard. | **P0** | **XS** | 1.1 | New opportunities no longer imply an application was already submitted. | | 1.3 | **Drag-and-drop on the Kanban** | **P2** | **M** | 1.1 | Board is drop-target-only today. Table stakes at every competitor. Deferred: not blocking. | | 1.4 | **Rotate DataProtection keys** | **P1** | **XS** | none | **Needs an operator — cannot be done from here.** Keys remain recoverable from git history (`519c32e`, `955cae6`). Open since 2026-07-03. | -| 1.5 | **Fix the CORS wildcard landmine** — `Cors:Origins="*"` triggers `SetIsOriginAllowed(_ => true)` **with** `AllowCredentials()` (`Program.cs:96-102`): any site could make authenticated requests with the user's session cookie. Not currently active (compose never sets `Cors__Origins`), but it is one config value away. Reject the `*`+credentials combination outright. | **P1** | **XS** | none | **Found during Phase 0.** Cheap fix, severe if ever triggered. Was out of Phase 0's 5-item scope. | -| 1.6 | **Resolve the dead `careerView` prop** — either wire it or remove the tab | **P1** | **XS** | none | Ships a visible "CV Builder" tab that does nothing (`views/ProfilePage.tsx:231`). Removing it until Phase 4 is honest; leaving it is not. **Both files are uncommitted WIP — confirm intent before touching.** | -| 1.7 | **Fix the onboarding CV check** — read the structured profile, not `profileCvText` | **P2** | **XS** | none | `components/OnboardingChecklist.tsx:31` tells users with a parsed profile to upload a CV again. | -| 1.8 | **Fix the 5 pre-existing frontend test failures** in `profile-page.test.tsx` and `settings-view.test.tsx` | **P1** | **S** | none | **Failing on `main` before Phase 0** (verified by stashing all changes and re-running). CI runs the whole suite, so `main` is red — every future change lands on a broken baseline. | +| 1.5 | ✅ **DONE (2026-07-30)** — startup rejects wildcard CORS origins when credentialed requests are enabled. | **P1** | **XS** | none | Unsafe configuration now fails closed. | +| 1.6 | ✅ **DONE** — the dead `careerView` prop/tab is gone; the implemented CV Builder has its own routed workspace. | **P1** | **XS** | none | No dead navigation remains. | +| 1.7 | ✅ **DONE** — onboarding reads structured career-profile collections with raw CV text only as fallback. | **P2** | **XS** | none | Parsed profiles are recognized correctly. | +| 1.8 | ✅ **DONE** — full frontend suite is green (142 tests on 2026-07-30). | **P1** | **S** | none | CI has a clean regression baseline. | | 1.9 | **Decide what to do with the `feature/career-workspace` branch.** ✅ *Investigated 2026-07-17 — see below.* The orphan tables are not an abandoned prototype: they are the local footprint of **10 unmerged commits** (local + `origin`, last touched 2026-07-12) containing working, tested code and 1,100 lines of research/strategy. All 7 tables are **empty** in dev, so there is no data to migrate. Branch is **29 commits behind main**. | **P0** | **M** | none | **Blocks Phases 3 and 4 from being planned honestly.** Re-deriving this work would waste weeks; ignoring it leaves a rebase debt that grows every day main moves. See `docs/career-workspace-branch-assessment.md`. | | 1.10 | **Dev DB is missing 2 migrations** (`AddCorrespondenceEmailFields`, `AddShortSummary`) yet has `SyncModelSnapshot` — the reconciler patched the columns instead. | **P2** | **S** | none | Local-only inconsistency, but it means the dev DB is not a faithful rehearsal for a prod migration. Worth reconciling before the Phase 1 cutover. | diff --git a/job-tracker-ui/src/components/AddJobModal.tsx b/job-tracker-ui/src/components/AddJobModal.tsx index bf38ed4..15df2b1 100644 --- a/job-tracker-ui/src/components/AddJobModal.tsx +++ b/job-tracker-ui/src/components/AddJobModal.tsx @@ -122,7 +122,7 @@ export default function AddJobModal({ open, onClose, onCreated, initialUrl }: Pr const [dateApplied, setDateApplied] = useState(() => getTodayIso()); const [jobTitle, setJobTitle] = useState(""); - const [status, setStatus] = useState<(typeof PIPELINE_STATUSES)[number]>("Applied"); + const [status, setStatus] = useState<(typeof PIPELINE_STATUSES)[number]>("Saved"); const [location, setLocation] = useState(""); const [salary, setSalary] = useState(""); const [salaryMin, setSalaryMin] = useState("");