Commit Graph

113 Commits

Author SHA1 Message Date
cesnimda 14f8d4e928 docs(email): record SMTP retirement evidence
CI and Deploy / test (pull_request) Failing after 4m5s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-10 00:45:30 +02:00
cesnimda d7b556e494 docs(deps): record advisory remediation
CI and Deploy / test (pull_request) Failing after 4m12s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-10 00:42:41 +02:00
cesnimda c14b8a0ee4 docs(email): record recovery evidence
CI and Deploy / test (pull_request) Failing after 1m30s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-10 00:21:19 +02:00
cesnimda 4de08b7c77 docs(email): record composer evidence
CI and Deploy / test (pull_request) Failing after 1m33s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-10 00:11:40 +02:00
cesnimda 90f9bf576c docs(email): record send API evidence
CI and Deploy / test (pull_request) Failing after 1m34s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-10 00:02:29 +02:00
cesnimda d44c8ceb08 docs(email): record delivery adapter evidence
CI and Deploy / test (pull_request) Failing after 1m32s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-09 23:48:59 +02:00
cesnimda 429f427f49 docs(email): record send ledger evidence
CI and Deploy / test (pull_request) Failing after 1m34s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-09 23:41:09 +02:00
cesnimda 3a7e4f1088 docs(email): record message detail evidence
CI and Deploy / test (pull_request) Failing after 1m33s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-09 21:47:27 +02:00
cesnimda 6f0e9bb516 docs(email): record provider read boundary
CI and Deploy / test (pull_request) Failing after 1m29s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-09 21:38:21 +02:00
cesnimda 0e2a59a8ef docs(email): track hub consolidation evidence
CI and Deploy / test (pull_request) Failing after 1m35s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-09 21:22:39 +02:00
cesnimda efacc3a06b docs(cv): complete builder implementation evidence
CI and Deploy / test (pull_request) Failing after 1m36s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-09 21:08:28 +02:00
cesnimda df89a69306 docs(cv): track builder integrity progress
CI and Deploy / test (pull_request) Failing after 1m31s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-09 19:10:33 +02:00
cesnimda c201832603 docs(career): record workspace evidence
CI and Deploy / test (pull_request) Failing after 1m35s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-09 19:02:34 +02:00
cesnimda 3143568df0 docs(match): record term-quality evidence
CI and Deploy / test (pull_request) Failing after 1m33s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-09 18:49:41 +02:00
cesnimda f2d1963c61 docs(theme): record deterministic state evidence
CI and Deploy / test (pull_request) Failing after 1m31s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-09 18:37:52 +02:00
cesnimda 378807b3b9 docs(auth): record unified sign-in evidence
CI and Deploy / test (pull_request) Failing after 1m30s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-09 17:06:08 +02:00
cesnimda 83ddc0718e docs(cv): record durable processing evidence
CI and Deploy / test (pull_request) Failing after 1m38s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-09 15:14:39 +02:00
cesnimda 39e98049ea docs(cv): record durable processing trace
CI and Deploy / test (pull_request) Failing after 1m39s
CI and Deploy / deploy (pull_request) Has been skipped
2026-08-09 13:27:19 +02:00
cesnimda 89b9cdd92d docs(ai): record strategy queue evidence 2026-08-09 13:24:26 +02:00
cesnimda 5eb9b3cb96 feat(ai): enforce local-first routing
Keep external providers behind server consent, task, and prompt-cost gates while persisting actual provider provenance.
2026-08-09 12:30:11 +02:00
cesnimda c3f4a57195 feat/Update_Controllers_to_Allow_for_Premium_Membership 2026-08-03 09:17:28 +02:00
cesnimda 06518a7d52 fix: require verified production email
CI and Deploy / test (pull_request) Successful in 4m42s
CI and Deploy / deploy (pull_request) Has been skipped
CI and Deploy / test (push) Successful in 4m2s
CI and Deploy / deploy (push) Failing after 1m15s
Expose the existing email-verification setting through Compose and close the completed DataProtection rotation blocker.
2026-08-02 17:59:05 +02:00
cesnimda 955182b7c2 fix: close release preflight gaps
CI and Deploy / test (pull_request) Failing after 1m22s
CI and Deploy / deploy (pull_request) Has been skipped
Route public health checks to the API, backfill and synchronize job opportunities, stabilize SPA smoke tests, and document operator-only production steps.
2026-07-31 20:18:30 +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 a23c3dfc97 docs: record remaining product decisions
CI and Deploy / test (push) Successful in 2m34s
CI and Deploy / deploy (push) Successful in 28s
2026-07-31 00:18:32 +02:00
cesnimda 235d22c059 feat: add salary insights
CI and Deploy / test (push) Successful in 2m41s
CI and Deploy / deploy (push) Successful in 58s
2026-07-31 00:15:38 +02:00
cesnimda 9f16a5675a feat: show account AI usage
CI and Deploy / test (push) Successful in 2m40s
CI and Deploy / deploy (push) Successful in 50s
2026-07-31 00:08:41 +02:00
cesnimda 2126a2db5c fix: reconcile orphan migration history
CI and Deploy / test (push) Successful in 2m42s
CI and Deploy / deploy (push) Successful in 55s
2026-07-30 23:51:08 +02:00
cesnimda 988a91a151 feat: persist job source and market
CI and Deploy / test (push) Successful in 2m34s
CI and Deploy / deploy (push) Successful in 56s
2026-07-30 23:38:22 +02:00
cesnimda efc9d83c25 fix: finish prospect workflow safeguards
CI and Deploy / test (push) Successful in 2m37s
CI and Deploy / deploy (push) Successful in 54s
2026-07-30 23:34:42 +02:00
cesnimda 792814b04e feat: cap per-user AI token spend
CI and Deploy / test (push) Successful in 2m43s
CI and Deploy / deploy (push) Successful in 57s
2026-07-30 23:32:13 +02:00
cesnimda 09fc2b03f7 feat: gate premium CV themes
CI and Deploy / test (push) Successful in 2m35s
CI and Deploy / deploy (push) Successful in 1m1s
2026-07-30 23:24:19 +02:00
cesnimda fd2c60e70f feat: complete public CV sharing
CI and Deploy / test (push) Successful in 2m34s
CI and Deploy / deploy (push) Successful in 1m0s
2026-07-30 23:19:17 +02:00
cesnimda 158970fa01 feat: enforce account usage limits
CI and Deploy / test (push) Successful in 2m39s
CI and Deploy / deploy (push) Successful in 55s
2026-07-30 23:14:42 +02:00
cesnimda 9cd2e5c2e3 feat: protect auth with Turnstile
CI and Deploy / test (push) Successful in 2m41s
CI and Deploy / deploy (push) Successful in 59s
2026-07-30 23:08:36 +02:00
cesnimda 6382e83e28 ci: report dependency vulnerabilities
CI and Deploy / test (push) Successful in 2m34s
CI and Deploy / deploy (push) Successful in 29s
2026-07-30 22:58:59 +02:00
cesnimda 405e6d833c feat: add NAV job discovery
CI and Deploy / test (push) Successful in 2m27s
CI and Deploy / deploy (push) Successful in 1m0s
2026-07-30 22:57:17 +02:00
cesnimda 7fab996407 docs: reconcile phase 6 status 2026-07-30 22:42:49 +02:00
cesnimda c08232b9d7 feat: meter AI usage
CI and Deploy / test (push) Failing after 58s
CI and Deploy / deploy (push) Has been skipped
2026-07-30 22:39:24 +02:00
cesnimda f8466c2ebc feat: advance phase 5 AI workflow 2026-07-30 22:27:10 +02:00
cesnimda e4acfbd0bf refactor: complete phase 4 builder cleanup 2026-07-30 22:23:55 +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 173187dcbb feat(cv): Phase 2.1-b — extract Projects, Certifications, and languages-from-prose
The structured model and StructuredCvProfileJson.FromSections already map
Projects/Certifications/Languages headings, but the AI normalize prompt
never emitted them, so on the benchmark CV the entire Projects section and
the in-summary languages (English Native, Norwegian B1) were silently
dropped. This closes that gap upstream — no backend schema or data change.

