Commit Graph

90 Commits

Author SHA1 Message Date
cesnimda 5c3ed28766 fix(i18n): localize helper defaults 2026-08-29 23:51:01 +02:00
cesnimda b0cb28a113 fix(i18n): localize security challenge 2026-08-29 23:42:13 +02:00
cesnimda cf6509ce13 fix(i18n): localize admin recovery states 2026-08-29 23:40:29 +02:00
cesnimda 10ce0f2086 fix(i18n): unify shared view states 2026-08-29 23:37:07 +02:00
cesnimda 6210909b62 fix(i18n): close shared ui gaps 2026-08-29 22:55:29 +02:00
cesnimda 3c9b22c97e fix(i18n): localize job email workflows 2026-08-29 22:45:49 +02:00
cesnimda ee8eacf0de fix(i18n): localize admin diagnostics 2026-08-29 22:35:28 +02:00
cesnimda 0ef51fed74 fix(cv): localize format labels 2026-08-29 22:32:29 +02:00
cesnimda 464ba7f4d9 feat(i18n): localize public landing 2026-08-29 22:30:08 +02:00
cesnimda e9f8653d19 fix(i18n): localize job email hub 2026-08-29 22:10:53 +02:00
cesnimda f89e37bb4f fix(i18n): localize discovery and accounts 2026-08-29 22:01:26 +02:00
cesnimda 457f0601c0 fix(i18n): finish career activity copy 2026-08-29 21:57:40 +02:00
cesnimda a704c75440 fix(i18n): localize application workflows
Use stable checklist and interview keys for system copy while preserving user-authored content. Localize creation-tab errors, language selectors, match bands, dates, and selected-CV context.
2026-08-29 16:51:59 +02:00
cesnimda 9edcbfc5de feat(workspace): refine career workflows
Make job/CV comparisons language-aware and filter recruitment noise. Improve responsive career navigation, shared spacing, dashboard priorities, settings, localized workspace controls, and portable browser tests.
2026-08-29 16:44:44 +02:00
cesnimda 0f17d95c57 feat(cv): expand builder studio tools 2026-08-29 01:45:30 +02:00
cesnimda 3bb792f1dc feat(i18n): localise career workspace overview 2026-08-28 20:35:20 +02:00
cesnimda 245b39f6fa feat(cv): localise section AI output 2026-08-28 20:30:42 +02:00
cesnimda 557121ad31 feat(i18n): localise CV dashboard 2026-08-28 20:27:33 +02:00
cesnimda cf549d6ed1 feat(i18n): localise CV builder workflow 2026-08-28 20:25:10 +02:00
cesnimda 10f348db32 feat(i18n): localise CV editor chrome 2026-08-28 20:10:47 +02:00
cesnimda 50f276c6c0 feat(i18n): localise document editing controls 2026-08-28 20:06:01 +02:00
cesnimda a57b2fe58c feat(i18n): localise application workspace 2026-08-28 20:04:11 +02:00
cesnimda 8e344379b4 feat(interview): integrate contextual AI prep 2026-08-28 12:53:35 +02:00
cesnimda 3b4adb8281 refactor(ui): centralise themed dialogs 2026-08-28 12:48:38 +02:00
cesnimda 5805c1a621 feat(i18n): persist Bokmal preference globally 2026-08-28 12:44:02 +02:00
cesnimda 367b70681a feat(cv): rebuild professional resume studio 2026-08-24 20:21:23 +02:00
cesnimda 842e793f69 feat(account): add deletion lifecycle
CI and Deploy / test (pull_request) Successful in 5m18s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-15 19:03:54 +02:00
cesnimda 1ec9dd037e feat(export): add readable account archive
CI and Deploy / test (pull_request) Successful in 5m13s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-15 18:36:40 +02:00
cesnimda a25c31b93a feat(plans): publish honest Free and Pro
CI and Deploy / test (pull_request) Successful in 5m6s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-15 18:04:18 +02:00
cesnimda 998ee07a9a feat(notifications): open bell popover
CI and Deploy / test (pull_request) Failing after 2m55s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-15 13:37:29 +02:00
cesnimda 15e5464da7 fix(admin): protect administrator access
CI and Deploy / test (pull_request) Failing after 4m31s
CI and Deploy / deploy (pull_request) Has been skipped
Reject final-admin demotion and deletion at the API boundary. Require explicit confirmation before any administrator role removal.
2026-08-15 13:11:54 +02:00
cesnimda 8fe39031ea fix(email): retire legacy SMTP follow-up
CI and Deploy / test (pull_request) Failing after 55s
CI and Deploy / deploy (pull_request) Has been skipped
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.
2026-08-10 00:43:52 +02:00
cesnimda da1aa8bb2a fix(match): prioritize meaningful job terms 2026-08-09 18:47:21 +02:00
cesnimda 93b869259e feat(auth): unify sign-in options 2026-08-09 16:07:33 +02:00
cesnimda c3f4a57195 feat/Update_Controllers_to_Allow_for_Premium_Membership 2026-08-03 09:17:28 +02:00
cesnimda ce76046a29 feat: complete release readiness work
- 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
2026-07-31 16:54:16 +02:00
cesnimda 6ed56fd493 fix: localize usage and salary insights
CI and Deploy / test (push) Successful in 2m40s
CI and Deploy / deploy (push) Successful in 56s
2026-07-31 00:17:33 +02:00
cesnimda 4cf26405f6 feat: complete phase 3 career workspace
CI and Deploy / test (push) Failing after 1m6s
CI and Deploy / deploy (push) Has been skipped
2026-07-30 22:19:13 +02:00
cesnimda 56fed05d70 feat: complete phase 2 UX improvements
CI and Deploy / test (push) Successful in 2m42s
CI and Deploy / deploy (push) Failing after 9s
2026-07-30 21:35:52 +02:00
cesnimda 63473bae85 refactor(career): Phase 1 increment — user-facing terminology + component split
UI-only restructuring of the Career Profile surface. No change to
database models, CareerProfiles schema, CvVariants, extraction APIs, AI
services, CV rendering, or public CV.

