Files
jobtrackingapp/docs/architecture/application-workspace.md
T
cesnimda e55a6e86b7
CI and Deploy / test (push) Failing after 1m13s
CI and Deploy / deploy (push) Has been skipped
feat(workspace): Application Workspace foundation (Phase 5 milestone 1)
Every JobApplication gets a dedicated workspace at /applications/{id} — a
surface, not a new data store. It owns no data and duplicates none: CV comes
from the Phase 4 CvVariant lens, analysis/match/interview from the existing
AiWorkspacePanel, documents from Attachments, communication from
Correspondence, activity from JobEvent, stage semantics from JobPipeline. No
career data is copied and nothing here writes.

- GET /api/jobapplications/{id}/workspace: one aggregate read (role, company,
  stage, dates, attached CV variant, cover letter, documents, AI history,
  recent activity) replacing the page fanning out across endpoints
- Next recommended action: ordered rules answering "what do I do next?", the
  core product principle for this phase
- ApplicationWorkspacePage: left nav + linkable ?section=, reusing the existing
  component for each domain; later-milestone sections say so rather than faking
- Entry point from the job dialog via an optional onOpenWorkspace callback —
  the dialog must not depend on router context (it is mounted without a
  <Router> in several suites), so the caller owns navigation
- 8 backend tests (aggregate, CV variant surfacing, counts, activity ordering,
  next-step rules, tenant scoping)

Local: 314 backend, 88/88 frontend (31 suites), tsc clean, production build ok.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 23:57:24 +02:00

4.3 KiB

Application Workspace (Phase 5)

Phase 5, Milestone 1 (2026-07-18). The per-application workspace: what it is, what it deliberately is not, and how it composes existing systems. Companion to cv-builder.md, ai-career-assistant.md, career-profile-model.md.

What it is

A dedicated surface for one JobApplication at /applications/{id}, so an application is a place you work rather than a row you edit in a modal. Job tracking stays the product; the workspace is the application's home.

Core principle: the user should never ask "what do I do next?" — the overview always answers it.

What it is NOT

The workspace owns no data and duplicates none. It is an aggregate read plus a navigation shell:

Section Backed by (existing system)
CV Phase 4 CvVariant — a lens over the master CareerProfile
Analysis / Match / Interview Phase 5 AiWorkspacePanel + AiInteraction history
Documents Attachment
Communication Correspondence
Activity / Timeline JobEvent
Stage semantics JobPipeline

No career data is copied into the application. Nothing in this feature writes to the master profile, a CV variant, or a cover letter.

Backend

GET /api/jobapplications/{id}/workspaceWorkspaceOverviewDto (ApplicationWorkspaceController + ApplicationWorkspaceService).

One aggregate read instead of the page fanning out: role/company/location/salary, status + pipeline group, applied/deadline/follow-up dates, the attached CV variant (id, name, theme), cover-letter presence, document count, AI interaction count + last run, recent JobEvent activity, and the computed next recommended action.

Read-only and tenant-scoped (OwnerUserId), returning 404 for another user's application.

First unmet rule wins, ordered to match where the application actually is — understand the role, prepare the material, send it, then chase it:

  1. add-job-details — no advert text (analysis and matching need it)
  2. prepare-cv — no CV variant attached and no tailored CV text
  3. write-cover-letter — no cover letter
  4. attach-documents — nothing attached
  5. prepare-interview — the application reached an interview stage
  6. schedule-follow-up — applied with no follow-up date
  7. set-next-action — no next action written

Prospect-stage applications short-circuit to CV → cover letter → submit. null means nothing is outstanding.

Frontend

ApplicationWorkspacePage (/applications/:id) — a left nav plus a content pane, section selected by ?section=, so a section is linkable and survives refresh. Reached from the job dialog's "Open application workspace" button.

The dialog passes an optional onOpenWorkspace callback rather than calling useNavigate itself: JobDetailsDialog must stay renderable without a <Router> (several suites mount it standalone), so router context belongs to the caller.

Implemented now: Overview, Job Details, and the sections that reuse an existing component (Analysis/Match/Interview → AiWorkspacePanel, Documents → Attachments, Communication → Correspondence). Sections owned by later milestones state their milestone instead of faking functionality.

Relationship to /readiness

GET /{id}/readiness already computes a polish-oriented checklist (score, completed, missing, reminders) and still backs the dialog's Readiness tab. The workspace's next-action rules are deliberately narrower and action-shaped. Milestone 2 introduces the persisted, user-editable checklist and folds the readiness signals into it as defaults — at which point the overlap is resolved in one place rather than two.

Extension points

  • New section: add to WORKSPACE_SECTIONS and render it; nav is data-driven.
  • New next-action rule: add one clause to ApplicationWorkspaceService.NextStep — ordered, so position is the priority.
  • More overview data: extend WorkspaceOverviewDto; the page reads one payload.

Milestones

  1. Workspace foundation — route, nav shell, aggregate overview, next recommended action.
  2. Checklist and progress tracking (persisted + custom items).
  3. Timeline and activity history. 4. Job analysis. 5. Career matching. 6. CV integration.
  4. Cover letter workflow. 8. Documents. 9. Interview preparation. 10. Dashboard improvements.