ai-service (tools/summarizer/app.py):
- /cv/normalize: added # Projects and # Certifications headings; a
  languages-from-prose rule (pull "native English", "Norwegian at B1" out
  of the summary even with no Languages section; ignore programming
  languages); and skill-group prefix stripping ("Development:",
  "DevOps & Infrastructure:", "Practices:" dropped, only the skills kept).
- /cv/classify-block: Projects and Certifications added to the section
  enum + rules (fallback path).

Backend:
- LooksLikeNormalizedMarkdownCv now recognises # Projects / # Certifications
  so those CVs still take the markdown assembly path.

Tests:
- CvExtractionCoverageTests (4) lock the C# mapping of Projects,
  Certifications and Languages sections into the structured profile.
- ai-service test_classify_block_supports_projects_section (1).
426 backend tests, 17 ai-service tests pass; app.py compiles.

The LLM behaviour (prompt -> headings) needs Ollama to observe and was not
run here; the C# side that consumes the headings is proven and the prompt
change is additive. Merge-not-replace + the review screen are the next
increment (2.1-a, approved: always-review, conservative merge).

Deployment: these prompts live in the ai-service container, which
deploy.sh does not rebuild by default -- deploy with
DEPLOY_BUILD_AI_SERVICE=true or the change won't take effect.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 11:40:04 +02:00
cesnimda fe9cd4dda1 refactor(career): Phase 1 increment 2 — extract editor sections, hide duplicate CV concepts
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>
2026-07-20 11:00:26 +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 4f69d395be fix(nav): only the most-specific sidebar item is active
On /career/builder/{id} both "Career Workspace" (/career) and "CV Builder"
(/career/builder) highlighted, because AppShell tested each item with
`pathname === to || pathname.startsWith(to + "/")` — so /career matched
every /career/... child. No "most specific wins" rule.