Terminology -> user-facing (i18n strings):
- "Structured CV editor"     -> "Career information"
- "CV structure overview"    -> "Profile sections"
- "Summary bullets"          -> "Professional summary"
- "Core skills"              -> "Skills"
- "Analyze sections"         -> "Read sections"
- "Original extraction"      -> "Original import"
- hardcoded "Master career profile" -> "Career profile"
Help text de-jargoned; the Career information help now frames it as the
source the CV Builder consumes.

Component split (first step): extract ProfileCompleteness (completeness
meter + missing chips + version history) into src/views/career/. Display
only, props in, no state or API.

Save path untouched: api.put("/career/profile", { profile, cvText }). A
new test pins that exact call as the refactor invariant so the remaining
section extraction cannot silently change save behaviour. Existing
profile-page tests re-pointed to the new labels; every behavioural
assertion (save, parse, field values) kept.

Verified: tsc clean, production build clean, 136 frontend tests pass
(135 + 1 invariant). Sidebar fix from the previous task still passes.
Backend untouched.

The remaining Phase 1 work (per-section editor components, hiding the
template-driven builder and structure-overview blocks, actionable
per-section empty states) is staged in docs/career-workspace-ux-refactor.md
because it touches the live extraction test surface and is best verified
by driving the authenticated UI. This increment is a clean, non-regressing
checkpoint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 02:50:52 +02:00
cesnimda eac34705e3 feat: Phase 0 foundation — Job entity, expanded pipeline, AI service lockdown, DateApplied history
Unblocks the documented core workflow and closes the AI-service exposure,
without changing existing behaviour.

Job/JobApplication split (additive; see ADR-002):
- New Job entity (the opportunity) with owner-scoped query filter; nullable
  JobApplication.JobId FK. Nothing reads Job yet.