Add AppShell.activeNavTo(pathname, tos): the longest `to` that the path is
at or under wins, across both nav lists; every other item is inactive. A
child route never lights up a parent nav item. `selected` now compares
against that single computed activeTo. Exported as a pure function so the
ownership rule is unit-tested directly (sidebar-active-nav.test.ts):
exactly one active item for /career, /career/builder and
/career/builder/{id}, and no double-highlight.

Also give the breadcrumb/title in App.tsx explicit /career/builder ->
"CV Builder" ownership (it previously showed "Career Workspace"), and
reframe the Career Workspace header to the "Career Profile" product
framing: "This information powers your CVs, applications, cover letters
and AI assistance."

Frontend only — no change to CareerProfiles, CvVariants, CV generation,
extraction APIs, AI, permissions or tenant isolation. Plan for the deeper
information-architecture work is in docs/career-workspace-ux-refactor.md,
staged so the 1376-line CareerProfilePage and the live CV/extraction
pipeline are refactored incrementally with verification, not in one risky
rewrite.

Verified: tsc clean, frontend build clean, 135 frontend tests pass
(128 + 7 new nav tests). Backend untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 02:29:50 +02:00
cesnimda 83206df9d7 docs(release): final release report
CI and Deploy / test (push) Successful in 2m47s
CI and Deploy / deploy (push) Failing after 7s
Consolidates release-candidate verification: backend 420 (incl. the CI
runner's exact Ubuntu 20.04/libicu66 environment), frontend 128, all
four DB scenarios, backup/restore with a byte-exact æøå round trip,
health and auth checks.

Status: READY WITH DOCUMENTED RISKS. No open code blocker. Remaining
risks separated into code (none), infrastructure (runner instability
A/B, still unconfirmed-fixed; old runner ICU), and manual owner
verification (sign-in, production backup, production scale).

Recommendation: deploy with documented risks -- re-run CI with the ICU
fix, owner runs a real backup + scratch restore, deploy, then run the
manual smoke test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 23:15:41 +02:00
cesnimda 57fabe9a97 docs(deployment): backup-restore, smoke test, runner finding C
- docs/deployment/backup-restore.md: production backup checklist; documents
  that deploy.sh loads the env, validates before backup, and validates the
  dump. Adds VERIFIED UTF-8/Norwegian-character round trip (æ ø å survive a
  real deploy.sh backup -> restore byte-exact; HEX compared). States plainly
  that no production database was reached and the owner must run one real
  backup + scratch restore.
- docs/deployment/manual-smoke-test.md: owner-run post-deploy checklist
  (auth, applications, career profile, CV builder, AI, files). Each item
  names what "wrong" looks like. Documents that login requires the owner.
- runner-investigation.md: Finding C -- the latest CI red was a real ICU
  code bug the runner caught correctly, not instability. Amends the blanket
  "outside the repository" conclusion. A and B stand as separate env issues.
- release-candidate-review.md: corrected drifted line refs after the index
  fix; noted the CI ICU finding so the "purely external" verdict is honest.

All claims reflect behaviour verified this session.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 23:14:41 +02:00
cesnimda b705cbaf60 chore: pin shell scripts to LF via .gitattributes
deploy.sh and the other scripts run on the Linux deploy host and in
Docker. A CRLF checkout breaks them with "bad interpreter: bash\r".
The committed blobs are already LF, but nothing guaranteed it against a
host with core.autocrlf=true. `*.sh text eol=lf` makes it explicit.

Verified: git ls-files --eol shows attr/text eol=lf on all .sh files;
renormalize produced no index churn (already LF).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 23:14:27 +02:00