- Migration AddJobEntityAndProspectStages, hand-edited to drop reconciler-owned
  tables the scaffolder re-emitted; verified against the real dev DB.

Pipeline: 10 internal stages across three concerns kept separate —
PipelineStage (workflow) / PipelineGroup (UI: NotApplied/Active/Closed) /
PipelineCategory (analytics). Adds Saved/Interested/Preparing/Withdrawn;
keeps Waiting and Ghosted. Kanban shows 3 grouped columns; cards keep a stage
chip and full transitions; drag applies only safe transitions (never infers
Ghosted/Withdrawn).

DateApplied nullable + SavedAt. Cleared when leaving Applied so analytics stay
accurate; the discarded date is preserved as an AppliedDateCleared JobEvent.

AI service lockdown: no host port; private ai_internal network (backend is the
only other member); X-Ai-Service-Token required on all non-/health endpoints;
AI_SERVICE_TOKEN mandatory via compose. Verified backend-only against the live
stack.

Also carries two pre-existing working-tree files (views/ProfilePage.tsx,
views/CareerWorkspacePage.tsx) so the tree is clean for the branch integration.

Tests: +40 backend (247 total), +5 sidecar (16), +15 frontend.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 17:05:25 +02:00
cesnimda 81512db1cb style(ui): redesign Dashboard and Kanban to match mockups
CI and Deploy / test (push) Successful in 2m16s
CI and Deploy / deploy (push) Successful in 42s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-13 09:05:54 +02:00
cesnimda b8b7987c58 fix(auth): polish login/register/reset pages for consistency and accessibility
CI and Deploy / test (push) Successful in 2m9s
CI and Deploy / deploy (push) Successful in 39s
- LoginPage: add client-side email/password validation (inline error +
  helperText, matching the 2FA components' established pattern), and a
  proper register-mode toggle with a "Confirm password" field. The
  brief asked for confirm-password on registration but the page only
  had one shared password field; a toggle (mirroring the existing
  Tabs-for-mode pattern already used for Google/Microsoft) keeps this
  from cluttering the login form for returning users.
- Fix a real bug in ResetPasswordPage: it didn't use the app's
  getApiErrorMessage helper, so a non-string error response body would
  render as "[object Object]" in the toast. Also add a confirm-password
  field and matching client-side validation for parity with register.
- ForgotPasswordPage: add proper email format validation instead of
  only checking for non-empty.
- Add matching i18n keys (en/no) for every new validation message.

Verified live end-to-end against a running backend: register-mode
toggle, confirm-password mismatch blocking submission client-side,
and a full registration completing and landing on the dashboard.
2026-07-13 08:34:17 +02:00
cesnimda c6918cbeea feat(auth): add server-tracked sessions with view/revoke
JWTs were previously fully stateless -- the token alone was the credential
until its own expiry, with no way to list or kill a session server-side. Add
a UserSession table alongside every JWT issued (AppSessionIssuer), embed its
id as a "sid" claim, and check that claim against the DB on every "local"
scheme request (Program.cs OnTokenValidated) so a session can actually be
revoked before its JWT naturally expires. New /api/auth/sessions endpoints
(list, revoke one, revoke-others) plus a Sessions card on the profile page.

Fails closed on a missing "sid" claim: every JWT issued going forward has
one, so a token without it is either pre-deploy (forces one re-login for
already-signed-in users at deploy time, same additive-forward cost the
2FA/trusted-device work on this branch already paid) or forged.
2026-07-13 01:47:31 +02:00
cesnimda 904f3a8ec8 feat(auth): add configurable email verification enforcement
Auth:RequireEmailVerification (default off) gates whether local
register requires confirming email before login. OAuth new-user paths
are untouched -- Google/Microsoft already assert a verified email.
Adds verify-email and resend-verification-email endpoints, mirroring
the existing reset-password enumeration-avoidance and rate-limiting
patterns, plus a login-embedded resend affordance and a verify-email
landing page on the frontend.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-13 01:22:26 +02:00
cesnimda 0ca2f2b261 feat(auth): add trusted-device 30-day 2FA skip (frontend)
Adds a "Trust this device for 30 days" checkbox to the 2FA challenge step,
and a "Trusted devices" section to the 2FA settings card: list devices with
a "this device" badge, per-row revoke, and a confirm-gated "sign out all
other trusted devices" action. Both flows are opt-in and additive -- default
unchecked, so nothing changes for a user who never uses them.
2026-07-13 01:02:43 +02:00
cesnimda b85dc1ffb7 feat(auth): add 2FA setup UI and login challenge step 2026-07-12 21:17:09 +02:00
cesnimda d5d82cb528 feat(ux): onboarding checklist, dashboard-first landing (fixed)
CI and Deploy / test (pull_request) Successful in 2m5s
CI and Deploy / deploy (pull_request) Has been skipped
Dashboard onboarding checklist: a dismissible card with 3 steps (add
CV, import first job, check match score), each linking straight to
where you'd do it. Auto-hides once both CV and a job exist; otherwise
persists per-user via localStorage until dismissed.

Fixes the actual authenticated-landing redirect to /dashboard: my
earlier commit changed App.tsx's inner Shell route for "/", which
turned out to be dead code -- the outer router claims "/" for
LandingPage first, so Shell's own "/" route is never reached on a
direct hit. The real redirect lives in LandingPage.tsx's post-auth-check
navigate() and LoginPage.tsx's post-login nextPath default; both now
point at /dashboard. Verified live: an authenticated visitor hitting
"/" now lands on Dashboard with the onboarding checklist visible,
confirmed via rendered page text and screenshot.
2026-07-12 04:26:17 +02:00
cesnimda 9615ee3f41 feat(ux): per-view subtitles, correspondence cross-links, mobile kanban, a11y
Continuing the product/UX review's deferred items:

- Every top-level view now gets a one-line subtitle under its title
  (Dashboard/Jobs/Kanban/Reminders/Correspondence/Gmail review) stating
  what that specific view is for, instead of navigation being the only
  signal of what each page does.
- Correspondence inbox and Gmail review queue cross-link to each other
  instead of being two unexplained flat sidebar items -- kept both nav
  entries (renaming/nesting risked breaking muscle memory) but made the
  relationship between them explicit in the UI itself.
- Kanban board switches to a horizontal scroll-snap row on phone-width
  viewports instead of stacking all 5 columns vertically, which meant
  a lot of scrolling to see anything past "Applied".
- Match-score ring gets an aria-label with the actual percentage --
  it was two nested decorative CircularProgress elements with no
  accessible text. (Keyboard-accessible status changes on kanban cards
  were already covered by the existing "..." menu -- no gap there.)
2026-07-12 04:14:37 +02:00
cesnimda 58868fc2b6 feat(ux): first-time onboarding, empty states, and copy fixes
Implements the six "propose first" items from the product/UX review:

- "/" now redirects to /dashboard instead of the empty /jobs table --
  a new user's first screen is now an overview with orientation, not
  a data table with zero rows and four filter dropdowns.
- Jobs table gets a real first-time empty state (distinct from "no
  results match your filters") pointing at Add Job and the bookmarklet,
  instead of a bare "No jobs found."
- Match Score card and Candidate Fit tab now each get a one-line
  caption explaining what they are and how they differ (deterministic
  keyword coverage vs. AI opinion) -- they previously sat side by side
  with no explanation of why there are two.
- Google sign-in hint now reflects self-serve signup when
  Auth:AllowRegistration is on, instead of always implying you need an
  existing linked account.
- Quick Search button now shows its keyboard shortcut (Ctrl+K / ⌘K)
  inline instead of being undiscoverable.
2026-07-12 04:05:32 +02:00